@particle-academy/google-calendar-ui 0.0.0 → 0.1.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/index.js ADDED
@@ -0,0 +1,457 @@
1
+ import { defineConnectorKind, summarize } from '@particle-academy/fancy-flow/connectors';
2
+
3
+ // src/service.ts
4
+ var CONNECTOR_API_VERSION = 1;
5
+ var GOOGLE_CALENDAR_SERVICE = {
6
+ service: "google_calendar",
7
+ serviceTitle: "Google Calendar",
8
+ domain: "calendar",
9
+ sandbox: "none"
10
+ };
11
+ var GOOGLE_CALENDAR_CREDENTIALS = [
12
+ {
13
+ "key": "clientId",
14
+ "label": "OAuth client ID",
15
+ "scope": "provider",
16
+ "secret": false,
17
+ "help": "From Google Cloud Console -> APIs & Services -> Credentials. ONE value for the whole installation, not per connected account."
18
+ },
19
+ {
20
+ "key": "clientSecret",
21
+ "label": "OAuth client secret",
22
+ "scope": "provider",
23
+ "secret": true,
24
+ "help": "The client secret for the same OAuth app. One value for the whole installation."
25
+ },
26
+ {
27
+ "key": "accessToken",
28
+ "label": "Access token",
29
+ "scope": "account",
30
+ "secret": true,
31
+ "help": "Per connected Google account, and it expires after ONE HOUR. The host refreshes it with the refresh token."
32
+ },
33
+ {
34
+ "key": "refreshToken",
35
+ "label": "Refresh token",
36
+ "scope": "account",
37
+ "secret": true,
38
+ "help": "Per connected Google account. Google issues one only when the consent request asks for offline access; without it the connection dies within the hour."
39
+ },
40
+ {
41
+ "key": "channelToken",
42
+ "label": "Channel token",
43
+ "scope": "account",
44
+ "secret": true,
45
+ "help": "A secret the host chooses per connected account and sends as `token` on every events.watch. Google echoes it back in the X-Goog-Channel-Token header of every notification, and that echo is the ONLY thing that authenticates a delivery -- Google does not sign them. Up to 256 characters."
46
+ }
47
+ ];
48
+ var GOOGLE_CALENDAR_OAUTH = {
49
+ "flow": "authorization_code",
50
+ "authorizeUrl": "https://accounts.google.com/o/oauth2/v2/auth",
51
+ "tokenUrl": "https://oauth2.googleapis.com/token",
52
+ "scopes": [
53
+ "https://www.googleapis.com/auth/calendar.events"
54
+ ],
55
+ "accessTokenCredential": "accessToken",
56
+ "refreshTokenCredential": "refreshToken",
57
+ "refreshTokenRotates": false,
58
+ "accessTokenTtlSeconds": 3600
59
+ };
60
+ function googleCalendarMeta(role, operation, docs) {
61
+ return { ...GOOGLE_CALENDAR_SERVICE, role, operation, docs };
62
+ }
63
+ var GOOGLE_CALENDAR_CHANNEL_STOP_KIND = "@particle-academy/google_calendar_channel_stop";
64
+ var GOOGLE_CALENDAR_CHANNEL_STOP_OPERATION = "channel_stop";
65
+ var GOOGLE_CALENDAR_CHANNEL_STOP_META = googleCalendarMeta("action", "stop a channel", "https://developers.google.com/workspace/calendar/api/v3/reference/channels/stop");
66
+ var GOOGLE_CALENDAR_CHANNEL_STOP_OUTPUT = [
67
+ {
68
+ "path": "mode",
69
+ "type": "string",
70
+ "description": "Which estate this ran against. Google answers with an empty body, so this is the only thing published."
71
+ }
72
+ ];
73
+ var googleCalendarChannelStopKind = defineConnectorKind(GOOGLE_CALENDAR_CHANNEL_STOP_META, {
74
+ name: GOOGLE_CALENDAR_CHANNEL_STOP_KIND,
75
+ aliases: ["google_calendar_channel_stop"],
76
+ label: "Google Calendar stop watching",
77
+ description: "Close a push-notification channel. The host's subscription machinery calls this before re-creating a channel and when a trigger is removed.",
78
+ inputs: [{ id: "in" }],
79
+ outputs: [{ id: "out" }],
80
+ sideEffects: "idempotent",
81
+ outputShape: GOOGLE_CALENDAR_CHANNEL_STOP_OUTPUT,
82
+ configSchema: [
83
+ {
84
+ "type": "text",
85
+ "key": "channelId",
86
+ "label": "Channel ID",
87
+ "required": true,
88
+ "description": "The channel's id, as sent to channel_watch."
89
+ },
90
+ {
91
+ "type": "text",
92
+ "key": "resourceId",
93
+ "label": "Resource ID",
94
+ "required": true,
95
+ "description": "The resourceId channel_watch answered with. Both are needed; Google refuses a stop with only one."
96
+ }
97
+ ],
98
+ defaultConfig: {
99
+ "mode": "auto"
100
+ },
101
+ renderBody: ({ config }) => summarize(GOOGLE_CALENDAR_CHANNEL_STOP_META, config, "stop a channel")
102
+ });
103
+ var GOOGLE_CALENDAR_CHANNEL_WATCH_KIND = "@particle-academy/google_calendar_channel_watch";
104
+ var GOOGLE_CALENDAR_CHANNEL_WATCH_OPERATION = "channel_watch";
105
+ var GOOGLE_CALENDAR_CHANNEL_WATCH_META = googleCalendarMeta("action", "watch a calendar", "https://developers.google.com/workspace/calendar/api/v3/reference/events/watch");
106
+ var GOOGLE_CALENDAR_CHANNEL_WATCH_OUTPUT = [
107
+ {
108
+ "path": "data.id",
109
+ "type": "string",
110
+ "description": "The channel id -- what was sent."
111
+ },
112
+ {
113
+ "path": "data.resourceId",
114
+ "type": "string",
115
+ "description": "Google's opaque id for the watched resource. channel_stop needs it together with the channel id."
116
+ },
117
+ {
118
+ "path": "data.resourceUri",
119
+ "type": "string",
120
+ "description": "The watched resource's URI."
121
+ },
122
+ {
123
+ "path": "data.token",
124
+ "type": "string",
125
+ "description": "The token that will be echoed on every notification."
126
+ },
127
+ {
128
+ "path": "data.expiration",
129
+ "type": "string",
130
+ "description": "When the channel expires, as epoch MILLISECONDS in a string. The subscription trigger's lease is built from this."
131
+ },
132
+ {
133
+ "path": "mode",
134
+ "type": "string",
135
+ "description": "Which estate this ran against. Google has no sandbox, so: fake or live."
136
+ }
137
+ ];
138
+ var googleCalendarChannelWatchKind = defineConnectorKind(GOOGLE_CALENDAR_CHANNEL_WATCH_META, {
139
+ name: GOOGLE_CALENDAR_CHANNEL_WATCH_KIND,
140
+ aliases: ["google_calendar_channel_watch"],
141
+ label: "Google Calendar watch",
142
+ description: "Open a push-notification channel on a calendar's events. The host's subscription machinery calls this; it is not a node most workflows need.",
143
+ inputs: [{ id: "in" }],
144
+ outputs: [{ id: "out" }],
145
+ sideEffects: "unsafe-to-replay",
146
+ outputShape: GOOGLE_CALENDAR_CHANNEL_WATCH_OUTPUT,
147
+ configSchema: [
148
+ {
149
+ "type": "text",
150
+ "key": "calendarId",
151
+ "label": "Calendar ID",
152
+ "required": true,
153
+ "default": "primary",
154
+ "description": "`primary` for the connected account's own calendar, or a calendar's id."
155
+ },
156
+ {
157
+ "type": "text",
158
+ "key": "channelId",
159
+ "label": "Channel ID",
160
+ "required": true,
161
+ "description": "A UUID the host mints for THIS channel. Google requires it to be unique; it comes back in every notification as X-Goog-Channel-ID and is what channel_stop needs."
162
+ },
163
+ {
164
+ "type": "text",
165
+ "key": "address",
166
+ "label": "Notification URL",
167
+ "required": true,
168
+ "description": "The HTTPS URL the host mounts for this trigger. Google POSTs notifications here with an EMPTY body and the facts in X-Goog-* headers."
169
+ },
170
+ {
171
+ "type": "text",
172
+ "key": "token",
173
+ "label": "Channel token",
174
+ "required": true,
175
+ "description": "The connection's channelToken. The host fills this from the connection -- never type a value here. Google echoes it in X-Goog-Channel-Token, and that echo is how a delivery is verified."
176
+ },
177
+ {
178
+ "type": "text",
179
+ "key": "ttlSeconds",
180
+ "label": "Lifetime (seconds)",
181
+ "required": true,
182
+ "default": "604800",
183
+ "description": "How long Google keeps the channel alive. Google's default is 604800 (one week), and the discovery document types it as a STRING inside `params`."
184
+ }
185
+ ],
186
+ defaultConfig: {
187
+ "mode": "auto"
188
+ },
189
+ renderBody: ({ config }) => summarize(GOOGLE_CALENDAR_CHANNEL_WATCH_META, config, "watch a calendar")
190
+ });
191
+ var GOOGLE_CALENDAR_EVENT_GET_KIND = "@particle-academy/google_calendar_event_get";
192
+ var GOOGLE_CALENDAR_EVENT_GET_OPERATION = "event_get";
193
+ var GOOGLE_CALENDAR_EVENT_GET_META = googleCalendarMeta("action", "read an event", "https://developers.google.com/workspace/calendar/api/v3/reference/events/get");
194
+ var GOOGLE_CALENDAR_EVENT_GET_OUTPUT = [
195
+ {
196
+ "path": "data.id",
197
+ "type": "string",
198
+ "description": "The event id."
199
+ },
200
+ {
201
+ "path": "data.status",
202
+ "type": "string",
203
+ "description": "confirmed, tentative or cancelled."
204
+ },
205
+ {
206
+ "path": "data.summary",
207
+ "type": "string",
208
+ "description": "The title."
209
+ },
210
+ {
211
+ "path": "data.description",
212
+ "type": "string",
213
+ "description": "The description, when there is one."
214
+ },
215
+ {
216
+ "path": "data.start.dateTime",
217
+ "type": "string",
218
+ "description": "RFC 3339 start. All-day events carry start.date instead."
219
+ },
220
+ {
221
+ "path": "data.end.dateTime",
222
+ "type": "string",
223
+ "description": "RFC 3339 end. All-day events carry end.date instead."
224
+ },
225
+ {
226
+ "path": "data.htmlLink",
227
+ "type": "string",
228
+ "description": "The event in the Google Calendar UI."
229
+ },
230
+ {
231
+ "path": "data.updated",
232
+ "type": "string",
233
+ "description": "RFC 3339 last modification."
234
+ },
235
+ {
236
+ "path": "data.organizer.email",
237
+ "type": "string",
238
+ "description": "Who organises it."
239
+ },
240
+ {
241
+ "path": "mode",
242
+ "type": "string",
243
+ "description": "Which estate this ran against. Google has no sandbox, so: fake or live."
244
+ }
245
+ ];
246
+ var googleCalendarEventGetKind = defineConnectorKind(GOOGLE_CALENDAR_EVENT_GET_META, {
247
+ name: GOOGLE_CALENDAR_EVENT_GET_KIND,
248
+ aliases: ["google_calendar_event_get"],
249
+ label: "Google Calendar event",
250
+ description: "Read one event from a Google Calendar.",
251
+ inputs: [{ id: "in" }],
252
+ outputs: [{ id: "out" }],
253
+ sideEffects: "none",
254
+ outputShape: GOOGLE_CALENDAR_EVENT_GET_OUTPUT,
255
+ configSchema: [
256
+ {
257
+ "type": "text",
258
+ "key": "calendarId",
259
+ "label": "Calendar ID",
260
+ "required": true,
261
+ "default": "primary",
262
+ "description": "`primary` for the connected account's own calendar, or a calendar's id (usually an email address)."
263
+ },
264
+ {
265
+ "type": "text",
266
+ "key": "eventId",
267
+ "label": "Event ID",
268
+ "required": true,
269
+ "description": "The event's id, as published by another node or by a notification's follow-up list."
270
+ }
271
+ ],
272
+ defaultConfig: {
273
+ "mode": "auto"
274
+ },
275
+ renderBody: ({ config }) => summarize(GOOGLE_CALENDAR_EVENT_GET_META, config, "read an event")
276
+ });
277
+ var GOOGLE_CALENDAR_EVENT_LIST_KIND = "@particle-academy/google_calendar_event_list";
278
+ var GOOGLE_CALENDAR_EVENT_LIST_OPERATION = "event_list";
279
+ var GOOGLE_CALENDAR_EVENT_LIST_META = googleCalendarMeta("action", "list events", "https://developers.google.com/workspace/calendar/api/v3/reference/events/list");
280
+ var GOOGLE_CALENDAR_EVENT_LIST_OUTPUT = [
281
+ {
282
+ "path": "data.items",
283
+ "type": "array",
284
+ "description": "The events on this page, each shaped like event_get's output."
285
+ },
286
+ {
287
+ "path": "data.nextPageToken",
288
+ "type": "string",
289
+ "description": "Present when there is another page."
290
+ },
291
+ {
292
+ "path": "data.nextSyncToken",
293
+ "type": "string",
294
+ "description": "Present on the LAST page only. Store it and pass it as syncToken next time to get only what changed."
295
+ },
296
+ {
297
+ "path": "data.updated",
298
+ "type": "string",
299
+ "description": "RFC 3339 last modification of the calendar."
300
+ },
301
+ {
302
+ "path": "mode",
303
+ "type": "string",
304
+ "description": "Which estate this ran against. Google has no sandbox, so: fake or live."
305
+ }
306
+ ];
307
+ var googleCalendarEventListKind = defineConnectorKind(GOOGLE_CALENDAR_EVENT_LIST_META, {
308
+ name: GOOGLE_CALENDAR_EVENT_LIST_KIND,
309
+ aliases: ["google_calendar_event_list"],
310
+ label: "Google Calendar events",
311
+ description: "List events from a Google Calendar, in full or incrementally with a sync token.",
312
+ inputs: [{ id: "in" }],
313
+ outputs: [{ id: "out" }],
314
+ sideEffects: "none",
315
+ outputShape: GOOGLE_CALENDAR_EVENT_LIST_OUTPUT,
316
+ configSchema: [
317
+ {
318
+ "type": "text",
319
+ "key": "calendarId",
320
+ "label": "Calendar ID",
321
+ "required": true,
322
+ "default": "primary",
323
+ "description": "`primary` for the connected account's own calendar, or a calendar's id."
324
+ },
325
+ {
326
+ "type": "text",
327
+ "key": "syncToken",
328
+ "label": "Sync token",
329
+ "description": "From a previous list's nextSyncToken. With one set, Google returns ONLY what changed since -- including deletions, as cancelled events. Leave blank for a full list."
330
+ },
331
+ {
332
+ "type": "text",
333
+ "key": "timeMin",
334
+ "label": "From",
335
+ "description": "RFC 3339 lower bound on an event's END time, e.g. 2026-09-15T00:00:00Z. Not allowed together with a sync token."
336
+ },
337
+ {
338
+ "type": "text",
339
+ "key": "timeMax",
340
+ "label": "To",
341
+ "description": "RFC 3339 upper bound on an event's START time. Not allowed together with a sync token."
342
+ },
343
+ {
344
+ "type": "number",
345
+ "key": "maxResults",
346
+ "label": "Page size",
347
+ "min": 1,
348
+ "max": 2500,
349
+ "default": 250,
350
+ "description": "Events per page. Google's default is 250 and its maximum 2500; a nextPageToken means there are more."
351
+ },
352
+ {
353
+ "type": "text",
354
+ "key": "pageToken",
355
+ "label": "Page token",
356
+ "description": "From a previous page's nextPageToken."
357
+ },
358
+ {
359
+ "type": "switch",
360
+ "key": "singleEvents",
361
+ "label": "Expand recurring events",
362
+ "default": true,
363
+ "description": "Return each occurrence of a recurring event as its own item, rather than the series once."
364
+ }
365
+ ],
366
+ defaultConfig: {
367
+ "mode": "auto"
368
+ },
369
+ renderBody: ({ config }) => summarize(GOOGLE_CALENDAR_EVENT_LIST_META, config, "list events")
370
+ });
371
+ var GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_KIND = "@particle-academy/google_calendar_events_changed_trigger";
372
+ var GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_OPERATION = "events_changed";
373
+ var GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_META = googleCalendarMeta("trigger", "a calendar change", "https://developers.google.com/workspace/calendar/api/guides/push");
374
+ var GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_OUTPUT = [
375
+ {
376
+ "path": "channelId",
377
+ "type": "string",
378
+ "description": "X-Goog-Channel-ID: which channel this came from."
379
+ },
380
+ {
381
+ "path": "messageNumber",
382
+ "type": "string",
383
+ "description": "X-Goog-Message-Number: increases per channel; 1 is the sync message."
384
+ },
385
+ {
386
+ "path": "resourceId",
387
+ "type": "string",
388
+ "description": "X-Goog-Resource-ID: the watched resource."
389
+ },
390
+ {
391
+ "path": "resourceState",
392
+ "type": "string",
393
+ "description": "X-Goog-Resource-State: sync, exists or not_exists. `sync` carries no change."
394
+ },
395
+ {
396
+ "path": "resourceUri",
397
+ "type": "string",
398
+ "description": "X-Goog-Resource-URI: the watched resource's URI."
399
+ },
400
+ {
401
+ "path": "channelExpiration",
402
+ "type": "string",
403
+ "description": "X-Goog-Channel-Expiration, when Google sends it: the channel's expiry in a human-readable format, not an instant to compute with."
404
+ }
405
+ ];
406
+ var googleCalendarEventsChangedTriggerKind = defineConnectorKind(GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_META, {
407
+ name: GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_KIND,
408
+ aliases: ["google_calendar_events_changed_trigger"],
409
+ label: "Google Calendar change",
410
+ description: "Start a run when something changes on a watched Google Calendar.",
411
+ icon: "\u{1F4C5}",
412
+ inputs: [],
413
+ outputs: [{ id: "out" }],
414
+ sideEffects: "none",
415
+ outputShape: GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_OUTPUT,
416
+ configSchema: [
417
+ {
418
+ "type": "select",
419
+ "key": "sample",
420
+ "label": "Sample state (fake mode)",
421
+ "default": "exists",
422
+ "description": "Which resource state the faked notification carries: `exists` is a change, `sync` is the first message on a new channel, `not_exists` is the resource going away.",
423
+ "options": [
424
+ {
425
+ "value": "exists",
426
+ "label": "exists \u2014 something changed"
427
+ },
428
+ {
429
+ "value": "sync",
430
+ "label": "sync \u2014 the channel just opened"
431
+ },
432
+ {
433
+ "value": "not_exists",
434
+ "label": "not_exists \u2014 the resource is gone"
435
+ }
436
+ ]
437
+ }
438
+ ],
439
+ defaultConfig: {
440
+ "mode": "auto",
441
+ "sample": "exists"
442
+ },
443
+ renderBody: ({ config }) => summarize(GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_META, config, "a calendar change")
444
+ });
445
+
446
+ // src/index.ts
447
+ var GOOGLE_CALENDAR_KINDS = [
448
+ googleCalendarChannelStopKind,
449
+ googleCalendarChannelWatchKind,
450
+ googleCalendarEventGetKind,
451
+ googleCalendarEventListKind,
452
+ googleCalendarEventsChangedTriggerKind
453
+ ];
454
+
455
+ export { CONNECTOR_API_VERSION, GOOGLE_CALENDAR_CHANNEL_STOP_KIND, GOOGLE_CALENDAR_CHANNEL_STOP_META, GOOGLE_CALENDAR_CHANNEL_STOP_OPERATION, GOOGLE_CALENDAR_CHANNEL_STOP_OUTPUT, GOOGLE_CALENDAR_CHANNEL_WATCH_KIND, GOOGLE_CALENDAR_CHANNEL_WATCH_META, GOOGLE_CALENDAR_CHANNEL_WATCH_OPERATION, GOOGLE_CALENDAR_CHANNEL_WATCH_OUTPUT, GOOGLE_CALENDAR_CREDENTIALS, GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_KIND, GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_META, GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_OPERATION, GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_OUTPUT, GOOGLE_CALENDAR_EVENT_GET_KIND, GOOGLE_CALENDAR_EVENT_GET_META, GOOGLE_CALENDAR_EVENT_GET_OPERATION, GOOGLE_CALENDAR_EVENT_GET_OUTPUT, GOOGLE_CALENDAR_EVENT_LIST_KIND, GOOGLE_CALENDAR_EVENT_LIST_META, GOOGLE_CALENDAR_EVENT_LIST_OPERATION, GOOGLE_CALENDAR_EVENT_LIST_OUTPUT, GOOGLE_CALENDAR_KINDS, GOOGLE_CALENDAR_OAUTH, GOOGLE_CALENDAR_SERVICE, googleCalendarChannelStopKind, googleCalendarChannelWatchKind, googleCalendarEventGetKind, googleCalendarEventListKind, googleCalendarEventsChangedTriggerKind, googleCalendarMeta };
456
+ //# sourceMappingURL=index.js.map
457
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/service.ts","../src/kinds/channel-stop.ts","../src/kinds/channel-watch.ts","../src/kinds/event-get.ts","../src/kinds/event-list.ts","../src/kinds/events-changed.ts","../src/index.ts"],"names":["defineConnectorKind","summarize"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * GENERATED FILE — do not edit.\n *\n * Emitted from provider/manifest.json by weaver's generator.\n * A hand-edit here is destroyed by the next protocol sync, which is worse than\n * being rejected, because it works until it silently does not. Fix\n * provider/manifest.json (or weaver's template/) and regenerate:\n *\n * npm run provider -- google_calendar\n */\n\n/**\n * Google Calendar's identity on the authoring surface, shared by every Google\n * Calendar node.\n *\n * This file must import nothing from the js package: a PHP or Python project\n * installs the ui package and never that one, and the import would be a\n * dangling module the moment it did.\n *\n * ## The sandbox trap\n *\n * Google has no sandbox for Calendar. A test calendar is a real one in a real\n * account, so every watch and every read is real -- point this at a scratch\n * calendar, not a production one. The faker is the only way to develop against\n * it without touching an account.\n */\n\nimport type { ConnectorDomain, ConnectorMeta } from \"@particle-academy/fancy-flow/connectors\";\n\n/**\n * The connector API version this package was GENERATED against.\n *\n * A literal, never imported — an imported constant lets an upgrade rewrite the\n * very claim it exists to detect.\n */\nexport const CONNECTOR_API_VERSION = 1;\n\n/** The parts of a connector's identity that belong to the SERVICE, not the node. */\nexport const GOOGLE_CALENDAR_SERVICE = {\n service: \"google_calendar\",\n serviceTitle: \"Google Calendar\",\n domain: \"calendar\",\n sandbox: \"none\",\n} as const satisfies Pick<ConnectorMeta, \"service\" | \"serviceTitle\" | \"domain\" | \"sandbox\">;\n\n/**\n * Every connector domain weaver knows, pinned against fancy-flow's union.\n *\n * A closed set copied into three codebases stays correct only while something\n * MAKES it: this line fails to compile the moment weaver carries a value\n * fancy-flow does not, including the values no provider uses yet.\n */\nconst WEAVER_DOMAINS: readonly ConnectorDomain[] = [\n \"payments\",\n \"commerce\",\n \"messaging\",\n \"email\",\n \"crm\",\n \"support\",\n \"storage\",\n \"calendar\",\n \"productivity\",\n \"database\",\n \"devtools\",\n \"analytics\",\n \"marketing\",\n \"ai\",\n \"forms\",\n \"hr\",\n \"geo\"\n];\nvoid WEAVER_DOMAINS;\n\n/** The credentials a Google Calendar connection holds. */\nexport const GOOGLE_CALENDAR_CREDENTIALS = [\n {\n \"key\": \"clientId\",\n \"label\": \"OAuth client ID\",\n \"scope\": \"provider\",\n \"secret\": false,\n \"help\": \"From Google Cloud Console -> APIs & Services -> Credentials. ONE value for the whole installation, not per connected account.\"\n },\n {\n \"key\": \"clientSecret\",\n \"label\": \"OAuth client secret\",\n \"scope\": \"provider\",\n \"secret\": true,\n \"help\": \"The client secret for the same OAuth app. One value for the whole installation.\"\n },\n {\n \"key\": \"accessToken\",\n \"label\": \"Access token\",\n \"scope\": \"account\",\n \"secret\": true,\n \"help\": \"Per connected Google account, and it expires after ONE HOUR. The host refreshes it with the refresh token.\"\n },\n {\n \"key\": \"refreshToken\",\n \"label\": \"Refresh token\",\n \"scope\": \"account\",\n \"secret\": true,\n \"help\": \"Per connected Google account. Google issues one only when the consent request asks for offline access; without it the connection dies within the hour.\"\n },\n {\n \"key\": \"channelToken\",\n \"label\": \"Channel token\",\n \"scope\": \"account\",\n \"secret\": true,\n \"help\": \"A secret the host chooses per connected account and sends as `token` on every events.watch. Google echoes it back in the X-Goog-Channel-Token header of every notification, and that echo is the ONLY thing that authenticates a delivery -- Google does not sign them. Up to 256 characters.\"\n }\n] as const;\n\n/**\n * The OAuth2 exchange Google Calendar requires — DECLARED here, performed by\n * the host.\n *\n * A consent screen needs a browser, a redirect URI and somewhere to persist\n * the result, and all three belong to the host; a package that ran the dance\n * itself would have to own a web server. So this says precisely enough for a\n * host to do it.\n *\n * The access token lasts 3600 seconds. A host that never refreshes will work\n * all afternoon and be broken by morning, which is why the lifetime is stated\n * rather than left to be discovered.\n *\n * Its refresh tokens do NOT rotate: the same one is reusable, so a refresh may\n * safely be retried and may run concurrently. That is stated rather than\n * assumed because the opposite — a provider that spends the token and revokes\n * the grant on a replay — looks identical until it happens.\n */\nexport const GOOGLE_CALENDAR_OAUTH = {\n \"flow\": \"authorization_code\",\n \"authorizeUrl\": \"https://accounts.google.com/o/oauth2/v2/auth\",\n \"tokenUrl\": \"https://oauth2.googleapis.com/token\",\n \"scopes\": [\n \"https://www.googleapis.com/auth/calendar.events\"\n ],\n \"accessTokenCredential\": \"accessToken\",\n \"refreshTokenCredential\": \"refreshToken\",\n \"refreshTokenRotates\": false,\n \"accessTokenTtlSeconds\": 3600\n} as const;\n\n/** Build a Google Calendar node's connector metadata from the operation it performs. */\nexport function googleCalendarMeta(\n role: ConnectorMeta[\"role\"],\n operation: string,\n docs: string,\n): ConnectorMeta {\n return { ...GOOGLE_CALENDAR_SERVICE, role, operation, docs };\n}\n","/**\n * GENERATED FILE — do not edit.\n *\n * Emitted from provider/actions/channel-stop.json by weaver's generator.\n * A hand-edit here is destroyed by the next protocol sync, which is worse than\n * being rejected, because it works until it silently does not. Fix\n * provider/actions/channel-stop.json (or weaver's template/) and regenerate:\n *\n * npm run provider -- google_calendar\n */\n\n/**\n * Google Calendar stop watching — Close a push-notification channel. The\n * host's subscription machinery calls this before re-creating a channel and\n * when a trigger is removed.\n *\n * https://developers.google.com/workspace/calendar/api/v3/reference/channels/stop\n */\n\nimport type { NodeKindDefinition } from \"@particle-academy/fancy-flow/engine\";\nimport { defineConnectorKind, summarize, type OutputField } from \"@particle-academy/fancy-flow/connectors\";\nimport { googleCalendarMeta } from \"../service.js\";\n\nexport const GOOGLE_CALENDAR_CHANNEL_STOP_KIND = \"@particle-academy/google_calendar_channel_stop\";\nexport const GOOGLE_CALENDAR_CHANNEL_STOP_OPERATION = \"channel_stop\";\n\nexport const GOOGLE_CALENDAR_CHANNEL_STOP_META = googleCalendarMeta(\"action\", \"stop a channel\", \"https://developers.google.com/workspace/calendar/api/v3/reference/channels/stop\");\n\n/**\n * What this node emits — the \"ingredients\" a downstream node can reference.\n *\n * fancy-flow reads `outputShape` off the kind and offers it in the variable\n * picker, so declaring it is the whole of the work: an author configuring the\n * next node picks `{{ $json.data.id }}` off a list instead of typing a path\n * and hoping.\n */\nexport const GOOGLE_CALENDAR_CHANNEL_STOP_OUTPUT: OutputField[] = [\n {\n \"path\": \"mode\",\n \"type\": \"string\",\n \"description\": \"Which estate this ran against. Google answers with an empty body, so this is the only thing published.\"\n }\n];\n\nexport const googleCalendarChannelStopKind: NodeKindDefinition = defineConnectorKind(GOOGLE_CALENDAR_CHANNEL_STOP_META, {\n name: GOOGLE_CALENDAR_CHANNEL_STOP_KIND,\n aliases: [\"google_calendar_channel_stop\"],\n label: \"Google Calendar stop watching\",\n description: \"Close a push-notification channel. The host's subscription machinery calls this before re-creating a channel and when a trigger is removed.\",\n inputs: [{ id: \"in\" }],\n outputs: [{ id: \"out\" }],\n sideEffects: \"idempotent\",\n outputShape: GOOGLE_CALENDAR_CHANNEL_STOP_OUTPUT,\n configSchema: [\n {\n \"type\": \"text\",\n \"key\": \"channelId\",\n \"label\": \"Channel ID\",\n \"required\": true,\n \"description\": \"The channel's id, as sent to channel_watch.\"\n },\n {\n \"type\": \"text\",\n \"key\": \"resourceId\",\n \"label\": \"Resource ID\",\n \"required\": true,\n \"description\": \"The resourceId channel_watch answered with. Both are needed; Google refuses a stop with only one.\"\n }\n ],\n defaultConfig: {\n \"mode\": \"auto\"\n },\n renderBody: ({ config }) =>\n summarize(GOOGLE_CALENDAR_CHANNEL_STOP_META, config as Record<string, unknown>, \"stop a channel\"),\n});\n","/**\n * GENERATED FILE — do not edit.\n *\n * Emitted from provider/actions/channel-watch.json by weaver's generator.\n * A hand-edit here is destroyed by the next protocol sync, which is worse than\n * being rejected, because it works until it silently does not. Fix\n * provider/actions/channel-watch.json (or weaver's template/) and regenerate:\n *\n * npm run provider -- google_calendar\n */\n\n/**\n * Google Calendar watch — Open a push-notification channel on a calendar's\n * events. The host's subscription machinery calls this; it is not a node most\n * workflows need.\n *\n * https://developers.google.com/workspace/calendar/api/v3/reference/events/watch\n *\n * `unsafe-to-replay`.\n */\n\nimport type { NodeKindDefinition } from \"@particle-academy/fancy-flow/engine\";\nimport { defineConnectorKind, summarize, type OutputField } from \"@particle-academy/fancy-flow/connectors\";\nimport { googleCalendarMeta } from \"../service.js\";\n\nexport const GOOGLE_CALENDAR_CHANNEL_WATCH_KIND = \"@particle-academy/google_calendar_channel_watch\";\nexport const GOOGLE_CALENDAR_CHANNEL_WATCH_OPERATION = \"channel_watch\";\n\nexport const GOOGLE_CALENDAR_CHANNEL_WATCH_META = googleCalendarMeta(\"action\", \"watch a calendar\", \"https://developers.google.com/workspace/calendar/api/v3/reference/events/watch\");\n\n/**\n * What this node emits — the \"ingredients\" a downstream node can reference.\n *\n * fancy-flow reads `outputShape` off the kind and offers it in the variable\n * picker, so declaring it is the whole of the work: an author configuring the\n * next node picks `{{ $json.data.id }}` off a list instead of typing a path\n * and hoping.\n */\nexport const GOOGLE_CALENDAR_CHANNEL_WATCH_OUTPUT: OutputField[] = [\n {\n \"path\": \"data.id\",\n \"type\": \"string\",\n \"description\": \"The channel id -- what was sent.\"\n },\n {\n \"path\": \"data.resourceId\",\n \"type\": \"string\",\n \"description\": \"Google's opaque id for the watched resource. channel_stop needs it together with the channel id.\"\n },\n {\n \"path\": \"data.resourceUri\",\n \"type\": \"string\",\n \"description\": \"The watched resource's URI.\"\n },\n {\n \"path\": \"data.token\",\n \"type\": \"string\",\n \"description\": \"The token that will be echoed on every notification.\"\n },\n {\n \"path\": \"data.expiration\",\n \"type\": \"string\",\n \"description\": \"When the channel expires, as epoch MILLISECONDS in a string. The subscription trigger's lease is built from this.\"\n },\n {\n \"path\": \"mode\",\n \"type\": \"string\",\n \"description\": \"Which estate this ran against. Google has no sandbox, so: fake or live.\"\n }\n];\n\nexport const googleCalendarChannelWatchKind: NodeKindDefinition = defineConnectorKind(GOOGLE_CALENDAR_CHANNEL_WATCH_META, {\n name: GOOGLE_CALENDAR_CHANNEL_WATCH_KIND,\n aliases: [\"google_calendar_channel_watch\"],\n label: \"Google Calendar watch\",\n description: \"Open a push-notification channel on a calendar's events. The host's subscription machinery calls this; it is not a node most workflows need.\",\n inputs: [{ id: \"in\" }],\n outputs: [{ id: \"out\" }],\n sideEffects: \"unsafe-to-replay\",\n outputShape: GOOGLE_CALENDAR_CHANNEL_WATCH_OUTPUT,\n configSchema: [\n {\n \"type\": \"text\",\n \"key\": \"calendarId\",\n \"label\": \"Calendar ID\",\n \"required\": true,\n \"default\": \"primary\",\n \"description\": \"`primary` for the connected account's own calendar, or a calendar's id.\"\n },\n {\n \"type\": \"text\",\n \"key\": \"channelId\",\n \"label\": \"Channel ID\",\n \"required\": true,\n \"description\": \"A UUID the host mints for THIS channel. Google requires it to be unique; it comes back in every notification as X-Goog-Channel-ID and is what channel_stop needs.\"\n },\n {\n \"type\": \"text\",\n \"key\": \"address\",\n \"label\": \"Notification URL\",\n \"required\": true,\n \"description\": \"The HTTPS URL the host mounts for this trigger. Google POSTs notifications here with an EMPTY body and the facts in X-Goog-* headers.\"\n },\n {\n \"type\": \"text\",\n \"key\": \"token\",\n \"label\": \"Channel token\",\n \"required\": true,\n \"description\": \"The connection's channelToken. The host fills this from the connection -- never type a value here. Google echoes it in X-Goog-Channel-Token, and that echo is how a delivery is verified.\"\n },\n {\n \"type\": \"text\",\n \"key\": \"ttlSeconds\",\n \"label\": \"Lifetime (seconds)\",\n \"required\": true,\n \"default\": \"604800\",\n \"description\": \"How long Google keeps the channel alive. Google's default is 604800 (one week), and the discovery document types it as a STRING inside `params`.\"\n }\n ],\n defaultConfig: {\n \"mode\": \"auto\"\n },\n renderBody: ({ config }) =>\n summarize(GOOGLE_CALENDAR_CHANNEL_WATCH_META, config as Record<string, unknown>, \"watch a calendar\"),\n});\n","/**\n * GENERATED FILE — do not edit.\n *\n * Emitted from provider/actions/event-get.json by weaver's generator.\n * A hand-edit here is destroyed by the next protocol sync, which is worse than\n * being rejected, because it works until it silently does not. Fix\n * provider/actions/event-get.json (or weaver's template/) and regenerate:\n *\n * npm run provider -- google_calendar\n */\n\n/**\n * Google Calendar event — Read one event from a Google Calendar.\n *\n * https://developers.google.com/workspace/calendar/api/v3/reference/events/get\n */\n\nimport type { NodeKindDefinition } from \"@particle-academy/fancy-flow/engine\";\nimport { defineConnectorKind, summarize, type OutputField } from \"@particle-academy/fancy-flow/connectors\";\nimport { googleCalendarMeta } from \"../service.js\";\n\nexport const GOOGLE_CALENDAR_EVENT_GET_KIND = \"@particle-academy/google_calendar_event_get\";\nexport const GOOGLE_CALENDAR_EVENT_GET_OPERATION = \"event_get\";\n\nexport const GOOGLE_CALENDAR_EVENT_GET_META = googleCalendarMeta(\"action\", \"read an event\", \"https://developers.google.com/workspace/calendar/api/v3/reference/events/get\");\n\n/**\n * What this node emits — the \"ingredients\" a downstream node can reference.\n *\n * fancy-flow reads `outputShape` off the kind and offers it in the variable\n * picker, so declaring it is the whole of the work: an author configuring the\n * next node picks `{{ $json.data.id }}` off a list instead of typing a path\n * and hoping.\n */\nexport const GOOGLE_CALENDAR_EVENT_GET_OUTPUT: OutputField[] = [\n {\n \"path\": \"data.id\",\n \"type\": \"string\",\n \"description\": \"The event id.\"\n },\n {\n \"path\": \"data.status\",\n \"type\": \"string\",\n \"description\": \"confirmed, tentative or cancelled.\"\n },\n {\n \"path\": \"data.summary\",\n \"type\": \"string\",\n \"description\": \"The title.\"\n },\n {\n \"path\": \"data.description\",\n \"type\": \"string\",\n \"description\": \"The description, when there is one.\"\n },\n {\n \"path\": \"data.start.dateTime\",\n \"type\": \"string\",\n \"description\": \"RFC 3339 start. All-day events carry start.date instead.\"\n },\n {\n \"path\": \"data.end.dateTime\",\n \"type\": \"string\",\n \"description\": \"RFC 3339 end. All-day events carry end.date instead.\"\n },\n {\n \"path\": \"data.htmlLink\",\n \"type\": \"string\",\n \"description\": \"The event in the Google Calendar UI.\"\n },\n {\n \"path\": \"data.updated\",\n \"type\": \"string\",\n \"description\": \"RFC 3339 last modification.\"\n },\n {\n \"path\": \"data.organizer.email\",\n \"type\": \"string\",\n \"description\": \"Who organises it.\"\n },\n {\n \"path\": \"mode\",\n \"type\": \"string\",\n \"description\": \"Which estate this ran against. Google has no sandbox, so: fake or live.\"\n }\n];\n\nexport const googleCalendarEventGetKind: NodeKindDefinition = defineConnectorKind(GOOGLE_CALENDAR_EVENT_GET_META, {\n name: GOOGLE_CALENDAR_EVENT_GET_KIND,\n aliases: [\"google_calendar_event_get\"],\n label: \"Google Calendar event\",\n description: \"Read one event from a Google Calendar.\",\n inputs: [{ id: \"in\" }],\n outputs: [{ id: \"out\" }],\n sideEffects: \"none\",\n outputShape: GOOGLE_CALENDAR_EVENT_GET_OUTPUT,\n configSchema: [\n {\n \"type\": \"text\",\n \"key\": \"calendarId\",\n \"label\": \"Calendar ID\",\n \"required\": true,\n \"default\": \"primary\",\n \"description\": \"`primary` for the connected account's own calendar, or a calendar's id (usually an email address).\"\n },\n {\n \"type\": \"text\",\n \"key\": \"eventId\",\n \"label\": \"Event ID\",\n \"required\": true,\n \"description\": \"The event's id, as published by another node or by a notification's follow-up list.\"\n }\n ],\n defaultConfig: {\n \"mode\": \"auto\"\n },\n renderBody: ({ config }) =>\n summarize(GOOGLE_CALENDAR_EVENT_GET_META, config as Record<string, unknown>, \"read an event\"),\n});\n","/**\n * GENERATED FILE — do not edit.\n *\n * Emitted from provider/actions/event-list.json by weaver's generator.\n * A hand-edit here is destroyed by the next protocol sync, which is worse than\n * being rejected, because it works until it silently does not. Fix\n * provider/actions/event-list.json (or weaver's template/) and regenerate:\n *\n * npm run provider -- google_calendar\n */\n\n/**\n * Google Calendar events — List events from a Google Calendar, in full or\n * incrementally with a sync token.\n *\n * https://developers.google.com/workspace/calendar/api/v3/reference/events/list\n */\n\nimport type { NodeKindDefinition } from \"@particle-academy/fancy-flow/engine\";\nimport { defineConnectorKind, summarize, type OutputField } from \"@particle-academy/fancy-flow/connectors\";\nimport { googleCalendarMeta } from \"../service.js\";\n\nexport const GOOGLE_CALENDAR_EVENT_LIST_KIND = \"@particle-academy/google_calendar_event_list\";\nexport const GOOGLE_CALENDAR_EVENT_LIST_OPERATION = \"event_list\";\n\nexport const GOOGLE_CALENDAR_EVENT_LIST_META = googleCalendarMeta(\"action\", \"list events\", \"https://developers.google.com/workspace/calendar/api/v3/reference/events/list\");\n\n/**\n * What this node emits — the \"ingredients\" a downstream node can reference.\n *\n * fancy-flow reads `outputShape` off the kind and offers it in the variable\n * picker, so declaring it is the whole of the work: an author configuring the\n * next node picks `{{ $json.data.id }}` off a list instead of typing a path\n * and hoping.\n */\nexport const GOOGLE_CALENDAR_EVENT_LIST_OUTPUT: OutputField[] = [\n {\n \"path\": \"data.items\",\n \"type\": \"array\",\n \"description\": \"The events on this page, each shaped like event_get's output.\"\n },\n {\n \"path\": \"data.nextPageToken\",\n \"type\": \"string\",\n \"description\": \"Present when there is another page.\"\n },\n {\n \"path\": \"data.nextSyncToken\",\n \"type\": \"string\",\n \"description\": \"Present on the LAST page only. Store it and pass it as syncToken next time to get only what changed.\"\n },\n {\n \"path\": \"data.updated\",\n \"type\": \"string\",\n \"description\": \"RFC 3339 last modification of the calendar.\"\n },\n {\n \"path\": \"mode\",\n \"type\": \"string\",\n \"description\": \"Which estate this ran against. Google has no sandbox, so: fake or live.\"\n }\n];\n\nexport const googleCalendarEventListKind: NodeKindDefinition = defineConnectorKind(GOOGLE_CALENDAR_EVENT_LIST_META, {\n name: GOOGLE_CALENDAR_EVENT_LIST_KIND,\n aliases: [\"google_calendar_event_list\"],\n label: \"Google Calendar events\",\n description: \"List events from a Google Calendar, in full or incrementally with a sync token.\",\n inputs: [{ id: \"in\" }],\n outputs: [{ id: \"out\" }],\n sideEffects: \"none\",\n outputShape: GOOGLE_CALENDAR_EVENT_LIST_OUTPUT,\n configSchema: [\n {\n \"type\": \"text\",\n \"key\": \"calendarId\",\n \"label\": \"Calendar ID\",\n \"required\": true,\n \"default\": \"primary\",\n \"description\": \"`primary` for the connected account's own calendar, or a calendar's id.\"\n },\n {\n \"type\": \"text\",\n \"key\": \"syncToken\",\n \"label\": \"Sync token\",\n \"description\": \"From a previous list's nextSyncToken. With one set, Google returns ONLY what changed since -- including deletions, as cancelled events. Leave blank for a full list.\"\n },\n {\n \"type\": \"text\",\n \"key\": \"timeMin\",\n \"label\": \"From\",\n \"description\": \"RFC 3339 lower bound on an event's END time, e.g. 2026-09-15T00:00:00Z. Not allowed together with a sync token.\"\n },\n {\n \"type\": \"text\",\n \"key\": \"timeMax\",\n \"label\": \"To\",\n \"description\": \"RFC 3339 upper bound on an event's START time. Not allowed together with a sync token.\"\n },\n {\n \"type\": \"number\",\n \"key\": \"maxResults\",\n \"label\": \"Page size\",\n \"min\": 1,\n \"max\": 2500,\n \"default\": 250,\n \"description\": \"Events per page. Google's default is 250 and its maximum 2500; a nextPageToken means there are more.\"\n },\n {\n \"type\": \"text\",\n \"key\": \"pageToken\",\n \"label\": \"Page token\",\n \"description\": \"From a previous page's nextPageToken.\"\n },\n {\n \"type\": \"switch\",\n \"key\": \"singleEvents\",\n \"label\": \"Expand recurring events\",\n \"default\": true,\n \"description\": \"Return each occurrence of a recurring event as its own item, rather than the series once.\"\n }\n ],\n defaultConfig: {\n \"mode\": \"auto\"\n },\n renderBody: ({ config }) =>\n summarize(GOOGLE_CALENDAR_EVENT_LIST_META, config as Record<string, unknown>, \"list events\"),\n});\n","/**\n * GENERATED FILE — do not edit.\n *\n * Emitted from provider/triggers/events-changed.json by weaver's generator.\n * A hand-edit here is destroyed by the next protocol sync, which is worse than\n * being rejected, because it works until it silently does not. Fix\n * provider/triggers/events-changed.json (or weaver's template/) and regenerate:\n *\n * npm run provider -- google_calendar\n */\n\n/**\n * Google Calendar change — Start a run when something changes on a watched\n * Google Calendar.\n *\n * https://developers.google.com/workspace/calendar/api/guides/push\n *\n * Delivery: subscription. The host mints a UUID, calls channel_watch with it,\n * its own URL for this trigger and the connection's channelToken, and stores\n * the returned id, resourceId and expiration. Google cannot renew a channel:\n * 86400 seconds before it expires the host calls channel_stop and then\n * channel_watch again. A channel that lapsed is re-listed FIRST (event_list\n * with the stored syncToken; a 410 means list in full) and then re-created,\n * because notifications during the gap are gone. Google delivers with an EMPTY\n * body: the host verifies X-Goog-Channel-Token against the connection's\n * channelToken and injects the X-Goog-* headers as the event, camel-cased as\n * below. The first message on a new channel is `sync` and carries no change.\n */\n\nimport type { NodeKindDefinition } from \"@particle-academy/fancy-flow/engine\";\nimport { defineConnectorKind, summarize, type OutputField } from \"@particle-academy/fancy-flow/connectors\";\nimport { googleCalendarMeta } from \"../service.js\";\n\nexport const GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_KIND = \"@particle-academy/google_calendar_events_changed_trigger\";\nexport const GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_OPERATION = \"events_changed\";\n\nexport const GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_META = googleCalendarMeta(\"trigger\", \"a calendar change\", \"https://developers.google.com/workspace/calendar/api/guides/push\");\n\n/**\n * What this node emits — the \"ingredients\" a downstream node can reference.\n *\n * fancy-flow reads `outputShape` off the kind and offers it in the variable\n * picker, so declaring it is the whole of the work: an author configuring the\n * next node picks `{{ $json.data.id }}` off a list instead of typing a path\n * and hoping.\n */\nexport const GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_OUTPUT: OutputField[] = [\n {\n \"path\": \"channelId\",\n \"type\": \"string\",\n \"description\": \"X-Goog-Channel-ID: which channel this came from.\"\n },\n {\n \"path\": \"messageNumber\",\n \"type\": \"string\",\n \"description\": \"X-Goog-Message-Number: increases per channel; 1 is the sync message.\"\n },\n {\n \"path\": \"resourceId\",\n \"type\": \"string\",\n \"description\": \"X-Goog-Resource-ID: the watched resource.\"\n },\n {\n \"path\": \"resourceState\",\n \"type\": \"string\",\n \"description\": \"X-Goog-Resource-State: sync, exists or not_exists. `sync` carries no change.\"\n },\n {\n \"path\": \"resourceUri\",\n \"type\": \"string\",\n \"description\": \"X-Goog-Resource-URI: the watched resource's URI.\"\n },\n {\n \"path\": \"channelExpiration\",\n \"type\": \"string\",\n \"description\": \"X-Goog-Channel-Expiration, when Google sends it: the channel's expiry in a human-readable format, not an instant to compute with.\"\n }\n];\n\nexport const googleCalendarEventsChangedTriggerKind: NodeKindDefinition = defineConnectorKind(GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_META, {\n name: GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_KIND,\n aliases: [\"google_calendar_events_changed_trigger\"],\n label: \"Google Calendar change\",\n description: \"Start a run when something changes on a watched Google Calendar.\",\n icon: \"📅\",\n inputs: [],\n outputs: [{ id: \"out\" }],\n sideEffects: \"none\",\n outputShape: GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_OUTPUT,\n configSchema: [\n {\n \"type\": \"select\",\n \"key\": \"sample\",\n \"label\": \"Sample state (fake mode)\",\n \"default\": \"exists\",\n \"description\": \"Which resource state the faked notification carries: `exists` is a change, `sync` is the first message on a new channel, `not_exists` is the resource going away.\",\n \"options\": [\n {\n \"value\": \"exists\",\n \"label\": \"exists — something changed\"\n },\n {\n \"value\": \"sync\",\n \"label\": \"sync — the channel just opened\"\n },\n {\n \"value\": \"not_exists\",\n \"label\": \"not_exists — the resource is gone\"\n }\n ]\n }\n ],\n defaultConfig: {\n \"mode\": \"auto\",\n \"sample\": \"exists\"\n },\n renderBody: ({ config }) =>\n summarize(GOOGLE_CALENDAR_EVENTS_CHANGED_TRIGGER_META, config as Record<string, unknown>, \"a calendar change\"),\n});\n","/**\n * GENERATED FILE — do not edit.\n *\n * Emitted from provider/manifest.json by weaver's generator.\n * A hand-edit here is destroyed by the next protocol sync, which is worse than\n * being rejected, because it works until it silently does not. Fix\n * provider/manifest.json (or weaver's template/) and regenerate:\n *\n * npm run provider -- google_calendar\n */\n\n/**\n * Google Calendar's node kinds for fancy-flow.\n *\n * Install this on every host. The TypeScript executors live in the js\n * package's `./flow` subpath; PHP and Python hosts run their own and need only\n * this.\n */\n\nexport * from \"./service.js\";\nexport * from \"./kinds/channel-stop.js\";\nexport * from \"./kinds/channel-watch.js\";\nexport * from \"./kinds/event-get.js\";\nexport * from \"./kinds/event-list.js\";\nexport * from \"./kinds/events-changed.js\";\n\nimport type { NodeKindDefinition } from \"@particle-academy/fancy-flow/engine\";\nimport { googleCalendarChannelStopKind } from \"./kinds/channel-stop.js\";\nimport { googleCalendarChannelWatchKind } from \"./kinds/channel-watch.js\";\nimport { googleCalendarEventGetKind } from \"./kinds/event-get.js\";\nimport { googleCalendarEventListKind } from \"./kinds/event-list.js\";\nimport { googleCalendarEventsChangedTriggerKind } from \"./kinds/events-changed.js\";\n\n/** Every Google Calendar kind, for a host that registers the lot. */\nexport const GOOGLE_CALENDAR_KINDS: NodeKindDefinition[] = [\n googleCalendarChannelStopKind,\n googleCalendarChannelWatchKind,\n googleCalendarEventGetKind,\n googleCalendarEventListKind,\n googleCalendarEventsChangedTriggerKind,\n];\n"]}
package/package.json CHANGED
@@ -1,18 +1,69 @@
1
1
  {
2
2
  "name": "@particle-academy/google-calendar-ui",
3
- "version": "0.0.0",
4
- "description": "A placeholder that claims the name @particle-academy/google-calendar-ui; the real release follows through Fancy-Friends/google-calendar's publish.yml with provenance. Do not install this version.",
5
- "license": "MIT",
3
+ "version": "0.1.0",
4
+ "description": "Google Calendar's authoring surface for fancy-flow — the node kinds, their config schemas and their declared output shapes. React on every host; carries no executor.",
6
5
  "repository": {
7
6
  "type": "git",
8
7
  "url": "git+https://github.com/Fancy-Friends/google-calendar.git",
9
8
  "directory": "packages/ui"
10
9
  },
11
10
  "homepage": "https://github.com/Fancy-Friends/google-calendar#readme",
11
+ "bugs": "https://github.com/Fancy-Friends/google-calendar/issues",
12
+ "type": "module",
13
+ "main": "./dist/index.cjs",
14
+ "module": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "import": {
19
+ "types": "./dist/index.d.ts",
20
+ "default": "./dist/index.js"
21
+ },
22
+ "require": {
23
+ "types": "./dist/index.d.cts",
24
+ "default": "./dist/index.cjs"
25
+ }
26
+ },
27
+ "./package.json": "./package.json"
28
+ },
29
+ "files": [
30
+ "dist",
31
+ "art",
32
+ "README.md",
33
+ "CHANGELOG.md",
34
+ "LICENSE"
35
+ ],
36
+ "scripts": {
37
+ "build": "tsup",
38
+ "lint": "tsc --noEmit",
39
+ "test": "node --import tsx --test tests/*.test.ts",
40
+ "prepublishOnly": "tsup"
41
+ },
42
+ "dependencies": {},
43
+ "peerDependencies": {
44
+ "@particle-academy/fancy-flow": ">=0.48.0 <2.0"
45
+ },
46
+ "devDependencies": {
47
+ "@particle-academy/fancy-flow": ">=0.48.0 <2.0",
48
+ "@types/node": "^26.2.0",
49
+ "tsup": "^8.5.0",
50
+ "tsx": "^4.19.0",
51
+ "typescript": "^5.8.0"
52
+ },
12
53
  "publishConfig": {
13
54
  "access": "public"
14
55
  },
15
- "files": [
16
- "README.md"
17
- ]
56
+ "keywords": [
57
+ "google_calendar",
58
+ "calendar",
59
+ "connector",
60
+ "fancy-flow",
61
+ "fancy-ui",
62
+ "particle-academy"
63
+ ],
64
+ "license": "MIT",
65
+ "sideEffects": false,
66
+ "engines": {
67
+ "node": ">=22"
68
+ }
18
69
  }