@notionhq/workers 0.0.82

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.
Files changed (73) hide show
  1. package/README.md +22 -0
  2. package/dist/block.d.ts +321 -0
  3. package/dist/block.d.ts.map +1 -0
  4. package/dist/block.js +0 -0
  5. package/dist/builder.d.ts +117 -0
  6. package/dist/builder.d.ts.map +1 -0
  7. package/dist/builder.js +168 -0
  8. package/dist/capabilities/automation.d.ts +91 -0
  9. package/dist/capabilities/automation.d.ts.map +1 -0
  10. package/dist/capabilities/automation.js +40 -0
  11. package/dist/capabilities/automation.test.d.ts +2 -0
  12. package/dist/capabilities/automation.test.d.ts.map +1 -0
  13. package/dist/capabilities/context.d.ts +7 -0
  14. package/dist/capabilities/context.d.ts.map +1 -0
  15. package/dist/capabilities/context.js +15 -0
  16. package/dist/capabilities/oauth.d.ts +120 -0
  17. package/dist/capabilities/oauth.d.ts.map +1 -0
  18. package/dist/capabilities/oauth.js +55 -0
  19. package/dist/capabilities/oauth.test.d.ts +2 -0
  20. package/dist/capabilities/oauth.test.d.ts.map +1 -0
  21. package/dist/capabilities/sync.d.ts +180 -0
  22. package/dist/capabilities/sync.d.ts.map +1 -0
  23. package/dist/capabilities/sync.js +84 -0
  24. package/dist/capabilities/sync.test.d.ts +2 -0
  25. package/dist/capabilities/sync.test.d.ts.map +1 -0
  26. package/dist/capabilities/tool.d.ts +68 -0
  27. package/dist/capabilities/tool.d.ts.map +1 -0
  28. package/dist/capabilities/tool.js +174 -0
  29. package/dist/capabilities/tool.test.d.ts +2 -0
  30. package/dist/capabilities/tool.test.d.ts.map +1 -0
  31. package/dist/error.d.ts +12 -0
  32. package/dist/error.d.ts.map +1 -0
  33. package/dist/error.js +15 -0
  34. package/dist/icon-names.d.ts +6 -0
  35. package/dist/icon-names.d.ts.map +1 -0
  36. package/dist/icon-names.js +0 -0
  37. package/dist/index.d.ts +10 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +9 -0
  40. package/dist/json-schema.d.ts +117 -0
  41. package/dist/json-schema.d.ts.map +1 -0
  42. package/dist/json-schema.js +0 -0
  43. package/dist/json-schema.test.d.ts +2 -0
  44. package/dist/json-schema.test.d.ts.map +1 -0
  45. package/dist/schema.d.ts +178 -0
  46. package/dist/schema.d.ts.map +1 -0
  47. package/dist/schema.js +66 -0
  48. package/dist/types.d.ts +206 -0
  49. package/dist/types.d.ts.map +1 -0
  50. package/dist/types.js +0 -0
  51. package/dist/worker.d.ts +177 -0
  52. package/dist/worker.d.ts.map +1 -0
  53. package/dist/worker.js +219 -0
  54. package/package.json +68 -0
  55. package/src/block.ts +529 -0
  56. package/src/builder.ts +299 -0
  57. package/src/capabilities/automation.test.ts +152 -0
  58. package/src/capabilities/automation.ts +130 -0
  59. package/src/capabilities/context.ts +23 -0
  60. package/src/capabilities/oauth.test.ts +52 -0
  61. package/src/capabilities/oauth.ts +157 -0
  62. package/src/capabilities/sync.test.ts +104 -0
  63. package/src/capabilities/sync.ts +311 -0
  64. package/src/capabilities/tool.test.ts +351 -0
  65. package/src/capabilities/tool.ts +279 -0
  66. package/src/error.ts +19 -0
  67. package/src/icon-names.ts +890 -0
  68. package/src/index.ts +34 -0
  69. package/src/json-schema.test.ts +719 -0
  70. package/src/json-schema.ts +179 -0
  71. package/src/schema.ts +241 -0
  72. package/src/types.ts +272 -0
  73. package/src/worker.ts +285 -0
@@ -0,0 +1,91 @@
1
+ import type { HandlerOptions } from "../types.js";
2
+ import type { CapabilityContext } from "./context.js";
3
+ /**
4
+ * Event provided to automation execute functions
5
+ */
6
+ export interface AutomationEvent {
7
+ /**
8
+ * The ID of the page that triggered the automation (if applicable)
9
+ */
10
+ pageId?: string;
11
+ /**
12
+ * The type of automation action that was triggered
13
+ */
14
+ actionType: string;
15
+ /**
16
+ * The full page object from Notion's Public API (if triggered by a database page)
17
+ */
18
+ pageData?: PageObjectResponse;
19
+ }
20
+ /**
21
+ * Page object from Notion's Public API
22
+ * This represents a database page with all its properties.
23
+ * Properties are in Notion's Public API format.
24
+ * See: https://developers.notion.com/reference/page
25
+ */
26
+ export interface PageObjectResponse {
27
+ object: "page";
28
+ id: string;
29
+ created_time: string;
30
+ last_edited_time: string;
31
+ created_by: {
32
+ id: string;
33
+ };
34
+ last_edited_by: {
35
+ id: string;
36
+ };
37
+ cover: unknown;
38
+ icon: unknown;
39
+ parent: unknown;
40
+ archived: boolean;
41
+ properties: Record<string, unknown>;
42
+ url: string;
43
+ public_url?: string | null;
44
+ }
45
+ /**
46
+ * Configuration for an automation capability
47
+ */
48
+ export interface AutomationConfiguration {
49
+ /**
50
+ * Title of the automation - shown in the UI when selecting automations
51
+ */
52
+ title: string;
53
+ /**
54
+ * Description of what this automation does - shown in the UI
55
+ */
56
+ description: string;
57
+ /**
58
+ * The function that executes when the automation is triggered
59
+ * @param event - Event data about the automation trigger, including page data if applicable
60
+ * @param context - The capability execution context (Notion client, etc.)
61
+ * @returns A promise that resolves when the automation completes
62
+ */
63
+ execute: (event: AutomationEvent, context: CapabilityContext) => Promise<void> | void;
64
+ }
65
+ /**
66
+ * Result returned from automation execution
67
+ */
68
+ export interface AutomationHandlerResult {
69
+ title: string;
70
+ description: string;
71
+ }
72
+ export type AutomationCapability = ReturnType<typeof createAutomationCapability>;
73
+ /**
74
+ * Creates an automation capability from configuration.
75
+ *
76
+ * @param key - The unique name for this capability.
77
+ * @param config - The automation configuration.
78
+ * @returns The capability object.
79
+ */
80
+ export declare function createAutomationCapability(key: string, config: AutomationConfiguration): {
81
+ _tag: "automation";
82
+ key: string;
83
+ config: {
84
+ title: string;
85
+ description: string;
86
+ };
87
+ handler(event: AutomationEvent, options?: HandlerOptions): Promise<{
88
+ status: "success";
89
+ } | undefined>;
90
+ };
91
+ //# sourceMappingURL=automation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"automation.d.ts","sourceRoot":"","sources":["../../src/capabilities/automation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGtD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC9B;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3B,cAAc,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACvC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;;;OAKG;IACH,OAAO,EAAE,CACR,KAAK,EAAE,eAAe,EACtB,OAAO,EAAE,iBAAiB,KACtB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,oBAAoB,GAAG,UAAU,CAC5C,OAAO,0BAA0B,CACjC,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACzC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,uBAAuB;;;;;;;mBAUtB,eAAe,YACZ,cAAc,GACtB,OAAO,CAAC;QAAE,MAAM,EAAE,SAAS,CAAA;KAAE,GAAG,SAAS,CAAC;EAyB9C"}
@@ -0,0 +1,40 @@
1
+ import { ExecutionError } from "../error.js";
2
+ import { createCapabilityContext } from "./context.js";
3
+ function createAutomationCapability(key, config) {
4
+ return {
5
+ _tag: "automation",
6
+ key,
7
+ config: {
8
+ title: config.title,
9
+ description: config.description
10
+ },
11
+ async handler(event, options) {
12
+ try {
13
+ const capabilityContext = createCapabilityContext();
14
+ await config.execute(event, capabilityContext);
15
+ if (options?.concreteOutput) {
16
+ return { status: "success" };
17
+ } else {
18
+ process.stdout.write(
19
+ `
20
+ <output>${JSON.stringify({ status: "success" })}</output>
21
+ `
22
+ );
23
+ }
24
+ } catch (err) {
25
+ const error = new ExecutionError(err);
26
+ if (!options?.concreteOutput) {
27
+ process.stdout.write(
28
+ `
29
+ <output>${JSON.stringify({ status: "error", error: { name: error.name, message: error.message } })}</output>
30
+ `
31
+ );
32
+ }
33
+ throw error;
34
+ }
35
+ }
36
+ };
37
+ }
38
+ export {
39
+ createAutomationCapability
40
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=automation.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"automation.test.d.ts","sourceRoot":"","sources":["../../src/capabilities/automation.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import { Client } from "@notionhq/client";
2
+ export type CapabilityContext = {
3
+ /** Notion API SDK client for this execution. */
4
+ notion: Client;
5
+ };
6
+ export declare function createCapabilityContext(): CapabilityContext;
7
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/capabilities/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG1C,MAAM,MAAM,iBAAiB,GAAG;IAC/B,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAgB,uBAAuB,IAAI,iBAAiB,CAc3D"}
@@ -0,0 +1,15 @@
1
+ import { Client } from "@notionhq/client";
2
+ function createCapabilityContext() {
3
+ const options = {};
4
+ if (process.env.NOTION_API_BASE_URL) {
5
+ options.baseUrl = process.env.NOTION_API_BASE_URL;
6
+ }
7
+ if (process.env.NOTION_API_TOKEN) {
8
+ options.auth = process.env.NOTION_API_TOKEN;
9
+ }
10
+ const notion = new Client(options);
11
+ return { notion };
12
+ }
13
+ export {
14
+ createCapabilityContext
15
+ };
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Configuration for a Notion-managed OAuth provider.
3
+ *
4
+ * Notion owns the OAuth app credentials (client ID/secret) and the backend has
5
+ * pre-configured provider settings.
6
+ */
7
+ export interface NotionManagedOAuthConfiguration {
8
+ /**
9
+ * The unique identifier for this OAuth provider instance.
10
+ */
11
+ name: string;
12
+ /**
13
+ * The pre-configured provider to use (e.g., "google", "github", "salesforce").
14
+ * The backend will use this to look up the OAuth configuration.
15
+ */
16
+ provider: string;
17
+ /**
18
+ * Optional default access token expiry (in milliseconds) to use when the OAuth provider
19
+ * does not return `expires_in` in token responses.
20
+ *
21
+ * Some providers (e.g. Salesforce in certain configurations) may omit expiry information.
22
+ */
23
+ accessTokenExpireMs?: number;
24
+ }
25
+ /**
26
+ * Configuration for a user-managed OAuth provider.
27
+ *
28
+ * You own the OAuth app credentials and must explicitly provide endpoints and
29
+ * other OAuth parameters.
30
+ */
31
+ export interface UserManagedOAuthConfiguration {
32
+ /**
33
+ * The unique identifier for this OAuth provider instance.
34
+ */
35
+ name: string;
36
+ /**
37
+ * The client ID for the OAuth app.
38
+ */
39
+ clientId: string;
40
+ /**
41
+ * The client secret for the OAuth app.
42
+ */
43
+ clientSecret: string;
44
+ /**
45
+ * The OAuth 2.0 authorization endpoint URL.
46
+ */
47
+ authorizationEndpoint: string;
48
+ /**
49
+ * The OAuth 2.0 token endpoint URL.
50
+ */
51
+ tokenEndpoint: string;
52
+ /**
53
+ * The OAuth scope(s) to request.
54
+ */
55
+ scope: string;
56
+ /**
57
+ * Optional additional authorization parameters to include in the authorization request.
58
+ */
59
+ authorizationParams?: Record<string, string>;
60
+ /**
61
+ * Optional callback URL for OAuth redirect.
62
+ */
63
+ callbackUrl?: string;
64
+ /**
65
+ * Optional default access token expiry (in milliseconds) to use when the OAuth provider
66
+ * does not return `expires_in` in token responses.
67
+ *
68
+ * Some providers (e.g. Salesforce in certain configurations) may omit expiry information.
69
+ */
70
+ accessTokenExpireMs?: number;
71
+ }
72
+ /**
73
+ * Union type representing either Notion-managed or user-managed OAuth configuration.
74
+ */
75
+ export type OAuthConfiguration = NotionManagedOAuthConfiguration | UserManagedOAuthConfiguration;
76
+ export type OAuthCapability = ReturnType<typeof createOAuthCapability>;
77
+ /**
78
+ * Creates an OAuth provider configuration for authenticating with third-party services.
79
+ *
80
+ * @param config - The OAuth configuration (Notion-managed or user-managed).
81
+ * @returns An OAuth provider definition.
82
+ */
83
+ export declare function createOAuthCapability(key: string, config: OAuthConfiguration): {
84
+ _tag: "oauth";
85
+ key: string;
86
+ envKey: string;
87
+ accessToken(): Promise<string>;
88
+ config: {
89
+ type: "notion_managed";
90
+ name: string;
91
+ provider: string;
92
+ accessTokenExpireMs: number | undefined;
93
+ authorizationEndpoint?: never;
94
+ tokenEndpoint?: never;
95
+ scope?: never;
96
+ clientId?: never;
97
+ clientSecret?: never;
98
+ authorizationParams?: never;
99
+ callbackUrl?: never;
100
+ };
101
+ } | {
102
+ _tag: "oauth";
103
+ key: string;
104
+ envKey: string;
105
+ accessToken(): Promise<string>;
106
+ config: {
107
+ type: "user_managed";
108
+ name: string;
109
+ authorizationEndpoint: string;
110
+ tokenEndpoint: string;
111
+ scope: string;
112
+ clientId: string;
113
+ clientSecret: string;
114
+ authorizationParams: Record<string, string> | undefined;
115
+ callbackUrl: string | undefined;
116
+ accessTokenExpireMs: number | undefined;
117
+ provider?: never;
118
+ };
119
+ };
120
+ //# sourceMappingURL=oauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/capabilities/oauth.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,+BAA+B;IAC/C;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;GAKG;AACH,MAAM,WAAW,6BAA6B;IAC7C;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,qBAAqB,EAAE,MAAM,CAAC;IAE9B;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE7C;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAC3B,+BAA+B,GAC/B,6BAA6B,CAAC;AAEjC,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEvE;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB;;;;mBAQrD,OAAO,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;;;;mBAgBhB,OAAO,CAAC,MAAM,CAAC;;;;;;;;;;;;;;EAgBrC"}
@@ -0,0 +1,55 @@
1
+ function createOAuthCapability(key, config) {
2
+ const envKey = oauthNameToEnvKey(config.name);
3
+ if ("provider" in config) {
4
+ return {
5
+ _tag: "oauth",
6
+ key,
7
+ envKey,
8
+ async accessToken() {
9
+ return readRequiredEnvVar(envKey, { name: config.name });
10
+ },
11
+ config: {
12
+ type: "notion_managed",
13
+ name: config.name,
14
+ provider: config.provider,
15
+ accessTokenExpireMs: config.accessTokenExpireMs
16
+ }
17
+ };
18
+ }
19
+ return {
20
+ _tag: "oauth",
21
+ key,
22
+ envKey,
23
+ async accessToken() {
24
+ return readRequiredEnvVar(envKey, { name: config.name });
25
+ },
26
+ config: {
27
+ type: "user_managed",
28
+ name: config.name,
29
+ authorizationEndpoint: config.authorizationEndpoint,
30
+ tokenEndpoint: config.tokenEndpoint,
31
+ scope: config.scope,
32
+ clientId: config.clientId,
33
+ clientSecret: config.clientSecret,
34
+ authorizationParams: config.authorizationParams,
35
+ callbackUrl: config.callbackUrl,
36
+ accessTokenExpireMs: config.accessTokenExpireMs
37
+ }
38
+ };
39
+ }
40
+ function oauthNameToEnvKey(identifier) {
41
+ const encoded = Buffer.from(identifier).toString("hex").toUpperCase();
42
+ return `OAUTH_${encoded}_ACCESS_TOKEN`;
43
+ }
44
+ function readRequiredEnvVar(key, context) {
45
+ const value = process.env[key];
46
+ if (value) {
47
+ return value;
48
+ }
49
+ throw new Error(
50
+ `Missing OAuth access token env var "${key}" (name: "${context.name}"). Make sure you've completed OAuth for this capability and are running inside the worker runtime.`
51
+ );
52
+ }
53
+ export {
54
+ createOAuthCapability
55
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=oauth.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.test.d.ts","sourceRoot":"","sources":["../../src/capabilities/oauth.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,180 @@
1
+ import type { PropertyConfiguration, PropertySchema, Schema } from "../schema.js";
2
+ import type { HandlerOptions, Icon, PeopleValue, PlaceValue, RelationValue, Schedule, SyncSchedule, TextValue } from "../types.js";
3
+ import type { CapabilityContext } from "./context.js";
4
+ /**
5
+ * Maps a property configuration to its corresponding value type.
6
+ */
7
+ type PropertyValueType<T extends PropertyConfiguration> = T extends {
8
+ type: "people";
9
+ } ? PeopleValue : T extends {
10
+ type: "place";
11
+ } ? PlaceValue : T extends {
12
+ type: "relation";
13
+ } ? RelationValue : TextValue;
14
+ /**
15
+ * Sync mode determines how the sync handles data lifecycle.
16
+ */
17
+ export type SyncMode = "replace" | "incremental";
18
+ /**
19
+ * A change representing a record to be created or updated.
20
+ */
21
+ export type SyncChangeUpsert<PK extends string, S extends PropertySchema<PK>> = {
22
+ /**
23
+ * The type of change. Use `"upsert"` to create or update a record.
24
+ */
25
+ type: "upsert";
26
+ /**
27
+ * A unique identifier for this record, used to match against existing pages.
28
+ * This value will be stored in the property specified by `primaryKeyProperty`.
29
+ */
30
+ key: string;
31
+ /**
32
+ * The property values for this record.
33
+ * Keys must match the property names defined in the schema.
34
+ * Use the Builder helpers (e.g., `Builder.title()`, `Builder.richText()`) to create values.
35
+ */
36
+ properties: {
37
+ [Property in keyof S]: PropertyValueType<S[Property]>;
38
+ };
39
+ /**
40
+ * Optional icon to use as the icon for this row's page.
41
+ * Use the `Builder.emojiIcon()`, `Builder.notionIcon()`, or `Builder.imageIcon()` helpers.
42
+ */
43
+ icon?: Icon;
44
+ /**
45
+ * Optional markdown content to add to the page body.
46
+ * This will be converted to Notion blocks and added as page content.
47
+ */
48
+ pageContentMarkdown?: string;
49
+ };
50
+ /**
51
+ * A change representing a record to be deleted.
52
+ * Only applicable when using `mode: "incremental"`.
53
+ */
54
+ export type SyncChangeDelete = {
55
+ /**
56
+ * The type of change. Use `"delete"` to remove a record.
57
+ */
58
+ type: "delete";
59
+ /**
60
+ * The unique identifier of the record to delete.
61
+ * Must match the `key` of a previously upserted record.
62
+ */
63
+ key: string;
64
+ };
65
+ /**
66
+ * A change to be applied to the synced database.
67
+ * Can be either an upsert (create/update) or a delete.
68
+ */
69
+ export type SyncChange<PK extends string, S extends PropertySchema<PK>> = SyncChangeUpsert<PK, S> | SyncChangeDelete;
70
+ /**
71
+ * Result returned from the sync execute function.
72
+ */
73
+ export type SyncExecutionResult<PK extends string, State = unknown> = {
74
+ /**
75
+ * The batch of changes to apply in this execution.
76
+ * Can include upserts (create/update) and deletes.
77
+ */
78
+ changes: SyncChange<PK, PropertySchema<PK>>[];
79
+ /**
80
+ * Indicates whether there is more data to fetch.
81
+ * - `true`: More data available, will trigger another execution with nextState
82
+ * - `false`: No more data to fetch, sync is complete
83
+ */
84
+ hasMore: boolean;
85
+ /**
86
+ * Optional state data to pass to the next execution.
87
+ * Required if `hasMore` is `true`, ignored if `hasMore` is `false`.
88
+ * This can be any type of data (cursor, page number, timestamp, etc.).
89
+ * The same data will be provided as `state` in the next execution.
90
+ */
91
+ nextState?: State;
92
+ };
93
+ /**
94
+ * A configuration object that enables synchronization between a data
95
+ * source and a third-party source.
96
+ */
97
+ export type SyncConfiguration<PK extends string, S extends Schema<PK>, State = unknown> = {
98
+ /**
99
+ * The property of the data source that maps to a "primary key" in the
100
+ * third-party data. This is used to match existing pages to
101
+ * records in the third-party service. Must be a property defined in the schema.
102
+ */
103
+ primaryKeyProperty: PK;
104
+ /**
105
+ * The schema defining the structure of properties in the collection.
106
+ */
107
+ schema: S;
108
+ /**
109
+ * How the sync handles data lifecycle:
110
+ * - "replace": Each sync returns the complete dataset. After hasMore:false,
111
+ * pages not seen in this sync run are deleted.
112
+ * - "incremental": Sync returns changes only. After hasMore:false, sync
113
+ * continues from saved cursor. Use delete markers
114
+ * to explicitly remove pages.
115
+ *
116
+ * @default "replace"
117
+ */
118
+ mode?: SyncMode;
119
+ /**
120
+ * How often the sync should run.
121
+ * - "continuous": Run as frequently as the system allows
122
+ * - Interval string: Run at specified intervals, e.g. "1h", "30m", "1d"
123
+ *
124
+ * Minimum interval: 1 minute ("1m")
125
+ * Maximum interval: 7 days ("7d")
126
+ *
127
+ * @default "30m"
128
+ */
129
+ schedule?: Schedule;
130
+ /**
131
+ * A function that fetches the data to sync from the third-party service.
132
+ *
133
+ * This function can return all data at once, or implement pagination by:
134
+ * 1. Returning a batch of changes with `hasMore: true` and a `nextState`
135
+ * 2. The runtime will call execute again with that state
136
+ * 3. Continue until `hasMore: false` is returned
137
+ *
138
+ * The runtime will handle diffing against the data source and creating,
139
+ * updating, and deleting pages as necessary.
140
+ *
141
+ * @param state - User-defined state from the previous execution (undefined on first call)
142
+ * @param context - Runtime context, including Notion client
143
+ * @returns A result containing changes, hasMore status, and optional nextState
144
+ */
145
+ execute: (state: State | undefined, context: CapabilityContext) => Promise<SyncExecutionResult<PK, State>>;
146
+ };
147
+ export type SyncCapability = ReturnType<typeof createSyncCapability>;
148
+ /**
149
+ * Runtime context object passed from the runtime to sync capability handlers.
150
+ */
151
+ type RuntimeContext<UserContext = unknown> = {
152
+ /** The user-defined/-controlled state (cursor, pagination state, etc.) */
153
+ state?: UserContext;
154
+ /** Legacy field for user-defined/-controlled state. */
155
+ userContext?: UserContext;
156
+ };
157
+ /**
158
+ * Creates a special handler for syncing third-party data to a collection.
159
+ *
160
+ * @param syncConfiguration - The configuration for the sync.
161
+ * @returns A handler function that executes the sync function, and passes data
162
+ * needed to complete the sync back to the platform.
163
+ */
164
+ export declare function createSyncCapability<PK extends string, S extends Schema<PK>, Context = unknown>(key: string, syncConfiguration: SyncConfiguration<PK, S, Context>): {
165
+ _tag: "sync";
166
+ key: string;
167
+ config: {
168
+ primaryKeyProperty: PK;
169
+ schema: S;
170
+ mode: SyncMode | undefined;
171
+ schedule: SyncSchedule;
172
+ };
173
+ handler(runtimeContext?: RuntimeContext<Context>, options?: HandlerOptions): Promise<{
174
+ changes: SyncChange<PK, PropertySchema<PK>>[];
175
+ hasMore: boolean;
176
+ nextUserContext: Context | undefined;
177
+ }>;
178
+ };
179
+ export {};
180
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/capabilities/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ import { ExecutionError, unreachable } from "../error.js";
2
+ import { createCapabilityContext } from "./context.js";
3
+ function createSyncCapability(key, syncConfiguration) {
4
+ return {
5
+ _tag: "sync",
6
+ key,
7
+ config: {
8
+ primaryKeyProperty: syncConfiguration.primaryKeyProperty,
9
+ schema: syncConfiguration.schema,
10
+ mode: syncConfiguration.mode,
11
+ schedule: parseSchedule(syncConfiguration.schedule)
12
+ },
13
+ async handler(runtimeContext, options) {
14
+ const capabilityContext = createCapabilityContext();
15
+ const state = runtimeContext?.state ?? runtimeContext?.userContext;
16
+ const executionResult = await syncConfiguration.execute(state, capabilityContext).catch((err) => {
17
+ throw new ExecutionError(err);
18
+ });
19
+ const result = {
20
+ changes: executionResult.changes,
21
+ hasMore: executionResult.hasMore,
22
+ nextUserContext: executionResult.nextState
23
+ };
24
+ if (options?.concreteOutput) {
25
+ return result;
26
+ } else {
27
+ process.stdout.write(`
28
+ <output>${JSON.stringify(result)}</output>
29
+ `);
30
+ }
31
+ return result;
32
+ }
33
+ };
34
+ }
35
+ const MS_PER_MINUTE = 60 * 1e3;
36
+ const MS_PER_HOUR = 60 * MS_PER_MINUTE;
37
+ const MS_PER_DAY = 24 * MS_PER_HOUR;
38
+ const MIN_INTERVAL_MS = MS_PER_MINUTE;
39
+ const MAX_INTERVAL_MS = 7 * MS_PER_DAY;
40
+ const DEFAULT_INTERVAL_MS = 30 * MS_PER_MINUTE;
41
+ function parseSchedule(schedule) {
42
+ if (schedule === "continuous") {
43
+ return { type: "continuous" };
44
+ }
45
+ if (!schedule) {
46
+ return { type: "interval", intervalMs: DEFAULT_INTERVAL_MS };
47
+ }
48
+ const match = schedule.match(/^(\d+)(m|h|d)$/);
49
+ if (!match || !match[1] || !match[2]) {
50
+ throw new Error(
51
+ `Invalid schedule format: "${schedule}". Use "continuous" or an interval like "30m", "1h", "1d".`
52
+ );
53
+ }
54
+ const value = parseInt(match[1], 10);
55
+ const unit = match[2];
56
+ let intervalMs;
57
+ switch (unit) {
58
+ case "m":
59
+ intervalMs = value * MS_PER_MINUTE;
60
+ break;
61
+ case "h":
62
+ intervalMs = value * MS_PER_HOUR;
63
+ break;
64
+ case "d":
65
+ intervalMs = value * MS_PER_DAY;
66
+ break;
67
+ default:
68
+ unreachable(unit);
69
+ }
70
+ if (intervalMs < MIN_INTERVAL_MS) {
71
+ throw new Error(
72
+ `Schedule interval must be at least 1 minute. Got: "${schedule}"`
73
+ );
74
+ }
75
+ if (intervalMs > MAX_INTERVAL_MS) {
76
+ throw new Error(
77
+ `Schedule interval must be at most 7 days. Got: "${schedule}"`
78
+ );
79
+ }
80
+ return { type: "interval", intervalMs };
81
+ }
82
+ export {
83
+ createSyncCapability
84
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sync.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.test.d.ts","sourceRoot":"","sources":["../../src/capabilities/sync.test.ts"],"names":[],"mappings":""}