zele 0.1.2 → 0.2.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/AGENTS.md +4 -0
- package/CHANGELOG.md +36 -0
- package/README.md +112 -0
- package/dist/api-utils.d.ts +6 -0
- package/dist/api-utils.js +52 -0
- package/dist/api-utils.js.map +1 -0
- package/dist/auth.d.ts +16 -0
- package/dist/auth.js +74 -5
- package/dist/auth.js.map +1 -1
- package/dist/calendar-client.d.ts +135 -0
- package/dist/calendar-client.js +498 -0
- package/dist/calendar-client.js.map +1 -0
- package/dist/calendar-time.d.ts +24 -0
- package/dist/calendar-time.js +245 -0
- package/dist/calendar-time.js.map +1 -0
- package/dist/cli.js +5 -3
- package/dist/cli.js.map +1 -1
- package/dist/commands/auth-cmd.js +5 -5
- package/dist/commands/auth-cmd.js.map +1 -1
- package/dist/commands/calendar.d.ts +2 -0
- package/dist/commands/calendar.js +563 -0
- package/dist/commands/calendar.js.map +1 -0
- package/dist/generated/browser.d.ts +10 -0
- package/dist/generated/client.d.ts +10 -0
- package/dist/generated/internal/class.d.ts +22 -0
- package/dist/generated/internal/class.js +2 -2
- package/dist/generated/internal/class.js.map +1 -1
- package/dist/generated/internal/prismaNamespace.d.ts +174 -1
- package/dist/generated/internal/prismaNamespace.js +21 -0
- package/dist/generated/internal/prismaNamespace.js.map +1 -1
- package/dist/generated/internal/prismaNamespaceBrowser.d.ts +23 -0
- package/dist/generated/internal/prismaNamespaceBrowser.js +21 -0
- package/dist/generated/internal/prismaNamespaceBrowser.js.map +1 -1
- package/dist/generated/models/accounts.d.ts +281 -0
- package/dist/generated/models/calendar_events.d.ts +1433 -0
- package/dist/generated/models/calendar_events.js +2 -0
- package/dist/generated/models/calendar_events.js.map +1 -0
- package/dist/generated/models/calendar_lists.d.ts +1131 -0
- package/dist/generated/models/calendar_lists.js +2 -0
- package/dist/generated/models/calendar_lists.js.map +1 -0
- package/dist/generated/models.d.ts +2 -0
- package/dist/gmail-cache.d.ts +22 -0
- package/dist/gmail-cache.js +76 -0
- package/dist/gmail-cache.js.map +1 -1
- package/dist/gmail-client.js +1 -48
- package/dist/gmail-client.js.map +1 -1
- package/dist/output.d.ts +11 -0
- package/dist/output.js +42 -0
- package/dist/output.js.map +1 -1
- package/package.json +4 -2
- package/schema.prisma +39 -6
- package/scripts/test-device-code-clients.ts +186 -0
- package/scripts/test-micropython-scopes.ts +72 -0
- package/scripts/test-oauth-clients.ts +257 -0
- package/src/api-utils.ts +60 -0
- package/src/auth.ts +92 -5
- package/src/calendar-client.ts +758 -0
- package/src/calendar-time.ts +299 -0
- package/src/cli.ts +5 -3
- package/src/commands/auth-cmd.ts +5 -5
- package/src/commands/calendar.ts +634 -0
- package/src/gmail-cache.ts +96 -0
- package/src/gmail-client.ts +1 -57
- package/src/output.ts +51 -0
- package/src/schema.sql +22 -0
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
// CalDAV-based calendar client for CLI use.
|
|
2
|
+
// Uses tsdav for CalDAV protocol and ts-ics for typed iCalendar parse/generate.
|
|
3
|
+
// Auth: passes a Bearer token via headers (reuses existing google-auth-library OAuth2).
|
|
4
|
+
// Google CalDAV endpoint: https://apidata.googleusercontent.com/caldav/v2/
|
|
5
|
+
import { fetchCalendars, fetchCalendarObjects, createCalendarObject, updateCalendarObject, deleteCalendarObject, } from 'tsdav';
|
|
6
|
+
import { convertIcsCalendar, generateIcsCalendar, } from 'ts-ics';
|
|
7
|
+
import crypto from 'node:crypto';
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// ts-ics conversion helpers
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
/** Convert an IcsDateObject to an RFC3339 string or YYYY-MM-DD date string */
|
|
12
|
+
function icsDateToString(d) {
|
|
13
|
+
if (d.type === 'DATE') {
|
|
14
|
+
// All-day: return YYYY-MM-DD
|
|
15
|
+
return d.date.toISOString().split('T')[0];
|
|
16
|
+
}
|
|
17
|
+
return d.date.toISOString();
|
|
18
|
+
}
|
|
19
|
+
/** Map ts-ics PARTSTAT to our lowercase status */
|
|
20
|
+
function mapPartstat(partstat) {
|
|
21
|
+
if (!partstat)
|
|
22
|
+
return 'needsAction';
|
|
23
|
+
switch (partstat) {
|
|
24
|
+
case 'ACCEPTED': return 'accepted';
|
|
25
|
+
case 'DECLINED': return 'declined';
|
|
26
|
+
case 'TENTATIVE': return 'tentative';
|
|
27
|
+
case 'NEEDS-ACTION': return 'needsAction';
|
|
28
|
+
default: return partstat.toLowerCase();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** Create an IcsDateObject from an RFC3339 string or YYYY-MM-DD */
|
|
32
|
+
function toIcsDate(dateStr, allDay = false) {
|
|
33
|
+
if (allDay || /^\d{4}-\d{2}-\d{2}$/.test(dateStr)) {
|
|
34
|
+
return { date: new Date(dateStr + 'T00:00:00Z'), type: 'DATE' };
|
|
35
|
+
}
|
|
36
|
+
return { date: new Date(dateStr), type: 'DATE-TIME' };
|
|
37
|
+
}
|
|
38
|
+
/** Generate a new UID for calendar events */
|
|
39
|
+
function generateUID() {
|
|
40
|
+
return `${crypto.randomUUID()}@zele`;
|
|
41
|
+
}
|
|
42
|
+
/** Convert a single IcsEvent to our CalendarEvent type */
|
|
43
|
+
function icsEventToCalendarEvent(event, calObj) {
|
|
44
|
+
const allDay = event.start.type === 'DATE';
|
|
45
|
+
const startStr = icsDateToString(event.start);
|
|
46
|
+
// ts-ics events have either `end` or `duration`
|
|
47
|
+
const endDate = event.end
|
|
48
|
+
? icsDateToString(event.end)
|
|
49
|
+
: startStr; // fallback if no end
|
|
50
|
+
// Attendees
|
|
51
|
+
const attendees = (event.attendees ?? []).map((a) => ({
|
|
52
|
+
email: a.email,
|
|
53
|
+
name: a.name ?? null,
|
|
54
|
+
status: mapPartstat(a.partstat),
|
|
55
|
+
self: false,
|
|
56
|
+
organizer: false,
|
|
57
|
+
}));
|
|
58
|
+
// Mark organizer in attendees
|
|
59
|
+
if (event.organizer) {
|
|
60
|
+
for (const a of attendees) {
|
|
61
|
+
if (a.email.toLowerCase() === event.organizer.email.toLowerCase()) {
|
|
62
|
+
a.organizer = true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Extract Meet link from description
|
|
67
|
+
let meetLink = null;
|
|
68
|
+
const desc = event.description ?? '';
|
|
69
|
+
const meetMatch = desc.match(/https:\/\/meet\.google\.com\/[\w-]+/);
|
|
70
|
+
if (meetMatch)
|
|
71
|
+
meetLink = meetMatch[0];
|
|
72
|
+
// Recurrence rules — convert back to RRULE string if present
|
|
73
|
+
const recurrence = [];
|
|
74
|
+
if (event.recurrenceRule) {
|
|
75
|
+
// ts-ics stores parsed rule; we'd need to re-serialize — store as-is for display
|
|
76
|
+
const r = event.recurrenceRule;
|
|
77
|
+
const parts = [`FREQ=${r.frequency}`];
|
|
78
|
+
if (r.interval)
|
|
79
|
+
parts.push(`INTERVAL=${r.interval}`);
|
|
80
|
+
if (r.count)
|
|
81
|
+
parts.push(`COUNT=${r.count}`);
|
|
82
|
+
if (r.until)
|
|
83
|
+
parts.push(`UNTIL=${icsDateToString(r.until).replace(/[-:]/g, '')}`);
|
|
84
|
+
if (r.byDay)
|
|
85
|
+
parts.push(`BYDAY=${r.byDay.map((d) => (d.occurrence ?? '') + d.day).join(',')}`);
|
|
86
|
+
if (r.byMonth)
|
|
87
|
+
parts.push(`BYMONTH=${r.byMonth.join(',')}`);
|
|
88
|
+
if (r.byMonthday)
|
|
89
|
+
parts.push(`BYMONTHDAY=${r.byMonthday.join(',')}`);
|
|
90
|
+
recurrence.push(`RRULE:${parts.join(';')}`);
|
|
91
|
+
}
|
|
92
|
+
// Reminders from alarms
|
|
93
|
+
const reminders = (event.alarms ?? []).map((alarm) => {
|
|
94
|
+
let minutes = 0;
|
|
95
|
+
if (alarm.trigger.type === 'relative') {
|
|
96
|
+
const d = alarm.trigger.value;
|
|
97
|
+
minutes = (d.weeks ?? 0) * 10080 + (d.days ?? 0) * 1440 + (d.hours ?? 0) * 60 + (d.minutes ?? 0);
|
|
98
|
+
}
|
|
99
|
+
return { method: alarm.action ?? 'popup', minutes };
|
|
100
|
+
});
|
|
101
|
+
return {
|
|
102
|
+
id: event.uid,
|
|
103
|
+
summary: event.summary || '(no title)',
|
|
104
|
+
start: startStr,
|
|
105
|
+
end: endDate,
|
|
106
|
+
startDate: allDay ? startStr : undefined,
|
|
107
|
+
endDate: allDay ? endDate : undefined,
|
|
108
|
+
allDay,
|
|
109
|
+
description: desc,
|
|
110
|
+
location: event.location ?? '',
|
|
111
|
+
status: (event.status ?? 'CONFIRMED').toLowerCase(),
|
|
112
|
+
htmlLink: '',
|
|
113
|
+
meetLink,
|
|
114
|
+
attendees,
|
|
115
|
+
recurrence,
|
|
116
|
+
reminders,
|
|
117
|
+
colorId: null,
|
|
118
|
+
visibility: event.class === 'PRIVATE' ? 'private' : 'default',
|
|
119
|
+
transparency: event.timeTransparent === 'TRANSPARENT' ? 'transparent' : 'opaque',
|
|
120
|
+
url: calObj?.url,
|
|
121
|
+
etag: calObj?.etag,
|
|
122
|
+
uid: event.uid,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/** Parse all events from a raw iCal data string using ts-ics */
|
|
126
|
+
function parseICalData(data, calObj) {
|
|
127
|
+
try {
|
|
128
|
+
const calendar = convertIcsCalendar(undefined, data);
|
|
129
|
+
return (calendar.events ?? []).map((ev) => icsEventToCalendarEvent(ev, calObj));
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
console.error('[calendar] failed to parse iCal data:', err instanceof Error ? err.stack ?? err.message : err);
|
|
133
|
+
return [];
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/** Build an iCal string from event properties using ts-ics */
|
|
137
|
+
function buildICalString(props) {
|
|
138
|
+
const uid = props.uid ?? generateUID();
|
|
139
|
+
const now = { date: new Date(), type: 'DATE-TIME' };
|
|
140
|
+
const event = {
|
|
141
|
+
uid,
|
|
142
|
+
summary: props.summary,
|
|
143
|
+
stamp: now,
|
|
144
|
+
start: toIcsDate(props.start, props.allDay),
|
|
145
|
+
end: toIcsDate(props.end, props.allDay),
|
|
146
|
+
};
|
|
147
|
+
if (props.description)
|
|
148
|
+
event.description = props.description;
|
|
149
|
+
if (props.location)
|
|
150
|
+
event.location = props.location;
|
|
151
|
+
if (props.status)
|
|
152
|
+
event.status = props.status.toUpperCase();
|
|
153
|
+
if (props.transparency)
|
|
154
|
+
event.timeTransparent = props.transparency.toUpperCase();
|
|
155
|
+
if (props.visibility === 'private')
|
|
156
|
+
event.class = 'PRIVATE';
|
|
157
|
+
if (props.sequence !== undefined)
|
|
158
|
+
event.sequence = props.sequence;
|
|
159
|
+
if (props.organizer) {
|
|
160
|
+
event.organizer = { email: props.organizer.email, name: props.organizer.name };
|
|
161
|
+
}
|
|
162
|
+
if (props.attendees && props.attendees.length > 0) {
|
|
163
|
+
event.attendees = props.attendees.map((a) => ({
|
|
164
|
+
email: a.email,
|
|
165
|
+
name: a.name,
|
|
166
|
+
partstat: a.partstat ?? 'NEEDS-ACTION',
|
|
167
|
+
rsvp: true,
|
|
168
|
+
}));
|
|
169
|
+
}
|
|
170
|
+
const calendar = {
|
|
171
|
+
version: '2.0',
|
|
172
|
+
prodId: '-//zele//zele CLI//EN',
|
|
173
|
+
events: [event],
|
|
174
|
+
};
|
|
175
|
+
return generateIcsCalendar(calendar);
|
|
176
|
+
}
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
// CalDAV timezone extraction
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
/** Extract IANA timezone name from CalDAV timezone data.
|
|
181
|
+
* The timezone field may contain raw VTIMEZONE iCal data like:
|
|
182
|
+
* BEGIN:VCALENDAR\n...TZID:Europe/Rome\n...END:VCALENDAR
|
|
183
|
+
* We extract the TZID value from it. */
|
|
184
|
+
function extractTimezone(tz) {
|
|
185
|
+
if (!tz)
|
|
186
|
+
return 'UTC';
|
|
187
|
+
// If it's already an IANA timezone name (no whitespace/newlines), return as-is
|
|
188
|
+
if (!tz.includes('\n') && !tz.includes('BEGIN:'))
|
|
189
|
+
return tz;
|
|
190
|
+
// Extract TZID from VTIMEZONE data
|
|
191
|
+
const match = tz.match(/TZID:(.+)/m);
|
|
192
|
+
if (match)
|
|
193
|
+
return match[1].trim();
|
|
194
|
+
// Try X-WR-TIMEZONE
|
|
195
|
+
const wrMatch = tz.match(/X-WR-TIMEZONE:(.+)/m);
|
|
196
|
+
if (wrMatch)
|
|
197
|
+
return wrMatch[1].trim();
|
|
198
|
+
return 'UTC';
|
|
199
|
+
}
|
|
200
|
+
// ---------------------------------------------------------------------------
|
|
201
|
+
// CalendarClient
|
|
202
|
+
// ---------------------------------------------------------------------------
|
|
203
|
+
const GOOGLE_CALDAV_URL = 'https://apidata.googleusercontent.com/caldav/v2/';
|
|
204
|
+
export class CalendarClient {
|
|
205
|
+
headers;
|
|
206
|
+
email;
|
|
207
|
+
calendarCache = null;
|
|
208
|
+
timezoneCache = {};
|
|
209
|
+
constructor({ accessToken, email }) {
|
|
210
|
+
this.headers = { Authorization: `Bearer ${accessToken}` };
|
|
211
|
+
this.email = email;
|
|
212
|
+
}
|
|
213
|
+
/** Update the access token (e.g. after refresh) */
|
|
214
|
+
updateAccessToken(token) {
|
|
215
|
+
this.headers = { Authorization: `Bearer ${token}` };
|
|
216
|
+
}
|
|
217
|
+
// =========================================================================
|
|
218
|
+
// Internal: fetch DAVCalendar list (cached per instance)
|
|
219
|
+
// =========================================================================
|
|
220
|
+
async fetchDAVCalendars() {
|
|
221
|
+
if (this.calendarCache)
|
|
222
|
+
return this.calendarCache;
|
|
223
|
+
const calendars = await fetchCalendars({
|
|
224
|
+
account: {
|
|
225
|
+
serverUrl: GOOGLE_CALDAV_URL,
|
|
226
|
+
rootUrl: GOOGLE_CALDAV_URL,
|
|
227
|
+
accountType: 'caldav',
|
|
228
|
+
homeUrl: `${GOOGLE_CALDAV_URL}${this.email}/`,
|
|
229
|
+
},
|
|
230
|
+
headers: this.headers,
|
|
231
|
+
});
|
|
232
|
+
this.calendarCache = calendars;
|
|
233
|
+
return calendars;
|
|
234
|
+
}
|
|
235
|
+
/** Resolve a calendarId to a DAVCalendar. 'primary' maps to the user's email. */
|
|
236
|
+
async resolveCalendar(calendarId) {
|
|
237
|
+
const calendars = await this.fetchDAVCalendars();
|
|
238
|
+
// 'primary' = the user's own calendar (URL contains their email)
|
|
239
|
+
const targetId = calendarId === 'primary' ? this.email : calendarId;
|
|
240
|
+
const match = calendars.find((c) => {
|
|
241
|
+
const urlLower = c.url.toLowerCase();
|
|
242
|
+
return urlLower.includes(`/${encodeURIComponent(targetId).toLowerCase()}/`) ||
|
|
243
|
+
urlLower.includes(`/${targetId.toLowerCase()}/`);
|
|
244
|
+
});
|
|
245
|
+
if (!match) {
|
|
246
|
+
throw new Error(`Calendar not found: ${calendarId}. Available: ${calendars.map((c) => c.displayName || c.url).join(', ')}`);
|
|
247
|
+
}
|
|
248
|
+
return match;
|
|
249
|
+
}
|
|
250
|
+
// =========================================================================
|
|
251
|
+
// Calendar list
|
|
252
|
+
// =========================================================================
|
|
253
|
+
async listCalendars() {
|
|
254
|
+
const calendars = await this.fetchDAVCalendars();
|
|
255
|
+
return calendars.map((cal) => {
|
|
256
|
+
// Extract calendar ID from URL
|
|
257
|
+
// URL looks like: https://apidata.googleusercontent.com/caldav/v2/user%40gmail.com/events/
|
|
258
|
+
const urlParts = cal.url.replace(/\/$/, '').split('/');
|
|
259
|
+
const eventsIdx = urlParts.indexOf('events');
|
|
260
|
+
const idEncoded = eventsIdx > 0 ? urlParts[eventsIdx - 1] : urlParts[urlParts.length - 1];
|
|
261
|
+
const id = decodeURIComponent(idEncoded);
|
|
262
|
+
const isPrimary = id.toLowerCase() === this.email.toLowerCase();
|
|
263
|
+
return {
|
|
264
|
+
id,
|
|
265
|
+
summary: typeof cal.displayName === 'string'
|
|
266
|
+
? cal.displayName
|
|
267
|
+
: cal.displayName?._text ?? id,
|
|
268
|
+
primary: isPrimary,
|
|
269
|
+
role: 'owner',
|
|
270
|
+
timezone: extractTimezone(cal.timezone),
|
|
271
|
+
backgroundColor: cal.calendarColor ?? '',
|
|
272
|
+
};
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
// =========================================================================
|
|
276
|
+
// Timezone
|
|
277
|
+
// =========================================================================
|
|
278
|
+
async getTimezone(calendarId = 'primary') {
|
|
279
|
+
if (this.timezoneCache[calendarId])
|
|
280
|
+
return this.timezoneCache[calendarId];
|
|
281
|
+
try {
|
|
282
|
+
const cal = await this.resolveCalendar(calendarId);
|
|
283
|
+
const tz = extractTimezone(cal.timezone);
|
|
284
|
+
this.timezoneCache[calendarId] = tz;
|
|
285
|
+
return tz;
|
|
286
|
+
}
|
|
287
|
+
catch (err) {
|
|
288
|
+
console.error('[calendar] failed to resolve timezone for', calendarId, '-', err instanceof Error ? err.stack ?? err.message : err);
|
|
289
|
+
const calendars = await this.listCalendars();
|
|
290
|
+
const target = calendarId === 'primary' ? this.email : calendarId;
|
|
291
|
+
const match = calendars.find((c) => c.id.toLowerCase() === target.toLowerCase());
|
|
292
|
+
const tz = match?.timezone || 'UTC';
|
|
293
|
+
this.timezoneCache[calendarId] = tz;
|
|
294
|
+
return tz;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// =========================================================================
|
|
298
|
+
// Events
|
|
299
|
+
// =========================================================================
|
|
300
|
+
async listEvents({ calendarId = 'primary', timeMin, timeMax, query, maxResults = 20, pageToken, } = {}) {
|
|
301
|
+
const cal = await this.resolveCalendar(calendarId);
|
|
302
|
+
const tz = await this.getTimezone(calendarId);
|
|
303
|
+
const fetchOpts = {
|
|
304
|
+
calendar: cal,
|
|
305
|
+
headers: this.headers,
|
|
306
|
+
urlFilter: () => true,
|
|
307
|
+
};
|
|
308
|
+
if (timeMin && timeMax) {
|
|
309
|
+
fetchOpts.timeRange = { start: timeMin, end: timeMax };
|
|
310
|
+
}
|
|
311
|
+
const calObjects = await fetchCalendarObjects(fetchOpts);
|
|
312
|
+
let events = [];
|
|
313
|
+
for (const obj of calObjects) {
|
|
314
|
+
if (!obj.data)
|
|
315
|
+
continue;
|
|
316
|
+
events.push(...parseICalData(obj.data, obj));
|
|
317
|
+
}
|
|
318
|
+
if (query) {
|
|
319
|
+
const q = query.toLowerCase();
|
|
320
|
+
events = events.filter((e) => e.summary.toLowerCase().includes(q) ||
|
|
321
|
+
e.description.toLowerCase().includes(q) ||
|
|
322
|
+
e.location.toLowerCase().includes(q));
|
|
323
|
+
}
|
|
324
|
+
events.sort((a, b) => new Date(a.start).getTime() - new Date(b.start).getTime());
|
|
325
|
+
return {
|
|
326
|
+
events: events.slice(0, maxResults),
|
|
327
|
+
nextPageToken: null,
|
|
328
|
+
timezone: tz,
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
async getEvent({ calendarId = 'primary', eventId, }) {
|
|
332
|
+
const cal = await this.resolveCalendar(calendarId);
|
|
333
|
+
const calObjects = await fetchCalendarObjects({
|
|
334
|
+
calendar: cal,
|
|
335
|
+
headers: this.headers,
|
|
336
|
+
urlFilter: () => true,
|
|
337
|
+
});
|
|
338
|
+
for (const obj of calObjects) {
|
|
339
|
+
if (!obj.data)
|
|
340
|
+
continue;
|
|
341
|
+
const events = parseICalData(obj.data, obj);
|
|
342
|
+
const match = events.find((e) => e.id === eventId || e.uid === eventId);
|
|
343
|
+
if (match)
|
|
344
|
+
return match;
|
|
345
|
+
}
|
|
346
|
+
throw new Error(`Event not found: ${eventId}`);
|
|
347
|
+
}
|
|
348
|
+
async createEvent({ calendarId = 'primary', summary, start, end, allDay = false, description, location, attendees, withMeet = false, recurrence, reminders, colorId, visibility, transparency, }) {
|
|
349
|
+
const cal = await this.resolveCalendar(calendarId);
|
|
350
|
+
const uid = generateUID();
|
|
351
|
+
const iCalString = buildICalString({
|
|
352
|
+
uid,
|
|
353
|
+
summary,
|
|
354
|
+
start,
|
|
355
|
+
end,
|
|
356
|
+
allDay,
|
|
357
|
+
description,
|
|
358
|
+
location,
|
|
359
|
+
attendees: attendees?.map((email) => ({ email })),
|
|
360
|
+
transparency,
|
|
361
|
+
visibility,
|
|
362
|
+
organizer: { email: this.email },
|
|
363
|
+
});
|
|
364
|
+
const filename = `${uid.split('@')[0]}.ics`;
|
|
365
|
+
await createCalendarObject({
|
|
366
|
+
calendar: cal,
|
|
367
|
+
filename,
|
|
368
|
+
iCalString,
|
|
369
|
+
headers: this.headers,
|
|
370
|
+
});
|
|
371
|
+
const events = parseICalData(iCalString);
|
|
372
|
+
const event = events[0];
|
|
373
|
+
if (!event)
|
|
374
|
+
throw new Error('Failed to parse created event');
|
|
375
|
+
event.url = `${cal.url}${filename}`;
|
|
376
|
+
return event;
|
|
377
|
+
}
|
|
378
|
+
async updateEvent({ calendarId = 'primary', eventId, summary, start, end, allDay, description, location, addAttendees, removeAttendees, withMeet, colorId, visibility, transparency, }) {
|
|
379
|
+
const existing = await this.getEvent({ calendarId, eventId });
|
|
380
|
+
if (!existing.url || !existing.etag) {
|
|
381
|
+
throw new Error(`Cannot update event: missing CalDAV URL or etag for event ${eventId}`);
|
|
382
|
+
}
|
|
383
|
+
// Handle attendee add/remove
|
|
384
|
+
let mergedAttendees = existing.attendees.map((a) => ({
|
|
385
|
+
email: a.email,
|
|
386
|
+
name: a.name ?? undefined,
|
|
387
|
+
partstat: a.status === 'needsAction' ? 'NEEDS-ACTION' : a.status.toUpperCase(),
|
|
388
|
+
}));
|
|
389
|
+
if (removeAttendees) {
|
|
390
|
+
const removeSet = new Set(removeAttendees.map((e) => e.toLowerCase()));
|
|
391
|
+
mergedAttendees = mergedAttendees.filter((a) => !removeSet.has(a.email.toLowerCase()));
|
|
392
|
+
}
|
|
393
|
+
if (addAttendees) {
|
|
394
|
+
const existingSet = new Set(mergedAttendees.map((a) => a.email.toLowerCase()));
|
|
395
|
+
for (const email of addAttendees) {
|
|
396
|
+
if (!existingSet.has(email.toLowerCase())) {
|
|
397
|
+
mergedAttendees.push({ email, name: undefined, partstat: 'NEEDS-ACTION' });
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
const iCalString = buildICalString({
|
|
402
|
+
uid: existing.uid ?? eventId,
|
|
403
|
+
summary: summary ?? existing.summary,
|
|
404
|
+
start: start ?? existing.start,
|
|
405
|
+
end: end ?? existing.end,
|
|
406
|
+
allDay: allDay ?? existing.allDay,
|
|
407
|
+
description: description !== undefined ? description : existing.description || undefined,
|
|
408
|
+
location: location !== undefined ? location : existing.location || undefined,
|
|
409
|
+
attendees: mergedAttendees.length > 0 ? mergedAttendees : undefined,
|
|
410
|
+
transparency: transparency ?? existing.transparency,
|
|
411
|
+
visibility: visibility ?? existing.visibility,
|
|
412
|
+
sequence: 1,
|
|
413
|
+
organizer: { email: this.email },
|
|
414
|
+
});
|
|
415
|
+
await updateCalendarObject({
|
|
416
|
+
calendarObject: { url: existing.url, data: iCalString, etag: existing.etag },
|
|
417
|
+
headers: this.headers,
|
|
418
|
+
});
|
|
419
|
+
const events = parseICalData(iCalString);
|
|
420
|
+
const event = events[0];
|
|
421
|
+
if (!event)
|
|
422
|
+
throw new Error('Failed to parse updated event');
|
|
423
|
+
event.url = existing.url;
|
|
424
|
+
event.etag = existing.etag;
|
|
425
|
+
return event;
|
|
426
|
+
}
|
|
427
|
+
async deleteEvent({ calendarId = 'primary', eventId, }) {
|
|
428
|
+
const existing = await this.getEvent({ calendarId, eventId });
|
|
429
|
+
if (!existing.url) {
|
|
430
|
+
throw new Error(`Cannot delete event: missing CalDAV URL for event ${eventId}`);
|
|
431
|
+
}
|
|
432
|
+
await deleteCalendarObject({
|
|
433
|
+
calendarObject: { url: existing.url, etag: existing.etag },
|
|
434
|
+
headers: this.headers,
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
async respondToEvent({ calendarId = 'primary', eventId, status, comment, }) {
|
|
438
|
+
const existing = await this.getEvent({ calendarId, eventId });
|
|
439
|
+
if (!existing.url || !existing.etag) {
|
|
440
|
+
throw new Error(`Cannot respond to event: missing CalDAV URL or etag for event ${eventId}`);
|
|
441
|
+
}
|
|
442
|
+
// Update our PARTSTAT in attendees
|
|
443
|
+
const attendees = existing.attendees.map((a) => ({
|
|
444
|
+
email: a.email,
|
|
445
|
+
name: a.name ?? undefined,
|
|
446
|
+
partstat: a.email.toLowerCase() === this.email.toLowerCase()
|
|
447
|
+
? status.toUpperCase()
|
|
448
|
+
: (a.status === 'needsAction' ? 'NEEDS-ACTION' : a.status.toUpperCase()),
|
|
449
|
+
}));
|
|
450
|
+
const organizer = existing.attendees.find((a) => a.organizer);
|
|
451
|
+
const iCalString = buildICalString({
|
|
452
|
+
uid: existing.uid ?? eventId,
|
|
453
|
+
summary: existing.summary,
|
|
454
|
+
start: existing.start,
|
|
455
|
+
end: existing.end,
|
|
456
|
+
allDay: existing.allDay,
|
|
457
|
+
description: existing.description || undefined,
|
|
458
|
+
location: existing.location || undefined,
|
|
459
|
+
attendees,
|
|
460
|
+
organizer: organizer
|
|
461
|
+
? { email: organizer.email, name: organizer.name ?? undefined }
|
|
462
|
+
: { email: this.email },
|
|
463
|
+
});
|
|
464
|
+
await updateCalendarObject({
|
|
465
|
+
calendarObject: { url: existing.url, data: iCalString, etag: existing.etag },
|
|
466
|
+
headers: this.headers,
|
|
467
|
+
});
|
|
468
|
+
const events = parseICalData(iCalString);
|
|
469
|
+
const event = events[0];
|
|
470
|
+
if (!event)
|
|
471
|
+
throw new Error('Failed to parse response event');
|
|
472
|
+
event.url = existing.url;
|
|
473
|
+
return event;
|
|
474
|
+
}
|
|
475
|
+
async getFreeBusy({ calendarIds, timeMin, timeMax, }) {
|
|
476
|
+
const results = [];
|
|
477
|
+
for (const calId of calendarIds) {
|
|
478
|
+
try {
|
|
479
|
+
const { events } = await this.listEvents({
|
|
480
|
+
calendarId: calId,
|
|
481
|
+
timeMin,
|
|
482
|
+
timeMax,
|
|
483
|
+
maxResults: 200,
|
|
484
|
+
});
|
|
485
|
+
const busy = events
|
|
486
|
+
.filter((e) => e.transparency !== 'transparent' && !e.allDay)
|
|
487
|
+
.map((e) => ({ start: e.start, end: e.end }));
|
|
488
|
+
results.push({ calendar: calId, busy });
|
|
489
|
+
}
|
|
490
|
+
catch (err) {
|
|
491
|
+
console.error('[calendar] freebusy failed for', calId, '-', err instanceof Error ? err.stack ?? err.message : err);
|
|
492
|
+
results.push({ calendar: calId, busy: [] });
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
return results;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
//# sourceMappingURL=calendar-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar-client.js","sourceRoot":"","sources":["../src/calendar-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare function parseDuration(input: string): number | null;
|
|
2
|
+
/** Check if a string looks like a date-only value (YYYY-MM-DD) */
|
|
3
|
+
export declare function isDateOnly(input: string): boolean;
|
|
4
|
+
/** Parse a time expression into an RFC3339 string */
|
|
5
|
+
export declare function parseTimeExpression(input: string, tz: string): string;
|
|
6
|
+
export interface TimeRangeOptions {
|
|
7
|
+
from?: string;
|
|
8
|
+
to?: string;
|
|
9
|
+
today?: boolean;
|
|
10
|
+
tomorrow?: boolean;
|
|
11
|
+
week?: boolean;
|
|
12
|
+
days?: number;
|
|
13
|
+
weekStart?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ResolvedTimeRange {
|
|
16
|
+
timeMin: string;
|
|
17
|
+
timeMax: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Resolve time range from command options.
|
|
21
|
+
* Convenience flags (--today, --tomorrow, --week, --days) take priority over --from/--to.
|
|
22
|
+
* Default: next 7 days from now.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveTimeRange(opts: TimeRangeOptions, tz: string): ResolvedTimeRange;
|