@zapier/zapier-sdk-cli 0.47.0 → 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 +14 -0
- package/README.md +1 -1
- package/dist/cli.cjs +559 -84
- package/dist/cli.mjs +559 -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/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/login.cjs
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var Conf = require('conf');
|
|
4
|
-
var fs = require('fs');
|
|
5
3
|
var jwt = require('jsonwebtoken');
|
|
6
4
|
var crossKeychain = require('cross-keychain');
|
|
5
|
+
var Conf = require('conf');
|
|
6
|
+
var fs = require('fs');
|
|
7
7
|
var crypto = require('crypto');
|
|
8
8
|
var path = require('path');
|
|
9
9
|
var lockfile = require('proper-lockfile');
|
|
10
|
+
var zod = require('zod');
|
|
10
11
|
|
|
11
12
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
13
|
|
|
@@ -28,8 +29,8 @@ function _interopNamespace(e) {
|
|
|
28
29
|
return Object.freeze(n);
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
var Conf__default = /*#__PURE__*/_interopDefault(Conf);
|
|
32
32
|
var jwt__namespace = /*#__PURE__*/_interopNamespace(jwt);
|
|
33
|
+
var Conf__default = /*#__PURE__*/_interopDefault(Conf);
|
|
33
34
|
var lockfile__namespace = /*#__PURE__*/_interopNamespace(lockfile);
|
|
34
35
|
|
|
35
36
|
// src/login/index.ts
|
|
@@ -108,6 +109,30 @@ async function clearTokensFromKeychain({
|
|
|
108
109
|
}
|
|
109
110
|
});
|
|
110
111
|
}
|
|
112
|
+
var DEFAULT_AUTH_BASE_URL = "https://zapier.com";
|
|
113
|
+
var config = null;
|
|
114
|
+
function getConfig() {
|
|
115
|
+
if (!config) {
|
|
116
|
+
config = new Conf__default.default({ projectName: "zapier-sdk-cli" });
|
|
117
|
+
if (!config.has("login_storage_mode")) {
|
|
118
|
+
config.set(
|
|
119
|
+
"login_storage_mode",
|
|
120
|
+
fs.existsSync(config.path) ? "config" : "keychain"
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return config;
|
|
125
|
+
}
|
|
126
|
+
function resetConfig() {
|
|
127
|
+
config = null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// src/login/legacy-jwt.ts
|
|
131
|
+
function clearLegacyJwtConfigKeys(config2) {
|
|
132
|
+
config2.delete("login_jwt");
|
|
133
|
+
config2.delete("login_refresh_token");
|
|
134
|
+
config2.delete("login_expires_at");
|
|
135
|
+
}
|
|
111
136
|
var SERVICE2 = "zapier-sdk-cache";
|
|
112
137
|
var CONFIG_KEY = "cache";
|
|
113
138
|
var LOCK_UPDATE_MS = 5e3;
|
|
@@ -235,6 +260,63 @@ function createCache() {
|
|
|
235
260
|
}
|
|
236
261
|
};
|
|
237
262
|
}
|
|
263
|
+
var SERVICE3 = "zapier-sdk-cli";
|
|
264
|
+
var CREDENTIALS_KEY = "credentials";
|
|
265
|
+
var REGISTRY_KEY = "credentialsRegistry";
|
|
266
|
+
var CredentialsEntrySchema = zod.z.object({
|
|
267
|
+
name: zod.z.string(),
|
|
268
|
+
clientId: zod.z.string(),
|
|
269
|
+
createdAt: zod.z.number(),
|
|
270
|
+
scopes: zod.z.array(zod.z.string()),
|
|
271
|
+
baseUrl: zod.z.string()
|
|
272
|
+
});
|
|
273
|
+
function normalizeBaseUrl(baseUrl) {
|
|
274
|
+
return baseUrl ?? DEFAULT_AUTH_BASE_URL;
|
|
275
|
+
}
|
|
276
|
+
function keychainAccount2(key) {
|
|
277
|
+
return crypto.createHash("sha256").update(key).digest("hex");
|
|
278
|
+
}
|
|
279
|
+
function buildKeychainKey(clientId, scopes, baseUrl) {
|
|
280
|
+
const sortedScopes = [...scopes].sort().join(",");
|
|
281
|
+
return `zapier-sdk/client-credentials-secret/${clientId}:${sortedScopes}:${baseUrl}`;
|
|
282
|
+
}
|
|
283
|
+
function findEntry(registry, name, baseUrl) {
|
|
284
|
+
return registry.find((e) => e.name === name && e.baseUrl === baseUrl);
|
|
285
|
+
}
|
|
286
|
+
function readRegistry() {
|
|
287
|
+
const stored = getConfig().get(REGISTRY_KEY);
|
|
288
|
+
if (!Array.isArray(stored)) return [];
|
|
289
|
+
return stored.flatMap((entry) => {
|
|
290
|
+
const result = CredentialsEntrySchema.safeParse(entry);
|
|
291
|
+
return result.success ? [result.data] : [];
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
function getActiveCredentials(options) {
|
|
295
|
+
const name = getConfig().get(CREDENTIALS_KEY);
|
|
296
|
+
if (!name) return void 0;
|
|
297
|
+
return findEntry(readRegistry(), name, normalizeBaseUrl(options?.baseUrl));
|
|
298
|
+
}
|
|
299
|
+
async function getStoredClientCredentials(options) {
|
|
300
|
+
const entry = options?.name ? findEntry(readRegistry(), options.name, normalizeBaseUrl(options.baseUrl)) : getActiveCredentials(options);
|
|
301
|
+
if (!entry) return void 0;
|
|
302
|
+
const keychainKey = buildKeychainKey(
|
|
303
|
+
entry.clientId,
|
|
304
|
+
entry.scopes,
|
|
305
|
+
entry.baseUrl
|
|
306
|
+
);
|
|
307
|
+
const clientSecret = await enqueue(async () => {
|
|
308
|
+
await getBackendInfo();
|
|
309
|
+
return crossKeychain.getPassword(SERVICE3, keychainAccount2(keychainKey));
|
|
310
|
+
});
|
|
311
|
+
if (!clientSecret) return void 0;
|
|
312
|
+
return {
|
|
313
|
+
type: "client_credentials",
|
|
314
|
+
clientId: entry.clientId,
|
|
315
|
+
clientSecret,
|
|
316
|
+
baseUrl: entry.baseUrl,
|
|
317
|
+
scope: [...entry.scopes].sort().join(" ")
|
|
318
|
+
};
|
|
319
|
+
}
|
|
238
320
|
|
|
239
321
|
// src/login/index.ts
|
|
240
322
|
var ZapierAuthenticationError = class extends Error {
|
|
@@ -243,7 +325,6 @@ var ZapierAuthenticationError = class extends Error {
|
|
|
243
325
|
this.name = "ZapierAuthenticationError";
|
|
244
326
|
}
|
|
245
327
|
};
|
|
246
|
-
var config = null;
|
|
247
328
|
var DEFAULT_AUTH_CLIENT_ID = "grwWZD5hUWGvb4V8ODBuOtXer3h0DBEZ2HR8aay6";
|
|
248
329
|
var TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1e3;
|
|
249
330
|
function createDebugLog(enabled) {
|
|
@@ -269,7 +350,6 @@ function getAuthClientId(clientId) {
|
|
|
269
350
|
return clientId || DEFAULT_AUTH_CLIENT_ID;
|
|
270
351
|
}
|
|
271
352
|
var AUTH_MODE_HEADER = "X-Auth";
|
|
272
|
-
var DEFAULT_AUTH_BASE_URL = "https://zapier.com";
|
|
273
353
|
function getAuthTokenUrl(options) {
|
|
274
354
|
const authBaseUrl = options?.baseUrl || DEFAULT_AUTH_BASE_URL;
|
|
275
355
|
return `${authBaseUrl}/oauth/token/`;
|
|
@@ -279,29 +359,16 @@ function getAuthAuthorizeUrl(options) {
|
|
|
279
359
|
return `${authBaseUrl}/oauth/authorize/`;
|
|
280
360
|
}
|
|
281
361
|
function getPkceLoginConfig(options) {
|
|
362
|
+
const effectiveBaseUrl = options?.credentials?.baseUrl ?? options?.baseUrl;
|
|
282
363
|
return {
|
|
283
364
|
clientId: getAuthClientId(options?.credentials?.clientId),
|
|
284
|
-
tokenUrl: getAuthTokenUrl({ baseUrl:
|
|
285
|
-
authorizeUrl: getAuthAuthorizeUrl({
|
|
286
|
-
baseUrl: options?.credentials?.baseUrl
|
|
287
|
-
})
|
|
365
|
+
tokenUrl: getAuthTokenUrl({ baseUrl: effectiveBaseUrl }),
|
|
366
|
+
authorizeUrl: getAuthAuthorizeUrl({ baseUrl: effectiveBaseUrl })
|
|
288
367
|
};
|
|
289
368
|
}
|
|
290
369
|
var cachedLogin;
|
|
291
|
-
function getConfig() {
|
|
292
|
-
if (!config) {
|
|
293
|
-
config = new Conf__default.default({ projectName: "zapier-sdk-cli" });
|
|
294
|
-
if (!config.has("login_storage_mode")) {
|
|
295
|
-
config.set(
|
|
296
|
-
"login_storage_mode",
|
|
297
|
-
fs.existsSync(config.path) ? "config" : "keychain"
|
|
298
|
-
);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
return config;
|
|
302
|
-
}
|
|
303
370
|
function unloadConfig() {
|
|
304
|
-
|
|
371
|
+
resetConfig();
|
|
305
372
|
cachedLogin = void 0;
|
|
306
373
|
}
|
|
307
374
|
async function updateLogin(loginData, options = {}) {
|
|
@@ -574,9 +641,7 @@ async function logout(options = {}) {
|
|
|
574
641
|
await clearTokensFromKeychain();
|
|
575
642
|
const cfg = getConfig();
|
|
576
643
|
cfg.set("login_storage_mode", mode);
|
|
577
|
-
cfg
|
|
578
|
-
cfg.delete("login_jwt");
|
|
579
|
-
cfg.delete("login_refresh_token");
|
|
644
|
+
clearLegacyJwtConfigKeys(cfg);
|
|
580
645
|
onEvent?.({
|
|
581
646
|
type: "auth_logout",
|
|
582
647
|
payload: { message: "Logged out successfully", operation: "logout" },
|
|
@@ -589,8 +654,11 @@ function getConfigPath() {
|
|
|
589
654
|
}
|
|
590
655
|
|
|
591
656
|
exports.AUTH_MODE_HEADER = AUTH_MODE_HEADER;
|
|
657
|
+
exports.DEFAULT_AUTH_BASE_URL = DEFAULT_AUTH_BASE_URL;
|
|
592
658
|
exports.ZapierAuthenticationError = ZapierAuthenticationError;
|
|
659
|
+
exports.clearTokensFromKeychain = clearTokensFromKeychain;
|
|
593
660
|
exports.createCache = createCache;
|
|
661
|
+
exports.getActiveCredentials = getActiveCredentials;
|
|
594
662
|
exports.getAuthAuthorizeUrl = getAuthAuthorizeUrl;
|
|
595
663
|
exports.getAuthTokenUrl = getAuthTokenUrl;
|
|
596
664
|
exports.getConfig = getConfig;
|
|
@@ -598,6 +666,7 @@ exports.getConfigPath = getConfigPath;
|
|
|
598
666
|
exports.getLoggedInUser = getLoggedInUser;
|
|
599
667
|
exports.getLoginStorageMode = getLoginStorageMode;
|
|
600
668
|
exports.getPkceLoginConfig = getPkceLoginConfig;
|
|
669
|
+
exports.getStoredClientCredentials = getStoredClientCredentials;
|
|
601
670
|
exports.getToken = getToken;
|
|
602
671
|
exports.logout = logout;
|
|
603
672
|
exports.unloadConfig = unloadConfig;
|
package/dist/login.d.mts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import Conf from 'conf';
|
|
2
|
+
import { ClientCredentialsObject } from '@zapier/zapier-sdk';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
|
|
5
|
+
declare const DEFAULT_AUTH_BASE_URL = "https://zapier.com";
|
|
6
|
+
declare function getConfig(): Conf;
|
|
2
7
|
|
|
3
8
|
/**
|
|
4
9
|
* Default filesystem + OS keychain cache adapter for the SDK.
|
|
@@ -26,6 +31,27 @@ declare function createCache(): {
|
|
|
26
31
|
withLock<T>(key: string, fn: () => Promise<T>): Promise<T>;
|
|
27
32
|
};
|
|
28
33
|
|
|
34
|
+
declare const CredentialsEntrySchema: z.ZodObject<{
|
|
35
|
+
name: z.ZodString;
|
|
36
|
+
clientId: z.ZodString;
|
|
37
|
+
createdAt: z.ZodNumber;
|
|
38
|
+
scopes: z.ZodArray<z.ZodString>;
|
|
39
|
+
baseUrl: z.ZodString;
|
|
40
|
+
}, z.core.$strip>;
|
|
41
|
+
type CredentialsEntry = z.infer<typeof CredentialsEntrySchema>;
|
|
42
|
+
declare function getActiveCredentials(options?: {
|
|
43
|
+
baseUrl?: string;
|
|
44
|
+
}): CredentialsEntry | undefined;
|
|
45
|
+
declare function getStoredClientCredentials(options?: {
|
|
46
|
+
name?: string;
|
|
47
|
+
baseUrl?: string;
|
|
48
|
+
}): Promise<ClientCredentialsObject | undefined>;
|
|
49
|
+
|
|
50
|
+
type DebugLog = (message: string, data?: unknown) => void;
|
|
51
|
+
declare function clearTokensFromKeychain({ debugLog, }?: {
|
|
52
|
+
debugLog?: DebugLog;
|
|
53
|
+
}): Promise<void>;
|
|
54
|
+
|
|
29
55
|
/**
|
|
30
56
|
* Zapier SDK CLI Login Package
|
|
31
57
|
*
|
|
@@ -91,12 +117,13 @@ interface PkceLoginConfig {
|
|
|
91
117
|
/**
|
|
92
118
|
* Gets all configuration needed for the PKCE login flow.
|
|
93
119
|
* Credentials should have baseUrl already resolved by SDK.
|
|
120
|
+
* baseUrl is a fallback used when credentials carry no baseUrl of their own.
|
|
94
121
|
*/
|
|
95
122
|
declare function getPkceLoginConfig(options?: {
|
|
96
123
|
credentials?: PkceCredentials;
|
|
124
|
+
baseUrl?: string;
|
|
97
125
|
}): PkceLoginConfig;
|
|
98
126
|
type LoginStorageMode = "keychain" | "config";
|
|
99
|
-
declare function getConfig(): Conf;
|
|
100
127
|
/**
|
|
101
128
|
* Drops the cached Conf instance so the next getConfig() call re-initializes
|
|
102
129
|
* from disk (including re-running the pre-existing file detection).
|
|
@@ -141,4 +168,4 @@ declare function logout(options?: Pick<AuthOptions, "onEvent">): Promise<void>;
|
|
|
141
168
|
*/
|
|
142
169
|
declare function getConfigPath(): string;
|
|
143
170
|
|
|
144
|
-
export { AUTH_MODE_HEADER, type AuthOptions, type LoginData, type LoginStorageMode, type PkceCredentials, type PkceLoginConfig, ZapierAuthenticationError, createCache, getAuthAuthorizeUrl, getAuthTokenUrl, getConfig, getConfigPath, getLoggedInUser, getLoginStorageMode, getPkceLoginConfig, getToken, logout, unloadConfig, updateLogin };
|
|
171
|
+
export { AUTH_MODE_HEADER, type AuthOptions, DEFAULT_AUTH_BASE_URL, type LoginData, type LoginStorageMode, type PkceCredentials, type PkceLoginConfig, ZapierAuthenticationError, clearTokensFromKeychain, createCache, getActiveCredentials, getAuthAuthorizeUrl, getAuthTokenUrl, getConfig, getConfigPath, getLoggedInUser, getLoginStorageMode, getPkceLoginConfig, getStoredClientCredentials, getToken, logout, unloadConfig, updateLogin };
|
package/dist/login.d.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import Conf from 'conf';
|
|
2
|
+
import { ClientCredentialsObject } from '@zapier/zapier-sdk';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
|
|
5
|
+
declare const DEFAULT_AUTH_BASE_URL = "https://zapier.com";
|
|
6
|
+
declare function getConfig(): Conf;
|
|
2
7
|
|
|
3
8
|
/**
|
|
4
9
|
* Default filesystem + OS keychain cache adapter for the SDK.
|
|
@@ -26,6 +31,27 @@ declare function createCache(): {
|
|
|
26
31
|
withLock<T>(key: string, fn: () => Promise<T>): Promise<T>;
|
|
27
32
|
};
|
|
28
33
|
|
|
34
|
+
declare const CredentialsEntrySchema: z.ZodObject<{
|
|
35
|
+
name: z.ZodString;
|
|
36
|
+
clientId: z.ZodString;
|
|
37
|
+
createdAt: z.ZodNumber;
|
|
38
|
+
scopes: z.ZodArray<z.ZodString>;
|
|
39
|
+
baseUrl: z.ZodString;
|
|
40
|
+
}, z.core.$strip>;
|
|
41
|
+
type CredentialsEntry = z.infer<typeof CredentialsEntrySchema>;
|
|
42
|
+
declare function getActiveCredentials(options?: {
|
|
43
|
+
baseUrl?: string;
|
|
44
|
+
}): CredentialsEntry | undefined;
|
|
45
|
+
declare function getStoredClientCredentials(options?: {
|
|
46
|
+
name?: string;
|
|
47
|
+
baseUrl?: string;
|
|
48
|
+
}): Promise<ClientCredentialsObject | undefined>;
|
|
49
|
+
|
|
50
|
+
type DebugLog = (message: string, data?: unknown) => void;
|
|
51
|
+
declare function clearTokensFromKeychain({ debugLog, }?: {
|
|
52
|
+
debugLog?: DebugLog;
|
|
53
|
+
}): Promise<void>;
|
|
54
|
+
|
|
29
55
|
/**
|
|
30
56
|
* Zapier SDK CLI Login Package
|
|
31
57
|
*
|
|
@@ -91,12 +117,13 @@ interface PkceLoginConfig {
|
|
|
91
117
|
/**
|
|
92
118
|
* Gets all configuration needed for the PKCE login flow.
|
|
93
119
|
* Credentials should have baseUrl already resolved by SDK.
|
|
120
|
+
* baseUrl is a fallback used when credentials carry no baseUrl of their own.
|
|
94
121
|
*/
|
|
95
122
|
declare function getPkceLoginConfig(options?: {
|
|
96
123
|
credentials?: PkceCredentials;
|
|
124
|
+
baseUrl?: string;
|
|
97
125
|
}): PkceLoginConfig;
|
|
98
126
|
type LoginStorageMode = "keychain" | "config";
|
|
99
|
-
declare function getConfig(): Conf;
|
|
100
127
|
/**
|
|
101
128
|
* Drops the cached Conf instance so the next getConfig() call re-initializes
|
|
102
129
|
* from disk (including re-running the pre-existing file detection).
|
|
@@ -141,4 +168,4 @@ declare function logout(options?: Pick<AuthOptions, "onEvent">): Promise<void>;
|
|
|
141
168
|
*/
|
|
142
169
|
declare function getConfigPath(): string;
|
|
143
170
|
|
|
144
|
-
export { AUTH_MODE_HEADER, type AuthOptions, type LoginData, type LoginStorageMode, type PkceCredentials, type PkceLoginConfig, ZapierAuthenticationError, createCache, getAuthAuthorizeUrl, getAuthTokenUrl, getConfig, getConfigPath, getLoggedInUser, getLoginStorageMode, getPkceLoginConfig, getToken, logout, unloadConfig, updateLogin };
|
|
171
|
+
export { AUTH_MODE_HEADER, type AuthOptions, DEFAULT_AUTH_BASE_URL, type LoginData, type LoginStorageMode, type PkceCredentials, type PkceLoginConfig, ZapierAuthenticationError, clearTokensFromKeychain, createCache, getActiveCredentials, getAuthAuthorizeUrl, getAuthTokenUrl, getConfig, getConfigPath, getLoggedInUser, getLoginStorageMode, getPkceLoginConfig, getStoredClientCredentials, getToken, logout, unloadConfig, updateLogin };
|
package/dist/login.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import Conf from 'conf';
|
|
2
|
-
import { mkdirSync, existsSync, writeFileSync } from 'fs';
|
|
3
1
|
import * as jwt from 'jsonwebtoken';
|
|
4
2
|
import { deletePassword, setPassword, getKeyring, getPassword } from 'cross-keychain';
|
|
3
|
+
import Conf from 'conf';
|
|
4
|
+
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
5
5
|
import { createHash } from 'crypto';
|
|
6
6
|
import { dirname } from 'path';
|
|
7
7
|
import * as lockfile from 'proper-lockfile';
|
|
8
|
+
import { z } from 'zod';
|
|
8
9
|
|
|
9
10
|
// src/login/index.ts
|
|
10
11
|
var SERVICE = "zapier-sdk-cli";
|
|
@@ -82,6 +83,30 @@ async function clearTokensFromKeychain({
|
|
|
82
83
|
}
|
|
83
84
|
});
|
|
84
85
|
}
|
|
86
|
+
var DEFAULT_AUTH_BASE_URL = "https://zapier.com";
|
|
87
|
+
var config = null;
|
|
88
|
+
function getConfig() {
|
|
89
|
+
if (!config) {
|
|
90
|
+
config = new Conf({ projectName: "zapier-sdk-cli" });
|
|
91
|
+
if (!config.has("login_storage_mode")) {
|
|
92
|
+
config.set(
|
|
93
|
+
"login_storage_mode",
|
|
94
|
+
existsSync(config.path) ? "config" : "keychain"
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return config;
|
|
99
|
+
}
|
|
100
|
+
function resetConfig() {
|
|
101
|
+
config = null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/login/legacy-jwt.ts
|
|
105
|
+
function clearLegacyJwtConfigKeys(config2) {
|
|
106
|
+
config2.delete("login_jwt");
|
|
107
|
+
config2.delete("login_refresh_token");
|
|
108
|
+
config2.delete("login_expires_at");
|
|
109
|
+
}
|
|
85
110
|
var SERVICE2 = "zapier-sdk-cache";
|
|
86
111
|
var CONFIG_KEY = "cache";
|
|
87
112
|
var LOCK_UPDATE_MS = 5e3;
|
|
@@ -209,6 +234,63 @@ function createCache() {
|
|
|
209
234
|
}
|
|
210
235
|
};
|
|
211
236
|
}
|
|
237
|
+
var SERVICE3 = "zapier-sdk-cli";
|
|
238
|
+
var CREDENTIALS_KEY = "credentials";
|
|
239
|
+
var REGISTRY_KEY = "credentialsRegistry";
|
|
240
|
+
var CredentialsEntrySchema = z.object({
|
|
241
|
+
name: z.string(),
|
|
242
|
+
clientId: z.string(),
|
|
243
|
+
createdAt: z.number(),
|
|
244
|
+
scopes: z.array(z.string()),
|
|
245
|
+
baseUrl: z.string()
|
|
246
|
+
});
|
|
247
|
+
function normalizeBaseUrl(baseUrl) {
|
|
248
|
+
return baseUrl ?? DEFAULT_AUTH_BASE_URL;
|
|
249
|
+
}
|
|
250
|
+
function keychainAccount2(key) {
|
|
251
|
+
return createHash("sha256").update(key).digest("hex");
|
|
252
|
+
}
|
|
253
|
+
function buildKeychainKey(clientId, scopes, baseUrl) {
|
|
254
|
+
const sortedScopes = [...scopes].sort().join(",");
|
|
255
|
+
return `zapier-sdk/client-credentials-secret/${clientId}:${sortedScopes}:${baseUrl}`;
|
|
256
|
+
}
|
|
257
|
+
function findEntry(registry, name, baseUrl) {
|
|
258
|
+
return registry.find((e) => e.name === name && e.baseUrl === baseUrl);
|
|
259
|
+
}
|
|
260
|
+
function readRegistry() {
|
|
261
|
+
const stored = getConfig().get(REGISTRY_KEY);
|
|
262
|
+
if (!Array.isArray(stored)) return [];
|
|
263
|
+
return stored.flatMap((entry) => {
|
|
264
|
+
const result = CredentialsEntrySchema.safeParse(entry);
|
|
265
|
+
return result.success ? [result.data] : [];
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
function getActiveCredentials(options) {
|
|
269
|
+
const name = getConfig().get(CREDENTIALS_KEY);
|
|
270
|
+
if (!name) return void 0;
|
|
271
|
+
return findEntry(readRegistry(), name, normalizeBaseUrl(options?.baseUrl));
|
|
272
|
+
}
|
|
273
|
+
async function getStoredClientCredentials(options) {
|
|
274
|
+
const entry = options?.name ? findEntry(readRegistry(), options.name, normalizeBaseUrl(options.baseUrl)) : getActiveCredentials(options);
|
|
275
|
+
if (!entry) return void 0;
|
|
276
|
+
const keychainKey = buildKeychainKey(
|
|
277
|
+
entry.clientId,
|
|
278
|
+
entry.scopes,
|
|
279
|
+
entry.baseUrl
|
|
280
|
+
);
|
|
281
|
+
const clientSecret = await enqueue(async () => {
|
|
282
|
+
await getBackendInfo();
|
|
283
|
+
return getPassword(SERVICE3, keychainAccount2(keychainKey));
|
|
284
|
+
});
|
|
285
|
+
if (!clientSecret) return void 0;
|
|
286
|
+
return {
|
|
287
|
+
type: "client_credentials",
|
|
288
|
+
clientId: entry.clientId,
|
|
289
|
+
clientSecret,
|
|
290
|
+
baseUrl: entry.baseUrl,
|
|
291
|
+
scope: [...entry.scopes].sort().join(" ")
|
|
292
|
+
};
|
|
293
|
+
}
|
|
212
294
|
|
|
213
295
|
// src/login/index.ts
|
|
214
296
|
var ZapierAuthenticationError = class extends Error {
|
|
@@ -217,7 +299,6 @@ var ZapierAuthenticationError = class extends Error {
|
|
|
217
299
|
this.name = "ZapierAuthenticationError";
|
|
218
300
|
}
|
|
219
301
|
};
|
|
220
|
-
var config = null;
|
|
221
302
|
var DEFAULT_AUTH_CLIENT_ID = "grwWZD5hUWGvb4V8ODBuOtXer3h0DBEZ2HR8aay6";
|
|
222
303
|
var TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1e3;
|
|
223
304
|
function createDebugLog(enabled) {
|
|
@@ -243,7 +324,6 @@ function getAuthClientId(clientId) {
|
|
|
243
324
|
return clientId || DEFAULT_AUTH_CLIENT_ID;
|
|
244
325
|
}
|
|
245
326
|
var AUTH_MODE_HEADER = "X-Auth";
|
|
246
|
-
var DEFAULT_AUTH_BASE_URL = "https://zapier.com";
|
|
247
327
|
function getAuthTokenUrl(options) {
|
|
248
328
|
const authBaseUrl = options?.baseUrl || DEFAULT_AUTH_BASE_URL;
|
|
249
329
|
return `${authBaseUrl}/oauth/token/`;
|
|
@@ -253,29 +333,16 @@ function getAuthAuthorizeUrl(options) {
|
|
|
253
333
|
return `${authBaseUrl}/oauth/authorize/`;
|
|
254
334
|
}
|
|
255
335
|
function getPkceLoginConfig(options) {
|
|
336
|
+
const effectiveBaseUrl = options?.credentials?.baseUrl ?? options?.baseUrl;
|
|
256
337
|
return {
|
|
257
338
|
clientId: getAuthClientId(options?.credentials?.clientId),
|
|
258
|
-
tokenUrl: getAuthTokenUrl({ baseUrl:
|
|
259
|
-
authorizeUrl: getAuthAuthorizeUrl({
|
|
260
|
-
baseUrl: options?.credentials?.baseUrl
|
|
261
|
-
})
|
|
339
|
+
tokenUrl: getAuthTokenUrl({ baseUrl: effectiveBaseUrl }),
|
|
340
|
+
authorizeUrl: getAuthAuthorizeUrl({ baseUrl: effectiveBaseUrl })
|
|
262
341
|
};
|
|
263
342
|
}
|
|
264
343
|
var cachedLogin;
|
|
265
|
-
function getConfig() {
|
|
266
|
-
if (!config) {
|
|
267
|
-
config = new Conf({ projectName: "zapier-sdk-cli" });
|
|
268
|
-
if (!config.has("login_storage_mode")) {
|
|
269
|
-
config.set(
|
|
270
|
-
"login_storage_mode",
|
|
271
|
-
existsSync(config.path) ? "config" : "keychain"
|
|
272
|
-
);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
return config;
|
|
276
|
-
}
|
|
277
344
|
function unloadConfig() {
|
|
278
|
-
|
|
345
|
+
resetConfig();
|
|
279
346
|
cachedLogin = void 0;
|
|
280
347
|
}
|
|
281
348
|
async function updateLogin(loginData, options = {}) {
|
|
@@ -548,9 +615,7 @@ async function logout(options = {}) {
|
|
|
548
615
|
await clearTokensFromKeychain();
|
|
549
616
|
const cfg = getConfig();
|
|
550
617
|
cfg.set("login_storage_mode", mode);
|
|
551
|
-
cfg
|
|
552
|
-
cfg.delete("login_jwt");
|
|
553
|
-
cfg.delete("login_refresh_token");
|
|
618
|
+
clearLegacyJwtConfigKeys(cfg);
|
|
554
619
|
onEvent?.({
|
|
555
620
|
type: "auth_logout",
|
|
556
621
|
payload: { message: "Logged out successfully", operation: "logout" },
|
|
@@ -562,4 +627,4 @@ function getConfigPath() {
|
|
|
562
627
|
return cfg.path;
|
|
563
628
|
}
|
|
564
629
|
|
|
565
|
-
export { AUTH_MODE_HEADER, ZapierAuthenticationError, createCache, getAuthAuthorizeUrl, getAuthTokenUrl, getConfig, getConfigPath, getLoggedInUser, getLoginStorageMode, getPkceLoginConfig, getToken, logout, unloadConfig, updateLogin };
|
|
630
|
+
export { AUTH_MODE_HEADER, DEFAULT_AUTH_BASE_URL, ZapierAuthenticationError, clearTokensFromKeychain, createCache, getActiveCredentials, getAuthAuthorizeUrl, getAuthTokenUrl, getConfig, getConfigPath, getLoggedInUser, getLoginStorageMode, getPkceLoginConfig, getStoredClientCredentials, getToken, logout, unloadConfig, updateLogin };
|
package/dist/package.json
CHANGED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import Conf from "conf";
|
|
2
|
+
import { existsSync } from "fs";
|
|
3
|
+
export const DEFAULT_AUTH_BASE_URL = "https://zapier.com";
|
|
4
|
+
let config = null;
|
|
5
|
+
export function getConfig() {
|
|
6
|
+
if (!config) {
|
|
7
|
+
// Conf does not create the file until the first set() call.
|
|
8
|
+
config = new Conf({ projectName: "zapier-sdk-cli" });
|
|
9
|
+
// If the config file already exists but has no cache mode marker, an older
|
|
10
|
+
// SDK version created it. Set the marker to "config" so the login flow will
|
|
11
|
+
// prompt the user to upgrade to keychain cache. Otherwise, stamp "keychain"
|
|
12
|
+
// so that any future writes to the config don't leave it unmarked.
|
|
13
|
+
if (!config.has("login_storage_mode")) {
|
|
14
|
+
config.set("login_storage_mode", existsSync(config.path) ? "config" : "keychain");
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return config;
|
|
18
|
+
}
|
|
19
|
+
export function resetConfig() {
|
|
20
|
+
config = null;
|
|
21
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ApiClient } from "@zapier/zapier-sdk";
|
|
2
|
+
import { type CredentialsEntry } from "./credentials-store";
|
|
3
|
+
export type LogoutEventEmitter = (event: {
|
|
4
|
+
type: string;
|
|
5
|
+
payload: Record<string, unknown>;
|
|
6
|
+
timestamp: number;
|
|
7
|
+
}) => void;
|
|
8
|
+
export declare function emitAuthLogout(onEvent: LogoutEventEmitter | undefined): void;
|
|
9
|
+
export declare function revokeCredentials({ api, credentials, onEvent, }: {
|
|
10
|
+
api: ApiClient;
|
|
11
|
+
credentials: CredentialsEntry;
|
|
12
|
+
onEvent?: LogoutEventEmitter;
|
|
13
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { invalidateCachedToken } from "@zapier/zapier-sdk";
|
|
2
|
+
import { clearLegacyJwtState } from "./legacy-jwt";
|
|
3
|
+
import { deleteStoredClientCredentials, } from "./credentials-store";
|
|
4
|
+
import { withRetry } from "../utils/retry";
|
|
5
|
+
export function emitAuthLogout(onEvent) {
|
|
6
|
+
onEvent?.({
|
|
7
|
+
type: "auth_logout",
|
|
8
|
+
payload: { message: "Logged out successfully", operation: "logout" },
|
|
9
|
+
timestamp: Date.now(),
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function isNotFoundError(err) {
|
|
13
|
+
return (typeof err === "object" &&
|
|
14
|
+
err !== null &&
|
|
15
|
+
"statusCode" in err &&
|
|
16
|
+
err.statusCode === 404);
|
|
17
|
+
}
|
|
18
|
+
// Re-login flows pass no emitter so credential rotation stays silent.
|
|
19
|
+
export async function revokeCredentials({ api, credentials, onEvent, }) {
|
|
20
|
+
await withRetry({
|
|
21
|
+
action: async () => {
|
|
22
|
+
try {
|
|
23
|
+
await api.delete(`/api/v0/client-credentials/${credentials.clientId}`, undefined, { authRequired: true, requiredScopes: ["credentials"] });
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
if (isNotFoundError(err))
|
|
27
|
+
return;
|
|
28
|
+
throw err;
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
try {
|
|
33
|
+
await deleteStoredClientCredentials({
|
|
34
|
+
name: credentials.name,
|
|
35
|
+
baseUrl: credentials.baseUrl,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
console.warn("[revokeCredentials] Local store cleanup failed:", err);
|
|
40
|
+
}
|
|
41
|
+
await clearLegacyJwtState();
|
|
42
|
+
await invalidateCachedToken({
|
|
43
|
+
clientId: credentials.clientId,
|
|
44
|
+
scopes: credentials.scopes,
|
|
45
|
+
baseUrl: credentials.baseUrl,
|
|
46
|
+
});
|
|
47
|
+
emitAuthLogout(onEvent);
|
|
48
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ClientCredentialsObject } from "@zapier/zapier-sdk";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
declare const CredentialsEntrySchema: z.ZodObject<{
|
|
4
|
+
name: z.ZodString;
|
|
5
|
+
clientId: z.ZodString;
|
|
6
|
+
createdAt: z.ZodNumber;
|
|
7
|
+
scopes: z.ZodArray<z.ZodString>;
|
|
8
|
+
baseUrl: z.ZodString;
|
|
9
|
+
}, z.core.$strip>;
|
|
10
|
+
export type CredentialsEntry = z.infer<typeof CredentialsEntrySchema>;
|
|
11
|
+
export declare function getActiveCredentials(options?: {
|
|
12
|
+
baseUrl?: string;
|
|
13
|
+
}): CredentialsEntry | undefined;
|
|
14
|
+
export declare function storeClientCredentials({ name, clientId, clientSecret, scopes, baseUrl, }: {
|
|
15
|
+
name: string;
|
|
16
|
+
clientId: string;
|
|
17
|
+
clientSecret: string;
|
|
18
|
+
scopes: string[];
|
|
19
|
+
baseUrl?: string;
|
|
20
|
+
}): Promise<void>;
|
|
21
|
+
export declare function credentialsNameExists({ name, baseUrl, }: {
|
|
22
|
+
name: string;
|
|
23
|
+
baseUrl?: string;
|
|
24
|
+
}): boolean;
|
|
25
|
+
export declare function getStoredClientCredentials(options?: {
|
|
26
|
+
name?: string;
|
|
27
|
+
baseUrl?: string;
|
|
28
|
+
}): Promise<ClientCredentialsObject | undefined>;
|
|
29
|
+
export declare function deleteStoredClientCredentials({ name, baseUrl, }: {
|
|
30
|
+
name: string;
|
|
31
|
+
baseUrl?: string;
|
|
32
|
+
}): Promise<void>;
|
|
33
|
+
export {};
|