@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,413 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SchemaParameterResolver = void 0;
|
|
7
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const zod_1 = require("zod");
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Schema Parameter Resolver
|
|
12
|
+
// ============================================================================
|
|
13
|
+
class SchemaParameterResolver {
|
|
14
|
+
async resolveParameters(schema, providedParams, sdk) {
|
|
15
|
+
// 1. Try to parse with current parameters
|
|
16
|
+
const parseResult = schema.safeParse(providedParams);
|
|
17
|
+
// Even if parsing succeeds, check if we should resolve optional but important parameters
|
|
18
|
+
const allResolvable = this.findAllResolvableParameters(schema);
|
|
19
|
+
const shouldResolveAnyway = allResolvable.filter((param) => {
|
|
20
|
+
const hasValue = this.getNestedValue(providedParams, param.path) !== undefined;
|
|
21
|
+
// Resolve any parameters with resolvers even if optional, unless explicitly provided
|
|
22
|
+
return !hasValue && param.resolverMeta?.resolver;
|
|
23
|
+
});
|
|
24
|
+
if (parseResult.success && shouldResolveAnyway.length === 0) {
|
|
25
|
+
return parseResult.data;
|
|
26
|
+
}
|
|
27
|
+
// 2. Analyze what's missing and can be resolved
|
|
28
|
+
let missingResolvable;
|
|
29
|
+
if (!parseResult.success) {
|
|
30
|
+
missingResolvable = this.findResolvableParameters(schema, parseResult.error, providedParams);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
// Schema parsing succeeded, but we want to resolve optional important parameters
|
|
34
|
+
missingResolvable = shouldResolveAnyway;
|
|
35
|
+
}
|
|
36
|
+
if (missingResolvable.length === 0) {
|
|
37
|
+
// No resolvable parameters, throw original error
|
|
38
|
+
throw parseResult.error;
|
|
39
|
+
}
|
|
40
|
+
// 3. Resolve missing parameters interactively
|
|
41
|
+
const resolvedParams = { ...providedParams };
|
|
42
|
+
const context = {
|
|
43
|
+
sdk,
|
|
44
|
+
currentParams: providedParams,
|
|
45
|
+
resolvedParams,
|
|
46
|
+
};
|
|
47
|
+
// Sort by dependency order (parameters that depend on others go last)
|
|
48
|
+
const sortedMissing = this.sortByDependencies(missingResolvable);
|
|
49
|
+
for (const missing of sortedMissing) {
|
|
50
|
+
try {
|
|
51
|
+
const value = await this.resolveParameter(missing, context);
|
|
52
|
+
this.setNestedValue(resolvedParams, missing.path, value);
|
|
53
|
+
// Update context with newly resolved value
|
|
54
|
+
context.resolvedParams = resolvedParams;
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (this.isUserCancellation(error)) {
|
|
58
|
+
console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
|
|
59
|
+
process.exit(0);
|
|
60
|
+
}
|
|
61
|
+
console.error(chalk_1.default.red(`Failed to resolve ${missing.name}:`), error);
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// 4. Validate final parameters
|
|
66
|
+
const finalResult = schema.safeParse(resolvedParams);
|
|
67
|
+
if (!finalResult.success) {
|
|
68
|
+
console.error(chalk_1.default.red("❌ Parameter validation failed after resolution:"));
|
|
69
|
+
throw finalResult.error;
|
|
70
|
+
}
|
|
71
|
+
return finalResult.data;
|
|
72
|
+
}
|
|
73
|
+
findAllResolvableParameters(schema) {
|
|
74
|
+
const resolvable = [];
|
|
75
|
+
this.analyzeSchema(schema, [], resolvable);
|
|
76
|
+
return resolvable;
|
|
77
|
+
}
|
|
78
|
+
findResolvableParameters(schema, error, providedParams) {
|
|
79
|
+
const resolvable = this.findAllResolvableParameters(schema);
|
|
80
|
+
// Filter to only include parameters that are actually missing/invalid
|
|
81
|
+
const errorPaths = new Set(error.issues.map((issue) => issue.path.join(".")));
|
|
82
|
+
return resolvable.filter((param) => {
|
|
83
|
+
const paramPath = param.path.join(".");
|
|
84
|
+
const isErrorPath = errorPaths.has(paramPath);
|
|
85
|
+
const hasValue = this.getNestedValue(providedParams, param.path) !== undefined;
|
|
86
|
+
// Include if there's an error for this path or if it's required and missing
|
|
87
|
+
// Also include optional parameters that have resolvers and aren't provided
|
|
88
|
+
const shouldResolve = isErrorPath ||
|
|
89
|
+
(param.isRequired && !hasValue) ||
|
|
90
|
+
(!param.isRequired && !hasValue && param.resolverMeta?.resolver);
|
|
91
|
+
return shouldResolve;
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
analyzeSchema(schema, currentPath, resolvable) {
|
|
95
|
+
// Handle different Zod types
|
|
96
|
+
if (schema instanceof zod_1.z.ZodObject) {
|
|
97
|
+
const shape = schema.shape;
|
|
98
|
+
Object.entries(shape).forEach(([key, fieldSchema]) => {
|
|
99
|
+
const fieldPath = [...currentPath, key];
|
|
100
|
+
this.analyzeSchemaField(key, fieldSchema, fieldPath, resolvable);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
else if (schema instanceof zod_1.z.ZodOptional) {
|
|
104
|
+
this.analyzeSchema(schema.unwrap(), currentPath, resolvable);
|
|
105
|
+
}
|
|
106
|
+
else if (schema instanceof zod_1.z.ZodDefault) {
|
|
107
|
+
this.analyzeSchema(schema.removeDefault(), currentPath, resolvable);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
analyzeSchemaField(name, schema, path, resolvable) {
|
|
111
|
+
const resolverMeta = schema._def.resolverMeta;
|
|
112
|
+
if (resolverMeta?.resolver) {
|
|
113
|
+
resolvable.push({
|
|
114
|
+
name,
|
|
115
|
+
path,
|
|
116
|
+
schema,
|
|
117
|
+
description: schema.description,
|
|
118
|
+
resolverMeta,
|
|
119
|
+
isRequired: !schema.isOptional(),
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
// Recursively analyze nested objects
|
|
123
|
+
if (schema instanceof zod_1.z.ZodObject) {
|
|
124
|
+
this.analyzeSchema(schema, path, resolvable);
|
|
125
|
+
}
|
|
126
|
+
else if (schema instanceof zod_1.z.ZodOptional) {
|
|
127
|
+
this.analyzeSchemaField(name, schema.unwrap(), path, resolvable);
|
|
128
|
+
}
|
|
129
|
+
else if (schema instanceof zod_1.z.ZodDefault) {
|
|
130
|
+
this.analyzeSchemaField(name, schema.removeDefault(), path, resolvable);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
sortByDependencies(parameters) {
|
|
134
|
+
// Simple topological sort based on 'depends' field
|
|
135
|
+
const sorted = [];
|
|
136
|
+
const remaining = [...parameters];
|
|
137
|
+
while (remaining.length > 0) {
|
|
138
|
+
const canResolve = remaining.filter((param) => {
|
|
139
|
+
const depends = param.resolverMeta?.resolver?.depends || [];
|
|
140
|
+
return depends.every((dep) => sorted.some((resolved) => resolved.name === dep));
|
|
141
|
+
});
|
|
142
|
+
if (canResolve.length === 0) {
|
|
143
|
+
// No more resolvable parameters, add remaining ones (circular dependency or no dependencies)
|
|
144
|
+
sorted.push(...remaining);
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
sorted.push(...canResolve);
|
|
148
|
+
canResolve.forEach((param) => {
|
|
149
|
+
const index = remaining.indexOf(param);
|
|
150
|
+
remaining.splice(index, 1);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
return sorted;
|
|
154
|
+
}
|
|
155
|
+
async resolveParameter(paramInfo, context) {
|
|
156
|
+
const resolver = paramInfo.resolverMeta?.resolver;
|
|
157
|
+
if (!resolver) {
|
|
158
|
+
return await this.promptStaticInput(paramInfo);
|
|
159
|
+
}
|
|
160
|
+
if (resolver.type === "static") {
|
|
161
|
+
return await this.promptStaticInput(paramInfo, resolver);
|
|
162
|
+
}
|
|
163
|
+
if (resolver.type === "dynamic") {
|
|
164
|
+
return await this.resolveDynamicParameter(paramInfo, resolver, context);
|
|
165
|
+
}
|
|
166
|
+
if (resolver.type === "fields") {
|
|
167
|
+
return await this.resolveFieldsParameter(paramInfo, resolver, context);
|
|
168
|
+
}
|
|
169
|
+
throw new Error(`Unknown resolver type: ${resolver.type}`);
|
|
170
|
+
}
|
|
171
|
+
async promptStaticInput(paramInfo, resolver) {
|
|
172
|
+
const promptConfig = {
|
|
173
|
+
type: resolver?.inputType === "editor"
|
|
174
|
+
? "input"
|
|
175
|
+
: resolver?.inputType || "input",
|
|
176
|
+
name: "value",
|
|
177
|
+
message: `Enter ${paramInfo.description || paramInfo.name}${paramInfo.isRequired ? "" : " (optional)"}:`,
|
|
178
|
+
};
|
|
179
|
+
// Only use placeholder as default for required parameters
|
|
180
|
+
if (resolver?.placeholder && paramInfo.isRequired) {
|
|
181
|
+
promptConfig.default = resolver.placeholder;
|
|
182
|
+
}
|
|
183
|
+
// Add validation for required parameters
|
|
184
|
+
if (paramInfo.isRequired) {
|
|
185
|
+
promptConfig.validate = (input) => {
|
|
186
|
+
if (!input || (typeof input === "string" && input.trim() === "")) {
|
|
187
|
+
return "This field is required. Please enter a value.";
|
|
188
|
+
}
|
|
189
|
+
return true;
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
// For editor-like prompts, provide helpful instructions
|
|
193
|
+
if (resolver?.inputType === "editor") {
|
|
194
|
+
promptConfig.message += " (JSON format)";
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
const result = await inquirer_1.default.prompt([promptConfig]);
|
|
198
|
+
// For optional parameters, treat empty input as undefined
|
|
199
|
+
if (!paramInfo.isRequired &&
|
|
200
|
+
(!result.value || result.value.trim() === "")) {
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
// Try to parse JSON if it looks like JSON
|
|
204
|
+
if (typeof result.value === "string" &&
|
|
205
|
+
result.value.trim().startsWith("{")) {
|
|
206
|
+
try {
|
|
207
|
+
return JSON.parse(result.value);
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
console.warn(chalk_1.default.yellow("Warning: Could not parse as JSON, using as string"));
|
|
211
|
+
return result.value;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return result.value;
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
if (this.isUserCancellation(error)) {
|
|
218
|
+
console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
|
|
219
|
+
process.exit(0);
|
|
220
|
+
}
|
|
221
|
+
throw error;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
async resolveDynamicParameter(paramInfo, resolver, context) {
|
|
225
|
+
console.log(chalk_1.default.gray(`Fetching options for ${paramInfo.name}...`));
|
|
226
|
+
try {
|
|
227
|
+
// Use the new fetch function approach
|
|
228
|
+
const options = await resolver.fetch(context.sdk, context.resolvedParams);
|
|
229
|
+
if (options.length === 0) {
|
|
230
|
+
console.log(chalk_1.default.yellow(`No options available for ${paramInfo.name}`));
|
|
231
|
+
return await this.promptStaticInput(paramInfo);
|
|
232
|
+
}
|
|
233
|
+
// Generate prompt configuration
|
|
234
|
+
const promptConfig = resolver.prompt(options, context.resolvedParams);
|
|
235
|
+
// Execute the prompt
|
|
236
|
+
let result;
|
|
237
|
+
try {
|
|
238
|
+
result = await inquirer_1.default.prompt([promptConfig]);
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
if (this.isUserCancellation(error)) {
|
|
242
|
+
console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
|
|
243
|
+
process.exit(0);
|
|
244
|
+
}
|
|
245
|
+
throw error;
|
|
246
|
+
}
|
|
247
|
+
let value = result[promptConfig.name || "value"];
|
|
248
|
+
// Handle JSON parsing if the value looks like JSON
|
|
249
|
+
if (typeof value === "string" && value.trim().startsWith("{")) {
|
|
250
|
+
try {
|
|
251
|
+
value = JSON.parse(value);
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
console.warn(chalk_1.default.yellow("Warning: Could not parse as JSON, using as string"));
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return value;
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
if (this.isUserCancellation(error)) {
|
|
261
|
+
console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
|
|
262
|
+
process.exit(0);
|
|
263
|
+
}
|
|
264
|
+
if (error instanceof Error && error.message.includes("401")) {
|
|
265
|
+
console.log(chalk_1.default.yellow(`⚠️ Invalid auth token, falling back to manual input for ${paramInfo.name}`));
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
console.error(chalk_1.default.red(`Failed to fetch options for ${paramInfo.name}:`), error);
|
|
269
|
+
console.log(chalk_1.default.yellow("Falling back to manual input..."));
|
|
270
|
+
}
|
|
271
|
+
return await this.promptStaticInput(paramInfo);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
async resolveFieldsParameter(paramInfo, resolver, context) {
|
|
275
|
+
console.log(chalk_1.default.gray(`Fetching field definitions for ${paramInfo.name}...`));
|
|
276
|
+
try {
|
|
277
|
+
// Fetch field definitions using the resolver's fetch function
|
|
278
|
+
const fields = await resolver.fetch(context.sdk, context.resolvedParams);
|
|
279
|
+
if (fields.length === 0) {
|
|
280
|
+
console.log(chalk_1.default.yellow(`No input fields required for this action`));
|
|
281
|
+
return {};
|
|
282
|
+
}
|
|
283
|
+
console.log(chalk_1.default.blue(`\nConfiguring inputs for ${context.resolvedParams.app} ${context.resolvedParams.type} ${context.resolvedParams.action}:`));
|
|
284
|
+
const inputs = {};
|
|
285
|
+
// Separate required and optional fields
|
|
286
|
+
const requiredFields = fields.filter((field) => field.required);
|
|
287
|
+
const optionalFields = fields.filter((field) => !field.required);
|
|
288
|
+
// First, prompt for all required fields
|
|
289
|
+
if (requiredFields.length > 0) {
|
|
290
|
+
console.log(chalk_1.default.cyan(`\nRequired fields (${requiredFields.length}):`));
|
|
291
|
+
for (const field of requiredFields) {
|
|
292
|
+
await this.promptForField(field, inputs);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// Then ask if user wants to configure optional fields
|
|
296
|
+
if (optionalFields.length > 0) {
|
|
297
|
+
console.log(chalk_1.default.gray(`\nThere are ${optionalFields.length} optional field(s) available.`));
|
|
298
|
+
let shouldConfigureOptional;
|
|
299
|
+
try {
|
|
300
|
+
shouldConfigureOptional = await inquirer_1.default.prompt([
|
|
301
|
+
{
|
|
302
|
+
type: "confirm",
|
|
303
|
+
name: "configure",
|
|
304
|
+
message: "Would you like to configure optional fields?",
|
|
305
|
+
default: false,
|
|
306
|
+
},
|
|
307
|
+
]);
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
if (this.isUserCancellation(error)) {
|
|
311
|
+
console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
|
|
312
|
+
process.exit(0);
|
|
313
|
+
}
|
|
314
|
+
throw error;
|
|
315
|
+
}
|
|
316
|
+
if (shouldConfigureOptional.configure) {
|
|
317
|
+
console.log(chalk_1.default.cyan(`\nOptional fields:`));
|
|
318
|
+
for (const field of optionalFields) {
|
|
319
|
+
await this.promptForField(field, inputs);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return inputs;
|
|
324
|
+
}
|
|
325
|
+
catch (error) {
|
|
326
|
+
if (this.isUserCancellation(error)) {
|
|
327
|
+
console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
|
|
328
|
+
process.exit(0);
|
|
329
|
+
}
|
|
330
|
+
console.error(chalk_1.default.red(`Failed to fetch field definitions for ${paramInfo.name}:`), error);
|
|
331
|
+
console.log(chalk_1.default.yellow("Falling back to manual JSON input..."));
|
|
332
|
+
return await this.promptStaticInput(paramInfo);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
async promptForField(field, inputs) {
|
|
336
|
+
const fieldPrompt = {
|
|
337
|
+
type: "input",
|
|
338
|
+
name: field.key,
|
|
339
|
+
message: `${field.label || field.key}${field.required ? " (required)" : " (optional)"}:`,
|
|
340
|
+
};
|
|
341
|
+
// Add description/help text if available
|
|
342
|
+
if (field.help_text || field.description) {
|
|
343
|
+
fieldPrompt.message += `\n ${chalk_1.default.dim(field.help_text || field.description)}`;
|
|
344
|
+
}
|
|
345
|
+
// Set default value
|
|
346
|
+
if (field.default !== undefined) {
|
|
347
|
+
fieldPrompt.default = field.default;
|
|
348
|
+
}
|
|
349
|
+
// Add validation for required fields
|
|
350
|
+
if (field.required) {
|
|
351
|
+
fieldPrompt.validate = (input) => {
|
|
352
|
+
if (!input || (typeof input === "string" && input.trim() === "")) {
|
|
353
|
+
return "This field is required. Please enter a value.";
|
|
354
|
+
}
|
|
355
|
+
return true;
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
let result;
|
|
359
|
+
try {
|
|
360
|
+
result = await inquirer_1.default.prompt([fieldPrompt]);
|
|
361
|
+
}
|
|
362
|
+
catch (error) {
|
|
363
|
+
if (this.isUserCancellation(error)) {
|
|
364
|
+
console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
|
|
365
|
+
process.exit(0);
|
|
366
|
+
}
|
|
367
|
+
throw error;
|
|
368
|
+
}
|
|
369
|
+
// Only include non-empty values
|
|
370
|
+
if (result[field.key] !== undefined && result[field.key] !== "") {
|
|
371
|
+
let value = result[field.key];
|
|
372
|
+
// Try to parse as appropriate type
|
|
373
|
+
if (field.type === "integer" && typeof value === "string") {
|
|
374
|
+
const parsed = parseInt(value, 10);
|
|
375
|
+
if (!isNaN(parsed))
|
|
376
|
+
value = parsed;
|
|
377
|
+
}
|
|
378
|
+
else if (field.type === "number" && typeof value === "string") {
|
|
379
|
+
const parsed = parseFloat(value);
|
|
380
|
+
if (!isNaN(parsed))
|
|
381
|
+
value = parsed;
|
|
382
|
+
}
|
|
383
|
+
else if (field.type === "boolean" && typeof value === "string") {
|
|
384
|
+
value = value.toLowerCase() === "true" || value === "1";
|
|
385
|
+
}
|
|
386
|
+
inputs[field.key] = value;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
getNestedValue(obj, path) {
|
|
390
|
+
return path.reduce((current, key) => current?.[key], obj);
|
|
391
|
+
}
|
|
392
|
+
setNestedValue(obj, path, value) {
|
|
393
|
+
const lastKey = path[path.length - 1];
|
|
394
|
+
const parentPath = path.slice(0, -1);
|
|
395
|
+
const parent = parentPath.reduce((current, key) => {
|
|
396
|
+
if (!current[key]) {
|
|
397
|
+
current[key] = {};
|
|
398
|
+
}
|
|
399
|
+
return current[key];
|
|
400
|
+
}, obj);
|
|
401
|
+
parent[lastKey] = value;
|
|
402
|
+
}
|
|
403
|
+
isUserCancellation(error) {
|
|
404
|
+
// Check for various ways user cancellation can be detected
|
|
405
|
+
return (error &&
|
|
406
|
+
(error.name === "ExitPromptError" ||
|
|
407
|
+
error.message?.includes("User force closed the prompt") ||
|
|
408
|
+
error.message?.includes("SIGINT") ||
|
|
409
|
+
error.code === "SIGINT" ||
|
|
410
|
+
error.signal === "SIGINT"));
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
exports.SchemaParameterResolver = SchemaParameterResolver;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.formatItemsFromSchema = formatItemsFromSchema;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const output_schemas_1 = require("../../../actions-sdk/dist/output-schemas");
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Generic Schema-Driven Formatter
|
|
11
|
+
// ============================================================================
|
|
12
|
+
function formatItemsFromSchema(inputSchema, items) {
|
|
13
|
+
// Get the output schema and its format metadata
|
|
14
|
+
const outputSchema = (0, output_schemas_1.getOutputSchema)(inputSchema);
|
|
15
|
+
if (!outputSchema) {
|
|
16
|
+
// Fallback to generic formatting if no output schema
|
|
17
|
+
formatItemsGeneric(items);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const formatMeta = (0, output_schemas_1.getFormatMetadata)(outputSchema);
|
|
21
|
+
if (!formatMeta) {
|
|
22
|
+
// Fallback to generic formatting if no format metadata
|
|
23
|
+
formatItemsGeneric(items);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
// Format each item using the schema metadata
|
|
27
|
+
items.forEach((item, index) => {
|
|
28
|
+
formatSingleItem(item, index, formatMeta);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function formatSingleItem(item, index, formatMeta) {
|
|
32
|
+
// Get the formatted item from the format function
|
|
33
|
+
const formatted = formatMeta.format(item);
|
|
34
|
+
// Build the main title line
|
|
35
|
+
let titleLine = `${chalk_1.default.gray(`${index + 1}.`)} ${chalk_1.default.cyan(formatted.title)}`;
|
|
36
|
+
if (formatted.subtitle) {
|
|
37
|
+
titleLine += ` ${chalk_1.default.gray(formatted.subtitle)}`;
|
|
38
|
+
}
|
|
39
|
+
console.log(titleLine);
|
|
40
|
+
// Format detail lines
|
|
41
|
+
for (const detail of formatted.details) {
|
|
42
|
+
const styledText = applyStyle(detail.text, detail.style);
|
|
43
|
+
console.log(` ${styledText}`);
|
|
44
|
+
}
|
|
45
|
+
console.log(); // Empty line between items
|
|
46
|
+
}
|
|
47
|
+
function applyStyle(value, style) {
|
|
48
|
+
switch (style) {
|
|
49
|
+
case "dim":
|
|
50
|
+
return chalk_1.default.dim(value);
|
|
51
|
+
case "accent":
|
|
52
|
+
return chalk_1.default.magenta(value);
|
|
53
|
+
case "warning":
|
|
54
|
+
return chalk_1.default.red(value);
|
|
55
|
+
case "success":
|
|
56
|
+
return chalk_1.default.green(value);
|
|
57
|
+
case "normal":
|
|
58
|
+
default:
|
|
59
|
+
return chalk_1.default.blue(value);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function formatItemsGeneric(items) {
|
|
63
|
+
// Fallback formatting for items without schema metadata
|
|
64
|
+
items.forEach((item, index) => {
|
|
65
|
+
const name = item.name || item.key || item.id || "Item";
|
|
66
|
+
console.log(`${chalk_1.default.gray(`${index + 1}.`)} ${chalk_1.default.cyan(name)}`);
|
|
67
|
+
if (item.description) {
|
|
68
|
+
console.log(` ${chalk_1.default.dim(item.description)}`);
|
|
69
|
+
}
|
|
70
|
+
console.log();
|
|
71
|
+
});
|
|
72
|
+
}
|