@zapier/zapier-sdk 0.13.6 → 0.13.8

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 (155) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/api/client.d.ts.map +1 -1
  3. package/dist/api/client.js +5 -5
  4. package/dist/api/client.test.d.ts +2 -0
  5. package/dist/api/client.test.d.ts.map +1 -0
  6. package/dist/api/client.test.js +80 -0
  7. package/dist/api/index.d.ts +1 -0
  8. package/dist/api/index.d.ts.map +1 -1
  9. package/dist/api/index.js +3 -1
  10. package/dist/api/schemas.d.ts +20 -20
  11. package/dist/api/types.d.ts +2 -0
  12. package/dist/api/types.d.ts.map +1 -1
  13. package/dist/auth.d.ts +3 -0
  14. package/dist/auth.d.ts.map +1 -1
  15. package/dist/auth.test.d.ts +2 -0
  16. package/dist/auth.test.d.ts.map +1 -0
  17. package/dist/auth.test.js +102 -0
  18. package/dist/constants.d.ts +4 -4
  19. package/dist/constants.d.ts.map +1 -1
  20. package/dist/constants.js +4 -4
  21. package/dist/index.cjs +89 -21
  22. package/dist/index.d.mts +21 -1
  23. package/dist/index.d.ts +1 -0
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +2 -0
  26. package/dist/index.mjs +88 -22
  27. package/dist/plugins/api/index.d.ts.map +1 -1
  28. package/dist/plugins/api/index.js +4 -1
  29. package/dist/plugins/eventEmission/index.d.ts +2 -0
  30. package/dist/plugins/eventEmission/index.d.ts.map +1 -1
  31. package/dist/plugins/eventEmission/index.js +35 -9
  32. package/dist/plugins/eventEmission/index.test.js +100 -0
  33. package/dist/schemas/Action.d.ts +2 -2
  34. package/dist/schemas/Auth.d.ts +4 -4
  35. package/dist/schemas/Field.d.ts +10 -10
  36. package/dist/sdk.test.js +121 -1
  37. package/dist/types/sdk.d.ts +3 -0
  38. package/dist/types/sdk.d.ts.map +1 -1
  39. package/dist/utils/url-utils.d.ts +19 -0
  40. package/dist/utils/url-utils.d.ts.map +1 -0
  41. package/dist/utils/url-utils.js +62 -0
  42. package/dist/utils/url-utils.test.d.ts +2 -0
  43. package/dist/utils/url-utils.test.d.ts.map +1 -0
  44. package/dist/utils/url-utils.test.js +103 -0
  45. package/package.json +8 -3
  46. package/src/api/auth.ts +0 -28
  47. package/src/api/client.ts +0 -491
  48. package/src/api/debug.test.ts +0 -76
  49. package/src/api/debug.ts +0 -154
  50. package/src/api/index.ts +0 -90
  51. package/src/api/polling.test.ts +0 -405
  52. package/src/api/polling.ts +0 -253
  53. package/src/api/schemas.ts +0 -465
  54. package/src/api/types.ts +0 -152
  55. package/src/auth.ts +0 -72
  56. package/src/constants.ts +0 -16
  57. package/src/index.ts +0 -111
  58. package/src/plugins/api/index.ts +0 -43
  59. package/src/plugins/apps/index.ts +0 -203
  60. package/src/plugins/apps/schemas.ts +0 -64
  61. package/src/plugins/eventEmission/builders.ts +0 -115
  62. package/src/plugins/eventEmission/index.test.ts +0 -169
  63. package/src/plugins/eventEmission/index.ts +0 -294
  64. package/src/plugins/eventEmission/transport.test.ts +0 -214
  65. package/src/plugins/eventEmission/transport.ts +0 -135
  66. package/src/plugins/eventEmission/types.ts +0 -58
  67. package/src/plugins/eventEmission/utils.ts +0 -121
  68. package/src/plugins/fetch/index.ts +0 -83
  69. package/src/plugins/fetch/schemas.ts +0 -37
  70. package/src/plugins/findFirstAuthentication/index.test.ts +0 -209
  71. package/src/plugins/findFirstAuthentication/index.ts +0 -68
  72. package/src/plugins/findFirstAuthentication/schemas.ts +0 -47
  73. package/src/plugins/findUniqueAuthentication/index.test.ts +0 -197
  74. package/src/plugins/findUniqueAuthentication/index.ts +0 -77
  75. package/src/plugins/findUniqueAuthentication/schemas.ts +0 -49
  76. package/src/plugins/getAction/index.test.ts +0 -239
  77. package/src/plugins/getAction/index.ts +0 -75
  78. package/src/plugins/getAction/schemas.ts +0 -41
  79. package/src/plugins/getApp/index.test.ts +0 -181
  80. package/src/plugins/getApp/index.ts +0 -60
  81. package/src/plugins/getApp/schemas.ts +0 -33
  82. package/src/plugins/getAuthentication/index.test.ts +0 -294
  83. package/src/plugins/getAuthentication/index.ts +0 -95
  84. package/src/plugins/getAuthentication/schemas.ts +0 -38
  85. package/src/plugins/getProfile/index.ts +0 -60
  86. package/src/plugins/getProfile/schemas.ts +0 -24
  87. package/src/plugins/listActions/index.test.ts +0 -526
  88. package/src/plugins/listActions/index.ts +0 -132
  89. package/src/plugins/listActions/schemas.ts +0 -55
  90. package/src/plugins/listApps/index.test.ts +0 -378
  91. package/src/plugins/listApps/index.ts +0 -159
  92. package/src/plugins/listApps/schemas.ts +0 -41
  93. package/src/plugins/listAuthentications/index.test.ts +0 -739
  94. package/src/plugins/listAuthentications/index.ts +0 -152
  95. package/src/plugins/listAuthentications/schemas.ts +0 -77
  96. package/src/plugins/listInputFieldChoices/index.test.ts +0 -653
  97. package/src/plugins/listInputFieldChoices/index.ts +0 -173
  98. package/src/plugins/listInputFieldChoices/schemas.ts +0 -125
  99. package/src/plugins/listInputFields/index.test.ts +0 -439
  100. package/src/plugins/listInputFields/index.ts +0 -294
  101. package/src/plugins/listInputFields/schemas.ts +0 -68
  102. package/src/plugins/manifest/index.test.ts +0 -776
  103. package/src/plugins/manifest/index.ts +0 -461
  104. package/src/plugins/manifest/schemas.ts +0 -60
  105. package/src/plugins/registry/index.ts +0 -160
  106. package/src/plugins/request/index.test.ts +0 -333
  107. package/src/plugins/request/index.ts +0 -105
  108. package/src/plugins/request/schemas.ts +0 -69
  109. package/src/plugins/runAction/index.test.ts +0 -388
  110. package/src/plugins/runAction/index.ts +0 -215
  111. package/src/plugins/runAction/schemas.ts +0 -60
  112. package/src/resolvers/actionKey.ts +0 -37
  113. package/src/resolvers/actionType.ts +0 -34
  114. package/src/resolvers/appKey.ts +0 -7
  115. package/src/resolvers/authenticationId.ts +0 -54
  116. package/src/resolvers/index.ts +0 -11
  117. package/src/resolvers/inputFieldKey.ts +0 -70
  118. package/src/resolvers/inputs.ts +0 -69
  119. package/src/schemas/Action.ts +0 -52
  120. package/src/schemas/App.ts +0 -45
  121. package/src/schemas/Auth.ts +0 -59
  122. package/src/schemas/Field.ts +0 -169
  123. package/src/schemas/Run.ts +0 -40
  124. package/src/schemas/UserProfile.ts +0 -60
  125. package/src/sdk.test.ts +0 -212
  126. package/src/sdk.ts +0 -178
  127. package/src/types/domain.test.ts +0 -50
  128. package/src/types/domain.ts +0 -66
  129. package/src/types/errors.ts +0 -278
  130. package/src/types/events.ts +0 -43
  131. package/src/types/functions.ts +0 -28
  132. package/src/types/optional-zapier-sdk-cli-login.d.ts +0 -37
  133. package/src/types/plugin.ts +0 -125
  134. package/src/types/properties.ts +0 -80
  135. package/src/types/sdk.ts +0 -111
  136. package/src/types/telemetry-events.ts +0 -85
  137. package/src/utils/array-utils.test.ts +0 -131
  138. package/src/utils/array-utils.ts +0 -41
  139. package/src/utils/domain-utils.test.ts +0 -433
  140. package/src/utils/domain-utils.ts +0 -267
  141. package/src/utils/file-utils.test.ts +0 -73
  142. package/src/utils/file-utils.ts +0 -94
  143. package/src/utils/function-utils.test.ts +0 -141
  144. package/src/utils/function-utils.ts +0 -245
  145. package/src/utils/pagination-utils.test.ts +0 -620
  146. package/src/utils/pagination-utils.ts +0 -242
  147. package/src/utils/schema-utils.ts +0 -207
  148. package/src/utils/string-utils.test.ts +0 -45
  149. package/src/utils/string-utils.ts +0 -54
  150. package/src/utils/validation.test.ts +0 -51
  151. package/src/utils/validation.ts +0 -44
  152. package/tsconfig.build.json +0 -18
  153. package/tsconfig.json +0 -20
  154. package/tsconfig.tsbuildinfo +0 -1
  155. package/tsup.config.ts +0 -23
@@ -1,526 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from "vitest";
2
- import {
3
- ZapierValidationError,
4
- ZapierAuthenticationError,
5
- ZapierConfigurationError,
6
- } from "../../types/errors";
7
- import { listActionsPlugin } from "./index";
8
- import { createSdk } from "../../sdk";
9
- import type { ApiClient } from "../../api";
10
- import type { ListActionsOptions } from "./schemas";
11
-
12
- import { listAppsPlugin } from "../listApps";
13
-
14
- const mockImplementationsResponse = {
15
- results: [
16
- {
17
- slug: "slack",
18
- selected_api: "slack",
19
- actions: [
20
- {
21
- key: "user_by_email",
22
- name: "Search User by Email",
23
- description: "Find a user by email address",
24
- type_of: "search",
25
- type: "search",
26
- },
27
- {
28
- key: "send_message",
29
- name: "Send Message",
30
- description: "Send a message to a channel",
31
- type_of: "write",
32
- type: "write",
33
- },
34
- {
35
- key: "create_channel",
36
- name: "Create Channel",
37
- description: "Create a new channel",
38
- type_of: "write",
39
- type: "write",
40
- },
41
- ],
42
- },
43
- ],
44
- meta: {
45
- next_cursor: null,
46
- },
47
- };
48
-
49
- const mockEmptyImplementationsResponse = {
50
- results: [],
51
- meta: {
52
- next_cursor: null,
53
- },
54
- };
55
-
56
- describe("listActions plugin", () => {
57
- let mockApiClient: ApiClient;
58
- let mockGetVersionedImplementationId: any;
59
-
60
- beforeEach(() => {
61
- vi.clearAllMocks();
62
- mockApiClient = {
63
- get: vi.fn().mockResolvedValue(mockImplementationsResponse),
64
- } as Partial<ApiClient> as ApiClient;
65
-
66
- mockGetVersionedImplementationId = vi
67
- .fn()
68
- .mockResolvedValue("SlackCLIAPI@1.21.1");
69
- });
70
-
71
- const mockResolveAppKeys = vi.fn().mockResolvedValue([]);
72
-
73
- function createTestSdk() {
74
- // Create a proper plugin chain with context dependencies
75
-
76
- // Build SDK with proper plugin composition, providing API in initial context
77
- return createSdk()
78
- .addPlugin(() => ({
79
- context: {
80
- api: mockApiClient,
81
- },
82
- }))
83
- .addPlugin(() => ({
84
- context: {
85
- manifest: null,
86
- getVersionedImplementationId: mockGetVersionedImplementationId,
87
- resolveAppKeys: mockResolveAppKeys,
88
- updateManifestEntry: vi
89
- .fn()
90
- .mockResolvedValue(["test-key", {}, { apps: {} }]),
91
- },
92
- }))
93
- .addPlugin(listAppsPlugin)
94
- .addPlugin(listActionsPlugin);
95
- }
96
-
97
- describe("schema validation", () => {
98
- it("should pass validation with valid appKey", async () => {
99
- const sdk = createTestSdk();
100
- const result = await sdk.listActions({ appKey: "slack" });
101
- expect(result.data).toHaveLength(3);
102
- });
103
-
104
- it("should throw validation error for missing appKey", () => {
105
- const sdk = createTestSdk();
106
- expect(() => {
107
- sdk.listActions(
108
- {} as Partial<ListActionsOptions> as ListActionsOptions,
109
- );
110
- }).toThrow(ZapierValidationError);
111
- });
112
-
113
- it("should throw validation error for invalid appKey type", () => {
114
- const sdk = createTestSdk();
115
- expect(() => {
116
- sdk.listActions({
117
- appKey: 123 as any,
118
- });
119
- }).toThrow(ZapierValidationError);
120
- });
121
-
122
- it("should throw validation error for empty appKey", () => {
123
- const sdk = createTestSdk();
124
- expect(() => {
125
- sdk.listActions({ appKey: "" });
126
- }).toThrow(ZapierValidationError);
127
- });
128
-
129
- it("should throw validation error for invalid pageSize", () => {
130
- const sdk = createTestSdk();
131
- expect(() => {
132
- sdk.listActions({ appKey: "slack", pageSize: 0 });
133
- }).toThrow(ZapierValidationError);
134
-
135
- expect(() => {
136
- sdk.listActions({ appKey: "slack", pageSize: -5 });
137
- }).toThrow(ZapierValidationError);
138
- });
139
-
140
- it("should throw validation error for invalid maxItems", () => {
141
- const sdk = createTestSdk();
142
- expect(() => {
143
- sdk.listActions({ appKey: "slack", maxItems: 0 as any });
144
- }).toThrow(ZapierValidationError);
145
-
146
- expect(() => {
147
- sdk.listActions({ appKey: "slack", maxItems: -10 as any });
148
- }).toThrow(ZapierValidationError);
149
- });
150
-
151
- it("should throw validation error for invalid actionType", () => {
152
- const sdk = createTestSdk();
153
- expect(() => {
154
- sdk.listActions({
155
- appKey: "slack",
156
- actionType: "invalid-type" as any,
157
- });
158
- }).toThrow(ZapierValidationError);
159
- });
160
-
161
- it("should pass validation with all valid fields", async () => {
162
- const sdk = createTestSdk();
163
- const result = await sdk.listActions({
164
- appKey: "slack",
165
- actionType: "write",
166
- pageSize: 10,
167
- maxItems: 50,
168
- });
169
-
170
- expect(result.data).toHaveLength(2); // Only write actions
171
- expect(
172
- result.data.every((action: any) => action.action_type === "write"),
173
- ).toBe(true);
174
- });
175
- });
176
-
177
- describe("actionType enum validation", () => {
178
- const validActionTypes = [
179
- "read",
180
- "read_bulk",
181
- "write",
182
- "run",
183
- "search",
184
- "search_or_write",
185
- "search_and_write",
186
- "filter",
187
- ] as const;
188
-
189
- validActionTypes.forEach((actionType) => {
190
- it(`should accept valid actionType: ${actionType}`, async () => {
191
- const mockResponse = {
192
- results: [
193
- {
194
- slug: "slack",
195
- actions: [
196
- {
197
- key: "test_action",
198
- name: "Test Action",
199
- description: "Test description",
200
- type_of: actionType,
201
- type: actionType,
202
- },
203
- ],
204
- },
205
- ],
206
- meta: { next_cursor: null },
207
- };
208
-
209
- mockApiClient.get = vi.fn().mockResolvedValue(mockResponse);
210
-
211
- const sdk = createTestSdk();
212
- const result = await sdk.listActions({
213
- appKey: "slack",
214
- actionType: actionType,
215
- });
216
-
217
- expect(result.data).toHaveLength(1);
218
- expect(result.data[0].action_type).toBe(actionType);
219
- });
220
- });
221
- });
222
-
223
- describe("data transformation", () => {
224
- it("should transform implementation actions to ActionItem format", async () => {
225
- const sdk = createTestSdk();
226
- const result = await sdk.listActions({ appKey: "slack" });
227
-
228
- const firstAction = result.data[0];
229
-
230
- // Check all required ActionItem fields are present
231
- expect(firstAction).toHaveProperty("key");
232
- expect(firstAction).toHaveProperty("type", "action");
233
- expect(firstAction).toHaveProperty("action_type");
234
- expect(firstAction).toHaveProperty("title");
235
- expect(firstAction).toHaveProperty("app_key", "slack");
236
- expect(firstAction).toHaveProperty("description");
237
-
238
- // Check that title is mapped from API name field
239
- expect(firstAction.title).toBe("Search User by Email");
240
- expect(firstAction.app_key).toBe("slack");
241
- expect(firstAction.type).toBe("action");
242
- });
243
-
244
- it("should map type_of to action_type", async () => {
245
- const sdk = createTestSdk();
246
- const result = await sdk.listActions({ appKey: "slack" });
247
-
248
- expect(result.data[0].action_type).toBe("search"); // From type_of field
249
- expect(result.data[1].action_type).toBe("write"); // From type_of field
250
- });
251
-
252
- it("should fall back to type field if type_of is missing", async () => {
253
- const mockResponseWithoutTypeOf = {
254
- results: [
255
- {
256
- slug: "slack",
257
- actions: [
258
- {
259
- key: "test_action",
260
- name: "Test Action",
261
- description: "Test description",
262
- type: "read", // Only type field, no type_of
263
- },
264
- ],
265
- },
266
- ],
267
- meta: { next_cursor: null },
268
- };
269
-
270
- mockApiClient.get = vi.fn().mockResolvedValue(mockResponseWithoutTypeOf);
271
-
272
- const sdk = createTestSdk();
273
- const result = await sdk.listActions({ appKey: "slack" });
274
-
275
- expect(result.data[0].action_type).toBe("read"); // Falls back to type field
276
- });
277
-
278
- it("should handle actions with read type", async () => {
279
- const mockResponseWithoutType = {
280
- results: [
281
- {
282
- slug: "slack",
283
- actions: [
284
- {
285
- key: "test_action",
286
- name: "Test Action",
287
- description: "Test description",
288
- type: "read", // Provide the required type field
289
- },
290
- ],
291
- },
292
- ],
293
- meta: { next_cursor: null },
294
- };
295
-
296
- mockApiClient.get = vi.fn().mockResolvedValue(mockResponseWithoutType);
297
-
298
- const sdk = createTestSdk();
299
- const result = await sdk.listActions({ appKey: "slack" });
300
-
301
- expect(result.data[0].action_type).toBe("read"); // Should match provided type
302
- });
303
- });
304
-
305
- describe("filtering", () => {
306
- it("should filter actions by actionType", async () => {
307
- const sdk = createTestSdk();
308
- const result = await sdk.listActions({
309
- appKey: "slack",
310
- actionType: "write",
311
- });
312
-
313
- expect(result.data).toHaveLength(2);
314
- expect(
315
- result.data.every((action: any) => action.action_type === "write"),
316
- ).toBe(true);
317
- expect(result.data.map((action: any) => action.key)).toEqual([
318
- "send_message",
319
- "create_channel",
320
- ]);
321
- });
322
-
323
- it("should return empty array when no actions match filter", async () => {
324
- const sdk = createTestSdk();
325
- const result = await sdk.listActions({
326
- appKey: "slack",
327
- actionType: "filter", // No actions of this type in mock data
328
- });
329
-
330
- expect(result.data).toHaveLength(0);
331
- });
332
-
333
- it("should return all actions when no actionType filter provided", async () => {
334
- const sdk = createTestSdk();
335
- const result = await sdk.listActions({ appKey: "slack" });
336
-
337
- expect(result.data).toHaveLength(3); // All actions
338
- });
339
- });
340
-
341
- describe("pagination", () => {
342
- it("should handle maxItems limit", async () => {
343
- const sdk = createTestSdk();
344
- const result = await sdk.listActions({
345
- appKey: "slack",
346
- maxItems: 2,
347
- });
348
-
349
- expect(result.data).toHaveLength(2); // Limited to maxItems
350
- });
351
-
352
- it("should support async iteration over pages", async () => {
353
- const sdk = createTestSdk();
354
- const listActions = sdk.listActions({ appKey: "slack" });
355
-
356
- const pages = [];
357
- for await (const page of listActions) {
358
- pages.push(page);
359
- break; // Just get first page for testing
360
- }
361
-
362
- expect(pages).toHaveLength(1);
363
- expect(pages[0].data).toHaveLength(3);
364
- expect(pages[0].data[0].key).toBe("user_by_email");
365
- });
366
-
367
- it("should support async iteration over individual items", async () => {
368
- const sdk = createTestSdk();
369
- const listActions = sdk.listActions({
370
- appKey: "slack",
371
- maxItems: 2,
372
- });
373
-
374
- const items = [];
375
- for await (const item of listActions.items()) {
376
- items.push(item);
377
- }
378
-
379
- expect(items).toHaveLength(2);
380
- expect(items[0].key).toBe("user_by_email");
381
- expect(items[1].key).toBe("send_message");
382
- });
383
-
384
- it("should respect pageSize parameter", async () => {
385
- const sdk = createTestSdk();
386
- await sdk.listActions({
387
- appKey: "slack",
388
- pageSize: 10,
389
- });
390
-
391
- // Note: Since listActions doesn't actually use pagination internally,
392
- // we just verify it accepts the parameter without error
393
- expect(mockApiClient.get).toHaveBeenCalled();
394
- });
395
- });
396
-
397
- describe("API integration", () => {
398
- it("should call getApp to get implementation ID", async () => {
399
- const sdk = createTestSdk();
400
- await sdk.listActions({ appKey: "slack" });
401
-
402
- expect(mockGetVersionedImplementationId).toHaveBeenCalledWith("slack");
403
- });
404
-
405
- it("should pass correct search parameters to implementations API", async () => {
406
- const sdk = createTestSdk();
407
- await sdk.listActions({ appKey: "slack" });
408
-
409
- expect(mockApiClient.get).toHaveBeenCalledWith(
410
- "/api/v4/implementations/",
411
- expect.objectContaining({
412
- searchParams: expect.objectContaining({
413
- global: "true",
414
- public_only: "true",
415
- selected_apis: "SlackCLIAPI@1.21.1",
416
- }),
417
- }),
418
- );
419
- });
420
- });
421
-
422
- describe("error handling", () => {
423
- it("should throw ZapierConfigurationError when app has no current_implementation_id", async () => {
424
- mockGetVersionedImplementationId.mockResolvedValue(null);
425
-
426
- const sdk = createTestSdk();
427
- await expect(sdk.listActions({ appKey: "slack" })).rejects.toThrow(
428
- ZapierConfigurationError,
429
- );
430
- });
431
-
432
- it("should throw ZapierConfigurationError when current_implementation_id is empty", async () => {
433
- mockGetVersionedImplementationId.mockResolvedValue("");
434
-
435
- const sdk = createTestSdk();
436
- await expect(sdk.listActions({ appKey: "slack" })).rejects.toThrow(
437
- ZapierConfigurationError,
438
- );
439
- });
440
-
441
- it("should handle authentication error (401)", async () => {
442
- mockApiClient.get = vi.fn().mockImplementation((_url, options) => {
443
- if (options.customErrorHandler) {
444
- const error = options.customErrorHandler({ status: 401 });
445
- if (error) {
446
- throw error;
447
- }
448
- }
449
- throw new Error("Unauthorized");
450
- });
451
-
452
- const sdk = createTestSdk();
453
- await expect(sdk.listActions({ appKey: "slack" })).rejects.toThrow(
454
- ZapierAuthenticationError,
455
- );
456
- });
457
-
458
- it("should handle forbidden error (403)", async () => {
459
- mockApiClient.get = vi.fn().mockImplementation((_url, options) => {
460
- if (options.customErrorHandler) {
461
- const error = options.customErrorHandler({ status: 403 });
462
- if (error) {
463
- throw error;
464
- }
465
- }
466
- throw new Error("Forbidden");
467
- });
468
-
469
- const sdk = createTestSdk();
470
- await expect(sdk.listActions({ appKey: "slack" })).rejects.toThrow(
471
- ZapierAuthenticationError,
472
- );
473
- });
474
-
475
- it("should return empty array when implementations API returns no results", async () => {
476
- mockApiClient.get = vi
477
- .fn()
478
- .mockResolvedValue(mockEmptyImplementationsResponse);
479
-
480
- const sdk = createTestSdk();
481
- const result = await sdk.listActions({ appKey: "slack" });
482
-
483
- expect(result.data).toHaveLength(0);
484
- });
485
-
486
- it("should handle implementation without actions", async () => {
487
- const mockResponseWithoutActions = {
488
- results: [
489
- {
490
- slug: "slack",
491
- // No actions property
492
- },
493
- ],
494
- meta: { next_cursor: null },
495
- };
496
-
497
- mockApiClient.get = vi.fn().mockResolvedValue(mockResponseWithoutActions);
498
-
499
- const sdk = createTestSdk();
500
- const result = await sdk.listActions({ appKey: "slack" });
501
-
502
- expect(result.data).toHaveLength(0);
503
- });
504
-
505
- it("should propagate getVersionedImplementationId errors", async () => {
506
- mockGetVersionedImplementationId.mockRejectedValue(
507
- new Error("App not found"),
508
- );
509
-
510
- const sdk = createTestSdk();
511
- await expect(sdk.listActions({ appKey: "nonexistent" })).rejects.toThrow(
512
- "App not found",
513
- );
514
- });
515
- });
516
-
517
- describe("context and metadata", () => {
518
- it("should provide context with meta information", () => {
519
- const sdk = createTestSdk();
520
- const context = sdk.getContext();
521
-
522
- expect(context.meta.listActions).toBeDefined();
523
- expect(context.meta.listActions.inputSchema).toBeDefined();
524
- });
525
- });
526
- });
@@ -1,132 +0,0 @@
1
- import type { Plugin, GetSdkType } from "../../types/plugin";
2
- import type { ApiClient, Implementation } from "../../api";
3
- import type { ActionItem } from "../../types/domain";
4
- import { normalizeActionItem } from "../../utils/domain-utils";
5
- import {
6
- ListActionsSchema,
7
- type ListActionsOptions,
8
- type ListActionsPage,
9
- } from "./schemas";
10
- import { ActionItemSchema } from "../../schemas/Action";
11
- import {
12
- ZapierConfigurationError,
13
- ZapierAuthenticationError,
14
- } from "../../types/errors";
15
- import { createPaginatedFunction } from "../../utils/function-utils";
16
- import type { ManifestPluginProvides } from "../manifest";
17
- import type { GetVersionedImplementationId } from "../manifest/schemas";
18
- import { appKeyResolver, actionTypeResolver } from "../../resolvers";
19
-
20
- export interface ListActionsPluginProvides {
21
- listActions: (options?: ListActionsOptions) => Promise<{
22
- data: ActionItem[];
23
- nextCursor?: string;
24
- }> &
25
- AsyncIterable<{ data: ActionItem[]; nextCursor?: string }> & {
26
- items(): AsyncIterable<ActionItem>;
27
- };
28
- context: {
29
- meta: {
30
- listActions: {
31
- inputSchema: typeof ListActionsSchema;
32
- };
33
- };
34
- };
35
- }
36
-
37
- export const listActionsPlugin: Plugin<
38
- GetSdkType<ManifestPluginProvides>,
39
- {
40
- api: ApiClient;
41
- getVersionedImplementationId: GetVersionedImplementationId;
42
- },
43
- ListActionsPluginProvides
44
- > = ({ context }) => {
45
- const listActions = createPaginatedFunction(async function listActionsPage(
46
- options: ListActionsOptions & { cursor?: string } & { pageSize: number },
47
- ): Promise<ListActionsPage> {
48
- const { api, getVersionedImplementationId } = context;
49
-
50
- // Use getVersionedImplementationId (optimized to check manifest first)
51
- const selectedApi = await getVersionedImplementationId(options.appKey);
52
-
53
- if (!selectedApi) {
54
- throw new ZapierConfigurationError(
55
- "No current_implementation_id found for app",
56
- { configType: "current_implementation_id" },
57
- );
58
- }
59
-
60
- const searchParams: Record<string, string> = {
61
- global: "true",
62
- public_only: "true",
63
- selected_apis: selectedApi,
64
- };
65
-
66
- const data = await api.get<{ results: Implementation[] }>(
67
- "/api/v4/implementations/",
68
- {
69
- searchParams,
70
- customErrorHandler: ({ status }) => {
71
- if (status === 401) {
72
- return new ZapierAuthenticationError(
73
- `Authentication failed. Your token may not have permission to access implementations or may be expired. (HTTP ${status})`,
74
- { statusCode: status },
75
- );
76
- }
77
- if (status === 403) {
78
- return new ZapierAuthenticationError(
79
- `Access forbidden. Your token may not have the required scopes to list implementations. (HTTP ${status})`,
80
- { statusCode: status },
81
- );
82
- }
83
- return undefined;
84
- },
85
- },
86
- );
87
-
88
- let allActions: ActionItem[] = [];
89
-
90
- for (const implementation of data.results || []) {
91
- if (implementation.actions) {
92
- for (const action of implementation.actions) {
93
- const actionWithContext = {
94
- ...action,
95
- selected_api: action.selected_api || implementation.selected_api,
96
- };
97
- allActions.push(normalizeActionItem(actionWithContext));
98
- }
99
- }
100
- }
101
-
102
- if (options.actionType) {
103
- allActions = allActions.filter(
104
- (action) => action.action_type === options.actionType,
105
- );
106
- }
107
-
108
- return {
109
- data: allActions,
110
- nextCursor: undefined,
111
- };
112
- }, ListActionsSchema);
113
-
114
- return {
115
- listActions,
116
- context: {
117
- meta: {
118
- listActions: {
119
- categories: ["action"],
120
- type: "list",
121
- itemType: "Action",
122
- inputSchema: ListActionsSchema,
123
- outputSchema: ActionItemSchema,
124
- resolvers: {
125
- appKey: appKeyResolver,
126
- actionType: actionTypeResolver,
127
- },
128
- },
129
- },
130
- },
131
- };
132
- };
@@ -1,55 +0,0 @@
1
- import { z } from "zod";
2
- import {
3
- AppKeyPropertySchema,
4
- ActionTypePropertySchema,
5
- } from "../../types/properties";
6
- import type { ActionItem } from "../../types/domain";
7
- import type { PaginatedSdkFunction } from "../../types/functions";
8
- import type {
9
- ZapierAuthenticationError,
10
- ZapierValidationError,
11
- ZapierUnknownError,
12
- } from "../../types/errors";
13
-
14
- // Pure Zod schema - no resolver metadata!
15
- export const ListActionsSchema = z
16
- .object({
17
- appKey: AppKeyPropertySchema.describe(
18
- "App key of actions to list (e.g., 'SlackCLIAPI' or slug like 'github')",
19
- ),
20
- actionType: ActionTypePropertySchema.optional().describe(
21
- "Filter actions by type",
22
- ),
23
- pageSize: z
24
- .number()
25
- .min(1)
26
- .optional()
27
- .describe("Number of actions per page"),
28
- maxItems: z
29
- .number()
30
- .min(1)
31
- .optional()
32
- .describe("Maximum total items to return across all pages"),
33
- cursor: z.string().optional().describe("Cursor to start from"),
34
- })
35
- .describe("List all actions for a specific app");
36
-
37
- // Type inferred from schema
38
- export type ListActionsOptions = z.infer<typeof ListActionsSchema>;
39
-
40
- // Page result structure
41
- export interface ListActionsPage {
42
- data: ActionItem[];
43
- nextCursor?: string;
44
- }
45
-
46
- // Error union for this function
47
- export type ListActionsError =
48
- | ZapierAuthenticationError
49
- | ZapierValidationError
50
- | ZapierUnknownError;
51
-
52
- // SDK function interface
53
- export interface ListActionsSdkFunction {
54
- listActions: PaginatedSdkFunction<ListActionsOptions, ActionItem>;
55
- }