@zapier/zapier-sdk-cli 0.35.1 → 0.36.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/CHANGELOG.md +21 -0
- package/README.md +232 -0
- package/dist/cli.cjs +337 -168
- package/dist/cli.mjs +335 -167
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/package.json +7 -1
- package/dist/src/utils/cli-generator.js +46 -12
- package/dist/src/utils/parameter-resolver.d.ts +11 -0
- package/dist/src/utils/parameter-resolver.js +262 -157
- package/dist/src/utils/schema-formatter.d.ts +6 -1
- package/dist/src/utils/schema-formatter.js +45 -3
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -4
package/dist/cli.mjs
CHANGED
|
@@ -4,14 +4,15 @@ import { z } from 'zod';
|
|
|
4
4
|
import { createFunction, OutputPropertySchema, DEFAULT_CONFIG_PATH, injectCliLogin, createZapierSdkWithoutRegistry, registryPlugin, ZapierError, ZapierValidationError, ZapierUnknownError, batch, toSnakeCase, buildApplicationLifecycleEvent, isCredentialsObject, isPositional, runWithTelemetryContext, formatErrorMessage, getOsInfo, getPlatformVersions, getCiPlatform, isCi, getReleaseId, getCurrentTimestamp, generateEventId } from '@zapier/zapier-sdk';
|
|
5
5
|
import inquirer from 'inquirer';
|
|
6
6
|
import chalk7 from 'chalk';
|
|
7
|
+
import ora from 'ora';
|
|
7
8
|
import util from 'util';
|
|
9
|
+
import wrapAnsi from 'wrap-ansi';
|
|
8
10
|
import * as cliLogin from '@zapier/zapier-sdk-cli-login';
|
|
9
11
|
import { logout, getConfigPath, getLoggedInUser, getPkceLoginConfig, AUTH_MODE_HEADER, getLoginStorageMode, updateLogin, getConfig } from '@zapier/zapier-sdk-cli-login';
|
|
10
12
|
import open from 'open';
|
|
11
13
|
import crypto, { createHash } from 'crypto';
|
|
12
14
|
import express from 'express';
|
|
13
15
|
import pkceChallenge from 'pkce-challenge';
|
|
14
|
-
import ora from 'ora';
|
|
15
16
|
import { startMcpServer } from '@zapier/zapier-sdk-mcp';
|
|
16
17
|
import { buildSync } from 'esbuild';
|
|
17
18
|
import * as fs from 'fs';
|
|
@@ -106,9 +107,31 @@ function getLocalResolutionOrderForParams(paramNames, resolvers) {
|
|
|
106
107
|
return order;
|
|
107
108
|
}
|
|
108
109
|
var SchemaParameterResolver = class {
|
|
110
|
+
constructor() {
|
|
111
|
+
this.debug = false;
|
|
112
|
+
this.spinner = null;
|
|
113
|
+
}
|
|
114
|
+
debugLog(message) {
|
|
115
|
+
if (this.debug) {
|
|
116
|
+
this.stopSpinner();
|
|
117
|
+
console.log(chalk7.gray(`[Zapier CLI] ${message}`));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
startSpinner() {
|
|
121
|
+
if (!this.debug && !this.spinner) {
|
|
122
|
+
this.spinner = ora({ text: "", spinner: "dots" }).start();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
stopSpinner() {
|
|
126
|
+
if (this.spinner) {
|
|
127
|
+
this.spinner.stop();
|
|
128
|
+
this.spinner = null;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
109
131
|
async resolveParameters(schema, providedParams, sdk2, functionName, options) {
|
|
110
132
|
return runWithTelemetryContext(async () => {
|
|
111
|
-
|
|
133
|
+
this.debug = options?.debug ?? false;
|
|
134
|
+
const interactiveMode = (options?.interactiveMode ?? true) && !!process.stdin.isTTY;
|
|
112
135
|
const parseResult = schema.safeParse(providedParams);
|
|
113
136
|
const allParams = this.extractParametersFromSchema(schema);
|
|
114
137
|
const resolvableParams = allParams.filter(
|
|
@@ -118,27 +141,18 @@ var SchemaParameterResolver = class {
|
|
|
118
141
|
const hasValue = this.getNestedValue(providedParams, param.path) !== void 0;
|
|
119
142
|
return !hasValue;
|
|
120
143
|
});
|
|
121
|
-
const
|
|
144
|
+
const required = missingResolvable.filter((param) => {
|
|
122
145
|
if (param.isRequired) return true;
|
|
123
|
-
if (param.name === "inputs")
|
|
124
|
-
return interactiveMode;
|
|
125
|
-
}
|
|
146
|
+
if (param.name === "inputs") return interactiveMode;
|
|
126
147
|
return false;
|
|
127
148
|
});
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
if (param.name === "connectionId") {
|
|
131
|
-
return true;
|
|
132
|
-
}
|
|
133
|
-
return false;
|
|
134
|
-
});
|
|
135
|
-
const trulyOptional = missingResolvable.filter(
|
|
136
|
-
(param) => !functionallyRequired.includes(param) && !alwaysPrompt.includes(param)
|
|
149
|
+
const optional = missingResolvable.filter(
|
|
150
|
+
(param) => !required.includes(param)
|
|
137
151
|
);
|
|
138
|
-
if (parseResult.success &&
|
|
152
|
+
if (parseResult.success && required.length === 0 && optional.length === 0) {
|
|
139
153
|
return parseResult.data;
|
|
140
154
|
}
|
|
141
|
-
if (
|
|
155
|
+
if (required.length === 0 && optional.length === 0) {
|
|
142
156
|
if (!parseResult.success) {
|
|
143
157
|
throw new ZapierCliValidationError(formatZodError(parseResult.error));
|
|
144
158
|
}
|
|
@@ -152,19 +166,16 @@ var SchemaParameterResolver = class {
|
|
|
152
166
|
functionName
|
|
153
167
|
};
|
|
154
168
|
const localResolvers = this.getLocalResolvers(sdk2, functionName);
|
|
155
|
-
if (
|
|
156
|
-
const requiredParamNames =
|
|
169
|
+
if (required.length > 0) {
|
|
170
|
+
const requiredParamNames = required.map((p) => p.name);
|
|
157
171
|
const requiredResolutionOrder = getLocalResolutionOrderForParams(
|
|
158
172
|
requiredParamNames,
|
|
159
173
|
localResolvers
|
|
160
174
|
);
|
|
161
175
|
const orderedRequiredParams = requiredResolutionOrder.map((paramName) => {
|
|
162
|
-
let param =
|
|
176
|
+
let param = required.find((p) => p.name === paramName);
|
|
163
177
|
if (!param) {
|
|
164
|
-
param =
|
|
165
|
-
}
|
|
166
|
-
if (!param) {
|
|
167
|
-
param = trulyOptional.find((p) => p.name === paramName);
|
|
178
|
+
param = optional.find((p) => p.name === paramName);
|
|
168
179
|
}
|
|
169
180
|
return param;
|
|
170
181
|
}).filter((param) => param !== void 0);
|
|
@@ -197,33 +208,31 @@ var SchemaParameterResolver = class {
|
|
|
197
208
|
const resolvedParamNames = new Set(
|
|
198
209
|
orderedRequiredParams.map((p) => p.name)
|
|
199
210
|
);
|
|
200
|
-
|
|
201
|
-
0,
|
|
202
|
-
alwaysPrompt.length,
|
|
203
|
-
...alwaysPrompt.filter((p) => !resolvedParamNames.has(p.name))
|
|
204
|
-
);
|
|
205
|
-
trulyOptional.splice(
|
|
211
|
+
optional.splice(
|
|
206
212
|
0,
|
|
207
|
-
|
|
208
|
-
...
|
|
213
|
+
optional.length,
|
|
214
|
+
...optional.filter((p) => !resolvedParamNames.has(p.name))
|
|
209
215
|
);
|
|
210
216
|
}
|
|
211
|
-
if (interactiveMode &&
|
|
212
|
-
const
|
|
213
|
-
const
|
|
214
|
-
|
|
217
|
+
if (interactiveMode && optional.length > 0) {
|
|
218
|
+
const optionalParamNames = optional.map((p) => p.name);
|
|
219
|
+
const optionalResolutionOrder = getLocalResolutionOrderForParams(
|
|
220
|
+
optionalParamNames,
|
|
215
221
|
localResolvers
|
|
216
222
|
);
|
|
217
|
-
const
|
|
218
|
-
for (const param of
|
|
223
|
+
const orderedOptionalParams = optionalResolutionOrder.map((paramName) => optional.find((p) => p.name === paramName)).filter((param) => param !== void 0);
|
|
224
|
+
for (const param of orderedOptionalParams) {
|
|
219
225
|
try {
|
|
220
226
|
const value = await this.resolveParameter(
|
|
221
227
|
param,
|
|
222
228
|
context,
|
|
223
|
-
functionName
|
|
229
|
+
functionName,
|
|
230
|
+
{ isOptional: true }
|
|
224
231
|
);
|
|
225
|
-
|
|
226
|
-
|
|
232
|
+
if (value !== void 0) {
|
|
233
|
+
this.setNestedValue(resolvedParams, param.path, value);
|
|
234
|
+
context.resolvedParams = resolvedParams;
|
|
235
|
+
}
|
|
227
236
|
} catch (error) {
|
|
228
237
|
if (this.isUserCancellation(error)) {
|
|
229
238
|
console.log(chalk7.yellow("\n\nOperation cancelled by user"));
|
|
@@ -233,44 +242,6 @@ var SchemaParameterResolver = class {
|
|
|
233
242
|
}
|
|
234
243
|
}
|
|
235
244
|
}
|
|
236
|
-
if (interactiveMode && trulyOptional.length > 0) {
|
|
237
|
-
const optionalNames = trulyOptional.map((p) => p.name).join(", ");
|
|
238
|
-
const shouldResolveOptional = await inquirer.prompt([
|
|
239
|
-
{
|
|
240
|
-
type: "confirm",
|
|
241
|
-
name: "resolveOptional",
|
|
242
|
-
message: `Would you like to be prompted for optional parameters (${optionalNames})?`,
|
|
243
|
-
default: false
|
|
244
|
-
}
|
|
245
|
-
]);
|
|
246
|
-
if (shouldResolveOptional.resolveOptional) {
|
|
247
|
-
const optionalParamNames = trulyOptional.map((p) => p.name);
|
|
248
|
-
const optionalResolutionOrder = getLocalResolutionOrderForParams(
|
|
249
|
-
optionalParamNames,
|
|
250
|
-
localResolvers
|
|
251
|
-
);
|
|
252
|
-
const orderedOptionalParams = optionalResolutionOrder.map((paramName) => trulyOptional.find((p) => p.name === paramName)).filter(
|
|
253
|
-
(param) => param !== void 0
|
|
254
|
-
);
|
|
255
|
-
for (const param of orderedOptionalParams) {
|
|
256
|
-
try {
|
|
257
|
-
const value = await this.resolveParameter(
|
|
258
|
-
param,
|
|
259
|
-
context,
|
|
260
|
-
functionName
|
|
261
|
-
);
|
|
262
|
-
this.setNestedValue(resolvedParams, param.path, value);
|
|
263
|
-
context.resolvedParams = resolvedParams;
|
|
264
|
-
} catch (error) {
|
|
265
|
-
if (this.isUserCancellation(error)) {
|
|
266
|
-
console.log(chalk7.yellow("\n\nOperation cancelled by user"));
|
|
267
|
-
throw new ZapierCliUserCancellationError();
|
|
268
|
-
}
|
|
269
|
-
throw error;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
245
|
const finalResult = schema.safeParse(resolvedParams);
|
|
275
246
|
if (!finalResult.success) {
|
|
276
247
|
throw new ZapierCliValidationError(
|
|
@@ -365,7 +336,7 @@ var SchemaParameterResolver = class {
|
|
|
365
336
|
throw new ZapierCliMissingParametersError(missingParams);
|
|
366
337
|
}
|
|
367
338
|
}
|
|
368
|
-
async resolveParameter(param, context, functionName) {
|
|
339
|
+
async resolveParameter(param, context, functionName, options) {
|
|
369
340
|
const resolver = this.getResolver(
|
|
370
341
|
param.name,
|
|
371
342
|
context.sdk,
|
|
@@ -374,53 +345,102 @@ var SchemaParameterResolver = class {
|
|
|
374
345
|
if (!resolver) {
|
|
375
346
|
throw new Error(`No resolver found for parameter: ${param.name}`);
|
|
376
347
|
}
|
|
377
|
-
|
|
378
|
-
|
|
348
|
+
return this.resolveWithResolver(resolver, param, context, {
|
|
349
|
+
isOptional: options?.isOptional
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
async resolveWithResolver(resolver, param, context, options = {}) {
|
|
353
|
+
const { arrayIndex, isOptional } = options;
|
|
354
|
+
const inArrayContext = arrayIndex != null;
|
|
355
|
+
const promptLabel = inArrayContext ? `${param.name}[${arrayIndex}]` : param.name;
|
|
356
|
+
const promptName = inArrayContext ? "value" : param.name;
|
|
357
|
+
this.debugLog(`Resolving ${promptLabel}${isOptional ? " (optional)" : ""}`);
|
|
379
358
|
if (resolver.type === "static") {
|
|
380
359
|
const staticResolver = resolver;
|
|
381
360
|
const promptConfig = {
|
|
382
361
|
type: staticResolver.inputType === "password" ? "password" : "input",
|
|
383
|
-
name:
|
|
384
|
-
message: `Enter ${
|
|
362
|
+
name: promptName,
|
|
363
|
+
message: `Enter ${promptLabel}${isOptional ? " (optional)" : ""}:`,
|
|
385
364
|
...staticResolver.placeholder && {
|
|
386
365
|
default: staticResolver.placeholder
|
|
387
366
|
}
|
|
388
367
|
};
|
|
368
|
+
this.stopSpinner();
|
|
389
369
|
const answers = await inquirer.prompt([promptConfig]);
|
|
390
|
-
|
|
370
|
+
const value = answers[promptName];
|
|
371
|
+
if (isOptional && (value === void 0 || value === "")) {
|
|
372
|
+
return void 0;
|
|
373
|
+
}
|
|
374
|
+
return value;
|
|
391
375
|
} else if (resolver.type === "dynamic") {
|
|
392
376
|
const dynamicResolver = resolver;
|
|
377
|
+
this.startSpinner();
|
|
393
378
|
const autoResolution = await this.tryAutoResolve(
|
|
394
379
|
dynamicResolver,
|
|
395
380
|
context
|
|
396
381
|
);
|
|
397
382
|
if (autoResolution != null) {
|
|
383
|
+
this.stopSpinner();
|
|
398
384
|
return autoResolution.resolvedValue;
|
|
399
385
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
}
|
|
403
|
-
const items = await dynamicResolver.fetch(
|
|
386
|
+
this.debugLog(`Fetching options for ${promptLabel}`);
|
|
387
|
+
const fetchResult = await dynamicResolver.fetch(
|
|
404
388
|
context.sdk,
|
|
405
389
|
context.resolvedParams
|
|
406
390
|
);
|
|
407
|
-
const
|
|
391
|
+
const items = Array.isArray(fetchResult) ? fetchResult : fetchResult?.data ?? [];
|
|
408
392
|
const promptConfig = dynamicResolver.prompt(
|
|
409
|
-
|
|
393
|
+
items,
|
|
410
394
|
context.resolvedParams
|
|
411
395
|
);
|
|
396
|
+
promptConfig.name = promptName;
|
|
397
|
+
this.stopSpinner();
|
|
398
|
+
if (isOptional && promptConfig.choices) {
|
|
399
|
+
const SKIP_SENTINEL = Symbol("SKIP");
|
|
400
|
+
promptConfig.choices = [
|
|
401
|
+
{ name: chalk7.dim("(Skip)"), value: SKIP_SENTINEL },
|
|
402
|
+
...promptConfig.choices
|
|
403
|
+
];
|
|
404
|
+
const answers2 = await inquirer.prompt([promptConfig]);
|
|
405
|
+
const value = answers2[promptName];
|
|
406
|
+
if (value === SKIP_SENTINEL) {
|
|
407
|
+
return void 0;
|
|
408
|
+
}
|
|
409
|
+
return value;
|
|
410
|
+
}
|
|
412
411
|
const answers = await inquirer.prompt([promptConfig]);
|
|
413
|
-
return answers[
|
|
412
|
+
return answers[promptName];
|
|
414
413
|
} else if (resolver.type === "fields") {
|
|
414
|
+
if (isOptional && !inArrayContext) {
|
|
415
|
+
this.stopSpinner();
|
|
416
|
+
const { confirm } = await inquirer.prompt([
|
|
417
|
+
{
|
|
418
|
+
type: "confirm",
|
|
419
|
+
name: "confirm",
|
|
420
|
+
message: `Add ${promptLabel}?`,
|
|
421
|
+
default: false
|
|
422
|
+
}
|
|
423
|
+
]);
|
|
424
|
+
if (!confirm) {
|
|
425
|
+
return void 0;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
415
428
|
return await this.resolveFieldsRecursively(
|
|
429
|
+
resolver,
|
|
430
|
+
context,
|
|
431
|
+
param,
|
|
432
|
+
{ inArrayContext }
|
|
433
|
+
);
|
|
434
|
+
} else if (resolver.type === "array") {
|
|
435
|
+
return await this.resolveArrayRecursively(
|
|
416
436
|
resolver,
|
|
417
437
|
context,
|
|
418
438
|
param
|
|
419
439
|
);
|
|
420
440
|
}
|
|
421
|
-
throw new Error(`Unknown resolver type for ${
|
|
441
|
+
throw new Error(`Unknown resolver type for ${promptLabel}`);
|
|
422
442
|
}
|
|
423
|
-
async resolveFieldsRecursively(resolver, context, param) {
|
|
443
|
+
async resolveFieldsRecursively(resolver, context, param, options = {}) {
|
|
424
444
|
const inputs = {};
|
|
425
445
|
let processedFieldKeys = /* @__PURE__ */ new Set();
|
|
426
446
|
let iteration = 0;
|
|
@@ -434,15 +454,15 @@ var SchemaParameterResolver = class {
|
|
|
434
454
|
inputs
|
|
435
455
|
}
|
|
436
456
|
};
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
`Fetching input fields for ${param.name}${iteration > 1 ? ` (iteration ${iteration})` : ""}...`
|
|
440
|
-
)
|
|
457
|
+
this.debugLog(
|
|
458
|
+
`Fetching input fields for ${param.name}${iteration > 1 ? ` (iteration ${iteration})` : ""}`
|
|
441
459
|
);
|
|
460
|
+
this.startSpinner();
|
|
442
461
|
const rootFieldItems = await resolver.fetch(
|
|
443
462
|
updatedContext.sdk,
|
|
444
463
|
updatedContext.resolvedParams
|
|
445
464
|
);
|
|
465
|
+
this.stopSpinner();
|
|
446
466
|
if (!rootFieldItems || rootFieldItems.length === 0) {
|
|
447
467
|
if (iteration === 1) {
|
|
448
468
|
console.log(
|
|
@@ -457,7 +477,8 @@ var SchemaParameterResolver = class {
|
|
|
457
477
|
processedFieldKeys,
|
|
458
478
|
[],
|
|
459
479
|
iteration,
|
|
460
|
-
updatedContext
|
|
480
|
+
updatedContext,
|
|
481
|
+
{ inArrayContext: options.inArrayContext }
|
|
461
482
|
);
|
|
462
483
|
if (fieldStats.newRequired === 0 && fieldStats.newOptional === 0) {
|
|
463
484
|
break;
|
|
@@ -474,13 +495,60 @@ var SchemaParameterResolver = class {
|
|
|
474
495
|
)
|
|
475
496
|
);
|
|
476
497
|
}
|
|
498
|
+
if (resolver.transform) {
|
|
499
|
+
return resolver.transform(inputs);
|
|
500
|
+
}
|
|
477
501
|
return inputs;
|
|
478
502
|
}
|
|
503
|
+
/**
|
|
504
|
+
* Resolves an array parameter by repeatedly prompting for items until user says no
|
|
505
|
+
*/
|
|
506
|
+
async resolveArrayRecursively(resolver, context, param) {
|
|
507
|
+
const items = [];
|
|
508
|
+
const minItems = resolver.minItems ?? 0;
|
|
509
|
+
const maxItems = resolver.maxItems ?? Infinity;
|
|
510
|
+
while (items.length < maxItems) {
|
|
511
|
+
const currentIndex = items.length;
|
|
512
|
+
if (currentIndex >= minItems) {
|
|
513
|
+
this.stopSpinner();
|
|
514
|
+
const confirmAnswer = await inquirer.prompt([
|
|
515
|
+
{
|
|
516
|
+
type: "confirm",
|
|
517
|
+
name: "addItem",
|
|
518
|
+
message: `Add ${param.name}[${currentIndex}]?`,
|
|
519
|
+
default: false
|
|
520
|
+
}
|
|
521
|
+
]);
|
|
522
|
+
if (!confirmAnswer.addItem) {
|
|
523
|
+
break;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
const innerResolver = await resolver.fetch(
|
|
527
|
+
context.sdk,
|
|
528
|
+
context.resolvedParams
|
|
529
|
+
);
|
|
530
|
+
const itemValue = await this.resolveWithResolver(
|
|
531
|
+
innerResolver,
|
|
532
|
+
param,
|
|
533
|
+
context,
|
|
534
|
+
{ arrayIndex: currentIndex }
|
|
535
|
+
);
|
|
536
|
+
items.push(itemValue);
|
|
537
|
+
context.resolvedParams = {
|
|
538
|
+
...context.resolvedParams,
|
|
539
|
+
[param.name]: items
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
if (items.length >= maxItems) {
|
|
543
|
+
console.log(chalk7.gray(`Maximum of ${maxItems} items reached.`));
|
|
544
|
+
}
|
|
545
|
+
return items;
|
|
546
|
+
}
|
|
479
547
|
/**
|
|
480
548
|
* Recursively processes fieldsets and their fields, maintaining natural structure
|
|
481
549
|
* and creating nested inputs as needed (e.g., fieldset "foo" becomes inputs.foo = [{}])
|
|
482
550
|
*/
|
|
483
|
-
async processFieldItems(items, targetInputs, processedFieldKeys, fieldsetPath = [], iteration = 1, context) {
|
|
551
|
+
async processFieldItems(items, targetInputs, processedFieldKeys, fieldsetPath = [], iteration = 1, context, options = {}) {
|
|
484
552
|
let newRequiredCount = 0;
|
|
485
553
|
let newOptionalCount = 0;
|
|
486
554
|
let optionalSkipped = false;
|
|
@@ -506,7 +574,8 @@ var SchemaParameterResolver = class {
|
|
|
506
574
|
processedFieldKeys,
|
|
507
575
|
nestedPath,
|
|
508
576
|
iteration,
|
|
509
|
-
context
|
|
577
|
+
context,
|
|
578
|
+
options
|
|
510
579
|
);
|
|
511
580
|
newRequiredCount += nestedStats.newRequired;
|
|
512
581
|
newOptionalCount += nestedStats.newOptional;
|
|
@@ -520,15 +589,22 @@ var SchemaParameterResolver = class {
|
|
|
520
589
|
const isRequired = typedItem.is_required || false;
|
|
521
590
|
if (isRequired) {
|
|
522
591
|
newRequiredCount++;
|
|
523
|
-
if (
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
592
|
+
if (typedItem.resolver && context) {
|
|
593
|
+
const param = {
|
|
594
|
+
name: typedItem.key,
|
|
595
|
+
path: [typedItem.key],
|
|
596
|
+
schema: z.unknown(),
|
|
597
|
+
isRequired: true
|
|
598
|
+
};
|
|
599
|
+
targetInputs[typedItem.key] = await this.resolveWithResolver(
|
|
600
|
+
typedItem.resolver,
|
|
601
|
+
param,
|
|
602
|
+
context,
|
|
603
|
+
{ isOptional: false }
|
|
529
604
|
);
|
|
605
|
+
} else {
|
|
606
|
+
await this.promptForField(typedItem, targetInputs, context);
|
|
530
607
|
}
|
|
531
|
-
await this.promptForField(typedItem, targetInputs, context);
|
|
532
608
|
processedFieldKeys.add(typedItem.key);
|
|
533
609
|
} else {
|
|
534
610
|
newOptionalCount++;
|
|
@@ -542,42 +618,50 @@ var SchemaParameterResolver = class {
|
|
|
542
618
|
});
|
|
543
619
|
if (optionalFields.length > 0) {
|
|
544
620
|
const pathContext = fieldsetPath.length > 0 ? ` in ${fieldsetPath.join(" > ")}` : "";
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
621
|
+
if (options.inArrayContext) {
|
|
622
|
+
for (const field of optionalFields) {
|
|
623
|
+
await this.promptForField(field, targetInputs, context);
|
|
624
|
+
const typedField = field;
|
|
625
|
+
processedFieldKeys.add(typedField.key);
|
|
626
|
+
}
|
|
627
|
+
} else {
|
|
628
|
+
console.log(
|
|
629
|
+
chalk7.gray(
|
|
630
|
+
`
|
|
548
631
|
There are ${optionalFields.length} ${iteration === 1 ? "" : "additional "}optional field(s) available${pathContext}.`
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
632
|
+
)
|
|
633
|
+
);
|
|
634
|
+
try {
|
|
635
|
+
const shouldConfigureOptional = await inquirer.prompt([
|
|
636
|
+
{
|
|
637
|
+
type: "confirm",
|
|
638
|
+
name: "configure",
|
|
639
|
+
message: `Would you like to configure ${iteration === 1 ? "" : "these additional "}optional fields${pathContext}?`,
|
|
640
|
+
default: false
|
|
641
|
+
}
|
|
642
|
+
]);
|
|
643
|
+
if (shouldConfigureOptional.configure) {
|
|
644
|
+
console.log(chalk7.cyan(`
|
|
562
645
|
Optional fields${pathContext}:`));
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
646
|
+
for (const field of optionalFields) {
|
|
647
|
+
await this.promptForField(field, targetInputs, context);
|
|
648
|
+
const typedField = field;
|
|
649
|
+
processedFieldKeys.add(typedField.key);
|
|
650
|
+
}
|
|
651
|
+
} else {
|
|
652
|
+
optionalSkipped = true;
|
|
653
|
+
optionalFields.forEach((field) => {
|
|
654
|
+
const typedField = field;
|
|
655
|
+
processedFieldKeys.add(typedField.key);
|
|
656
|
+
});
|
|
567
657
|
}
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
}
|
|
575
|
-
} catch (error) {
|
|
576
|
-
if (this.isUserCancellation(error)) {
|
|
577
|
-
console.log(chalk7.yellow("\n\nOperation cancelled by user"));
|
|
578
|
-
throw new ZapierCliUserCancellationError();
|
|
658
|
+
} catch (error) {
|
|
659
|
+
if (this.isUserCancellation(error)) {
|
|
660
|
+
console.log(chalk7.yellow("\n\nOperation cancelled by user"));
|
|
661
|
+
throw new ZapierCliUserCancellationError();
|
|
662
|
+
}
|
|
663
|
+
throw error;
|
|
579
664
|
}
|
|
580
|
-
throw error;
|
|
581
665
|
}
|
|
582
666
|
}
|
|
583
667
|
}
|
|
@@ -617,10 +701,11 @@ Optional fields${pathContext}:`));
|
|
|
617
701
|
isRequired: fieldObj.is_required || false,
|
|
618
702
|
defaultValue: fieldObj.default_value ?? fieldObj.default,
|
|
619
703
|
valueType,
|
|
620
|
-
hasDropdown: fieldObj.format === "SELECT",
|
|
704
|
+
hasDropdown: fieldObj.format === "SELECT" || Boolean(fieldObj.choices),
|
|
621
705
|
isMultiSelect: Boolean(
|
|
622
706
|
valueType === "array" || fieldObj.items && fieldObj.items.type !== void 0
|
|
623
|
-
)
|
|
707
|
+
),
|
|
708
|
+
inlineChoices: fieldObj.choices
|
|
624
709
|
};
|
|
625
710
|
}
|
|
626
711
|
/**
|
|
@@ -628,11 +713,10 @@ Optional fields${pathContext}:`));
|
|
|
628
713
|
*/
|
|
629
714
|
async fetchChoices(fieldMeta, inputs, context, cursor) {
|
|
630
715
|
try {
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
cursor ? ` Fetching more choices...` : ` Fetching choices for ${fieldMeta.title}...`
|
|
634
|
-
)
|
|
716
|
+
this.debugLog(
|
|
717
|
+
cursor ? `Fetching more choices for ${fieldMeta.title}` : `Fetching choices for ${fieldMeta.title}`
|
|
635
718
|
);
|
|
719
|
+
this.startSpinner();
|
|
636
720
|
const page = await context.sdk.listInputFieldChoices({
|
|
637
721
|
appKey: context.resolvedParams.appKey,
|
|
638
722
|
actionKey: context.resolvedParams.actionKey,
|
|
@@ -642,13 +726,14 @@ Optional fields${pathContext}:`));
|
|
|
642
726
|
inputs,
|
|
643
727
|
...cursor && { cursor }
|
|
644
728
|
});
|
|
729
|
+
this.stopSpinner();
|
|
645
730
|
const choices = page.data.map((choice) => ({
|
|
646
731
|
label: choice.label || choice.key || String(choice.value),
|
|
647
732
|
value: choice.value ?? choice.key
|
|
648
733
|
}));
|
|
649
734
|
if (choices.length === 0 && !cursor) {
|
|
650
735
|
console.log(
|
|
651
|
-
chalk7.yellow(`
|
|
736
|
+
chalk7.yellow(`No choices available for ${fieldMeta.title}`)
|
|
652
737
|
);
|
|
653
738
|
}
|
|
654
739
|
return {
|
|
@@ -656,8 +741,9 @@ Optional fields${pathContext}:`));
|
|
|
656
741
|
nextCursor: page.nextCursor
|
|
657
742
|
};
|
|
658
743
|
} catch (error) {
|
|
744
|
+
this.stopSpinner();
|
|
659
745
|
console.warn(
|
|
660
|
-
chalk7.yellow(`
|
|
746
|
+
chalk7.yellow(`Failed to fetch choices for ${fieldMeta.title}:`),
|
|
661
747
|
error
|
|
662
748
|
);
|
|
663
749
|
return { choices: [] };
|
|
@@ -673,6 +759,7 @@ Optional fields${pathContext}:`));
|
|
|
673
759
|
inputs,
|
|
674
760
|
context
|
|
675
761
|
}) {
|
|
762
|
+
this.stopSpinner();
|
|
676
763
|
const choices = [...initialChoices];
|
|
677
764
|
let nextCursor = initialCursor;
|
|
678
765
|
const LOAD_MORE_SENTINEL = Symbol("LOAD_MORE");
|
|
@@ -735,6 +822,27 @@ Optional fields${pathContext}:`));
|
|
|
735
822
|
if (fieldMeta.valueType === "boolean") {
|
|
736
823
|
promptConfig.type = "confirm";
|
|
737
824
|
promptConfig.default = fieldMeta.defaultValue !== void 0 ? Boolean(fieldMeta.defaultValue) : void 0;
|
|
825
|
+
} else if (fieldMeta.valueType === "array") {
|
|
826
|
+
promptConfig.type = "input";
|
|
827
|
+
promptConfig.default = fieldMeta.defaultValue;
|
|
828
|
+
promptConfig.message = `${fieldMeta.title}${fieldMeta.isRequired ? " (required)" : " (optional)"} (JSON array or comma-separated):`;
|
|
829
|
+
promptConfig.validate = (input) => {
|
|
830
|
+
if (fieldMeta.isRequired && !input) {
|
|
831
|
+
return "This field is required";
|
|
832
|
+
}
|
|
833
|
+
return true;
|
|
834
|
+
};
|
|
835
|
+
promptConfig.filter = (input) => {
|
|
836
|
+
if (!input) return input;
|
|
837
|
+
const trimmed = input.trim();
|
|
838
|
+
if (trimmed.startsWith("[")) {
|
|
839
|
+
try {
|
|
840
|
+
return JSON.parse(trimmed);
|
|
841
|
+
} catch {
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
return trimmed.split(",").map((s) => s.trim());
|
|
845
|
+
};
|
|
738
846
|
} else {
|
|
739
847
|
promptConfig.type = "input";
|
|
740
848
|
promptConfig.default = fieldMeta.defaultValue;
|
|
@@ -782,7 +890,9 @@ Optional fields${pathContext}:`));
|
|
|
782
890
|
const fieldMeta = this.extractFieldMetadata(field);
|
|
783
891
|
let choices = [];
|
|
784
892
|
let nextCursor;
|
|
785
|
-
if (fieldMeta.
|
|
893
|
+
if (fieldMeta.inlineChoices) {
|
|
894
|
+
choices = fieldMeta.inlineChoices;
|
|
895
|
+
} else if (fieldMeta.hasDropdown && context) {
|
|
786
896
|
const result = await this.fetchChoices(fieldMeta, inputs, context);
|
|
787
897
|
choices = result.choices;
|
|
788
898
|
nextCursor = result.nextCursor;
|
|
@@ -876,7 +986,7 @@ var SHARED_COMMAND_CLI_OPTIONS = [
|
|
|
876
986
|
|
|
877
987
|
// package.json
|
|
878
988
|
var package_default = {
|
|
879
|
-
version: "0.
|
|
989
|
+
version: "0.36.1"};
|
|
880
990
|
|
|
881
991
|
// src/telemetry/builders.ts
|
|
882
992
|
function createCliBaseEvent(context = {}) {
|
|
@@ -944,7 +1054,7 @@ function formatJsonOutput(data) {
|
|
|
944
1054
|
util.inspect(data, { colors: true, depth: null, breakLength: 80 })
|
|
945
1055
|
);
|
|
946
1056
|
}
|
|
947
|
-
function formatItemsFromSchema(functionInfo, items, startingNumber = 0) {
|
|
1057
|
+
async function formatItemsFromSchema(functionInfo, items, startingNumber = 0, options) {
|
|
948
1058
|
const outputSchema = functionInfo.outputSchema || getOutputSchema(functionInfo.inputSchema);
|
|
949
1059
|
if (!outputSchema) {
|
|
950
1060
|
formatItemsGeneric(items, startingNumber);
|
|
@@ -985,11 +1095,39 @@ function formatSingleItem(formatted, itemNumber) {
|
|
|
985
1095
|
return;
|
|
986
1096
|
}
|
|
987
1097
|
for (const detail of formatted.details) {
|
|
988
|
-
|
|
989
|
-
|
|
1098
|
+
if (detail.label) {
|
|
1099
|
+
const isMultiline = detail.text.includes("\n");
|
|
1100
|
+
if (isMultiline) {
|
|
1101
|
+
console.log(` ${chalk7.gray(detail.label + ":")}`);
|
|
1102
|
+
const displayText = formatDetailText(
|
|
1103
|
+
detail.text,
|
|
1104
|
+
DETAIL_INDENT + " "
|
|
1105
|
+
);
|
|
1106
|
+
const styledText = applyStyle(displayText, detail.style);
|
|
1107
|
+
console.log(`${DETAIL_INDENT} ${styledText}`);
|
|
1108
|
+
} else {
|
|
1109
|
+
const styledValue = applyStyle(detail.text, detail.style);
|
|
1110
|
+
console.log(` ${chalk7.gray(detail.label + ":")} ${styledValue}`);
|
|
1111
|
+
}
|
|
1112
|
+
} else {
|
|
1113
|
+
const displayText = formatDetailText(detail.text, DETAIL_INDENT);
|
|
1114
|
+
const styledText = applyStyle(displayText, detail.style);
|
|
1115
|
+
console.log(` ${styledText}`);
|
|
1116
|
+
}
|
|
990
1117
|
}
|
|
991
1118
|
console.log();
|
|
992
1119
|
}
|
|
1120
|
+
var DETAIL_INDENT = " ";
|
|
1121
|
+
var DETAIL_MAX_LINES = 5;
|
|
1122
|
+
function formatDetailText(text, indent = DETAIL_INDENT) {
|
|
1123
|
+
const columns = Math.max((process.stdout.columns || 80) - indent.length, 40);
|
|
1124
|
+
const wrapped = wrapAnsi(text, columns, { hard: true, trim: false });
|
|
1125
|
+
const lines = wrapped.split("\n");
|
|
1126
|
+
if (lines.length <= DETAIL_MAX_LINES) {
|
|
1127
|
+
return lines.join("\n" + indent);
|
|
1128
|
+
}
|
|
1129
|
+
return lines.slice(0, DETAIL_MAX_LINES).join("\n" + indent) + "\n" + indent + "\u2026";
|
|
1130
|
+
}
|
|
993
1131
|
function applyStyle(value, style) {
|
|
994
1132
|
switch (style) {
|
|
995
1133
|
case "dim":
|
|
@@ -1336,15 +1474,16 @@ var CONFIRM_MESSAGES = {
|
|
|
1336
1474
|
messageBefore: "You are about to create a sensitive secret that will be displayed as plain text.\nOnce created, you cannot retrieve it again.",
|
|
1337
1475
|
messageAfter: "Please treat this secret like a password and store it securely!"
|
|
1338
1476
|
},
|
|
1339
|
-
delete: {
|
|
1340
|
-
messageBefore:
|
|
1341
|
-
}
|
|
1477
|
+
delete: (itemType) => ({
|
|
1478
|
+
messageBefore: `You are about to delete the ${itemType || "item"}.`
|
|
1479
|
+
})
|
|
1342
1480
|
};
|
|
1343
|
-
async function promptConfirm(confirmType) {
|
|
1481
|
+
async function promptConfirm(confirmType, itemType) {
|
|
1344
1482
|
if (!confirmType || !CONFIRM_MESSAGES[confirmType]) {
|
|
1345
1483
|
return { confirmed: true };
|
|
1346
1484
|
}
|
|
1347
|
-
const
|
|
1485
|
+
const configOrFn = CONFIRM_MESSAGES[confirmType];
|
|
1486
|
+
const { messageBefore, messageAfter } = typeof configOrFn === "function" ? configOrFn(itemType) : configOrFn;
|
|
1348
1487
|
console.log(chalk7.yellow(`
|
|
1349
1488
|
${messageBefore}
|
|
1350
1489
|
`));
|
|
@@ -1428,6 +1567,7 @@ function analyzeZodField(name, schema, functionInfo) {
|
|
|
1428
1567
|
}
|
|
1429
1568
|
}
|
|
1430
1569
|
let paramType = "string";
|
|
1570
|
+
let elementType;
|
|
1431
1571
|
let choices;
|
|
1432
1572
|
if (baseSchema instanceof z.ZodString) {
|
|
1433
1573
|
paramType = "string";
|
|
@@ -1437,6 +1577,14 @@ function analyzeZodField(name, schema, functionInfo) {
|
|
|
1437
1577
|
paramType = "boolean";
|
|
1438
1578
|
} else if (baseSchema instanceof z.ZodArray) {
|
|
1439
1579
|
paramType = "array";
|
|
1580
|
+
const elementSchema = baseSchema._zod.def.element;
|
|
1581
|
+
if (elementSchema instanceof z.ZodObject || elementSchema instanceof z.ZodRecord) {
|
|
1582
|
+
elementType = "object";
|
|
1583
|
+
} else if (elementSchema instanceof z.ZodNumber) {
|
|
1584
|
+
elementType = "number";
|
|
1585
|
+
} else if (elementSchema instanceof z.ZodBoolean) {
|
|
1586
|
+
elementType = "boolean";
|
|
1587
|
+
}
|
|
1440
1588
|
} else if (baseSchema instanceof z.ZodEnum) {
|
|
1441
1589
|
paramType = "string";
|
|
1442
1590
|
choices = baseSchema.options;
|
|
@@ -1455,7 +1603,8 @@ function analyzeZodField(name, schema, functionInfo) {
|
|
|
1455
1603
|
default: defaultValue,
|
|
1456
1604
|
choices,
|
|
1457
1605
|
hasResolver: paramHasResolver,
|
|
1458
|
-
isPositional: isPositional(schema)
|
|
1606
|
+
isPositional: isPositional(schema),
|
|
1607
|
+
elementType
|
|
1459
1608
|
};
|
|
1460
1609
|
}
|
|
1461
1610
|
function analyzeInputParameters(inputParameters, functionInfo) {
|
|
@@ -1642,7 +1791,10 @@ function createCommandConfig(cliCommandName, functionInfo, sdk2) {
|
|
|
1642
1791
|
rawParams,
|
|
1643
1792
|
sdk2,
|
|
1644
1793
|
functionInfo.name,
|
|
1645
|
-
{
|
|
1794
|
+
{
|
|
1795
|
+
interactiveMode,
|
|
1796
|
+
debug: !!options2.debug || process.env.DEBUG === "true" || process.argv.includes("--debug")
|
|
1797
|
+
}
|
|
1646
1798
|
);
|
|
1647
1799
|
} else {
|
|
1648
1800
|
resolvedParams = rawParams;
|
|
@@ -1650,7 +1802,10 @@ function createCommandConfig(cliCommandName, functionInfo, sdk2) {
|
|
|
1650
1802
|
const confirm = functionInfo.confirm;
|
|
1651
1803
|
let confirmMessageAfter;
|
|
1652
1804
|
if (confirm && interactiveMode) {
|
|
1653
|
-
const confirmResult = await promptConfirm(
|
|
1805
|
+
const confirmResult = await promptConfirm(
|
|
1806
|
+
confirm,
|
|
1807
|
+
functionInfo.itemType
|
|
1808
|
+
);
|
|
1654
1809
|
if (!confirmResult.confirmed) {
|
|
1655
1810
|
console.log(chalk7.yellow("Operation cancelled."));
|
|
1656
1811
|
return;
|
|
@@ -1839,7 +1994,8 @@ function convertCliArgsToSdkParams(parameters, positionalArgs, options) {
|
|
|
1839
1994
|
if ((param.required || param.isPositional) && argIndex < positionalArgs.length) {
|
|
1840
1995
|
sdkParams[param.name] = convertValue(
|
|
1841
1996
|
positionalArgs[argIndex],
|
|
1842
|
-
param.type
|
|
1997
|
+
param.type,
|
|
1998
|
+
param.elementType
|
|
1843
1999
|
);
|
|
1844
2000
|
argIndex++;
|
|
1845
2001
|
}
|
|
@@ -1851,12 +2007,12 @@ function convertCliArgsToSdkParams(parameters, positionalArgs, options) {
|
|
|
1851
2007
|
if (param.type === "array" && Array.isArray(value) && value.length === 0) {
|
|
1852
2008
|
return;
|
|
1853
2009
|
}
|
|
1854
|
-
sdkParams[camelKey] = convertValue(value, param.type);
|
|
2010
|
+
sdkParams[camelKey] = convertValue(value, param.type, param.elementType);
|
|
1855
2011
|
}
|
|
1856
2012
|
});
|
|
1857
2013
|
return sdkParams;
|
|
1858
2014
|
}
|
|
1859
|
-
function convertValue(value, type) {
|
|
2015
|
+
function convertValue(value, type, elementType) {
|
|
1860
2016
|
if (value === void 0) {
|
|
1861
2017
|
return void 0;
|
|
1862
2018
|
}
|
|
@@ -1865,8 +2021,20 @@ function convertValue(value, type) {
|
|
|
1865
2021
|
return Number(value);
|
|
1866
2022
|
case "boolean":
|
|
1867
2023
|
return Boolean(value);
|
|
1868
|
-
case "array":
|
|
1869
|
-
|
|
2024
|
+
case "array": {
|
|
2025
|
+
const arr = Array.isArray(value) ? value : [value];
|
|
2026
|
+
if (elementType !== "object") return arr;
|
|
2027
|
+
return arr.flatMap((item) => {
|
|
2028
|
+
if (typeof item === "string" && (item.startsWith("{") || item.startsWith("["))) {
|
|
2029
|
+
try {
|
|
2030
|
+
return JSON.parse(item);
|
|
2031
|
+
} catch {
|
|
2032
|
+
return item;
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2035
|
+
return item;
|
|
2036
|
+
});
|
|
2037
|
+
}
|
|
1870
2038
|
case "string":
|
|
1871
2039
|
return value;
|
|
1872
2040
|
case "object":
|
|
@@ -4352,7 +4520,7 @@ function createZapierCliSdk(options = {}) {
|
|
|
4352
4520
|
// package.json with { type: 'json' }
|
|
4353
4521
|
var package_default2 = {
|
|
4354
4522
|
name: "@zapier/zapier-sdk-cli",
|
|
4355
|
-
version: "0.
|
|
4523
|
+
version: "0.36.1"};
|
|
4356
4524
|
var ONE_DAY_MS = 24 * 60 * 60 * 1e3;
|
|
4357
4525
|
var CACHE_RESET_INTERVAL_MS = (() => {
|
|
4358
4526
|
const { ZAPIER_SDK_UPDATE_CHECK_INTERVAL_MS = `${ONE_DAY_MS}` } = process.env;
|