feat(runtime)!: narrow useStdin to Ink's public surface; name composable returns UseXReturn (#79)
useStdin() returned the full internal StdinContext (8 members incl. the raw-mode
ref-counting primitives acquireRawMode/releaseRawMode, setBracketedPasteMode, and
internal_eventEmitter/internal_exitOnCtrlC). Ink's useStdin() returns only its PublicProps
— { stdin, setRawMode, isRawModeSupported } — keeping the rest on the internal context,
reached via the internal useStdinContext()/inject. Verified against Ink 7.0.4
(src/hooks/use-stdin.ts:10, src/components/StdinContext.ts).
- Narrow useStdin(): UseStdinReturn (the 3 public fields). The full StdinContext stays
internal, reached by useInput/useFocus/usePaste via inject(StdinContextKey) — the runtime
object is unchanged, only the public type narrows (mirrors Ink's type-level narrowing).
- Name every stdio/app composable return type per VueUse's UseXReturn convention and export
them: UseStdinReturn, UseStdoutReturn, UseStderrReturn, UseAppReturn (shapes byte-identical
to Ink's StdinProps/StdoutProps/StderrProps/AppProps). vue-tui reserves XProps for component
props (BoxProps, via ExtractPublicPropTypes), so composable returns use UseXReturn — the
Vue-community-idiomatic name.
- Unify the two pre-existing return types onto the same convention:
AnimationResult → UseAnimationReturn, UseBoxMetricsResult → UseBoxMetricsReturn.
- Type-level test (public-types.test-d.ts) locks the shapes and asserts useStdin()'s public
return excludes the internal members.
- Docs: trim the type-reexport divergence area to genuine divergences (fold
RenderOptions/Instance → MountOptions/TuiApp into createApp; keep DOMElement → TuiNode);
drop the AppProps/StdinProps/StdoutProps/StderrProps "N/A" entry — those Ink names are the
hook return types, now mirrored as UseXReturn (recorded under Framework idioms). Supersedes #77.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,13 +4,15 @@
|
||||
// framework-neutral data shapes under stable names. These names (BoxProps, TextProps,
|
||||
// …, WindowSize, CursorPosition) have nothing to do with React vs Vue — a <Box> has
|
||||
// props in Vue exactly as in React — so vue-tui re-exports them too, letting consumers
|
||||
// name a component's props the same way they would in Ink. See
|
||||
// `.agents/docs/ink-divergences.md` ("Named type / prop re-exports").
|
||||
// name a component's props the same way they would in Ink. This is parity, not a
|
||||
// divergence, so it is deliberately absent from `.agents/docs/ink-divergences.md` (which
|
||||
// records only divergences); this test is the guard that the names stay aligned.
|
||||
//
|
||||
// These assertions are erased at runtime; the real gate is `tsc --noEmit` (the package's
|
||||
// `check:type` script). This file is named `*.test-d.ts` on purpose so vitest does NOT
|
||||
// pick it up as a runtime test (its include is `*.test.ts`), while tsc still checks it.
|
||||
import { expectTypeOf } from "vite-plus/test";
|
||||
import { useApp, useStdin, useStdout, useStderr } from "@vue-tui/runtime";
|
||||
import type {
|
||||
BoxProps,
|
||||
TextProps,
|
||||
@@ -19,6 +21,10 @@ import type {
|
||||
NewlineProps,
|
||||
WindowSize,
|
||||
CursorPosition,
|
||||
UseAppReturn,
|
||||
UseStdinReturn,
|
||||
UseStdoutReturn,
|
||||
UseStderrReturn,
|
||||
} from "@vue-tui/runtime";
|
||||
|
||||
// Prop types carry their component's real, declared props.
|
||||
@@ -36,3 +42,36 @@ expectTypeOf<NewlineProps["count"]>().toEqualTypeOf<number | undefined>();
|
||||
// Framework-neutral data shapes, mirrored from Ink exactly.
|
||||
expectTypeOf<WindowSize>().toEqualTypeOf<{ readonly columns: number; readonly rows: number }>();
|
||||
expectTypeOf<CursorPosition>().toEqualTypeOf<{ x: number; y: number }>();
|
||||
|
||||
// Composable return types: named per VueUse's `UseXReturn` convention, and shape-locked to
|
||||
// Ink's public hook returns. useStdin() in particular must expose ONLY Ink's `PublicProps`
|
||||
// (stdin/setRawMode/isRawModeSupported) — never the internal raw-mode/paste controller
|
||||
// (acquireRawMode/releaseRawMode/setBracketedPasteMode/internal_*), which the framework's
|
||||
// own composables reach via inject(StdinContextKey).
|
||||
expectTypeOf<UseStdinReturn>().toEqualTypeOf<{
|
||||
readonly stdin: NodeJS.ReadStream;
|
||||
readonly setRawMode: (mode: boolean) => void;
|
||||
readonly isRawModeSupported: boolean;
|
||||
}>();
|
||||
expectTypeOf<ReturnType<typeof useStdin>>().toEqualTypeOf<UseStdinReturn>();
|
||||
expectTypeOf<keyof ReturnType<typeof useStdin>>().toEqualTypeOf<
|
||||
"stdin" | "setRawMode" | "isRawModeSupported"
|
||||
>();
|
||||
|
||||
expectTypeOf<UseStdoutReturn>().toEqualTypeOf<{
|
||||
readonly stdout: NodeJS.WriteStream;
|
||||
readonly write: (data: string) => void;
|
||||
}>();
|
||||
expectTypeOf<ReturnType<typeof useStdout>>().toEqualTypeOf<UseStdoutReturn>();
|
||||
|
||||
expectTypeOf<UseStderrReturn>().toEqualTypeOf<{
|
||||
readonly stderr: NodeJS.WriteStream;
|
||||
readonly write: (data: string) => void;
|
||||
}>();
|
||||
expectTypeOf<ReturnType<typeof useStderr>>().toEqualTypeOf<UseStderrReturn>();
|
||||
|
||||
expectTypeOf<UseAppReturn>().toEqualTypeOf<{
|
||||
readonly exit: (errorOrResult?: unknown) => void;
|
||||
readonly waitUntilRenderFlush: () => Promise<void>;
|
||||
}>();
|
||||
expectTypeOf<ReturnType<typeof useApp>>().toEqualTypeOf<UseAppReturn>();
|
||||
|
||||
Reference in New Issue
Block a user