@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
package/bin/zsdk.js
ADDED
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const commander_1 = require("commander");
|
|
5
|
+
const actions_sdk_1 = require("@zapier/actions-sdk");
|
|
6
|
+
const cli_generator_1 = require("./utils/cli-generator");
|
|
7
|
+
const program = new commander_1.Command();
|
|
8
|
+
program
|
|
9
|
+
.name("zapier-sdk")
|
|
10
|
+
.description("CLI for Zapier SDK - Commands auto-generated from SDK schemas")
|
|
11
|
+
.version("1.0.0")
|
|
12
|
+
.option("--debug", "Enable debug logging");
|
|
13
|
+
// Check for debug flag early
|
|
14
|
+
const isDebugMode = process.env.DEBUG === "true" || process.argv.includes("--debug");
|
|
15
|
+
// Create SDK instance for CLI operations
|
|
16
|
+
// Auth will be resolved from environment variables or command options
|
|
17
|
+
const sdk = (0, actions_sdk_1.createActionsSDK)({
|
|
18
|
+
// Token will be picked up from ZAPIER_TOKEN env var or provided via options
|
|
19
|
+
debug: isDebugMode,
|
|
20
|
+
});
|
|
21
|
+
// Generate CLI commands from SDK schemas
|
|
22
|
+
(0, cli_generator_1.generateCLICommands)(program, sdk);
|
|
23
|
+
// Add enhanced help information
|
|
24
|
+
(0, cli_generator_1.enhanceCommandHelp)(program);
|
|
25
|
+
program.parse();
|
|
@@ -0,0 +1,295 @@
|
|
|
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.actionCommand = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
+
const ora_1 = __importDefault(require("ora"));
|
|
11
|
+
const cli_table3_1 = __importDefault(require("cli-table3"));
|
|
12
|
+
const actions_sdk_1 = require("@zapier/actions-sdk");
|
|
13
|
+
const auth_picker_1 = require("../utils/auth-picker");
|
|
14
|
+
exports.actionCommand = new commander_1.Command('action')
|
|
15
|
+
.description('Execute Zapier actions with interactive field collection')
|
|
16
|
+
.argument('<app>', 'App slug (e.g., slack)')
|
|
17
|
+
.argument('<type>', 'Action type (e.g., search, read, write)')
|
|
18
|
+
.argument('<action>', 'Action key (e.g., user_by_email)')
|
|
19
|
+
.option('--auth <id>', 'Authentication ID', (value) => parseInt(value))
|
|
20
|
+
.option('--token <token>', 'Authentication token (JWT or Bearer) - can also use ZAPIER_TOKEN env var')
|
|
21
|
+
.option('--field <key=value>', 'Pre-supply field values', collectFields, [])
|
|
22
|
+
.option('--interactive', 'Force interactive mode even with all fields provided')
|
|
23
|
+
.option('--help-fields', 'Show field requirements without executing')
|
|
24
|
+
.option('--debug', 'Enable debug logging')
|
|
25
|
+
.action(executeAction);
|
|
26
|
+
function collectFields(value, previous = []) {
|
|
27
|
+
return previous.concat([value]);
|
|
28
|
+
}
|
|
29
|
+
async function executeAction(app, type, action, options) {
|
|
30
|
+
try {
|
|
31
|
+
console.log(chalk_1.default.blue('š Zapier Action Executor'));
|
|
32
|
+
console.log(chalk_1.default.gray(`App: ${app}, Type: ${type}, Action: ${action}\n`));
|
|
33
|
+
// Get token from option or environment variable
|
|
34
|
+
const token = options.token || process.env.ZAPIER_TOKEN;
|
|
35
|
+
// Validate required parameters early
|
|
36
|
+
if (!token) {
|
|
37
|
+
console.error(chalk_1.default.red('Authentication token is required'));
|
|
38
|
+
console.log(chalk_1.default.gray('Use --token <jwt-or-bearer-token> or set ZAPIER_TOKEN environment variable'));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
// Create SDK instance for browsing (without specific app auth)
|
|
42
|
+
const browseSdk = (0, actions_sdk_1.createActionsSDK)({
|
|
43
|
+
auth: {
|
|
44
|
+
token: token,
|
|
45
|
+
authentications: {}
|
|
46
|
+
},
|
|
47
|
+
debug: options.debug
|
|
48
|
+
});
|
|
49
|
+
let authId = options.auth;
|
|
50
|
+
if (!authId) {
|
|
51
|
+
console.log(chalk_1.default.yellow('No authentication ID provided. Let\'s select one...'));
|
|
52
|
+
const authResult = await (0, auth_picker_1.pickAuthentication)({
|
|
53
|
+
sdk: browseSdk,
|
|
54
|
+
appKey: app,
|
|
55
|
+
message: `Select an authentication for ${app} action execution:`
|
|
56
|
+
});
|
|
57
|
+
if (authResult.skipped) {
|
|
58
|
+
console.error(chalk_1.default.red('Authentication ID is required for action execution'));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
authId = authResult.authId;
|
|
62
|
+
}
|
|
63
|
+
// Create SDK instance with selected authentication
|
|
64
|
+
const sdk = (0, actions_sdk_1.createActionsSDK)({
|
|
65
|
+
auth: {
|
|
66
|
+
token: token,
|
|
67
|
+
authentications: {
|
|
68
|
+
[app]: [{ id: authId }]
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
debug: options.debug
|
|
72
|
+
});
|
|
73
|
+
// Fetch action fields
|
|
74
|
+
const spinner = (0, ora_1.default)('Fetching action field requirements...').start();
|
|
75
|
+
let fields;
|
|
76
|
+
try {
|
|
77
|
+
fields = await sdk.fields.list({
|
|
78
|
+
app: app,
|
|
79
|
+
action: action,
|
|
80
|
+
type: type,
|
|
81
|
+
authId: authId
|
|
82
|
+
});
|
|
83
|
+
spinner.succeed('Field requirements loaded');
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
spinner.fail('Failed to fetch field requirements');
|
|
87
|
+
if (error instanceof actions_sdk_1.AppNotFoundError) {
|
|
88
|
+
console.error(chalk_1.default.red(`ā ${error.message}`));
|
|
89
|
+
console.log(chalk_1.default.gray('Use "zapier browse apps" to see available apps'));
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
console.error(chalk_1.default.red('Error:'), error instanceof Error ? error.message : 'Unknown error');
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// Show field help if requested
|
|
96
|
+
if (options.helpFields) {
|
|
97
|
+
displayFieldHelp(fields);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// Parse pre-supplied fields
|
|
101
|
+
const suppliedFields = parseSuppliedFields(options.field || []);
|
|
102
|
+
// Collect missing fields interactively
|
|
103
|
+
const allInputs = await collectAllFields(fields, suppliedFields, options.interactive);
|
|
104
|
+
// Validate required fields
|
|
105
|
+
const missingRequired = validateRequiredFields(fields, allInputs);
|
|
106
|
+
if (missingRequired.length > 0) {
|
|
107
|
+
console.error(chalk_1.default.red('Missing required fields:'), missingRequired.join(', '));
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
// Execute action
|
|
111
|
+
console.log(chalk_1.default.yellow('\nš” Executing action...'));
|
|
112
|
+
const executionSpinner = (0, ora_1.default)('Running action').start();
|
|
113
|
+
try {
|
|
114
|
+
const result = await sdk.actions.run[app][type][action]({
|
|
115
|
+
inputs: allInputs
|
|
116
|
+
});
|
|
117
|
+
executionSpinner.succeed('Action completed');
|
|
118
|
+
displayResults(result);
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
executionSpinner.fail('Action execution failed');
|
|
122
|
+
console.error(chalk_1.default.red('Error:'), error instanceof Error ? error.message : 'Unknown error');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
console.error(chalk_1.default.red('Unexpected error:'), error instanceof Error ? error.message : 'Unknown error');
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function displayFieldHelp(fields) {
|
|
131
|
+
console.log(chalk_1.default.green('š Action Field Requirements\n'));
|
|
132
|
+
if (fields.length === 0) {
|
|
133
|
+
console.log(chalk_1.default.gray('No fields required for this action.'));
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const table = new cli_table3_1.default({
|
|
137
|
+
head: ['Field', 'Required', 'Type', 'Description'],
|
|
138
|
+
style: { head: ['cyan'] },
|
|
139
|
+
wordWrap: true,
|
|
140
|
+
colWidths: [20, 10, 15, 50]
|
|
141
|
+
});
|
|
142
|
+
fields.forEach(field => {
|
|
143
|
+
const description = [
|
|
144
|
+
field.helpText,
|
|
145
|
+
field.placeholder ? `Placeholder: ${field.placeholder}` : '',
|
|
146
|
+
field.default ? `Default: ${field.default}` : '',
|
|
147
|
+
field.choices && field.choices.length > 0 ?
|
|
148
|
+
`Choices: ${field.choices.map((c) => c.label || c.value).join(', ')}` : ''
|
|
149
|
+
].filter(Boolean).join('\n');
|
|
150
|
+
table.push([
|
|
151
|
+
field.label || field.key,
|
|
152
|
+
field.required ? chalk_1.default.red('Yes') : chalk_1.default.gray('No'),
|
|
153
|
+
field.type || 'string',
|
|
154
|
+
description || chalk_1.default.gray('No description')
|
|
155
|
+
]);
|
|
156
|
+
});
|
|
157
|
+
console.log(table.toString());
|
|
158
|
+
}
|
|
159
|
+
function parseSuppliedFields(fieldArgs) {
|
|
160
|
+
const fields = {};
|
|
161
|
+
fieldArgs.forEach(arg => {
|
|
162
|
+
const [key, ...valueParts] = arg.split('=');
|
|
163
|
+
if (key && valueParts.length > 0) {
|
|
164
|
+
const value = valueParts.join('='); // Handle values with = in them
|
|
165
|
+
fields[key] = value;
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
return fields;
|
|
169
|
+
}
|
|
170
|
+
async function collectAllFields(fields, suppliedFields, forceInteractive = false) {
|
|
171
|
+
const allInputs = { ...suppliedFields };
|
|
172
|
+
// Find missing required fields
|
|
173
|
+
const missingRequired = fields.filter(field => field.required && !(field.key in allInputs));
|
|
174
|
+
// Find optional fields that aren't supplied
|
|
175
|
+
const missingOptional = fields.filter(field => !field.required && !(field.key in allInputs));
|
|
176
|
+
// If we have all required fields and not forcing interactive, we're done
|
|
177
|
+
if (missingRequired.length === 0 && !forceInteractive) {
|
|
178
|
+
if (Object.keys(suppliedFields).length > 0) {
|
|
179
|
+
console.log(chalk_1.default.green('ā
Using pre-supplied field values'));
|
|
180
|
+
}
|
|
181
|
+
return allInputs;
|
|
182
|
+
}
|
|
183
|
+
console.log(chalk_1.default.yellow('š Interactive field collection'));
|
|
184
|
+
// Collect missing required fields
|
|
185
|
+
if (missingRequired.length > 0) {
|
|
186
|
+
console.log(chalk_1.default.red(`\nRequired fields (${missingRequired.length}):`));
|
|
187
|
+
for (const field of missingRequired) {
|
|
188
|
+
const value = await promptForField(field);
|
|
189
|
+
if (value !== undefined && value !== '') {
|
|
190
|
+
allInputs[field.key] = value;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// Ask if user wants to provide optional fields
|
|
195
|
+
if (missingOptional.length > 0) {
|
|
196
|
+
const { provideOptional } = await inquirer_1.default.prompt([{
|
|
197
|
+
type: 'confirm',
|
|
198
|
+
name: 'provideOptional',
|
|
199
|
+
message: `Would you like to provide any of the ${missingOptional.length} optional fields?`,
|
|
200
|
+
default: false
|
|
201
|
+
}]);
|
|
202
|
+
if (provideOptional) {
|
|
203
|
+
const { selectedOptional } = await inquirer_1.default.prompt([{
|
|
204
|
+
type: 'checkbox',
|
|
205
|
+
name: 'selectedOptional',
|
|
206
|
+
message: 'Select optional fields to provide:',
|
|
207
|
+
choices: missingOptional.map(field => ({
|
|
208
|
+
name: `${field.label || field.key}${field.helpText ? ` - ${field.helpText}` : ''}`,
|
|
209
|
+
value: field.key
|
|
210
|
+
}))
|
|
211
|
+
}]);
|
|
212
|
+
for (const fieldKey of selectedOptional) {
|
|
213
|
+
const field = missingOptional.find(f => f.key === fieldKey);
|
|
214
|
+
const value = await promptForField(field);
|
|
215
|
+
if (value !== undefined && value !== '') {
|
|
216
|
+
allInputs[field.key] = value;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return allInputs;
|
|
222
|
+
}
|
|
223
|
+
async function promptForField(field) {
|
|
224
|
+
const promptConfig = {
|
|
225
|
+
name: 'value',
|
|
226
|
+
message: `${field.label || field.key}${field.required ? ' (required)' : ''}:`,
|
|
227
|
+
};
|
|
228
|
+
if (field.helpText) {
|
|
229
|
+
promptConfig.message += chalk_1.default.gray(` ${field.helpText}`);
|
|
230
|
+
}
|
|
231
|
+
if (field.choices && field.choices.length > 0) {
|
|
232
|
+
promptConfig.type = 'list';
|
|
233
|
+
promptConfig.choices = field.choices.map((choice) => ({
|
|
234
|
+
name: choice.label,
|
|
235
|
+
value: choice.value
|
|
236
|
+
}));
|
|
237
|
+
}
|
|
238
|
+
else if (field.type === 'boolean') {
|
|
239
|
+
promptConfig.type = 'confirm';
|
|
240
|
+
promptConfig.default = field.default === 'true';
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
promptConfig.type = 'input';
|
|
244
|
+
if (field.default) {
|
|
245
|
+
promptConfig.default = field.default;
|
|
246
|
+
}
|
|
247
|
+
if (field.placeholder) {
|
|
248
|
+
promptConfig.message += chalk_1.default.gray(` (${field.placeholder})`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (field.required) {
|
|
252
|
+
promptConfig.validate = (input) => {
|
|
253
|
+
if (!input && input !== false && input !== 0) {
|
|
254
|
+
return 'This field is required';
|
|
255
|
+
}
|
|
256
|
+
return true;
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
const result = await inquirer_1.default.prompt([promptConfig]);
|
|
260
|
+
return result.value;
|
|
261
|
+
}
|
|
262
|
+
function validateRequiredFields(fields, inputs) {
|
|
263
|
+
return fields
|
|
264
|
+
.filter(field => field.required && !(field.key in inputs))
|
|
265
|
+
.map(field => field.key);
|
|
266
|
+
}
|
|
267
|
+
function displayResults(result) {
|
|
268
|
+
console.log(chalk_1.default.green('\nš Action Results\n'));
|
|
269
|
+
if (result.success) {
|
|
270
|
+
console.log(chalk_1.default.green('Status:'), 'SUCCESS');
|
|
271
|
+
if (result.data) {
|
|
272
|
+
console.log(chalk_1.default.blue('\nData:'));
|
|
273
|
+
if (Array.isArray(result.data)) {
|
|
274
|
+
result.data.forEach((item, index) => {
|
|
275
|
+
console.log(chalk_1.default.gray(`[${index}]`), JSON.stringify(item, null, 2));
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
console.log(JSON.stringify(result.data, null, 2));
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
if (result.metadata) {
|
|
283
|
+
console.log(chalk_1.default.gray('\nMetadata:'));
|
|
284
|
+
console.log(`Execution Time: ${result.metadata.executionTime}ms`);
|
|
285
|
+
console.log(`Request ID: ${result.metadata.requestId}`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
console.log(chalk_1.default.red('Status:'), 'FAILED');
|
|
290
|
+
console.log(chalk_1.default.red('Error:'), result.error);
|
|
291
|
+
if (result.metadata) {
|
|
292
|
+
console.log(chalk_1.default.gray('\nRequest ID:'), result.metadata.requestId);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
@@ -0,0 +1,257 @@
|
|
|
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.browseCommand = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const actions_sdk_1 = require("@zapier/actions-sdk");
|
|
10
|
+
const pager_1 = require("../utils/pager");
|
|
11
|
+
exports.browseCommand = new commander_1.Command('browse')
|
|
12
|
+
.description('Browse available apps and actions');
|
|
13
|
+
// zapier browse apps
|
|
14
|
+
exports.browseCommand
|
|
15
|
+
.command('apps')
|
|
16
|
+
.description('List all available apps')
|
|
17
|
+
.option('-c, --category <category>', 'Filter by category')
|
|
18
|
+
.option('-l, --limit <number>', 'Limit number of results', '20')
|
|
19
|
+
.option('--page', 'Enable interactive paging to load more results')
|
|
20
|
+
.option('--debug', 'Enable debug logging')
|
|
21
|
+
.action(async (options) => {
|
|
22
|
+
try {
|
|
23
|
+
const sdk = (0, actions_sdk_1.createActionsSDK)({
|
|
24
|
+
debug: options.debug
|
|
25
|
+
});
|
|
26
|
+
const limit = parseInt(options.limit);
|
|
27
|
+
console.log(chalk_1.default.blue('š± Fetching available apps...'));
|
|
28
|
+
if (options.page) {
|
|
29
|
+
// Use interactive paging
|
|
30
|
+
const pager = (0, pager_1.createPager)({
|
|
31
|
+
pageSize: Math.min(limit, 20),
|
|
32
|
+
itemName: 'apps'
|
|
33
|
+
});
|
|
34
|
+
const displayApps = (apps, totalShown, totalAvailable) => {
|
|
35
|
+
console.clear();
|
|
36
|
+
console.log(chalk_1.default.blue('š± Available Apps\n'));
|
|
37
|
+
if (apps.length === 0) {
|
|
38
|
+
console.log(chalk_1.default.yellow('No apps found.'));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
apps.forEach((app, index) => {
|
|
42
|
+
console.log(`${chalk_1.default.gray(`${index + 1}.`)} ${chalk_1.default.cyan(app.name)} ${chalk_1.default.gray(`(${app.key})`)}`);
|
|
43
|
+
if (app.description) {
|
|
44
|
+
console.log(` ${chalk_1.default.dim(app.description)}`);
|
|
45
|
+
}
|
|
46
|
+
if (app.category) {
|
|
47
|
+
console.log(` ${chalk_1.default.magenta(`Category: ${app.category}`)}`);
|
|
48
|
+
}
|
|
49
|
+
console.log();
|
|
50
|
+
});
|
|
51
|
+
const totalInfo = totalAvailable ? ` of ${totalAvailable.toLocaleString()} total` : '';
|
|
52
|
+
console.log(chalk_1.default.green(`\nā
Showing ${totalShown}${totalInfo} apps`));
|
|
53
|
+
};
|
|
54
|
+
await pager.paginate((params) => sdk.apps.list({
|
|
55
|
+
category: options.category,
|
|
56
|
+
...params
|
|
57
|
+
}), {}, displayApps);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
// Traditional single-page fetch
|
|
61
|
+
const allApps = await sdk.apps.list({
|
|
62
|
+
category: options.category,
|
|
63
|
+
limit: Math.max(limit, 50) // Fetch at least 50 to get pagination info
|
|
64
|
+
});
|
|
65
|
+
if (allApps.length === 0) {
|
|
66
|
+
console.log(chalk_1.default.yellow('No apps found.'));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// Check for pagination metadata
|
|
70
|
+
const pagination = allApps.__pagination;
|
|
71
|
+
const totalCount = pagination?.count || allApps.length;
|
|
72
|
+
// Slice to requested limit (client-side limiting)
|
|
73
|
+
const apps = allApps.slice(0, limit);
|
|
74
|
+
console.log(chalk_1.default.green(`\nā
Found ${totalCount.toLocaleString()} total apps, showing first ${apps.length}:\n`));
|
|
75
|
+
apps.forEach(app => {
|
|
76
|
+
console.log(`${chalk_1.default.cyan(app.name)} ${chalk_1.default.gray(`(${app.key})`)}`);
|
|
77
|
+
if (app.description) {
|
|
78
|
+
console.log(` ${chalk_1.default.dim(app.description)}`);
|
|
79
|
+
}
|
|
80
|
+
if (app.category) {
|
|
81
|
+
console.log(` ${chalk_1.default.magenta(`Category: ${app.category}`)}`);
|
|
82
|
+
}
|
|
83
|
+
console.log();
|
|
84
|
+
});
|
|
85
|
+
if (totalCount > limit) {
|
|
86
|
+
console.log(chalk_1.default.yellow(`\nš Showing first ${apps.length} of ${totalCount.toLocaleString()} total apps (limit: ${limit})`));
|
|
87
|
+
console.log(chalk_1.default.gray(`Use --limit to increase the limit, or add --page for interactive paging`));
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
console.log(chalk_1.default.gray(`\nš Showing all ${apps.length} apps`));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
console.error(chalk_1.default.red('ā Error fetching apps:'), error instanceof Error ? error.message : error);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
// zapier browse actions
|
|
100
|
+
exports.browseCommand
|
|
101
|
+
.command('actions')
|
|
102
|
+
.description('List available actions for a specific app')
|
|
103
|
+
.argument('<app>', 'App key (e.g., slack, google-sheets)')
|
|
104
|
+
.option('-t, --type <type>', 'Filter by action type (create, read, update, delete, search)')
|
|
105
|
+
.option('--debug', 'Enable debug logging')
|
|
106
|
+
.action(async (app, options) => {
|
|
107
|
+
try {
|
|
108
|
+
const sdk = (0, actions_sdk_1.createActionsSDK)({
|
|
109
|
+
debug: options.debug
|
|
110
|
+
});
|
|
111
|
+
console.log(chalk_1.default.blue(`ā” Fetching actions for ${app}...`));
|
|
112
|
+
// Get all actions for the specific app
|
|
113
|
+
let actions;
|
|
114
|
+
try {
|
|
115
|
+
actions = await sdk.actions.list({
|
|
116
|
+
appKey: app,
|
|
117
|
+
type: options.type
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
if (error instanceof actions_sdk_1.AppNotFoundError) {
|
|
122
|
+
console.error(chalk_1.default.red(`ā ${error.message}`));
|
|
123
|
+
console.log(chalk_1.default.gray('Use "zapier browse apps" to see available apps'));
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
128
|
+
if (actions.length === 0) {
|
|
129
|
+
const typeFilter = options.type ? ` of type "${options.type}"` : '';
|
|
130
|
+
console.log(chalk_1.default.yellow(`No actions found for ${app}${typeFilter}.`));
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const typeFilter = options.type ? ` (type: ${options.type})` : '';
|
|
134
|
+
console.log(chalk_1.default.green(`\nā
Found ${actions.length} actions for ${app}${typeFilter}:\n`));
|
|
135
|
+
actions.forEach((action, index) => {
|
|
136
|
+
console.log(`${chalk_1.default.gray(`${index + 1}.`)} ${chalk_1.default.cyan(action.name)} ${chalk_1.default.gray(`(${action.key})`)}`);
|
|
137
|
+
console.log(` ${chalk_1.default.magenta(`Type: ${action.type}`)}`);
|
|
138
|
+
if (action.description) {
|
|
139
|
+
console.log(` ${chalk_1.default.dim(action.description)}`);
|
|
140
|
+
}
|
|
141
|
+
console.log();
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
console.error(chalk_1.default.red('ā Error fetching actions:'), error instanceof Error ? error.message : error);
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
// zapier browse auths
|
|
150
|
+
exports.browseCommand
|
|
151
|
+
.command('auths')
|
|
152
|
+
.description('List available authentications (optionally for a specific app)')
|
|
153
|
+
.argument('[app]', 'App key to filter by (e.g., slack, google-sheets)')
|
|
154
|
+
.option('--acct <account_id>', 'Filter by account ID')
|
|
155
|
+
.option('-o, --owner <owner>', 'Filter by owner (use "me" for current user)')
|
|
156
|
+
.option('-l, --limit <number>', 'Limit number of results', '20')
|
|
157
|
+
.option('--page', 'Enable interactive paging to load more results')
|
|
158
|
+
.option('--debug', 'Enable debug logging')
|
|
159
|
+
.action(async (app, options) => {
|
|
160
|
+
try {
|
|
161
|
+
const sdk = (0, actions_sdk_1.createActionsSDK)({
|
|
162
|
+
debug: options.debug
|
|
163
|
+
});
|
|
164
|
+
const limit = parseInt(options.limit);
|
|
165
|
+
console.log(chalk_1.default.blue('š Fetching available authentications...'));
|
|
166
|
+
if (options.page) {
|
|
167
|
+
// Use interactive paging
|
|
168
|
+
const pager = (0, pager_1.createPager)({
|
|
169
|
+
pageSize: Math.min(limit, 20),
|
|
170
|
+
itemName: 'authentications'
|
|
171
|
+
});
|
|
172
|
+
const displayAuths = (auths, totalShown) => {
|
|
173
|
+
console.clear();
|
|
174
|
+
console.log(chalk_1.default.blue('š Available Authentications\n'));
|
|
175
|
+
if (auths.length === 0) {
|
|
176
|
+
const filterMsg = app ? ` for app "${app}"` : '';
|
|
177
|
+
console.log(chalk_1.default.yellow(`No authentications found${filterMsg}.`));
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
auths.forEach((auth, index) => {
|
|
181
|
+
console.log(`${chalk_1.default.gray(`${index + 1}.`)} ${chalk_1.default.cyan(`ID: ${auth.id}`)} ${chalk_1.default.gray(`(${auth.selected_api})`)}`);
|
|
182
|
+
if (auth.label) {
|
|
183
|
+
console.log(` ${chalk_1.default.blue(`Label: ${auth.label}`)}`);
|
|
184
|
+
}
|
|
185
|
+
if (auth.identifier) {
|
|
186
|
+
console.log(` ${chalk_1.default.magenta(`Identifier: ${auth.identifier}`)}`);
|
|
187
|
+
}
|
|
188
|
+
if (auth.title) {
|
|
189
|
+
console.log(` ${chalk_1.default.white(`Title: ${auth.title}`)}`);
|
|
190
|
+
}
|
|
191
|
+
console.log(` ${chalk_1.default.dim(`Account: ${auth.account_id} | Private: ${auth.is_private} | Shared: ${auth.shared_with_all}`)}`);
|
|
192
|
+
if (auth.marked_stale_at) {
|
|
193
|
+
console.log(` ${chalk_1.default.red(`ā ļø Marked stale: ${new Date(auth.marked_stale_at).toLocaleDateString()}`)}`);
|
|
194
|
+
}
|
|
195
|
+
console.log();
|
|
196
|
+
});
|
|
197
|
+
const filterMsg = app ? ` for app "${app}"` : '';
|
|
198
|
+
console.log(chalk_1.default.green(`\nā
Showing ${totalShown} authentications${filterMsg}`));
|
|
199
|
+
};
|
|
200
|
+
await pager.paginate((params) => sdk.auths.list({
|
|
201
|
+
account_id: options.acct,
|
|
202
|
+
owner: options.owner,
|
|
203
|
+
appKey: app,
|
|
204
|
+
...params
|
|
205
|
+
}), {}, displayAuths);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
// Traditional single-page fetch
|
|
209
|
+
const allAuths = await sdk.auths.list({
|
|
210
|
+
account_id: options.acct,
|
|
211
|
+
owner: options.owner,
|
|
212
|
+
appKey: app,
|
|
213
|
+
limit: Math.max(limit, 50) // Fetch more than requested to ensure we have enough
|
|
214
|
+
});
|
|
215
|
+
if (allAuths.length === 0) {
|
|
216
|
+
const filterMsg = app ? ` for app "${app}"` : '';
|
|
217
|
+
console.log(chalk_1.default.yellow(`No authentications found${filterMsg}.`));
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
// Check for pagination metadata
|
|
221
|
+
const pagination = allAuths.__pagination;
|
|
222
|
+
const totalCount = pagination?.count || allAuths.length;
|
|
223
|
+
// Slice to requested limit (client-side limiting)
|
|
224
|
+
const auths = allAuths.slice(0, limit);
|
|
225
|
+
const filterMsg = app ? ` for app "${app}"` : '';
|
|
226
|
+
console.log(chalk_1.default.green(`\nā
Found ${totalCount.toLocaleString()} total authentications${filterMsg}, showing first ${auths.length}:\n`));
|
|
227
|
+
auths.forEach(auth => {
|
|
228
|
+
console.log(`${chalk_1.default.cyan(`ID: ${auth.id}`)} ${chalk_1.default.gray(`(${auth.selected_api})`)}`);
|
|
229
|
+
if (auth.label) {
|
|
230
|
+
console.log(` ${chalk_1.default.blue(`Label: ${auth.label}`)}`);
|
|
231
|
+
}
|
|
232
|
+
if (auth.identifier) {
|
|
233
|
+
console.log(` ${chalk_1.default.magenta(`Identifier: ${auth.identifier}`)}`);
|
|
234
|
+
}
|
|
235
|
+
if (auth.title) {
|
|
236
|
+
console.log(` ${chalk_1.default.white(`Title: ${auth.title}`)}`);
|
|
237
|
+
}
|
|
238
|
+
console.log(` ${chalk_1.default.dim(`Account: ${auth.account_id} | Private: ${auth.is_private} | Shared: ${auth.shared_with_all}`)}`);
|
|
239
|
+
if (auth.marked_stale_at) {
|
|
240
|
+
console.log(` ${chalk_1.default.red(`ā ļø Marked stale: ${new Date(auth.marked_stale_at).toLocaleDateString()}`)}`);
|
|
241
|
+
}
|
|
242
|
+
console.log();
|
|
243
|
+
});
|
|
244
|
+
if (totalCount > limit) {
|
|
245
|
+
console.log(chalk_1.default.yellow(`\nš Showing first ${auths.length} of ${totalCount.toLocaleString()} total authentications (limit: ${limit})`));
|
|
246
|
+
console.log(chalk_1.default.gray(`Use --limit to increase the limit, or add --page for interactive paging`));
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
console.log(chalk_1.default.gray(`\nš Showing all ${auths.length} authentications`));
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
catch (error) {
|
|
254
|
+
console.error(chalk_1.default.red('ā Error fetching authentications:'), error instanceof Error ? error.message : error);
|
|
255
|
+
process.exit(1);
|
|
256
|
+
}
|
|
257
|
+
});
|