@kitsy/cnos-cli 1.1.0 → 1.1.1
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/index.js +189 -55
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -15,6 +15,7 @@ var COMMAND_OPTION_KEYS_WITH_VALUE = /* @__PURE__ */ new Set([
|
|
|
15
15
|
"--to",
|
|
16
16
|
"--provider",
|
|
17
17
|
"--passphrase",
|
|
18
|
+
"--vault",
|
|
18
19
|
"--inherit"
|
|
19
20
|
]);
|
|
20
21
|
var COMMAND_FLAG_KEYS = /* @__PURE__ */ new Set(["--flatten", "--public", "--local", "--remote", "--ref"]);
|
|
@@ -99,6 +100,10 @@ function parseArgs(argv) {
|
|
|
99
100
|
options.json = true;
|
|
100
101
|
continue;
|
|
101
102
|
}
|
|
103
|
+
if (token === "--verbose") {
|
|
104
|
+
options.verbose = true;
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
102
107
|
if (token === "--help" || token === "-h") {
|
|
103
108
|
options.help = true;
|
|
104
109
|
continue;
|
|
@@ -181,12 +186,13 @@ function printJson(value) {
|
|
|
181
186
|
}
|
|
182
187
|
|
|
183
188
|
// src/services/writes.ts
|
|
184
|
-
import { randomUUID } from "crypto";
|
|
185
189
|
import { mkdir, readFile, rm, writeFile } from "fs/promises";
|
|
186
190
|
import path from "path";
|
|
187
191
|
import {
|
|
192
|
+
createSecretVault,
|
|
188
193
|
parseYaml,
|
|
189
194
|
resolveConfigDocumentPath,
|
|
195
|
+
resolveSecretPassphrase,
|
|
190
196
|
resolveSecretStoreRoot,
|
|
191
197
|
stringifyYaml,
|
|
192
198
|
writeLocalSecret
|
|
@@ -315,6 +321,22 @@ async function defineValue(namespace, configPath, rawValue, options = {}) {
|
|
|
315
321
|
value: parsedValue
|
|
316
322
|
};
|
|
317
323
|
}
|
|
324
|
+
async function createVault(vault, options = {}) {
|
|
325
|
+
const passphrase = options.passphrase ?? resolveSecretPassphrase(vault, options.processEnv ?? process.env);
|
|
326
|
+
if (!passphrase) {
|
|
327
|
+
throw new Error("Vault creation requires --passphrase or CNOS_SECRET_PASSPHRASE");
|
|
328
|
+
}
|
|
329
|
+
const normalizedVault = vault.trim() || "default";
|
|
330
|
+
const filePath = await createSecretVault(
|
|
331
|
+
resolveSecretStoreRoot(options.processEnv),
|
|
332
|
+
normalizedVault,
|
|
333
|
+
passphrase
|
|
334
|
+
);
|
|
335
|
+
return {
|
|
336
|
+
vault: normalizedVault,
|
|
337
|
+
filePath
|
|
338
|
+
};
|
|
339
|
+
}
|
|
318
340
|
async function setSecret(configPath, rawValue, options = {}) {
|
|
319
341
|
const runtime = await createRuntimeService(options);
|
|
320
342
|
const workspaceRoot = getSelectedWorkspaceRoot(options, runtime);
|
|
@@ -322,25 +344,20 @@ async function setSecret(configPath, rawValue, options = {}) {
|
|
|
322
344
|
const filePath = resolveConfigDocumentPath(workspaceRoot, "secret", configPath, profile);
|
|
323
345
|
const document = await readYamlDocument(filePath);
|
|
324
346
|
const mode = options.mode ?? "local";
|
|
347
|
+
const vault = options.vault?.trim() || "default";
|
|
325
348
|
let reference;
|
|
326
349
|
let storePath;
|
|
327
350
|
if (mode === "local") {
|
|
328
|
-
const passphrase = options.passphrase ?? options.processEnv
|
|
351
|
+
const passphrase = options.passphrase ?? resolveSecretPassphrase(vault, options.processEnv ?? process.env);
|
|
329
352
|
if (!passphrase) {
|
|
330
|
-
throw new Error("
|
|
353
|
+
throw new Error(`Vault "${vault}" requires --passphrase or CNOS_SECRET_PASSPHRASE`);
|
|
331
354
|
}
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
runtime.manifest.project.name,
|
|
335
|
-
runtime.graph.workspace.workspaceId,
|
|
336
|
-
profileSegment,
|
|
337
|
-
...configPath.split("."),
|
|
338
|
-
randomUUID()
|
|
339
|
-
].map((segment) => segment.replace(/[^A-Za-z0-9._-]+/g, "-")).join("/");
|
|
340
|
-
storePath = await writeLocalSecret(resolveSecretStoreRoot(options.processEnv), ref, rawValue, passphrase);
|
|
355
|
+
const ref = configPath;
|
|
356
|
+
storePath = await writeLocalSecret(resolveSecretStoreRoot(options.processEnv), ref, rawValue, passphrase, vault);
|
|
341
357
|
reference = {
|
|
342
358
|
provider: "local",
|
|
343
|
-
ref
|
|
359
|
+
ref,
|
|
360
|
+
vault
|
|
344
361
|
};
|
|
345
362
|
} else {
|
|
346
363
|
reference = {
|
|
@@ -355,6 +372,7 @@ async function setSecret(configPath, rawValue, options = {}) {
|
|
|
355
372
|
filePath,
|
|
356
373
|
provider: reference.provider,
|
|
357
374
|
ref: reference.ref,
|
|
375
|
+
...reference.vault ? { vault: reference.vault } : {},
|
|
358
376
|
...storePath ? { storePath } : {}
|
|
359
377
|
};
|
|
360
378
|
}
|
|
@@ -376,7 +394,13 @@ async function deleteSecret(configPath, options = {}) {
|
|
|
376
394
|
let removedStore;
|
|
377
395
|
const secretRef = metadata?.secretRef;
|
|
378
396
|
if (isSecretReference(secretRef) && secretRef.provider === "local") {
|
|
379
|
-
const storePath = path.join(
|
|
397
|
+
const storePath = path.join(
|
|
398
|
+
resolveSecretStoreRoot(options.processEnv),
|
|
399
|
+
"vaults",
|
|
400
|
+
secretRef.vault ?? "default",
|
|
401
|
+
"store",
|
|
402
|
+
...secretRef.ref.split("/")
|
|
403
|
+
).concat(".json");
|
|
380
404
|
await rm(storePath, { force: true });
|
|
381
405
|
removedStore = storePath;
|
|
382
406
|
}
|
|
@@ -608,7 +632,12 @@ async function runExportEnv(options = {}) {
|
|
|
608
632
|
const env = isPublic ? runtime.toPublicEnv({
|
|
609
633
|
...framework ? { framework } : {},
|
|
610
634
|
...prefix ? { prefix } : {}
|
|
611
|
-
}) :
|
|
635
|
+
}) : Object.fromEntries(
|
|
636
|
+
Object.entries(runtime.manifest.envMapping.explicit).map(([envVar, logicalKey]) => [envVar, runtime.read(logicalKey)]).filter((entry) => entry[1] !== void 0).map(([envVar, value]) => [
|
|
637
|
+
envVar,
|
|
638
|
+
typeof value === "string" ? value : typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" ? String(value) : JSON.stringify(value)
|
|
639
|
+
])
|
|
640
|
+
);
|
|
612
641
|
if (options.json) {
|
|
613
642
|
return printJson(env);
|
|
614
643
|
}
|
|
@@ -645,6 +674,10 @@ var GLOBAL_OPTIONS = [
|
|
|
645
674
|
flag: "--json",
|
|
646
675
|
description: "Emit JSON output for commands that support structured responses."
|
|
647
676
|
},
|
|
677
|
+
{
|
|
678
|
+
flag: "--verbose",
|
|
679
|
+
description: "Print full stack traces and verbose diagnostics for command failures."
|
|
680
|
+
},
|
|
648
681
|
{
|
|
649
682
|
flag: "--help, -h",
|
|
650
683
|
description: "Show command help."
|
|
@@ -810,18 +843,18 @@ var COMMANDS = [
|
|
|
810
843
|
{
|
|
811
844
|
id: "use",
|
|
812
845
|
summary: "Persist repo-local CLI defaults such as workspace and profile.",
|
|
813
|
-
usage: "cnos use [--workspace <id>] [--profile <name>] [--global-root <path>] [--root <path>] [--json]",
|
|
814
|
-
description: "
|
|
815
|
-
examples: ["cnos use --workspace api --profile stage", "cnos use --global-root ~/.cnos"]
|
|
846
|
+
usage: "cnos use [show] [--workspace <id>] [--profile <name>] [--global-root <path>] [--root <path>] [--json]",
|
|
847
|
+
description: "Shows the current repo-local CLI context by default, or writes .cnos-workspace.yml when workspace/profile/global-root flags are provided.",
|
|
848
|
+
examples: ["cnos use show", "cnos use --workspace api --profile stage", "cnos use --global-root ~/.cnos"]
|
|
816
849
|
},
|
|
817
850
|
{
|
|
818
851
|
id: "list",
|
|
819
852
|
summary: "List resolved config entries.",
|
|
820
|
-
usage: "cnos list [value|secret|meta|all] [--prefix <path>] [global-options]",
|
|
821
|
-
description: "Lists
|
|
853
|
+
usage: "cnos list [value|secret|meta|env|public|all] [--prefix <path>] [global-options]",
|
|
854
|
+
description: "Lists stored config or derived projections across one namespace or the full effective graph, with optional prefix filtering.",
|
|
822
855
|
options: [
|
|
823
856
|
{
|
|
824
|
-
flag: "--namespace <value|secret|meta|all>",
|
|
857
|
+
flag: "--namespace <value|secret|meta|env|public|all>",
|
|
825
858
|
description: "Explicit namespace selector when not using a positional namespace argument."
|
|
826
859
|
},
|
|
827
860
|
{
|
|
@@ -829,7 +862,7 @@ var COMMANDS = [
|
|
|
829
862
|
description: "Filter list output to entries whose logical keys begin with this prefix."
|
|
830
863
|
}
|
|
831
864
|
],
|
|
832
|
-
examples: ["cnos list", "cnos list value --prefix app.", "cnos list --namespace secret"]
|
|
865
|
+
examples: ["cnos list", "cnos list value --prefix app.", "cnos list env", "cnos list --namespace secret"]
|
|
833
866
|
},
|
|
834
867
|
{
|
|
835
868
|
id: "profile",
|
|
@@ -879,9 +912,19 @@ var COMMANDS = [
|
|
|
879
912
|
{
|
|
880
913
|
id: "secret set",
|
|
881
914
|
summary: "Write a secret securely.",
|
|
882
|
-
usage: "cnos secret set <path> <value> [--local|--remote|--ref] [--provider <name>] [--passphrase <value>] [global-options]",
|
|
883
|
-
description: "Writes a secret reference into the repo and, when --local is used, stores encrypted secret material outside the repo under ~/.cnos/secrets
|
|
884
|
-
examples: [
|
|
915
|
+
usage: "cnos secret set <path> <value> [--local|--remote|--ref] [--vault <name>] [--provider <name>] [--passphrase <value>] [global-options]",
|
|
916
|
+
description: "Writes a secret reference into the repo and, when --local is used, stores encrypted secret material outside the repo under ~/.cnos/secrets/vaults/<vault>.",
|
|
917
|
+
examples: [
|
|
918
|
+
"cnos secret create vault db --passphrase dev-pass",
|
|
919
|
+
"cnos secret set app.token super-secret --local --vault db --passphrase dev-pass"
|
|
920
|
+
]
|
|
921
|
+
},
|
|
922
|
+
{
|
|
923
|
+
id: "secret create vault",
|
|
924
|
+
summary: "Create a local secret vault.",
|
|
925
|
+
usage: "cnos secret create vault <name> --passphrase <value> [global-options]",
|
|
926
|
+
description: "Creates a named local secret vault under ~/.cnos/secrets/vaults.",
|
|
927
|
+
examples: ["cnos secret create vault db --passphrase dev-pass"]
|
|
885
928
|
},
|
|
886
929
|
{
|
|
887
930
|
id: "secret list",
|
|
@@ -1363,25 +1406,54 @@ function printValue(value, json = false) {
|
|
|
1363
1406
|
|
|
1364
1407
|
// src/services/listing.ts
|
|
1365
1408
|
import { flattenObject as flattenObject2 } from "@kitsy/cnos/internal";
|
|
1409
|
+
function matchesPrefix(key, prefix) {
|
|
1410
|
+
if (!prefix) {
|
|
1411
|
+
return true;
|
|
1412
|
+
}
|
|
1413
|
+
return key.startsWith(prefix) || key.split(".").slice(1).join(".").startsWith(prefix);
|
|
1414
|
+
}
|
|
1415
|
+
function toStoredEntry(namespace, entry) {
|
|
1416
|
+
const sourceId = namespace === "value" ? "filesystem-values" : "filesystem-secrets";
|
|
1417
|
+
const candidates = [entry.winner, ...entry.overridden].filter((candidate) => candidate.sourceId === sourceId);
|
|
1418
|
+
if (candidates.length === 0) {
|
|
1419
|
+
return void 0;
|
|
1420
|
+
}
|
|
1421
|
+
return {
|
|
1422
|
+
key: entry.key,
|
|
1423
|
+
value: candidates[0]?.value
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1426
|
+
function listStoredNamespace(namespace, options) {
|
|
1427
|
+
return createRuntimeService(options).then(
|
|
1428
|
+
(runtime) => Array.from(runtime.graph.entries.values()).filter((entry) => entry.namespace === namespace).map((entry) => toStoredEntry(namespace, entry)).filter((entry) => Boolean(entry)).filter((entry) => matchesPrefix(entry.key, options.prefix)).sort((left, right) => left.key.localeCompare(right.key))
|
|
1429
|
+
);
|
|
1430
|
+
}
|
|
1431
|
+
function listProjectedNamespace(namespace, options) {
|
|
1432
|
+
return createRuntimeService(options).then((runtime) => {
|
|
1433
|
+
const projected = namespace === "meta" ? flattenObject2(runtime.toNamespace("meta")) : namespace === "env" ? runtime.manifest.envMapping.explicit : runtime.toPublicEnv();
|
|
1434
|
+
const entries = namespace === "env" ? Object.entries(projected).map(([envVar, logicalKey]) => ({
|
|
1435
|
+
key: envVar,
|
|
1436
|
+
value: runtime.read(logicalKey)
|
|
1437
|
+
})) : Object.entries(projected).map(([key, value]) => ({
|
|
1438
|
+
key: namespace === "meta" ? `meta.${key}` : key,
|
|
1439
|
+
value
|
|
1440
|
+
}));
|
|
1441
|
+
return entries.filter((entry) => entry.value !== void 0).filter((entry) => matchesPrefix(entry.key, options.prefix)).sort((left, right) => left.key.localeCompare(right.key));
|
|
1442
|
+
});
|
|
1443
|
+
}
|
|
1366
1444
|
async function listConfigEntries(namespace, options = {}) {
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
const entries = [];
|
|
1370
|
-
const prefix = options.prefix?.trim();
|
|
1371
|
-
for (const currentNamespace of namespaces) {
|
|
1372
|
-
const projected = flattenObject2(runtime.toNamespace(currentNamespace));
|
|
1373
|
-
for (const [path10, value] of Object.entries(projected)) {
|
|
1374
|
-
const key = `${currentNamespace}.${path10}`;
|
|
1375
|
-
if (prefix && !key.startsWith(prefix) && !path10.startsWith(prefix)) {
|
|
1376
|
-
continue;
|
|
1377
|
-
}
|
|
1378
|
-
entries.push({
|
|
1379
|
-
key,
|
|
1380
|
-
value
|
|
1381
|
-
});
|
|
1382
|
-
}
|
|
1445
|
+
if (namespace === "value" || namespace === "secret") {
|
|
1446
|
+
return listStoredNamespace(namespace, options);
|
|
1383
1447
|
}
|
|
1384
|
-
|
|
1448
|
+
if (namespace === "meta" || namespace === "env" || namespace === "public") {
|
|
1449
|
+
return listProjectedNamespace(namespace, options);
|
|
1450
|
+
}
|
|
1451
|
+
const [values, secrets, meta] = await Promise.all([
|
|
1452
|
+
listStoredNamespace("value", options),
|
|
1453
|
+
listStoredNamespace("secret", options),
|
|
1454
|
+
listProjectedNamespace("meta", options)
|
|
1455
|
+
]);
|
|
1456
|
+
return [...values, ...secrets, ...meta].sort((left, right) => left.key.localeCompare(right.key));
|
|
1385
1457
|
}
|
|
1386
1458
|
|
|
1387
1459
|
// src/commands/list.ts
|
|
@@ -1398,6 +1470,12 @@ function normalizeNamespace(value) {
|
|
|
1398
1470
|
if (value === "meta") {
|
|
1399
1471
|
return "meta";
|
|
1400
1472
|
}
|
|
1473
|
+
if (value === "env") {
|
|
1474
|
+
return "env";
|
|
1475
|
+
}
|
|
1476
|
+
if (value === "public") {
|
|
1477
|
+
return "public";
|
|
1478
|
+
}
|
|
1401
1479
|
throw new Error(`Unsupported list namespace: ${value}`);
|
|
1402
1480
|
}
|
|
1403
1481
|
async function runList(args = [], options = {}) {
|
|
@@ -1412,6 +1490,9 @@ async function runList(args = [], options = {}) {
|
|
|
1412
1490
|
if (options.json) {
|
|
1413
1491
|
return printJson(entries);
|
|
1414
1492
|
}
|
|
1493
|
+
if (entries.length === 0) {
|
|
1494
|
+
return "";
|
|
1495
|
+
}
|
|
1415
1496
|
return entries.map((entry) => `${entry.key}=${printValue(entry.value)}`).join("\n");
|
|
1416
1497
|
}
|
|
1417
1498
|
|
|
@@ -1691,19 +1772,25 @@ function isSecretRef(value) {
|
|
|
1691
1772
|
);
|
|
1692
1773
|
}
|
|
1693
1774
|
function normalizeSecretCommand(args) {
|
|
1694
|
-
const [actionOrPath, ...tail] = args;
|
|
1775
|
+
const [actionOrPath, next, ...tail] = args;
|
|
1695
1776
|
if (!actionOrPath) {
|
|
1696
1777
|
return {
|
|
1697
1778
|
action: "list",
|
|
1698
1779
|
tail: []
|
|
1699
1780
|
};
|
|
1700
1781
|
}
|
|
1701
|
-
if (
|
|
1782
|
+
if ((actionOrPath === "create" || actionOrPath === "add") && next === "vault") {
|
|
1702
1783
|
return {
|
|
1703
|
-
action:
|
|
1784
|
+
action: "create-vault",
|
|
1704
1785
|
tail
|
|
1705
1786
|
};
|
|
1706
1787
|
}
|
|
1788
|
+
if (["get", "set", "list", "delete", "remove"].includes(actionOrPath)) {
|
|
1789
|
+
return {
|
|
1790
|
+
action: actionOrPath === "remove" ? "delete" : actionOrPath,
|
|
1791
|
+
tail: [next, ...tail].filter((value) => Boolean(value))
|
|
1792
|
+
};
|
|
1793
|
+
}
|
|
1707
1794
|
return {
|
|
1708
1795
|
action: "get",
|
|
1709
1796
|
tail: args
|
|
@@ -1713,13 +1800,30 @@ async function runSecret(argsOrPath, options = {}) {
|
|
|
1713
1800
|
const args = Array.isArray(argsOrPath) ? argsOrPath : [argsOrPath];
|
|
1714
1801
|
const { action, tail } = normalizeSecretCommand(args);
|
|
1715
1802
|
const cliArgs = [...options.cliArgs ?? []];
|
|
1803
|
+
if (action === "create-vault") {
|
|
1804
|
+
const vault = tail[0] ?? "default";
|
|
1805
|
+
const passphrase = consumeOption(cliArgs, "--passphrase");
|
|
1806
|
+
const result = await createVault(vault, {
|
|
1807
|
+
...options,
|
|
1808
|
+
cliArgs,
|
|
1809
|
+
...passphrase ? { passphrase } : {}
|
|
1810
|
+
});
|
|
1811
|
+
if (options.json) {
|
|
1812
|
+
return printJson(result);
|
|
1813
|
+
}
|
|
1814
|
+
return `created secret vault "${result.vault}" in ${result.filePath}`;
|
|
1815
|
+
}
|
|
1716
1816
|
if (action === "list") {
|
|
1717
|
-
const
|
|
1718
|
-
const
|
|
1817
|
+
const prefix = consumeOption(cliArgs, "--prefix");
|
|
1818
|
+
const entries = await listConfigEntries("secret", {
|
|
1819
|
+
...options,
|
|
1820
|
+
cliArgs,
|
|
1821
|
+
...prefix ? { prefix } : {}
|
|
1822
|
+
});
|
|
1719
1823
|
if (options.json) {
|
|
1720
|
-
return printJson(
|
|
1824
|
+
return printJson(entries);
|
|
1721
1825
|
}
|
|
1722
|
-
return
|
|
1826
|
+
return entries.map((entry) => `${entry.key}=${printValue(entry.value)}`).join("\n");
|
|
1723
1827
|
}
|
|
1724
1828
|
if (action === "set") {
|
|
1725
1829
|
const secretPath = tail[0];
|
|
@@ -1730,19 +1834,21 @@ async function runSecret(argsOrPath, options = {}) {
|
|
|
1730
1834
|
const target = consumeOption(cliArgs, "--target") ?? "local";
|
|
1731
1835
|
const provider = consumeOption(cliArgs, "--provider");
|
|
1732
1836
|
const passphrase = consumeOption(cliArgs, "--passphrase");
|
|
1837
|
+
const vault = consumeOption(cliArgs, "--vault") ?? "default";
|
|
1733
1838
|
const mode = local ? "local" : remote ? "remote" : ref ? "ref" : "local";
|
|
1734
1839
|
const result = await setSecret(secretPath ?? "app.token", rawValue, {
|
|
1735
1840
|
...options,
|
|
1736
1841
|
cliArgs,
|
|
1737
1842
|
target,
|
|
1738
1843
|
mode,
|
|
1844
|
+
vault,
|
|
1739
1845
|
...provider ? { provider } : {},
|
|
1740
1846
|
...passphrase ? { passphrase } : {}
|
|
1741
1847
|
});
|
|
1742
1848
|
if (options.json) {
|
|
1743
1849
|
return printJson(result);
|
|
1744
1850
|
}
|
|
1745
|
-
return `set secret.${secretPath} via ${result.provider} in ${result.filePath}`;
|
|
1851
|
+
return result.provider === "local" ? `set secret.${secretPath} in vault "${result.vault ?? "default"}" with ref "${result.ref}" and repo pointer ${result.filePath}` : `set secret.${secretPath} via ${result.provider} in ${result.filePath}`;
|
|
1746
1852
|
}
|
|
1747
1853
|
if (action === "delete") {
|
|
1748
1854
|
const secretPath = tail[0];
|
|
@@ -1763,8 +1869,9 @@ async function runSecret(argsOrPath, options = {}) {
|
|
|
1763
1869
|
throw new Error(`Missing CNOS secret path: ${tail[0] ?? "app.token"}`);
|
|
1764
1870
|
}
|
|
1765
1871
|
if (isSecretRef(value)) {
|
|
1872
|
+
const vault = value.vault ?? "default";
|
|
1766
1873
|
throw new Error(
|
|
1767
|
-
`Secret ${tail[0] ?? "app.token"} is stored as
|
|
1874
|
+
`Secret ${tail[0] ?? "app.token"} is stored in vault "${vault}" as ref "${value.ref}". Provide the correct vault passphrase to resolve it.`
|
|
1768
1875
|
);
|
|
1769
1876
|
}
|
|
1770
1877
|
if (options.json) {
|
|
@@ -1778,8 +1885,17 @@ async function runSecret(argsOrPath, options = {}) {
|
|
|
1778
1885
|
|
|
1779
1886
|
// src/commands/use.ts
|
|
1780
1887
|
import path9 from "path";
|
|
1781
|
-
async function runUse(options = {}) {
|
|
1888
|
+
async function runUse(args = [], options = {}) {
|
|
1782
1889
|
const root = path9.resolve(options.root ?? process.cwd());
|
|
1890
|
+
const action = args[0] ?? "show";
|
|
1891
|
+
const hasUpdates = Boolean(options.workspace || options.profile || options.globalRoot);
|
|
1892
|
+
if (action === "show" || !hasUpdates) {
|
|
1893
|
+
const context = await loadCliContext(root);
|
|
1894
|
+
if (options.json) {
|
|
1895
|
+
return printJson(context);
|
|
1896
|
+
}
|
|
1897
|
+
return Object.keys(context).length === 0 ? "no CLI context configured" : printJson(context);
|
|
1898
|
+
}
|
|
1783
1899
|
const result = await saveCliContext({
|
|
1784
1900
|
root,
|
|
1785
1901
|
...options.workspace ? { workspace: options.workspace } : {},
|
|
@@ -1807,7 +1923,7 @@ async function runValidate(options = {}) {
|
|
|
1807
1923
|
// package.json
|
|
1808
1924
|
var package_default = {
|
|
1809
1925
|
name: "@kitsy/cnos-cli",
|
|
1810
|
-
version: "1.
|
|
1926
|
+
version: "1.1.1",
|
|
1811
1927
|
description: "CLI entry point and developer tooling for CNOS.",
|
|
1812
1928
|
type: "module",
|
|
1813
1929
|
main: "./dist/index.js",
|
|
@@ -1850,6 +1966,7 @@ var package_default = {
|
|
|
1850
1966
|
clean: "rimraf dist",
|
|
1851
1967
|
dev: "tsup src/index.ts --watch --format esm --dts",
|
|
1852
1968
|
lint: "eslint src test",
|
|
1969
|
+
prepack: "pnpm build",
|
|
1853
1970
|
test: "vitest run",
|
|
1854
1971
|
typecheck: "tsc -p tsconfig.json --noEmit"
|
|
1855
1972
|
}
|
|
@@ -1952,6 +2069,9 @@ function resolveHelpTopic(command, args) {
|
|
|
1952
2069
|
return normalizeHelpTopic([command, args[0]]);
|
|
1953
2070
|
}
|
|
1954
2071
|
if (command === "secret" && args[0] && ["set", "create", "add", "list", "delete", "remove"].includes(args[0])) {
|
|
2072
|
+
if ((args[0] === "create" || args[0] === "add") && args[1] === "vault") {
|
|
2073
|
+
return normalizeHelpTopic(["secret", "create", "vault"]);
|
|
2074
|
+
}
|
|
1955
2075
|
return normalizeHelpTopic([
|
|
1956
2076
|
command,
|
|
1957
2077
|
args[0] === "remove" ? "delete" : args[0] === "create" || args[0] === "add" ? "set" : args[0]
|
|
@@ -1991,6 +2111,9 @@ async function main(argv) {
|
|
|
1991
2111
|
...options.json ? {
|
|
1992
2112
|
json: true
|
|
1993
2113
|
} : {},
|
|
2114
|
+
...options.verbose ? {
|
|
2115
|
+
verbose: true
|
|
2116
|
+
} : {},
|
|
1994
2117
|
...options.cliArgs.length > 0 ? {
|
|
1995
2118
|
cliArgs: options.cliArgs
|
|
1996
2119
|
} : {}
|
|
@@ -2029,7 +2152,7 @@ async function main(argv) {
|
|
|
2029
2152
|
`);
|
|
2030
2153
|
return;
|
|
2031
2154
|
case "use":
|
|
2032
|
-
process.stdout.write(`${await runUse(runtimeOptions)}
|
|
2155
|
+
process.stdout.write(`${await runUse(args, runtimeOptions)}
|
|
2033
2156
|
`);
|
|
2034
2157
|
return;
|
|
2035
2158
|
case "profile":
|
|
@@ -2084,7 +2207,18 @@ async function main(argv) {
|
|
|
2084
2207
|
process.exitCode = 1;
|
|
2085
2208
|
}
|
|
2086
2209
|
}
|
|
2087
|
-
void main(process.argv.slice(2))
|
|
2210
|
+
void main(process.argv.slice(2)).catch((error) => {
|
|
2211
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2212
|
+
const verbose = process.argv.includes("--verbose");
|
|
2213
|
+
if (verbose && error instanceof Error && error.stack) {
|
|
2214
|
+
process.stderr.write(`${error.stack}
|
|
2215
|
+
`);
|
|
2216
|
+
} else {
|
|
2217
|
+
process.stderr.write(`${message}
|
|
2218
|
+
`);
|
|
2219
|
+
}
|
|
2220
|
+
process.exitCode = 1;
|
|
2221
|
+
});
|
|
2088
2222
|
export {
|
|
2089
2223
|
main
|
|
2090
2224
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kitsy/cnos-cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "CLI entry point and developer tooling for CNOS.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"access": "public"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@kitsy/cnos": "1.1.
|
|
39
|
+
"@kitsy/cnos": "1.1.1"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"build": "tsup src/index.ts --format esm --dts",
|