@zapier/zapier-sdk-cli 0.16.1 → 0.16.3

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.
Files changed (60) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/cli.cjs +7 -7
  3. package/dist/cli.mjs +7 -7
  4. package/dist/index.cjs +1 -1
  5. package/dist/index.mjs +1 -1
  6. package/dist/package.json +8 -2
  7. package/dist/src/cli.js +2 -1
  8. package/dist/src/utils/cli-generator.js +8 -7
  9. package/dist/tsconfig.tsbuildinfo +1 -1
  10. package/package.json +11 -5
  11. package/src/cli.test.ts +0 -28
  12. package/src/cli.ts +0 -96
  13. package/src/generators/ast-generator.test.ts +0 -908
  14. package/src/generators/ast-generator.ts +0 -774
  15. package/src/index.ts +0 -12
  16. package/src/plugins/add/index.test.ts +0 -58
  17. package/src/plugins/add/index.ts +0 -177
  18. package/src/plugins/add/schemas.ts +0 -35
  19. package/src/plugins/buildManifest/index.test.ts +0 -679
  20. package/src/plugins/buildManifest/index.ts +0 -131
  21. package/src/plugins/buildManifest/schemas.ts +0 -55
  22. package/src/plugins/bundleCode/index.ts +0 -128
  23. package/src/plugins/bundleCode/schemas.ts +0 -24
  24. package/src/plugins/generateAppTypes/index.test.ts +0 -679
  25. package/src/plugins/generateAppTypes/index.ts +0 -227
  26. package/src/plugins/generateAppTypes/schemas.ts +0 -61
  27. package/src/plugins/getLoginConfigPath/index.ts +0 -45
  28. package/src/plugins/getLoginConfigPath/schemas.ts +0 -10
  29. package/src/plugins/index.ts +0 -8
  30. package/src/plugins/login/index.ts +0 -135
  31. package/src/plugins/login/schemas.ts +0 -13
  32. package/src/plugins/logout/index.ts +0 -37
  33. package/src/plugins/logout/schemas.ts +0 -8
  34. package/src/plugins/mcp/index.ts +0 -43
  35. package/src/plugins/mcp/schemas.ts +0 -13
  36. package/src/sdk.ts +0 -45
  37. package/src/telemetry/builders.ts +0 -113
  38. package/src/telemetry/events.ts +0 -39
  39. package/src/types/sdk.ts +0 -8
  40. package/src/utils/api/client.ts +0 -44
  41. package/src/utils/auth/login.ts +0 -214
  42. package/src/utils/cli-generator-utils.ts +0 -169
  43. package/src/utils/cli-generator.test.ts +0 -347
  44. package/src/utils/cli-generator.ts +0 -807
  45. package/src/utils/constants.ts +0 -9
  46. package/src/utils/directory-detection.ts +0 -23
  47. package/src/utils/errors.ts +0 -26
  48. package/src/utils/getCallablePromise.ts +0 -21
  49. package/src/utils/log.ts +0 -23
  50. package/src/utils/manifest-helpers.ts +0 -25
  51. package/src/utils/package-manager-detector.ts +0 -83
  52. package/src/utils/parameter-resolver.ts +0 -1075
  53. package/src/utils/schema-formatter.ts +0 -153
  54. package/src/utils/serializeAsync.ts +0 -26
  55. package/src/utils/spinner.ts +0 -23
  56. package/src/utils/version-checker.test.ts +0 -239
  57. package/src/utils/version-checker.ts +0 -237
  58. package/tsconfig.build.json +0 -18
  59. package/tsconfig.json +0 -19
  60. package/tsup.config.ts +0 -23
@@ -1,113 +0,0 @@
1
- /**
2
- * CLI-specific event builders
3
- *
4
- * Provides builder functions for CLI command telemetry that auto-populate
5
- * common CLI fields and system information.
6
- */
7
-
8
- import type { BaseEvent } from "@zapier/zapier-sdk";
9
- import {
10
- generateEventId,
11
- getCurrentTimestamp,
12
- getReleaseId,
13
- getOsInfo,
14
- getPlatformVersions,
15
- isCi,
16
- getCiPlatform,
17
- } from "@zapier/zapier-sdk";
18
- import type { CliCommandExecutedEvent } from "./events";
19
- import cliPackageJson from "../../package.json";
20
-
21
- // CLI context that can be injected into events
22
- export interface CliEventContext {
23
- customuser_id?: number | null;
24
- account_id?: number | null;
25
- identity_id?: number | null;
26
- visitor_id?: string | null;
27
- correlation_id?: string | null;
28
- session_id?: string | null;
29
- selected_api?: string | null;
30
- app_id?: number | null;
31
- app_version_id?: number | null;
32
- }
33
-
34
- // Create base event for CLI events
35
- function createCliBaseEvent(context: CliEventContext = {}): BaseEvent {
36
- return {
37
- event_id: generateEventId(),
38
- timestamp_ms: getCurrentTimestamp(),
39
- release_id: getReleaseId(),
40
- customuser_id: context.customuser_id ?? null,
41
- account_id: context.account_id ?? null,
42
- identity_id: context.identity_id ?? null,
43
- visitor_id: context.visitor_id ?? null,
44
- correlation_id: context.correlation_id ?? null,
45
- };
46
- }
47
-
48
- // CLI Command Executed Event Builder
49
- // This interface corresponds to the cli_command_executed_event.avsc Avro schema
50
- export interface CliCommandExecutedEventData {
51
- cli_primary_command: string;
52
- success_flag: boolean;
53
- execution_duration_ms?: number | null;
54
- exit_code?: number | null;
55
- error_message?: string | null;
56
- command_category?: string | null;
57
- requires_auth?: boolean | null;
58
- cli_arguments?: (string | null)[] | null;
59
- // Allow overriding auto-detected values if needed
60
- cli_version?: string | null;
61
- made_network_requests?: boolean | null;
62
- files_modified_count?: number | null;
63
- files_created_count?: number | null;
64
- files_processed_size_bytes?: number | null;
65
- peak_memory_usage_bytes?: number | null;
66
- cpu_time_ms?: number | null;
67
- subprocess_count?: number | null;
68
- package_manager?: string | null;
69
- }
70
-
71
- export function buildCliCommandExecutedEvent({
72
- data,
73
- context = {},
74
- cliVersion = cliPackageJson.version,
75
- }: {
76
- data: CliCommandExecutedEventData;
77
- context?: CliEventContext;
78
- cliVersion?: string;
79
- }): CliCommandExecutedEvent {
80
- const osInfo = getOsInfo();
81
- const platformVersions = getPlatformVersions();
82
-
83
- return {
84
- ...createCliBaseEvent(context),
85
- system_name: "zapier-sdk-cli",
86
- session_id: context.session_id ?? null,
87
- cli_version: data.cli_version ?? cliVersion,
88
- cli_arguments: data.cli_arguments ?? null,
89
- cli_primary_command: data.cli_primary_command,
90
- os_platform: osInfo.platform,
91
- os_release: osInfo.release,
92
- os_architecture: osInfo.architecture,
93
- platform_versions: platformVersions,
94
- selected_api: context.selected_api ?? null,
95
- app_id: context.app_id ?? null,
96
- app_version_id: context.app_version_id ?? null,
97
- execution_duration_ms: data.execution_duration_ms ?? null,
98
- success_flag: data.success_flag,
99
- exit_code: data.exit_code ?? (data.success_flag ? 0 : 1),
100
- error_message: data.error_message ?? null,
101
- command_category: data.command_category ?? null,
102
- requires_auth: data.requires_auth ?? null,
103
- is_ci_environment: isCi(),
104
- ci_platform: getCiPlatform(),
105
- package_manager: data.package_manager ?? "pnpm", // Default based on project setup
106
- made_network_requests: data.made_network_requests ?? null,
107
- files_modified_count: data.files_modified_count ?? null,
108
- files_created_count: data.files_created_count ?? null,
109
- files_processed_size_bytes: data.files_processed_size_bytes ?? null,
110
- cpu_time_ms: data.cpu_time_ms ?? null,
111
- subprocess_count: data.subprocess_count ?? null,
112
- };
113
- }
@@ -1,39 +0,0 @@
1
- /**
2
- * CLI-specific telemetry event definitions
3
- */
4
-
5
- import type { BaseEvent } from "@zapier/zapier-sdk";
6
-
7
- /**
8
- * Event emitted when a CLI command is executed
9
- */
10
- export interface CliCommandExecutedEvent extends BaseEvent {
11
- system_name: string;
12
- session_id?: string | null;
13
- cli_version?: string | null;
14
- cli_arguments?: (string | null)[] | null;
15
- cli_primary_command?: string | null;
16
- os_platform?: string | null;
17
- os_release?: string | null;
18
- os_architecture?: string | null;
19
- platform_versions?: Record<string, string | null> | null;
20
- selected_api?: string | null;
21
- app_id?: number | null;
22
- app_version_id?: number | null;
23
- execution_duration_ms?: number | null;
24
- success_flag: boolean;
25
- exit_code?: number | null;
26
- error_message?: string | null;
27
- command_category?: string | null;
28
- requires_auth?: boolean | null;
29
- is_ci_environment?: boolean | null;
30
- ci_platform?: string | null;
31
- package_manager?: string | null;
32
- made_network_requests?: boolean | null;
33
- files_modified_count?: number | null;
34
- files_created_count?: number | null;
35
- files_processed_size_bytes?: number | null;
36
- peak_memory_usage_bytes?: number | null;
37
- cpu_time_ms?: number | null;
38
- subprocess_count?: number | null;
39
- }
package/src/types/sdk.ts DELETED
@@ -1,8 +0,0 @@
1
- import type { GetSdkType, ZapierSdk } from "@zapier/zapier-sdk";
2
- import type { BuildManifestPluginProvides } from "../plugins/buildManifest";
3
- import type { GenerateAppTypesPluginProvides } from "../plugins/generateAppTypes";
4
-
5
- export interface ZapierSdkCli
6
- extends GetSdkType<
7
- ZapierSdk & BuildManifestPluginProvides & GenerateAppTypesPluginProvides
8
- > {}
@@ -1,44 +0,0 @@
1
- // Simple HTTP client for OAuth authentication
2
- export interface ApiResponse<T = unknown> {
3
- data: T;
4
- status: number;
5
- }
6
-
7
- export const createApiClient = () => {
8
- const post = async <T = unknown>(
9
- url: string,
10
- data: Record<string, string>,
11
- options: {
12
- headers?: Record<string, string>;
13
- } = {},
14
- ): Promise<ApiResponse<T>> => {
15
- const { headers = {} } = options;
16
-
17
- const response = await fetch(url, {
18
- method: "POST",
19
- headers: {
20
- "Content-Type": "application/x-www-form-urlencoded",
21
- Connection: "close",
22
- ...headers,
23
- },
24
- body: new URLSearchParams(data),
25
- });
26
-
27
- if (!response.ok) {
28
- throw new Error(`${response.status} ${response.statusText}`);
29
- }
30
-
31
- const responseData = await response.json();
32
- return {
33
- data: responseData,
34
- status: response.status,
35
- };
36
- };
37
-
38
- return {
39
- post,
40
- };
41
- };
42
-
43
- const api = createApiClient();
44
- export default api;
@@ -1,214 +0,0 @@
1
- import open from "open";
2
- import crypto from "node:crypto";
3
- import express from "express";
4
- import pkceChallenge from "pkce-challenge";
5
- import type { Socket } from "net";
6
-
7
- import {
8
- AUTH_MODE_HEADER,
9
- ZAPIER_AUTH_CLIENT_ID,
10
- LOGIN_PORTS,
11
- LOGIN_TIMEOUT_MS,
12
- } from "../constants";
13
- import { spinPromise } from "../spinner";
14
- import log from "../log";
15
- import api from "../api/client";
16
- import getCallablePromise from "../getCallablePromise";
17
- import {
18
- updateLogin,
19
- logout,
20
- getAuthTokenUrl,
21
- getAuthAuthorizeUrl,
22
- } from "@zapier/zapier-sdk-cli-login";
23
- import { ZapierCliUserCancellationError } from "../errors";
24
-
25
- const findAvailablePort = (): Promise<number> => {
26
- return new Promise((resolve, reject) => {
27
- let portIndex = 0;
28
-
29
- const tryPort = (port: number) => {
30
- const server = express().listen(port, () => {
31
- server.close();
32
- resolve(port);
33
- });
34
-
35
- server.on("error", (err: NodeJS.ErrnoException) => {
36
- if (err.code === "EADDRINUSE") {
37
- if (portIndex < LOGIN_PORTS.length) {
38
- // Try next predefined port
39
- tryPort(LOGIN_PORTS[portIndex++]);
40
- } else {
41
- // All configured ports are busy
42
- reject(
43
- new Error(
44
- `All configured OAuth callback ports are busy: ${LOGIN_PORTS.join(", ")}. Please try again later or close applications using these ports.`,
45
- ),
46
- );
47
- }
48
- } else {
49
- reject(err);
50
- }
51
- });
52
- };
53
-
54
- if (LOGIN_PORTS.length > 0) {
55
- tryPort(LOGIN_PORTS[portIndex++]);
56
- } else {
57
- reject(new Error("No OAuth callback ports configured"));
58
- }
59
- });
60
- };
61
-
62
- const generateRandomString = () => {
63
- const array = new Uint32Array(28);
64
- crypto.getRandomValues(array);
65
- return Array.from(array, (dec) =>
66
- ("0" + dec.toString(16)).substring(-2),
67
- ).join("");
68
- };
69
-
70
- interface LoginOptions {
71
- timeoutMs?: number;
72
- baseUrl?: string;
73
- authBaseUrl?: string;
74
- authClientId?: string;
75
- }
76
-
77
- const login = async ({
78
- timeoutMs = LOGIN_TIMEOUT_MS,
79
- baseUrl,
80
- authBaseUrl,
81
- authClientId,
82
- }: LoginOptions): Promise<string> => {
83
- const authOptions = { baseUrl, authBaseUrl };
84
- const tokenUrl = getAuthTokenUrl(authOptions);
85
- const authorizeUrl = getAuthAuthorizeUrl(authOptions);
86
- // Force logout
87
- logout();
88
-
89
- // Find an available port
90
- const availablePort = await findAvailablePort();
91
- const redirectUri = `http://localhost:${availablePort}/oauth`;
92
-
93
- log.info(`Using port ${availablePort} for OAuth callback`);
94
-
95
- const {
96
- promise: promisedCode,
97
- resolve: setCode,
98
- reject: rejectCode,
99
- } = getCallablePromise<string>();
100
-
101
- const app = express();
102
-
103
- app.get("/oauth", (req, res) => {
104
- setCode(String(req.query.code));
105
- // Set headers to prevent keep-alive
106
- res.setHeader("Connection", "close");
107
- res.end("You can now close this tab and return to the CLI.");
108
- });
109
-
110
- const server = app.listen(availablePort);
111
-
112
- // Track connections to force close them if needed
113
- const connections = new Set<Socket>();
114
- server.on("connection", (conn) => {
115
- connections.add(conn);
116
- conn.on("close", () => connections.delete(conn));
117
- });
118
-
119
- // Set up signal handlers for graceful shutdown
120
- const cleanup = () => {
121
- server.close();
122
- log.info("\n❌ Login cancelled by user");
123
- rejectCode(new ZapierCliUserCancellationError());
124
- };
125
-
126
- process.on("SIGINT", cleanup);
127
- process.on("SIGTERM", cleanup);
128
-
129
- const { code_verifier: codeVerifier, code_challenge: codeChallenge } =
130
- await pkceChallenge();
131
-
132
- const authUrl = `${authorizeUrl}?${new URLSearchParams({
133
- response_type: "code",
134
- client_id: authClientId || ZAPIER_AUTH_CLIENT_ID,
135
- redirect_uri: redirectUri,
136
- scope: "internal offline_access",
137
- state: generateRandomString(),
138
- code_challenge: codeChallenge,
139
- code_challenge_method: "S256",
140
- }).toString()}`;
141
-
142
- log.info("Opening your browser to log in.");
143
- log.info("If it doesn't open, visit:", authUrl);
144
-
145
- open(authUrl);
146
-
147
- try {
148
- await spinPromise(
149
- Promise.race([
150
- promisedCode,
151
- new Promise<string>((_resolve, reject) =>
152
- setTimeout(() => {
153
- reject(
154
- new Error(
155
- `Login timed out after ${Math.round(timeoutMs / 1000)} seconds.`,
156
- ),
157
- );
158
- }, timeoutMs),
159
- ),
160
- ]),
161
- "Waiting for you to login and authorize",
162
- );
163
- } finally {
164
- // Remove signal handlers
165
- process.off("SIGINT", cleanup);
166
- process.off("SIGTERM", cleanup);
167
-
168
- // Close server with timeout and force-close connections if needed
169
- await new Promise<void>((resolve) => {
170
- const timeout = setTimeout(() => {
171
- log.info("Server close timed out, forcing connection shutdown...");
172
- // Force close all connections
173
- connections.forEach((conn) => conn.destroy());
174
- resolve();
175
- }, 1000); // 1 second timeout
176
-
177
- server.close(() => {
178
- clearTimeout(timeout);
179
- resolve();
180
- });
181
- });
182
- }
183
-
184
- log.info("Exchanging authorization code for tokens...");
185
-
186
- const { data } = await api.post<{
187
- access_token: string;
188
- refresh_token: string;
189
- expires_in: number;
190
- }>(
191
- tokenUrl,
192
- {
193
- grant_type: "authorization_code",
194
- code: await promisedCode,
195
- redirect_uri: redirectUri,
196
- client_id: authClientId || ZAPIER_AUTH_CLIENT_ID,
197
- code_verifier: codeVerifier,
198
- },
199
- {
200
- headers: {
201
- [AUTH_MODE_HEADER]: "no",
202
- "Content-Type": "application/x-www-form-urlencoded",
203
- },
204
- },
205
- );
206
-
207
- updateLogin(data);
208
-
209
- log.info("Token exchange completed successfully");
210
-
211
- return data.access_token;
212
- };
213
-
214
- export default login;
@@ -1,169 +0,0 @@
1
- import { z } from "zod";
2
- import { isPositional, type FunctionRegistryEntry } from "@zapier/zapier-sdk";
3
-
4
- // ============================================================================
5
- // Types
6
- // ============================================================================
7
-
8
- export interface CliParameter {
9
- name: string;
10
- type: "string" | "number" | "boolean" | "array";
11
- required: boolean;
12
- description?: string;
13
- default?: unknown;
14
- choices?: string[];
15
- hasResolver?: boolean;
16
- isPositional?: boolean;
17
- }
18
-
19
- // ============================================================================
20
- // Schema Analysis
21
- // ============================================================================
22
-
23
- export function analyzeZodSchema(
24
- schema: z.ZodSchema,
25
- functionInfo?: FunctionRegistryEntry,
26
- ): CliParameter[] {
27
- const parameters: CliParameter[] = [];
28
-
29
- if (schema instanceof z.ZodObject) {
30
- const shape = schema.shape;
31
-
32
- for (const [key, fieldSchema] of Object.entries<z.ZodSchema>(shape)) {
33
- const param = analyzeZodField(key, fieldSchema, functionInfo);
34
- if (param) {
35
- parameters.push(param);
36
- }
37
- }
38
- }
39
-
40
- return parameters;
41
- }
42
-
43
- function analyzeZodField(
44
- name: string,
45
- schema: z.ZodSchema,
46
- functionInfo?: FunctionRegistryEntry,
47
- ): CliParameter | null {
48
- let baseSchema = schema;
49
- let required = true;
50
- let defaultValue: unknown = undefined;
51
-
52
- // Unwrap optional and default wrappers
53
- if (baseSchema instanceof z.ZodOptional) {
54
- required = false;
55
- baseSchema = baseSchema._zod.def.innerType as z.ZodSchema;
56
- }
57
-
58
- if (baseSchema instanceof z.ZodDefault) {
59
- required = false;
60
- defaultValue = (baseSchema._zod.def.defaultValue as () => unknown)();
61
- baseSchema = baseSchema._zod.def.innerType as z.ZodSchema;
62
- }
63
-
64
- // Determine parameter type
65
- let paramType: CliParameter["type"] = "string";
66
- let choices: string[] | undefined;
67
-
68
- if (baseSchema instanceof z.ZodString) {
69
- paramType = "string";
70
- } else if (baseSchema instanceof z.ZodNumber) {
71
- paramType = "number";
72
- } else if (baseSchema instanceof z.ZodBoolean) {
73
- paramType = "boolean";
74
- } else if (baseSchema instanceof z.ZodArray) {
75
- paramType = "array";
76
- } else if (baseSchema instanceof z.ZodEnum) {
77
- paramType = "string";
78
- choices = baseSchema.options as string[];
79
- } else if (baseSchema instanceof z.ZodRecord) {
80
- // Handle Record<string, any> as JSON string input
81
- paramType = "string";
82
- }
83
-
84
- // Check if this parameter has a resolver
85
- let paramHasResolver = false;
86
-
87
- // Check function-specific resolvers first
88
- if (functionInfo?.resolvers?.[name]) {
89
- paramHasResolver = true;
90
- }
91
-
92
- // Extract resolver metadata
93
- return {
94
- name,
95
- type: paramType,
96
- required,
97
- description: schema.description,
98
- default: defaultValue,
99
- choices,
100
- hasResolver: paramHasResolver,
101
- isPositional: isPositional(schema),
102
- };
103
- }
104
-
105
- // ============================================================================
106
- // Parameter Conversion
107
- // ============================================================================
108
-
109
- export function convertCliArgsToSdkParams(
110
- parameters: CliParameter[],
111
- positionalArgs: unknown[],
112
- options: Record<string, unknown>,
113
- ): Record<string, unknown> {
114
- const sdkParams: Record<string, unknown> = {};
115
-
116
- // Handle positional arguments (required parameters or optional positional parameters)
117
- let argIndex = 0;
118
- parameters.forEach((param) => {
119
- if (
120
- (param.required || param.isPositional) &&
121
- argIndex < positionalArgs.length
122
- ) {
123
- // Use the original camelCase parameter name for the SDK
124
- sdkParams[param.name] = convertValue(
125
- positionalArgs[argIndex],
126
- param.type,
127
- );
128
- argIndex++;
129
- }
130
- });
131
-
132
- // Handle option flags
133
- Object.entries(options).forEach(([key, value]) => {
134
- // Convert kebab-case back to camelCase
135
- const camelKey = key.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
136
- const param = parameters.find((p) => p.name === camelKey);
137
-
138
- if (param && value !== undefined) {
139
- sdkParams[camelKey] = convertValue(value, param.type);
140
- }
141
- });
142
-
143
- return sdkParams;
144
- }
145
-
146
- function convertValue(value: unknown, type: CliParameter["type"]): unknown {
147
- switch (type) {
148
- case "number":
149
- return Number(value);
150
- case "boolean":
151
- return Boolean(value);
152
- case "array":
153
- return Array.isArray(value) ? value : [value];
154
- case "string":
155
- default:
156
- // Handle JSON string for objects
157
- if (
158
- typeof value === "string" &&
159
- (value.startsWith("{") || value.startsWith("["))
160
- ) {
161
- try {
162
- return JSON.parse(value);
163
- } catch {
164
- return value;
165
- }
166
- }
167
- return value;
168
- }
169
- }