@zapier/zapier-sdk-cli 0.0.3 → 0.1.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/dist/cli.js +1 -3
- package/dist/utils/cli-generator.d.ts +2 -3
- package/dist/utils/cli-generator.js +98 -124
- package/dist/utils/parameter-resolver.d.ts +6 -11
- package/dist/utils/parameter-resolver.js +223 -329
- package/dist/utils/schema-formatter.js +8 -3
- package/package.json +5 -3
- package/src/cli.ts +3 -6
- package/src/utils/cli-generator.ts +123 -161
- package/src/utils/parameter-resolver.ts +277 -432
- package/src/utils/schema-formatter.ts +23 -5
- package/tsconfig.json +1 -1
- package/dist/commands/action.d.ts +0 -2
- package/dist/commands/action.js +0 -295
- package/dist/commands/browse.d.ts +0 -2
- package/dist/commands/browse.js +0 -257
- package/dist/commands/bundle.d.ts +0 -2
- package/dist/commands/bundle.js +0 -101
- package/dist/commands/generate.d.ts +0 -9
- package/dist/commands/generate.js +0 -281
- package/dist/utils/auth-picker.d.ts +0 -17
- package/dist/utils/auth-picker.js +0 -121
- package/dist/utils/schema-generator.d.ts +0 -4
- package/dist/utils/schema-generator.js +0 -389
|
@@ -7,6 +7,7 @@ exports.SchemaParameterResolver = void 0;
|
|
|
7
7
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
8
8
|
const chalk_1 = __importDefault(require("chalk"));
|
|
9
9
|
const zod_1 = require("zod");
|
|
10
|
+
const zapier_sdk_1 = require("@zapier/zapier-sdk");
|
|
10
11
|
// ============================================================================
|
|
11
12
|
// Schema Parameter Resolver
|
|
12
13
|
// ============================================================================
|
|
@@ -14,55 +15,106 @@ class SchemaParameterResolver {
|
|
|
14
15
|
async resolveParameters(schema, providedParams, sdk) {
|
|
15
16
|
// 1. Try to parse with current parameters
|
|
16
17
|
const parseResult = schema.safeParse(providedParams);
|
|
17
|
-
//
|
|
18
|
-
const
|
|
19
|
-
const
|
|
18
|
+
// Get all schema parameters to check which ones have resolvers
|
|
19
|
+
const allParams = this.extractParametersFromSchema(schema);
|
|
20
|
+
const resolvableParams = allParams.filter((param) => (0, zapier_sdk_1.hasResolver)(param.name));
|
|
21
|
+
// Get all missing parameters that have resolvers
|
|
22
|
+
const missingResolvable = resolvableParams.filter((param) => {
|
|
20
23
|
const hasValue = this.getNestedValue(providedParams, param.path) !== undefined;
|
|
21
|
-
|
|
22
|
-
return !hasValue && param.resolverMeta?.resolver;
|
|
24
|
+
return !hasValue;
|
|
23
25
|
});
|
|
24
|
-
|
|
26
|
+
// Determine which parameters are "functionally required" vs truly optional
|
|
27
|
+
// For run-action: appKey, actionType, actionKey are schema-required
|
|
28
|
+
// authenticationId and inputs are schema-optional but functionally needed
|
|
29
|
+
const functionallyRequired = missingResolvable.filter((param) => {
|
|
30
|
+
// Schema-required parameters are always functionally required
|
|
31
|
+
if (param.isRequired)
|
|
32
|
+
return true;
|
|
33
|
+
// For run-action, inputs and authenticationId are functionally required
|
|
34
|
+
// even though schema-optional
|
|
35
|
+
if (param.name === "inputs" || param.name === "authenticationId") {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
});
|
|
40
|
+
const trulyOptional = missingResolvable.filter((param) => !functionallyRequired.includes(param));
|
|
41
|
+
if (parseResult.success && functionallyRequired.length === 0) {
|
|
25
42
|
return parseResult.data;
|
|
26
43
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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;
|
|
44
|
+
if (functionallyRequired.length === 0) {
|
|
45
|
+
// No functionally required parameters missing, but check if we can parse
|
|
46
|
+
if (!parseResult.success) {
|
|
47
|
+
throw parseResult.error;
|
|
48
|
+
}
|
|
49
|
+
return parseResult.data;
|
|
39
50
|
}
|
|
40
|
-
//
|
|
51
|
+
// 2. Resolve functionally required parameters first
|
|
41
52
|
const resolvedParams = { ...providedParams };
|
|
42
53
|
const context = {
|
|
43
54
|
sdk,
|
|
44
55
|
currentParams: providedParams,
|
|
45
56
|
resolvedParams,
|
|
46
57
|
};
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
58
|
+
if (functionallyRequired.length > 0) {
|
|
59
|
+
const requiredParamNames = functionallyRequired.map((p) => p.name);
|
|
60
|
+
const requiredResolutionOrder = (0, zapier_sdk_1.getResolutionOrderForParams)(requiredParamNames);
|
|
61
|
+
const orderedRequiredParams = requiredResolutionOrder
|
|
62
|
+
.map((paramName) => functionallyRequired.find((p) => p.name === paramName))
|
|
63
|
+
.filter((param) => param !== undefined);
|
|
64
|
+
for (const param of orderedRequiredParams) {
|
|
65
|
+
try {
|
|
66
|
+
const value = await this.resolveParameter(param, context);
|
|
67
|
+
this.setNestedValue(resolvedParams, param.path, value);
|
|
68
|
+
// Update context with newly resolved value
|
|
69
|
+
context.resolvedParams = resolvedParams;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
if (this.isUserCancellation(error)) {
|
|
73
|
+
console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
|
|
74
|
+
process.exit(0);
|
|
75
|
+
}
|
|
76
|
+
console.error(chalk_1.default.red(`Failed to resolve ${param.name}:`), error);
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
55
79
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
80
|
+
}
|
|
81
|
+
// 3. Ask user if they want to resolve truly optional parameters
|
|
82
|
+
if (trulyOptional.length > 0) {
|
|
83
|
+
const optionalNames = trulyOptional.map((p) => p.name).join(", ");
|
|
84
|
+
const shouldResolveOptional = await inquirer_1.default.prompt([
|
|
85
|
+
{
|
|
86
|
+
type: "confirm",
|
|
87
|
+
name: "resolveOptional",
|
|
88
|
+
message: `Would you like to be prompted for optional parameters (${optionalNames})?`,
|
|
89
|
+
default: false,
|
|
90
|
+
},
|
|
91
|
+
]);
|
|
92
|
+
if (shouldResolveOptional.resolveOptional) {
|
|
93
|
+
// Resolve optional parameters using their resolvers
|
|
94
|
+
const optionalParamNames = trulyOptional.map((p) => p.name);
|
|
95
|
+
const optionalResolutionOrder = (0, zapier_sdk_1.getResolutionOrderForParams)(optionalParamNames);
|
|
96
|
+
const orderedOptionalParams = optionalResolutionOrder
|
|
97
|
+
.map((paramName) => trulyOptional.find((p) => p.name === paramName))
|
|
98
|
+
.filter((param) => param !== undefined);
|
|
99
|
+
for (const param of orderedOptionalParams) {
|
|
100
|
+
try {
|
|
101
|
+
const value = await this.resolveParameter(param, context);
|
|
102
|
+
this.setNestedValue(resolvedParams, param.path, value);
|
|
103
|
+
// Update context with newly resolved value
|
|
104
|
+
context.resolvedParams = resolvedParams;
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
if (this.isUserCancellation(error)) {
|
|
108
|
+
console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
|
|
109
|
+
process.exit(0);
|
|
110
|
+
}
|
|
111
|
+
console.error(chalk_1.default.red(`Failed to resolve ${param.name}:`), error);
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
60
114
|
}
|
|
61
|
-
console.error(chalk_1.default.red(`Failed to resolve ${missing.name}:`), error);
|
|
62
|
-
throw error;
|
|
63
115
|
}
|
|
64
116
|
}
|
|
65
|
-
//
|
|
117
|
+
// 3. Validate final parameters
|
|
66
118
|
const finalResult = schema.safeParse(resolvedParams);
|
|
67
119
|
if (!finalResult.success) {
|
|
68
120
|
console.error(chalk_1.default.red("❌ Parameter validation failed after resolution:"));
|
|
@@ -70,294 +122,173 @@ class SchemaParameterResolver {
|
|
|
70
122
|
}
|
|
71
123
|
return finalResult.data;
|
|
72
124
|
}
|
|
73
|
-
|
|
74
|
-
const
|
|
75
|
-
|
|
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
|
|
125
|
+
extractParametersFromSchema(schema) {
|
|
126
|
+
const parameters = [];
|
|
127
|
+
// Only handle ZodObject at the top level
|
|
96
128
|
if (schema instanceof zod_1.z.ZodObject) {
|
|
97
129
|
const shape = schema.shape;
|
|
98
|
-
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
this.analyzeSchema(schema.unwrap(), currentPath, resolvable);
|
|
105
|
-
}
|
|
106
|
-
else if (schema instanceof zod_1.z.ZodDefault) {
|
|
107
|
-
this.analyzeSchema(schema.removeDefault(), currentPath, resolvable);
|
|
130
|
+
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
131
|
+
const param = this.analyzeFieldSchema(key, fieldSchema);
|
|
132
|
+
if (param) {
|
|
133
|
+
parameters.push(param);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
108
136
|
}
|
|
137
|
+
return parameters;
|
|
109
138
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
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
|
-
}
|
|
139
|
+
analyzeFieldSchema(fieldName, fieldSchema) {
|
|
140
|
+
let baseSchema = fieldSchema;
|
|
141
|
+
let isRequired = true;
|
|
142
|
+
// Check if field is optional or has default
|
|
143
|
+
if (baseSchema instanceof zod_1.z.ZodOptional) {
|
|
144
|
+
isRequired = false;
|
|
145
|
+
baseSchema = baseSchema._def.innerType;
|
|
146
|
+
}
|
|
147
|
+
if (baseSchema instanceof zod_1.z.ZodDefault) {
|
|
148
|
+
isRequired = false;
|
|
149
|
+
baseSchema = baseSchema._def.innerType;
|
|
150
|
+
}
|
|
151
|
+
return this.createResolvableParameter([fieldName], baseSchema, isRequired);
|
|
132
152
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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;
|
|
153
|
+
createResolvableParameter(path, schema, isRequired) {
|
|
154
|
+
if (path.length === 0)
|
|
155
|
+
return null;
|
|
156
|
+
const name = path[path.length - 1];
|
|
157
|
+
return {
|
|
158
|
+
name,
|
|
159
|
+
path,
|
|
160
|
+
schema,
|
|
161
|
+
description: schema.description,
|
|
162
|
+
isRequired,
|
|
163
|
+
};
|
|
154
164
|
}
|
|
155
|
-
async resolveParameter(
|
|
156
|
-
const resolver =
|
|
165
|
+
async resolveParameter(param, context) {
|
|
166
|
+
const resolver = (0, zapier_sdk_1.getResolver)(param.name);
|
|
157
167
|
if (!resolver) {
|
|
158
|
-
|
|
168
|
+
throw new Error(`No resolver found for parameter: ${param.name}`);
|
|
159
169
|
}
|
|
170
|
+
console.log(chalk_1.default.blue(`\n🔍 Resolving ${param.name}...`));
|
|
160
171
|
if (resolver.type === "static") {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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;
|
|
172
|
+
// Static resolver - just prompt for input
|
|
173
|
+
const promptConfig = {
|
|
174
|
+
type: resolver.inputType === "password" ? "password" : "input",
|
|
175
|
+
name: param.name,
|
|
176
|
+
message: `Enter ${param.name}:`,
|
|
177
|
+
...(resolver.placeholder && { default: resolver.placeholder }),
|
|
190
178
|
};
|
|
179
|
+
const answers = await inquirer_1.default.prompt([promptConfig]);
|
|
180
|
+
return answers[param.name];
|
|
191
181
|
}
|
|
192
|
-
|
|
193
|
-
|
|
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;
|
|
182
|
+
else if (resolver.type === "dynamic") {
|
|
183
|
+
// Dynamic resolver - fetch options and prompt for selection
|
|
237
184
|
try {
|
|
238
|
-
|
|
185
|
+
console.log(chalk_1.default.gray(`Fetching options for ${param.name}...`));
|
|
186
|
+
const items = await resolver.fetch(context.sdk, context.resolvedParams);
|
|
187
|
+
if (!items || items.length === 0) {
|
|
188
|
+
throw new Error(`No options available for ${param.name}`);
|
|
189
|
+
}
|
|
190
|
+
const promptConfig = resolver.prompt(items, context.resolvedParams);
|
|
191
|
+
const answers = await inquirer_1.default.prompt([promptConfig]);
|
|
192
|
+
return answers[param.name];
|
|
239
193
|
}
|
|
240
194
|
catch (error) {
|
|
241
|
-
|
|
242
|
-
console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
|
|
243
|
-
process.exit(0);
|
|
244
|
-
}
|
|
195
|
+
console.error(chalk_1.default.red(`Failed to fetch options for ${param.name}:`), error instanceof Error ? error.message : error);
|
|
245
196
|
throw error;
|
|
246
197
|
}
|
|
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
198
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
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
|
-
]);
|
|
199
|
+
else if (resolver.type === "fields") {
|
|
200
|
+
// Fields resolver - fetch field definitions and prompt for each input
|
|
201
|
+
try {
|
|
202
|
+
console.log(chalk_1.default.gray(`Fetching input fields for ${param.name}...`));
|
|
203
|
+
const fields = await resolver.fetch(context.sdk, context.resolvedParams);
|
|
204
|
+
if (!fields || fields.length === 0) {
|
|
205
|
+
console.log(chalk_1.default.yellow(`No input fields required for this action.`));
|
|
206
|
+
return {};
|
|
308
207
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
208
|
+
const inputs = {};
|
|
209
|
+
// Separate required and optional fields
|
|
210
|
+
const requiredFields = fields.filter((field) => field.required);
|
|
211
|
+
const optionalFields = fields.filter((field) => !field.required);
|
|
212
|
+
// First, prompt for all required fields
|
|
213
|
+
if (requiredFields.length > 0) {
|
|
214
|
+
console.log(chalk_1.default.blue(`\n📝 Please provide values for the following input fields:`));
|
|
215
|
+
for (const field of requiredFields) {
|
|
216
|
+
await this.promptForField(field, inputs);
|
|
313
217
|
}
|
|
314
|
-
throw error;
|
|
315
218
|
}
|
|
316
|
-
if
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
219
|
+
// Then ask if user wants to configure optional fields
|
|
220
|
+
if (optionalFields.length > 0) {
|
|
221
|
+
console.log(chalk_1.default.gray(`\nThere are ${optionalFields.length} optional field(s) available.`));
|
|
222
|
+
let shouldConfigureOptional;
|
|
223
|
+
try {
|
|
224
|
+
shouldConfigureOptional = await inquirer_1.default.prompt([
|
|
225
|
+
{
|
|
226
|
+
type: "confirm",
|
|
227
|
+
name: "configure",
|
|
228
|
+
message: "Would you like to configure optional fields?",
|
|
229
|
+
default: false,
|
|
230
|
+
},
|
|
231
|
+
]);
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
if (this.isUserCancellation(error)) {
|
|
235
|
+
console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
|
|
236
|
+
process.exit(0);
|
|
237
|
+
}
|
|
238
|
+
throw error;
|
|
239
|
+
}
|
|
240
|
+
if (shouldConfigureOptional.configure) {
|
|
241
|
+
console.log(chalk_1.default.cyan(`\nOptional fields:`));
|
|
242
|
+
for (const field of optionalFields) {
|
|
243
|
+
await this.promptForField(field, inputs);
|
|
244
|
+
}
|
|
320
245
|
}
|
|
321
246
|
}
|
|
247
|
+
return inputs;
|
|
322
248
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
if (this.isUserCancellation(error)) {
|
|
327
|
-
console.log(chalk_1.default.yellow("\n\nOperation cancelled by user"));
|
|
328
|
-
process.exit(0);
|
|
249
|
+
catch (error) {
|
|
250
|
+
console.error(chalk_1.default.red(`Failed to fetch fields for ${param.name}:`), error instanceof Error ? error.message : error);
|
|
251
|
+
throw error;
|
|
329
252
|
}
|
|
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
253
|
}
|
|
254
|
+
throw new Error(`Unknown resolver type for ${param.name}`);
|
|
255
|
+
}
|
|
256
|
+
getNestedValue(obj, path) {
|
|
257
|
+
return path.reduce((current, key) => current?.[key], obj);
|
|
258
|
+
}
|
|
259
|
+
setNestedValue(obj, path, value) {
|
|
260
|
+
const lastKey = path[path.length - 1];
|
|
261
|
+
const parent = path.slice(0, -1).reduce((current, key) => {
|
|
262
|
+
if (!(key in current)) {
|
|
263
|
+
current[key] = {};
|
|
264
|
+
}
|
|
265
|
+
return current[key];
|
|
266
|
+
}, obj);
|
|
267
|
+
parent[lastKey] = value;
|
|
334
268
|
}
|
|
335
269
|
async promptForField(field, inputs) {
|
|
336
270
|
const fieldPrompt = {
|
|
337
|
-
type: "input",
|
|
271
|
+
type: field.type === "boolean" ? "confirm" : "input",
|
|
338
272
|
name: field.key,
|
|
339
273
|
message: `${field.label || field.key}${field.required ? " (required)" : " (optional)"}:`,
|
|
274
|
+
...(field.helpText && { prefix: chalk_1.default.gray(`ℹ ${field.helpText}\n`) }),
|
|
275
|
+
...(field.default && { default: field.default }),
|
|
340
276
|
};
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
fieldPrompt.
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
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
|
-
};
|
|
277
|
+
if (field.choices && field.choices.length > 0) {
|
|
278
|
+
fieldPrompt.type = "list";
|
|
279
|
+
fieldPrompt.choices = field.choices.map((choice) => ({
|
|
280
|
+
name: choice.label || choice.value,
|
|
281
|
+
value: choice.value,
|
|
282
|
+
}));
|
|
357
283
|
}
|
|
358
|
-
let result;
|
|
359
284
|
try {
|
|
360
|
-
|
|
285
|
+
const answer = await inquirer_1.default.prompt([fieldPrompt]);
|
|
286
|
+
if (answer[field.key] !== undefined && answer[field.key] !== "") {
|
|
287
|
+
inputs[field.key] = answer[field.key];
|
|
288
|
+
}
|
|
289
|
+
else if (field.required) {
|
|
290
|
+
throw new Error(`Required field ${field.key} cannot be empty`);
|
|
291
|
+
}
|
|
361
292
|
}
|
|
362
293
|
catch (error) {
|
|
363
294
|
if (this.isUserCancellation(error)) {
|
|
@@ -366,48 +297,11 @@ class SchemaParameterResolver {
|
|
|
366
297
|
}
|
|
367
298
|
throw error;
|
|
368
299
|
}
|
|
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
300
|
}
|
|
403
301
|
isUserCancellation(error) {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
error.message?.includes("User force closed the prompt") ||
|
|
408
|
-
error.message?.includes("SIGINT") ||
|
|
409
|
-
error.code === "SIGINT" ||
|
|
410
|
-
error.signal === "SIGINT"));
|
|
302
|
+
return (error?.name === "ExitPromptError" ||
|
|
303
|
+
error?.message?.includes("User force closed") ||
|
|
304
|
+
error?.isTTYError);
|
|
411
305
|
}
|
|
412
306
|
}
|
|
413
307
|
exports.SchemaParameterResolver = SchemaParameterResolver;
|
|
@@ -5,19 +5,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.formatItemsFromSchema = formatItemsFromSchema;
|
|
7
7
|
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
-
|
|
8
|
+
function getFormatMetadata(schema) {
|
|
9
|
+
return schema?._def?.formatMeta;
|
|
10
|
+
}
|
|
11
|
+
function getOutputSchema(schema) {
|
|
12
|
+
return schema?._def?.outputSchema;
|
|
13
|
+
}
|
|
9
14
|
// ============================================================================
|
|
10
15
|
// Generic Schema-Driven Formatter
|
|
11
16
|
// ============================================================================
|
|
12
17
|
function formatItemsFromSchema(inputSchema, items) {
|
|
13
18
|
// Get the output schema and its format metadata
|
|
14
|
-
const outputSchema =
|
|
19
|
+
const outputSchema = getOutputSchema(inputSchema);
|
|
15
20
|
if (!outputSchema) {
|
|
16
21
|
// Fallback to generic formatting if no output schema
|
|
17
22
|
formatItemsGeneric(items);
|
|
18
23
|
return;
|
|
19
24
|
}
|
|
20
|
-
const formatMeta =
|
|
25
|
+
const formatMeta = getFormatMetadata(outputSchema);
|
|
21
26
|
if (!formatMeta) {
|
|
22
27
|
// Fallback to generic formatting if no format metadata
|
|
23
28
|
formatItemsGeneric(items);
|