@kitsy/cnos-cli 1.7.0 → 1.8.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.
Files changed (2) hide show
  1. package/dist/index.js +278 -37
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -23,7 +23,8 @@ var COMMAND_OPTION_KEYS_WITH_VALUE = /* @__PURE__ */ new Set([
23
23
  "--as",
24
24
  "--set",
25
25
  "--debounce",
26
- "--expr"
26
+ "--expr",
27
+ "--extends"
27
28
  ]);
28
29
  var COMMAND_FLAG_KEYS = /* @__PURE__ */ new Set([
29
30
  "--flatten",
@@ -42,7 +43,8 @@ var COMMAND_FLAG_KEYS = /* @__PURE__ */ new Set([
42
43
  "--apply",
43
44
  "--rewrite",
44
45
  "--signal",
45
- "--derive"
46
+ "--derive",
47
+ "--onboard-current"
46
48
  ]);
47
49
  function normalizeCommand(argv) {
48
50
  const [command = "doctor", ...rest] = argv;
@@ -2214,10 +2216,48 @@ var COMMANDS = [
2214
2216
  },
2215
2217
  {
2216
2218
  id: "workspace",
2217
- summary: "Attach or detach package-local workspace config from a parent CNOS root.",
2218
- usage: "cnos workspace <attach|detach> [options] [global-options]",
2219
- description: "Detaches a child package into a standalone .cnos root or reattaches a detached package back into a parent workspace.",
2220
- examples: ["cnos workspace detach", "cnos workspace attach --package-root apps/travel"]
2219
+ summary: "Manage workspace creation, listing, migration, and attach/detach flows.",
2220
+ usage: "cnos workspace <add|list|remove|scaffold|attach|detach> [options] [global-options]",
2221
+ description: "Adds and removes manifest workspaces, scaffolds package anchors, migrates single-root projects into workspace mode, and handles detach/attach flows for independent child packages.",
2222
+ examples: [
2223
+ "cnos workspace list",
2224
+ "cnos workspace add travel --package-root apps/travel --extends base",
2225
+ "cnos workspace add main --onboard-current",
2226
+ "cnos workspace remove gallery",
2227
+ "cnos workspace detach --package-root apps/travel"
2228
+ ]
2229
+ },
2230
+ {
2231
+ id: "workspace add",
2232
+ summary: "Add a workspace to the manifest and scaffold its on-disk layout.",
2233
+ usage: "cnos workspace add <id> [--package-root <path>] [--extends <workspace>] [--onboard-current] [--force] [global-options]",
2234
+ description: "Creates .cnos/workspaces/<id>, updates cnos.yml, writes a .cnosrc.yml anchor at the selected package root, and optionally migrates an existing single-root .cnos tree into workspace mode with --onboard-current.",
2235
+ examples: [
2236
+ "cnos workspace add travel --package-root apps/travel --extends base",
2237
+ "cnos workspace add insights --package-root apps/insights",
2238
+ "cnos workspace add main --onboard-current"
2239
+ ]
2240
+ },
2241
+ {
2242
+ id: "workspace scaffold",
2243
+ summary: "Scaffold a workspace and anchor without changing other runtime flows.",
2244
+ usage: "cnos workspace scaffold <id> [--package-root <path>] [--extends <workspace>] [--force] [global-options]",
2245
+ description: "Creates the workspace manifest entry, workspace folders, and package anchor for a new app or package. This is an alias-oriented workflow for teams that prefer scaffold wording over add.",
2246
+ examples: ["cnos workspace scaffold gallery --package-root apps/gallery --extends base"]
2247
+ },
2248
+ {
2249
+ id: "workspace list",
2250
+ summary: "List declared workspaces and their inheritance.",
2251
+ usage: "cnos workspace list [global-options]",
2252
+ description: "Shows the declared workspace ids, default workspace, and extends relationships from cnos.yml.",
2253
+ examples: ["cnos workspace list", "cnos workspace list --json"]
2254
+ },
2255
+ {
2256
+ id: "workspace remove",
2257
+ summary: "Remove a workspace from the manifest and delete its local workspace tree.",
2258
+ usage: "cnos workspace remove <id> [global-options]",
2259
+ description: "Deletes .cnos/workspaces/<id> and removes the workspace entry from cnos.yml. CNOS refuses to remove the current default workspace until you change workspaces.default.",
2260
+ examples: ["cnos workspace remove gallery", "cnos workspace remove insights --json"]
2221
2261
  },
2222
2262
  {
2223
2263
  id: "workspace detach",
@@ -2576,8 +2616,7 @@ async function ensureGitignore(root) {
2576
2616
  `, "utf8");
2577
2617
  return true;
2578
2618
  }
2579
- async function scaffoldWorkspace(root, workspace) {
2580
- const cnosRoot = path9.join(root, ".cnos");
2619
+ async function ensureWorkspaceLayout(cnosRoot, workspace) {
2581
2620
  const workspaceRoot = workspace ? path9.join(cnosRoot, "workspaces", workspace) : cnosRoot;
2582
2621
  const createdPaths = [];
2583
2622
  await mkdir4(path9.join(workspaceRoot, "profiles"), { recursive: true });
@@ -2598,18 +2637,28 @@ async function scaffoldWorkspace(root, workspace) {
2598
2637
  for (const relativePath of relativePaths) {
2599
2638
  const filePath = path9.join(cnosRoot, ...relativePath);
2600
2639
  if (await ensureFile(filePath, "")) {
2601
- createdPaths.push(path9.relative(root, filePath).replace(/\\/g, "/"));
2640
+ createdPaths.push(path9.relative(path9.dirname(cnosRoot), filePath).replace(/\\/g, "/"));
2602
2641
  }
2603
2642
  }
2604
- if (await ensureFile(path9.join(cnosRoot, "cnos.yml"), scaffoldManifest(path9.basename(root), workspace))) {
2605
- createdPaths.push(".cnos/cnos.yml");
2606
- }
2607
- if (await ensureFile(
2643
+ return createdPaths;
2644
+ }
2645
+ async function ensureCnosrc(root, workspace) {
2646
+ return ensureFile(
2608
2647
  path9.join(root, ".cnosrc.yml"),
2609
2648
  workspace ? `root: ./.cnos
2610
2649
  workspace: ${workspace}
2611
2650
  ` : "root: ./.cnos\n"
2612
- )) {
2651
+ );
2652
+ }
2653
+ async function scaffoldWorkspace(root, workspace) {
2654
+ const cnosRoot = path9.join(root, ".cnos");
2655
+ const createdPaths = (await ensureWorkspaceLayout(cnosRoot, workspace)).map(
2656
+ (entry) => entry.replace(/^\.cnos\//, ".cnos/")
2657
+ );
2658
+ if (await ensureFile(path9.join(cnosRoot, "cnos.yml"), scaffoldManifest(path9.basename(root), workspace))) {
2659
+ createdPaths.push(".cnos/cnos.yml");
2660
+ }
2661
+ if (await ensureCnosrc(root, workspace)) {
2613
2662
  createdPaths.push(".cnosrc.yml");
2614
2663
  }
2615
2664
  if (workspace && await ensureFile(path9.join(root, ".cnos-workspace.yml"), `workspace: ${workspace}
@@ -3937,7 +3986,7 @@ async function runValidate(options = {}) {
3937
3986
  // package.json
3938
3987
  var package_default = {
3939
3988
  name: "@kitsy/cnos-cli",
3940
- version: "1.7.0",
3989
+ version: "1.8.0",
3941
3990
  description: "CLI entry point and developer tooling for CNOS.",
3942
3991
  type: "module",
3943
3992
  main: "./dist/index.js",
@@ -4212,7 +4261,7 @@ async function runWatch(command, options = {}) {
4212
4261
  }
4213
4262
 
4214
4263
  // src/commands/workspace.ts
4215
- import { cp, mkdir as mkdir6, rename, rm as rm5, stat as stat2, writeFile as writeFile9, readFile as readFile6 } from "fs/promises";
4264
+ import { cp, mkdir as mkdir6, readdir as readdir5, readFile as readFile6, rename, rm as rm5, stat as stat2, writeFile as writeFile9 } from "fs/promises";
4216
4265
  import path23 from "path";
4217
4266
  import { loadManifest as loadManifest8, parseYaml as parseYaml5, stringifyYaml as stringifyYaml7 } from "@kitsy/cnos/internal";
4218
4267
  async function exists(targetPath) {
@@ -4230,22 +4279,34 @@ async function copyIfExists(source, target) {
4230
4279
  await mkdir6(path23.dirname(target), { recursive: true });
4231
4280
  await cp(source, target, { recursive: true, force: true });
4232
4281
  }
4282
+ async function moveIfExists(source, target, force = false) {
4283
+ if (!await exists(source)) {
4284
+ return false;
4285
+ }
4286
+ if (force) {
4287
+ await rm5(target, { recursive: true, force: true });
4288
+ } else if (await exists(target)) {
4289
+ throw new Error(`Refusing to overwrite existing path ${target}. Use --force to replace it.`);
4290
+ }
4291
+ await mkdir6(path23.dirname(target), { recursive: true });
4292
+ await rename(source, target);
4293
+ return true;
4294
+ }
4233
4295
  async function mergeWorkspaceRootsIntoStandalone(targetCnosRoot, sourceRoots) {
4234
4296
  for (const sourceRoot of sourceRoots) {
4235
4297
  for (const folderName of ["values", "secrets", "env", "profiles"]) {
4236
- await copyIfExists(
4237
- path23.join(sourceRoot, folderName),
4238
- path23.join(targetCnosRoot, folderName)
4239
- );
4298
+ await copyIfExists(path23.join(sourceRoot, folderName), path23.join(targetCnosRoot, folderName));
4240
4299
  }
4241
4300
  }
4242
4301
  }
4243
- async function writeCnosrc(packageRoot, config) {
4302
+ async function writeAnchor(packageRoot, manifestRoot, workspace) {
4303
+ const relativeRoot = path23.relative(packageRoot, manifestRoot).replace(/\\/g, "/");
4304
+ const rootValue = relativeRoot.length === 0 ? "./.cnos" : relativeRoot.startsWith(".") ? relativeRoot : `./${relativeRoot}`;
4244
4305
  await writeFile9(
4245
4306
  path23.join(packageRoot, ".cnosrc.yml"),
4246
4307
  stringifyYaml7({
4247
- root: config.root,
4248
- ...config.workspace ? { workspace: config.workspace } : {}
4308
+ root: rootValue,
4309
+ ...workspace ? { workspace } : {}
4249
4310
  }),
4250
4311
  "utf8"
4251
4312
  );
@@ -4257,6 +4318,36 @@ function createDetachedManifest(rawManifest) {
4257
4318
  }
4258
4319
  return next;
4259
4320
  }
4321
+ function normalizeWorkspaceId(value) {
4322
+ const workspaceId = value?.trim();
4323
+ if (!workspaceId) {
4324
+ throw new Error("Workspace id is required");
4325
+ }
4326
+ if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(workspaceId)) {
4327
+ throw new Error(`Invalid workspace id "${workspaceId}". Use letters, numbers, dot, underscore, or dash.`);
4328
+ }
4329
+ return workspaceId;
4330
+ }
4331
+ function splitExtends(value) {
4332
+ if (!value) {
4333
+ return void 0;
4334
+ }
4335
+ const items = value.split(",").map((entry) => entry.trim()).filter(Boolean);
4336
+ return items.length > 0 ? items : void 0;
4337
+ }
4338
+ async function hasDirectConfigData(cnosRoot) {
4339
+ for (const folderName of ["values", "secrets", "env", "profiles"]) {
4340
+ const folder = path23.join(cnosRoot, folderName);
4341
+ if (!await exists(folder)) {
4342
+ continue;
4343
+ }
4344
+ const entries = await readdir5(folder, { withFileTypes: true });
4345
+ if (entries.some((entry) => entry.name !== ".gitkeep")) {
4346
+ return true;
4347
+ }
4348
+ }
4349
+ return false;
4350
+ }
4260
4351
  async function runDetach(packageRoot, options = {}) {
4261
4352
  const loaded = await loadManifest8({ cwd: packageRoot });
4262
4353
  if (!loaded.anchorPath || !loaded.anchoredWorkspace) {
@@ -4294,7 +4385,7 @@ async function runDetach(packageRoot, options = {}) {
4294
4385
  }
4295
4386
  };
4296
4387
  await writeFile9(path23.join(targetCnosRoot, ".detached"), stringifyYaml7(marker), "utf8");
4297
- await writeCnosrc(packageRoot, { root: "./.cnos" });
4388
+ await writeFile9(path23.join(packageRoot, ".cnosrc.yml"), stringifyYaml7({ root: "./.cnos" }), "utf8");
4298
4389
  if (options.json) {
4299
4390
  return printJson({
4300
4391
  packageRoot,
@@ -4335,7 +4426,7 @@ async function runAttach(packageRoot, options = {}) {
4335
4426
  for (const folderName of ["values", "secrets", "env", "profiles"]) {
4336
4427
  await copyIfExists(path23.join(childCnosRoot, folderName), path23.join(parentWorkspaceRoot, folderName));
4337
4428
  }
4338
- const rawManifest = parentLoaded.rawManifest;
4429
+ const rawManifest = structuredClone(parentLoaded.rawManifest);
4339
4430
  const workspaces = rawManifest.workspaces ?? {};
4340
4431
  const items = workspaces.items ?? {};
4341
4432
  items[workspaceId] = items[workspaceId] ?? {};
@@ -4345,10 +4436,7 @@ async function runAttach(packageRoot, options = {}) {
4345
4436
  const archivePath = path23.join(packageRoot, ".cnos.detached.bak");
4346
4437
  await rm5(archivePath, { recursive: true, force: true });
4347
4438
  await rename(childCnosRoot, archivePath);
4348
- await writeCnosrc(packageRoot, {
4349
- root: marker.originalCnosrc.root,
4350
- ...workspaceId ? { workspace: workspaceId } : {}
4351
- });
4439
+ await writeAnchor(packageRoot, parentLoaded.manifestRoot, workspaceId);
4352
4440
  if (options.json) {
4353
4441
  return printJson({
4354
4442
  packageRoot,
@@ -4359,15 +4447,168 @@ async function runAttach(packageRoot, options = {}) {
4359
4447
  }
4360
4448
  return `attached workspace ${workspaceId} to ${displayPath(parentLoaded.manifestRoot, packageRoot)}`;
4361
4449
  }
4362
- async function runWorkspace(args = [], options = {}) {
4363
- const [action] = args;
4450
+ async function runList2(manifestCwd, options = {}) {
4451
+ const loaded = await loadManifest8({
4452
+ ...options.root ? { root: options.root } : {},
4453
+ cwd: manifestCwd,
4454
+ ...options.processEnv ? { processEnv: options.processEnv } : {}
4455
+ });
4456
+ const entries = Object.entries(loaded.manifest.workspaces.items).map(([id, config]) => ({
4457
+ id,
4458
+ extends: config.extends,
4459
+ default: loaded.manifest.workspaces.default === id,
4460
+ path: path23.join(loaded.manifestRoot, "workspaces", id)
4461
+ })).sort((left, right) => left.id.localeCompare(right.id));
4462
+ if (options.json) {
4463
+ return printJson({
4464
+ default: loaded.manifest.workspaces.default,
4465
+ workspaces: entries
4466
+ });
4467
+ }
4468
+ if (entries.length === 0) {
4469
+ return "no workspaces declared";
4470
+ }
4471
+ return entries.map((entry) => {
4472
+ const tags = [
4473
+ entry.default ? "default" : void 0,
4474
+ entry.extends.length > 0 ? `extends=${entry.extends.join(",")}` : void 0
4475
+ ].filter(Boolean);
4476
+ return `${entry.id}${tags.length > 0 ? ` (${tags.join(", ")})` : ""}`;
4477
+ }).join("\n");
4478
+ }
4479
+ async function runAddOrScaffold(action, workspaceId, manifestCwd, packageRoot, options = {}) {
4364
4480
  const cliArgs = [...options.cliArgs ?? []];
4365
- const packageRoot = path23.resolve(consumeOption(cliArgs, "--package-root") ?? options.root ?? process.cwd());
4481
+ const extendsOption = splitExtends(consumeOption(cliArgs, "--extends"));
4482
+ const onboardCurrent = consumeFlag(cliArgs, "--onboard-current");
4483
+ const force = consumeFlag(cliArgs, "--force");
4484
+ if (cliArgs.length > 0) {
4485
+ throw new Error(`Unsupported workspace arguments: ${cliArgs.join(" ")}`);
4486
+ }
4487
+ const loaded = await loadManifest8({
4488
+ ...options.root ? { root: options.root } : {},
4489
+ cwd: manifestCwd,
4490
+ ...options.processEnv ? { processEnv: options.processEnv } : {}
4491
+ });
4492
+ if (loaded.rootResolution.readOnly) {
4493
+ throw new Error(
4494
+ `Cannot ${action} workspace because the active CNOS root is remote and read-only (${loaded.rootResolution.rootUri}). Clone the config repo and edit it directly.`
4495
+ );
4496
+ }
4497
+ const manifestRoot = loaded.manifestRoot;
4498
+ const cnosRoot = manifestRoot;
4499
+ const rawManifest = structuredClone(loaded.rawManifest);
4500
+ const rawWorkspaces = rawManifest.workspaces ?? {};
4501
+ const rawItems = rawWorkspaces.items ?? {};
4502
+ const isWorkspaceMode = Object.keys(rawItems).length > 0;
4503
+ const directConfigPresent = await hasDirectConfigData(cnosRoot);
4504
+ if (!isWorkspaceMode && directConfigPresent && !onboardCurrent) {
4505
+ throw new Error(
4506
+ "This CNOS root is in single-root mode and already has direct values/secrets/env/profiles data. Re-run with --onboard-current to migrate it into workspace mode."
4507
+ );
4508
+ }
4509
+ if (rawItems[workspaceId] && !force) {
4510
+ throw new Error(`workspace "${workspaceId}" already exists. Use --force to update its manifest entry and anchor.`);
4511
+ }
4512
+ const defaultExtends = extendsOption ?? (!["base", "root"].includes(workspaceId) && rawItems.base ? ["base"] : void 0);
4513
+ rawItems[workspaceId] = defaultExtends && defaultExtends.length > 0 ? { extends: defaultExtends } : {};
4514
+ rawWorkspaces.items = rawItems;
4515
+ rawWorkspaces.default = rawWorkspaces.default ?? workspaceId;
4516
+ rawManifest.workspaces = rawWorkspaces;
4517
+ const workspaceRoot = path23.join(cnosRoot, "workspaces", workspaceId);
4518
+ if (onboardCurrent) {
4519
+ if (isWorkspaceMode) {
4520
+ throw new Error("--onboard-current can only be used when the manifest is not already in workspace mode.");
4521
+ }
4522
+ for (const folderName of ["values", "secrets", "env", "profiles"]) {
4523
+ await moveIfExists(path23.join(cnosRoot, folderName), path23.join(workspaceRoot, folderName), force);
4524
+ }
4525
+ }
4526
+ const created = await ensureWorkspaceLayout(cnosRoot, workspaceId);
4527
+ await writeFile9(path23.join(cnosRoot, "cnos.yml"), stringifyYaml7(rawManifest), "utf8");
4528
+ await ensureGitignore(path23.dirname(cnosRoot));
4529
+ await writeAnchor(packageRoot, cnosRoot, workspaceId);
4530
+ await ensureFile(path23.join(packageRoot, ".cnos-workspace.yml"), `workspace: ${workspaceId}
4531
+ globalRoot: ~/.cnos
4532
+ `);
4533
+ const result = {
4534
+ workspace: workspaceId,
4535
+ root: path23.dirname(cnosRoot),
4536
+ packageRoot,
4537
+ onboarded: onboardCurrent,
4538
+ created
4539
+ };
4540
+ if (options.json) {
4541
+ return printJson(result);
4542
+ }
4543
+ const verb = action === "add" ? "added" : "scaffolded";
4544
+ return `${verb} workspace ${workspaceId} at ${displayPath(workspaceRoot, packageRoot)}`;
4545
+ }
4546
+ async function runRemove(workspaceId, manifestCwd, options = {}) {
4547
+ const cliArgs = [...options.cliArgs ?? []];
4548
+ consumeFlag(cliArgs, "--force");
4549
+ if (cliArgs.length > 0) {
4550
+ throw new Error(`Unsupported workspace arguments: ${cliArgs.join(" ")}`);
4551
+ }
4552
+ const loaded = await loadManifest8({
4553
+ ...options.root ? { root: options.root } : {},
4554
+ cwd: manifestCwd,
4555
+ ...options.processEnv ? { processEnv: options.processEnv } : {}
4556
+ });
4557
+ if (loaded.rootResolution.readOnly) {
4558
+ throw new Error(
4559
+ `Cannot remove workspace because the active CNOS root is remote and read-only (${loaded.rootResolution.rootUri}). Clone the config repo and edit it directly.`
4560
+ );
4561
+ }
4562
+ const rawManifest = structuredClone(loaded.rawManifest);
4563
+ const rawWorkspaces = rawManifest.workspaces ?? {};
4564
+ const rawItems = rawWorkspaces.items ?? {};
4565
+ if (!rawItems[workspaceId]) {
4566
+ throw new Error(`workspace "${workspaceId}" does not exist`);
4567
+ }
4568
+ if (rawWorkspaces.default === workspaceId) {
4569
+ throw new Error(`Cannot remove workspace "${workspaceId}" because it is the default workspace. Change workspaces.default first.`);
4570
+ }
4571
+ delete rawItems[workspaceId];
4572
+ rawWorkspaces.items = rawItems;
4573
+ rawManifest.workspaces = rawWorkspaces;
4574
+ await writeFile9(path23.join(loaded.manifestRoot, "cnos.yml"), stringifyYaml7(rawManifest), "utf8");
4575
+ await rm5(path23.join(loaded.manifestRoot, "workspaces", workspaceId), { recursive: true, force: true });
4576
+ if (options.json) {
4577
+ return printJson({
4578
+ workspace: workspaceId,
4579
+ removedFrom: loaded.manifestRoot
4580
+ });
4581
+ }
4582
+ return `removed workspace ${workspaceId}`;
4583
+ }
4584
+ async function runWorkspace(args = [], options = {}) {
4585
+ const [action, workspaceArg] = args;
4586
+ const baseCliArgs = [...options.cliArgs ?? []];
4587
+ const manifestCwd = path23.resolve(options.root ?? process.cwd());
4588
+ const packageRoot = path23.resolve(consumeOption(baseCliArgs, "--package-root") ?? options.root ?? process.cwd());
4366
4589
  switch (action) {
4367
- case "detach":
4368
- return runDetach(packageRoot, { ...options, cliArgs });
4369
4590
  case "attach":
4370
- return runAttach(packageRoot, { ...options, cliArgs });
4591
+ return runAttach(packageRoot, { ...options, cliArgs: baseCliArgs });
4592
+ case "detach":
4593
+ return runDetach(packageRoot, { ...options, cliArgs: baseCliArgs });
4594
+ case "list":
4595
+ return runList2(manifestCwd, options);
4596
+ case "add":
4597
+ return runAddOrScaffold("add", normalizeWorkspaceId(workspaceArg), manifestCwd, packageRoot, {
4598
+ ...options,
4599
+ cliArgs: baseCliArgs
4600
+ });
4601
+ case "scaffold":
4602
+ return runAddOrScaffold("scaffold", normalizeWorkspaceId(workspaceArg), manifestCwd, packageRoot, {
4603
+ ...options,
4604
+ cliArgs: baseCliArgs
4605
+ });
4606
+ case "remove":
4607
+ case "delete":
4608
+ return runRemove(normalizeWorkspaceId(workspaceArg), manifestCwd, {
4609
+ ...options,
4610
+ cliArgs: baseCliArgs
4611
+ });
4371
4612
  default:
4372
4613
  throw new Error(`Unsupported workspace action: ${action ?? "(missing)"}`);
4373
4614
  }
@@ -4393,8 +4634,8 @@ function resolveHelpTopic(command, args) {
4393
4634
  if (command === "dev" && args[0] === "env") {
4394
4635
  return normalizeHelpTopic([command, args[0]]);
4395
4636
  }
4396
- if (command === "workspace" && args[0] && ["attach", "detach"].includes(args[0])) {
4397
- return normalizeHelpTopic([command, args[0]]);
4637
+ if (command === "workspace" && args[0] && ["attach", "detach", "add", "list", "remove", "delete", "scaffold"].includes(args[0])) {
4638
+ return normalizeHelpTopic([command, args[0] === "delete" ? "remove" : args[0]]);
4398
4639
  }
4399
4640
  if (command === "vault" && args[0] && ["create", "add", "list", "delete", "remove"].includes(args[0])) {
4400
4641
  return normalizeHelpTopic([command, args[0] === "delete" ? "remove" : args[0] === "add" ? "create" : args[0]]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitsy/cnos-cli",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
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.7.0"
39
+ "@kitsy/cnos": "1.8.0"
40
40
  },
41
41
  "scripts": {
42
42
  "build": "tsup src/index.ts --format esm --dts",