@zapier/zapier-sdk-cli 0.13.9 → 0.13.11

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.
@@ -8,7 +8,11 @@ import type {
8
8
  ManifestPluginProvides,
9
9
  AppItem,
10
10
  } from "@zapier/zapier-sdk";
11
- import { createFunction } from "@zapier/zapier-sdk";
11
+ import {
12
+ createFunction,
13
+ ZapierValidationError,
14
+ ZapierUnknownError,
15
+ } from "@zapier/zapier-sdk";
12
16
  import {
13
17
  GenerateAppTypesSchema,
14
18
  type GenerateAppTypesOptions,
@@ -17,7 +21,8 @@ import {
17
21
  import { AstTypeGenerator } from "../../generators/ast-generator";
18
22
  import { getManifestKey } from "../../utils/manifest-helpers";
19
23
  import { mkdir, writeFile } from "fs/promises";
20
- import { join } from "path";
24
+ import { join, resolve } from "path";
25
+ import { detectTypesOutputDirectory } from "../../utils/directory-detection";
21
26
 
22
27
  export interface GenerateAppTypesPluginProvides {
23
28
  generateAppTypes: (
@@ -50,20 +55,14 @@ export const generateAppTypesPlugin: Plugin<
50
55
  appKeys,
51
56
  authenticationIds,
52
57
  skipWrite = false,
53
- typesOutputDirectory,
58
+ typesOutputDirectory = await detectTypesOutputDirectory(),
54
59
  onProgress,
55
60
  } = options;
56
61
 
57
- // Validate that typesOutputDirectory is provided when skipWrite is false
58
- if (!skipWrite && !typesOutputDirectory) {
59
- throw new Error(
60
- "typesOutputDirectory is required when skipWrite is false",
61
- );
62
- }
62
+ const resolvedTypesOutput = resolve(typesOutputDirectory);
63
63
 
64
64
  const result: GenerateAppTypesResult = {
65
65
  typeDefinitions: {},
66
- errors: [],
67
66
  };
68
67
 
69
68
  // Get apps using listApps (which respects existing manifest for version locking)
@@ -100,8 +99,8 @@ export const generateAppTypesPlugin: Plugin<
100
99
  }
101
100
 
102
101
  // Ensure output directory exists if we're writing files
103
- if (!skipWrite && typesOutputDirectory) {
104
- await mkdir(typesOutputDirectory, { recursive: true });
102
+ if (!skipWrite && resolvedTypesOutput) {
103
+ await mkdir(resolvedTypesOutput, { recursive: true });
105
104
  }
106
105
 
107
106
  // Initialize writtenFiles if we're writing to disk
@@ -119,17 +118,18 @@ export const generateAppTypesPlugin: Plugin<
119
118
 
120
119
  try {
121
120
  if (!app.version) {
122
- const error = `Invalid implementation ID format: ${app.implementation_id}. Expected format: <implementationName>@<version>`;
123
- result.errors.push({
124
- appKey: app.key,
125
- error,
126
- });
121
+ const errorMessage = `Invalid implementation ID format: ${app.implementation_id}. Expected format: <implementationName>@<version>`;
127
122
  onProgress?.({
128
123
  type: "app_processing_error",
129
124
  appKey: app.key,
130
- error,
125
+ error: errorMessage,
126
+ });
127
+ throw new ZapierValidationError(errorMessage, {
128
+ details: {
129
+ appKey: app.key,
130
+ implementationId: app.implementation_id,
131
+ },
131
132
  });
132
- continue;
133
133
  }
134
134
 
135
135
  // Find matching authentication for this app if authentications were provided
@@ -158,63 +158,55 @@ export const generateAppTypesPlugin: Plugin<
158
158
  const manifestKey = getManifestKey(app);
159
159
 
160
160
  // Generate type definitions
161
- try {
162
- const generator = new AstTypeGenerator();
163
- const typeDefinitionString = await generator.generateTypes({
164
- app,
165
- authenticationId,
166
- sdk,
167
- });
168
-
169
- result.typeDefinitions[manifestKey] = typeDefinitionString;
161
+ const generator = new AstTypeGenerator();
162
+ const typeDefinitionString = await generator.generateTypes({
163
+ app,
164
+ authenticationId,
165
+ sdk,
166
+ });
170
167
 
171
- onProgress?.({
172
- type: "type_generated",
173
- manifestKey,
174
- sizeBytes: typeDefinitionString.length,
175
- });
168
+ result.typeDefinitions[manifestKey] = typeDefinitionString;
176
169
 
177
- // Write to file if skipWrite is false
178
- if (!skipWrite && typesOutputDirectory && result.writtenFiles) {
179
- const filePath = join(typesOutputDirectory, `${manifestKey}.d.ts`);
180
- await writeFile(filePath, typeDefinitionString, "utf8");
170
+ onProgress?.({
171
+ type: "type_generated",
172
+ manifestKey,
173
+ sizeBytes: typeDefinitionString.length,
174
+ });
181
175
 
182
- result.writtenFiles[manifestKey] = filePath;
176
+ // Write to file if skipWrite is false
177
+ if (!skipWrite && resolvedTypesOutput && result.writtenFiles) {
178
+ const filePath = join(resolvedTypesOutput, `${manifestKey}.d.ts`);
179
+ await writeFile(filePath, typeDefinitionString, "utf8");
183
180
 
184
- onProgress?.({
185
- type: "file_written",
186
- manifestKey,
187
- filePath,
188
- });
189
- }
181
+ result.writtenFiles[manifestKey] = filePath;
190
182
 
191
183
  onProgress?.({
192
- type: "app_processing_complete",
193
- appKey: app.key,
194
- });
195
- } catch (error) {
196
- const errorMessage = `Failed to generate types: ${error}`;
197
- result.errors.push({
198
- appKey: app.key,
199
- error: errorMessage,
200
- });
201
- onProgress?.({
202
- type: "app_processing_error",
203
- appKey: app.key,
204
- error: errorMessage,
184
+ type: "file_written",
185
+ manifestKey,
186
+ filePath,
205
187
  });
206
188
  }
207
- } catch (error) {
208
- const errorMessage = `Failed to process app: ${error}`;
209
- result.errors.push({
189
+
190
+ onProgress?.({
191
+ type: "app_processing_complete",
210
192
  appKey: app.key,
211
- error: errorMessage,
212
193
  });
194
+ } catch (error) {
195
+ const errorMessage = `Failed to process app ${app.key}: ${error instanceof Error ? error.message : String(error)}`;
196
+
213
197
  onProgress?.({
214
198
  type: "app_processing_error",
215
199
  appKey: app.key,
216
200
  error: errorMessage,
217
201
  });
202
+
203
+ if (error instanceof ZapierValidationError) {
204
+ throw error; // Preserve the specific error type
205
+ } else {
206
+ throw new ZapierUnknownError(errorMessage, {
207
+ cause: error, // Works for both Error and non-Error
208
+ });
209
+ }
218
210
  }
219
211
  }
220
212
 
@@ -58,8 +58,4 @@ export type AppTypesProgressEvent =
58
58
  export interface GenerateAppTypesResult {
59
59
  typeDefinitions: Record<string, string>; // manifestKey -> type definition string
60
60
  writtenFiles?: Record<string, string>; // manifestKey -> file path (only when skipWrite is false)
61
- errors: Array<{
62
- appKey: string;
63
- error: string;
64
- }>;
65
61
  }
@@ -29,22 +29,36 @@ interface LoginPluginProvides {
29
29
  const CLI_COMMAND_EXECUTED_EVENT_SUBJECT =
30
30
  "platform.sdk.CliCommandExecutedEvent";
31
31
 
32
- const loginWithSdk = createFunction(async function loginWithSdk(
33
- options: LoginOptions,
34
- ): Promise<void> {
35
- const timeoutSeconds = options.timeout ? parseInt(options.timeout, 10) : 300;
36
- if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {
37
- throw new Error("Timeout must be a positive number");
38
- }
32
+ // Internal type for loginWithSdk that includes SDK URL options
33
+ interface LoginWithSdkOptions extends LoginOptions {
34
+ baseUrl?: string;
35
+ authBaseUrl?: string;
36
+ authClientId?: string;
37
+ }
38
+
39
+ const loginWithSdk = createFunction(
40
+ async (options: LoginWithSdkOptions): Promise<void> => {
41
+ const timeoutSeconds = options.timeout
42
+ ? parseInt(options.timeout, 10)
43
+ : 300;
44
+ if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {
45
+ throw new Error("Timeout must be a positive number");
46
+ }
39
47
 
40
- await login(timeoutSeconds * 1000); // Convert to milliseconds
41
- const user = await getLoggedInUser();
48
+ await login({
49
+ timeoutMs: timeoutSeconds * 1000,
50
+ baseUrl: options.baseUrl,
51
+ authBaseUrl: options.authBaseUrl,
52
+ authClientId: options.authClientId,
53
+ });
54
+ const user = await getLoggedInUser();
42
55
 
43
- console.log(`✅ Successfully logged in as ${user.email}`);
56
+ console.log(`✅ Successfully logged in as ${user.email}`);
44
57
 
45
- // Force immediate exit to prevent hanging (especially in development with tsx)
46
- setTimeout(() => process.exit(0), 100);
47
- }, LoginSchema);
58
+ // Force immediate exit to prevent hanging (especially in development with tsx)
59
+ setTimeout(() => process.exit(0), 100);
60
+ },
61
+ );
48
62
 
49
63
  export const loginPlugin: Plugin<
50
64
  {},
@@ -58,7 +72,12 @@ export const loginPlugin: Plugin<
58
72
  let errorMessage: string | null = null;
59
73
 
60
74
  try {
61
- await loginWithSdk(options);
75
+ await loginWithSdk({
76
+ ...options,
77
+ baseUrl: context.options?.baseUrl,
78
+ authBaseUrl: context.options?.authBaseUrl,
79
+ authClientId: context.options?.authClientId,
80
+ });
62
81
  success = true;
63
82
  } catch (error) {
64
83
  success = false;
@@ -6,16 +6,20 @@ import type { Socket } from "net";
6
6
 
7
7
  import {
8
8
  AUTH_MODE_HEADER,
9
- LOGIN_CLIENT_ID,
9
+ ZAPIER_AUTH_CLIENT_ID,
10
10
  LOGIN_PORTS,
11
11
  LOGIN_TIMEOUT_MS,
12
- ZAPIER_BASE,
13
12
  } from "../constants";
14
13
  import { spinPromise } from "../spinner";
15
14
  import log from "../log";
16
15
  import api from "../api/client";
17
16
  import getCallablePromise from "../getCallablePromise";
18
- import { updateLogin, logout } from "@zapier/zapier-sdk-cli-login";
17
+ import {
18
+ updateLogin,
19
+ logout,
20
+ getAuthTokenUrl,
21
+ getAuthAuthorizeUrl,
22
+ } from "@zapier/zapier-sdk-cli-login";
19
23
 
20
24
  const findAvailablePort = (): Promise<number> => {
21
25
  return new Promise((resolve, reject) => {
@@ -62,7 +66,22 @@ const generateRandomString = () => {
62
66
  ).join("");
63
67
  };
64
68
 
65
- const login = async (timeoutMs: number = LOGIN_TIMEOUT_MS): Promise<string> => {
69
+ interface LoginOptions {
70
+ timeoutMs?: number;
71
+ baseUrl?: string;
72
+ authBaseUrl?: string;
73
+ authClientId?: string;
74
+ }
75
+
76
+ const login = async ({
77
+ timeoutMs = LOGIN_TIMEOUT_MS,
78
+ baseUrl,
79
+ authBaseUrl,
80
+ authClientId,
81
+ }: LoginOptions): Promise<string> => {
82
+ const authOptions = { baseUrl, authBaseUrl };
83
+ const tokenUrl = getAuthTokenUrl(authOptions);
84
+ const authorizeUrl = getAuthAuthorizeUrl(authOptions);
66
85
  // Force logout
67
86
  logout();
68
87
 
@@ -106,9 +125,9 @@ const login = async (timeoutMs: number = LOGIN_TIMEOUT_MS): Promise<string> => {
106
125
  const { code_verifier: codeVerifier, code_challenge: codeChallenge } =
107
126
  await pkceChallenge();
108
127
 
109
- const authUrl = `${ZAPIER_BASE}/oauth/authorize/?${new URLSearchParams({
128
+ const authUrl = `${authorizeUrl}?${new URLSearchParams({
110
129
  response_type: "code",
111
- client_id: LOGIN_CLIENT_ID,
130
+ client_id: authClientId || ZAPIER_AUTH_CLIENT_ID,
112
131
  redirect_uri: redirectUri,
113
132
  scope: "internal offline_access",
114
133
  state: generateRandomString(),
@@ -165,12 +184,12 @@ const login = async (timeoutMs: number = LOGIN_TIMEOUT_MS): Promise<string> => {
165
184
  refresh_token: string;
166
185
  expires_in: number;
167
186
  }>(
168
- `${ZAPIER_BASE}/oauth/token/`,
187
+ tokenUrl,
169
188
  {
170
189
  grant_type: "authorization_code",
171
190
  code: await promisedCode,
172
191
  redirect_uri: redirectUri,
173
- client_id: LOGIN_CLIENT_ID,
192
+ client_id: authClientId || ZAPIER_AUTH_CLIENT_ID,
174
193
  code_verifier: codeVerifier,
175
194
  },
176
195
  {
@@ -1,7 +1,6 @@
1
1
  // Import shared OAuth constants from login package
2
2
  export {
3
- ZAPIER_BASE,
4
- LOGIN_CLIENT_ID,
3
+ ZAPIER_AUTH_CLIENT_ID,
5
4
  AUTH_MODE_HEADER,
6
5
  } from "@zapier/zapier-sdk-cli-login";
7
6