@notionhq/workers 0.3.0 → 0.5.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/block.d.ts +1 -1
- package/dist/block.d.ts.map +1 -1
- package/dist/builder.d.ts +7 -1
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +13 -0
- package/dist/capabilities/ai_connector.js +1 -1
- package/dist/capabilities/automation.js +1 -1
- package/dist/capabilities/context.d.ts +2 -1
- package/dist/capabilities/context.d.ts.map +1 -1
- package/dist/capabilities/context.js +21 -3
- package/dist/capabilities/stateful-capability.js +1 -1
- package/dist/capabilities/sync.d.ts +11 -1
- package/dist/capabilities/sync.d.ts.map +1 -1
- package/dist/capabilities/sync.js +25 -5
- package/dist/capabilities/tool.d.ts +21 -0
- package/dist/capabilities/tool.d.ts.map +1 -1
- package/dist/capabilities/tool.js +3 -2
- package/dist/capabilities/webhook.js +1 -1
- package/dist/capabilities/workflow.d.ts +50 -0
- package/dist/capabilities/workflow.d.ts.map +1 -0
- package/dist/capabilities/workflow.js +40 -0
- package/dist/capabilities/workflow.test.d.ts +2 -0
- package/dist/capabilities/workflow.test.d.ts.map +1 -0
- package/dist/error.d.ts +36 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +14 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/schema-builder.d.ts.map +1 -1
- package/dist/triggers.d.ts +365 -0
- package/dist/triggers.d.ts.map +1 -0
- package/dist/triggers.generated.d.ts +246 -0
- package/dist/triggers.generated.d.ts.map +1 -0
- package/dist/triggers.generated.js +239 -0
- package/dist/triggers.js +0 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/worker.d.ts +33 -2
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +34 -0
- package/package.json +9 -2
- package/src/block.ts +40 -40
- package/src/builder.ts +20 -0
- package/src/capabilities/ai_connector.ts +1 -1
- package/src/capabilities/automation.ts +1 -1
- package/src/capabilities/context.ts +45 -3
- package/src/capabilities/stateful-capability.ts +1 -1
- package/src/capabilities/sync.test.ts +172 -1
- package/src/capabilities/sync.ts +46 -5
- package/src/capabilities/tool.test.ts +63 -0
- package/src/capabilities/tool.ts +23 -1
- package/src/capabilities/webhook.ts +1 -1
- package/src/capabilities/workflow.test.ts +184 -0
- package/src/capabilities/workflow.ts +119 -0
- package/src/error.ts +40 -0
- package/src/index.ts +22 -2
- package/src/schema-builder.ts +1 -0
- package/src/triggers.generated.ts +489 -0
- package/src/triggers.ts +504 -0
- package/src/types.ts +20 -0
- package/src/worker.ts +101 -8
package/src/triggers.ts
ADDED
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Trigger Types — Public API
|
|
3
|
+
*
|
|
4
|
+
* Shared type definitions for agent triggers between @notionhq/workers and the Notion repository.
|
|
5
|
+
* This file MUST be kept identical in both repositories.
|
|
6
|
+
*
|
|
7
|
+
* Conventions:
|
|
8
|
+
* - Protocols define the standard fields every consumer can rely on.
|
|
9
|
+
* - Vendor-specific fields use `x-<vendor>-` prefix (e.g., "x-slack-threadId").
|
|
10
|
+
* - Only public URLs — no internal URIs.
|
|
11
|
+
* - No `data` sub-object — vendor fields live at the top level with `x-<vendor>-`.
|
|
12
|
+
* - Types only — no runtime values.
|
|
13
|
+
* - All fields are required. Nullable fields use `T | null` (no `?:`) so they
|
|
14
|
+
* map directly to required + nullable in JSON Schema for LLM structured output.
|
|
15
|
+
* - Conversions must always provide explicit values (use `null` when absent).
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
// ============================================================
|
|
19
|
+
// Vendor extension pattern
|
|
20
|
+
// ============================================================
|
|
21
|
+
|
|
22
|
+
/** Allows arbitrary vendor-specific fields prefixed with `x-<vendor>-`. */
|
|
23
|
+
export type VendorExtensions = {
|
|
24
|
+
[key: `x-${string}`]: unknown
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ============================================================
|
|
28
|
+
// Protocols (composable capabilities)
|
|
29
|
+
// ============================================================
|
|
30
|
+
|
|
31
|
+
/** Has a human-readable message / summary. */
|
|
32
|
+
export type MessageLike = {
|
|
33
|
+
message: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Has an actor who performed the action. */
|
|
37
|
+
export type ActorLike = {
|
|
38
|
+
actor: Actor | null
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Has a navigable URL. */
|
|
42
|
+
export type LinkLike = {
|
|
43
|
+
url: string | null
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Has a timestamp. */
|
|
47
|
+
export type TimestampLike = {
|
|
48
|
+
/** ISO 8601 */
|
|
49
|
+
timestamp: string | null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Has a conversation thread. */
|
|
53
|
+
export type ThreadLike<M = ThreadMessage> = {
|
|
54
|
+
thread: Array<M>
|
|
55
|
+
/** Whether this event is a follow-up in a previously subscribed thread. */
|
|
56
|
+
isFollowUpMessage: boolean | null
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* A chat message. Any chat platform (Slack, Discord, MS Teams, etc.) implements this.
|
|
61
|
+
* Composes MessageLike, ActorLike, LinkLike, TimestampLike.
|
|
62
|
+
*/
|
|
63
|
+
export type ChatMessageLike = MessageLike &
|
|
64
|
+
ActorLike &
|
|
65
|
+
LinkLike &
|
|
66
|
+
TimestampLike & {
|
|
67
|
+
id: string
|
|
68
|
+
channelId: string
|
|
69
|
+
channelName: string | null
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** An email message. Any mail provider (Gmail, Outlook, etc.) implements this. */
|
|
73
|
+
export type EmailMessageLike = MessageLike &
|
|
74
|
+
LinkLike &
|
|
75
|
+
TimestampLike & {
|
|
76
|
+
id: string
|
|
77
|
+
subject: string
|
|
78
|
+
from: string
|
|
79
|
+
fromName: string | null
|
|
80
|
+
to: Array<string>
|
|
81
|
+
cc: Array<string> | null
|
|
82
|
+
bcc: Array<string> | null
|
|
83
|
+
/** Plain-text or HTML body content. */
|
|
84
|
+
body: string
|
|
85
|
+
isRead: boolean | null
|
|
86
|
+
hasAttachments: boolean | null
|
|
87
|
+
labels: Array<string> | null
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** An email thread. Any mail provider implements this. */
|
|
91
|
+
export type EmailThreadLike = {
|
|
92
|
+
id: string
|
|
93
|
+
subject: string
|
|
94
|
+
participants: Array<string>
|
|
95
|
+
messageCount: number
|
|
96
|
+
/** ISO 8601 */
|
|
97
|
+
lastMessageAt: string
|
|
98
|
+
hasUnread: boolean
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** A calendar event. Any calendar provider (Google, Outlook, iCal, etc.) implements this. */
|
|
102
|
+
export type CalendarEventLike = LinkLike &
|
|
103
|
+
TimestampLike & {
|
|
104
|
+
eventId: string
|
|
105
|
+
summary: string
|
|
106
|
+
description: string | null
|
|
107
|
+
location: string | null
|
|
108
|
+
/** ISO 8601 */
|
|
109
|
+
startTime: string
|
|
110
|
+
/** ISO 8601 */
|
|
111
|
+
endTime: string | null
|
|
112
|
+
isAllDay: boolean | null
|
|
113
|
+
isRecurring: boolean | null
|
|
114
|
+
attendees: Array<Actor> | null
|
|
115
|
+
calendarId: string
|
|
116
|
+
accountId: string
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ============================================================
|
|
120
|
+
// Core types
|
|
121
|
+
// ============================================================
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* An actor who performed an action.
|
|
125
|
+
*
|
|
126
|
+
* `id` / `displayName` / `email` are the Notion-resolved identity.
|
|
127
|
+
* `vendorActor` carries the identity in the originating system.
|
|
128
|
+
*/
|
|
129
|
+
export type Actor = {
|
|
130
|
+
/** Notion user ID (when resolved). */
|
|
131
|
+
id: string | null
|
|
132
|
+
displayName: string | null
|
|
133
|
+
email: string | null
|
|
134
|
+
/** The actor's identity in the vendor system. */
|
|
135
|
+
vendorActor: VendorActor | null
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Vendor-specific actor identity. */
|
|
139
|
+
export type VendorActor = {
|
|
140
|
+
/** Vendor name: "slack", "gmail", "discord", "notion", etc. */
|
|
141
|
+
vendor: string
|
|
142
|
+
/** Vendor-specific ID. */
|
|
143
|
+
id: string
|
|
144
|
+
displayName: string | null
|
|
145
|
+
/** Handle / username (e.g., Slack @handle). */
|
|
146
|
+
handle: string | null
|
|
147
|
+
/** "user", "bot", or a vendor-specific string. */
|
|
148
|
+
type: "user" | "bot" | string | null
|
|
149
|
+
/** URL to the actor's profile in the vendor system. */
|
|
150
|
+
url: string | null
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// ============================================================
|
|
154
|
+
// Thread message
|
|
155
|
+
// ============================================================
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* A single message inside a thread.
|
|
159
|
+
* Implements MessageLike, ActorLike, LinkLike, TimestampLike.
|
|
160
|
+
* Vendor-specific fields use `x-<vendor>-` prefix.
|
|
161
|
+
*/
|
|
162
|
+
export type ThreadMessage = MessageLike &
|
|
163
|
+
ActorLike &
|
|
164
|
+
LinkLike &
|
|
165
|
+
TimestampLike &
|
|
166
|
+
VendorExtensions & {
|
|
167
|
+
id: string
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** A chat thread message. Extends ChatMessageLike with VendorExtensions. */
|
|
171
|
+
export type ChatThreadMessage = ChatMessageLike & VendorExtensions
|
|
172
|
+
|
|
173
|
+
/** An email message in a trigger. Extends EmailMessageLike with VendorExtensions. */
|
|
174
|
+
export type EmailTriggerMessage = EmailMessageLike & VendorExtensions
|
|
175
|
+
|
|
176
|
+
// ============================================================
|
|
177
|
+
// Trigger event base
|
|
178
|
+
// ============================================================
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Every trigger event has at least these fields.
|
|
182
|
+
* `message` is a human-readable summary of what happened.
|
|
183
|
+
*/
|
|
184
|
+
export type TriggerEventBase = MessageLike &
|
|
185
|
+
ActorLike &
|
|
186
|
+
VendorExtensions & {
|
|
187
|
+
type: string
|
|
188
|
+
vendor: string
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Base shape for chat trigger events (Slack, Discord, MS Teams, etc.).
|
|
193
|
+
* Parameterized on the message type so each platform can narrow
|
|
194
|
+
* `triggerMessage` and `thread` to its vendor-specific message shape.
|
|
195
|
+
*/
|
|
196
|
+
type ChatEventBase<M extends ChatThreadMessage = ChatThreadMessage> =
|
|
197
|
+
TriggerEventBase &
|
|
198
|
+
LinkLike &
|
|
199
|
+
TimestampLike &
|
|
200
|
+
ThreadLike<M> & {
|
|
201
|
+
/** The message that fired the trigger. */
|
|
202
|
+
triggerMessage: M
|
|
203
|
+
channelId: string
|
|
204
|
+
channelName: string | null
|
|
205
|
+
threadId: string | null
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// ============================================================
|
|
209
|
+
// Slack
|
|
210
|
+
// ============================================================
|
|
211
|
+
|
|
212
|
+
export type SlackChatThreadMessage = ChatThreadMessage & {
|
|
213
|
+
"x-slack-fileUrls": Array<string> | null
|
|
214
|
+
/** URLs extracted from the message text. */
|
|
215
|
+
"x-slack-urls": Array<string> | null
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export type SlackMessageEvent = ChatEventBase<SlackChatThreadMessage> & {
|
|
219
|
+
type: "slack.message"
|
|
220
|
+
vendor: "slack"
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export type SlackReactionAddedEvent = ChatEventBase<SlackChatThreadMessage> & {
|
|
224
|
+
type: "slack.reaction.added"
|
|
225
|
+
vendor: "slack"
|
|
226
|
+
/** The emoji name (without colons), e.g. "thumbsup". */
|
|
227
|
+
"x-slack-reaction": string | null
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export type SlackAppMentionEvent = ChatEventBase<SlackChatThreadMessage> & {
|
|
231
|
+
type: "slack.app.mention"
|
|
232
|
+
vendor: "slack"
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// ============================================================
|
|
236
|
+
// Mail
|
|
237
|
+
// ============================================================
|
|
238
|
+
|
|
239
|
+
/** Base shape for all mail trigger events. */
|
|
240
|
+
type MailEventBase = TriggerEventBase &
|
|
241
|
+
LinkLike &
|
|
242
|
+
TimestampLike & {
|
|
243
|
+
vendor: "notionmail" | "gmail" | string
|
|
244
|
+
/** The triggering email. */
|
|
245
|
+
email: EmailTriggerMessage
|
|
246
|
+
/** The email thread this message belongs to. */
|
|
247
|
+
emailThread: EmailThreadLike
|
|
248
|
+
/** The email address of the mailbox owner. */
|
|
249
|
+
userEmail: string
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export type MailEmailReceivedEvent = MailEventBase & {
|
|
253
|
+
type: "mail.email.received"
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export type MailEmailSentEvent = MailEventBase & {
|
|
257
|
+
type: "mail.email.sent"
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export type MailLabelAppliedEvent = MailEventBase & {
|
|
261
|
+
type: "mail.label.applied"
|
|
262
|
+
/** The label that was applied. */
|
|
263
|
+
appliedLabel: string
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// ============================================================
|
|
267
|
+
// Calendar
|
|
268
|
+
// ============================================================
|
|
269
|
+
|
|
270
|
+
/** Base shape for all calendar trigger events. */
|
|
271
|
+
type CalendarEventBase = TriggerEventBase &
|
|
272
|
+
CalendarEventLike & {
|
|
273
|
+
vendor: "notion-calendar" | "google" | string
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export type CalendarEventCreatedEvent = CalendarEventBase & {
|
|
277
|
+
type: "calendar.event.created"
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export type CalendarEventUpdatedEvent = CalendarEventBase & {
|
|
281
|
+
type: "calendar.event.updated"
|
|
282
|
+
/** Which fields changed. */
|
|
283
|
+
updatedFields: Array<string> | null
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export type CalendarEventCanceledEvent = CalendarEventBase & {
|
|
287
|
+
type: "calendar.event.canceled"
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// ============================================================
|
|
291
|
+
// Discord
|
|
292
|
+
// ============================================================
|
|
293
|
+
|
|
294
|
+
export type DiscordChatThreadMessage = ChatThreadMessage & {
|
|
295
|
+
"x-discord-guildId": string | null
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export type DiscordInteractionEvent =
|
|
299
|
+
ChatEventBase<DiscordChatThreadMessage> & {
|
|
300
|
+
type: "discord.interaction"
|
|
301
|
+
vendor: "discord"
|
|
302
|
+
"x-discord-guildId": string | null
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// ============================================================
|
|
306
|
+
// Notion — Page / Database triggers
|
|
307
|
+
// ============================================================
|
|
308
|
+
|
|
309
|
+
/** A property edit with before/after snapshots. */
|
|
310
|
+
export type NotionPageEdit = {
|
|
311
|
+
before: Record<string, unknown> | null
|
|
312
|
+
after: Record<string, unknown> | null
|
|
313
|
+
afterContent: string | null
|
|
314
|
+
contentChanged: boolean | null
|
|
315
|
+
timestamp: number
|
|
316
|
+
editedBy: Actor | null
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export type NotionPageCreatedEvent = TriggerEventBase &
|
|
320
|
+
LinkLike &
|
|
321
|
+
TimestampLike & {
|
|
322
|
+
type: "notion.page.created"
|
|
323
|
+
vendor: "notion"
|
|
324
|
+
/** Page properties as key-value pairs. */
|
|
325
|
+
page: Record<string, unknown>
|
|
326
|
+
/** Rendered markdown content of the page. */
|
|
327
|
+
content: string
|
|
328
|
+
edits: Array<NotionPageEdit> | null
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
export type NotionPageUpdatedEvent = TriggerEventBase &
|
|
332
|
+
LinkLike &
|
|
333
|
+
TimestampLike & {
|
|
334
|
+
type: "notion.page.updated"
|
|
335
|
+
vendor: "notion"
|
|
336
|
+
/** Chronological array of edits (accumulated during debounce). */
|
|
337
|
+
edits: Array<NotionPageEdit>
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export type NotionPageDeletedEvent = TriggerEventBase &
|
|
341
|
+
LinkLike &
|
|
342
|
+
TimestampLike & {
|
|
343
|
+
type: "notion.page.deleted"
|
|
344
|
+
vendor: "notion"
|
|
345
|
+
page: Record<string, unknown>
|
|
346
|
+
content: string
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
export type NotionMeetingNoteSummaryCompletedEvent = TriggerEventBase &
|
|
350
|
+
LinkLike &
|
|
351
|
+
TimestampLike & {
|
|
352
|
+
type: "notion.meetingNote.summary.completed"
|
|
353
|
+
vendor: "notion"
|
|
354
|
+
page: Record<string, unknown>
|
|
355
|
+
content: string
|
|
356
|
+
meetingNoteBlockId: string
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// ============================================================
|
|
360
|
+
// Notion — Discussion / Comment triggers
|
|
361
|
+
// ============================================================
|
|
362
|
+
|
|
363
|
+
export type NotionCommentAddedEvent = TriggerEventBase &
|
|
364
|
+
LinkLike &
|
|
365
|
+
TimestampLike & {
|
|
366
|
+
type: "notion.page.discussion.comment.added"
|
|
367
|
+
vendor: "notion"
|
|
368
|
+
/** The full discussion context. */
|
|
369
|
+
discussion: {
|
|
370
|
+
id: string
|
|
371
|
+
pageId: string
|
|
372
|
+
resolved: boolean
|
|
373
|
+
context: "inline" | "block" | "page" | "databaseProperty" | null
|
|
374
|
+
parentBlockId: string | null
|
|
375
|
+
propertyId: string | null
|
|
376
|
+
propertyName: string | null
|
|
377
|
+
}
|
|
378
|
+
/** The new comment. */
|
|
379
|
+
comment: {
|
|
380
|
+
id: string
|
|
381
|
+
text: string
|
|
382
|
+
url: string
|
|
383
|
+
timestamp: string
|
|
384
|
+
actor: Actor | null
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// ============================================================
|
|
389
|
+
// Notion — Agent / Button triggers
|
|
390
|
+
// ============================================================
|
|
391
|
+
|
|
392
|
+
export type NotionAgentMentionedEvent = TriggerEventBase &
|
|
393
|
+
LinkLike &
|
|
394
|
+
TimestampLike & {
|
|
395
|
+
type: "notion.agent.mentioned"
|
|
396
|
+
vendor: "notion"
|
|
397
|
+
page: Record<string, unknown>
|
|
398
|
+
content: string
|
|
399
|
+
mentionLocation: "page_content" | "person_property"
|
|
400
|
+
mentionBlockContent: string | null
|
|
401
|
+
propertyId: string | null
|
|
402
|
+
propertyName: string | null
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
export type NotionButtonPressedEvent = TriggerEventBase &
|
|
406
|
+
LinkLike &
|
|
407
|
+
TimestampLike & {
|
|
408
|
+
type: "notion.button.pressed"
|
|
409
|
+
vendor: "notion"
|
|
410
|
+
blockUrl: string
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
export type NotionDatabaseAgentUpdatedEvent = TriggerEventBase &
|
|
414
|
+
TimestampLike & {
|
|
415
|
+
type: "notion.database.agent.updated"
|
|
416
|
+
vendor: "notion"
|
|
417
|
+
agentId: string
|
|
418
|
+
runtimeInstructions: string
|
|
419
|
+
shouldRunOverDatabase: boolean
|
|
420
|
+
viewId: string | null
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
export type WebhookEvent = TriggerEventBase &
|
|
424
|
+
TimestampLike & {
|
|
425
|
+
type: "webhooks.webhook"
|
|
426
|
+
vendor: "webhooks"
|
|
427
|
+
triggerId: string
|
|
428
|
+
verificationSchema: string
|
|
429
|
+
eventType: string | null
|
|
430
|
+
deliveryId: string | null
|
|
431
|
+
payload: unknown
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// ============================================================
|
|
435
|
+
// Google Drive OAuth — File changed (polling) trigger
|
|
436
|
+
// ============================================================
|
|
437
|
+
|
|
438
|
+
export type GoogleDriveOauthFilesChangedEvent = TriggerEventBase &
|
|
439
|
+
TimestampLike & {
|
|
440
|
+
type: "googleDriveOauth.filesChanged"
|
|
441
|
+
vendor: "google-drive"
|
|
442
|
+
/** The page token from before this poll. */
|
|
443
|
+
changeToken: string
|
|
444
|
+
/** The page token after this poll. */
|
|
445
|
+
newChangeToken: string
|
|
446
|
+
/** Number of changes detected. */
|
|
447
|
+
changeCount: number
|
|
448
|
+
/** The folder or drive being watched. */
|
|
449
|
+
scope:
|
|
450
|
+
| { type: "folder"; folderId: string }
|
|
451
|
+
| { type: "drive"; driveId: string }
|
|
452
|
+
/** Upper time bound for this poll window (ISO 8601). */
|
|
453
|
+
lastEventTimestamp: string
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// ============================================================
|
|
457
|
+
// Recurrence (scheduled) trigger
|
|
458
|
+
// ============================================================
|
|
459
|
+
|
|
460
|
+
export type RecurrenceFrequency = "hour" | "day" | "week" | "month" | "year"
|
|
461
|
+
|
|
462
|
+
export type RecurrenceEvent = TriggerEventBase &
|
|
463
|
+
TimestampLike & {
|
|
464
|
+
type: "recurrence"
|
|
465
|
+
vendor: "notion"
|
|
466
|
+
frequency: RecurrenceFrequency
|
|
467
|
+
interval: number
|
|
468
|
+
timezone: string
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// ============================================================
|
|
472
|
+
// Derived union types
|
|
473
|
+
// ============================================================
|
|
474
|
+
|
|
475
|
+
/** Map from trigger type string to its event shape. Single source of truth. */
|
|
476
|
+
export type TriggerEventMap = {
|
|
477
|
+
"slack.message": SlackMessageEvent
|
|
478
|
+
"slack.reaction.added": SlackReactionAddedEvent
|
|
479
|
+
"slack.app.mention": SlackAppMentionEvent
|
|
480
|
+
"discord.interaction": DiscordInteractionEvent
|
|
481
|
+
"mail.email.received": MailEmailReceivedEvent
|
|
482
|
+
"mail.email.sent": MailEmailSentEvent
|
|
483
|
+
"mail.label.applied": MailLabelAppliedEvent
|
|
484
|
+
"calendar.event.created": CalendarEventCreatedEvent
|
|
485
|
+
"calendar.event.updated": CalendarEventUpdatedEvent
|
|
486
|
+
"calendar.event.canceled": CalendarEventCanceledEvent
|
|
487
|
+
"notion.page.created": NotionPageCreatedEvent
|
|
488
|
+
"notion.page.updated": NotionPageUpdatedEvent
|
|
489
|
+
"notion.page.deleted": NotionPageDeletedEvent
|
|
490
|
+
"notion.meetingNote.summary.completed": NotionMeetingNoteSummaryCompletedEvent
|
|
491
|
+
"notion.page.discussion.comment.added": NotionCommentAddedEvent
|
|
492
|
+
"notion.agent.mentioned": NotionAgentMentionedEvent
|
|
493
|
+
"notion.button.pressed": NotionButtonPressedEvent
|
|
494
|
+
"notion.database.agent.updated": NotionDatabaseAgentUpdatedEvent
|
|
495
|
+
"webhooks.webhook": WebhookEvent
|
|
496
|
+
"googleDriveOauth.filesChanged": GoogleDriveOauthFilesChangedEvent
|
|
497
|
+
recurrence: RecurrenceEvent
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/** All trigger type strings. Derived from TriggerEventMap. */
|
|
501
|
+
export type TriggerType = keyof TriggerEventMap
|
|
502
|
+
|
|
503
|
+
/** Discriminated union of all trigger events. Derived from TriggerEventMap. */
|
|
504
|
+
export type TriggerEvent = TriggerEventMap[TriggerType]
|
package/src/types.ts
CHANGED
|
@@ -182,6 +182,26 @@ export interface ImageIcon {
|
|
|
182
182
|
*/
|
|
183
183
|
export type Icon = EmojiIcon | NoticonIcon | ImageIcon;
|
|
184
184
|
|
|
185
|
+
/**
|
|
186
|
+
* Cover image for a Notion page.
|
|
187
|
+
*/
|
|
188
|
+
export interface ImageCover {
|
|
189
|
+
type: "image";
|
|
190
|
+
/**
|
|
191
|
+
* The URL of the image (must be a valid http/https URL)
|
|
192
|
+
*/
|
|
193
|
+
url: string;
|
|
194
|
+
/**
|
|
195
|
+
* Vertical image position, from 0 (top) to 1 (bottom).
|
|
196
|
+
*/
|
|
197
|
+
position?: number;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* All possible cover types
|
|
202
|
+
*/
|
|
203
|
+
export type Cover = ImageCover;
|
|
204
|
+
|
|
185
205
|
/**
|
|
186
206
|
* Person reference - represents a user in a people property
|
|
187
207
|
*/
|
package/src/worker.ts
CHANGED
|
@@ -31,24 +31,33 @@ import {
|
|
|
31
31
|
createWebhookCapability,
|
|
32
32
|
WebhookVerificationError,
|
|
33
33
|
} from "./capabilities/webhook.js";
|
|
34
|
+
import type {
|
|
35
|
+
WorkflowCapability,
|
|
36
|
+
WorkflowConfiguration,
|
|
37
|
+
WorkflowEvent,
|
|
38
|
+
} from "./capabilities/workflow.js";
|
|
39
|
+
import { createWorkflowCapability } from "./capabilities/workflow.js";
|
|
34
40
|
import type { PacerDeclaration } from "./pacer_internal.js";
|
|
35
41
|
import { pacerWait } from "./pacer_internal.js";
|
|
36
42
|
import type { Schema } from "./schema.js";
|
|
43
|
+
import type { WorkflowTrigger } from "./triggers.generated.js";
|
|
37
44
|
import type { HandlerOptions, JSONValue } from "./types.js";
|
|
38
45
|
|
|
39
46
|
// Re-export types for convenience
|
|
40
47
|
export type {
|
|
48
|
+
AiConnectorConfiguration,
|
|
41
49
|
AutomationConfiguration,
|
|
42
50
|
AutomationEvent,
|
|
43
|
-
AiConnectorConfiguration,
|
|
44
51
|
CapabilityContext,
|
|
45
|
-
OAuthConfiguration,
|
|
46
52
|
NotionManagedOAuthConfiguration,
|
|
47
|
-
|
|
53
|
+
OAuthConfiguration,
|
|
48
54
|
SyncConfiguration,
|
|
49
55
|
ToolConfiguration,
|
|
56
|
+
UserManagedOAuthConfiguration,
|
|
50
57
|
WebhookConfiguration,
|
|
51
58
|
WebhookEvent,
|
|
59
|
+
WorkflowConfiguration,
|
|
60
|
+
WorkflowEvent,
|
|
52
61
|
};
|
|
53
62
|
export { WebhookVerificationError };
|
|
54
63
|
|
|
@@ -62,6 +71,49 @@ type Capability =
|
|
|
62
71
|
// biome-ignore lint/suspicious/noExplicitAny: tool capabilities are generic over arbitrary input/output payloads.
|
|
63
72
|
| ToolCapability<any, any>
|
|
64
73
|
| AutomationCapability
|
|
74
|
+
| WorkflowCapability
|
|
75
|
+
| OAuthCapability
|
|
76
|
+
| WebhookCapability;
|
|
77
|
+
|
|
78
|
+
export type CapabilityType = Capability["_tag"];
|
|
79
|
+
|
|
80
|
+
// ============================================================================
|
|
81
|
+
// Internal capability storage
|
|
82
|
+
// ============================================================================
|
|
83
|
+
//
|
|
84
|
+
// Registration methods return capabilities whose handler parameters are
|
|
85
|
+
// narrowed to the inputs they declared (e.g. a workflow handler only
|
|
86
|
+
// accepts events for its declared triggers). Handlers are contravariant in
|
|
87
|
+
// those parameters, so the narrowed capabilities are not assignable to the
|
|
88
|
+
// all-inputs members of `Capability`. Rather than cast them, the internal
|
|
89
|
+
// store is honest about this type erasure: stored handlers take `never`,
|
|
90
|
+
// recording that the store cannot prove what each handler accepts. `run()`
|
|
91
|
+
// is the single place that re-asserts the platform's contract that the
|
|
92
|
+
// incoming context matches the capability's declared input.
|
|
93
|
+
|
|
94
|
+
/** A tool capability as stored: its input/output types are erased. */
|
|
95
|
+
type StoredToolCapability = Omit<
|
|
96
|
+
Extract<Capability, { _tag: "tool" }>,
|
|
97
|
+
"handler"
|
|
98
|
+
> & {
|
|
99
|
+
handler: (input: never, options?: HandlerOptions) => Promise<unknown>;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/** A workflow capability as stored: its event type is erased. */
|
|
103
|
+
type StoredWorkflowCapability = Omit<WorkflowCapability, "handler"> & {
|
|
104
|
+
handler: (
|
|
105
|
+
event: never,
|
|
106
|
+
options?: HandlerOptions,
|
|
107
|
+
) => Promise<{ status: "success" } | undefined>;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/** How `Worker` stores registered capabilities internally. */
|
|
111
|
+
type StoredCapability =
|
|
112
|
+
| SyncCapability
|
|
113
|
+
| AiConnectorCapability
|
|
114
|
+
| StoredToolCapability
|
|
115
|
+
| AutomationCapability
|
|
116
|
+
| StoredWorkflowCapability
|
|
65
117
|
| OAuthCapability
|
|
66
118
|
| WebhookCapability;
|
|
67
119
|
|
|
@@ -196,7 +248,7 @@ const SDK_VERSION = (() => {
|
|
|
196
248
|
// ============================================================================
|
|
197
249
|
|
|
198
250
|
export class Worker {
|
|
199
|
-
#capabilities: Map<string,
|
|
251
|
+
#capabilities: Map<string, StoredCapability> = new Map();
|
|
200
252
|
#databases: Map<string, RegisteredDatabase> = new Map();
|
|
201
253
|
#pacers: Map<string, PacerDeclaration> = new Map();
|
|
202
254
|
|
|
@@ -407,8 +459,7 @@ export class Worker {
|
|
|
407
459
|
): ToolCapability<I, O> {
|
|
408
460
|
this.#validateUniqueKey(key);
|
|
409
461
|
const capability = createToolCapability(key, config);
|
|
410
|
-
|
|
411
|
-
this.#capabilities.set(key, capability as ToolCapability<any, any>);
|
|
462
|
+
this.#capabilities.set(key, capability);
|
|
412
463
|
return capability;
|
|
413
464
|
}
|
|
414
465
|
|
|
@@ -454,6 +505,45 @@ export class Worker {
|
|
|
454
505
|
return capability;
|
|
455
506
|
}
|
|
456
507
|
|
|
508
|
+
/**
|
|
509
|
+
* Register a workflow capability.
|
|
510
|
+
*
|
|
511
|
+
* Example:
|
|
512
|
+
*
|
|
513
|
+
* ```ts
|
|
514
|
+
* import { Worker } from "@notionhq/workers";
|
|
515
|
+
* import { triggers } from "@notionhq/workers/triggers";
|
|
516
|
+
*
|
|
517
|
+
* const worker = new Worker();
|
|
518
|
+
* export default worker;
|
|
519
|
+
*
|
|
520
|
+
* worker.workflow("sendWelcomeEmail", {
|
|
521
|
+
* title: "Send Welcome Email",
|
|
522
|
+
* description: "Sends a welcome email when a new user is added",
|
|
523
|
+
* triggers: [triggers.notionPageCreated()],
|
|
524
|
+
* execute: async (event) => {
|
|
525
|
+
* console.log(event.page);
|
|
526
|
+
* console.log(event.content);
|
|
527
|
+
* },
|
|
528
|
+
* })
|
|
529
|
+
* ```
|
|
530
|
+
*
|
|
531
|
+
* @param key - The unique key for this capability.
|
|
532
|
+
* @param config - The workflow configuration.
|
|
533
|
+
* @returns The capability object.
|
|
534
|
+
*/
|
|
535
|
+
workflow<
|
|
536
|
+
const TTriggers extends readonly [WorkflowTrigger, ...WorkflowTrigger[]],
|
|
537
|
+
>(
|
|
538
|
+
key: string,
|
|
539
|
+
config: WorkflowConfiguration<TTriggers>,
|
|
540
|
+
): WorkflowCapability<TTriggers> {
|
|
541
|
+
this.#validateUniqueKey(key);
|
|
542
|
+
const capability = createWorkflowCapability(key, config);
|
|
543
|
+
this.#capabilities.set(key, capability);
|
|
544
|
+
return capability;
|
|
545
|
+
}
|
|
546
|
+
|
|
457
547
|
/**
|
|
458
548
|
* Register a webhook capability.
|
|
459
549
|
*
|
|
@@ -586,8 +676,11 @@ export class Worker {
|
|
|
586
676
|
throw new Error(`Capability "${key}" cannot be executed`);
|
|
587
677
|
}
|
|
588
678
|
|
|
589
|
-
//
|
|
590
|
-
|
|
679
|
+
// The store erases handler parameter types to `never` (see
|
|
680
|
+
// `StoredCapability`); the platform guarantees the context passed by
|
|
681
|
+
// external code matches the capability's declared input, so re-assert
|
|
682
|
+
// that contract here.
|
|
683
|
+
return capability.handler(context as never, options);
|
|
591
684
|
}
|
|
592
685
|
|
|
593
686
|
#validateUniqueKey(key: string): void {
|