@zapier/zapier-sdk-cli 0.0.1
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/bin/zapier-sdk.js +4 -0
- package/bin/zsdk.js +4 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +25 -0
- package/dist/commands/action.d.ts +2 -0
- package/dist/commands/action.js +295 -0
- package/dist/commands/browse.d.ts +2 -0
- package/dist/commands/browse.js +257 -0
- package/dist/commands/bundle.d.ts +2 -0
- package/dist/commands/bundle.js +101 -0
- package/dist/commands/generate.d.ts +9 -0
- package/dist/commands/generate.js +281 -0
- package/dist/index.d.ts +0 -0
- package/dist/index.js +3 -0
- package/dist/utils/auth-picker.d.ts +17 -0
- package/dist/utils/auth-picker.js +121 -0
- package/dist/utils/cli-generator.d.ts +4 -0
- package/dist/utils/cli-generator.js +414 -0
- package/dist/utils/pager.d.ts +48 -0
- package/dist/utils/pager.js +147 -0
- package/dist/utils/parameter-resolver.d.ts +18 -0
- package/dist/utils/parameter-resolver.js +413 -0
- package/dist/utils/schema-formatter.d.ts +2 -0
- package/dist/utils/schema-formatter.js +72 -0
- package/dist/utils/schema-generator.d.ts +4 -0
- package/dist/utils/schema-generator.js +389 -0
- package/package.json +42 -0
- package/src/cli.ts +32 -0
- package/src/index.ts +2 -0
- package/src/utils/cli-generator.ts +578 -0
- package/src/utils/pager.ts +202 -0
- package/src/utils/parameter-resolver.ts +573 -0
- package/src/utils/schema-formatter.ts +88 -0
- package/test/cli.test.ts +46 -0
- package/tsconfig.build.json +6 -0
- package/tsconfig.json +22 -0
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { ActionsSDK } from "@zapier/actions-sdk";
|
|
4
|
+
import { SDKSchemas } from "../../../actions-sdk/dist/schemas";
|
|
5
|
+
import { SchemaParameterResolver } from "./parameter-resolver";
|
|
6
|
+
import { createPager } from "./pager";
|
|
7
|
+
import { formatItemsFromSchema } from "./schema-formatter";
|
|
8
|
+
import chalk from "chalk";
|
|
9
|
+
import util from "util";
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// JSON Formatting
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
function formatJSONOutput(data: any): void {
|
|
16
|
+
// Show success message for action results
|
|
17
|
+
if (
|
|
18
|
+
data &&
|
|
19
|
+
typeof data === "object" &&
|
|
20
|
+
!Array.isArray(data) &&
|
|
21
|
+
(data.success !== undefined || data.id || data.status)
|
|
22
|
+
) {
|
|
23
|
+
console.log(chalk.green("ā
Action completed successfully!\n"));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Use util.inspect for colored output
|
|
27
|
+
console.log(
|
|
28
|
+
util.inspect(data, { colors: true, depth: null, breakLength: 80 }),
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ============================================================================
|
|
33
|
+
// Types
|
|
34
|
+
// ============================================================================
|
|
35
|
+
|
|
36
|
+
interface CLICommandConfig {
|
|
37
|
+
description: string;
|
|
38
|
+
parameters: CLIParameter[];
|
|
39
|
+
handler: (...args: any[]) => Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface CLIParameter {
|
|
43
|
+
name: string;
|
|
44
|
+
type: "string" | "number" | "boolean" | "array";
|
|
45
|
+
required: boolean;
|
|
46
|
+
description?: string;
|
|
47
|
+
default?: any;
|
|
48
|
+
choices?: string[];
|
|
49
|
+
resolverMeta?: any;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ============================================================================
|
|
53
|
+
// Schema Analysis
|
|
54
|
+
// ============================================================================
|
|
55
|
+
|
|
56
|
+
function analyzeZodSchema(schema: z.ZodSchema): CLIParameter[] {
|
|
57
|
+
const parameters: CLIParameter[] = [];
|
|
58
|
+
|
|
59
|
+
if (schema instanceof z.ZodObject) {
|
|
60
|
+
const shape = schema.shape;
|
|
61
|
+
|
|
62
|
+
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
63
|
+
const param = analyzeZodField(key, fieldSchema as z.ZodSchema);
|
|
64
|
+
if (param) {
|
|
65
|
+
parameters.push(param);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return parameters;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function analyzeZodField(
|
|
74
|
+
name: string,
|
|
75
|
+
schema: z.ZodSchema,
|
|
76
|
+
): CLIParameter | null {
|
|
77
|
+
let baseSchema = schema;
|
|
78
|
+
let required = true;
|
|
79
|
+
let defaultValue: any = undefined;
|
|
80
|
+
|
|
81
|
+
// Unwrap optional and default wrappers
|
|
82
|
+
if (baseSchema instanceof z.ZodOptional) {
|
|
83
|
+
required = false;
|
|
84
|
+
baseSchema = baseSchema._def.innerType;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (baseSchema instanceof z.ZodDefault) {
|
|
88
|
+
required = false;
|
|
89
|
+
defaultValue = baseSchema._def.defaultValue();
|
|
90
|
+
baseSchema = baseSchema._def.innerType;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Determine parameter type
|
|
94
|
+
let paramType: CLIParameter["type"] = "string";
|
|
95
|
+
let choices: string[] | undefined;
|
|
96
|
+
|
|
97
|
+
if (baseSchema instanceof z.ZodString) {
|
|
98
|
+
paramType = "string";
|
|
99
|
+
} else if (baseSchema instanceof z.ZodNumber) {
|
|
100
|
+
paramType = "number";
|
|
101
|
+
} else if (baseSchema instanceof z.ZodBoolean) {
|
|
102
|
+
paramType = "boolean";
|
|
103
|
+
} else if (baseSchema instanceof z.ZodArray) {
|
|
104
|
+
paramType = "array";
|
|
105
|
+
} else if (baseSchema instanceof z.ZodEnum) {
|
|
106
|
+
paramType = "string";
|
|
107
|
+
choices = baseSchema._def.values;
|
|
108
|
+
} else if (baseSchema instanceof z.ZodRecord) {
|
|
109
|
+
// Handle Record<string, any> as JSON string input
|
|
110
|
+
paramType = "string";
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Extract resolver metadata
|
|
114
|
+
const resolverMeta = (schema._def as any).resolverMeta;
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
name,
|
|
118
|
+
type: paramType,
|
|
119
|
+
required,
|
|
120
|
+
description: schema.description,
|
|
121
|
+
default: defaultValue,
|
|
122
|
+
choices,
|
|
123
|
+
resolverMeta,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ============================================================================
|
|
128
|
+
// CLI Command Generation
|
|
129
|
+
// ============================================================================
|
|
130
|
+
|
|
131
|
+
export function generateCLICommands(program: Command, sdk: ActionsSDK): void {
|
|
132
|
+
// Check if SDKSchemas is available
|
|
133
|
+
if (!SDKSchemas) {
|
|
134
|
+
console.error("SDKSchemas not available");
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Generate namespace commands (apps, actions, auths, fields)
|
|
139
|
+
Object.entries(SDKSchemas).forEach(([namespace, methods]) => {
|
|
140
|
+
if (namespace === "generate" || namespace === "bundle") {
|
|
141
|
+
// Handle root tools separately
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const namespaceCommand = program
|
|
146
|
+
.command(namespace)
|
|
147
|
+
.description(`${namespace} management commands`);
|
|
148
|
+
|
|
149
|
+
if (typeof methods === "object" && methods !== null) {
|
|
150
|
+
Object.entries(methods).forEach(([method, schema]) => {
|
|
151
|
+
const config = createCommandConfig(
|
|
152
|
+
namespace,
|
|
153
|
+
method,
|
|
154
|
+
schema as z.ZodSchema,
|
|
155
|
+
sdk,
|
|
156
|
+
);
|
|
157
|
+
addSubCommand(namespaceCommand, method, config);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Generate root tool commands
|
|
163
|
+
if (SDKSchemas.generate) {
|
|
164
|
+
const generateConfig = createCommandConfig(
|
|
165
|
+
"",
|
|
166
|
+
"generate",
|
|
167
|
+
SDKSchemas.generate,
|
|
168
|
+
sdk,
|
|
169
|
+
);
|
|
170
|
+
addSubCommand(program, "generate", generateConfig);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (SDKSchemas.bundle) {
|
|
174
|
+
const bundleConfig = createCommandConfig(
|
|
175
|
+
"",
|
|
176
|
+
"bundle",
|
|
177
|
+
SDKSchemas.bundle,
|
|
178
|
+
sdk,
|
|
179
|
+
);
|
|
180
|
+
addSubCommand(program, "bundle", bundleConfig);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function createCommandConfig(
|
|
185
|
+
namespace: string,
|
|
186
|
+
method: string,
|
|
187
|
+
schema: z.ZodSchema,
|
|
188
|
+
sdk: ActionsSDK,
|
|
189
|
+
): CLICommandConfig {
|
|
190
|
+
const parameters = analyzeZodSchema(schema);
|
|
191
|
+
const description = schema.description || `${namespace} ${method} command`;
|
|
192
|
+
|
|
193
|
+
const handler = async (...args: any[]) => {
|
|
194
|
+
try {
|
|
195
|
+
// The last argument is always the command object with parsed options
|
|
196
|
+
const command = args[args.length - 1];
|
|
197
|
+
const options = command.opts();
|
|
198
|
+
|
|
199
|
+
// Check if this is a list command with pagination support
|
|
200
|
+
const isListCommand = method === "list";
|
|
201
|
+
const hasPaginationParams = parameters.some(
|
|
202
|
+
(p) => p.name === "limit" || p.name === "offset",
|
|
203
|
+
);
|
|
204
|
+
const hasUserSpecifiedLimit =
|
|
205
|
+
"limit" in options && options.limit !== undefined;
|
|
206
|
+
const shouldUsePaging =
|
|
207
|
+
isListCommand && hasPaginationParams && !hasUserSpecifiedLimit;
|
|
208
|
+
const shouldUseJSON = options.json;
|
|
209
|
+
|
|
210
|
+
// Convert CLI args to SDK method parameters
|
|
211
|
+
const rawParams = convertCLIArgsToSDKParams(
|
|
212
|
+
parameters,
|
|
213
|
+
args.slice(0, -1),
|
|
214
|
+
options,
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
// NEW: Resolve missing parameters interactively using schema metadata
|
|
218
|
+
const resolver = new SchemaParameterResolver();
|
|
219
|
+
const resolvedParams = await resolver.resolveParameters(
|
|
220
|
+
schema,
|
|
221
|
+
rawParams,
|
|
222
|
+
sdk,
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
if (shouldUsePaging && !shouldUseJSON) {
|
|
226
|
+
// Use interactive paging for list commands
|
|
227
|
+
await handlePaginatedList(namespace, method, resolvedParams, sdk);
|
|
228
|
+
} else {
|
|
229
|
+
// Call the appropriate SDK method with complete, validated parameters
|
|
230
|
+
let result: any;
|
|
231
|
+
if (namespace === "") {
|
|
232
|
+
// Root tool (generate, bundle)
|
|
233
|
+
result = await (sdk as any)[method](resolvedParams);
|
|
234
|
+
} else {
|
|
235
|
+
// Regular namespace method
|
|
236
|
+
result = await (sdk as any)[namespace][method](resolvedParams);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Special handling for generate and bundle commands - don't output to console if writing to file
|
|
240
|
+
const isRootCommandWithOutput =
|
|
241
|
+
namespace === "" && (method === "generate" || method === "bundle");
|
|
242
|
+
const hasOutputFile = isRootCommandWithOutput && resolvedParams.output;
|
|
243
|
+
|
|
244
|
+
// Output result (JSON or formatted)
|
|
245
|
+
if (!hasOutputFile && (shouldUseJSON || !isListCommand)) {
|
|
246
|
+
// Use raw JSON if --json flag is specified, otherwise use pretty formatting
|
|
247
|
+
if (shouldUseJSON) {
|
|
248
|
+
console.log(JSON.stringify(result, null, 2));
|
|
249
|
+
} else {
|
|
250
|
+
formatJSONOutput(result);
|
|
251
|
+
}
|
|
252
|
+
} else if (!hasOutputFile) {
|
|
253
|
+
// Format list results nicely (non-paginated)
|
|
254
|
+
formatNonPaginatedResults(
|
|
255
|
+
namespace,
|
|
256
|
+
result,
|
|
257
|
+
resolvedParams.limit,
|
|
258
|
+
hasUserSpecifiedLimit,
|
|
259
|
+
shouldUseJSON,
|
|
260
|
+
);
|
|
261
|
+
} else if (hasOutputFile) {
|
|
262
|
+
// Show success message for file output instead of printing generated content
|
|
263
|
+
console.log(chalk.green(`ā
${method} completed successfully!`));
|
|
264
|
+
console.log(
|
|
265
|
+
chalk.gray(`Output written to: ${resolvedParams.output}`),
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
} catch (error) {
|
|
270
|
+
console.error(
|
|
271
|
+
"Error:",
|
|
272
|
+
error instanceof Error ? error.message : "Unknown error",
|
|
273
|
+
);
|
|
274
|
+
process.exit(1);
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
return {
|
|
279
|
+
description,
|
|
280
|
+
parameters,
|
|
281
|
+
handler,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function addSubCommand(
|
|
286
|
+
parentCommand: Command,
|
|
287
|
+
name: string,
|
|
288
|
+
config: CLICommandConfig,
|
|
289
|
+
): void {
|
|
290
|
+
const command = parentCommand.command(name).description(config.description);
|
|
291
|
+
|
|
292
|
+
// Add parameters to command
|
|
293
|
+
config.parameters.forEach((param) => {
|
|
294
|
+
if (param.resolverMeta?.resolver && param.required) {
|
|
295
|
+
// Required parameters with resolvers become optional positional arguments (resolver handles prompting)
|
|
296
|
+
command.argument(
|
|
297
|
+
`[${param.name}]`,
|
|
298
|
+
param.description || `${param.name} parameter`,
|
|
299
|
+
);
|
|
300
|
+
} else if (param.required) {
|
|
301
|
+
// Required parameters without resolvers become required positional arguments
|
|
302
|
+
command.argument(
|
|
303
|
+
`<${param.name}>`,
|
|
304
|
+
param.description || `${param.name} parameter`,
|
|
305
|
+
);
|
|
306
|
+
} else {
|
|
307
|
+
// Optional parameters become flags (whether they have resolvers or not)
|
|
308
|
+
const flags = [
|
|
309
|
+
`--${param.name.replace(/([A-Z])/g, "-$1").toLowerCase()}`,
|
|
310
|
+
];
|
|
311
|
+
|
|
312
|
+
if (param.type === "boolean") {
|
|
313
|
+
command.option(flags.join(", "), param.description);
|
|
314
|
+
} else {
|
|
315
|
+
const flagSignature = flags.join(", ") + ` <${param.type}>`;
|
|
316
|
+
command.option(flagSignature, param.description, param.default);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// Add formatting options for all commands
|
|
322
|
+
command.option("--json", "Output raw JSON instead of formatted results");
|
|
323
|
+
|
|
324
|
+
command.action(config.handler);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// ============================================================================
|
|
328
|
+
// Parameter Conversion
|
|
329
|
+
// ============================================================================
|
|
330
|
+
|
|
331
|
+
function convertCLIArgsToSDKParams(
|
|
332
|
+
parameters: CLIParameter[],
|
|
333
|
+
positionalArgs: any[],
|
|
334
|
+
options: Record<string, any>,
|
|
335
|
+
): Record<string, any> {
|
|
336
|
+
const sdkParams: Record<string, any> = {};
|
|
337
|
+
|
|
338
|
+
// Handle positional arguments (required parameters only, whether they have resolvers or not)
|
|
339
|
+
let argIndex = 0;
|
|
340
|
+
parameters.forEach((param) => {
|
|
341
|
+
if (param.required && argIndex < positionalArgs.length) {
|
|
342
|
+
sdkParams[param.name] = convertValue(
|
|
343
|
+
positionalArgs[argIndex],
|
|
344
|
+
param.type,
|
|
345
|
+
);
|
|
346
|
+
argIndex++;
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
// Handle option flags
|
|
351
|
+
Object.entries(options).forEach(([key, value]) => {
|
|
352
|
+
// Convert kebab-case back to camelCase
|
|
353
|
+
const camelKey = key.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
|
|
354
|
+
const param = parameters.find((p) => p.name === camelKey);
|
|
355
|
+
|
|
356
|
+
if (param && value !== undefined) {
|
|
357
|
+
sdkParams[camelKey] = convertValue(value, param.type);
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
return sdkParams;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function convertValue(value: any, type: CLIParameter["type"]): any {
|
|
365
|
+
switch (type) {
|
|
366
|
+
case "number":
|
|
367
|
+
return Number(value);
|
|
368
|
+
case "boolean":
|
|
369
|
+
return Boolean(value);
|
|
370
|
+
case "array":
|
|
371
|
+
return Array.isArray(value) ? value : [value];
|
|
372
|
+
case "string":
|
|
373
|
+
default:
|
|
374
|
+
// Handle JSON string for objects
|
|
375
|
+
if (
|
|
376
|
+
typeof value === "string" &&
|
|
377
|
+
(value.startsWith("{") || value.startsWith("["))
|
|
378
|
+
) {
|
|
379
|
+
try {
|
|
380
|
+
return JSON.parse(value);
|
|
381
|
+
} catch {
|
|
382
|
+
return value;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
return value;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// ============================================================================
|
|
390
|
+
// Pagination Handlers
|
|
391
|
+
// ============================================================================
|
|
392
|
+
|
|
393
|
+
async function handlePaginatedList(
|
|
394
|
+
namespace: string,
|
|
395
|
+
method: string,
|
|
396
|
+
baseParams: any,
|
|
397
|
+
sdk: ActionsSDK,
|
|
398
|
+
): Promise<void> {
|
|
399
|
+
const limit = baseParams.limit || 20;
|
|
400
|
+
const itemName = getItemName(namespace);
|
|
401
|
+
|
|
402
|
+
console.log(chalk.blue(`š Fetching ${itemName}...`));
|
|
403
|
+
|
|
404
|
+
const pager = createPager({
|
|
405
|
+
pageSize: Math.min(limit, 20),
|
|
406
|
+
itemName,
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
const displayFunction = (
|
|
410
|
+
items: any[],
|
|
411
|
+
totalShown: number,
|
|
412
|
+
totalAvailable?: number,
|
|
413
|
+
) => {
|
|
414
|
+
// Only clear screen if we have items to show
|
|
415
|
+
if (items.length > 0) {
|
|
416
|
+
console.clear();
|
|
417
|
+
}
|
|
418
|
+
console.log(chalk.blue(`š ${getListTitle(namespace)}\n`));
|
|
419
|
+
|
|
420
|
+
if (items.length === 0) {
|
|
421
|
+
console.log(chalk.yellow(`No ${itemName} found.`));
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// Get the schema for this namespace/method to extract formatting info
|
|
426
|
+
const schema = SDKSchemas[namespace as keyof typeof SDKSchemas];
|
|
427
|
+
const listSchema =
|
|
428
|
+
schema && typeof schema === "object" && "list" in schema
|
|
429
|
+
? schema.list
|
|
430
|
+
: null;
|
|
431
|
+
|
|
432
|
+
if (listSchema) {
|
|
433
|
+
formatItemsFromSchema(listSchema as z.ZodType, items);
|
|
434
|
+
} else {
|
|
435
|
+
// Fallback to generic formatting
|
|
436
|
+
formatItemsGeneric(items);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
const totalInfo = totalAvailable
|
|
440
|
+
? ` of ${totalAvailable.toLocaleString()} total`
|
|
441
|
+
: "";
|
|
442
|
+
console.log(
|
|
443
|
+
chalk.green(`\nā
Showing ${totalShown}${totalInfo} ${itemName}`),
|
|
444
|
+
);
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
await pager.paginate(
|
|
448
|
+
(params) =>
|
|
449
|
+
(sdk as any)[namespace][method]({
|
|
450
|
+
...baseParams,
|
|
451
|
+
...params,
|
|
452
|
+
}),
|
|
453
|
+
{},
|
|
454
|
+
displayFunction,
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
function formatNonPaginatedResults(
|
|
459
|
+
namespace: string,
|
|
460
|
+
result: any[],
|
|
461
|
+
requestedLimit?: number,
|
|
462
|
+
userSpecifiedLimit?: boolean,
|
|
463
|
+
useRawJSON?: boolean,
|
|
464
|
+
): void {
|
|
465
|
+
if (!Array.isArray(result)) {
|
|
466
|
+
if (useRawJSON) {
|
|
467
|
+
console.log(JSON.stringify(result, null, 2));
|
|
468
|
+
} else {
|
|
469
|
+
formatJSONOutput(result);
|
|
470
|
+
}
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
if (useRawJSON) {
|
|
475
|
+
console.log(JSON.stringify(result, null, 2));
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
const itemName = getItemName(namespace);
|
|
480
|
+
|
|
481
|
+
if (result.length === 0) {
|
|
482
|
+
console.log(chalk.yellow(`No ${itemName} found.`));
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
console.log(chalk.green(`\nā
Found ${result.length} ${itemName}:\n`));
|
|
487
|
+
|
|
488
|
+
// Get the schema for this namespace/method to extract formatting info
|
|
489
|
+
const schema = SDKSchemas[namespace as keyof typeof SDKSchemas];
|
|
490
|
+
const listSchema =
|
|
491
|
+
schema && typeof schema === "object" && "list" in schema
|
|
492
|
+
? schema.list
|
|
493
|
+
: null;
|
|
494
|
+
|
|
495
|
+
if (listSchema) {
|
|
496
|
+
formatItemsFromSchema(listSchema as z.ZodType, result);
|
|
497
|
+
} else {
|
|
498
|
+
// Fallback to generic formatting
|
|
499
|
+
formatItemsGeneric(result);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// Show appropriate status message
|
|
503
|
+
if (userSpecifiedLimit && requestedLimit) {
|
|
504
|
+
console.log(
|
|
505
|
+
chalk.gray(
|
|
506
|
+
`\nš Showing up to ${requestedLimit} ${itemName} (--limit ${requestedLimit})`,
|
|
507
|
+
),
|
|
508
|
+
);
|
|
509
|
+
} else {
|
|
510
|
+
console.log(chalk.gray(`\nš All available ${itemName} shown`));
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function formatItemsGeneric(items: any[]): void {
|
|
515
|
+
// Fallback formatting for items without schema metadata
|
|
516
|
+
items.forEach((item, index) => {
|
|
517
|
+
const name = item.name || item.key || item.id || "Item";
|
|
518
|
+
console.log(`${chalk.gray(`${index + 1}.`)} ${chalk.cyan(name)}`);
|
|
519
|
+
if (item.description) {
|
|
520
|
+
console.log(` ${chalk.dim(item.description)}`);
|
|
521
|
+
}
|
|
522
|
+
console.log();
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
function getItemName(namespace: string): string {
|
|
527
|
+
switch (namespace) {
|
|
528
|
+
case "apps":
|
|
529
|
+
return "apps";
|
|
530
|
+
case "actions":
|
|
531
|
+
return "actions";
|
|
532
|
+
case "auths":
|
|
533
|
+
return "authentications";
|
|
534
|
+
case "fields":
|
|
535
|
+
return "fields";
|
|
536
|
+
default:
|
|
537
|
+
return "items";
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
function getListTitle(namespace: string): string {
|
|
542
|
+
switch (namespace) {
|
|
543
|
+
case "apps":
|
|
544
|
+
return "Available Apps";
|
|
545
|
+
case "actions":
|
|
546
|
+
return "Available Actions";
|
|
547
|
+
case "auths":
|
|
548
|
+
return "Available Authentications";
|
|
549
|
+
case "fields":
|
|
550
|
+
return "Available Fields";
|
|
551
|
+
default:
|
|
552
|
+
return "Available Items";
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// ============================================================================
|
|
557
|
+
// Help Text Enhancement
|
|
558
|
+
// ============================================================================
|
|
559
|
+
|
|
560
|
+
export function enhanceCommandHelp(program: Command): void {
|
|
561
|
+
// Add custom help that shows schema-driven nature
|
|
562
|
+
program.on("--help", () => {
|
|
563
|
+
console.log("");
|
|
564
|
+
console.log("Commands are automatically generated from SDK schemas.");
|
|
565
|
+
console.log(
|
|
566
|
+
"Each command maps directly to an SDK method with the same parameters.",
|
|
567
|
+
);
|
|
568
|
+
console.log("");
|
|
569
|
+
console.log("Examples:");
|
|
570
|
+
console.log(" zapier-sdk apps list --category=productivity --limit=10");
|
|
571
|
+
console.log(
|
|
572
|
+
' zapier-sdk actions run slack search user_by_email --inputs=\'{"email":"user@example.com"}\'',
|
|
573
|
+
);
|
|
574
|
+
console.log(" zapier-sdk generate my-app --output=./generated/");
|
|
575
|
+
console.log(" zsdk apps list --limit=5 # Using the shorter alias");
|
|
576
|
+
console.log("");
|
|
577
|
+
});
|
|
578
|
+
}
|