@zapier/zapier-sdk-cli 0.13.10 → 0.13.12
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/CHANGELOG.md +20 -0
- package/dist/cli.cjs +106 -56
- package/dist/cli.mjs +108 -58
- package/dist/index.cjs +84 -52
- package/dist/index.mjs +86 -54
- package/dist/package.json +1 -1
- package/dist/src/cli.js +23 -3
- package/dist/src/generators/ast-generator.js +33 -29
- package/dist/src/plugins/login/index.js +17 -5
- package/dist/src/utils/auth/login.d.ts +7 -1
- package/dist/src/utils/auth/login.js +10 -7
- package/dist/src/utils/constants.d.ts +1 -1
- package/dist/src/utils/constants.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/cli.test.ts +10 -0
- package/src/cli.ts +35 -3
- package/src/generators/ast-generator.test.ts +908 -0
- package/src/generators/ast-generator.ts +54 -46
- package/src/plugins/login/index.ts +33 -14
- package/src/utils/auth/login.ts +27 -8
- package/src/utils/constants.ts +1 -2
package/dist/index.cjs
CHANGED
|
@@ -161,7 +161,15 @@ var generateRandomString = () => {
|
|
|
161
161
|
(dec) => ("0" + dec.toString(16)).substring(-2)
|
|
162
162
|
).join("");
|
|
163
163
|
};
|
|
164
|
-
var login = async (
|
|
164
|
+
var login = async ({
|
|
165
|
+
timeoutMs = LOGIN_TIMEOUT_MS,
|
|
166
|
+
baseUrl,
|
|
167
|
+
authBaseUrl,
|
|
168
|
+
authClientId
|
|
169
|
+
}) => {
|
|
170
|
+
const authOptions = { baseUrl, authBaseUrl };
|
|
171
|
+
const tokenUrl = zapierSdkCliLogin.getAuthTokenUrl(authOptions);
|
|
172
|
+
const authorizeUrl = zapierSdkCliLogin.getAuthAuthorizeUrl(authOptions);
|
|
165
173
|
zapierSdkCliLogin.logout();
|
|
166
174
|
const availablePort = await findAvailablePort();
|
|
167
175
|
const redirectUri = `http://localhost:${availablePort}/oauth`;
|
|
@@ -187,9 +195,9 @@ var login = async (timeoutMs = LOGIN_TIMEOUT_MS) => {
|
|
|
187
195
|
process.on("SIGINT", cleanup);
|
|
188
196
|
process.on("SIGTERM", cleanup);
|
|
189
197
|
const { code_verifier: codeVerifier, code_challenge: codeChallenge } = await pkceChallenge__default.default();
|
|
190
|
-
const authUrl = `${
|
|
198
|
+
const authUrl = `${authorizeUrl}?${new URLSearchParams({
|
|
191
199
|
response_type: "code",
|
|
192
|
-
client_id: zapierSdkCliLogin.
|
|
200
|
+
client_id: authClientId || zapierSdkCliLogin.ZAPIER_AUTH_CLIENT_ID,
|
|
193
201
|
redirect_uri: redirectUri,
|
|
194
202
|
scope: "internal offline_access",
|
|
195
203
|
state: generateRandomString(),
|
|
@@ -232,12 +240,12 @@ var login = async (timeoutMs = LOGIN_TIMEOUT_MS) => {
|
|
|
232
240
|
}
|
|
233
241
|
log_default.info("Exchanging authorization code for tokens...");
|
|
234
242
|
const { data } = await client_default.post(
|
|
235
|
-
|
|
243
|
+
tokenUrl,
|
|
236
244
|
{
|
|
237
245
|
grant_type: "authorization_code",
|
|
238
246
|
code: await promisedCode,
|
|
239
247
|
redirect_uri: redirectUri,
|
|
240
|
-
client_id: zapierSdkCliLogin.
|
|
248
|
+
client_id: authClientId || zapierSdkCliLogin.ZAPIER_AUTH_CLIENT_ID,
|
|
241
249
|
code_verifier: codeVerifier
|
|
242
250
|
},
|
|
243
251
|
{
|
|
@@ -258,7 +266,7 @@ var LoginSchema = zod.z.object({
|
|
|
258
266
|
|
|
259
267
|
// package.json
|
|
260
268
|
var package_default = {
|
|
261
|
-
version: "0.13.
|
|
269
|
+
version: "0.13.12"};
|
|
262
270
|
|
|
263
271
|
// src/telemetry/builders.ts
|
|
264
272
|
function createCliBaseEvent(context = {}) {
|
|
@@ -316,23 +324,35 @@ function buildCliCommandExecutedEvent({
|
|
|
316
324
|
|
|
317
325
|
// src/plugins/login/index.ts
|
|
318
326
|
var CLI_COMMAND_EXECUTED_EVENT_SUBJECT = "platform.sdk.CliCommandExecutedEvent";
|
|
319
|
-
var loginWithSdk = zapierSdk.createFunction(
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
327
|
+
var loginWithSdk = zapierSdk.createFunction(
|
|
328
|
+
async (options) => {
|
|
329
|
+
const timeoutSeconds = options.timeout ? parseInt(options.timeout, 10) : 300;
|
|
330
|
+
if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
331
|
+
throw new Error("Timeout must be a positive number");
|
|
332
|
+
}
|
|
333
|
+
await login_default({
|
|
334
|
+
timeoutMs: timeoutSeconds * 1e3,
|
|
335
|
+
baseUrl: options.baseUrl,
|
|
336
|
+
authBaseUrl: options.authBaseUrl,
|
|
337
|
+
authClientId: options.authClientId
|
|
338
|
+
});
|
|
339
|
+
const user = await zapierSdkCliLogin.getLoggedInUser();
|
|
340
|
+
console.log(`\u2705 Successfully logged in as ${user.email}`);
|
|
341
|
+
setTimeout(() => process.exit(0), 100);
|
|
323
342
|
}
|
|
324
|
-
|
|
325
|
-
const user = await zapierSdkCliLogin.getLoggedInUser();
|
|
326
|
-
console.log(`\u2705 Successfully logged in as ${user.email}`);
|
|
327
|
-
setTimeout(() => process.exit(0), 100);
|
|
328
|
-
}, LoginSchema);
|
|
343
|
+
);
|
|
329
344
|
var loginPlugin = ({ context }) => {
|
|
330
345
|
const loginWithTelemetry = async (options) => {
|
|
331
346
|
const startTime = Date.now();
|
|
332
347
|
let success = false;
|
|
333
348
|
let errorMessage = null;
|
|
334
349
|
try {
|
|
335
|
-
await loginWithSdk(
|
|
350
|
+
await loginWithSdk({
|
|
351
|
+
...options,
|
|
352
|
+
baseUrl: context.options?.baseUrl,
|
|
353
|
+
authBaseUrl: context.options?.authBaseUrl,
|
|
354
|
+
authClientId: context.options?.authClientId
|
|
355
|
+
});
|
|
336
356
|
success = true;
|
|
337
357
|
} catch (error) {
|
|
338
358
|
success = false;
|
|
@@ -697,44 +717,56 @@ var AstTypeGenerator = class {
|
|
|
697
717
|
});
|
|
698
718
|
const actions = actionsResult.data;
|
|
699
719
|
const actionsWithFields = [];
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
720
|
+
const inputFieldsTasks = actions.map(
|
|
721
|
+
(action) => () => sdk.listInputFields({
|
|
722
|
+
appKey: app.implementation_id,
|
|
723
|
+
actionKey: action.key,
|
|
724
|
+
actionType: action.action_type,
|
|
725
|
+
authenticationId
|
|
726
|
+
})
|
|
727
|
+
);
|
|
728
|
+
const results = await zapierSdk.batch(inputFieldsTasks, {
|
|
729
|
+
concurrency: 50,
|
|
730
|
+
// Limit to 50 concurrent requests
|
|
731
|
+
retry: true,
|
|
732
|
+
// Automatically retry transient failures
|
|
733
|
+
timeoutMs: 18e4,
|
|
734
|
+
// 3 minute overall timeout
|
|
735
|
+
taskTimeoutMs: 3e4
|
|
736
|
+
// 30 seconds per-task timeout (API calls shouldn't take longer)
|
|
737
|
+
});
|
|
738
|
+
const failedActions = [];
|
|
739
|
+
results.forEach((result, i) => {
|
|
740
|
+
const action = actions[i];
|
|
741
|
+
if (result.status === "fulfilled") {
|
|
742
|
+
actionsWithFields.push({
|
|
743
|
+
...action,
|
|
744
|
+
inputFields: result.value.data,
|
|
745
|
+
name: action.title || action.key
|
|
746
|
+
});
|
|
747
|
+
} else {
|
|
748
|
+
failedActions.push(
|
|
749
|
+
`${action.key} (${action.action_type}): ${result.reason?.message || "Unknown error"}`
|
|
750
|
+
);
|
|
751
|
+
actionsWithFields.push({
|
|
752
|
+
...action,
|
|
753
|
+
inputFields: [],
|
|
754
|
+
name: action.title || action.key,
|
|
755
|
+
app_key: action.app_key || app.implementation_id,
|
|
756
|
+
action_type: action.action_type || "write",
|
|
757
|
+
title: action.title || action.key,
|
|
758
|
+
type: "action",
|
|
759
|
+
description: action.description || ""
|
|
760
|
+
});
|
|
722
761
|
}
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
...action,
|
|
728
|
-
inputFields: [],
|
|
729
|
-
name: action.title || action.key,
|
|
730
|
-
app_key: action.app_key || app.implementation_id,
|
|
731
|
-
action_type: action.action_type || "write",
|
|
732
|
-
title: action.title || action.key,
|
|
733
|
-
type: "action",
|
|
734
|
-
description: action.description || ""
|
|
735
|
-
});
|
|
736
|
-
}
|
|
762
|
+
});
|
|
763
|
+
if (failedActions.length > 0) {
|
|
764
|
+
console.warn(
|
|
765
|
+
`Failed to fetch input fields for ${failedActions.length} action(s):`
|
|
737
766
|
);
|
|
767
|
+
failedActions.forEach((failedAction) => {
|
|
768
|
+
console.warn(` - ${failedAction}`);
|
|
769
|
+
});
|
|
738
770
|
}
|
|
739
771
|
const sourceFile = this.createSourceFile(app, actionsWithFields);
|
|
740
772
|
return this.printer.printFile(sourceFile);
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { createFunction, OutputPropertySchema, DEFAULT_CONFIG_PATH, getOsInfo, getPlatformVersions, getCiPlatform, isCi, createZapierSdkWithoutRegistry, registryPlugin, getReleaseId, getCurrentTimestamp, generateEventId, ZapierValidationError, ZapierUnknownError, toSnakeCase } from '@zapier/zapier-sdk';
|
|
1
|
+
import { createFunction, OutputPropertySchema, DEFAULT_CONFIG_PATH, getOsInfo, getPlatformVersions, getCiPlatform, isCi, createZapierSdkWithoutRegistry, registryPlugin, getReleaseId, getCurrentTimestamp, generateEventId, ZapierValidationError, ZapierUnknownError, batch, toSnakeCase } from '@zapier/zapier-sdk';
|
|
2
2
|
import open from 'open';
|
|
3
3
|
import crypto from 'crypto';
|
|
4
4
|
import express from 'express';
|
|
5
5
|
import pkceChallenge from 'pkce-challenge';
|
|
6
|
-
import { getLoggedInUser, logout,
|
|
6
|
+
import { getLoggedInUser, logout, getAuthTokenUrl, getAuthAuthorizeUrl, ZAPIER_AUTH_CLIENT_ID, AUTH_MODE_HEADER, updateLogin, getConfigPath } from '@zapier/zapier-sdk-cli-login';
|
|
7
7
|
import ora from 'ora';
|
|
8
8
|
import chalk from 'chalk';
|
|
9
9
|
import { z } from 'zod';
|
|
@@ -130,7 +130,15 @@ var generateRandomString = () => {
|
|
|
130
130
|
(dec) => ("0" + dec.toString(16)).substring(-2)
|
|
131
131
|
).join("");
|
|
132
132
|
};
|
|
133
|
-
var login = async (
|
|
133
|
+
var login = async ({
|
|
134
|
+
timeoutMs = LOGIN_TIMEOUT_MS,
|
|
135
|
+
baseUrl,
|
|
136
|
+
authBaseUrl,
|
|
137
|
+
authClientId
|
|
138
|
+
}) => {
|
|
139
|
+
const authOptions = { baseUrl, authBaseUrl };
|
|
140
|
+
const tokenUrl = getAuthTokenUrl(authOptions);
|
|
141
|
+
const authorizeUrl = getAuthAuthorizeUrl(authOptions);
|
|
134
142
|
logout();
|
|
135
143
|
const availablePort = await findAvailablePort();
|
|
136
144
|
const redirectUri = `http://localhost:${availablePort}/oauth`;
|
|
@@ -156,9 +164,9 @@ var login = async (timeoutMs = LOGIN_TIMEOUT_MS) => {
|
|
|
156
164
|
process.on("SIGINT", cleanup);
|
|
157
165
|
process.on("SIGTERM", cleanup);
|
|
158
166
|
const { code_verifier: codeVerifier, code_challenge: codeChallenge } = await pkceChallenge();
|
|
159
|
-
const authUrl = `${
|
|
167
|
+
const authUrl = `${authorizeUrl}?${new URLSearchParams({
|
|
160
168
|
response_type: "code",
|
|
161
|
-
client_id:
|
|
169
|
+
client_id: authClientId || ZAPIER_AUTH_CLIENT_ID,
|
|
162
170
|
redirect_uri: redirectUri,
|
|
163
171
|
scope: "internal offline_access",
|
|
164
172
|
state: generateRandomString(),
|
|
@@ -201,12 +209,12 @@ var login = async (timeoutMs = LOGIN_TIMEOUT_MS) => {
|
|
|
201
209
|
}
|
|
202
210
|
log_default.info("Exchanging authorization code for tokens...");
|
|
203
211
|
const { data } = await client_default.post(
|
|
204
|
-
|
|
212
|
+
tokenUrl,
|
|
205
213
|
{
|
|
206
214
|
grant_type: "authorization_code",
|
|
207
215
|
code: await promisedCode,
|
|
208
216
|
redirect_uri: redirectUri,
|
|
209
|
-
client_id:
|
|
217
|
+
client_id: authClientId || ZAPIER_AUTH_CLIENT_ID,
|
|
210
218
|
code_verifier: codeVerifier
|
|
211
219
|
},
|
|
212
220
|
{
|
|
@@ -227,7 +235,7 @@ var LoginSchema = z.object({
|
|
|
227
235
|
|
|
228
236
|
// package.json
|
|
229
237
|
var package_default = {
|
|
230
|
-
version: "0.13.
|
|
238
|
+
version: "0.13.12"};
|
|
231
239
|
|
|
232
240
|
// src/telemetry/builders.ts
|
|
233
241
|
function createCliBaseEvent(context = {}) {
|
|
@@ -285,23 +293,35 @@ function buildCliCommandExecutedEvent({
|
|
|
285
293
|
|
|
286
294
|
// src/plugins/login/index.ts
|
|
287
295
|
var CLI_COMMAND_EXECUTED_EVENT_SUBJECT = "platform.sdk.CliCommandExecutedEvent";
|
|
288
|
-
var loginWithSdk = createFunction(
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
296
|
+
var loginWithSdk = createFunction(
|
|
297
|
+
async (options) => {
|
|
298
|
+
const timeoutSeconds = options.timeout ? parseInt(options.timeout, 10) : 300;
|
|
299
|
+
if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
300
|
+
throw new Error("Timeout must be a positive number");
|
|
301
|
+
}
|
|
302
|
+
await login_default({
|
|
303
|
+
timeoutMs: timeoutSeconds * 1e3,
|
|
304
|
+
baseUrl: options.baseUrl,
|
|
305
|
+
authBaseUrl: options.authBaseUrl,
|
|
306
|
+
authClientId: options.authClientId
|
|
307
|
+
});
|
|
308
|
+
const user = await getLoggedInUser();
|
|
309
|
+
console.log(`\u2705 Successfully logged in as ${user.email}`);
|
|
310
|
+
setTimeout(() => process.exit(0), 100);
|
|
292
311
|
}
|
|
293
|
-
|
|
294
|
-
const user = await getLoggedInUser();
|
|
295
|
-
console.log(`\u2705 Successfully logged in as ${user.email}`);
|
|
296
|
-
setTimeout(() => process.exit(0), 100);
|
|
297
|
-
}, LoginSchema);
|
|
312
|
+
);
|
|
298
313
|
var loginPlugin = ({ context }) => {
|
|
299
314
|
const loginWithTelemetry = async (options) => {
|
|
300
315
|
const startTime = Date.now();
|
|
301
316
|
let success = false;
|
|
302
317
|
let errorMessage = null;
|
|
303
318
|
try {
|
|
304
|
-
await loginWithSdk(
|
|
319
|
+
await loginWithSdk({
|
|
320
|
+
...options,
|
|
321
|
+
baseUrl: context.options?.baseUrl,
|
|
322
|
+
authBaseUrl: context.options?.authBaseUrl,
|
|
323
|
+
authClientId: context.options?.authClientId
|
|
324
|
+
});
|
|
305
325
|
success = true;
|
|
306
326
|
} catch (error) {
|
|
307
327
|
success = false;
|
|
@@ -666,44 +686,56 @@ var AstTypeGenerator = class {
|
|
|
666
686
|
});
|
|
667
687
|
const actions = actionsResult.data;
|
|
668
688
|
const actionsWithFields = [];
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
689
|
+
const inputFieldsTasks = actions.map(
|
|
690
|
+
(action) => () => sdk.listInputFields({
|
|
691
|
+
appKey: app.implementation_id,
|
|
692
|
+
actionKey: action.key,
|
|
693
|
+
actionType: action.action_type,
|
|
694
|
+
authenticationId
|
|
695
|
+
})
|
|
696
|
+
);
|
|
697
|
+
const results = await batch(inputFieldsTasks, {
|
|
698
|
+
concurrency: 50,
|
|
699
|
+
// Limit to 50 concurrent requests
|
|
700
|
+
retry: true,
|
|
701
|
+
// Automatically retry transient failures
|
|
702
|
+
timeoutMs: 18e4,
|
|
703
|
+
// 3 minute overall timeout
|
|
704
|
+
taskTimeoutMs: 3e4
|
|
705
|
+
// 30 seconds per-task timeout (API calls shouldn't take longer)
|
|
706
|
+
});
|
|
707
|
+
const failedActions = [];
|
|
708
|
+
results.forEach((result, i) => {
|
|
709
|
+
const action = actions[i];
|
|
710
|
+
if (result.status === "fulfilled") {
|
|
711
|
+
actionsWithFields.push({
|
|
712
|
+
...action,
|
|
713
|
+
inputFields: result.value.data,
|
|
714
|
+
name: action.title || action.key
|
|
715
|
+
});
|
|
716
|
+
} else {
|
|
717
|
+
failedActions.push(
|
|
718
|
+
`${action.key} (${action.action_type}): ${result.reason?.message || "Unknown error"}`
|
|
719
|
+
);
|
|
720
|
+
actionsWithFields.push({
|
|
721
|
+
...action,
|
|
722
|
+
inputFields: [],
|
|
723
|
+
name: action.title || action.key,
|
|
724
|
+
app_key: action.app_key || app.implementation_id,
|
|
725
|
+
action_type: action.action_type || "write",
|
|
726
|
+
title: action.title || action.key,
|
|
727
|
+
type: "action",
|
|
728
|
+
description: action.description || ""
|
|
729
|
+
});
|
|
691
730
|
}
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
...action,
|
|
697
|
-
inputFields: [],
|
|
698
|
-
name: action.title || action.key,
|
|
699
|
-
app_key: action.app_key || app.implementation_id,
|
|
700
|
-
action_type: action.action_type || "write",
|
|
701
|
-
title: action.title || action.key,
|
|
702
|
-
type: "action",
|
|
703
|
-
description: action.description || ""
|
|
704
|
-
});
|
|
705
|
-
}
|
|
731
|
+
});
|
|
732
|
+
if (failedActions.length > 0) {
|
|
733
|
+
console.warn(
|
|
734
|
+
`Failed to fetch input fields for ${failedActions.length} action(s):`
|
|
706
735
|
);
|
|
736
|
+
failedActions.forEach((failedAction) => {
|
|
737
|
+
console.warn(` - ${failedAction}`);
|
|
738
|
+
});
|
|
707
739
|
}
|
|
708
740
|
const sourceFile = this.createSourceFile(app, actionsWithFields);
|
|
709
741
|
return this.printer.printFile(sourceFile);
|
package/dist/package.json
CHANGED
package/dist/src/cli.js
CHANGED
|
@@ -8,12 +8,32 @@ program
|
|
|
8
8
|
.name("zapier-sdk")
|
|
9
9
|
.description("CLI for Zapier SDK")
|
|
10
10
|
.version(packageJson.version, "-v, --version", "display version number")
|
|
11
|
-
.option("--debug", "Enable debug logging")
|
|
12
|
-
|
|
11
|
+
.option("--debug", "Enable debug logging")
|
|
12
|
+
.option("--base-url <url>", "Base URL for Zapier API endpoints")
|
|
13
|
+
.option("--auth-base-url <url>", "Base URL for Zapier authentication endpoints")
|
|
14
|
+
.option("--auth-client-id <id>", "OAuth client ID for Zapier authentication")
|
|
15
|
+
.option("--tracking-base-url <url>", "Base URL for Zapier tracking endpoints");
|
|
16
|
+
// Check for debug flag early (support both flag and env var)
|
|
13
17
|
const isDebugMode = process.env.DEBUG === "true" || process.argv.includes("--debug");
|
|
14
|
-
//
|
|
18
|
+
// Extract URL options from process.argv for early SDK creation
|
|
19
|
+
// We need to create the SDK before parsing to generate commands from schemas
|
|
20
|
+
const baseUrlIndex = process.argv.indexOf("--base-url");
|
|
21
|
+
const authBaseUrlIndex = process.argv.indexOf("--auth-base-url");
|
|
22
|
+
const authClientIdIndex = process.argv.indexOf("--auth-client-id");
|
|
23
|
+
const trackingBaseUrlIndex = process.argv.indexOf("--tracking-base-url");
|
|
24
|
+
const baseUrl = baseUrlIndex !== -1 ? process.argv[baseUrlIndex + 1] : undefined;
|
|
25
|
+
const authBaseUrl = authBaseUrlIndex !== -1 ? process.argv[authBaseUrlIndex + 1] : undefined;
|
|
26
|
+
const authClientId = authClientIdIndex !== -1 ? process.argv[authClientIdIndex + 1] : undefined;
|
|
27
|
+
const trackingBaseUrl = trackingBaseUrlIndex !== -1
|
|
28
|
+
? process.argv[trackingBaseUrlIndex + 1]
|
|
29
|
+
: undefined;
|
|
30
|
+
// Create CLI SDK instance with all plugins and URL options
|
|
15
31
|
const sdk = createZapierCliSdk({
|
|
16
32
|
debug: isDebugMode,
|
|
33
|
+
baseUrl,
|
|
34
|
+
authBaseUrl,
|
|
35
|
+
authClientId,
|
|
36
|
+
trackingBaseUrl,
|
|
17
37
|
});
|
|
18
38
|
// Auth commands now handled by plugins
|
|
19
39
|
// Generate CLI commands from SDK schemas (including CLI plugins)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as ts from "typescript";
|
|
2
|
-
import { toSnakeCase } from "@zapier/zapier-sdk";
|
|
2
|
+
import { toSnakeCase, batch } from "@zapier/zapier-sdk";
|
|
3
3
|
/**
|
|
4
4
|
* AST-based TypeScript type generator using the TypeScript Compiler API
|
|
5
5
|
*/
|
|
@@ -24,35 +24,33 @@ export class AstTypeGenerator {
|
|
|
24
24
|
const actions = actionsResult.data;
|
|
25
25
|
// Fetch input fields for each action
|
|
26
26
|
const actionsWithFields = [];
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
27
|
+
// Fetch all input fields with concurrency limiting for better reliability
|
|
28
|
+
// Using batch() instead of Promise.allSettled() prevents overwhelming the API
|
|
29
|
+
// and triggering rate limits when apps have many actions
|
|
30
|
+
const inputFieldsTasks = actions.map((action) => () => sdk.listInputFields({
|
|
31
|
+
appKey: app.implementation_id,
|
|
32
|
+
actionKey: action.key,
|
|
33
|
+
actionType: action.action_type,
|
|
34
|
+
authenticationId: authenticationId,
|
|
35
|
+
}));
|
|
36
|
+
const results = await batch(inputFieldsTasks, {
|
|
37
|
+
concurrency: 50, // Limit to 50 concurrent requests
|
|
38
|
+
retry: true, // Automatically retry transient failures
|
|
39
|
+
timeoutMs: 180000, // 3 minute overall timeout
|
|
40
|
+
taskTimeoutMs: 30000, // 30 seconds per-task timeout (API calls shouldn't take longer)
|
|
41
|
+
});
|
|
42
|
+
const failedActions = [];
|
|
43
|
+
results.forEach((result, i) => {
|
|
44
|
+
const action = actions[i];
|
|
45
|
+
if (result.status === "fulfilled") {
|
|
46
|
+
actionsWithFields.push({
|
|
47
|
+
...action,
|
|
48
|
+
inputFields: result.value.data,
|
|
49
|
+
name: action.title || action.key,
|
|
50
|
+
});
|
|
51
51
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
// Convert actions to have empty input fields (will generate generic types)
|
|
55
|
-
actions.forEach((action) => {
|
|
52
|
+
else {
|
|
53
|
+
failedActions.push(`${action.key} (${action.action_type}): ${result.reason?.message || "Unknown error"}`);
|
|
56
54
|
actionsWithFields.push({
|
|
57
55
|
...action,
|
|
58
56
|
inputFields: [],
|
|
@@ -63,6 +61,12 @@ export class AstTypeGenerator {
|
|
|
63
61
|
type: "action",
|
|
64
62
|
description: action.description || "",
|
|
65
63
|
});
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
if (failedActions.length > 0) {
|
|
67
|
+
console.warn(`Failed to fetch input fields for ${failedActions.length} action(s):`);
|
|
68
|
+
failedActions.forEach((failedAction) => {
|
|
69
|
+
console.warn(` - ${failedAction}`);
|
|
66
70
|
});
|
|
67
71
|
}
|
|
68
72
|
// Generate TypeScript AST nodes
|
|
@@ -5,17 +5,24 @@ import { LoginSchema } from "./schemas";
|
|
|
5
5
|
import { buildCliCommandExecutedEvent } from "../../telemetry/builders";
|
|
6
6
|
import cliPackageJson from "../../../package.json";
|
|
7
7
|
const CLI_COMMAND_EXECUTED_EVENT_SUBJECT = "platform.sdk.CliCommandExecutedEvent";
|
|
8
|
-
const loginWithSdk = createFunction(async
|
|
9
|
-
const timeoutSeconds = options.timeout
|
|
8
|
+
const loginWithSdk = createFunction(async (options) => {
|
|
9
|
+
const timeoutSeconds = options.timeout
|
|
10
|
+
? parseInt(options.timeout, 10)
|
|
11
|
+
: 300;
|
|
10
12
|
if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
11
13
|
throw new Error("Timeout must be a positive number");
|
|
12
14
|
}
|
|
13
|
-
await login(
|
|
15
|
+
await login({
|
|
16
|
+
timeoutMs: timeoutSeconds * 1000,
|
|
17
|
+
baseUrl: options.baseUrl,
|
|
18
|
+
authBaseUrl: options.authBaseUrl,
|
|
19
|
+
authClientId: options.authClientId,
|
|
20
|
+
});
|
|
14
21
|
const user = await getLoggedInUser();
|
|
15
22
|
console.log(`✅ Successfully logged in as ${user.email}`);
|
|
16
23
|
// Force immediate exit to prevent hanging (especially in development with tsx)
|
|
17
24
|
setTimeout(() => process.exit(0), 100);
|
|
18
|
-
}
|
|
25
|
+
});
|
|
19
26
|
export const loginPlugin = ({ context }) => {
|
|
20
27
|
// Wrap the login function to emit telemetry events
|
|
21
28
|
const loginWithTelemetry = async (options) => {
|
|
@@ -23,7 +30,12 @@ export const loginPlugin = ({ context }) => {
|
|
|
23
30
|
let success = false;
|
|
24
31
|
let errorMessage = null;
|
|
25
32
|
try {
|
|
26
|
-
await loginWithSdk(
|
|
33
|
+
await loginWithSdk({
|
|
34
|
+
...options,
|
|
35
|
+
baseUrl: context.options?.baseUrl,
|
|
36
|
+
authBaseUrl: context.options?.authBaseUrl,
|
|
37
|
+
authClientId: context.options?.authClientId,
|
|
38
|
+
});
|
|
27
39
|
success = true;
|
|
28
40
|
}
|
|
29
41
|
catch (error) {
|
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
interface LoginOptions {
|
|
2
|
+
timeoutMs?: number;
|
|
3
|
+
baseUrl?: string;
|
|
4
|
+
authBaseUrl?: string;
|
|
5
|
+
authClientId?: string;
|
|
6
|
+
}
|
|
7
|
+
declare const login: ({ timeoutMs, baseUrl, authBaseUrl, authClientId, }: LoginOptions) => Promise<string>;
|
|
2
8
|
export default login;
|
|
@@ -2,12 +2,12 @@ import open from "open";
|
|
|
2
2
|
import crypto from "node:crypto";
|
|
3
3
|
import express from "express";
|
|
4
4
|
import pkceChallenge from "pkce-challenge";
|
|
5
|
-
import { AUTH_MODE_HEADER,
|
|
5
|
+
import { AUTH_MODE_HEADER, ZAPIER_AUTH_CLIENT_ID, LOGIN_PORTS, LOGIN_TIMEOUT_MS, } from "../constants";
|
|
6
6
|
import { spinPromise } from "../spinner";
|
|
7
7
|
import log from "../log";
|
|
8
8
|
import api from "../api/client";
|
|
9
9
|
import getCallablePromise from "../getCallablePromise";
|
|
10
|
-
import { updateLogin, logout } from "@zapier/zapier-sdk-cli-login";
|
|
10
|
+
import { updateLogin, logout, getAuthTokenUrl, getAuthAuthorizeUrl, } from "@zapier/zapier-sdk-cli-login";
|
|
11
11
|
const findAvailablePort = () => {
|
|
12
12
|
return new Promise((resolve, reject) => {
|
|
13
13
|
let portIndex = 0;
|
|
@@ -45,7 +45,10 @@ const generateRandomString = () => {
|
|
|
45
45
|
crypto.getRandomValues(array);
|
|
46
46
|
return Array.from(array, (dec) => ("0" + dec.toString(16)).substring(-2)).join("");
|
|
47
47
|
};
|
|
48
|
-
const login = async (timeoutMs = LOGIN_TIMEOUT_MS) => {
|
|
48
|
+
const login = async ({ timeoutMs = LOGIN_TIMEOUT_MS, baseUrl, authBaseUrl, authClientId, }) => {
|
|
49
|
+
const authOptions = { baseUrl, authBaseUrl };
|
|
50
|
+
const tokenUrl = getAuthTokenUrl(authOptions);
|
|
51
|
+
const authorizeUrl = getAuthAuthorizeUrl(authOptions);
|
|
49
52
|
// Force logout
|
|
50
53
|
logout();
|
|
51
54
|
// Find an available port
|
|
@@ -76,9 +79,9 @@ const login = async (timeoutMs = LOGIN_TIMEOUT_MS) => {
|
|
|
76
79
|
process.on("SIGINT", cleanup);
|
|
77
80
|
process.on("SIGTERM", cleanup);
|
|
78
81
|
const { code_verifier: codeVerifier, code_challenge: codeChallenge } = await pkceChallenge();
|
|
79
|
-
const authUrl = `${
|
|
82
|
+
const authUrl = `${authorizeUrl}?${new URLSearchParams({
|
|
80
83
|
response_type: "code",
|
|
81
|
-
client_id:
|
|
84
|
+
client_id: authClientId || ZAPIER_AUTH_CLIENT_ID,
|
|
82
85
|
redirect_uri: redirectUri,
|
|
83
86
|
scope: "internal offline_access",
|
|
84
87
|
state: generateRandomString(),
|
|
@@ -115,11 +118,11 @@ const login = async (timeoutMs = LOGIN_TIMEOUT_MS) => {
|
|
|
115
118
|
});
|
|
116
119
|
}
|
|
117
120
|
log.info("Exchanging authorization code for tokens...");
|
|
118
|
-
const { data } = await api.post(
|
|
121
|
+
const { data } = await api.post(tokenUrl, {
|
|
119
122
|
grant_type: "authorization_code",
|
|
120
123
|
code: await promisedCode,
|
|
121
124
|
redirect_uri: redirectUri,
|
|
122
|
-
client_id:
|
|
125
|
+
client_id: authClientId || ZAPIER_AUTH_CLIENT_ID,
|
|
123
126
|
code_verifier: codeVerifier,
|
|
124
127
|
}, {
|
|
125
128
|
headers: {
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { ZAPIER_AUTH_CLIENT_ID, AUTH_MODE_HEADER, } from "@zapier/zapier-sdk-cli-login";
|
|
2
2
|
export declare const LOGIN_PORTS: number[];
|
|
3
3
|
export declare const LOGIN_TIMEOUT_MS = 300000;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Import shared OAuth constants from login package
|
|
2
|
-
export {
|
|
2
|
+
export { ZAPIER_AUTH_CLIENT_ID, AUTH_MODE_HEADER, } from "@zapier/zapier-sdk-cli-login";
|
|
3
3
|
// CLI-specific constants
|
|
4
4
|
export const LOGIN_PORTS = [49505, 50575, 52804, 55981, 61010, 63851];
|
|
5
5
|
export const LOGIN_TIMEOUT_MS = 300000; // 5 minutes
|