@zapier/zapier-sdk-cli 0.49.1 → 0.51.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 +28 -0
- package/README.md +26 -25
- package/dist/cli.cjs +50 -10
- package/dist/cli.mjs +50 -10
- package/dist/experimental.cjs +31 -8
- package/dist/experimental.mjs +31 -8
- package/dist/index.cjs +32 -9
- package/dist/index.mjs +32 -9
- package/dist/package.json +2 -1
- package/dist/src/plugins/login/index.d.ts +1 -0
- package/dist/src/plugins/login/index.js +9 -2
- package/dist/src/plugins/login/schemas.d.ts +1 -0
- package/dist/src/plugins/login/schemas.js +4 -0
- package/dist/src/utils/auth/client-credentials.d.ts +11 -1
- package/dist/src/utils/auth/client-credentials.js +18 -4
- package/dist/src/utils/parameter-resolver.d.ts +21 -0
- package/dist/src/utils/parameter-resolver.js +41 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -3
package/dist/index.cjs
CHANGED
|
@@ -1180,10 +1180,18 @@ async function runOauthFlow({
|
|
|
1180
1180
|
|
|
1181
1181
|
// src/utils/auth/client-credentials.ts
|
|
1182
1182
|
var CREDENTIALS_SCOPES = ["external", "credentials"];
|
|
1183
|
-
|
|
1183
|
+
var EMPTY_POLICY = {
|
|
1184
|
+
version: 2,
|
|
1185
|
+
statements: []
|
|
1186
|
+
};
|
|
1187
|
+
async function createCredentialsOnServer(api2, name, policy) {
|
|
1184
1188
|
const response = await api2.post(
|
|
1185
1189
|
"/api/v0/client-credentials",
|
|
1186
|
-
{
|
|
1190
|
+
{
|
|
1191
|
+
name,
|
|
1192
|
+
allowed_scopes: CREDENTIALS_SCOPES,
|
|
1193
|
+
...policy !== void 0 && { policy }
|
|
1194
|
+
},
|
|
1187
1195
|
{ authRequired: true, requiredScopes: ["credentials"] }
|
|
1188
1196
|
);
|
|
1189
1197
|
return {
|
|
@@ -1200,9 +1208,14 @@ async function deleteCredentialsOnServer(api2, clientId) {
|
|
|
1200
1208
|
async function setupClientCredentials({
|
|
1201
1209
|
api: api2,
|
|
1202
1210
|
name,
|
|
1203
|
-
credentialsBaseUrl
|
|
1211
|
+
credentialsBaseUrl,
|
|
1212
|
+
policy
|
|
1204
1213
|
}) {
|
|
1205
|
-
const { clientId, clientSecret } = await createCredentialsOnServer(
|
|
1214
|
+
const { clientId, clientSecret } = await createCredentialsOnServer(
|
|
1215
|
+
api2,
|
|
1216
|
+
name,
|
|
1217
|
+
policy
|
|
1218
|
+
);
|
|
1206
1219
|
try {
|
|
1207
1220
|
await withRetry({
|
|
1208
1221
|
action: () => storeClientCredentials({
|
|
@@ -1244,7 +1257,10 @@ async function resolveCredentialsBaseUrl(context) {
|
|
|
1244
1257
|
return getBaseUrlFromResolvedCredentials(resolvedCredentials) ?? getBaseUrlFromOptionsCredentials(context.options?.credentials) ?? context.options?.baseUrl;
|
|
1245
1258
|
}
|
|
1246
1259
|
var LoginSchema = zod.z.object({
|
|
1247
|
-
timeout: zod.z.string().optional().describe("Login timeout in seconds (default: 300)")
|
|
1260
|
+
timeout: zod.z.string().optional().describe("Login timeout in seconds (default: 300)"),
|
|
1261
|
+
useApprovals: zod.z.boolean().optional().describe(
|
|
1262
|
+
"Require approvals for actions performed with these credentials"
|
|
1263
|
+
)
|
|
1248
1264
|
}).describe("Log in to Zapier to access your account");
|
|
1249
1265
|
|
|
1250
1266
|
// src/plugins/login/index.ts
|
|
@@ -1338,7 +1354,9 @@ function emitLoginSuccess({
|
|
|
1338
1354
|
sdk.context.eventEmission.emit(
|
|
1339
1355
|
"platform.sdk.ApplicationLifecycleEvent",
|
|
1340
1356
|
zapierSdk.buildApplicationLifecycleEvent(
|
|
1341
|
-
{
|
|
1357
|
+
{
|
|
1358
|
+
lifecycle_event_type: "login_success"
|
|
1359
|
+
},
|
|
1342
1360
|
{
|
|
1343
1361
|
customuser_id: profile.user_id,
|
|
1344
1362
|
account_id: profile.roles[0]?.account_id ?? null
|
|
@@ -1410,15 +1428,20 @@ var loginPlugin = zapierSdk.definePlugin(
|
|
|
1410
1428
|
profile.email,
|
|
1411
1429
|
credentialsBaseUrl
|
|
1412
1430
|
);
|
|
1431
|
+
const useApprovals = options.useApprovals === true;
|
|
1413
1432
|
await setupClientCredentials({
|
|
1414
1433
|
api: scopedApi,
|
|
1415
1434
|
name: credentialName,
|
|
1416
|
-
credentialsBaseUrl
|
|
1435
|
+
credentialsBaseUrl,
|
|
1436
|
+
...useApprovals && { policy: EMPTY_POLICY }
|
|
1417
1437
|
});
|
|
1418
1438
|
await bestEffortClearLegacyJwtState();
|
|
1419
1439
|
console.log(
|
|
1420
1440
|
`\u2705 Credentials "${credentialName}" created and set as default. You are ready to use the Zapier SDK.`
|
|
1421
1441
|
);
|
|
1442
|
+
if (useApprovals) {
|
|
1443
|
+
console.log("\u{1F510} Approvals are enabled for these credentials.");
|
|
1444
|
+
}
|
|
1422
1445
|
emitLoginSuccess({ sdk: sdk2, profile });
|
|
1423
1446
|
}
|
|
1424
1447
|
})
|
|
@@ -3962,7 +3985,7 @@ zapierSdk.definePlugin(
|
|
|
3962
3985
|
// package.json with { type: 'json' }
|
|
3963
3986
|
var package_default = {
|
|
3964
3987
|
name: "@zapier/zapier-sdk-cli",
|
|
3965
|
-
version: "0.
|
|
3988
|
+
version: "0.51.0"};
|
|
3966
3989
|
|
|
3967
3990
|
// src/sdk.ts
|
|
3968
3991
|
zapierSdk.injectCliLogin(login_exports);
|
|
@@ -3990,7 +4013,7 @@ function createZapierCliSdk(options = {}) {
|
|
|
3990
4013
|
|
|
3991
4014
|
// package.json
|
|
3992
4015
|
var package_default2 = {
|
|
3993
|
-
version: "0.
|
|
4016
|
+
version: "0.51.0"};
|
|
3994
4017
|
|
|
3995
4018
|
// src/telemetry/builders.ts
|
|
3996
4019
|
function createCliBaseEvent(context = {}) {
|
package/dist/index.mjs
CHANGED
|
@@ -1144,10 +1144,18 @@ async function runOauthFlow({
|
|
|
1144
1144
|
|
|
1145
1145
|
// src/utils/auth/client-credentials.ts
|
|
1146
1146
|
var CREDENTIALS_SCOPES = ["external", "credentials"];
|
|
1147
|
-
|
|
1147
|
+
var EMPTY_POLICY = {
|
|
1148
|
+
version: 2,
|
|
1149
|
+
statements: []
|
|
1150
|
+
};
|
|
1151
|
+
async function createCredentialsOnServer(api2, name, policy) {
|
|
1148
1152
|
const response = await api2.post(
|
|
1149
1153
|
"/api/v0/client-credentials",
|
|
1150
|
-
{
|
|
1154
|
+
{
|
|
1155
|
+
name,
|
|
1156
|
+
allowed_scopes: CREDENTIALS_SCOPES,
|
|
1157
|
+
...policy !== void 0 && { policy }
|
|
1158
|
+
},
|
|
1151
1159
|
{ authRequired: true, requiredScopes: ["credentials"] }
|
|
1152
1160
|
);
|
|
1153
1161
|
return {
|
|
@@ -1164,9 +1172,14 @@ async function deleteCredentialsOnServer(api2, clientId) {
|
|
|
1164
1172
|
async function setupClientCredentials({
|
|
1165
1173
|
api: api2,
|
|
1166
1174
|
name,
|
|
1167
|
-
credentialsBaseUrl
|
|
1175
|
+
credentialsBaseUrl,
|
|
1176
|
+
policy
|
|
1168
1177
|
}) {
|
|
1169
|
-
const { clientId, clientSecret } = await createCredentialsOnServer(
|
|
1178
|
+
const { clientId, clientSecret } = await createCredentialsOnServer(
|
|
1179
|
+
api2,
|
|
1180
|
+
name,
|
|
1181
|
+
policy
|
|
1182
|
+
);
|
|
1170
1183
|
try {
|
|
1171
1184
|
await withRetry({
|
|
1172
1185
|
action: () => storeClientCredentials({
|
|
@@ -1208,7 +1221,10 @@ async function resolveCredentialsBaseUrl(context) {
|
|
|
1208
1221
|
return getBaseUrlFromResolvedCredentials(resolvedCredentials) ?? getBaseUrlFromOptionsCredentials(context.options?.credentials) ?? context.options?.baseUrl;
|
|
1209
1222
|
}
|
|
1210
1223
|
var LoginSchema = z.object({
|
|
1211
|
-
timeout: z.string().optional().describe("Login timeout in seconds (default: 300)")
|
|
1224
|
+
timeout: z.string().optional().describe("Login timeout in seconds (default: 300)"),
|
|
1225
|
+
useApprovals: z.boolean().optional().describe(
|
|
1226
|
+
"Require approvals for actions performed with these credentials"
|
|
1227
|
+
)
|
|
1212
1228
|
}).describe("Log in to Zapier to access your account");
|
|
1213
1229
|
|
|
1214
1230
|
// src/plugins/login/index.ts
|
|
@@ -1302,7 +1318,9 @@ function emitLoginSuccess({
|
|
|
1302
1318
|
sdk.context.eventEmission.emit(
|
|
1303
1319
|
"platform.sdk.ApplicationLifecycleEvent",
|
|
1304
1320
|
buildApplicationLifecycleEvent(
|
|
1305
|
-
{
|
|
1321
|
+
{
|
|
1322
|
+
lifecycle_event_type: "login_success"
|
|
1323
|
+
},
|
|
1306
1324
|
{
|
|
1307
1325
|
customuser_id: profile.user_id,
|
|
1308
1326
|
account_id: profile.roles[0]?.account_id ?? null
|
|
@@ -1374,15 +1392,20 @@ var loginPlugin = definePlugin(
|
|
|
1374
1392
|
profile.email,
|
|
1375
1393
|
credentialsBaseUrl
|
|
1376
1394
|
);
|
|
1395
|
+
const useApprovals = options.useApprovals === true;
|
|
1377
1396
|
await setupClientCredentials({
|
|
1378
1397
|
api: scopedApi,
|
|
1379
1398
|
name: credentialName,
|
|
1380
|
-
credentialsBaseUrl
|
|
1399
|
+
credentialsBaseUrl,
|
|
1400
|
+
...useApprovals && { policy: EMPTY_POLICY }
|
|
1381
1401
|
});
|
|
1382
1402
|
await bestEffortClearLegacyJwtState();
|
|
1383
1403
|
console.log(
|
|
1384
1404
|
`\u2705 Credentials "${credentialName}" created and set as default. You are ready to use the Zapier SDK.`
|
|
1385
1405
|
);
|
|
1406
|
+
if (useApprovals) {
|
|
1407
|
+
console.log("\u{1F510} Approvals are enabled for these credentials.");
|
|
1408
|
+
}
|
|
1386
1409
|
emitLoginSuccess({ sdk: sdk2, profile });
|
|
1387
1410
|
}
|
|
1388
1411
|
})
|
|
@@ -3926,7 +3949,7 @@ definePlugin(
|
|
|
3926
3949
|
// package.json with { type: 'json' }
|
|
3927
3950
|
var package_default = {
|
|
3928
3951
|
name: "@zapier/zapier-sdk-cli",
|
|
3929
|
-
version: "0.
|
|
3952
|
+
version: "0.51.0"};
|
|
3930
3953
|
|
|
3931
3954
|
// src/sdk.ts
|
|
3932
3955
|
injectCliLogin(login_exports);
|
|
@@ -3954,7 +3977,7 @@ function createZapierCliSdk(options = {}) {
|
|
|
3954
3977
|
|
|
3955
3978
|
// package.json
|
|
3956
3979
|
var package_default2 = {
|
|
3957
|
-
version: "0.
|
|
3980
|
+
version: "0.51.0"};
|
|
3958
3981
|
|
|
3959
3982
|
// src/telemetry/builders.ts
|
|
3960
3983
|
function createCliBaseEvent(context = {}) {
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zapier/zapier-sdk-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.51.0",
|
|
4
4
|
"description": "Command line interface for Zapier SDK",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
"access": "public"
|
|
79
79
|
},
|
|
80
80
|
"dependencies": {
|
|
81
|
+
"@zapier/policy-schema": "0.11.0",
|
|
81
82
|
"@inquirer/search": "^3.2.2",
|
|
82
83
|
"@zapier/zapier-sdk": "workspace:*",
|
|
83
84
|
"@zapier/zapier-sdk-mcp": "workspace:*",
|
|
@@ -5,7 +5,7 @@ import { clearLegacyJwtState, hasLegacyJwtConfig, } from "../../login/legacy-jwt
|
|
|
5
5
|
import { getActiveCredentials, credentialsNameExists, deleteStoredClientCredentials, } from "../../login/credentials-store";
|
|
6
6
|
import { revokeCredentials } from "../../login/credentials-revoke";
|
|
7
7
|
import { runOauthFlow } from "../../utils/auth/oauth-flow";
|
|
8
|
-
import { setupClientCredentials } from "../../utils/auth/client-credentials";
|
|
8
|
+
import { EMPTY_POLICY, setupClientCredentials, } from "../../utils/auth/client-credentials";
|
|
9
9
|
import { resolveCredentialsBaseUrl } from "../auth/credentials-base-url";
|
|
10
10
|
import { LoginSchema } from "./schemas";
|
|
11
11
|
function toPkceCredentials(credentials) {
|
|
@@ -98,7 +98,9 @@ async function promptCredentialsName(email, baseUrl) {
|
|
|
98
98
|
return credentialName;
|
|
99
99
|
}
|
|
100
100
|
function emitLoginSuccess({ sdk, profile, }) {
|
|
101
|
-
sdk.context.eventEmission.emit("platform.sdk.ApplicationLifecycleEvent", buildApplicationLifecycleEvent({
|
|
101
|
+
sdk.context.eventEmission.emit("platform.sdk.ApplicationLifecycleEvent", buildApplicationLifecycleEvent({
|
|
102
|
+
lifecycle_event_type: "login_success",
|
|
103
|
+
}, {
|
|
102
104
|
customuser_id: profile.user_id,
|
|
103
105
|
account_id: profile.roles[0]?.account_id ?? null,
|
|
104
106
|
}));
|
|
@@ -168,13 +170,18 @@ export const loginPlugin = definePlugin((sdk) => createPluginMethod(sdk, {
|
|
|
168
170
|
console.log(`👤 Logged in as ${profile.email}`);
|
|
169
171
|
console.log("\nGenerating credentials so this machine can make authenticated requests on your behalf.");
|
|
170
172
|
const credentialName = await promptCredentialsName(profile.email, credentialsBaseUrl);
|
|
173
|
+
const useApprovals = options.useApprovals === true;
|
|
171
174
|
await setupClientCredentials({
|
|
172
175
|
api: scopedApi,
|
|
173
176
|
name: credentialName,
|
|
174
177
|
credentialsBaseUrl,
|
|
178
|
+
...(useApprovals && { policy: EMPTY_POLICY }),
|
|
175
179
|
});
|
|
176
180
|
await bestEffortClearLegacyJwtState();
|
|
177
181
|
console.log(`✅ Credentials "${credentialName}" created and set as default. You are ready to use the Zapier SDK.`);
|
|
182
|
+
if (useApprovals) {
|
|
183
|
+
console.log("🔐 Approvals are enabled for these credentials.");
|
|
184
|
+
}
|
|
178
185
|
emitLoginSuccess({ sdk, profile });
|
|
179
186
|
},
|
|
180
187
|
}));
|
|
@@ -6,5 +6,9 @@ export const LoginSchema = z
|
|
|
6
6
|
.string()
|
|
7
7
|
.optional()
|
|
8
8
|
.describe("Login timeout in seconds (default: 300)"),
|
|
9
|
+
useApprovals: z
|
|
10
|
+
.boolean()
|
|
11
|
+
.optional()
|
|
12
|
+
.describe("Require approvals for actions performed with these credentials"),
|
|
9
13
|
})
|
|
10
14
|
.describe("Log in to Zapier to access your account");
|
|
@@ -1,8 +1,18 @@
|
|
|
1
|
+
import type { Policy } from "@zapier/policy-schema";
|
|
1
2
|
import type { ApiClient } from "@zapier/zapier-sdk";
|
|
3
|
+
/**
|
|
4
|
+
* The canonical empty approvals policy. Attaching this to a credential at
|
|
5
|
+
* creation time tells the server that requests made with these credentials
|
|
6
|
+
* are subject to approval. Server-side enforcement decides which specific
|
|
7
|
+
* requests trigger the approval flow; the SDK only attaches the policy.
|
|
8
|
+
*/
|
|
9
|
+
export declare const EMPTY_POLICY: Policy;
|
|
2
10
|
export interface SetupClientCredentialsOptions {
|
|
3
11
|
api: ApiClient;
|
|
4
12
|
name: string;
|
|
5
13
|
credentialsBaseUrl?: string;
|
|
14
|
+
/** Optional policy document to attach to the new credential. */
|
|
15
|
+
policy?: Policy;
|
|
6
16
|
}
|
|
7
17
|
export interface SetupClientCredentialsResult {
|
|
8
18
|
clientId: string;
|
|
@@ -13,4 +23,4 @@ export interface SetupClientCredentialsResult {
|
|
|
13
23
|
* to roll back the orphan; if that rollback also fails, surface a
|
|
14
24
|
* manual-fix message and re-throw the original store error.
|
|
15
25
|
*/
|
|
16
|
-
export declare function setupClientCredentials({ api, name, credentialsBaseUrl, }: SetupClientCredentialsOptions): Promise<SetupClientCredentialsResult>;
|
|
26
|
+
export declare function setupClientCredentials({ api, name, credentialsBaseUrl, policy, }: SetupClientCredentialsOptions): Promise<SetupClientCredentialsResult>;
|
|
@@ -3,10 +3,24 @@ import { withRetry } from "../retry";
|
|
|
3
3
|
// "external" allows SDK operations (listing, running actions, etc.);
|
|
4
4
|
// "credentials" allows managing client credentials (list, create, delete).
|
|
5
5
|
const CREDENTIALS_SCOPES = ["external", "credentials"];
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* The canonical empty approvals policy. Attaching this to a credential at
|
|
8
|
+
* creation time tells the server that requests made with these credentials
|
|
9
|
+
* are subject to approval. Server-side enforcement decides which specific
|
|
10
|
+
* requests trigger the approval flow; the SDK only attaches the policy.
|
|
11
|
+
*/
|
|
12
|
+
export const EMPTY_POLICY = {
|
|
13
|
+
version: 2,
|
|
14
|
+
statements: [],
|
|
15
|
+
};
|
|
16
|
+
async function createCredentialsOnServer(api, name, policy) {
|
|
7
17
|
// The server wraps the credential in `{ data: { ... } }`; mirror the
|
|
8
18
|
// shape the SDK's own createClientCredentials plugin reads.
|
|
9
|
-
const response = await api.post("/api/v0/client-credentials", {
|
|
19
|
+
const response = await api.post("/api/v0/client-credentials", {
|
|
20
|
+
name,
|
|
21
|
+
allowed_scopes: CREDENTIALS_SCOPES,
|
|
22
|
+
...(policy !== undefined && { policy }),
|
|
23
|
+
}, { authRequired: true, requiredScopes: ["credentials"] });
|
|
10
24
|
return {
|
|
11
25
|
clientId: response.data.client_id,
|
|
12
26
|
clientSecret: response.data.client_secret,
|
|
@@ -24,8 +38,8 @@ async function deleteCredentialsOnServer(api, clientId) {
|
|
|
24
38
|
* to roll back the orphan; if that rollback also fails, surface a
|
|
25
39
|
* manual-fix message and re-throw the original store error.
|
|
26
40
|
*/
|
|
27
|
-
export async function setupClientCredentials({ api, name, credentialsBaseUrl, }) {
|
|
28
|
-
const { clientId, clientSecret } = await createCredentialsOnServer(api, name);
|
|
41
|
+
export async function setupClientCredentials({ api, name, credentialsBaseUrl, policy, }) {
|
|
42
|
+
const { clientId, clientSecret } = await createCredentialsOnServer(api, name, policy);
|
|
29
43
|
try {
|
|
30
44
|
await withRetry({
|
|
31
45
|
action: () => storeClientCredentials({
|
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { type ZapierSdk } from "@zapier/zapier-sdk";
|
|
3
|
+
/**
|
|
4
|
+
* Append a choice's `hint` to its name as dimmed parens, returning a new
|
|
5
|
+
* choice object. An array hint is joined with ", ". Used by every prompt
|
|
6
|
+
* backend that renders resolver-supplied choices so the dim styling lives
|
|
7
|
+
* in one place.
|
|
8
|
+
*
|
|
9
|
+
* Default-when-unset: if `hint` is not provided and the choice's `value`
|
|
10
|
+
* is a primitive (string or number), the value is auto-rendered as the
|
|
11
|
+
* hint. So a resolver returning `{ name: "Slack", value: "SlackCLIAPI" }`
|
|
12
|
+
* with no `hint` renders as `Slack (SlackCLIAPI)`. To opt out of the
|
|
13
|
+
* auto-default, set `hint: ""` or `hint: []` explicitly.
|
|
14
|
+
*
|
|
15
|
+
* Skip-when-equal: a hint that matches the rendered name verbatim is
|
|
16
|
+
* suppressed so primitive-enum resolvers (where `name === String(value)`)
|
|
17
|
+
* don't render "read (read)". Case differences still render both.
|
|
18
|
+
*/
|
|
19
|
+
export declare function renderChoiceLabel<T extends {
|
|
20
|
+
name: string;
|
|
21
|
+
value: unknown;
|
|
22
|
+
hint?: string | string[];
|
|
23
|
+
}>(choice: T): T;
|
|
3
24
|
export declare class SchemaParameterResolver {
|
|
4
25
|
private debug;
|
|
5
26
|
private spinner;
|
|
@@ -87,6 +87,40 @@ function coerceToSchemaType(value, schema) {
|
|
|
87
87
|
// ============================================================================
|
|
88
88
|
// Schema Parameter Resolver
|
|
89
89
|
// ============================================================================
|
|
90
|
+
/**
|
|
91
|
+
* Append a choice's `hint` to its name as dimmed parens, returning a new
|
|
92
|
+
* choice object. An array hint is joined with ", ". Used by every prompt
|
|
93
|
+
* backend that renders resolver-supplied choices so the dim styling lives
|
|
94
|
+
* in one place.
|
|
95
|
+
*
|
|
96
|
+
* Default-when-unset: if `hint` is not provided and the choice's `value`
|
|
97
|
+
* is a primitive (string or number), the value is auto-rendered as the
|
|
98
|
+
* hint. So a resolver returning `{ name: "Slack", value: "SlackCLIAPI" }`
|
|
99
|
+
* with no `hint` renders as `Slack (SlackCLIAPI)`. To opt out of the
|
|
100
|
+
* auto-default, set `hint: ""` or `hint: []` explicitly.
|
|
101
|
+
*
|
|
102
|
+
* Skip-when-equal: a hint that matches the rendered name verbatim is
|
|
103
|
+
* suppressed so primitive-enum resolvers (where `name === String(value)`)
|
|
104
|
+
* don't render "read (read)". Case differences still render both.
|
|
105
|
+
*/
|
|
106
|
+
export function renderChoiceLabel(choice) {
|
|
107
|
+
let effectiveHint = choice.hint;
|
|
108
|
+
if (effectiveHint === undefined &&
|
|
109
|
+
(typeof choice.value === "string" || typeof choice.value === "number")) {
|
|
110
|
+
effectiveHint = String(choice.value);
|
|
111
|
+
}
|
|
112
|
+
if (!effectiveHint ||
|
|
113
|
+
(Array.isArray(effectiveHint) && effectiveHint.length === 0)) {
|
|
114
|
+
return choice;
|
|
115
|
+
}
|
|
116
|
+
const hintText = Array.isArray(effectiveHint)
|
|
117
|
+
? effectiveHint.join(", ")
|
|
118
|
+
: effectiveHint;
|
|
119
|
+
if (hintText === choice.name) {
|
|
120
|
+
return choice;
|
|
121
|
+
}
|
|
122
|
+
return { ...choice, name: `${choice.name} ${chalk.dim(`(${hintText})`)}` };
|
|
123
|
+
}
|
|
90
124
|
export class SchemaParameterResolver {
|
|
91
125
|
constructor() {
|
|
92
126
|
this.debug = false;
|
|
@@ -513,7 +547,7 @@ export class SchemaParameterResolver {
|
|
|
513
547
|
}
|
|
514
548
|
const { items } = await this.unpackFetchResult(fetchResult, promptLabel);
|
|
515
549
|
const choicesConfig = resolver.prompt(items, searchParams);
|
|
516
|
-
const dataChoices = choicesConfig.choices ?? [];
|
|
550
|
+
const dataChoices = (choicesConfig.choices ?? []).map(renderChoiceLabel);
|
|
517
551
|
const capabilityHintMessages = await this.computeCapabilityHints(resolver, context);
|
|
518
552
|
const selected = await search({
|
|
519
553
|
message: choicesConfig.message,
|
|
@@ -730,6 +764,12 @@ export class SchemaParameterResolver {
|
|
|
730
764
|
while (true) {
|
|
731
765
|
const promptConfig = dynamicResolver.prompt(items, context.resolvedParams);
|
|
732
766
|
promptConfig.name = promptName;
|
|
767
|
+
// Fold any per-choice `hint` into the rendered name once, here, so
|
|
768
|
+
// both the search-backed list path and the checkbox path below
|
|
769
|
+
// pick up the dim styling without each having to know about hints.
|
|
770
|
+
if (promptConfig.choices) {
|
|
771
|
+
promptConfig.choices = promptConfig.choices.map(renderChoiceLabel);
|
|
772
|
+
}
|
|
733
773
|
// Friendlier than inquirer's default "No selectable choices. All
|
|
734
774
|
// choices are disabled." when the resolver returns no items (or
|
|
735
775
|
// filters everything out in `prompt`). Use ZapierCliValidationError
|