Files
vue-tui/packages/cli
Yunfei He 43eda7aa77 fix(cli): serialize extractBundle to prevent concurrent outDir race (#174)
* fix(cli): serialize extractBundle to prevent concurrent outDir race

extractBundle() wipes (rm) then repopulates (mkdir + writeFile) the shared
outDir in place, and dev.ts calls it from two unsynchronized sources — the
vue-tui:request-reload hot handler and the 500ms crash-respawn interval. When
two calls overlap, a second call's rm() can delete the tree a first call is
mid-writeFile into (ENOENT/EINVAL/ENOTEMPTY), or leave a torn, partially
populated dir that the child then loads.

Serialize extractions through a single module-level in-flight promise chain so
concurrent callers queue instead of racing the shared outDir. The internal
chain swallows errors so one failed run can't permanently wedge the queue,
while each caller still receives the real result/rejection. dev.ts is left
untouched; the external contract (args, output layout) is unchanged.

Adds a test that reproduces the race with staggered concurrent calls: red on
origin/main (rejects with EINVAL/ENOENT/ENOTEMPTY), green with the fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(cli): slim extractBundle race test to fit CI timeout

The race test timed out at 5042ms on the 4-core ubuntu CI runner (vitest's
default 5s testTimeout) — it wrote 200 files x ~8KB across 20 staggered
concurrent calls, ~4000 serial ~8KB writes once extractBundle is serialized.

The race window is driven by the NUMBER of files in the write loop and the
staggered starts (more chances for an overlapping rm to interleave a
writeFile), not by file size. So shrink each file's payload from 8KB to 32
bytes to slash write time, keep FILE_COUNT=200, and trim CALLS 20->16 (the
minimum that still reds reliably). Also add an explicit 30s per-test timeout
for comfortable CI headroom.

Verified: green 5x consecutively (~410ms test time locally, ~1.4% of the
timeout); still red 3x on origin/main with the race signature
(EINVAL/ENOENT/ENOTEMPTY). Assertions unchanged in spirit (none reject; final
dir holds the complete file set). Production code untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 20:35:41 +08:00
..

@vue-tui/cli

Early stage — under active development. Bug reports welcome, but not recommended for production use yet.

Development server for vue-tui — Vite-powered HMR for Vue 3 terminal apps.

npm version npm downloads

Why

  • Terminal HMR — edit a .vue file, see the terminal update instantly
  • Works with your Vite config — just run vue-tui dev in a project with index.html and your existing Vite plugins
  • Crash recovery — auto-restarts the process after a crash

Built on Vite's bundledDev mode. Bundles your vue-tui app into a single Node.js process with hot module replacement — the same edit-save-see loop you get with Vite on the web, but for TUI development.

Install

npm install -D @vue-tui/cli

Usage

vue-tui dev

Starts a Vite dev server in bundledDev mode, builds your app, and runs it in a managed child process. Most file changes are applied via HMR; changes that require a full reload restart the process automatically.

package.json script

{
  "scripts": {
    "dev": "vue-tui dev"
  }
}

License

MIT