dev-cockpit 0.2.6 → 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.
- package/README.md +32 -32
- package/bin/dev-cockpit.mjs +1 -1
- package/dist/buildCli.d.ts.map +1 -1
- package/dist/{chunk-A446TCT5.js → chunk-YTMK7EXK.js} +1 -1
- package/dist/chunk-YTMK7EXK.js.map +7 -0
- package/dist/cockpit/Footer.d.ts.map +1 -1
- package/dist/cockpit/hooks/useGlobalKeys.d.ts.map +1 -1
- package/dist/cockpit/panes/FilterModal.d.ts.map +1 -1
- package/dist/cockpit/panes/Output.d.ts.map +1 -1
- package/dist/cockpit/panes/Repos.d.ts.map +1 -1
- package/dist/cockpit/panes/SearchModal.d.ts.map +1 -1
- package/dist/cockpit/state/store.d.ts.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/init-config-wizard.d.ts.map +1 -1
- package/dist/commands/init-config.d.ts.map +1 -1
- package/dist/commands/link.d.ts.map +1 -1
- package/dist/commands/migrate-config.d.ts.map +1 -1
- package/dist/commands/mount.d.ts +1 -3
- package/dist/commands/mount.d.ts.map +1 -1
- package/dist/core/config-discovery.d.ts.map +1 -1
- package/dist/core/config.d.ts +27 -6
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/manifest.d.ts.map +1 -1
- package/dist/core/migrations.d.ts.map +1 -1
- package/dist/core/paths.d.ts.map +1 -1
- package/dist/core/subprocess.d.ts.map +1 -1
- package/dist/core/types.d.ts +16 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/docker/highlights.d.ts.map +1 -1
- package/dist/health/builtin.d.ts.map +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +274 -170
- package/dist/index.js.map +3 -3
- package/dist/ink.d.ts +1 -1
- package/dist/ink.d.ts.map +1 -1
- package/dist/{link-VWT2VQH6.js → link-Y7OFHOUP.js} +4 -6
- package/dist/link-Y7OFHOUP.js.map +7 -0
- package/dist/mount/compose.d.ts.map +1 -1
- package/dist/mount/symlinks.d.ts +4 -4
- package/dist/mount/symlinks.d.ts.map +1 -1
- package/dist/mount/types.d.ts +15 -2
- package/dist/mount/types.d.ts.map +1 -1
- package/docs/commands.md +8 -8
- package/docs/config-reference.md +45 -41
- package/docs/health.md +32 -22
- package/docs/init-config.md +16 -16
- package/docs/mount.md +14 -9
- package/docs/notifications.md +3 -3
- package/docs/panes.md +5 -5
- package/docs/processes.md +7 -5
- package/examples/cockpit.schema.json +230 -59
- package/examples/cockpit.yaml +8 -6
- package/package.json +99 -93
- package/prettier-config.json +7 -0
- package/dist/chunk-A446TCT5.js.map +0 -7
- 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-
|
|
26
|
+
} from "./chunk-YTMK7EXK.js";
|
|
27
27
|
import {
|
|
28
28
|
__commonJS,
|
|
29
29
|
__export,
|
|
@@ -4819,7 +4819,7 @@ var require_cross_spawn = __commonJS({
|
|
|
4819
4819
|
enoent.hookChildProcess(spawned, parsed);
|
|
4820
4820
|
return spawned;
|
|
4821
4821
|
}
|
|
4822
|
-
function
|
|
4822
|
+
function spawnSync3(command, args, options2) {
|
|
4823
4823
|
const parsed = parse(command, args, options2);
|
|
4824
4824
|
const result = cp.spawnSync(parsed.command, parsed.args, parsed.options);
|
|
4825
4825
|
result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
|
|
@@ -4827,7 +4827,7 @@ var require_cross_spawn = __commonJS({
|
|
|
4827
4827
|
}
|
|
4828
4828
|
module.exports = spawn2;
|
|
4829
4829
|
module.exports.spawn = spawn2;
|
|
4830
|
-
module.exports.sync =
|
|
4830
|
+
module.exports.sync = spawnSync3;
|
|
4831
4831
|
module.exports._parse = parse;
|
|
4832
4832
|
module.exports._enoent = enoent;
|
|
4833
4833
|
}
|
|
@@ -83970,9 +83970,13 @@ var NotificationsSchema = external_exports.object({
|
|
|
83970
83970
|
});
|
|
83971
83971
|
var MountSchema = external_exports.object({
|
|
83972
83972
|
hostPath: external_exports.string(),
|
|
83973
|
-
containerPath: external_exports.string(),
|
|
83973
|
+
containerPath: external_exports.string().optional(),
|
|
83974
|
+
kind: external_exports.enum(["bind", "symlink-only"]).optional(),
|
|
83974
83975
|
meta: external_exports.record(external_exports.unknown()).optional()
|
|
83975
|
-
})
|
|
83976
|
+
}).refine(
|
|
83977
|
+
(m) => m.kind === "symlink-only" ? true : typeof m.containerPath === "string" && m.containerPath.length > 0,
|
|
83978
|
+
{ message: "Mount with kind='bind' (default) requires containerPath" }
|
|
83979
|
+
);
|
|
83976
83980
|
var ActionSchema = external_exports.object({
|
|
83977
83981
|
id: external_exports.string(),
|
|
83978
83982
|
label: external_exports.string(),
|
|
@@ -83994,7 +83998,9 @@ var MountSettingsSchema = external_exports.object({
|
|
|
83994
83998
|
*/
|
|
83995
83999
|
overlayPath: external_exports.string().optional(),
|
|
83996
84000
|
/** Basename inside stateDir for the manifest. */
|
|
83997
|
-
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()
|
|
83998
84004
|
});
|
|
83999
84005
|
var BaseCockpitConfigSchema = external_exports.object({
|
|
84000
84006
|
version: external_exports.number().int(),
|
|
@@ -84176,9 +84182,7 @@ var FOCUS_ORDER = ["repos", "output", "health", "help"];
|
|
|
84176
84182
|
function filterActions(actions, filter) {
|
|
84177
84183
|
if (!filter) return actions;
|
|
84178
84184
|
const f = filter.toLowerCase();
|
|
84179
|
-
return actions.filter(
|
|
84180
|
-
(a2) => a2.id.toLowerCase().includes(f) || a2.label.toLowerCase().includes(f)
|
|
84181
|
-
);
|
|
84185
|
+
return actions.filter((a2) => a2.id.toLowerCase().includes(f) || a2.label.toLowerCase().includes(f));
|
|
84182
84186
|
}
|
|
84183
84187
|
var cockpitStore = createStore()((set, get2) => ({
|
|
84184
84188
|
repos: {},
|
|
@@ -84447,7 +84451,7 @@ function Repos() {
|
|
|
84447
84451
|
const heading2 = kind === "repo" ? "Repos" : kind === "docker" ? "Docker" : "Processes";
|
|
84448
84452
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box_default, { flexDirection: "column", marginTop: 1, children: [
|
|
84449
84453
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, { dimColor: true, children: [
|
|
84450
|
-
"
|
|
84454
|
+
" ",
|
|
84451
84455
|
heading2
|
|
84452
84456
|
] }),
|
|
84453
84457
|
entriesInKind.map(({ key, idx, entry }) => {
|
|
@@ -84484,7 +84488,7 @@ function Repos() {
|
|
|
84484
84488
|
" ",
|
|
84485
84489
|
a2.label
|
|
84486
84490
|
] }),
|
|
84487
|
-
isDefault && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: "
|
|
84491
|
+
isDefault && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { dimColor: true, children: " (default)" })
|
|
84488
84492
|
] }, a2.id);
|
|
84489
84493
|
})
|
|
84490
84494
|
]
|
|
@@ -84585,9 +84589,7 @@ function Output() {
|
|
|
84585
84589
|
} else if (key.downArrow) {
|
|
84586
84590
|
setScrollOffset((prev) => Math.max(0, prev - 1));
|
|
84587
84591
|
} else if (key.pageUp) {
|
|
84588
|
-
setScrollOffset(
|
|
84589
|
-
(prev) => Math.min(prev + visibleLines, Math.max(0, total - visibleLines))
|
|
84590
|
-
);
|
|
84592
|
+
setScrollOffset((prev) => Math.min(prev + visibleLines, Math.max(0, total - visibleLines)));
|
|
84591
84593
|
} else if (key.pageDown) {
|
|
84592
84594
|
setScrollOffset((prev) => Math.max(0, prev - visibleLines));
|
|
84593
84595
|
} else if (key.return) {
|
|
@@ -87647,7 +87649,9 @@ function Footer({ legends } = {}) {
|
|
|
87647
87649
|
if (!key) return NAV_HINT;
|
|
87648
87650
|
const keyed = actionsForRepoRow(s.actions, key).filter((a2) => a2.key);
|
|
87649
87651
|
if (keyed.length === 0) return NAV_HINT;
|
|
87650
|
-
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
|
+
);
|
|
87651
87655
|
});
|
|
87652
87656
|
let legend;
|
|
87653
87657
|
if (focus === "repos") {
|
|
@@ -87667,7 +87671,9 @@ var import_react5 = __toESM(require_react(), 1);
|
|
|
87667
87671
|
var import_jsx_runtime7 = __toESM(require_jsx_runtime(), 1);
|
|
87668
87672
|
function FilterModal() {
|
|
87669
87673
|
const outputFilter = useCockpitStore((s) => s.outputFilter);
|
|
87670
|
-
const [severityDraft, setSeverityDraft] = (0, import_react5.useState)(
|
|
87674
|
+
const [severityDraft, setSeverityDraft] = (0, import_react5.useState)(
|
|
87675
|
+
outputFilter.severity
|
|
87676
|
+
);
|
|
87671
87677
|
const SEVERITIES = [void 0, "info", "warn", "error"];
|
|
87672
87678
|
use_input_default((input, key) => {
|
|
87673
87679
|
if (input === "s") {
|
|
@@ -87680,26 +87686,16 @@ function FilterModal() {
|
|
|
87680
87686
|
cockpitStore.getState().setActiveModal(null);
|
|
87681
87687
|
}
|
|
87682
87688
|
});
|
|
87683
|
-
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Box_default, { flexGrow: 1, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
87684
|
-
|
|
87685
|
-
{
|
|
87686
|
-
|
|
87687
|
-
|
|
87688
|
-
|
|
87689
|
-
|
|
87690
|
-
|
|
87691
|
-
|
|
87692
|
-
|
|
87693
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: " " }),
|
|
87694
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Box_default, { children: [
|
|
87695
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: "Severity (s to cycle): " }),
|
|
87696
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { color: "cyan", children: severityDraft ?? "all" })
|
|
87697
|
-
] }),
|
|
87698
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: " " }),
|
|
87699
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { dimColor: true, children: "Enter = apply \xB7 Esc = cancel" })
|
|
87700
|
-
]
|
|
87701
|
-
}
|
|
87702
|
-
) });
|
|
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
|
+
] }) });
|
|
87703
87699
|
}
|
|
87704
87700
|
|
|
87705
87701
|
// src/cockpit/panes/SearchModal.tsx
|
|
@@ -87729,29 +87725,19 @@ function SearchModal() {
|
|
|
87729
87725
|
setQuery((prev) => prev + input);
|
|
87730
87726
|
}
|
|
87731
87727
|
});
|
|
87732
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Box_default, { flexGrow: 1, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
87733
|
-
|
|
87734
|
-
{
|
|
87735
|
-
|
|
87736
|
-
|
|
87737
|
-
|
|
87738
|
-
|
|
87739
|
-
|
|
87740
|
-
|
|
87741
|
-
|
|
87742
|
-
|
|
87743
|
-
|
|
87744
|
-
|
|
87745
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Text, { color: "cyan", children: [
|
|
87746
|
-
query,
|
|
87747
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: "gray", children: "\u2588" })
|
|
87748
|
-
] })
|
|
87749
|
-
] }),
|
|
87750
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { children: " " }),
|
|
87751
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { dimColor: true, children: "Enter = apply \xB7 Esc = cancel \xB7 Backspace = delete" })
|
|
87752
|
-
]
|
|
87753
|
-
}
|
|
87754
|
-
) });
|
|
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
|
+
] }) });
|
|
87755
87741
|
}
|
|
87756
87742
|
|
|
87757
87743
|
// src/cockpit/panes/CommandModal.tsx
|
|
@@ -87906,9 +87892,7 @@ function useGlobalKeys(opts) {
|
|
|
87906
87892
|
return;
|
|
87907
87893
|
}
|
|
87908
87894
|
if (input === "e" && onOpenError) {
|
|
87909
|
-
const target = state.recentErrors.find(
|
|
87910
|
-
(er) => er.file && typeof er.line === "number"
|
|
87911
|
-
);
|
|
87895
|
+
const target = state.recentErrors.find((er) => er.file && typeof er.line === "number");
|
|
87912
87896
|
if (target?.file && typeof target.line === "number") {
|
|
87913
87897
|
onOpenError({
|
|
87914
87898
|
file: target.file,
|
|
@@ -87946,10 +87930,7 @@ function useGlobalKeys(opts) {
|
|
|
87946
87930
|
healthId: dispatch.healthId,
|
|
87947
87931
|
healthLabel: dispatch.healthLabel
|
|
87948
87932
|
});
|
|
87949
|
-
withMinHold(
|
|
87950
|
-
dispatch.promise,
|
|
87951
|
-
() => cockpitStore.getState().setActiveRemediation(null)
|
|
87952
|
-
);
|
|
87933
|
+
withMinHold(dispatch.promise, () => cockpitStore.getState().setActiveRemediation(null));
|
|
87953
87934
|
return;
|
|
87954
87935
|
}
|
|
87955
87936
|
}
|
|
@@ -90963,11 +90944,7 @@ async function devCommand(opts = {}) {
|
|
|
90963
90944
|
const builtinActions = buildBuiltinActions(config);
|
|
90964
90945
|
const actions = buildActionRegistry(
|
|
90965
90946
|
[...config.actions],
|
|
90966
|
-
[
|
|
90967
|
-
...builtinActions,
|
|
90968
|
-
...profile?.actions ?? [],
|
|
90969
|
-
...bootResult.actions ?? []
|
|
90970
|
-
]
|
|
90947
|
+
[...builtinActions, ...profile?.actions ?? [], ...bootResult.actions ?? []]
|
|
90971
90948
|
);
|
|
90972
90949
|
const [shell, shellFlag] = process.platform === "win32" ? ["cmd", "/c"] : ["/bin/sh", "-c"];
|
|
90973
90950
|
const highlightMatcher = compileHighlights(config.highlights);
|
|
@@ -91040,7 +91017,12 @@ async function devCommand(opts = {}) {
|
|
|
91040
91017
|
}
|
|
91041
91018
|
if (action.id.startsWith(BUILTIN_RESTART_PROCESS)) {
|
|
91042
91019
|
const procId = action.id.slice(BUILTIN_RESTART_PROCESS.length);
|
|
91043
|
-
store.appendOutput({
|
|
91020
|
+
store.appendOutput({
|
|
91021
|
+
ts: Date.now(),
|
|
91022
|
+
source: procId,
|
|
91023
|
+
severity: "info",
|
|
91024
|
+
text: `> restart ${procId}`
|
|
91025
|
+
});
|
|
91044
91026
|
await killSpawnedByTag(procId);
|
|
91045
91027
|
spawnProcessById(procId);
|
|
91046
91028
|
store.setFocus("output");
|
|
@@ -91334,10 +91316,7 @@ function renderWizardYaml(result) {
|
|
|
91334
91316
|
if (health.length > 0) blocks.push(health);
|
|
91335
91317
|
const actions = renderActions(result.actions);
|
|
91336
91318
|
if (actions.length > 0) blocks.push(actions);
|
|
91337
|
-
blocks.push([
|
|
91338
|
-
"notifications:",
|
|
91339
|
-
indent(`enabled: ${result.notifications.enabled}`, 1)
|
|
91340
|
-
]);
|
|
91319
|
+
blocks.push(["notifications:", indent(`enabled: ${result.notifications.enabled}`, 1)]);
|
|
91341
91320
|
if (result.profileLines && result.profileLines.length > 0) {
|
|
91342
91321
|
blocks.push([
|
|
91343
91322
|
"profile:",
|
|
@@ -91406,7 +91385,12 @@ function safeReadJson(p) {
|
|
|
91406
91385
|
}
|
|
91407
91386
|
}
|
|
91408
91387
|
function detectComposeFile(cwd) {
|
|
91409
|
-
for (const candidate of [
|
|
91388
|
+
for (const candidate of [
|
|
91389
|
+
"compose.yaml",
|
|
91390
|
+
"compose.yml",
|
|
91391
|
+
"docker-compose.yml",
|
|
91392
|
+
"docker-compose.yaml"
|
|
91393
|
+
]) {
|
|
91410
91394
|
if (fs11.existsSync(path15.join(cwd, candidate))) return candidate;
|
|
91411
91395
|
}
|
|
91412
91396
|
return void 0;
|
|
@@ -91444,7 +91428,10 @@ function detectRepoSuggestions(cwd, pkg) {
|
|
|
91444
91428
|
}
|
|
91445
91429
|
for (const glob of workspaceGlobs) {
|
|
91446
91430
|
for (const entry of expandSimpleGlob(cwd, glob)) {
|
|
91447
|
-
out.push({
|
|
91431
|
+
out.push({
|
|
91432
|
+
id: path15.basename(entry),
|
|
91433
|
+
path: path15.relative(cwd, path15.join(cwd, entry)) || "."
|
|
91434
|
+
});
|
|
91448
91435
|
}
|
|
91449
91436
|
}
|
|
91450
91437
|
const pnpmFile = path15.join(cwd, "pnpm-workspace.yaml");
|
|
@@ -91787,7 +91774,9 @@ async function promptHealthChecks(prompts, hints, hasDocker) {
|
|
|
91787
91774
|
].join("\n")
|
|
91788
91775
|
);
|
|
91789
91776
|
const out = [];
|
|
91790
|
-
let typeChoices = baseHealthTypeChoices(
|
|
91777
|
+
let typeChoices = baseHealthTypeChoices(
|
|
91778
|
+
Boolean(hints.composeFile && hints.composeServices.length > 0)
|
|
91779
|
+
);
|
|
91791
91780
|
if (!hasDocker) {
|
|
91792
91781
|
typeChoices = typeChoices.filter((c3) => c3.value !== "container-running");
|
|
91793
91782
|
}
|
|
@@ -91852,7 +91841,14 @@ async function promptOneHealthCheck(prompts, type, hints) {
|
|
|
91852
91841
|
})).trim();
|
|
91853
91842
|
idDefault = `${slugify(container)}-up`;
|
|
91854
91843
|
labelDefault = `Container \`${container}\` running`;
|
|
91855
|
-
typeArgs = {
|
|
91844
|
+
typeArgs = {
|
|
91845
|
+
type,
|
|
91846
|
+
container,
|
|
91847
|
+
id: "",
|
|
91848
|
+
label: "",
|
|
91849
|
+
severity: "error",
|
|
91850
|
+
remediation: { key: "", label: "", command: "" }
|
|
91851
|
+
};
|
|
91856
91852
|
break;
|
|
91857
91853
|
}
|
|
91858
91854
|
case "port-open": {
|
|
@@ -91861,7 +91857,15 @@ async function promptOneHealthCheck(prompts, type, hints) {
|
|
|
91861
91857
|
const port = portRaw ?? 0;
|
|
91862
91858
|
idDefault = `port-${port}-open`;
|
|
91863
91859
|
labelDefault = `Port ${port} open`;
|
|
91864
|
-
typeArgs = {
|
|
91860
|
+
typeArgs = {
|
|
91861
|
+
type,
|
|
91862
|
+
host,
|
|
91863
|
+
port,
|
|
91864
|
+
id: "",
|
|
91865
|
+
label: "",
|
|
91866
|
+
severity: "error",
|
|
91867
|
+
remediation: { key: "", label: "", command: "" }
|
|
91868
|
+
};
|
|
91865
91869
|
break;
|
|
91866
91870
|
}
|
|
91867
91871
|
case "http-ok": {
|
|
@@ -91873,7 +91877,14 @@ async function promptOneHealthCheck(prompts, type, hints) {
|
|
|
91873
91877
|
const pathPart = url.replace(/^https?:\/\/[^/]+/, "").replace(/^\//, "") || "root";
|
|
91874
91878
|
idDefault = `http-${slugify(pathPart)}`;
|
|
91875
91879
|
labelDefault = `GET ${url} returns 2xx`;
|
|
91876
|
-
typeArgs = {
|
|
91880
|
+
typeArgs = {
|
|
91881
|
+
type,
|
|
91882
|
+
url,
|
|
91883
|
+
id: "",
|
|
91884
|
+
label: "",
|
|
91885
|
+
severity: "error",
|
|
91886
|
+
remediation: { key: "", label: "", command: "" }
|
|
91887
|
+
};
|
|
91877
91888
|
break;
|
|
91878
91889
|
}
|
|
91879
91890
|
case "file-exists": {
|
|
@@ -91885,16 +91896,33 @@ async function promptOneHealthCheck(prompts, type, hints) {
|
|
|
91885
91896
|
const basename3 = filePath.split("/").filter(Boolean).pop() ?? filePath;
|
|
91886
91897
|
idDefault = `${slugify(basename3)}-exists`;
|
|
91887
91898
|
labelDefault = `\`${filePath}\` exists`;
|
|
91888
|
-
typeArgs = {
|
|
91899
|
+
typeArgs = {
|
|
91900
|
+
type,
|
|
91901
|
+
path: filePath,
|
|
91902
|
+
id: "",
|
|
91903
|
+
label: "",
|
|
91904
|
+
severity: "error",
|
|
91905
|
+
remediation: { key: "", label: "", command: "" }
|
|
91906
|
+
};
|
|
91889
91907
|
break;
|
|
91890
91908
|
}
|
|
91891
91909
|
case "exec-zero": {
|
|
91892
91910
|
explain(" The command runs once at startup. Exit code 0 = pass, anything else = fail.");
|
|
91893
|
-
const command = (await prompts.input({
|
|
91911
|
+
const command = (await prompts.input({
|
|
91912
|
+
message: "command",
|
|
91913
|
+
validate: (s) => s.trim().length > 0 ? true : "cannot be empty"
|
|
91914
|
+
})).trim();
|
|
91894
91915
|
const verb = slugify(command.split(/\s+/)[0] ?? "exec");
|
|
91895
91916
|
idDefault = `${verb}-ok`;
|
|
91896
91917
|
labelDefault = `\`${command.length > 40 ? command.slice(0, 37) + "\u2026" : command}\` exits 0`;
|
|
91897
|
-
typeArgs = {
|
|
91918
|
+
typeArgs = {
|
|
91919
|
+
type,
|
|
91920
|
+
command,
|
|
91921
|
+
id: "",
|
|
91922
|
+
label: "",
|
|
91923
|
+
severity: "error",
|
|
91924
|
+
remediation: { key: "", label: "", command: "" }
|
|
91925
|
+
};
|
|
91898
91926
|
break;
|
|
91899
91927
|
}
|
|
91900
91928
|
}
|
|
@@ -91918,7 +91946,11 @@ async function promptOneHealthCheck(prompts, type, hints) {
|
|
|
91918
91946
|
});
|
|
91919
91947
|
const typed = { ...typeArgs, id, label, severity };
|
|
91920
91948
|
blank();
|
|
91921
|
-
line(
|
|
91949
|
+
line(
|
|
91950
|
+
source_default.bold(
|
|
91951
|
+
" Remediation \u2014 what should pressing a key in the cockpit do when this check fails?"
|
|
91952
|
+
)
|
|
91953
|
+
);
|
|
91922
91954
|
explain(
|
|
91923
91955
|
[
|
|
91924
91956
|
" Three pieces:",
|
|
@@ -91973,7 +92005,15 @@ function defaultRemediationCommand(type, hints) {
|
|
|
91973
92005
|
return 'echo "edit cockpit.yaml to set the fix command"';
|
|
91974
92006
|
}
|
|
91975
92007
|
}
|
|
91976
|
-
var ACTION_SCRIPT_CANDIDATES = [
|
|
92008
|
+
var ACTION_SCRIPT_CANDIDATES = [
|
|
92009
|
+
"test",
|
|
92010
|
+
"build",
|
|
92011
|
+
"lint",
|
|
92012
|
+
"format",
|
|
92013
|
+
"typecheck",
|
|
92014
|
+
"type-check",
|
|
92015
|
+
"check"
|
|
92016
|
+
];
|
|
91977
92017
|
function defaultKeyFor(scriptName) {
|
|
91978
92018
|
const map = {
|
|
91979
92019
|
test: "t",
|
|
@@ -91993,9 +92033,7 @@ async function promptActions(prompts, hints) {
|
|
|
91993
92033
|
"from `processes` (long-running streams) and `health` (state-checked)."
|
|
91994
92034
|
].join("\n")
|
|
91995
92035
|
);
|
|
91996
|
-
const suggestionScripts = ACTION_SCRIPT_CANDIDATES.filter(
|
|
91997
|
-
(s) => hints.packageJsonScripts[s]
|
|
91998
|
-
);
|
|
92036
|
+
const suggestionScripts = ACTION_SCRIPT_CANDIDATES.filter((s) => hints.packageJsonScripts[s]);
|
|
91999
92037
|
const actions = [];
|
|
92000
92038
|
if (suggestionScripts.length > 0) {
|
|
92001
92039
|
blank();
|
|
@@ -92011,7 +92049,10 @@ async function promptActions(prompts, hints) {
|
|
|
92011
92049
|
const key = defaultKeyFor(s);
|
|
92012
92050
|
const keyHint = key ? ` [${key}]` : "";
|
|
92013
92051
|
return {
|
|
92014
|
-
name: `${s}${keyHint} \u2192 npm run ${s} (${hints.packageJsonScripts[s] ?? ""})`.slice(
|
|
92052
|
+
name: `${s}${keyHint} \u2192 npm run ${s} (${hints.packageJsonScripts[s] ?? ""})`.slice(
|
|
92053
|
+
0,
|
|
92054
|
+
80
|
|
92055
|
+
),
|
|
92015
92056
|
value: s,
|
|
92016
92057
|
checked: true
|
|
92017
92058
|
};
|
|
@@ -92102,7 +92143,9 @@ async function runInitWizard(opts) {
|
|
|
92102
92143
|
line(source_default.dim(" 8. Notifications \u2014 native OS toasts on state changes"));
|
|
92103
92144
|
blank();
|
|
92104
92145
|
line(" Anything you skip you can add later by hand-editing cockpit.yaml.");
|
|
92105
|
-
line(
|
|
92146
|
+
line(
|
|
92147
|
+
` Press ${source_default.cyan("Ctrl-C")} to quit; press ${source_default.cyan("enter")} to accept any default.`
|
|
92148
|
+
);
|
|
92106
92149
|
blank();
|
|
92107
92150
|
const proceed = await prompts.confirm({ message: "Ready?", default: true });
|
|
92108
92151
|
if (!proceed) {
|
|
@@ -92264,14 +92307,18 @@ dev-cockpit init-config: wrote ${target}
|
|
|
92264
92307
|
try {
|
|
92265
92308
|
await doctorCommand({ config: target, profile: opts.profile });
|
|
92266
92309
|
} catch (err) {
|
|
92267
|
-
process.stderr.write(
|
|
92310
|
+
process.stderr.write(
|
|
92311
|
+
`
|
|
92268
92312
|
doctor failed: ${err instanceof Error ? err.message : String(err)}
|
|
92269
|
-
`
|
|
92313
|
+
`
|
|
92314
|
+
);
|
|
92270
92315
|
}
|
|
92271
92316
|
}
|
|
92272
92317
|
process.stdout.write("\nNext:\n");
|
|
92273
92318
|
process.stdout.write(" \u2022 Edit cockpit.yaml any time, then re-run `dev-cockpit doctor`.\n");
|
|
92274
|
-
process.stdout.write(
|
|
92319
|
+
process.stdout.write(
|
|
92320
|
+
" \u2022 Run `dev-cockpit dev` to launch the cockpit (Tab/arrows cycle panes, q quits).\n"
|
|
92321
|
+
);
|
|
92275
92322
|
process.stdout.write(" \u2022 The Help tab inside the cockpit has the full docs.\n");
|
|
92276
92323
|
} else {
|
|
92277
92324
|
process.stdout.write(" Run `dev-cockpit doctor` to verify the config loads cleanly.\n");
|
|
@@ -92346,14 +92393,19 @@ function validateMountManifest(filePath, raw) {
|
|
|
92346
92393
|
// src/mount/compose.ts
|
|
92347
92394
|
function renderDockerOverlay(mounts, opts) {
|
|
92348
92395
|
const lines = [];
|
|
92349
|
-
lines.push(
|
|
92396
|
+
lines.push(
|
|
92397
|
+
opts.banner ?? "# Generated by `dev-cockpit mount`. Do not edit by hand \u2014 re-run the command."
|
|
92398
|
+
);
|
|
92350
92399
|
lines.push("services:");
|
|
92351
92400
|
lines.push(` ${opts.service}:`);
|
|
92352
|
-
|
|
92401
|
+
const binds = mounts.filter(
|
|
92402
|
+
(m) => m.kind !== "symlink-only" && typeof m.containerPath === "string"
|
|
92403
|
+
);
|
|
92404
|
+
if (binds.length === 0) {
|
|
92353
92405
|
lines.push(" volumes: []");
|
|
92354
92406
|
} else {
|
|
92355
92407
|
lines.push(" volumes:");
|
|
92356
|
-
for (const m of
|
|
92408
|
+
for (const m of binds) {
|
|
92357
92409
|
const source = m.hostPath.replace(/\\/g, "/");
|
|
92358
92410
|
lines.push(" - type: bind");
|
|
92359
92411
|
lines.push(` source: ${source}`);
|
|
@@ -92379,35 +92431,66 @@ function resolveOverlayPath(opts) {
|
|
|
92379
92431
|
// src/mount/symlinks.ts
|
|
92380
92432
|
import fs14 from "node:fs";
|
|
92381
92433
|
import path19 from "node:path";
|
|
92434
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
92382
92435
|
function applyManagedSymlinks(workspaceRoot, mounts, strategy) {
|
|
92383
92436
|
const report = { created: [], replaced: [], skipped: [] };
|
|
92384
92437
|
for (const m of mounts) {
|
|
92385
92438
|
const linkPath = strategy.linkPath(m, workspaceRoot);
|
|
92386
92439
|
if (!linkPath) continue;
|
|
92387
|
-
|
|
92388
|
-
|
|
92389
|
-
|
|
92390
|
-
|
|
92391
|
-
|
|
92392
|
-
|
|
92393
|
-
|
|
92394
|
-
|
|
92395
|
-
|
|
92440
|
+
const outcome = applyOneSymlink(linkPath, m.hostPath);
|
|
92441
|
+
if (outcome === "created") report.created.push(linkPath);
|
|
92442
|
+
else if (outcome === "replaced") report.replaced.push(linkPath);
|
|
92443
|
+
else report.skipped.push(linkPath);
|
|
92444
|
+
}
|
|
92445
|
+
return report;
|
|
92446
|
+
}
|
|
92447
|
+
function applyOneSymlink(linkPath, hostPath) {
|
|
92448
|
+
let preExistingRealDir = false;
|
|
92449
|
+
let existing = null;
|
|
92450
|
+
try {
|
|
92451
|
+
existing = fs14.lstatSync(linkPath);
|
|
92452
|
+
} catch {
|
|
92453
|
+
}
|
|
92454
|
+
if (existing) {
|
|
92455
|
+
if (existing.isSymbolicLink()) {
|
|
92456
|
+
try {
|
|
92457
|
+
if (fs14.readlinkSync(linkPath) === hostPath) return "created";
|
|
92396
92458
|
fs14.unlinkSync(linkPath);
|
|
92397
|
-
}
|
|
92398
|
-
|
|
92399
|
-
|
|
92400
|
-
|
|
92459
|
+
} catch {
|
|
92460
|
+
return "skipped";
|
|
92461
|
+
}
|
|
92462
|
+
} else if (existing.isDirectory()) {
|
|
92463
|
+
preExistingRealDir = true;
|
|
92464
|
+
if (!tryRemoveDir(linkPath)) return "skipped";
|
|
92465
|
+
} else {
|
|
92466
|
+
try {
|
|
92401
92467
|
fs14.unlinkSync(linkPath);
|
|
92468
|
+
} catch {
|
|
92469
|
+
return "skipped";
|
|
92402
92470
|
}
|
|
92403
|
-
} catch {
|
|
92404
92471
|
}
|
|
92472
|
+
}
|
|
92473
|
+
try {
|
|
92405
92474
|
fs14.mkdirSync(path19.dirname(linkPath), { recursive: true });
|
|
92406
|
-
fs14.symlinkSync(
|
|
92407
|
-
|
|
92408
|
-
|
|
92475
|
+
fs14.symlinkSync(hostPath, linkPath);
|
|
92476
|
+
} catch {
|
|
92477
|
+
return "skipped";
|
|
92409
92478
|
}
|
|
92410
|
-
return
|
|
92479
|
+
return preExistingRealDir ? "replaced" : "created";
|
|
92480
|
+
}
|
|
92481
|
+
function tryRemoveDir(p) {
|
|
92482
|
+
try {
|
|
92483
|
+
fs14.rmSync(p, { recursive: true, force: true });
|
|
92484
|
+
} catch {
|
|
92485
|
+
if (process.platform === "darwin") {
|
|
92486
|
+
spawnSync2("chmod", ["-RN", p], { stdio: "ignore" });
|
|
92487
|
+
try {
|
|
92488
|
+
fs14.rmSync(p, { recursive: true, force: true });
|
|
92489
|
+
} catch {
|
|
92490
|
+
}
|
|
92491
|
+
}
|
|
92492
|
+
}
|
|
92493
|
+
return !fs14.existsSync(p);
|
|
92411
92494
|
}
|
|
92412
92495
|
function removeManagedSymlinks(workspaceRoot, mounts, strategy) {
|
|
92413
92496
|
for (const m of mounts) {
|
|
@@ -92449,23 +92532,19 @@ function detectBrokenSymlinks(workspaceRoot, mounts, strategy) {
|
|
|
92449
92532
|
async function readGitInfo(hostPath) {
|
|
92450
92533
|
try {
|
|
92451
92534
|
let branchOut = "";
|
|
92452
|
-
const branchHandle = spawnStream(
|
|
92453
|
-
|
|
92454
|
-
["-C", hostPath, "rev-parse", "--abbrev-ref", "HEAD"],
|
|
92455
|
-
{ onStdout: (line2) => {
|
|
92535
|
+
const branchHandle = spawnStream("git", ["-C", hostPath, "rev-parse", "--abbrev-ref", "HEAD"], {
|
|
92536
|
+
onStdout: (line2) => {
|
|
92456
92537
|
branchOut += line2;
|
|
92457
|
-
}
|
|
92458
|
-
);
|
|
92538
|
+
}
|
|
92539
|
+
});
|
|
92459
92540
|
const branchCode = await branchHandle.exitCode;
|
|
92460
92541
|
if (branchCode !== 0) return null;
|
|
92461
92542
|
let statusOut = "";
|
|
92462
|
-
const statusHandle = spawnStream(
|
|
92463
|
-
|
|
92464
|
-
["-C", hostPath, "status", "--porcelain"],
|
|
92465
|
-
{ onStdout: (line2) => {
|
|
92543
|
+
const statusHandle = spawnStream("git", ["-C", hostPath, "status", "--porcelain"], {
|
|
92544
|
+
onStdout: (line2) => {
|
|
92466
92545
|
statusOut += line2;
|
|
92467
|
-
}
|
|
92468
|
-
);
|
|
92546
|
+
}
|
|
92547
|
+
});
|
|
92469
92548
|
await statusHandle.exitCode;
|
|
92470
92549
|
return {
|
|
92471
92550
|
branch: branchOut.trim() || "?",
|
|
@@ -92477,10 +92556,14 @@ async function readGitInfo(hostPath) {
|
|
|
92477
92556
|
}
|
|
92478
92557
|
|
|
92479
92558
|
// src/commands/mount.ts
|
|
92559
|
+
function mountKey(m) {
|
|
92560
|
+
if (m.kind === "symlink-only") return `symlink:${m.hostPath}`;
|
|
92561
|
+
return `bind:${m.containerPath ?? m.hostPath}`;
|
|
92562
|
+
}
|
|
92480
92563
|
function mergeMounts(configMounts, providerMounts) {
|
|
92481
92564
|
const seen = /* @__PURE__ */ new Map();
|
|
92482
|
-
for (const m of providerMounts) seen.set(m
|
|
92483
|
-
for (const m of configMounts) seen.set(m
|
|
92565
|
+
for (const m of providerMounts) seen.set(mountKey(m), m);
|
|
92566
|
+
for (const m of configMounts) seen.set(mountKey(m), m);
|
|
92484
92567
|
return Array.from(seen.values());
|
|
92485
92568
|
}
|
|
92486
92569
|
async function resolveContext(opts) {
|
|
@@ -92503,20 +92586,18 @@ async function resolveContext(opts) {
|
|
|
92503
92586
|
throw err;
|
|
92504
92587
|
}
|
|
92505
92588
|
if (!fs15.existsSync(configPath)) {
|
|
92506
|
-
process.stderr.write(
|
|
92507
|
-
|
|
92508
|
-
`
|
|
92509
|
-
);
|
|
92589
|
+
process.stderr.write(`dev-cockpit mount: cockpit.yaml at ${configPath} doesn't exist.
|
|
92590
|
+
`);
|
|
92510
92591
|
process.exit(1);
|
|
92511
92592
|
}
|
|
92512
92593
|
const config = loadConfig(configPath, {
|
|
92513
92594
|
configSchemaExt: profile?.configSchemaExt,
|
|
92514
92595
|
profileKey: profile?.appName
|
|
92515
92596
|
});
|
|
92516
|
-
const explicitService = opts.service ?? config.docker?.services?.[0]?.name;
|
|
92597
|
+
const explicitService = opts.service ?? config.mount.service ?? config.docker?.services?.[0]?.name;
|
|
92517
92598
|
if (!explicitService) {
|
|
92518
92599
|
process.stderr.write(
|
|
92519
|
-
"dev-cockpit mount: no target service. Pass --service <name
|
|
92600
|
+
"dev-cockpit mount: no target service. Pass --service <name>, set mount.service in cockpit.yaml, or set docker.services in cockpit.yaml.\n"
|
|
92520
92601
|
);
|
|
92521
92602
|
process.exit(1);
|
|
92522
92603
|
}
|
|
@@ -92544,18 +92625,11 @@ var stdoutSink = (line2) => process.stdout.write(`${line2}
|
|
|
92544
92625
|
`);
|
|
92545
92626
|
var stderrSink = (line2) => process.stderr.write(`${line2}
|
|
92546
92627
|
`);
|
|
92547
|
-
function applyExclude(mounts, exclude) {
|
|
92548
|
-
if (exclude.length === 0) return [...mounts];
|
|
92549
|
-
const set = new Set(exclude);
|
|
92550
|
-
return mounts.filter((m) => {
|
|
92551
|
-
const name = m.meta?.["name"] ?? "";
|
|
92552
|
-
return !set.has(name);
|
|
92553
|
-
});
|
|
92554
|
-
}
|
|
92555
92628
|
async function pickMounts(candidates) {
|
|
92556
92629
|
const { checkbox } = await import("@inquirer/prompts");
|
|
92557
92630
|
const choices = candidates.map((m) => {
|
|
92558
|
-
const
|
|
92631
|
+
const fallbackName = m.containerPath ?? (m.kind === "symlink-only" ? `(symlink) ${m.hostPath}` : m.hostPath);
|
|
92632
|
+
const name = m.meta?.["name"] ?? fallbackName;
|
|
92559
92633
|
const type = m.meta?.["type"];
|
|
92560
92634
|
const label = type ? `${name} (${type}) ${m.hostPath}` : `${name} ${m.hostPath}`;
|
|
92561
92635
|
return { name: label, value: m, checked: true };
|
|
@@ -92567,8 +92641,17 @@ async function pickMounts(candidates) {
|
|
|
92567
92641
|
}
|
|
92568
92642
|
async function mountCommand(opts = {}) {
|
|
92569
92643
|
const ctx = await resolveContext(opts);
|
|
92570
|
-
const {
|
|
92571
|
-
|
|
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);
|
|
92572
92655
|
if (merged.length === 0) {
|
|
92573
92656
|
process.stdout.write(
|
|
92574
92657
|
"dev-cockpit mount: no mount candidates from config.mounts[] or profile.mountCandidatesProvider.\n"
|
|
@@ -92615,7 +92698,8 @@ async function mountCommand(opts = {}) {
|
|
|
92615
92698
|
`
|
|
92616
92699
|
);
|
|
92617
92700
|
}
|
|
92618
|
-
for (const p of report.skipped)
|
|
92701
|
+
for (const p of report.skipped)
|
|
92702
|
+
process.stdout.write(`dev-cockpit mount: skipped (could not replace) \u2192 ${p}
|
|
92619
92703
|
`);
|
|
92620
92704
|
}
|
|
92621
92705
|
if (profile?.onMountApply) {
|
|
@@ -92674,7 +92758,7 @@ dev-cockpit mount status \u2014 service: ${manifest.service}
|
|
|
92674
92758
|
const headers = ["NAME", "BRANCH", "DIRTY", ...Array.from(extraKeys)];
|
|
92675
92759
|
const widths = headers.map((h2) => h2.length);
|
|
92676
92760
|
const dataRows = rows.map((r) => {
|
|
92677
|
-
const name = r.mount.meta?.["name"] ?? r.mount.containerPath;
|
|
92761
|
+
const name = r.mount.meta?.["name"] ?? r.mount.containerPath ?? r.mount.hostPath;
|
|
92678
92762
|
const branch = (r.info.branch ?? "?").slice(0, 24);
|
|
92679
92763
|
const dirty = r.info.dirty === void 0 ? "?" : r.info.dirty ? "yes" : "no";
|
|
92680
92764
|
const extras = Array.from(extraKeys).map((k) => r.info.extra?.[k] ?? "");
|
|
@@ -92757,8 +92841,10 @@ async function migrateConfigCommand(opts = {}) {
|
|
|
92757
92841
|
}
|
|
92758
92842
|
const fromVersion = raw["version"];
|
|
92759
92843
|
if (fromVersion === CONFIG_VERSION) {
|
|
92760
|
-
process.stdout.write(
|
|
92761
|
-
`
|
|
92844
|
+
process.stdout.write(
|
|
92845
|
+
`dev-cockpit migrate-config: already at v${CONFIG_VERSION}; nothing to do.
|
|
92846
|
+
`
|
|
92847
|
+
);
|
|
92762
92848
|
return;
|
|
92763
92849
|
}
|
|
92764
92850
|
if (fromVersion > CONFIG_VERSION) {
|
|
@@ -92810,24 +92896,32 @@ function buildCli(opts = {}) {
|
|
|
92810
92896
|
const program2 = new Command();
|
|
92811
92897
|
const profile = opts.profile;
|
|
92812
92898
|
const appName = profile?.appName ?? "dev-cockpit";
|
|
92813
|
-
program2.name(appName).description(
|
|
92814
|
-
profile ? `${appName} \u2014 built on dev-cockpit` : "Generic terminal UI dev cockpit"
|
|
92815
|
-
).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");
|
|
92816
92900
|
if (profile?.setupCli) {
|
|
92817
92901
|
profile.setupCli(program2);
|
|
92818
92902
|
}
|
|
92819
92903
|
if (!hasCommand(program2, "dev")) {
|
|
92820
|
-
program2.command("dev").description("Boot the three-pane TUI (Repos / Output / Health / Help)").option(
|
|
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) => {
|
|
92821
92908
|
await devCommand({ config: cmdOpts.config, profile });
|
|
92822
92909
|
});
|
|
92823
92910
|
}
|
|
92824
92911
|
if (!hasCommand(program2, "doctor")) {
|
|
92825
|
-
program2.command("doctor").description("Run all health checks once and print a status table").option(
|
|
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) => {
|
|
92826
92916
|
await doctorCommand({ config: cmdOpts.config, profile });
|
|
92827
92917
|
});
|
|
92828
92918
|
}
|
|
92829
92919
|
if (!hasCommand(program2, "init-config")) {
|
|
92830
|
-
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(
|
|
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(
|
|
92831
92925
|
async (cmdOpts) => {
|
|
92832
92926
|
await initConfigCommand({
|
|
92833
92927
|
force: cmdOpts.force ?? false,
|
|
@@ -92842,42 +92936,52 @@ function buildCli(opts = {}) {
|
|
|
92842
92936
|
}
|
|
92843
92937
|
if (!hasCommand(program2, "link")) {
|
|
92844
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) => {
|
|
92845
|
-
const { linkAddCommand } = await import("./link-
|
|
92939
|
+
const { linkAddCommand } = await import("./link-Y7OFHOUP.js");
|
|
92846
92940
|
linkAddCommand({ configPath });
|
|
92847
92941
|
});
|
|
92848
92942
|
linkCmd.command("list").description("Print all registered project \u2192 config mappings").action(async () => {
|
|
92849
|
-
const { linkListCommand } = await import("./link-
|
|
92943
|
+
const { linkListCommand } = await import("./link-Y7OFHOUP.js");
|
|
92850
92944
|
linkListCommand();
|
|
92851
92945
|
});
|
|
92852
92946
|
linkCmd.command("remove").description("Unregister the current directory from the manifest").action(async () => {
|
|
92853
|
-
const { linkRemoveCommand } = await import("./link-
|
|
92947
|
+
const { linkRemoveCommand } = await import("./link-Y7OFHOUP.js");
|
|
92854
92948
|
linkRemoveCommand();
|
|
92855
92949
|
});
|
|
92856
92950
|
}
|
|
92857
92951
|
if (!hasCommand(program2, "mount")) {
|
|
92858
|
-
const mountCmd = program2.command("mount").description(
|
|
92859
|
-
|
|
92860
|
-
|
|
92861
|
-
|
|
92862
|
-
|
|
92863
|
-
|
|
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) => {
|
|
92864
92960
|
await mountCommand({
|
|
92865
92961
|
config: cmdOpts.config,
|
|
92866
92962
|
service: cmdOpts.service,
|
|
92867
92963
|
quiet: cmdOpts.quiet ?? false,
|
|
92868
|
-
exclude: cmdOpts.exclude ?? [],
|
|
92869
92964
|
profile
|
|
92870
92965
|
});
|
|
92871
92966
|
});
|
|
92872
|
-
mountCmd.command("status").description("Show active mounts with branch, dirty, and broken-symlink status").option(
|
|
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) => {
|
|
92873
92971
|
await mountStatusCommand({ config: cmdOpts.config, profile });
|
|
92874
92972
|
});
|
|
92875
|
-
mountCmd.command("clear").description("Remove the overlay, manifest, and managed symlinks; runs profile.onMountClear").option(
|
|
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) => {
|
|
92876
92977
|
await mountClearCommand({ config: cmdOpts.config, profile });
|
|
92877
92978
|
});
|
|
92878
92979
|
}
|
|
92879
92980
|
if (!hasCommand(program2, "migrate-config")) {
|
|
92880
|
-
program2.command("migrate-config").description("Rewrite cockpit.yaml at the current CONFIG_VERSION").option(
|
|
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) => {
|
|
92881
92985
|
await migrateConfigCommand({ config: cmdOpts.config, dryRun: cmdOpts.dryRun });
|
|
92882
92986
|
});
|
|
92883
92987
|
}
|