Commit Graph

19 Commits

Author SHA1 Message Date
Yunfei He 90dc89272e fix(ci): include runtime and testing unit tests in vp run ci
The ci graph's test:integration task runs `vp run -r test:integration`, but
that script only existed in runtime-tests, so `vp run -r` silently skipped
packages/runtime (11 files, 309 tests) and packages/testing (2 files, 7 tests)
— their unit tests never ran in CI.

Give both packages a test:integration script (= vp test) and make their `test`
compose it, mirroring runtime-tests. `vp run -r test:integration` now covers
all three packages. PTY stays its own branch (no double-run).

Verified: `CI=true vp run ci` on a fresh checkout runs runtime (309) + testing
(7) + runtime-tests (756), exit 0.

Reported-by: @reviewer on PR #25
2026-05-29 16:54:13 +08:00
Yunfei He 1d6c47ca88 feat(scripts): add check:type running real tsc per package
Each package gets check:type = `tsc --noEmit` (under its own tsconfig); root
check:type = `vp run -r check:type` fans out across the workspace. Unlike vp's
tsgolint-based type-aware path, this is the standard TypeScript compiler, so it
honors each tsconfig's real project semantics.

Additive only here — vp lint still carries typeCheck; the switch-over and ready
rewiring land in the next commit. Note: testing and runtime-tests resolve
@vue-tui/runtime types from its built dist, so check:type requires a prior
build.
2026-05-29 16:54:13 +08:00
Yunfei He 6ca8990270 refactor(scripts): restructure workspace scripts into check:* / test:* families
Replace the opaque `vp check` bundling and the ad-hoc `ready` chain (which
shelled out via `cd ... && pnpm ...`) with explicit, composable named scripts.

Root delegates; category splits live in the package that owns them:

  root: check:fmt / check:lint / check:fixtures / test / build / ready
  runtime-tests: test = test:integration + test:pty; check:fixtures

`ready` now composes the named scripts in dependency order (fmt, lint, build,
fixtures, test) — build runs before check:fixtures and test:pty, which need
the built dist. Drop the broken root `dev` (referenced a non-existent website
package) and the redundant per-package `check` scripts (fmt/lint already run
workspace-wide from root). Renames: pty-test -> test:pty, typecheck:fixtures
-> check:fixtures.
2026-05-29 16:54:13 +08:00
Yunfei He fb1f6d33d4 refactor(config): drop per-package lint/fmt blocks redundant with root
The root vite.config.ts lint/fmt settings cascade into every workspace
package, and a package-level lint block merges with — rather than replaces —
the root options. So the `lint.options { typeAware, typeCheck }` and the empty
`fmt: {}` repeated in runtime, testing, and runtime-tests only restated what
each package already inherits.

Remove them. runtime-tests keeps just its `ignorePatterns` (the one genuine
per-package override); typeAware/typeCheck now come from root via the merge.
Verified with `vp check`: no lint or typecheck regression, and the PTY
fixtures stay excluded from lint.
2026-05-29 16:54:13 +08:00
Yunfei He 1f871e1ba5 chore: bump all packages to 0.0.2
Bump @vue-tui/runtime, @vue-tui/cli, and @vue-tui/testing from 0.0.1 to 0.0.2.
2026-05-28 01:10:20 +08:00
Yunfei He 8209f8440b docs: write/optimize READMEs for all published packages
- @vue-tui/runtime: rewrite with pitch, badges, SFC+shallowRef example,
  accurate component/composable tables, app lifecycle examples
- @vue-tui/cli: new README documenting vue-tui dev, HMR, crash recovery
- @vue-tui/testing: rewrite with @testing-library positioning, correct
  async render API, cleanup globals:true requirement
- Add early-stage warning to all sub-packages (matching root README)
- Fix CLI package.json: add license field, correct description

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 16:08:48 +08:00
Yunfei He 72cf46987c chore: optimize package.json descriptions for npm discoverability
Improve descriptions across all packages to include key differentiators
(Yoga flexbox, AI agent, React Ink lineage) and rename workspace root
from vue-tui to vue-tui-monorepo to avoid confusion with the taken npm name.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 14:39:24 +08:00
Yunfei He 3422e6edc1 feat: stdin.ref/unref, raw mode default false, conditional listener, maxListeners
- stdin.ref() on raw mode enable, stdin.unref() on disable
- setEncoding("utf8") on raw mode enable
- Raw mode default changed from true to false (hooks acquire it)
- useStdin().setRawMode routed through ref-counted controller
- Stdin listeners attached only when raw mode is active
- EventEmitter maxListeners set to Infinity

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 22:22:58 +08:00
Yunfei He 05c4dd5076 feat: add beforeExit natural unmount + stdout write barrier
Register process.once('beforeExit') in waitUntilExit() so TUI apps
that finish naturally (no explicit exit/unmount) clean up before the
event loop drains. Add stdout write barrier in resolveExit() to ensure
all output is flushed before settling the exit promise.

Update testing render helper to await the additional async tick
introduced by the write barrier so early-error detection still works.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 22:18:56 +08:00
Yunfei He 3ee01dc278 feat: add patchConsole, waitUntilRenderFlush, onRender, and maxFps
Add four behavioral surfaces to the runtime:

- patchConsole (default: true): intercepts console.* methods to route
  output through writeToStdout/writeToStderr, preventing frame corruption.
  Disabled in debug mode. Restored before Vue cleanup on teardown.
- waitUntilRenderFlush(): flushes pending throttled renders and waits
  for the stdout write barrier, exposed on TuiApp and testing RenderResult.
- onRender callback: fires after each commit with { renderTime } in ms.
- maxFps option: overrides the scheduler's default 32ms throttle interval
  with 1000/maxFps. The scheduler now accepts a throttleMs option and
  exposes hasPending() for flush coordination.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 15:54:18 +08:00
Yunfei He f51079a5ea feat: rewrite stdin pipeline with input-parser, exitOnCtrlC via \x03
- Replace data event with readable + input-parser state machine
- Intercept \x03 in input pipeline (not process SIGINT)
- useInput now uses parse-keypress for semantic key mapping
- 20ms pending escape flush timer matching Ink
- Esc focus reset in input pipeline
- Delete old key-parser.ts (replaced by input-parser + parse-keypress)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 14:04:39 +08:00
Yunfei He 1106be867b feat: add error boundary with onErrorCaptured to catch descendant errors
Wrap user root component in an InternalErrorBoundary that catches all
descendant errors (setup, render, lifecycle) via onErrorCaptured and
routes them through exit(error). This prevents yoga WASM state corruption
that occurred when errors propagated uncaught during Vue's render phase.

- Add ErrorOverview component for rendering error frames
- Replace try-catch around mount with onErrorCaptured boundary
- Update testing render() to detect early exit errors
- Convert 3 todo tests to active tests (nested setup, unhandledRejection, post-mount)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 13:48:23 +08:00
Yunfei He bcfdaddec7 feat: exit() accepts result value, waitUntilExit resolves with it
Change exit(error?: Error) to exit(errorOrResult?: unknown). When an
Error is passed, waitUntilExit rejects; otherwise it resolves with the
value. This matches Ink's behavior where exit("hello") resolves the
promise with "hello".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 00:10:52 +08:00
Yunfei He 5e54e5742d refactor: replace ref() with shallowRef() in all test files
AGENTS.md requires shallowRef by default. All test state uses
reassignment (not mutation), so shallowRef is correct.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 23:28:06 +08:00
Yunfei He 0209d5b5aa test: port Ink text tests (13 passing, 4 skipped)
Adds 17 text tests from Ink: color (standard/hex/rgb/ansi256),
background color, dim, bold, inversion, reactive remeasure, and
edge cases. 4 tests skipped due to null-children yoga crash and
constructor text lookup bug.

Also fixes lastFrame() treating empty-string frames as undefined
(Codex review feedback) and adds strip-ansi dev dependency.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 21:39:10 +08:00
Yunfei He 22ecbe0f80 test: port Ink layout tests (157 passing, 21 known failures)
Translates flex, direction, wrap, align, justify, gap, padding,
margin, width-height, position, display, and overflow tests from
Ink. Adds trimLines mode and trailing-newline strip to test helper.
Fixes Box type for alignContent (space-between/around/evenly) and
alignSelf (stretch/baseline).

21 tests fail due to behavioral differences (overflow clipping,
percentage dimensions, relative position offsets, align-content
space-* variants). These represent real gaps to investigate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 21:24:31 +08:00
Yunfei He 5a3de85079 feat(testing): add raw frame access via lastFrame({ raw: true })
Stores raw (untrimmed) frames internally. lastFrame() still trims
by default for backward compat. lastFrame({ raw: true }) returns
the untrimmed output for layout tests asserting exact widths.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 20:37:01 +08:00
Yunfei He ae33947c37 chore: prepare v0.0.1 release
- Bump all packages to 0.0.1
- Add publishConfig.access: public to @vue-tui/cli
- Disable tsgo for dts generation (missing native-preview dep)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 22:58:29 +08:00
Yunfei He 71c517b79f feat(testing): test harness for @vue-tui/runtime
Provides render() for integration testing — async with auto-flush,
trimmed frames, fake terminal with resize(), stdin.write() with
auto-flush, and auto-cleanup via afterEach.

Exports: render, cleanup, RenderResult, RenderOptions, Terminal

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 18:13:47 +08:00