dev-cockpit 0.2.7 → 0.2.8

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 (53) hide show
  1. package/README.md +32 -32
  2. package/bin/dev-cockpit.mjs +1 -1
  3. package/dist/buildCli.d.ts.map +1 -1
  4. package/dist/{chunk-A446TCT5.js → chunk-YTMK7EXK.js} +1 -1
  5. package/dist/chunk-YTMK7EXK.js.map +7 -0
  6. package/dist/cockpit/Footer.d.ts.map +1 -1
  7. package/dist/cockpit/hooks/useGlobalKeys.d.ts.map +1 -1
  8. package/dist/cockpit/panes/FilterModal.d.ts.map +1 -1
  9. package/dist/cockpit/panes/Output.d.ts.map +1 -1
  10. package/dist/cockpit/panes/Repos.d.ts.map +1 -1
  11. package/dist/cockpit/panes/SearchModal.d.ts.map +1 -1
  12. package/dist/cockpit/state/store.d.ts.map +1 -1
  13. package/dist/commands/dev.d.ts.map +1 -1
  14. package/dist/commands/doctor.d.ts.map +1 -1
  15. package/dist/commands/init-config-wizard.d.ts.map +1 -1
  16. package/dist/commands/init-config.d.ts.map +1 -1
  17. package/dist/commands/link.d.ts.map +1 -1
  18. package/dist/commands/migrate-config.d.ts.map +1 -1
  19. package/dist/commands/mount.d.ts +1 -3
  20. package/dist/commands/mount.d.ts.map +1 -1
  21. package/dist/core/config-discovery.d.ts.map +1 -1
  22. package/dist/core/config.d.ts +6 -0
  23. package/dist/core/config.d.ts.map +1 -1
  24. package/dist/core/manifest.d.ts.map +1 -1
  25. package/dist/core/migrations.d.ts.map +1 -1
  26. package/dist/core/paths.d.ts.map +1 -1
  27. package/dist/core/subprocess.d.ts.map +1 -1
  28. package/dist/docker/highlights.d.ts.map +1 -1
  29. package/dist/health/builtin.d.ts.map +1 -1
  30. package/dist/index.d.ts +8 -8
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +206 -143
  33. package/dist/index.js.map +2 -2
  34. package/dist/ink.d.ts +1 -1
  35. package/dist/ink.d.ts.map +1 -1
  36. package/dist/{link-VWT2VQH6.js → link-Y7OFHOUP.js} +4 -6
  37. package/dist/link-Y7OFHOUP.js.map +7 -0
  38. package/dist/mount/compose.d.ts.map +1 -1
  39. package/dist/mount/symlinks.d.ts.map +1 -1
  40. package/docs/commands.md +8 -8
  41. package/docs/config-reference.md +45 -41
  42. package/docs/health.md +32 -22
  43. package/docs/init-config.md +16 -16
  44. package/docs/mount.md +8 -7
  45. package/docs/notifications.md +3 -3
  46. package/docs/panes.md +5 -5
  47. package/docs/processes.md +7 -5
  48. package/examples/cockpit.schema.json +217 -57
  49. package/examples/cockpit.yaml +8 -10
  50. package/package.json +99 -93
  51. package/prettier-config.json +7 -0
  52. package/dist/chunk-A446TCT5.js.map +0 -7
  53. package/dist/link-VWT2VQH6.js.map +0 -7
package/dist/index.js CHANGED
@@ -23,7 +23,7 @@ import {
23
23
  readManifest,
24
24
  removeMapping,
25
25
  setMapping
26
- } from "./chunk-A446TCT5.js";
26
+ } from "./chunk-YTMK7EXK.js";
27
27
  import {
28
28
  __commonJS,
29
29
  __export,
@@ -83998,7 +83998,9 @@ var MountSettingsSchema = external_exports.object({
83998
83998
  */
83999
83999
  overlayPath: external_exports.string().optional(),
84000
84000
  /** Basename inside stateDir for the manifest. */
84001
- manifestFile: external_exports.string().optional().default("mount.manifest.json")
84001
+ manifestFile: external_exports.string().optional().default("mount.manifest.json"),
84002
+ /** Target compose service. Unset = first in docker.services. */
84003
+ service: external_exports.string().optional()
84002
84004
  });
84003
84005
  var BaseCockpitConfigSchema = external_exports.object({
84004
84006
  version: external_exports.number().int(),
@@ -84180,9 +84182,7 @@ var FOCUS_ORDER = ["repos", "output", "health", "help"];
84180
84182
  function filterActions(actions, filter) {
84181
84183
  if (!filter) return actions;
84182
84184
  const f = filter.toLowerCase();
84183
- return actions.filter(
84184
- (a2) => a2.id.toLowerCase().includes(f) || a2.label.toLowerCase().includes(f)
84185
- );
84185
+ return actions.filter((a2) => a2.id.toLowerCase().includes(f) || a2.label.toLowerCase().includes(f));
84186
84186
  }
84187
84187
  var cockpitStore = createStore()((set, get2) => ({
84188
84188
  repos: {},
@@ -84451,7 +84451,7 @@ function Repos() {
84451
84451
  const heading2 = kind === "repo" ? "Repos" : kind === "docker" ? "Docker" : "Processes";
84452
84452
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { flexDirection: "column", marginTop: 1, children: [
84453
84453
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { dimColor: true, children: [
84454
- " ",
84454
+ " ",
84455
84455
  heading2
84456
84456
  ] }),
84457
84457
  entriesInKind.map(({ key, idx, entry }) => {
@@ -84488,7 +84488,7 @@ function Repos() {
84488
84488
  " ",
84489
84489
  a2.label
84490
84490
  ] }),
84491
- isDefault && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: " (default)" })
84491
+ isDefault && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: " (default)" })
84492
84492
  ] }, a2.id);
84493
84493
  })
84494
84494
  ]
@@ -84589,9 +84589,7 @@ function Output() {
84589
84589
  } else if (key.downArrow) {
84590
84590
  setScrollOffset((prev) => Math.max(0, prev - 1));
84591
84591
  } else if (key.pageUp) {
84592
- setScrollOffset(
84593
- (prev) => Math.min(prev + visibleLines, Math.max(0, total - visibleLines))
84594
- );
84592
+ setScrollOffset((prev) => Math.min(prev + visibleLines, Math.max(0, total - visibleLines)));
84595
84593
  } else if (key.pageDown) {
84596
84594
  setScrollOffset((prev) => Math.max(0, prev - visibleLines));
84597
84595
  } else if (key.return) {
@@ -87651,7 +87649,9 @@ function Footer({ legends } = {}) {
87651
87649
  if (!key) return NAV_HINT;
87652
87650
  const keyed = actionsForRepoRow(s.actions, key).filter((a2) => a2.key);
87653
87651
  if (keyed.length === 0) return NAV_HINT;
87654
- return [NAV_HINT, ...keyed.map((a2) => `[${a2.key}] ${shortLabel(a2.label).toLowerCase()}`)].join(" ");
87652
+ return [NAV_HINT, ...keyed.map((a2) => `[${a2.key}] ${shortLabel(a2.label).toLowerCase()}`)].join(
87653
+ " "
87654
+ );
87655
87655
  });
87656
87656
  let legend;
87657
87657
  if (focus === "repos") {
@@ -87671,7 +87671,9 @@ var import_react5 = __toESM(require_react(), 1);
87671
87671
  var import_jsx_runtime7 = __toESM(require_jsx_runtime(), 1);
87672
87672
  function FilterModal() {
87673
87673
  const outputFilter = useCockpitStore((s) => s.outputFilter);
87674
- const [severityDraft, setSeverityDraft] = (0, import_react5.useState)(outputFilter.severity);
87674
+ const [severityDraft, setSeverityDraft] = (0, import_react5.useState)(
87675
+ outputFilter.severity
87676
+ );
87675
87677
  const SEVERITIES = [void 0, "info", "warn", "error"];
87676
87678
  use_input_default((input, key) => {
87677
87679
  if (input === "s") {
@@ -87684,26 +87686,16 @@ function FilterModal() {
87684
87686
  cockpitStore.getState().setActiveModal(null);
87685
87687
  }
87686
87688
  });
87687
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Box_default, { flexGrow: 1, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
87688
- Box_default,
87689
- {
87690
- flexDirection: "column",
87691
- borderStyle: "round",
87692
- borderColor: "cyan",
87693
- paddingX: 2,
87694
- paddingY: 1,
87695
- children: [
87696
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { bold: true, children: " Filter Output " }),
87697
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: " " }),
87698
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { children: [
87699
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: "Severity (s to cycle): " }),
87700
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: "cyan", children: severityDraft ?? "all" })
87701
- ] }),
87702
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: " " }),
87703
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { dimColor: true, children: "Enter = apply \xB7 Esc = cancel" })
87704
- ]
87705
- }
87706
- ) });
87689
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Box_default, { flexGrow: 1, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1, children: [
87690
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { bold: true, children: " Filter Output " }),
87691
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: " " }),
87692
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { children: [
87693
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: "Severity (s to cycle): " }),
87694
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: "cyan", children: severityDraft ?? "all" })
87695
+ ] }),
87696
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: " " }),
87697
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { dimColor: true, children: "Enter = apply \xB7 Esc = cancel" })
87698
+ ] }) });
87707
87699
  }
87708
87700
 
87709
87701
  // src/cockpit/panes/SearchModal.tsx
@@ -87733,29 +87725,19 @@ function SearchModal() {
87733
87725
  setQuery((prev) => prev + input);
87734
87726
  }
87735
87727
  });
87736
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Box_default, { flexGrow: 1, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
87737
- Box_default,
87738
- {
87739
- flexDirection: "column",
87740
- borderStyle: "round",
87741
- borderColor: "cyan",
87742
- paddingX: 2,
87743
- paddingY: 1,
87744
- children: [
87745
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { bold: true, children: " Search Output " }),
87746
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { children: " " }),
87747
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Box_default, { children: [
87748
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { children: "Query: " }),
87749
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Text, { color: "cyan", children: [
87750
- query,
87751
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: "gray", children: "\u2588" })
87752
- ] })
87753
- ] }),
87754
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { children: " " }),
87755
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { dimColor: true, children: "Enter = apply \xB7 Esc = cancel \xB7 Backspace = delete" })
87756
- ]
87757
- }
87758
- ) });
87728
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Box_default, { flexGrow: 1, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Box_default, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1, children: [
87729
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { bold: true, children: " Search Output " }),
87730
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { children: " " }),
87731
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Box_default, { children: [
87732
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { children: "Query: " }),
87733
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Text, { color: "cyan", children: [
87734
+ query,
87735
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: "gray", children: "\u2588" })
87736
+ ] })
87737
+ ] }),
87738
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { children: " " }),
87739
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { dimColor: true, children: "Enter = apply \xB7 Esc = cancel \xB7 Backspace = delete" })
87740
+ ] }) });
87759
87741
  }
87760
87742
 
87761
87743
  // src/cockpit/panes/CommandModal.tsx
@@ -87910,9 +87892,7 @@ function useGlobalKeys(opts) {
87910
87892
  return;
87911
87893
  }
87912
87894
  if (input === "e" && onOpenError) {
87913
- const target = state.recentErrors.find(
87914
- (er) => er.file && typeof er.line === "number"
87915
- );
87895
+ const target = state.recentErrors.find((er) => er.file && typeof er.line === "number");
87916
87896
  if (target?.file && typeof target.line === "number") {
87917
87897
  onOpenError({
87918
87898
  file: target.file,
@@ -87950,10 +87930,7 @@ function useGlobalKeys(opts) {
87950
87930
  healthId: dispatch.healthId,
87951
87931
  healthLabel: dispatch.healthLabel
87952
87932
  });
87953
- withMinHold(
87954
- dispatch.promise,
87955
- () => cockpitStore.getState().setActiveRemediation(null)
87956
- );
87933
+ withMinHold(dispatch.promise, () => cockpitStore.getState().setActiveRemediation(null));
87957
87934
  return;
87958
87935
  }
87959
87936
  }
@@ -90967,11 +90944,7 @@ async function devCommand(opts = {}) {
90967
90944
  const builtinActions = buildBuiltinActions(config);
90968
90945
  const actions = buildActionRegistry(
90969
90946
  [...config.actions],
90970
- [
90971
- ...builtinActions,
90972
- ...profile?.actions ?? [],
90973
- ...bootResult.actions ?? []
90974
- ]
90947
+ [...builtinActions, ...profile?.actions ?? [], ...bootResult.actions ?? []]
90975
90948
  );
90976
90949
  const [shell, shellFlag] = process.platform === "win32" ? ["cmd", "/c"] : ["/bin/sh", "-c"];
90977
90950
  const highlightMatcher = compileHighlights(config.highlights);
@@ -91044,7 +91017,12 @@ async function devCommand(opts = {}) {
91044
91017
  }
91045
91018
  if (action.id.startsWith(BUILTIN_RESTART_PROCESS)) {
91046
91019
  const procId = action.id.slice(BUILTIN_RESTART_PROCESS.length);
91047
- store.appendOutput({ ts: Date.now(), source: procId, severity: "info", text: `> restart ${procId}` });
91020
+ store.appendOutput({
91021
+ ts: Date.now(),
91022
+ source: procId,
91023
+ severity: "info",
91024
+ text: `> restart ${procId}`
91025
+ });
91048
91026
  await killSpawnedByTag(procId);
91049
91027
  spawnProcessById(procId);
91050
91028
  store.setFocus("output");
@@ -91338,10 +91316,7 @@ function renderWizardYaml(result) {
91338
91316
  if (health.length > 0) blocks.push(health);
91339
91317
  const actions = renderActions(result.actions);
91340
91318
  if (actions.length > 0) blocks.push(actions);
91341
- blocks.push([
91342
- "notifications:",
91343
- indent(`enabled: ${result.notifications.enabled}`, 1)
91344
- ]);
91319
+ blocks.push(["notifications:", indent(`enabled: ${result.notifications.enabled}`, 1)]);
91345
91320
  if (result.profileLines && result.profileLines.length > 0) {
91346
91321
  blocks.push([
91347
91322
  "profile:",
@@ -91410,7 +91385,12 @@ function safeReadJson(p) {
91410
91385
  }
91411
91386
  }
91412
91387
  function detectComposeFile(cwd) {
91413
- for (const candidate of ["compose.yaml", "compose.yml", "docker-compose.yml", "docker-compose.yaml"]) {
91388
+ for (const candidate of [
91389
+ "compose.yaml",
91390
+ "compose.yml",
91391
+ "docker-compose.yml",
91392
+ "docker-compose.yaml"
91393
+ ]) {
91414
91394
  if (fs11.existsSync(path15.join(cwd, candidate))) return candidate;
91415
91395
  }
91416
91396
  return void 0;
@@ -91448,7 +91428,10 @@ function detectRepoSuggestions(cwd, pkg) {
91448
91428
  }
91449
91429
  for (const glob of workspaceGlobs) {
91450
91430
  for (const entry of expandSimpleGlob(cwd, glob)) {
91451
- out.push({ id: path15.basename(entry), path: path15.relative(cwd, path15.join(cwd, entry)) || "." });
91431
+ out.push({
91432
+ id: path15.basename(entry),
91433
+ path: path15.relative(cwd, path15.join(cwd, entry)) || "."
91434
+ });
91452
91435
  }
91453
91436
  }
91454
91437
  const pnpmFile = path15.join(cwd, "pnpm-workspace.yaml");
@@ -91791,7 +91774,9 @@ async function promptHealthChecks(prompts, hints, hasDocker) {
91791
91774
  ].join("\n")
91792
91775
  );
91793
91776
  const out = [];
91794
- let typeChoices = baseHealthTypeChoices(Boolean(hints.composeFile && hints.composeServices.length > 0));
91777
+ let typeChoices = baseHealthTypeChoices(
91778
+ Boolean(hints.composeFile && hints.composeServices.length > 0)
91779
+ );
91795
91780
  if (!hasDocker) {
91796
91781
  typeChoices = typeChoices.filter((c3) => c3.value !== "container-running");
91797
91782
  }
@@ -91856,7 +91841,14 @@ async function promptOneHealthCheck(prompts, type, hints) {
91856
91841
  })).trim();
91857
91842
  idDefault = `${slugify(container)}-up`;
91858
91843
  labelDefault = `Container \`${container}\` running`;
91859
- typeArgs = { type, container, id: "", label: "", severity: "error", remediation: { key: "", label: "", command: "" } };
91844
+ typeArgs = {
91845
+ type,
91846
+ container,
91847
+ id: "",
91848
+ label: "",
91849
+ severity: "error",
91850
+ remediation: { key: "", label: "", command: "" }
91851
+ };
91860
91852
  break;
91861
91853
  }
91862
91854
  case "port-open": {
@@ -91865,7 +91857,15 @@ async function promptOneHealthCheck(prompts, type, hints) {
91865
91857
  const port = portRaw ?? 0;
91866
91858
  idDefault = `port-${port}-open`;
91867
91859
  labelDefault = `Port ${port} open`;
91868
- typeArgs = { type, host, port, id: "", label: "", severity: "error", remediation: { key: "", label: "", command: "" } };
91860
+ typeArgs = {
91861
+ type,
91862
+ host,
91863
+ port,
91864
+ id: "",
91865
+ label: "",
91866
+ severity: "error",
91867
+ remediation: { key: "", label: "", command: "" }
91868
+ };
91869
91869
  break;
91870
91870
  }
91871
91871
  case "http-ok": {
@@ -91877,7 +91877,14 @@ async function promptOneHealthCheck(prompts, type, hints) {
91877
91877
  const pathPart = url.replace(/^https?:\/\/[^/]+/, "").replace(/^\//, "") || "root";
91878
91878
  idDefault = `http-${slugify(pathPart)}`;
91879
91879
  labelDefault = `GET ${url} returns 2xx`;
91880
- typeArgs = { type, url, id: "", label: "", severity: "error", remediation: { key: "", label: "", command: "" } };
91880
+ typeArgs = {
91881
+ type,
91882
+ url,
91883
+ id: "",
91884
+ label: "",
91885
+ severity: "error",
91886
+ remediation: { key: "", label: "", command: "" }
91887
+ };
91881
91888
  break;
91882
91889
  }
91883
91890
  case "file-exists": {
@@ -91889,16 +91896,33 @@ async function promptOneHealthCheck(prompts, type, hints) {
91889
91896
  const basename3 = filePath.split("/").filter(Boolean).pop() ?? filePath;
91890
91897
  idDefault = `${slugify(basename3)}-exists`;
91891
91898
  labelDefault = `\`${filePath}\` exists`;
91892
- typeArgs = { type, path: filePath, id: "", label: "", severity: "error", remediation: { key: "", label: "", command: "" } };
91899
+ typeArgs = {
91900
+ type,
91901
+ path: filePath,
91902
+ id: "",
91903
+ label: "",
91904
+ severity: "error",
91905
+ remediation: { key: "", label: "", command: "" }
91906
+ };
91893
91907
  break;
91894
91908
  }
91895
91909
  case "exec-zero": {
91896
91910
  explain(" The command runs once at startup. Exit code 0 = pass, anything else = fail.");
91897
- const command = (await prompts.input({ message: "command", validate: (s) => s.trim().length > 0 ? true : "cannot be empty" })).trim();
91911
+ const command = (await prompts.input({
91912
+ message: "command",
91913
+ validate: (s) => s.trim().length > 0 ? true : "cannot be empty"
91914
+ })).trim();
91898
91915
  const verb = slugify(command.split(/\s+/)[0] ?? "exec");
91899
91916
  idDefault = `${verb}-ok`;
91900
91917
  labelDefault = `\`${command.length > 40 ? command.slice(0, 37) + "\u2026" : command}\` exits 0`;
91901
- typeArgs = { type, command, id: "", label: "", severity: "error", remediation: { key: "", label: "", command: "" } };
91918
+ typeArgs = {
91919
+ type,
91920
+ command,
91921
+ id: "",
91922
+ label: "",
91923
+ severity: "error",
91924
+ remediation: { key: "", label: "", command: "" }
91925
+ };
91902
91926
  break;
91903
91927
  }
91904
91928
  }
@@ -91922,7 +91946,11 @@ async function promptOneHealthCheck(prompts, type, hints) {
91922
91946
  });
91923
91947
  const typed = { ...typeArgs, id, label, severity };
91924
91948
  blank();
91925
- line(source_default.bold(" Remediation \u2014 what should pressing a key in the cockpit do when this check fails?"));
91949
+ line(
91950
+ source_default.bold(
91951
+ " Remediation \u2014 what should pressing a key in the cockpit do when this check fails?"
91952
+ )
91953
+ );
91926
91954
  explain(
91927
91955
  [
91928
91956
  " Three pieces:",
@@ -91977,7 +92005,15 @@ function defaultRemediationCommand(type, hints) {
91977
92005
  return 'echo "edit cockpit.yaml to set the fix command"';
91978
92006
  }
91979
92007
  }
91980
- var ACTION_SCRIPT_CANDIDATES = ["test", "build", "lint", "format", "typecheck", "type-check", "check"];
92008
+ var ACTION_SCRIPT_CANDIDATES = [
92009
+ "test",
92010
+ "build",
92011
+ "lint",
92012
+ "format",
92013
+ "typecheck",
92014
+ "type-check",
92015
+ "check"
92016
+ ];
91981
92017
  function defaultKeyFor(scriptName) {
91982
92018
  const map = {
91983
92019
  test: "t",
@@ -91997,9 +92033,7 @@ async function promptActions(prompts, hints) {
91997
92033
  "from `processes` (long-running streams) and `health` (state-checked)."
91998
92034
  ].join("\n")
91999
92035
  );
92000
- const suggestionScripts = ACTION_SCRIPT_CANDIDATES.filter(
92001
- (s) => hints.packageJsonScripts[s]
92002
- );
92036
+ const suggestionScripts = ACTION_SCRIPT_CANDIDATES.filter((s) => hints.packageJsonScripts[s]);
92003
92037
  const actions = [];
92004
92038
  if (suggestionScripts.length > 0) {
92005
92039
  blank();
@@ -92015,7 +92049,10 @@ async function promptActions(prompts, hints) {
92015
92049
  const key = defaultKeyFor(s);
92016
92050
  const keyHint = key ? ` [${key}]` : "";
92017
92051
  return {
92018
- name: `${s}${keyHint} \u2192 npm run ${s} (${hints.packageJsonScripts[s] ?? ""})`.slice(0, 80),
92052
+ name: `${s}${keyHint} \u2192 npm run ${s} (${hints.packageJsonScripts[s] ?? ""})`.slice(
92053
+ 0,
92054
+ 80
92055
+ ),
92019
92056
  value: s,
92020
92057
  checked: true
92021
92058
  };
@@ -92106,7 +92143,9 @@ async function runInitWizard(opts) {
92106
92143
  line(source_default.dim(" 8. Notifications \u2014 native OS toasts on state changes"));
92107
92144
  blank();
92108
92145
  line(" Anything you skip you can add later by hand-editing cockpit.yaml.");
92109
- line(` Press ${source_default.cyan("Ctrl-C")} to quit; press ${source_default.cyan("enter")} to accept any default.`);
92146
+ line(
92147
+ ` Press ${source_default.cyan("Ctrl-C")} to quit; press ${source_default.cyan("enter")} to accept any default.`
92148
+ );
92110
92149
  blank();
92111
92150
  const proceed = await prompts.confirm({ message: "Ready?", default: true });
92112
92151
  if (!proceed) {
@@ -92268,14 +92307,18 @@ dev-cockpit init-config: wrote ${target}
92268
92307
  try {
92269
92308
  await doctorCommand({ config: target, profile: opts.profile });
92270
92309
  } catch (err) {
92271
- process.stderr.write(`
92310
+ process.stderr.write(
92311
+ `
92272
92312
  doctor failed: ${err instanceof Error ? err.message : String(err)}
92273
- `);
92313
+ `
92314
+ );
92274
92315
  }
92275
92316
  }
92276
92317
  process.stdout.write("\nNext:\n");
92277
92318
  process.stdout.write(" \u2022 Edit cockpit.yaml any time, then re-run `dev-cockpit doctor`.\n");
92278
- process.stdout.write(" \u2022 Run `dev-cockpit dev` to launch the cockpit (Tab/arrows cycle panes, q quits).\n");
92319
+ process.stdout.write(
92320
+ " \u2022 Run `dev-cockpit dev` to launch the cockpit (Tab/arrows cycle panes, q quits).\n"
92321
+ );
92279
92322
  process.stdout.write(" \u2022 The Help tab inside the cockpit has the full docs.\n");
92280
92323
  } else {
92281
92324
  process.stdout.write(" Run `dev-cockpit doctor` to verify the config loads cleanly.\n");
@@ -92350,10 +92393,14 @@ function validateMountManifest(filePath, raw) {
92350
92393
  // src/mount/compose.ts
92351
92394
  function renderDockerOverlay(mounts, opts) {
92352
92395
  const lines = [];
92353
- lines.push(opts.banner ?? "# Generated by `dev-cockpit mount`. Do not edit by hand \u2014 re-run the command.");
92396
+ lines.push(
92397
+ opts.banner ?? "# Generated by `dev-cockpit mount`. Do not edit by hand \u2014 re-run the command."
92398
+ );
92354
92399
  lines.push("services:");
92355
92400
  lines.push(` ${opts.service}:`);
92356
- const binds = mounts.filter((m) => m.kind !== "symlink-only" && typeof m.containerPath === "string");
92401
+ const binds = mounts.filter(
92402
+ (m) => m.kind !== "symlink-only" && typeof m.containerPath === "string"
92403
+ );
92357
92404
  if (binds.length === 0) {
92358
92405
  lines.push(" volumes: []");
92359
92406
  } else {
@@ -92485,23 +92532,19 @@ function detectBrokenSymlinks(workspaceRoot, mounts, strategy) {
92485
92532
  async function readGitInfo(hostPath) {
92486
92533
  try {
92487
92534
  let branchOut = "";
92488
- const branchHandle = spawnStream(
92489
- "git",
92490
- ["-C", hostPath, "rev-parse", "--abbrev-ref", "HEAD"],
92491
- { onStdout: (line2) => {
92535
+ const branchHandle = spawnStream("git", ["-C", hostPath, "rev-parse", "--abbrev-ref", "HEAD"], {
92536
+ onStdout: (line2) => {
92492
92537
  branchOut += line2;
92493
- } }
92494
- );
92538
+ }
92539
+ });
92495
92540
  const branchCode = await branchHandle.exitCode;
92496
92541
  if (branchCode !== 0) return null;
92497
92542
  let statusOut = "";
92498
- const statusHandle = spawnStream(
92499
- "git",
92500
- ["-C", hostPath, "status", "--porcelain"],
92501
- { onStdout: (line2) => {
92543
+ const statusHandle = spawnStream("git", ["-C", hostPath, "status", "--porcelain"], {
92544
+ onStdout: (line2) => {
92502
92545
  statusOut += line2;
92503
- } }
92504
- );
92546
+ }
92547
+ });
92505
92548
  await statusHandle.exitCode;
92506
92549
  return {
92507
92550
  branch: branchOut.trim() || "?",
@@ -92543,20 +92586,18 @@ async function resolveContext(opts) {
92543
92586
  throw err;
92544
92587
  }
92545
92588
  if (!fs15.existsSync(configPath)) {
92546
- process.stderr.write(
92547
- `dev-cockpit mount: cockpit.yaml at ${configPath} doesn't exist.
92548
- `
92549
- );
92589
+ process.stderr.write(`dev-cockpit mount: cockpit.yaml at ${configPath} doesn't exist.
92590
+ `);
92550
92591
  process.exit(1);
92551
92592
  }
92552
92593
  const config = loadConfig(configPath, {
92553
92594
  configSchemaExt: profile?.configSchemaExt,
92554
92595
  profileKey: profile?.appName
92555
92596
  });
92556
- const explicitService = opts.service ?? config.docker?.services?.[0]?.name;
92597
+ const explicitService = opts.service ?? config.mount.service ?? config.docker?.services?.[0]?.name;
92557
92598
  if (!explicitService) {
92558
92599
  process.stderr.write(
92559
- "dev-cockpit mount: no target service. Pass --service <name> or set docker.services in cockpit.yaml.\n"
92600
+ "dev-cockpit mount: no target service. Pass --service <name>, set mount.service in cockpit.yaml, or set docker.services in cockpit.yaml.\n"
92560
92601
  );
92561
92602
  process.exit(1);
92562
92603
  }
@@ -92584,14 +92625,6 @@ var stdoutSink = (line2) => process.stdout.write(`${line2}
92584
92625
  `);
92585
92626
  var stderrSink = (line2) => process.stderr.write(`${line2}
92586
92627
  `);
92587
- function applyExclude(mounts, exclude) {
92588
- if (exclude.length === 0) return [...mounts];
92589
- const set = new Set(exclude);
92590
- return mounts.filter((m) => {
92591
- const name = m.meta?.["name"] ?? "";
92592
- return !set.has(name);
92593
- });
92594
- }
92595
92628
  async function pickMounts(candidates) {
92596
92629
  const { checkbox } = await import("@inquirer/prompts");
92597
92630
  const choices = candidates.map((m) => {
@@ -92608,8 +92641,17 @@ async function pickMounts(candidates) {
92608
92641
  }
92609
92642
  async function mountCommand(opts = {}) {
92610
92643
  const ctx = await resolveContext(opts);
92611
- const { workspaceRoot, appName, service, configMounts, providerMounts, overlayPath, manifestPath: manifestPath2, profile } = ctx;
92612
- const merged = applyExclude(mergeMounts(configMounts, providerMounts), opts.exclude ?? []);
92644
+ const {
92645
+ workspaceRoot,
92646
+ appName,
92647
+ service,
92648
+ configMounts,
92649
+ providerMounts,
92650
+ overlayPath,
92651
+ manifestPath: manifestPath2,
92652
+ profile
92653
+ } = ctx;
92654
+ const merged = mergeMounts(configMounts, providerMounts);
92613
92655
  if (merged.length === 0) {
92614
92656
  process.stdout.write(
92615
92657
  "dev-cockpit mount: no mount candidates from config.mounts[] or profile.mountCandidatesProvider.\n"
@@ -92656,7 +92698,8 @@ async function mountCommand(opts = {}) {
92656
92698
  `
92657
92699
  );
92658
92700
  }
92659
- for (const p of report.skipped) process.stdout.write(`dev-cockpit mount: skipped (could not replace) \u2192 ${p}
92701
+ for (const p of report.skipped)
92702
+ process.stdout.write(`dev-cockpit mount: skipped (could not replace) \u2192 ${p}
92660
92703
  `);
92661
92704
  }
92662
92705
  if (profile?.onMountApply) {
@@ -92798,8 +92841,10 @@ async function migrateConfigCommand(opts = {}) {
92798
92841
  }
92799
92842
  const fromVersion = raw["version"];
92800
92843
  if (fromVersion === CONFIG_VERSION) {
92801
- process.stdout.write(`dev-cockpit migrate-config: already at v${CONFIG_VERSION}; nothing to do.
92802
- `);
92844
+ process.stdout.write(
92845
+ `dev-cockpit migrate-config: already at v${CONFIG_VERSION}; nothing to do.
92846
+ `
92847
+ );
92803
92848
  return;
92804
92849
  }
92805
92850
  if (fromVersion > CONFIG_VERSION) {
@@ -92851,24 +92896,32 @@ function buildCli(opts = {}) {
92851
92896
  const program2 = new Command();
92852
92897
  const profile = opts.profile;
92853
92898
  const appName = profile?.appName ?? "dev-cockpit";
92854
- program2.name(appName).description(
92855
- profile ? `${appName} \u2014 built on dev-cockpit` : "Generic terminal UI dev cockpit"
92856
- ).version(readPackageVersion(), "-V, --version", "Output the version number");
92899
+ program2.name(appName).description(profile ? `${appName} \u2014 built on dev-cockpit` : "Generic terminal UI dev cockpit").version(readPackageVersion(), "-V, --version", "Output the version number");
92857
92900
  if (profile?.setupCli) {
92858
92901
  profile.setupCli(program2);
92859
92902
  }
92860
92903
  if (!hasCommand(program2, "dev")) {
92861
- program2.command("dev").description("Boot the three-pane TUI (Repos / Output / Health / Help)").option("-c, --config <path>", "Path to cockpit.yaml (default: <cwd>/cockpit.yaml or registered via `link`)").action(async (cmdOpts) => {
92904
+ program2.command("dev").description("Boot the three-pane TUI (Repos / Output / Health / Help)").option(
92905
+ "-c, --config <path>",
92906
+ "Path to cockpit.yaml (default: <cwd>/cockpit.yaml or registered via `link`)"
92907
+ ).action(async (cmdOpts) => {
92862
92908
  await devCommand({ config: cmdOpts.config, profile });
92863
92909
  });
92864
92910
  }
92865
92911
  if (!hasCommand(program2, "doctor")) {
92866
- program2.command("doctor").description("Run all health checks once and print a status table").option("-c, --config <path>", "Path to cockpit.yaml (default: <cwd>/cockpit.yaml or registered via `link`)").action(async (cmdOpts) => {
92912
+ program2.command("doctor").description("Run all health checks once and print a status table").option(
92913
+ "-c, --config <path>",
92914
+ "Path to cockpit.yaml (default: <cwd>/cockpit.yaml or registered via `link`)"
92915
+ ).action(async (cmdOpts) => {
92867
92916
  await doctorCommand({ config: cmdOpts.config, profile });
92868
92917
  });
92869
92918
  }
92870
92919
  if (!hasCommand(program2, "init-config")) {
92871
- program2.command("init-config").description("Write a starter cockpit.yaml in the current directory").option("-f, --force", "Overwrite an existing cockpit.yaml without prompting", false).option("--with-docker", "Include an uncommented docker block (static template only)", false).option("-i, --interactive", "Walk through prompts to populate the file (skips static template)", false).option("-o, --output <path>", "Write the file to this path instead of <cwd>/cockpit.yaml").action(
92920
+ program2.command("init-config").description("Write a starter cockpit.yaml in the current directory").option("-f, --force", "Overwrite an existing cockpit.yaml without prompting", false).option("--with-docker", "Include an uncommented docker block (static template only)", false).option(
92921
+ "-i, --interactive",
92922
+ "Walk through prompts to populate the file (skips static template)",
92923
+ false
92924
+ ).option("-o, --output <path>", "Write the file to this path instead of <cwd>/cockpit.yaml").action(
92872
92925
  async (cmdOpts) => {
92873
92926
  await initConfigCommand({
92874
92927
  force: cmdOpts.force ?? false,
@@ -92883,42 +92936,52 @@ function buildCli(opts = {}) {
92883
92936
  }
92884
92937
  if (!hasCommand(program2, "link")) {
92885
92938
  const linkCmd = program2.command("link").description("Register the current directory as using a cockpit.yaml that lives elsewhere").argument("<config-path>", "Path to the cockpit.yaml to associate with this directory").action(async (configPath) => {
92886
- const { linkAddCommand } = await import("./link-VWT2VQH6.js");
92939
+ const { linkAddCommand } = await import("./link-Y7OFHOUP.js");
92887
92940
  linkAddCommand({ configPath });
92888
92941
  });
92889
92942
  linkCmd.command("list").description("Print all registered project \u2192 config mappings").action(async () => {
92890
- const { linkListCommand } = await import("./link-VWT2VQH6.js");
92943
+ const { linkListCommand } = await import("./link-Y7OFHOUP.js");
92891
92944
  linkListCommand();
92892
92945
  });
92893
92946
  linkCmd.command("remove").description("Unregister the current directory from the manifest").action(async () => {
92894
- const { linkRemoveCommand } = await import("./link-VWT2VQH6.js");
92947
+ const { linkRemoveCommand } = await import("./link-Y7OFHOUP.js");
92895
92948
  linkRemoveCommand();
92896
92949
  });
92897
92950
  }
92898
92951
  if (!hasCommand(program2, "mount")) {
92899
- const mountCmd = program2.command("mount").description("Apply a docker-compose bind-mount overlay (interactive picker by default)").option("-c, --config <path>", "Path to cockpit.yaml (default: <cwd>/cockpit.yaml or registered via `link`)").option("-s, --service <name>", "Target compose service (default: first in docker.services)").option("-q, --quiet", "Skip the interactive picker; apply all candidates").option(
92900
- "-e, --exclude <name>",
92901
- "Exclude a candidate by meta.name (repeatable)",
92902
- (val, prev) => [...prev, val],
92903
- []
92904
- ).action(async (cmdOpts) => {
92952
+ const mountCmd = program2.command("mount").description(
92953
+ `Apply a docker-compose bind-mount overlay (interactive picker by default)
92954
+
92955
+ This creates a docker-compose overlay file. The location of the overlay file is configurable in the cockpit.yaml file. You must then include the overlay file in your compose file as a wildcard include. eg. \`docker-compose.yml -f docker/compose/web/docker-compose.dev-link.yml\``
92956
+ ).option(
92957
+ "-c, --config <path>",
92958
+ "Path to cockpit.yaml (default: <cwd>/cockpit.yaml or registered via `link`)"
92959
+ ).option("-s, --service <name>", "Target compose service (default: first in docker.services)").option("-q, --quiet", "Skip the interactive picker; apply all candidates").action(async (cmdOpts) => {
92905
92960
  await mountCommand({
92906
92961
  config: cmdOpts.config,
92907
92962
  service: cmdOpts.service,
92908
92963
  quiet: cmdOpts.quiet ?? false,
92909
- exclude: cmdOpts.exclude ?? [],
92910
92964
  profile
92911
92965
  });
92912
92966
  });
92913
- mountCmd.command("status").description("Show active mounts with branch, dirty, and broken-symlink status").option("-c, --config <path>", "Path to cockpit.yaml (default: <cwd>/cockpit.yaml or registered via `link`)").action(async (cmdOpts) => {
92967
+ mountCmd.command("status").description("Show active mounts with branch, dirty, and broken-symlink status").option(
92968
+ "-c, --config <path>",
92969
+ "Path to cockpit.yaml (default: <cwd>/cockpit.yaml or registered via `link`)"
92970
+ ).action(async (cmdOpts) => {
92914
92971
  await mountStatusCommand({ config: cmdOpts.config, profile });
92915
92972
  });
92916
- mountCmd.command("clear").description("Remove the overlay, manifest, and managed symlinks; runs profile.onMountClear").option("-c, --config <path>", "Path to cockpit.yaml (default: <cwd>/cockpit.yaml or registered via `link`)").action(async (cmdOpts) => {
92973
+ mountCmd.command("clear").description("Remove the overlay, manifest, and managed symlinks; runs profile.onMountClear").option(
92974
+ "-c, --config <path>",
92975
+ "Path to cockpit.yaml (default: <cwd>/cockpit.yaml or registered via `link`)"
92976
+ ).action(async (cmdOpts) => {
92917
92977
  await mountClearCommand({ config: cmdOpts.config, profile });
92918
92978
  });
92919
92979
  }
92920
92980
  if (!hasCommand(program2, "migrate-config")) {
92921
- program2.command("migrate-config").description("Rewrite cockpit.yaml at the current CONFIG_VERSION").option("-c, --config <path>", "Path to cockpit.yaml (default: <cwd>/cockpit.yaml or registered via `link`)").option("--dry-run", "Print the migrated YAML to stdout instead of writing").action(async (cmdOpts) => {
92981
+ program2.command("migrate-config").description("Rewrite cockpit.yaml at the current CONFIG_VERSION").option(
92982
+ "-c, --config <path>",
92983
+ "Path to cockpit.yaml (default: <cwd>/cockpit.yaml or registered via `link`)"
92984
+ ).option("--dry-run", "Print the migrated YAML to stdout instead of writing").action(async (cmdOpts) => {
92922
92985
  await migrateConfigCommand({ config: cmdOpts.config, dryRun: cmdOpts.dryRun });
92923
92986
  });
92924
92987
  }