@ncukondo/gcal-cli 0.2.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +409 -217
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -587668,6 +587668,24 @@ function formatSearchResultText(query, events) {
587668
587668
  return lines.join(`
587669
587669
  `);
587670
587670
  }
587671
+ function formatQuietText(events) {
587672
+ if (events.length === 0)
587673
+ return "No events found.";
587674
+ const lines = [];
587675
+ for (const event of events) {
587676
+ const month = event.start.slice(5, 7);
587677
+ const day = event.start.slice(8, 10);
587678
+ const datePrefix = `${month}/${day}`;
587679
+ if (event.all_day) {
587680
+ lines.push(`${datePrefix} All day ${event.title}`);
587681
+ } else {
587682
+ const time3 = formatTimeRange(event);
587683
+ lines.push(`${datePrefix} ${time3} ${event.title}`);
587684
+ }
587685
+ }
587686
+ return lines.join(`
587687
+ `);
587688
+ }
587671
587689
  var CALENDAR_ID_MAX = 15;
587672
587690
  var CALENDAR_ID_COL = 18;
587673
587691
  function truncateId(id) {
@@ -587736,7 +587754,7 @@ function errorCodeToExitCode(code) {
587736
587754
  // package.json
587737
587755
  var package_default = {
587738
587756
  name: "@ncukondo/gcal-cli",
587739
- version: "0.2.3",
587757
+ version: "0.4.0",
587740
587758
  type: "module",
587741
587759
  exports: {
587742
587760
  ".": "./dist/index.js"
@@ -587790,12 +587808,9 @@ var package_default = {
587790
587808
 
587791
587809
  // src/cli.ts
587792
587810
  var FormatSchema = _enum(["text", "json"]);
587793
- function collect(value, previous) {
587794
- return [...previous, value];
587795
- }
587796
587811
  function createProgram() {
587797
587812
  const program2 = new Command;
587798
- program2.name("gcal").description("CLI tool for managing Google Calendar events").version(package_default.version).option("-f, --format <format>", "Output format: text | json", "text").option("-c, --calendar <id>", "Target calendar ID (repeatable)", collect, []).option("-q, --quiet", "Minimal output", false).option("--tz, --timezone <zone>", "Timezone (e.g., Asia/Tokyo)");
587813
+ program2.name("gcal").description("CLI tool for managing Google Calendar events").version(package_default.version).option("-f, --format <format>", "Output format: text | json", "text").option("-q, --quiet", "Minimal output", false).option("--tz, --timezone <zone>", "Timezone (e.g., Asia/Tokyo)");
587799
587814
  program2.on("command:*", (operands) => {
587800
587815
  process.stderr.write(`error: unknown command '${operands[0]}'
587801
587816
 
@@ -587815,7 +587830,6 @@ function resolveGlobalOptions(program2) {
587815
587830
  }
587816
587831
  return {
587817
587832
  format: formatResult.data,
587818
- calendar: raw.calendar,
587819
587833
  timezone: raw.timezone,
587820
587834
  quiet: raw.quiet
587821
587835
  };
@@ -588424,6 +588438,61 @@ function applyFilters(events, options) {
588424
588438
  const afterTransparency = filterByTransparency(events, options.transparency);
588425
588439
  return filterByStatus(afterTransparency, options);
588426
588440
  }
588441
+
588442
+ // src/commands/shared.ts
588443
+ import * as nodeFs from "node:fs";
588444
+ var fsAdapter = {
588445
+ existsSync: (p) => nodeFs.existsSync(p),
588446
+ readFileSync: (p) => nodeFs.readFileSync(p, "utf-8"),
588447
+ writeFileSync: (p, d) => nodeFs.writeFileSync(p, d, "utf-8"),
588448
+ mkdirSync: (p) => nodeFs.mkdirSync(p, { recursive: true }),
588449
+ unlinkSync: (p) => nodeFs.unlinkSync(p),
588450
+ chmodSync: (p, m) => nodeFs.chmodSync(p, m)
588451
+ };
588452
+ function collect(value, previous) {
588453
+ return [...previous, value];
588454
+ }
588455
+ function createGoogleCalendarApi(calendar) {
588456
+ return {
588457
+ calendarList: {
588458
+ list: async (p) => {
588459
+ const res = await calendar.calendarList.list(p);
588460
+ const data = {};
588461
+ if (res.data.items)
588462
+ data.items = res.data.items;
588463
+ if (res.data.nextPageToken)
588464
+ data.nextPageToken = res.data.nextPageToken;
588465
+ return { data };
588466
+ }
588467
+ },
588468
+ events: {
588469
+ list: async (p) => {
588470
+ const res = await calendar.events.list(p);
588471
+ const data = {};
588472
+ if (res.data.items)
588473
+ data.items = res.data.items;
588474
+ if (res.data.nextPageToken)
588475
+ data.nextPageToken = res.data.nextPageToken;
588476
+ return { data };
588477
+ },
588478
+ get: async (p) => {
588479
+ const res = await calendar.events.get(p);
588480
+ return { data: res.data };
588481
+ },
588482
+ insert: async (p) => {
588483
+ const res = await calendar.events.insert(p);
588484
+ return { data: res.data };
588485
+ },
588486
+ patch: async (p) => {
588487
+ const res = await calendar.events.patch(p);
588488
+ return { data: res.data };
588489
+ },
588490
+ delete: async (p) => {
588491
+ await calendar.events.delete(p);
588492
+ }
588493
+ }
588494
+ };
588495
+ }
588427
588496
  // node_modules/date-fns/locale/en-US/_lib/formatDistance.mjs
588428
588497
  var formatDistanceLocale = {
588429
588498
  lessThanXSeconds: {
@@ -590596,8 +590665,8 @@ function parseDateTimeInZone(dateStr, timezone) {
590596
590665
  // src/commands/search.ts
590597
590666
  var DEFAULT_SEARCH_DAYS = 30;
590598
590667
  async function handleSearch(opts) {
590599
- const { api: api2, query, format: format4, calendars, timezone, write } = opts;
590600
- const writeErr = opts.writeErr ?? (() => {});
590668
+ const { api: api2, query, format: format4, calendars, timezone, write, quiet } = opts;
590669
+ const writeErr = quiet ? () => {} : opts.writeErr ?? (() => {});
590601
590670
  const now = new Date;
590602
590671
  const days = opts.days ?? DEFAULT_SEARCH_DAYS;
590603
590672
  const isNegativeDays = days < 0;
@@ -590605,7 +590674,7 @@ async function handleSearch(opts) {
590605
590674
  let timeMax;
590606
590675
  if (opts.from && opts.to) {
590607
590676
  timeMin = formatDateTimeInZone(parseDateTimeInZone(opts.from, timezone), timezone);
590608
- timeMax = formatDateTimeInZone(parseDateTimeInZone(opts.to + "T23:59:59", timezone), timezone);
590677
+ timeMax = formatDateTimeInZone(addDays(parseDateTimeInZone(opts.to, timezone), 1), timezone);
590609
590678
  } else if (opts.from) {
590610
590679
  const startDate = parseDateTimeInZone(opts.from, timezone);
590611
590680
  timeMin = formatDateTimeInZone(startDate, timezone);
@@ -590613,7 +590682,7 @@ async function handleSearch(opts) {
590613
590682
  endDate.setDate(endDate.getDate() + days);
590614
590683
  timeMax = formatDateTimeInZone(endDate, timezone);
590615
590684
  } else if (opts.to) {
590616
- timeMax = formatDateTimeInZone(parseDateTimeInZone(opts.to + "T23:59:59", timezone), timezone);
590685
+ timeMax = formatDateTimeInZone(addDays(parseDateTimeInZone(opts.to, timezone), 1), timezone);
590617
590686
  timeMin = formatDateTimeInZone(now, timezone);
590618
590687
  } else if (isNegativeDays) {
590619
590688
  const pastDate = new Date(now.getTime());
@@ -590627,7 +590696,7 @@ async function handleSearch(opts) {
590627
590696
  timeMax = formatDateTimeInZone(endDate, timezone);
590628
590697
  }
590629
590698
  const displayFrom = timeMin.slice(0, 10);
590630
- const displayTo = timeMax.slice(0, 10);
590699
+ const displayTo = opts.to ?? timeMax.slice(0, 10);
590631
590700
  writeErr(`Searching: ${displayFrom} to ${displayTo}`);
590632
590701
  const hasExplicitRange = opts.days !== undefined || opts.from !== undefined || opts.to !== undefined;
590633
590702
  if (!hasExplicitRange) {
@@ -590648,6 +590717,8 @@ async function handleSearch(opts) {
590648
590717
  events: filtered,
590649
590718
  count: filtered.length
590650
590719
  }));
590720
+ } else if (quiet) {
590721
+ write(formatQuietText(filtered));
590651
590722
  } else {
590652
590723
  write(formatSearchResultText(query, filtered));
590653
590724
  }
@@ -590655,9 +590726,10 @@ async function handleSearch(opts) {
590655
590726
  }
590656
590727
  function createSearchCommand() {
590657
590728
  const cmd = new Command("search").description("Search events by keyword").argument("<query>", "Search query string");
590729
+ cmd.option("-c, --calendar <id>", "Target calendar ID (repeatable)", collect, []);
590658
590730
  cmd.option("--from <date>", "Start date for search range");
590659
590731
  cmd.option("--to <date>", "End date for search range");
590660
- cmd.option("--days <n>", "Search within next n days (default: 30)", Number.parseInt);
590732
+ cmd.option("--days <n>", "Search within next n days (default: 30)", (v) => Number.parseInt(v, 10));
590661
590733
  const daysOpt = cmd.options.find((o) => o.long === "--days");
590662
590734
  const fromOpt = cmd.options.find((o) => o.long === "--from");
590663
590735
  const toOpt = cmd.options.find((o) => o.long === "--to");
@@ -590667,32 +590739,26 @@ function createSearchCommand() {
590667
590739
  cmd.option("--busy", "Show only busy (opaque) events");
590668
590740
  cmd.option("--free", "Show only free (transparent) events");
590669
590741
  cmd.option("--confirmed", "Show only confirmed events");
590670
- cmd.option("--include-tentative", "Include tentative events");
590742
+ cmd.option("--include-tentative", "Include tentative events (excluded by default)");
590743
+ const busyOpt = cmd.options.find((o) => o.long === "--busy");
590744
+ const freeOpt = cmd.options.find((o) => o.long === "--free");
590745
+ busyOpt.conflicts(["free"]);
590746
+ freeOpt.conflicts(["busy"]);
590671
590747
  return cmd;
590672
590748
  }
590673
590749
 
590674
590750
  // src/commands/show.ts
590675
590751
  async function handleShow(opts) {
590676
- const { api: api2, eventId, calendarId, calendarName, format: format4, timezone, write } = opts;
590677
- try {
590678
- const event = await getEvent(api2, calendarId, calendarName, eventId, timezone);
590679
- if (format4 === "json") {
590680
- write(formatJsonSuccess({ event }));
590681
- } else {
590682
- write(formatEventDetailText(event));
590683
- }
590684
- return { exitCode: ExitCode.SUCCESS };
590685
- } catch (error) {
590686
- if (error instanceof ApiError) {
590687
- if (format4 === "json") {
590688
- write(formatJsonError(error.code, error.message));
590689
- } else {
590690
- write(`Error: ${error.message}`);
590691
- }
590692
- return { exitCode: errorCodeToExitCode(error.code) };
590693
- }
590694
- throw error;
590752
+ const { api: api2, eventId, calendarId, calendarName, format: format4, quiet, timezone, write } = opts;
590753
+ const event = await getEvent(api2, calendarId, calendarName, eventId, timezone);
590754
+ if (format4 === "json") {
590755
+ write(formatJsonSuccess({ event }));
590756
+ } else if (quiet) {
590757
+ write(`${event.title} ${event.start} ${event.end}`);
590758
+ } else {
590759
+ write(formatEventDetailText(event));
590695
590760
  }
590761
+ return { exitCode: ExitCode.SUCCESS };
590696
590762
  }
590697
590763
  function createShowCommand() {
590698
590764
  return new Command("show").description("Show event details").argument("<event-id>", "Event ID").option("-c, --calendar <id>", "Calendar ID to query");
@@ -591778,24 +591844,6 @@ function resolveDateRange(input, timezone, now = () => new Date) {
591778
591844
  timeMax: formatDateTimeInZone(end, timezone)
591779
591845
  };
591780
591846
  }
591781
- function formatQuietText(events) {
591782
- if (events.length === 0)
591783
- return "No events found.";
591784
- const lines = [];
591785
- for (const event of events) {
591786
- const month = event.start.slice(5, 7);
591787
- const day = event.start.slice(8, 10);
591788
- const datePrefix = `${month}/${day}`;
591789
- if (event.all_day) {
591790
- lines.push(`${datePrefix} All day ${event.title}`);
591791
- } else {
591792
- const time3 = formatTimeRange(event);
591793
- lines.push(`${datePrefix} ${time3} ${event.title}`);
591794
- }
591795
- }
591796
- return lines.join(`
591797
- `);
591798
- }
591799
591847
  async function handleList(options, deps) {
591800
591848
  const config2 = deps.loadConfig();
591801
591849
  const timezone = resolveTimezone(options.timezone, config2.timezone);
@@ -591813,7 +591861,7 @@ async function handleList(options, deps) {
591813
591861
  if (dateRange.warning && deps.writeErr) {
591814
591862
  deps.writeErr(dateRange.warning);
591815
591863
  }
591816
- const calendars = selectCalendars(options.calendar, config2);
591864
+ const calendars = selectCalendars(options.calendar && options.calendar.length > 0 ? options.calendar : undefined, config2);
591817
591865
  const apiOptions = {
591818
591866
  timeMin: dateRange.timeMin,
591819
591867
  timeMax: dateRange.timeMax
@@ -591852,6 +591900,7 @@ async function handleList(options, deps) {
591852
591900
  }
591853
591901
  function createListCommand() {
591854
591902
  const cmd = new Command("list").description("List events within a date range");
591903
+ cmd.option("-c, --calendar <id>", "Target calendar ID (repeatable)", collect, []);
591855
591904
  cmd.option("--today", "Show today's events");
591856
591905
  cmd.option("--days <n>", "Events for next n days (default: 7)", (v) => Number.parseInt(v, 10));
591857
591906
  cmd.option("--from <date>", "Start date (ISO 8601 or YYYY-MM-DD)");
@@ -591865,18 +591914,204 @@ function createListCommand() {
591865
591914
  const fromOpt = cmd.options.find((o) => o.long === "--from");
591866
591915
  const busyOpt = cmd.options.find((o) => o.long === "--busy");
591867
591916
  const freeOpt = cmd.options.find((o) => o.long === "--free");
591917
+ const toOpt = cmd.options.find((o) => o.long === "--to");
591868
591918
  todayOpt.conflicts(["days", "from"]);
591869
- daysOpt.conflicts(["today", "from"]);
591919
+ daysOpt.conflicts(["today", "from", "to"]);
591870
591920
  fromOpt.conflicts(["today", "days"]);
591921
+ toOpt.conflicts(["days"]);
591871
591922
  busyOpt.conflicts(["free"]);
591872
591923
  freeOpt.conflicts(["busy"]);
591873
591924
  return cmd;
591874
591925
  }
591875
591926
 
591927
+ // src/lib/date-utils.ts
591928
+ var DATE_ONLY_RE2 = /^\d{4}-\d{2}-\d{2}$/;
591929
+ function isDateOnly(input) {
591930
+ if (!DATE_ONLY_RE2.test(input))
591931
+ return false;
591932
+ const [y, m, d] = input.split("-").map(Number);
591933
+ const date3 = new Date(Date.UTC(y, m - 1, d));
591934
+ return date3.getUTCFullYear() === y && date3.getUTCMonth() === m - 1 && date3.getUTCDate() === d;
591935
+ }
591936
+ function addDaysToDateString(dateStr, days) {
591937
+ const [y, m, d] = dateStr.split("-").map(Number);
591938
+ const date3 = new Date(Date.UTC(y, m - 1, d + days));
591939
+ return date3.toISOString().slice(0, 10);
591940
+ }
591941
+
591942
+ // src/lib/duration.ts
591943
+ var DURATION_RE = /^(?:(\d+)d)?(?:(\d+)h)?(?:(\d+)m)?$/;
591944
+ function parseDuration(input) {
591945
+ const match2 = DURATION_RE.exec(input);
591946
+ if (!match2 || input === "") {
591947
+ throw new Error(`Invalid duration: "${input}". Use formats like 30m, 1h, 2d, 1h30m.`);
591948
+ }
591949
+ const days = Number(match2[1] || 0);
591950
+ const hours = Number(match2[2] || 0);
591951
+ const minutes = Number(match2[3] || 0);
591952
+ const ms = ((days * 24 + hours) * 60 + minutes) * 60 * 1000;
591953
+ if (ms === 0) {
591954
+ throw new Error("Duration must be greater than zero.");
591955
+ }
591956
+ return ms;
591957
+ }
591958
+
591876
591959
  // src/commands/update.ts
591960
+ var MS_PER_DAY = 24 * 60 * 60 * 1000;
591961
+ function resolveTimedEvent(startStr, endStr, timezone) {
591962
+ const parsedStart = parseDateTimeInZone(startStr, timezone);
591963
+ const parsedEnd = parseDateTimeInZone(endStr, timezone);
591964
+ return {
591965
+ start: formatDateTimeInZone(parsedStart, timezone),
591966
+ end: formatDateTimeInZone(parsedEnd, timezone),
591967
+ allDay: false
591968
+ };
591969
+ }
591970
+ function resolveAllDayEvent(startStr, endStr) {
591971
+ return {
591972
+ start: startStr,
591973
+ end: addDaysToDateString(endStr, 1),
591974
+ allDay: true
591975
+ };
591976
+ }
591977
+ function resolveStartAndEnd(startStr, endStr, allDay, timezone) {
591978
+ if (allDay) {
591979
+ return resolveAllDayEvent(startStr, endStr);
591980
+ }
591981
+ return resolveTimedEvent(startStr, endStr, timezone);
591982
+ }
591983
+ function resolveStartAndDuration(startStr, durationMs, allDay, timezone) {
591984
+ if (allDay) {
591985
+ const days = durationMs / MS_PER_DAY;
591986
+ return {
591987
+ start: startStr,
591988
+ end: addDaysToDateString(startStr, days),
591989
+ allDay: true
591990
+ };
591991
+ }
591992
+ const parsedStart = parseDateTimeInZone(startStr, timezone);
591993
+ const endDate = new Date(parsedStart.getTime() + durationMs);
591994
+ return {
591995
+ start: formatDateTimeInZone(parsedStart, timezone),
591996
+ end: formatDateTimeInZone(endDate, timezone),
591997
+ allDay: false
591998
+ };
591999
+ }
592000
+ function resolveStartOnly(startStr, existing, allDay, timezone) {
592001
+ if (allDay) {
592002
+ const existingStartMs2 = new Date(existing.start).getTime();
592003
+ const existingEndMs2 = new Date(existing.end).getTime();
592004
+ const durationDays = Math.round((existingEndMs2 - existingStartMs2) / MS_PER_DAY);
592005
+ return {
592006
+ start: startStr,
592007
+ end: addDaysToDateString(startStr, durationDays),
592008
+ allDay: true,
592009
+ existingEvent: existing
592010
+ };
592011
+ }
592012
+ const existingStartMs = new Date(existing.start).getTime();
592013
+ const existingEndMs = new Date(existing.end).getTime();
592014
+ const durationMs = existingEndMs - existingStartMs;
592015
+ const parsedStart = parseDateTimeInZone(startStr, timezone);
592016
+ const endDate = new Date(parsedStart.getTime() + durationMs);
592017
+ return {
592018
+ start: formatDateTimeInZone(parsedStart, timezone),
592019
+ end: formatDateTimeInZone(endDate, timezone),
592020
+ allDay: false,
592021
+ existingEvent: existing
592022
+ };
592023
+ }
592024
+ function resolveEndOnly(endStr, existing, allDay, timezone) {
592025
+ if (allDay) {
592026
+ return {
592027
+ start: existing.start,
592028
+ end: addDaysToDateString(endStr, 1),
592029
+ allDay: true,
592030
+ existingEvent: existing
592031
+ };
592032
+ }
592033
+ const parsedEnd = parseDateTimeInZone(endStr, timezone);
592034
+ return {
592035
+ start: existing.start,
592036
+ end: formatDateTimeInZone(parsedEnd, timezone),
592037
+ allDay: false,
592038
+ existingEvent: existing
592039
+ };
592040
+ }
592041
+ function resolveDurationOnly(durationMs, existing, allDay, timezone) {
592042
+ if (allDay) {
592043
+ const days = durationMs / MS_PER_DAY;
592044
+ return {
592045
+ start: existing.start,
592046
+ end: addDaysToDateString(existing.start, days),
592047
+ allDay: true,
592048
+ existingEvent: existing
592049
+ };
592050
+ }
592051
+ const existingStartMs = new Date(existing.start).getTime();
592052
+ const endDate = new Date(existingStartMs + durationMs);
592053
+ return {
592054
+ start: existing.start,
592055
+ end: formatDateTimeInZone(endDate, timezone),
592056
+ allDay: false,
592057
+ existingEvent: existing
592058
+ };
592059
+ }
592060
+ async function resolveTimeUpdate(opts) {
592061
+ const { timezone, calendarId, calendarName, eventId, getEvent: getEvent2 } = opts;
592062
+ const hasStart = opts.start !== undefined;
592063
+ const hasEnd = opts.end !== undefined;
592064
+ const hasDuration = opts.duration !== undefined;
592065
+ if (!hasStart && !hasEnd && !hasDuration)
592066
+ return null;
592067
+ const durationMs = hasDuration ? parseDuration(opts.duration) : undefined;
592068
+ const needExisting = hasStart && !hasEnd && !hasDuration || hasEnd && !hasStart || hasDuration && !hasStart;
592069
+ let existing;
592070
+ if (needExisting) {
592071
+ existing = await getEvent2(calendarId, calendarName, eventId, timezone);
592072
+ }
592073
+ const allDay = hasStart ? isDateOnly(opts.start) : existing.all_day;
592074
+ if (hasStart && hasEnd) {
592075
+ const startIsDateOnly = isDateOnly(opts.start);
592076
+ const endIsDateOnly = isDateOnly(opts.end);
592077
+ if (startIsDateOnly !== endIsDateOnly) {
592078
+ throw new ApiError("INVALID_ARGS", "--start and --end must be the same type (both date-only or both datetime)");
592079
+ }
592080
+ }
592081
+ if (hasEnd && !hasStart && existing) {
592082
+ const endIsDateOnly = isDateOnly(opts.end);
592083
+ if (existing.all_day && !endIsDateOnly) {
592084
+ throw new ApiError("INVALID_ARGS", "--end format (datetime) does not match existing event type (all-day). Use date-only format (YYYY-MM-DD) or provide --start to change event type.");
592085
+ }
592086
+ if (!existing.all_day && endIsDateOnly) {
592087
+ throw new ApiError("INVALID_ARGS", "--end format (date-only) does not match existing event type (timed). Use datetime format (YYYY-MM-DDTHH:MM) or provide --start to change event type.");
592088
+ }
592089
+ }
592090
+ if (durationMs !== undefined && allDay) {
592091
+ if (durationMs % MS_PER_DAY !== 0) {
592092
+ throw new ApiError("INVALID_ARGS", "All-day events require day-unit duration (e.g. 1d, 2d). Sub-day durations like hours or minutes are not allowed.");
592093
+ }
592094
+ }
592095
+ if (hasStart && hasEnd) {
592096
+ return resolveStartAndEnd(opts.start, opts.end, allDay, timezone);
592097
+ }
592098
+ if (hasStart && durationMs !== undefined) {
592099
+ return resolveStartAndDuration(opts.start, durationMs, allDay, timezone);
592100
+ }
592101
+ if (hasStart) {
592102
+ return resolveStartOnly(opts.start, existing, allDay, timezone);
592103
+ }
592104
+ if (hasEnd) {
592105
+ return resolveEndOnly(opts.end, existing, allDay, timezone);
592106
+ }
592107
+ if (durationMs !== undefined) {
592108
+ return resolveDurationOnly(durationMs, existing, allDay, timezone);
592109
+ }
592110
+ return null;
592111
+ }
591877
592112
  async function handleUpdate(opts) {
591878
592113
  const { api: api2, eventId, calendarId, calendarName, format: format4, timezone, write } = opts;
591879
- const hasUpdate = opts.title !== undefined || opts.start !== undefined || opts.end !== undefined || opts.description !== undefined || opts.busy !== undefined || opts.free !== undefined;
592114
+ const hasUpdate = opts.title !== undefined || opts.start !== undefined || opts.end !== undefined || opts.duration !== undefined || opts.description !== undefined || opts.busy !== undefined || opts.free !== undefined;
591880
592115
  if (!hasUpdate) {
591881
592116
  throw new ApiError("INVALID_ARGS", "at least one update option must be provided");
591882
592117
  }
@@ -591892,19 +592127,21 @@ async function handleUpdate(opts) {
591892
592127
  } else if (opts.free) {
591893
592128
  input.transparency = "transparent";
591894
592129
  }
591895
- if (opts.start !== undefined || opts.end !== undefined) {
591896
- if (opts.start === undefined || opts.end === undefined) {
591897
- throw new ApiError("INVALID_ARGS", "start, end, and allDay must all be provided together");
591898
- }
591899
- const startStr = opts.start;
591900
- const endStr = opts.end;
591901
- const parsedStart = parseDateTimeInZone(startStr, timezone);
591902
- const parsedEnd = parseDateTimeInZone(endStr, timezone);
592130
+ const timeResult = await resolveTimeUpdate(opts);
592131
+ if (timeResult) {
591903
592132
  const withTime = input;
591904
- withTime.start = formatDateTimeInZone(parsedStart, timezone);
591905
- withTime.end = formatDateTimeInZone(parsedEnd, timezone);
591906
- withTime.allDay = false;
592133
+ withTime.start = timeResult.start;
592134
+ withTime.end = timeResult.end;
592135
+ withTime.allDay = timeResult.allDay;
591907
592136
  input.timeZone = timezone;
592137
+ if (timeResult.existingEvent) {
592138
+ const existing = timeResult.existingEvent;
592139
+ if (existing.all_day && !timeResult.allDay) {
592140
+ opts.writeStderr("⚠ Event type changed from all-day to timed");
592141
+ } else if (!existing.all_day && timeResult.allDay) {
592142
+ opts.writeStderr("⚠ Event type changed from timed to all-day");
592143
+ }
592144
+ }
591908
592145
  }
591909
592146
  if (opts.dryRun) {
591910
592147
  const changes = {};
@@ -591919,6 +592156,8 @@ async function handleUpdate(opts) {
591919
592156
  changes.start = withTime.start;
591920
592157
  if (withTime.end !== undefined)
591921
592158
  changes.end = withTime.end;
592159
+ if (withTime.allDay !== undefined)
592160
+ changes.allDay = withTime.allDay;
591922
592161
  if (format4 === "json") {
591923
592162
  write(formatJsonSuccess({
591924
592163
  dry_run: true,
@@ -591945,9 +592184,14 @@ async function handleUpdate(opts) {
591945
592184
  }
591946
592185
  const updated = await updateEvent(api2, calendarId, calendarName, eventId, input);
591947
592186
  if (format4 === "json") {
591948
- write(formatJsonSuccess({ event: updated }));
592187
+ write(formatJsonSuccess({ event: updated, message: "Event updated" }));
592188
+ } else if (opts.quiet) {
592189
+ write(updated.id);
591949
592190
  } else {
591950
- write(formatEventDetailText(updated));
592191
+ const detail = formatEventDetailText(updated);
592192
+ write(`Event updated
592193
+
592194
+ ${detail}`);
591951
592195
  }
591952
592196
  return { exitCode: ExitCode.SUCCESS };
591953
592197
  }
@@ -591955,51 +592199,37 @@ function createUpdateCommand() {
591955
592199
  const cmd = new Command("update").description("Update an existing event").argument("<event-id>", "Event ID to update");
591956
592200
  cmd.option("-c, --calendar <id>", "Calendar ID");
591957
592201
  cmd.option("-t, --title <title>", "New title");
591958
- cmd.option("-s, --start <datetime>", "New start datetime");
591959
- cmd.option("-e, --end <datetime>", "New end datetime");
592202
+ cmd.option("-s, --start <datetime>", "Start date or datetime. Date-only (YYYY-MM-DD) → all-day. Datetime (YYYY-MM-DDTHH:MM) → timed. Can be specified alone (preserves existing duration).");
592203
+ cmd.option("-e, --end <datetime>", "End date or datetime. Can be specified alone (preserves existing start). All-day end is inclusive.");
592204
+ cmd.option("--duration <duration>", "Duration instead of --end (e.g. 30m, 1h, 2d, 1h30m). Mutually exclusive with --end. Can be specified alone (preserves existing start).");
591960
592205
  cmd.option("-d, --description <text>", "New description");
591961
592206
  cmd.option("--busy", "Mark as busy");
591962
592207
  cmd.option("--free", "Mark as free");
591963
592208
  cmd.option("--dry-run", "Preview without executing");
592209
+ const endOpt = cmd.options.find((o) => o.long === "--end");
592210
+ const durationOpt = cmd.options.find((o) => o.long === "--duration");
592211
+ endOpt.conflicts(["duration"]);
592212
+ durationOpt.conflicts(["end"]);
591964
592213
  const busyOpt = cmd.options.find((o) => o.long === "--busy");
591965
592214
  const freeOpt = cmd.options.find((o) => o.long === "--free");
591966
592215
  busyOpt.conflicts(["free"]);
591967
592216
  freeOpt.conflicts(["busy"]);
592217
+ cmd.addHelpText("after", `
592218
+ Examples:
592219
+ gcal update abc123 -t "Updated Meeting" # Title only
592220
+ gcal update abc123 -s "2026-01-24T11:00" # Start only, keep duration
592221
+ gcal update abc123 -e "2026-01-24T12:00" # End only, keep start
592222
+ gcal update abc123 --duration 2h # Duration only, keep start
592223
+ gcal update abc123 -s "2026-01-24T11:00" -e "2026-01-24T12:30" # Start + end
592224
+ gcal update abc123 -s "2026-01-24T10:00" --duration 30m # Start + duration
592225
+ gcal update abc123 -s "2026-03-01" -e "2026-03-03" # All-day, 3 days (inclusive)
592226
+ gcal update abc123 -s "2026-03-01" --duration 2d # All-day, 2 days
592227
+ gcal update abc123 --free # Transparency only
592228
+ gcal update abc123 --dry-run -t "Preview" # Dry run
592229
+ `);
591968
592230
  return cmd;
591969
592231
  }
591970
592232
 
591971
- // src/lib/date-utils.ts
591972
- var DATE_ONLY_RE2 = /^\d{4}-\d{2}-\d{2}$/;
591973
- function isDateOnly(input) {
591974
- if (!DATE_ONLY_RE2.test(input))
591975
- return false;
591976
- const [y, m, d] = input.split("-").map(Number);
591977
- const date3 = new Date(Date.UTC(y, m - 1, d));
591978
- return date3.getUTCFullYear() === y && date3.getUTCMonth() === m - 1 && date3.getUTCDate() === d;
591979
- }
591980
- function addDaysToDateString(dateStr, days) {
591981
- const [y, m, d] = dateStr.split("-").map(Number);
591982
- const date3 = new Date(Date.UTC(y, m - 1, d + days));
591983
- return date3.toISOString().slice(0, 10);
591984
- }
591985
-
591986
- // src/lib/duration.ts
591987
- var DURATION_RE = /^(?:(\d+)d)?(?:(\d+)h)?(?:(\d+)m)?$/;
591988
- function parseDuration(input) {
591989
- const match2 = DURATION_RE.exec(input);
591990
- if (!match2 || input === "") {
591991
- throw new Error(`Invalid duration: "${input}". Use formats like 30m, 1h, 2d, 1h30m.`);
591992
- }
591993
- const days = Number(match2[1] || 0);
591994
- const hours = Number(match2[2] || 0);
591995
- const minutes = Number(match2[3] || 0);
591996
- const ms = ((days * 24 + hours) * 60 + minutes) * 60 * 1000;
591997
- if (ms === 0) {
591998
- throw new Error("Duration must be greater than zero.");
591999
- }
592000
- return ms;
592001
- }
592002
-
592003
592233
  // src/commands/add.ts
592004
592234
  async function handleAdd(options, deps) {
592005
592235
  if (!options.title) {
@@ -592045,12 +592275,12 @@ async function handleAdd(options, deps) {
592045
592275
  deps.write(formatJsonError("INVALID_ARGS", `Invalid duration: "${options.duration}". Use formats like 30m, 1h, 2d, 1h30m.`));
592046
592276
  return { exitCode: ExitCode.ARGUMENT };
592047
592277
  }
592048
- const MS_PER_DAY = 24 * 60 * 60 * 1000;
592049
- if (durationMs % MS_PER_DAY !== 0) {
592278
+ const MS_PER_DAY2 = 24 * 60 * 60 * 1000;
592279
+ if (durationMs % MS_PER_DAY2 !== 0) {
592050
592280
  deps.write(formatJsonError("INVALID_ARGS", "All-day events require day-unit duration (e.g. 1d, 2d). Sub-day durations like hours or minutes are not allowed."));
592051
592281
  return { exitCode: ExitCode.ARGUMENT };
592052
592282
  }
592053
- const days = durationMs / MS_PER_DAY;
592283
+ const days = durationMs / MS_PER_DAY2;
592054
592284
  end = addDaysToDateString(options.start, days);
592055
592285
  } else {
592056
592286
  end = addDaysToDateString(options.start, 1);
@@ -592087,9 +592317,37 @@ async function handleAdd(options, deps) {
592087
592317
  if (options.description !== undefined) {
592088
592318
  input.description = options.description;
592089
592319
  }
592320
+ if (options.dryRun) {
592321
+ const preview = {
592322
+ title: input.title,
592323
+ start: input.start,
592324
+ end: input.end
592325
+ };
592326
+ if (input.description !== undefined)
592327
+ preview.description = input.description;
592328
+ if (input.transparency !== "opaque")
592329
+ preview.transparency = input.transparency;
592330
+ if (options.format === "json") {
592331
+ deps.write(formatJsonSuccess({ dry_run: true, action: "add", event: preview }));
592332
+ } else {
592333
+ const lines = ["DRY RUN: Would create event:"];
592334
+ lines.push(` title: "${preview.title}"`);
592335
+ lines.push(` start: "${preview.start}"`);
592336
+ lines.push(` end: "${preview.end}"`);
592337
+ if (preview.description !== undefined)
592338
+ lines.push(` description: "${preview.description}"`);
592339
+ if (preview.transparency !== undefined)
592340
+ lines.push(` transparency: ${preview.transparency}`);
592341
+ deps.write(lines.join(`
592342
+ `));
592343
+ }
592344
+ return { exitCode: ExitCode.SUCCESS };
592345
+ }
592090
592346
  const event = await deps.createEvent(calendarId, calendarName, input);
592091
592347
  if (options.format === "json") {
592092
592348
  deps.write(formatJsonSuccess({ event, message: "Event created" }));
592349
+ } else if (options.quiet) {
592350
+ deps.write(event.id);
592093
592351
  } else {
592094
592352
  const detail = formatEventDetailText(event);
592095
592353
  deps.write(`Event created
@@ -592104,9 +592362,11 @@ function createAddCommand() {
592104
592362
  cmd.requiredOption("-s, --start <datetime>", "Start date or datetime. Date-only (YYYY-MM-DD) creates all-day event. Datetime (YYYY-MM-DDTHH:MM) creates timed event.");
592105
592363
  cmd.option("-e, --end <datetime>", "End date or datetime. Optional. Default: same day (all-day) or +1h (timed). All-day end is inclusive.");
592106
592364
  cmd.option("--duration <duration>", "Duration instead of --end (e.g. 30m, 1h, 2d, 1h30m). Mutually exclusive with --end.");
592365
+ cmd.option("-c, --calendar <id>", "Target calendar ID");
592107
592366
  cmd.option("-d, --description <text>", "Event description");
592108
592367
  cmd.option("--busy", "Mark as busy (default)");
592109
592368
  cmd.option("--free", "Mark as free (transparent)");
592369
+ cmd.option("--dry-run", "Preview without executing");
592110
592370
  const endOpt = cmd.options.find((o) => o.long === "--end");
592111
592371
  const durationOpt = cmd.options.find((o) => o.long === "--duration");
592112
592372
  endOpt.conflicts(["duration"]);
@@ -592132,8 +592392,7 @@ Examples:
592132
592392
  async function handleDelete(opts) {
592133
592393
  const { api: api2, eventId, calendarId, format: format4, quiet, dryRun = false, write } = opts;
592134
592394
  if (!eventId) {
592135
- write(formatJsonError("INVALID_ARGS", "event-id is required"));
592136
- return { exitCode: ExitCode.ARGUMENT };
592395
+ throw new ApiError("INVALID_ARGS", "event-id is required");
592137
592396
  }
592138
592397
  if (dryRun) {
592139
592398
  if (format4 === "json") {
@@ -592148,27 +592407,15 @@ async function handleDelete(opts) {
592148
592407
  }
592149
592408
  return { exitCode: ExitCode.SUCCESS };
592150
592409
  }
592151
- try {
592152
- await deleteEvent(api2, calendarId, eventId);
592153
- if (!quiet) {
592154
- if (format4 === "json") {
592155
- write(formatJsonSuccess({ deleted_id: eventId, message: "Event deleted" }));
592156
- } else {
592157
- write("Event deleted");
592158
- }
592159
- }
592160
- return { exitCode: ExitCode.SUCCESS };
592161
- } catch (error) {
592162
- if (error instanceof ApiError) {
592163
- if (format4 === "json") {
592164
- write(formatJsonError(error.code, error.message));
592165
- } else {
592166
- write(`Error: ${error.message}`);
592167
- }
592168
- return { exitCode: errorCodeToExitCode(error.code) };
592410
+ await deleteEvent(api2, calendarId, eventId);
592411
+ if (!quiet) {
592412
+ if (format4 === "json") {
592413
+ write(formatJsonSuccess({ deleted_id: eventId, message: "Event deleted" }));
592414
+ } else {
592415
+ write("Event deleted");
592169
592416
  }
592170
- throw error;
592171
592417
  }
592418
+ return { exitCode: ExitCode.SUCCESS };
592172
592419
  }
592173
592420
  function createDeleteCommand() {
592174
592421
  return new Command("delete").description("Delete a calendar event").argument("<event-id>", "Event ID").option("-c, --calendar <id>", "Calendar ID to query").option("--dry-run", "Preview without executing");
@@ -592187,20 +592434,7 @@ function mergeCalendarsWithConfig(apiCalendars, configCalendars) {
592187
592434
  }
592188
592435
  async function handleCalendars(opts) {
592189
592436
  const { api: api2, format: format4, quiet, write, configCalendars } = opts;
592190
- let apiCalendars;
592191
- try {
592192
- apiCalendars = await listCalendars(api2);
592193
- } catch (error) {
592194
- if (error instanceof ApiError) {
592195
- if (format4 === "json") {
592196
- write(formatJsonError(error.code, error.message));
592197
- } else {
592198
- write(error.message);
592199
- }
592200
- return { exitCode: errorCodeToExitCode(error.code) };
592201
- }
592202
- throw error;
592203
- }
592437
+ const apiCalendars = await listCalendars(api2);
592204
592438
  const calendars = mergeCalendarsWithConfig(apiCalendars, configCalendars);
592205
592439
  if (quiet) {
592206
592440
  write(calendars.map((c) => c.id).join(`
@@ -592312,58 +592546,6 @@ function createInitCommand() {
592312
592546
  return cmd;
592313
592547
  }
592314
592548
 
592315
- // src/commands/shared.ts
592316
- import * as nodeFs from "node:fs";
592317
- var fsAdapter = {
592318
- existsSync: (p) => nodeFs.existsSync(p),
592319
- readFileSync: (p) => nodeFs.readFileSync(p, "utf-8"),
592320
- writeFileSync: (p, d) => nodeFs.writeFileSync(p, d, "utf-8"),
592321
- mkdirSync: (p) => nodeFs.mkdirSync(p, { recursive: true }),
592322
- unlinkSync: (p) => nodeFs.unlinkSync(p),
592323
- chmodSync: (p, m) => nodeFs.chmodSync(p, m)
592324
- };
592325
- function createGoogleCalendarApi(calendar) {
592326
- return {
592327
- calendarList: {
592328
- list: async (p) => {
592329
- const res = await calendar.calendarList.list(p);
592330
- const data = {};
592331
- if (res.data.items)
592332
- data.items = res.data.items;
592333
- if (res.data.nextPageToken)
592334
- data.nextPageToken = res.data.nextPageToken;
592335
- return { data };
592336
- }
592337
- },
592338
- events: {
592339
- list: async (p) => {
592340
- const res = await calendar.events.list(p);
592341
- const data = {};
592342
- if (res.data.items)
592343
- data.items = res.data.items;
592344
- if (res.data.nextPageToken)
592345
- data.nextPageToken = res.data.nextPageToken;
592346
- return { data };
592347
- },
592348
- get: async (p) => {
592349
- const res = await calendar.events.get(p);
592350
- return { data: res.data };
592351
- },
592352
- insert: async (p) => {
592353
- const res = await calendar.events.insert(p);
592354
- return { data: res.data };
592355
- },
592356
- patch: async (p) => {
592357
- const res = await calendar.events.patch(p);
592358
- return { data: res.data };
592359
- },
592360
- delete: async (p) => {
592361
- await calendar.events.delete(p);
592362
- }
592363
- }
592364
- };
592365
- }
592366
-
592367
592549
  // src/cli.ts
592368
592550
  var FormatSchema2 = _enum(["text", "json"]);
592369
592551
  function resolveGlobalOptions2(program2) {
@@ -592376,7 +592558,6 @@ function resolveGlobalOptions2(program2) {
592376
592558
  }
592377
592559
  return {
592378
592560
  format: formatResult.data,
592379
- calendar: raw.calendar,
592380
592561
  timezone: raw.timezone,
592381
592562
  quiet: raw.quiet
592382
592563
  };
@@ -592489,19 +592670,23 @@ ${url}`);
592489
592670
  const calendarsCmd = createCalendarsCommand();
592490
592671
  calendarsCmd.action(async () => {
592491
592672
  const globalOpts = resolveGlobalOptions2(program2);
592492
- const config2 = loadConfig(fsAdapter);
592493
- const oauth2Client = await getAuthenticatedClient(fsAdapter);
592494
- const calendar = import_googleapis2.google.calendar({ version: "v3", auth: oauth2Client });
592495
- const api2 = createGoogleCalendarApi(calendar);
592496
- const result = await handleCalendars({
592497
- api: api2,
592498
- format: globalOpts.format,
592499
- quiet: globalOpts.quiet,
592500
- write: (msg) => process.stdout.write(msg + `
592673
+ try {
592674
+ const config2 = loadConfig(fsAdapter);
592675
+ const oauth2Client = await getAuthenticatedClient(fsAdapter);
592676
+ const calendar = import_googleapis2.google.calendar({ version: "v3", auth: oauth2Client });
592677
+ const api2 = createGoogleCalendarApi(calendar);
592678
+ const result = await handleCalendars({
592679
+ api: api2,
592680
+ format: globalOpts.format,
592681
+ quiet: globalOpts.quiet,
592682
+ write: (msg) => process.stdout.write(msg + `
592501
592683
  `),
592502
- configCalendars: config2.calendars
592503
- });
592504
- process.exit(result.exitCode);
592684
+ configCalendars: config2.calendars
592685
+ });
592686
+ process.exit(result.exitCode);
592687
+ } catch (error) {
592688
+ handleError2(error, globalOpts.format);
592689
+ }
592505
592690
  });
592506
592691
  program2.addCommand(calendarsCmd);
592507
592692
  const listCmd = createListCommand();
@@ -592510,7 +592695,7 @@ ${url}`);
592510
592695
  const listOpts = listCmd.opts();
592511
592696
  try {
592512
592697
  const auth = await getAuthenticatedClient(fsAdapter);
592513
- const api2 = import_googleapis2.google.calendar({ version: "v3", auth });
592698
+ const api2 = createGoogleCalendarApi(import_googleapis2.google.calendar({ version: "v3", auth }));
592514
592699
  const deps = {
592515
592700
  listEvents: (calendarId, calendarName, options) => listEvents(api2, calendarId, calendarName, options),
592516
592701
  loadConfig: () => loadConfig(fsAdapter),
@@ -592522,8 +592707,7 @@ ${url}`);
592522
592707
  const handleOpts = {
592523
592708
  ...listOpts,
592524
592709
  format: globalOpts.format,
592525
- quiet: globalOpts.quiet,
592526
- calendar: globalOpts.calendar
592710
+ quiet: globalOpts.quiet
592527
592711
  };
592528
592712
  if (globalOpts.timezone)
592529
592713
  handleOpts.timezone = globalOpts.timezone;
@@ -592544,11 +592728,12 @@ ${url}`);
592544
592728
  const calendarApi = import_googleapis2.google.calendar({ version: "v3", auth });
592545
592729
  const api2 = createGoogleCalendarApi(calendarApi);
592546
592730
  const timezone = resolveTimezone(globalOpts.timezone, config2.timezone);
592547
- const calendars = selectCalendars(globalOpts.calendar, config2);
592731
+ const calendars = selectCalendars(searchOpts.calendar.length > 0 ? searchOpts.calendar : undefined, config2);
592548
592732
  const result = await handleSearch({
592549
592733
  api: api2,
592550
592734
  query,
592551
592735
  format: globalOpts.format,
592736
+ quiet: globalOpts.quiet,
592552
592737
  calendars,
592553
592738
  timezone,
592554
592739
  days: searchOpts.days,
@@ -592570,7 +592755,7 @@ ${url}`);
592570
592755
  });
592571
592756
  program2.addCommand(searchCmd);
592572
592757
  const showCmd = createShowCommand();
592573
- showCmd.action(async () => {
592758
+ showCmd.action(async (eventId) => {
592574
592759
  const globalOpts = resolveGlobalOptions2(program2);
592575
592760
  const showOpts = showCmd.opts();
592576
592761
  try {
@@ -592578,23 +592763,24 @@ ${url}`);
592578
592763
  const auth = await getAuthenticatedClient(fsAdapter);
592579
592764
  const calendarApi = import_googleapis2.google.calendar({ version: "v3", auth });
592580
592765
  const api2 = createGoogleCalendarApi(calendarApi);
592581
- const calendarId = showOpts.calendar ?? (globalOpts.calendar.length > 0 ? globalOpts.calendar[0] : undefined);
592766
+ const calendarId = showOpts.calendar;
592582
592767
  let cal;
592583
592768
  if (calendarId) {
592584
592769
  const found = config2.calendars.find((c) => c.id === calendarId);
592585
592770
  cal = found ? { id: found.id, name: found.name } : { id: calendarId, name: calendarId };
592586
592771
  } else {
592587
592772
  const calendars = selectCalendars(undefined, config2);
592588
- const resolved = await resolveEventCalendar(api2, showCmd.args[0], calendars);
592773
+ const resolved = await resolveEventCalendar(api2, eventId, calendars);
592589
592774
  cal = resolved;
592590
592775
  }
592591
592776
  const timezone = resolveTimezone(globalOpts.timezone, config2.timezone);
592592
592777
  const result = await handleShow({
592593
592778
  api: api2,
592594
- eventId: showCmd.args[0],
592779
+ eventId,
592595
592780
  calendarId: cal.id,
592596
592781
  calendarName: cal.name,
592597
592782
  format: globalOpts.format,
592783
+ quiet: globalOpts.quiet,
592598
592784
  timezone,
592599
592785
  write: (msg) => process.stdout.write(msg + `
592600
592786
  `)
@@ -592615,8 +592801,8 @@ ${url}`);
592615
592801
  const calendarApi = import_googleapis2.google.calendar({ version: "v3", auth });
592616
592802
  const api2 = createGoogleCalendarApi(calendarApi);
592617
592803
  let resolvedCalendarId;
592618
- if (deleteOpts.calendar || globalOpts.calendar.length > 0) {
592619
- const calendars = selectCalendars(deleteOpts.calendar ? [deleteOpts.calendar] : globalOpts.calendar, config2);
592804
+ if (deleteOpts.calendar) {
592805
+ const calendars = selectCalendars([deleteOpts.calendar], config2);
592620
592806
  resolvedCalendarId = calendars[0]?.id ?? "primary";
592621
592807
  } else {
592622
592808
  const calendars = selectCalendars(undefined, config2);
@@ -592660,10 +592846,12 @@ ${url}`);
592660
592846
  description: addOpts.description,
592661
592847
  busy: addOpts.busy,
592662
592848
  free: addOpts.free,
592849
+ dryRun: addOpts.dryRun,
592850
+ quiet: globalOpts.quiet,
592663
592851
  format: globalOpts.format
592664
592852
  };
592665
- if (globalOpts.calendar?.[0])
592666
- handleOpts.calendar = globalOpts.calendar[0];
592853
+ if (addOpts.calendar)
592854
+ handleOpts.calendar = addOpts.calendar;
592667
592855
  if (globalOpts.timezone)
592668
592856
  handleOpts.timezone = globalOpts.timezone;
592669
592857
  const result = await handleAdd(handleOpts, deps);
@@ -592736,8 +592924,8 @@ ${authUrl}`);
592736
592924
  const timezone = resolveTimezone(globalOpts.timezone, config2.timezone);
592737
592925
  const updateOpsCalendar = updateOpts.calendar;
592738
592926
  let cal;
592739
- if (updateOpsCalendar || globalOpts.calendar.length > 0) {
592740
- const calendars = selectCalendars(updateOpsCalendar ? [updateOpsCalendar] : globalOpts.calendar, config2);
592927
+ if (updateOpsCalendar) {
592928
+ const calendars = selectCalendars([updateOpsCalendar], config2);
592741
592929
  cal = calendars[0];
592742
592930
  } else {
592743
592931
  const calendars = selectCalendars(undefined, config2);
@@ -592750,9 +592938,13 @@ ${authUrl}`);
592750
592938
  calendarId: cal.id,
592751
592939
  calendarName: cal.name,
592752
592940
  format: globalOpts.format,
592941
+ quiet: globalOpts.quiet,
592753
592942
  timezone,
592754
592943
  write: (msg) => process.stdout.write(msg + `
592755
592944
  `),
592945
+ writeStderr: (msg) => process.stderr.write(msg + `
592946
+ `),
592947
+ getEvent: (calId, calName, evtId, tz) => getEvent(api2, calId, calName, evtId, tz),
592756
592948
  ...updateOpts
592757
592949
  });
592758
592950
  process.exit(result.exitCode);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ncukondo/gcal-cli",
3
- "version": "0.2.3",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dist/index.js"