@notionhq/workers 0.5.0 → 0.7.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.
Files changed (182) hide show
  1. package/dist/alpha/ajv-formats.d.js +0 -0
  2. package/dist/alpha/builder.d.ts +149 -0
  3. package/dist/alpha/builder.d.ts.map +1 -0
  4. package/dist/alpha/builder.js +260 -0
  5. package/dist/alpha/builder.test.d.ts +2 -0
  6. package/dist/alpha/builder.test.d.ts.map +1 -0
  7. package/dist/alpha/cli/build.d.ts +13 -0
  8. package/dist/alpha/cli/build.d.ts.map +1 -0
  9. package/dist/alpha/cli/build.js +36 -0
  10. package/dist/alpha/cli/build.test.d.ts +2 -0
  11. package/dist/alpha/cli/build.test.d.ts.map +1 -0
  12. package/dist/alpha/cli/codegen.d.ts +10 -0
  13. package/dist/alpha/cli/codegen.d.ts.map +1 -0
  14. package/dist/alpha/cli/codegen.js +41 -0
  15. package/dist/alpha/cli/codegen.test.d.ts +2 -0
  16. package/dist/alpha/cli/codegen.test.d.ts.map +1 -0
  17. package/dist/alpha/cli/discover.d.ts +35 -0
  18. package/dist/alpha/cli/discover.d.ts.map +1 -0
  19. package/dist/alpha/cli/discover.js +39 -0
  20. package/dist/alpha/cli/discover.test.d.ts +2 -0
  21. package/dist/alpha/cli/discover.test.d.ts.map +1 -0
  22. package/dist/alpha/cli/emit-manifest.d.ts +33 -0
  23. package/dist/alpha/cli/emit-manifest.d.ts.map +1 -0
  24. package/dist/alpha/cli/emit-manifest.js +266 -0
  25. package/dist/alpha/cli/emit-manifest.test.d.ts +2 -0
  26. package/dist/alpha/cli/emit-manifest.test.d.ts.map +1 -0
  27. package/dist/alpha/cli/index.d.ts +3 -0
  28. package/dist/alpha/cli/index.d.ts.map +1 -0
  29. package/dist/alpha/cli/index.js +36 -0
  30. package/dist/alpha/context.d.ts +8 -0
  31. package/dist/alpha/context.d.ts.map +1 -0
  32. package/dist/alpha/context.js +33 -0
  33. package/dist/alpha/database.d.ts +90 -0
  34. package/dist/alpha/database.d.ts.map +1 -0
  35. package/dist/alpha/database.js +9 -0
  36. package/dist/alpha/error.d.ts +41 -0
  37. package/dist/alpha/error.d.ts.map +1 -0
  38. package/dist/alpha/error.js +25 -0
  39. package/dist/alpha/icon-names.d.ts +6 -0
  40. package/dist/alpha/icon-names.d.ts.map +1 -0
  41. package/dist/alpha/icon-names.js +0 -0
  42. package/dist/alpha/json-schema.d.ts +117 -0
  43. package/dist/alpha/json-schema.d.ts.map +1 -0
  44. package/dist/alpha/json-schema.js +0 -0
  45. package/dist/alpha/manifest.d.ts +44 -0
  46. package/dist/alpha/manifest.d.ts.map +1 -0
  47. package/dist/alpha/manifest.js +0 -0
  48. package/dist/alpha/output.d.ts +7 -0
  49. package/dist/alpha/output.d.ts.map +1 -0
  50. package/dist/alpha/output.js +8 -0
  51. package/dist/alpha/pacer.d.ts +74 -0
  52. package/dist/alpha/pacer.d.ts.map +1 -0
  53. package/dist/alpha/pacer.js +66 -0
  54. package/dist/alpha/pacer.test.d.ts +2 -0
  55. package/dist/alpha/pacer.test.d.ts.map +1 -0
  56. package/dist/alpha/schedule.d.ts +6 -0
  57. package/dist/alpha/schedule.d.ts.map +1 -0
  58. package/dist/alpha/schedule.js +43 -0
  59. package/dist/alpha/schedule.test.d.ts +2 -0
  60. package/dist/alpha/schedule.test.d.ts.map +1 -0
  61. package/dist/alpha/schema-builder.d.ts +79 -0
  62. package/dist/alpha/schema-builder.d.ts.map +1 -0
  63. package/dist/alpha/schema-builder.js +135 -0
  64. package/dist/alpha/schema.d.ts +185 -0
  65. package/dist/alpha/schema.d.ts.map +1 -0
  66. package/dist/alpha/schema.js +115 -0
  67. package/dist/alpha/sync.d.ts +233 -0
  68. package/dist/alpha/sync.d.ts.map +1 -0
  69. package/dist/alpha/sync.js +70 -0
  70. package/dist/alpha/sync.test.d.ts +2 -0
  71. package/dist/alpha/sync.test.d.ts.map +1 -0
  72. package/dist/alpha/tool.d.ts +132 -0
  73. package/dist/alpha/tool.d.ts.map +1 -0
  74. package/dist/alpha/tool.js +156 -0
  75. package/dist/alpha/tool.test.d.ts +2 -0
  76. package/dist/alpha/tool.test.d.ts.map +1 -0
  77. package/dist/alpha/triggers.d.ts +365 -0
  78. package/dist/alpha/triggers.d.ts.map +1 -0
  79. package/dist/alpha/triggers.generated.d.ts +246 -0
  80. package/dist/alpha/triggers.generated.d.ts.map +1 -0
  81. package/dist/alpha/triggers.generated.js +239 -0
  82. package/dist/alpha/triggers.js +0 -0
  83. package/dist/alpha/types.d.ts +228 -0
  84. package/dist/alpha/types.d.ts.map +1 -0
  85. package/dist/alpha/types.js +0 -0
  86. package/dist/alpha/workflow.d.ts +70 -0
  87. package/dist/alpha/workflow.d.ts.map +1 -0
  88. package/dist/alpha/workflow.js +39 -0
  89. package/dist/alpha/workflow.test.d.ts +2 -0
  90. package/dist/alpha/workflow.test.d.ts.map +1 -0
  91. package/dist/block.d.ts.map +1 -1
  92. package/dist/builder.d.ts.map +1 -1
  93. package/dist/builder.js +2 -6
  94. package/dist/capabilities/ai_connector.d.ts.map +1 -1
  95. package/dist/capabilities/automation.d.ts.map +1 -1
  96. package/dist/capabilities/context.d.ts.map +1 -1
  97. package/dist/capabilities/oauth.d.ts.map +1 -1
  98. package/dist/capabilities/output.d.ts.map +1 -1
  99. package/dist/capabilities/output.js +2 -4
  100. package/dist/capabilities/stateful-capability.d.ts.map +1 -1
  101. package/dist/capabilities/stateful-capability.js +2 -6
  102. package/dist/capabilities/sync.d.ts.map +1 -1
  103. package/dist/capabilities/sync.js +2 -8
  104. package/dist/capabilities/tool.d.ts.map +1 -1
  105. package/dist/capabilities/tool.js +6 -20
  106. package/dist/capabilities/webhook.d.ts.map +1 -1
  107. package/dist/capabilities/workflow.d.ts +2 -2
  108. package/dist/capabilities/workflow.d.ts.map +1 -1
  109. package/dist/index.d.ts +2 -2
  110. package/dist/index.d.ts.map +1 -1
  111. package/dist/index.js +1 -7
  112. package/dist/json-schema.d.ts.map +1 -1
  113. package/dist/schema-builder.d.ts.map +1 -1
  114. package/dist/schema.d.ts.map +1 -1
  115. package/dist/types.d.ts.map +1 -1
  116. package/dist/worker.d.ts.map +1 -1
  117. package/dist/worker.js +1 -4
  118. package/package.json +74 -14
  119. package/src/alpha/ajv-formats.d.ts +7 -0
  120. package/src/alpha/builder.test.ts +197 -0
  121. package/src/alpha/builder.ts +338 -0
  122. package/src/alpha/cli/build.test.ts +240 -0
  123. package/src/alpha/cli/build.ts +57 -0
  124. package/src/alpha/cli/codegen.test.ts +31 -0
  125. package/src/alpha/cli/codegen.ts +51 -0
  126. package/src/alpha/cli/discover.test.ts +43 -0
  127. package/src/alpha/cli/discover.ts +81 -0
  128. package/src/alpha/cli/emit-manifest.test.ts +45 -0
  129. package/src/alpha/cli/emit-manifest.ts +409 -0
  130. package/src/alpha/cli/index.ts +41 -0
  131. package/src/alpha/context.ts +61 -0
  132. package/src/alpha/database.ts +102 -0
  133. package/src/alpha/error.ts +49 -0
  134. package/src/alpha/icon-names.ts +890 -0
  135. package/src/alpha/json-schema.ts +180 -0
  136. package/src/alpha/manifest.ts +47 -0
  137. package/src/alpha/output.ts +8 -0
  138. package/src/alpha/pacer.test.ts +81 -0
  139. package/src/alpha/pacer.ts +181 -0
  140. package/src/alpha/schedule.test.ts +31 -0
  141. package/src/alpha/schedule.ts +53 -0
  142. package/src/alpha/schema-builder.ts +193 -0
  143. package/src/alpha/schema.ts +222 -0
  144. package/src/alpha/sync.test.ts +191 -0
  145. package/src/alpha/sync.ts +340 -0
  146. package/src/alpha/tool.test.ts +116 -0
  147. package/src/alpha/tool.ts +319 -0
  148. package/src/alpha/triggers.generated.ts +489 -0
  149. package/src/alpha/triggers.ts +500 -0
  150. package/src/alpha/types.ts +284 -0
  151. package/src/alpha/workflow.test.ts +84 -0
  152. package/src/alpha/workflow.ts +131 -0
  153. package/src/block.ts +1 -5
  154. package/src/builder.test.ts +28 -60
  155. package/src/builder.ts +3 -10
  156. package/src/capabilities/ai_connector.test.ts +9 -32
  157. package/src/capabilities/ai_connector.ts +5 -17
  158. package/src/capabilities/automation.test.ts +3 -12
  159. package/src/capabilities/automation.ts +3 -11
  160. package/src/capabilities/context.ts +3 -6
  161. package/src/capabilities/oauth.test.ts +1 -0
  162. package/src/capabilities/oauth.ts +1 -3
  163. package/src/capabilities/output.ts +1 -3
  164. package/src/capabilities/stateful-capability.test.ts +1 -0
  165. package/src/capabilities/stateful-capability.ts +2 -6
  166. package/src/capabilities/sync.test.ts +15 -45
  167. package/src/capabilities/sync.ts +10 -40
  168. package/src/capabilities/tool.test.ts +106 -146
  169. package/src/capabilities/tool.ts +17 -39
  170. package/src/capabilities/webhook.ts +3 -10
  171. package/src/capabilities/workflow.test.ts +10 -31
  172. package/src/capabilities/workflow.ts +5 -12
  173. package/src/index.ts +2 -12
  174. package/src/json-schema.test.ts +2 -4
  175. package/src/json-schema.ts +7 -6
  176. package/src/pacer.test.ts +1 -3
  177. package/src/pacer_internal.ts +1 -5
  178. package/src/schema-builder.test.ts +10 -35
  179. package/src/schema-builder.ts +5 -16
  180. package/src/schema.ts +2 -10
  181. package/src/types.ts +1 -7
  182. package/src/worker.ts +8 -34
package/src/builder.ts CHANGED
@@ -234,9 +234,7 @@ export function relation(primaryKey: string): RelationReference {
234
234
  */
235
235
  function validateDateString(dateString: string): void {
236
236
  if (!/^\d{4}-\d{2}-\d{2}$/.test(dateString)) {
237
- throw new Error(
238
- `Invalid date format: ${dateString}. Expected YYYY-MM-DD format.`,
239
- );
237
+ throw new Error(`Invalid date format: ${dateString}. Expected YYYY-MM-DD format.`);
240
238
  }
241
239
 
242
240
  const date = new Date(dateString);
@@ -290,10 +288,7 @@ export function emojiIcon(emoji: string): Icon {
290
288
  * @param icon - The name of the Notion icon (e.g., "checkmark", "pizza", "rocket")
291
289
  * @param color - The color variant (defaults to "gray")
292
290
  */
293
- export function notionIcon(
294
- icon: NoticonName,
295
- color: NoticonColor = "gray",
296
- ): Icon {
291
+ export function notionIcon(icon: NoticonName, color: NoticonColor = "gray"): Icon {
297
292
  return {
298
293
  type: "notion",
299
294
  icon,
@@ -319,9 +314,7 @@ export function imageIcon(url: string): Icon {
319
314
  */
320
315
  export function imageCover(url: string, position = 0.5): Cover {
321
316
  if (!Number.isFinite(position) || position < 0 || position > 1) {
322
- throw new Error(
323
- `Invalid cover position: ${position}. Expected a number between 0 and 1.`,
324
- );
317
+ throw new Error(`Invalid cover position: ${position}. Expected a number between 0 and 1.`);
325
318
  }
326
319
 
327
320
  return {
@@ -1,12 +1,5 @@
1
- import {
2
- afterEach,
3
- beforeEach,
4
- describe,
5
- expect,
6
- it,
7
- type Mock,
8
- vi,
9
- } from "vitest";
1
+ import { afterEach, beforeEach, describe, expect, it, type Mock, vi } from "vitest";
2
+
10
3
  import { ExecutionError } from "../error.js";
11
4
  import { getPacerState } from "../pacer_internal.js";
12
5
  import { Worker } from "../worker.js";
@@ -17,9 +10,7 @@ describe("Worker.aiConnector", () => {
17
10
  let stdoutSpy: Mock<typeof process.stdout.write>;
18
11
 
19
12
  beforeEach(() => {
20
- stdoutSpy = vi
21
- .spyOn(process.stdout, "write")
22
- .mockImplementation(() => true);
13
+ stdoutSpy = vi.spyOn(process.stdout, "write").mockImplementation(() => true);
23
14
  });
24
15
 
25
16
  afterEach(() => {
@@ -86,12 +77,8 @@ describe("Worker.aiConnector", () => {
86
77
 
87
78
  await capability.handler();
88
79
 
89
- expect(stdoutSpy).toHaveBeenCalledWith(
90
- expect.stringContaining(`"_tag":"success"`),
91
- );
92
- expect(stdoutSpy).toHaveBeenCalledWith(
93
- expect.stringContaining(`"thread-1"`),
94
- );
80
+ expect(stdoutSpy).toHaveBeenCalledWith(expect.stringContaining(`"_tag":"success"`));
81
+ expect(stdoutSpy).toHaveBeenCalledWith(expect.stringContaining(`"thread-1"`));
95
82
  });
96
83
 
97
84
  it("passes state through from legacy runtime userContext", async () => {
@@ -106,15 +93,9 @@ describe("Worker.aiConnector", () => {
106
93
  execute,
107
94
  });
108
95
 
109
- await capability.handler(
110
- { userContext: { cursor: "cursor-1" } },
111
- { concreteOutput: true },
112
- );
96
+ await capability.handler({ userContext: { cursor: "cursor-1" } }, { concreteOutput: true });
113
97
 
114
- expect(execute).toHaveBeenCalledWith(
115
- { cursor: "cursor-1" },
116
- expect.anything(),
117
- );
98
+ expect(execute).toHaveBeenCalledWith({ cursor: "cursor-1" }, expect.anything());
118
99
  expect(stdoutSpy).not.toHaveBeenCalled();
119
100
  });
120
101
 
@@ -161,9 +142,7 @@ describe("Worker.aiConnector", () => {
161
142
  },
162
143
  },
163
144
  });
164
- expect(
165
- result.nextPacerStates.api?.lastScheduledAtMs,
166
- ).toBeGreaterThanOrEqual(before);
145
+ expect(result.nextPacerStates.api?.lastScheduledAtMs).toBeGreaterThanOrEqual(before);
167
146
  });
168
147
 
169
148
  describe("pacer local fallback", () => {
@@ -243,9 +222,7 @@ describe("Worker.aiConnector", () => {
243
222
  });
244
223
 
245
224
  await expect(capability.handler()).rejects.toThrow(ExecutionError);
246
- expect(stdoutSpy).toHaveBeenCalledWith(
247
- expect.stringContaining(`"_tag":"error"`),
248
- );
225
+ expect(stdoutSpy).toHaveBeenCalledWith(expect.stringContaining(`"_tag":"error"`));
249
226
  });
250
227
 
251
228
  it("accepts chat records at compile time", () => {
@@ -85,18 +85,14 @@ export type AiConnectorChangeUpsert<A extends AiConnectorArchetype> = {
85
85
  record: AiConnectorRecordByArchetype[A];
86
86
  };
87
87
 
88
- export type AiConnectorChange<A extends AiConnectorArchetype> =
89
- AiConnectorChangeUpsert<A>;
88
+ export type AiConnectorChange<A extends AiConnectorArchetype> = AiConnectorChangeUpsert<A>;
90
89
 
91
90
  export type AiConnectorExecutionResult<
92
91
  A extends AiConnectorArchetype,
93
92
  State = unknown,
94
93
  > = StatefulExecutionResult<AiConnectorChange<A>, State>;
95
94
 
96
- export type AiConnectorConfiguration<
97
- A extends AiConnectorArchetype,
98
- State = unknown,
99
- > = {
95
+ export type AiConnectorConfiguration<A extends AiConnectorArchetype, State = unknown> = {
100
96
  /**
101
97
  * The Notion record ID of an existing custom connector in the target workspace.
102
98
  *
@@ -113,9 +109,7 @@ export type AiConnectorConfiguration<
113
109
  ) => Promise<AiConnectorExecutionResult<A, State>>;
114
110
  };
115
111
 
116
- export type AiConnectorCapability = ReturnType<
117
- typeof createAiConnectorCapability
118
- >;
112
+ export type AiConnectorCapability = ReturnType<typeof createAiConnectorCapability>;
119
113
 
120
114
  type NormalizedAiConnectorConfiguration<A extends AiConnectorArchetype> = {
121
115
  aiConnectorId: string;
@@ -131,10 +125,7 @@ type AiConnectorHandlerResult<A extends AiConnectorArchetype, State> = {
131
125
  nextPacerStates: Record<string, PacerEntry>;
132
126
  };
133
127
 
134
- export function createAiConnectorCapability<
135
- A extends AiConnectorArchetype,
136
- State = unknown,
137
- >(
128
+ export function createAiConnectorCapability<A extends AiConnectorArchetype, State = unknown>(
138
129
  key: string,
139
130
  configuration: AiConnectorConfiguration<A, State>,
140
131
  pacerDeclarations?: readonly PacerDeclaration[],
@@ -150,10 +141,7 @@ export function createAiConnectorCapability<
150
141
  ? {}
151
142
  : { schedule: parseSchedule(configuration.schedule) }),
152
143
  } satisfies NormalizedAiConnectorConfiguration<A>,
153
- async handler(
154
- runtimeContext?: StatefulRuntimeContext<State>,
155
- options?: HandlerOptions,
156
- ) {
144
+ async handler(runtimeContext?: StatefulRuntimeContext<State>, options?: HandlerOptions) {
157
145
  const capabilityContext = createCapabilityContext("ai_connector");
158
146
  const state = runtimeContext?.state ?? runtimeContext?.userContext;
159
147
 
@@ -1,12 +1,5 @@
1
- import {
2
- afterEach,
3
- beforeEach,
4
- describe,
5
- expect,
6
- it,
7
- type Mock,
8
- vi,
9
- } from "vitest";
1
+ import { afterEach, beforeEach, describe, expect, it, type Mock, vi } from "vitest";
2
+
10
3
  import { ExecutionError } from "../error.js";
11
4
  import type { PageObjectResponse } from "./automation.js";
12
5
  import { createAutomationCapability } from "./automation.js";
@@ -15,9 +8,7 @@ describe("createAutomationCapability", () => {
15
8
  let stdoutSpy: Mock<typeof process.stdout.write>;
16
9
 
17
10
  beforeEach(() => {
18
- stdoutSpy = vi
19
- .spyOn(process.stdout, "write")
20
- .mockImplementation(() => true);
11
+ stdoutSpy = vi.spyOn(process.stdout, "write").mockImplementation(() => true);
21
12
  });
22
13
 
23
14
  afterEach(() => {
@@ -64,10 +64,7 @@ export interface AutomationConfiguration {
64
64
  * @param context - The capability execution context (Notion client, etc.)
65
65
  * @returns A promise that resolves when the automation completes
66
66
  */
67
- execute: (
68
- event: AutomationEvent,
69
- context: CapabilityContext,
70
- ) => Promise<void> | void;
67
+ execute: (event: AutomationEvent, context: CapabilityContext) => Promise<void> | void;
71
68
  }
72
69
 
73
70
  /**
@@ -78,9 +75,7 @@ export interface AutomationHandlerResult {
78
75
  description: string;
79
76
  }
80
77
 
81
- export type AutomationCapability = ReturnType<
82
- typeof createAutomationCapability
83
- >;
78
+ export type AutomationCapability = ReturnType<typeof createAutomationCapability>;
84
79
 
85
80
  /**
86
81
  * Creates an automation capability from configuration.
@@ -89,10 +84,7 @@ export type AutomationCapability = ReturnType<
89
84
  * @param config - The automation configuration.
90
85
  * @returns The capability object.
91
86
  */
92
- export function createAutomationCapability(
93
- key: string,
94
- config: AutomationConfiguration,
95
- ) {
87
+ export function createAutomationCapability(key: string, config: AutomationConfiguration) {
96
88
  return {
97
89
  _tag: "automation" as const,
98
90
  key,
@@ -1,5 +1,6 @@
1
1
  import { Client } from "@notionhq/client";
2
2
  import type { ClientOptions } from "@notionhq/client/build/src/Client.js";
3
+
3
4
  import type { CapabilityType } from "../worker.js";
4
5
 
5
6
  export type CapabilityContext = {
@@ -32,9 +33,7 @@ function missingTokenMessage(capabilityType: CapabilityType): string {
32
33
  );
33
34
  }
34
35
 
35
- function createUnauthenticatedNotionProxy(
36
- capabilityType: CapabilityType,
37
- ): Client {
36
+ function createUnauthenticatedNotionProxy(capabilityType: CapabilityType): Client {
38
37
  return new Proxy({} as Client, {
39
38
  get(_target, prop) {
40
39
  if (prop === "then" || typeof prop === "symbol") {
@@ -45,9 +44,7 @@ function createUnauthenticatedNotionProxy(
45
44
  });
46
45
  }
47
46
 
48
- export function createCapabilityContext(
49
- capabilityType: CapabilityType,
50
- ): CapabilityContext {
47
+ export function createCapabilityContext(capabilityType: CapabilityType): CapabilityContext {
51
48
  const options: ClientOptions = {};
52
49
 
53
50
  if (process.env.NOTION_API_BASE_URL) {
@@ -1,4 +1,5 @@
1
1
  import { afterEach, describe, expect, it } from "vitest";
2
+
2
3
  import { createOAuthCapability } from "./oauth.js";
3
4
 
4
5
  describe("oauth", () => {
@@ -84,9 +84,7 @@ export interface UserManagedOAuthConfiguration {
84
84
  /**
85
85
  * Union type representing either Notion-managed or user-managed OAuth configuration.
86
86
  */
87
- export type OAuthConfiguration =
88
- | NotionManagedOAuthConfiguration
89
- | UserManagedOAuthConfiguration;
87
+ export type OAuthConfiguration = NotionManagedOAuthConfiguration | UserManagedOAuthConfiguration;
90
88
 
91
89
  export type OAuthCapability = ReturnType<typeof createOAuthCapability>;
92
90
 
@@ -2,7 +2,5 @@
2
2
  * Writes a notion_output envelope to stdout using the shared wire format.
3
3
  */
4
4
  export function writeOutput(value: unknown): void {
5
- process.stdout.write(
6
- `\n<__notion_output__>${JSON.stringify(value)}</__notion_output__>\n`,
7
- );
5
+ process.stdout.write(`\n<__notion_output__>${JSON.stringify(value)}</__notion_output__>\n`);
8
6
  }
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, it } from "vitest";
2
+
2
3
  import { parseSchedule } from "./stateful-capability.js";
3
4
 
4
5
  describe("stateful capability shared primitives", () => {
@@ -73,14 +73,10 @@ export function parseSchedule(schedule: Schedule): SyncSchedule {
73
73
  }
74
74
 
75
75
  if (intervalMs < MIN_INTERVAL_MS) {
76
- throw new Error(
77
- `Schedule interval must be at least 1 minute. Got: "${schedule}"`,
78
- );
76
+ throw new Error(`Schedule interval must be at least 1 minute. Got: "${schedule}"`);
79
77
  }
80
78
  if (intervalMs > MAX_INTERVAL_MS) {
81
- throw new Error(
82
- `Schedule interval must be at most 7 days. Got: "${schedule}"`,
83
- );
79
+ throw new Error(`Schedule interval must be at most 7 days. Got: "${schedule}"`);
84
80
  }
85
81
 
86
82
  return { type: "interval", intervalMs };
@@ -1,12 +1,5 @@
1
- import {
2
- afterEach,
3
- beforeEach,
4
- describe,
5
- expect,
6
- it,
7
- type Mock,
8
- vi,
9
- } from "vitest";
1
+ import { afterEach, beforeEach, describe, expect, it, type Mock, vi } from "vitest";
2
+
10
3
  import * as Builder from "../builder.js";
11
4
  import { ExecutionError, RateLimitError } from "../error.js";
12
5
  import { getPacerState } from "../pacer_internal.js";
@@ -18,9 +11,7 @@ describe("Worker.sync", () => {
18
11
  let stdoutSpy: Mock<typeof process.stdout.write>;
19
12
 
20
13
  beforeEach(() => {
21
- stdoutSpy = vi
22
- .spyOn(process.stdout, "write")
23
- .mockImplementation(() => true);
14
+ stdoutSpy = vi.spyOn(process.stdout, "write").mockImplementation(() => true);
24
15
  });
25
16
 
26
17
  afterEach(() => {
@@ -47,10 +38,7 @@ describe("Worker.sync", () => {
47
38
  });
48
39
 
49
40
  it("can be used to build relation arrays", () => {
50
- const value = [
51
- Builder.relation("project-123"),
52
- Builder.relation("project-456"),
53
- ];
41
+ const value = [Builder.relation("project-123"), Builder.relation("project-456")];
54
42
 
55
43
  expect(value).toEqual([
56
44
  { type: "primaryKey", value: "project-123" },
@@ -81,9 +69,9 @@ describe("Worker.sync", () => {
81
69
  });
82
70
 
83
71
  it("rejects cover positions outside the supported range", () => {
84
- expect(() =>
85
- Builder.imageCover("https://example.com/cover.jpg", 1.5),
86
- ).toThrow("Expected a number between 0 and 1");
72
+ expect(() => Builder.imageCover("https://example.com/cover.jpg", 1.5)).toThrow(
73
+ "Expected a number between 0 and 1",
74
+ );
87
75
  });
88
76
  });
89
77
 
@@ -119,10 +107,7 @@ describe("Worker.sync", () => {
119
107
  key: "task-2",
120
108
  properties: {
121
109
  "Task ID": Builder.title("TASK-002"),
122
- Project: [
123
- Builder.relation("project-123"),
124
- Builder.relation("project-456"),
125
- ],
110
+ Project: [Builder.relation("project-123"), Builder.relation("project-456")],
126
111
  },
127
112
  },
128
113
  ],
@@ -307,12 +292,8 @@ describe("Worker.sync", () => {
307
292
 
308
293
  await expect(capability.handler()).rejects.toThrow(ExecutionError);
309
294
 
310
- expect(stdoutSpy).toHaveBeenCalledWith(
311
- expect.stringContaining(`"_tag":"error"`),
312
- );
313
- expect(stdoutSpy).toHaveBeenCalledWith(
314
- expect.stringContaining(`"name":"ExecutionError"`),
315
- );
295
+ expect(stdoutSpy).toHaveBeenCalledWith(expect.stringContaining(`"_tag":"error"`));
296
+ expect(stdoutSpy).toHaveBeenCalledWith(expect.stringContaining(`"name":"ExecutionError"`));
316
297
  });
317
298
 
318
299
  it("wraps RateLimitError in error envelope with _tag rate_limit", async () => {
@@ -337,12 +318,8 @@ describe("Worker.sync", () => {
337
318
 
338
319
  await expect(capability.handler()).rejects.toThrow(RateLimitError);
339
320
 
340
- expect(stdoutSpy).toHaveBeenCalledWith(
341
- expect.stringContaining(`"_tag":"rate_limit"`),
342
- );
343
- expect(stdoutSpy).toHaveBeenCalledWith(
344
- expect.stringContaining(`"name":"RateLimitError"`),
345
- );
321
+ expect(stdoutSpy).toHaveBeenCalledWith(expect.stringContaining(`"_tag":"rate_limit"`));
322
+ expect(stdoutSpy).toHaveBeenCalledWith(expect.stringContaining(`"name":"RateLimitError"`));
346
323
  });
347
324
 
348
325
  it("includes retryAfter in rate_limit error envelope when provided", async () => {
@@ -371,18 +348,14 @@ describe("Worker.sync", () => {
371
348
  .map((call) => String(call[0]))
372
349
  .find((s) => s.includes(`"_tag":"rate_limit"`)) as string;
373
350
  const parsed = JSON.parse(
374
- output.replace(
375
- /\n<__notion_output__>(.*)<\/__notion_output__>\n/,
376
- "$1",
377
- ),
351
+ output.replace(/\n<__notion_output__>(.*)<\/__notion_output__>\n/, "$1"),
378
352
  );
379
353
  expect(parsed).toEqual({
380
354
  _tag: "error",
381
355
  error: {
382
356
  _tag: "rate_limit",
383
357
  name: "RateLimitError",
384
- message:
385
- "Error during worker execution: Rate limited by external API",
358
+ message: "Error during worker execution: Rate limited by external API",
386
359
  retryAfter: 30,
387
360
  },
388
361
  });
@@ -414,10 +387,7 @@ describe("Worker.sync", () => {
414
387
  .map((call) => String(call[0]))
415
388
  .find((s) => s.includes(`"_tag":"rate_limit"`)) as string;
416
389
  const parsed = JSON.parse(
417
- output.replace(
418
- /\n<__notion_output__>(.*)<\/__notion_output__>\n/,
419
- "$1",
420
- ),
390
+ output.replace(/\n<__notion_output__>(.*)<\/__notion_output__>\n/, "$1"),
421
391
  );
422
392
  expect(parsed.error.retryAfter).toBeUndefined();
423
393
  });
@@ -1,14 +1,6 @@
1
1
  import { ExecutionError, RateLimitError } from "../error.js";
2
- import {
3
- getPacerState,
4
- initPacerState,
5
- type PacerDeclaration,
6
- } from "../pacer_internal.js";
7
- import type {
8
- PropertyConfiguration,
9
- PropertySchema,
10
- Schema,
11
- } from "../schema.js";
2
+ import { getPacerState, initPacerState, type PacerDeclaration } from "../pacer_internal.js";
3
+ import type { PropertyConfiguration, PropertySchema, Schema } from "../schema.js";
12
4
  import type {
13
5
  Cover,
14
6
  HandlerOptions,
@@ -62,10 +54,7 @@ export type SyncMode = StatefulCapabilityMode;
62
54
  /**
63
55
  * A change representing a record to be created or updated.
64
56
  */
65
- export type SyncChangeUpsert<
66
- PK extends string,
67
- S extends PropertySchema<PK>,
68
- > = {
57
+ export type SyncChangeUpsert<PK extends string, S extends PropertySchema<PK>> = {
69
58
  /**
70
59
  * The type of change. Use `"upsert"` to create or update a record.
71
60
  */
@@ -168,11 +157,7 @@ export type SyncExecutionResult<PK extends string, State = unknown> = {
168
157
  /**
169
158
  * Configuration for a sync capability that syncs data to a database.
170
159
  */
171
- export type SyncConfiguration<
172
- PK extends string,
173
- S extends Schema<PK>,
174
- State = unknown,
175
- > = {
160
+ export type SyncConfiguration<PK extends string, S extends Schema<PK>, State = unknown> = {
176
161
  /**
177
162
  * The database to sync data into.
178
163
  */
@@ -233,11 +218,7 @@ export type SyncCapability = ReturnType<typeof createSyncCapability>;
233
218
  * @returns A handler function that executes the sync function, and passes data
234
219
  * needed to complete the sync back to the platform.
235
220
  */
236
- export function createSyncCapability<
237
- PK extends string,
238
- S extends Schema<PK>,
239
- Context = unknown,
240
- >(
221
+ export function createSyncCapability<PK extends string, S extends Schema<PK>, Context = unknown>(
241
222
  key: string,
242
223
  syncConfiguration: SyncConfiguration<PK, S, Context>,
243
224
  pacerDeclarations?: readonly PacerDeclaration[],
@@ -249,14 +230,9 @@ export function createSyncCapability<
249
230
  databaseKey: syncConfiguration.database.key,
250
231
  primaryKeyProperty: syncConfiguration.database.config.primaryKeyProperty,
251
232
  mode: syncConfiguration.mode,
252
- schedule: syncConfiguration.schedule
253
- ? parseSchedule(syncConfiguration.schedule)
254
- : undefined,
233
+ schedule: syncConfiguration.schedule ? parseSchedule(syncConfiguration.schedule) : undefined,
255
234
  },
256
- async handler(
257
- runtimeContext?: StatefulRuntimeContext<Context>,
258
- options?: HandlerOptions,
259
- ) {
235
+ async handler(runtimeContext?: StatefulRuntimeContext<Context>, options?: HandlerOptions) {
260
236
  const capabilityContext = createCapabilityContext("sync");
261
237
  const state = runtimeContext?.state ?? runtimeContext?.userContext;
262
238
 
@@ -264,10 +240,7 @@ export function createSyncCapability<
264
240
 
265
241
  let executionResult: SyncExecutionResult<PK, Context>;
266
242
  try {
267
- executionResult = await syncConfiguration.execute(
268
- state,
269
- capabilityContext,
270
- );
243
+ executionResult = await syncConfiguration.execute(state, capabilityContext);
271
244
  } catch (err) {
272
245
  if (err instanceof RateLimitError) {
273
246
  if (!options?.concreteOutput) {
@@ -277,9 +250,7 @@ export function createSyncCapability<
277
250
  _tag: "rate_limit",
278
251
  name: err.name,
279
252
  message: err.message,
280
- ...(err.retryAfter !== undefined
281
- ? { retryAfter: err.retryAfter }
282
- : {}),
253
+ ...(err.retryAfter !== undefined ? { retryAfter: err.retryAfter } : {}),
283
254
  },
284
255
  };
285
256
  writeOutput(envelope);
@@ -304,8 +275,7 @@ export function createSyncCapability<
304
275
 
305
276
  const changes = executionResult.changes.map((change) => ({
306
277
  ...change,
307
- targetDatabaseKey:
308
- change.targetDatabaseKey ?? syncConfiguration.database.key,
278
+ targetDatabaseKey: change.targetDatabaseKey ?? syncConfiguration.database.key,
309
279
  }));
310
280
 
311
281
  const result = {