dev-cockpit 0.3.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cockpit/panes/Health.d.ts.map +1 -1
- package/dist/cockpit/state/store.d.ts +7 -0
- package/dist/cockpit/state/store.d.ts.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/init-config-wizard.d.ts.map +1 -1
- package/dist/core/config.d.ts +51 -57
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/migrations.d.ts.map +1 -1
- package/dist/health/remediations.d.ts +15 -1
- package/dist/health/remediations.d.ts.map +1 -1
- package/dist/health/useHealth.d.ts +7 -0
- package/dist/health/useHealth.d.ts.map +1 -1
- package/dist/index.js +146 -57
- package/dist/index.js.map +3 -3
- package/examples/cockpit.schema.json +21 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15378,18 +15378,18 @@ var require_react_jsx_runtime_development = __commonJS({
|
|
|
15378
15378
|
function isValidElement(object) {
|
|
15379
15379
|
return "object" === typeof object && null !== object && object.$$typeof === REACT_ELEMENT_TYPE;
|
|
15380
15380
|
}
|
|
15381
|
-
var
|
|
15381
|
+
var React8 = require_react(), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = React8.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
|
|
15382
15382
|
return null;
|
|
15383
15383
|
};
|
|
15384
|
-
|
|
15384
|
+
React8 = {
|
|
15385
15385
|
react_stack_bottom_frame: function(callStackForError) {
|
|
15386
15386
|
return callStackForError();
|
|
15387
15387
|
}
|
|
15388
15388
|
};
|
|
15389
15389
|
var specialPropKeyWarningShown;
|
|
15390
15390
|
var didWarnAboutElementRef = {};
|
|
15391
|
-
var unknownOwnerDebugStack =
|
|
15392
|
-
|
|
15391
|
+
var unknownOwnerDebugStack = React8.react_stack_bottom_frame.bind(
|
|
15392
|
+
React8,
|
|
15393
15393
|
UnknownOwner
|
|
15394
15394
|
)();
|
|
15395
15395
|
var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
|
|
@@ -83869,8 +83869,40 @@ var v1ToV2 = (raw) => {
|
|
|
83869
83869
|
if (watchers === void 0) return { ...rest, version: 2 };
|
|
83870
83870
|
return { ...rest, processes: watchers, version: 2 };
|
|
83871
83871
|
};
|
|
83872
|
+
var v2ToV3 = (raw) => {
|
|
83873
|
+
const existing = raw["keybindings"] ?? {};
|
|
83874
|
+
const merged = {};
|
|
83875
|
+
for (const [k, v] of Object.entries(existing)) {
|
|
83876
|
+
const ids = Array.isArray(v) ? v : [v];
|
|
83877
|
+
merged[k] = ids.filter((s) => typeof s === "string" && s.length > 0);
|
|
83878
|
+
}
|
|
83879
|
+
const health = Array.isArray(raw["health"]) ? raw["health"] : [];
|
|
83880
|
+
const migratedHealth = health.map((entry) => {
|
|
83881
|
+
if (!entry || typeof entry !== "object") return entry;
|
|
83882
|
+
const e = entry;
|
|
83883
|
+
const rem = e["remediation"];
|
|
83884
|
+
const id = e["id"];
|
|
83885
|
+
if (!rem || typeof rem.key !== "string" || !id) return entry;
|
|
83886
|
+
const key = rem.key;
|
|
83887
|
+
const bucket = merged[key] ?? [];
|
|
83888
|
+
if (!bucket.includes(id)) bucket.push(id);
|
|
83889
|
+
merged[key] = bucket;
|
|
83890
|
+
const remRest = {};
|
|
83891
|
+
for (const [k, v] of Object.entries(rem)) {
|
|
83892
|
+
if (k !== "key") remRest[k] = v;
|
|
83893
|
+
}
|
|
83894
|
+
return { ...e, remediation: remRest };
|
|
83895
|
+
});
|
|
83896
|
+
const result = { ...raw, version: 3 };
|
|
83897
|
+
result["health"] = migratedHealth;
|
|
83898
|
+
if (Object.keys(merged).length > 0) {
|
|
83899
|
+
result["keybindings"] = merged;
|
|
83900
|
+
}
|
|
83901
|
+
return result;
|
|
83902
|
+
};
|
|
83872
83903
|
var MIGRATORS = {
|
|
83873
|
-
1: v1ToV2
|
|
83904
|
+
1: v1ToV2,
|
|
83905
|
+
2: v2ToV3
|
|
83874
83906
|
};
|
|
83875
83907
|
var MigrationError = class extends Error {
|
|
83876
83908
|
constructor(fromVersion, toVersion, reason) {
|
|
@@ -83900,7 +83932,7 @@ function runMigrations(raw, fromVersion, toVersion) {
|
|
|
83900
83932
|
}
|
|
83901
83933
|
|
|
83902
83934
|
// src/core/config.ts
|
|
83903
|
-
var CONFIG_VERSION =
|
|
83935
|
+
var CONFIG_VERSION = 3;
|
|
83904
83936
|
var NotifyOverrideSchema = external_exports.union([
|
|
83905
83937
|
external_exports.literal(false),
|
|
83906
83938
|
external_exports.object({
|
|
@@ -83935,15 +83967,6 @@ var HighlightSchema = external_exports.object({
|
|
|
83935
83967
|
severity: external_exports.enum(["info", "warn", "error"]).optional().default("info")
|
|
83936
83968
|
});
|
|
83937
83969
|
var RemediationSchema = external_exports.object({
|
|
83938
|
-
/**
|
|
83939
|
-
* Optional keypress binding on the Health pane. When omitted, the
|
|
83940
|
-
* remediation is documentation-only — the row shows the label but pressing
|
|
83941
|
-
* any key does nothing for this entry. Useful when several health entries
|
|
83942
|
-
* share the same shell command and you only want ONE row to be the
|
|
83943
|
-
* trigger — see `docker compose up -d` covering all four container-running
|
|
83944
|
-
* checks in the awc wrapper config.
|
|
83945
|
-
*/
|
|
83946
|
-
key: external_exports.string().optional(),
|
|
83947
83970
|
label: external_exports.string(),
|
|
83948
83971
|
command: external_exports.string(),
|
|
83949
83972
|
cwd: external_exports.string().optional()
|
|
@@ -84007,6 +84030,7 @@ var ComposerSettingsSchema = external_exports.object({
|
|
|
84007
84030
|
*/
|
|
84008
84031
|
packageDirs: external_exports.array(external_exports.string()).optional().default(["."])
|
|
84009
84032
|
});
|
|
84033
|
+
var KeybindingsSchema = external_exports.record(external_exports.union([external_exports.string(), external_exports.array(external_exports.string())]));
|
|
84010
84034
|
var MountSettingsSchema = external_exports.object({
|
|
84011
84035
|
/**
|
|
84012
84036
|
* Override path for the generated docker-compose overlay. When unset
|
|
@@ -84040,6 +84064,7 @@ var BaseCockpitConfigSchema = external_exports.object({
|
|
|
84040
84064
|
manifestFile: "mount.manifest.json"
|
|
84041
84065
|
}),
|
|
84042
84066
|
composer: ComposerSettingsSchema.optional().default({ packageDirs: ["."] }),
|
|
84067
|
+
keybindings: KeybindingsSchema.optional().default({}),
|
|
84043
84068
|
/** Which pane the cockpit lands on when it boots. Profile may override. */
|
|
84044
84069
|
defaultPane: external_exports.enum(["repos", "output", "health", "help"]).optional().default("repos"),
|
|
84045
84070
|
/** Named keystroke-bound shell commands surfaced via the `:` palette. */
|
|
@@ -84051,6 +84076,16 @@ var BaseCockpitConfigSchema = external_exports.object({
|
|
|
84051
84076
|
*/
|
|
84052
84077
|
profile: external_exports.record(external_exports.unknown()).optional().default({})
|
|
84053
84078
|
});
|
|
84079
|
+
function normaliseKeybindings(raw) {
|
|
84080
|
+
const out = {};
|
|
84081
|
+
if (!raw) return out;
|
|
84082
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
84083
|
+
const ids = Array.isArray(value) ? value : [value];
|
|
84084
|
+
const clean = ids.filter((s) => typeof s === "string" && s.length > 0);
|
|
84085
|
+
if (clean.length > 0) out[key] = clean;
|
|
84086
|
+
}
|
|
84087
|
+
return out;
|
|
84088
|
+
}
|
|
84054
84089
|
var ConfigVersionError = class extends Error {
|
|
84055
84090
|
constructor(filePath, found, supported) {
|
|
84056
84091
|
super(
|
|
@@ -84166,7 +84201,7 @@ var {
|
|
|
84166
84201
|
} = import_index.default;
|
|
84167
84202
|
|
|
84168
84203
|
// src/cockpit/Cockpit.tsx
|
|
84169
|
-
var
|
|
84204
|
+
var import_react9 = __toESM(require_react(), 1);
|
|
84170
84205
|
|
|
84171
84206
|
// src/cockpit/hooks/useCockpitStore.ts
|
|
84172
84207
|
var import_react = __toESM(require_react(), 1);
|
|
@@ -84213,6 +84248,7 @@ var cockpitStore = createStore()((set, get2) => ({
|
|
|
84213
84248
|
output: [],
|
|
84214
84249
|
outputFilter: {},
|
|
84215
84250
|
knownSources: [],
|
|
84251
|
+
keybindings: {},
|
|
84216
84252
|
activeModal: null,
|
|
84217
84253
|
actions: [],
|
|
84218
84254
|
commandFilter: "",
|
|
@@ -84306,6 +84342,7 @@ var cockpitStore = createStore()((set, get2) => ({
|
|
|
84306
84342
|
setActiveRemediation: (remediation) => set({ activeRemediation: remediation }),
|
|
84307
84343
|
setHelpConfig: (config) => set({ helpConfig: config }),
|
|
84308
84344
|
setFocus: (focus) => set({ focus }),
|
|
84345
|
+
setKeybindings: (bindings) => set({ keybindings: bindings }),
|
|
84309
84346
|
setActions: (actions) => set({ actions }),
|
|
84310
84347
|
setCommandFilter: (filter) => set((state) => {
|
|
84311
84348
|
const filtered = filterActions(state.actions, filter);
|
|
@@ -84678,7 +84715,17 @@ function RecentErrorRow({ err }) {
|
|
|
84678
84715
|
}
|
|
84679
84716
|
|
|
84680
84717
|
// src/cockpit/panes/Health.tsx
|
|
84718
|
+
var import_react4 = __toESM(require_react(), 1);
|
|
84681
84719
|
var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
|
|
84720
|
+
function buildReverseKeybindings(bindings) {
|
|
84721
|
+
const out = {};
|
|
84722
|
+
for (const [key, ids] of Object.entries(bindings)) {
|
|
84723
|
+
for (const id of ids) {
|
|
84724
|
+
if (!(id in out)) out[id] = key;
|
|
84725
|
+
}
|
|
84726
|
+
}
|
|
84727
|
+
return out;
|
|
84728
|
+
}
|
|
84682
84729
|
var SEVERITY_GLYPH = { ok: "\u2713", warn: "\u26A0", error: "\u2717" };
|
|
84683
84730
|
var SEVERITY_COLOR = {
|
|
84684
84731
|
ok: "green",
|
|
@@ -84692,6 +84739,8 @@ function Health() {
|
|
|
84692
84739
|
const focus = useCockpitStore((s) => s.focus);
|
|
84693
84740
|
const notificationsEnabledSession = useCockpitStore((s) => s.notificationsEnabledSession);
|
|
84694
84741
|
const activeRemediation = useCockpitStore((s) => s.activeRemediation);
|
|
84742
|
+
const keybindings = useCockpitStore((s) => s.keybindings);
|
|
84743
|
+
const idToKey = (0, import_react4.useMemo)(() => buildReverseKeybindings(keybindings), [keybindings]);
|
|
84695
84744
|
const isFocused = focus === "health";
|
|
84696
84745
|
if (health.length === 0) {
|
|
84697
84746
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { flexDirection: "column", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { dimColor: true, children: "running health checks\u2026" }) });
|
|
@@ -84708,7 +84757,8 @@ function Health() {
|
|
|
84708
84757
|
const isRunning = activeRemediation?.healthId === item.id;
|
|
84709
84758
|
const glyph = isRunning ? "\u2026" : SEVERITY_GLYPH[item.severity] ?? "?";
|
|
84710
84759
|
const color = isRunning ? "yellow" : SEVERITY_COLOR[item.severity] ?? "white";
|
|
84711
|
-
const
|
|
84760
|
+
const displayKey = idToKey[item.id] ?? item.remediationKey ?? null;
|
|
84761
|
+
const remKey = displayKey ? ` [${displayKey}]` : "";
|
|
84712
84762
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { flexDirection: "column", children: [
|
|
84713
84763
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { children: [
|
|
84714
84764
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: isSelected ? "cyan" : void 0, children: isSelected ? "\u25B6 " : " " }),
|
|
@@ -84731,7 +84781,7 @@ function Health() {
|
|
|
84731
84781
|
}
|
|
84732
84782
|
|
|
84733
84783
|
// src/cockpit/panes/Help.tsx
|
|
84734
|
-
var
|
|
84784
|
+
var import_react5 = __toESM(require_react(), 1);
|
|
84735
84785
|
|
|
84736
84786
|
// src/cockpit/help/loader.ts
|
|
84737
84787
|
import fs5 from "node:fs";
|
|
@@ -87542,7 +87592,7 @@ function Help2() {
|
|
|
87542
87592
|
const helpConfig = useCockpitStore((s) => s.helpConfig);
|
|
87543
87593
|
const { stdout } = use_stdout_default();
|
|
87544
87594
|
const isActive = focus === "help";
|
|
87545
|
-
const initial = (0,
|
|
87595
|
+
const initial = (0, import_react5.useMemo)(() => {
|
|
87546
87596
|
const result = loadHelpPages({
|
|
87547
87597
|
sources: helpConfig.sources,
|
|
87548
87598
|
defaultPage: helpConfig.defaultPage
|
|
@@ -87551,17 +87601,17 @@ function Help2() {
|
|
|
87551
87601
|
return { pages: [FALLBACK_PAGE], defaultIndex: 0 };
|
|
87552
87602
|
}, [helpConfig.sources, helpConfig.defaultPage]);
|
|
87553
87603
|
const pages = initial.pages;
|
|
87554
|
-
const [pageIndex, setPageIndex] = (0,
|
|
87555
|
-
const [scrollOffset, setScrollOffset] = (0,
|
|
87556
|
-
const lastPageIndexRef = (0,
|
|
87557
|
-
(0,
|
|
87604
|
+
const [pageIndex, setPageIndex] = (0, import_react5.useState)(initial.defaultIndex);
|
|
87605
|
+
const [scrollOffset, setScrollOffset] = (0, import_react5.useState)(0);
|
|
87606
|
+
const lastPageIndexRef = (0, import_react5.useRef)(pageIndex);
|
|
87607
|
+
(0, import_react5.useEffect)(() => {
|
|
87558
87608
|
if (lastPageIndexRef.current !== pageIndex) {
|
|
87559
87609
|
lastPageIndexRef.current = pageIndex;
|
|
87560
87610
|
setScrollOffset(0);
|
|
87561
87611
|
}
|
|
87562
87612
|
}, [pageIndex]);
|
|
87563
87613
|
const activePage = pages[pageIndex] ?? pages[0];
|
|
87564
|
-
const renderedLines = (0,
|
|
87614
|
+
const renderedLines = (0, import_react5.useMemo)(
|
|
87565
87615
|
() => renderMarkdown(activePage.body).split("\n"),
|
|
87566
87616
|
[activePage.body]
|
|
87567
87617
|
);
|
|
@@ -87689,20 +87739,20 @@ function Footer({ legends } = {}) {
|
|
|
87689
87739
|
}
|
|
87690
87740
|
|
|
87691
87741
|
// src/cockpit/panes/FilterModal.tsx
|
|
87692
|
-
var
|
|
87742
|
+
var import_react6 = __toESM(require_react(), 1);
|
|
87693
87743
|
var import_jsx_runtime7 = __toESM(require_jsx_runtime(), 1);
|
|
87694
87744
|
var SEVERITIES = [void 0, "info", "warn", "error"];
|
|
87695
87745
|
function FilterModal() {
|
|
87696
87746
|
const outputFilter = useCockpitStore((s) => s.outputFilter);
|
|
87697
87747
|
const knownSources = useCockpitStore((s) => s.knownSources);
|
|
87698
|
-
const [severityDraft, setSeverityDraft] = (0,
|
|
87748
|
+
const [severityDraft, setSeverityDraft] = (0, import_react6.useState)(
|
|
87699
87749
|
outputFilter.severity
|
|
87700
87750
|
);
|
|
87701
87751
|
const initialSelected = new Set(
|
|
87702
87752
|
outputFilter.sources && outputFilter.sources.length > 0 ? outputFilter.sources : knownSources
|
|
87703
87753
|
);
|
|
87704
|
-
const [selectedSources, setSelectedSources] = (0,
|
|
87705
|
-
const [cursor, setCursor] = (0,
|
|
87754
|
+
const [selectedSources, setSelectedSources] = (0, import_react6.useState)(initialSelected);
|
|
87755
|
+
const [cursor, setCursor] = (0, import_react6.useState)(0);
|
|
87706
87756
|
const sources = knownSources;
|
|
87707
87757
|
const hasSources = sources.length > 0;
|
|
87708
87758
|
use_input_default((input, key) => {
|
|
@@ -87787,11 +87837,11 @@ function FilterModal() {
|
|
|
87787
87837
|
}
|
|
87788
87838
|
|
|
87789
87839
|
// src/cockpit/panes/SearchModal.tsx
|
|
87790
|
-
var
|
|
87840
|
+
var import_react7 = __toESM(require_react(), 1);
|
|
87791
87841
|
var import_jsx_runtime8 = __toESM(require_jsx_runtime(), 1);
|
|
87792
87842
|
function SearchModal() {
|
|
87793
87843
|
const outputFilter = useCockpitStore((s) => s.outputFilter);
|
|
87794
|
-
const [query, setQuery] = (0,
|
|
87844
|
+
const [query, setQuery] = (0, import_react7.useState)(outputFilter.search ?? "");
|
|
87795
87845
|
use_input_default((input, key) => {
|
|
87796
87846
|
if (key.escape) {
|
|
87797
87847
|
cockpitStore.getState().setActiveModal(null);
|
|
@@ -88026,7 +88076,7 @@ function useGlobalKeys(opts) {
|
|
|
88026
88076
|
}
|
|
88027
88077
|
|
|
88028
88078
|
// src/health/useHealth.ts
|
|
88029
|
-
var
|
|
88079
|
+
var import_react8 = __toESM(require_react(), 1);
|
|
88030
88080
|
|
|
88031
88081
|
// src/health/scheduler.ts
|
|
88032
88082
|
import path9 from "node:path";
|
|
@@ -88159,10 +88209,21 @@ var HealthScheduler = class {
|
|
|
88159
88209
|
};
|
|
88160
88210
|
|
|
88161
88211
|
// src/health/remediations.ts
|
|
88162
|
-
|
|
88163
|
-
const
|
|
88164
|
-
if (
|
|
88165
|
-
|
|
88212
|
+
function findChecksByKey(key, checks, keybindings) {
|
|
88213
|
+
const ids = keybindings?.[key];
|
|
88214
|
+
if (ids && ids.length > 0) {
|
|
88215
|
+
return ids.map((id) => checks.find((c4) => c4.id === id)).filter((c4) => Boolean(c4));
|
|
88216
|
+
}
|
|
88217
|
+
const c3 = checks.find((c4) => c4.remediation.key === key);
|
|
88218
|
+
return c3 ? [c3] : [];
|
|
88219
|
+
}
|
|
88220
|
+
async function runRemediation(key, checks, ctx, workspaceRoot, keybindings) {
|
|
88221
|
+
const matched = findChecksByKey(key, checks, keybindings);
|
|
88222
|
+
await Promise.all(
|
|
88223
|
+
matched.map(
|
|
88224
|
+
(check) => dispatchRemediation(check.remediation, ctx, workspaceRoot, check.id)
|
|
88225
|
+
)
|
|
88226
|
+
);
|
|
88166
88227
|
}
|
|
88167
88228
|
function findRemediation(key, checks) {
|
|
88168
88229
|
return checks.find((c3) => c3.remediation.key === key);
|
|
@@ -88449,23 +88510,23 @@ function buildHealthContext(workspaceRoot, appendOutput) {
|
|
|
88449
88510
|
|
|
88450
88511
|
// src/health/useHealth.ts
|
|
88451
88512
|
function useHealth(opts) {
|
|
88452
|
-
const checks = (0,
|
|
88513
|
+
const checks = (0, import_react8.useMemo)(() => {
|
|
88453
88514
|
if (!opts) return [];
|
|
88454
88515
|
return buildHealthRegistry({
|
|
88455
88516
|
profileChecks: opts.profileChecks,
|
|
88456
88517
|
configEntries: opts.configEntries
|
|
88457
88518
|
});
|
|
88458
88519
|
}, [opts]);
|
|
88459
|
-
const checksRef = (0,
|
|
88460
|
-
const ctxRef = (0,
|
|
88461
|
-
const optsRef = (0,
|
|
88462
|
-
const schedulerRef = (0,
|
|
88463
|
-
(0,
|
|
88520
|
+
const checksRef = (0, import_react8.useRef)(checks);
|
|
88521
|
+
const ctxRef = (0, import_react8.useRef)(opts?.ctx);
|
|
88522
|
+
const optsRef = (0, import_react8.useRef)(opts);
|
|
88523
|
+
const schedulerRef = (0, import_react8.useRef)(null);
|
|
88524
|
+
(0, import_react8.useEffect)(() => {
|
|
88464
88525
|
checksRef.current = checks;
|
|
88465
88526
|
ctxRef.current = opts?.ctx;
|
|
88466
88527
|
optsRef.current = opts;
|
|
88467
88528
|
}, [checks, opts]);
|
|
88468
|
-
(0,
|
|
88529
|
+
(0, import_react8.useEffect)(() => {
|
|
88469
88530
|
if (!opts) return;
|
|
88470
88531
|
if (checks.length === 0) return;
|
|
88471
88532
|
const scheduler3 = new HealthScheduler({
|
|
@@ -88504,21 +88565,25 @@ function useHealth(opts) {
|
|
|
88504
88565
|
runRemediation: (key) => {
|
|
88505
88566
|
const list3 = checksRef.current;
|
|
88506
88567
|
const ctx = ctxRef.current ?? buildDefaultCtx(optsRef.current?.workspaceRoot ?? ".");
|
|
88507
|
-
const
|
|
88508
|
-
|
|
88568
|
+
const keybindings = optsRef.current?.keybindings;
|
|
88569
|
+
const matched = findChecksByKey(key, list3, keybindings);
|
|
88570
|
+
if (matched.length === 0) return null;
|
|
88571
|
+
const first = matched[0];
|
|
88572
|
+
const banner = matched.length === 1 ? first.remediation.label : `${matched.length} remediations`;
|
|
88509
88573
|
const promise = runRemediation(
|
|
88510
88574
|
key,
|
|
88511
88575
|
list3,
|
|
88512
88576
|
ctx,
|
|
88513
|
-
optsRef.current?.workspaceRoot ?? "."
|
|
88577
|
+
optsRef.current?.workspaceRoot ?? ".",
|
|
88578
|
+
keybindings
|
|
88514
88579
|
).finally(() => {
|
|
88515
88580
|
void schedulerRef.current?.runAll();
|
|
88516
88581
|
});
|
|
88517
88582
|
return {
|
|
88518
|
-
label:
|
|
88583
|
+
label: banner,
|
|
88519
88584
|
promise,
|
|
88520
|
-
healthId:
|
|
88521
|
-
healthLabel:
|
|
88585
|
+
healthId: first.id,
|
|
88586
|
+
healthLabel: first.label
|
|
88522
88587
|
};
|
|
88523
88588
|
}
|
|
88524
88589
|
};
|
|
@@ -88551,8 +88616,8 @@ function Cockpit(props) {
|
|
|
88551
88616
|
const { stdout } = use_stdout_default();
|
|
88552
88617
|
const focus = useCockpitStore((s) => s.focus);
|
|
88553
88618
|
const activeModal = useCockpitStore((s) => s.activeModal);
|
|
88554
|
-
const [rows, setRows] = (0,
|
|
88555
|
-
(0,
|
|
88619
|
+
const [rows, setRows] = (0, import_react9.useState)(stdout.rows ?? 24);
|
|
88620
|
+
(0, import_react9.useEffect)(() => {
|
|
88556
88621
|
const onResize = () => setRows(stdout.rows ?? 24);
|
|
88557
88622
|
stdout.on("resize", onResize);
|
|
88558
88623
|
return () => {
|
|
@@ -91386,7 +91451,7 @@ function hasLockfile(workspaceRoot) {
|
|
|
91386
91451
|
}
|
|
91387
91452
|
|
|
91388
91453
|
// src/runCockpit.ts
|
|
91389
|
-
var
|
|
91454
|
+
var import_react10 = __toESM(require_react(), 1);
|
|
91390
91455
|
var ENTER_ALT_SCREEN = "\x1B[?1049h\x1B[H";
|
|
91391
91456
|
var EXIT_ALT_SCREEN = "\x1B[?1049l";
|
|
91392
91457
|
function runCockpit(opts = {}) {
|
|
@@ -91425,7 +91490,7 @@ function runCockpit(opts = {}) {
|
|
|
91425
91490
|
throw err;
|
|
91426
91491
|
});
|
|
91427
91492
|
}
|
|
91428
|
-
const ink = render_default(
|
|
91493
|
+
const ink = render_default(import_react10.default.createElement(Cockpit, cockpitProps), { exitOnCtrlC: true });
|
|
91429
91494
|
return {
|
|
91430
91495
|
waitUntilExit: async () => {
|
|
91431
91496
|
try {
|
|
@@ -91533,6 +91598,7 @@ async function devCommand(opts = {}) {
|
|
|
91533
91598
|
const requestedHidden = requestedPane === "repos" && reposEmpty || requestedPane === "health" && healthEmpty;
|
|
91534
91599
|
const initialFocus = requestedHidden ? "output" : requestedPane;
|
|
91535
91600
|
cockpitStore.getState().setFocus(initialFocus);
|
|
91601
|
+
cockpitStore.getState().setKeybindings(normaliseKeybindings(config.keybindings));
|
|
91536
91602
|
const builtinActions = buildBuiltinActions(config);
|
|
91537
91603
|
const actions = buildActionRegistry(
|
|
91538
91604
|
[...config.actions],
|
|
@@ -91664,7 +91730,8 @@ async function devCommand(opts = {}) {
|
|
|
91664
91730
|
exclude: config.notifications.exclude
|
|
91665
91731
|
},
|
|
91666
91732
|
appName: config.appName,
|
|
91667
|
-
subscribeFsEvents: bootResult.subscribeFsEvents
|
|
91733
|
+
subscribeFsEvents: bootResult.subscribeFsEvents,
|
|
91734
|
+
keybindings: normaliseKeybindings(config.keybindings)
|
|
91668
91735
|
}
|
|
91669
91736
|
});
|
|
91670
91737
|
for (const proc of config.processes) {
|
|
@@ -91802,6 +91869,29 @@ function quote(value) {
|
|
|
91802
91869
|
if (/^[A-Za-z0-9_./-]+$/.test(value)) return value;
|
|
91803
91870
|
return `'${value.replace(/'/g, "''")}'`;
|
|
91804
91871
|
}
|
|
91872
|
+
function renderKeybindings(checks) {
|
|
91873
|
+
const bindings = {};
|
|
91874
|
+
for (const c3 of checks) {
|
|
91875
|
+
const key = c3.remediation.key;
|
|
91876
|
+
if (!key) continue;
|
|
91877
|
+
if (!bindings[key]) bindings[key] = [];
|
|
91878
|
+
if (!bindings[key].includes(c3.id)) bindings[key].push(c3.id);
|
|
91879
|
+
}
|
|
91880
|
+
const entries = Object.entries(bindings);
|
|
91881
|
+
if (entries.length === 0) return [];
|
|
91882
|
+
const out = ["keybindings:"];
|
|
91883
|
+
for (const [key, ids] of entries) {
|
|
91884
|
+
if (ids.length === 1) {
|
|
91885
|
+
out.push(indent(`${quote(key)}: ${quote(ids[0])}`, 1));
|
|
91886
|
+
} else {
|
|
91887
|
+
out.push(indent(`${quote(key)}:`, 1));
|
|
91888
|
+
for (const id of ids) {
|
|
91889
|
+
out.push(indent(`- ${quote(id)}`, 2));
|
|
91890
|
+
}
|
|
91891
|
+
}
|
|
91892
|
+
}
|
|
91893
|
+
return out;
|
|
91894
|
+
}
|
|
91805
91895
|
function renderHealth(checks) {
|
|
91806
91896
|
if (checks.length === 0) return [];
|
|
91807
91897
|
const out = ["health:"];
|
|
@@ -91829,9 +91919,6 @@ function renderHealth(checks) {
|
|
|
91829
91919
|
break;
|
|
91830
91920
|
}
|
|
91831
91921
|
out.push(indent(` remediation:`, 1));
|
|
91832
|
-
if (c3.remediation.key) {
|
|
91833
|
-
out.push(indent(` key: ${quote(c3.remediation.key)}`, 1));
|
|
91834
|
-
}
|
|
91835
91922
|
out.push(indent(` label: ${quote(c3.remediation.label)}`, 1));
|
|
91836
91923
|
out.push(indent(` command: ${quote(c3.remediation.command)}`, 1));
|
|
91837
91924
|
}
|
|
@@ -91896,7 +91983,7 @@ function renderWizardYaml(result) {
|
|
|
91896
91983
|
blocks.push([
|
|
91897
91984
|
"# Generated by `dev-cockpit init-config --interactive`. Edit freely.",
|
|
91898
91985
|
"",
|
|
91899
|
-
"version:
|
|
91986
|
+
"version: 3",
|
|
91900
91987
|
`appName: ${quote(result.appName)}`
|
|
91901
91988
|
]);
|
|
91902
91989
|
const processes = renderProcesses(result.processes);
|
|
@@ -91909,6 +91996,8 @@ function renderWizardYaml(result) {
|
|
|
91909
91996
|
if (highlights.length > 0) blocks.push(highlights);
|
|
91910
91997
|
const health = renderHealth(result.health);
|
|
91911
91998
|
if (health.length > 0) blocks.push(health);
|
|
91999
|
+
const keybindings = renderKeybindings(result.health);
|
|
92000
|
+
if (keybindings.length > 0) blocks.push(keybindings);
|
|
91912
92001
|
const actions = renderActions(result.actions);
|
|
91913
92002
|
if (actions.length > 0) blocks.push(actions);
|
|
91914
92003
|
blocks.push(["notifications:", indent(`enabled: ${result.notifications.enabled}`, 1)]);
|