@zapier/zapier-sdk-cli 0.1.0 ā 0.2.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 +15 -11
- package/dist/commands/configPath.d.ts +2 -0
- package/dist/commands/configPath.js +9 -0
- package/dist/commands/index.d.ts +4 -0
- package/dist/commands/index.js +4 -0
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.js +25 -0
- package/dist/commands/logout.d.ts +2 -0
- package/dist/commands/logout.js +16 -0
- package/dist/commands/whoami.d.ts +2 -0
- package/dist/commands/whoami.js +16 -0
- package/dist/utils/api/client.d.ts +15 -0
- package/dist/utils/api/client.js +27 -0
- package/dist/utils/auth/ensureValidToken.d.ts +7 -0
- package/dist/utils/auth/ensureValidToken.js +33 -0
- package/dist/utils/auth/getAuthState.d.ts +12 -0
- package/dist/utils/auth/getAuthState.js +17 -0
- package/dist/utils/auth/getJWT.d.ts +2 -0
- package/dist/utils/auth/getJWT.js +13 -0
- package/dist/utils/auth/getLoggedInUser.d.ts +6 -0
- package/dist/utils/auth/getLoggedInUser.js +47 -0
- package/dist/utils/auth/login.d.ts +2 -0
- package/dist/utils/auth/login.js +135 -0
- package/dist/utils/auth/logout.d.ts +2 -0
- package/dist/utils/auth/logout.js +7 -0
- package/dist/utils/auth/refreshJWT.d.ts +2 -0
- package/dist/utils/auth/refreshJWT.js +33 -0
- package/dist/utils/auth/updateLogin.d.ts +7 -0
- package/dist/utils/auth/updateLogin.js +7 -0
- package/dist/utils/cli-generator.js +49 -49
- package/dist/utils/config.d.ts +2 -0
- package/dist/utils/config.js +2 -0
- package/dist/utils/constants.d.ts +5 -0
- package/dist/utils/constants.js +6 -0
- package/dist/utils/getCallablePromise.d.ts +6 -0
- package/dist/utils/getCallablePromise.js +14 -0
- package/dist/utils/getConfigPath.d.ts +1 -0
- package/dist/utils/getConfigPath.js +4 -0
- package/dist/utils/log.d.ts +7 -0
- package/dist/utils/log.js +16 -0
- package/dist/utils/pager.js +10 -20
- package/dist/utils/parameter-resolver.js +34 -41
- package/dist/utils/schema-formatter.js +11 -17
- package/dist/utils/serializeAsync.d.ts +2 -0
- package/dist/utils/serializeAsync.js +16 -0
- package/dist/utils/spinner.d.ts +1 -0
- package/dist/utils/spinner.js +13 -0
- package/package.json +9 -2
- package/src/cli.ts +15 -3
- package/src/commands/configPath.ts +10 -0
- package/src/commands/index.ts +4 -0
- package/src/commands/login.ts +34 -0
- package/src/commands/logout.ts +19 -0
- package/src/commands/whoami.ts +20 -0
- package/src/utils/api/client.ts +44 -0
- package/src/utils/auth/ensureValidToken.ts +35 -0
- package/src/utils/auth/getAuthState.ts +36 -0
- package/src/utils/auth/getJWT.ts +20 -0
- package/src/utils/auth/getLoggedInUser.ts +68 -0
- package/src/utils/auth/login.ts +191 -0
- package/src/utils/auth/logout.ts +9 -0
- package/src/utils/auth/refreshJWT.ts +50 -0
- package/src/utils/auth/updateLogin.ts +19 -0
- package/src/utils/cli-generator.ts +14 -3
- package/src/utils/config.ts +3 -0
- package/src/utils/constants.ts +9 -0
- package/src/utils/getCallablePromise.ts +21 -0
- package/src/utils/getConfigPath.ts +5 -0
- package/src/utils/log.ts +18 -0
- package/src/utils/serializeAsync.ts +26 -0
- package/src/utils/spinner.ts +16 -0
- package/tsconfig.json +2 -2
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const zapier_sdk_1 = require("@zapier/zapier-sdk");
|
|
9
|
-
const parameter_resolver_1 = require("./parameter-resolver");
|
|
10
|
-
const pager_1 = require("./pager");
|
|
11
|
-
const schema_formatter_1 = require("./schema-formatter");
|
|
12
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
13
|
-
const util_1 = __importDefault(require("util"));
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { hasResolver, isPositional } from "@zapier/zapier-sdk";
|
|
3
|
+
import { SchemaParameterResolver } from "./parameter-resolver";
|
|
4
|
+
import { createPager } from "./pager";
|
|
5
|
+
import { formatItemsFromSchema } from "./schema-formatter";
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import util from "util";
|
|
14
8
|
// ============================================================================
|
|
15
9
|
// JSON Formatting
|
|
16
10
|
// ============================================================================
|
|
@@ -20,17 +14,17 @@ function formatJsonOutput(data) {
|
|
|
20
14
|
typeof data === "object" &&
|
|
21
15
|
!Array.isArray(data) &&
|
|
22
16
|
(data.success !== undefined || data.id || data.status)) {
|
|
23
|
-
console.log(
|
|
17
|
+
console.log(chalk.green("ā
Action completed successfully!\n"));
|
|
24
18
|
}
|
|
25
19
|
// Use util.inspect for colored output
|
|
26
|
-
console.log(
|
|
20
|
+
console.log(util.inspect(data, { colors: true, depth: null, breakLength: 80 }));
|
|
27
21
|
}
|
|
28
22
|
// ============================================================================
|
|
29
23
|
// Schema Analysis
|
|
30
24
|
// ============================================================================
|
|
31
25
|
function analyzeZodSchema(schema) {
|
|
32
26
|
const parameters = [];
|
|
33
|
-
if (schema instanceof
|
|
27
|
+
if (schema instanceof z.ZodObject) {
|
|
34
28
|
const shape = schema.shape;
|
|
35
29
|
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
36
30
|
const param = analyzeZodField(key, fieldSchema);
|
|
@@ -46,11 +40,11 @@ function analyzeZodField(name, schema) {
|
|
|
46
40
|
let required = true;
|
|
47
41
|
let defaultValue = undefined;
|
|
48
42
|
// Unwrap optional and default wrappers
|
|
49
|
-
if (baseSchema instanceof
|
|
43
|
+
if (baseSchema instanceof z.ZodOptional) {
|
|
50
44
|
required = false;
|
|
51
45
|
baseSchema = baseSchema._def.innerType;
|
|
52
46
|
}
|
|
53
|
-
if (baseSchema instanceof
|
|
47
|
+
if (baseSchema instanceof z.ZodDefault) {
|
|
54
48
|
required = false;
|
|
55
49
|
defaultValue = baseSchema._def.defaultValue();
|
|
56
50
|
baseSchema = baseSchema._def.innerType;
|
|
@@ -58,23 +52,23 @@ function analyzeZodField(name, schema) {
|
|
|
58
52
|
// Determine parameter type
|
|
59
53
|
let paramType = "string";
|
|
60
54
|
let choices;
|
|
61
|
-
if (baseSchema instanceof
|
|
55
|
+
if (baseSchema instanceof z.ZodString) {
|
|
62
56
|
paramType = "string";
|
|
63
57
|
}
|
|
64
|
-
else if (baseSchema instanceof
|
|
58
|
+
else if (baseSchema instanceof z.ZodNumber) {
|
|
65
59
|
paramType = "number";
|
|
66
60
|
}
|
|
67
|
-
else if (baseSchema instanceof
|
|
61
|
+
else if (baseSchema instanceof z.ZodBoolean) {
|
|
68
62
|
paramType = "boolean";
|
|
69
63
|
}
|
|
70
|
-
else if (baseSchema instanceof
|
|
64
|
+
else if (baseSchema instanceof z.ZodArray) {
|
|
71
65
|
paramType = "array";
|
|
72
66
|
}
|
|
73
|
-
else if (baseSchema instanceof
|
|
67
|
+
else if (baseSchema instanceof z.ZodEnum) {
|
|
74
68
|
paramType = "string";
|
|
75
69
|
choices = baseSchema._def.values;
|
|
76
70
|
}
|
|
77
|
-
else if (baseSchema instanceof
|
|
71
|
+
else if (baseSchema instanceof z.ZodRecord) {
|
|
78
72
|
// Handle Record<string, any> as JSON string input
|
|
79
73
|
paramType = "string";
|
|
80
74
|
}
|
|
@@ -86,7 +80,8 @@ function analyzeZodField(name, schema) {
|
|
|
86
80
|
description: schema.description,
|
|
87
81
|
default: defaultValue,
|
|
88
82
|
choices,
|
|
89
|
-
hasResolver:
|
|
83
|
+
hasResolver: hasResolver(name),
|
|
84
|
+
isPositional: isPositional(schema),
|
|
90
85
|
};
|
|
91
86
|
}
|
|
92
87
|
// ============================================================================
|
|
@@ -109,7 +104,7 @@ function methodNameToCliCommand(methodName) {
|
|
|
109
104
|
// ============================================================================
|
|
110
105
|
// CLI Command Generation - Completely Generic
|
|
111
106
|
// ============================================================================
|
|
112
|
-
function generateCliCommands(program, sdk) {
|
|
107
|
+
export function generateCliCommands(program, sdk) {
|
|
113
108
|
// Check if SDK has registry
|
|
114
109
|
if (!sdk.__registry) {
|
|
115
110
|
console.error("SDK registry not available");
|
|
@@ -144,7 +139,7 @@ function createCommandConfig(cliCommandName, sdkMethodName, schema, sdk) {
|
|
|
144
139
|
// Convert CLI args to SDK method parameters
|
|
145
140
|
const rawParams = convertCliArgsToSdkParams(parameters, args.slice(0, -1), options);
|
|
146
141
|
// Resolve missing parameters interactively using schema metadata
|
|
147
|
-
const resolver = new
|
|
142
|
+
const resolver = new SchemaParameterResolver();
|
|
148
143
|
const resolvedParams = await resolver.resolveParameters(schema, rawParams, sdk);
|
|
149
144
|
if (shouldUsePaging && !shouldUseJson) {
|
|
150
145
|
// Use interactive paging for list commands
|
|
@@ -171,8 +166,8 @@ function createCommandConfig(cliCommandName, sdkMethodName, schema, sdk) {
|
|
|
171
166
|
}
|
|
172
167
|
else if (hasOutputFile) {
|
|
173
168
|
// Show success message for file output instead of printing generated content
|
|
174
|
-
console.log(
|
|
175
|
-
console.log(
|
|
169
|
+
console.log(chalk.green(`ā
${cliCommandName} completed successfully!`));
|
|
170
|
+
console.log(chalk.gray(`Output written to: ${resolvedParams.output}`));
|
|
176
171
|
}
|
|
177
172
|
}
|
|
178
173
|
}
|
|
@@ -181,19 +176,19 @@ function createCommandConfig(cliCommandName, sdkMethodName, schema, sdk) {
|
|
|
181
176
|
if (error instanceof Error && error.message.includes('"code"')) {
|
|
182
177
|
try {
|
|
183
178
|
const validationErrors = JSON.parse(error.message);
|
|
184
|
-
console.error(
|
|
179
|
+
console.error(chalk.red("ā Validation Error:"));
|
|
185
180
|
validationErrors.forEach((err) => {
|
|
186
181
|
const field = err.path?.join(".") || "unknown";
|
|
187
|
-
console.error(
|
|
182
|
+
console.error(chalk.yellow(` ⢠${field}: ${err.message}`));
|
|
188
183
|
});
|
|
189
|
-
console.error("\n" +
|
|
184
|
+
console.error("\n" + chalk.dim(`Use --help to see available options`));
|
|
190
185
|
}
|
|
191
186
|
catch {
|
|
192
|
-
console.error(
|
|
187
|
+
console.error(chalk.red("Error:"), error.message);
|
|
193
188
|
}
|
|
194
189
|
}
|
|
195
190
|
else {
|
|
196
|
-
console.error(
|
|
191
|
+
console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
|
|
197
192
|
}
|
|
198
193
|
process.exit(1);
|
|
199
194
|
}
|
|
@@ -218,6 +213,10 @@ function addCommand(program, commandName, config) {
|
|
|
218
213
|
// Required parameters without resolvers become required positional arguments
|
|
219
214
|
command.argument(`<${kebabName}>`, param.description || `${kebabName} parameter`);
|
|
220
215
|
}
|
|
216
|
+
else if (param.isPositional) {
|
|
217
|
+
// Optional parameters marked as positional become optional positional arguments
|
|
218
|
+
command.argument(`[${kebabName}]`, param.description || `${kebabName} parameter`);
|
|
219
|
+
}
|
|
221
220
|
else {
|
|
222
221
|
// Optional parameters become flags (whether they have resolvers or not)
|
|
223
222
|
const flags = [`--${kebabName}`];
|
|
@@ -239,10 +238,11 @@ function addCommand(program, commandName, config) {
|
|
|
239
238
|
// ============================================================================
|
|
240
239
|
function convertCliArgsToSdkParams(parameters, positionalArgs, options) {
|
|
241
240
|
const sdkParams = {};
|
|
242
|
-
// Handle positional arguments (required parameters
|
|
241
|
+
// Handle positional arguments (required parameters or optional positional parameters)
|
|
243
242
|
let argIndex = 0;
|
|
244
243
|
parameters.forEach((param) => {
|
|
245
|
-
if (param.required
|
|
244
|
+
if ((param.required || param.isPositional) &&
|
|
245
|
+
argIndex < positionalArgs.length) {
|
|
246
246
|
// Use the original camelCase parameter name for the SDK
|
|
247
247
|
sdkParams[param.name] = convertValue(positionalArgs[argIndex], param.type);
|
|
248
248
|
argIndex++;
|
|
@@ -288,8 +288,8 @@ function convertValue(value, type) {
|
|
|
288
288
|
async function handlePaginatedList(sdkMethodName, baseParams, sdk, schema) {
|
|
289
289
|
const limit = baseParams.limit || 20;
|
|
290
290
|
const itemName = getItemNameFromMethod(sdkMethodName);
|
|
291
|
-
console.log(
|
|
292
|
-
const pager =
|
|
291
|
+
console.log(chalk.blue(`š Fetching ${itemName}...`));
|
|
292
|
+
const pager = createPager({
|
|
293
293
|
pageSize: Math.min(limit, 20),
|
|
294
294
|
itemName,
|
|
295
295
|
});
|
|
@@ -298,14 +298,14 @@ async function handlePaginatedList(sdkMethodName, baseParams, sdk, schema) {
|
|
|
298
298
|
if (items.length > 0) {
|
|
299
299
|
console.clear();
|
|
300
300
|
}
|
|
301
|
-
console.log(
|
|
301
|
+
console.log(chalk.blue(`š ${getListTitleFromMethod(sdkMethodName)}\n`));
|
|
302
302
|
if (items.length === 0) {
|
|
303
|
-
console.log(
|
|
303
|
+
console.log(chalk.yellow(`No ${itemName} found.`));
|
|
304
304
|
return;
|
|
305
305
|
}
|
|
306
306
|
// Use schema for formatting
|
|
307
307
|
if (schema) {
|
|
308
|
-
|
|
308
|
+
formatItemsFromSchema(schema, items);
|
|
309
309
|
}
|
|
310
310
|
else {
|
|
311
311
|
// Fallback to generic formatting
|
|
@@ -314,7 +314,7 @@ async function handlePaginatedList(sdkMethodName, baseParams, sdk, schema) {
|
|
|
314
314
|
const totalInfo = totalAvailable
|
|
315
315
|
? ` of ${totalAvailable.toLocaleString()} total`
|
|
316
316
|
: "";
|
|
317
|
-
console.log(
|
|
317
|
+
console.log(chalk.green(`\nā
Showing ${totalShown}${totalInfo} ${itemName}`));
|
|
318
318
|
};
|
|
319
319
|
await pager.paginate((params) => sdk[sdkMethodName]({
|
|
320
320
|
...baseParams,
|
|
@@ -337,13 +337,13 @@ function formatNonPaginatedResults(result, requestedLimit, userSpecifiedLimit, u
|
|
|
337
337
|
}
|
|
338
338
|
const itemName = methodName ? getItemNameFromMethod(methodName) : "items";
|
|
339
339
|
if (result.length === 0) {
|
|
340
|
-
console.log(
|
|
340
|
+
console.log(chalk.yellow(`No ${itemName} found.`));
|
|
341
341
|
return;
|
|
342
342
|
}
|
|
343
|
-
console.log(
|
|
343
|
+
console.log(chalk.green(`\nā
Found ${result.length} ${itemName}:\n`));
|
|
344
344
|
// Use schema for formatting
|
|
345
345
|
if (schema) {
|
|
346
|
-
|
|
346
|
+
formatItemsFromSchema(schema, result);
|
|
347
347
|
}
|
|
348
348
|
else {
|
|
349
349
|
// Fallback to generic formatting
|
|
@@ -351,19 +351,19 @@ function formatNonPaginatedResults(result, requestedLimit, userSpecifiedLimit, u
|
|
|
351
351
|
}
|
|
352
352
|
// Show appropriate status message
|
|
353
353
|
if (userSpecifiedLimit && requestedLimit) {
|
|
354
|
-
console.log(
|
|
354
|
+
console.log(chalk.gray(`\nš Showing up to ${requestedLimit} ${itemName} (--limit ${requestedLimit})`));
|
|
355
355
|
}
|
|
356
356
|
else {
|
|
357
|
-
console.log(
|
|
357
|
+
console.log(chalk.gray(`\nš All available ${itemName} shown`));
|
|
358
358
|
}
|
|
359
359
|
}
|
|
360
360
|
function formatItemsGeneric(items) {
|
|
361
361
|
// Fallback formatting for items without schema metadata
|
|
362
362
|
items.forEach((item, index) => {
|
|
363
363
|
const name = item.name || item.key || item.id || "Item";
|
|
364
|
-
console.log(`${
|
|
364
|
+
console.log(`${chalk.gray(`${index + 1}.`)} ${chalk.cyan(name)}`);
|
|
365
365
|
if (item.description) {
|
|
366
|
-
console.log(` ${
|
|
366
|
+
console.log(` ${chalk.dim(item.description)}`);
|
|
367
367
|
}
|
|
368
368
|
console.log();
|
|
369
369
|
});
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const ZAPIER_BASE = "https://zapier.com";
|
|
2
|
+
export declare const LOGIN_CLIENT_ID = "K5eEnRE9TTmSFATdkkWhKF8NOKwoiOnYAyIqJjae";
|
|
3
|
+
export declare const LOGIN_PORTS: number[];
|
|
4
|
+
export declare const LOGIN_TIMEOUT_MS = 300000;
|
|
5
|
+
export declare const AUTH_MODE_HEADER = "X-Auth";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const ZAPIER_BASE = "https://zapier.com";
|
|
2
|
+
// OAuth client ID for zapier-sdk CLI
|
|
3
|
+
export const LOGIN_CLIENT_ID = "K5eEnRE9TTmSFATdkkWhKF8NOKwoiOnYAyIqJjae";
|
|
4
|
+
export const LOGIN_PORTS = [49505, 50575, 52804, 55981, 61010, 63851];
|
|
5
|
+
export const LOGIN_TIMEOUT_MS = 300000; // 5 minutes
|
|
6
|
+
export const AUTH_MODE_HEADER = "X-Auth";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const getCallablePromise = () => {
|
|
2
|
+
let resolve = () => { };
|
|
3
|
+
let reject = () => { };
|
|
4
|
+
const promise = new Promise((_resolve, _reject) => {
|
|
5
|
+
resolve = _resolve;
|
|
6
|
+
reject = _reject;
|
|
7
|
+
});
|
|
8
|
+
return {
|
|
9
|
+
promise,
|
|
10
|
+
resolve,
|
|
11
|
+
reject,
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
export default getCallablePromise;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getConfigPath: () => string;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
const log = {
|
|
3
|
+
info: (message, ...args) => {
|
|
4
|
+
console.log(chalk.blue("ā¹"), message, ...args);
|
|
5
|
+
},
|
|
6
|
+
error: (message, ...args) => {
|
|
7
|
+
console.error(chalk.red("ā"), message, ...args);
|
|
8
|
+
},
|
|
9
|
+
success: (message, ...args) => {
|
|
10
|
+
console.log(chalk.green("ā"), message, ...args);
|
|
11
|
+
},
|
|
12
|
+
warn: (message, ...args) => {
|
|
13
|
+
console.log(chalk.yellow("ā "), message, ...args);
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
export default log;
|
package/dist/utils/pager.js
CHANGED
|
@@ -1,19 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.Pager = void 0;
|
|
7
|
-
exports.createPager = createPager;
|
|
8
|
-
exports.fetchAllPages = fetchAllPages;
|
|
9
|
-
exports.showPaginationStatus = showPaginationStatus;
|
|
10
|
-
const inquirer_1 = __importDefault(require("inquirer"));
|
|
11
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
1
|
+
import inquirer from "inquirer";
|
|
2
|
+
import chalk from "chalk";
|
|
12
3
|
/**
|
|
13
4
|
* Generic pager that handles pagination for any data source
|
|
14
5
|
* Supports interactive "load more" functionality
|
|
15
6
|
*/
|
|
16
|
-
class Pager {
|
|
7
|
+
export class Pager {
|
|
17
8
|
constructor(options = {}) {
|
|
18
9
|
this.allItems = [];
|
|
19
10
|
this.currentOffset = 0;
|
|
@@ -67,7 +58,7 @@ class Pager {
|
|
|
67
58
|
: "";
|
|
68
59
|
const message = `Load more ${this.itemName}? (${this.allItems.length}${totalInfo} shown so far)`;
|
|
69
60
|
// Ask user if they want to load more
|
|
70
|
-
const { loadMore } = await
|
|
61
|
+
const { loadMore } = await inquirer.prompt([
|
|
71
62
|
{
|
|
72
63
|
type: "confirm",
|
|
73
64
|
name: "loadMore",
|
|
@@ -98,17 +89,16 @@ class Pager {
|
|
|
98
89
|
this.currentOffset = 0;
|
|
99
90
|
}
|
|
100
91
|
}
|
|
101
|
-
exports.Pager = Pager;
|
|
102
92
|
/**
|
|
103
93
|
* Convenience function to create a pager for a specific use case
|
|
104
94
|
*/
|
|
105
|
-
function createPager(options = {}) {
|
|
95
|
+
export function createPager(options = {}) {
|
|
106
96
|
return new Pager(options);
|
|
107
97
|
}
|
|
108
98
|
/**
|
|
109
99
|
* Simple pagination without interactivity - just fetches all results up to a limit
|
|
110
100
|
*/
|
|
111
|
-
async function fetchAllPages(fetchFunction, baseParams, maxResults = 100) {
|
|
101
|
+
export async function fetchAllPages(fetchFunction, baseParams, maxResults = 100) {
|
|
112
102
|
const pageSize = Math.min(maxResults, 50); // Reasonable page size
|
|
113
103
|
const allItems = [];
|
|
114
104
|
let offset = 0;
|
|
@@ -136,12 +126,12 @@ async function fetchAllPages(fetchFunction, baseParams, maxResults = 100) {
|
|
|
136
126
|
/**
|
|
137
127
|
* Display helper for showing pagination status
|
|
138
128
|
*/
|
|
139
|
-
function showPaginationStatus(currentCount, requestedLimit, itemName = "items") {
|
|
129
|
+
export function showPaginationStatus(currentCount, requestedLimit, itemName = "items") {
|
|
140
130
|
if (currentCount >= requestedLimit) {
|
|
141
|
-
console.log(
|
|
142
|
-
console.log(
|
|
131
|
+
console.log(chalk.yellow(`\nš Showing first ${currentCount} ${itemName} (limit: ${requestedLimit})`));
|
|
132
|
+
console.log(chalk.gray(`Use --limit to increase the limit, or add paging with --page`));
|
|
143
133
|
}
|
|
144
134
|
else {
|
|
145
|
-
console.log(
|
|
135
|
+
console.log(chalk.gray(`\nš Showing all ${currentCount} ${itemName}`));
|
|
146
136
|
}
|
|
147
137
|
}
|
|
@@ -1,23 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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
|
-
const zapier_sdk_1 = require("@zapier/zapier-sdk");
|
|
1
|
+
import inquirer from "inquirer";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { getResolver, hasResolver, getResolutionOrderForParams, } from "@zapier/zapier-sdk";
|
|
11
5
|
// ============================================================================
|
|
12
6
|
// Schema Parameter Resolver
|
|
13
7
|
// ============================================================================
|
|
14
|
-
class SchemaParameterResolver {
|
|
8
|
+
export class SchemaParameterResolver {
|
|
15
9
|
async resolveParameters(schema, providedParams, sdk) {
|
|
16
10
|
// 1. Try to parse with current parameters
|
|
17
11
|
const parseResult = schema.safeParse(providedParams);
|
|
18
12
|
// Get all schema parameters to check which ones have resolvers
|
|
19
13
|
const allParams = this.extractParametersFromSchema(schema);
|
|
20
|
-
const resolvableParams = allParams.filter((param) =>
|
|
14
|
+
const resolvableParams = allParams.filter((param) => hasResolver(param.name));
|
|
21
15
|
// Get all missing parameters that have resolvers
|
|
22
16
|
const missingResolvable = resolvableParams.filter((param) => {
|
|
23
17
|
const hasValue = this.getNestedValue(providedParams, param.path) !== undefined;
|
|
@@ -57,7 +51,7 @@ class SchemaParameterResolver {
|
|
|
57
51
|
};
|
|
58
52
|
if (functionallyRequired.length > 0) {
|
|
59
53
|
const requiredParamNames = functionallyRequired.map((p) => p.name);
|
|
60
|
-
const requiredResolutionOrder =
|
|
54
|
+
const requiredResolutionOrder = getResolutionOrderForParams(requiredParamNames);
|
|
61
55
|
const orderedRequiredParams = requiredResolutionOrder
|
|
62
56
|
.map((paramName) => functionallyRequired.find((p) => p.name === paramName))
|
|
63
57
|
.filter((param) => param !== undefined);
|
|
@@ -70,10 +64,10 @@ class SchemaParameterResolver {
|
|
|
70
64
|
}
|
|
71
65
|
catch (error) {
|
|
72
66
|
if (this.isUserCancellation(error)) {
|
|
73
|
-
console.log(
|
|
67
|
+
console.log(chalk.yellow("\n\nOperation cancelled by user"));
|
|
74
68
|
process.exit(0);
|
|
75
69
|
}
|
|
76
|
-
console.error(
|
|
70
|
+
console.error(chalk.red(`Failed to resolve ${param.name}:`), error);
|
|
77
71
|
throw error;
|
|
78
72
|
}
|
|
79
73
|
}
|
|
@@ -81,7 +75,7 @@ class SchemaParameterResolver {
|
|
|
81
75
|
// 3. Ask user if they want to resolve truly optional parameters
|
|
82
76
|
if (trulyOptional.length > 0) {
|
|
83
77
|
const optionalNames = trulyOptional.map((p) => p.name).join(", ");
|
|
84
|
-
const shouldResolveOptional = await
|
|
78
|
+
const shouldResolveOptional = await inquirer.prompt([
|
|
85
79
|
{
|
|
86
80
|
type: "confirm",
|
|
87
81
|
name: "resolveOptional",
|
|
@@ -92,7 +86,7 @@ class SchemaParameterResolver {
|
|
|
92
86
|
if (shouldResolveOptional.resolveOptional) {
|
|
93
87
|
// Resolve optional parameters using their resolvers
|
|
94
88
|
const optionalParamNames = trulyOptional.map((p) => p.name);
|
|
95
|
-
const optionalResolutionOrder =
|
|
89
|
+
const optionalResolutionOrder = getResolutionOrderForParams(optionalParamNames);
|
|
96
90
|
const orderedOptionalParams = optionalResolutionOrder
|
|
97
91
|
.map((paramName) => trulyOptional.find((p) => p.name === paramName))
|
|
98
92
|
.filter((param) => param !== undefined);
|
|
@@ -105,10 +99,10 @@ class SchemaParameterResolver {
|
|
|
105
99
|
}
|
|
106
100
|
catch (error) {
|
|
107
101
|
if (this.isUserCancellation(error)) {
|
|
108
|
-
console.log(
|
|
102
|
+
console.log(chalk.yellow("\n\nOperation cancelled by user"));
|
|
109
103
|
process.exit(0);
|
|
110
104
|
}
|
|
111
|
-
console.error(
|
|
105
|
+
console.error(chalk.red(`Failed to resolve ${param.name}:`), error);
|
|
112
106
|
throw error;
|
|
113
107
|
}
|
|
114
108
|
}
|
|
@@ -117,7 +111,7 @@ class SchemaParameterResolver {
|
|
|
117
111
|
// 3. Validate final parameters
|
|
118
112
|
const finalResult = schema.safeParse(resolvedParams);
|
|
119
113
|
if (!finalResult.success) {
|
|
120
|
-
console.error(
|
|
114
|
+
console.error(chalk.red("ā Parameter validation failed after resolution:"));
|
|
121
115
|
throw finalResult.error;
|
|
122
116
|
}
|
|
123
117
|
return finalResult.data;
|
|
@@ -125,7 +119,7 @@ class SchemaParameterResolver {
|
|
|
125
119
|
extractParametersFromSchema(schema) {
|
|
126
120
|
const parameters = [];
|
|
127
121
|
// Only handle ZodObject at the top level
|
|
128
|
-
if (schema instanceof
|
|
122
|
+
if (schema instanceof z.ZodObject) {
|
|
129
123
|
const shape = schema.shape;
|
|
130
124
|
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
131
125
|
const param = this.analyzeFieldSchema(key, fieldSchema);
|
|
@@ -140,11 +134,11 @@ class SchemaParameterResolver {
|
|
|
140
134
|
let baseSchema = fieldSchema;
|
|
141
135
|
let isRequired = true;
|
|
142
136
|
// Check if field is optional or has default
|
|
143
|
-
if (baseSchema instanceof
|
|
137
|
+
if (baseSchema instanceof z.ZodOptional) {
|
|
144
138
|
isRequired = false;
|
|
145
139
|
baseSchema = baseSchema._def.innerType;
|
|
146
140
|
}
|
|
147
|
-
if (baseSchema instanceof
|
|
141
|
+
if (baseSchema instanceof z.ZodDefault) {
|
|
148
142
|
isRequired = false;
|
|
149
143
|
baseSchema = baseSchema._def.innerType;
|
|
150
144
|
}
|
|
@@ -163,11 +157,11 @@ class SchemaParameterResolver {
|
|
|
163
157
|
};
|
|
164
158
|
}
|
|
165
159
|
async resolveParameter(param, context) {
|
|
166
|
-
const resolver =
|
|
160
|
+
const resolver = getResolver(param.name);
|
|
167
161
|
if (!resolver) {
|
|
168
162
|
throw new Error(`No resolver found for parameter: ${param.name}`);
|
|
169
163
|
}
|
|
170
|
-
console.log(
|
|
164
|
+
console.log(chalk.blue(`\nš Resolving ${param.name}...`));
|
|
171
165
|
if (resolver.type === "static") {
|
|
172
166
|
// Static resolver - just prompt for input
|
|
173
167
|
const promptConfig = {
|
|
@@ -176,33 +170,33 @@ class SchemaParameterResolver {
|
|
|
176
170
|
message: `Enter ${param.name}:`,
|
|
177
171
|
...(resolver.placeholder && { default: resolver.placeholder }),
|
|
178
172
|
};
|
|
179
|
-
const answers = await
|
|
173
|
+
const answers = await inquirer.prompt([promptConfig]);
|
|
180
174
|
return answers[param.name];
|
|
181
175
|
}
|
|
182
176
|
else if (resolver.type === "dynamic") {
|
|
183
177
|
// Dynamic resolver - fetch options and prompt for selection
|
|
184
178
|
try {
|
|
185
|
-
console.log(
|
|
179
|
+
console.log(chalk.gray(`Fetching options for ${param.name}...`));
|
|
186
180
|
const items = await resolver.fetch(context.sdk, context.resolvedParams);
|
|
187
181
|
if (!items || items.length === 0) {
|
|
188
182
|
throw new Error(`No options available for ${param.name}`);
|
|
189
183
|
}
|
|
190
184
|
const promptConfig = resolver.prompt(items, context.resolvedParams);
|
|
191
|
-
const answers = await
|
|
185
|
+
const answers = await inquirer.prompt([promptConfig]);
|
|
192
186
|
return answers[param.name];
|
|
193
187
|
}
|
|
194
188
|
catch (error) {
|
|
195
|
-
console.error(
|
|
189
|
+
console.error(chalk.red(`Failed to fetch options for ${param.name}:`), error instanceof Error ? error.message : error);
|
|
196
190
|
throw error;
|
|
197
191
|
}
|
|
198
192
|
}
|
|
199
193
|
else if (resolver.type === "fields") {
|
|
200
194
|
// Fields resolver - fetch field definitions and prompt for each input
|
|
201
195
|
try {
|
|
202
|
-
console.log(
|
|
196
|
+
console.log(chalk.gray(`Fetching input fields for ${param.name}...`));
|
|
203
197
|
const fields = await resolver.fetch(context.sdk, context.resolvedParams);
|
|
204
198
|
if (!fields || fields.length === 0) {
|
|
205
|
-
console.log(
|
|
199
|
+
console.log(chalk.yellow(`No input fields required for this action.`));
|
|
206
200
|
return {};
|
|
207
201
|
}
|
|
208
202
|
const inputs = {};
|
|
@@ -211,17 +205,17 @@ class SchemaParameterResolver {
|
|
|
211
205
|
const optionalFields = fields.filter((field) => !field.required);
|
|
212
206
|
// First, prompt for all required fields
|
|
213
207
|
if (requiredFields.length > 0) {
|
|
214
|
-
console.log(
|
|
208
|
+
console.log(chalk.blue(`\nš Please provide values for the following input fields:`));
|
|
215
209
|
for (const field of requiredFields) {
|
|
216
210
|
await this.promptForField(field, inputs);
|
|
217
211
|
}
|
|
218
212
|
}
|
|
219
213
|
// Then ask if user wants to configure optional fields
|
|
220
214
|
if (optionalFields.length > 0) {
|
|
221
|
-
console.log(
|
|
215
|
+
console.log(chalk.gray(`\nThere are ${optionalFields.length} optional field(s) available.`));
|
|
222
216
|
let shouldConfigureOptional;
|
|
223
217
|
try {
|
|
224
|
-
shouldConfigureOptional = await
|
|
218
|
+
shouldConfigureOptional = await inquirer.prompt([
|
|
225
219
|
{
|
|
226
220
|
type: "confirm",
|
|
227
221
|
name: "configure",
|
|
@@ -232,13 +226,13 @@ class SchemaParameterResolver {
|
|
|
232
226
|
}
|
|
233
227
|
catch (error) {
|
|
234
228
|
if (this.isUserCancellation(error)) {
|
|
235
|
-
console.log(
|
|
229
|
+
console.log(chalk.yellow("\n\nOperation cancelled by user"));
|
|
236
230
|
process.exit(0);
|
|
237
231
|
}
|
|
238
232
|
throw error;
|
|
239
233
|
}
|
|
240
234
|
if (shouldConfigureOptional.configure) {
|
|
241
|
-
console.log(
|
|
235
|
+
console.log(chalk.cyan(`\nOptional fields:`));
|
|
242
236
|
for (const field of optionalFields) {
|
|
243
237
|
await this.promptForField(field, inputs);
|
|
244
238
|
}
|
|
@@ -247,7 +241,7 @@ class SchemaParameterResolver {
|
|
|
247
241
|
return inputs;
|
|
248
242
|
}
|
|
249
243
|
catch (error) {
|
|
250
|
-
console.error(
|
|
244
|
+
console.error(chalk.red(`Failed to fetch fields for ${param.name}:`), error instanceof Error ? error.message : error);
|
|
251
245
|
throw error;
|
|
252
246
|
}
|
|
253
247
|
}
|
|
@@ -271,7 +265,7 @@ class SchemaParameterResolver {
|
|
|
271
265
|
type: field.type === "boolean" ? "confirm" : "input",
|
|
272
266
|
name: field.key,
|
|
273
267
|
message: `${field.label || field.key}${field.required ? " (required)" : " (optional)"}:`,
|
|
274
|
-
...(field.helpText && { prefix:
|
|
268
|
+
...(field.helpText && { prefix: chalk.gray(`ā¹ ${field.helpText}\n`) }),
|
|
275
269
|
...(field.default && { default: field.default }),
|
|
276
270
|
};
|
|
277
271
|
if (field.choices && field.choices.length > 0) {
|
|
@@ -282,7 +276,7 @@ class SchemaParameterResolver {
|
|
|
282
276
|
}));
|
|
283
277
|
}
|
|
284
278
|
try {
|
|
285
|
-
const answer = await
|
|
279
|
+
const answer = await inquirer.prompt([fieldPrompt]);
|
|
286
280
|
if (answer[field.key] !== undefined && answer[field.key] !== "") {
|
|
287
281
|
inputs[field.key] = answer[field.key];
|
|
288
282
|
}
|
|
@@ -292,7 +286,7 @@ class SchemaParameterResolver {
|
|
|
292
286
|
}
|
|
293
287
|
catch (error) {
|
|
294
288
|
if (this.isUserCancellation(error)) {
|
|
295
|
-
console.log(
|
|
289
|
+
console.log(chalk.yellow("\n\nOperation cancelled by user"));
|
|
296
290
|
process.exit(0);
|
|
297
291
|
}
|
|
298
292
|
throw error;
|
|
@@ -304,4 +298,3 @@ class SchemaParameterResolver {
|
|
|
304
298
|
error?.isTTYError);
|
|
305
299
|
}
|
|
306
300
|
}
|
|
307
|
-
exports.SchemaParameterResolver = SchemaParameterResolver;
|