@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.
@@ -1,101 +0,0 @@
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.bundleCommand = void 0;
7
- const commander_1 = require("commander");
8
- const chalk_1 = __importDefault(require("chalk"));
9
- const ora_1 = __importDefault(require("ora"));
10
- const esbuild_1 = require("esbuild");
11
- const fs_1 = require("fs");
12
- const path_1 = require("path");
13
- exports.bundleCommand = new commander_1.Command('bundle')
14
- .description('Bundle TypeScript/JavaScript into a single file')
15
- .argument('<input>', 'Input file path (e.g., packages/example/src/index.ts)')
16
- .option('--output <path>', 'Output file path (default: bundle.js)')
17
- .option('--string', 'Output as a quoted string for node -e')
18
- .option('--minify', 'Minify the output')
19
- .option('--cjs', 'Output as CommonJS (default: ESM)')
20
- .option('--target <target>', 'JavaScript target (default: node18)', 'node18')
21
- .action(bundleFile);
22
- async function bundleFile(inputPath, options) {
23
- try {
24
- console.log(chalk_1.default.blue('šŸ“¦ JavaScript Bundler'));
25
- console.log(chalk_1.default.gray(`Input: ${inputPath}\n`));
26
- const spinner = (0, ora_1.default)('Bundling JavaScript...').start();
27
- // Resolve input path from current working directory
28
- const resolvedInput = (0, path_1.resolve)(process.cwd(), inputPath);
29
- console.log(chalk_1.default.gray(`Resolved input: ${resolvedInput}`));
30
- // Default output path
31
- const outputPath = options.output || 'bundle.js';
32
- try {
33
- // Bundle with esbuild
34
- const result = (0, esbuild_1.buildSync)({
35
- entryPoints: [resolvedInput],
36
- bundle: true,
37
- platform: 'node',
38
- target: options.target,
39
- format: options.cjs ? 'cjs' : 'esm',
40
- minify: options.minify,
41
- write: false,
42
- external: [], // Bundle everything
43
- banner: {
44
- js: '#!/usr/bin/env node',
45
- },
46
- });
47
- if (result.errors.length > 0) {
48
- spinner.fail('Bundle failed');
49
- result.errors.forEach(error => {
50
- console.error(chalk_1.default.red('Error:'), error.text);
51
- });
52
- return;
53
- }
54
- const bundledCode = result.outputFiles?.[0]?.text;
55
- if (!bundledCode) {
56
- spinner.fail('No output generated');
57
- return;
58
- }
59
- spinner.succeed('Bundle created');
60
- if (options.string) {
61
- // Output as quoted string for node -e using JSON.stringify
62
- const quotedString = JSON.stringify(bundledCode);
63
- if (options.output) {
64
- // Write quoted string to file
65
- (0, fs_1.writeFileSync)(outputPath, quotedString, 'utf8');
66
- console.log(chalk_1.default.green(`āœ… Quoted string saved to: ${outputPath}`));
67
- }
68
- else {
69
- // Output to console
70
- console.log(chalk_1.default.green('\nšŸ“‹ Quoted string for node -e:\n'));
71
- console.log(quotedString);
72
- }
73
- console.log(chalk_1.default.gray('\nUsage:'));
74
- console.log(chalk_1.default.blue(`node -e ${quotedString.substring(0, 50)}...`));
75
- }
76
- else {
77
- // Write normal bundle
78
- (0, fs_1.writeFileSync)(outputPath, bundledCode, 'utf8');
79
- console.log(chalk_1.default.green(`āœ… Bundle saved to: ${outputPath}`));
80
- console.log(chalk_1.default.gray('\nUsage:'));
81
- console.log(chalk_1.default.blue(`node ${outputPath}`));
82
- }
83
- // Show bundle info
84
- const sizeKB = (bundledCode.length / 1024).toFixed(1);
85
- console.log(chalk_1.default.gray(`\nBundle size: ${sizeKB} KB`));
86
- }
87
- catch (error) {
88
- spinner.fail('Bundle failed');
89
- if (error instanceof Error) {
90
- console.error(chalk_1.default.red('Error:'), error.message);
91
- }
92
- else {
93
- console.error(chalk_1.default.red('Unknown error:'), error);
94
- }
95
- }
96
- }
97
- catch (error) {
98
- console.error(chalk_1.default.red('Unexpected error:'), error instanceof Error ? error.message : 'Unknown error');
99
- process.exit(1);
100
- }
101
- }
@@ -1,9 +0,0 @@
1
- import { Command } from 'commander';
2
- import { Action, ActionField } from '@zapier/actions-sdk';
3
- interface ActionWithActionFields extends Omit<Action, 'inputFields'> {
4
- inputFields: ActionField[];
5
- }
6
- export declare const generateCommand: Command;
7
- export declare function generateTypeDefinitions(appKey: string, actions: ActionWithActionFields[], version?: string): string;
8
- export declare function capitalize(str: string): string;
9
- export {};
@@ -1,281 +0,0 @@
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.generateCommand = void 0;
7
- exports.generateTypeDefinitions = generateTypeDefinitions;
8
- exports.capitalize = capitalize;
9
- const commander_1 = require("commander");
10
- const chalk_1 = __importDefault(require("chalk"));
11
- const ora_1 = __importDefault(require("ora"));
12
- const actions_sdk_1 = require("@zapier/actions-sdk");
13
- const fs_1 = require("fs");
14
- const path_1 = require("path");
15
- const auth_picker_1 = require("../utils/auth-picker");
16
- exports.generateCommand = new commander_1.Command('generate')
17
- .description('Generate TypeScript types for Zapier app actions')
18
- .argument('<app>', 'App identifier (e.g., slack, slack@1.2.3)')
19
- .option('--token <token>', 'Authentication token (JWT or Bearer) - can also use ZAPIER_TOKEN env var')
20
- .option('--auth <id>', 'Authentication ID', (value) => parseInt(value))
21
- .option('--output <path>', 'Output file path (default: ./types/[app].d.ts)')
22
- .option('--debug', 'Enable debug logging')
23
- .action(generateTypes);
24
- async function generateTypes(appIdentifier, options) {
25
- try {
26
- console.log(chalk_1.default.blue('šŸŽÆ Zapier Type Generator'));
27
- console.log(chalk_1.default.gray(`Generating types for: ${appIdentifier}\n`));
28
- // Parse app identifier (support app@version format)
29
- const { appKey, version } = parseAppIdentifier(appIdentifier);
30
- // Get token from option or environment variable
31
- const token = options.token || process.env.ZAPIER_TOKEN;
32
- if (!token) {
33
- console.error(chalk_1.default.red('Authentication token is required'));
34
- console.log(chalk_1.default.gray('Use --token <jwt-or-bearer-token> or set ZAPIER_TOKEN environment variable'));
35
- return;
36
- }
37
- // Create SDK instance
38
- const sdk = (0, actions_sdk_1.createActionsSDK)({
39
- auth: options.auth ? {
40
- token: token,
41
- authentications: {
42
- [appKey]: [{ id: options.auth }]
43
- }
44
- } : {
45
- token: token,
46
- authentications: {}
47
- },
48
- debug: options.debug
49
- });
50
- // Fetch all actions for the app
51
- const spinner = (0, ora_1.default)('Fetching app actions...').start();
52
- let actions;
53
- try {
54
- actions = await sdk.actions.list({ appKey });
55
- spinner.succeed(`Found ${actions.length} actions for ${appKey}`);
56
- }
57
- catch (error) {
58
- spinner.fail('Failed to fetch actions');
59
- console.error(chalk_1.default.red('Error:'), error instanceof Error ? error.message : 'Unknown error');
60
- return;
61
- }
62
- if (actions.length === 0) {
63
- console.log(chalk_1.default.yellow('No actions found for this app'));
64
- return;
65
- }
66
- // Fetch input fields for each action (with optional interactive auth selection)
67
- const actionsWithFields = [];
68
- let authId = options.auth;
69
- // If no auth provided, offer to select one interactively
70
- if (!authId) {
71
- console.log(chalk_1.default.yellow('No authentication ID provided.'));
72
- const authResult = await (0, auth_picker_1.pickAuthentication)({
73
- sdk,
74
- appKey,
75
- message: `Select an authentication for ${appKey} type generation (or skip for generic types):`,
76
- allowSkip: true,
77
- skipMessage: 'Skip - Generate generic types without specific input fields'
78
- });
79
- if (!authResult.skipped) {
80
- authId = authResult.authId;
81
- }
82
- }
83
- if (authId) {
84
- const fieldsSpinner = (0, ora_1.default)('Fetching action input fields...').start();
85
- for (const action of actions) {
86
- try {
87
- const fields = await sdk.fields.list({
88
- app: action.appKey,
89
- action: action.key,
90
- type: action.type,
91
- authId: authId
92
- });
93
- actionsWithFields.push({ ...action, inputFields: fields });
94
- }
95
- catch (error) {
96
- // If we can't get fields for an action, include it without fields
97
- console.warn(`Warning: Could not fetch fields for ${action.key}:`, error instanceof Error ? error.message : 'Unknown error');
98
- actionsWithFields.push({ ...action, inputFields: [] });
99
- }
100
- }
101
- fieldsSpinner.succeed(`Fetched input fields for ${actionsWithFields.length} actions`);
102
- }
103
- else {
104
- console.log(chalk_1.default.yellow('āš ļø Generating types without specific input field types (using generic Record<string, any>)'));
105
- // Convert actions to have empty input fields (will generate generic types)
106
- actions.forEach(action => {
107
- actionsWithFields.push({ ...action, inputFields: [] });
108
- });
109
- }
110
- // Generate TypeScript types
111
- const typeSpinner = (0, ora_1.default)('Generating TypeScript types...').start();
112
- const typeDefinitions = generateTypeDefinitions(appKey, actionsWithFields, version);
113
- // Determine output path
114
- const outputPath = options.output || `./types/${appKey}.d.ts`;
115
- // Ensure output directory exists
116
- (0, fs_1.mkdirSync)((0, path_1.dirname)(outputPath), { recursive: true });
117
- // Write the types file
118
- (0, fs_1.writeFileSync)(outputPath, typeDefinitions, 'utf8');
119
- typeSpinner.succeed(`Types generated: ${outputPath}`);
120
- console.log(chalk_1.default.green('\nāœ… Type generation complete!'));
121
- console.log(chalk_1.default.gray('\nTo use the generated types:'));
122
- console.log(chalk_1.default.blue(`import type { ${capitalize(appKey)}Actions } from '${outputPath.replace('.d.ts', '')}'`));
123
- console.log(chalk_1.default.blue(`const sdk: ZapierSDK & { actions: ${capitalize(appKey)}Actions } = createActionsSDK(...)`));
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 parseAppIdentifier(identifier) {
131
- const parts = identifier.split('@');
132
- return {
133
- appKey: parts[0],
134
- version: parts[1]
135
- };
136
- }
137
- function generateTypeDefinitions(appKey, actions, version) {
138
- // Handle empty actions
139
- if (actions.length === 0) {
140
- return generateEmptyTypesFile(appKey, version);
141
- }
142
- // Group actions by type
143
- const actionsByType = actions.reduce((acc, action) => {
144
- if (!acc[action.type]) {
145
- acc[action.type] = [];
146
- }
147
- acc[action.type].push(action);
148
- return acc;
149
- }, {});
150
- const appName = capitalize(appKey);
151
- const versionComment = version ? ` * Generated for ${appKey}@${version}` : ` * Generated for ${appKey}`;
152
- let output = `/**
153
- * Auto-generated TypeScript types for Zapier ${appKey} actions
154
- ${versionComment}
155
- * Generated on: ${new Date().toISOString()}
156
- *
157
- * Usage:
158
- * import type { ${appName}Actions } from './path/to/this/file'
159
- * const sdk: ZapierSDK & { actions: ${appName}Actions } = createActionsSDK(...)
160
- */
161
-
162
- import type { ActionExecutionOptions, ActionExecutionResult } from '@zapier/shared-sdk'
163
-
164
- `;
165
- // Generate input types for each action
166
- actions.forEach((action) => {
167
- if (action.inputFields.length > 0) {
168
- const inputTypeName = `${appName}${capitalize(action.type)}${capitalize(sanitizeActionName(action.key))}Inputs`;
169
- output += `interface ${inputTypeName} {\n`;
170
- action.inputFields.forEach((field) => {
171
- const isOptional = !field.required;
172
- const fieldType = mapFieldTypeToTypeScript(field);
173
- const description = field.helpText ? ` /** ${escapeComment(field.helpText)} */\n` : '';
174
- output += `${description} ${sanitizeFieldName(field.key)}${isOptional ? '?' : ''}: ${fieldType}\n`;
175
- });
176
- output += `}\n\n`;
177
- }
178
- });
179
- // Generate action type interfaces for each action type
180
- Object.entries(actionsByType).forEach(([actionType, typeActions]) => {
181
- const typeName = `${appName}${capitalize(actionType)}Actions`;
182
- output += `interface ${typeName} {\n`;
183
- typeActions.forEach((action) => {
184
- const actionName = sanitizeActionName(action.key);
185
- const description = action.description ? ` /** ${escapeComment(action.description)} */\n` : '';
186
- // Generate type-safe action method signature
187
- if (action.inputFields.length > 0) {
188
- const inputTypeName = `${appName}${capitalize(action.type)}${capitalize(sanitizeActionName(action.key))}Inputs`;
189
- output += `${description} ${actionName}: (options: { inputs: ${inputTypeName} } & Omit<ActionExecutionOptions, 'inputs'>) => Promise<ActionExecutionResult>\n`;
190
- }
191
- else {
192
- // No specific input fields available - use generic Record<string, any> for inputs
193
- output += `${description} ${actionName}: (options?: { inputs?: Record<string, any> } & ActionExecutionOptions) => Promise<ActionExecutionResult>\n`;
194
- }
195
- });
196
- output += `}\n\n`;
197
- });
198
- // Generate the main app actions interface
199
- output += `export interface ${appName}Actions {\n`;
200
- output += ` ${appKey}: {\n`;
201
- Object.keys(actionsByType).forEach(actionType => {
202
- const typeName = `${appName}${capitalize(actionType)}Actions`;
203
- output += ` ${actionType}: ${typeName}\n`;
204
- });
205
- output += ` }\n`;
206
- output += `}\n`;
207
- return output;
208
- }
209
- function generateEmptyTypesFile(appKey, version) {
210
- const appName = capitalize(appKey);
211
- const versionComment = version ? ` * Generated for ${appKey}@${version}` : ` * Generated for ${appKey}`;
212
- return `/**
213
- * Auto-generated TypeScript types for Zapier ${appKey} actions
214
- ${versionComment}
215
- * Generated on: ${new Date().toISOString()}
216
- *
217
- * No actions found for this app.
218
- */
219
-
220
- import type { ActionExecutionOptions, ActionExecutionResult } from '@zapier/shared-sdk'
221
-
222
- export interface ${appName}Actions {
223
- ${appKey}: {
224
- // No actions available
225
- }
226
- }
227
- `;
228
- }
229
- function capitalize(str) {
230
- return str.charAt(0).toUpperCase() + str.slice(1).replace(/[-_]/g, '');
231
- }
232
- function sanitizeActionName(actionKey) {
233
- // Ensure the action name is a valid TypeScript identifier
234
- return actionKey.replace(/[^a-zA-Z0-9_$]/g, '_');
235
- }
236
- function sanitizeFieldName(fieldKey) {
237
- // Ensure the field name is a valid TypeScript identifier
238
- return fieldKey.replace(/[^a-zA-Z0-9_$]/g, '_');
239
- }
240
- function escapeComment(comment) {
241
- // Escape comment text to prevent breaking the JSDoc comment
242
- return comment.replace(/\*\//g, '*\\/').replace(/\r?\n/g, ' ');
243
- }
244
- function mapFieldTypeToTypeScript(field) {
245
- // Handle choices (enum-like fields)
246
- if (field.choices && field.choices.length > 0) {
247
- const choiceValues = field.choices
248
- .filter(choice => choice.value !== undefined && choice.value !== null && choice.value !== '')
249
- .map(choice => typeof choice.value === 'string' ? `"${choice.value}"` : choice.value);
250
- if (choiceValues.length > 0) {
251
- return choiceValues.join(' | ');
252
- }
253
- // If all choices were filtered out, fall through to default type handling
254
- }
255
- // Map Zapier field types to TypeScript types
256
- switch (field.type?.toLowerCase()) {
257
- case 'string':
258
- case 'text':
259
- case 'email':
260
- case 'url':
261
- case 'password':
262
- return 'string';
263
- case 'integer':
264
- case 'number':
265
- return 'number';
266
- case 'boolean':
267
- return 'boolean';
268
- case 'datetime':
269
- case 'date':
270
- return 'string'; // ISO date strings
271
- case 'file':
272
- return 'string'; // File URL or content
273
- case 'array':
274
- return 'any[]';
275
- case 'object':
276
- return 'Record<string, any>';
277
- default:
278
- // Default to string for unknown types, with union for common cases
279
- return 'string | number | boolean';
280
- }
281
- }
@@ -1,17 +0,0 @@
1
- import { ActionsSDK } from '@zapier/actions-sdk';
2
- export interface AuthPickerOptions {
3
- sdk: ActionsSDK;
4
- appKey?: string;
5
- message?: string;
6
- allowSkip?: boolean;
7
- skipMessage?: string;
8
- }
9
- export interface AuthPickerResult {
10
- authId: number | null;
11
- skipped: boolean;
12
- }
13
- /**
14
- * Interactive authentication picker that shows available auths
15
- * and lets the user select one or skip (if allowed)
16
- */
17
- export declare function pickAuthentication(options: AuthPickerOptions): Promise<AuthPickerResult>;
@@ -1,121 +0,0 @@
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.pickAuthentication = pickAuthentication;
7
- const inquirer_1 = __importDefault(require("inquirer"));
8
- const chalk_1 = __importDefault(require("chalk"));
9
- const actions_sdk_1 = require("@zapier/actions-sdk");
10
- /**
11
- * Interactive authentication picker that shows available auths
12
- * and lets the user select one or skip (if allowed)
13
- */
14
- async function pickAuthentication(options) {
15
- const { sdk, appKey, message = 'Select an authentication to use:', allowSkip = false, skipMessage = 'Skip (continue without authentication)' } = options;
16
- try {
17
- console.log(chalk_1.default.blue('šŸ” Fetching available authentications...'));
18
- // Since auths.list now requires appKey, we need one to proceed
19
- if (!appKey) {
20
- console.log(chalk_1.default.red('āŒ App key is required to list authentications'));
21
- return { authId: null, skipped: true };
22
- }
23
- // Fetch authentications for the specified app
24
- let auths;
25
- try {
26
- auths = await sdk.auths.list({
27
- appKey,
28
- owner: 'me', // Only show user's own auths for selection
29
- limit: 100 // Get a reasonable number of auths
30
- });
31
- }
32
- catch (error) {
33
- if (error instanceof actions_sdk_1.AppNotFoundError) {
34
- console.error(chalk_1.default.red(`āŒ ${error.message}`));
35
- console.log(chalk_1.default.gray('Use "zapier browse apps" to see available apps'));
36
- if (allowSkip) {
37
- return { authId: null, skipped: true };
38
- }
39
- else {
40
- process.exit(1);
41
- }
42
- }
43
- throw error;
44
- }
45
- if (auths.length === 0) {
46
- const appFilter = appKey ? ` for app "${appKey}"` : '';
47
- console.log(chalk_1.default.yellow(`No authentications found${appFilter}.`));
48
- console.log(chalk_1.default.gray('You may need to create an authentication in the Zapier web interface first.'));
49
- if (allowSkip) {
50
- return { authId: null, skipped: true };
51
- }
52
- else {
53
- process.exit(1);
54
- }
55
- }
56
- // Prepare choices for inquirer
57
- const SKIP_VALUE = -1; // Sentinel value for skip option
58
- const choices = auths.map(auth => ({
59
- name: formatAuthChoice(auth),
60
- value: auth.id,
61
- short: `Auth ${auth.id}`
62
- }));
63
- // Add skip option if allowed
64
- if (allowSkip) {
65
- choices.push({
66
- name: chalk_1.default.gray(skipMessage),
67
- value: SKIP_VALUE,
68
- short: 'Skip'
69
- });
70
- }
71
- // Show interactive selection
72
- const { selectedAuthId } = await inquirer_1.default.prompt([{
73
- type: 'list',
74
- name: 'selectedAuthId',
75
- message,
76
- choices,
77
- pageSize: Math.min(15, choices.length) // Limit visible choices
78
- }]);
79
- if (selectedAuthId === SKIP_VALUE) {
80
- return { authId: null, skipped: true };
81
- }
82
- console.log(chalk_1.default.green(`āœ… Selected authentication ID: ${selectedAuthId}`));
83
- return { authId: selectedAuthId, skipped: false };
84
- }
85
- catch (error) {
86
- console.error(chalk_1.default.red('āŒ Error fetching authentications:'), error instanceof Error ? error.message : error);
87
- if (allowSkip) {
88
- console.log(chalk_1.default.yellow('Continuing without authentication...'));
89
- return { authId: null, skipped: true };
90
- }
91
- else {
92
- process.exit(1);
93
- }
94
- }
95
- }
96
- /**
97
- * Format an authentication for display in the picker
98
- */
99
- function formatAuthChoice(auth) {
100
- const parts = [];
101
- // Auth ID and API
102
- parts.push(chalk_1.default.cyan(`ID: ${auth.id}`));
103
- parts.push(chalk_1.default.gray(`(${auth.selected_api})`));
104
- // Add label if available
105
- if (auth.label) {
106
- parts.push(chalk_1.default.blue(`- ${auth.label}`));
107
- }
108
- // Add identifier if available
109
- if (auth.identifier) {
110
- parts.push(chalk_1.default.magenta(`[${auth.identifier}]`));
111
- }
112
- // Add title if available
113
- if (auth.title) {
114
- parts.push(chalk_1.default.white(`"${auth.title}"`));
115
- }
116
- // Add warning if stale
117
- if (auth.marked_stale_at) {
118
- parts.push(chalk_1.default.red('āš ļø STALE'));
119
- }
120
- return parts.join(' ');
121
- }
@@ -1,4 +0,0 @@
1
- import { Command } from 'commander';
2
- import { ActionsSDK } from '@zapier/actions-sdk';
3
- export declare function generateCLICommands(program: Command, sdk: ActionsSDK): void;
4
- export declare function enhanceCommandHelp(program: Command): void;