@project-ajax/sdk 0.0.68 → 0.0.70
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.
- package/dist/capabilities/automation.d.ts +8 -28
- package/dist/capabilities/automation.d.ts.map +1 -1
- package/dist/capabilities/automation.js +3 -2
- package/dist/capabilities/oauth.d.ts +6 -31
- package/dist/capabilities/oauth.d.ts.map +1 -1
- package/dist/capabilities/oauth.js +4 -2
- package/dist/capabilities/sync.d.ts +71 -30
- package/dist/capabilities/sync.d.ts.map +1 -1
- package/dist/capabilities/sync.js +6 -5
- package/dist/capabilities/tool.d.ts +5 -25
- package/dist/capabilities/tool.d.ts.map +1 -1
- package/dist/capabilities/tool.js +3 -2
- package/dist/index.d.ts +5 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -9
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/worker.d.ts +175 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +218 -0
- package/package.json +1 -5
- package/src/capabilities/automation.test.ts +17 -23
- package/src/capabilities/automation.ts +14 -30
- package/src/capabilities/oauth.test.ts +16 -15
- package/src/capabilities/oauth.ts +7 -31
- package/src/capabilities/sync.ts +81 -31
- package/src/capabilities/tool.test.ts +105 -89
- package/src/capabilities/tool.ts +12 -31
- package/src/index.ts +9 -5
- package/src/types.ts +11 -0
- package/src/worker.ts +278 -0
package/dist/worker.d.ts
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import type { AutomationCapability, AutomationConfiguration, AutomationContext } from "./capabilities/automation.js";
|
|
2
|
+
import type { NotionManagedOAuthConfiguration, OAuthCapability, OAuthConfiguration, UserManagedOAuthConfiguration } from "./capabilities/oauth.js";
|
|
3
|
+
import type { SyncCapability, SyncConfiguration } from "./capabilities/sync.js";
|
|
4
|
+
import type { ToolCapability, ToolConfiguration } from "./capabilities/tool.js";
|
|
5
|
+
import type { Schema } from "./schema.js";
|
|
6
|
+
import type { JSONValue } from "./types.js";
|
|
7
|
+
export type { AutomationConfiguration, AutomationContext, OAuthConfiguration, NotionManagedOAuthConfiguration, UserManagedOAuthConfiguration, SyncConfiguration, ToolConfiguration, };
|
|
8
|
+
type Capability = SyncCapability | ToolCapability<any, any> | AutomationCapability | OAuthCapability;
|
|
9
|
+
export declare class Worker {
|
|
10
|
+
#private;
|
|
11
|
+
/**
|
|
12
|
+
* Register a sync capability.
|
|
13
|
+
*
|
|
14
|
+
* Example:
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { Worker } from "@project-ajax/sdk";
|
|
18
|
+
* import * as Builder from "@project-ajax/sdk/builder";
|
|
19
|
+
* import * as Schema from "@project-ajax/sdk/schema";
|
|
20
|
+
*
|
|
21
|
+
* const worker = new Worker();
|
|
22
|
+
* export default worker;
|
|
23
|
+
*
|
|
24
|
+
* worker.sync("tasksSync", {
|
|
25
|
+
* primaryKeyProperty: "Task ID",
|
|
26
|
+
* schema: {
|
|
27
|
+
* defaultName: "Tasks",
|
|
28
|
+
* properties: {
|
|
29
|
+
* "Task Name": Schema.title(),
|
|
30
|
+
* "Task ID": Schema.richText(),
|
|
31
|
+
* Status: Schema.select([
|
|
32
|
+
* { name: "Open", color: "default" },
|
|
33
|
+
* { name: "Done", color: "green" },
|
|
34
|
+
* ]),
|
|
35
|
+
* },
|
|
36
|
+
* },
|
|
37
|
+
* execute: async () => {
|
|
38
|
+
* const changes = [
|
|
39
|
+
* {
|
|
40
|
+
* key: "task-1",
|
|
41
|
+
* properties: {
|
|
42
|
+
* "Task Name": Builder.title("Write docs"),
|
|
43
|
+
* "Task ID": Builder.richText("task-1"),
|
|
44
|
+
* Status: Builder.select("Open"),
|
|
45
|
+
* },
|
|
46
|
+
* },
|
|
47
|
+
* ];
|
|
48
|
+
*
|
|
49
|
+
* return { changes, hasMore: false };
|
|
50
|
+
* },
|
|
51
|
+
* });
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* @param key - The unique key for this capability.
|
|
55
|
+
* @param config - The sync configuration.
|
|
56
|
+
* @returns The capability object.
|
|
57
|
+
*/
|
|
58
|
+
sync<PK extends string, S extends Schema<PK>, Context = unknown>(key: string, config: SyncConfiguration<PK, S, Context>): SyncCapability;
|
|
59
|
+
/**
|
|
60
|
+
* Register a tool capability.
|
|
61
|
+
*
|
|
62
|
+
* Example:
|
|
63
|
+
*
|
|
64
|
+
* ```ts
|
|
65
|
+
* worker.tool<{ name: string }, string>("sayHello", {
|
|
66
|
+
* title: "Say Hello",
|
|
67
|
+
* description: "Say hello to the user",
|
|
68
|
+
* schema: {
|
|
69
|
+
* type: "object",
|
|
70
|
+
* properties: {
|
|
71
|
+
* name: { type: "string" },
|
|
72
|
+
* },
|
|
73
|
+
* required: ["name"],
|
|
74
|
+
* },
|
|
75
|
+
* execute: ({ name }) => {
|
|
76
|
+
* return `Hello, ${name}!`;
|
|
77
|
+
* },
|
|
78
|
+
* })
|
|
79
|
+
* ```
|
|
80
|
+
*
|
|
81
|
+
*
|
|
82
|
+
* @param key - The unique key for this capability.
|
|
83
|
+
* @param config - The tool configuration.
|
|
84
|
+
* @returns The capability object.
|
|
85
|
+
*/
|
|
86
|
+
tool<I extends JSONValue, O extends JSONValue = JSONValue>(key: string, config: ToolConfiguration<I, O>): ToolCapability<I, O>;
|
|
87
|
+
/**
|
|
88
|
+
* Register an automation capability.
|
|
89
|
+
*
|
|
90
|
+
* Example:
|
|
91
|
+
*
|
|
92
|
+
* ```ts
|
|
93
|
+
* const worker = new Worker();
|
|
94
|
+
* export default worker;
|
|
95
|
+
*
|
|
96
|
+
* worker.automation("sendWelcomeEmail", {
|
|
97
|
+
* title: "Send Welcome Email",
|
|
98
|
+
* description: "Sends a welcome email when a new user is added",
|
|
99
|
+
* execute: async (context) => {
|
|
100
|
+
* const { pageId, pageData } = context;
|
|
101
|
+
*
|
|
102
|
+
* // Access page properties from the Public API format
|
|
103
|
+
* if (pageData) {
|
|
104
|
+
* const name = pageData.properties.Name; // Access any property
|
|
105
|
+
* const status = pageData.properties.Status;
|
|
106
|
+
* console.log(`Processing: ${name}`);
|
|
107
|
+
* }
|
|
108
|
+
*
|
|
109
|
+
* // Your automation logic here
|
|
110
|
+
* await sendEmail(pageId);
|
|
111
|
+
* },
|
|
112
|
+
* })
|
|
113
|
+
* ```
|
|
114
|
+
*
|
|
115
|
+
* @param key - The unique key for this capability.
|
|
116
|
+
* @param config - The automation configuration.
|
|
117
|
+
* @returns The capability object.
|
|
118
|
+
*/
|
|
119
|
+
automation(key: string, config: AutomationConfiguration): AutomationCapability;
|
|
120
|
+
/**
|
|
121
|
+
* Register an OAuth capability.
|
|
122
|
+
*
|
|
123
|
+
* There are two ways to configure OAuth:
|
|
124
|
+
*
|
|
125
|
+
* 1. Notion-managed providers:
|
|
126
|
+
* ```ts
|
|
127
|
+
* const worker = new Worker();
|
|
128
|
+
* export default worker;
|
|
129
|
+
*
|
|
130
|
+
* worker.oauth("googleAuth", {
|
|
131
|
+
* type: "notion_managed",
|
|
132
|
+
* name: "my-google-auth",
|
|
133
|
+
* provider: "google"
|
|
134
|
+
* })
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
137
|
+
* 2. User-managed OAuth configuration:
|
|
138
|
+
* ```ts
|
|
139
|
+
* const worker = new Worker();
|
|
140
|
+
* export default worker;
|
|
141
|
+
*
|
|
142
|
+
* worker.oauth("myCustomAuth", {
|
|
143
|
+
* type: "user_managed",
|
|
144
|
+
* name: "my-custom-oauth",
|
|
145
|
+
* authorizationEndpoint: "https://provider.com/oauth/authorize",
|
|
146
|
+
* tokenEndpoint: "https://provider.com/oauth/token",
|
|
147
|
+
* scope: "read write",
|
|
148
|
+
* clientId: process.env.CLIENT_ID,
|
|
149
|
+
* clientSecret: process.env.CLIENT_SECRET,
|
|
150
|
+
* authorizationParams: {
|
|
151
|
+
* access_type: "offline",
|
|
152
|
+
* prompt: "consent"
|
|
153
|
+
* }
|
|
154
|
+
* })
|
|
155
|
+
* ```
|
|
156
|
+
*
|
|
157
|
+
* @param key - The unique key used to register this OAuth capability.
|
|
158
|
+
* @param config - The OAuth configuration (Notion-managed or user-managed) for this capability.
|
|
159
|
+
* @returns The registered OAuth capability.
|
|
160
|
+
*/
|
|
161
|
+
oauth(key: string, config: OAuthConfiguration): OAuthCapability;
|
|
162
|
+
/**
|
|
163
|
+
* Get all registered capabilities (for discovery) without their handlers.
|
|
164
|
+
*/
|
|
165
|
+
get capabilities(): Pick<Capability, "_tag" | "key" | "config">[];
|
|
166
|
+
/**
|
|
167
|
+
* Execute a capability by key.
|
|
168
|
+
*
|
|
169
|
+
* @param key - The key of the capability to execute.
|
|
170
|
+
* @param context - The context to pass to the capability.
|
|
171
|
+
* @returns The result of the capability execution.
|
|
172
|
+
*/
|
|
173
|
+
run(key: string, context: unknown): Promise<unknown>;
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=worker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,oBAAoB,EACpB,uBAAuB,EACvB,iBAAiB,EACjB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,KAAK,EACX,+BAA+B,EAC/B,eAAe,EACf,kBAAkB,EAClB,6BAA6B,EAC7B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhF,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5C,YAAY,EACX,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,+BAA+B,EAC/B,6BAA6B,EAC7B,iBAAiB,EACjB,iBAAiB,GACjB,CAAC;AAMF,KAAK,UAAU,GACZ,cAAc,GAEd,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,GACxB,oBAAoB,GACpB,eAAe,CAAC;AAMnB,qBAAa,MAAM;;IAGlB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8CG;IACH,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,CAAC,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,EAC9D,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,iBAAiB,CAAC,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,GACvC,cAAc;IAOjB;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,IAAI,CAAC,CAAC,SAAS,SAAS,EAAE,CAAC,SAAS,SAAS,GAAG,SAAS,EACxD,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC,GAC7B,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC;IAQvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACH,UAAU,CACT,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,uBAAuB,GAC7B,oBAAoB;IAOvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAwCG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,eAAe;IAO/D;;OAEG;IACH,IAAI,YAAY,IAAI,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC,EAAE,CAMhE;IAED;;;;;;OAMG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;CAyB1D"}
|
package/dist/worker.js
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { createAutomationCapability } from "./capabilities/automation.js";
|
|
2
|
+
import { createOAuthCapability } from "./capabilities/oauth.js";
|
|
3
|
+
import { createSyncCapability } from "./capabilities/sync.js";
|
|
4
|
+
import { createToolCapability } from "./capabilities/tool.js";
|
|
5
|
+
class Worker {
|
|
6
|
+
#capabilities = /* @__PURE__ */ new Map();
|
|
7
|
+
/**
|
|
8
|
+
* Register a sync capability.
|
|
9
|
+
*
|
|
10
|
+
* Example:
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { Worker } from "@project-ajax/sdk";
|
|
14
|
+
* import * as Builder from "@project-ajax/sdk/builder";
|
|
15
|
+
* import * as Schema from "@project-ajax/sdk/schema";
|
|
16
|
+
*
|
|
17
|
+
* const worker = new Worker();
|
|
18
|
+
* export default worker;
|
|
19
|
+
*
|
|
20
|
+
* worker.sync("tasksSync", {
|
|
21
|
+
* primaryKeyProperty: "Task ID",
|
|
22
|
+
* schema: {
|
|
23
|
+
* defaultName: "Tasks",
|
|
24
|
+
* properties: {
|
|
25
|
+
* "Task Name": Schema.title(),
|
|
26
|
+
* "Task ID": Schema.richText(),
|
|
27
|
+
* Status: Schema.select([
|
|
28
|
+
* { name: "Open", color: "default" },
|
|
29
|
+
* { name: "Done", color: "green" },
|
|
30
|
+
* ]),
|
|
31
|
+
* },
|
|
32
|
+
* },
|
|
33
|
+
* execute: async () => {
|
|
34
|
+
* const changes = [
|
|
35
|
+
* {
|
|
36
|
+
* key: "task-1",
|
|
37
|
+
* properties: {
|
|
38
|
+
* "Task Name": Builder.title("Write docs"),
|
|
39
|
+
* "Task ID": Builder.richText("task-1"),
|
|
40
|
+
* Status: Builder.select("Open"),
|
|
41
|
+
* },
|
|
42
|
+
* },
|
|
43
|
+
* ];
|
|
44
|
+
*
|
|
45
|
+
* return { changes, hasMore: false };
|
|
46
|
+
* },
|
|
47
|
+
* });
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @param key - The unique key for this capability.
|
|
51
|
+
* @param config - The sync configuration.
|
|
52
|
+
* @returns The capability object.
|
|
53
|
+
*/
|
|
54
|
+
sync(key, config) {
|
|
55
|
+
this.#validateUniqueKey(key);
|
|
56
|
+
const capability = createSyncCapability(key, config);
|
|
57
|
+
this.#capabilities.set(key, capability);
|
|
58
|
+
return capability;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Register a tool capability.
|
|
62
|
+
*
|
|
63
|
+
* Example:
|
|
64
|
+
*
|
|
65
|
+
* ```ts
|
|
66
|
+
* worker.tool<{ name: string }, string>("sayHello", {
|
|
67
|
+
* title: "Say Hello",
|
|
68
|
+
* description: "Say hello to the user",
|
|
69
|
+
* schema: {
|
|
70
|
+
* type: "object",
|
|
71
|
+
* properties: {
|
|
72
|
+
* name: { type: "string" },
|
|
73
|
+
* },
|
|
74
|
+
* required: ["name"],
|
|
75
|
+
* },
|
|
76
|
+
* execute: ({ name }) => {
|
|
77
|
+
* return `Hello, ${name}!`;
|
|
78
|
+
* },
|
|
79
|
+
* })
|
|
80
|
+
* ```
|
|
81
|
+
*
|
|
82
|
+
*
|
|
83
|
+
* @param key - The unique key for this capability.
|
|
84
|
+
* @param config - The tool configuration.
|
|
85
|
+
* @returns The capability object.
|
|
86
|
+
*/
|
|
87
|
+
tool(key, config) {
|
|
88
|
+
this.#validateUniqueKey(key);
|
|
89
|
+
const capability = createToolCapability(key, config);
|
|
90
|
+
this.#capabilities.set(key, capability);
|
|
91
|
+
return capability;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Register an automation capability.
|
|
95
|
+
*
|
|
96
|
+
* Example:
|
|
97
|
+
*
|
|
98
|
+
* ```ts
|
|
99
|
+
* const worker = new Worker();
|
|
100
|
+
* export default worker;
|
|
101
|
+
*
|
|
102
|
+
* worker.automation("sendWelcomeEmail", {
|
|
103
|
+
* title: "Send Welcome Email",
|
|
104
|
+
* description: "Sends a welcome email when a new user is added",
|
|
105
|
+
* execute: async (context) => {
|
|
106
|
+
* const { pageId, pageData } = context;
|
|
107
|
+
*
|
|
108
|
+
* // Access page properties from the Public API format
|
|
109
|
+
* if (pageData) {
|
|
110
|
+
* const name = pageData.properties.Name; // Access any property
|
|
111
|
+
* const status = pageData.properties.Status;
|
|
112
|
+
* console.log(`Processing: ${name}`);
|
|
113
|
+
* }
|
|
114
|
+
*
|
|
115
|
+
* // Your automation logic here
|
|
116
|
+
* await sendEmail(pageId);
|
|
117
|
+
* },
|
|
118
|
+
* })
|
|
119
|
+
* ```
|
|
120
|
+
*
|
|
121
|
+
* @param key - The unique key for this capability.
|
|
122
|
+
* @param config - The automation configuration.
|
|
123
|
+
* @returns The capability object.
|
|
124
|
+
*/
|
|
125
|
+
automation(key, config) {
|
|
126
|
+
this.#validateUniqueKey(key);
|
|
127
|
+
const capability = createAutomationCapability(key, config);
|
|
128
|
+
this.#capabilities.set(key, capability);
|
|
129
|
+
return capability;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Register an OAuth capability.
|
|
133
|
+
*
|
|
134
|
+
* There are two ways to configure OAuth:
|
|
135
|
+
*
|
|
136
|
+
* 1. Notion-managed providers:
|
|
137
|
+
* ```ts
|
|
138
|
+
* const worker = new Worker();
|
|
139
|
+
* export default worker;
|
|
140
|
+
*
|
|
141
|
+
* worker.oauth("googleAuth", {
|
|
142
|
+
* type: "notion_managed",
|
|
143
|
+
* name: "my-google-auth",
|
|
144
|
+
* provider: "google"
|
|
145
|
+
* })
|
|
146
|
+
* ```
|
|
147
|
+
*
|
|
148
|
+
* 2. User-managed OAuth configuration:
|
|
149
|
+
* ```ts
|
|
150
|
+
* const worker = new Worker();
|
|
151
|
+
* export default worker;
|
|
152
|
+
*
|
|
153
|
+
* worker.oauth("myCustomAuth", {
|
|
154
|
+
* type: "user_managed",
|
|
155
|
+
* name: "my-custom-oauth",
|
|
156
|
+
* authorizationEndpoint: "https://provider.com/oauth/authorize",
|
|
157
|
+
* tokenEndpoint: "https://provider.com/oauth/token",
|
|
158
|
+
* scope: "read write",
|
|
159
|
+
* clientId: process.env.CLIENT_ID,
|
|
160
|
+
* clientSecret: process.env.CLIENT_SECRET,
|
|
161
|
+
* authorizationParams: {
|
|
162
|
+
* access_type: "offline",
|
|
163
|
+
* prompt: "consent"
|
|
164
|
+
* }
|
|
165
|
+
* })
|
|
166
|
+
* ```
|
|
167
|
+
*
|
|
168
|
+
* @param key - The unique key used to register this OAuth capability.
|
|
169
|
+
* @param config - The OAuth configuration (Notion-managed or user-managed) for this capability.
|
|
170
|
+
* @returns The registered OAuth capability.
|
|
171
|
+
*/
|
|
172
|
+
oauth(key, config) {
|
|
173
|
+
this.#validateUniqueKey(key);
|
|
174
|
+
const capability = createOAuthCapability(key, config);
|
|
175
|
+
this.#capabilities.set(key, capability);
|
|
176
|
+
return capability;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Get all registered capabilities (for discovery) without their handlers.
|
|
180
|
+
*/
|
|
181
|
+
get capabilities() {
|
|
182
|
+
return Array.from(this.#capabilities.values()).map((c) => ({
|
|
183
|
+
_tag: c._tag,
|
|
184
|
+
key: c.key,
|
|
185
|
+
config: c.config
|
|
186
|
+
}));
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Execute a capability by key.
|
|
190
|
+
*
|
|
191
|
+
* @param key - The key of the capability to execute.
|
|
192
|
+
* @param context - The context to pass to the capability.
|
|
193
|
+
* @returns The result of the capability execution.
|
|
194
|
+
*/
|
|
195
|
+
async run(key, context) {
|
|
196
|
+
const capability = this.#capabilities.get(key);
|
|
197
|
+
if (!capability) {
|
|
198
|
+
throw new Error(`Capability "${key}" not found`);
|
|
199
|
+
}
|
|
200
|
+
if (capability._tag === "oauth") {
|
|
201
|
+
throw new Error(
|
|
202
|
+
`Cannot run OAuth capability "${key}" - OAuth capabilities only provide configuration`
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
return capability.handler(context);
|
|
206
|
+
}
|
|
207
|
+
#validateUniqueKey(key) {
|
|
208
|
+
if (!key || typeof key !== "string") {
|
|
209
|
+
throw new Error("Capability key must be a non-empty string");
|
|
210
|
+
}
|
|
211
|
+
if (this.#capabilities.has(key)) {
|
|
212
|
+
throw new Error(`Capability with key "${key}" already registered`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
export {
|
|
217
|
+
Worker
|
|
218
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@project-ajax/sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.70",
|
|
4
4
|
"description": "An SDK for building workers for the Project Ajax platform",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -28,10 +28,6 @@
|
|
|
28
28
|
"./types": {
|
|
29
29
|
"types": "./dist/types.d.ts",
|
|
30
30
|
"default": "./dist/types.js"
|
|
31
|
-
},
|
|
32
|
-
"./sync": {
|
|
33
|
-
"types": "./dist/capabilities/sync.d.ts",
|
|
34
|
-
"default": "./dist/capabilities/sync.js"
|
|
35
31
|
}
|
|
36
32
|
},
|
|
37
33
|
"engines": {
|
|
@@ -8,14 +8,10 @@ import {
|
|
|
8
8
|
vi,
|
|
9
9
|
} from "vitest";
|
|
10
10
|
import { ExecutionError } from "../error.js";
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
type AutomationContext,
|
|
14
|
-
automation,
|
|
15
|
-
type PageObjectResponse,
|
|
16
|
-
} from "./automation.js";
|
|
11
|
+
import type { AutomationContext, PageObjectResponse } from "./automation.js";
|
|
12
|
+
import { createAutomationCapability } from "./automation.js";
|
|
17
13
|
|
|
18
|
-
describe("
|
|
14
|
+
describe("createAutomationCapability", () => {
|
|
19
15
|
let stdoutSpy: Mock<typeof process.stdout.write>;
|
|
20
16
|
|
|
21
17
|
beforeEach(() => {
|
|
@@ -29,23 +25,21 @@ describe("automation", () => {
|
|
|
29
25
|
});
|
|
30
26
|
|
|
31
27
|
it("creates automation capability with correct structure", () => {
|
|
32
|
-
const
|
|
28
|
+
const capability = createAutomationCapability("testAutomation", {
|
|
33
29
|
title: "Test Automation",
|
|
34
30
|
description: "Test automation description",
|
|
35
31
|
execute: () => {},
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const result = automation(config);
|
|
32
|
+
});
|
|
39
33
|
|
|
40
|
-
expect(
|
|
41
|
-
expect(
|
|
42
|
-
expect(
|
|
43
|
-
expect(
|
|
34
|
+
expect(capability).toBeDefined();
|
|
35
|
+
expect(capability?._tag).toBe("automation");
|
|
36
|
+
expect(capability.config.title).toBe("Test Automation");
|
|
37
|
+
expect(capability.config.description).toBe("Test automation description");
|
|
44
38
|
});
|
|
45
39
|
|
|
46
40
|
it("executes automation without page data", async () => {
|
|
47
41
|
const executeFn = vi.fn();
|
|
48
|
-
const
|
|
42
|
+
const capability = createAutomationCapability("syncAutomation", {
|
|
49
43
|
title: "Sync Automation",
|
|
50
44
|
description: "Executes synchronously",
|
|
51
45
|
execute: executeFn,
|
|
@@ -56,7 +50,7 @@ describe("automation", () => {
|
|
|
56
50
|
actionType: "test_action",
|
|
57
51
|
};
|
|
58
52
|
|
|
59
|
-
await
|
|
53
|
+
await capability.handler(context);
|
|
60
54
|
|
|
61
55
|
expect(executeFn).toHaveBeenCalledWith(context);
|
|
62
56
|
expect(stdoutSpy).toHaveBeenCalledWith(
|
|
@@ -66,7 +60,7 @@ describe("automation", () => {
|
|
|
66
60
|
|
|
67
61
|
it("executes automation with page data", async () => {
|
|
68
62
|
const executeFn = vi.fn();
|
|
69
|
-
const
|
|
63
|
+
const capability = createAutomationCapability("pageAutomation", {
|
|
70
64
|
title: "Page Automation",
|
|
71
65
|
description: "Processes page data",
|
|
72
66
|
execute: executeFn,
|
|
@@ -97,7 +91,7 @@ describe("automation", () => {
|
|
|
97
91
|
pageData,
|
|
98
92
|
};
|
|
99
93
|
|
|
100
|
-
await
|
|
94
|
+
await capability.handler(context);
|
|
101
95
|
|
|
102
96
|
expect(executeFn).toHaveBeenCalledWith(context);
|
|
103
97
|
expect(stdoutSpy).toHaveBeenCalledWith(
|
|
@@ -106,7 +100,7 @@ describe("automation", () => {
|
|
|
106
100
|
});
|
|
107
101
|
|
|
108
102
|
it("handles execution error from function", async () => {
|
|
109
|
-
const
|
|
103
|
+
const capability = createAutomationCapability("errorAutomation", {
|
|
110
104
|
title: "Error Automation",
|
|
111
105
|
description: "Throws an error",
|
|
112
106
|
execute: () => {
|
|
@@ -119,7 +113,7 @@ describe("automation", () => {
|
|
|
119
113
|
actionType: "error_action",
|
|
120
114
|
};
|
|
121
115
|
|
|
122
|
-
await expect(
|
|
116
|
+
await expect(capability.handler(context)).rejects.toThrow(ExecutionError);
|
|
123
117
|
|
|
124
118
|
expect(stdoutSpy).toHaveBeenCalledWith(
|
|
125
119
|
`\n<output>{"status":"error","error":{"name":"ExecutionError","message":"Error during worker execution: Error: Something went wrong"}}</output>\n`,
|
|
@@ -127,7 +121,7 @@ describe("automation", () => {
|
|
|
127
121
|
});
|
|
128
122
|
|
|
129
123
|
it("handles execution error with non-Error object", async () => {
|
|
130
|
-
const
|
|
124
|
+
const capability = createAutomationCapability("nonErrorAutomation", {
|
|
131
125
|
title: "Non-Error Automation",
|
|
132
126
|
description: "Throws a non-Error object",
|
|
133
127
|
execute: () => {
|
|
@@ -139,7 +133,7 @@ describe("automation", () => {
|
|
|
139
133
|
actionType: "string_error_action",
|
|
140
134
|
};
|
|
141
135
|
|
|
142
|
-
await expect(
|
|
136
|
+
await expect(capability.handler(context)).rejects.toThrow(ExecutionError);
|
|
143
137
|
|
|
144
138
|
expect(stdoutSpy).toHaveBeenCalledWith(
|
|
145
139
|
`\n<output>{"status":"error","error":{"name":"ExecutionError","message":"Error during worker execution: String error"}}</output>\n`,
|
|
@@ -70,38 +70,24 @@ export interface AutomationHandlerResult {
|
|
|
70
70
|
description: string;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
export type AutomationCapability = ReturnType<
|
|
74
|
+
typeof createAutomationCapability
|
|
75
|
+
>;
|
|
76
|
+
|
|
73
77
|
/**
|
|
74
|
-
* Creates
|
|
75
|
-
* from database automations in Notion.
|
|
76
|
-
*
|
|
77
|
-
* Example:
|
|
78
|
-
*
|
|
79
|
-
* ```ts
|
|
80
|
-
* automation({
|
|
81
|
-
* title: "Send Welcome Email",
|
|
82
|
-
* description: "Sends a welcome email when a new user is added",
|
|
83
|
-
* execute: async (context) => {
|
|
84
|
-
* const { pageId, pageData } = context;
|
|
85
|
-
*
|
|
86
|
-
* // Access page properties from the Public API format
|
|
87
|
-
* if (pageData) {
|
|
88
|
-
* const name = pageData.properties.Name; // Access any property
|
|
89
|
-
* const status = pageData.properties.Status;
|
|
90
|
-
* console.log(`Processing: ${name}`);
|
|
91
|
-
* }
|
|
92
|
-
*
|
|
93
|
-
* // Your automation logic here
|
|
94
|
-
* await sendEmail(pageId);
|
|
95
|
-
* },
|
|
96
|
-
* })
|
|
97
|
-
* ```
|
|
78
|
+
* Creates an automation capability from configuration.
|
|
98
79
|
*
|
|
99
|
-
* @param
|
|
100
|
-
* @
|
|
80
|
+
* @param key - The unique name for this capability.
|
|
81
|
+
* @param config - The automation configuration.
|
|
82
|
+
* @returns The capability object.
|
|
101
83
|
*/
|
|
102
|
-
export function
|
|
84
|
+
export function createAutomationCapability(
|
|
85
|
+
key: string,
|
|
86
|
+
config: AutomationConfiguration,
|
|
87
|
+
) {
|
|
103
88
|
return {
|
|
104
|
-
_tag: "automation",
|
|
89
|
+
_tag: "automation" as const,
|
|
90
|
+
key,
|
|
105
91
|
config: {
|
|
106
92
|
title: config.title,
|
|
107
93
|
description: config.description,
|
|
@@ -109,12 +95,10 @@ export function automation(config: AutomationConfiguration) {
|
|
|
109
95
|
async handler(context: AutomationContext): Promise<void> {
|
|
110
96
|
try {
|
|
111
97
|
await config.execute(context);
|
|
112
|
-
// Write success result
|
|
113
98
|
process.stdout.write(
|
|
114
99
|
`\n<output>${JSON.stringify({ status: "success" })}</output>\n`,
|
|
115
100
|
);
|
|
116
101
|
} catch (err) {
|
|
117
|
-
// Convert error to ExecutionError and write it
|
|
118
102
|
const error = new ExecutionError(err);
|
|
119
103
|
process.stdout.write(
|
|
120
104
|
`\n<output>${JSON.stringify({ status: "error", error: { name: error.name, message: error.message } })}</output>\n`,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { afterEach, describe, expect, it } from "vitest";
|
|
2
|
-
import {
|
|
2
|
+
import { createOAuthCapability } from "./oauth.js";
|
|
3
3
|
|
|
4
4
|
describe("oauth", () => {
|
|
5
5
|
afterEach(() => {
|
|
@@ -9,42 +9,43 @@ describe("oauth", () => {
|
|
|
9
9
|
});
|
|
10
10
|
|
|
11
11
|
it("creates notion-managed oauth capability with accessToken helper", async () => {
|
|
12
|
-
const
|
|
12
|
+
const capability = createOAuthCapability("googleAuth", {
|
|
13
13
|
name: "googleAuth",
|
|
14
14
|
provider: "google",
|
|
15
15
|
accessTokenExpireMs: 60_000,
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
-
expect(
|
|
19
|
-
expect(
|
|
20
|
-
expect(
|
|
21
|
-
expect(
|
|
22
|
-
|
|
18
|
+
expect(capability).toBeDefined();
|
|
19
|
+
expect(capability?._tag).toBe("oauth");
|
|
20
|
+
expect(capability.config.type).toBe("notion_managed");
|
|
21
|
+
expect(capability.config.accessTokenExpireMs).toBe(60_000);
|
|
22
|
+
|
|
23
|
+
expect(typeof capability.accessToken).toBe("function");
|
|
23
24
|
|
|
24
25
|
process.env.OAUTH_676F6F676C6541757468_ACCESS_TOKEN = "token-123";
|
|
25
|
-
await expect(
|
|
26
|
+
await expect(capability.accessToken()).resolves.toBe("token-123");
|
|
26
27
|
});
|
|
27
28
|
|
|
28
29
|
it("normalizes non-alphanumeric characters in the identifier", () => {
|
|
29
|
-
const
|
|
30
|
+
const capability = createOAuthCapability("googleCalendar", {
|
|
30
31
|
name: "google-calendar",
|
|
31
32
|
provider: "google",
|
|
32
33
|
accessTokenExpireMs: 3600_000,
|
|
33
34
|
});
|
|
34
35
|
|
|
35
|
-
expect(
|
|
36
|
-
|
|
37
|
-
);
|
|
38
|
-
expect(
|
|
36
|
+
expect(capability).toBeDefined();
|
|
37
|
+
expect(capability?._tag).toBe("oauth");
|
|
38
|
+
expect(capability.config.type).toBe("notion_managed");
|
|
39
|
+
expect(capability.config.accessTokenExpireMs).toBe(3600_000);
|
|
39
40
|
});
|
|
40
41
|
|
|
41
42
|
it("throws a helpful error when the token env var is missing", async () => {
|
|
42
|
-
const
|
|
43
|
+
const capability = createOAuthCapability("googleAuthMissing", {
|
|
43
44
|
name: "googleAuth",
|
|
44
45
|
provider: "google",
|
|
45
46
|
});
|
|
46
47
|
|
|
47
|
-
await expect(
|
|
48
|
+
await expect(capability.accessToken()).rejects.toThrow(
|
|
48
49
|
/Missing OAuth access token env var "OAUTH_676F6F676C6541757468_ACCESS_TOKEN"/,
|
|
49
50
|
);
|
|
50
51
|
});
|