@runtypelabs/cli 2.59.0 → 2.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.
- package/dist/chunk-0-T9NWjH.js +3899 -0
- package/dist/chunk-0x7UKC1U.js +17 -0
- package/dist/chunk-2ySxXtcg.js +418 -0
- package/dist/chunk-3An_BRHv.js +501 -0
- package/dist/chunk-6uTxgdiY.js +16218 -0
- package/dist/chunk-87nRnNRG.js +1363 -0
- package/dist/chunk-B3wo8uRx.js +322 -0
- package/dist/chunk-BGp3ZdBy.js +560 -0
- package/dist/chunk-BJQv9Elp.js +107 -0
- package/dist/chunk-BOpO6xE-.js +6053 -0
- package/dist/chunk-BQXXCL8B.js +102 -0
- package/dist/chunk-BV-8isOd.js +34 -0
- package/dist/chunk-BVMhjGVe.js +826 -0
- package/dist/chunk-BW2fg46T.js +141 -0
- package/dist/chunk-BWJdY5Ag.js +36 -0
- package/dist/chunk-BYJOrLhh.js +302 -0
- package/dist/chunk-BYab8EVL.js +127 -0
- package/dist/chunk-BfEKvp7h.js +82 -0
- package/dist/chunk-BhgLSfH6.js +1123 -0
- package/dist/chunk-BirUxTtH.js +296 -0
- package/dist/chunk-BmB6UVZ9.js +1559 -0
- package/dist/chunk-BnWhIqW1.js +109 -0
- package/dist/chunk-Bpfnfk0t.js +123 -0
- package/dist/chunk-BrhgdnM3.js +108 -0
- package/dist/chunk-Bt0XAgX5.js +327 -0
- package/dist/chunk-Bu0FJr6S.js +84 -0
- package/dist/chunk-BvEoKpN3.js +255 -0
- package/dist/chunk-BxNJgYbE.js +28 -0
- package/dist/chunk-C1OFhd7F.js +6131 -0
- package/dist/chunk-C7e7WwbU.js +331 -0
- package/dist/chunk-CDTYP6bN.js +558 -0
- package/dist/chunk-CGDQoqDC.js +24 -0
- package/dist/chunk-CJraEBVd.js +127 -0
- package/dist/chunk-CQrNhOtv.js +40 -0
- package/dist/chunk-CW6AzBH6.js +128 -0
- package/dist/chunk-CXgL4w-9.js +317 -0
- package/dist/chunk-CZrqoPyf.js +233 -0
- package/dist/chunk-CcFCyqbB.js +83 -0
- package/dist/chunk-CdaIvO-y.js +485 -0
- package/dist/chunk-CehSXtgK.js +624 -0
- package/dist/chunk-Ciqkop65.js +218 -0
- package/dist/chunk-CoAWdSiE.js +43 -0
- package/dist/chunk-Crb4y7t4.js +830 -0
- package/dist/chunk-CrlqIfmb.js +337 -0
- package/dist/chunk-Cs4pwCQ-.js +324 -0
- package/dist/chunk-CwM_9y01.js +519 -0
- package/dist/chunk-CyRbIJg8.js +440 -0
- package/dist/chunk-D0OHsyMy.js +212 -0
- package/dist/chunk-D3y2bURs.js +1347 -0
- package/dist/chunk-D4_mJk03.js +2338 -0
- package/dist/chunk-D6C8rned.js +578 -0
- package/dist/chunk-D9ZbUnks.js +11 -0
- package/dist/chunk-DEPmLshX.js +834 -0
- package/dist/chunk-DFj1UPB2.js +330 -0
- package/dist/chunk-DGdFdZVf.js +197 -0
- package/dist/chunk-DGv7X9S_.js +63 -0
- package/dist/chunk-DJQ47WYZ.js +664 -0
- package/dist/chunk-DJw3O61j.js +1974 -0
- package/dist/chunk-DK4FbWVK.js +100 -0
- package/dist/chunk-DSRYhUus.js +993 -0
- package/dist/chunk-DajZ9Eg4.js +299 -0
- package/dist/chunk-Df4dunvU.js +195 -0
- package/dist/chunk-DjNTPhfO.js +481 -0
- package/dist/chunk-Dn8eaJuu.js +1042 -0
- package/dist/chunk-DwDWqSxM.js +637 -0
- package/dist/chunk-Dz7cEtxl.js +84 -0
- package/dist/chunk-E_0bgjrS.js +359 -0
- package/dist/chunk-KPYN2vUp.js +776 -0
- package/dist/chunk-KcqPQJBi.js +86 -0
- package/dist/chunk-N9H0JnoG.js +349 -0
- package/dist/chunk-NONFcXkn.js +728 -0
- package/dist/chunk-PrFjcpmH.js +256 -0
- package/dist/chunk-QSfNYiw9.js +11 -0
- package/dist/chunk-R265bzj9.js +226 -0
- package/dist/chunk-X9V_r6jM.js +166 -0
- package/dist/chunk-ZBtPUtyA.js +55 -0
- package/dist/chunk-ZCTfmOs7.js +4939 -0
- package/dist/chunk-h6oavj0t.js +97 -0
- package/dist/chunk-i7DwkvvD.js +42 -0
- package/dist/chunk-mG-4eZ6S.js +203 -0
- package/dist/chunk-o0ygUbCf.js +313 -0
- package/dist/chunk-ucu5lrDZ.js +5715 -0
- package/dist/index.js +11367 -73764
- package/package.json +6 -6
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { t as isTTY } from "./index.js";
|
|
3
|
+
import { ConfirmPrompt, DataList, EntityCard, MutationResult, React, mutationResultProps, render, useEffect, useMutationState, useState } from "./chunk-CoAWdSiE.js";
|
|
4
|
+
import { r as createCliClient } from "./chunk-BW2fg46T.js";
|
|
5
|
+
import { n as ensureAuth } from "./chunk-CJraEBVd.js";
|
|
6
|
+
import { a as printJson, i as printDetail } from "./chunk-CcFCyqbB.js";
|
|
7
|
+
import { Command } from "commander";
|
|
8
|
+
import chalk from "chalk";
|
|
9
|
+
// src/commands/secrets.ts
|
|
10
|
+
/**
|
|
11
|
+
* Read a secret value from stdin without echoing it back. Used when `--value`
|
|
12
|
+
* is not supplied so the value never appears in shell history or terminal
|
|
13
|
+
* scrollback in the same way an inline flag would.
|
|
14
|
+
*/
|
|
15
|
+
async function readSecretFromStdin() {
|
|
16
|
+
if (process.stdin.isTTY) throw new Error("No secret value provided. Pass --value <v> or pipe the value on stdin.");
|
|
17
|
+
const chunks = [];
|
|
18
|
+
for await (const chunk of process.stdin) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
19
|
+
const value = Buffer.concat(chunks).toString("utf-8").replace(/\r?\n$/, "");
|
|
20
|
+
if (value.length === 0) throw new Error("No secret value provided. Pass --value <v> or pipe the value on stdin.");
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
const secretsCommand = new Command("secrets").description("Manage secrets (values are write-only and never displayed)");
|
|
24
|
+
secretsCommand.command("list").description("List your secrets (metadata only)").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (options) => {
|
|
25
|
+
const apiKey = await ensureAuth();
|
|
26
|
+
if (!apiKey) return;
|
|
27
|
+
const client = createCliClient(apiKey);
|
|
28
|
+
if (!isTTY(options) || options.json) {
|
|
29
|
+
try {
|
|
30
|
+
const data = await client.get("/secrets");
|
|
31
|
+
if (options.json) {
|
|
32
|
+
printJson(data);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const secrets = data.data ?? [];
|
|
36
|
+
if (secrets.length === 0) {
|
|
37
|
+
console.log(chalk.gray("No secrets found"));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
console.log(chalk.cyan("Your Secrets:"));
|
|
41
|
+
for (const s of secrets) {
|
|
42
|
+
const status = s.status === "active" ? chalk.green(s.status) : chalk.yellow(s.status);
|
|
43
|
+
const desc = s.description ? chalk.gray(` — ${s.description}`) : "";
|
|
44
|
+
console.log(` ${chalk.green(s.id)} ${s.key} [${status}] v${s.version}${desc}`);
|
|
45
|
+
}
|
|
46
|
+
console.log(chalk.dim(`\n Total: ${data.total ?? secrets.length} secrets`));
|
|
47
|
+
} catch (error) {
|
|
48
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
49
|
+
console.error(chalk.red(`Failed to fetch secrets: ${message}`));
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const App = () => {
|
|
55
|
+
const [items, setItems] = useState(null);
|
|
56
|
+
const [error, setError] = useState(null);
|
|
57
|
+
const [total, setTotal] = useState();
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
client.get("/secrets").then((res) => {
|
|
60
|
+
setItems(res.data ?? []);
|
|
61
|
+
setTotal(res.total);
|
|
62
|
+
}).catch((err) => setError(err instanceof Error ? err : new Error(String(err))));
|
|
63
|
+
}, []);
|
|
64
|
+
return React.createElement(DataList, {
|
|
65
|
+
title: "Your Secrets",
|
|
66
|
+
items,
|
|
67
|
+
error,
|
|
68
|
+
loading: items === null && error === null,
|
|
69
|
+
total,
|
|
70
|
+
emptyMessage: "No secrets found",
|
|
71
|
+
renderCard: (item) => {
|
|
72
|
+
const s = item;
|
|
73
|
+
return React.createElement(EntityCard, { fields: [
|
|
74
|
+
{
|
|
75
|
+
label: "ID",
|
|
76
|
+
value: s.id,
|
|
77
|
+
color: "green"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
label: "Key",
|
|
81
|
+
value: s.key
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
label: "Status",
|
|
85
|
+
value: s.status
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
label: "Version",
|
|
89
|
+
value: String(s.version)
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
label: "Description",
|
|
93
|
+
value: s.description,
|
|
94
|
+
color: "gray"
|
|
95
|
+
}
|
|
96
|
+
] });
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
const { waitUntilExit } = render(React.createElement(App));
|
|
101
|
+
await waitUntilExit();
|
|
102
|
+
});
|
|
103
|
+
secretsCommand.command("get <id>").description("Get secret metadata (value is never displayed)").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (id, options) => {
|
|
104
|
+
const apiKey = await ensureAuth();
|
|
105
|
+
if (!apiKey) return;
|
|
106
|
+
const client = createCliClient(apiKey);
|
|
107
|
+
if (!isTTY(options) || options.json) {
|
|
108
|
+
try {
|
|
109
|
+
const data = await client.get(`/secrets/${id}`);
|
|
110
|
+
if (options.json) {
|
|
111
|
+
printJson(data);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const s = data.data;
|
|
115
|
+
printDetail("Secret", [
|
|
116
|
+
{
|
|
117
|
+
label: "ID",
|
|
118
|
+
value: s.id
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
label: "Key",
|
|
122
|
+
value: s.key
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
label: "Description",
|
|
126
|
+
value: s.description
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
label: "Status",
|
|
130
|
+
value: s.status
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
label: "Version",
|
|
134
|
+
value: s.version
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
label: "Value Preview",
|
|
138
|
+
value: s.valuePreview
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
label: "Last Rotated",
|
|
142
|
+
value: s.lastRotatedAt
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
label: "Created",
|
|
146
|
+
value: s.createdAt
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
label: "Updated",
|
|
150
|
+
value: s.updatedAt
|
|
151
|
+
}
|
|
152
|
+
]);
|
|
153
|
+
} catch (error) {
|
|
154
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
155
|
+
console.error(chalk.red(`Failed to fetch secret: ${message}`));
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const App = () => {
|
|
161
|
+
const mutation = useMutationState();
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
const run = async () => {
|
|
164
|
+
try {
|
|
165
|
+
const s = (await client.get(`/secrets/${id}`)).data;
|
|
166
|
+
mutation.succeed(React.createElement(EntityCard, { fields: [
|
|
167
|
+
{
|
|
168
|
+
label: "ID",
|
|
169
|
+
value: s.id,
|
|
170
|
+
color: "green"
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
label: "Key",
|
|
174
|
+
value: s.key
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
label: "Description",
|
|
178
|
+
value: s.description
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
label: "Status",
|
|
182
|
+
value: s.status
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
label: "Version",
|
|
186
|
+
value: String(s.version)
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
label: "Value Preview",
|
|
190
|
+
value: s.valuePreview
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
label: "Created",
|
|
194
|
+
value: s.createdAt
|
|
195
|
+
}
|
|
196
|
+
] }));
|
|
197
|
+
} catch (err) {
|
|
198
|
+
mutation.fail(err);
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
run();
|
|
202
|
+
}, []);
|
|
203
|
+
return React.createElement(MutationResult, {
|
|
204
|
+
...mutationResultProps(mutation.state),
|
|
205
|
+
loadingLabel: "Fetching secret...",
|
|
206
|
+
successMessage: "Secret"
|
|
207
|
+
});
|
|
208
|
+
};
|
|
209
|
+
const { waitUntilExit } = render(React.createElement(App));
|
|
210
|
+
await waitUntilExit();
|
|
211
|
+
});
|
|
212
|
+
secretsCommand.command("create").description("Create a new secret (provide the value via --value or stdin)").requiredOption("-k, --key <key>", "Secret key (alphanumeric/underscore, starts with a letter)").option("--value <value>", "Secret value (omit to read from stdin without echo)").option("-d, --description <text>", "Secret description").option("--product-tenant-id <id>", "Scope the secret to a Product Tenant (tnt_*). Omit for an org-level secret; a scoped secret requires a value.").option("--end-user-id <id>", "Scope the secret to an End User (eu_*); its enclosing tenant is derived server-side. Omit for an org-level secret; a scoped secret requires a value.").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (options) => {
|
|
213
|
+
const apiKey = await ensureAuth();
|
|
214
|
+
if (!apiKey) return;
|
|
215
|
+
let value = options.value;
|
|
216
|
+
if (value === void 0 && !process.stdin.isTTY) try {
|
|
217
|
+
value = await readSecretFromStdin();
|
|
218
|
+
} catch (error) {
|
|
219
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
220
|
+
console.error(chalk.red(`Failed to read secret value: ${message}`));
|
|
221
|
+
process.exit(1);
|
|
222
|
+
}
|
|
223
|
+
const client = createCliClient(apiKey);
|
|
224
|
+
const body = {
|
|
225
|
+
key: options.key,
|
|
226
|
+
description: options.description
|
|
227
|
+
};
|
|
228
|
+
if (value !== void 0) body.value = value;
|
|
229
|
+
if (options.productTenantId !== void 0) body.productTenantId = options.productTenantId;
|
|
230
|
+
if (options.endUserId !== void 0) body.endUserId = options.endUserId;
|
|
231
|
+
if (!isTTY(options) || options.json) {
|
|
232
|
+
try {
|
|
233
|
+
const data = await client.post("/secrets", body);
|
|
234
|
+
if (options.json) {
|
|
235
|
+
printJson(data);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const s = data.data;
|
|
239
|
+
console.log(chalk.green("Secret created"));
|
|
240
|
+
console.log(` ID: ${chalk.green(s.id)}`);
|
|
241
|
+
console.log(` Key: ${s.key}`);
|
|
242
|
+
console.log(` Status: ${s.status}`);
|
|
243
|
+
} catch (error) {
|
|
244
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
245
|
+
console.error(chalk.red(`Failed to create secret: ${message}`));
|
|
246
|
+
process.exit(1);
|
|
247
|
+
}
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
const App = () => {
|
|
251
|
+
const mutation = useMutationState();
|
|
252
|
+
useEffect(() => {
|
|
253
|
+
const run = async () => {
|
|
254
|
+
try {
|
|
255
|
+
const data = await client.post("/secrets", body);
|
|
256
|
+
mutation.succeed(React.createElement(EntityCard, { fields: [
|
|
257
|
+
{
|
|
258
|
+
label: "ID",
|
|
259
|
+
value: data.data.id,
|
|
260
|
+
color: "green"
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
label: "Key",
|
|
264
|
+
value: data.data.key
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
label: "Status",
|
|
268
|
+
value: data.data.status
|
|
269
|
+
}
|
|
270
|
+
] }));
|
|
271
|
+
} catch (err) {
|
|
272
|
+
mutation.fail(err);
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
run();
|
|
276
|
+
}, []);
|
|
277
|
+
return React.createElement(MutationResult, {
|
|
278
|
+
...mutationResultProps(mutation.state),
|
|
279
|
+
loadingLabel: "Creating secret...",
|
|
280
|
+
successMessage: "Secret created"
|
|
281
|
+
});
|
|
282
|
+
};
|
|
283
|
+
const { waitUntilExit } = render(React.createElement(App));
|
|
284
|
+
await waitUntilExit();
|
|
285
|
+
});
|
|
286
|
+
secretsCommand.command("update <id>").description("Update or rotate a secret (value via --value or stdin)").option("--value <value>", "New secret value (omit to read from stdin without echo)").option("-d, --description <text>", "New secret description").option("--expected-version <n>", "Expected current version for optimistic concurrency").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (id, options) => {
|
|
287
|
+
const apiKey = await ensureAuth();
|
|
288
|
+
if (!apiKey) return;
|
|
289
|
+
let value = options.value;
|
|
290
|
+
if (value === void 0 && !process.stdin.isTTY) try {
|
|
291
|
+
value = await readSecretFromStdin();
|
|
292
|
+
} catch (error) {
|
|
293
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
294
|
+
console.error(chalk.red(`Failed to read secret value: ${message}`));
|
|
295
|
+
process.exit(1);
|
|
296
|
+
}
|
|
297
|
+
if (value === void 0 && options.description === void 0) {
|
|
298
|
+
console.error(chalk.red("Error: provide at least one of --value (or piped stdin) or --description"));
|
|
299
|
+
process.exit(1);
|
|
300
|
+
}
|
|
301
|
+
const client = createCliClient(apiKey);
|
|
302
|
+
const body = {};
|
|
303
|
+
if (value !== void 0) body.value = value;
|
|
304
|
+
if (options.description !== void 0) body.description = options.description;
|
|
305
|
+
if (options.expectedVersion !== void 0) {
|
|
306
|
+
const parsedVersion = parseInt(options.expectedVersion, 10);
|
|
307
|
+
if (Number.isNaN(parsedVersion)) {
|
|
308
|
+
console.error(chalk.red("Error: --expected-version must be a number"));
|
|
309
|
+
process.exit(1);
|
|
310
|
+
}
|
|
311
|
+
body.expectedVersion = parsedVersion;
|
|
312
|
+
}
|
|
313
|
+
if (!isTTY(options) || options.json) {
|
|
314
|
+
try {
|
|
315
|
+
const data = await client.put(`/secrets/${id}`, body);
|
|
316
|
+
if (options.json) {
|
|
317
|
+
printJson(data);
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
const s = data.data;
|
|
321
|
+
console.log(chalk.green("Secret updated"));
|
|
322
|
+
console.log(` ID: ${chalk.green(s.id)}`);
|
|
323
|
+
console.log(` Key: ${s.key}`);
|
|
324
|
+
console.log(` Version: ${s.version}`);
|
|
325
|
+
} catch (error) {
|
|
326
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
327
|
+
console.error(chalk.red(`Failed to update secret: ${message}`));
|
|
328
|
+
process.exit(1);
|
|
329
|
+
}
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
const App = () => {
|
|
333
|
+
const mutation = useMutationState();
|
|
334
|
+
useEffect(() => {
|
|
335
|
+
const run = async () => {
|
|
336
|
+
try {
|
|
337
|
+
const data = await client.put(`/secrets/${id}`, body);
|
|
338
|
+
mutation.succeed(React.createElement(EntityCard, { fields: [
|
|
339
|
+
{
|
|
340
|
+
label: "ID",
|
|
341
|
+
value: data.data.id,
|
|
342
|
+
color: "green"
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
label: "Key",
|
|
346
|
+
value: data.data.key
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
label: "Version",
|
|
350
|
+
value: String(data.data.version)
|
|
351
|
+
}
|
|
352
|
+
] }));
|
|
353
|
+
} catch (err) {
|
|
354
|
+
mutation.fail(err);
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
run();
|
|
358
|
+
}, []);
|
|
359
|
+
return React.createElement(MutationResult, {
|
|
360
|
+
...mutationResultProps(mutation.state),
|
|
361
|
+
loadingLabel: "Updating secret...",
|
|
362
|
+
successMessage: "Secret updated"
|
|
363
|
+
});
|
|
364
|
+
};
|
|
365
|
+
const { waitUntilExit } = render(React.createElement(App));
|
|
366
|
+
await waitUntilExit();
|
|
367
|
+
});
|
|
368
|
+
secretsCommand.command("delete <id>").description("Delete a secret").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").option("--yes", "Skip confirmation").action(async (id, options) => {
|
|
369
|
+
const apiKey = await ensureAuth();
|
|
370
|
+
if (!apiKey) return;
|
|
371
|
+
const client = createCliClient(apiKey);
|
|
372
|
+
if (!isTTY(options)) {
|
|
373
|
+
try {
|
|
374
|
+
await client.secrets.delete(id);
|
|
375
|
+
console.log(chalk.green("Secret deleted"));
|
|
376
|
+
} catch (error) {
|
|
377
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
378
|
+
console.error(chalk.red(`Failed to delete secret: ${message}`));
|
|
379
|
+
process.exit(1);
|
|
380
|
+
}
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
const runDelete = () => {
|
|
384
|
+
const App = () => {
|
|
385
|
+
const mutation = useMutationState();
|
|
386
|
+
useEffect(() => {
|
|
387
|
+
client.delete(`/secrets/${id}`).then(() => {
|
|
388
|
+
mutation.succeed();
|
|
389
|
+
}).catch((err) => {
|
|
390
|
+
mutation.fail(err);
|
|
391
|
+
});
|
|
392
|
+
}, []);
|
|
393
|
+
return React.createElement(MutationResult, {
|
|
394
|
+
...mutationResultProps(mutation.state),
|
|
395
|
+
loadingLabel: "Deleting secret...",
|
|
396
|
+
successMessage: "Secret deleted"
|
|
397
|
+
});
|
|
398
|
+
};
|
|
399
|
+
return App;
|
|
400
|
+
};
|
|
401
|
+
if (options.yes) {
|
|
402
|
+
const { waitUntilExit } = render(React.createElement(runDelete()));
|
|
403
|
+
await waitUntilExit();
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
if (!await new Promise((resolve) => {
|
|
407
|
+
const { unmount } = render(React.createElement(ConfirmPrompt, {
|
|
408
|
+
message: `Delete secret ${id}?`,
|
|
409
|
+
defaultValue: false,
|
|
410
|
+
onConfirm: (result) => {
|
|
411
|
+
resolve(result);
|
|
412
|
+
unmount();
|
|
413
|
+
}
|
|
414
|
+
}));
|
|
415
|
+
})) return;
|
|
416
|
+
const { waitUntilExit } = render(React.createElement(runDelete()));
|
|
417
|
+
await waitUntilExit();
|
|
418
|
+
});
|
|
419
|
+
secretsCommand.command("check <keys...>").description("Check which secret keys exist, are missing, or revoked").option("--json", "Output as JSON").option("--tty", "Force TTY mode").option("--no-tty", "Force non-TTY mode").action(async (keys, options) => {
|
|
420
|
+
const apiKey = await ensureAuth();
|
|
421
|
+
if (!apiKey) return;
|
|
422
|
+
const client = createCliClient(apiKey);
|
|
423
|
+
const body = { keys };
|
|
424
|
+
if (!isTTY(options) || options.json) {
|
|
425
|
+
try {
|
|
426
|
+
const data = await client.post("/secrets/check", body);
|
|
427
|
+
if (options.json) {
|
|
428
|
+
printJson(data);
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
console.log(chalk.cyan("Secret Check:"));
|
|
432
|
+
if (data.found.length > 0) console.log(` ${chalk.green("found")}: ${data.found.join(", ")}`);
|
|
433
|
+
if (data.missing.length > 0) console.log(` ${chalk.yellow("missing")}: ${data.missing.join(", ")}`);
|
|
434
|
+
if (data.revoked.length > 0) console.log(` ${chalk.red("revoked")}: ${data.revoked.join(", ")}`);
|
|
435
|
+
} catch (error) {
|
|
436
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
437
|
+
console.error(chalk.red(`Failed to check secrets: ${message}`));
|
|
438
|
+
process.exit(1);
|
|
439
|
+
}
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
const App = () => {
|
|
443
|
+
const mutation = useMutationState();
|
|
444
|
+
useEffect(() => {
|
|
445
|
+
const run = async () => {
|
|
446
|
+
try {
|
|
447
|
+
const data = await client.post("/secrets/check", body);
|
|
448
|
+
mutation.succeed(React.createElement(EntityCard, { fields: [
|
|
449
|
+
{
|
|
450
|
+
label: "Found",
|
|
451
|
+
value: data.found.join(", ") || "(none)",
|
|
452
|
+
color: "green"
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
label: "Missing",
|
|
456
|
+
value: data.missing.join(", ") || "(none)",
|
|
457
|
+
color: "yellow"
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
label: "Revoked",
|
|
461
|
+
value: data.revoked.join(", ") || "(none)",
|
|
462
|
+
color: "red"
|
|
463
|
+
}
|
|
464
|
+
] }));
|
|
465
|
+
} catch (err) {
|
|
466
|
+
mutation.fail(err);
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
run();
|
|
470
|
+
}, []);
|
|
471
|
+
return React.createElement(MutationResult, {
|
|
472
|
+
...mutationResultProps(mutation.state),
|
|
473
|
+
loadingLabel: "Checking secrets...",
|
|
474
|
+
successMessage: "Secret check"
|
|
475
|
+
});
|
|
476
|
+
};
|
|
477
|
+
const { waitUntilExit } = render(React.createElement(App));
|
|
478
|
+
await waitUntilExit();
|
|
479
|
+
});
|
|
480
|
+
export { secretsCommand };
|
|
481
|
+
|