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.
- 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 +6 -0
- 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/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 +206 -143
- package/dist/index.js.map +2 -2
- 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.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 +8 -7
- package/docs/notifications.md +3 -3
- package/docs/panes.md +5 -5
- package/docs/processes.md +7 -5
- package/examples/cockpit.schema.json +217 -57
- package/examples/cockpit.yaml +8 -10
- 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,
|
|
@@ -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: "
|
|
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)(
|
|
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
|
-
|
|
87689
|
-
{
|
|
87690
|
-
|
|
87691
|
-
|
|
87692
|
-
|
|
87693
|
-
|
|
87694
|
-
|
|
87695
|
-
|
|
87696
|
-
|
|
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
|
-
|
|
87738
|
-
{
|
|
87739
|
-
|
|
87740
|
-
|
|
87741
|
-
|
|
87742
|
-
|
|
87743
|
-
|
|
87744
|
-
|
|
87745
|
-
|
|
87746
|
-
|
|
87747
|
-
|
|
87748
|
-
|
|
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({
|
|
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 [
|
|
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({
|
|
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(
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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({
|
|
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 = {
|
|
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(
|
|
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 = [
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 {
|
|
92612
|
-
|
|
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)
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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-
|
|
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-
|
|
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-
|
|
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(
|
|
92900
|
-
|
|
92901
|
-
|
|
92902
|
-
|
|
92903
|
-
|
|
92904
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
}
|