@zapier/zapier-sdk-cli 0.4.4 → 0.6.0
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 +30 -0
- package/README.md +92 -72
- package/dist/cli.js +212 -67
- package/dist/src/cli.js +1 -1
- package/dist/src/commands/bundle-code/cli.js +1 -1
- package/dist/src/commands/generate-types/cli.js +17 -6
- package/dist/src/commands/generate-types/index.js +26 -5
- package/dist/src/commands/generate-types/schemas.d.ts +3 -0
- package/dist/src/commands/generate-types/schemas.js +4 -0
- package/dist/src/utils/api/client.d.ts +3 -3
- package/dist/src/utils/cli-generator-utils.d.ts +2 -2
- package/dist/src/utils/cli-generator.js +84 -23
- package/dist/src/utils/log.d.ts +4 -4
- package/dist/src/utils/parameter-resolver.d.ts +1 -1
- package/dist/src/utils/parameter-resolver.js +45 -30
- package/dist/src/utils/schema-formatter.d.ts +1 -1
- package/dist/src/utils/schema-formatter.js +6 -4
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/cli.test.ts +1 -2
- package/src/cli.ts +1 -1
- package/src/commands/bundle-code/cli.ts +19 -4
- package/src/commands/generate-types/cli.ts +25 -9
- package/src/commands/generate-types/index.ts +32 -6
- package/src/commands/generate-types/schemas.ts +4 -0
- package/src/utils/api/client.ts +3 -3
- package/src/utils/auth/login.ts +2 -1
- package/src/utils/cli-generator-utils.ts +7 -7
- package/src/utils/cli-generator.ts +154 -48
- package/src/utils/log.ts +4 -4
- package/src/utils/parameter-resolver.ts +106 -55
- package/src/utils/schema-formatter.ts +20 -11
package/src/utils/log.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
|
|
3
3
|
const log = {
|
|
4
|
-
info: (message: string, ...args:
|
|
4
|
+
info: (message: string, ...args: unknown[]) => {
|
|
5
5
|
console.log(chalk.blue("ℹ"), message, ...args);
|
|
6
6
|
},
|
|
7
|
-
error: (message: string, ...args:
|
|
7
|
+
error: (message: string, ...args: unknown[]) => {
|
|
8
8
|
console.error(chalk.red("✖"), message, ...args);
|
|
9
9
|
},
|
|
10
|
-
success: (message: string, ...args:
|
|
10
|
+
success: (message: string, ...args: unknown[]) => {
|
|
11
11
|
console.log(chalk.green("✓"), message, ...args);
|
|
12
12
|
},
|
|
13
|
-
warn: (message: string, ...args:
|
|
13
|
+
warn: (message: string, ...args: unknown[]) => {
|
|
14
14
|
console.log(chalk.yellow("⚠"), message, ...args);
|
|
15
15
|
},
|
|
16
16
|
};
|
|
@@ -22,8 +22,8 @@ interface ResolvableParameter {
|
|
|
22
22
|
|
|
23
23
|
interface ResolverContext {
|
|
24
24
|
sdk: ZapierSdk;
|
|
25
|
-
currentParams:
|
|
26
|
-
resolvedParams:
|
|
25
|
+
currentParams: Record<string, unknown>;
|
|
26
|
+
resolvedParams: Record<string, unknown>;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
// ============================================================================
|
|
@@ -33,9 +33,9 @@ interface ResolverContext {
|
|
|
33
33
|
export class SchemaParameterResolver {
|
|
34
34
|
async resolveParameters(
|
|
35
35
|
schema: z.ZodSchema,
|
|
36
|
-
providedParams:
|
|
36
|
+
providedParams: unknown,
|
|
37
37
|
sdk: ZapierSdk,
|
|
38
|
-
): Promise<
|
|
38
|
+
): Promise<unknown> {
|
|
39
39
|
// 1. Try to parse with current parameters
|
|
40
40
|
const parseResult = schema.safeParse(providedParams);
|
|
41
41
|
|
|
@@ -102,11 +102,11 @@ export class SchemaParameterResolver {
|
|
|
102
102
|
return parseResult.data;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
// 2. Resolve functionally required parameters
|
|
106
|
-
const resolvedParams = { ...providedParams };
|
|
105
|
+
// 2. Resolve functionally required parameters first
|
|
106
|
+
const resolvedParams = { ...(providedParams as Record<string, unknown>) };
|
|
107
107
|
const context: ResolverContext = {
|
|
108
108
|
sdk,
|
|
109
|
-
currentParams: providedParams,
|
|
109
|
+
currentParams: providedParams as Record<string, unknown>,
|
|
110
110
|
resolvedParams,
|
|
111
111
|
};
|
|
112
112
|
|
|
@@ -306,7 +306,7 @@ export class SchemaParameterResolver {
|
|
|
306
306
|
private async resolveParameter(
|
|
307
307
|
param: ResolvableParameter,
|
|
308
308
|
context: ResolverContext,
|
|
309
|
-
): Promise<
|
|
309
|
+
): Promise<unknown> {
|
|
310
310
|
const resolver = getResolver(param.name);
|
|
311
311
|
if (!resolver) {
|
|
312
312
|
throw new Error(`No resolver found for parameter: ${param.name}`);
|
|
@@ -314,39 +314,55 @@ export class SchemaParameterResolver {
|
|
|
314
314
|
|
|
315
315
|
console.log(chalk.blue(`\n🔍 Resolving ${param.name}...`));
|
|
316
316
|
|
|
317
|
-
|
|
317
|
+
const typedResolver = resolver as {
|
|
318
|
+
type: string;
|
|
319
|
+
inputType?: string;
|
|
320
|
+
placeholder?: string;
|
|
321
|
+
fetch?: Function;
|
|
322
|
+
prompt?: Function;
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
if (typedResolver.type === "static") {
|
|
318
326
|
// Static resolver - just prompt for input
|
|
319
327
|
const promptConfig = {
|
|
320
|
-
type:
|
|
328
|
+
type: typedResolver.inputType === "password" ? "password" : "input",
|
|
321
329
|
name: param.name,
|
|
322
330
|
message: `Enter ${param.name}:`,
|
|
323
|
-
...(
|
|
331
|
+
...(typedResolver.placeholder && {
|
|
332
|
+
default: typedResolver.placeholder,
|
|
333
|
+
}),
|
|
324
334
|
};
|
|
325
335
|
|
|
326
336
|
const answers = await inquirer.prompt([promptConfig as any]);
|
|
327
337
|
return answers[param.name];
|
|
328
|
-
} else if (
|
|
338
|
+
} else if (typedResolver.type === "dynamic") {
|
|
329
339
|
// Dynamic resolver - fetch options and prompt for selection
|
|
330
340
|
try {
|
|
331
341
|
// Only show "Fetching..." for required parameters that typically have many options
|
|
332
342
|
if (param.isRequired && param.name !== "authenticationId") {
|
|
333
343
|
console.log(chalk.gray(`Fetching options for ${param.name}...`));
|
|
334
344
|
}
|
|
335
|
-
const items = await
|
|
345
|
+
const items = await typedResolver.fetch!(
|
|
346
|
+
context.sdk,
|
|
347
|
+
context.resolvedParams,
|
|
348
|
+
);
|
|
336
349
|
|
|
337
350
|
// Let the resolver's prompt handle empty lists (e.g., authenticationId can show "skip authentication")
|
|
338
351
|
const safeItems = items || [];
|
|
339
|
-
const promptConfig =
|
|
352
|
+
const promptConfig = typedResolver.prompt!(
|
|
353
|
+
safeItems,
|
|
354
|
+
context.resolvedParams,
|
|
355
|
+
);
|
|
340
356
|
const answers = await inquirer.prompt([promptConfig as any]);
|
|
341
357
|
return answers[param.name];
|
|
342
358
|
} catch (error) {
|
|
343
359
|
// Let the main CLI error handler display user-friendly errors
|
|
344
360
|
throw error;
|
|
345
361
|
}
|
|
346
|
-
} else if (
|
|
362
|
+
} else if (typedResolver.type === "fields") {
|
|
347
363
|
// Fields resolver - fetch field definitions and prompt for each input with recursive field resolution
|
|
348
364
|
return await this.resolveFieldsRecursively(
|
|
349
|
-
resolver as
|
|
365
|
+
resolver as unknown,
|
|
350
366
|
context,
|
|
351
367
|
param,
|
|
352
368
|
);
|
|
@@ -356,11 +372,12 @@ export class SchemaParameterResolver {
|
|
|
356
372
|
}
|
|
357
373
|
|
|
358
374
|
private async resolveFieldsRecursively(
|
|
359
|
-
resolver:
|
|
375
|
+
resolver: unknown,
|
|
360
376
|
context: ResolverContext,
|
|
361
377
|
param: ResolvableParameter,
|
|
362
|
-
): Promise<Record<string,
|
|
363
|
-
const
|
|
378
|
+
): Promise<Record<string, unknown>> {
|
|
379
|
+
const typedResolver = resolver as { fetch: Function };
|
|
380
|
+
const inputs: Record<string, unknown> = {};
|
|
364
381
|
let processedFieldKeys = new Set<string>();
|
|
365
382
|
let iteration = 0;
|
|
366
383
|
const maxIterations = 5; // Prevent infinite loops
|
|
@@ -383,7 +400,7 @@ export class SchemaParameterResolver {
|
|
|
383
400
|
),
|
|
384
401
|
);
|
|
385
402
|
|
|
386
|
-
const fields = await
|
|
403
|
+
const fields = await typedResolver.fetch(
|
|
387
404
|
updatedContext.sdk,
|
|
388
405
|
updatedContext.resolvedParams,
|
|
389
406
|
);
|
|
@@ -399,7 +416,11 @@ export class SchemaParameterResolver {
|
|
|
399
416
|
|
|
400
417
|
// Find new fields that we haven't processed yet
|
|
401
418
|
const newFields = fields.filter(
|
|
402
|
-
(field:
|
|
419
|
+
(field: unknown) =>
|
|
420
|
+
!(
|
|
421
|
+
(field as { key: string }).key &&
|
|
422
|
+
processedFieldKeys.has((field as { key: string }).key)
|
|
423
|
+
),
|
|
403
424
|
);
|
|
404
425
|
|
|
405
426
|
if (newFields.length === 0) {
|
|
@@ -409,10 +430,10 @@ export class SchemaParameterResolver {
|
|
|
409
430
|
|
|
410
431
|
// Separate new required and optional fields
|
|
411
432
|
const newRequiredFields = newFields.filter(
|
|
412
|
-
(field:
|
|
433
|
+
(field: unknown) => (field as { required: boolean }).required,
|
|
413
434
|
);
|
|
414
435
|
const newOptionalFields = newFields.filter(
|
|
415
|
-
(field:
|
|
436
|
+
(field: unknown) => !(field as { required: boolean }).required,
|
|
416
437
|
);
|
|
417
438
|
|
|
418
439
|
// Prompt for new required fields
|
|
@@ -424,7 +445,7 @@ export class SchemaParameterResolver {
|
|
|
424
445
|
);
|
|
425
446
|
for (const field of newRequiredFields) {
|
|
426
447
|
await this.promptForField(field, inputs);
|
|
427
|
-
processedFieldKeys.add(field.key);
|
|
448
|
+
processedFieldKeys.add((field as { key: string }).key);
|
|
428
449
|
}
|
|
429
450
|
}
|
|
430
451
|
|
|
@@ -458,12 +479,12 @@ export class SchemaParameterResolver {
|
|
|
458
479
|
console.log(chalk.cyan(`\nOptional fields:`));
|
|
459
480
|
for (const field of newOptionalFields) {
|
|
460
481
|
await this.promptForField(field, inputs);
|
|
461
|
-
processedFieldKeys.add(field.key);
|
|
482
|
+
processedFieldKeys.add((field as { key: string }).key);
|
|
462
483
|
}
|
|
463
484
|
} else {
|
|
464
485
|
// Mark these fields as processed even if skipped to avoid re-asking
|
|
465
|
-
newOptionalFields.forEach((field:
|
|
466
|
-
processedFieldKeys.add(field.key),
|
|
486
|
+
newOptionalFields.forEach((field: unknown) =>
|
|
487
|
+
processedFieldKeys.add((field as { key: string }).key),
|
|
467
488
|
);
|
|
468
489
|
}
|
|
469
490
|
}
|
|
@@ -488,48 +509,73 @@ export class SchemaParameterResolver {
|
|
|
488
509
|
return inputs;
|
|
489
510
|
}
|
|
490
511
|
|
|
491
|
-
private getNestedValue(obj:
|
|
492
|
-
return path.reduce(
|
|
512
|
+
private getNestedValue(obj: unknown, path: string[]): unknown {
|
|
513
|
+
return path.reduce(
|
|
514
|
+
(current, key) => (current as Record<string, unknown>)?.[key],
|
|
515
|
+
obj,
|
|
516
|
+
);
|
|
493
517
|
}
|
|
494
518
|
|
|
495
|
-
private setNestedValue(obj:
|
|
519
|
+
private setNestedValue(obj: unknown, path: string[], value: unknown): void {
|
|
496
520
|
const lastKey = path[path.length - 1];
|
|
497
521
|
const parent = path.slice(0, -1).reduce((current, key) => {
|
|
498
|
-
|
|
499
|
-
|
|
522
|
+
const currentObj = current as Record<string, unknown>;
|
|
523
|
+
if (!(key in currentObj)) {
|
|
524
|
+
currentObj[key] = {};
|
|
500
525
|
}
|
|
501
|
-
return
|
|
502
|
-
}, obj)
|
|
526
|
+
return currentObj[key];
|
|
527
|
+
}, obj) as Record<string, unknown>;
|
|
503
528
|
parent[lastKey] = value;
|
|
504
529
|
}
|
|
505
530
|
|
|
506
531
|
private async promptForField(
|
|
507
|
-
field:
|
|
508
|
-
inputs: Record<string,
|
|
532
|
+
field: unknown,
|
|
533
|
+
inputs: Record<string, unknown>,
|
|
509
534
|
): Promise<void> {
|
|
510
|
-
const
|
|
511
|
-
type
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
535
|
+
const fieldObj = field as {
|
|
536
|
+
type?: string;
|
|
537
|
+
key: string;
|
|
538
|
+
label?: string;
|
|
539
|
+
required?: boolean;
|
|
540
|
+
helpText?: string;
|
|
541
|
+
default?: unknown;
|
|
542
|
+
choices?: Array<{ label?: string; value: unknown }>;
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
const fieldPrompt: Record<string, unknown> = {
|
|
546
|
+
type: fieldObj.type === "boolean" ? "confirm" : "input",
|
|
547
|
+
name: fieldObj.key,
|
|
548
|
+
message: `${fieldObj.label || fieldObj.key}${fieldObj.required ? " (required)" : " (optional)"}:`,
|
|
516
549
|
};
|
|
517
550
|
|
|
518
|
-
if (
|
|
551
|
+
if (fieldObj.helpText) {
|
|
552
|
+
fieldPrompt.prefix = chalk.gray(`ℹ ${fieldObj.helpText}\n`);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
if (fieldObj.default !== undefined) {
|
|
556
|
+
fieldPrompt.default = fieldObj.default;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
if (fieldObj.choices && fieldObj.choices.length > 0) {
|
|
519
560
|
fieldPrompt.type = "list";
|
|
520
|
-
(fieldPrompt as
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
561
|
+
(fieldPrompt as { choices: unknown[] }).choices = fieldObj.choices.map(
|
|
562
|
+
(choice: unknown) => {
|
|
563
|
+
const choiceObj = choice as { label?: unknown; value: unknown };
|
|
564
|
+
return {
|
|
565
|
+
name: choiceObj.label || choiceObj.value,
|
|
566
|
+
value: choiceObj.value,
|
|
567
|
+
};
|
|
568
|
+
},
|
|
569
|
+
);
|
|
524
570
|
}
|
|
525
571
|
|
|
526
572
|
try {
|
|
527
573
|
const answer = await inquirer.prompt([fieldPrompt as any]);
|
|
528
574
|
|
|
529
|
-
if (answer[
|
|
530
|
-
inputs[
|
|
531
|
-
} else if (
|
|
532
|
-
throw new Error(`Required field ${
|
|
575
|
+
if (answer[fieldObj.key] !== undefined && answer[fieldObj.key] !== "") {
|
|
576
|
+
inputs[fieldObj.key] = answer[fieldObj.key];
|
|
577
|
+
} else if (fieldObj.required) {
|
|
578
|
+
throw new Error(`Required field ${fieldObj.key} cannot be empty`);
|
|
533
579
|
}
|
|
534
580
|
} catch (error) {
|
|
535
581
|
if (this.isUserCancellation(error)) {
|
|
@@ -540,11 +586,16 @@ export class SchemaParameterResolver {
|
|
|
540
586
|
}
|
|
541
587
|
}
|
|
542
588
|
|
|
543
|
-
private isUserCancellation(error:
|
|
589
|
+
private isUserCancellation(error: unknown): boolean {
|
|
590
|
+
const errorObj = error as {
|
|
591
|
+
name?: string;
|
|
592
|
+
message?: string;
|
|
593
|
+
isTTYError?: boolean;
|
|
594
|
+
};
|
|
544
595
|
return (
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
596
|
+
errorObj?.name === "ExitPromptError" ||
|
|
597
|
+
errorObj?.message?.includes("User force closed") ||
|
|
598
|
+
errorObj?.isTTYError === true
|
|
548
599
|
);
|
|
549
600
|
}
|
|
550
601
|
}
|
|
@@ -13,15 +13,16 @@ interface FormattedItem {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
interface FormatMetadata {
|
|
16
|
-
format: (item:
|
|
16
|
+
format: (item: unknown) => FormattedItem;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
function getFormatMetadata(schema:
|
|
20
|
-
return schema?._def
|
|
19
|
+
function getFormatMetadata(schema: unknown): FormatMetadata | undefined {
|
|
20
|
+
return (schema as { _def?: { formatMeta?: FormatMetadata } })?._def
|
|
21
|
+
?.formatMeta;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
function getOutputSchema(schema:
|
|
24
|
-
return schema?._def?.outputSchema;
|
|
24
|
+
function getOutputSchema(schema: unknown): unknown {
|
|
25
|
+
return (schema as { _def?: { outputSchema?: unknown } })?._def?.outputSchema;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
// ============================================================================
|
|
@@ -30,7 +31,7 @@ function getOutputSchema(schema: any): any {
|
|
|
30
31
|
|
|
31
32
|
export function formatItemsFromSchema(
|
|
32
33
|
inputSchema: z.ZodType,
|
|
33
|
-
items:
|
|
34
|
+
items: unknown[],
|
|
34
35
|
): void {
|
|
35
36
|
// Get the output schema and its format metadata
|
|
36
37
|
const outputSchema = getOutputSchema(inputSchema);
|
|
@@ -54,7 +55,7 @@ export function formatItemsFromSchema(
|
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
function formatSingleItem(
|
|
57
|
-
item:
|
|
58
|
+
item: unknown,
|
|
58
59
|
index: number,
|
|
59
60
|
formatMeta: FormatMetadata,
|
|
60
61
|
): void {
|
|
@@ -93,13 +94,21 @@ function applyStyle(value: string, style: string): string {
|
|
|
93
94
|
}
|
|
94
95
|
}
|
|
95
96
|
|
|
96
|
-
function formatItemsGeneric(items:
|
|
97
|
+
function formatItemsGeneric(items: unknown[]): void {
|
|
97
98
|
// Fallback formatting for items without schema metadata
|
|
98
99
|
items.forEach((item, index) => {
|
|
99
|
-
const
|
|
100
|
+
const itemObj = item as {
|
|
101
|
+
title?: string;
|
|
102
|
+
name?: string;
|
|
103
|
+
key?: string;
|
|
104
|
+
id?: string;
|
|
105
|
+
description?: string;
|
|
106
|
+
};
|
|
107
|
+
const name =
|
|
108
|
+
itemObj.title || itemObj.name || itemObj.key || itemObj.id || "Item";
|
|
100
109
|
console.log(`${chalk.gray(`${index + 1}.`)} ${chalk.cyan(name)}`);
|
|
101
|
-
if (
|
|
102
|
-
console.log(` ${chalk.dim(
|
|
110
|
+
if (itemObj.description) {
|
|
111
|
+
console.log(` ${chalk.dim(itemObj.description)}`);
|
|
103
112
|
}
|
|
104
113
|
console.log();
|
|
105
114
|
});
|