@zapier/zapier-sdk 0.33.0 → 0.33.2
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 +12 -0
- package/dist/index.cjs +2 -1
- package/dist/index.d.mts +9 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +2 -1
- package/dist/plugins/registry/index.d.ts.map +1 -1
- package/dist/plugins/registry/index.js +1 -0
- package/dist/types/sdk.d.ts +8 -0
- package/dist/types/sdk.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/api/auth.test.d.ts +0 -2
- package/dist/api/auth.test.d.ts.map +0 -1
- package/dist/api/auth.test.js +0 -220
- package/dist/api/client.test.d.ts +0 -2
- package/dist/api/client.test.d.ts.map +0 -1
- package/dist/api/client.test.js +0 -611
- package/dist/api/debug.test.d.ts +0 -2
- package/dist/api/debug.test.d.ts.map +0 -1
- package/dist/api/debug.test.js +0 -59
- package/dist/api/polling.test.d.ts +0 -2
- package/dist/api/polling.test.d.ts.map +0 -1
- package/dist/api/polling.test.js +0 -360
- package/dist/auth.test.d.ts +0 -2
- package/dist/auth.test.d.ts.map +0 -1
- package/dist/auth.test.js +0 -480
- package/dist/plugins/eventEmission/builders.test.d.ts +0 -2
- package/dist/plugins/eventEmission/builders.test.d.ts.map +0 -1
- package/dist/plugins/eventEmission/builders.test.js +0 -138
- package/dist/plugins/eventEmission/index.test.d.ts +0 -5
- package/dist/plugins/eventEmission/index.test.d.ts.map +0 -1
- package/dist/plugins/eventEmission/index.test.js +0 -712
- package/dist/plugins/eventEmission/transport.test.d.ts +0 -5
- package/dist/plugins/eventEmission/transport.test.d.ts.map +0 -1
- package/dist/plugins/eventEmission/transport.test.js +0 -164
- package/dist/plugins/fetch/index.test.d.ts +0 -2
- package/dist/plugins/fetch/index.test.d.ts.map +0 -1
- package/dist/plugins/fetch/index.test.js +0 -428
- package/dist/plugins/findFirstConnection/index.test.d.ts +0 -2
- package/dist/plugins/findFirstConnection/index.test.d.ts.map +0 -1
- package/dist/plugins/findFirstConnection/index.test.js +0 -177
- package/dist/plugins/findUniqueConnection/index.test.d.ts +0 -2
- package/dist/plugins/findUniqueConnection/index.test.d.ts.map +0 -1
- package/dist/plugins/findUniqueConnection/index.test.js +0 -159
- package/dist/plugins/getAction/index.test.d.ts +0 -2
- package/dist/plugins/getAction/index.test.d.ts.map +0 -1
- package/dist/plugins/getAction/index.test.js +0 -211
- package/dist/plugins/getApp/index.test.d.ts +0 -2
- package/dist/plugins/getApp/index.test.d.ts.map +0 -1
- package/dist/plugins/getApp/index.test.js +0 -157
- package/dist/plugins/getConnection/index.test.d.ts +0 -2
- package/dist/plugins/getConnection/index.test.d.ts.map +0 -1
- package/dist/plugins/getConnection/index.test.js +0 -124
- package/dist/plugins/getInputFieldsSchema/index.test.d.ts +0 -2
- package/dist/plugins/getInputFieldsSchema/index.test.d.ts.map +0 -1
- package/dist/plugins/getInputFieldsSchema/index.test.js +0 -291
- package/dist/plugins/listActions/index.test.d.ts +0 -2
- package/dist/plugins/listActions/index.test.d.ts.map +0 -1
- package/dist/plugins/listActions/index.test.js +0 -454
- package/dist/plugins/listApps/index.test.d.ts +0 -2
- package/dist/plugins/listApps/index.test.d.ts.map +0 -1
- package/dist/plugins/listApps/index.test.js +0 -124
- package/dist/plugins/listConnections/index.test.d.ts +0 -2
- package/dist/plugins/listConnections/index.test.d.ts.map +0 -1
- package/dist/plugins/listConnections/index.test.js +0 -920
- package/dist/plugins/listInputFieldChoices/index.test.d.ts +0 -2
- package/dist/plugins/listInputFieldChoices/index.test.d.ts.map +0 -1
- package/dist/plugins/listInputFieldChoices/index.test.js +0 -717
- package/dist/plugins/listInputFields/index.test.d.ts +0 -2
- package/dist/plugins/listInputFields/index.test.d.ts.map +0 -1
- package/dist/plugins/listInputFields/index.test.js +0 -359
- package/dist/plugins/manifest/index.test.d.ts +0 -2
- package/dist/plugins/manifest/index.test.d.ts.map +0 -1
- package/dist/plugins/manifest/index.test.js +0 -1179
- package/dist/plugins/request/index.test.d.ts +0 -2
- package/dist/plugins/request/index.test.d.ts.map +0 -1
- package/dist/plugins/request/index.test.js +0 -458
- package/dist/plugins/runAction/index.test.d.ts +0 -2
- package/dist/plugins/runAction/index.test.d.ts.map +0 -1
- package/dist/plugins/runAction/index.test.js +0 -350
- package/dist/resolvers/connectionId.test.d.ts +0 -2
- package/dist/resolvers/connectionId.test.d.ts.map +0 -1
- package/dist/resolvers/connectionId.test.js +0 -61
- package/dist/sdk.test.d.ts +0 -2
- package/dist/sdk.test.d.ts.map +0 -1
- package/dist/sdk.test.js +0 -260
- package/dist/types/domain.test.d.ts +0 -2
- package/dist/types/domain.test.d.ts.map +0 -1
- package/dist/types/domain.test.js +0 -39
- package/dist/utils/array-utils.test.d.ts +0 -2
- package/dist/utils/array-utils.test.d.ts.map +0 -1
- package/dist/utils/array-utils.test.js +0 -107
- package/dist/utils/batch-utils.test.d.ts +0 -2
- package/dist/utils/batch-utils.test.d.ts.map +0 -1
- package/dist/utils/batch-utils.test.js +0 -476
- package/dist/utils/domain-utils.test.d.ts +0 -2
- package/dist/utils/domain-utils.test.d.ts.map +0 -1
- package/dist/utils/domain-utils.test.js +0 -346
- package/dist/utils/file-utils.test.d.ts +0 -2
- package/dist/utils/file-utils.test.d.ts.map +0 -1
- package/dist/utils/file-utils.test.js +0 -51
- package/dist/utils/function-utils.test.d.ts +0 -2
- package/dist/utils/function-utils.test.d.ts.map +0 -1
- package/dist/utils/function-utils.test.js +0 -188
- package/dist/utils/id-utils.test.d.ts +0 -2
- package/dist/utils/id-utils.test.d.ts.map +0 -1
- package/dist/utils/id-utils.test.js +0 -22
- package/dist/utils/pagination-utils.test.d.ts +0 -17
- package/dist/utils/pagination-utils.test.d.ts.map +0 -1
- package/dist/utils/pagination-utils.test.js +0 -461
- package/dist/utils/retry-utils.test.d.ts +0 -2
- package/dist/utils/retry-utils.test.d.ts.map +0 -1
- package/dist/utils/retry-utils.test.js +0 -90
- package/dist/utils/string-utils.test.d.ts +0 -2
- package/dist/utils/string-utils.test.d.ts.map +0 -1
- package/dist/utils/string-utils.test.js +0 -59
- package/dist/utils/telemetry-context.test.d.ts +0 -2
- package/dist/utils/telemetry-context.test.d.ts.map +0 -1
- package/dist/utils/telemetry-context.test.js +0 -154
- package/dist/utils/telemetry-utils.test.d.ts +0 -2
- package/dist/utils/telemetry-utils.test.d.ts.map +0 -1
- package/dist/utils/telemetry-utils.test.js +0 -155
- package/dist/utils/url-utils.test.d.ts +0 -2
- package/dist/utils/url-utils.test.d.ts.map +0 -1
- package/dist/utils/url-utils.test.js +0 -103
- package/dist/utils/validation.test.d.ts +0 -2
- package/dist/utils/validation.test.d.ts.map +0 -1
- package/dist/utils/validation.test.js +0 -44
|
@@ -1,350 +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 { DEFAULT_ACTION_TIMEOUT_MS } from "../../constants";
|
|
6
|
-
const mockAction = {
|
|
7
|
-
type: "action",
|
|
8
|
-
key: "send_message",
|
|
9
|
-
title: "Send Message",
|
|
10
|
-
description: "Send a message to a channel",
|
|
11
|
-
app_key: "slack",
|
|
12
|
-
action_type: "write",
|
|
13
|
-
};
|
|
14
|
-
const mockActionResponse = {
|
|
15
|
-
results: [
|
|
16
|
-
{
|
|
17
|
-
id: "msg_123",
|
|
18
|
-
text: "Hello, world!",
|
|
19
|
-
channel: "#general",
|
|
20
|
-
user: "user_456",
|
|
21
|
-
},
|
|
22
|
-
],
|
|
23
|
-
meta: {
|
|
24
|
-
next_cursor: null,
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
describe("runAction plugin", () => {
|
|
28
|
-
let mockApiClient;
|
|
29
|
-
let mockGetAction;
|
|
30
|
-
let mockGetApp;
|
|
31
|
-
beforeEach(() => {
|
|
32
|
-
vi.clearAllMocks();
|
|
33
|
-
mockApiClient = {
|
|
34
|
-
post: vi.fn().mockResolvedValue({ data: { id: "run_123" } }),
|
|
35
|
-
poll: vi.fn().mockResolvedValue({ results: mockActionResponse.results }),
|
|
36
|
-
};
|
|
37
|
-
mockGetAction = vi.fn().mockResolvedValue({
|
|
38
|
-
data: mockAction,
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
function createTestSdk() {
|
|
42
|
-
return createSdk()
|
|
43
|
-
.addPlugin(() => ({
|
|
44
|
-
context: {
|
|
45
|
-
options: {},
|
|
46
|
-
},
|
|
47
|
-
}))
|
|
48
|
-
.addPlugin(() => ({
|
|
49
|
-
getAction: mockGetAction,
|
|
50
|
-
getApp: mockGetApp,
|
|
51
|
-
context: {
|
|
52
|
-
api: mockApiClient,
|
|
53
|
-
getVersionedImplementationId: () => "SlackCLIAPI@1.21.1",
|
|
54
|
-
eventEmission: {
|
|
55
|
-
emitMethodCalled: vi.fn(),
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
}))
|
|
59
|
-
.addPlugin(runActionPlugin);
|
|
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
|
-
});
|
|
70
|
-
}).toThrow(ZapierValidationError);
|
|
71
|
-
});
|
|
72
|
-
it("should throw validation error for missing actionType", () => {
|
|
73
|
-
const sdk = createTestSdk();
|
|
74
|
-
expect(() => {
|
|
75
|
-
sdk.runAction({
|
|
76
|
-
appKey: "slack",
|
|
77
|
-
actionKey: "send_message",
|
|
78
|
-
inputs: { message: "Hello" },
|
|
79
|
-
});
|
|
80
|
-
}).toThrow(ZapierValidationError);
|
|
81
|
-
});
|
|
82
|
-
it("should throw validation error for missing actionKey", () => {
|
|
83
|
-
const sdk = createTestSdk();
|
|
84
|
-
expect(() => {
|
|
85
|
-
sdk.runAction({
|
|
86
|
-
appKey: "slack",
|
|
87
|
-
actionType: "write",
|
|
88
|
-
inputs: { message: "Hello" },
|
|
89
|
-
});
|
|
90
|
-
}).toThrow(ZapierValidationError);
|
|
91
|
-
});
|
|
92
|
-
it("should pass validation with all required fields", async () => {
|
|
93
|
-
const sdk = createTestSdk();
|
|
94
|
-
const result = await sdk.runAction({
|
|
95
|
-
appKey: "slack",
|
|
96
|
-
actionType: "write",
|
|
97
|
-
actionKey: "send_message",
|
|
98
|
-
inputs: { message: "Hello" },
|
|
99
|
-
});
|
|
100
|
-
expect(result.data).toHaveLength(1);
|
|
101
|
-
expect(result.data[0]).toEqual(mockActionResponse.results[0]);
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
describe("action execution", () => {
|
|
105
|
-
it("should validate action exists using getAction", async () => {
|
|
106
|
-
const sdk = createTestSdk();
|
|
107
|
-
await sdk.runAction({
|
|
108
|
-
appKey: "slack",
|
|
109
|
-
actionType: "write",
|
|
110
|
-
actionKey: "send_message",
|
|
111
|
-
inputs: { message: "Hello" },
|
|
112
|
-
});
|
|
113
|
-
expect(mockGetAction).toHaveBeenCalledWith(expect.objectContaining({
|
|
114
|
-
appKey: "slack",
|
|
115
|
-
actionKey: "send_message",
|
|
116
|
-
actionType: "write",
|
|
117
|
-
}));
|
|
118
|
-
});
|
|
119
|
-
it("should throw error when action type doesn't match", async () => {
|
|
120
|
-
// Mock getAction to return an action with different type
|
|
121
|
-
mockGetAction.mockResolvedValue({
|
|
122
|
-
data: { ...mockAction, action_type: "read" },
|
|
123
|
-
});
|
|
124
|
-
const sdk = createTestSdk();
|
|
125
|
-
await expect(sdk.runAction({
|
|
126
|
-
appKey: "slack",
|
|
127
|
-
actionType: "write", // Different from mocked action type
|
|
128
|
-
actionKey: "send_message",
|
|
129
|
-
inputs: { message: "Hello" },
|
|
130
|
-
})).rejects.toThrow(ZapierValidationError);
|
|
131
|
-
});
|
|
132
|
-
it("should execute action with correct API call", async () => {
|
|
133
|
-
const sdk = createTestSdk();
|
|
134
|
-
await sdk.runAction({
|
|
135
|
-
appKey: "slack",
|
|
136
|
-
actionType: "write",
|
|
137
|
-
actionKey: "send_message",
|
|
138
|
-
inputs: { message: "Hello", channel: "#general" },
|
|
139
|
-
authenticationId: 12345,
|
|
140
|
-
});
|
|
141
|
-
expect(mockApiClient.post).toHaveBeenCalledWith("/zapier/api/actions/v1/runs", {
|
|
142
|
-
data: {
|
|
143
|
-
selected_api: "SlackCLIAPI@1.21.1",
|
|
144
|
-
action_key: "send_message",
|
|
145
|
-
action_type: "write",
|
|
146
|
-
inputs: { message: "Hello", channel: "#general" },
|
|
147
|
-
authentication_id: 12345,
|
|
148
|
-
},
|
|
149
|
-
});
|
|
150
|
-
expect(mockApiClient.poll).toHaveBeenCalledWith("/zapier/api/actions/v1/runs/run_123", {
|
|
151
|
-
successStatus: 200,
|
|
152
|
-
pendingStatus: 202,
|
|
153
|
-
timeoutMs: DEFAULT_ACTION_TIMEOUT_MS,
|
|
154
|
-
isPending: expect.any(Function),
|
|
155
|
-
resultExtractor: expect.any(Function),
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
it("should execute action without authentication ID", async () => {
|
|
159
|
-
const sdk = createTestSdk();
|
|
160
|
-
await sdk.runAction({
|
|
161
|
-
appKey: "slack",
|
|
162
|
-
actionType: "write",
|
|
163
|
-
actionKey: "send_message",
|
|
164
|
-
inputs: { message: "Hello" },
|
|
165
|
-
});
|
|
166
|
-
expect(mockApiClient.post).toHaveBeenCalledWith("/zapier/api/actions/v1/runs", {
|
|
167
|
-
data: {
|
|
168
|
-
selected_api: "SlackCLIAPI@1.21.1",
|
|
169
|
-
action_key: "send_message",
|
|
170
|
-
action_type: "write",
|
|
171
|
-
inputs: { message: "Hello" },
|
|
172
|
-
},
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
it("should pass custom timeoutMs to poll", async () => {
|
|
176
|
-
const customTimeout = 300000; // 5 minutes
|
|
177
|
-
const sdk = createTestSdk();
|
|
178
|
-
await sdk.runAction({
|
|
179
|
-
appKey: "slack",
|
|
180
|
-
actionType: "write",
|
|
181
|
-
actionKey: "send_message",
|
|
182
|
-
inputs: { message: "Hello" },
|
|
183
|
-
timeoutMs: customTimeout,
|
|
184
|
-
});
|
|
185
|
-
expect(mockApiClient.poll).toHaveBeenCalledWith("/zapier/api/actions/v1/runs/run_123", expect.objectContaining({
|
|
186
|
-
timeoutMs: customTimeout,
|
|
187
|
-
}));
|
|
188
|
-
});
|
|
189
|
-
it("should handle pagination cursor", async () => {
|
|
190
|
-
const sdk = createTestSdk();
|
|
191
|
-
const runActionResult = sdk.runAction({
|
|
192
|
-
appKey: "slack",
|
|
193
|
-
actionType: "write",
|
|
194
|
-
actionKey: "send_message",
|
|
195
|
-
inputs: { message: "Hello" },
|
|
196
|
-
});
|
|
197
|
-
// Simulate pagination by getting an iterator
|
|
198
|
-
const iterator = runActionResult[Symbol.asyncIterator]();
|
|
199
|
-
await iterator.next();
|
|
200
|
-
expect(mockApiClient.post).toHaveBeenCalledWith("/zapier/api/actions/v1/runs", expect.objectContaining({
|
|
201
|
-
data: expect.objectContaining({
|
|
202
|
-
inputs: { message: "Hello" },
|
|
203
|
-
selected_api: "SlackCLIAPI@1.21.1",
|
|
204
|
-
action_key: "send_message",
|
|
205
|
-
action_type: "write",
|
|
206
|
-
}),
|
|
207
|
-
}));
|
|
208
|
-
});
|
|
209
|
-
it("should return results in correct format", async () => {
|
|
210
|
-
const sdk = createTestSdk();
|
|
211
|
-
const result = await sdk.runAction({
|
|
212
|
-
appKey: "slack",
|
|
213
|
-
actionType: "write",
|
|
214
|
-
actionKey: "send_message",
|
|
215
|
-
inputs: { message: "Hello" },
|
|
216
|
-
});
|
|
217
|
-
expect(result.data).toEqual(mockActionResponse.results);
|
|
218
|
-
});
|
|
219
|
-
it("should handle single result (not array)", async () => {
|
|
220
|
-
const singleResult = { id: "msg_123", text: "Hello" };
|
|
221
|
-
mockApiClient.post = vi
|
|
222
|
-
.fn()
|
|
223
|
-
.mockResolvedValue({ data: { id: "run_123" } });
|
|
224
|
-
mockApiClient.poll = vi.fn().mockResolvedValue({
|
|
225
|
-
results: [singleResult], // Poll returns the actual results
|
|
226
|
-
});
|
|
227
|
-
const sdk = createTestSdk();
|
|
228
|
-
const result = await sdk.runAction({
|
|
229
|
-
appKey: "slack",
|
|
230
|
-
actionType: "write",
|
|
231
|
-
actionKey: "send_message",
|
|
232
|
-
inputs: { message: "Hello" },
|
|
233
|
-
});
|
|
234
|
-
expect(result.data).toEqual([singleResult]); // Should be wrapped in array
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
describe("error handling", () => {
|
|
238
|
-
it("should handle action execution errors", async () => {
|
|
239
|
-
mockApiClient.post = vi
|
|
240
|
-
.fn()
|
|
241
|
-
.mockResolvedValue({ data: { id: "run_123" } });
|
|
242
|
-
mockApiClient.poll = vi.fn().mockResolvedValue({
|
|
243
|
-
results: [],
|
|
244
|
-
errors: [
|
|
245
|
-
{ title: "Invalid inputs", detail: "Message cannot be empty" },
|
|
246
|
-
],
|
|
247
|
-
});
|
|
248
|
-
const sdk = createTestSdk();
|
|
249
|
-
await expect(sdk.runAction({
|
|
250
|
-
appKey: "slack",
|
|
251
|
-
actionType: "write",
|
|
252
|
-
actionKey: "send_message",
|
|
253
|
-
inputs: { message: "" }, // Invalid input
|
|
254
|
-
})).rejects.toThrow(ZapierActionError);
|
|
255
|
-
});
|
|
256
|
-
it("should handle server errors", async () => {
|
|
257
|
-
mockApiClient.post = vi.fn().mockImplementation((_url, options) => {
|
|
258
|
-
const error = options.customErrorHandler?.({
|
|
259
|
-
status: 500,
|
|
260
|
-
data: { message: "Internal server error" },
|
|
261
|
-
});
|
|
262
|
-
if (error)
|
|
263
|
-
throw error;
|
|
264
|
-
throw new Error("Server Error");
|
|
265
|
-
});
|
|
266
|
-
const sdk = createTestSdk();
|
|
267
|
-
await expect(sdk.runAction({
|
|
268
|
-
appKey: "slack",
|
|
269
|
-
actionType: "write",
|
|
270
|
-
actionKey: "send_message",
|
|
271
|
-
inputs: { message: "Hello" },
|
|
272
|
-
})).rejects.toThrow();
|
|
273
|
-
});
|
|
274
|
-
it("should propagate getAction errors", async () => {
|
|
275
|
-
mockGetAction.mockRejectedValue(new Error("Action not found"));
|
|
276
|
-
const sdk = createTestSdk();
|
|
277
|
-
await expect(sdk.runAction({
|
|
278
|
-
appKey: "slack",
|
|
279
|
-
actionType: "write",
|
|
280
|
-
actionKey: "nonexistent",
|
|
281
|
-
inputs: { message: "Hello" },
|
|
282
|
-
})).rejects.toThrow("Action not found");
|
|
283
|
-
});
|
|
284
|
-
it("should handle unexpected errors during execution", async () => {
|
|
285
|
-
mockApiClient.post = vi
|
|
286
|
-
.fn()
|
|
287
|
-
.mockRejectedValue(new Error("Network error"));
|
|
288
|
-
const sdk = createTestSdk();
|
|
289
|
-
await expect(sdk.runAction({
|
|
290
|
-
appKey: "slack",
|
|
291
|
-
actionType: "write",
|
|
292
|
-
actionKey: "send_message",
|
|
293
|
-
inputs: { message: "Hello" },
|
|
294
|
-
})).rejects.toThrow("Network error");
|
|
295
|
-
});
|
|
296
|
-
});
|
|
297
|
-
describe("pagination", () => {
|
|
298
|
-
it("should support maxItems limit", async () => {
|
|
299
|
-
const sdk = createTestSdk();
|
|
300
|
-
const result = await sdk.runAction({
|
|
301
|
-
appKey: "slack",
|
|
302
|
-
actionType: "write",
|
|
303
|
-
actionKey: "send_message",
|
|
304
|
-
inputs: { message: "Hello" },
|
|
305
|
-
maxItems: 1,
|
|
306
|
-
});
|
|
307
|
-
expect(result.data).toHaveLength(1);
|
|
308
|
-
});
|
|
309
|
-
it("should support async iteration over pages", async () => {
|
|
310
|
-
const sdk = createTestSdk();
|
|
311
|
-
const runActionResult = sdk.runAction({
|
|
312
|
-
appKey: "slack",
|
|
313
|
-
actionType: "write",
|
|
314
|
-
actionKey: "send_message",
|
|
315
|
-
inputs: { message: "Hello" },
|
|
316
|
-
});
|
|
317
|
-
const pages = [];
|
|
318
|
-
for await (const page of runActionResult) {
|
|
319
|
-
pages.push(page);
|
|
320
|
-
break; // Just get first page for testing
|
|
321
|
-
}
|
|
322
|
-
expect(pages).toHaveLength(1);
|
|
323
|
-
expect(pages[0].data).toEqual(mockActionResponse.results);
|
|
324
|
-
});
|
|
325
|
-
it("should support async iteration over individual items", async () => {
|
|
326
|
-
const sdk = createTestSdk();
|
|
327
|
-
const runActionResult = sdk.runAction({
|
|
328
|
-
appKey: "slack",
|
|
329
|
-
actionType: "write",
|
|
330
|
-
actionKey: "send_message",
|
|
331
|
-
inputs: { message: "Hello" },
|
|
332
|
-
maxItems: 1,
|
|
333
|
-
});
|
|
334
|
-
const items = [];
|
|
335
|
-
for await (const item of runActionResult.items()) {
|
|
336
|
-
items.push(item);
|
|
337
|
-
}
|
|
338
|
-
expect(items).toHaveLength(1);
|
|
339
|
-
expect(items[0]).toEqual(mockActionResponse.results[0]);
|
|
340
|
-
});
|
|
341
|
-
});
|
|
342
|
-
describe("context and metadata", () => {
|
|
343
|
-
it("should provide context with meta information", () => {
|
|
344
|
-
const sdk = createTestSdk();
|
|
345
|
-
const context = sdk.getContext();
|
|
346
|
-
expect(context.meta.runAction).toBeDefined();
|
|
347
|
-
expect(context.meta.runAction.inputSchema).toBeDefined();
|
|
348
|
-
});
|
|
349
|
-
});
|
|
350
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"connectionId.test.d.ts","sourceRoot":"","sources":["../../src/resolvers/connectionId.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeAll } from "vitest";
|
|
2
|
-
import { connectionIdResolver } from "./connectionId";
|
|
3
|
-
describe("connectionIdResolver.tryResolveWithoutPrompt", () => {
|
|
4
|
-
let tryResolveWithoutPrompt;
|
|
5
|
-
beforeAll(() => {
|
|
6
|
-
if (!connectionIdResolver.tryResolveWithoutPrompt) {
|
|
7
|
-
throw new Error("connectionIdResolver.tryResolveWithoutPrompt is not defined");
|
|
8
|
-
}
|
|
9
|
-
tryResolveWithoutPrompt = connectionIdResolver.tryResolveWithoutPrompt;
|
|
10
|
-
});
|
|
11
|
-
it("returns null when no appKey is provided, deferring to the normal prompt", async () => {
|
|
12
|
-
const result = await tryResolveWithoutPrompt({}, {});
|
|
13
|
-
expect(result).toBeNull();
|
|
14
|
-
});
|
|
15
|
-
it("returns { resolvedValue: null } when the app has no auth_type, skipping the connection prompt", async () => {
|
|
16
|
-
const mockSdk = {
|
|
17
|
-
getApp: vi.fn().mockResolvedValue({ data: { auth_type: null } }),
|
|
18
|
-
};
|
|
19
|
-
const result = await tryResolveWithoutPrompt(mockSdk, {
|
|
20
|
-
appKey: "web-search-by-zapier",
|
|
21
|
-
});
|
|
22
|
-
expect(mockSdk.getApp).toHaveBeenCalledWith({
|
|
23
|
-
appKey: "web-search-by-zapier",
|
|
24
|
-
});
|
|
25
|
-
expect(result).toEqual({ resolvedValue: null });
|
|
26
|
-
});
|
|
27
|
-
it("returns { resolvedValue: null } when auth_type is absent from the app data", async () => {
|
|
28
|
-
const mockSdk = {
|
|
29
|
-
getApp: vi.fn().mockResolvedValue({ data: {} }),
|
|
30
|
-
};
|
|
31
|
-
const result = await tryResolveWithoutPrompt(mockSdk, {
|
|
32
|
-
appKey: "web-search-by-zapier",
|
|
33
|
-
});
|
|
34
|
-
expect(result).toEqual({ resolvedValue: null });
|
|
35
|
-
});
|
|
36
|
-
it("returns { resolvedValue: null } when auth_type is an empty string", async () => {
|
|
37
|
-
const mockSdk = {
|
|
38
|
-
getApp: vi.fn().mockResolvedValue({ data: { auth_type: "" } }),
|
|
39
|
-
};
|
|
40
|
-
const result = await tryResolveWithoutPrompt(mockSdk, {
|
|
41
|
-
appKey: "formatter",
|
|
42
|
-
});
|
|
43
|
-
expect(result).toEqual({ resolvedValue: null });
|
|
44
|
-
});
|
|
45
|
-
it("returns null for an app with auth_type set, allowing the connection picker to appear", async () => {
|
|
46
|
-
const mockSdk = {
|
|
47
|
-
getApp: vi.fn().mockResolvedValue({ data: { auth_type: "oauth" } }),
|
|
48
|
-
};
|
|
49
|
-
const result = await tryResolveWithoutPrompt(mockSdk, { appKey: "slack" });
|
|
50
|
-
expect(result).toBeNull();
|
|
51
|
-
});
|
|
52
|
-
it("returns null when getApp throws, falling back gracefully to the normal connection prompt", async () => {
|
|
53
|
-
const mockSdk = {
|
|
54
|
-
getApp: vi.fn().mockRejectedValue(new Error("App not found")),
|
|
55
|
-
};
|
|
56
|
-
const result = await tryResolveWithoutPrompt(mockSdk, {
|
|
57
|
-
appKey: "unknown-app",
|
|
58
|
-
});
|
|
59
|
-
expect(result).toBeNull();
|
|
60
|
-
});
|
|
61
|
-
});
|
package/dist/sdk.test.d.ts
DELETED
package/dist/sdk.test.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sdk.test.d.ts","sourceRoot":"","sources":["../src/sdk.test.ts"],"names":[],"mappings":""}
|
package/dist/sdk.test.js
DELETED
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
// Test the flat plugin system
|
|
2
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
3
|
-
import { createZapierSdk, createSdk } from "./sdk";
|
|
4
|
-
describe("Flat Plugin System", () => {
|
|
5
|
-
it("should create SDK with all expected methods", () => {
|
|
6
|
-
const sdk = createZapierSdk();
|
|
7
|
-
// Test that methods are available (one from each category)
|
|
8
|
-
expect(sdk.listApps).toBeDefined(); // app
|
|
9
|
-
expect(sdk.runAction).toBeDefined(); // action
|
|
10
|
-
expect(sdk.listConnections).toBeDefined(); // connection
|
|
11
|
-
expect(sdk.fetch).toBeDefined(); // http
|
|
12
|
-
expect(sdk.listClientCredentials).toBeDefined(); // client-credentials
|
|
13
|
-
expect(sdk.getProfile).toBeDefined(); // account
|
|
14
|
-
expect(sdk.apps).toBeDefined(); // apps proxy
|
|
15
|
-
// Deprecated methods (kept for backward compatibility)
|
|
16
|
-
expect(sdk.listAuthentications).toBeDefined();
|
|
17
|
-
expect(sdk.request).toBeDefined();
|
|
18
|
-
// Test that getContext method is available
|
|
19
|
-
expect(sdk.getContext).toBeDefined();
|
|
20
|
-
expect(typeof sdk.getContext).toBe("function");
|
|
21
|
-
});
|
|
22
|
-
it("should have getContext method that returns context", () => {
|
|
23
|
-
const sdk = createZapierSdk();
|
|
24
|
-
const context = sdk.getContext(); // Type assertion to work around complex context inference
|
|
25
|
-
// Context should be an object
|
|
26
|
-
expect(typeof context).toBe("object");
|
|
27
|
-
expect(context).not.toBeNull();
|
|
28
|
-
// Context should have some properties (specific properties depend on plugin composition)
|
|
29
|
-
expect(Object.keys(context).length).toBeGreaterThan(0);
|
|
30
|
-
// Should have meta object
|
|
31
|
-
expect(context.meta).toBeDefined();
|
|
32
|
-
expect(typeof context.meta).toBe("object");
|
|
33
|
-
// Should have getProfile metadata from the plugin (verify it exists in meta)
|
|
34
|
-
expect("getProfile" in context.meta).toBe(true);
|
|
35
|
-
expect(context.meta.getProfile).toBeDefined();
|
|
36
|
-
expect(context.meta.getProfile.inputSchema).toBeDefined();
|
|
37
|
-
});
|
|
38
|
-
it("should have plugins return flat structure", () => {
|
|
39
|
-
const sdk = createZapierSdk();
|
|
40
|
-
// fetch should be directly available (not sdk.plugins.fetch or sdk.fetch.fetch)
|
|
41
|
-
expect(typeof sdk.fetch).toBe("function");
|
|
42
|
-
// apps should be directly available
|
|
43
|
-
expect(typeof sdk.apps).toBe("object");
|
|
44
|
-
// getProfile should be directly available
|
|
45
|
-
expect(typeof sdk.getProfile).toBe("function");
|
|
46
|
-
});
|
|
47
|
-
it("should support fluent plugin chaining with createSdk", () => {
|
|
48
|
-
// Test that createSdk().addPlugin().addPlugin() works and returns properly typed SDK
|
|
49
|
-
const testPlugin = () => ({
|
|
50
|
-
testMethod: () => "test result",
|
|
51
|
-
});
|
|
52
|
-
const sdk = createSdk().addPlugin(testPlugin);
|
|
53
|
-
// Should have getContext method
|
|
54
|
-
expect(typeof sdk.getContext).toBe("function");
|
|
55
|
-
// Should have addPlugin method for further chaining
|
|
56
|
-
expect(typeof sdk.addPlugin).toBe("function");
|
|
57
|
-
// Should have the plugin method
|
|
58
|
-
expect(typeof sdk.testMethod).toBe("function");
|
|
59
|
-
expect(sdk.testMethod()).toBe("test result");
|
|
60
|
-
});
|
|
61
|
-
it("should support fluent plugin chaining without .getSdk()", () => {
|
|
62
|
-
// This demonstrates the simplified API - no .getSdk() needed!
|
|
63
|
-
const plugin1 = () => ({ method1: () => "method1" });
|
|
64
|
-
const plugin2 = () => ({ method2: () => "method2" });
|
|
65
|
-
// Fluent chaining - each addPlugin returns a new SDK
|
|
66
|
-
const sdk = createSdk().addPlugin(plugin1).addPlugin(plugin2);
|
|
67
|
-
expect(sdk.method1()).toBe("method1");
|
|
68
|
-
expect(sdk.method2()).toBe("method2");
|
|
69
|
-
expect(typeof sdk.getContext).toBe("function");
|
|
70
|
-
expect(typeof sdk.addPlugin).toBe("function"); // Can still add more plugins!
|
|
71
|
-
});
|
|
72
|
-
it("should support plugins with options", () => {
|
|
73
|
-
// Test that addPlugin(pluginFn, options) works correctly
|
|
74
|
-
const pluginWithOptions = (params) => ({
|
|
75
|
-
getMessage: () => params.message,
|
|
76
|
-
});
|
|
77
|
-
const sdk = createSdk().addPlugin(pluginWithOptions, {
|
|
78
|
-
message: "Hello from options!",
|
|
79
|
-
});
|
|
80
|
-
expect(typeof sdk.getMessage).toBe("function");
|
|
81
|
-
expect(sdk.getMessage()).toBe("Hello from options!");
|
|
82
|
-
});
|
|
83
|
-
it("should merge context.meta from multiple plugins", () => {
|
|
84
|
-
// Test that multiple plugins can provide meta without overwriting each other
|
|
85
|
-
const plugin1 = () => ({
|
|
86
|
-
method1: () => "method1",
|
|
87
|
-
context: {
|
|
88
|
-
meta: {
|
|
89
|
-
plugin1: { info: "Plugin 1 metadata" },
|
|
90
|
-
},
|
|
91
|
-
},
|
|
92
|
-
});
|
|
93
|
-
const plugin2 = () => ({
|
|
94
|
-
method2: () => "method2",
|
|
95
|
-
context: {
|
|
96
|
-
meta: {
|
|
97
|
-
plugin2: { info: "Plugin 2 metadata" },
|
|
98
|
-
},
|
|
99
|
-
},
|
|
100
|
-
});
|
|
101
|
-
const sdk = createSdk().addPlugin(plugin1).addPlugin(plugin2);
|
|
102
|
-
const context = sdk.getContext();
|
|
103
|
-
// Both plugins should have their meta preserved
|
|
104
|
-
expect(context.meta.plugin1.info).toBe("Plugin 1 metadata");
|
|
105
|
-
expect(context.meta.plugin2.info).toBe("Plugin 2 metadata");
|
|
106
|
-
// Both methods should work
|
|
107
|
-
expect(sdk.method1()).toBe("method1");
|
|
108
|
-
expect(sdk.method2()).toBe("method2");
|
|
109
|
-
});
|
|
110
|
-
it("should support context requirements for cleaner plugin definitions", () => {
|
|
111
|
-
// Test context requirements work correctly
|
|
112
|
-
const pluginWithHelper = ({ sdk, context }) => ({
|
|
113
|
-
helperMethod: () => `Helper: ${sdk.existingMethod()} + ${context.customContext}`,
|
|
114
|
-
});
|
|
115
|
-
const baseSdk = { existingMethod: () => "base" };
|
|
116
|
-
const baseContext = { customContext: "custom", meta: {} };
|
|
117
|
-
const sdk = createSdk({}, baseSdk, baseContext).addPlugin(pluginWithHelper);
|
|
118
|
-
expect(sdk.helperMethod()).toBe("Helper: base + custom");
|
|
119
|
-
expect(sdk.existingMethod()).toBe("base"); // Original method still works
|
|
120
|
-
});
|
|
121
|
-
it("should ensure context.meta is always available", () => {
|
|
122
|
-
// Test that context.meta is always at least an empty object, even without explicit initialization
|
|
123
|
-
const plugin = ({ context }) => ({
|
|
124
|
-
testMethod: () => `Meta keys: ${Object.keys(context.meta).length}`,
|
|
125
|
-
});
|
|
126
|
-
// Create SDK without explicitly providing meta
|
|
127
|
-
const sdk = createSdk({}).addPlugin(plugin);
|
|
128
|
-
// Should work without error - meta should be at least an empty object
|
|
129
|
-
expect(sdk.testMethod()).toBe("Meta keys: 0");
|
|
130
|
-
// getContext() should also provide meta
|
|
131
|
-
const context = sdk.getContext();
|
|
132
|
-
expect(context.meta).toBeDefined();
|
|
133
|
-
expect(typeof context.meta).toBe("object");
|
|
134
|
-
expect(context.meta).not.toBeNull();
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
describe("Environment Variable Support", () => {
|
|
138
|
-
let originalEnv;
|
|
139
|
-
beforeEach(() => {
|
|
140
|
-
// Save original environment variable
|
|
141
|
-
originalEnv = process.env.ZAPIER_BASE_URL;
|
|
142
|
-
});
|
|
143
|
-
afterEach(() => {
|
|
144
|
-
// Restore original environment variable
|
|
145
|
-
if (originalEnv !== undefined) {
|
|
146
|
-
process.env.ZAPIER_BASE_URL = originalEnv;
|
|
147
|
-
}
|
|
148
|
-
else {
|
|
149
|
-
delete process.env.ZAPIER_BASE_URL;
|
|
150
|
-
}
|
|
151
|
-
// Clear module cache to ensure constants are re-evaluated
|
|
152
|
-
vi.resetModules();
|
|
153
|
-
});
|
|
154
|
-
it("should use custom base URL from ZAPIER_BASE_URL environment variable", async () => {
|
|
155
|
-
// Set custom base URL via environment variable
|
|
156
|
-
const customBaseUrl = "https://custom-zapier.example.com";
|
|
157
|
-
process.env.ZAPIER_BASE_URL = customBaseUrl;
|
|
158
|
-
// Clear module cache and re-import to get fresh constants
|
|
159
|
-
vi.resetModules();
|
|
160
|
-
const { createZapierSdk } = await import("./sdk");
|
|
161
|
-
// Create mock fetch function to capture requests
|
|
162
|
-
const mockFetch = vi.fn().mockResolvedValue({
|
|
163
|
-
ok: true,
|
|
164
|
-
status: 200,
|
|
165
|
-
text: async () => JSON.stringify({
|
|
166
|
-
data: [],
|
|
167
|
-
links: { next: null },
|
|
168
|
-
meta: { count: 0, limit: 100, offset: 0 },
|
|
169
|
-
}),
|
|
170
|
-
headers: new Headers(),
|
|
171
|
-
});
|
|
172
|
-
// Create SDK instance with mock fetch
|
|
173
|
-
const sdk = createZapierSdk({
|
|
174
|
-
token: "test-token",
|
|
175
|
-
fetch: mockFetch,
|
|
176
|
-
});
|
|
177
|
-
// Make an API call that should use the custom base URL
|
|
178
|
-
await sdk.listApps();
|
|
179
|
-
// Verify that the request was made to the custom base URL
|
|
180
|
-
expect(mockFetch).toHaveBeenCalledTimes(1);
|
|
181
|
-
const [actualUrl] = mockFetch.mock.calls[0];
|
|
182
|
-
expect(actualUrl).toMatch(new RegExp(`^${customBaseUrl}`));
|
|
183
|
-
expect(actualUrl).toContain("/api/v0/");
|
|
184
|
-
});
|
|
185
|
-
it("should use default base URL when ZAPIER_BASE_URL is not set", async () => {
|
|
186
|
-
// Ensure environment variable is not set
|
|
187
|
-
delete process.env.ZAPIER_BASE_URL;
|
|
188
|
-
// Clear module cache and re-import to get fresh constants
|
|
189
|
-
vi.resetModules();
|
|
190
|
-
const { createZapierSdk } = await import("./sdk");
|
|
191
|
-
// Create mock fetch function to capture requests
|
|
192
|
-
const mockFetch = vi.fn().mockResolvedValue({
|
|
193
|
-
ok: true,
|
|
194
|
-
status: 200,
|
|
195
|
-
text: async () => JSON.stringify({
|
|
196
|
-
data: [],
|
|
197
|
-
links: { next: null },
|
|
198
|
-
meta: { count: 0, limit: 100, offset: 0 },
|
|
199
|
-
}),
|
|
200
|
-
headers: new Headers(),
|
|
201
|
-
});
|
|
202
|
-
// Create SDK instance with mock fetch
|
|
203
|
-
const sdk = createZapierSdk({
|
|
204
|
-
token: "test-token",
|
|
205
|
-
fetch: mockFetch,
|
|
206
|
-
});
|
|
207
|
-
// Make an API call that should use the default base URL
|
|
208
|
-
await sdk.listApps();
|
|
209
|
-
// Verify that the request was made to the default base URL
|
|
210
|
-
expect(mockFetch).toHaveBeenCalledTimes(1);
|
|
211
|
-
const [actualUrl] = mockFetch.mock.calls[0];
|
|
212
|
-
expect(actualUrl).toMatch(/^https:\/\/sdkapi\.zapier\.com/);
|
|
213
|
-
expect(actualUrl).toContain("/api/v0/");
|
|
214
|
-
});
|
|
215
|
-
it("should use explicit baseUrl option for SDK API requests", async () => {
|
|
216
|
-
// Clear environment variable to ensure we're testing the explicit option
|
|
217
|
-
delete process.env.ZAPIER_BASE_URL;
|
|
218
|
-
// Clear module cache and re-import to get fresh constants
|
|
219
|
-
vi.resetModules();
|
|
220
|
-
const { createZapierSdk } = await import("./sdk");
|
|
221
|
-
const customBaseUrl = "https://staging.zapier.com";
|
|
222
|
-
// Create mock fetch function to capture requests
|
|
223
|
-
const mockFetch = vi.fn().mockResolvedValue({
|
|
224
|
-
ok: true,
|
|
225
|
-
status: 200,
|
|
226
|
-
text: async () => JSON.stringify({
|
|
227
|
-
data: [],
|
|
228
|
-
links: { next: null },
|
|
229
|
-
meta: { count: 0, limit: 100, offset: 0 },
|
|
230
|
-
}),
|
|
231
|
-
headers: new Headers(),
|
|
232
|
-
});
|
|
233
|
-
// Create SDK instance with explicit baseUrl option and mock fetch
|
|
234
|
-
const sdk = createZapierSdk({
|
|
235
|
-
baseUrl: customBaseUrl,
|
|
236
|
-
token: "test-token",
|
|
237
|
-
fetch: mockFetch,
|
|
238
|
-
});
|
|
239
|
-
// Make an API call that should use the custom base URL
|
|
240
|
-
await sdk.listApps();
|
|
241
|
-
// Verify that the request was made to the custom base URL
|
|
242
|
-
expect(mockFetch).toHaveBeenCalledTimes(1);
|
|
243
|
-
const [actualUrl] = mockFetch.mock.calls[0];
|
|
244
|
-
expect(actualUrl).toMatch(new RegExp(`^${customBaseUrl}`));
|
|
245
|
-
expect(actualUrl).toContain("/api/v0/");
|
|
246
|
-
});
|
|
247
|
-
it("should accept credentials with clientId in SDK options", async () => {
|
|
248
|
-
delete process.env.ZAPIER_BASE_URL;
|
|
249
|
-
vi.resetModules();
|
|
250
|
-
const { createZapierSdk } = await import("./sdk");
|
|
251
|
-
const sdk = createZapierSdk({
|
|
252
|
-
credentials: {
|
|
253
|
-
clientId: "test-client-id",
|
|
254
|
-
},
|
|
255
|
-
});
|
|
256
|
-
// Verify SDK was created successfully with credentials option
|
|
257
|
-
expect(sdk).toBeDefined();
|
|
258
|
-
expect(sdk.listApps).toBeDefined();
|
|
259
|
-
});
|
|
260
|
-
});
|