@gachlab/devup 0.3.0 → 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/CHANGELOG.md CHANGED
@@ -5,6 +5,35 @@ All notable changes to `@gachlab/devup` are documented here.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.4.0] — 2026-05-21
9
+
10
+ Polish + standalone CLI release. Eight focused improvements landed as a single PR with one commit per issue.
11
+
12
+ ### Added
13
+ - **`devup --version` / `-v` and `devup --help` / `-h`** (#6). Both short-circuit before any config loading and exit `0`. Version is read from `package.json` at runtime so dev (via tsx) and the published tarball both report the right number.
14
+ - **Standalone subcommands** (#17): `devup logs <service> [--follow|-f]`, `devup install`, `devup status`, `devup help [<subcommand>]`. Reuse the persistent log files and the health-check primitives without launching the TUI. `logs --follow` tails new lines via `watchFile` and exits cleanly on SIGINT. `install` runs `npm install` across every service.cwd in parallel (max 4 at a time), skipping ones whose `.install-stamp` matches. `status` probes each service's healthCheck and prints a table.
15
+ - **Pre-flight check for `--watch-path` arguments** (#5). Before spawning a service, devup scans its args for `--watch` / `--watch-path` (both `--flag value` and `--flag=value` forms) and verifies every referenced path exists relative to the service's `cwd`. Missing paths mark the service `crashed` with one grouped error line instead of letting Node 22 die with a cryptic message after a rebase that renamed directories.
16
+ - **Browser open respects proxy + TLS** (#10). Pressing `o` in the TUI now opens `https://<sub>.<domain>` when `--proxy` is active and the service has a route. Falls back to `http://localhost:<port>` otherwise. Honors `proxy.tls: false` by using `http://` on the subdomain.
17
+ - **Crash-loop badge** (#11). Services that exhausted their auto-restart budget (`status === 'crashed' && restarts >= MAX_RESTARTS`) now render with `✖` (red, bold), status label `looping`, and a `⚠ N need attention` counter in the stats panel header. Easy to spot in a long service list.
18
+ - **Fuzzy filter in `ServiceList` modal** (#18). All three picker modals (`f`, `r`, `o`) now accept typed characters to filter the list in real time. Backspace removes a character. First Esc clears the filter, second Esc closes the modal. Sub-second selection on stacks with 30+ services.
19
+ - **Contextual tips** (#22). At teachable moments the TUI shows a dim one-liner in the header bar (e.g. "tip: press / to search in logs" once logs exceed 1000 lines, or "tip: press r to restart" when a service crash-loops). Each tip shows at most once per session and auto-clears after 12 s. Priority order favors actionable tips (crash → search → filter).
20
+
21
+ ### Changed
22
+ - **`npm pkg fix` cleanup** (#7). `bin.devup` normalised to `dist/index.js` (no leading `./`), `repository.url` to `git+https://...`. New `prepack` script runs `npm pkg fix` on every publish so the warnings from 0.2.0 don't reappear.
23
+ - `ServiceList` footer hint updated: `type to filter ↑↓ navigate Enter select Esc clear/close`.
24
+ - README gets a new "CLI subcommands" section and additions to the Features list ("Pre-flight validation", "Subcommands").
25
+
26
+ ### Fixed
27
+ - Reordering inside the TUI key-binding handler so `Ctrl+F` (PgDn) never falls through to the filter modal (`f`). Same fix applied to other `Ctrl`-modified bindings.
28
+
29
+ ### Internals
30
+ - Exported `extractWatchPaths(args)` from `process/manager.ts` (handles `--watch X`, `--watch-path X`, `--watch=X`, `--watch-path=X`; ignores `--watch-path` followed by another flag; doesn't match unrelated flags like `--watcher`).
31
+ - Exported `isCrashLooped(st)` + `MAX_RESTARTS` constant from `tui/StatsPanel.tsx` for test reuse and to drive the crash-loop banner.
32
+ - Exported `buildServiceUrl(name, port, proxyActive, proxyOpts)` from `tui/App.tsx` for testability.
33
+ - New `src/tui/tips.ts` with a pure `pickTip(state)` function — easy to extend by appending to the priority list.
34
+ - New `src/orchestrator/subcommands.ts` with `detectSubcommand`, `runLogs`, `runInstall`, `runStatus`, `runHelp`.
35
+ - Test suite grown to ~274.
36
+
8
37
  ## [0.3.0] — 2026-05-21
9
38
 
10
39
  ### Added
@@ -106,6 +135,7 @@ Initial release.
106
135
  - Config file resolution order: `devup.config.ts` → `.js` → `.json`, with `--config <path>` override. TypeScript loaded via the `tsx` import hook.
107
136
  - CLI flags: `--only`, `--services`, `--skip`, `--lazy`/`--no-lazy`, `--timeout`, `--proxy`, `--proxy-host`, `--proxy-conf`, `--proxy-tls`/`--no-proxy-tls`, `--proxy-entrypoint`, `--config`.
108
137
 
138
+ [0.4.0]: https://github.com/gachlab/devup/releases/tag/0.4.0
109
139
  [0.3.0]: https://github.com/gachlab/devup/releases/tag/0.3.0
110
140
  [0.2.0]: https://github.com/gachlab/devup/releases/tag/0.2.0
111
141
  [0.1.1]: https://github.com/gachlab/devup/releases/tag/0.1.1
package/README.md CHANGED
@@ -20,6 +20,8 @@ Built with TypeScript 6, Ink (React for terminals), and zero test dependencies (
20
20
  - **npm install management** — automatic dependency installation with hash-based stamps to skip redundant installs
21
21
  - **Auto-restart with backoff** — crashed services restart automatically with exponential backoff (2s → 4s → 8s), max 3 attempts; manual restart resets the counter
22
22
  - **Port conflict detection** — checks if a port is already in use before starting a service; also validates lazy `port + 10000` collisions at config-load time
23
+ - **Pre-flight validation** — `--watch-path` arguments are checked against disk before spawn so a stale config after a rebase fails loudly instead of silently
24
+ - **Subcommands** — `devup logs <svc>`, `devup install`, `devup status` work without launching the TUI
23
25
 
24
26
  ## Quick start
25
27
 
@@ -239,6 +241,20 @@ When lazy mode is active (default), services not in `alwaysOn` start a TCP proxy
239
241
 
240
242
  The proxy config is only generated when `--proxy` is passed on the CLI. Only services with `health === 'up'` are included in the generated config.
241
243
 
244
+ ## CLI subcommands
245
+
246
+ ```
247
+ devup # launch the interactive TUI (default)
248
+ devup logs <service> [--follow] # print the persisted log file
249
+ devup install # parallel npm install across services
250
+ devup status # health-check every service in config
251
+ devup help [<subcommand>] # show usage
252
+ devup --version # print version
253
+ devup --help # print flag summary
254
+ ```
255
+
256
+ All subcommands need the project's `devup.config.ts` to be resolvable (use `--config <path>` to override).
257
+
242
258
  ## CLI flags
243
259
 
244
260
  ```
@@ -18,6 +18,7 @@ export interface CliArgs {
18
18
  logFile: boolean;
19
19
  logDir?: string;
20
20
  }
21
+ export declare const USAGE = "devup \u2014 terminal UI dev stack runner\n\nUsage: devup [options]\n\nService selection:\n --only apis | webs Start only APIs or only webs\n --services a,b,c Start only the named services\n --profile <name> Start the services in a named profile (see ROADMAP)\n --skip a,b,c Start everything except these\n --config <path> Use a custom config file\n\nLazy mode:\n --lazy Enable lazy mode (default)\n --no-lazy Start every service immediately\n --timeout <minutes> Idle timeout for lazy services. Default: 10\n\nReverse proxy:\n --proxy Enable proxy config generation\n --proxy-host <host> Override the target host (Docker/local)\n --proxy-conf <path> Override the generated config file path\n --proxy-tls Enable TLS in the generated config (default)\n --no-proxy-tls Disable TLS\n --proxy-entrypoint <n> Override entrypoint name (Traefik only)\n\nCI / scripting:\n --dry-run Print the resolved boot plan and exit\n --once Boot, wait for readiness, exit 0/1 (no TUI)\n --once-timeout <s> Max seconds to wait in --once mode. Default: 90\n\nLog files:\n --no-log-file Disable persistent log files\n --log-dir <path> Override log root (default: ~/.devup/logs)\n\nOther:\n -h, --help Show this help and exit\n -v, --version Show version and exit\n\nSee https://github.com/gachlab/devup for the full documentation.";
21
22
  export declare function parseCliArgs(argv: string[]): CliArgs;
22
23
  export declare function filterServices(services: ServiceConfig[], args: CliArgs, config?: Pick<DevStackConfig, 'profiles'>): ServiceConfig[];
23
24
  //# sourceMappingURL=cli.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/config/cli.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhE,MAAM,WAAW,OAAO;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAKD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CA0CpD;AAED,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,aAAa,EAAE,EACzB,IAAI,EAAE,OAAO,EACb,MAAM,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC,GACxC,aAAa,EAAE,CA6BjB"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/config/cli.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhE,MAAM,WAAW,OAAO;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAKD,eAAO,MAAM,KAAK,8gDAqC+C,CAAC;AAElE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CA0CpD;AAED,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,aAAa,EAAE,EACzB,IAAI,EAAE,OAAO,EACb,MAAM,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC,GACxC,aAAa,EAAE,CA6BjB"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChG,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAClE,YAAY,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChG,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAClE,YAAY,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC"}