dev-cockpit 0.1.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/CHANGELOG.md +36 -0
- package/LICENSE +21 -0
- package/README.md +131 -0
- package/bin/dev-cockpit.mjs +20 -0
- package/dist/buildCli.d.ts +17 -0
- package/dist/buildCli.d.ts.map +1 -0
- package/dist/buildCli.js +107 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +2 -0
- package/dist/cockpit/Cockpit.d.ts +33 -0
- package/dist/cockpit/Cockpit.d.ts.map +1 -0
- package/dist/cockpit/Cockpit.js +73 -0
- package/dist/cockpit/Footer.d.ts +22 -0
- package/dist/cockpit/Footer.d.ts.map +1 -0
- package/dist/cockpit/Footer.js +33 -0
- package/dist/cockpit/TabBar.d.ts +3 -0
- package/dist/cockpit/TabBar.d.ts.map +1 -0
- package/dist/cockpit/TabBar.js +12 -0
- package/dist/cockpit/help/content.d.ts +12 -0
- package/dist/cockpit/help/content.d.ts.map +1 -0
- package/dist/cockpit/help/content.js +22 -0
- package/dist/cockpit/help/loader.d.ts +65 -0
- package/dist/cockpit/help/loader.d.ts.map +1 -0
- package/dist/cockpit/help/loader.js +118 -0
- package/dist/cockpit/help/renderer.d.ts +16 -0
- package/dist/cockpit/help/renderer.d.ts.map +1 -0
- package/dist/cockpit/help/renderer.js +35 -0
- package/dist/cockpit/help/types.d.ts +12 -0
- package/dist/cockpit/help/types.d.ts.map +1 -0
- package/dist/cockpit/help/types.js +1 -0
- package/dist/cockpit/hooks/useCockpitStore.d.ts +3 -0
- package/dist/cockpit/hooks/useCockpitStore.d.ts.map +1 -0
- package/dist/cockpit/hooks/useCockpitStore.js +5 -0
- package/dist/cockpit/hooks/useGlobalKeys.d.ts +56 -0
- package/dist/cockpit/hooks/useGlobalKeys.d.ts.map +1 -0
- package/dist/cockpit/hooks/useGlobalKeys.js +173 -0
- package/dist/cockpit/panes/FilterModal.d.ts +3 -0
- package/dist/cockpit/panes/FilterModal.d.ts.map +1 -0
- package/dist/cockpit/panes/FilterModal.js +22 -0
- package/dist/cockpit/panes/Health.d.ts +13 -0
- package/dist/cockpit/panes/Health.d.ts.map +1 -0
- package/dist/cockpit/panes/Health.js +30 -0
- package/dist/cockpit/panes/Help.d.ts +14 -0
- package/dist/cockpit/panes/Help.d.ts.map +1 -0
- package/dist/cockpit/panes/Help.js +81 -0
- package/dist/cockpit/panes/Output.d.ts +14 -0
- package/dist/cockpit/panes/Output.d.ts.map +1 -0
- package/dist/cockpit/panes/Output.js +108 -0
- package/dist/cockpit/panes/Repos.d.ts +3 -0
- package/dist/cockpit/panes/Repos.d.ts.map +1 -0
- package/dist/cockpit/panes/Repos.js +48 -0
- package/dist/cockpit/panes/SearchModal.d.ts +3 -0
- package/dist/cockpit/panes/SearchModal.d.ts.map +1 -0
- package/dist/cockpit/panes/SearchModal.js +31 -0
- package/dist/cockpit/state/store.d.ts +93 -0
- package/dist/cockpit/state/store.d.ts.map +1 -0
- package/dist/cockpit/state/store.js +111 -0
- package/dist/cockpit/tab-state.d.ts +4 -0
- package/dist/cockpit/tab-state.d.ts.map +1 -0
- package/dist/cockpit/tab-state.js +7 -0
- package/dist/commands/dev.d.ts +20 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +158 -0
- package/dist/commands/doctor.d.ts +20 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +66 -0
- package/dist/commands/init-config-wizard.d.ts +84 -0
- package/dist/commands/init-config-wizard.d.ts.map +1 -0
- package/dist/commands/init-config-wizard.js +818 -0
- package/dist/commands/init-config.d.ts +35 -0
- package/dist/commands/init-config.d.ts.map +1 -0
- package/dist/commands/init-config.js +131 -0
- package/dist/commands/mount.d.ts +48 -0
- package/dist/commands/mount.d.ts.map +1 -0
- package/dist/commands/mount.js +150 -0
- package/dist/core/config.d.ts +391 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +152 -0
- package/dist/core/logger.d.ts +6 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +38 -0
- package/dist/core/notifier.d.ts +23 -0
- package/dist/core/notifier.d.ts.map +1 -0
- package/dist/core/notifier.js +100 -0
- package/dist/core/paths.d.ts +15 -0
- package/dist/core/paths.d.ts.map +1 -0
- package/dist/core/paths.js +18 -0
- package/dist/core/subprocess.d.ts +20 -0
- package/dist/core/subprocess.d.ts.map +1 -0
- package/dist/core/subprocess.js +82 -0
- package/dist/core/types.d.ts +125 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +1 -0
- package/dist/docker/highlights.d.ts +48 -0
- package/dist/docker/highlights.d.ts.map +1 -0
- package/dist/docker/highlights.js +79 -0
- package/dist/docker/logs.d.ts +84 -0
- package/dist/docker/logs.d.ts.map +1 -0
- package/dist/docker/logs.js +172 -0
- package/dist/docker/restart.d.ts +26 -0
- package/dist/docker/restart.d.ts.map +1 -0
- package/dist/docker/restart.js +45 -0
- package/dist/docker/stack-trace.d.ts +25 -0
- package/dist/docker/stack-trace.d.ts.map +1 -0
- package/dist/docker/stack-trace.js +44 -0
- package/dist/health/builtin.d.ts +8 -0
- package/dist/health/builtin.d.ts.map +1 -0
- package/dist/health/builtin.js +144 -0
- package/dist/health/context.d.ts +3 -0
- package/dist/health/context.d.ts.map +1 -0
- package/dist/health/context.js +31 -0
- package/dist/health/notify-resolver.d.ts +18 -0
- package/dist/health/notify-resolver.d.ts.map +1 -0
- package/dist/health/notify-resolver.js +28 -0
- package/dist/health/registry.d.ts +20 -0
- package/dist/health/registry.d.ts.map +1 -0
- package/dist/health/registry.js +64 -0
- package/dist/health/remediations.d.ts +6 -0
- package/dist/health/remediations.d.ts.map +1 -0
- package/dist/health/remediations.js +41 -0
- package/dist/health/runner.d.ts +4 -0
- package/dist/health/runner.d.ts.map +1 -0
- package/dist/health/runner.js +22 -0
- package/dist/health/scheduler.d.ts +41 -0
- package/dist/health/scheduler.d.ts.map +1 -0
- package/dist/health/scheduler.js +107 -0
- package/dist/health/types.d.ts +73 -0
- package/dist/health/types.d.ts.map +1 -0
- package/dist/health/types.js +1 -0
- package/dist/health/useHealth.d.ts +40 -0
- package/dist/health/useHealth.d.ts.map +1 -0
- package/dist/health/useHealth.js +122 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/ink.d.ts +3 -0
- package/dist/ink.d.ts.map +1 -0
- package/dist/ink.js +1 -0
- package/dist/lint/reactive.d.ts +38 -0
- package/dist/lint/reactive.d.ts.map +1 -0
- package/dist/lint/reactive.js +131 -0
- package/dist/react.d.ts +3 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +1 -0
- package/dist/runCockpit.d.ts +34 -0
- package/dist/runCockpit.d.ts.map +1 -0
- package/dist/runCockpit.js +75 -0
- package/dist/watchers/manager.d.ts +63 -0
- package/dist/watchers/manager.d.ts.map +1 -0
- package/dist/watchers/manager.js +239 -0
- package/dist/watchers/path-mapper.d.ts +23 -0
- package/dist/watchers/path-mapper.d.ts.map +1 -0
- package/dist/watchers/path-mapper.js +29 -0
- package/dist/watchers/types.d.ts +22 -0
- package/dist/watchers/types.d.ts.map +1 -0
- package/dist/watchers/types.js +9 -0
- package/docs/commands.md +71 -0
- package/docs/config-reference.md +20 -0
- package/docs/getting-started.md +39 -0
- package/docs/health.md +120 -0
- package/docs/index.md +13 -0
- package/docs/init-config.md +46 -0
- package/docs/mount.md +55 -0
- package/docs/notifications.md +39 -0
- package/docs/panes.md +45 -0
- package/docs/watchers.md +27 -0
- package/examples/cockpit.yaml +116 -0
- package/package.json +91 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remediations.d.ts","sourceRoot":"","sources":["../../src/health/remediations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE1E,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAEpC,wBAAsB,cAAc,CAClC,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,WAAW,EAAE,EACrB,GAAG,EAAE,aAAa,EAClB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,WAAW,EAAE,GACpB,WAAW,GAAG,SAAS,CAEzB;AAED,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,WAAW,EACxB,GAAG,EAAE,aAAa,EAClB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAiCf"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { spawnStream } from '../core/subprocess.js';
|
|
2
|
+
export async function runRemediation(key, checks, ctx, workspaceRoot) {
|
|
3
|
+
const check = checks.find((c) => c.remediation.key === key);
|
|
4
|
+
if (!check)
|
|
5
|
+
return;
|
|
6
|
+
await dispatchRemediation(check.remediation, ctx, workspaceRoot, check.id);
|
|
7
|
+
}
|
|
8
|
+
export function findRemediation(key, checks) {
|
|
9
|
+
return checks.find((c) => c.remediation.key === key);
|
|
10
|
+
}
|
|
11
|
+
export async function dispatchRemediation(remediation, ctx, workspaceRoot, sourceId) {
|
|
12
|
+
if ('run' in remediation) {
|
|
13
|
+
await remediation.run(ctx, workspaceRoot);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const cmdline = remediation.command.trim();
|
|
17
|
+
if (!cmdline)
|
|
18
|
+
return;
|
|
19
|
+
const parts = cmdline.split(/\s+/);
|
|
20
|
+
const program = parts[0];
|
|
21
|
+
if (!program)
|
|
22
|
+
return;
|
|
23
|
+
const args = parts.slice(1);
|
|
24
|
+
const cwd = remediation.cwd ?? workspaceRoot;
|
|
25
|
+
const handle = spawnStream(program, args, {
|
|
26
|
+
cwd,
|
|
27
|
+
onStdout: (line) => ctx.appendOutput?.({
|
|
28
|
+
ts: Date.now(),
|
|
29
|
+
source: `health:${sourceId}`,
|
|
30
|
+
severity: 'info',
|
|
31
|
+
text: line,
|
|
32
|
+
}),
|
|
33
|
+
onStderr: (line) => ctx.appendOutput?.({
|
|
34
|
+
ts: Date.now(),
|
|
35
|
+
source: `health:${sourceId}`,
|
|
36
|
+
severity: 'warn',
|
|
37
|
+
text: line,
|
|
38
|
+
}),
|
|
39
|
+
});
|
|
40
|
+
await handle.exitCode;
|
|
41
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { HealthCheck, HealthContext, TriggerKind } from './types.js';
|
|
2
|
+
import type { HealthStatus } from '../core/types.js';
|
|
3
|
+
export declare function runChecks(checks: HealthCheck[], triggerSet: TriggerKind[], ctx: HealthContext): Promise<HealthStatus[]>;
|
|
4
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/health/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,wBAAsB,SAAS,CAC7B,MAAM,EAAE,WAAW,EAAE,EACrB,UAAU,EAAE,WAAW,EAAE,EACzB,GAAG,EAAE,aAAa,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC,CA4BzB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export async function runChecks(checks, triggerSet, ctx) {
|
|
2
|
+
const triggerSetAsSet = new Set(triggerSet);
|
|
3
|
+
const relevantChecks = checks.filter((check) => check.triggers.some((t) => triggerSetAsSet.has(t)));
|
|
4
|
+
if (relevantChecks.length === 0) {
|
|
5
|
+
return [];
|
|
6
|
+
}
|
|
7
|
+
const results = await Promise.all(relevantChecks.map(async (check) => {
|
|
8
|
+
try {
|
|
9
|
+
return await check.predicate(ctx);
|
|
10
|
+
}
|
|
11
|
+
catch (err) {
|
|
12
|
+
return {
|
|
13
|
+
id: check.id,
|
|
14
|
+
label: check.label,
|
|
15
|
+
severity: 'warn',
|
|
16
|
+
detail: `check failed with error: ${String(err)}`,
|
|
17
|
+
remediationKey: check.remediation.key,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}));
|
|
21
|
+
return results;
|
|
22
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { HealthCheck, HealthContext } from './types.js';
|
|
2
|
+
import type { HealthStatus } from '../core/types.js';
|
|
3
|
+
export interface SchedulerDeps {
|
|
4
|
+
onHealthUpdate: (statuses: HealthStatus[]) => void;
|
|
5
|
+
ctx: HealthContext;
|
|
6
|
+
checks: HealthCheck[];
|
|
7
|
+
/** Override the fs-event debounce interval (ms). Default: 500. */
|
|
8
|
+
fsEventDebounceMs?: number;
|
|
9
|
+
/** Lockfile filenames to recognise. Default: composer.lock, package-lock.json, yarn.lock. */
|
|
10
|
+
lockfileNames?: string[];
|
|
11
|
+
/**
|
|
12
|
+
* Poll interval (ms) for `docker`-triggered checks. Docker has no native
|
|
13
|
+
* push event from outside the container, and `docker compose down` mid-
|
|
14
|
+
* session would otherwise leave container-running / port-open checks
|
|
15
|
+
* stale. Default: 5000. Set to 0 to disable polling.
|
|
16
|
+
*/
|
|
17
|
+
dockerPollIntervalMs?: number;
|
|
18
|
+
}
|
|
19
|
+
export declare class HealthScheduler {
|
|
20
|
+
private readonly deps;
|
|
21
|
+
private readonly debounceMs;
|
|
22
|
+
private readonly lockfileNames;
|
|
23
|
+
private readonly dockerPollMs;
|
|
24
|
+
private fsDebounceTimer;
|
|
25
|
+
private dockerPollTimer;
|
|
26
|
+
private running;
|
|
27
|
+
constructor(deps: SchedulerDeps);
|
|
28
|
+
start(): Promise<void>;
|
|
29
|
+
onFsEvent(filePath: string): void;
|
|
30
|
+
onDockerEvent(): void;
|
|
31
|
+
/**
|
|
32
|
+
* Force every registered check to re-run, regardless of triggers. Used
|
|
33
|
+
* after a remediation completes so the user gets immediate visual
|
|
34
|
+
* confirmation without waiting for an external fsevent.
|
|
35
|
+
*/
|
|
36
|
+
runAll(): Promise<void>;
|
|
37
|
+
stop(): void;
|
|
38
|
+
private debounceRun;
|
|
39
|
+
private runTrigger;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/health/scheduler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAe,MAAM,YAAY,CAAC;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGrD,MAAM,WAAW,aAAa;IAC5B,cAAc,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;IACnD,GAAG,EAAE,aAAa,CAAC;IACnB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,kEAAkE;IAClE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,6FAA6F;IAC7F,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAMD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAc;IAC5C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,eAAe,CAA8C;IACrE,OAAO,CAAC,eAAe,CAA+C;IACtE,OAAO,CAAC,OAAO,CAAS;gBAEZ,IAAI,EAAE,aAAa;IAOzB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB5B,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAcjC,aAAa,IAAI,IAAI;IAKrB;;;;OAIG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB7B,IAAI,IAAI,IAAI;IAYZ,OAAO,CAAC,WAAW;YAUL,UAAU;CAOzB"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { runChecks } from './runner.js';
|
|
3
|
+
const DEFAULT_FSEVENT_DEBOUNCE_MS = 500;
|
|
4
|
+
const DEFAULT_LOCKFILE_NAMES = ['composer.lock', 'package-lock.json', 'yarn.lock'];
|
|
5
|
+
const DEFAULT_DOCKER_POLL_MS = 5000;
|
|
6
|
+
export class HealthScheduler {
|
|
7
|
+
deps;
|
|
8
|
+
debounceMs;
|
|
9
|
+
lockfileNames;
|
|
10
|
+
dockerPollMs;
|
|
11
|
+
fsDebounceTimer = null;
|
|
12
|
+
dockerPollTimer = null;
|
|
13
|
+
running = false;
|
|
14
|
+
constructor(deps) {
|
|
15
|
+
this.deps = deps;
|
|
16
|
+
this.debounceMs = deps.fsEventDebounceMs ?? DEFAULT_FSEVENT_DEBOUNCE_MS;
|
|
17
|
+
this.lockfileNames = new Set(deps.lockfileNames ?? DEFAULT_LOCKFILE_NAMES);
|
|
18
|
+
this.dockerPollMs = deps.dockerPollIntervalMs ?? DEFAULT_DOCKER_POLL_MS;
|
|
19
|
+
}
|
|
20
|
+
async start() {
|
|
21
|
+
if (this.running)
|
|
22
|
+
return;
|
|
23
|
+
this.running = true;
|
|
24
|
+
await this.runTrigger(['startup']);
|
|
25
|
+
// Start the docker poll only if some check actually subscribes to it.
|
|
26
|
+
// Otherwise we'd waste a setInterval on a no-op. Disable entirely with
|
|
27
|
+
// dockerPollIntervalMs: 0.
|
|
28
|
+
const hasDockerChecks = this.deps.checks.some((c) => c.triggers.includes('docker'));
|
|
29
|
+
if (hasDockerChecks && this.dockerPollMs > 0) {
|
|
30
|
+
this.dockerPollTimer = setInterval(() => {
|
|
31
|
+
if (!this.running)
|
|
32
|
+
return;
|
|
33
|
+
void this.runTrigger(['docker']);
|
|
34
|
+
}, this.dockerPollMs);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
onFsEvent(filePath) {
|
|
38
|
+
if (!this.running)
|
|
39
|
+
return;
|
|
40
|
+
const fileName = path.basename(filePath);
|
|
41
|
+
const isLockfile = this.lockfileNames.has(fileName);
|
|
42
|
+
const triggers = ['fsevent'];
|
|
43
|
+
if (isLockfile) {
|
|
44
|
+
triggers.push('lockfile');
|
|
45
|
+
}
|
|
46
|
+
this.debounceRun(triggers);
|
|
47
|
+
}
|
|
48
|
+
onDockerEvent() {
|
|
49
|
+
if (!this.running)
|
|
50
|
+
return;
|
|
51
|
+
this.debounceRun(['docker']);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Force every registered check to re-run, regardless of triggers. Used
|
|
55
|
+
* after a remediation completes so the user gets immediate visual
|
|
56
|
+
* confirmation without waiting for an external fsevent.
|
|
57
|
+
*/
|
|
58
|
+
async runAll() {
|
|
59
|
+
if (!this.running)
|
|
60
|
+
return;
|
|
61
|
+
const { checks, ctx, onHealthUpdate } = this.deps;
|
|
62
|
+
const results = await Promise.all(checks.map(async (check) => {
|
|
63
|
+
try {
|
|
64
|
+
return await check.predicate(ctx);
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
return {
|
|
68
|
+
id: check.id,
|
|
69
|
+
label: check.label,
|
|
70
|
+
severity: 'warn',
|
|
71
|
+
detail: `check failed with error: ${String(err)}`,
|
|
72
|
+
remediationKey: check.remediation.key,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}));
|
|
76
|
+
if (results.length > 0) {
|
|
77
|
+
onHealthUpdate(results);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
stop() {
|
|
81
|
+
this.running = false;
|
|
82
|
+
if (this.fsDebounceTimer) {
|
|
83
|
+
clearTimeout(this.fsDebounceTimer);
|
|
84
|
+
this.fsDebounceTimer = null;
|
|
85
|
+
}
|
|
86
|
+
if (this.dockerPollTimer) {
|
|
87
|
+
clearInterval(this.dockerPollTimer);
|
|
88
|
+
this.dockerPollTimer = null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
debounceRun(triggers) {
|
|
92
|
+
if (this.fsDebounceTimer) {
|
|
93
|
+
clearTimeout(this.fsDebounceTimer);
|
|
94
|
+
}
|
|
95
|
+
this.fsDebounceTimer = setTimeout(() => {
|
|
96
|
+
this.fsDebounceTimer = null;
|
|
97
|
+
void this.runTrigger(triggers);
|
|
98
|
+
}, this.debounceMs);
|
|
99
|
+
}
|
|
100
|
+
async runTrigger(triggers) {
|
|
101
|
+
const { checks, ctx, onHealthUpdate } = this.deps;
|
|
102
|
+
const results = await runChecks(checks, triggers, ctx);
|
|
103
|
+
if (results.length > 0) {
|
|
104
|
+
onHealthUpdate(results);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { Severity, HealthStatus, NotifiableEvent } from '../core/types.js';
|
|
2
|
+
export type TriggerKind = 'startup' | 'fsevent' | 'lockfile' | 'docker';
|
|
3
|
+
export interface FsHelpers {
|
|
4
|
+
existsSync: (p: string) => boolean;
|
|
5
|
+
statSync: (p: string) => {
|
|
6
|
+
mtimeMs: number;
|
|
7
|
+
};
|
|
8
|
+
readdirSync: (p: string, opts?: {
|
|
9
|
+
withFileTypes?: boolean;
|
|
10
|
+
}) => Array<{
|
|
11
|
+
name: string;
|
|
12
|
+
isDirectory(): boolean;
|
|
13
|
+
} | string>;
|
|
14
|
+
}
|
|
15
|
+
export type ExecHelper = (cmd: string, args: string[], cwd?: string) => Promise<{
|
|
16
|
+
stdout: string;
|
|
17
|
+
exitCode: number;
|
|
18
|
+
}>;
|
|
19
|
+
export interface HealthOutputLine {
|
|
20
|
+
ts: number;
|
|
21
|
+
source: string;
|
|
22
|
+
severity: 'info' | 'warn' | 'error';
|
|
23
|
+
text: string;
|
|
24
|
+
}
|
|
25
|
+
export interface HealthContext {
|
|
26
|
+
workspaceRoot: string;
|
|
27
|
+
fs: FsHelpers;
|
|
28
|
+
exec: ExecHelper;
|
|
29
|
+
appendOutput?: (line: HealthOutputLine) => void;
|
|
30
|
+
}
|
|
31
|
+
export type NotifyPolicy = false | {
|
|
32
|
+
onTransitionTo?: NotifiableEvent[];
|
|
33
|
+
};
|
|
34
|
+
export type Remediation = {
|
|
35
|
+
key: string;
|
|
36
|
+
label: string;
|
|
37
|
+
command: string;
|
|
38
|
+
cwd?: string;
|
|
39
|
+
} | {
|
|
40
|
+
key: string;
|
|
41
|
+
label: string;
|
|
42
|
+
run: (ctx: HealthContext, workspaceRoot: string) => Promise<void>;
|
|
43
|
+
};
|
|
44
|
+
export interface HealthCheck {
|
|
45
|
+
id: string;
|
|
46
|
+
label: string;
|
|
47
|
+
severity: Severity;
|
|
48
|
+
triggers: TriggerKind[];
|
|
49
|
+
predicate: (ctx: HealthContext) => Promise<HealthStatus>;
|
|
50
|
+
remediation: Remediation;
|
|
51
|
+
notify?: NotifyPolicy;
|
|
52
|
+
}
|
|
53
|
+
export interface HealthCheckConfig {
|
|
54
|
+
id: string;
|
|
55
|
+
label: string;
|
|
56
|
+
type: string;
|
|
57
|
+
severity?: Severity;
|
|
58
|
+
triggers?: TriggerKind[];
|
|
59
|
+
remediation: Remediation;
|
|
60
|
+
notify?: NotifyPolicy;
|
|
61
|
+
container?: string;
|
|
62
|
+
port?: number;
|
|
63
|
+
host?: string;
|
|
64
|
+
url?: string;
|
|
65
|
+
expectStatus?: number;
|
|
66
|
+
path?: string;
|
|
67
|
+
command?: string;
|
|
68
|
+
args?: string[];
|
|
69
|
+
cwd?: string;
|
|
70
|
+
}
|
|
71
|
+
export type BuiltinCheckType = 'container-running' | 'port-open' | 'http-ok' | 'file-exists' | 'exec-zero';
|
|
72
|
+
export type CheckPredicateFactory = (entry: HealthCheckConfig) => HealthCheck['predicate'];
|
|
73
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/health/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { RemediationDispatch } from '../cockpit/hooks/useGlobalKeys.js';
|
|
2
|
+
import { type NotificationsConfig } from '../core/notifier.js';
|
|
3
|
+
import type { HealthStatus } from '../core/types.js';
|
|
4
|
+
import type { HealthCheck, HealthCheckConfig, HealthContext } from './types.js';
|
|
5
|
+
/** Subset of WatcherManager surface that useHealth depends on. */
|
|
6
|
+
export interface FsEventSource {
|
|
7
|
+
/** Setter the cockpit can call when a watcher reports a file event. */
|
|
8
|
+
registerFsEventListener?: (listener: (path: string) => void) => () => void;
|
|
9
|
+
}
|
|
10
|
+
export interface UseHealthOptions {
|
|
11
|
+
/** Working directory injected into the HealthContext. */
|
|
12
|
+
workspaceRoot: string;
|
|
13
|
+
/** Pre-built checks contributed by the active profile. */
|
|
14
|
+
profileChecks?: HealthCheck[];
|
|
15
|
+
/** Config-driven entries (from cockpit.yaml `health[]`). */
|
|
16
|
+
configEntries?: HealthCheckConfig[];
|
|
17
|
+
/** Caller-built HealthContext. If omitted, a default is constructed lazily. */
|
|
18
|
+
ctx?: HealthContext;
|
|
19
|
+
/** Notification policy (global). */
|
|
20
|
+
notifications: NotificationsConfig;
|
|
21
|
+
/** Used in notification titles. Defaults to 'cockpit'. */
|
|
22
|
+
appName?: string;
|
|
23
|
+
/** Inject an alternate OS notifier (tests pass a no-op). */
|
|
24
|
+
notificationSender?: (title: string, message: string) => void;
|
|
25
|
+
/**
|
|
26
|
+
* fs-event source. Pass a function that subscribes a listener and returns an
|
|
27
|
+
* unsubscribe callback. Typically wired to WatcherManager.
|
|
28
|
+
*/
|
|
29
|
+
subscribeFsEvents?: (listener: (filePath: string) => void) => () => void;
|
|
30
|
+
/**
|
|
31
|
+
* Optional callback fired after every check run, before the store is updated.
|
|
32
|
+
* Useful for tests + advanced consumers who want to peek.
|
|
33
|
+
*/
|
|
34
|
+
onResults?: (statuses: HealthStatus[]) => void;
|
|
35
|
+
}
|
|
36
|
+
export interface UseHealthHandle {
|
|
37
|
+
runRemediation: (key: string) => RemediationDispatch | null;
|
|
38
|
+
}
|
|
39
|
+
export declare function useHealth(opts: UseHealthOptions | undefined): UseHealthHandle | null;
|
|
40
|
+
//# sourceMappingURL=useHealth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useHealth.d.ts","sourceRoot":"","sources":["../../src/health/useHealth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EAA6B,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAMrD,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhF,kEAAkE;AAClE,MAAM,WAAW,aAAa;IAC5B,uEAAuE;IACvE,uBAAuB,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;CAC5E;AAED,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,aAAa,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,WAAW,EAAE,CAAC;IAC9B,4DAA4D;IAC5D,aAAa,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACpC,+EAA+E;IAC/E,GAAG,CAAC,EAAE,aAAa,CAAC;IACpB,oCAAoC;IACpC,aAAa,EAAE,mBAAmB,CAAC;IACnC,0DAA0D;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9D;;;OAGG;IACH,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IACzE;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;CAChD;AAED,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,mBAAmB,GAAG,IAAI,CAAC;CAC7D;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,SAAS,GAAG,eAAe,GAAG,IAAI,CA4FpF"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { useEffect, useMemo, useRef } from 'react';
|
|
2
|
+
import { cockpitStore } from '../cockpit/state/store.js';
|
|
3
|
+
import { detectTransitions, notify } from '../core/notifier.js';
|
|
4
|
+
import { HealthScheduler } from './scheduler.js';
|
|
5
|
+
import { runRemediation as dispatchRemediationKey } from './remediations.js';
|
|
6
|
+
import { resolveNotify } from './notify-resolver.js';
|
|
7
|
+
import { buildHealthRegistry } from './registry.js';
|
|
8
|
+
import { buildHealthContext } from './context.js';
|
|
9
|
+
export function useHealth(opts) {
|
|
10
|
+
const checks = useMemo(() => {
|
|
11
|
+
if (!opts)
|
|
12
|
+
return [];
|
|
13
|
+
return buildHealthRegistry({
|
|
14
|
+
profileChecks: opts.profileChecks,
|
|
15
|
+
configEntries: opts.configEntries,
|
|
16
|
+
});
|
|
17
|
+
}, [opts]);
|
|
18
|
+
const checksRef = useRef(checks);
|
|
19
|
+
const ctxRef = useRef(opts?.ctx);
|
|
20
|
+
const optsRef = useRef(opts);
|
|
21
|
+
const schedulerRef = useRef(null);
|
|
22
|
+
// Keep refs current so the orchestration loop sees latest options without
|
|
23
|
+
// requiring full teardown on prop churn.
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
checksRef.current = checks;
|
|
26
|
+
ctxRef.current = opts?.ctx;
|
|
27
|
+
optsRef.current = opts;
|
|
28
|
+
}, [checks, opts]);
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (!opts)
|
|
31
|
+
return;
|
|
32
|
+
if (checks.length === 0)
|
|
33
|
+
return;
|
|
34
|
+
const scheduler = new HealthScheduler({
|
|
35
|
+
checks,
|
|
36
|
+
ctx: opts.ctx ?? buildDefaultCtx(opts.workspaceRoot),
|
|
37
|
+
onHealthUpdate: (statuses) => {
|
|
38
|
+
// Trigger-scoped runs (fsevent, lockfile, docker) produce only the
|
|
39
|
+
// statuses for checks subscribed to that trigger. If we replaced the
|
|
40
|
+
// full array with the partial set, every other check's last-known
|
|
41
|
+
// state would be wiped on each poll. Merge by id, replacing any
|
|
42
|
+
// existing entry with the new value while preserving the rest.
|
|
43
|
+
const prev = cockpitStore.getState().health;
|
|
44
|
+
const merged = mergeHealthStatuses(prev, statuses);
|
|
45
|
+
const transitions = detectTransitions(prev, statuses);
|
|
46
|
+
const sessionEnabled = cockpitStore.getState().notificationsEnabledSession;
|
|
47
|
+
for (const t of transitions) {
|
|
48
|
+
const owner = checksRef.current.find((c) => c.id === t.id);
|
|
49
|
+
if (!resolveNotify(t, opts.notifications, owner?.notify))
|
|
50
|
+
continue;
|
|
51
|
+
notify(t, {
|
|
52
|
+
config: opts.notifications,
|
|
53
|
+
sessionEnabled,
|
|
54
|
+
appName: opts.appName ?? 'cockpit',
|
|
55
|
+
sender: opts.notificationSender,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
cockpitStore.getState().setHealth(merged);
|
|
59
|
+
opts.onResults?.(merged);
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
schedulerRef.current = scheduler;
|
|
63
|
+
void scheduler.start();
|
|
64
|
+
const unsub = opts.subscribeFsEvents?.((filePath) => scheduler.onFsEvent(filePath));
|
|
65
|
+
return () => {
|
|
66
|
+
unsub?.();
|
|
67
|
+
scheduler.stop();
|
|
68
|
+
schedulerRef.current = null;
|
|
69
|
+
};
|
|
70
|
+
}, [checks]);
|
|
71
|
+
if (!opts)
|
|
72
|
+
return null;
|
|
73
|
+
return {
|
|
74
|
+
runRemediation: (key) => {
|
|
75
|
+
const list = checksRef.current;
|
|
76
|
+
const ctx = ctxRef.current ?? buildDefaultCtx(optsRef.current?.workspaceRoot ?? '.');
|
|
77
|
+
const check = list.find((c) => c.remediation.key === key);
|
|
78
|
+
if (!check)
|
|
79
|
+
return null;
|
|
80
|
+
const promise = dispatchRemediationKey(key, list, ctx, optsRef.current?.workspaceRoot ?? '.').finally(() => {
|
|
81
|
+
// Re-run all checks after the remediation completes so the user sees
|
|
82
|
+
// the new state immediately, without waiting for an external fsevent.
|
|
83
|
+
void schedulerRef.current?.runAll();
|
|
84
|
+
});
|
|
85
|
+
return {
|
|
86
|
+
label: check.remediation.label,
|
|
87
|
+
promise,
|
|
88
|
+
healthId: check.id,
|
|
89
|
+
healthLabel: check.label,
|
|
90
|
+
};
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function buildDefaultCtx(workspaceRoot) {
|
|
95
|
+
return buildHealthContext(workspaceRoot);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Merge a partial set of fresh statuses into the previous full array,
|
|
99
|
+
* preserving original order and updating any entry whose id matches.
|
|
100
|
+
* Statuses present in `next` but not in `prev` are appended at the end —
|
|
101
|
+
* shouldn't happen during normal operation (the registry is fixed) but
|
|
102
|
+
* keeps the function total.
|
|
103
|
+
*/
|
|
104
|
+
function mergeHealthStatuses(prev, next) {
|
|
105
|
+
if (next.length === 0)
|
|
106
|
+
return prev;
|
|
107
|
+
const byId = new Map();
|
|
108
|
+
for (const s of next)
|
|
109
|
+
byId.set(s.id, s);
|
|
110
|
+
const merged = [];
|
|
111
|
+
const seen = new Set();
|
|
112
|
+
for (const s of prev) {
|
|
113
|
+
const updated = byId.get(s.id);
|
|
114
|
+
merged.push(updated ?? s);
|
|
115
|
+
seen.add(s.id);
|
|
116
|
+
}
|
|
117
|
+
for (const s of next) {
|
|
118
|
+
if (!seen.has(s.id))
|
|
119
|
+
merged.push(s);
|
|
120
|
+
}
|
|
121
|
+
return merged;
|
|
122
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export type { Severity, HealthStatus, Transition, NotifiableEvent, BuiltinNotifiableEvent, Watcher, Service, Repo, Mount, HelpSource, Workspace, Profile, ProfileBootContext, ProfileBootResult, ProfileBootHook, ProfileCockpitHandlers, ProfileAsyncActionDispatch, RepoState, RepoStatus, RepoKind, LintStatus, } from './core/types.js';
|
|
2
|
+
export type { TriggerKind, FsHelpers, ExecHelper, HealthOutputLine, HealthContext, NotifyPolicy, Remediation, HealthCheck, HealthCheckConfig, BuiltinCheckType, CheckPredicateFactory, } from './health/types.js';
|
|
3
|
+
export { hashWorkspacePath, getStatePaths, type StatePaths, type StatePathsOptions, } from './core/paths.js';
|
|
4
|
+
export { createLogger, initLogger, getLogger, type Logger } from './core/logger.js';
|
|
5
|
+
export { spawnStream, killAllSpawned, type ProcessHandle, type SpawnOptions, } from './core/subprocess.js';
|
|
6
|
+
export { detectTransitions, notify, notifyTransitions, emitEvent, type NotificationsConfig, type NotifyOptions, } from './core/notifier.js';
|
|
7
|
+
export { CONFIG_VERSION, loadConfig, BaseCockpitConfigSchema, ConfigValidationError, ConfigVersionError, type BaseCockpitConfig, type LoadConfigOptions, } from './core/config.js';
|
|
8
|
+
export { Command } from 'commander';
|
|
9
|
+
export type { Command as CommanderCommand } from 'commander';
|
|
10
|
+
export { z } from 'zod';
|
|
11
|
+
export { Cockpit, type CockpitProps } from './cockpit/Cockpit.js';
|
|
12
|
+
export { TabBar } from './cockpit/TabBar.js';
|
|
13
|
+
export { Footer, type FooterLegends, type FooterProps } from './cockpit/Footer.js';
|
|
14
|
+
export { Repos } from './cockpit/panes/Repos.js';
|
|
15
|
+
export { Output } from './cockpit/panes/Output.js';
|
|
16
|
+
export { Health } from './cockpit/panes/Health.js';
|
|
17
|
+
export { Help } from './cockpit/panes/Help.js';
|
|
18
|
+
export { FilterModal } from './cockpit/panes/FilterModal.js';
|
|
19
|
+
export { SearchModal } from './cockpit/panes/SearchModal.js';
|
|
20
|
+
export { TAB_ORDER, TAB_LABELS } from './cockpit/tab-state.js';
|
|
21
|
+
export { cockpitStore, type CockpitState, type FocusTarget, type OutputLine, type OutputFilter, type RecentError, type HelpConfig, type OnTransitionCallback, } from './cockpit/state/store.js';
|
|
22
|
+
export { useCockpitStore } from './cockpit/hooks/useCockpitStore.js';
|
|
23
|
+
export { useGlobalKeys, type UseGlobalKeysOptions, type AsyncActionDispatch, type RemediationDispatch, } from './cockpit/hooks/useGlobalKeys.js';
|
|
24
|
+
export { loadHelpPages, resolveDocsRoot, parseIndex, loadPagesFromDir, type HelpSourceInput, type LoadHelpPagesOptions, type LoadHelpPagesResult, } from './cockpit/help/loader.js';
|
|
25
|
+
export type { HelpPage } from './cockpit/help/types.js';
|
|
26
|
+
export { renderMarkdown } from './cockpit/help/renderer.js';
|
|
27
|
+
export { FALLBACK_PAGE } from './cockpit/help/content.js';
|
|
28
|
+
export { compileHighlights, matchHighlights, DEFAULT_HIGHLIGHT_PATTERNS, type HighlightMatch, type HighlightSeverity, type CompiledHighlights, } from './docker/highlights.js';
|
|
29
|
+
export { extractFileLine, type FileLine } from './docker/stack-trace.js';
|
|
30
|
+
export { restartDockerService, type RestartDockerDeps } from './docker/restart.js';
|
|
31
|
+
export { DockerLogTailer, DEBOUNCE_MS as DOCKER_NOTIFY_DEBOUNCE_MS, SILENT_THRESHOLD_MS as DOCKER_SILENT_THRESHOLD_MS, type DockerLogTailerOptions, } from './docker/logs.js';
|
|
32
|
+
export { WatcherManager, type WatcherManagerDeps, type ManagedRepo, } from './watchers/manager.js';
|
|
33
|
+
export { mapPathToRepo, type RepoPrefixEntry } from './watchers/path-mapper.js';
|
|
34
|
+
export type { NormalizedRepoConfig } from './watchers/types.js';
|
|
35
|
+
export { scheduleLint, runAllLints, selectLintCommand, type LintRunnerOptions, } from './lint/reactive.js';
|
|
36
|
+
export { runChecks } from './health/runner.js';
|
|
37
|
+
export { HealthScheduler, type SchedulerDeps } from './health/scheduler.js';
|
|
38
|
+
export { buildHealthContext } from './health/context.js';
|
|
39
|
+
export { runRemediation, findRemediation, dispatchRemediation, type RemediationKey, } from './health/remediations.js';
|
|
40
|
+
export { BUILTIN_CHECK_FACTORIES, BUILTIN_DEFAULT_TRIGGERS, BUILTIN_DEFAULT_SEVERITY, } from './health/builtin.js';
|
|
41
|
+
export { buildHealthRegistry, type BuildHealthRegistryOptions, } from './health/registry.js';
|
|
42
|
+
export { resolveNotify } from './health/notify-resolver.js';
|
|
43
|
+
export { useHealth, type UseHealthOptions, type UseHealthHandle, type FsEventSource, } from './health/useHealth.js';
|
|
44
|
+
export { runCockpit, type RunCockpitOptions, type RunCockpitHandle } from './runCockpit.js';
|
|
45
|
+
export { buildCli, type BuildCliOptions } from './buildCli.js';
|
|
46
|
+
export { devCommand, type DevCommandOptions } from './commands/dev.js';
|
|
47
|
+
export { doctorCommand, formatResults, type DoctorCommandOptions, } from './commands/doctor.js';
|
|
48
|
+
export { initConfigCommand, buildTemplate, type InitConfigOptions, type InitConfigResult, } from './commands/init-config.js';
|
|
49
|
+
export { mountCommand, mountStatusCommand, mountClearCommand, mergeMounts, renderOverlay, type MountCommandOptions, type MountManifest, } from './commands/mount.js';
|
|
50
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,eAAe,EACf,sBAAsB,EACtB,OAAO,EACP,OAAO,EACP,IAAI,EACJ,KAAK,EACL,UAAU,EACV,SAAS,EACT,OAAO,EACP,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,sBAAsB,EACtB,0BAA0B,EAC1B,SAAS,EACT,UAAU,EACV,QAAQ,EACR,UAAU,GACX,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,WAAW,EACX,SAAS,EACT,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,KAAK,UAAU,EACf,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEpF,OAAO,EACL,WAAW,EACX,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,YAAY,GAClB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,iBAAiB,EACjB,MAAM,EACN,iBAAiB,EACjB,SAAS,EACT,KAAK,mBAAmB,EACxB,KAAK,aAAa,GACnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,cAAc,EACd,UAAU,EACV,uBAAuB,EACvB,qBAAqB,EACrB,kBAAkB,EAClB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,GACvB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACnF,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,EACL,YAAY,EACZ,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,oBAAoB,GAC1B,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAErE,OAAO,EACL,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,GACzB,MAAM,kCAAkC,CAAC;AAG1C,OAAO,EACL,aAAa,EACb,eAAe,EACf,UAAU,EACV,gBAAgB,EAChB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,GACzB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAExD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAG1D,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC1B,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,GACxB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACnF,OAAO,EACL,eAAe,EACf,WAAW,IAAI,yBAAyB,EACxC,mBAAmB,IAAI,0BAA0B,EACjD,KAAK,sBAAsB,GAC5B,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,cAAc,EACd,KAAK,kBAAkB,EACvB,KAAK,WAAW,GACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAChF,YAAY,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EACL,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,KAAK,iBAAiB,GACvB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EACL,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,KAAK,cAAc,GACpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,mBAAmB,EACnB,KAAK,0BAA0B,GAChC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EACL,SAAS,EACT,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAG5F,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EACL,aAAa,EACb,aAAa,EACb,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,aAAa,GACnB,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// ─── Core runtime exports ───────────────────────────────────────────────────
|
|
2
|
+
export { hashWorkspacePath, getStatePaths, } from './core/paths.js';
|
|
3
|
+
export { createLogger, initLogger, getLogger } from './core/logger.js';
|
|
4
|
+
export { spawnStream, killAllSpawned, } from './core/subprocess.js';
|
|
5
|
+
export { detectTransitions, notify, notifyTransitions, emitEvent, } from './core/notifier.js';
|
|
6
|
+
export { CONFIG_VERSION, loadConfig, BaseCockpitConfigSchema, ConfigValidationError, ConfigVersionError, } from './core/config.js';
|
|
7
|
+
// ─── Re-exported third-party types/values ──────────────────────────────────
|
|
8
|
+
export { Command } from 'commander';
|
|
9
|
+
export { z } from 'zod';
|
|
10
|
+
// ─── Cockpit shell ──────────────────────────────────────────────────────────
|
|
11
|
+
export { Cockpit } from './cockpit/Cockpit.js';
|
|
12
|
+
export { TabBar } from './cockpit/TabBar.js';
|
|
13
|
+
export { Footer } from './cockpit/Footer.js';
|
|
14
|
+
export { Repos } from './cockpit/panes/Repos.js';
|
|
15
|
+
export { Output } from './cockpit/panes/Output.js';
|
|
16
|
+
export { Health } from './cockpit/panes/Health.js';
|
|
17
|
+
export { Help } from './cockpit/panes/Help.js';
|
|
18
|
+
export { FilterModal } from './cockpit/panes/FilterModal.js';
|
|
19
|
+
export { SearchModal } from './cockpit/panes/SearchModal.js';
|
|
20
|
+
export { TAB_ORDER, TAB_LABELS } from './cockpit/tab-state.js';
|
|
21
|
+
export { cockpitStore, } from './cockpit/state/store.js';
|
|
22
|
+
export { useCockpitStore } from './cockpit/hooks/useCockpitStore.js';
|
|
23
|
+
export { useGlobalKeys, } from './cockpit/hooks/useGlobalKeys.js';
|
|
24
|
+
// ─── Help loader / renderer ─────────────────────────────────────────────────
|
|
25
|
+
export { loadHelpPages, resolveDocsRoot, parseIndex, loadPagesFromDir, } from './cockpit/help/loader.js';
|
|
26
|
+
export { renderMarkdown } from './cockpit/help/renderer.js';
|
|
27
|
+
export { FALLBACK_PAGE } from './cockpit/help/content.js';
|
|
28
|
+
// ─── Docker subsystem ───────────────────────────────────────────────────────
|
|
29
|
+
export { compileHighlights, matchHighlights, DEFAULT_HIGHLIGHT_PATTERNS, } from './docker/highlights.js';
|
|
30
|
+
export { extractFileLine } from './docker/stack-trace.js';
|
|
31
|
+
export { restartDockerService } from './docker/restart.js';
|
|
32
|
+
export { DockerLogTailer, DEBOUNCE_MS as DOCKER_NOTIFY_DEBOUNCE_MS, SILENT_THRESHOLD_MS as DOCKER_SILENT_THRESHOLD_MS, } from './docker/logs.js';
|
|
33
|
+
// ─── Watchers + lint ────────────────────────────────────────────────────────
|
|
34
|
+
export { WatcherManager, } from './watchers/manager.js';
|
|
35
|
+
export { mapPathToRepo } from './watchers/path-mapper.js';
|
|
36
|
+
export { scheduleLint, runAllLints, selectLintCommand, } from './lint/reactive.js';
|
|
37
|
+
// ─── Health framework ──────────────────────────────────────────────────────
|
|
38
|
+
export { runChecks } from './health/runner.js';
|
|
39
|
+
export { HealthScheduler } from './health/scheduler.js';
|
|
40
|
+
export { buildHealthContext } from './health/context.js';
|
|
41
|
+
export { runRemediation, findRemediation, dispatchRemediation, } from './health/remediations.js';
|
|
42
|
+
export { BUILTIN_CHECK_FACTORIES, BUILTIN_DEFAULT_TRIGGERS, BUILTIN_DEFAULT_SEVERITY, } from './health/builtin.js';
|
|
43
|
+
export { buildHealthRegistry, } from './health/registry.js';
|
|
44
|
+
export { resolveNotify } from './health/notify-resolver.js';
|
|
45
|
+
export { useHealth, } from './health/useHealth.js';
|
|
46
|
+
// ─── Boot entry ─────────────────────────────────────────────────────────────
|
|
47
|
+
export { runCockpit } from './runCockpit.js';
|
|
48
|
+
// ─── CLI builder + commands ────────────────────────────────────────────────
|
|
49
|
+
export { buildCli } from './buildCli.js';
|
|
50
|
+
export { devCommand } from './commands/dev.js';
|
|
51
|
+
export { doctorCommand, formatResults, } from './commands/doctor.js';
|
|
52
|
+
export { initConfigCommand, buildTemplate, } from './commands/init-config.js';
|
|
53
|
+
export { mountCommand, mountStatusCommand, mountClearCommand, mergeMounts, renderOverlay, } from './commands/mount.js';
|
package/dist/ink.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ink.d.ts","sourceRoot":"","sources":["../src/ink.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,eAAe,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AACzJ,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC"}
|
package/dist/ink.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Box, Text, render, useApp, useInput, useFocus, useFocusManager, useStdout, useStderr, useStdin, Static, Newline, Spacer, Transform } from 'ink';
|