@zapier/zapier-sdk-cli 0.17.3 → 0.18.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.
- package/CHANGELOG.md +22 -0
- package/README.md +1 -1
- package/dist/cli.cjs +82 -49
- package/dist/cli.mjs +84 -51
- package/dist/index.cjs +40 -34
- package/dist/index.mjs +42 -36
- package/dist/package.json +1 -1
- package/dist/src/cli.js +47 -15
- package/dist/src/plugins/login/index.d.ts +2 -1
- package/dist/src/plugins/login/index.js +31 -29
- package/dist/src/utils/auth/login.d.ts +3 -4
- package/dist/src/utils/auth/login.js +17 -9
- 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/dist/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { createFunction, OutputPropertySchema, DEFAULT_CONFIG_PATH,
|
|
1
|
+
import { createFunction, OutputPropertySchema, DEFAULT_CONFIG_PATH, getOsInfo, getPlatformVersions, getCiPlatform, isCi, createZapierSdkWithoutRegistry, registryPlugin, getReleaseId, getCurrentTimestamp, generateEventId, ZapierValidationError, ZapierUnknownError, batch, toSnakeCase, isCredentialsObject, ZapierError } 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 {
|
|
6
|
+
import { logout, getConfigPath, getLoggedInUser, getPkceLoginConfig, AUTH_MODE_HEADER, updateLogin } from '@zapier/zapier-sdk-cli-login';
|
|
7
7
|
import ora from 'ora';
|
|
8
8
|
import chalk from 'chalk';
|
|
9
9
|
import { z } from 'zod';
|
|
@@ -151,15 +151,22 @@ var generateRandomString = () => {
|
|
|
151
151
|
(dec) => ("0" + dec.toString(16)).substring(-2)
|
|
152
152
|
).join("");
|
|
153
153
|
};
|
|
154
|
+
function ensureOfflineAccess(scope) {
|
|
155
|
+
if (scope.includes("offline_access")) {
|
|
156
|
+
return scope;
|
|
157
|
+
}
|
|
158
|
+
return `${scope} offline_access`;
|
|
159
|
+
}
|
|
154
160
|
var login = async ({
|
|
155
161
|
timeoutMs = LOGIN_TIMEOUT_MS,
|
|
156
|
-
|
|
157
|
-
authBaseUrl,
|
|
158
|
-
authClientId
|
|
162
|
+
credentials
|
|
159
163
|
}) => {
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
164
|
+
const { clientId, tokenUrl, authorizeUrl } = getPkceLoginConfig({
|
|
165
|
+
credentials
|
|
166
|
+
});
|
|
167
|
+
const scope = ensureOfflineAccess(
|
|
168
|
+
credentials?.scope || "internal credentials"
|
|
169
|
+
);
|
|
163
170
|
logout();
|
|
164
171
|
const availablePort = await findAvailablePort();
|
|
165
172
|
const redirectUri = `http://localhost:${availablePort}/oauth`;
|
|
@@ -191,9 +198,9 @@ var login = async ({
|
|
|
191
198
|
const { code_verifier: codeVerifier, code_challenge: codeChallenge } = await pkceChallenge();
|
|
192
199
|
const authUrl = `${authorizeUrl}?${new URLSearchParams({
|
|
193
200
|
response_type: "code",
|
|
194
|
-
client_id:
|
|
201
|
+
client_id: clientId,
|
|
195
202
|
redirect_uri: redirectUri,
|
|
196
|
-
scope
|
|
203
|
+
scope,
|
|
197
204
|
state: generateRandomString(),
|
|
198
205
|
code_challenge: codeChallenge,
|
|
199
206
|
code_challenge_method: "S256"
|
|
@@ -243,7 +250,7 @@ var login = async ({
|
|
|
243
250
|
grant_type: "authorization_code",
|
|
244
251
|
code: await promisedCode,
|
|
245
252
|
redirect_uri: redirectUri,
|
|
246
|
-
client_id:
|
|
253
|
+
client_id: clientId,
|
|
247
254
|
code_verifier: codeVerifier
|
|
248
255
|
},
|
|
249
256
|
{
|
|
@@ -264,7 +271,7 @@ var LoginSchema = z.object({
|
|
|
264
271
|
|
|
265
272
|
// package.json
|
|
266
273
|
var package_default = {
|
|
267
|
-
version: "0.
|
|
274
|
+
version: "0.18.0"};
|
|
268
275
|
|
|
269
276
|
// src/telemetry/builders.ts
|
|
270
277
|
function createCliBaseEvent(context = {}) {
|
|
@@ -321,22 +328,17 @@ function buildCliCommandExecutedEvent({
|
|
|
321
328
|
|
|
322
329
|
// src/plugins/login/index.ts
|
|
323
330
|
var CLI_COMMAND_EXECUTED_EVENT_SUBJECT = "platform.sdk.CliCommandExecutedEvent";
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
baseUrl: options.baseUrl,
|
|
333
|
-
authBaseUrl: options.authBaseUrl,
|
|
334
|
-
authClientId: options.authClientId
|
|
335
|
-
});
|
|
336
|
-
const user = await getLoggedInUser();
|
|
337
|
-
console.log(`\u2705 Successfully logged in as ${user.email}`);
|
|
331
|
+
function toPkceCredentials(credentials) {
|
|
332
|
+
if (credentials && isCredentialsObject(credentials) && !("clientSecret" in credentials)) {
|
|
333
|
+
return {
|
|
334
|
+
type: "pkce",
|
|
335
|
+
clientId: credentials.clientId,
|
|
336
|
+
baseUrl: credentials.baseUrl,
|
|
337
|
+
scope: credentials.scope
|
|
338
|
+
};
|
|
338
339
|
}
|
|
339
|
-
|
|
340
|
+
return void 0;
|
|
341
|
+
}
|
|
340
342
|
var loginPlugin = ({ context }) => {
|
|
341
343
|
const loginWithTelemetry = async (options) => {
|
|
342
344
|
const startTime = Date.now();
|
|
@@ -345,17 +347,21 @@ var loginPlugin = ({ context }) => {
|
|
|
345
347
|
let accountId = null;
|
|
346
348
|
let customUserId = null;
|
|
347
349
|
try {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
350
|
+
const timeoutSeconds = options.timeout ? parseInt(options.timeout, 10) : 300;
|
|
351
|
+
if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
352
|
+
throw new Error("Timeout must be a positive number");
|
|
353
|
+
}
|
|
354
|
+
const resolvedCredentials = await context.resolveCredentials();
|
|
355
|
+
const pkceCredentials = toPkceCredentials(resolvedCredentials);
|
|
356
|
+
await login_default({
|
|
357
|
+
timeoutMs: timeoutSeconds * 1e3,
|
|
358
|
+
credentials: pkceCredentials
|
|
353
359
|
});
|
|
360
|
+
const user = await getLoggedInUser();
|
|
361
|
+
accountId = user.accountId;
|
|
362
|
+
customUserId = user.customUserId;
|
|
363
|
+
console.log(`\u2705 Successfully logged in as ${user.email}`);
|
|
354
364
|
success = true;
|
|
355
|
-
try {
|
|
356
|
-
({ accountId, customUserId } = await getLoggedInUser());
|
|
357
|
-
} catch {
|
|
358
|
-
}
|
|
359
365
|
} catch (error) {
|
|
360
366
|
success = false;
|
|
361
367
|
errorMessage = error instanceof Error ? error.message : "Login failed";
|
package/dist/package.json
CHANGED
package/dist/src/cli.js
CHANGED
|
@@ -12,29 +12,61 @@ program
|
|
|
12
12
|
.version(packageJson.version, "-v, --version", "display version number")
|
|
13
13
|
.option("--debug", "Enable debug logging")
|
|
14
14
|
.option("--base-url <url>", "Base URL for Zapier API endpoints")
|
|
15
|
-
.option("--
|
|
16
|
-
.option("--
|
|
15
|
+
.option("--credentials <token>", "Authentication token")
|
|
16
|
+
.option("--credentials-client-id <id>", "OAuth client ID for authentication")
|
|
17
|
+
.option("--credentials-client-secret <secret>", "OAuth client secret for authentication")
|
|
18
|
+
.option("--credentials-base-url <url>", "Base URL for authentication endpoints")
|
|
17
19
|
.option("--tracking-base-url <url>", "Base URL for Zapier tracking endpoints");
|
|
18
20
|
// Check for debug flag early (support both flag and env var)
|
|
19
21
|
const isDebugMode = process.env.DEBUG === "true" || process.argv.includes("--debug");
|
|
20
|
-
//
|
|
22
|
+
// Helper to get flag value from argv
|
|
23
|
+
function getFlagValue(flagName) {
|
|
24
|
+
const index = process.argv.indexOf(flagName);
|
|
25
|
+
return index !== -1 ? process.argv[index + 1] : undefined;
|
|
26
|
+
}
|
|
27
|
+
// Extract options from process.argv for early SDK creation
|
|
21
28
|
// We need to create the SDK before parsing to generate commands from schemas
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
const baseUrl = getFlagValue("--base-url");
|
|
30
|
+
const credentialsToken = getFlagValue("--credentials");
|
|
31
|
+
const credentialsClientId = getFlagValue("--credentials-client-id");
|
|
32
|
+
const credentialsClientSecret = getFlagValue("--credentials-client-secret");
|
|
33
|
+
const credentialsBaseUrl = getFlagValue("--credentials-base-url");
|
|
34
|
+
const trackingBaseUrl = getFlagValue("--tracking-base-url");
|
|
35
|
+
// Build credentials object from flags
|
|
36
|
+
function buildCredentialsFromFlags() {
|
|
37
|
+
// If a direct token is provided, use it
|
|
38
|
+
if (credentialsToken) {
|
|
39
|
+
return credentialsToken;
|
|
40
|
+
}
|
|
41
|
+
// If client ID is provided, build a credentials object
|
|
42
|
+
if (credentialsClientId) {
|
|
43
|
+
if (credentialsClientSecret) {
|
|
44
|
+
// Client credentials flow
|
|
45
|
+
return {
|
|
46
|
+
type: "client_credentials",
|
|
47
|
+
clientId: credentialsClientId,
|
|
48
|
+
clientSecret: credentialsClientSecret,
|
|
49
|
+
baseUrl: credentialsBaseUrl,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// PKCE flow (no secret)
|
|
54
|
+
return {
|
|
55
|
+
type: "pkce",
|
|
56
|
+
clientId: credentialsClientId,
|
|
57
|
+
baseUrl: credentialsBaseUrl,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// No credentials from flags - will fall back to env vars or stored login
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
const credentials = buildCredentialsFromFlags();
|
|
32
65
|
// Create CLI SDK instance with all plugins and URL options
|
|
33
66
|
const sdk = createZapierCliSdk({
|
|
34
67
|
debug: isDebugMode,
|
|
68
|
+
credentials,
|
|
35
69
|
baseUrl,
|
|
36
|
-
authBaseUrl,
|
|
37
|
-
authClientId,
|
|
38
70
|
trackingBaseUrl,
|
|
39
71
|
});
|
|
40
72
|
// Auth commands now handled by plugins
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Plugin } from "@zapier/zapier-sdk";
|
|
1
|
+
import type { Plugin, ResolvedCredentials } from "@zapier/zapier-sdk";
|
|
2
2
|
import type { EventEmissionContext } from "@zapier/zapier-sdk";
|
|
3
3
|
import { LoginSchema, type LoginOptions } from "./schemas";
|
|
4
4
|
interface CliContext {
|
|
@@ -6,6 +6,7 @@ interface CliContext {
|
|
|
6
6
|
selected_api?: string | null;
|
|
7
7
|
app_id?: number | null;
|
|
8
8
|
app_version_id?: number | null;
|
|
9
|
+
resolveCredentials: () => Promise<ResolvedCredentials | undefined>;
|
|
9
10
|
}
|
|
10
11
|
interface LoginPluginProvides {
|
|
11
12
|
login: (options: LoginOptions) => Promise<void>;
|
|
@@ -1,26 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isCredentialsObject } from "@zapier/zapier-sdk";
|
|
2
2
|
import login from "../../utils/auth/login";
|
|
3
|
-
import { getLoggedInUser } from "@zapier/zapier-sdk-cli-login";
|
|
3
|
+
import { getLoggedInUser, } from "@zapier/zapier-sdk-cli-login";
|
|
4
4
|
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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
function toPkceCredentials(credentials) {
|
|
9
|
+
if (credentials &&
|
|
10
|
+
isCredentialsObject(credentials) &&
|
|
11
|
+
!("clientSecret" in credentials)) {
|
|
12
|
+
return {
|
|
13
|
+
type: "pkce",
|
|
14
|
+
clientId: credentials.clientId,
|
|
15
|
+
baseUrl: credentials.baseUrl,
|
|
16
|
+
scope: credentials.scope,
|
|
17
|
+
};
|
|
14
18
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
baseUrl: options.baseUrl,
|
|
18
|
-
authBaseUrl: options.authBaseUrl,
|
|
19
|
-
authClientId: options.authClientId,
|
|
20
|
-
});
|
|
21
|
-
const user = await getLoggedInUser();
|
|
22
|
-
console.log(`✅ Successfully logged in as ${user.email}`);
|
|
23
|
-
});
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
24
21
|
export const loginPlugin = ({ context }) => {
|
|
25
22
|
// Wrap the login function to emit telemetry events
|
|
26
23
|
const loginWithTelemetry = async (options) => {
|
|
@@ -30,20 +27,25 @@ export const loginPlugin = ({ context }) => {
|
|
|
30
27
|
let accountId = null;
|
|
31
28
|
let customUserId = null;
|
|
32
29
|
try {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
const timeoutSeconds = options.timeout
|
|
31
|
+
? parseInt(options.timeout, 10)
|
|
32
|
+
: 300;
|
|
33
|
+
if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
34
|
+
throw new Error("Timeout must be a positive number");
|
|
35
|
+
}
|
|
36
|
+
// Resolve credentials from options and env vars
|
|
37
|
+
const resolvedCredentials = await context.resolveCredentials();
|
|
38
|
+
const pkceCredentials = toPkceCredentials(resolvedCredentials);
|
|
39
|
+
await login({
|
|
40
|
+
timeoutMs: timeoutSeconds * 1000,
|
|
41
|
+
credentials: pkceCredentials,
|
|
38
42
|
});
|
|
43
|
+
// Get user info after successful login
|
|
44
|
+
const user = await getLoggedInUser();
|
|
45
|
+
accountId = user.accountId;
|
|
46
|
+
customUserId = user.customUserId;
|
|
47
|
+
console.log(`✅ Successfully logged in as ${user.email}`);
|
|
39
48
|
success = true;
|
|
40
|
-
// Extract user IDs after successful login
|
|
41
|
-
try {
|
|
42
|
-
({ accountId, customUserId } = await getLoggedInUser());
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
// If we can't get user info, continue without it
|
|
46
|
-
}
|
|
47
49
|
}
|
|
48
50
|
catch (error) {
|
|
49
51
|
success = false;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
+
import { type PkceCredentials } from "@zapier/zapier-sdk-cli-login";
|
|
1
2
|
interface LoginOptions {
|
|
2
3
|
timeoutMs?: number;
|
|
3
|
-
|
|
4
|
-
authBaseUrl?: string;
|
|
5
|
-
authClientId?: string;
|
|
4
|
+
credentials?: PkceCredentials;
|
|
6
5
|
}
|
|
7
|
-
declare const login: ({ timeoutMs,
|
|
6
|
+
declare const login: ({ timeoutMs, credentials, }: LoginOptions) => Promise<string>;
|
|
8
7
|
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, 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,
|
|
10
|
+
import { updateLogin, logout, getPkceLoginConfig, } from "@zapier/zapier-sdk-cli-login";
|
|
11
11
|
import { ZapierCliUserCancellationError } from "../errors";
|
|
12
12
|
const findAvailablePort = () => {
|
|
13
13
|
return new Promise((resolve, reject) => {
|
|
@@ -46,10 +46,18 @@ const generateRandomString = () => {
|
|
|
46
46
|
crypto.getRandomValues(array);
|
|
47
47
|
return Array.from(array, (dec) => ("0" + dec.toString(16)).substring(-2)).join("");
|
|
48
48
|
};
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
// Ensure offline_access is included in scope for PKCE (needed for refresh tokens)
|
|
50
|
+
function ensureOfflineAccess(scope) {
|
|
51
|
+
if (scope.includes("offline_access")) {
|
|
52
|
+
return scope;
|
|
53
|
+
}
|
|
54
|
+
return `${scope} offline_access`;
|
|
55
|
+
}
|
|
56
|
+
const login = async ({ timeoutMs = LOGIN_TIMEOUT_MS, credentials, }) => {
|
|
57
|
+
const { clientId, tokenUrl, authorizeUrl } = getPkceLoginConfig({
|
|
58
|
+
credentials,
|
|
59
|
+
});
|
|
60
|
+
const scope = ensureOfflineAccess(credentials?.scope || "internal credentials");
|
|
53
61
|
// Force logout
|
|
54
62
|
logout();
|
|
55
63
|
// Find an available port
|
|
@@ -82,9 +90,9 @@ const login = async ({ timeoutMs = LOGIN_TIMEOUT_MS, baseUrl, authBaseUrl, authC
|
|
|
82
90
|
const { code_verifier: codeVerifier, code_challenge: codeChallenge } = await pkceChallenge();
|
|
83
91
|
const authUrl = `${authorizeUrl}?${new URLSearchParams({
|
|
84
92
|
response_type: "code",
|
|
85
|
-
client_id:
|
|
93
|
+
client_id: clientId,
|
|
86
94
|
redirect_uri: redirectUri,
|
|
87
|
-
scope
|
|
95
|
+
scope,
|
|
88
96
|
state: generateRandomString(),
|
|
89
97
|
code_challenge: codeChallenge,
|
|
90
98
|
code_challenge_method: "S256",
|
|
@@ -131,7 +139,7 @@ const login = async ({ timeoutMs = LOGIN_TIMEOUT_MS, baseUrl, authBaseUrl, authC
|
|
|
131
139
|
grant_type: "authorization_code",
|
|
132
140
|
code: await promisedCode,
|
|
133
141
|
redirect_uri: redirectUri,
|
|
134
|
-
client_id:
|
|
142
|
+
client_id: clientId,
|
|
135
143
|
code_verifier: codeVerifier,
|
|
136
144
|
}, {
|
|
137
145
|
headers: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Import shared OAuth constants from login package
|
|
2
|
-
export {
|
|
2
|
+
export { 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
|