From bfd680490fbe9ddcd193428b5f9e234d2e580134 Mon Sep 17 00:00:00 2001 From: Yunfei He Date: Sat, 30 May 2026 23:32:22 +0800 Subject: [PATCH] refactor(runtime)!: rename useAppContext() to useApp() (full Ink alignment) (#73) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #69 added `useAppContext()` as a Vue-native rename of Ink's `useApp()`, qualified to avoid reading as the Vue application instance. On reflection the "Context" suffix borrowed the name of an internal grab-bag context and slightly mislabels the hook — it returns app lifecycle controls, not that context. The collision worry doesn't hold up: Vue has no `useApp()`, the returned `{ exit, waitUntilRenderFlush }` is clearly not the Vue app instance, and "App" in vue-tui already means the `TuiApp` from `createApp()`. Rename to `useApp()` for full Ink fidelity (same name + same shape), and drop the now-defunct "App composable" entry from ink-divergences.md — it ceases to be a divergence. Internal context cleanup (the grab-bag `AppContext` + the `StdinContext` duplication) is intentionally out of scope here, tracked separately. BREAKING CHANGE: `useAppContext()` is renamed to `useApp()`. Replace `const { exit } = useAppContext()` with `const { exit } = useApp()`. Co-authored-by: Claude Opus 4.8 --- .agents/docs/ink-divergences.md | 10 ----- README.md | 12 ++--- examples/coding-agent/src/App.vue | 4 +- examples/flappy-bird/src/App.vue | 4 +- .../lifecycle/error-handling.test.tsx | 8 ++-- .../integration/lifecycle/exit.test.tsx | 44 +++++++++---------- .../integration/lifecycle/wait-flush.test.tsx | 16 +++---- ...exit-on-exit-with-error-value-property.tsx | 4 +- .../pty/fixtures/exit-on-exit-with-error.tsx | 4 +- .../pty/fixtures/exit-on-exit-with-result.tsx | 4 +- .../exit-on-exit-with-value-object.tsx | 4 +- .../integration/pty/fixtures/exit-on-exit.tsx | 4 +- .../fixtures/exit-raw-on-exit-with-error.tsx | 4 +- .../pty/fixtures/exit-raw-on-exit.tsx | 4 +- .../pty/fixtures/exit-with-static.tsx | 4 +- .../fixtures/fullscreen-no-extra-newline.tsx | 4 +- .../pty/fixtures/issue-442-full-height.tsx | 4 +- .../fixtures/issue-450-fixture-helpers.tsx | 6 +-- .../use-animation-interactive-false-exit.tsx | 4 +- .../use-animation-non-interactive-exit.tsx | 4 +- .../pty/fixtures/use-input-ctrl-c.tsx | 4 +- .../fixtures/use-input-discrete-priority.tsx | 4 +- .../pty/fixtures/use-input-kitty.tsx | 4 +- .../pty/fixtures/use-input-many.tsx | 4 +- .../pty/fixtures/use-input-multiple.tsx | 4 +- .../integration/pty/fixtures/use-input.tsx | 4 +- .../integration/pty/fixtures/use-paste.tsx | 6 +-- .../integration/pty/fixtures/use-stdout.tsx | 4 +- .../integration/public-api.test.ts | 2 +- .../integration/render-to-string.test.tsx | 6 +-- packages/runtime/README.md | 2 +- packages/runtime/src/composables/useApp.ts | 23 ++++++++++ .../runtime/src/composables/useAppContext.ts | 27 ------------ packages/runtime/src/index.ts | 2 +- packages/runtime/src/render-to-string.ts | 2 +- packages/runtime/src/render.ts | 6 +-- 36 files changed, 121 insertions(+), 135 deletions(-) create mode 100644 packages/runtime/src/composables/useApp.ts delete mode 100644 packages/runtime/src/composables/useAppContext.ts diff --git a/.agents/docs/ink-divergences.md b/.agents/docs/ink-divergences.md index 5b7556d..1af8141 100644 --- a/.agents/docs/ink-divergences.md +++ b/.agents/docs/ink-divergences.md @@ -31,16 +31,6 @@ deliberate. Divergences fall into a few kinds: - **Why:** mirrors Vue's own `createApp` mental model — a Vue developer expects an app object they mount, not a one-shot render call. -### App composable — `useAppContext()` instead of `useApp()` - -- **Ink:** `useApp()` returns `{ exit, waitUntilRenderFlush }` — stdin/stdout/stderr are - separate hooks (`useStdin`/`useStdout`/`useStderr`), not part of it. -- **vue-tui:** `useAppContext()` returns the same `{ exit, waitUntilRenderFlush }`, with - streams on those same peer composables. -- **Why:** only the name differs — `useApp` reads as "the Vue application instance" - (`createApp`, `app.mount`), so vue-tui qualifies it as `useAppContext`. The shape is - identical to Ink; a naming divergence, not a surface one. - ### Named type / prop re-exports - **Ink:** re-exports its component prop types plus a few data/handle types: diff --git a/README.md b/README.md index b727872..ca1d5e1 100644 --- a/README.md +++ b/README.md @@ -83,11 +83,11 @@ useInput((input) => { ## Packages -| Package | Description | -| -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| [`@vue-tui/runtime`](https://www.npmjs.com/package/@vue-tui/runtime) | The core framework — Vue 3 renderer for the terminal with components (`Box`, `Text`, `Static`, etc.), composables (`useInput`, `useFocus`, `useAppContext`, etc.), and yoga-based flexbox layout | -| [`@vue-tui/cli`](https://www.npmjs.com/package/@vue-tui/cli) | Development tool — `vue-tui dev` starts your app with Vite-powered HMR | -| [`@vue-tui/testing`](https://www.npmjs.com/package/@vue-tui/testing) | Test harness — render in an isolated fake terminal, simulate input, assert output frame by frame | +| Package | Description | +| -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [`@vue-tui/runtime`](https://www.npmjs.com/package/@vue-tui/runtime) | The core framework — Vue 3 renderer for the terminal with components (`Box`, `Text`, `Static`, etc.), composables (`useInput`, `useFocus`, `useApp`, etc.), and yoga-based flexbox layout | +| [`@vue-tui/cli`](https://www.npmjs.com/package/@vue-tui/cli) | Development tool — `vue-tui dev` starts your app with Vite-powered HMR | +| [`@vue-tui/testing`](https://www.npmjs.com/package/@vue-tui/testing) | Test harness — render in an isolated fake terminal, simulate input, assert output frame by frame | ## Examples @@ -116,7 +116,7 @@ useInput((input) => { | `useInput(handler, opts?)` | Handle keyboard input — receives `(input, key)` with modifier and arrow key detection | | `useFocus(opts?)` | Component-level focus — returns `{ isFocused, focus }` | | `useFocusManager()` | App-level focus control — `focusNext()`, `focusPrevious()`, `focus(id)` | -| `useAppContext()` | App context — `{ exit(error?), waitUntilRenderFlush() }` | +| `useApp()` | App lifecycle — `{ exit(error?), waitUntilRenderFlush() }` | | `useTerminalSize()` | Reactive terminal dimensions — `{ columns, rows }` | | `useStdin()` | Access stdin stream and raw mode control | | `useStdout()` | Write directly to stdout | diff --git a/examples/coding-agent/src/App.vue b/examples/coding-agent/src/App.vue index b4a7c76..80c95aa 100644 --- a/examples/coding-agent/src/App.vue +++ b/examples/coding-agent/src/App.vue @@ -1,6 +1,6 @@