@zapier/zapier-sdk-cli 0.59.1 → 0.59.2

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.
Files changed (174) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/cli.cjs +2 -2
  3. package/dist/cli.mjs +2 -2
  4. package/dist/experimental.cjs +1 -1
  5. package/dist/experimental.mjs +1 -1
  6. package/dist/index.cjs +2 -2
  7. package/dist/index.mjs +2 -2
  8. package/package.json +3 -3
  9. package/dist/package.json +0 -121
  10. package/dist/src/cli.d.ts +0 -2
  11. package/dist/src/cli.js +0 -219
  12. package/dist/src/experimental.d.ts +0 -33
  13. package/dist/src/experimental.js +0 -86
  14. package/dist/src/generators/ast-generator.d.ts +0 -41
  15. package/dist/src/generators/ast-generator.js +0 -405
  16. package/dist/src/index.d.ts +0 -5
  17. package/dist/src/index.js +0 -5
  18. package/dist/src/login/config.d.ts +0 -4
  19. package/dist/src/login/config.js +0 -21
  20. package/dist/src/login/credentials-revoke.d.ts +0 -14
  21. package/dist/src/login/credentials-revoke.js +0 -95
  22. package/dist/src/login/credentials-store.d.ts +0 -60
  23. package/dist/src/login/credentials-store.js +0 -181
  24. package/dist/src/login/filesystem-cache.d.ts +0 -25
  25. package/dist/src/login/filesystem-cache.js +0 -195
  26. package/dist/src/login/index.d.ts +0 -110
  27. package/dist/src/login/index.js +0 -424
  28. package/dist/src/login/keychain.d.ts +0 -18
  29. package/dist/src/login/keychain.js +0 -74
  30. package/dist/src/login/legacy-jwt.d.ts +0 -4
  31. package/dist/src/login/legacy-jwt.js +0 -18
  32. package/dist/src/login.d.ts +0 -10
  33. package/dist/src/login.js +0 -10
  34. package/dist/src/paths.d.ts +0 -1
  35. package/dist/src/paths.js +0 -6
  36. package/dist/src/plugins/add/index.d.ts +0 -254
  37. package/dist/src/plugins/add/index.js +0 -95
  38. package/dist/src/plugins/add/schemas.d.ts +0 -8
  39. package/dist/src/plugins/add/schemas.js +0 -22
  40. package/dist/src/plugins/auth/credentials-base-url.d.ts +0 -11
  41. package/dist/src/plugins/auth/credentials-base-url.js +0 -24
  42. package/dist/src/plugins/buildManifest/index.d.ts +0 -120
  43. package/dist/src/plugins/buildManifest/index.js +0 -71
  44. package/dist/src/plugins/buildManifest/schemas.d.ts +0 -44
  45. package/dist/src/plugins/buildManifest/schemas.js +0 -17
  46. package/dist/src/plugins/bundleCode/index.d.ts +0 -23
  47. package/dist/src/plugins/bundleCode/index.js +0 -62
  48. package/dist/src/plugins/bundleCode/schemas.d.ts +0 -10
  49. package/dist/src/plugins/bundleCode/schemas.js +0 -19
  50. package/dist/src/plugins/cliOverrides/index.d.ts +0 -21
  51. package/dist/src/plugins/cliOverrides/index.js +0 -17
  52. package/dist/src/plugins/curl/index.d.ts +0 -76
  53. package/dist/src/plugins/curl/index.js +0 -236
  54. package/dist/src/plugins/curl/schemas.d.ts +0 -40
  55. package/dist/src/plugins/curl/schemas.js +0 -108
  56. package/dist/src/plugins/curl/utils.d.ts +0 -34
  57. package/dist/src/plugins/curl/utils.js +0 -150
  58. package/dist/src/plugins/drainTriggerInbox/index.d.ts +0 -46
  59. package/dist/src/plugins/drainTriggerInbox/index.js +0 -178
  60. package/dist/src/plugins/feedback/index.d.ts +0 -24
  61. package/dist/src/plugins/feedback/index.js +0 -52
  62. package/dist/src/plugins/feedback/schemas.d.ts +0 -5
  63. package/dist/src/plugins/feedback/schemas.js +0 -8
  64. package/dist/src/plugins/generateAppTypes/index.d.ts +0 -265
  65. package/dist/src/plugins/generateAppTypes/index.js +0 -129
  66. package/dist/src/plugins/generateAppTypes/schemas.d.ts +0 -58
  67. package/dist/src/plugins/generateAppTypes/schemas.js +0 -21
  68. package/dist/src/plugins/getLoginConfigPath/index.d.ts +0 -16
  69. package/dist/src/plugins/getLoginConfigPath/index.js +0 -9
  70. package/dist/src/plugins/getLoginConfigPath/schemas.d.ts +0 -3
  71. package/dist/src/plugins/getLoginConfigPath/schemas.js +0 -5
  72. package/dist/src/plugins/index.d.ts +0 -15
  73. package/dist/src/plugins/index.js +0 -15
  74. package/dist/src/plugins/init/display.d.ts +0 -9
  75. package/dist/src/plugins/init/display.js +0 -72
  76. package/dist/src/plugins/init/index.d.ts +0 -21
  77. package/dist/src/plugins/init/index.js +0 -56
  78. package/dist/src/plugins/init/schemas.d.ts +0 -9
  79. package/dist/src/plugins/init/schemas.js +0 -19
  80. package/dist/src/plugins/init/steps.d.ts +0 -39
  81. package/dist/src/plugins/init/steps.js +0 -141
  82. package/dist/src/plugins/init/types.d.ts +0 -31
  83. package/dist/src/plugins/init/types.js +0 -1
  84. package/dist/src/plugins/init/utils.d.ts +0 -48
  85. package/dist/src/plugins/init/utils.js +0 -135
  86. package/dist/src/plugins/login/index.d.ts +0 -25
  87. package/dist/src/plugins/login/index.js +0 -12
  88. package/dist/src/plugins/login/schemas.d.ts +0 -9
  89. package/dist/src/plugins/login/schemas.js +0 -27
  90. package/dist/src/plugins/logout/index.d.ts +0 -30
  91. package/dist/src/plugins/logout/index.js +0 -33
  92. package/dist/src/plugins/logout/schemas.d.ts +0 -2
  93. package/dist/src/plugins/logout/schemas.js +0 -4
  94. package/dist/src/plugins/mcp/index.d.ts +0 -28
  95. package/dist/src/plugins/mcp/index.js +0 -24
  96. package/dist/src/plugins/mcp/schemas.d.ts +0 -5
  97. package/dist/src/plugins/mcp/schemas.js +0 -10
  98. package/dist/src/plugins/signup/index.d.ts +0 -25
  99. package/dist/src/plugins/signup/index.js +0 -12
  100. package/dist/src/plugins/signup/schemas.d.ts +0 -9
  101. package/dist/src/plugins/signup/schemas.js +0 -26
  102. package/dist/src/plugins/signup/test-harness.d.ts +0 -34
  103. package/dist/src/plugins/signup/test-harness.js +0 -76
  104. package/dist/src/plugins/watchTriggerInbox/index.d.ts +0 -46
  105. package/dist/src/plugins/watchTriggerInbox/index.js +0 -166
  106. package/dist/src/sdk.d.ts +0 -17
  107. package/dist/src/sdk.js +0 -67
  108. package/dist/src/telemetry/builders.d.ts +0 -44
  109. package/dist/src/telemetry/builders.js +0 -59
  110. package/dist/src/telemetry/events.d.ts +0 -40
  111. package/dist/src/telemetry/events.js +0 -4
  112. package/dist/src/types/sdk.d.ts +0 -6
  113. package/dist/src/types/sdk.js +0 -1
  114. package/dist/src/utils/api/client.d.ts +0 -15
  115. package/dist/src/utils/api/client.js +0 -27
  116. package/dist/src/utils/approval-errors.d.ts +0 -1
  117. package/dist/src/utils/approval-errors.js +0 -9
  118. package/dist/src/utils/approval-progress.d.ts +0 -12
  119. package/dist/src/utils/approval-progress.js +0 -179
  120. package/dist/src/utils/auth/account-auth.d.ts +0 -33
  121. package/dist/src/utils/auth/account-auth.js +0 -302
  122. package/dist/src/utils/auth/client-credentials.d.ts +0 -26
  123. package/dist/src/utils/auth/client-credentials.js +0 -67
  124. package/dist/src/utils/auth/oauth-callback.d.ts +0 -6
  125. package/dist/src/utils/auth/oauth-callback.js +0 -28
  126. package/dist/src/utils/auth/oauth-errors.d.ts +0 -2
  127. package/dist/src/utils/auth/oauth-errors.js +0 -39
  128. package/dist/src/utils/auth/oauth-flow.d.ts +0 -37
  129. package/dist/src/utils/auth/oauth-flow.js +0 -313
  130. package/dist/src/utils/auth/oauth-transaction.d.ts +0 -35
  131. package/dist/src/utils/auth/oauth-transaction.js +0 -69
  132. package/dist/src/utils/cli-generator-utils.d.ts +0 -14
  133. package/dist/src/utils/cli-generator-utils.js +0 -122
  134. package/dist/src/utils/cli-generator.d.ts +0 -4
  135. package/dist/src/utils/cli-generator.js +0 -831
  136. package/dist/src/utils/cli-options.d.ts +0 -16
  137. package/dist/src/utils/cli-options.js +0 -34
  138. package/dist/src/utils/cli-renderer.d.ts +0 -53
  139. package/dist/src/utils/cli-renderer.js +0 -265
  140. package/dist/src/utils/constants.d.ts +0 -3
  141. package/dist/src/utils/constants.js +0 -5
  142. package/dist/src/utils/directory-detection.d.ts +0 -5
  143. package/dist/src/utils/directory-detection.js +0 -21
  144. package/dist/src/utils/errors.d.ts +0 -33
  145. package/dist/src/utils/errors.js +0 -36
  146. package/dist/src/utils/extensions.d.ts +0 -20
  147. package/dist/src/utils/extensions.js +0 -66
  148. package/dist/src/utils/getCallablePromise.d.ts +0 -6
  149. package/dist/src/utils/getCallablePromise.js +0 -14
  150. package/dist/src/utils/log.d.ts +0 -8
  151. package/dist/src/utils/log.js +0 -26
  152. package/dist/src/utils/manifest-helpers.d.ts +0 -10
  153. package/dist/src/utils/manifest-helpers.js +0 -19
  154. package/dist/src/utils/non-interactive.d.ts +0 -14
  155. package/dist/src/utils/non-interactive.js +0 -15
  156. package/dist/src/utils/package-manager-detector.d.ts +0 -18
  157. package/dist/src/utils/package-manager-detector.js +0 -72
  158. package/dist/src/utils/parameter-resolver.d.ts +0 -179
  159. package/dist/src/utils/parameter-resolver.js +0 -1554
  160. package/dist/src/utils/retry.d.ts +0 -6
  161. package/dist/src/utils/retry.js +0 -21
  162. package/dist/src/utils/schema-formatter.d.ts +0 -11
  163. package/dist/src/utils/schema-formatter.js +0 -131
  164. package/dist/src/utils/serializeAsync.d.ts +0 -2
  165. package/dist/src/utils/serializeAsync.js +0 -16
  166. package/dist/src/utils/spinner.d.ts +0 -1
  167. package/dist/src/utils/spinner.js +0 -21
  168. package/dist/src/utils/string-utils.d.ts +0 -1
  169. package/dist/src/utils/string-utils.js +0 -6
  170. package/dist/src/utils/triggerDrain.d.ts +0 -144
  171. package/dist/src/utils/triggerDrain.js +0 -351
  172. package/dist/src/utils/version-checker.d.ts +0 -17
  173. package/dist/src/utils/version-checker.js +0 -154
  174. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -1,181 +0,0 @@
1
- import { createHash } from "crypto";
2
- import { getPassword, setPassword, deletePassword } from "cross-keychain";
3
- import { z } from "zod";
4
- import { DEFAULT_AUTH_BASE_URL, getConfig } from "./config";
5
- import { enqueue, getBackendInfo } from "./keychain";
6
- import { ZapierCliValidationError } from "../utils/errors";
7
- const SERVICE = "zapier-sdk-cli";
8
- const CREDENTIALS_KEY = "credentials";
9
- const REGISTRY_KEY = "credentialsRegistry";
10
- const CredentialsEntrySchema = z.object({
11
- name: z.string(),
12
- clientId: z.string(),
13
- createdAt: z.number(),
14
- scopes: z.array(z.string()),
15
- baseUrl: z.string(),
16
- });
17
- function normalizeBaseUrl(baseUrl) {
18
- return baseUrl ?? DEFAULT_AUTH_BASE_URL;
19
- }
20
- function keychainAccount(key) {
21
- return createHash("sha256").update(key).digest("hex");
22
- }
23
- function buildKeychainKey(clientId, scopes, baseUrl) {
24
- const sortedScopes = [...scopes].sort().join(",");
25
- return `zapier-sdk/client-credentials-secret/${clientId}:${sortedScopes}:${baseUrl}`;
26
- }
27
- function findEntry(registry, name, baseUrl) {
28
- return registry.find((e) => e.name === name && e.baseUrl === baseUrl);
29
- }
30
- function readRegistry() {
31
- const stored = getConfig().get(REGISTRY_KEY);
32
- if (!Array.isArray(stored))
33
- return [];
34
- return stored.flatMap((entry) => {
35
- const result = CredentialsEntrySchema.safeParse(entry);
36
- return result.success ? [result.data] : [];
37
- });
38
- }
39
- export function getActiveCredentials(options) {
40
- const name = getConfig().get(CREDENTIALS_KEY);
41
- if (!name)
42
- return undefined;
43
- return findEntry(readRegistry(), name, normalizeBaseUrl(options?.baseUrl));
44
- }
45
- const MAX_CREDENTIAL_NAME_ATTEMPTS = 500;
46
- /**
47
- * Pick the first credential name not already present in `taken`. Returns
48
- * `baseName` if it is free, otherwise appends an incrementing `-1`, `-2`, …
49
- * suffix to the literal base — a base ending in a digit is left intact, so
50
- * `acme-1` collides into `acme-1-1`. Storing a credential under a name that
51
- * already exists locally silently replaces that entry (and deletes its
52
- * keychain secret), so non-interactive login uses this to avoid clobbering a
53
- * dormant credential of the same name.
54
- */
55
- export function firstAvailableCredentialName({ baseName, taken, }) {
56
- if (!taken.has(baseName))
57
- return baseName;
58
- for (let i = 1; i <= MAX_CREDENTIAL_NAME_ATTEMPTS; i++) {
59
- const candidate = `${baseName}-${i}`;
60
- if (!taken.has(candidate))
61
- return candidate;
62
- }
63
- throw new ZapierCliValidationError(`Could not find an available credential name for "${baseName}" after ${MAX_CREDENTIAL_NAME_ATTEMPTS} attempts.`);
64
- }
65
- /**
66
- * Resolve a locally-unique credential name for the given baseUrl. Local
67
- * credentials are keyed by (name, baseUrl), so name collisions — and the
68
- * suffixing that avoids them — are scoped per baseUrl.
69
- */
70
- export function resolveAvailableCredentialName({ baseName, baseUrl, }) {
71
- const resolvedBaseUrl = normalizeBaseUrl(baseUrl);
72
- const taken = new Set(readRegistry()
73
- .filter((e) => e.baseUrl === resolvedBaseUrl)
74
- .map((e) => e.name));
75
- return firstAvailableCredentialName({ baseName, taken });
76
- }
77
- /**
78
- * Whether a credential with this exact (name, baseUrl) is already stored
79
- * locally. Used to reject an explicitly-supplied login name that would
80
- * otherwise silently overwrite a dormant credential of the same name.
81
- */
82
- export function credentialNameExists({ name, baseUrl, }) {
83
- const resolvedBaseUrl = normalizeBaseUrl(baseUrl);
84
- return readRegistry().some((e) => e.name === name && e.baseUrl === resolvedBaseUrl);
85
- }
86
- export async function storeClientCredentials({ name, clientId, clientSecret, scopes, baseUrl, }) {
87
- if (!name || typeof name !== "string") {
88
- throw new Error("storeClientCredentials: name is required");
89
- }
90
- if (!clientId || typeof clientId !== "string") {
91
- throw new Error("storeClientCredentials: clientId is required");
92
- }
93
- if (!clientSecret || typeof clientSecret !== "string") {
94
- throw new Error("storeClientCredentials: clientSecret is required");
95
- }
96
- if (!Array.isArray(scopes) || scopes.length === 0) {
97
- throw new Error("storeClientCredentials: scopes must be a non-empty array");
98
- }
99
- const sortedScopes = [...scopes].sort();
100
- const resolvedBaseUrl = normalizeBaseUrl(baseUrl);
101
- const keychainKey = buildKeychainKey(clientId, sortedScopes, resolvedBaseUrl);
102
- const existingEntry = findEntry(readRegistry(), name, resolvedBaseUrl);
103
- const existingKeychainKey = existingEntry
104
- ? buildKeychainKey(existingEntry.clientId, existingEntry.scopes, existingEntry.baseUrl)
105
- : undefined;
106
- await enqueue(async () => {
107
- await getBackendInfo();
108
- await setPassword(SERVICE, keychainAccount(keychainKey), clientSecret);
109
- });
110
- const entry = {
111
- name,
112
- clientId,
113
- createdAt: Date.now(),
114
- scopes: sortedScopes,
115
- baseUrl: resolvedBaseUrl,
116
- };
117
- const registry = readRegistry().filter((e) => !(e.name === name && e.baseUrl === resolvedBaseUrl));
118
- registry.push(entry);
119
- const cfg = getConfig();
120
- cfg.set(REGISTRY_KEY, registry);
121
- cfg.set(CREDENTIALS_KEY, name);
122
- if (existingEntry && existingKeychainKey !== keychainKey) {
123
- await deleteKeychainSecret(existingEntry);
124
- }
125
- }
126
- export async function getStoredClientCredentials(options) {
127
- const entry = options?.name
128
- ? findEntry(readRegistry(), options.name, normalizeBaseUrl(options.baseUrl))
129
- : getActiveCredentials(options);
130
- if (!entry)
131
- return undefined;
132
- const keychainKey = buildKeychainKey(entry.clientId, entry.scopes, entry.baseUrl);
133
- const clientSecret = await enqueue(async () => {
134
- await getBackendInfo();
135
- return getPassword(SERVICE, keychainAccount(keychainKey));
136
- });
137
- if (!clientSecret)
138
- return undefined;
139
- return {
140
- type: "client_credentials",
141
- clientId: entry.clientId,
142
- clientSecret,
143
- baseUrl: entry.baseUrl,
144
- scope: [...entry.scopes].sort().join(" "),
145
- };
146
- }
147
- function deleteRegistryEntry(registry, name, baseUrl) {
148
- const idx = registry.findIndex((e) => e.name === name && e.baseUrl === baseUrl);
149
- if (idx === -1)
150
- return undefined;
151
- const [removed] = registry.splice(idx, 1);
152
- return removed;
153
- }
154
- function unsetMatchingCredentialsKey(cfg, name) {
155
- const activeName = cfg.get(CREDENTIALS_KEY);
156
- if (activeName === name && !readRegistry().some((e) => e.name === name)) {
157
- cfg.delete(CREDENTIALS_KEY);
158
- }
159
- }
160
- async function deleteKeychainSecret(entry) {
161
- const keychainKey = buildKeychainKey(entry.clientId, entry.scopes, entry.baseUrl);
162
- try {
163
- await enqueue(async () => {
164
- await getBackendInfo();
165
- await deletePassword(SERVICE, keychainAccount(keychainKey));
166
- });
167
- }
168
- catch {
169
- // Best-effort; key may already be gone.
170
- }
171
- }
172
- export async function deleteStoredClientCredentials({ name, baseUrl, }) {
173
- const registry = readRegistry();
174
- const removed = deleteRegistryEntry(registry, name, normalizeBaseUrl(baseUrl));
175
- if (!removed)
176
- return;
177
- const cfg = getConfig();
178
- cfg.set(REGISTRY_KEY, registry);
179
- unsetMatchingCredentialsKey(cfg, name);
180
- await deleteKeychainSecret(removed);
181
- }
@@ -1,25 +0,0 @@
1
- /**
2
- * Default filesystem + OS keychain cache adapter for the SDK.
3
- *
4
- * Conforms to the generic ZapierCache interface that the SDK defines.
5
- * Secrets go to the OS keychain via cross-keychain; non-secret values
6
- * and the identity metadata (expires_at, secret flag) go to the
7
- * existing zapier-sdk-cli Conf file. A proper-lockfile lock wraps the
8
- * exchange/persist critical section so N concurrent CLI invocations
9
- * collapse to a single network exchange.
10
- *
11
- * The SDK treats this (like any ZapierCache) as a cache — values may
12
- * disappear, and the caller must always be able to recreate them.
13
- */
14
- export declare function createCache(): {
15
- get(key: string): Promise<{
16
- value: string;
17
- expiresAt?: number;
18
- } | undefined>;
19
- set(key: string, value: string, options?: {
20
- secret?: boolean;
21
- ttl?: number;
22
- }): Promise<void>;
23
- delete(key: string): Promise<void>;
24
- withLock<T>(key: string, fn: () => Promise<T>): Promise<T>;
25
- };
@@ -1,195 +0,0 @@
1
- /**
2
- * Default filesystem + OS keychain cache adapter for the SDK.
3
- *
4
- * Conforms to the generic ZapierCache interface that the SDK defines.
5
- * Secrets go to the OS keychain via cross-keychain; non-secret values
6
- * and the identity metadata (expires_at, secret flag) go to the
7
- * existing zapier-sdk-cli Conf file. A proper-lockfile lock wraps the
8
- * exchange/persist critical section so N concurrent CLI invocations
9
- * collapse to a single network exchange.
10
- *
11
- * The SDK treats this (like any ZapierCache) as a cache — values may
12
- * disappear, and the caller must always be able to recreate them.
13
- */
14
- import { createHash } from "crypto";
15
- import { dirname } from "path";
16
- import { existsSync, mkdirSync, writeFileSync } from "fs";
17
- import { getPassword, setPassword, deletePassword } from "cross-keychain";
18
- import * as lockfile from "proper-lockfile";
19
- import { getConfig } from "./index";
20
- import { enqueue, getBackendInfo } from "./keychain";
21
- const SERVICE = "zapier-sdk-cache";
22
- const CONFIG_KEY = "cache";
23
- const LOCK_UPDATE_MS = 5000;
24
- const LOCK_STALE_MS = 10000;
25
- const LOCK_RETRY_WAIT_MS = 100;
26
- const LOCK_RETRY_MAX_WAIT_MS = 1000;
27
- const LOCK_RETRY_COUNT = 120; // ~2 min worst-case wait under heavy contention
28
- /**
29
- * cross-keychain's native macOS backend restricts account names to
30
- * alphanumeric + . _ @ -. Hash arbitrary SDK keys to a hex digest to
31
- * stay inside that alphabet.
32
- */
33
- function keychainAccount(key) {
34
- return createHash("sha256").update(key).digest("hex");
35
- }
36
- function readConfigMap() {
37
- const cfg = getConfig();
38
- const stored = cfg.get(CONFIG_KEY);
39
- if (stored && typeof stored === "object") {
40
- return stored;
41
- }
42
- return {};
43
- }
44
- function writeConfigMap(map) {
45
- getConfig().set(CONFIG_KEY, map);
46
- }
47
- function entryIsExpired(entry) {
48
- return entry.expires_at !== undefined && entry.expires_at <= Date.now();
49
- }
50
- export function createCache() {
51
- return {
52
- async get(key) {
53
- const entry = readConfigMap()[key];
54
- if (!entry)
55
- return undefined;
56
- if (entryIsExpired(entry))
57
- return undefined;
58
- if (entry.secret) {
59
- const stored = await enqueue(async () => {
60
- await getBackendInfo();
61
- return getPassword(SERVICE, keychainAccount(key));
62
- });
63
- if (!stored) {
64
- // Config claims a secret exists but keychain doesn't have it.
65
- // Treat as a miss so the caller re-produces the value.
66
- return undefined;
67
- }
68
- return { value: stored, expiresAt: entry.expires_at };
69
- }
70
- if (entry.value === undefined)
71
- return undefined;
72
- return { value: entry.value, expiresAt: entry.expires_at };
73
- },
74
- async set(key, value, options) {
75
- const secret = options?.secret ?? false;
76
- const expiresAt = options?.ttl
77
- ? Date.now() + options.ttl * 1000
78
- : undefined;
79
- if (secret) {
80
- // Keychain first so a failed keychain write doesn't leave a
81
- // dangling config pointer to a non-existent secret.
82
- try {
83
- await enqueue(async () => {
84
- await getBackendInfo();
85
- await setPassword(SERVICE, keychainAccount(key), value);
86
- });
87
- }
88
- catch {
89
- // No keychain available (headless CI, sandboxed env). Skip
90
- // the config write too so subsequent reads cleanly miss.
91
- return;
92
- }
93
- const map = readConfigMap();
94
- map[key] = { secret: true, expires_at: expiresAt };
95
- try {
96
- writeConfigMap(map);
97
- }
98
- catch {
99
- // Config is read-only; orphan the keychain entry. Reads find
100
- // no config pointer and treat as a miss — self-healing on the
101
- // next successful write.
102
- }
103
- }
104
- else {
105
- const map = readConfigMap();
106
- map[key] = { secret: false, value, expires_at: expiresAt };
107
- try {
108
- writeConfigMap(map);
109
- }
110
- catch {
111
- // Nothing we can do; next write for this key is the next
112
- // chance to persist.
113
- }
114
- }
115
- },
116
- async delete(key) {
117
- // Config first: an orphan keychain entry with no config pointer
118
- // is unreachable via `get`, which is better than a stuck stale
119
- // value if the keychain delete succeeds but config write fails.
120
- const map = readConfigMap();
121
- const entry = map[key];
122
- if (entry) {
123
- delete map[key];
124
- try {
125
- writeConfigMap(map);
126
- }
127
- catch {
128
- // ignore
129
- }
130
- }
131
- if (entry?.secret) {
132
- try {
133
- await enqueue(async () => {
134
- await getBackendInfo();
135
- await deletePassword(SERVICE, keychainAccount(key));
136
- });
137
- }
138
- catch {
139
- // Best-effort
140
- }
141
- }
142
- },
143
- async withLock(_key, fn) {
144
- // Global lock on the Conf file: Conf writes the whole file
145
- // atomically, so a per-key lock wouldn't prevent sibling keys
146
- // from clobbering each other. Fleet-wide serialization is fine
147
- // at CLI scale (<1 request/second sustained per machine).
148
- const cfg = getConfig();
149
- const lockTarget = `${cfg.path}.cache-lock`;
150
- try {
151
- mkdirSync(dirname(lockTarget), { recursive: true });
152
- if (!existsSync(lockTarget)) {
153
- writeFileSync(lockTarget, "");
154
- }
155
- }
156
- catch {
157
- // Can't create the lock file (read-only fs, no HOME, etc.).
158
- // Proceed unsynchronized — correctness is maintained at the
159
- // cost of possibly N exchanges in the worst case, same as
160
- // before this MR.
161
- return fn();
162
- }
163
- let release = null;
164
- try {
165
- release = await lockfile.lock(lockTarget, {
166
- stale: LOCK_STALE_MS,
167
- update: LOCK_UPDATE_MS,
168
- retries: {
169
- retries: LOCK_RETRY_COUNT,
170
- factor: 1.2,
171
- minTimeout: LOCK_RETRY_WAIT_MS,
172
- maxTimeout: LOCK_RETRY_MAX_WAIT_MS,
173
- },
174
- });
175
- }
176
- catch {
177
- // Lock is genuinely unavailable. Same graceful-degrade as above.
178
- return fn();
179
- }
180
- try {
181
- return await fn();
182
- }
183
- finally {
184
- try {
185
- await release();
186
- }
187
- catch {
188
- // If release fails (e.g. the lockfile was reclaimed as stale
189
- // while we held it), there's nothing useful to do — the next
190
- // acquirer will handle it.
191
- }
192
- }
193
- },
194
- };
195
- }
@@ -1,110 +0,0 @@
1
- /**
2
- * Zapier SDK CLI Login Package
3
- *
4
- * Handles login, logout, token cache and refresh for Zapier SDK CLI.
5
- * Provides getToken function that can be optionally imported by zapier-sdk.
6
- */
7
- export { DEFAULT_AUTH_BASE_URL, getConfig } from "./config";
8
- export { createCache } from "./filesystem-cache";
9
- export { ZapierAuthenticationError } from "@zapier/zapier-sdk";
10
- export interface PkceCredentials {
11
- type: "pkce";
12
- clientId: string;
13
- baseUrl?: string;
14
- scope?: string;
15
- }
16
- export interface AuthOptions {
17
- onEvent?: (event: {
18
- type: string;
19
- payload: Record<string, unknown>;
20
- timestamp: number;
21
- }) => void;
22
- fetch?: typeof globalThis.fetch;
23
- /** Credentials object from SDK. Contains clientId and resolved auth baseUrl. */
24
- credentials?: PkceCredentials;
25
- /** Enable debug logging for fetch requests and config operations. */
26
- debug?: boolean;
27
- }
28
- export interface LoginData {
29
- access_token: string;
30
- refresh_token: string;
31
- expires_in: number;
32
- }
33
- export declare const AUTH_MODE_HEADER = "X-Auth";
34
- /**
35
- * Gets the OAuth token endpoint URL.
36
- * baseUrl should be the auth base URL (e.g., https://zapier.com), already resolved by SDK.
37
- */
38
- export declare function getAuthTokenUrl(options?: {
39
- baseUrl?: string;
40
- }): string;
41
- /**
42
- * Gets the OAuth authorization endpoint URL.
43
- * baseUrl should be the auth base URL (e.g., https://zapier.com), already resolved by SDK.
44
- */
45
- export declare function getAuthAuthorizeUrl(options?: {
46
- baseUrl?: string;
47
- }): string;
48
- /**
49
- * Configuration needed for PKCE login flow.
50
- */
51
- export interface PkceLoginConfig {
52
- clientId: string;
53
- tokenUrl: string;
54
- authorizeUrl: string;
55
- }
56
- /**
57
- * Gets all configuration needed for the PKCE login flow.
58
- * Credentials should have baseUrl already resolved by SDK.
59
- * baseUrl is a fallback used when credentials carry no baseUrl of their own.
60
- */
61
- export declare function getPkceLoginConfig(options?: {
62
- credentials?: PkceCredentials;
63
- baseUrl?: string;
64
- }): PkceLoginConfig;
65
- export type LoginStorageMode = "keychain" | "config";
66
- /**
67
- * Drops the cached Conf instance so the next getConfig() call re-initializes
68
- * from disk (including re-running the pre-existing file detection).
69
- */
70
- export declare function unloadConfig(): void;
71
- export declare function updateLogin(loginData: LoginData, options?: {
72
- storage?: LoginStorageMode;
73
- debug?: boolean;
74
- }): Promise<void>;
75
- /**
76
- * Main function exported for zapier-sdk to optionally use.
77
- * Returns the stored token from CLI configuration (with auto-refresh).
78
- *
79
- * Note: Environment variable handling (ZAPIER_CREDENTIALS, ZAPIER_TOKEN)
80
- * is done by the SDK before calling this function.
81
- *
82
- * Returns undefined if no valid token is found.
83
- */
84
- export declare function getToken(options?: AuthOptions): Promise<string | undefined>;
85
- /**
86
- * Gets the logged-in user information from JWT token.
87
- * Automatically refreshes token if expired.
88
- */
89
- export declare function getLoggedInUser(options?: AuthOptions): Promise<{
90
- accountId: number;
91
- customUserId: number;
92
- email: string;
93
- }>;
94
- /**
95
- * Checks config to determine current cache mode without reading keychain.
96
- * Credential keys in config are ground truth — if login_jwt exists, we're in
97
- * config mode regardless of the marker. The marker only matters when no
98
- * credential keys are present (e.g. after logout or when using keychain).
99
- */
100
- export declare function getLoginStorageMode(): LoginStorageMode;
101
- /**
102
- * Clears stored login information.
103
- */
104
- export declare function logout(options?: Pick<AuthOptions, "onEvent">): Promise<void>;
105
- /**
106
- * Gets the path to the configuration file.
107
- */
108
- export declare function getConfigPath(): string;
109
- export { getStoredClientCredentials, getActiveCredentials, } from "./credentials-store";
110
- export { clearTokensFromKeychain } from "./keychain";