@zapier/zapier-sdk-cli 0.9.0 → 0.11.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 +32 -0
- package/dist/cli.cjs +316 -144
- package/dist/cli.mjs +317 -145
- package/dist/index.cjs +15 -12
- package/dist/index.mjs +15 -12
- package/dist/package.json +1 -1
- package/dist/src/plugins/add/index.js +11 -13
- package/dist/src/utils/cli-generator-utils.d.ts +2 -1
- package/dist/src/utils/cli-generator-utils.js +11 -5
- package/dist/src/utils/cli-generator.js +50 -65
- package/dist/src/utils/parameter-resolver.d.ts +9 -1
- package/dist/src/utils/parameter-resolver.js +192 -56
- package/dist/src/utils/schema-formatter.d.ts +5 -1
- package/dist/src/utils/schema-formatter.js +48 -18
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/plugins/add/index.ts +15 -15
- package/src/utils/cli-generator-utils.ts +17 -5
- package/src/utils/cli-generator.ts +68 -79
- package/src/utils/parameter-resolver.ts +310 -80
- package/src/utils/schema-formatter.ts +68 -33
package/dist/cli.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { createFunction, OutputPropertySchema, DEFAULT_CONFIG_PATH, createZapierSdkWithoutRegistry, registryPlugin, ZapierError, formatErrorMessage, isPositional
|
|
4
|
+
import { createFunction, OutputPropertySchema, DEFAULT_CONFIG_PATH, createZapierSdkWithoutRegistry, registryPlugin, ZapierError, formatErrorMessage, isPositional } from '@zapier/zapier-sdk';
|
|
5
5
|
import inquirer from 'inquirer';
|
|
6
6
|
import chalk3 from 'chalk';
|
|
7
7
|
import util from 'util';
|
|
@@ -19,12 +19,45 @@ import { resolve, join } from 'path';
|
|
|
19
19
|
import * as ts from 'typescript';
|
|
20
20
|
import { mkdir, writeFile, access } from 'fs/promises';
|
|
21
21
|
|
|
22
|
+
function getLocalResolutionOrder(paramName, resolvers, resolved = /* @__PURE__ */ new Set()) {
|
|
23
|
+
const resolver = resolvers[paramName];
|
|
24
|
+
if (!resolver || resolver.type === "static") {
|
|
25
|
+
return [paramName];
|
|
26
|
+
}
|
|
27
|
+
const order = [];
|
|
28
|
+
if ("depends" in resolver && resolver.depends) {
|
|
29
|
+
for (const dependency of resolver.depends) {
|
|
30
|
+
if (!resolved.has(dependency)) {
|
|
31
|
+
order.push(...getLocalResolutionOrder(dependency, resolvers, resolved));
|
|
32
|
+
resolved.add(dependency);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (!resolved.has(paramName)) {
|
|
37
|
+
order.push(paramName);
|
|
38
|
+
resolved.add(paramName);
|
|
39
|
+
}
|
|
40
|
+
return order;
|
|
41
|
+
}
|
|
42
|
+
function getLocalResolutionOrderForParams(paramNames, resolvers) {
|
|
43
|
+
const resolved = /* @__PURE__ */ new Set();
|
|
44
|
+
const order = [];
|
|
45
|
+
for (const paramName of paramNames) {
|
|
46
|
+
const paramOrder = getLocalResolutionOrder(paramName, resolvers, resolved);
|
|
47
|
+
for (const param of paramOrder) {
|
|
48
|
+
if (!order.includes(param)) {
|
|
49
|
+
order.push(param);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return order;
|
|
54
|
+
}
|
|
22
55
|
var SchemaParameterResolver = class {
|
|
23
|
-
async resolveParameters(schema, providedParams, sdk2) {
|
|
56
|
+
async resolveParameters(schema, providedParams, sdk2, functionName) {
|
|
24
57
|
const parseResult = schema.safeParse(providedParams);
|
|
25
58
|
const allParams = this.extractParametersFromSchema(schema);
|
|
26
59
|
const resolvableParams = allParams.filter(
|
|
27
|
-
(param) => hasResolver(param.name)
|
|
60
|
+
(param) => this.hasResolver(param.name, sdk2, functionName)
|
|
28
61
|
);
|
|
29
62
|
const missingResolvable = resolvableParams.filter((param) => {
|
|
30
63
|
const hasValue = this.getNestedValue(providedParams, param.path) !== void 0;
|
|
@@ -60,11 +93,16 @@ var SchemaParameterResolver = class {
|
|
|
60
93
|
const context = {
|
|
61
94
|
sdk: sdk2,
|
|
62
95
|
currentParams: providedParams,
|
|
63
|
-
resolvedParams
|
|
96
|
+
resolvedParams,
|
|
97
|
+
functionName
|
|
64
98
|
};
|
|
99
|
+
const localResolvers = this.getLocalResolvers(sdk2, functionName);
|
|
65
100
|
if (functionallyRequired.length > 0) {
|
|
66
101
|
const requiredParamNames = functionallyRequired.map((p) => p.name);
|
|
67
|
-
const requiredResolutionOrder =
|
|
102
|
+
const requiredResolutionOrder = getLocalResolutionOrderForParams(
|
|
103
|
+
requiredParamNames,
|
|
104
|
+
localResolvers
|
|
105
|
+
);
|
|
68
106
|
const orderedRequiredParams = requiredResolutionOrder.map((paramName) => {
|
|
69
107
|
let param = functionallyRequired.find((p) => p.name === paramName);
|
|
70
108
|
if (!param) {
|
|
@@ -77,7 +115,11 @@ var SchemaParameterResolver = class {
|
|
|
77
115
|
}).filter((param) => param !== void 0);
|
|
78
116
|
for (const param of orderedRequiredParams) {
|
|
79
117
|
try {
|
|
80
|
-
const value = await this.resolveParameter(
|
|
118
|
+
const value = await this.resolveParameter(
|
|
119
|
+
param,
|
|
120
|
+
context,
|
|
121
|
+
functionName
|
|
122
|
+
);
|
|
81
123
|
this.setNestedValue(resolvedParams, param.path, value);
|
|
82
124
|
context.resolvedParams = resolvedParams;
|
|
83
125
|
} catch (error) {
|
|
@@ -104,11 +146,18 @@ var SchemaParameterResolver = class {
|
|
|
104
146
|
}
|
|
105
147
|
if (alwaysPrompt.length > 0) {
|
|
106
148
|
const alwaysPromptNames = alwaysPrompt.map((p) => p.name);
|
|
107
|
-
const alwaysPromptResolutionOrder =
|
|
149
|
+
const alwaysPromptResolutionOrder = getLocalResolutionOrderForParams(
|
|
150
|
+
alwaysPromptNames,
|
|
151
|
+
localResolvers
|
|
152
|
+
);
|
|
108
153
|
const orderedAlwaysPromptParams = alwaysPromptResolutionOrder.map((paramName) => alwaysPrompt.find((p) => p.name === paramName)).filter((param) => param !== void 0);
|
|
109
154
|
for (const param of orderedAlwaysPromptParams) {
|
|
110
155
|
try {
|
|
111
|
-
const value = await this.resolveParameter(
|
|
156
|
+
const value = await this.resolveParameter(
|
|
157
|
+
param,
|
|
158
|
+
context,
|
|
159
|
+
functionName
|
|
160
|
+
);
|
|
112
161
|
this.setNestedValue(resolvedParams, param.path, value);
|
|
113
162
|
context.resolvedParams = resolvedParams;
|
|
114
163
|
} catch (error) {
|
|
@@ -132,11 +181,18 @@ var SchemaParameterResolver = class {
|
|
|
132
181
|
]);
|
|
133
182
|
if (shouldResolveOptional.resolveOptional) {
|
|
134
183
|
const optionalParamNames = trulyOptional.map((p) => p.name);
|
|
135
|
-
const optionalResolutionOrder =
|
|
184
|
+
const optionalResolutionOrder = getLocalResolutionOrderForParams(
|
|
185
|
+
optionalParamNames,
|
|
186
|
+
localResolvers
|
|
187
|
+
);
|
|
136
188
|
const orderedOptionalParams = optionalResolutionOrder.map((paramName) => trulyOptional.find((p) => p.name === paramName)).filter((param) => param !== void 0);
|
|
137
189
|
for (const param of orderedOptionalParams) {
|
|
138
190
|
try {
|
|
139
|
-
const value = await this.resolveParameter(
|
|
191
|
+
const value = await this.resolveParameter(
|
|
192
|
+
param,
|
|
193
|
+
context,
|
|
194
|
+
functionName
|
|
195
|
+
);
|
|
140
196
|
this.setNestedValue(resolvedParams, param.path, value);
|
|
141
197
|
context.resolvedParams = resolvedParams;
|
|
142
198
|
} catch (error) {
|
|
@@ -195,8 +251,8 @@ var SchemaParameterResolver = class {
|
|
|
195
251
|
isRequired
|
|
196
252
|
};
|
|
197
253
|
}
|
|
198
|
-
async resolveParameter(param, context) {
|
|
199
|
-
const resolver = getResolver(param.name);
|
|
254
|
+
async resolveParameter(param, context, functionName) {
|
|
255
|
+
const resolver = this.getResolver(param.name, context.sdk, functionName);
|
|
200
256
|
if (!resolver) {
|
|
201
257
|
throw new Error(`No resolver found for parameter: ${param.name}`);
|
|
202
258
|
}
|
|
@@ -247,7 +303,7 @@ var SchemaParameterResolver = class {
|
|
|
247
303
|
const inputs = {};
|
|
248
304
|
let processedFieldKeys = /* @__PURE__ */ new Set();
|
|
249
305
|
let iteration = 0;
|
|
250
|
-
const maxIterations =
|
|
306
|
+
const maxIterations = 10;
|
|
251
307
|
while (iteration < maxIterations) {
|
|
252
308
|
iteration++;
|
|
253
309
|
const updatedContext = {
|
|
@@ -262,11 +318,11 @@ var SchemaParameterResolver = class {
|
|
|
262
318
|
`Fetching input fields for ${param.name}${iteration > 1 ? ` (iteration ${iteration})` : ""}...`
|
|
263
319
|
)
|
|
264
320
|
);
|
|
265
|
-
const
|
|
321
|
+
const rootFieldItems = await typedResolver.fetch(
|
|
266
322
|
updatedContext.sdk,
|
|
267
323
|
updatedContext.resolvedParams
|
|
268
324
|
);
|
|
269
|
-
if (!
|
|
325
|
+
if (!rootFieldItems || rootFieldItems.length === 0) {
|
|
270
326
|
if (iteration === 1) {
|
|
271
327
|
console.log(
|
|
272
328
|
chalk3.yellow(`No input fields required for this action.`)
|
|
@@ -274,47 +330,125 @@ var SchemaParameterResolver = class {
|
|
|
274
330
|
}
|
|
275
331
|
break;
|
|
276
332
|
}
|
|
277
|
-
const
|
|
278
|
-
|
|
333
|
+
const fieldStats = await this.processFieldItems(
|
|
334
|
+
rootFieldItems,
|
|
335
|
+
inputs,
|
|
336
|
+
processedFieldKeys,
|
|
337
|
+
[],
|
|
338
|
+
iteration
|
|
279
339
|
);
|
|
280
|
-
if (
|
|
340
|
+
if (fieldStats.newRequired === 0 && fieldStats.newOptional === 0) {
|
|
281
341
|
break;
|
|
282
342
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
343
|
+
if (fieldStats.newRequired === 0 && fieldStats.optionalSkipped) {
|
|
344
|
+
break;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
if (iteration >= maxIterations) {
|
|
348
|
+
console.log(
|
|
349
|
+
chalk3.yellow(
|
|
350
|
+
`
|
|
351
|
+
\u26A0\uFE0F Maximum field resolution iterations reached. Some dynamic fields may not have been discovered.`
|
|
352
|
+
)
|
|
288
353
|
);
|
|
289
|
-
|
|
354
|
+
}
|
|
355
|
+
return inputs;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Recursively processes fieldsets and their fields, maintaining natural structure
|
|
359
|
+
* and creating nested inputs as needed (e.g., fieldset "foo" becomes inputs.foo = [{}])
|
|
360
|
+
*/
|
|
361
|
+
async processFieldItems(items, targetInputs, processedFieldKeys, fieldsetPath = [], iteration = 1) {
|
|
362
|
+
let newRequiredCount = 0;
|
|
363
|
+
let newOptionalCount = 0;
|
|
364
|
+
let optionalSkipped = false;
|
|
365
|
+
for (const item of items) {
|
|
366
|
+
const typedItem = item;
|
|
367
|
+
if (typedItem.type === "fieldset" && typedItem.fields && typedItem.key) {
|
|
368
|
+
const fieldsetTitle = typedItem.title || typedItem.key;
|
|
369
|
+
const pathDisplay = fieldsetPath.length > 0 ? ` (in ${fieldsetPath.join(" > ")})` : "";
|
|
290
370
|
console.log(
|
|
291
|
-
chalk3.
|
|
371
|
+
chalk3.cyan(
|
|
292
372
|
`
|
|
293
|
-
\u{
|
|
373
|
+
\u{1F4C1} Processing fieldset: ${fieldsetTitle}${pathDisplay}`
|
|
294
374
|
)
|
|
295
375
|
);
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
376
|
+
if (!targetInputs[typedItem.key]) {
|
|
377
|
+
targetInputs[typedItem.key] = [{}];
|
|
378
|
+
}
|
|
379
|
+
const fieldsetTarget = targetInputs[typedItem.key][0];
|
|
380
|
+
const nestedPath = [...fieldsetPath, fieldsetTitle];
|
|
381
|
+
const nestedStats = await this.processFieldItems(
|
|
382
|
+
typedItem.fields,
|
|
383
|
+
fieldsetTarget,
|
|
384
|
+
processedFieldKeys,
|
|
385
|
+
nestedPath,
|
|
386
|
+
iteration
|
|
387
|
+
);
|
|
388
|
+
newRequiredCount += nestedStats.newRequired;
|
|
389
|
+
newOptionalCount += nestedStats.newOptional;
|
|
390
|
+
if (nestedStats.optionalSkipped) {
|
|
391
|
+
optionalSkipped = true;
|
|
392
|
+
}
|
|
393
|
+
} else if (typedItem.type === "input_field" && typedItem.key) {
|
|
394
|
+
if (processedFieldKeys.has(typedItem.key)) {
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
const isRequired = typedItem.is_required || false;
|
|
398
|
+
if (isRequired) {
|
|
399
|
+
newRequiredCount++;
|
|
400
|
+
if (newRequiredCount === 1 && fieldsetPath.length === 0) {
|
|
401
|
+
console.log(
|
|
402
|
+
chalk3.blue(
|
|
403
|
+
`
|
|
404
|
+
\u{1F4DD} Please provide values for the following ${iteration === 1 ? "" : "additional "}input fields:`
|
|
405
|
+
)
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
await this.promptForField(typedItem, targetInputs);
|
|
409
|
+
processedFieldKeys.add(typedItem.key);
|
|
410
|
+
} else {
|
|
411
|
+
newOptionalCount++;
|
|
299
412
|
}
|
|
300
413
|
}
|
|
301
|
-
|
|
302
|
-
|
|
414
|
+
}
|
|
415
|
+
if (newOptionalCount > 0) {
|
|
416
|
+
const optionalFields = items.filter((item) => {
|
|
417
|
+
const typedItem = item;
|
|
418
|
+
return typedItem.type === "input_field" && typedItem.key && !typedItem.is_required && !processedFieldKeys.has(typedItem.key);
|
|
419
|
+
});
|
|
420
|
+
if (optionalFields.length > 0) {
|
|
421
|
+
const pathContext = fieldsetPath.length > 0 ? ` in ${fieldsetPath.join(" > ")}` : "";
|
|
303
422
|
console.log(
|
|
304
423
|
chalk3.gray(
|
|
305
424
|
`
|
|
306
|
-
There are ${
|
|
425
|
+
There are ${optionalFields.length} ${iteration === 1 ? "" : "additional "}optional field(s) available${pathContext}.`
|
|
307
426
|
)
|
|
308
427
|
);
|
|
309
428
|
try {
|
|
310
|
-
shouldConfigureOptional = await inquirer.prompt([
|
|
429
|
+
const shouldConfigureOptional = await inquirer.prompt([
|
|
311
430
|
{
|
|
312
431
|
type: "confirm",
|
|
313
432
|
name: "configure",
|
|
314
|
-
message: `Would you like to configure ${iteration === 1 ? "" : "these additional "}optional fields?`,
|
|
433
|
+
message: `Would you like to configure ${iteration === 1 ? "" : "these additional "}optional fields${pathContext}?`,
|
|
315
434
|
default: false
|
|
316
435
|
}
|
|
317
436
|
]);
|
|
437
|
+
if (shouldConfigureOptional.configure) {
|
|
438
|
+
console.log(chalk3.cyan(`
|
|
439
|
+
Optional fields${pathContext}:`));
|
|
440
|
+
for (const field of optionalFields) {
|
|
441
|
+
await this.promptForField(field, targetInputs);
|
|
442
|
+
const typedField = field;
|
|
443
|
+
processedFieldKeys.add(typedField.key);
|
|
444
|
+
}
|
|
445
|
+
} else {
|
|
446
|
+
optionalSkipped = true;
|
|
447
|
+
optionalFields.forEach((field) => {
|
|
448
|
+
const typedField = field;
|
|
449
|
+
processedFieldKeys.add(typedField.key);
|
|
450
|
+
});
|
|
451
|
+
}
|
|
318
452
|
} catch (error) {
|
|
319
453
|
if (this.isUserCancellation(error)) {
|
|
320
454
|
console.log(chalk3.yellow("\n\nOperation cancelled by user"));
|
|
@@ -322,32 +456,13 @@ There are ${newOptionalFields.length} ${iteration === 1 ? "" : "additional "}opt
|
|
|
322
456
|
}
|
|
323
457
|
throw error;
|
|
324
458
|
}
|
|
325
|
-
if (shouldConfigureOptional.configure) {
|
|
326
|
-
console.log(chalk3.cyan(`
|
|
327
|
-
Optional fields:`));
|
|
328
|
-
for (const field of newOptionalFields) {
|
|
329
|
-
await this.promptForField(field, inputs);
|
|
330
|
-
processedFieldKeys.add(field.key);
|
|
331
|
-
}
|
|
332
|
-
} else {
|
|
333
|
-
newOptionalFields.forEach(
|
|
334
|
-
(field) => processedFieldKeys.add(field.key)
|
|
335
|
-
);
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
if (newRequiredFields.length === 0 && (!newOptionalFields.length || !shouldConfigureOptional.configure)) {
|
|
339
|
-
break;
|
|
340
459
|
}
|
|
341
460
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
)
|
|
348
|
-
);
|
|
349
|
-
}
|
|
350
|
-
return inputs;
|
|
461
|
+
return {
|
|
462
|
+
newRequired: newRequiredCount,
|
|
463
|
+
newOptional: newOptionalCount,
|
|
464
|
+
optionalSkipped
|
|
465
|
+
};
|
|
351
466
|
}
|
|
352
467
|
getNestedValue(obj, path2) {
|
|
353
468
|
return path2.reduce(
|
|
@@ -371,7 +486,7 @@ Optional fields:`));
|
|
|
371
486
|
const fieldPrompt = {
|
|
372
487
|
type: fieldObj.type === "boolean" ? "confirm" : "input",
|
|
373
488
|
name: fieldObj.key,
|
|
374
|
-
message: `${fieldObj.label || fieldObj.key}${fieldObj.
|
|
489
|
+
message: `${fieldObj.label || fieldObj.key}${fieldObj.is_required ? " (required)" : " (optional)"}:`
|
|
375
490
|
};
|
|
376
491
|
if (fieldObj.helpText) {
|
|
377
492
|
fieldPrompt.prefix = chalk3.gray(`\u2139 ${fieldObj.helpText}
|
|
@@ -396,7 +511,7 @@ Optional fields:`));
|
|
|
396
511
|
const answer = await inquirer.prompt([fieldPrompt]);
|
|
397
512
|
if (answer[fieldObj.key] !== void 0 && answer[fieldObj.key] !== "") {
|
|
398
513
|
inputs[fieldObj.key] = answer[fieldObj.key];
|
|
399
|
-
} else if (fieldObj.
|
|
514
|
+
} else if (fieldObj.is_required) {
|
|
400
515
|
throw new Error(`Required field ${fieldObj.key} cannot be empty`);
|
|
401
516
|
}
|
|
402
517
|
} catch (error) {
|
|
@@ -411,6 +526,40 @@ Optional fields:`));
|
|
|
411
526
|
const errorObj = error;
|
|
412
527
|
return errorObj?.name === "ExitPromptError" || errorObj?.message?.includes("User force closed") || errorObj?.isTTYError === true;
|
|
413
528
|
}
|
|
529
|
+
hasResolver(paramName, sdk2, functionName) {
|
|
530
|
+
if (functionName && typeof sdk2.getRegistry === "function") {
|
|
531
|
+
const registry = sdk2.getRegistry();
|
|
532
|
+
const functionInfo = registry.functions.find(
|
|
533
|
+
(f) => f.name === functionName
|
|
534
|
+
);
|
|
535
|
+
if (functionInfo && functionInfo.resolvers?.[paramName]) {
|
|
536
|
+
return true;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
return false;
|
|
540
|
+
}
|
|
541
|
+
getResolver(paramName, sdk2, functionName) {
|
|
542
|
+
if (functionName && typeof sdk2.getRegistry === "function") {
|
|
543
|
+
const registry = sdk2.getRegistry();
|
|
544
|
+
const functionInfo = registry.functions.find(
|
|
545
|
+
(f) => f.name === functionName
|
|
546
|
+
);
|
|
547
|
+
if (functionInfo && functionInfo.resolvers?.[paramName]) {
|
|
548
|
+
return functionInfo.resolvers[paramName];
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
return null;
|
|
552
|
+
}
|
|
553
|
+
getLocalResolvers(sdk2, functionName) {
|
|
554
|
+
if (!functionName || typeof sdk2.getRegistry !== "function") {
|
|
555
|
+
return {};
|
|
556
|
+
}
|
|
557
|
+
const registry = sdk2.getRegistry();
|
|
558
|
+
const functionInfo = registry.functions.find(
|
|
559
|
+
(f) => f.name === functionName
|
|
560
|
+
);
|
|
561
|
+
return functionInfo?.resolvers || {};
|
|
562
|
+
}
|
|
414
563
|
};
|
|
415
564
|
function getFormatMetadata(schema) {
|
|
416
565
|
return schema?._def?.formatMeta;
|
|
@@ -418,8 +567,16 @@ function getFormatMetadata(schema) {
|
|
|
418
567
|
function getOutputSchema(schema) {
|
|
419
568
|
return schema?._def?.outputSchema;
|
|
420
569
|
}
|
|
421
|
-
function
|
|
422
|
-
|
|
570
|
+
function formatJsonOutput(data) {
|
|
571
|
+
if (data === void 0) {
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
console.log(
|
|
575
|
+
util.inspect(data, { colors: true, depth: null, breakLength: 80 })
|
|
576
|
+
);
|
|
577
|
+
}
|
|
578
|
+
function formatItemsFromSchema(functionInfo, items, startingNumber = 0) {
|
|
579
|
+
const outputSchema = functionInfo.outputSchema || getOutputSchema(functionInfo.inputSchema);
|
|
423
580
|
if (!outputSchema) {
|
|
424
581
|
formatItemsGeneric(items, startingNumber);
|
|
425
582
|
return;
|
|
@@ -430,16 +587,26 @@ function formatItemsFromSchema(inputSchema, items, startingNumber = 0) {
|
|
|
430
587
|
return;
|
|
431
588
|
}
|
|
432
589
|
items.forEach((item, index) => {
|
|
433
|
-
|
|
590
|
+
const formatted = formatMeta.format(item);
|
|
591
|
+
formatSingleItem(formatted, startingNumber + index);
|
|
434
592
|
});
|
|
435
593
|
}
|
|
436
|
-
function formatSingleItem(
|
|
437
|
-
const formatted = formatMeta.format(item);
|
|
594
|
+
function formatSingleItem(formatted, itemNumber) {
|
|
438
595
|
let titleLine = `${chalk3.gray(`${itemNumber + 1}.`)} ${chalk3.cyan(formatted.title)}`;
|
|
439
|
-
if (formatted.
|
|
440
|
-
titleLine += ` ${chalk3.gray(formatted.
|
|
596
|
+
if (formatted.id) {
|
|
597
|
+
titleLine += ` ${chalk3.gray(`(ID: ${formatted.id})`)}`;
|
|
598
|
+
} else if (formatted.key) {
|
|
599
|
+
titleLine += ` ${chalk3.gray(`(${formatted.key})`)}`;
|
|
441
600
|
}
|
|
442
601
|
console.log(titleLine);
|
|
602
|
+
if (formatted.description) {
|
|
603
|
+
console.log(` ${chalk3.dim(formatted.description)}`);
|
|
604
|
+
}
|
|
605
|
+
if (formatted.data !== void 0) {
|
|
606
|
+
formatJsonOutput(formatted.data);
|
|
607
|
+
console.log();
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
443
610
|
for (const detail of formatted.details) {
|
|
444
611
|
const styledText = applyStyle(detail.text, detail.style);
|
|
445
612
|
console.log(` ${styledText}`);
|
|
@@ -461,40 +628,36 @@ function applyStyle(value, style) {
|
|
|
461
628
|
return chalk3.blue(value);
|
|
462
629
|
}
|
|
463
630
|
}
|
|
631
|
+
function convertGenericItemToFormattedItem(item) {
|
|
632
|
+
const itemObj = item;
|
|
633
|
+
return {
|
|
634
|
+
title: itemObj.title || itemObj.name || itemObj.key || itemObj.id || "Item",
|
|
635
|
+
id: itemObj.id,
|
|
636
|
+
key: itemObj.key,
|
|
637
|
+
description: itemObj.description,
|
|
638
|
+
details: []
|
|
639
|
+
};
|
|
640
|
+
}
|
|
464
641
|
function formatItemsGeneric(items, startingNumber = 0) {
|
|
465
642
|
items.forEach((item, index) => {
|
|
466
|
-
const
|
|
467
|
-
|
|
468
|
-
console.log(
|
|
469
|
-
`${chalk3.gray(`${startingNumber + index + 1}.`)} ${chalk3.cyan(name)}`
|
|
470
|
-
);
|
|
471
|
-
if (itemObj.description) {
|
|
472
|
-
console.log(` ${chalk3.dim(itemObj.description)}`);
|
|
473
|
-
}
|
|
474
|
-
console.log();
|
|
643
|
+
const formatted = convertGenericItemToFormattedItem(item);
|
|
644
|
+
formatSingleItem(formatted, startingNumber + index);
|
|
475
645
|
});
|
|
476
646
|
}
|
|
477
|
-
function
|
|
478
|
-
if (data === void 0) {
|
|
479
|
-
return;
|
|
480
|
-
}
|
|
481
|
-
if (data && typeof data === "object" && !Array.isArray(data) && (data.success !== void 0 || data.id || data.status)) {
|
|
482
|
-
console.log(chalk3.green("\u2705 Action completed successfully!\n"));
|
|
483
|
-
}
|
|
484
|
-
console.log(
|
|
485
|
-
util.inspect(data, { colors: true, depth: null, breakLength: 80 })
|
|
486
|
-
);
|
|
487
|
-
}
|
|
488
|
-
function analyzeZodSchema(schema) {
|
|
647
|
+
function analyzeZodSchema(schema, functionInfo) {
|
|
489
648
|
const parameters = [];
|
|
490
649
|
if (schema._def && schema._def.typeName === "ZodEffects") {
|
|
491
650
|
const innerSchema = schema._def.schema;
|
|
492
|
-
return analyzeZodSchema(innerSchema);
|
|
651
|
+
return analyzeZodSchema(innerSchema, functionInfo);
|
|
493
652
|
}
|
|
494
653
|
if (schema instanceof z.ZodObject) {
|
|
495
654
|
const shape = schema.shape;
|
|
496
655
|
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
497
|
-
const param = analyzeZodField(
|
|
656
|
+
const param = analyzeZodField(
|
|
657
|
+
key,
|
|
658
|
+
fieldSchema,
|
|
659
|
+
functionInfo
|
|
660
|
+
);
|
|
498
661
|
if (param) {
|
|
499
662
|
parameters.push(param);
|
|
500
663
|
}
|
|
@@ -502,7 +665,7 @@ function analyzeZodSchema(schema) {
|
|
|
502
665
|
}
|
|
503
666
|
return parameters;
|
|
504
667
|
}
|
|
505
|
-
function analyzeZodField(name, schema) {
|
|
668
|
+
function analyzeZodField(name, schema, functionInfo) {
|
|
506
669
|
let baseSchema = schema;
|
|
507
670
|
let required = true;
|
|
508
671
|
let defaultValue = void 0;
|
|
@@ -536,6 +699,10 @@ function analyzeZodField(name, schema) {
|
|
|
536
699
|
} else if (baseSchema instanceof z.ZodRecord) {
|
|
537
700
|
paramType = "string";
|
|
538
701
|
}
|
|
702
|
+
let paramHasResolver = false;
|
|
703
|
+
if (functionInfo?.resolvers?.[name]) {
|
|
704
|
+
paramHasResolver = true;
|
|
705
|
+
}
|
|
539
706
|
return {
|
|
540
707
|
name,
|
|
541
708
|
type: paramType,
|
|
@@ -543,7 +710,7 @@ function analyzeZodField(name, schema) {
|
|
|
543
710
|
description: schema.description,
|
|
544
711
|
default: defaultValue,
|
|
545
712
|
choices,
|
|
546
|
-
hasResolver:
|
|
713
|
+
hasResolver: paramHasResolver,
|
|
547
714
|
isPositional: isPositional(schema)
|
|
548
715
|
};
|
|
549
716
|
}
|
|
@@ -565,12 +732,7 @@ function generateCliCommands(program2, sdk2) {
|
|
|
565
732
|
return;
|
|
566
733
|
}
|
|
567
734
|
const cliCommandName = methodNameToCliCommand(fnInfo.name);
|
|
568
|
-
const config = createCommandConfig(
|
|
569
|
-
cliCommandName,
|
|
570
|
-
fnInfo.name,
|
|
571
|
-
fnInfo.inputSchema,
|
|
572
|
-
sdk2
|
|
573
|
-
);
|
|
735
|
+
const config = createCommandConfig(cliCommandName, fnInfo, sdk2);
|
|
574
736
|
addCommand(program2, cliCommandName, config);
|
|
575
737
|
});
|
|
576
738
|
program2.configureHelp({
|
|
@@ -634,14 +796,15 @@ function generateCliCommands(program2, sdk2) {
|
|
|
634
796
|
}
|
|
635
797
|
});
|
|
636
798
|
}
|
|
637
|
-
function createCommandConfig(cliCommandName,
|
|
638
|
-
const
|
|
799
|
+
function createCommandConfig(cliCommandName, functionInfo, sdk2) {
|
|
800
|
+
const schema = functionInfo.inputSchema;
|
|
801
|
+
const parameters = analyzeZodSchema(schema, functionInfo);
|
|
639
802
|
const description = schema.description || `${cliCommandName} command`;
|
|
640
803
|
const handler = async (...args) => {
|
|
641
804
|
try {
|
|
642
805
|
const commandObj = args[args.length - 1];
|
|
643
806
|
const options = commandObj.opts();
|
|
644
|
-
const isListCommand =
|
|
807
|
+
const isListCommand = functionInfo.type === "list";
|
|
645
808
|
const hasPaginationParams = parameters.some(
|
|
646
809
|
(p) => p.name === "maxItems" || p.name === "pageSize"
|
|
647
810
|
);
|
|
@@ -656,21 +819,22 @@ function createCommandConfig(cliCommandName, sdkMethodName, schema, sdk2) {
|
|
|
656
819
|
const resolvedParams = await resolver.resolveParameters(
|
|
657
820
|
schema,
|
|
658
821
|
rawParams,
|
|
659
|
-
sdk2
|
|
822
|
+
sdk2,
|
|
823
|
+
functionInfo.name
|
|
660
824
|
);
|
|
661
825
|
if (isListCommand && hasPaginationParams && !shouldUseJson && !hasUserSpecifiedMaxItems) {
|
|
662
826
|
const sdkObj = sdk2;
|
|
663
|
-
const sdkIterator = sdkObj[
|
|
827
|
+
const sdkIterator = sdkObj[functionInfo.name](resolvedParams);
|
|
664
828
|
await handlePaginatedListWithAsyncIteration(
|
|
665
|
-
|
|
829
|
+
functionInfo.name,
|
|
666
830
|
sdkIterator,
|
|
667
|
-
|
|
831
|
+
functionInfo
|
|
668
832
|
);
|
|
669
833
|
} else {
|
|
670
834
|
const hasOutputFile = resolvedParams.output;
|
|
671
835
|
if (hasOutputFile) {
|
|
672
836
|
const sdkObj2 = sdk2;
|
|
673
|
-
await sdkObj2[
|
|
837
|
+
await sdkObj2[functionInfo.name](resolvedParams);
|
|
674
838
|
console.log(
|
|
675
839
|
chalk3.green(`\u2705 ${cliCommandName} completed successfully!`)
|
|
676
840
|
);
|
|
@@ -678,7 +842,7 @@ function createCommandConfig(cliCommandName, sdkMethodName, schema, sdk2) {
|
|
|
678
842
|
return;
|
|
679
843
|
}
|
|
680
844
|
const sdkObj = sdk2;
|
|
681
|
-
const result = await sdkObj[
|
|
845
|
+
const result = await sdkObj[functionInfo.name](resolvedParams);
|
|
682
846
|
const items = result?.data ? result.data : result;
|
|
683
847
|
if (shouldUseJson) {
|
|
684
848
|
console.log(JSON.stringify(items, null, 2));
|
|
@@ -688,8 +852,7 @@ function createCommandConfig(cliCommandName, sdkMethodName, schema, sdk2) {
|
|
|
688
852
|
resolvedParams.maxItems,
|
|
689
853
|
hasUserSpecifiedMaxItems,
|
|
690
854
|
shouldUseJson,
|
|
691
|
-
|
|
692
|
-
sdkMethodName
|
|
855
|
+
functionInfo
|
|
693
856
|
);
|
|
694
857
|
} else {
|
|
695
858
|
formatJsonOutput(items);
|
|
@@ -810,6 +973,9 @@ function convertCliArgsToSdkParams(parameters, positionalArgs, options) {
|
|
|
810
973
|
return sdkParams;
|
|
811
974
|
}
|
|
812
975
|
function convertValue(value, type) {
|
|
976
|
+
if (value === void 0) {
|
|
977
|
+
return void 0;
|
|
978
|
+
}
|
|
813
979
|
switch (type) {
|
|
814
980
|
case "number":
|
|
815
981
|
return Number(value);
|
|
@@ -829,12 +995,14 @@ function convertValue(value, type) {
|
|
|
829
995
|
return value;
|
|
830
996
|
}
|
|
831
997
|
}
|
|
832
|
-
async function handlePaginatedListWithAsyncIteration(sdkMethodName, sdkResult,
|
|
833
|
-
const itemName = getItemNameFromMethod(
|
|
998
|
+
async function handlePaginatedListWithAsyncIteration(sdkMethodName, sdkResult, functionInfo) {
|
|
999
|
+
const itemName = getItemNameFromMethod(functionInfo);
|
|
834
1000
|
let totalShown = 0;
|
|
835
1001
|
let pageCount = 0;
|
|
836
|
-
console.log(
|
|
837
|
-
|
|
1002
|
+
console.log(
|
|
1003
|
+
chalk3.blue(`\u{1F4CB} ${getListTitleFromMethod(sdkMethodName, functionInfo)}
|
|
1004
|
+
`)
|
|
1005
|
+
);
|
|
838
1006
|
try {
|
|
839
1007
|
for await (const page of sdkResult) {
|
|
840
1008
|
const items = page.data || page;
|
|
@@ -853,12 +1021,14 @@ async function handlePaginatedListWithAsyncIteration(sdkMethodName, sdkResult, s
|
|
|
853
1021
|
if (pageCount > 1) {
|
|
854
1022
|
console.clear();
|
|
855
1023
|
console.log(
|
|
856
|
-
chalk3.blue(
|
|
857
|
-
|
|
1024
|
+
chalk3.blue(
|
|
1025
|
+
`\u{1F4CB} ${getListTitleFromMethod(sdkMethodName, functionInfo)}
|
|
1026
|
+
`
|
|
1027
|
+
)
|
|
858
1028
|
);
|
|
859
1029
|
}
|
|
860
|
-
if (
|
|
861
|
-
formatItemsFromSchema(
|
|
1030
|
+
if (functionInfo) {
|
|
1031
|
+
formatItemsFromSchema(functionInfo, items, totalShown);
|
|
862
1032
|
} else {
|
|
863
1033
|
formatItemsGeneric2(items, totalShown);
|
|
864
1034
|
}
|
|
@@ -894,8 +1064,8 @@ async function handlePaginatedListWithAsyncIteration(sdkMethodName, sdkResult, s
|
|
|
894
1064
|
console.log(chalk3.yellow(`No ${itemName} found.`));
|
|
895
1065
|
return;
|
|
896
1066
|
}
|
|
897
|
-
if (
|
|
898
|
-
formatItemsFromSchema(
|
|
1067
|
+
if (functionInfo) {
|
|
1068
|
+
formatItemsFromSchema(functionInfo, items, 0);
|
|
899
1069
|
} else {
|
|
900
1070
|
formatItemsGeneric2(items, 0);
|
|
901
1071
|
}
|
|
@@ -906,7 +1076,7 @@ async function handlePaginatedListWithAsyncIteration(sdkMethodName, sdkResult, s
|
|
|
906
1076
|
}
|
|
907
1077
|
}
|
|
908
1078
|
}
|
|
909
|
-
function formatNonPaginatedResults(result, requestedMaxItems, userSpecifiedMaxItems, useRawJson,
|
|
1079
|
+
function formatNonPaginatedResults(result, requestedMaxItems, userSpecifiedMaxItems, useRawJson, functionInfo) {
|
|
910
1080
|
if (!Array.isArray(result)) {
|
|
911
1081
|
if (useRawJson) {
|
|
912
1082
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -919,7 +1089,7 @@ function formatNonPaginatedResults(result, requestedMaxItems, userSpecifiedMaxIt
|
|
|
919
1089
|
console.log(JSON.stringify(result, null, 2));
|
|
920
1090
|
return;
|
|
921
1091
|
}
|
|
922
|
-
const itemName =
|
|
1092
|
+
const itemName = functionInfo ? getItemNameFromMethod(functionInfo) : "items";
|
|
923
1093
|
if (result.length === 0) {
|
|
924
1094
|
console.log(chalk3.yellow(`No ${itemName} found.`));
|
|
925
1095
|
return;
|
|
@@ -927,8 +1097,8 @@ function formatNonPaginatedResults(result, requestedMaxItems, userSpecifiedMaxIt
|
|
|
927
1097
|
console.log(chalk3.green(`
|
|
928
1098
|
\u2705 Found ${result.length} ${itemName}:
|
|
929
1099
|
`));
|
|
930
|
-
if (
|
|
931
|
-
formatItemsFromSchema(
|
|
1100
|
+
if (functionInfo) {
|
|
1101
|
+
formatItemsFromSchema(functionInfo, result);
|
|
932
1102
|
} else {
|
|
933
1103
|
formatItemsGeneric2(result);
|
|
934
1104
|
}
|
|
@@ -957,18 +1127,17 @@ function formatItemsGeneric2(items, startingNumber = 0) {
|
|
|
957
1127
|
console.log();
|
|
958
1128
|
});
|
|
959
1129
|
}
|
|
960
|
-
function getItemNameFromMethod(
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
return listMatch[1].toLowerCase();
|
|
1130
|
+
function getItemNameFromMethod(functionInfo) {
|
|
1131
|
+
if (functionInfo.itemType) {
|
|
1132
|
+
return `${functionInfo.itemType} items`;
|
|
964
1133
|
}
|
|
965
1134
|
return "items";
|
|
966
1135
|
}
|
|
967
|
-
function getListTitleFromMethod(methodName) {
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
return
|
|
1136
|
+
function getListTitleFromMethod(methodName, functionInfo) {
|
|
1137
|
+
if (functionInfo.itemType) {
|
|
1138
|
+
return `Available ${functionInfo.itemType} items`;
|
|
1139
|
+
}
|
|
1140
|
+
return `${methodName} items`;
|
|
972
1141
|
}
|
|
973
1142
|
|
|
974
1143
|
// src/utils/constants.ts
|
|
@@ -1998,26 +2167,25 @@ var addPlugin = ({ sdk: sdk2, context }) => {
|
|
|
1998
2167
|
console.log(`\u{1F510} Found ${authentications.length} authentication(s)`);
|
|
1999
2168
|
}
|
|
2000
2169
|
for (const app of apps) {
|
|
2001
|
-
|
|
2170
|
+
const appSlugAndKey = app.slug ? `${app.slug} (${app.key})` : app.key;
|
|
2171
|
+
console.log(`\u{1F4E6} Adding ${appSlugAndKey}...`);
|
|
2002
2172
|
try {
|
|
2003
|
-
|
|
2004
|
-
const [implementationName, version] = currentImplementationId.split("@");
|
|
2005
|
-
if (!implementationName || !version) {
|
|
2173
|
+
if (!app.version) {
|
|
2006
2174
|
console.warn(
|
|
2007
|
-
`\u26A0\uFE0F Invalid implementation ID format for '${
|
|
2175
|
+
`\u26A0\uFE0F Invalid implementation ID format for '${appSlugAndKey}': ${app.implementation_id}. Expected format: <implementationName>@<version>. Skipping...`
|
|
2008
2176
|
);
|
|
2009
2177
|
continue;
|
|
2010
2178
|
}
|
|
2011
2179
|
const [manifestKey] = await context.updateManifestEntry(
|
|
2012
2180
|
app.key,
|
|
2013
2181
|
{
|
|
2014
|
-
implementationName,
|
|
2015
|
-
version
|
|
2182
|
+
implementationName: app.key,
|
|
2183
|
+
version: app.version
|
|
2016
2184
|
},
|
|
2017
2185
|
configPath
|
|
2018
2186
|
);
|
|
2019
2187
|
console.log(
|
|
2020
|
-
`\u{1F4DD} Locked ${
|
|
2188
|
+
`\u{1F4DD} Locked ${appSlugAndKey} to ${app.key}@${app.version} using key '${manifestKey}'`
|
|
2021
2189
|
);
|
|
2022
2190
|
let authenticationId;
|
|
2023
2191
|
if (authentications.length > 0) {
|
|
@@ -2027,10 +2195,12 @@ var addPlugin = ({ sdk: sdk2, context }) => {
|
|
|
2027
2195
|
if (matchingAuth) {
|
|
2028
2196
|
authenticationId = matchingAuth.id;
|
|
2029
2197
|
console.log(
|
|
2030
|
-
`\u{1F510} Using authentication ${authenticationId} (${matchingAuth.title}) for ${
|
|
2198
|
+
`\u{1F510} Using authentication ${authenticationId} (${matchingAuth.title}) for ${appSlugAndKey}`
|
|
2031
2199
|
);
|
|
2032
2200
|
} else {
|
|
2033
|
-
console.warn(
|
|
2201
|
+
console.warn(
|
|
2202
|
+
`\u26A0\uFE0F No matching authentication found for ${appSlugAndKey}`
|
|
2203
|
+
);
|
|
2034
2204
|
}
|
|
2035
2205
|
}
|
|
2036
2206
|
const typesPath = join(resolvedTypesOutput, `${manifestKey}.d.ts`);
|
|
@@ -2044,10 +2214,12 @@ var addPlugin = ({ sdk: sdk2, context }) => {
|
|
|
2044
2214
|
await writeFile(typesPath, typeDefinitions, "utf8");
|
|
2045
2215
|
console.log(`\u{1F527} Generated types for ${manifestKey} at ${typesPath}`);
|
|
2046
2216
|
} catch (error) {
|
|
2047
|
-
console.warn(
|
|
2217
|
+
console.warn(
|
|
2218
|
+
`\u26A0\uFE0F Failed to generate types for ${appSlugAndKey}: ${error}`
|
|
2219
|
+
);
|
|
2048
2220
|
}
|
|
2049
2221
|
} catch (error) {
|
|
2050
|
-
console.warn(`\u26A0\uFE0F Failed to process ${
|
|
2222
|
+
console.warn(`\u26A0\uFE0F Failed to process ${appSlugAndKey}: ${error}`);
|
|
2051
2223
|
}
|
|
2052
2224
|
}
|
|
2053
2225
|
console.log(`\u2705 Added ${apps.length} app(s) to manifest`);
|
|
@@ -2082,7 +2254,7 @@ function createZapierCliSdk(options = {}) {
|
|
|
2082
2254
|
|
|
2083
2255
|
// package.json
|
|
2084
2256
|
var package_default = {
|
|
2085
|
-
version: "0.
|
|
2257
|
+
version: "0.11.0"};
|
|
2086
2258
|
|
|
2087
2259
|
// src/cli.ts
|
|
2088
2260
|
var program = new Command();
|