@notionhq/workers 0.8.0 → 0.8.1

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.
@@ -22,7 +22,7 @@ export type WorkflowConfiguration<TTriggers extends readonly [WorkflowTrigger, .
22
22
  * Each trigger defines a specific event or condition that causes the workflow to run.
23
23
  */
24
24
  triggers: TTriggers;
25
- handler: (event: WorkflowEventForTriggers<TTriggers>, context: CapabilityContext) => Promise<void> | void;
25
+ handler: (event: WorkflowEventForTriggers<TTriggers>, context: WorkflowContext) => Promise<void> | void;
26
26
  };
27
27
  /**
28
28
  * A workflow capability as returned by {@link createWorkflow}.
@@ -60,11 +60,39 @@ export type Workflow<TTriggers extends readonly [WorkflowTrigger, ...WorkflowTri
60
60
  * title: "Send Welcome Email",
61
61
  * description: "Sends a welcome email when a new page is added",
62
62
  * triggers: [triggers.notionPageCreated()],
63
- * handler: async (event) => {
63
+ * handler: async (event, context) => {
64
64
  * console.log(event.page);
65
+ * await context.step("Process page", async ({ id }) => {
66
+ * console.log(`Running step ${id}`);
67
+ * return processPage(event.page);
68
+ * });
65
69
  * },
66
70
  * });
67
71
  * ```
68
72
  */
69
73
  export declare function createWorkflow<const TTriggers extends readonly [WorkflowTrigger, ...WorkflowTrigger[]]>(configuration: WorkflowConfiguration<TTriggers>): Workflow<TTriggers>;
74
+ /** Context passed to a workflow step. */
75
+ export type StepContext = {
76
+ /** An identifier for this invocation of the step. May be used as an idempotency key. */
77
+ id: string;
78
+ };
79
+ /** Context passed to a workflow handler. */
80
+ export type WorkflowContext = CapabilityContext & {
81
+ /**
82
+ * Run an observable unit of work within the workflow.
83
+ *
84
+ * The callback may be synchronous or asynchronous, but `step` always returns
85
+ * a promise. Its return value must be JSON-serializable so it can be included
86
+ * in the success event written to stdout.
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * const page = await context.step("Fetch page", async ({ id }) => {
91
+ * console.log(`Running step ${id}`);
92
+ * return context.notion.pages.retrieve({ page_id: pageId });
93
+ * });
94
+ * ```
95
+ */
96
+ step: <T>(name: string, fn: (context: StepContext) => T | Promise<T>) => Promise<T>;
97
+ };
70
98
  //# sourceMappingURL=workflow.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/alpha/workflow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAItD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AACjF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,MAAM,aAAa,GAAG,gBAAgB,CAAC,MAAM,gBAAgB,CAAC,CAAC;AAErE,MAAM,MAAM,uBAAuB,CAAC,CAAC,SAAS,eAAe,IAAI,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAE7F,MAAM,MAAM,wBAAwB,CAAC,CAAC,SAAS,SAAS,eAAe,EAAE,IACxE,uBAAuB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAEpC;;GAEG;AACH,MAAM,MAAM,qBAAqB,CAChC,SAAS,SAAS,SAAS,CAAC,eAAe,EAAE,GAAG,eAAe,EAAE,CAAC,IAC/D;IACH;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;;OAIG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB,OAAO,EAAE,CACR,KAAK,EAAE,wBAAwB,CAAC,SAAS,CAAC,EAC1C,OAAO,EAAE,iBAAiB,KACtB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,CACnB,SAAS,SAAS,SAAS,CAAC,eAAe,EAAE,GAAG,eAAe,EAAE,CAAC,GAAG,SAAS;IAC7E,eAAe;IACf,GAAG,eAAe,EAAE;CACpB,IACE;IACH,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,SAAS,CAAC;KACpB,CAAC;IACF,OAAO,EAAE,CACR,KAAK,EAAE,wBAAwB,CAAC,SAAS,CAAC,EAC1C,OAAO,CAAC,EAAE,cAAc,KACpB,OAAO,CAAC;QAAE,MAAM,EAAE,SAAS,CAAA;KAAE,GAAG,SAAS,CAAC,CAAC;CAChD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,cAAc,CAC7B,KAAK,CAAC,SAAS,SAAS,SAAS,CAAC,eAAe,EAAE,GAAG,eAAe,EAAE,CAAC,EACvE,aAAa,EAAE,qBAAqB,CAAC,SAAS,CAAC,GAAG,QAAQ,CAAC,SAAS,CAAC,CAuCtE"}
1
+ {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/alpha/workflow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAItD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AACjF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,MAAM,aAAa,GAAG,gBAAgB,CAAC,MAAM,gBAAgB,CAAC,CAAC;AAErE,MAAM,MAAM,uBAAuB,CAAC,CAAC,SAAS,eAAe,IAAI,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAE7F,MAAM,MAAM,wBAAwB,CAAC,CAAC,SAAS,SAAS,eAAe,EAAE,IACxE,uBAAuB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAEpC;;GAEG;AACH,MAAM,MAAM,qBAAqB,CAChC,SAAS,SAAS,SAAS,CAAC,eAAe,EAAE,GAAG,eAAe,EAAE,CAAC,IAC/D;IACH;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;;OAIG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB,OAAO,EAAE,CACR,KAAK,EAAE,wBAAwB,CAAC,SAAS,CAAC,EAC1C,OAAO,EAAE,eAAe,KACpB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,CACnB,SAAS,SAAS,SAAS,CAAC,eAAe,EAAE,GAAG,eAAe,EAAE,CAAC,GAAG,SAAS;IAC7E,eAAe;IACf,GAAG,eAAe,EAAE;CACpB,IACE;IACH,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,SAAS,CAAC;KACpB,CAAC;IACF,OAAO,EAAE,CACR,KAAK,EAAE,wBAAwB,CAAC,SAAS,CAAC,EAC1C,OAAO,CAAC,EAAE,cAAc,KACpB,OAAO,CAAC;QAAE,MAAM,EAAE,SAAS,CAAA;KAAE,GAAG,SAAS,CAAC,CAAC;CAChD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,cAAc,CAC7B,KAAK,CAAC,SAAS,SAAS,SAAS,CAAC,eAAe,EAAE,GAAG,eAAe,EAAE,CAAC,EACvE,aAAa,EAAE,qBAAqB,CAAC,SAAS,CAAC,GAAG,QAAQ,CAAC,SAAS,CAAC,CA0CtE;AAED,yCAAyC;AACzC,MAAM,MAAM,WAAW,GAAG;IACzB,wFAAwF;IACxF,EAAE,EAAE,MAAM,CAAC;CACX,CAAC;AAEF,4CAA4C;AAC5C,MAAM,MAAM,eAAe,GAAG,iBAAiB,GAAG;IACjD;;;;;;;;;;;;;;OAcG;IACH,IAAI,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;CACpF,CAAC"}
@@ -11,7 +11,10 @@ function createWorkflow(configuration) {
11
11
  },
12
12
  async handler(event, options) {
13
13
  try {
14
- const capabilityContext = createCapabilityContext("workflow");
14
+ const capabilityContext = {
15
+ ...createCapabilityContext("workflow"),
16
+ step
17
+ };
15
18
  await configuration.handler(event, capabilityContext);
16
19
  if (options?.concreteOutput) {
17
20
  return { status: "success" };
@@ -34,6 +37,53 @@ function createWorkflow(configuration) {
34
37
  }
35
38
  };
36
39
  }
40
+ function generateUuidV7() {
41
+ const bytes = crypto.getRandomValues(new Uint8Array(16));
42
+ let timestamp = Date.now();
43
+ for (let index = 5; index >= 0; index--) {
44
+ bytes[index] = timestamp % 256;
45
+ timestamp = Math.floor(timestamp / 256);
46
+ }
47
+ bytes[6] = bytes[6] & 15 | 112;
48
+ bytes[8] = bytes[8] & 63 | 128;
49
+ const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
50
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
51
+ }
52
+ function writeStepEvent(event, value) {
53
+ const tag = `__notion_step_${event}__`;
54
+ process.stdout.write(`
55
+ <${tag}>${JSON.stringify(value)}</${tag}>
56
+ `);
57
+ }
58
+ async function step(name, fn) {
59
+ const context = { id: generateUuidV7() };
60
+ const event = { id: context.id, name };
61
+ writeStepEvent("started", event);
62
+ try {
63
+ const value = await fn(context);
64
+ writeStepEvent("success", { ...event, value });
65
+ writeStepEvent("completed", {
66
+ ...event,
67
+ type: "success"
68
+ });
69
+ return value;
70
+ } catch (err) {
71
+ const error = new ExecutionError(err);
72
+ writeStepEvent("failure", {
73
+ ...event,
74
+ error: {
75
+ name: error.name,
76
+ message: error.message,
77
+ trace: error.stack
78
+ }
79
+ });
80
+ writeStepEvent("completed", {
81
+ ...event,
82
+ type: "failure"
83
+ });
84
+ throw err;
85
+ }
86
+ }
37
87
  export {
38
88
  createWorkflow
39
89
  };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * A symbolic marker for the declared credential value. It is safe to include
3
+ * in Worker source and manifests because it never contains the stored secret.
4
+ */
5
+ export declare const CREDENTIAL_VALUE = "{{credential}}";
6
+ export type CredentialKey = string;
7
+ /** A Vercel-compatible collection of headers to add or replace. */
8
+ export type CredentialHeaderTransform = {
9
+ readonly headers: Readonly<Record<string, string>>;
10
+ };
11
+ /**
12
+ * Limits credential injection to a domain. This does not grant or deny general
13
+ * network egress; the sandbox's egress policy remains a separate concern.
14
+ */
15
+ export type CredentialNetworkRule = {
16
+ readonly domain: string;
17
+ readonly transform: readonly CredentialHeaderTransform[];
18
+ };
19
+ export type CredentialConfiguration = {
20
+ /** Destinations and header templates where the credential may be injected. */
21
+ readonly network: readonly CredentialNetworkRule[];
22
+ };
23
+ export type CredentialDeclaration = CredentialConfiguration & {
24
+ readonly key: CredentialKey;
25
+ };
26
+ //# sourceMappingURL=credential.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential.d.ts","sourceRoot":"","sources":["../src/credential.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,gBAAgB,mBAAmB,CAAC;AAkBjD,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC;AAEnC,mEAAmE;AACnE,MAAM,MAAM,yBAAyB,GAAG;IACvC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACnD,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,SAAS,yBAAyB,EAAE,CAAC;CACzD,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACrC,8EAA8E;IAC9E,QAAQ,CAAC,OAAO,EAAE,SAAS,qBAAqB,EAAE,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,uBAAuB,GAAG;IAC7D,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAC;CAC5B,CAAC"}
@@ -0,0 +1,176 @@
1
+ const CREDENTIAL_VALUE = "{{credential}}";
2
+ const MAX_CREDENTIALS = 100;
3
+ const MAX_CREDENTIAL_DECLARATIONS_BYTES = 256 * 1024;
4
+ const MAX_NETWORK_RULES_PER_CREDENTIAL = 20;
5
+ const MAX_TRANSFORMS_PER_NETWORK_RULE = 20;
6
+ const MAX_HEADERS_PER_NETWORK_RULE = 20;
7
+ const MAX_DOMAIN_LENGTH = 253;
8
+ const MAX_HEADER_NAME_LENGTH = 256;
9
+ const MAX_HEADER_TEMPLATE_BYTES = 8 * 1024;
10
+ const ALLOWED_NOTION_CREDENTIAL_KEYS = /* @__PURE__ */ new Set(["NOTION_API_TOKEN", "NOTION_API_BASE_URL"]);
11
+ const CREDENTIAL_DOMAIN_PATTERN = /^(?:\*\.)?(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
12
+ function createCredentialDeclaration(key, config) {
13
+ validateCredentialKey(key);
14
+ if (config.network.length === 0) {
15
+ throw new Error(`Credential "${key}" must declare at least one network rule`);
16
+ }
17
+ if (config.network.length > MAX_NETWORK_RULES_PER_CREDENTIAL) {
18
+ throw new Error(
19
+ `Credential "${key}" cannot declare more than ${MAX_NETWORK_RULES_PER_CREDENTIAL} domains`
20
+ );
21
+ }
22
+ const domains = /* @__PURE__ */ new Set();
23
+ const network = config.network.map((rule) => {
24
+ const domain = normalizeDomain(rule.domain);
25
+ if (domains.has(domain)) {
26
+ throw new Error(`Credential "${key}" declares domain "${domain}" more than once`);
27
+ }
28
+ domains.add(domain);
29
+ if (rule.transform.length === 0 || rule.transform.length > MAX_TRANSFORMS_PER_NETWORK_RULE) {
30
+ throw new Error(
31
+ `Credential "${key}" must declare 1-${MAX_TRANSFORMS_PER_NETWORK_RULE} transforms for domain "${domain}"`
32
+ );
33
+ }
34
+ const headerNames = /* @__PURE__ */ new Set();
35
+ return {
36
+ domain,
37
+ transform: rule.transform.map((transform) => {
38
+ const headers = normalizeHeaders({
39
+ credentialKey: key,
40
+ domain,
41
+ headers: transform.headers
42
+ });
43
+ for (const headerName of Object.keys(headers)) {
44
+ const normalizedHeaderName = headerName.toLowerCase();
45
+ if (headerNames.has(normalizedHeaderName)) {
46
+ throw new Error(
47
+ `Credential "${key}" declares header "${headerName}" more than once for domain "${domain}"`
48
+ );
49
+ }
50
+ headerNames.add(normalizedHeaderName);
51
+ if (headerNames.size > MAX_HEADERS_PER_NETWORK_RULE) {
52
+ throw new Error(
53
+ `Credential "${key}" cannot inject more than ${MAX_HEADERS_PER_NETWORK_RULE} headers for domain "${domain}"`
54
+ );
55
+ }
56
+ }
57
+ return { headers };
58
+ })
59
+ };
60
+ });
61
+ return {
62
+ key,
63
+ network
64
+ };
65
+ }
66
+ function validateCredentialDeclarationConflicts(existingDeclarations, declaration) {
67
+ for (const existing of existingDeclarations) {
68
+ for (const rule of declaration.network) {
69
+ for (const existingRule of existing.network) {
70
+ if (!credentialDomainsOverlap(rule.domain, existingRule.domain)) {
71
+ continue;
72
+ }
73
+ const existingHeaders = new Set(
74
+ existingRule.transform.flatMap(
75
+ (transform) => Object.keys(transform.headers).map((name) => name.toLowerCase())
76
+ )
77
+ );
78
+ for (const transform of rule.transform) {
79
+ for (const headerName of Object.keys(transform.headers)) {
80
+ if (existingHeaders.has(headerName.toLowerCase())) {
81
+ throw new Error(
82
+ `Credential "${declaration.key}" conflicts with credential "${existing.key}" for header "${headerName}" on overlapping domains "${rule.domain}" and "${existingRule.domain}"`
83
+ );
84
+ }
85
+ }
86
+ }
87
+ }
88
+ }
89
+ }
90
+ }
91
+ function validateCredentialKey(key) {
92
+ if (!/^[A-Za-z][A-Za-z0-9_]{0,63}$/.test(key)) {
93
+ throw new Error(
94
+ `Credential key "${key}" must start with a letter, contain only letters, numbers, or underscores, and be at most 64 characters`
95
+ );
96
+ }
97
+ const normalizedKey = key.toUpperCase();
98
+ if (normalizedKey.startsWith("NOTION_") && !ALLOWED_NOTION_CREDENTIAL_KEYS.has(normalizedKey)) {
99
+ throw new Error(`Credential key "${key}" uses the reserved NOTION_ prefix`);
100
+ }
101
+ }
102
+ function normalizeDomain(value) {
103
+ const domain = value.trim().toLowerCase().replace(/\.$/, "");
104
+ if (domain.length > MAX_DOMAIN_LENGTH || !CREDENTIAL_DOMAIN_PATTERN.test(domain)) {
105
+ throw new Error(
106
+ `Credential network domain "${value}" must be an exact hostname or a leading wildcard such as "*.example.com"`
107
+ );
108
+ }
109
+ return domain;
110
+ }
111
+ function credentialDomainsOverlap(first, second) {
112
+ if (first === second) {
113
+ return true;
114
+ }
115
+ const firstBase = first.startsWith("*.") ? first.slice(2) : void 0;
116
+ const secondBase = second.startsWith("*.") ? second.slice(2) : void 0;
117
+ if (firstBase === void 0 && secondBase === void 0) {
118
+ return false;
119
+ }
120
+ if (firstBase !== void 0 && secondBase === void 0) {
121
+ return second.endsWith(`.${firstBase}`);
122
+ }
123
+ if (firstBase === void 0 && secondBase !== void 0) {
124
+ return first.endsWith(`.${secondBase}`);
125
+ }
126
+ return firstBase !== void 0 && secondBase !== void 0 && (firstBase.endsWith(`.${secondBase}`) || secondBase.endsWith(`.${firstBase}`));
127
+ }
128
+ function normalizeHeaders(args) {
129
+ const entries = Object.entries(args.headers);
130
+ if (entries.length === 0) {
131
+ throw new Error(
132
+ `Credential "${args.credentialKey}" has an empty header transform for domain "${args.domain}"`
133
+ );
134
+ }
135
+ return Object.fromEntries(
136
+ entries.map(([name, template]) => {
137
+ if (name.length > MAX_HEADER_NAME_LENGTH || !/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/.test(name)) {
138
+ throw new Error(`Invalid credential header name "${name}"`);
139
+ }
140
+ if (typeof template !== "string") {
141
+ throw new Error(`Credential header "${name}" must use a string template`);
142
+ }
143
+ validateHeaderTemplate(name, template);
144
+ return [name, template];
145
+ })
146
+ );
147
+ }
148
+ function validateHeaderTemplate(name, template) {
149
+ if (hasControlCharacters(template)) {
150
+ throw new Error(`Credential header "${name}" template cannot contain control characters`);
151
+ }
152
+ const markerCount = template.split(CREDENTIAL_VALUE).length - 1;
153
+ if (markerCount !== 1) {
154
+ throw new Error(
155
+ `Credential header "${name}" template must contain CREDENTIAL_VALUE exactly once`
156
+ );
157
+ }
158
+ if (new TextEncoder().encode(template).byteLength > MAX_HEADER_TEMPLATE_BYTES) {
159
+ throw new Error(
160
+ `Credential header "${name}" template must be at most ${MAX_HEADER_TEMPLATE_BYTES} bytes`
161
+ );
162
+ }
163
+ }
164
+ function hasControlCharacters(value) {
165
+ return Array.from(value).some((character) => {
166
+ const codePoint = character.codePointAt(0);
167
+ return codePoint !== void 0 && (codePoint <= 31 || codePoint === 127);
168
+ });
169
+ }
170
+ export {
171
+ CREDENTIAL_VALUE,
172
+ MAX_CREDENTIALS,
173
+ MAX_CREDENTIAL_DECLARATIONS_BYTES,
174
+ createCredentialDeclaration,
175
+ validateCredentialDeclarationConflicts
176
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=credential.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential.test.d.ts","sourceRoot":"","sources":["../src/credential.test.ts"],"names":[],"mappings":""}
package/dist/index.d.ts CHANGED
@@ -9,6 +9,8 @@ export type { ToolCapability, ToolConfiguration, ToolHints } from "./capabilitie
9
9
  export type { WebhookCapability, WebhookConfiguration, WebhookEvent, } from "./capabilities/webhook.js";
10
10
  export { WebhookVerificationError } from "./capabilities/webhook.js";
11
11
  export type { WorkflowCapability, WorkflowConfiguration, WorkflowEvent, WorkflowEventForTrigger, WorkflowEventForTriggers, } from "./capabilities/workflow.js";
12
+ export type { CredentialConfiguration, CredentialDeclaration, CredentialHeaderTransform, CredentialKey, CredentialNetworkRule, } from "./credential.js";
13
+ export { CREDENTIAL_VALUE } from "./credential.js";
12
14
  export { RateLimitError } from "./error.js";
13
15
  export type { AnyJSONSchema, JSONSchema } from "./json-schema.js";
14
16
  export type { Infer, SchemaBuilder } from "./schema-builder.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACX,qBAAqB,EACrB,2BAA2B,EAC3B,wBAAwB,EACxB,mBAAmB,EACnB,6BAA6B,GAC7B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACnF,YAAY,EACX,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,EACrB,wBAAwB,EACxB,0BAA0B,EAC1B,eAAe,EACf,uBAAuB,EACvB,wBAAwB,EACxB,4BAA4B,GAC5B,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACX,oBAAoB,EACpB,uBAAuB,EACvB,eAAe,EACf,kBAAkB,GAClB,MAAM,8BAA8B,CAAC;AACtC,YAAY,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,YAAY,EACX,+BAA+B,EAC/B,eAAe,EACf,kBAAkB,EAClB,6BAA6B,GAC7B,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACX,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,QAAQ,GACR,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC3F,YAAY,EACX,iBAAiB,EACjB,oBAAoB,EACpB,YAAY,GACZ,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,YAAY,EACX,kBAAkB,EAClB,qBAAqB,EACrB,aAAa,EACb,uBAAuB,EACvB,wBAAwB,GACxB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAClE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EACX,KAAK,EACL,IAAI,EACJ,UAAU,EACV,SAAS,EACT,YAAY,EACZ,WAAW,EACX,UAAU,EACV,QAAQ,GACR,MAAM,YAAY,CAAC;AACpB,YAAY,EACX,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,cAAc,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACX,qBAAqB,EACrB,2BAA2B,EAC3B,wBAAwB,EACxB,mBAAmB,EACnB,6BAA6B,GAC7B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACnF,YAAY,EACX,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,EACrB,wBAAwB,EACxB,0BAA0B,EAC1B,eAAe,EACf,uBAAuB,EACvB,wBAAwB,EACxB,4BAA4B,GAC5B,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACX,oBAAoB,EACpB,uBAAuB,EACvB,eAAe,EACf,kBAAkB,GAClB,MAAM,8BAA8B,CAAC;AACtC,YAAY,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,YAAY,EACX,+BAA+B,EAC/B,eAAe,EACf,kBAAkB,EAClB,6BAA6B,GAC7B,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACX,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,QAAQ,GACR,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC3F,YAAY,EACX,iBAAiB,EACjB,oBAAoB,EACpB,YAAY,GACZ,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,YAAY,EACX,kBAAkB,EAClB,qBAAqB,EACrB,aAAa,EACb,uBAAuB,EACvB,wBAAwB,GACxB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACX,uBAAuB,EACvB,qBAAqB,EACrB,yBAAyB,EACzB,aAAa,EACb,qBAAqB,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAClE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EACX,KAAK,EACL,IAAI,EACJ,UAAU,EACV,SAAS,EACT,YAAY,EACZ,WAAW,EACX,UAAU,EACV,QAAQ,GACR,MAAM,YAAY,CAAC;AACpB,YAAY,EACX,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,cAAc,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import { emojiIcon, imageCover, imageIcon, notionIcon, place } from "./builder.js";
2
2
  import { WebhookVerificationError } from "./capabilities/webhook.js";
3
+ import { CREDENTIAL_VALUE } from "./credential.js";
3
4
  import { RateLimitError } from "./error.js";
4
5
  import { getSchema, j } from "./schema-builder.js";
5
6
  import { Worker } from "./worker.js";
6
7
  export {
8
+ CREDENTIAL_VALUE,
7
9
  RateLimitError,
8
10
  WebhookVerificationError,
9
11
  Worker,
package/dist/worker.d.ts CHANGED
@@ -8,6 +8,7 @@ import type { ToolCapability, ToolConfiguration } from "./capabilities/tool.js";
8
8
  import type { WebhookCapability, WebhookConfiguration, WebhookEvent } from "./capabilities/webhook.js";
9
9
  import { WebhookVerificationError } from "./capabilities/webhook.js";
10
10
  import type { WorkflowCapability, WorkflowConfiguration, WorkflowEvent } from "./capabilities/workflow.js";
11
+ import type { CredentialConfiguration, CredentialDeclaration, CredentialKey } from "./credential.js";
11
12
  import type { PacerDeclaration } from "./pacer_internal.js";
12
13
  import type { Schema } from "./schema.js";
13
14
  import type { WorkflowTrigger } from "./triggers.generated.js";
@@ -105,12 +106,18 @@ type CapabilityManifestEntry = Pick<Capability, "_tag" | "key" | "config">;
105
106
  */
106
107
  export type WorkerManifest = {
107
108
  readonly sdkVersion: string;
109
+ readonly credentials: readonly CredentialDeclaration[];
108
110
  readonly databases: readonly RegisteredDatabase[];
109
111
  readonly pacers: readonly PacerDeclaration[];
110
112
  readonly capabilities: readonly CapabilityManifestEntry[];
111
113
  };
112
114
  export declare class Worker {
113
115
  #private;
116
+ /**
117
+ * Declare a credential that is injected into matching outbound HTTPS
118
+ * requests without exposing its value to Worker code.
119
+ */
120
+ credential(key: CredentialKey, config: CredentialConfiguration): void;
114
121
  database<PK extends string, S extends Schema<PK>>(key: string, config: DatabaseConfig<PK, S>): DatabaseHandle<PK, S>;
115
122
  /**
116
123
  * Register a pacer for rate-limiting requests to an external API.
@@ -1 +1 @@
1
- {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"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"}
package/dist/worker.js CHANGED
@@ -6,6 +6,12 @@ import { createSyncCapability } from "./capabilities/sync.js";
6
6
  import { createToolCapability } from "./capabilities/tool.js";
7
7
  import { createWebhookCapability, WebhookVerificationError } from "./capabilities/webhook.js";
8
8
  import { createWorkflowCapability } from "./capabilities/workflow.js";
9
+ import {
10
+ createCredentialDeclaration,
11
+ MAX_CREDENTIAL_DECLARATIONS_BYTES,
12
+ MAX_CREDENTIALS,
13
+ validateCredentialDeclarationConflicts
14
+ } from "./credential.js";
9
15
  import { pacerWait } from "./pacer_internal.js";
10
16
  import { createRequire } from "node:module";
11
17
  const SDK_VERSION = (() => {
@@ -18,8 +24,28 @@ const SDK_VERSION = (() => {
18
24
  })();
19
25
  class Worker {
20
26
  #capabilities = /* @__PURE__ */ new Map();
27
+ #credentials = /* @__PURE__ */ new Map();
21
28
  #databases = /* @__PURE__ */ new Map();
22
29
  #pacers = /* @__PURE__ */ new Map();
30
+ /**
31
+ * Declare a credential that is injected into matching outbound HTTPS
32
+ * requests without exposing its value to Worker code.
33
+ */
34
+ credential(key, config) {
35
+ this.#validateUniqueKey(key);
36
+ if (this.#credentials.size >= MAX_CREDENTIALS) {
37
+ throw new Error(`Worker cannot declare more than ${MAX_CREDENTIALS} credentials`);
38
+ }
39
+ const declaration = createCredentialDeclaration(key, config);
40
+ validateCredentialDeclarationConflicts(this.#credentials.values(), declaration);
41
+ const declarations = [...this.#credentials.values(), declaration];
42
+ if (new TextEncoder().encode(JSON.stringify(declarations)).byteLength > MAX_CREDENTIAL_DECLARATIONS_BYTES) {
43
+ throw new Error(
44
+ `Worker credential declarations must be at most ${MAX_CREDENTIAL_DECLARATIONS_BYTES} bytes`
45
+ );
46
+ }
47
+ this.#credentials.set(key, declaration);
48
+ }
23
49
  database(key, config) {
24
50
  this.#validateUniqueKey(key);
25
51
  const database = { key, config };
@@ -423,6 +449,7 @@ class Worker {
423
449
  get manifest() {
424
450
  return {
425
451
  sdkVersion: SDK_VERSION,
452
+ credentials: Array.from(this.#credentials.values()),
426
453
  databases: Array.from(this.#databases.values()),
427
454
  pacers: Array.from(this.#pacers.values()),
428
455
  capabilities: this.capabilities
@@ -460,7 +487,7 @@ class Worker {
460
487
  if (!key || typeof key !== "string") {
461
488
  throw new Error("Capability key must be a non-empty string");
462
489
  }
463
- if (this.#capabilities.has(key) || this.#databases.has(key) || this.#pacers.has(key)) {
490
+ if (this.#capabilities.has(key) || this.#credentials.has(key) || this.#databases.has(key) || this.#pacers.has(key)) {
464
491
  throw new Error(`Worker item with key "${key}" already registered`);
465
492
  }
466
493
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@notionhq/workers",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "An SDK for building workers for the Notion Workers platform",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -1,8 +1,8 @@
1
- import { afterEach, beforeEach, describe, expect, it, vi, type Mock } from "vitest";
1
+ import { afterEach, beforeEach, describe, expect, expectTypeOf, it, vi, type Mock } from "vitest";
2
2
 
3
3
  import { ExecutionError } from "./error.js";
4
4
  import { triggers, type NotionPageCreatedEvent } from "./triggers.generated.js";
5
- import { createWorkflow } from "./workflow.js";
5
+ import { createWorkflow, type StepContext, type WorkflowContext } from "./workflow.js";
6
6
 
7
7
  let stdoutSpy: Mock<typeof process.stdout.write>;
8
8
 
@@ -16,6 +16,128 @@ afterEach(() => {
16
16
 
17
17
  const event = { type: "notion.page.created" } as NotionPageCreatedEvent;
18
18
 
19
+ async function createWorkflowContext(): Promise<WorkflowContext> {
20
+ let context: WorkflowContext | undefined;
21
+ const workflow = createWorkflow({
22
+ title: "Test workflow",
23
+ description: "Captures its workflow context",
24
+ triggers: [triggers.notionPageCreated()],
25
+ handler: (_event, workflowContext) => {
26
+ context = workflowContext;
27
+ },
28
+ });
29
+
30
+ await workflow.handler(event, { concreteOutput: true });
31
+
32
+ if (!context) {
33
+ throw new Error("Workflow context was not created");
34
+ }
35
+
36
+ return context;
37
+ }
38
+
39
+ describe("step", () => {
40
+ it("runs a synchronous callback and writes success events in order", async () => {
41
+ const { step } = await createWorkflowContext();
42
+ let context: StepContext | undefined;
43
+ const resultPromise = step("Fetch page", (stepContext) => {
44
+ context = stepContext;
45
+ return { pageId: "page-1" } as const;
46
+ });
47
+
48
+ expectTypeOf(resultPromise).toEqualTypeOf<Promise<{ readonly pageId: "page-1" }>>();
49
+ await expect(resultPromise).resolves.toEqual({ pageId: "page-1" });
50
+
51
+ expect(context).toBeDefined();
52
+ const id = context!.id;
53
+ expect(id).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/);
54
+ expect(stdoutSpy.mock.calls.map(([output]) => output)).toEqual([
55
+ `\n<__notion_step_started__>{"id":"${id}","name":"Fetch page"}</__notion_step_started__>\n`,
56
+ `\n<__notion_step_success__>{"id":"${id}","name":"Fetch page","value":{"pageId":"page-1"}}</__notion_step_success__>\n`,
57
+ `\n<__notion_step_completed__>{"id":"${id}","name":"Fetch page","type":"success"}</__notion_step_completed__>\n`,
58
+ ]);
59
+ });
60
+
61
+ it("embeds the invocation timestamp in the UUID v7", async () => {
62
+ const { step } = await createWorkflowContext();
63
+ const now = 1_721_234_567_890;
64
+ const nowSpy = vi.spyOn(Date, "now").mockReturnValue(now);
65
+ let id = "";
66
+
67
+ try {
68
+ await step("Timestamped", async (context) => {
69
+ id = context.id;
70
+ });
71
+ } finally {
72
+ nowSpy.mockRestore();
73
+ }
74
+
75
+ expect(Number.parseInt(id.replaceAll("-", "").slice(0, 12), 16)).toBe(now);
76
+ });
77
+
78
+ it("uses a distinct UUID for each invocation", async () => {
79
+ const { step } = await createWorkflowContext();
80
+ const ids: string[] = [];
81
+
82
+ await step("First", ({ id }) => {
83
+ ids.push(id);
84
+ });
85
+ await step("Second", ({ id }) => {
86
+ ids.push(id);
87
+ });
88
+
89
+ expect(new Set(ids).size).toBe(2);
90
+ });
91
+
92
+ it("writes failure events in order and rethrows the original error", async () => {
93
+ const { step } = await createWorkflowContext();
94
+ const originalError = new Error("boom");
95
+ let id = "";
96
+ const fn = vi.fn((context: StepContext) => {
97
+ id = context.id;
98
+ throw originalError;
99
+ });
100
+
101
+ await expect(step("Explode", fn)).rejects.toBe(originalError);
102
+
103
+ expect(fn).toHaveBeenCalledOnce();
104
+ expect(stdoutSpy).toHaveBeenCalledTimes(3);
105
+ expect(stdoutSpy.mock.calls[0]?.[0]).toBe(
106
+ `\n<__notion_step_started__>{"id":"${id}","name":"Explode"}</__notion_step_started__>\n`,
107
+ );
108
+ expect(stdoutSpy.mock.calls[1]?.[0]).toEqual(
109
+ expect.stringContaining(
110
+ `<__notion_step_failure__>{"id":"${id}","name":"Explode","error":{"name":"ExecutionError","message":"Error during worker execution: Error: boom","trace":`,
111
+ ),
112
+ );
113
+ expect(stdoutSpy.mock.calls[2]?.[0]).toBe(
114
+ `\n<__notion_step_completed__>{"id":"${id}","name":"Explode","type":"failure"}</__notion_step_completed__>\n`,
115
+ );
116
+ });
117
+
118
+ it("writes step events under concreteOutput", async () => {
119
+ const workflow = createWorkflow({
120
+ title: "Log Pages",
121
+ description: "Logs created pages",
122
+ triggers: [triggers.notionPageCreated()],
123
+ handler: async (_event, context) => {
124
+ await context.step("Always visible", () => "done");
125
+ },
126
+ });
127
+
128
+ await workflow.handler(event, { concreteOutput: true });
129
+
130
+ expect(stdoutSpy).toHaveBeenCalledTimes(3);
131
+ expect(stdoutSpy.mock.calls[0]?.[0]).toEqual(
132
+ expect.stringContaining("<__notion_step_started__>"),
133
+ );
134
+ expect(stdoutSpy.mock.calls[1]?.[0]).toEqual(
135
+ expect.stringContaining("<__notion_step_success__>"),
136
+ );
137
+ expect(stdoutSpy.mock.calls[2]?.[0]).toEqual(expect.stringContaining('"type":"success"'));
138
+ });
139
+ });
140
+
19
141
  describe("createWorkflow", () => {
20
142
  it("is tagged and exposes triggers in config", () => {
21
143
  const workflow = createWorkflow({