@zapier/zapier-sdk-cli 0.16.1 → 0.16.3
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 +18 -0
- package/dist/cli.cjs +7 -7
- package/dist/cli.mjs +7 -7
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/package.json +8 -2
- package/dist/src/cli.js +2 -1
- package/dist/src/utils/cli-generator.js +8 -7
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +11 -5
- package/src/cli.test.ts +0 -28
- package/src/cli.ts +0 -96
- package/src/generators/ast-generator.test.ts +0 -908
- package/src/generators/ast-generator.ts +0 -774
- package/src/index.ts +0 -12
- package/src/plugins/add/index.test.ts +0 -58
- package/src/plugins/add/index.ts +0 -177
- package/src/plugins/add/schemas.ts +0 -35
- package/src/plugins/buildManifest/index.test.ts +0 -679
- package/src/plugins/buildManifest/index.ts +0 -131
- package/src/plugins/buildManifest/schemas.ts +0 -55
- package/src/plugins/bundleCode/index.ts +0 -128
- package/src/plugins/bundleCode/schemas.ts +0 -24
- package/src/plugins/generateAppTypes/index.test.ts +0 -679
- package/src/plugins/generateAppTypes/index.ts +0 -227
- package/src/plugins/generateAppTypes/schemas.ts +0 -61
- package/src/plugins/getLoginConfigPath/index.ts +0 -45
- package/src/plugins/getLoginConfigPath/schemas.ts +0 -10
- package/src/plugins/index.ts +0 -8
- package/src/plugins/login/index.ts +0 -135
- package/src/plugins/login/schemas.ts +0 -13
- package/src/plugins/logout/index.ts +0 -37
- package/src/plugins/logout/schemas.ts +0 -8
- package/src/plugins/mcp/index.ts +0 -43
- package/src/plugins/mcp/schemas.ts +0 -13
- package/src/sdk.ts +0 -45
- package/src/telemetry/builders.ts +0 -113
- package/src/telemetry/events.ts +0 -39
- package/src/types/sdk.ts +0 -8
- package/src/utils/api/client.ts +0 -44
- package/src/utils/auth/login.ts +0 -214
- package/src/utils/cli-generator-utils.ts +0 -169
- package/src/utils/cli-generator.test.ts +0 -347
- package/src/utils/cli-generator.ts +0 -807
- package/src/utils/constants.ts +0 -9
- package/src/utils/directory-detection.ts +0 -23
- package/src/utils/errors.ts +0 -26
- package/src/utils/getCallablePromise.ts +0 -21
- package/src/utils/log.ts +0 -23
- package/src/utils/manifest-helpers.ts +0 -25
- package/src/utils/package-manager-detector.ts +0 -83
- package/src/utils/parameter-resolver.ts +0 -1075
- package/src/utils/schema-formatter.ts +0 -153
- package/src/utils/serializeAsync.ts +0 -26
- package/src/utils/spinner.ts +0 -23
- package/src/utils/version-checker.test.ts +0 -239
- package/src/utils/version-checker.ts +0 -237
- package/tsconfig.build.json +0 -18
- package/tsconfig.json +0 -19
- package/tsup.config.ts +0 -23
|
@@ -1,347 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import chalk from "chalk";
|
|
3
|
-
import { generateCliCommands } from "./cli-generator";
|
|
4
|
-
import { Command } from "commander";
|
|
5
|
-
import type { ZapierSdk } from "@zapier/zapier-sdk";
|
|
6
|
-
import { z } from "zod";
|
|
7
|
-
|
|
8
|
-
// We need to create a test for the formatItemsGeneric function that's defined in cli-generator.ts
|
|
9
|
-
// Since it's not exported, we'll create a simple test that verifies the numbering logic
|
|
10
|
-
|
|
11
|
-
interface TestItem {
|
|
12
|
-
name?: string;
|
|
13
|
-
key?: string;
|
|
14
|
-
id?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
describe("CLI Generator Pagination Numbering", () => {
|
|
18
|
-
let mockConsoleLog: ReturnType<typeof vi.spyOn>;
|
|
19
|
-
|
|
20
|
-
beforeEach(() => {
|
|
21
|
-
mockConsoleLog = vi.spyOn(console, "log").mockImplementation(() => {});
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
afterEach(() => {
|
|
25
|
-
mockConsoleLog.mockRestore();
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
// Since formatItemsGeneric is not exported, let's create a regression test
|
|
29
|
-
// that tests the key functionality we care about: continuous numbering
|
|
30
|
-
it("should prevent pagination numbering regression by testing chalk formatting", () => {
|
|
31
|
-
// Simulate what formatItemsGeneric does for pagination numbering
|
|
32
|
-
const simulateFormatting = (items: TestItem[], startingNumber: number) => {
|
|
33
|
-
const calls: string[] = [];
|
|
34
|
-
items.forEach((item, index) => {
|
|
35
|
-
const name = item.name || item.key || item.id || "Item";
|
|
36
|
-
const formatted = `${chalk.gray(`${startingNumber + index + 1}.`)} ${chalk.cyan(String(name))}`;
|
|
37
|
-
calls.push(formatted);
|
|
38
|
-
});
|
|
39
|
-
return calls;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
// Test first page (items 1-3)
|
|
43
|
-
const page1Items = [
|
|
44
|
-
{ name: "App 1", key: "app1" },
|
|
45
|
-
{ name: "App 2", key: "app2" },
|
|
46
|
-
{ name: "App 3", key: "app3" },
|
|
47
|
-
];
|
|
48
|
-
|
|
49
|
-
const page2Items = [
|
|
50
|
-
{ name: "App 4", key: "app4" },
|
|
51
|
-
{ name: "App 5", key: "app5" },
|
|
52
|
-
];
|
|
53
|
-
|
|
54
|
-
// Format first page starting from 0
|
|
55
|
-
const page1Output = simulateFormatting(page1Items, 0);
|
|
56
|
-
|
|
57
|
-
// Format second page starting from 3 (3 items shown already)
|
|
58
|
-
const page2Output = simulateFormatting(page2Items, 3);
|
|
59
|
-
|
|
60
|
-
// Check that page 1 contains 1., 2., 3.
|
|
61
|
-
expect(page1Output.some((line) => line.includes("1."))).toBe(true);
|
|
62
|
-
expect(page1Output.some((line) => line.includes("2."))).toBe(true);
|
|
63
|
-
expect(page1Output.some((line) => line.includes("3."))).toBe(true);
|
|
64
|
-
|
|
65
|
-
// Check that page 2 contains 4., 5. (continuing from page 1)
|
|
66
|
-
expect(page2Output.some((line) => line.includes("4."))).toBe(true);
|
|
67
|
-
expect(page2Output.some((line) => line.includes("5."))).toBe(true);
|
|
68
|
-
|
|
69
|
-
// Most importantly: page 2 should NOT restart at 1.
|
|
70
|
-
expect(page2Output.some((line) => line.includes("1."))).toBe(false);
|
|
71
|
-
expect(page2Output.some((line) => line.includes("2."))).toBe(false);
|
|
72
|
-
expect(page2Output.some((line) => line.includes("3."))).toBe(false);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it("should handle edge case of starting number 0", () => {
|
|
76
|
-
const simulateFormatting = (
|
|
77
|
-
items: TestItem[],
|
|
78
|
-
startingNumber: number = 0,
|
|
79
|
-
) => {
|
|
80
|
-
const calls: string[] = [];
|
|
81
|
-
items.forEach((item, index) => {
|
|
82
|
-
const name = item.name || item.key || item.id || "Item";
|
|
83
|
-
const formatted = `${chalk.gray(`${startingNumber + index + 1}.`)} ${chalk.cyan(String(name))}`;
|
|
84
|
-
calls.push(formatted);
|
|
85
|
-
});
|
|
86
|
-
return calls;
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
const items = [{ name: "First Item" }, { name: "Second Item" }];
|
|
90
|
-
|
|
91
|
-
// Default startingNumber should be 0, resulting in 1. and 2.
|
|
92
|
-
const output = simulateFormatting(items, 0);
|
|
93
|
-
|
|
94
|
-
expect(output.some((line) => line.includes("1."))).toBe(true);
|
|
95
|
-
expect(output.some((line) => line.includes("2."))).toBe(true);
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
// Create proper Zod schema for testing
|
|
100
|
-
const testSchema = z
|
|
101
|
-
.object({
|
|
102
|
-
maxItems: z.number().optional(),
|
|
103
|
-
pageSize: z.number().optional(),
|
|
104
|
-
})
|
|
105
|
-
.describe("List all apps");
|
|
106
|
-
|
|
107
|
-
// Mock SDK for CLI tests
|
|
108
|
-
const mockSdk = {
|
|
109
|
-
getRegistry: vi.fn(() => ({
|
|
110
|
-
functions: [
|
|
111
|
-
{
|
|
112
|
-
name: "listApps",
|
|
113
|
-
type: "list",
|
|
114
|
-
inputSchema: testSchema,
|
|
115
|
-
},
|
|
116
|
-
],
|
|
117
|
-
categories: [],
|
|
118
|
-
})),
|
|
119
|
-
listApps: vi.fn().mockResolvedValue({ data: [] }),
|
|
120
|
-
} as unknown as ZapierSdk;
|
|
121
|
-
|
|
122
|
-
// Schema for request command testing
|
|
123
|
-
const requestSchema = z
|
|
124
|
-
.object({
|
|
125
|
-
url: z.string().describe("The URL to request"),
|
|
126
|
-
method: z.string().optional().describe("HTTP method"),
|
|
127
|
-
authenticationId: z.number().optional(),
|
|
128
|
-
})
|
|
129
|
-
.describe("Make authenticated HTTP requests");
|
|
130
|
-
|
|
131
|
-
describe("CLI Response Body Handling", () => {
|
|
132
|
-
let consoleSpy: ReturnType<typeof vi.spyOn>;
|
|
133
|
-
|
|
134
|
-
beforeEach(() => {
|
|
135
|
-
vi.clearAllMocks();
|
|
136
|
-
consoleSpy = vi.spyOn(console, "log").mockImplementation(() => {});
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
afterEach(() => {
|
|
140
|
-
consoleSpy.mockRestore();
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it("should wrap Response objects in structured envelope with statusCode, headers, body", async () => {
|
|
144
|
-
const bodyData = { ok: true, users: [{ id: 1, name: "Test User" }] };
|
|
145
|
-
|
|
146
|
-
// Create a mock Response object
|
|
147
|
-
const mockResponse = new Response(JSON.stringify(bodyData), {
|
|
148
|
-
status: 200,
|
|
149
|
-
headers: { "Content-Type": "application/json" },
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
const mockSdkWithRequest = {
|
|
153
|
-
getRegistry: vi.fn(() => ({
|
|
154
|
-
functions: [
|
|
155
|
-
{
|
|
156
|
-
name: "request",
|
|
157
|
-
type: "single",
|
|
158
|
-
inputSchema: requestSchema,
|
|
159
|
-
},
|
|
160
|
-
],
|
|
161
|
-
categories: [],
|
|
162
|
-
})),
|
|
163
|
-
request: vi.fn().mockResolvedValue(mockResponse),
|
|
164
|
-
} as unknown as ZapierSdk;
|
|
165
|
-
|
|
166
|
-
const program = new Command();
|
|
167
|
-
program.exitOverride();
|
|
168
|
-
|
|
169
|
-
generateCliCommands(program, mockSdkWithRequest);
|
|
170
|
-
|
|
171
|
-
await program.parseAsync([
|
|
172
|
-
"node",
|
|
173
|
-
"test",
|
|
174
|
-
"request",
|
|
175
|
-
"https://api.example.com/users",
|
|
176
|
-
"--json",
|
|
177
|
-
]);
|
|
178
|
-
|
|
179
|
-
// Verify the SDK method was called
|
|
180
|
-
expect(mockSdkWithRequest.request).toHaveBeenCalled();
|
|
181
|
-
|
|
182
|
-
// Verify output includes the structured envelope with statusCode, headers, and body
|
|
183
|
-
const expectedEnvelope = {
|
|
184
|
-
statusCode: 200,
|
|
185
|
-
headers: { "content-type": "application/json" },
|
|
186
|
-
body: bodyData,
|
|
187
|
-
};
|
|
188
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
189
|
-
JSON.stringify(expectedEnvelope, null, 2),
|
|
190
|
-
);
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
it("should handle invalid JSON in Response with helpful error", async () => {
|
|
194
|
-
// Create a mock Response with invalid JSON
|
|
195
|
-
const mockResponse = new Response("not valid json {", {
|
|
196
|
-
status: 200,
|
|
197
|
-
headers: { "Content-Type": "application/json" },
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
const mockSdkWithBadResponse = {
|
|
201
|
-
getRegistry: vi.fn(() => ({
|
|
202
|
-
functions: [
|
|
203
|
-
{
|
|
204
|
-
name: "request",
|
|
205
|
-
type: "single",
|
|
206
|
-
inputSchema: requestSchema,
|
|
207
|
-
},
|
|
208
|
-
],
|
|
209
|
-
categories: [],
|
|
210
|
-
})),
|
|
211
|
-
request: vi.fn().mockResolvedValue(mockResponse),
|
|
212
|
-
} as unknown as ZapierSdk;
|
|
213
|
-
|
|
214
|
-
const program = new Command();
|
|
215
|
-
program.exitOverride();
|
|
216
|
-
const consoleErrorSpy = vi
|
|
217
|
-
.spyOn(console, "error")
|
|
218
|
-
.mockImplementation(() => {});
|
|
219
|
-
|
|
220
|
-
generateCliCommands(program, mockSdkWithBadResponse);
|
|
221
|
-
|
|
222
|
-
try {
|
|
223
|
-
await program.parseAsync([
|
|
224
|
-
"node",
|
|
225
|
-
"test",
|
|
226
|
-
"request",
|
|
227
|
-
"https://api.example.com/users",
|
|
228
|
-
"--json",
|
|
229
|
-
]);
|
|
230
|
-
} catch {
|
|
231
|
-
// Expected to throw
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// Verify error message includes helpful context
|
|
235
|
-
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
236
|
-
expect.stringContaining("❌"),
|
|
237
|
-
expect.stringContaining("Failed to parse response as JSON"),
|
|
238
|
-
);
|
|
239
|
-
|
|
240
|
-
consoleErrorSpy.mockRestore();
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
it("should handle non-Response objects normally", async () => {
|
|
244
|
-
const regularData = { apps: [{ id: 1, name: "Test App" }] };
|
|
245
|
-
|
|
246
|
-
const mockSdkRegular = {
|
|
247
|
-
getRegistry: vi.fn(() => ({
|
|
248
|
-
functions: [
|
|
249
|
-
{
|
|
250
|
-
name: "getApp",
|
|
251
|
-
type: "single",
|
|
252
|
-
inputSchema: z.object({ appKey: z.string() }).describe("Get app"),
|
|
253
|
-
},
|
|
254
|
-
],
|
|
255
|
-
categories: [],
|
|
256
|
-
})),
|
|
257
|
-
getApp: vi.fn().mockResolvedValue(regularData),
|
|
258
|
-
} as unknown as ZapierSdk;
|
|
259
|
-
|
|
260
|
-
const program = new Command();
|
|
261
|
-
program.exitOverride();
|
|
262
|
-
|
|
263
|
-
generateCliCommands(program, mockSdkRegular);
|
|
264
|
-
|
|
265
|
-
await program.parseAsync(["node", "test", "get-app", "test-app", "--json"]);
|
|
266
|
-
|
|
267
|
-
expect(mockSdkRegular.getApp).toHaveBeenCalled();
|
|
268
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
269
|
-
JSON.stringify(regularData, null, 2),
|
|
270
|
-
);
|
|
271
|
-
});
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
describe("CLI Command Generation", () => {
|
|
275
|
-
beforeEach(() => {
|
|
276
|
-
vi.clearAllMocks();
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
it("should execute CLI commands successfully", async () => {
|
|
280
|
-
const program = new Command();
|
|
281
|
-
program.exitOverride(); // Prevent process.exit() in tests
|
|
282
|
-
|
|
283
|
-
// Generate CLI commands
|
|
284
|
-
generateCliCommands(program, mockSdk);
|
|
285
|
-
|
|
286
|
-
// Execute the command through Commander.js parsing
|
|
287
|
-
await program.parseAsync(["node", "test", "list-apps", "--json"]);
|
|
288
|
-
|
|
289
|
-
// Verify the SDK method was called
|
|
290
|
-
expect(mockSdk.listApps).toHaveBeenCalled();
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
it("should handle CLI command failures gracefully", async () => {
|
|
294
|
-
const program = new Command();
|
|
295
|
-
program.exitOverride(); // Prevent process.exit() in tests
|
|
296
|
-
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
297
|
-
|
|
298
|
-
// Generate CLI commands
|
|
299
|
-
generateCliCommands(program, mockSdk);
|
|
300
|
-
|
|
301
|
-
// Mock the SDK method to throw an error
|
|
302
|
-
(mockSdk as unknown).listApps = vi
|
|
303
|
-
.fn()
|
|
304
|
-
.mockRejectedValue(new Error("API error"));
|
|
305
|
-
|
|
306
|
-
try {
|
|
307
|
-
// Execute the command through Commander.js parsing
|
|
308
|
-
await program.parseAsync(["node", "test", "list-apps", "--json"]);
|
|
309
|
-
} catch {
|
|
310
|
-
// Expected due to exitOverride throwing CommanderError
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
// Verify the SDK method was attempted
|
|
314
|
-
expect(mockSdk.listApps).toHaveBeenCalled();
|
|
315
|
-
|
|
316
|
-
// Cleanup
|
|
317
|
-
consoleSpy.mockRestore();
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
it("should generate commands for SDK without event emission", async () => {
|
|
321
|
-
const mockSdkWithoutEvents = {
|
|
322
|
-
getRegistry: vi.fn(() => ({
|
|
323
|
-
functions: [
|
|
324
|
-
{
|
|
325
|
-
name: "listApps",
|
|
326
|
-
type: "list",
|
|
327
|
-
inputSchema: testSchema,
|
|
328
|
-
},
|
|
329
|
-
],
|
|
330
|
-
categories: [],
|
|
331
|
-
})),
|
|
332
|
-
listApps: vi.fn().mockResolvedValue({ data: [] }),
|
|
333
|
-
} as unknown as ZapierSdk;
|
|
334
|
-
|
|
335
|
-
const program = new Command();
|
|
336
|
-
program.exitOverride(); // Prevent process.exit() in tests
|
|
337
|
-
|
|
338
|
-
// Generate CLI commands
|
|
339
|
-
generateCliCommands(program, mockSdkWithoutEvents);
|
|
340
|
-
|
|
341
|
-
// Should not throw even without event emission capability
|
|
342
|
-
await program.parseAsync(["node", "test", "list-apps", "--json"]);
|
|
343
|
-
|
|
344
|
-
// Verify the command executed successfully
|
|
345
|
-
expect(mockSdkWithoutEvents.listApps).toHaveBeenCalled();
|
|
346
|
-
});
|
|
347
|
-
});
|