@zapier/zapier-sdk-cli 0.46.1 → 0.48.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 +20 -0
- package/README.md +1 -1
- package/dist/cli.cjs +569 -84
- package/dist/cli.mjs +569 -84
- package/dist/experimental.cjs +561 -86
- package/dist/experimental.mjs +560 -85
- package/dist/index.cjs +562 -87
- package/dist/index.mjs +561 -86
- package/dist/login.cjs +94 -25
- package/dist/login.d.mts +29 -2
- package/dist/login.d.ts +29 -2
- package/dist/login.mjs +90 -25
- package/dist/package.json +1 -1
- package/dist/src/login/config.d.ts +4 -0
- package/dist/src/login/config.js +21 -0
- package/dist/src/login/credentials-revoke.d.ts +13 -0
- package/dist/src/login/credentials-revoke.js +48 -0
- package/dist/src/login/credentials-store.d.ts +33 -0
- package/dist/src/login/credentials-store.js +142 -0
- package/dist/src/login/index.d.ts +5 -2
- package/dist/src/login/index.js +11 -27
- package/dist/src/login/legacy-jwt.d.ts +4 -0
- package/dist/src/login/legacy-jwt.js +18 -0
- package/dist/src/plugins/auth/credentials-base-url.d.ts +11 -0
- package/dist/src/plugins/auth/credentials-base-url.js +24 -0
- package/dist/src/plugins/login/index.d.ts +6 -1
- package/dist/src/plugins/login/index.js +154 -14
- package/dist/src/plugins/logout/index.d.ts +14 -0
- package/dist/src/plugins/logout/index.js +35 -3
- package/dist/src/utils/auth/client-credentials.d.ts +16 -0
- package/dist/src/utils/auth/client-credentials.js +53 -0
- package/dist/src/utils/auth/oauth-flow.d.ts +12 -0
- package/dist/src/utils/auth/{login.js → oauth-flow.js} +36 -58
- package/dist/src/utils/parameter-resolver.js +13 -0
- package/dist/src/utils/retry.d.ts +5 -0
- package/dist/src/utils/retry.js +21 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/dist/src/utils/auth/login.d.ts +0 -7
package/dist/cli.mjs
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command, CommanderError, Option } from 'commander';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { definePlugin, createPluginMethod,
|
|
4
|
+
import { definePlugin, createPluginMethod, getOrCreateApiClient, OutputPropertySchema, ZapierBundleError, DEFAULT_CONFIG_PATH, ZapierValidationError, ZapierUnknownError, ZapierReleaseTriggerMessageSignal, injectCliLogin, BaseSdkOptionsSchema, isCredentialsObject, invalidateCachedToken, buildApplicationLifecycleEvent, batch, toSnakeCase, ZapierAbortDrainSignal, createZapierSdk as createZapierSdk$1, ZapierError, isPositional, runWithTelemetryContext, buildCapabilityMessage, formatErrorMessage, getOsInfo, getPlatformVersions, getCiPlatform, isCi, getReleaseId, getCurrentTimestamp, generateEventId } from '@zapier/zapier-sdk';
|
|
5
5
|
import inquirer from 'inquirer';
|
|
6
6
|
import chalk7 from 'chalk';
|
|
7
7
|
import ora from 'ora';
|
|
8
8
|
import util from 'util';
|
|
9
9
|
import wrapAnsi from 'wrap-ansi';
|
|
10
|
+
import * as jwt from 'jsonwebtoken';
|
|
11
|
+
import { deletePassword, getKeyring, getPassword, setPassword } from 'cross-keychain';
|
|
10
12
|
import Conf from 'conf';
|
|
11
13
|
import * as fs from 'fs';
|
|
12
14
|
import { promises, createWriteStream, existsSync, readdirSync, rmSync, mkdirSync, writeFileSync, copyFileSync, readFileSync } from 'fs';
|
|
13
|
-
import * as jwt from 'jsonwebtoken';
|
|
14
|
-
import { getPassword, getKeyring, setPassword, deletePassword } from 'cross-keychain';
|
|
15
15
|
import crypto, { createHash } from 'crypto';
|
|
16
16
|
import * as path from 'path';
|
|
17
17
|
import { resolve, join, dirname, basename, relative, extname } from 'path';
|
|
18
18
|
import * as lockfile from 'proper-lockfile';
|
|
19
|
+
import { hostname } from 'os';
|
|
19
20
|
import open from 'open';
|
|
20
21
|
import express from 'express';
|
|
21
22
|
import pkceChallenge from 'pkce-challenge';
|
|
@@ -898,11 +899,18 @@ Optional fields${pathContext}:`));
|
|
|
898
899
|
const choices = [...initialChoices];
|
|
899
900
|
let nextCursor = initialCursor;
|
|
900
901
|
const LOAD_MORE_SENTINEL = Symbol("LOAD_MORE");
|
|
902
|
+
const CUSTOM_VALUE_SENTINEL = Symbol("CUSTOM_VALUE");
|
|
901
903
|
while (true) {
|
|
902
904
|
const promptChoices = choices.map((choice) => ({
|
|
903
905
|
name: choice.label,
|
|
904
906
|
value: choice.value
|
|
905
907
|
}));
|
|
908
|
+
if (!fieldMeta.isMultiSelect) {
|
|
909
|
+
promptChoices.unshift({
|
|
910
|
+
name: chalk7.dim("(Enter custom value)"),
|
|
911
|
+
value: CUSTOM_VALUE_SENTINEL
|
|
912
|
+
});
|
|
913
|
+
}
|
|
906
914
|
if (nextCursor) {
|
|
907
915
|
promptChoices.push({
|
|
908
916
|
name: chalk7.dim("(Load more...)"),
|
|
@@ -928,6 +936,9 @@ Optional fields${pathContext}:`));
|
|
|
928
936
|
};
|
|
929
937
|
const answer = await inquirer.prompt([promptConfig]);
|
|
930
938
|
let selectedValue = answer[fieldMeta.key];
|
|
939
|
+
if (selectedValue === CUSTOM_VALUE_SENTINEL) {
|
|
940
|
+
return await this.promptFreeForm(fieldMeta);
|
|
941
|
+
}
|
|
931
942
|
const wantsMore = fieldMeta.isMultiSelect ? Array.isArray(selectedValue) && selectedValue.includes(LOAD_MORE_SENTINEL) : selectedValue === LOAD_MORE_SENTINEL;
|
|
932
943
|
if (wantsMore && nextCursor && context) {
|
|
933
944
|
if (fieldMeta.isMultiSelect && Array.isArray(selectedValue)) {
|
|
@@ -1138,7 +1149,7 @@ var SHARED_COMMAND_CLI_OPTIONS = [
|
|
|
1138
1149
|
|
|
1139
1150
|
// package.json
|
|
1140
1151
|
var package_default = {
|
|
1141
|
-
version: "0.
|
|
1152
|
+
version: "0.48.0"};
|
|
1142
1153
|
|
|
1143
1154
|
// src/telemetry/builders.ts
|
|
1144
1155
|
function createCliBaseEvent(context = {}) {
|
|
@@ -2290,8 +2301,11 @@ function convertValue(value, type, elementType) {
|
|
|
2290
2301
|
var login_exports = {};
|
|
2291
2302
|
__export(login_exports, {
|
|
2292
2303
|
AUTH_MODE_HEADER: () => AUTH_MODE_HEADER,
|
|
2304
|
+
DEFAULT_AUTH_BASE_URL: () => DEFAULT_AUTH_BASE_URL,
|
|
2293
2305
|
ZapierAuthenticationError: () => ZapierAuthenticationError,
|
|
2306
|
+
clearTokensFromKeychain: () => clearTokensFromKeychain,
|
|
2294
2307
|
createCache: () => createCache,
|
|
2308
|
+
getActiveCredentials: () => getActiveCredentials,
|
|
2295
2309
|
getAuthAuthorizeUrl: () => getAuthAuthorizeUrl,
|
|
2296
2310
|
getAuthTokenUrl: () => getAuthTokenUrl,
|
|
2297
2311
|
getConfig: () => getConfig,
|
|
@@ -2299,6 +2313,7 @@ __export(login_exports, {
|
|
|
2299
2313
|
getLoggedInUser: () => getLoggedInUser,
|
|
2300
2314
|
getLoginStorageMode: () => getLoginStorageMode,
|
|
2301
2315
|
getPkceLoginConfig: () => getPkceLoginConfig,
|
|
2316
|
+
getStoredClientCredentials: () => getStoredClientCredentials,
|
|
2302
2317
|
getToken: () => getToken,
|
|
2303
2318
|
logout: () => logout,
|
|
2304
2319
|
unloadConfig: () => unloadConfig,
|
|
@@ -2379,6 +2394,38 @@ async function clearTokensFromKeychain({
|
|
|
2379
2394
|
}
|
|
2380
2395
|
});
|
|
2381
2396
|
}
|
|
2397
|
+
var DEFAULT_AUTH_BASE_URL = "https://zapier.com";
|
|
2398
|
+
var config = null;
|
|
2399
|
+
function getConfig() {
|
|
2400
|
+
if (!config) {
|
|
2401
|
+
config = new Conf({ projectName: "zapier-sdk-cli" });
|
|
2402
|
+
if (!config.has("login_storage_mode")) {
|
|
2403
|
+
config.set(
|
|
2404
|
+
"login_storage_mode",
|
|
2405
|
+
existsSync(config.path) ? "config" : "keychain"
|
|
2406
|
+
);
|
|
2407
|
+
}
|
|
2408
|
+
}
|
|
2409
|
+
return config;
|
|
2410
|
+
}
|
|
2411
|
+
function resetConfig() {
|
|
2412
|
+
config = null;
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
// src/login/legacy-jwt.ts
|
|
2416
|
+
function clearLegacyJwtConfigKeys(config2) {
|
|
2417
|
+
config2.delete("login_jwt");
|
|
2418
|
+
config2.delete("login_refresh_token");
|
|
2419
|
+
config2.delete("login_expires_at");
|
|
2420
|
+
}
|
|
2421
|
+
async function clearLegacyJwtState() {
|
|
2422
|
+
clearLegacyJwtConfigKeys(getConfig());
|
|
2423
|
+
await clearTokensFromKeychain();
|
|
2424
|
+
}
|
|
2425
|
+
function hasLegacyJwtConfig() {
|
|
2426
|
+
const cfg = getConfig();
|
|
2427
|
+
return typeof cfg.get("login_jwt") === "string" || typeof cfg.get("login_refresh_token") === "string" || typeof cfg.get("login_expires_at") === "number";
|
|
2428
|
+
}
|
|
2382
2429
|
var SERVICE2 = "zapier-sdk-cache";
|
|
2383
2430
|
var CONFIG_KEY = "cache";
|
|
2384
2431
|
var LOCK_UPDATE_MS = 5e3;
|
|
@@ -2506,6 +2553,163 @@ function createCache() {
|
|
|
2506
2553
|
}
|
|
2507
2554
|
};
|
|
2508
2555
|
}
|
|
2556
|
+
var SERVICE3 = "zapier-sdk-cli";
|
|
2557
|
+
var CREDENTIALS_KEY = "credentials";
|
|
2558
|
+
var REGISTRY_KEY = "credentialsRegistry";
|
|
2559
|
+
var CredentialsEntrySchema = z.object({
|
|
2560
|
+
name: z.string(),
|
|
2561
|
+
clientId: z.string(),
|
|
2562
|
+
createdAt: z.number(),
|
|
2563
|
+
scopes: z.array(z.string()),
|
|
2564
|
+
baseUrl: z.string()
|
|
2565
|
+
});
|
|
2566
|
+
function normalizeBaseUrl(baseUrl2) {
|
|
2567
|
+
return baseUrl2 ?? DEFAULT_AUTH_BASE_URL;
|
|
2568
|
+
}
|
|
2569
|
+
function keychainAccount2(key) {
|
|
2570
|
+
return createHash("sha256").update(key).digest("hex");
|
|
2571
|
+
}
|
|
2572
|
+
function buildKeychainKey(clientId, scopes, baseUrl2) {
|
|
2573
|
+
const sortedScopes = [...scopes].sort().join(",");
|
|
2574
|
+
return `zapier-sdk/client-credentials-secret/${clientId}:${sortedScopes}:${baseUrl2}`;
|
|
2575
|
+
}
|
|
2576
|
+
function findEntry(registry, name, baseUrl2) {
|
|
2577
|
+
return registry.find((e) => e.name === name && e.baseUrl === baseUrl2);
|
|
2578
|
+
}
|
|
2579
|
+
function readRegistry() {
|
|
2580
|
+
const stored = getConfig().get(REGISTRY_KEY);
|
|
2581
|
+
if (!Array.isArray(stored)) return [];
|
|
2582
|
+
return stored.flatMap((entry) => {
|
|
2583
|
+
const result = CredentialsEntrySchema.safeParse(entry);
|
|
2584
|
+
return result.success ? [result.data] : [];
|
|
2585
|
+
});
|
|
2586
|
+
}
|
|
2587
|
+
function getActiveCredentials(options) {
|
|
2588
|
+
const name = getConfig().get(CREDENTIALS_KEY);
|
|
2589
|
+
if (!name) return void 0;
|
|
2590
|
+
return findEntry(readRegistry(), name, normalizeBaseUrl(options?.baseUrl));
|
|
2591
|
+
}
|
|
2592
|
+
async function storeClientCredentials({
|
|
2593
|
+
name,
|
|
2594
|
+
clientId,
|
|
2595
|
+
clientSecret,
|
|
2596
|
+
scopes,
|
|
2597
|
+
baseUrl: baseUrl2
|
|
2598
|
+
}) {
|
|
2599
|
+
if (!name || typeof name !== "string") {
|
|
2600
|
+
throw new Error("storeClientCredentials: name is required");
|
|
2601
|
+
}
|
|
2602
|
+
if (!clientId || typeof clientId !== "string") {
|
|
2603
|
+
throw new Error("storeClientCredentials: clientId is required");
|
|
2604
|
+
}
|
|
2605
|
+
if (!clientSecret || typeof clientSecret !== "string") {
|
|
2606
|
+
throw new Error("storeClientCredentials: clientSecret is required");
|
|
2607
|
+
}
|
|
2608
|
+
if (!Array.isArray(scopes) || scopes.length === 0) {
|
|
2609
|
+
throw new Error("storeClientCredentials: scopes must be a non-empty array");
|
|
2610
|
+
}
|
|
2611
|
+
const sortedScopes = [...scopes].sort();
|
|
2612
|
+
const resolvedBaseUrl = normalizeBaseUrl(baseUrl2);
|
|
2613
|
+
const keychainKey = buildKeychainKey(clientId, sortedScopes, resolvedBaseUrl);
|
|
2614
|
+
const existingEntry = findEntry(readRegistry(), name, resolvedBaseUrl);
|
|
2615
|
+
const existingKeychainKey = existingEntry ? buildKeychainKey(
|
|
2616
|
+
existingEntry.clientId,
|
|
2617
|
+
existingEntry.scopes,
|
|
2618
|
+
existingEntry.baseUrl
|
|
2619
|
+
) : void 0;
|
|
2620
|
+
await enqueue(async () => {
|
|
2621
|
+
await getBackendInfo();
|
|
2622
|
+
await setPassword(SERVICE3, keychainAccount2(keychainKey), clientSecret);
|
|
2623
|
+
});
|
|
2624
|
+
const entry = {
|
|
2625
|
+
name,
|
|
2626
|
+
clientId,
|
|
2627
|
+
createdAt: Date.now(),
|
|
2628
|
+
scopes: sortedScopes,
|
|
2629
|
+
baseUrl: resolvedBaseUrl
|
|
2630
|
+
};
|
|
2631
|
+
const registry = readRegistry().filter(
|
|
2632
|
+
(e) => !(e.name === name && e.baseUrl === resolvedBaseUrl)
|
|
2633
|
+
);
|
|
2634
|
+
registry.push(entry);
|
|
2635
|
+
const cfg = getConfig();
|
|
2636
|
+
cfg.set(REGISTRY_KEY, registry);
|
|
2637
|
+
cfg.set(CREDENTIALS_KEY, name);
|
|
2638
|
+
if (existingEntry && existingKeychainKey !== keychainKey) {
|
|
2639
|
+
await deleteKeychainSecret(existingEntry);
|
|
2640
|
+
}
|
|
2641
|
+
}
|
|
2642
|
+
function credentialsNameExists({
|
|
2643
|
+
name,
|
|
2644
|
+
baseUrl: baseUrl2
|
|
2645
|
+
}) {
|
|
2646
|
+
return !!findEntry(readRegistry(), name, normalizeBaseUrl(baseUrl2));
|
|
2647
|
+
}
|
|
2648
|
+
async function getStoredClientCredentials(options) {
|
|
2649
|
+
const entry = options?.name ? findEntry(readRegistry(), options.name, normalizeBaseUrl(options.baseUrl)) : getActiveCredentials(options);
|
|
2650
|
+
if (!entry) return void 0;
|
|
2651
|
+
const keychainKey = buildKeychainKey(
|
|
2652
|
+
entry.clientId,
|
|
2653
|
+
entry.scopes,
|
|
2654
|
+
entry.baseUrl
|
|
2655
|
+
);
|
|
2656
|
+
const clientSecret = await enqueue(async () => {
|
|
2657
|
+
await getBackendInfo();
|
|
2658
|
+
return getPassword(SERVICE3, keychainAccount2(keychainKey));
|
|
2659
|
+
});
|
|
2660
|
+
if (!clientSecret) return void 0;
|
|
2661
|
+
return {
|
|
2662
|
+
type: "client_credentials",
|
|
2663
|
+
clientId: entry.clientId,
|
|
2664
|
+
clientSecret,
|
|
2665
|
+
baseUrl: entry.baseUrl,
|
|
2666
|
+
scope: [...entry.scopes].sort().join(" ")
|
|
2667
|
+
};
|
|
2668
|
+
}
|
|
2669
|
+
function deleteRegistryEntry(registry, name, baseUrl2) {
|
|
2670
|
+
const idx = registry.findIndex(
|
|
2671
|
+
(e) => e.name === name && e.baseUrl === baseUrl2
|
|
2672
|
+
);
|
|
2673
|
+
if (idx === -1) return void 0;
|
|
2674
|
+
const [removed] = registry.splice(idx, 1);
|
|
2675
|
+
return removed;
|
|
2676
|
+
}
|
|
2677
|
+
function unsetMatchingCredentialsKey(cfg, name) {
|
|
2678
|
+
const activeName = cfg.get(CREDENTIALS_KEY);
|
|
2679
|
+
if (activeName === name && !readRegistry().some((e) => e.name === name)) {
|
|
2680
|
+
cfg.delete(CREDENTIALS_KEY);
|
|
2681
|
+
}
|
|
2682
|
+
}
|
|
2683
|
+
async function deleteKeychainSecret(entry) {
|
|
2684
|
+
const keychainKey = buildKeychainKey(
|
|
2685
|
+
entry.clientId,
|
|
2686
|
+
entry.scopes,
|
|
2687
|
+
entry.baseUrl
|
|
2688
|
+
);
|
|
2689
|
+
try {
|
|
2690
|
+
await enqueue(async () => {
|
|
2691
|
+
await getBackendInfo();
|
|
2692
|
+
await deletePassword(SERVICE3, keychainAccount2(keychainKey));
|
|
2693
|
+
});
|
|
2694
|
+
} catch {
|
|
2695
|
+
}
|
|
2696
|
+
}
|
|
2697
|
+
async function deleteStoredClientCredentials({
|
|
2698
|
+
name,
|
|
2699
|
+
baseUrl: baseUrl2
|
|
2700
|
+
}) {
|
|
2701
|
+
const registry = readRegistry();
|
|
2702
|
+
const removed = deleteRegistryEntry(
|
|
2703
|
+
registry,
|
|
2704
|
+
name,
|
|
2705
|
+
normalizeBaseUrl(baseUrl2)
|
|
2706
|
+
);
|
|
2707
|
+
if (!removed) return;
|
|
2708
|
+
const cfg = getConfig();
|
|
2709
|
+
cfg.set(REGISTRY_KEY, registry);
|
|
2710
|
+
unsetMatchingCredentialsKey(cfg, name);
|
|
2711
|
+
await deleteKeychainSecret(removed);
|
|
2712
|
+
}
|
|
2509
2713
|
|
|
2510
2714
|
// src/login/index.ts
|
|
2511
2715
|
var ZapierAuthenticationError = class extends Error {
|
|
@@ -2514,7 +2718,6 @@ var ZapierAuthenticationError = class extends Error {
|
|
|
2514
2718
|
this.name = "ZapierAuthenticationError";
|
|
2515
2719
|
}
|
|
2516
2720
|
};
|
|
2517
|
-
var config = null;
|
|
2518
2721
|
var DEFAULT_AUTH_CLIENT_ID = "grwWZD5hUWGvb4V8ODBuOtXer3h0DBEZ2HR8aay6";
|
|
2519
2722
|
var TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1e3;
|
|
2520
2723
|
function createDebugLog(enabled) {
|
|
@@ -2540,7 +2743,6 @@ function getAuthClientId(clientId) {
|
|
|
2540
2743
|
return clientId || DEFAULT_AUTH_CLIENT_ID;
|
|
2541
2744
|
}
|
|
2542
2745
|
var AUTH_MODE_HEADER = "X-Auth";
|
|
2543
|
-
var DEFAULT_AUTH_BASE_URL = "https://zapier.com";
|
|
2544
2746
|
function getAuthTokenUrl(options) {
|
|
2545
2747
|
const authBaseUrl = options?.baseUrl || DEFAULT_AUTH_BASE_URL;
|
|
2546
2748
|
return `${authBaseUrl}/oauth/token/`;
|
|
@@ -2550,29 +2752,16 @@ function getAuthAuthorizeUrl(options) {
|
|
|
2550
2752
|
return `${authBaseUrl}/oauth/authorize/`;
|
|
2551
2753
|
}
|
|
2552
2754
|
function getPkceLoginConfig(options) {
|
|
2755
|
+
const effectiveBaseUrl = options?.credentials?.baseUrl ?? options?.baseUrl;
|
|
2553
2756
|
return {
|
|
2554
2757
|
clientId: getAuthClientId(options?.credentials?.clientId),
|
|
2555
|
-
tokenUrl: getAuthTokenUrl({ baseUrl:
|
|
2556
|
-
authorizeUrl: getAuthAuthorizeUrl({
|
|
2557
|
-
baseUrl: options?.credentials?.baseUrl
|
|
2558
|
-
})
|
|
2758
|
+
tokenUrl: getAuthTokenUrl({ baseUrl: effectiveBaseUrl }),
|
|
2759
|
+
authorizeUrl: getAuthAuthorizeUrl({ baseUrl: effectiveBaseUrl })
|
|
2559
2760
|
};
|
|
2560
2761
|
}
|
|
2561
2762
|
var cachedLogin;
|
|
2562
|
-
function getConfig() {
|
|
2563
|
-
if (!config) {
|
|
2564
|
-
config = new Conf({ projectName: "zapier-sdk-cli" });
|
|
2565
|
-
if (!config.has("login_storage_mode")) {
|
|
2566
|
-
config.set(
|
|
2567
|
-
"login_storage_mode",
|
|
2568
|
-
existsSync(config.path) ? "config" : "keychain"
|
|
2569
|
-
);
|
|
2570
|
-
}
|
|
2571
|
-
}
|
|
2572
|
-
return config;
|
|
2573
|
-
}
|
|
2574
2763
|
function unloadConfig() {
|
|
2575
|
-
|
|
2764
|
+
resetConfig();
|
|
2576
2765
|
cachedLogin = void 0;
|
|
2577
2766
|
}
|
|
2578
2767
|
async function updateLogin(loginData, options = {}) {
|
|
@@ -2845,9 +3034,7 @@ async function logout(options = {}) {
|
|
|
2845
3034
|
await clearTokensFromKeychain();
|
|
2846
3035
|
const cfg = getConfig();
|
|
2847
3036
|
cfg.set("login_storage_mode", mode);
|
|
2848
|
-
cfg
|
|
2849
|
-
cfg.delete("login_jwt");
|
|
2850
|
-
cfg.delete("login_refresh_token");
|
|
3037
|
+
clearLegacyJwtConfigKeys(cfg);
|
|
2851
3038
|
onEvent?.({
|
|
2852
3039
|
type: "auth_logout",
|
|
2853
3040
|
payload: { message: "Logged out successfully", operation: "logout" },
|
|
@@ -2859,6 +3046,79 @@ function getConfigPath() {
|
|
|
2859
3046
|
return cfg.path;
|
|
2860
3047
|
}
|
|
2861
3048
|
|
|
3049
|
+
// src/utils/retry.ts
|
|
3050
|
+
function sleep(ms) {
|
|
3051
|
+
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
3052
|
+
}
|
|
3053
|
+
async function withRetry({
|
|
3054
|
+
action,
|
|
3055
|
+
attempts = 3,
|
|
3056
|
+
initialDelayMs = 100
|
|
3057
|
+
}) {
|
|
3058
|
+
if (attempts <= 0) {
|
|
3059
|
+
throw new Error("withRetry: attempts must be greater than 0");
|
|
3060
|
+
}
|
|
3061
|
+
let lastError;
|
|
3062
|
+
for (let i = 0; i < attempts; i++) {
|
|
3063
|
+
try {
|
|
3064
|
+
return await action();
|
|
3065
|
+
} catch (err) {
|
|
3066
|
+
lastError = err;
|
|
3067
|
+
if (i < attempts - 1) {
|
|
3068
|
+
await sleep(initialDelayMs * 2 ** i);
|
|
3069
|
+
}
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3072
|
+
throw lastError;
|
|
3073
|
+
}
|
|
3074
|
+
|
|
3075
|
+
// src/login/credentials-revoke.ts
|
|
3076
|
+
function emitAuthLogout(onEvent) {
|
|
3077
|
+
onEvent?.({
|
|
3078
|
+
type: "auth_logout",
|
|
3079
|
+
payload: { message: "Logged out successfully", operation: "logout" },
|
|
3080
|
+
timestamp: Date.now()
|
|
3081
|
+
});
|
|
3082
|
+
}
|
|
3083
|
+
function isNotFoundError(err) {
|
|
3084
|
+
return typeof err === "object" && err !== null && "statusCode" in err && err.statusCode === 404;
|
|
3085
|
+
}
|
|
3086
|
+
async function revokeCredentials({
|
|
3087
|
+
api: api2,
|
|
3088
|
+
credentials: credentials2,
|
|
3089
|
+
onEvent
|
|
3090
|
+
}) {
|
|
3091
|
+
await withRetry({
|
|
3092
|
+
action: async () => {
|
|
3093
|
+
try {
|
|
3094
|
+
await api2.delete(
|
|
3095
|
+
`/api/v0/client-credentials/${credentials2.clientId}`,
|
|
3096
|
+
void 0,
|
|
3097
|
+
{ authRequired: true, requiredScopes: ["credentials"] }
|
|
3098
|
+
);
|
|
3099
|
+
} catch (err) {
|
|
3100
|
+
if (isNotFoundError(err)) return;
|
|
3101
|
+
throw err;
|
|
3102
|
+
}
|
|
3103
|
+
}
|
|
3104
|
+
});
|
|
3105
|
+
try {
|
|
3106
|
+
await deleteStoredClientCredentials({
|
|
3107
|
+
name: credentials2.name,
|
|
3108
|
+
baseUrl: credentials2.baseUrl
|
|
3109
|
+
});
|
|
3110
|
+
} catch (err) {
|
|
3111
|
+
console.warn("[revokeCredentials] Local store cleanup failed:", err);
|
|
3112
|
+
}
|
|
3113
|
+
await clearLegacyJwtState();
|
|
3114
|
+
await invalidateCachedToken({
|
|
3115
|
+
clientId: credentials2.clientId,
|
|
3116
|
+
scopes: credentials2.scopes,
|
|
3117
|
+
baseUrl: credentials2.baseUrl
|
|
3118
|
+
});
|
|
3119
|
+
emitAuthLogout(onEvent);
|
|
3120
|
+
}
|
|
3121
|
+
|
|
2862
3122
|
// src/utils/constants.ts
|
|
2863
3123
|
var LOGIN_PORTS = [49505, 50575, 52804, 55981, 61010, 63851];
|
|
2864
3124
|
var LOGIN_TIMEOUT_MS = 3e5;
|
|
@@ -2944,6 +3204,8 @@ var getCallablePromise = () => {
|
|
|
2944
3204
|
};
|
|
2945
3205
|
};
|
|
2946
3206
|
var getCallablePromise_default = getCallablePromise;
|
|
3207
|
+
|
|
3208
|
+
// src/utils/auth/oauth-flow.ts
|
|
2947
3209
|
var findAvailablePort = () => {
|
|
2948
3210
|
return new Promise((resolve4, reject) => {
|
|
2949
3211
|
let portIndex = 0;
|
|
@@ -2978,10 +3240,9 @@ var findAvailablePort = () => {
|
|
|
2978
3240
|
var generateRandomString = () => {
|
|
2979
3241
|
const array = new Uint32Array(28);
|
|
2980
3242
|
crypto.getRandomValues(array);
|
|
2981
|
-
return Array.from(
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
).join("");
|
|
3243
|
+
return Array.from(array, (dec) => ("0" + dec.toString(16)).slice(-2)).join(
|
|
3244
|
+
""
|
|
3245
|
+
);
|
|
2985
3246
|
};
|
|
2986
3247
|
function ensureOfflineAccess(scope) {
|
|
2987
3248
|
if (scope.includes("offline_access")) {
|
|
@@ -2989,17 +3250,18 @@ function ensureOfflineAccess(scope) {
|
|
|
2989
3250
|
}
|
|
2990
3251
|
return `${scope} offline_access`;
|
|
2991
3252
|
}
|
|
2992
|
-
|
|
3253
|
+
async function runOauthFlow({
|
|
2993
3254
|
timeoutMs = LOGIN_TIMEOUT_MS,
|
|
2994
|
-
|
|
2995
|
-
|
|
3255
|
+
pkceCredentials,
|
|
3256
|
+
baseUrl: baseUrl2
|
|
3257
|
+
}) {
|
|
2996
3258
|
const { clientId, tokenUrl, authorizeUrl } = getPkceLoginConfig({
|
|
2997
|
-
credentials:
|
|
3259
|
+
credentials: pkceCredentials,
|
|
3260
|
+
baseUrl: baseUrl2
|
|
2998
3261
|
});
|
|
2999
3262
|
const scope = ensureOfflineAccess(
|
|
3000
|
-
|
|
3263
|
+
pkceCredentials?.scope || "internal credentials"
|
|
3001
3264
|
);
|
|
3002
|
-
await logout();
|
|
3003
3265
|
const availablePort = await findAvailablePort();
|
|
3004
3266
|
const redirectUri = `http://localhost:${availablePort}/oauth`;
|
|
3005
3267
|
log_default.info(`Using port ${availablePort} for OAuth callback`);
|
|
@@ -3008,13 +3270,30 @@ var login = async ({
|
|
|
3008
3270
|
resolve: setCode,
|
|
3009
3271
|
reject: rejectCode
|
|
3010
3272
|
} = getCallablePromise_default();
|
|
3011
|
-
const
|
|
3012
|
-
|
|
3013
|
-
|
|
3273
|
+
const oauthState = generateRandomString();
|
|
3274
|
+
const expressApp = express();
|
|
3275
|
+
expressApp.get("/oauth", (req, res) => {
|
|
3014
3276
|
res.setHeader("Connection", "close");
|
|
3277
|
+
if (req.query.state !== oauthState) {
|
|
3278
|
+
rejectCode(new Error("OAuth state mismatch \u2014 possible CSRF"));
|
|
3279
|
+
res.status(400).end("Invalid state. You can close this tab.");
|
|
3280
|
+
return;
|
|
3281
|
+
}
|
|
3282
|
+
if (req.query.error) {
|
|
3283
|
+
const desc = req.query.error_description ?? req.query.error;
|
|
3284
|
+
rejectCode(new Error(`Authorization denied: ${desc}`));
|
|
3285
|
+
res.end("Authorization was denied. You can close this tab.");
|
|
3286
|
+
return;
|
|
3287
|
+
}
|
|
3288
|
+
if (!req.query.code) {
|
|
3289
|
+
rejectCode(new Error("No authorization code received"));
|
|
3290
|
+
res.end("No authorization code received. You can close this tab.");
|
|
3291
|
+
return;
|
|
3292
|
+
}
|
|
3293
|
+
setCode(String(req.query.code));
|
|
3015
3294
|
res.end("You can now close this tab and return to the CLI.");
|
|
3016
3295
|
});
|
|
3017
|
-
const server =
|
|
3296
|
+
const server = expressApp.listen(availablePort);
|
|
3018
3297
|
const connections = /* @__PURE__ */ new Set();
|
|
3019
3298
|
server.on("connection", (conn) => {
|
|
3020
3299
|
connections.add(conn);
|
|
@@ -3033,7 +3312,7 @@ var login = async ({
|
|
|
3033
3312
|
client_id: clientId,
|
|
3034
3313
|
redirect_uri: redirectUri,
|
|
3035
3314
|
scope,
|
|
3036
|
-
state:
|
|
3315
|
+
state: oauthState,
|
|
3037
3316
|
code_challenge: codeChallenge,
|
|
3038
3317
|
code_challenge_method: "S256"
|
|
3039
3318
|
}).toString()}`;
|
|
@@ -3092,36 +3371,79 @@ var login = async ({
|
|
|
3092
3371
|
}
|
|
3093
3372
|
}
|
|
3094
3373
|
);
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3374
|
+
log_default.info("Token exchange completed successfully");
|
|
3375
|
+
return {
|
|
3376
|
+
accessToken: data.access_token,
|
|
3377
|
+
refreshToken: data.refresh_token,
|
|
3378
|
+
expiresIn: data.expires_in
|
|
3379
|
+
};
|
|
3380
|
+
}
|
|
3381
|
+
|
|
3382
|
+
// src/utils/auth/client-credentials.ts
|
|
3383
|
+
var CREDENTIALS_SCOPES = ["external", "credentials"];
|
|
3384
|
+
async function createCredentialsOnServer(api2, name) {
|
|
3385
|
+
const response = await api2.post(
|
|
3386
|
+
"/api/v0/client-credentials",
|
|
3387
|
+
{ name, allowed_scopes: CREDENTIALS_SCOPES },
|
|
3388
|
+
{ authRequired: true, requiredScopes: ["credentials"] }
|
|
3389
|
+
);
|
|
3390
|
+
return {
|
|
3391
|
+
clientId: response.data.client_id,
|
|
3392
|
+
clientSecret: response.data.client_secret
|
|
3393
|
+
};
|
|
3394
|
+
}
|
|
3395
|
+
async function deleteCredentialsOnServer(api2, clientId) {
|
|
3396
|
+
await api2.delete(`/api/v0/client-credentials/${clientId}`, void 0, {
|
|
3397
|
+
authRequired: true,
|
|
3398
|
+
requiredScopes: ["credentials"]
|
|
3399
|
+
});
|
|
3400
|
+
}
|
|
3401
|
+
async function setupClientCredentials({
|
|
3402
|
+
api: api2,
|
|
3403
|
+
name,
|
|
3404
|
+
credentialsBaseUrl: credentialsBaseUrl2
|
|
3405
|
+
}) {
|
|
3406
|
+
const { clientId, clientSecret } = await createCredentialsOnServer(api2, name);
|
|
3109
3407
|
try {
|
|
3110
|
-
await
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3408
|
+
await withRetry({
|
|
3409
|
+
action: () => storeClientCredentials({
|
|
3410
|
+
name,
|
|
3411
|
+
clientId,
|
|
3412
|
+
clientSecret,
|
|
3413
|
+
scopes: [...CREDENTIALS_SCOPES],
|
|
3414
|
+
baseUrl: credentialsBaseUrl2
|
|
3415
|
+
})
|
|
3416
|
+
});
|
|
3417
|
+
} catch (storeErr) {
|
|
3418
|
+
try {
|
|
3419
|
+
await withRetry({
|
|
3420
|
+
action: () => deleteCredentialsOnServer(api2, clientId)
|
|
3421
|
+
});
|
|
3422
|
+
} catch {
|
|
3423
|
+
console.error(
|
|
3424
|
+
`Failed to roll back orphaned credential ${clientId}. Delete it manually with: zapier-sdk delete-client-credentials ${clientId}`
|
|
3115
3425
|
);
|
|
3116
|
-
await updateLogin(data, { storage: "config" });
|
|
3117
|
-
} else {
|
|
3118
|
-
throw err;
|
|
3119
3426
|
}
|
|
3427
|
+
throw storeErr;
|
|
3120
3428
|
}
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3429
|
+
return { clientId };
|
|
3430
|
+
}
|
|
3431
|
+
function getBaseUrlFromResolvedCredentials(credentials2) {
|
|
3432
|
+
if (credentials2 && isCredentialsObject(credentials2)) {
|
|
3433
|
+
return credentials2.baseUrl;
|
|
3434
|
+
}
|
|
3435
|
+
return void 0;
|
|
3436
|
+
}
|
|
3437
|
+
function getBaseUrlFromOptionsCredentials(credentials2) {
|
|
3438
|
+
if (credentials2 && typeof credentials2 === "object" && "baseUrl" in credentials2 && typeof credentials2.baseUrl === "string") {
|
|
3439
|
+
return credentials2.baseUrl;
|
|
3440
|
+
}
|
|
3441
|
+
return void 0;
|
|
3442
|
+
}
|
|
3443
|
+
async function resolveCredentialsBaseUrl(context) {
|
|
3444
|
+
const resolvedCredentials = "resolvedCredentials" in context ? context.resolvedCredentials : await context.resolveCredentials?.();
|
|
3445
|
+
return getBaseUrlFromResolvedCredentials(resolvedCredentials) ?? getBaseUrlFromOptionsCredentials(context.options?.credentials) ?? context.options?.baseUrl;
|
|
3446
|
+
}
|
|
3125
3447
|
var LoginSchema = z.object({
|
|
3126
3448
|
timeout: z.string().optional().describe("Login timeout in seconds (default: 300)")
|
|
3127
3449
|
}).describe("Log in to Zapier to access your account");
|
|
@@ -3138,6 +3460,105 @@ function toPkceCredentials(credentials2) {
|
|
|
3138
3460
|
}
|
|
3139
3461
|
return void 0;
|
|
3140
3462
|
}
|
|
3463
|
+
async function confirmRevokeAndRelogin(activeCredentials) {
|
|
3464
|
+
const { confirmed } = await inquirer.prompt([
|
|
3465
|
+
{
|
|
3466
|
+
type: "confirm",
|
|
3467
|
+
name: "confirmed",
|
|
3468
|
+
message: `You are already logged in as "${activeCredentials.name}".
|
|
3469
|
+
Logging out will delete these credentials and may interrupt other Zapier SDK or CLI sessions using them.
|
|
3470
|
+
Log out and log in again?`,
|
|
3471
|
+
default: false
|
|
3472
|
+
}
|
|
3473
|
+
]);
|
|
3474
|
+
if (!confirmed) {
|
|
3475
|
+
console.log("Login cancelled.");
|
|
3476
|
+
return false;
|
|
3477
|
+
}
|
|
3478
|
+
return true;
|
|
3479
|
+
}
|
|
3480
|
+
async function confirmJwtMigration() {
|
|
3481
|
+
const { confirmed } = await inquirer.prompt([
|
|
3482
|
+
{
|
|
3483
|
+
type: "confirm",
|
|
3484
|
+
name: "confirmed",
|
|
3485
|
+
message: "We're upgrading your login to client credentials for a simpler, more reliable experience and to support future security controls. Older Zapier SDK/CLI versions on this machine may stop working after the upgrade. Continue?",
|
|
3486
|
+
default: true
|
|
3487
|
+
}
|
|
3488
|
+
]);
|
|
3489
|
+
if (!confirmed) {
|
|
3490
|
+
console.log("Login cancelled.");
|
|
3491
|
+
return false;
|
|
3492
|
+
}
|
|
3493
|
+
return true;
|
|
3494
|
+
}
|
|
3495
|
+
async function confirmLocalLoginReset() {
|
|
3496
|
+
const { confirmed } = await inquirer.prompt([
|
|
3497
|
+
{
|
|
3498
|
+
type: "confirm",
|
|
3499
|
+
name: "confirmed",
|
|
3500
|
+
message: "Login cleanup failed. Reset local session state and continue?",
|
|
3501
|
+
default: false
|
|
3502
|
+
}
|
|
3503
|
+
]);
|
|
3504
|
+
if (!confirmed) {
|
|
3505
|
+
console.log("Login cancelled.");
|
|
3506
|
+
return false;
|
|
3507
|
+
}
|
|
3508
|
+
return true;
|
|
3509
|
+
}
|
|
3510
|
+
function parseTimeoutSeconds(timeout) {
|
|
3511
|
+
const timeoutSeconds = timeout ? parseInt(timeout, 10) : 300;
|
|
3512
|
+
if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
3513
|
+
throw new Error("Timeout must be a positive number");
|
|
3514
|
+
}
|
|
3515
|
+
return timeoutSeconds;
|
|
3516
|
+
}
|
|
3517
|
+
async function promptCredentialsName(email, baseUrl2) {
|
|
3518
|
+
const { credentialName } = await inquirer.prompt([
|
|
3519
|
+
{
|
|
3520
|
+
type: "input",
|
|
3521
|
+
name: "credentialName",
|
|
3522
|
+
message: "Enter a name to identify them:",
|
|
3523
|
+
default: `${email}@${hostname()}`,
|
|
3524
|
+
validate: (input) => {
|
|
3525
|
+
if (!input.trim()) return "Name cannot be empty";
|
|
3526
|
+
if (credentialsNameExists({ name: input.trim(), baseUrl: baseUrl2 })) {
|
|
3527
|
+
return `Credentials named "${input.trim()}" already exist. Please provide a different name.`;
|
|
3528
|
+
}
|
|
3529
|
+
return true;
|
|
3530
|
+
}
|
|
3531
|
+
}
|
|
3532
|
+
]);
|
|
3533
|
+
return credentialName;
|
|
3534
|
+
}
|
|
3535
|
+
function emitLoginSuccess({
|
|
3536
|
+
sdk,
|
|
3537
|
+
profile
|
|
3538
|
+
}) {
|
|
3539
|
+
sdk.context.eventEmission.emit(
|
|
3540
|
+
"platform.sdk.ApplicationLifecycleEvent",
|
|
3541
|
+
buildApplicationLifecycleEvent(
|
|
3542
|
+
{ lifecycle_event_type: "login_success" },
|
|
3543
|
+
{
|
|
3544
|
+
customuser_id: profile.user_id,
|
|
3545
|
+
account_id: profile.roles[0]?.account_id ?? null
|
|
3546
|
+
}
|
|
3547
|
+
)
|
|
3548
|
+
);
|
|
3549
|
+
}
|
|
3550
|
+
async function getProfile(api2) {
|
|
3551
|
+
return api2.get("/zapier/api/v4/profile/", {
|
|
3552
|
+
authRequired: true
|
|
3553
|
+
});
|
|
3554
|
+
}
|
|
3555
|
+
async function bestEffortClearLegacyJwtState() {
|
|
3556
|
+
try {
|
|
3557
|
+
await clearLegacyJwtState();
|
|
3558
|
+
} catch (err) {
|
|
3559
|
+
console.error("[login] Best-effort legacy JWT cleanup failed:", err);
|
|
3560
|
+
}
|
|
3561
|
+
}
|
|
3141
3562
|
var loginPlugin = definePlugin(
|
|
3142
3563
|
(sdk) => createPluginMethod(sdk, {
|
|
3143
3564
|
name: "login",
|
|
@@ -3145,25 +3566,61 @@ var loginPlugin = definePlugin(
|
|
|
3145
3566
|
inputSchema: LoginSchema,
|
|
3146
3567
|
supportsJsonOutput: false,
|
|
3147
3568
|
handler: async ({ sdk: sdk2, options }) => {
|
|
3148
|
-
const timeoutSeconds =
|
|
3149
|
-
if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
3150
|
-
throw new Error("Timeout must be a positive number");
|
|
3151
|
-
}
|
|
3569
|
+
const timeoutSeconds = parseTimeoutSeconds(options.timeout);
|
|
3152
3570
|
const resolvedCredentials = await sdk2.context.resolveCredentials();
|
|
3153
3571
|
const pkceCredentials = toPkceCredentials(resolvedCredentials);
|
|
3154
|
-
await
|
|
3572
|
+
const credentialsBaseUrl2 = await resolveCredentialsBaseUrl({
|
|
3573
|
+
...sdk2.context,
|
|
3574
|
+
resolvedCredentials
|
|
3575
|
+
});
|
|
3576
|
+
const activeCredentials = getActiveCredentials({
|
|
3577
|
+
baseUrl: credentialsBaseUrl2
|
|
3578
|
+
});
|
|
3579
|
+
if (activeCredentials) {
|
|
3580
|
+
if (!await confirmRevokeAndRelogin(activeCredentials)) return;
|
|
3581
|
+
try {
|
|
3582
|
+
await revokeCredentials({
|
|
3583
|
+
api: sdk2.context.api,
|
|
3584
|
+
credentials: activeCredentials
|
|
3585
|
+
});
|
|
3586
|
+
} catch {
|
|
3587
|
+
if (!await confirmLocalLoginReset()) return;
|
|
3588
|
+
await deleteStoredClientCredentials({
|
|
3589
|
+
name: activeCredentials.name,
|
|
3590
|
+
baseUrl: activeCredentials.baseUrl
|
|
3591
|
+
});
|
|
3592
|
+
}
|
|
3593
|
+
} else if (hasLegacyJwtConfig()) {
|
|
3594
|
+
if (!await confirmJwtMigration()) return;
|
|
3595
|
+
}
|
|
3596
|
+
const { accessToken } = await runOauthFlow({
|
|
3155
3597
|
timeoutMs: timeoutSeconds * 1e3,
|
|
3156
|
-
|
|
3598
|
+
pkceCredentials,
|
|
3599
|
+
baseUrl: credentialsBaseUrl2
|
|
3157
3600
|
});
|
|
3158
|
-
const
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3601
|
+
const scopedApi = getOrCreateApiClient({
|
|
3602
|
+
credentials: accessToken,
|
|
3603
|
+
baseUrl: credentialsBaseUrl2
|
|
3604
|
+
});
|
|
3605
|
+
const profile = await getProfile(scopedApi);
|
|
3606
|
+
console.log(`\u{1F464} Logged in as ${profile.email}`);
|
|
3607
|
+
console.log(
|
|
3608
|
+
"\nGenerating credentials so this machine can make authenticated requests on your behalf."
|
|
3609
|
+
);
|
|
3610
|
+
const credentialName = await promptCredentialsName(
|
|
3611
|
+
profile.email,
|
|
3612
|
+
credentialsBaseUrl2
|
|
3613
|
+
);
|
|
3614
|
+
await setupClientCredentials({
|
|
3615
|
+
api: scopedApi,
|
|
3616
|
+
name: credentialName,
|
|
3617
|
+
credentialsBaseUrl: credentialsBaseUrl2
|
|
3618
|
+
});
|
|
3619
|
+
await bestEffortClearLegacyJwtState();
|
|
3620
|
+
console.log(
|
|
3621
|
+
`\u2705 Credentials "${credentialName}" created and set as default. You are ready to use the Zapier SDK.`
|
|
3165
3622
|
);
|
|
3166
|
-
|
|
3623
|
+
emitLoginSuccess({ sdk: sdk2, profile });
|
|
3167
3624
|
}
|
|
3168
3625
|
})
|
|
3169
3626
|
);
|
|
@@ -3176,8 +3633,36 @@ var logoutPlugin = definePlugin(
|
|
|
3176
3633
|
categories: ["account"],
|
|
3177
3634
|
inputSchema: LogoutSchema,
|
|
3178
3635
|
supportsJsonOutput: false,
|
|
3179
|
-
handler: async () => {
|
|
3180
|
-
await
|
|
3636
|
+
handler: async ({ sdk: sdk2 }) => {
|
|
3637
|
+
const credentialsBaseUrl2 = await resolveCredentialsBaseUrl(sdk2.context);
|
|
3638
|
+
const activeCredentials = getActiveCredentials({
|
|
3639
|
+
baseUrl: credentialsBaseUrl2
|
|
3640
|
+
});
|
|
3641
|
+
const onEvent = sdk2.context.options?.onEvent;
|
|
3642
|
+
if (!activeCredentials) {
|
|
3643
|
+
await logout({ onEvent });
|
|
3644
|
+
console.log("\u2705 Successfully logged out");
|
|
3645
|
+
return;
|
|
3646
|
+
}
|
|
3647
|
+
const { confirmed } = await inquirer.prompt([
|
|
3648
|
+
{
|
|
3649
|
+
type: "confirm",
|
|
3650
|
+
name: "confirmed",
|
|
3651
|
+
message: `Logging out will delete credentials "${activeCredentials.name}".
|
|
3652
|
+
This may interrupt other Zapier SDK or CLI sessions using them.
|
|
3653
|
+
Do you want to continue?`,
|
|
3654
|
+
default: true
|
|
3655
|
+
}
|
|
3656
|
+
]);
|
|
3657
|
+
if (!confirmed) {
|
|
3658
|
+
console.log("Logout cancelled.");
|
|
3659
|
+
return;
|
|
3660
|
+
}
|
|
3661
|
+
await revokeCredentials({
|
|
3662
|
+
api: sdk2.context.api,
|
|
3663
|
+
credentials: activeCredentials,
|
|
3664
|
+
onEvent
|
|
3665
|
+
});
|
|
3181
3666
|
console.log("\u2705 Successfully logged out");
|
|
3182
3667
|
}
|
|
3183
3668
|
})
|
|
@@ -5694,7 +6179,7 @@ var watchTriggerInboxCliPlugin = definePlugin(
|
|
|
5694
6179
|
// package.json with { type: 'json' }
|
|
5695
6180
|
var package_default2 = {
|
|
5696
6181
|
name: "@zapier/zapier-sdk-cli",
|
|
5697
|
-
version: "0.
|
|
6182
|
+
version: "0.48.0"};
|
|
5698
6183
|
|
|
5699
6184
|
// src/sdk.ts
|
|
5700
6185
|
injectCliLogin(login_exports);
|