From e34812b3fde284f9726816ff917c55cf7e40dc91 Mon Sep 17 00:00:00 2001 From: seanlee02001 Date: Mon, 13 Jul 2026 01:42:25 +0800 Subject: [PATCH 1/2] fix(calendar): wire -f/-p through to calendar subcommands; add --past to events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit calendar.ts's list/events/search actions read options.format/options.profile from the local subcommand options instead of command.parent?.optsWithGlobals() (the pattern gmail.ts already uses correctly) — so -f json and an explicit -p were both silently ignored for the whole calendar subtree, always falling back to table output and the config's default profile. Also adds an additive --past flag to 'calendar events': listEvents/search hardcode timeMin=now, and Google's API filters timeMin on an event's END time, so a fully-ended event was permanently unlistable via any existing subcommand. --past flips the query window to [now-days, now]; default (forward-looking) behavior is unchanged for existing callers. --- src/commands/calendar.ts | 26 ++++++++++++++++---------- src/lib/calendar-client.ts | 13 ++++++++++--- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/commands/calendar.ts b/src/commands/calendar.ts index 70857e7..36fd7c5 100644 --- a/src/commands/calendar.ts +++ b/src/commands/calendar.ts @@ -23,14 +23,15 @@ export function registerCalendarCommands(program: Command): void { calendar .command('list') .description('List all calendars') - .action(async (options: GlobalOptions) => { + .action(async (options: GlobalOptions, command: Command) => { try { - const profileName = getActiveProfile(options.profile); + const globalOpts = command.parent?.optsWithGlobals() as GlobalOptions; + const profileName = getActiveProfile(globalOpts?.profile); const auth = await getAuthenticatedClient(profileName); const client = new CalendarClient(auth); const calendars = await client.listCalendars(); - const format = options.format || 'table'; + const format = globalOpts?.format || 'table'; const output = formatCalendarList(calendars, format); print(output); } catch (error) { @@ -46,13 +47,15 @@ export function registerCalendarCommands(program: Command): void { calendar .command('events') .description('List upcoming events') - .option('--days ', 'Number of days to look ahead', '7') + .option('--days ', 'Number of days to look ahead (or back, with --past)', '7') .option('--calendar ', 'Calendar ID to query', 'primary') .option('--limit ', 'Maximum number of events to return', '10') + .option('--past', 'Look back over the last N days (window end = now) instead of ahead') .action( - async (options: GlobalOptions & { days: string; calendar: string; limit: string }) => { + async (options: GlobalOptions & { days: string; calendar: string; limit: string; past?: boolean }, command: Command) => { try { - const profileName = getActiveProfile(options.profile); + const globalOpts = command.parent?.optsWithGlobals() as GlobalOptions; + const profileName = getActiveProfile(globalOpts?.profile); const auth = await getAuthenticatedClient(profileName); const client = new CalendarClient(auth); @@ -60,9 +63,10 @@ export function registerCalendarCommands(program: Command): void { calendarId: options.calendar, days: parseInt(options.days, 10), maxResults: parseInt(options.limit, 10), + direction: options.past ? 'past' : 'future', }); - const format = options.format || 'table'; + const format = globalOpts?.format || 'table'; const output = formatEventList(events, format); print(output); } catch (error) { @@ -84,10 +88,12 @@ export function registerCalendarCommands(program: Command): void { .action( async ( query: string, - options: GlobalOptions & { days: string; calendar: string } + options: GlobalOptions & { days: string; calendar: string }, + command: Command ) => { try { - const profileName = getActiveProfile(options.profile); + const globalOpts = command.parent?.optsWithGlobals() as GlobalOptions; + const profileName = getActiveProfile(globalOpts?.profile); const auth = await getAuthenticatedClient(profileName); const client = new CalendarClient(auth); @@ -96,7 +102,7 @@ export function registerCalendarCommands(program: Command): void { days: parseInt(options.days, 10), }); - const format = options.format || 'table'; + const format = globalOpts?.format || 'table'; const output = formatEventList(events, format); print(output); } catch (error) { diff --git a/src/lib/calendar-client.ts b/src/lib/calendar-client.ts index 4d4addf..8ca8c3b 100644 --- a/src/lib/calendar-client.ts +++ b/src/lib/calendar-client.ts @@ -35,13 +35,20 @@ export class CalendarClient { calendarId?: string; days?: number; maxResults?: number; + direction?: 'past' | 'future'; } = {}): Promise { const calendarId = options.calendarId || 'primary'; const days = options.days || 7; const maxResults = options.maxResults || 10; - - const timeMin = new Date().toISOString(); - const timeMax = new Date(Date.now() + days * 24 * 60 * 60 * 1000).toISOString(); + const direction = options.direction || 'future'; + + const now = Date.now(); + const timeMin = direction === 'past' + ? new Date(now - days * 24 * 60 * 60 * 1000).toISOString() + : new Date(now).toISOString(); + const timeMax = direction === 'past' + ? new Date(now).toISOString() + : new Date(now + days * 24 * 60 * 60 * 1000).toISOString(); const response = await this.calendar.events.list({ calendarId, From 7c011ff2529a71e2dbb42e49328149dc8a64f8cc Mon Sep 17 00:00:00 2001 From: seanlee02001 Date: Mon, 13 Jul 2026 07:55:07 +0800 Subject: [PATCH 2/2] chore: sync package-lock name with package.json rename Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01RxX9wGuESwVBwxgvWhcjvp --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 567a291..a208afb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "gwcli", + "name": "google-workspace-cli", "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "gwcli", + "name": "google-workspace-cli", "version": "0.1.0", "license": "MIT", "dependencies": {