@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,185 @@
1
+ import * as z from "zod";
2
+ const UUID_SCHEMA = z.uuid();
3
+ const ACCESS_ACTOR_SCHEMA = z.discriminatedUnion("type", [
4
+ z.object({ id: UUID_SCHEMA, type: z.literal("person") }),
5
+ z.object({ id: UUID_SCHEMA, type: z.literal("bot") }),
6
+ ]);
7
+ const AUTHOR_SCHEMA = z.discriminatedUnion("type", [
8
+ ...ACCESS_ACTOR_SCHEMA.options,
9
+ z.object({ id: UUID_SCHEMA, type: z.literal("agent") }),
10
+ ]);
11
+ const BASE_SHAPE = {
12
+ accessible_by: ACCESS_ACTOR_SCHEMA.array().optional(),
13
+ api_version: z.enum(["2022-06-28", "2025-09-03", "2026-03-11"]),
14
+ attempt_number: z.number().int().min(1).max(8),
15
+ authors: AUTHOR_SCHEMA.array(),
16
+ id: UUID_SCHEMA,
17
+ integration_id: UUID_SCHEMA,
18
+ subscription_id: UUID_SCHEMA,
19
+ timestamp: z.iso.datetime({ offset: true }),
20
+ workspace_id: UUID_SCHEMA,
21
+ workspace_name: z.string(),
22
+ };
23
+ const PARENT_SCHEMA = z.object({
24
+ data_source_id: UUID_SCHEMA.optional(),
25
+ id: UUID_SCHEMA,
26
+ type: z.enum(["space", "block", "page", "database", "team", "agent"]),
27
+ });
28
+ const EXTERNAL_BLOCK_SCHEMA = z.object({
29
+ id: UUID_SCHEMA,
30
+ type: z.enum(["page", "database", "block"]),
31
+ });
32
+ const UPDATED_BLOCK_SCHEMA = EXTERNAL_BLOCK_SCHEMA;
33
+ const PAGE_ENTITY_SCHEMA = z.object({
34
+ id: UUID_SCHEMA,
35
+ type: z.literal("page"),
36
+ });
37
+ const DATABASE_ENTITY_SCHEMA = z.object({
38
+ id: UUID_SCHEMA,
39
+ type: z.enum(["block", "database", "data_source"]),
40
+ });
41
+ const COMMENT_ENTITY_SCHEMA = z.object({
42
+ id: UUID_SCHEMA,
43
+ type: z.literal("comment"),
44
+ });
45
+ const FILE_UPLOAD_ENTITY_SCHEMA = z.object({
46
+ id: UUID_SCHEMA,
47
+ type: z.literal("file_upload"),
48
+ });
49
+ const VIEW_ENTITY_SCHEMA = z.object({
50
+ id: UUID_SCHEMA,
51
+ type: z.literal("view"),
52
+ });
53
+ const PARENT_DATA_SCHEMA = z.object({ parent: PARENT_SCHEMA });
54
+ const COMMENT_DATA_SCHEMA = z.object({
55
+ page_id: UUID_SCHEMA,
56
+ parent: EXTERNAL_BLOCK_SCHEMA,
57
+ });
58
+ const RAW_NOTION_EVENT_SCHEMA = z.discriminatedUnion("type", [
59
+ eventWithDataSchema("comment.created", COMMENT_ENTITY_SCHEMA, COMMENT_DATA_SCHEMA),
60
+ eventWithDataSchema("comment.deleted", COMMENT_ENTITY_SCHEMA, COMMENT_DATA_SCHEMA),
61
+ eventWithDataSchema("comment.updated", COMMENT_ENTITY_SCHEMA, COMMENT_DATA_SCHEMA),
62
+ eventWithDataSchema("data_source.content_updated", DATABASE_ENTITY_SCHEMA, z.object({
63
+ parent: PARENT_SCHEMA,
64
+ updated_blocks: UPDATED_BLOCK_SCHEMA.array(),
65
+ })),
66
+ eventWithDataSchema("data_source.created", DATABASE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
67
+ eventWithDataSchema("data_source.deleted", DATABASE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
68
+ eventWithDataSchema("data_source.moved", DATABASE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
69
+ eventWithDataSchema("data_source.schema_updated", DATABASE_ENTITY_SCHEMA, z.object({
70
+ parent: PARENT_SCHEMA,
71
+ updated_properties: z
72
+ .object({
73
+ action: z.enum(["created", "updated", "deleted"]),
74
+ id: z.string(),
75
+ name: z.string().nullable(),
76
+ })
77
+ .array()
78
+ .optional(),
79
+ })),
80
+ eventWithDataSchema("data_source.undeleted", DATABASE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
81
+ eventWithDataSchema("database.created", DATABASE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
82
+ eventWithDataSchema("database.deleted", DATABASE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
83
+ eventWithDataSchema("database.moved", DATABASE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
84
+ eventWithDataSchema("database.undeleted", DATABASE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
85
+ eventSchema("file_upload.completed", FILE_UPLOAD_ENTITY_SCHEMA),
86
+ eventSchema("file_upload.created", FILE_UPLOAD_ENTITY_SCHEMA),
87
+ eventSchema("file_upload.expired", FILE_UPLOAD_ENTITY_SCHEMA),
88
+ eventWithDataSchema("file_upload.upload_failed", FILE_UPLOAD_ENTITY_SCHEMA, z.object({
89
+ file_import_result: z.discriminatedUnion("type", [
90
+ z.object({
91
+ imported_time: z.iso.datetime({ offset: true }),
92
+ success: z.object({}),
93
+ type: z.literal("success"),
94
+ }),
95
+ z.object({
96
+ error: z.object({
97
+ code: z.string(),
98
+ message: z.string(),
99
+ parameter: z.string().nullable(),
100
+ status_code: z.number().nullable(),
101
+ type: z.enum([
102
+ "validation_error",
103
+ "internal_system_error",
104
+ "download_error",
105
+ "upload_error",
106
+ ]),
107
+ }),
108
+ imported_time: z.iso.datetime({ offset: true }),
109
+ type: z.literal("error"),
110
+ }),
111
+ ]),
112
+ })),
113
+ eventWithDataSchema("page.content_updated", PAGE_ENTITY_SCHEMA, z.object({
114
+ parent: PARENT_SCHEMA,
115
+ updated_blocks: UPDATED_BLOCK_SCHEMA.array(),
116
+ })),
117
+ eventWithDataSchema("page.created", PAGE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
118
+ eventWithDataSchema("page.deleted", PAGE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
119
+ eventWithDataSchema("page.locked", PAGE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
120
+ eventWithDataSchema("page.moved", PAGE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
121
+ eventWithDataSchema("page.properties_updated", PAGE_ENTITY_SCHEMA, z.object({
122
+ parent: PARENT_SCHEMA,
123
+ updated_properties: z.string().array(),
124
+ })),
125
+ eventWithDataSchema("page.transcription_block.transcript_deleted", PAGE_ENTITY_SCHEMA, z.object({
126
+ target: EXTERNAL_BLOCK_SCHEMA,
127
+ transcript_id: z.string().nullable(),
128
+ })),
129
+ eventWithDataSchema("page.undeleted", PAGE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
130
+ eventWithDataSchema("page.unlocked", PAGE_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
131
+ eventWithDataSchema("view.created", VIEW_ENTITY_SCHEMA, z.object({ parent: PARENT_SCHEMA, view_type: z.string() })),
132
+ eventWithDataSchema("view.deleted", VIEW_ENTITY_SCHEMA, PARENT_DATA_SCHEMA),
133
+ eventWithDataSchema("view.updated", VIEW_ENTITY_SCHEMA, z.object({
134
+ parent: PARENT_SCHEMA,
135
+ updated_fields: z
136
+ .enum(["name", "filter", "sorts", "configuration"])
137
+ .array(),
138
+ })),
139
+ ]);
140
+ /** Exact current Notion webhook schema shared by ingress and triggers. */
141
+ export const NOTION_EVENT_SCHEMA = RAW_NOTION_EVENT_SCHEMA;
142
+ /**
143
+ * Runtime schema for one semantic Notion webhook event.
144
+ *
145
+ * @param type - Official event discriminant to require.
146
+ */
147
+ export function notionSemanticEventSchema(type) {
148
+ return z.custom((value) => RAW_NOTION_EVENT_SCHEMA.safeParse(value).success &&
149
+ typeof value === "object" &&
150
+ value !== null &&
151
+ "type" in value &&
152
+ value.type === type, { message: `Expected a Notion ${type} webhook event.` });
153
+ }
154
+ /**
155
+ * Builds one provider webhook schema over the shared delivery envelope.
156
+ *
157
+ * @param type - Official event discriminant.
158
+ * @param entity - Entity reference schema for the event family.
159
+ */
160
+ function eventSchema(type, entity) {
161
+ return z
162
+ .object({
163
+ ...BASE_SHAPE,
164
+ entity,
165
+ type: z.literal(type),
166
+ })
167
+ .catchall(z.json());
168
+ }
169
+ /**
170
+ * Builds one provider webhook schema with event-specific data.
171
+ *
172
+ * @param type - Official event discriminant.
173
+ * @param entity - Entity reference schema for the event family.
174
+ * @param data - Event-specific data schema.
175
+ */
176
+ function eventWithDataSchema(type, entity, data) {
177
+ return z
178
+ .object({
179
+ ...BASE_SHAPE,
180
+ data,
181
+ entity,
182
+ type: z.literal(type),
183
+ })
184
+ .catchall(z.json());
185
+ }
@@ -9,6 +9,7 @@ import type { googleCalendarTriggerContracts } from "./google-calendar/index.js"
9
9
  import type { googleFormsTriggerContracts } from "./google-forms/index.js";
10
10
  import type { googleMeetTriggerContracts } from "./google-meet/index.js";
11
11
  import type { linearTriggerContracts } from "./linear/index.js";
12
+ import type { notionTriggerContracts } from "./notion/index.js";
12
13
  import type { outlookTriggerContracts } from "./outlook/index.js";
13
14
  import type { resendTriggerContracts } from "./resend/index.js";
14
15
  import type { slackTriggerContracts } from "./slack/index.js";
@@ -19,7 +20,7 @@ import type { vercelTriggerContracts } from "./vercel/index.js";
19
20
  import type { webflowTriggerContracts } from "./webflow/index.js";
20
21
  import type { whatsappTriggerContracts } from "./whatsapp/index.js";
21
22
  import type { z } from "zod";
22
- export type TriggerContractMap = typeof airtableTriggerContracts & typeof asanaTriggerContracts & typeof brevoTriggerContracts & typeof convexTriggerContracts & typeof closeTriggerContracts & typeof githubTriggerContracts & typeof gmailTriggerContracts & typeof googleCalendarTriggerContracts & typeof googleFormsTriggerContracts & typeof googleMeetTriggerContracts & typeof linearTriggerContracts & typeof outlookTriggerContracts & typeof resendTriggerContracts & typeof slackTriggerContracts & typeof stripeTriggerContracts & typeof teamsTriggerContracts & typeof trelloTriggerContracts & typeof vercelTriggerContracts & typeof webflowTriggerContracts & typeof whatsappTriggerContracts;
23
+ export type TriggerContractMap = typeof airtableTriggerContracts & typeof asanaTriggerContracts & typeof brevoTriggerContracts & typeof convexTriggerContracts & typeof closeTriggerContracts & typeof githubTriggerContracts & typeof gmailTriggerContracts & typeof googleCalendarTriggerContracts & typeof googleFormsTriggerContracts & typeof googleMeetTriggerContracts & typeof linearTriggerContracts & typeof notionTriggerContracts & typeof outlookTriggerContracts & typeof resendTriggerContracts & typeof slackTriggerContracts & typeof stripeTriggerContracts & typeof teamsTriggerContracts & typeof trelloTriggerContracts & typeof vercelTriggerContracts & typeof webflowTriggerContracts & typeof whatsappTriggerContracts;
23
24
  export type IntegrationTriggerType = keyof TriggerContractMap;
24
25
  /** Canonical authoring configuration for one integration trigger type. */
25
26
  export type TriggerConfig<TType extends IntegrationTriggerType> = z.input<TriggerContractMap[TType]["configSchema"]> extends Record<string, never> ? object : z.input<TriggerContractMap[TType]["configSchema"]>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automate.ax/integration-contracts",
3
- "version": "0.88.9",
3
+ "version": "0.89.0",
4
4
  "description": "Shared integration payload contracts and provider primitives for Automate.ax.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -29,6 +29,7 @@
29
29
  "./google-meet": "./src/google-meet/index.ts",
30
30
  "./github": "./src/github/index.ts",
31
31
  "./linear": "./src/linear/index.ts",
32
+ "./notion": "./src/notion/index.ts",
32
33
  "./outlook": "./src/outlook/index.ts",
33
34
  "./resend": "./src/resend/index.ts",
34
35
  "./slack": "./src/slack/index.ts",
@@ -46,12 +47,13 @@
46
47
  }
47
48
  },
48
49
  "dependencies": {
49
- "@automate.ax/codec": "0.88.9",
50
+ "@automate.ax/codec": "0.89.0",
50
51
  "@cfworker/json-schema": "^4.1.1",
51
52
  "@googleapis/calendar": "^15.0.0",
52
53
  "@googleapis/forms": "^6.0.1",
53
54
  "@googleapis/gmail": "^12.0.0",
54
55
  "@googleapis/meet": "^5.0.0",
56
+ "@notionhq/client": "5.26.0",
55
57
  "@octokit/openapi-webhooks-types": "^12.1.0",
56
58
  "@octokit/rest": "^22.0.1",
57
59
  "convex": "^1.45.0",
@@ -151,6 +153,11 @@
151
153
  "types": "./dist/linear/index.d.ts",
152
154
  "default": "./dist/linear/index.js"
153
155
  },
156
+ "./notion": {
157
+ "bun": "./src/notion/index.ts",
158
+ "types": "./dist/notion/index.d.ts",
159
+ "default": "./dist/notion/index.js"
160
+ },
154
161
  "./outlook": {
155
162
  "bun": "./src/outlook/index.ts",
156
163
  "types": "./dist/outlook/index.d.ts",
@@ -0,0 +1,179 @@
1
+ import * as z from "zod"
2
+ import {
3
+ NOTION_EVENT_SCHEMA,
4
+ notionSemanticEventSchema,
5
+ type NotionSemanticWebhookEvent,
6
+ type NotionWebhookEvent,
7
+ type NotionWebhookEventType,
8
+ } from "./schemas"
9
+
10
+ export * from "./schemas"
11
+
12
+ export const NOTION_TRIGGER_CONFIG_SCHEMA = z.object({})
13
+
14
+ export const NOTION_WEBHOOK_EVENT_TYPES = [
15
+ "comment.created",
16
+ "comment.deleted",
17
+ "comment.updated",
18
+ "data_source.content_updated",
19
+ "data_source.created",
20
+ "data_source.deleted",
21
+ "data_source.moved",
22
+ "data_source.schema_updated",
23
+ "data_source.undeleted",
24
+ "database.created",
25
+ "database.deleted",
26
+ "database.moved",
27
+ "database.undeleted",
28
+ "file_upload.completed",
29
+ "file_upload.created",
30
+ "file_upload.expired",
31
+ "file_upload.upload_failed",
32
+ "page.content_updated",
33
+ "page.created",
34
+ "page.deleted",
35
+ "page.locked",
36
+ "page.moved",
37
+ "page.properties_updated",
38
+ "page.transcription_block.transcript_deleted",
39
+ "page.undeleted",
40
+ "page.unlocked",
41
+ "view.created",
42
+ "view.deleted",
43
+ "view.updated",
44
+ ] as const satisfies readonly NotionWebhookEventType[]
45
+
46
+ type NotionTriggerContract<TEvent> = {
47
+ readonly configSchema: typeof NOTION_TRIGGER_CONFIG_SCHEMA
48
+ readonly eventSchema: z.ZodType<TEvent>
49
+ }
50
+
51
+ type NotionSemanticTriggerTypes = {
52
+ readonly "notion.comment.created": "comment.created"
53
+ readonly "notion.comment.deleted": "comment.deleted"
54
+ readonly "notion.comment.updated": "comment.updated"
55
+ readonly "notion.database.created": "database.created"
56
+ readonly "notion.database.deleted": "database.deleted"
57
+ readonly "notion.database.moved": "database.moved"
58
+ readonly "notion.database.undeleted": "database.undeleted"
59
+ readonly "notion.dataSource.contentUpdated": "data_source.content_updated"
60
+ readonly "notion.dataSource.created": "data_source.created"
61
+ readonly "notion.dataSource.deleted": "data_source.deleted"
62
+ readonly "notion.dataSource.moved": "data_source.moved"
63
+ readonly "notion.dataSource.schemaUpdated": "data_source.schema_updated"
64
+ readonly "notion.dataSource.undeleted": "data_source.undeleted"
65
+ readonly "notion.fileUpload.completed": "file_upload.completed"
66
+ readonly "notion.fileUpload.created": "file_upload.created"
67
+ readonly "notion.fileUpload.expired": "file_upload.expired"
68
+ readonly "notion.fileUpload.failed": "file_upload.upload_failed"
69
+ readonly "notion.page.contentUpdated": "page.content_updated"
70
+ readonly "notion.page.created": "page.created"
71
+ readonly "notion.page.deleted": "page.deleted"
72
+ readonly "notion.page.locked": "page.locked"
73
+ readonly "notion.page.moved": "page.moved"
74
+ readonly "notion.page.propertiesUpdated": "page.properties_updated"
75
+ readonly "notion.page.transcriptDeleted": "page.transcription_block.transcript_deleted"
76
+ readonly "notion.page.undeleted": "page.undeleted"
77
+ readonly "notion.page.unlocked": "page.unlocked"
78
+ readonly "notion.view.created": "view.created"
79
+ readonly "notion.view.deleted": "view.deleted"
80
+ readonly "notion.view.updated": "view.updated"
81
+ }
82
+
83
+ type NotionTriggerContracts = {
84
+ readonly [TTrigger in keyof NotionSemanticTriggerTypes]: NotionTriggerContract<
85
+ NotionSemanticWebhookEvent<NotionSemanticTriggerTypes[TTrigger]>
86
+ >
87
+ } & {
88
+ readonly "notion.event": NotionTriggerContract<NotionWebhookEvent>
89
+ }
90
+
91
+ export const notionEventTypeMap = {
92
+ "comment.created": "notion.comment.created",
93
+ "comment.deleted": "notion.comment.deleted",
94
+ "comment.updated": "notion.comment.updated",
95
+ "data_source.content_updated": "notion.dataSource.contentUpdated",
96
+ "data_source.created": "notion.dataSource.created",
97
+ "data_source.deleted": "notion.dataSource.deleted",
98
+ "data_source.moved": "notion.dataSource.moved",
99
+ "data_source.schema_updated": "notion.dataSource.schemaUpdated",
100
+ "data_source.undeleted": "notion.dataSource.undeleted",
101
+ "database.created": "notion.database.created",
102
+ "database.deleted": "notion.database.deleted",
103
+ "database.moved": "notion.database.moved",
104
+ "database.undeleted": "notion.database.undeleted",
105
+ "file_upload.completed": "notion.fileUpload.completed",
106
+ "file_upload.created": "notion.fileUpload.created",
107
+ "file_upload.expired": "notion.fileUpload.expired",
108
+ "file_upload.upload_failed": "notion.fileUpload.failed",
109
+ "page.content_updated": "notion.page.contentUpdated",
110
+ "page.created": "notion.page.created",
111
+ "page.deleted": "notion.page.deleted",
112
+ "page.locked": "notion.page.locked",
113
+ "page.moved": "notion.page.moved",
114
+ "page.properties_updated": "notion.page.propertiesUpdated",
115
+ "page.transcription_block.transcript_deleted":
116
+ "notion.page.transcriptDeleted",
117
+ "page.undeleted": "notion.page.undeleted",
118
+ "page.unlocked": "notion.page.unlocked",
119
+ "view.created": "notion.view.created",
120
+ "view.deleted": "notion.view.deleted",
121
+ "view.updated": "notion.view.updated",
122
+ } as const satisfies Record<
123
+ NotionWebhookEventType,
124
+ keyof NotionTriggerContracts
125
+ >
126
+
127
+ export const notionTriggerContracts: NotionTriggerContracts = {
128
+ "notion.comment.created": semanticContract("comment.created"),
129
+ "notion.comment.deleted": semanticContract("comment.deleted"),
130
+ "notion.comment.updated": semanticContract("comment.updated"),
131
+ "notion.database.created": semanticContract("database.created"),
132
+ "notion.database.deleted": semanticContract("database.deleted"),
133
+ "notion.database.moved": semanticContract("database.moved"),
134
+ "notion.database.undeleted": semanticContract("database.undeleted"),
135
+ "notion.dataSource.contentUpdated": semanticContract(
136
+ "data_source.content_updated",
137
+ ),
138
+ "notion.dataSource.created": semanticContract("data_source.created"),
139
+ "notion.dataSource.deleted": semanticContract("data_source.deleted"),
140
+ "notion.dataSource.moved": semanticContract("data_source.moved"),
141
+ "notion.dataSource.schemaUpdated": semanticContract(
142
+ "data_source.schema_updated",
143
+ ),
144
+ "notion.dataSource.undeleted": semanticContract("data_source.undeleted"),
145
+ "notion.event": {
146
+ configSchema: NOTION_TRIGGER_CONFIG_SCHEMA,
147
+ eventSchema: NOTION_EVENT_SCHEMA,
148
+ },
149
+ "notion.fileUpload.completed": semanticContract("file_upload.completed"),
150
+ "notion.fileUpload.created": semanticContract("file_upload.created"),
151
+ "notion.fileUpload.expired": semanticContract("file_upload.expired"),
152
+ "notion.fileUpload.failed": semanticContract("file_upload.upload_failed"),
153
+ "notion.page.contentUpdated": semanticContract("page.content_updated"),
154
+ "notion.page.created": semanticContract("page.created"),
155
+ "notion.page.deleted": semanticContract("page.deleted"),
156
+ "notion.page.locked": semanticContract("page.locked"),
157
+ "notion.page.moved": semanticContract("page.moved"),
158
+ "notion.page.propertiesUpdated": semanticContract("page.properties_updated"),
159
+ "notion.page.transcriptDeleted": semanticContract(
160
+ "page.transcription_block.transcript_deleted",
161
+ ),
162
+ "notion.page.undeleted": semanticContract("page.undeleted"),
163
+ "notion.page.unlocked": semanticContract("page.unlocked"),
164
+ "notion.view.created": semanticContract("view.created"),
165
+ "notion.view.deleted": semanticContract("view.deleted"),
166
+ "notion.view.updated": semanticContract("view.updated"),
167
+ }
168
+
169
+ /**
170
+ * Creates one semantic trigger contract from an official webhook type.
171
+ *
172
+ * @param type - Official Notion webhook event type.
173
+ */
174
+ function semanticContract<TType extends NotionWebhookEventType>(type: TType) {
175
+ return {
176
+ configSchema: NOTION_TRIGGER_CONFIG_SCHEMA,
177
+ eventSchema: notionSemanticEventSchema(type),
178
+ }
179
+ }