gws-axi 0.20.1 → 0.22.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.
- package/dist/src/commands/calendar/dateish.d.ts +47 -0
- package/dist/src/commands/calendar/dateish.js +140 -0
- package/dist/src/commands/calendar/dateish.js.map +1 -1
- package/dist/src/commands/calendar/dateish.test.d.ts +1 -0
- package/dist/src/commands/calendar/dateish.test.js +223 -0
- package/dist/src/commands/calendar/dateish.test.js.map +1 -0
- package/dist/src/commands/calendar/events.d.ts +1 -1
- package/dist/src/commands/calendar/events.js +59 -16
- package/dist/src/commands/calendar/events.js.map +1 -1
- package/dist/src/commands/calendar/freebusy.d.ts +1 -1
- package/dist/src/commands/calendar/freebusy.js +46 -16
- package/dist/src/commands/calendar/freebusy.js.map +1 -1
- package/dist/src/commands/calendar/search.d.ts +1 -1
- package/dist/src/commands/calendar/search.js +44 -12
- package/dist/src/commands/calendar/search.js.map +1 -1
- package/dist/src/commands/calendar/week-start.d.ts +13 -0
- package/dist/src/commands/calendar/week-start.js +95 -0
- package/dist/src/commands/calendar/week-start.js.map +1 -0
- package/dist/src/commands/calendar/week-start.test.d.ts +1 -0
- package/dist/src/commands/calendar/week-start.test.js +89 -0
- package/dist/src/commands/calendar/week-start.test.js.map +1 -0
- package/dist/src/commands/calendar.js +8 -1
- package/dist/src/commands/calendar.js.map +1 -1
- package/dist/src/commands/drive/activity.d.ts +1 -1
- package/dist/src/commands/drive/activity.js +25 -7
- package/dist/src/commands/drive/activity.js.map +1 -1
- package/dist/src/commands/gmail/compose.d.ts +14 -1
- package/dist/src/commands/gmail/compose.js +36 -1
- package/dist/src/commands/gmail/compose.js.map +1 -1
- package/dist/src/commands/gmail/compose.test.js +51 -0
- package/dist/src/commands/gmail/compose.test.js.map +1 -1
- package/dist/src/commands/gmail/draft.d.ts +1 -1
- package/dist/src/commands/gmail/draft.js +10 -2
- package/dist/src/commands/gmail/draft.js.map +1 -1
- package/dist/src/config.d.ts +7 -0
- package/dist/src/config.js +9 -0
- package/dist/src/config.js.map +1 -1
- package/package.json +1 -1
- package/dist/src/commands/service-stub.d.ts +0 -8
- package/dist/src/commands/service-stub.js +0 -69
- package/dist/src/commands/service-stub.js.map +0 -1
|
@@ -40,3 +40,50 @@ export declare function formatEventTime(value: {
|
|
|
40
40
|
* Invalid input returns the original string unchanged.
|
|
41
41
|
*/
|
|
42
42
|
export declare function toLocalOffsetISO(input: string): string;
|
|
43
|
+
export type RangeEdge = "from" | "to";
|
|
44
|
+
/**
|
|
45
|
+
* Parse one range-flag value into an ISO instant, honoring per-edge day
|
|
46
|
+
* expansion and relative tokens. Anything that isn't a token or a bare date
|
|
47
|
+
* falls through to `parseDateishFlag` unchanged (instant semantics, existing
|
|
48
|
+
* error messages).
|
|
49
|
+
*/
|
|
50
|
+
export declare function parseRangeFlag(value: string, edge: RangeEdge, now?: Date): string;
|
|
51
|
+
/** Local midnight of the most recent `weekStartDay` (0=Sun … 6=Sat) on or before `now`. */
|
|
52
|
+
export declare function startOfWeek(now: Date, weekStartDay: number): Date;
|
|
53
|
+
export interface WindowInput {
|
|
54
|
+
/** Raw, unresolved flag values — resolution happens here so errors can quote what was typed. */
|
|
55
|
+
from?: string;
|
|
56
|
+
to?: string;
|
|
57
|
+
today?: boolean;
|
|
58
|
+
thisWeek?: boolean;
|
|
59
|
+
}
|
|
60
|
+
export interface WindowOptions {
|
|
61
|
+
/** Already-ISO fallbacks used when the corresponding flag is absent. */
|
|
62
|
+
defaults?: {
|
|
63
|
+
from?: string;
|
|
64
|
+
to?: string;
|
|
65
|
+
};
|
|
66
|
+
/** Flag spellings for error messages — `drive activity` uses --since/--until. */
|
|
67
|
+
flagNames?: {
|
|
68
|
+
from: string;
|
|
69
|
+
to: string;
|
|
70
|
+
};
|
|
71
|
+
/** 0=Sun … 6=Sat. Callers resolve this from the account before calling. */
|
|
72
|
+
weekStartDay?: number;
|
|
73
|
+
/**
|
|
74
|
+
* Whether the calling command actually offers --today/--this-week. False for
|
|
75
|
+
* `drive activity`, whose errors must not suggest flags it doesn't have
|
|
76
|
+
* (principles.md#no-dead-end-surfaces).
|
|
77
|
+
*/
|
|
78
|
+
shortcuts?: boolean;
|
|
79
|
+
now?: Date;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Resolve `--today` / `--this-week` / `--from` / `--to` into one validated
|
|
83
|
+
* window. Single source of truth for the shortcut-conflict and empty-window
|
|
84
|
+
* rules so no call site re-implements them.
|
|
85
|
+
*/
|
|
86
|
+
export declare function resolveWindow(input: WindowInput, options?: WindowOptions): {
|
|
87
|
+
from: string | undefined;
|
|
88
|
+
to: string | undefined;
|
|
89
|
+
};
|
|
@@ -87,4 +87,144 @@ export function toLocalOffsetISO(input) {
|
|
|
87
87
|
`T${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}` +
|
|
88
88
|
offsetStr);
|
|
89
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Local midnight of a day, optionally shifted by whole days.
|
|
92
|
+
*
|
|
93
|
+
* The local `Date` constructor with an out-of-range day component is what makes
|
|
94
|
+
* this DST-, month- and year-rollover-correct in one stroke. Never do this with
|
|
95
|
+
* millisecond addition: `+ 86_400_000` across a DST boundary lands on 23:00 or
|
|
96
|
+
* 01:00, not midnight.
|
|
97
|
+
*/
|
|
98
|
+
function localMidnight(parts, plusDays = 0) {
|
|
99
|
+
return new Date(parts.y, parts.m - 1, parts.d + plusDays, 0, 0, 0, 0);
|
|
100
|
+
}
|
|
101
|
+
function partsOf(date) {
|
|
102
|
+
return { y: date.getFullYear(), m: date.getMonth() + 1, d: date.getDate() };
|
|
103
|
+
}
|
|
104
|
+
function dayOffsetFrom(now, days) {
|
|
105
|
+
return { kind: "day", parts: partsOf(localMidnight(partsOf(now), days)) };
|
|
106
|
+
}
|
|
107
|
+
const RELATIVE_RE = /^([+-])(\d+)([dwh])$/;
|
|
108
|
+
const DATE_ONLY_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
109
|
+
/**
|
|
110
|
+
* Resolve a relative/named token. Returns undefined when `value` isn't one, so
|
|
111
|
+
* the caller can fall through to literal parsing.
|
|
112
|
+
*/
|
|
113
|
+
function resolveToken(value, now) {
|
|
114
|
+
const v = value.trim().toLowerCase();
|
|
115
|
+
switch (v) {
|
|
116
|
+
case "now":
|
|
117
|
+
return { kind: "instant", date: new Date(now.getTime()) };
|
|
118
|
+
case "today":
|
|
119
|
+
return dayOffsetFrom(now, 0);
|
|
120
|
+
case "tomorrow":
|
|
121
|
+
return dayOffsetFrom(now, 1);
|
|
122
|
+
case "yesterday":
|
|
123
|
+
return dayOffsetFrom(now, -1);
|
|
124
|
+
}
|
|
125
|
+
const rel = RELATIVE_RE.exec(v);
|
|
126
|
+
if (!rel)
|
|
127
|
+
return undefined;
|
|
128
|
+
const sign = rel[1] === "-" ? -1 : 1;
|
|
129
|
+
const n = Number(rel[2]);
|
|
130
|
+
const unit = rel[3];
|
|
131
|
+
// Hours are instant-precision (no day expansion); days/weeks are day-precision.
|
|
132
|
+
if (unit === "h") {
|
|
133
|
+
return { kind: "instant", date: new Date(now.getTime() + sign * n * 3600 * 1000) };
|
|
134
|
+
}
|
|
135
|
+
return dayOffsetFrom(now, sign * n * (unit === "w" ? 7 : 1));
|
|
136
|
+
}
|
|
137
|
+
function materialize(resolved, edge) {
|
|
138
|
+
if (resolved.kind === "instant")
|
|
139
|
+
return resolved.date.toISOString();
|
|
140
|
+
// Day precision: the `from` edge opens at that day's midnight, the `to` edge
|
|
141
|
+
// closes at the NEXT midnight so the named day is included (ranges are
|
|
142
|
+
// half-open). This is the whole point — `--from D --to D` is all of day D.
|
|
143
|
+
return localMidnight(resolved.parts, edge === "to" ? 1 : 0).toISOString();
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Parse one range-flag value into an ISO instant, honoring per-edge day
|
|
147
|
+
* expansion and relative tokens. Anything that isn't a token or a bare date
|
|
148
|
+
* falls through to `parseDateishFlag` unchanged (instant semantics, existing
|
|
149
|
+
* error messages).
|
|
150
|
+
*/
|
|
151
|
+
export function parseRangeFlag(value, edge, now = new Date()) {
|
|
152
|
+
if (!value) {
|
|
153
|
+
throw new AxiError("Missing date/time value", "VALIDATION_ERROR", [
|
|
154
|
+
"Use a date (2026-04-20), a datetime (2026-04-20T14:00), or a token (today, tomorrow, +7d)",
|
|
155
|
+
]);
|
|
156
|
+
}
|
|
157
|
+
const token = resolveToken(value, now);
|
|
158
|
+
if (token)
|
|
159
|
+
return materialize(token, edge);
|
|
160
|
+
if (DATE_ONLY_RE.test(value)) {
|
|
161
|
+
const [y, m, d] = value.split("-").map(Number);
|
|
162
|
+
const probe = localMidnight({ y, m, d });
|
|
163
|
+
if (Number.isNaN(probe.getTime())) {
|
|
164
|
+
throw new AxiError(`Cannot parse date: ${value}`, "VALIDATION_ERROR", [
|
|
165
|
+
"Use YYYY-MM-DD (e.g. 2026-04-20)",
|
|
166
|
+
]);
|
|
167
|
+
}
|
|
168
|
+
return materialize({ kind: "day", parts: { y, m, d } }, edge);
|
|
169
|
+
}
|
|
170
|
+
return parseDateishFlag(value);
|
|
171
|
+
}
|
|
172
|
+
/** Local midnight of the most recent `weekStartDay` (0=Sun … 6=Sat) on or before `now`. */
|
|
173
|
+
export function startOfWeek(now, weekStartDay) {
|
|
174
|
+
const back = (now.getDay() - weekStartDay + 7) % 7;
|
|
175
|
+
return localMidnight(partsOf(now), -back);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Resolve `--today` / `--this-week` / `--from` / `--to` into one validated
|
|
179
|
+
* window. Single source of truth for the shortcut-conflict and empty-window
|
|
180
|
+
* rules so no call site re-implements them.
|
|
181
|
+
*/
|
|
182
|
+
export function resolveWindow(input, options = {}) {
|
|
183
|
+
const now = options.now ?? new Date();
|
|
184
|
+
const names = options.flagNames ?? { from: "--from", to: "--to" };
|
|
185
|
+
const shortcuts = [];
|
|
186
|
+
if (input.today)
|
|
187
|
+
shortcuts.push("--today");
|
|
188
|
+
if (input.thisWeek)
|
|
189
|
+
shortcuts.push("--this-week");
|
|
190
|
+
if (shortcuts.length > 1) {
|
|
191
|
+
throw new AxiError(`Cannot combine ${shortcuts.join(" and ")}`, "VALIDATION_ERROR", [
|
|
192
|
+
"Pass one window shortcut, or an explicit range with " + `${names.from} / ${names.to}`,
|
|
193
|
+
]);
|
|
194
|
+
}
|
|
195
|
+
if (shortcuts.length === 1) {
|
|
196
|
+
const explicit = [
|
|
197
|
+
input.from !== undefined ? names.from : undefined,
|
|
198
|
+
input.to !== undefined ? names.to : undefined,
|
|
199
|
+
].filter(Boolean);
|
|
200
|
+
if (explicit.length > 0) {
|
|
201
|
+
throw new AxiError(`Cannot combine ${shortcuts[0]} with ${explicit.join(" / ")}`, "VALIDATION_ERROR", [
|
|
202
|
+
`Use ${shortcuts[0]} on its own for that window`,
|
|
203
|
+
`Or drop ${shortcuts[0]} and set the range explicitly with ${names.from} / ${names.to}`,
|
|
204
|
+
]);
|
|
205
|
+
}
|
|
206
|
+
const start = input.today
|
|
207
|
+
? localMidnight(partsOf(now))
|
|
208
|
+
: startOfWeek(now, options.weekStartDay ?? 1);
|
|
209
|
+
const span = input.today ? 1 : 7;
|
|
210
|
+
return {
|
|
211
|
+
from: start.toISOString(),
|
|
212
|
+
to: localMidnight(partsOf(start), span).toISOString(),
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
const from = input.from !== undefined ? parseRangeFlag(input.from, "from", now) : options.defaults?.from;
|
|
216
|
+
const to = input.to !== undefined ? parseRangeFlag(input.to, "to", now) : options.defaults?.to;
|
|
217
|
+
// A window that cannot match anything must never render as an empty list —
|
|
218
|
+
// "no events found in the given time range" reads as "nothing is scheduled".
|
|
219
|
+
if (from !== undefined && to !== undefined && new Date(from) >= new Date(to)) {
|
|
220
|
+
throw new AxiError(`Empty time range: ${names.from} ${toLocalOffsetISO(from)} is not before ${names.to} ${toLocalOffsetISO(to)}`, "VALIDATION_ERROR", [
|
|
221
|
+
`A date-only ${names.to} already covers that whole day — ${names.from} 2026-04-20 ${names.to} 2026-04-20 is all of April 20`,
|
|
222
|
+
...(options.shortcuts === false
|
|
223
|
+
? []
|
|
224
|
+
: ["Use --today for today, or --this-week for the current week"]),
|
|
225
|
+
`Otherwise make ${names.to} later than ${names.from}`,
|
|
226
|
+
]);
|
|
227
|
+
}
|
|
228
|
+
return { from, to };
|
|
229
|
+
}
|
|
90
230
|
//# sourceMappingURL=dateish.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dateish.js","sourceRoot":"","sources":["../../../../src/commands/calendar/dateish.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dateish.js","sourceRoot":"","sources":["../../../../src/commands/calendar/dateish.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { AxiError } from "axi-sdk-js";
|
|
3
|
+
import { parseDateishFlag, parseRangeFlag, resolveWindow, startOfWeek } from "./dateish.js";
|
|
4
|
+
// These tests assume the repo's configured local zone (America/New_York) for the
|
|
5
|
+
// DST cases; every other case is zone-agnostic. `now` is always injected, so no
|
|
6
|
+
// test depends on the wall clock.
|
|
7
|
+
/** Local wall-clock rendering of an instant, for zone-independent assertions. */
|
|
8
|
+
function local(iso) {
|
|
9
|
+
const d = new Date(iso);
|
|
10
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
11
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
|
12
|
+
}
|
|
13
|
+
/** Whole days spanned by a window, by local midnight count. */
|
|
14
|
+
function spanDays(from, to) {
|
|
15
|
+
return Math.round((new Date(to).getTime() - new Date(from).getTime()) / (24 * 3600 * 1000));
|
|
16
|
+
}
|
|
17
|
+
const NOW = new Date(2026, 7, 26, 14, 30, 0); // Wed 2026-08-26 14:30 local
|
|
18
|
+
describe("parseRangeFlag — per-edge precision", () => {
|
|
19
|
+
it("opens a date-only value at that day's local midnight on the from edge", () => {
|
|
20
|
+
expect(local(parseRangeFlag("2026-08-26", "from", NOW))).toBe("2026-08-26 00:00");
|
|
21
|
+
});
|
|
22
|
+
it("closes a date-only value at the NEXT local midnight on the to edge", () => {
|
|
23
|
+
expect(local(parseRangeFlag("2026-08-26", "to", NOW))).toBe("2026-08-27 00:00");
|
|
24
|
+
});
|
|
25
|
+
it("makes --from D --to D cover the whole of day D", () => {
|
|
26
|
+
const from = parseRangeFlag("2026-08-26", "from", NOW);
|
|
27
|
+
const to = parseRangeFlag("2026-08-26", "to", NOW);
|
|
28
|
+
expect(spanDays(from, to)).toBe(1);
|
|
29
|
+
});
|
|
30
|
+
it("keeps each edge independently monotonic", () => {
|
|
31
|
+
// The rejected design (expand only when from === to) would make these two
|
|
32
|
+
// windows identical. They must differ by exactly one day.
|
|
33
|
+
const from = parseRangeFlag("2026-08-26", "from", NOW);
|
|
34
|
+
const sameDay = parseRangeFlag("2026-08-26", "to", NOW);
|
|
35
|
+
const nextDay = parseRangeFlag("2026-08-27", "to", NOW);
|
|
36
|
+
expect(spanDays(from, sameDay)).toBe(1);
|
|
37
|
+
expect(spanDays(from, nextDay)).toBe(2);
|
|
38
|
+
});
|
|
39
|
+
it("leaves instant values untouched on both edges", () => {
|
|
40
|
+
expect(parseRangeFlag("2026-08-26T14:00:00-04:00", "from", NOW)).toBe(new Date("2026-08-26T14:00:00-04:00").toISOString());
|
|
41
|
+
expect(parseRangeFlag("2026-08-26T14:00:00-04:00", "to", NOW)).toBe(new Date("2026-08-26T14:00:00-04:00").toISOString());
|
|
42
|
+
});
|
|
43
|
+
it("treats a local datetime as local on both edges (no day expansion)", () => {
|
|
44
|
+
expect(local(parseRangeFlag("2026-08-26T00:00", "to", NOW))).toBe("2026-08-26 00:00");
|
|
45
|
+
});
|
|
46
|
+
it("rejects garbage through the existing parseDateishFlag error", () => {
|
|
47
|
+
expect(() => parseRangeFlag("next thursday", "from", NOW)).toThrow(AxiError);
|
|
48
|
+
expect(() => parseRangeFlag("", "from", NOW)).toThrow(/Missing date\/time value/);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe("parseRangeFlag — tokens", () => {
|
|
52
|
+
it("resolves now to the current instant", () => {
|
|
53
|
+
expect(parseRangeFlag("now", "to", NOW)).toBe(NOW.toISOString());
|
|
54
|
+
});
|
|
55
|
+
it("resolves day tokens with per-edge expansion", () => {
|
|
56
|
+
expect(local(parseRangeFlag("today", "from", NOW))).toBe("2026-08-26 00:00");
|
|
57
|
+
expect(local(parseRangeFlag("today", "to", NOW))).toBe("2026-08-27 00:00");
|
|
58
|
+
expect(local(parseRangeFlag("tomorrow", "from", NOW))).toBe("2026-08-27 00:00");
|
|
59
|
+
expect(local(parseRangeFlag("yesterday", "from", NOW))).toBe("2026-08-25 00:00");
|
|
60
|
+
});
|
|
61
|
+
it("resolves day and week offsets", () => {
|
|
62
|
+
expect(local(parseRangeFlag("+6d", "to", NOW))).toBe("2026-09-02 00:00");
|
|
63
|
+
expect(local(parseRangeFlag("-2d", "from", NOW))).toBe("2026-08-24 00:00");
|
|
64
|
+
expect(local(parseRangeFlag("+1w", "from", NOW))).toBe("2026-09-02 00:00");
|
|
65
|
+
expect(local(parseRangeFlag("-1w", "from", NOW))).toBe("2026-08-19 00:00");
|
|
66
|
+
});
|
|
67
|
+
it("treats hour offsets as instants, not days", () => {
|
|
68
|
+
expect(parseRangeFlag("+4h", "to", NOW)).toBe(new Date(NOW.getTime() + 4 * 3600 * 1000).toISOString());
|
|
69
|
+
});
|
|
70
|
+
it("composes into the rest of today and the next seven days", () => {
|
|
71
|
+
const restOfToday = {
|
|
72
|
+
from: parseRangeFlag("now", "from", NOW),
|
|
73
|
+
to: parseRangeFlag("today", "to", NOW),
|
|
74
|
+
};
|
|
75
|
+
expect(local(restOfToday.from)).toBe("2026-08-26 14:30");
|
|
76
|
+
expect(local(restOfToday.to)).toBe("2026-08-27 00:00");
|
|
77
|
+
const nextSeven = {
|
|
78
|
+
from: parseRangeFlag("today", "from", NOW),
|
|
79
|
+
to: parseRangeFlag("+6d", "to", NOW),
|
|
80
|
+
};
|
|
81
|
+
expect(spanDays(nextSeven.from, nextSeven.to)).toBe(7);
|
|
82
|
+
});
|
|
83
|
+
it("is case- and whitespace-insensitive", () => {
|
|
84
|
+
expect(parseRangeFlag(" Today ", "from", NOW)).toBe(parseRangeFlag("today", "from", NOW));
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
describe("local-calendar arithmetic", () => {
|
|
88
|
+
it("rolls over a month boundary", () => {
|
|
89
|
+
const eom = new Date(2026, 7, 31, 9, 0, 0); // Aug 31
|
|
90
|
+
expect(local(parseRangeFlag("+1d", "from", eom))).toBe("2026-09-01 00:00");
|
|
91
|
+
});
|
|
92
|
+
it("rolls over a year boundary", () => {
|
|
93
|
+
const eoy = new Date(2026, 11, 31, 9, 0, 0); // Dec 31
|
|
94
|
+
expect(local(parseRangeFlag("+1d", "from", eoy))).toBe("2027-01-01 00:00");
|
|
95
|
+
});
|
|
96
|
+
it("lands on local midnight across a spring-forward DST transition", () => {
|
|
97
|
+
// 2026-03-08 is the US spring-forward date; that day is only 23h long, so
|
|
98
|
+
// millisecond addition would land on 01:00 rather than midnight.
|
|
99
|
+
const beforeDst = new Date(2026, 2, 7, 12, 0, 0);
|
|
100
|
+
expect(local(parseRangeFlag("+1d", "from", beforeDst))).toBe("2026-03-08 00:00");
|
|
101
|
+
expect(local(parseRangeFlag("+2d", "from", beforeDst))).toBe("2026-03-09 00:00");
|
|
102
|
+
});
|
|
103
|
+
it("lands on local midnight across a fall-back DST transition", () => {
|
|
104
|
+
// 2026-11-01 is the US fall-back date (25h long).
|
|
105
|
+
const beforeDst = new Date(2026, 9, 31, 12, 0, 0);
|
|
106
|
+
expect(local(parseRangeFlag("+1d", "from", beforeDst))).toBe("2026-11-01 00:00");
|
|
107
|
+
expect(local(parseRangeFlag("+2d", "from", beforeDst))).toBe("2026-11-02 00:00");
|
|
108
|
+
});
|
|
109
|
+
it("closes a date-only to edge at midnight even when that day is 23h long", () => {
|
|
110
|
+
expect(local(parseRangeFlag("2026-03-08", "to", NOW))).toBe("2026-03-09 00:00");
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
describe("startOfWeek", () => {
|
|
114
|
+
const wednesday = new Date(2026, 7, 26, 14, 30, 0); // Wed
|
|
115
|
+
const sunday = new Date(2026, 7, 30, 9, 0, 0);
|
|
116
|
+
const monday = new Date(2026, 7, 24, 9, 0, 0);
|
|
117
|
+
it("walks back to the configured start day (Monday)", () => {
|
|
118
|
+
expect(local(startOfWeek(wednesday, 1).toISOString())).toBe("2026-08-24 00:00");
|
|
119
|
+
expect(local(startOfWeek(sunday, 1).toISOString())).toBe("2026-08-24 00:00");
|
|
120
|
+
expect(local(startOfWeek(monday, 1).toISOString())).toBe("2026-08-24 00:00");
|
|
121
|
+
});
|
|
122
|
+
it("walks back to the configured start day (Sunday)", () => {
|
|
123
|
+
expect(local(startOfWeek(wednesday, 0).toISOString())).toBe("2026-08-23 00:00");
|
|
124
|
+
expect(local(startOfWeek(sunday, 0).toISOString())).toBe("2026-08-30 00:00");
|
|
125
|
+
expect(local(startOfWeek(monday, 0).toISOString())).toBe("2026-08-23 00:00");
|
|
126
|
+
});
|
|
127
|
+
it("walks back to the configured start day (Saturday)", () => {
|
|
128
|
+
expect(local(startOfWeek(wednesday, 6).toISOString())).toBe("2026-08-22 00:00");
|
|
129
|
+
expect(local(startOfWeek(sunday, 6).toISOString())).toBe("2026-08-29 00:00");
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
describe("resolveWindow — shortcuts", () => {
|
|
133
|
+
it("--today covers exactly today", () => {
|
|
134
|
+
const w = resolveWindow({ today: true }, { now: NOW });
|
|
135
|
+
expect(local(w.from)).toBe("2026-08-26 00:00");
|
|
136
|
+
expect(local(w.to)).toBe("2026-08-27 00:00");
|
|
137
|
+
});
|
|
138
|
+
it("--this-week spans seven days from the configured start day", () => {
|
|
139
|
+
for (const day of [0, 1, 6]) {
|
|
140
|
+
const w = resolveWindow({ thisWeek: true }, { now: NOW, weekStartDay: day });
|
|
141
|
+
expect(local(w.from)).toBe(local(startOfWeek(NOW, day).toISOString()));
|
|
142
|
+
expect(spanDays(w.from, w.to)).toBe(7);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
it("--this-week defaults to Monday when no week start is supplied", () => {
|
|
146
|
+
const w = resolveWindow({ thisWeek: true }, { now: NOW });
|
|
147
|
+
expect(local(w.from)).toBe("2026-08-24 00:00");
|
|
148
|
+
expect(local(w.to)).toBe("2026-08-31 00:00");
|
|
149
|
+
});
|
|
150
|
+
it("--this-week still spans seven local days across a DST transition", () => {
|
|
151
|
+
const dstWeek = new Date(2026, 2, 10, 12, 0, 0); // week containing spring-forward
|
|
152
|
+
const w = resolveWindow({ thisWeek: true }, { now: dstWeek, weekStartDay: 1 });
|
|
153
|
+
expect(local(w.from)).toBe("2026-03-09 00:00");
|
|
154
|
+
expect(local(w.to)).toBe("2026-03-16 00:00");
|
|
155
|
+
});
|
|
156
|
+
it("rejects two shortcuts at once", () => {
|
|
157
|
+
expect(() => resolveWindow({ today: true, thisWeek: true }, { now: NOW })).toThrow(/Cannot combine --today and --this-week/);
|
|
158
|
+
});
|
|
159
|
+
it("rejects a shortcut combined with an explicit edge", () => {
|
|
160
|
+
expect(() => resolveWindow({ today: true, from: "2026-08-26" }, { now: NOW })).toThrow(/Cannot combine --today with --from/);
|
|
161
|
+
expect(() => resolveWindow({ thisWeek: true, to: "2026-08-26" }, { now: NOW })).toThrow(/Cannot combine --this-week with --to/);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
describe("resolveWindow — empty windows and defaults", () => {
|
|
165
|
+
it("rejects a zero-width window rather than returning nothing", () => {
|
|
166
|
+
// The originating bug: this used to silently produce `count: 0`.
|
|
167
|
+
expect(() => resolveWindow({ from: "2026-08-26T00:00", to: "2026-08-26T00:00" }, { now: NOW })).toThrow(/Empty time range/);
|
|
168
|
+
});
|
|
169
|
+
it("rejects an inverted window", () => {
|
|
170
|
+
expect(() => resolveWindow({ from: "2026-08-26T10:00", to: "2026-08-26T09:00" }, { now: NOW })).toThrow(/is not before/);
|
|
171
|
+
});
|
|
172
|
+
it("accepts the date-only same-day window that used to be empty", () => {
|
|
173
|
+
const w = resolveWindow({ from: "2026-08-26", to: "2026-08-26" }, { now: NOW });
|
|
174
|
+
expect(spanDays(w.from, w.to)).toBe(1);
|
|
175
|
+
});
|
|
176
|
+
it("names the caller's own flag spellings in the error", () => {
|
|
177
|
+
expect(() => resolveWindow({ from: "2026-08-26T10:00", to: "2026-08-26T09:00" }, { now: NOW, flagNames: { from: "--since", to: "--until" } })).toThrow(/--since .* is not before --until/);
|
|
178
|
+
});
|
|
179
|
+
it("falls back to defaults for absent edges", () => {
|
|
180
|
+
const w = resolveWindow({ to: "2026-08-30" }, { now: NOW, defaults: { from: "2026-08-01T00:00:00.000Z", to: "2026-09-01T00:00:00.000Z" } });
|
|
181
|
+
expect(w.from).toBe("2026-08-01T00:00:00.000Z");
|
|
182
|
+
expect(local(w.to)).toBe("2026-08-31 00:00");
|
|
183
|
+
});
|
|
184
|
+
it("leaves both edges undefined when neither flag nor default is present", () => {
|
|
185
|
+
expect(resolveWindow({}, { now: NOW })).toEqual({ from: undefined, to: undefined });
|
|
186
|
+
});
|
|
187
|
+
it("skips the empty-window check when only one edge is set", () => {
|
|
188
|
+
const w = resolveWindow({ from: "2026-08-26" }, { now: NOW });
|
|
189
|
+
expect(w.to).toBeUndefined();
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
describe("parseDateishFlag is unchanged by the range layer", () => {
|
|
193
|
+
it("still resolves a date-only value to that day's local midnight", () => {
|
|
194
|
+
// `calendar create --start 2026-08-26` means midnight, NOT end of day.
|
|
195
|
+
expect(local(parseDateishFlag("2026-08-26"))).toBe("2026-08-26 00:00");
|
|
196
|
+
});
|
|
197
|
+
it("does not accept range tokens", () => {
|
|
198
|
+
expect(() => parseDateishFlag("today")).toThrow(AxiError);
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
describe("resolveWindow — suggestion targeting", () => {
|
|
202
|
+
it("suggests the shortcuts when the caller offers them", () => {
|
|
203
|
+
try {
|
|
204
|
+
resolveWindow({ from: "2026-08-26T10:00", to: "2026-08-26T09:00" }, { now: NOW });
|
|
205
|
+
expect.unreachable();
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
expect(err.suggestions.join(" ")).toMatch(/--today/);
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
it("omits them for a command that has no such flags", () => {
|
|
212
|
+
// `drive activity` takes --since/--until only; suggesting --today there
|
|
213
|
+
// would be a dead-end (principles.md#no-dead-end-surfaces).
|
|
214
|
+
try {
|
|
215
|
+
resolveWindow({ from: "2026-08-26T10:00", to: "2026-08-26T09:00" }, { now: NOW, shortcuts: false, flagNames: { from: "--since", to: "--until" } });
|
|
216
|
+
expect.unreachable();
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
expect(err.suggestions.join(" ")).not.toMatch(/--today/);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
//# sourceMappingURL=dateish.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dateish.test.js","sourceRoot":"","sources":["../../../../src/commands/calendar/dateish.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const EVENTS_HELP = "usage: gws-axi calendar events [flags]\nflags[
|
|
1
|
+
export declare const EVENTS_HELP = "usage: gws-axi calendar events [flags]\nflags[10]:\n --calendar <id> Calendar to query (default: \"primary\")\n --today Just today (local calendar day)\n --this-week The current week (starts on your Google Calendar's\n configured first day of the week)\n --from <when> Earliest event start (default: now)\n --to <when> Latest event start (default: 7 days from now)\n --limit <n> Max events to return (default: 100, max: 2500)\n --query <text> Full-text search across summary/description/location/attendees\n --single-events Expand recurring events into individual instances (default: true)\n --fields <list> Extra columns: status, organizer, location, attendees, description, htmlLink, hangoutLink, join_url, conference, conference_source\n --account <email> Account override when 2+ are configured\nexamples:\n gws-axi calendar events --today\n gws-axi calendar events --this-week\n gws-axi calendar events --from 2026-04-20 --to 2026-04-20 (all of Apr 20)\n gws-axi calendar events --from 2026-04-20T00:00 --to 2026-04-21T00:00\n gws-axi calendar events --calendar team@jarv.us --limit 50\n gws-axi calendar events --query standup\n gws-axi calendar events --fields status,attendees,location\n gws-axi calendar events --fields join_url,conference\ntime formats / ranges:\n Ranges are half-open: [--from, --to).\n Date-only: 2026-04-20 denotes the DAY \u2014 --from opens at its\n midnight, --to closes at the END of it. So\n --from 2026-04-20 --to 2026-04-20 is all of Apr 20.\n (--to 2026-04-20 and --to 2026-04-20T00:00 therefore\n differ by 24h \u2014 day granularity in, day boundary out.)\n Local time: 2026-04-20T14:00 (interpreted as local tz)\n With offset: 2026-04-20T14:00:00-04:00 (preserved as written)\n Tokens: now, today, tomorrow, yesterday, +Nd/-Nd, +Nw/-Nw\n (day precision), +Nh/-Nh (instant). Compose them:\n --from now --to today (rest of today)\n --from today --to +6d (next seven days)\noutput note:\n The start/end columns use datetime (with offset) for timed events\n and date-only strings for all-day events. Agents parsing these\n columns must handle both formats.\ndefault columns:\n id, summary, start, end, my_response (your responseStatus if you're\n an attendee; blank for self-organized events with no attendee list),\n attachments (compact count; \"(N Docs)\" suffix when meeting notes /\n Gemini Notes Docs are attached \u2014 chase any with `calendar get <id>`\n to see file_ids and hand off to `docs read`).\n status column suppressed by default (most events are \"confirmed\" \u2014\n add --fields status to see cancelled/tentative).\nconferencing:\n --fields join_url provider-uniform join link \u2014 resolves from\n structured conferenceData (Meet + Calendar add-on\n Zoom/Teams/Webex), then hangoutLink, then a\n provider-anchored URL scraped from the description\n or location (externally-organized Teams/Zoom/Webex\n meetings carry no conferenceData).\n --fields conference provider label (Google Meet / Zoom / Microsoft\n Teams / Webex).\n --fields conference_source where join_url came from: conferenceData |\n hangoutLink | description | location. A\n description/location value means a best-effort\n scrape \u2014 verify before use.\n";
|
|
2
2
|
export declare function calendarEventsCommand(account: string, args: string[]): Promise<string>;
|
|
@@ -2,28 +2,43 @@ import { AxiError } from "axi-sdk-js";
|
|
|
2
2
|
import { calendarClient, translateGoogleError } from "../../google/client.js";
|
|
3
3
|
import { computed, field, mapEnum, pluck, renderListResponse, truncated, } from "../../output/index.js";
|
|
4
4
|
import { extractConference, resolveJoinUrl } from "./conference.js";
|
|
5
|
-
import {
|
|
5
|
+
import { resolveWindow, toLocalOffsetISO } from "./dateish.js";
|
|
6
|
+
import { resolveWeekStart } from "./week-start.js";
|
|
6
7
|
export const EVENTS_HELP = `usage: gws-axi calendar events [flags]
|
|
7
|
-
flags[
|
|
8
|
+
flags[10]:
|
|
8
9
|
--calendar <id> Calendar to query (default: "primary")
|
|
9
|
-
--
|
|
10
|
-
--
|
|
10
|
+
--today Just today (local calendar day)
|
|
11
|
+
--this-week The current week (starts on your Google Calendar's
|
|
12
|
+
configured first day of the week)
|
|
13
|
+
--from <when> Earliest event start (default: now)
|
|
14
|
+
--to <when> Latest event start (default: 7 days from now)
|
|
11
15
|
--limit <n> Max events to return (default: 100, max: 2500)
|
|
12
16
|
--query <text> Full-text search across summary/description/location/attendees
|
|
13
17
|
--single-events Expand recurring events into individual instances (default: true)
|
|
14
18
|
--fields <list> Extra columns: status, organizer, location, attendees, description, htmlLink, hangoutLink, join_url, conference, conference_source
|
|
15
19
|
--account <email> Account override when 2+ are configured
|
|
16
20
|
examples:
|
|
17
|
-
gws-axi calendar events
|
|
21
|
+
gws-axi calendar events --today
|
|
22
|
+
gws-axi calendar events --this-week
|
|
23
|
+
gws-axi calendar events --from 2026-04-20 --to 2026-04-20 (all of Apr 20)
|
|
18
24
|
gws-axi calendar events --from 2026-04-20T00:00 --to 2026-04-21T00:00
|
|
19
25
|
gws-axi calendar events --calendar team@jarv.us --limit 50
|
|
20
26
|
gws-axi calendar events --query standup
|
|
21
27
|
gws-axi calendar events --fields status,attendees,location
|
|
22
28
|
gws-axi calendar events --fields join_url,conference
|
|
23
|
-
time formats:
|
|
24
|
-
|
|
29
|
+
time formats / ranges:
|
|
30
|
+
Ranges are half-open: [--from, --to).
|
|
31
|
+
Date-only: 2026-04-20 denotes the DAY — --from opens at its
|
|
32
|
+
midnight, --to closes at the END of it. So
|
|
33
|
+
--from 2026-04-20 --to 2026-04-20 is all of Apr 20.
|
|
34
|
+
(--to 2026-04-20 and --to 2026-04-20T00:00 therefore
|
|
35
|
+
differ by 24h — day granularity in, day boundary out.)
|
|
25
36
|
Local time: 2026-04-20T14:00 (interpreted as local tz)
|
|
26
|
-
|
|
37
|
+
With offset: 2026-04-20T14:00:00-04:00 (preserved as written)
|
|
38
|
+
Tokens: now, today, tomorrow, yesterday, +Nd/-Nd, +Nw/-Nw
|
|
39
|
+
(day precision), +Nh/-Nh (instant). Compose them:
|
|
40
|
+
--from now --to today (rest of today)
|
|
41
|
+
--from today --to +6d (next seven days)
|
|
27
42
|
output note:
|
|
28
43
|
The start/end columns use datetime (with offset) for timed events
|
|
29
44
|
and date-only strings for all-day events. Agents parsing these
|
|
@@ -53,8 +68,10 @@ conferencing:
|
|
|
53
68
|
function parseEventsFlags(args) {
|
|
54
69
|
const flags = {
|
|
55
70
|
calendar: "primary",
|
|
56
|
-
from:
|
|
57
|
-
to:
|
|
71
|
+
from: undefined,
|
|
72
|
+
to: undefined,
|
|
73
|
+
today: false,
|
|
74
|
+
thisWeek: false,
|
|
58
75
|
limit: 100,
|
|
59
76
|
query: undefined,
|
|
60
77
|
singleEvents: true,
|
|
@@ -69,13 +86,19 @@ function parseEventsFlags(args) {
|
|
|
69
86
|
i++;
|
|
70
87
|
break;
|
|
71
88
|
case "--from":
|
|
72
|
-
flags.from =
|
|
89
|
+
flags.from = next;
|
|
73
90
|
i++;
|
|
74
91
|
break;
|
|
75
92
|
case "--to":
|
|
76
|
-
flags.to =
|
|
93
|
+
flags.to = next;
|
|
77
94
|
i++;
|
|
78
95
|
break;
|
|
96
|
+
case "--today":
|
|
97
|
+
flags.today = true;
|
|
98
|
+
break;
|
|
99
|
+
case "--this-week":
|
|
100
|
+
flags.thisWeek = true;
|
|
101
|
+
break;
|
|
79
102
|
case "--limit":
|
|
80
103
|
flags.limit = Math.min(2500, Math.max(1, parseInt(next, 10) || 100));
|
|
81
104
|
i++;
|
|
@@ -216,11 +239,25 @@ function schemaWithExtras(extras) {
|
|
|
216
239
|
}
|
|
217
240
|
export async function calendarEventsCommand(account, args) {
|
|
218
241
|
const flags = parseEventsFlags(args);
|
|
242
|
+
// Only a week shortcut needs the account's weekStart preference — keep every
|
|
243
|
+
// other invocation to a single round trip.
|
|
244
|
+
const weekStart = flags.thisWeek ? await resolveWeekStart(account) : undefined;
|
|
245
|
+
const now = new Date();
|
|
246
|
+
const window = resolveWindow(flags, {
|
|
247
|
+
defaults: {
|
|
248
|
+
from: now.toISOString(),
|
|
249
|
+
to: new Date(now.getTime() + 7 * 24 * 3600 * 1000).toISOString(),
|
|
250
|
+
},
|
|
251
|
+
weekStartDay: weekStart?.day,
|
|
252
|
+
now,
|
|
253
|
+
});
|
|
254
|
+
const from = window.from;
|
|
255
|
+
const to = window.to;
|
|
219
256
|
const api = await calendarClient(account);
|
|
220
257
|
const requestParams = {
|
|
221
258
|
calendarId: flags.calendar,
|
|
222
|
-
timeMin:
|
|
223
|
-
timeMax:
|
|
259
|
+
timeMin: from,
|
|
260
|
+
timeMax: to,
|
|
224
261
|
maxResults: flags.limit,
|
|
225
262
|
singleEvents: flags.singleEvents,
|
|
226
263
|
orderBy: flags.singleEvents ? "startTime" : undefined,
|
|
@@ -254,8 +291,11 @@ export async function calendarEventsCommand(account, args) {
|
|
|
254
291
|
}
|
|
255
292
|
const summary = {
|
|
256
293
|
count: items.length,
|
|
257
|
-
range: `${
|
|
294
|
+
range: `${toLocalOffsetISO(from)} → ${toLocalOffsetISO(to)}`,
|
|
258
295
|
};
|
|
296
|
+
if (weekStart) {
|
|
297
|
+
summary.week_start = `${weekStart.label} (${weekStart.source})`;
|
|
298
|
+
}
|
|
259
299
|
if (flags.query) {
|
|
260
300
|
summary.query = flags.query;
|
|
261
301
|
}
|
|
@@ -290,7 +330,10 @@ export async function calendarEventsCommand(account, args) {
|
|
|
290
330
|
if (flags.query) {
|
|
291
331
|
suggestions.push(`Remove --query to show all events in the range, or try a broader search term`);
|
|
292
332
|
}
|
|
293
|
-
suggestions.push(`Broaden the time range with --from / --to (current: ${
|
|
333
|
+
suggestions.push(`Broaden the time range with --from / --to (current: ${toLocalOffsetISO(from)} → ${toLocalOffsetISO(to)})`);
|
|
334
|
+
if (!flags.thisWeek) {
|
|
335
|
+
suggestions.push(`Try \`--this-week\` for the current week, or \`--today\` for just today`);
|
|
336
|
+
}
|
|
294
337
|
if (flags.calendar === "primary") {
|
|
295
338
|
suggestions.push(`Try a different calendar with \`--calendar <id>\` (list them with \`gws-axi calendar calendars\`)`);
|
|
296
339
|
}
|