@zapier/zapier-sdk-cli 0.55.3 → 0.55.5
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 +16 -0
- package/README.md +2 -1
- package/dist/cli.cjs +47 -6
- package/dist/cli.mjs +48 -7
- package/dist/experimental.cjs +44 -5
- package/dist/experimental.mjs +44 -5
- package/dist/index.cjs +47 -6
- package/dist/index.d.mts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.mjs +48 -7
- package/dist/package.json +1 -1
- package/dist/src/login/credentials-store.d.ts +9 -0
- package/dist/src/login/credentials-store.js +9 -0
- package/dist/src/plugins/login/index.d.ts +1 -0
- package/dist/src/plugins/login/schemas.d.ts +1 -0
- package/dist/src/plugins/login/schemas.js +4 -0
- package/dist/src/telemetry/builders.js +3 -1
- package/dist/src/telemetry/events.d.ts +3 -0
- package/dist/src/utils/auth/account-auth.d.ts +1 -0
- package/dist/src/utils/auth/account-auth.js +41 -12
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import crypto, { createHash } from 'crypto';
|
|
|
7
7
|
import * as path from 'path';
|
|
8
8
|
import { resolve, join, dirname, basename, relative, extname } from 'path';
|
|
9
9
|
import * as lockfile from 'proper-lockfile';
|
|
10
|
-
import { definePlugin, createPluginMethod, OutputPropertySchema, ZapierBundleError, DEFAULT_CONFIG_PATH, ZapierValidationError, ZapierUnknownError, ZapierReleaseTriggerMessageSignal, injectCliLogin, getOrCreateApiClient, isPermanentHttpError, invalidateCachedToken, batch, toSnakeCase, ZapierAbortDrainSignal, isCredentialsObject, buildApplicationLifecycleEvent, ZapierAuthenticationError, ZapierError, createZapierSdkStack, addPlugin, getOsInfo, getPlatformVersions, getCiPlatform, isCi, getReleaseId, getCurrentTimestamp, generateEventId } from '@zapier/zapier-sdk';
|
|
10
|
+
import { definePlugin, createPluginMethod, OutputPropertySchema, ZapierBundleError, DEFAULT_CONFIG_PATH, ZapierValidationError, ZapierUnknownError, ZapierReleaseTriggerMessageSignal, injectCliLogin, getOrCreateApiClient, isPermanentHttpError, invalidateCachedToken, batch, toSnakeCase, ZapierAbortDrainSignal, isCredentialsObject, buildApplicationLifecycleEvent, ZapierAuthenticationError, ZapierError, createZapierSdkStack, addPlugin, getOsInfo, getPlatformVersions, getAgent, getTtyContext, getCiPlatform, isCi, getReleaseId, getCurrentTimestamp, generateEventId } from '@zapier/zapier-sdk';
|
|
11
11
|
import { z } from 'zod';
|
|
12
12
|
import { hostname } from 'os';
|
|
13
13
|
import inquirer from 'inquirer';
|
|
@@ -377,6 +377,15 @@ function resolveAvailableCredentialName({
|
|
|
377
377
|
);
|
|
378
378
|
return firstAvailableCredentialName({ baseName, taken });
|
|
379
379
|
}
|
|
380
|
+
function credentialNameExists({
|
|
381
|
+
name,
|
|
382
|
+
baseUrl
|
|
383
|
+
}) {
|
|
384
|
+
const resolvedBaseUrl = normalizeBaseUrl(baseUrl);
|
|
385
|
+
return readRegistry().some(
|
|
386
|
+
(e) => e.name === name && e.baseUrl === resolvedBaseUrl
|
|
387
|
+
);
|
|
388
|
+
}
|
|
380
389
|
async function storeClientCredentials({
|
|
381
390
|
name,
|
|
382
391
|
clientId,
|
|
@@ -1682,6 +1691,21 @@ function resolveDefaultCredentialsName({
|
|
|
1682
1691
|
}) {
|
|
1683
1692
|
return validateCredentialsName(defaultCredentialsName(email));
|
|
1684
1693
|
}
|
|
1694
|
+
async function resolveCredentialName({
|
|
1695
|
+
email,
|
|
1696
|
+
interactive,
|
|
1697
|
+
baseUrl,
|
|
1698
|
+
entryPoint
|
|
1699
|
+
}) {
|
|
1700
|
+
if (interactive) {
|
|
1701
|
+
return promptCredentialsName({
|
|
1702
|
+
email,
|
|
1703
|
+
promptMessage: getCredentialsPromptMessage(entryPoint)
|
|
1704
|
+
});
|
|
1705
|
+
}
|
|
1706
|
+
const baseName = resolveDefaultCredentialsName({ email });
|
|
1707
|
+
return resolveAvailableCredentialName({ baseName, baseUrl });
|
|
1708
|
+
}
|
|
1685
1709
|
function toPkceCredentials(credentials) {
|
|
1686
1710
|
if (credentials && isCredentialsObject(credentials) && !("clientSecret" in credentials)) {
|
|
1687
1711
|
return {
|
|
@@ -1878,6 +1902,17 @@ async function runAccountAuth({
|
|
|
1878
1902
|
...sdk.context,
|
|
1879
1903
|
resolvedCredentials
|
|
1880
1904
|
});
|
|
1905
|
+
const providedName = options.name !== void 0 ? validateCredentialsName(options.name) : void 0;
|
|
1906
|
+
if (providedName !== void 0) {
|
|
1907
|
+
const activeCredentials = getActiveCredentials({
|
|
1908
|
+
baseUrl: credentialsBaseUrl
|
|
1909
|
+
});
|
|
1910
|
+
if (activeCredentials?.name !== providedName && credentialNameExists({ name: providedName, baseUrl: credentialsBaseUrl })) {
|
|
1911
|
+
throw new ZapierCliValidationError(
|
|
1912
|
+
`A credential named "${providedName}" already exists. Choose a different --name.`
|
|
1913
|
+
);
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1881
1916
|
if (!await clearExistingAuthState({
|
|
1882
1917
|
sdk,
|
|
1883
1918
|
baseUrl: credentialsBaseUrl,
|
|
@@ -1904,11 +1939,12 @@ async function runAccountAuth({
|
|
|
1904
1939
|
console.log(
|
|
1905
1940
|
"\nGenerating credentials so this machine can make authenticated requests on your behalf."
|
|
1906
1941
|
);
|
|
1907
|
-
const
|
|
1942
|
+
const credentialName = providedName ?? await resolveCredentialName({
|
|
1908
1943
|
email: profile.email,
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1944
|
+
interactive,
|
|
1945
|
+
baseUrl: credentialsBaseUrl,
|
|
1946
|
+
entryPoint
|
|
1947
|
+
});
|
|
1912
1948
|
const useApprovals = options.useApprovals === true;
|
|
1913
1949
|
await saveClientCredentials({
|
|
1914
1950
|
api: scopedApi,
|
|
@@ -1926,6 +1962,9 @@ async function runAccountAuth({
|
|
|
1926
1962
|
emitAccountAuthSuccess({ sdk, profile });
|
|
1927
1963
|
}
|
|
1928
1964
|
var LoginSchema = z.object({
|
|
1965
|
+
name: z.string().optional().describe(
|
|
1966
|
+
"Name to identify these credentials (defaults to <email>@<hostname>). Provide this to set a custom name without the interactive prompt."
|
|
1967
|
+
),
|
|
1929
1968
|
timeout: z.string().optional().describe("Login timeout in seconds (default: 300)"),
|
|
1930
1969
|
useApprovals: z.boolean().optional().describe(
|
|
1931
1970
|
"Require approvals for actions performed with these credentials"
|
|
@@ -4514,7 +4553,7 @@ definePlugin(
|
|
|
4514
4553
|
// package.json with { type: 'json' }
|
|
4515
4554
|
var package_default = {
|
|
4516
4555
|
name: "@zapier/zapier-sdk-cli",
|
|
4517
|
-
version: "0.55.
|
|
4556
|
+
version: "0.55.5"};
|
|
4518
4557
|
|
|
4519
4558
|
// src/sdk.ts
|
|
4520
4559
|
injectCliLogin(login_exports);
|
|
@@ -4542,7 +4581,7 @@ function createZapierCliSdk(options = {}) {
|
|
|
4542
4581
|
|
|
4543
4582
|
// package.json
|
|
4544
4583
|
var package_default2 = {
|
|
4545
|
-
version: "0.55.
|
|
4584
|
+
version: "0.55.5"};
|
|
4546
4585
|
|
|
4547
4586
|
// src/telemetry/builders.ts
|
|
4548
4587
|
function createCliBaseEvent(context = {}) {
|
|
@@ -4586,6 +4625,8 @@ function buildCliCommandExecutedEvent({
|
|
|
4586
4625
|
requires_auth: data.requires_auth ?? null,
|
|
4587
4626
|
is_ci_environment: isCi(),
|
|
4588
4627
|
ci_platform: getCiPlatform(),
|
|
4628
|
+
...getTtyContext(),
|
|
4629
|
+
agent: getAgent(),
|
|
4589
4630
|
package_manager: data.package_manager ?? "pnpm",
|
|
4590
4631
|
// Default based on project setup
|
|
4591
4632
|
made_network_requests: data.made_network_requests ?? null,
|
package/dist/package.json
CHANGED
|
@@ -33,6 +33,15 @@ export declare function resolveAvailableCredentialName({ baseName, baseUrl, }: {
|
|
|
33
33
|
baseName: string;
|
|
34
34
|
baseUrl?: string;
|
|
35
35
|
}): string;
|
|
36
|
+
/**
|
|
37
|
+
* Whether a credential with this exact (name, baseUrl) is already stored
|
|
38
|
+
* locally. Used to reject an explicitly-supplied login name that would
|
|
39
|
+
* otherwise silently overwrite a dormant credential of the same name.
|
|
40
|
+
*/
|
|
41
|
+
export declare function credentialNameExists({ name, baseUrl, }: {
|
|
42
|
+
name: string;
|
|
43
|
+
baseUrl?: string;
|
|
44
|
+
}): boolean;
|
|
36
45
|
export declare function storeClientCredentials({ name, clientId, clientSecret, scopes, baseUrl, }: {
|
|
37
46
|
name: string;
|
|
38
47
|
clientId: string;
|
|
@@ -74,6 +74,15 @@ export function resolveAvailableCredentialName({ baseName, baseUrl, }) {
|
|
|
74
74
|
.map((e) => e.name));
|
|
75
75
|
return firstAvailableCredentialName({ baseName, taken });
|
|
76
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
|
+
}
|
|
77
86
|
export async function storeClientCredentials({ name, clientId, clientSecret, scopes, baseUrl, }) {
|
|
78
87
|
if (!name || typeof name !== "string") {
|
|
79
88
|
throw new Error("storeClientCredentials: name is required");
|
|
@@ -2,6 +2,10 @@ import { z } from "zod";
|
|
|
2
2
|
// Login schema
|
|
3
3
|
export const LoginSchema = z
|
|
4
4
|
.object({
|
|
5
|
+
name: z
|
|
6
|
+
.string()
|
|
7
|
+
.optional()
|
|
8
|
+
.describe("Name to identify these credentials (defaults to <email>@<hostname>). Provide this to set a custom name without the interactive prompt."),
|
|
5
9
|
timeout: z
|
|
6
10
|
.string()
|
|
7
11
|
.optional()
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Provides builder functions for CLI command telemetry that auto-populate
|
|
5
5
|
* common CLI fields and system information.
|
|
6
6
|
*/
|
|
7
|
-
import { generateEventId, getCurrentTimestamp, getReleaseId, getOsInfo, getPlatformVersions, isCi, getCiPlatform, } from "@zapier/zapier-sdk";
|
|
7
|
+
import { generateEventId, getCurrentTimestamp, getReleaseId, getOsInfo, getPlatformVersions, isCi, getCiPlatform, getTtyContext, getAgent, } from "@zapier/zapier-sdk";
|
|
8
8
|
import cliPackageJson from "../../package.json";
|
|
9
9
|
// Create base event for CLI events
|
|
10
10
|
function createCliBaseEvent(context = {}) {
|
|
@@ -44,6 +44,8 @@ export function buildCliCommandExecutedEvent({ data, context = {}, cliVersion =
|
|
|
44
44
|
requires_auth: data.requires_auth ?? null,
|
|
45
45
|
is_ci_environment: isCi(),
|
|
46
46
|
ci_platform: getCiPlatform(),
|
|
47
|
+
...getTtyContext(),
|
|
48
|
+
agent: getAgent(),
|
|
47
49
|
package_manager: data.package_manager ?? "pnpm", // Default based on project setup
|
|
48
50
|
made_network_requests: data.made_network_requests ?? null,
|
|
49
51
|
files_modified_count: data.files_modified_count ?? null,
|
|
@@ -34,4 +34,7 @@ export interface CliCommandExecutedEvent extends BaseEvent {
|
|
|
34
34
|
peak_memory_usage_bytes?: number | null;
|
|
35
35
|
cpu_time_ms?: number | null;
|
|
36
36
|
subprocess_count?: number | null;
|
|
37
|
+
stdin_is_tty?: boolean | null;
|
|
38
|
+
stdout_is_tty?: boolean | null;
|
|
39
|
+
agent?: string | null;
|
|
37
40
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type ApiClient, type EventEmissionProvides, type ResolvedCredentials } from "@zapier/zapier-sdk";
|
|
2
2
|
export type AccountAuthEntryPoint = "login" | "signup";
|
|
3
3
|
export interface AccountAuthOptions {
|
|
4
|
+
name?: string;
|
|
4
5
|
timeout?: string;
|
|
5
6
|
useApprovals?: boolean;
|
|
6
7
|
nonInteractive?: boolean;
|
|
@@ -2,7 +2,7 @@ import { hostname } from "node:os";
|
|
|
2
2
|
import inquirer from "inquirer";
|
|
3
3
|
import { buildApplicationLifecycleEvent, getOrCreateApiClient, isCredentialsObject, } from "@zapier/zapier-sdk";
|
|
4
4
|
import { revokeCredentials } from "../../login/credentials-revoke";
|
|
5
|
-
import { deleteStoredClientCredentials, getActiveCredentials, resolveAvailableCredentialName, } from "../../login/credentials-store";
|
|
5
|
+
import { credentialNameExists, deleteStoredClientCredentials, getActiveCredentials, resolveAvailableCredentialName, } from "../../login/credentials-store";
|
|
6
6
|
import { clearLegacyJwtState, hasLegacyJwtConfig, } from "../../login/legacy-jwt";
|
|
7
7
|
import { resolveCredentialsBaseUrl } from "../../plugins/auth/credentials-base-url";
|
|
8
8
|
import { resolveNonInteractive } from "../non-interactive";
|
|
@@ -61,6 +61,19 @@ async function promptCredentialsName({ email, promptMessage, }) {
|
|
|
61
61
|
function resolveDefaultCredentialsName({ email, }) {
|
|
62
62
|
return validateCredentialsName(defaultCredentialsName(email));
|
|
63
63
|
}
|
|
64
|
+
async function resolveCredentialName({ email, interactive, baseUrl, entryPoint, }) {
|
|
65
|
+
if (interactive) {
|
|
66
|
+
return promptCredentialsName({
|
|
67
|
+
email,
|
|
68
|
+
promptMessage: getCredentialsPromptMessage(entryPoint),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
// Non-interactive login can't prompt for a new name, so a default name that
|
|
72
|
+
// already exists locally would silently overwrite that credential. Suffix it
|
|
73
|
+
// instead.
|
|
74
|
+
const baseName = resolveDefaultCredentialsName({ email });
|
|
75
|
+
return resolveAvailableCredentialName({ baseName, baseUrl });
|
|
76
|
+
}
|
|
64
77
|
function toPkceCredentials(credentials) {
|
|
65
78
|
if (credentials &&
|
|
66
79
|
isCredentialsObject(credentials) &&
|
|
@@ -218,6 +231,27 @@ export async function runAccountAuth({ sdk, options, entryPoint, }) {
|
|
|
218
231
|
...sdk.context,
|
|
219
232
|
resolvedCredentials,
|
|
220
233
|
});
|
|
234
|
+
// An explicitly-supplied name is validated and collision-checked up front,
|
|
235
|
+
// before we tear down the existing session or run OAuth. Otherwise a blank or
|
|
236
|
+
// already-taken name would only surface after revoking the active credential
|
|
237
|
+
// and completing the browser flow, leaving the user logged out for nothing.
|
|
238
|
+
// The name is trimmed but otherwise honored as given — never auto-suffixed —
|
|
239
|
+
// so a collision is rejected rather than silently overwriting an existing
|
|
240
|
+
// credential.
|
|
241
|
+
const providedName = options.name !== undefined
|
|
242
|
+
? validateCredentialsName(options.name)
|
|
243
|
+
: undefined;
|
|
244
|
+
if (providedName !== undefined) {
|
|
245
|
+
const activeCredentials = getActiveCredentials({
|
|
246
|
+
baseUrl: credentialsBaseUrl,
|
|
247
|
+
});
|
|
248
|
+
// Re-login under the active credential's own name is a rotation, not a
|
|
249
|
+
// collision — clearExistingAuthState frees it below.
|
|
250
|
+
if (activeCredentials?.name !== providedName &&
|
|
251
|
+
credentialNameExists({ name: providedName, baseUrl: credentialsBaseUrl })) {
|
|
252
|
+
throw new ZapierCliValidationError(`A credential named "${providedName}" already exists. Choose a different --name.`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
221
255
|
if (!(await clearExistingAuthState({
|
|
222
256
|
sdk,
|
|
223
257
|
baseUrl: credentialsBaseUrl,
|
|
@@ -242,18 +276,13 @@ export async function runAccountAuth({ sdk, options, entryPoint, }) {
|
|
|
242
276
|
const profile = await getProfile(scopedApi);
|
|
243
277
|
console.log(getProfileMessage(entryPoint, profile.email));
|
|
244
278
|
console.log("\nGenerating credentials so this machine can make authenticated requests on your behalf.");
|
|
245
|
-
const
|
|
246
|
-
|
|
279
|
+
const credentialName = providedName ??
|
|
280
|
+
(await resolveCredentialName({
|
|
247
281
|
email: profile.email,
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
// already exists locally would silently overwrite that credential. Suffix it
|
|
253
|
-
// instead. Interactive callers chose the name themselves, so leave it as-is.
|
|
254
|
-
const credentialName = interactive
|
|
255
|
-
? baseName
|
|
256
|
-
: resolveAvailableCredentialName({ baseName, baseUrl: credentialsBaseUrl });
|
|
282
|
+
interactive,
|
|
283
|
+
baseUrl: credentialsBaseUrl,
|
|
284
|
+
entryPoint,
|
|
285
|
+
}));
|
|
257
286
|
const useApprovals = options.useApprovals === true;
|
|
258
287
|
await saveClientCredentials({
|
|
259
288
|
api: scopedApi,
|