@zapier/zapier-sdk 0.13.6 → 0.13.7
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/CHANGELOG.md +7 -0
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +7 -2
- package/src/api/auth.ts +0 -28
- package/src/api/client.ts +0 -491
- package/src/api/debug.test.ts +0 -76
- package/src/api/debug.ts +0 -154
- package/src/api/index.ts +0 -90
- package/src/api/polling.test.ts +0 -405
- package/src/api/polling.ts +0 -253
- package/src/api/schemas.ts +0 -465
- package/src/api/types.ts +0 -152
- package/src/auth.ts +0 -72
- package/src/constants.ts +0 -16
- package/src/index.ts +0 -111
- package/src/plugins/api/index.ts +0 -43
- package/src/plugins/apps/index.ts +0 -203
- package/src/plugins/apps/schemas.ts +0 -64
- package/src/plugins/eventEmission/builders.ts +0 -115
- package/src/plugins/eventEmission/index.test.ts +0 -169
- package/src/plugins/eventEmission/index.ts +0 -294
- package/src/plugins/eventEmission/transport.test.ts +0 -214
- package/src/plugins/eventEmission/transport.ts +0 -135
- package/src/plugins/eventEmission/types.ts +0 -58
- package/src/plugins/eventEmission/utils.ts +0 -121
- package/src/plugins/fetch/index.ts +0 -83
- package/src/plugins/fetch/schemas.ts +0 -37
- package/src/plugins/findFirstAuthentication/index.test.ts +0 -209
- package/src/plugins/findFirstAuthentication/index.ts +0 -68
- package/src/plugins/findFirstAuthentication/schemas.ts +0 -47
- package/src/plugins/findUniqueAuthentication/index.test.ts +0 -197
- package/src/plugins/findUniqueAuthentication/index.ts +0 -77
- package/src/plugins/findUniqueAuthentication/schemas.ts +0 -49
- package/src/plugins/getAction/index.test.ts +0 -239
- package/src/plugins/getAction/index.ts +0 -75
- package/src/plugins/getAction/schemas.ts +0 -41
- package/src/plugins/getApp/index.test.ts +0 -181
- package/src/plugins/getApp/index.ts +0 -60
- package/src/plugins/getApp/schemas.ts +0 -33
- package/src/plugins/getAuthentication/index.test.ts +0 -294
- package/src/plugins/getAuthentication/index.ts +0 -95
- package/src/plugins/getAuthentication/schemas.ts +0 -38
- package/src/plugins/getProfile/index.ts +0 -60
- package/src/plugins/getProfile/schemas.ts +0 -24
- package/src/plugins/listActions/index.test.ts +0 -526
- package/src/plugins/listActions/index.ts +0 -132
- package/src/plugins/listActions/schemas.ts +0 -55
- package/src/plugins/listApps/index.test.ts +0 -378
- package/src/plugins/listApps/index.ts +0 -159
- package/src/plugins/listApps/schemas.ts +0 -41
- package/src/plugins/listAuthentications/index.test.ts +0 -739
- package/src/plugins/listAuthentications/index.ts +0 -152
- package/src/plugins/listAuthentications/schemas.ts +0 -77
- package/src/plugins/listInputFieldChoices/index.test.ts +0 -653
- package/src/plugins/listInputFieldChoices/index.ts +0 -173
- package/src/plugins/listInputFieldChoices/schemas.ts +0 -125
- package/src/plugins/listInputFields/index.test.ts +0 -439
- package/src/plugins/listInputFields/index.ts +0 -294
- package/src/plugins/listInputFields/schemas.ts +0 -68
- package/src/plugins/manifest/index.test.ts +0 -776
- package/src/plugins/manifest/index.ts +0 -461
- package/src/plugins/manifest/schemas.ts +0 -60
- package/src/plugins/registry/index.ts +0 -160
- package/src/plugins/request/index.test.ts +0 -333
- package/src/plugins/request/index.ts +0 -105
- package/src/plugins/request/schemas.ts +0 -69
- package/src/plugins/runAction/index.test.ts +0 -388
- package/src/plugins/runAction/index.ts +0 -215
- package/src/plugins/runAction/schemas.ts +0 -60
- package/src/resolvers/actionKey.ts +0 -37
- package/src/resolvers/actionType.ts +0 -34
- package/src/resolvers/appKey.ts +0 -7
- package/src/resolvers/authenticationId.ts +0 -54
- package/src/resolvers/index.ts +0 -11
- package/src/resolvers/inputFieldKey.ts +0 -70
- package/src/resolvers/inputs.ts +0 -69
- package/src/schemas/Action.ts +0 -52
- package/src/schemas/App.ts +0 -45
- package/src/schemas/Auth.ts +0 -59
- package/src/schemas/Field.ts +0 -169
- package/src/schemas/Run.ts +0 -40
- package/src/schemas/UserProfile.ts +0 -60
- package/src/sdk.test.ts +0 -212
- package/src/sdk.ts +0 -178
- package/src/types/domain.test.ts +0 -50
- package/src/types/domain.ts +0 -66
- package/src/types/errors.ts +0 -278
- package/src/types/events.ts +0 -43
- package/src/types/functions.ts +0 -28
- package/src/types/optional-zapier-sdk-cli-login.d.ts +0 -37
- package/src/types/plugin.ts +0 -125
- package/src/types/properties.ts +0 -80
- package/src/types/sdk.ts +0 -111
- package/src/types/telemetry-events.ts +0 -85
- package/src/utils/array-utils.test.ts +0 -131
- package/src/utils/array-utils.ts +0 -41
- package/src/utils/domain-utils.test.ts +0 -433
- package/src/utils/domain-utils.ts +0 -267
- package/src/utils/file-utils.test.ts +0 -73
- package/src/utils/file-utils.ts +0 -94
- package/src/utils/function-utils.test.ts +0 -141
- package/src/utils/function-utils.ts +0 -245
- package/src/utils/pagination-utils.test.ts +0 -620
- package/src/utils/pagination-utils.ts +0 -242
- package/src/utils/schema-utils.ts +0 -207
- package/src/utils/string-utils.test.ts +0 -45
- package/src/utils/string-utils.ts +0 -54
- package/src/utils/validation.test.ts +0 -51
- package/src/utils/validation.ts +0 -44
- package/tsconfig.build.json +0 -18
- package/tsconfig.json +0 -20
- package/tsconfig.tsbuildinfo +0 -1
- package/tsup.config.ts +0 -23
|
@@ -1,388 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
-
import { ZapierValidationError, ZapierActionError } from "../../types/errors";
|
|
3
|
-
import { runActionPlugin } from "./index";
|
|
4
|
-
import { createSdk } from "../../sdk";
|
|
5
|
-
import type { ApiClient } from "../../api";
|
|
6
|
-
import type { RunActionOptions } from "./schemas";
|
|
7
|
-
import type { ActionItem } from "../../types/domain";
|
|
8
|
-
|
|
9
|
-
const mockAction: ActionItem = {
|
|
10
|
-
type: "action",
|
|
11
|
-
key: "send_message",
|
|
12
|
-
title: "Send Message",
|
|
13
|
-
description: "Send a message to a channel",
|
|
14
|
-
app_key: "slack",
|
|
15
|
-
action_type: "write",
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const mockActionResponse = {
|
|
19
|
-
results: [
|
|
20
|
-
{
|
|
21
|
-
id: "msg_123",
|
|
22
|
-
text: "Hello, world!",
|
|
23
|
-
channel: "#general",
|
|
24
|
-
user: "user_456",
|
|
25
|
-
},
|
|
26
|
-
],
|
|
27
|
-
meta: {
|
|
28
|
-
next_cursor: null,
|
|
29
|
-
},
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
describe("runAction plugin", () => {
|
|
33
|
-
let mockApiClient: ApiClient;
|
|
34
|
-
let mockGetAction: any;
|
|
35
|
-
let mockGetApp: any;
|
|
36
|
-
|
|
37
|
-
beforeEach(() => {
|
|
38
|
-
vi.clearAllMocks();
|
|
39
|
-
mockApiClient = {
|
|
40
|
-
post: vi.fn().mockResolvedValue({ data: { id: "run_123" } }),
|
|
41
|
-
poll: vi.fn().mockResolvedValue({ results: mockActionResponse.results }),
|
|
42
|
-
} as Partial<ApiClient> as ApiClient;
|
|
43
|
-
|
|
44
|
-
mockGetAction = vi.fn().mockResolvedValue({
|
|
45
|
-
data: mockAction,
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
function createTestSdk() {
|
|
50
|
-
return createSdk(
|
|
51
|
-
{},
|
|
52
|
-
{ getAction: mockGetAction, getApp: mockGetApp }, // Provide getAction and getApp in SDK
|
|
53
|
-
{
|
|
54
|
-
api: mockApiClient,
|
|
55
|
-
meta: {},
|
|
56
|
-
getVersionedImplementationId: () => "SlackCLIAPI@1.21.1",
|
|
57
|
-
},
|
|
58
|
-
).addPlugin(runActionPlugin as any);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
describe("schema validation", () => {
|
|
62
|
-
it("should throw validation error for missing appKey", () => {
|
|
63
|
-
const sdk = createTestSdk();
|
|
64
|
-
expect(() => {
|
|
65
|
-
sdk.runAction({
|
|
66
|
-
actionType: "write",
|
|
67
|
-
actionKey: "send_message",
|
|
68
|
-
inputs: { message: "Hello" },
|
|
69
|
-
} as Partial<RunActionOptions> as RunActionOptions);
|
|
70
|
-
}).toThrow(ZapierValidationError);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it("should throw validation error for missing actionType", () => {
|
|
74
|
-
const sdk = createTestSdk();
|
|
75
|
-
expect(() => {
|
|
76
|
-
sdk.runAction({
|
|
77
|
-
appKey: "slack",
|
|
78
|
-
actionKey: "send_message",
|
|
79
|
-
inputs: { message: "Hello" },
|
|
80
|
-
} as Partial<RunActionOptions> as RunActionOptions);
|
|
81
|
-
}).toThrow(ZapierValidationError);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it("should throw validation error for missing actionKey", () => {
|
|
85
|
-
const sdk = createTestSdk();
|
|
86
|
-
expect(() => {
|
|
87
|
-
sdk.runAction({
|
|
88
|
-
appKey: "slack",
|
|
89
|
-
actionType: "write",
|
|
90
|
-
inputs: { message: "Hello" },
|
|
91
|
-
} as Partial<RunActionOptions> as RunActionOptions);
|
|
92
|
-
}).toThrow(ZapierValidationError);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it("should pass validation with all required fields", async () => {
|
|
96
|
-
const sdk = createTestSdk();
|
|
97
|
-
const result = await sdk.runAction({
|
|
98
|
-
appKey: "slack",
|
|
99
|
-
actionType: "write",
|
|
100
|
-
actionKey: "send_message",
|
|
101
|
-
inputs: { message: "Hello" },
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
expect(result.data).toHaveLength(1);
|
|
105
|
-
expect(result.data[0]).toEqual(mockActionResponse.results[0]);
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
describe("action execution", () => {
|
|
110
|
-
it("should validate action exists using getAction", async () => {
|
|
111
|
-
const sdk = createTestSdk();
|
|
112
|
-
await sdk.runAction({
|
|
113
|
-
appKey: "slack",
|
|
114
|
-
actionType: "write",
|
|
115
|
-
actionKey: "send_message",
|
|
116
|
-
inputs: { message: "Hello" },
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
expect(mockGetAction).toHaveBeenCalledWith({
|
|
120
|
-
appKey: "slack",
|
|
121
|
-
actionKey: "send_message",
|
|
122
|
-
actionType: "write",
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it("should throw error when action type doesn't match", async () => {
|
|
127
|
-
// Mock getAction to return an action with different type
|
|
128
|
-
mockGetAction.mockResolvedValue({
|
|
129
|
-
data: { ...mockAction, action_type: "read" },
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
const sdk = createTestSdk();
|
|
133
|
-
await expect(
|
|
134
|
-
sdk.runAction({
|
|
135
|
-
appKey: "slack",
|
|
136
|
-
actionType: "write", // Different from mocked action type
|
|
137
|
-
actionKey: "send_message",
|
|
138
|
-
inputs: { message: "Hello" },
|
|
139
|
-
}),
|
|
140
|
-
).rejects.toThrow(ZapierValidationError);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it("should execute action with correct API call", async () => {
|
|
144
|
-
const sdk = createTestSdk();
|
|
145
|
-
await sdk.runAction({
|
|
146
|
-
appKey: "slack",
|
|
147
|
-
actionType: "write",
|
|
148
|
-
actionKey: "send_message",
|
|
149
|
-
inputs: { message: "Hello", channel: "#general" },
|
|
150
|
-
authenticationId: 12345,
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
expect(mockApiClient.post).toHaveBeenCalledWith("/api/actions/v1/runs", {
|
|
154
|
-
data: {
|
|
155
|
-
selected_api: "SlackCLIAPI@1.21.1",
|
|
156
|
-
action_key: "send_message",
|
|
157
|
-
action_type: "write",
|
|
158
|
-
inputs: { message: "Hello", channel: "#general" },
|
|
159
|
-
authentication_id: 12345,
|
|
160
|
-
},
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
expect(mockApiClient.poll).toHaveBeenCalledWith(
|
|
164
|
-
"/api/actions/v1/runs/run_123",
|
|
165
|
-
{
|
|
166
|
-
successStatus: 200,
|
|
167
|
-
pendingStatus: 202,
|
|
168
|
-
resultExtractor: expect.any(Function),
|
|
169
|
-
},
|
|
170
|
-
);
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
it("should execute action without authentication ID", async () => {
|
|
174
|
-
const sdk = createTestSdk();
|
|
175
|
-
await sdk.runAction({
|
|
176
|
-
appKey: "slack",
|
|
177
|
-
actionType: "write",
|
|
178
|
-
actionKey: "send_message",
|
|
179
|
-
inputs: { message: "Hello" },
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
expect(mockApiClient.post).toHaveBeenCalledWith("/api/actions/v1/runs", {
|
|
183
|
-
data: {
|
|
184
|
-
selected_api: "SlackCLIAPI@1.21.1",
|
|
185
|
-
action_key: "send_message",
|
|
186
|
-
action_type: "write",
|
|
187
|
-
inputs: { message: "Hello" },
|
|
188
|
-
},
|
|
189
|
-
});
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it("should handle pagination cursor", async () => {
|
|
193
|
-
const sdk = createTestSdk();
|
|
194
|
-
const runActionResult = sdk.runAction({
|
|
195
|
-
appKey: "slack",
|
|
196
|
-
actionType: "write",
|
|
197
|
-
actionKey: "send_message",
|
|
198
|
-
inputs: { message: "Hello" },
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
// Simulate pagination by getting an iterator
|
|
202
|
-
const iterator = runActionResult[Symbol.asyncIterator]();
|
|
203
|
-
await iterator.next();
|
|
204
|
-
|
|
205
|
-
expect(mockApiClient.post).toHaveBeenCalledWith(
|
|
206
|
-
"/api/actions/v1/runs",
|
|
207
|
-
expect.objectContaining({
|
|
208
|
-
data: expect.objectContaining({
|
|
209
|
-
inputs: { message: "Hello" },
|
|
210
|
-
selected_api: "SlackCLIAPI@1.21.1",
|
|
211
|
-
action_key: "send_message",
|
|
212
|
-
action_type: "write",
|
|
213
|
-
}),
|
|
214
|
-
}),
|
|
215
|
-
);
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
it("should return results in correct format", async () => {
|
|
219
|
-
const sdk = createTestSdk();
|
|
220
|
-
const result = await sdk.runAction({
|
|
221
|
-
appKey: "slack",
|
|
222
|
-
actionType: "write",
|
|
223
|
-
actionKey: "send_message",
|
|
224
|
-
inputs: { message: "Hello" },
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
expect(result.data).toEqual(mockActionResponse.results);
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
it("should handle single result (not array)", async () => {
|
|
231
|
-
const singleResult = { id: "msg_123", text: "Hello" };
|
|
232
|
-
mockApiClient.post = vi
|
|
233
|
-
.fn()
|
|
234
|
-
.mockResolvedValue({ data: { id: "run_123" } });
|
|
235
|
-
mockApiClient.poll = vi.fn().mockResolvedValue({
|
|
236
|
-
results: [singleResult], // Poll returns the actual results
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
const sdk = createTestSdk();
|
|
240
|
-
const result = await sdk.runAction({
|
|
241
|
-
appKey: "slack",
|
|
242
|
-
actionType: "write",
|
|
243
|
-
actionKey: "send_message",
|
|
244
|
-
inputs: { message: "Hello" },
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
expect(result.data).toEqual([singleResult]); // Should be wrapped in array
|
|
248
|
-
});
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
describe("error handling", () => {
|
|
252
|
-
it("should handle action execution errors", async () => {
|
|
253
|
-
mockApiClient.post = vi
|
|
254
|
-
.fn()
|
|
255
|
-
.mockResolvedValue({ data: { id: "run_123" } });
|
|
256
|
-
mockApiClient.poll = vi.fn().mockResolvedValue({
|
|
257
|
-
results: [],
|
|
258
|
-
errors: [
|
|
259
|
-
{ title: "Invalid inputs", detail: "Message cannot be empty" },
|
|
260
|
-
],
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
const sdk = createTestSdk();
|
|
264
|
-
await expect(
|
|
265
|
-
sdk.runAction({
|
|
266
|
-
appKey: "slack",
|
|
267
|
-
actionType: "write",
|
|
268
|
-
actionKey: "send_message",
|
|
269
|
-
inputs: { message: "" }, // Invalid input
|
|
270
|
-
}),
|
|
271
|
-
).rejects.toThrow(ZapierActionError);
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
it("should handle server errors", async () => {
|
|
275
|
-
mockApiClient.post = vi.fn().mockImplementation((_url, options) => {
|
|
276
|
-
const error = options.customErrorHandler?.({
|
|
277
|
-
status: 500,
|
|
278
|
-
data: { message: "Internal server error" },
|
|
279
|
-
});
|
|
280
|
-
if (error) throw error;
|
|
281
|
-
throw new Error("Server Error");
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
const sdk = createTestSdk();
|
|
285
|
-
await expect(
|
|
286
|
-
sdk.runAction({
|
|
287
|
-
appKey: "slack",
|
|
288
|
-
actionType: "write",
|
|
289
|
-
actionKey: "send_message",
|
|
290
|
-
inputs: { message: "Hello" },
|
|
291
|
-
}),
|
|
292
|
-
).rejects.toThrow();
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
it("should propagate getAction errors", async () => {
|
|
296
|
-
mockGetAction.mockRejectedValue(new Error("Action not found"));
|
|
297
|
-
|
|
298
|
-
const sdk = createTestSdk();
|
|
299
|
-
await expect(
|
|
300
|
-
sdk.runAction({
|
|
301
|
-
appKey: "slack",
|
|
302
|
-
actionType: "write",
|
|
303
|
-
actionKey: "nonexistent",
|
|
304
|
-
inputs: { message: "Hello" },
|
|
305
|
-
}),
|
|
306
|
-
).rejects.toThrow("Action not found");
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
it("should handle unexpected errors during execution", async () => {
|
|
310
|
-
mockApiClient.post = vi
|
|
311
|
-
.fn()
|
|
312
|
-
.mockRejectedValue(new Error("Network error"));
|
|
313
|
-
|
|
314
|
-
const sdk = createTestSdk();
|
|
315
|
-
await expect(
|
|
316
|
-
sdk.runAction({
|
|
317
|
-
appKey: "slack",
|
|
318
|
-
actionType: "write",
|
|
319
|
-
actionKey: "send_message",
|
|
320
|
-
inputs: { message: "Hello" },
|
|
321
|
-
}),
|
|
322
|
-
).rejects.toThrow("Network error");
|
|
323
|
-
});
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
describe("pagination", () => {
|
|
327
|
-
it("should support maxItems limit", async () => {
|
|
328
|
-
const sdk = createTestSdk();
|
|
329
|
-
const result = await sdk.runAction({
|
|
330
|
-
appKey: "slack",
|
|
331
|
-
actionType: "write",
|
|
332
|
-
actionKey: "send_message",
|
|
333
|
-
inputs: { message: "Hello" },
|
|
334
|
-
maxItems: 1,
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
expect(result.data).toHaveLength(1);
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
it("should support async iteration over pages", async () => {
|
|
341
|
-
const sdk = createTestSdk();
|
|
342
|
-
const runActionResult = sdk.runAction({
|
|
343
|
-
appKey: "slack",
|
|
344
|
-
actionType: "write",
|
|
345
|
-
actionKey: "send_message",
|
|
346
|
-
inputs: { message: "Hello" },
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
const pages = [];
|
|
350
|
-
for await (const page of runActionResult) {
|
|
351
|
-
pages.push(page);
|
|
352
|
-
break; // Just get first page for testing
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
expect(pages).toHaveLength(1);
|
|
356
|
-
expect(pages[0].data).toEqual(mockActionResponse.results);
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
it("should support async iteration over individual items", async () => {
|
|
360
|
-
const sdk = createTestSdk();
|
|
361
|
-
const runActionResult = sdk.runAction({
|
|
362
|
-
appKey: "slack",
|
|
363
|
-
actionType: "write",
|
|
364
|
-
actionKey: "send_message",
|
|
365
|
-
inputs: { message: "Hello" },
|
|
366
|
-
maxItems: 1,
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
const items = [];
|
|
370
|
-
for await (const item of runActionResult.items()) {
|
|
371
|
-
items.push(item);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
expect(items).toHaveLength(1);
|
|
375
|
-
expect(items[0]).toEqual(mockActionResponse.results[0]);
|
|
376
|
-
});
|
|
377
|
-
});
|
|
378
|
-
|
|
379
|
-
describe("context and metadata", () => {
|
|
380
|
-
it("should provide context with meta information", () => {
|
|
381
|
-
const sdk = createTestSdk();
|
|
382
|
-
const context = sdk.getContext();
|
|
383
|
-
|
|
384
|
-
expect((context.meta as any).runAction).toBeDefined();
|
|
385
|
-
expect((context.meta as any).runAction.inputSchema).toBeDefined();
|
|
386
|
-
});
|
|
387
|
-
});
|
|
388
|
-
});
|
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
import type { Plugin, GetSdkType } from "../../types/plugin";
|
|
2
|
-
import type { ApiClient } from "../../api";
|
|
3
|
-
import {
|
|
4
|
-
RunActionSchema,
|
|
5
|
-
type RunActionOptions,
|
|
6
|
-
type RunActionPage,
|
|
7
|
-
} from "./schemas";
|
|
8
|
-
import { ActionResultItemSchema } from "../../schemas/Run";
|
|
9
|
-
import {
|
|
10
|
-
ZapierValidationError,
|
|
11
|
-
ZapierConfigurationError,
|
|
12
|
-
ZapierActionError,
|
|
13
|
-
} from "../../types/errors";
|
|
14
|
-
import { createPaginatedFunction } from "../../utils/function-utils";
|
|
15
|
-
import type { GetActionPluginProvides } from "../getAction";
|
|
16
|
-
import type { GetAppPluginProvides } from "../getApp";
|
|
17
|
-
import {
|
|
18
|
-
appKeyResolver,
|
|
19
|
-
actionTypeResolver,
|
|
20
|
-
actionKeyResolver,
|
|
21
|
-
authenticationIdResolver,
|
|
22
|
-
inputsResolver,
|
|
23
|
-
} from "../../resolvers";
|
|
24
|
-
import type { GetVersionedImplementationId } from "../manifest/schemas";
|
|
25
|
-
|
|
26
|
-
export interface RunActionPluginProvides {
|
|
27
|
-
runAction: (options?: RunActionOptions) => Promise<{
|
|
28
|
-
data: any[];
|
|
29
|
-
nextCursor?: string;
|
|
30
|
-
}> &
|
|
31
|
-
AsyncIterable<{ data: any[]; nextCursor?: string }> & {
|
|
32
|
-
items(): AsyncIterable<any>;
|
|
33
|
-
};
|
|
34
|
-
context: {
|
|
35
|
-
meta: {
|
|
36
|
-
runAction: {
|
|
37
|
-
inputSchema: typeof RunActionSchema;
|
|
38
|
-
};
|
|
39
|
-
};
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
interface ExecuteActionOptions {
|
|
44
|
-
api: ApiClient;
|
|
45
|
-
context: {
|
|
46
|
-
getVersionedImplementationId: GetVersionedImplementationId;
|
|
47
|
-
};
|
|
48
|
-
appKey: string;
|
|
49
|
-
actionId?: string;
|
|
50
|
-
actionKey: string;
|
|
51
|
-
actionType: string;
|
|
52
|
-
executionOptions: { inputs: Record<string, unknown> };
|
|
53
|
-
authenticationId?: number | null;
|
|
54
|
-
options: RunActionOptions;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async function executeAction(actionOptions: ExecuteActionOptions): Promise<{
|
|
58
|
-
results: unknown[];
|
|
59
|
-
errors?: Array<{ detail?: string; title?: string }>;
|
|
60
|
-
}> {
|
|
61
|
-
const {
|
|
62
|
-
api,
|
|
63
|
-
context,
|
|
64
|
-
appKey,
|
|
65
|
-
actionId,
|
|
66
|
-
actionKey,
|
|
67
|
-
actionType,
|
|
68
|
-
executionOptions,
|
|
69
|
-
authenticationId,
|
|
70
|
-
} = actionOptions;
|
|
71
|
-
|
|
72
|
-
// Use the manifest plugin to get the current implementation ID
|
|
73
|
-
const selectedApi = await context.getVersionedImplementationId(appKey);
|
|
74
|
-
|
|
75
|
-
if (!selectedApi) {
|
|
76
|
-
throw new ZapierConfigurationError(
|
|
77
|
-
"No current_implementation_id found for app",
|
|
78
|
-
{ configType: "current_implementation_id" },
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Step 1: POST to /actions/v1/runs to start execution
|
|
83
|
-
const runRequestData: {
|
|
84
|
-
selected_api: string;
|
|
85
|
-
action_id?: string;
|
|
86
|
-
action_key: string;
|
|
87
|
-
action_type: string;
|
|
88
|
-
inputs: Record<string, unknown>;
|
|
89
|
-
authentication_id?: number | null;
|
|
90
|
-
} = {
|
|
91
|
-
selected_api: selectedApi,
|
|
92
|
-
action_id: actionId,
|
|
93
|
-
action_key: actionKey,
|
|
94
|
-
action_type: actionType,
|
|
95
|
-
inputs: executionOptions.inputs || {},
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
// Only include authentication_id if it's provided
|
|
99
|
-
if (authenticationId !== null && authenticationId !== undefined) {
|
|
100
|
-
runRequestData.authentication_id = authenticationId;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const runRequest = {
|
|
104
|
-
data: runRequestData,
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
const runData = await api.post<{ data: { id: string } }>(
|
|
108
|
-
"/api/actions/v1/runs",
|
|
109
|
-
runRequest,
|
|
110
|
-
);
|
|
111
|
-
const runId = runData.data.id;
|
|
112
|
-
|
|
113
|
-
// Step 2: Poll GET /actions/v1/runs/{run_id} for results
|
|
114
|
-
return await api.poll(`/api/actions/v1/runs/${runId}`, {
|
|
115
|
-
successStatus: 200,
|
|
116
|
-
pendingStatus: 202,
|
|
117
|
-
resultExtractor: (result: unknown) => (result as { data: unknown }).data,
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export const runActionPlugin: Plugin<
|
|
122
|
-
GetSdkType<GetActionPluginProvides & GetAppPluginProvides>, // requires getAction and getApp in SDK
|
|
123
|
-
{
|
|
124
|
-
api: ApiClient;
|
|
125
|
-
getVersionedImplementationId: GetVersionedImplementationId;
|
|
126
|
-
}, // requires api in context
|
|
127
|
-
RunActionPluginProvides
|
|
128
|
-
> = ({ sdk, context }) => {
|
|
129
|
-
const runAction = createPaginatedFunction(async function runActionPage(
|
|
130
|
-
options: RunActionOptions & { cursor?: string } & { pageSize: number },
|
|
131
|
-
): Promise<RunActionPage> {
|
|
132
|
-
const { api } = context;
|
|
133
|
-
const {
|
|
134
|
-
appKey,
|
|
135
|
-
actionKey,
|
|
136
|
-
actionType,
|
|
137
|
-
authenticationId,
|
|
138
|
-
inputs = {},
|
|
139
|
-
} = options;
|
|
140
|
-
|
|
141
|
-
// Validate that the action exists using the getAction plugin
|
|
142
|
-
const actionData = await sdk.getAction({
|
|
143
|
-
appKey: appKey,
|
|
144
|
-
actionKey: actionKey,
|
|
145
|
-
actionType: actionType,
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
// Validate action type matches
|
|
149
|
-
if (actionData.data.action_type !== actionType) {
|
|
150
|
-
throw new ZapierValidationError(
|
|
151
|
-
`Action type mismatch: expected ${actionType}, got ${actionData.data.action_type}`,
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const actionId = actionData.data.id;
|
|
156
|
-
|
|
157
|
-
// Execute the action using the Actions API (supports all action types)
|
|
158
|
-
const result = await executeAction({
|
|
159
|
-
api,
|
|
160
|
-
context,
|
|
161
|
-
appKey,
|
|
162
|
-
// Some actions require the action ID to run them, but technically the ID is not guaranteed to be available when
|
|
163
|
-
// we retrieve actions (probably legacy reasons), so we just pass along all the things!
|
|
164
|
-
actionId,
|
|
165
|
-
actionKey,
|
|
166
|
-
actionType,
|
|
167
|
-
executionOptions: { inputs },
|
|
168
|
-
authenticationId,
|
|
169
|
-
options,
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
// Check for errors in the result and throw if present
|
|
173
|
-
if (result.errors && result.errors.length > 0) {
|
|
174
|
-
const errorMessage = result.errors
|
|
175
|
-
.map(
|
|
176
|
-
(error: { detail?: string; title?: string }) =>
|
|
177
|
-
error.detail || error.title || "Unknown error",
|
|
178
|
-
)
|
|
179
|
-
.join("; ");
|
|
180
|
-
|
|
181
|
-
throw new ZapierActionError(`Action execution failed: ${errorMessage}`, {
|
|
182
|
-
appKey,
|
|
183
|
-
actionKey,
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Return the results array wrapped in data with empty nextCursor (no pagination for action execution)
|
|
188
|
-
return {
|
|
189
|
-
data: result.results || [],
|
|
190
|
-
nextCursor: undefined, // No pagination implemented yet
|
|
191
|
-
};
|
|
192
|
-
}, RunActionSchema);
|
|
193
|
-
|
|
194
|
-
return {
|
|
195
|
-
runAction,
|
|
196
|
-
context: {
|
|
197
|
-
meta: {
|
|
198
|
-
runAction: {
|
|
199
|
-
categories: ["action"],
|
|
200
|
-
type: "list",
|
|
201
|
-
itemType: "ActionResult",
|
|
202
|
-
inputSchema: RunActionSchema,
|
|
203
|
-
outputSchema: ActionResultItemSchema,
|
|
204
|
-
resolvers: {
|
|
205
|
-
appKey: appKeyResolver,
|
|
206
|
-
actionType: actionTypeResolver,
|
|
207
|
-
actionKey: actionKeyResolver,
|
|
208
|
-
authenticationId: authenticationIdResolver,
|
|
209
|
-
inputs: inputsResolver,
|
|
210
|
-
},
|
|
211
|
-
},
|
|
212
|
-
},
|
|
213
|
-
},
|
|
214
|
-
};
|
|
215
|
-
};
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import {
|
|
3
|
-
AppKeyPropertySchema,
|
|
4
|
-
ActionTypePropertySchema,
|
|
5
|
-
ActionKeyPropertySchema,
|
|
6
|
-
AuthenticationIdPropertySchema,
|
|
7
|
-
InputsPropertySchema,
|
|
8
|
-
} from "../../types/properties";
|
|
9
|
-
import type { PaginatedSdkFunction } from "../../types/functions";
|
|
10
|
-
import type {
|
|
11
|
-
ZapierActionError,
|
|
12
|
-
ZapierValidationError,
|
|
13
|
-
ZapierConfigurationError,
|
|
14
|
-
ZapierUnknownError,
|
|
15
|
-
} from "../../types/errors";
|
|
16
|
-
|
|
17
|
-
// Pure Zod schema - no resolver metadata!
|
|
18
|
-
export const RunActionSchema = z
|
|
19
|
-
.object({
|
|
20
|
-
appKey: AppKeyPropertySchema,
|
|
21
|
-
actionType: ActionTypePropertySchema,
|
|
22
|
-
actionKey: ActionKeyPropertySchema,
|
|
23
|
-
authenticationId: AuthenticationIdPropertySchema.nullable().optional(),
|
|
24
|
-
inputs: InputsPropertySchema.optional().describe(
|
|
25
|
-
"Input parameters for the action",
|
|
26
|
-
),
|
|
27
|
-
pageSize: z
|
|
28
|
-
.number()
|
|
29
|
-
.min(1)
|
|
30
|
-
.optional()
|
|
31
|
-
.describe("Number of results per page"),
|
|
32
|
-
maxItems: z
|
|
33
|
-
.number()
|
|
34
|
-
.min(1)
|
|
35
|
-
.optional()
|
|
36
|
-
.describe("Maximum total items to return across all pages"),
|
|
37
|
-
cursor: z.string().optional().describe("Cursor to start from"),
|
|
38
|
-
})
|
|
39
|
-
.describe("Execute an action with the given inputs");
|
|
40
|
-
|
|
41
|
-
// Type inferred from schema
|
|
42
|
-
export type RunActionOptions = z.infer<typeof RunActionSchema>;
|
|
43
|
-
|
|
44
|
-
// Page result structure (for consistency with other paginated functions)
|
|
45
|
-
export interface RunActionPage {
|
|
46
|
-
data: unknown[];
|
|
47
|
-
nextCursor?: string;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Error union for this function
|
|
51
|
-
export type RunActionError =
|
|
52
|
-
| ZapierActionError
|
|
53
|
-
| ZapierValidationError
|
|
54
|
-
| ZapierConfigurationError
|
|
55
|
-
| ZapierUnknownError;
|
|
56
|
-
|
|
57
|
-
// SDK function interface - ready to be mixed into main SDK interface
|
|
58
|
-
export interface RunActionSdkFunction {
|
|
59
|
-
runAction: PaginatedSdkFunction<RunActionOptions, unknown>;
|
|
60
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import type { DynamicResolver } from "../utils/schema-utils";
|
|
2
|
-
import type { ActionTypeProperty } from "../types/properties";
|
|
3
|
-
|
|
4
|
-
interface ActionItem {
|
|
5
|
-
key: string;
|
|
6
|
-
title?: string;
|
|
7
|
-
name?: string;
|
|
8
|
-
description?: string;
|
|
9
|
-
action_type: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export const actionKeyResolver: DynamicResolver<
|
|
13
|
-
ActionItem,
|
|
14
|
-
{ appKey: string; actionType: ActionTypeProperty }
|
|
15
|
-
> = {
|
|
16
|
-
type: "dynamic",
|
|
17
|
-
depends: ["appKey", "actionType"] as const,
|
|
18
|
-
fetch: async (sdk, resolvedParams) => {
|
|
19
|
-
const actionsResponse = await sdk.listActions({
|
|
20
|
-
appKey: resolvedParams.appKey,
|
|
21
|
-
});
|
|
22
|
-
return actionsResponse.data.filter(
|
|
23
|
-
(action: ActionItem) => action.action_type === resolvedParams.actionType,
|
|
24
|
-
);
|
|
25
|
-
},
|
|
26
|
-
prompt: (actions) => ({
|
|
27
|
-
type: "list",
|
|
28
|
-
name: "actionKey",
|
|
29
|
-
message: "Select action:",
|
|
30
|
-
choices: actions.map((action) => ({
|
|
31
|
-
name: `${action.title || action.name || action.key} - ${
|
|
32
|
-
action.description || "No description"
|
|
33
|
-
}`,
|
|
34
|
-
value: action.key,
|
|
35
|
-
})),
|
|
36
|
-
}),
|
|
37
|
-
};
|