@automate.ax/integration-contracts 0.88.9 → 0.89.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.
@@ -0,0 +1,365 @@
1
+ import type {
2
+ CommentCreatedWebhookPayload,
3
+ CommentDeletedWebhookPayload,
4
+ CommentUpdatedWebhookPayload,
5
+ DataSourceContentUpdatedWebhookPayload,
6
+ DataSourceCreatedWebhookPayload,
7
+ DataSourceDeletedWebhookPayload,
8
+ DataSourceMovedWebhookPayload,
9
+ DataSourceSchemaUpdatedWebhookPayload,
10
+ DataSourceUndeletedWebhookPayload,
11
+ DatabaseCreatedWebhookPayload,
12
+ DatabaseDeletedWebhookPayload,
13
+ DatabaseMovedWebhookPayload,
14
+ DatabaseUndeletedWebhookPayload,
15
+ FileUploadCompletedWebhookPayload,
16
+ FileUploadCreatedWebhookPayload,
17
+ FileUploadExpiredWebhookPayload,
18
+ FileUploadUploadFailedWebhookPayload,
19
+ PageContentUpdatedWebhookPayload,
20
+ PageCreatedWebhookPayload,
21
+ PageDeletedWebhookPayload,
22
+ PageLockedWebhookPayload,
23
+ PageMovedWebhookPayload,
24
+ PagePropertiesUpdatedWebhookPayload,
25
+ PageTranscriptionBlockTranscriptDeletedWebhookPayload,
26
+ PageUndeletedWebhookPayload,
27
+ PageUnlockedWebhookPayload,
28
+ ViewCreatedWebhookPayload,
29
+ ViewDeletedWebhookPayload,
30
+ ViewUpdatedWebhookPayload,
31
+ } from "@notionhq/client"
32
+ import * as z from "zod"
33
+
34
+ type OfficialNotionWebhookEvent =
35
+ | CommentCreatedWebhookPayload
36
+ | CommentDeletedWebhookPayload
37
+ | CommentUpdatedWebhookPayload
38
+ | DataSourceContentUpdatedWebhookPayload
39
+ | DataSourceCreatedWebhookPayload
40
+ | DataSourceDeletedWebhookPayload
41
+ | DataSourceMovedWebhookPayload
42
+ | DataSourceSchemaUpdatedWebhookPayload
43
+ | DataSourceUndeletedWebhookPayload
44
+ | DatabaseCreatedWebhookPayload
45
+ | DatabaseDeletedWebhookPayload
46
+ | DatabaseMovedWebhookPayload
47
+ | DatabaseUndeletedWebhookPayload
48
+ | FileUploadCompletedWebhookPayload
49
+ | FileUploadCreatedWebhookPayload
50
+ | FileUploadExpiredWebhookPayload
51
+ | FileUploadUploadFailedWebhookPayload
52
+ | PageContentUpdatedWebhookPayload
53
+ | PageCreatedWebhookPayload
54
+ | PageDeletedWebhookPayload
55
+ | PageLockedWebhookPayload
56
+ | PageMovedWebhookPayload
57
+ | PagePropertiesUpdatedWebhookPayload
58
+ | PageTranscriptionBlockTranscriptDeletedWebhookPayload
59
+ | PageUndeletedWebhookPayload
60
+ | PageUnlockedWebhookPayload
61
+ | ViewCreatedWebhookPayload
62
+ | ViewDeletedWebhookPayload
63
+ | ViewUpdatedWebhookPayload
64
+
65
+ /** Actor reported as the author of a current Notion webhook event. */
66
+ export type NotionWebhookAuthor = {
67
+ id: string
68
+ type: "agent" | "bot" | "person"
69
+ }
70
+
71
+ /** Official Notion webhook payload with agent-authored changes included. */
72
+ type ExpectedNotionWebhookEvent =
73
+ OfficialNotionWebhookEvent extends infer TEvent
74
+ ? TEvent extends OfficialNotionWebhookEvent
75
+ ? Omit<TEvent, "authors"> & { authors: NotionWebhookAuthor[] }
76
+ : never
77
+ : never
78
+ type OfficialNotionWebhookEventType = ExpectedNotionWebhookEvent["type"]
79
+
80
+ const UUID_SCHEMA = z.uuid()
81
+ const ACCESS_ACTOR_SCHEMA = z.discriminatedUnion("type", [
82
+ z.object({ id: UUID_SCHEMA, type: z.literal("person") }),
83
+ z.object({ id: UUID_SCHEMA, type: z.literal("bot") }),
84
+ ])
85
+ const AUTHOR_SCHEMA = z.discriminatedUnion("type", [
86
+ ...ACCESS_ACTOR_SCHEMA.options,
87
+ z.object({ id: UUID_SCHEMA, type: z.literal("agent") }),
88
+ ])
89
+ const BASE_SHAPE = {
90
+ accessible_by: ACCESS_ACTOR_SCHEMA.array().optional(),
91
+ api_version: z.enum(["2022-06-28", "2025-09-03", "2026-03-11"]),
92
+ attempt_number: z.number().int().min(1).max(8),
93
+ authors: AUTHOR_SCHEMA.array(),
94
+ id: UUID_SCHEMA,
95
+ integration_id: UUID_SCHEMA,
96
+ subscription_id: UUID_SCHEMA,
97
+ timestamp: z.iso.datetime({ offset: true }),
98
+ workspace_id: UUID_SCHEMA,
99
+ workspace_name: z.string(),
100
+ } as const
101
+ const PARENT_SCHEMA = z.object({
102
+ data_source_id: UUID_SCHEMA.optional(),
103
+ id: UUID_SCHEMA,
104
+ type: z.enum(["space", "block", "page", "database", "team", "agent"]),
105
+ })
106
+ const EXTERNAL_BLOCK_SCHEMA = z.object({
107
+ id: UUID_SCHEMA,
108
+ type: z.enum(["page", "database", "block"]),
109
+ })
110
+ const UPDATED_BLOCK_SCHEMA = EXTERNAL_BLOCK_SCHEMA
111
+ const PAGE_ENTITY_SCHEMA = z.object({
112
+ id: UUID_SCHEMA,
113
+ type: z.literal("page"),
114
+ })
115
+ const DATABASE_ENTITY_SCHEMA = z.object({
116
+ id: UUID_SCHEMA,
117
+ type: z.enum(["block", "database", "data_source"]),
118
+ })
119
+ const COMMENT_ENTITY_SCHEMA = z.object({
120
+ id: UUID_SCHEMA,
121
+ type: z.literal("comment"),
122
+ })
123
+ const FILE_UPLOAD_ENTITY_SCHEMA = z.object({
124
+ id: UUID_SCHEMA,
125
+ type: z.literal("file_upload"),
126
+ })
127
+ const VIEW_ENTITY_SCHEMA = z.object({
128
+ id: UUID_SCHEMA,
129
+ type: z.literal("view"),
130
+ })
131
+ const PARENT_DATA_SCHEMA = z.object({ parent: PARENT_SCHEMA })
132
+ const COMMENT_DATA_SCHEMA = z.object({
133
+ page_id: UUID_SCHEMA,
134
+ parent: EXTERNAL_BLOCK_SCHEMA,
135
+ })
136
+
137
+ const RAW_NOTION_EVENT_SCHEMA = z.discriminatedUnion("type", [
138
+ eventWithDataSchema(
139
+ "comment.created",
140
+ COMMENT_ENTITY_SCHEMA,
141
+ COMMENT_DATA_SCHEMA,
142
+ ),
143
+ eventWithDataSchema(
144
+ "comment.deleted",
145
+ COMMENT_ENTITY_SCHEMA,
146
+ COMMENT_DATA_SCHEMA,
147
+ ),
148
+ eventWithDataSchema(
149
+ "comment.updated",
150
+ COMMENT_ENTITY_SCHEMA,
151
+ COMMENT_DATA_SCHEMA,
152
+ ),
153
+ eventWithDataSchema(
154
+ "data_source.content_updated",
155
+ DATABASE_ENTITY_SCHEMA,
156
+ z.object({
157
+ parent: PARENT_SCHEMA,
158
+ updated_blocks: UPDATED_BLOCK_SCHEMA.array(),
159
+ }),
160
+ ),
161
+ eventWithDataSchema(
162
+ "data_source.created",
163
+ DATABASE_ENTITY_SCHEMA,
164
+ PARENT_DATA_SCHEMA,
165
+ ),
166
+ eventWithDataSchema(
167
+ "data_source.deleted",
168
+ DATABASE_ENTITY_SCHEMA,
169
+ PARENT_DATA_SCHEMA,
170
+ ),
171
+ eventWithDataSchema(
172
+ "data_source.moved",
173
+ DATABASE_ENTITY_SCHEMA,
174
+ PARENT_DATA_SCHEMA,
175
+ ),
176
+ eventWithDataSchema(
177
+ "data_source.schema_updated",
178
+ DATABASE_ENTITY_SCHEMA,
179
+ z.object({
180
+ parent: PARENT_SCHEMA,
181
+ updated_properties: z
182
+ .object({
183
+ action: z.enum(["created", "updated", "deleted"]),
184
+ id: z.string(),
185
+ name: z.string().nullable(),
186
+ })
187
+ .array()
188
+ .optional(),
189
+ }),
190
+ ),
191
+ eventWithDataSchema(
192
+ "data_source.undeleted",
193
+ DATABASE_ENTITY_SCHEMA,
194
+ PARENT_DATA_SCHEMA,
195
+ ),
196
+ eventWithDataSchema(
197
+ "database.created",
198
+ DATABASE_ENTITY_SCHEMA,
199
+ PARENT_DATA_SCHEMA,
200
+ ),
201
+ eventWithDataSchema(
202
+ "database.deleted",
203
+ DATABASE_ENTITY_SCHEMA,
204
+ PARENT_DATA_SCHEMA,
205
+ ),
206
+ eventWithDataSchema(
207
+ "database.moved",
208
+ DATABASE_ENTITY_SCHEMA,
209
+ PARENT_DATA_SCHEMA,
210
+ ),
211
+ eventWithDataSchema(
212
+ "database.undeleted",
213
+ DATABASE_ENTITY_SCHEMA,
214
+ PARENT_DATA_SCHEMA,
215
+ ),
216
+ eventSchema("file_upload.completed", FILE_UPLOAD_ENTITY_SCHEMA),
217
+ eventSchema("file_upload.created", FILE_UPLOAD_ENTITY_SCHEMA),
218
+ eventSchema("file_upload.expired", FILE_UPLOAD_ENTITY_SCHEMA),
219
+ eventWithDataSchema(
220
+ "file_upload.upload_failed",
221
+ FILE_UPLOAD_ENTITY_SCHEMA,
222
+ z.object({
223
+ file_import_result: z.discriminatedUnion("type", [
224
+ z.object({
225
+ imported_time: z.iso.datetime({ offset: true }),
226
+ success: z.object({}),
227
+ type: z.literal("success"),
228
+ }),
229
+ z.object({
230
+ error: z.object({
231
+ code: z.string(),
232
+ message: z.string(),
233
+ parameter: z.string().nullable(),
234
+ status_code: z.number().nullable(),
235
+ type: z.enum([
236
+ "validation_error",
237
+ "internal_system_error",
238
+ "download_error",
239
+ "upload_error",
240
+ ]),
241
+ }),
242
+ imported_time: z.iso.datetime({ offset: true }),
243
+ type: z.literal("error"),
244
+ }),
245
+ ]),
246
+ }),
247
+ ),
248
+ eventWithDataSchema(
249
+ "page.content_updated",
250
+ PAGE_ENTITY_SCHEMA,
251
+ z.object({
252
+ parent: PARENT_SCHEMA,
253
+ updated_blocks: UPDATED_BLOCK_SCHEMA.array(),
254
+ }),
255
+ ),
256
+ eventWithDataSchema("page.created", PAGE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
257
+ eventWithDataSchema("page.deleted", PAGE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
258
+ eventWithDataSchema("page.locked", PAGE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
259
+ eventWithDataSchema("page.moved", PAGE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
260
+ eventWithDataSchema(
261
+ "page.properties_updated",
262
+ PAGE_ENTITY_SCHEMA,
263
+ z.object({
264
+ parent: PARENT_SCHEMA,
265
+ updated_properties: z.string().array(),
266
+ }),
267
+ ),
268
+ eventWithDataSchema(
269
+ "page.transcription_block.transcript_deleted",
270
+ PAGE_ENTITY_SCHEMA,
271
+ z.object({
272
+ target: EXTERNAL_BLOCK_SCHEMA,
273
+ transcript_id: z.string().nullable(),
274
+ }),
275
+ ),
276
+ eventWithDataSchema("page.undeleted", PAGE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
277
+ eventWithDataSchema("page.unlocked", PAGE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
278
+ eventWithDataSchema(
279
+ "view.created",
280
+ VIEW_ENTITY_SCHEMA,
281
+ z.object({ parent: PARENT_SCHEMA, view_type: z.string() }),
282
+ ),
283
+ eventWithDataSchema("view.deleted", VIEW_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
284
+ eventWithDataSchema(
285
+ "view.updated",
286
+ VIEW_ENTITY_SCHEMA,
287
+ z.object({
288
+ parent: PARENT_SCHEMA,
289
+ updated_fields: z
290
+ .enum(["name", "filter", "sorts", "configuration"])
291
+ .array(),
292
+ }),
293
+ ),
294
+ ]) satisfies z.ZodType<ExpectedNotionWebhookEvent>
295
+
296
+ /** Current portable Notion webhook payload validated at ingress. */
297
+ export type NotionWebhookEvent = z.infer<typeof RAW_NOTION_EVENT_SCHEMA>
298
+
299
+ export type NotionWebhookEventType = NotionWebhookEvent["type"]
300
+
301
+ export type NotionSemanticWebhookEvent<TType extends NotionWebhookEventType> =
302
+ Extract<NotionWebhookEvent, { type: TType }>
303
+
304
+ /** Exact current Notion webhook schema shared by ingress and triggers. */
305
+ export const NOTION_EVENT_SCHEMA = RAW_NOTION_EVENT_SCHEMA
306
+
307
+ /**
308
+ * Runtime schema for one semantic Notion webhook event.
309
+ *
310
+ * @param type - Official event discriminant to require.
311
+ */
312
+ export function notionSemanticEventSchema<TType extends NotionWebhookEventType>(
313
+ type: TType,
314
+ ) {
315
+ return z.custom<NotionSemanticWebhookEvent<TType>>(
316
+ (value) =>
317
+ RAW_NOTION_EVENT_SCHEMA.safeParse(value).success &&
318
+ typeof value === "object" &&
319
+ value !== null &&
320
+ "type" in value &&
321
+ value.type === type,
322
+ { message: `Expected a Notion ${type} webhook event.` },
323
+ )
324
+ }
325
+
326
+ /**
327
+ * Builds one provider webhook schema over the shared delivery envelope.
328
+ *
329
+ * @param type - Official event discriminant.
330
+ * @param entity - Entity reference schema for the event family.
331
+ */
332
+ function eventSchema<
333
+ const TType extends OfficialNotionWebhookEventType,
334
+ TEntity extends z.ZodType,
335
+ >(type: TType, entity: TEntity) {
336
+ return z
337
+ .object({
338
+ ...BASE_SHAPE,
339
+ entity,
340
+ type: z.literal(type),
341
+ })
342
+ .catchall(z.json())
343
+ }
344
+
345
+ /**
346
+ * Builds one provider webhook schema with event-specific data.
347
+ *
348
+ * @param type - Official event discriminant.
349
+ * @param entity - Entity reference schema for the event family.
350
+ * @param data - Event-specific data schema.
351
+ */
352
+ function eventWithDataSchema<
353
+ const TType extends OfficialNotionWebhookEventType,
354
+ TEntity extends z.ZodType,
355
+ TData extends z.ZodType,
356
+ >(type: TType, entity: TEntity, data: TData) {
357
+ return z
358
+ .object({
359
+ ...BASE_SHAPE,
360
+ data,
361
+ entity,
362
+ type: z.literal(type),
363
+ })
364
+ .catchall(z.json())
365
+ }
package/src/triggers.ts CHANGED
@@ -9,6 +9,7 @@ import type { googleCalendarTriggerContracts } from "./google-calendar"
9
9
  import type { googleFormsTriggerContracts } from "./google-forms"
10
10
  import type { googleMeetTriggerContracts } from "./google-meet"
11
11
  import type { linearTriggerContracts } from "./linear"
12
+ import type { notionTriggerContracts } from "./notion"
12
13
  import type { outlookTriggerContracts } from "./outlook"
13
14
  import type { resendTriggerContracts } from "./resend"
14
15
  import type { slackTriggerContracts } from "./slack"
@@ -31,6 +32,7 @@ export type TriggerContractMap = typeof airtableTriggerContracts &
31
32
  typeof googleFormsTriggerContracts &
32
33
  typeof googleMeetTriggerContracts &
33
34
  typeof linearTriggerContracts &
35
+ typeof notionTriggerContracts &
34
36
  typeof outlookTriggerContracts &
35
37
  typeof resendTriggerContracts &
36
38
  typeof slackTriggerContracts &