@gachlab/devup 0.5.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +74 -454
  3. package/dist/config/cli.d.ts +2 -1
  4. package/dist/config/cli.d.ts.map +1 -1
  5. package/dist/config/diff.d.ts +19 -0
  6. package/dist/config/diff.d.ts.map +1 -0
  7. package/dist/config/validator.d.ts +9 -0
  8. package/dist/config/validator.d.ts.map +1 -1
  9. package/dist/control-plane/socket-server.d.ts +31 -0
  10. package/dist/control-plane/socket-server.d.ts.map +1 -0
  11. package/dist/index.js +1047 -525
  12. package/dist/index.js.map +1 -1
  13. package/dist/process/health-poller.d.ts +15 -0
  14. package/dist/process/health-poller.d.ts.map +1 -0
  15. package/dist/process/internals.d.ts +14 -0
  16. package/dist/process/internals.d.ts.map +1 -0
  17. package/dist/process/lifecycle.d.ts +31 -0
  18. package/dist/process/lifecycle.d.ts.map +1 -0
  19. package/dist/process/manager.d.ts +11 -13
  20. package/dist/process/manager.d.ts.map +1 -1
  21. package/dist/process/restarter.d.ts +26 -0
  22. package/dist/process/restarter.d.ts.map +1 -0
  23. package/dist/process/spawner.d.ts +38 -0
  24. package/dist/process/spawner.d.ts.map +1 -0
  25. package/dist/tui/App.d.ts.map +1 -1
  26. package/dist/tui/LogsPanel.d.ts +9 -1
  27. package/dist/tui/LogsPanel.d.ts.map +1 -1
  28. package/dist/tui/hooks/useBootSequence.d.ts +20 -0
  29. package/dist/tui/hooks/useBootSequence.d.ts.map +1 -0
  30. package/dist/tui/hooks/useContextualTips.d.ts +6 -0
  31. package/dist/tui/hooks/useContextualTips.d.ts.map +1 -0
  32. package/dist/tui/hooks/useControlPlane.d.ts +10 -0
  33. package/dist/tui/hooks/useControlPlane.d.ts.map +1 -0
  34. package/dist/tui/hooks/useHotReload.d.ts +7 -0
  35. package/dist/tui/hooks/useHotReload.d.ts.map +1 -0
  36. package/dist/tui/hooks/useLogsPause.d.ts +4 -0
  37. package/dist/tui/hooks/useLogsPause.d.ts.map +1 -0
  38. package/dist/tui/hooks/useTerminalSize.d.ts +4 -0
  39. package/dist/tui/hooks/useTerminalSize.d.ts.map +1 -0
  40. package/dist/utils/colors.d.ts +4 -0
  41. package/dist/utils/colors.d.ts.map +1 -0
  42. package/dist/utils/env.d.ts +5 -0
  43. package/dist/utils/env.d.ts.map +1 -0
  44. package/dist/utils/format.d.ts +3 -0
  45. package/dist/utils/format.d.ts.map +1 -0
  46. package/dist/utils/install-stamp.d.ts +6 -0
  47. package/dist/utils/install-stamp.d.ts.map +1 -0
  48. package/dist/utils/phases.d.ts +4 -0
  49. package/dist/utils/phases.d.ts.map +1 -0
  50. package/dist/utils/process-args.d.ts +8 -0
  51. package/dist/utils/process-args.d.ts.map +1 -0
  52. package/dist/utils/redact.d.ts +4 -0
  53. package/dist/utils/redact.d.ts.map +1 -0
  54. package/dist/utils/search.d.ts +17 -0
  55. package/dist/utils/search.d.ts.map +1 -0
  56. package/dist/utils/stats.d.ts +19 -0
  57. package/dist/utils/stats.d.ts.map +1 -0
  58. package/dist/utils.d.ts +10 -41
  59. package/dist/utils.d.ts.map +1 -1
  60. package/package.json +1 -1
@@ -0,0 +1,15 @@
1
+ import type { ProcessState, ProcessManagerEvents } from './types.js';
2
+ interface HealthPollerOpts {
3
+ state: Map<string, ProcessState>;
4
+ events: ProcessManagerEvents;
5
+ }
6
+ /** Runs one round of health probes across every service in `state`.
7
+ * Suppresses probes during `healthCheck.startPeriod` grace window. */
8
+ export declare class HealthPoller {
9
+ private readonly state;
10
+ private readonly events;
11
+ constructor(opts: HealthPollerOpts);
12
+ checkAll(): Promise<void>;
13
+ }
14
+ export {};
15
+ //# sourceMappingURL=health-poller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health-poller.d.ts","sourceRoot":"","sources":["../../src/process/health-poller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGrE,UAAU,gBAAgB;IACxB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACjC,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAED;uEACuE;AACvE,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA4B;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;gBAElC,IAAI,EAAE,gBAAgB;IAK5B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAmBhC"}
@@ -0,0 +1,14 @@
1
+ /** Buffered line splitter. Calls `onLine` for every newline-terminated chunk,
2
+ * preserves leftover for the next push. `flush()` emits any remaining tail. */
3
+ export declare function lineBuffer(onLine: (line: string) => void): {
4
+ push(chunk: Buffer): void;
5
+ flush(): void;
6
+ };
7
+ /** Accepts both '/foo/' (vim-style) and bare 'foo'. Case-insensitive by default. */
8
+ export declare function compileReadyPattern(pattern: string | undefined): RegExp | null;
9
+ /** Extracts the value tokens of `--watch` / `--watch-path` / `--watch=X` / `--watch-path=X`
10
+ * from a command's args list. Accepts both `--flag value` and `--flag=value` forms. */
11
+ export declare function extractWatchPaths(args: string[]): string[];
12
+ export declare const MAX_RESTARTS = 3;
13
+ export declare const BACKOFF_BASE_MS = 2000;
14
+ //# sourceMappingURL=internals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internals.d.ts","sourceRoot":"","sources":["../../src/process/internals.ts"],"names":[],"mappings":"AAAA;gFACgF;AAChF,wBAAgB,UAAU,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;gBAGzC,MAAM;;EAarB;AAED,oFAAoF;AACpF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAS9E;AAED;wFACwF;AACxF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAgB1D;AAED,eAAO,MAAM,YAAY,IAAI,CAAC;AAC9B,eAAO,MAAM,eAAe,OAAO,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { ChildProcess } from 'node:child_process';
2
+ import type { Platform } from '../platform/types.js';
3
+ import type { ProcessState } from './types.js';
4
+ interface LifecycleOpts {
5
+ state: Map<string, ProcessState>;
6
+ procs: Set<ChildProcess>;
7
+ platform: Platform;
8
+ }
9
+ /** Owns the kill-tree, watchBuild teardown, and graceful cleanup with SIGKILL
10
+ * fallback. Stateless beyond what's passed in via opts. */
11
+ export declare class Lifecycle {
12
+ private readonly state;
13
+ private readonly procs;
14
+ private readonly platform;
15
+ constructor(opts: LifecycleOpts);
16
+ /** Manual / external stop of a single service. Marks `intentionalStop` so the
17
+ * close handler doesn't auto-restart, kills the process tree, tears down the
18
+ * side-car watchBuild process if any. */
19
+ stop(name: string): void;
20
+ /** Tears down the side-car `watchBuild` process for a service (if any) and
21
+ * clears the reference. Safe to call repeatedly. */
22
+ stopWatchProc(state: ProcessState): void;
23
+ /** Graceful shutdown of every spawned process. Waits `gracePeriodMs` (default
24
+ * 3000) for clean exits, then SIGKILLs anything still alive. */
25
+ cleanup(opts?: {
26
+ gracePeriodMs?: number;
27
+ }): Promise<void>;
28
+ private findStateByProc;
29
+ }
30
+ export {};
31
+ //# sourceMappingURL=lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../src/process/lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,UAAU,aAAa;IACrB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACjC,KAAK,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;IACzB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED;4DAC4D;AAC5D,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA4B;IAClD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;IAC1C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;gBAExB,IAAI,EAAE,aAAa;IAM/B;;8CAE0C;IAC1C,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQxB;yDACqD;IACrD,aAAa,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IAOxC;qEACiE;IAC3D,OAAO,CAAC,IAAI,GAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA0CnE,OAAO,CAAC,eAAe;CAIxB"}
@@ -1,18 +1,23 @@
1
1
  import type { Platform } from '../platform/types.js';
2
2
  import type { ServiceConfig } from '../config/types.js';
3
3
  import type { ProcessState, ProcessManagerEvents } from './types.js';
4
- /** Accepts both '/foo/' (vim-style) and bare 'foo'. Case-insensitive by default. */
5
- export declare function compileReadyPattern(pattern: string | undefined): RegExp | null;
6
- /** Extracts the value tokens of `--watch` / `--watch-path` / `--watch=X` / `--watch-path=X`
7
- * from a command's args list. Accepts both `--flag value` and `--flag=value` forms. */
8
- export declare function extractWatchPaths(args: string[]): string[];
4
+ export { compileReadyPattern, extractWatchPaths } from './internals.js';
5
+ /** Thin facade composing Spawner, Restarter, HealthPoller, and Lifecycle.
6
+ * All four components share the same `state` Map and `procs` Set, so
7
+ * mutations from one are visible to the others.
8
+ *
9
+ * Public API is unchanged from the pre-refactor monolithic class —
10
+ * every TUI / orchestrator / control-plane call site keeps working. */
9
11
  export declare class ProcessManager {
10
12
  readonly state: Map<string, ProcessState>;
11
13
  private readonly procs;
12
14
  private readonly baseCwd;
13
15
  private readonly env;
14
- private readonly platform;
15
16
  private readonly events;
17
+ private readonly spawner;
18
+ private readonly restarter;
19
+ private readonly healthPoller;
20
+ private readonly lifecycle;
16
21
  constructor(opts: {
17
22
  baseCwd: string;
18
23
  env: Record<string, string>;
@@ -21,18 +26,11 @@ export declare class ProcessManager {
21
26
  });
22
27
  install(svc: ServiceConfig, colorIdx?: number): Promise<boolean>;
23
28
  start(svc: ServiceConfig, colorIdx: number, isRestart?: boolean): Promise<void>;
24
- private runPreBuild;
25
- private spawnWatchBuild;
26
- /** Create a state entry in 'crashed' status without spawning a process (used when preBuild fails). */
27
- private recordCrashedState;
28
29
  stop(name: string): void;
29
- private stopWatchProc;
30
30
  restart(name: string): Promise<void>;
31
31
  checkAllHealth(): Promise<void>;
32
32
  cleanup(opts?: {
33
33
  gracePeriodMs?: number;
34
34
  }): Promise<void>;
35
- private findStateByProc;
36
- private log;
37
35
  }
38
36
  //# sourceMappingURL=manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/process/manager.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAQrE,oFAAoF;AACpF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAS9E;AAED;wFACwF;AACxF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAgB1D;AAoBD,qBAAa,cAAc;IACzB,QAAQ,CAAC,KAAK,4BAAmC;IACjD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2B;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAyB;IAC7C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;gBAElC,IAAI,EAAE;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC5B,QAAQ,EAAE,QAAQ,CAAC;QACnB,MAAM,EAAE,oBAAoB,CAAC;KAC9B;IAOK,OAAO,CAAC,GAAG,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMhE,KAAK,CAAC,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAgHnF,OAAO,CAAC,WAAW;IA+BnB,OAAO,CAAC,eAAe;IAgBvB,sGAAsG;IACtG,OAAO,CAAC,kBAAkB;IAc1B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQxB,OAAO,CAAC,aAAa;IAOf,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYpC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB/B,OAAO,CAAC,IAAI,GAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAyCnE,OAAO,CAAC,eAAe;IAKvB,OAAO,CAAC,GAAG;CAGZ"}
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/process/manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAQrE,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExE;;;;;wEAKwE;AACxE,qBAAa,cAAc;IACzB,QAAQ,CAAC,KAAK,4BAAmC;IACjD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2B;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAyB;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;gBAE1B,IAAI,EAAE;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC5B,QAAQ,EAAE,QAAQ,CAAC;QACnB,MAAM,EAAE,oBAAoB,CAAC;KAC9B;IA6BD,OAAO,CAAC,GAAG,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMhE,KAAK,CAAC,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7E,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIxB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAI/B,OAAO,CAAC,IAAI,GAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAG9D"}
@@ -0,0 +1,26 @@
1
+ import type { ServiceConfig } from '../config/types.js';
2
+ import type { ProcessState, ProcessManagerEvents } from './types.js';
3
+ import type { Spawner } from './spawner.js';
4
+ import type { Lifecycle } from './lifecycle.js';
5
+ interface RestarterOpts {
6
+ state: Map<string, ProcessState>;
7
+ events: ProcessManagerEvents;
8
+ spawner: Spawner;
9
+ lifecycle: Lifecycle;
10
+ }
11
+ /** Two responsibilities:
12
+ * 1. Manual restart (`restart(name)`) — full stop + respawn, **resets** the
13
+ * auto-restart counter so the user gets a fresh budget.
14
+ * 2. Auto-restart on crash (`scheduleAutoRestart`) — exponential backoff,
15
+ * capped at MAX_RESTARTS. Spawner invokes this in its close handler. */
16
+ export declare class Restarter {
17
+ private readonly state;
18
+ private readonly events;
19
+ private readonly spawner;
20
+ private readonly lifecycle;
21
+ constructor(opts: RestarterOpts);
22
+ restart(name: string): Promise<void>;
23
+ scheduleAutoRestart(svc: ServiceConfig, state: ProcessState, colorIdx: number): void;
24
+ }
25
+ export {};
26
+ //# sourceMappingURL=restarter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restarter.d.ts","sourceRoot":"","sources":["../../src/process/restarter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGhD,UAAU,aAAa;IACrB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACjC,MAAM,EAAE,oBAAoB,CAAC;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,SAAS,CAAC;CACtB;AAED;;;;4EAI4E;AAC5E,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA4B;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;gBAE1B,IAAI,EAAE,aAAa;IAOzB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY1C,mBAAmB,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;CAUrF"}
@@ -0,0 +1,38 @@
1
+ import { type ChildProcess } from 'node:child_process';
2
+ import type { ServiceConfig } from '../config/types.js';
3
+ import type { ProcessState, ProcessManagerEvents } from './types.js';
4
+ import type { Lifecycle } from './lifecycle.js';
5
+ interface SpawnerOpts {
6
+ baseCwd: string;
7
+ env: Record<string, string>;
8
+ state: Map<string, ProcessState>;
9
+ procs: Set<ChildProcess>;
10
+ events: ProcessManagerEvents;
11
+ lifecycle: Lifecycle;
12
+ /** Called when a service exits non-zero, so the Restarter can schedule auto-restart. */
13
+ onCrash: (svc: ServiceConfig, state: ProcessState, colorIdx: number) => void;
14
+ }
15
+ /** Owns the spawn lifecycle: port check → preBuild → watch-path pre-flight →
16
+ * spawn → wire stdio (readyPattern + errorPattern + log) → watchBuild → close
17
+ * handler. On crash, delegates to `onCrash` (the Restarter wires this). */
18
+ export declare class Spawner {
19
+ private readonly baseCwd;
20
+ private readonly env;
21
+ private readonly state;
22
+ private readonly procs;
23
+ private readonly events;
24
+ private readonly lifecycle;
25
+ private readonly onCrash;
26
+ constructor(opts: SpawnerOpts);
27
+ start(svc: ServiceConfig, colorIdx: number, isRestart?: boolean): Promise<void>;
28
+ private wireStdio;
29
+ private wireCloseHandler;
30
+ private runPreBuild;
31
+ private spawnWatchBuild;
32
+ /** Create a state entry in 'crashed' status without spawning a process
33
+ * (used when preBuild fails or pre-flight checks fail). */
34
+ private recordCrashedState;
35
+ private log;
36
+ }
37
+ export {};
38
+ //# sourceMappingURL=spawner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawner.d.ts","sourceRoot":"","sources":["../../src/process/spawner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAG9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAIrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,UAAU,WAAW;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACjC,KAAK,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;IACzB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,SAAS,EAAE,SAAS,CAAC;IACrB,wFAAwF;IACxF,OAAO,EAAE,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9E;AAED;;4EAE4E;AAC5E,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAyB;IAC7C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA4B;IAClD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;IAC1C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;gBAErC,IAAI,EAAE,WAAW;IAUvB,KAAK,CAAC,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IA4DnF,OAAO,CAAC,SAAS;IA0BjB,OAAO,CAAC,gBAAgB;IAiBxB,OAAO,CAAC,WAAW;IA+BnB,OAAO,CAAC,eAAe;IAgBvB;gEAC4D;IAC5D,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,GAAG;CAGZ"}
@@ -1 +1 @@
1
- {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/tui/App.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAkBtD;;8FAE8F;AAC9F,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,OAAO,EACpB,SAAS,EAAE,SAAS,GAAG,IAAI,GAC1B,MAAM,CAUR;AAED,UAAU,KAAK;IACb,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC1C,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CACzB;AAED,wBAAgB,GAAG,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,KAAK,2CAkOlH"}
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/tui/App.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAkBtD;;8FAE8F;AAC9F,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,OAAO,EACpB,SAAS,EAAE,SAAS,GAAG,IAAI,GAC1B,MAAM,CAUR;AAED,UAAU,KAAK;IACb,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC1C,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CACzB;AAED,wBAAgB,GAAG,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,KAAK,2CA6FlH"}
@@ -1,4 +1,9 @@
1
1
  import type { LogEntry } from './hooks/useProcessManager.js';
2
+ /** Border color resolution rules:
3
+ * - focused wins (cyan), so the active-pane affordance is never lost
4
+ * - filtered + we know the service color → use it (subtle reinforcement)
5
+ * - otherwise gray */
6
+ export declare function resolveBorder(focused: boolean, filter: string | null, filteredColorIdx: number | null): string;
2
7
  interface Props {
3
8
  logs: LogEntry[];
4
9
  filter: string | null;
@@ -11,7 +16,10 @@ interface Props {
11
16
  scrollOffset: number;
12
17
  resetScroll: () => void;
13
18
  levelFilter?: 'all' | 'error' | 'warn';
19
+ /** When non-null, used to tint the panel border with the filtered service's tag color
20
+ * (subtle reinforcement of "you're seeing only this service"). */
21
+ filteredColorIdx?: number | null;
14
22
  }
15
- export declare function LogsPanel({ logs, filter, searchTerm, paused, showTimestamps, maxNameLen, height, focused, scrollOffset, resetScroll, levelFilter }: Props): import("react/jsx-runtime").JSX.Element;
23
+ export declare function LogsPanel({ logs, filter, searchTerm, paused, showTimestamps, maxNameLen, height, focused, scrollOffset, resetScroll, levelFilter, filteredColorIdx }: Props): import("react/jsx-runtime").JSX.Element;
16
24
  export {};
17
25
  //# sourceMappingURL=LogsPanel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LogsPanel.d.ts","sourceRoot":"","sources":["../../src/tui/LogsPanel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAG7D,UAAU,KAAK;IACb,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,WAAW,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,MAAM,CAAC;CACxC;AAED,wBAAgB,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,WAAmB,EAAE,EAAE,KAAK,2CA0DjK"}
1
+ {"version":3,"file":"LogsPanel.d.ts","sourceRoot":"","sources":["../../src/tui/LogsPanel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAG7D;;;uBAGuB;AACvB,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAM9G;AAED,UAAU,KAAK;IACb,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,WAAW,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,MAAM,CAAC;IACvC;uEACmE;IACnE,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,wBAAgB,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,WAAmB,EAAE,gBAAuB,EAAE,EAAE,KAAK,2CA0D1L"}
@@ -0,0 +1,20 @@
1
+ import type { Platform } from '../../platform/types.js';
2
+ import type { DevStackConfig, ServiceConfig } from '../../config/types.js';
3
+ import type { CliArgs } from '../../config/cli.js';
4
+ import type { ProcessManager } from '../../process/manager.js';
5
+ import { type LazyProxy } from '../../lazy/proxy.js';
6
+ import { type ExternalProc } from '../../process/external.js';
7
+ interface BootRefs {
8
+ lazyProxies: React.RefObject<Map<string, LazyProxy>>;
9
+ externals: React.RefObject<ExternalProc[]>;
10
+ }
11
+ /** Orchestrates the boot:
12
+ * 1. Externals first (docker compose etc.) — abort if any unhealthy.
13
+ * 2. In lazy mode: start always-on services in phase order, register lazy
14
+ * TCP proxies for the rest.
15
+ * 3. In normal mode: start every service in phase order.
16
+ *
17
+ * Within each phase, APIs are awaited via waitForPort; webs are not. */
18
+ export declare function useBootSequence(manager: ProcessManager | null, config: DevStackConfig, services: ServiceConfig[], cliArgs: CliArgs, platform: Platform, env: Record<string, string>, baseCwd: string, refs: BootRefs, pushLog: (svc: string, msg: string, colorIdx?: number) => void): void;
19
+ export {};
20
+ //# sourceMappingURL=useBootSequence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useBootSequence.d.ts","sourceRoot":"","sources":["../../../src/tui/hooks/useBootSequence.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAK/D,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9E,UAAU,QAAQ;IAChB,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IACrD,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC;CAC5C;AAED;;;;;;yEAMyE;AACzE,wBAAgB,eAAe,CAC7B,OAAO,EAAE,cAAc,GAAG,IAAI,EAC9B,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,aAAa,EAAE,EACzB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,GAC7D,IAAI,CA6GN"}
@@ -0,0 +1,6 @@
1
+ import type { ProcessState } from '../../process/types.js';
2
+ /** Surfaces a one-liner tip in teachable moments (high log volume, crash
3
+ * loop, etc.). Each tip shows at most once per session and auto-clears
4
+ * after 12 s. */
5
+ export declare function useContextualTips(totalLogs: number, hasSearch: boolean, hasFilter: boolean, states: Map<string, ProcessState>): string | null;
6
+ //# sourceMappingURL=useContextualTips.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useContextualTips.d.ts","sourceRoot":"","sources":["../../../src/tui/hooks/useContextualTips.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAI3D;;kBAEkB;AAClB,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,OAAO,EAClB,SAAS,EAAE,OAAO,EAClB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,GAChC,MAAM,GAAG,IAAI,CAqBf"}
@@ -0,0 +1,10 @@
1
+ import type { ProcessManager } from '../../process/manager.js';
2
+ import type { LogSink } from '../../process/log-sink.js';
3
+ import { type SocketServerHandle } from '../../control-plane/socket-server.js';
4
+ /** Lifecycle of the Unix-socket JSON-RPC control plane. Mounts when the
5
+ * manager is ready; tears down on unmount.
6
+ *
7
+ * On listen failure (perms, dir missing, port already-in-use on the inode)
8
+ * devup keeps running without the control plane and logs a single notice. */
9
+ export declare function useControlPlane(manager: ProcessManager | null, projectName: string, logSink: LogSink | null, pushLog: (svc: string, msg: string, colorIdx?: number) => void): React.RefObject<SocketServerHandle | null>;
10
+ //# sourceMappingURL=useControlPlane.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useControlPlane.d.ts","sourceRoot":"","sources":["../../../src/tui/hooks/useControlPlane.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAElG;;;;8EAI8E;AAC9E,wBAAgB,eAAe,CAC7B,OAAO,EAAE,cAAc,GAAG,IAAI,EAC9B,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,OAAO,GAAG,IAAI,EACvB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,GAC7D,KAAK,CAAC,SAAS,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAgC5C"}
@@ -0,0 +1,7 @@
1
+ import type { ProcessManager } from '../../process/manager.js';
2
+ import type { CliArgs } from '../../config/cli.js';
3
+ /** Watches the resolved config file when --watch-config is on. On each save:
4
+ * re-load, validate, diff against the running set, apply add/remove/restart.
5
+ * A failed validation leaves the running set untouched. 250 ms debounce. */
6
+ export declare function useHotReload(manager: ProcessManager | null, cliArgs: CliArgs, baseCwd: string, pushLog: (svc: string, msg: string, colorIdx?: number) => void): void;
7
+ //# sourceMappingURL=useHotReload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useHotReload.d.ts","sourceRoot":"","sources":["../../../src/tui/hooks/useHotReload.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAKnD;;6EAE6E;AAC7E,wBAAgB,YAAY,CAC1B,OAAO,EAAE,cAAc,GAAG,IAAI,EAC9B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,GAC7D,IAAI,CAoEN"}
@@ -0,0 +1,4 @@
1
+ /** Couples the keyboard pause state (explicit `p` toggle OR auto-pause when
2
+ * scrolled up) with the process manager's logs sink. */
3
+ export declare function useLogsPause(setPaused: (paused: boolean) => void, logsPaused: boolean, logsScrollOffset: number): void;
4
+ //# sourceMappingURL=useLogsPause.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLogsPause.d.ts","sourceRoot":"","sources":["../../../src/tui/hooks/useLogsPause.ts"],"names":[],"mappings":"AAEA;yDACyD;AACzD,wBAAgB,YAAY,CAC1B,SAAS,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,EACpC,UAAU,EAAE,OAAO,EACnB,gBAAgB,EAAE,MAAM,GACvB,IAAI,CAIN"}
@@ -0,0 +1,4 @@
1
+ /** Returns the current terminal row count, re-rendering on resize.
2
+ * Falls back to 40 when stdout isn't available (non-TTY mode). */
3
+ export declare function useTerminalSize(): number;
4
+ //# sourceMappingURL=useTerminalSize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTerminalSize.d.ts","sourceRoot":"","sources":["../../../src/tui/hooks/useTerminalSize.ts"],"names":[],"mappings":"AAGA;mEACmE;AACnE,wBAAgB,eAAe,IAAI,MAAM,CAUxC"}
@@ -0,0 +1,4 @@
1
+ /** Color palette used for the service-tag prefix in the logs panel.
2
+ * Wrapped modulo length when there are more services than entries. */
3
+ export declare const tagColors: string[];
4
+ //# sourceMappingURL=colors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../src/utils/colors.ts"],"names":[],"mappings":"AAAA;uEACuE;AACvE,eAAO,MAAM,SAAS,UAIrB,CAAC"}
@@ -0,0 +1,5 @@
1
+ /** Reads a `.env`-style file and overlays it on top of `baseEnv`.
2
+ * Lines starting with `#` are comments. Quoted values get the quotes stripped.
3
+ * Existing keys in `baseEnv` win — file values only fill the gaps. */
4
+ export declare function parseEnvFile(filePath: string, baseEnv?: Record<string, string>): Record<string, string>;
5
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/utils/env.ts"],"names":[],"mappings":"AAEA;;uEAEuE;AACvE,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAiB3G"}
@@ -0,0 +1,3 @@
1
+ /** Formats a duration (in ms) as a short human string: 45s, 2m5s, 1h2m, 2d3h. */
2
+ export declare function fmtUptime(ms: number): string;
3
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAU5C"}
@@ -0,0 +1,6 @@
1
+ /** Returns true if the service's node_modules is missing or its install stamp
2
+ * doesn't match the current package.json hash. */
3
+ export declare function needsInstall(fullCwd: string): boolean;
4
+ /** Writes the install stamp file for a service after a successful `npm install`. */
5
+ export declare function writeInstallStamp(fullCwd: string): void;
6
+ //# sourceMappingURL=install-stamp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-stamp.d.ts","sourceRoot":"","sources":["../../src/utils/install-stamp.ts"],"names":[],"mappings":"AAIA;mDACmD;AACnD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CASrD;AAED,oFAAoF;AACpF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAKvD"}
@@ -0,0 +1,4 @@
1
+ import type { ServiceConfig } from '../config/types.js';
2
+ /** Groups a flat list of services by their `phase` field. */
3
+ export declare function groupByPhase(services: ServiceConfig[]): Record<number, ServiceConfig[]>;
4
+ //# sourceMappingURL=phases.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phases.d.ts","sourceRoot":"","sources":["../../src/utils/phases.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,6DAA6D;AAC7D,wBAAgB,YAAY,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,CAMvF"}
@@ -0,0 +1,8 @@
1
+ import type { ServiceConfig } from '../config/types.js';
2
+ /** Builds the final args list for spawning a service: prepends `--max-old-space-size`
3
+ * for `node` commands when maxMem is set, plus any nodeArgs overrides. */
4
+ export declare function buildProcessArgs(svc: ServiceConfig): string[];
5
+ /** Builds the env for spawning a service: merges extraEnv and injects
6
+ * NODE_OPTIONS=--max-old-space-size when maxMem is set and cmd != 'node'. */
7
+ export declare function buildProcessEnv(svc: ServiceConfig, baseEnv: Record<string, string>): Record<string, string>;
8
+ //# sourceMappingURL=process-args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-args.d.ts","sourceRoot":"","sources":["../../src/utils/process-args.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD;2EAC2E;AAC3E,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,EAAE,CAK7D;AAED;8EAC8E;AAC9E,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAU3G"}
@@ -0,0 +1,4 @@
1
+ /** Returns the env record with values redacted to *** for keys that look
2
+ * secret-ish (token / password / secret / key / auth). Case-insensitive. */
3
+ export declare function redactSecrets(env: Record<string, string> | undefined): Record<string, string>;
4
+ //# sourceMappingURL=redact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/utils/redact.ts"],"names":[],"mappings":"AAAA;6EAC6E;AAC7E,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAO7F"}
@@ -0,0 +1,17 @@
1
+ export interface SearchMatcher {
2
+ test: (line: string) => boolean;
3
+ /** Set when the input was a vim-style /pattern/flags — used to drive highlighting. */
4
+ regex?: RegExp;
5
+ /** True when input started with `/` but produced an invalid regex; UI may show a hint. */
6
+ invalid?: boolean;
7
+ }
8
+ /** Compiles a search term to a matcher.
9
+ * - `/foo/` → regex (case-insensitive by default; honors flags after the closing slash)
10
+ * - anything else → case-insensitive substring (existing behavior)
11
+ * - invalid regex → falls back to substring, sets `invalid: true` */
12
+ export declare function compileSearchPattern(term: string | null): SearchMatcher | null;
13
+ export type LogLevel = 'error' | 'warn' | 'info';
14
+ /** Detects the level of a log line by case-insensitive keyword priority:
15
+ * error (and synonyms) > warn > info. Used by the L-level filter. */
16
+ export declare function detectLogLevel(line: string): LogLevel;
17
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/utils/search.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAChC,sFAAsF;IACtF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;sEAGsE;AACtE,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,aAAa,GAAG,IAAI,CAe9E;AAED,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEjD;sEACsE;AACtE,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAMrD"}
@@ -0,0 +1,19 @@
1
+ /** Returns a copy of `names` sorted by the requested mode.
2
+ * - `'name'` → alphabetical
3
+ * - `'mem'` → highest mem first (string-parsed)
4
+ * - any other (treated as `'errors'`) → highest error count first */
5
+ export declare function sortServiceNames(names: string[], sortMode: string, statsMap: Record<string, {
6
+ cpu?: string;
7
+ mem?: string;
8
+ }>, procState: Record<string, {
9
+ errors?: number;
10
+ }>): string[];
11
+ /** Converts cumulative CPU seconds into a percentage of wall-clock time
12
+ * elapsed since the previous sample. */
13
+ export declare function calcCpuPercent(totalCpuSec: number, prevCpu: number, prevTime: number): number;
14
+ /** Hysteresis state machine for the "RAM pressure" banner.
15
+ * - turns on when usagePct ≥ highWatermark
16
+ * - turns off when usagePct < lowWatermark
17
+ * - stays as-is in the dead band between watermarks */
18
+ export declare function nextRamBannerVisibility(usagePct: number, previousVisible: boolean, highWatermark?: number, lowWatermark?: number): boolean;
19
+ //# sourceMappingURL=stats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/utils/stats.ts"],"names":[],"mappings":"AAAA;;;sEAGsE;AACtE,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,EACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EACxD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAC7C,MAAM,EAAE,CAQV;AAED;yCACyC;AACzC,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAI7F;AAED;;;wDAGwD;AACxD,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,OAAO,EACxB,aAAa,SAAK,EAClB,YAAY,SAAK,GAChB,OAAO,CAIT"}
package/dist/utils.d.ts CHANGED
@@ -1,42 +1,11 @@
1
- import type { ServiceConfig } from './config/types.js';
2
- export declare function parseEnvFile(filePath: string, baseEnv?: Record<string, string>): Record<string, string>;
3
- /** Hysteresis state machine for the "RAM pressure" banner.
4
- * Returns the next visibility given the current sample and previous visibility.
5
- * - turns on when usagePct > highWatermark
6
- * - turns off when usagePct < lowWatermark
7
- * - stays as-is in the dead band between watermarks */
8
- export declare function nextRamBannerVisibility(usagePct: number, previousVisible: boolean, highWatermark?: number, lowWatermark?: number): boolean;
9
- /** Returns the env record with values redacted to *** for keys that look
10
- * secret-ish (token / password / secret / key / auth). Case-insensitive. */
11
- export declare function redactSecrets(env: Record<string, string> | undefined): Record<string, string>;
12
- export type LogLevel = 'error' | 'warn' | 'info';
13
- /** Detects the level of a log line by case-insensitive keyword priority:
14
- * error (and synonyms) > warn > info. Used by the L-level filter. */
15
- export declare function detectLogLevel(line: string): LogLevel;
16
- export interface SearchMatcher {
17
- test: (line: string) => boolean;
18
- /** Set when the input was a vim-style /pattern/flags — used to drive highlighting. */
19
- regex?: RegExp;
20
- /** True when input started with `/` but produced an invalid regex; UI may show a hint. */
21
- invalid?: boolean;
22
- }
23
- /** Compiles a search term to a matcher.
24
- * - `/foo/` → regex (case-insensitive by default; honors flags after the closing slash)
25
- * - anything else → case-insensitive substring (existing behavior)
26
- * - invalid regex → falls back to substring, sets `invalid: true` */
27
- export declare function compileSearchPattern(term: string | null): SearchMatcher | null;
28
- export declare function fmtUptime(ms: number): string;
29
- export declare function needsInstall(fullCwd: string): boolean;
30
- export declare function writeInstallStamp(fullCwd: string): void;
31
- export declare function sortServiceNames(names: string[], sortMode: string, statsMap: Record<string, {
32
- cpu?: string;
33
- mem?: string;
34
- }>, procState: Record<string, {
35
- errors?: number;
36
- }>): string[];
37
- export declare function groupByPhase(services: ServiceConfig[]): Record<number, ServiceConfig[]>;
38
- export declare function buildProcessArgs(svc: ServiceConfig): string[];
39
- export declare function buildProcessEnv(svc: ServiceConfig, baseEnv: Record<string, string>): Record<string, string>;
40
- export declare function calcCpuPercent(totalCpuSec: number, prevCpu: number, prevTime: number): number;
41
- export declare const tagColors: string[];
1
+ export { parseEnvFile } from './utils/env.js';
2
+ export { fmtUptime } from './utils/format.js';
3
+ export { compileSearchPattern, detectLogLevel } from './utils/search.js';
4
+ export type { SearchMatcher, LogLevel } from './utils/search.js';
5
+ export { redactSecrets } from './utils/redact.js';
6
+ export { needsInstall, writeInstallStamp } from './utils/install-stamp.js';
7
+ export { buildProcessArgs, buildProcessEnv } from './utils/process-args.js';
8
+ export { sortServiceNames, calcCpuPercent, nextRamBannerVisibility } from './utils/stats.js';
9
+ export { groupByPhase } from './utils/phases.js';
10
+ export { tagColors } from './utils/colors.js';
42
11
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIvD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAiB3G;AAID;;;;wDAIwD;AACxD,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,OAAO,EACxB,aAAa,SAAK,EAClB,YAAY,SAAK,GAChB,OAAO,CAIT;AAID;6EAC6E;AAC7E,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAO7F;AAID,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEjD;sEACsE;AACtE,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAMrD;AAID,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAChC,sFAAsF;IACtF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;sEAGsE;AACtE,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,aAAa,GAAG,IAAI,CAe9E;AAID,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAU5C;AAID,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CASrD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAKvD;AAID,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,EACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EACxD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAC7C,MAAM,EAAE,CAQV;AAID,wBAAgB,YAAY,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,CAMvF;AAID,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,EAAE,CAK7D;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAU3G;AAID,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAI7F;AAID,eAAO,MAAM,SAAS,UAIrB,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACzE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC7F,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gachlab/devup",
3
- "version": "0.5.0",
3
+ "version": "0.7.1",
4
4
  "description": "Dev stack runner with TUI, lazy proxy, and reverse proxy support",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",