{"version":3,"file":"index.cjs","names":[],"sources":["../../../src/server/constants.ts","../../../src/server/helpers.ts","../../../src/server/Terminal.ts","../../../src/server/factories.ts"],"sourcesContent":["// Server-terminals constants — the cursor and line-clear ANSI sequences the interactive `Terminal`\n// driver writes to redraw a field view IN PLACE, plus the copy the walk shows around those views:\n// the per-control format hints, the readline-fallback prompts, and the marks for a locked field and\n// an unavailable choice. UPPER_SNAKE, every member exported. Every sequence is built from the\n// console module's own `CSI` prefix, so no raw control character appears in source and this module\n// declares no second copy of that primitive.\n\nimport type { FieldControl } from '@orkestrel/form'\nimport { CSI } from '@orkestrel/console'\n\n/**\n * Holds the cursor-up sequence template (`ESC[{count}A`) —\n * {@link import('./helpers.js').renderCursorUp} interpolates the `{count}` placeholder with the\n * number of lines to climb. Kept as a template so the count stays out of the constant.\n */\nexport const CSI_UP = `${CSI}{count}A`\n\n/**\n * Hides the cursor (`ESC[?25l`) — written before the driver starts redrawing a prompt so the cursor\n * does not flicker across the view during an in-place re-render; paired with {@link CURSOR_SHOW}.\n */\nexport const CURSOR_HIDE = `${CSI}?25l`\n\n/** Shows the cursor (`ESC[?25h`) — restores the cursor after a prompt resolves / cancels (the {@link CURSOR_HIDE} pair). */\nexport const CURSOR_SHOW = `${CSI}?25h`\n\n/**\n * Erases from the cursor down to the end of the screen (`ESC[J`) — wipes the whole previous view,\n * which a `select` or `checkbox` can spread over several lines, in one write before the new view is\n * rendered, so a redraw never leaves orphaned rows behind.\n */\nexport const CLEAR_DOWN = `${CSI}J`\n\n/**\n * Holds the numbered-list prompt the non-TTY {@link import('./Terminal.js').Terminal} `select` fallback\n * appends — a piped (non-terminal) stream cannot navigate with arrow keys, so the choices are\n * printed numbered and the user types one number on a single readline line.\n */\nexport const FALLBACK_SELECT_HINT = 'Enter a number'\n\n/** Holds the comma-separated multi-select hint the non-TTY `checkbox` fallback shows (the user types one or more numbers). */\nexport const FALLBACK_CHECKBOX_HINT = 'Enter numbers separated by commas'\n\n/** Holds the hint the non-TTY `editor` fallback shows — a piped stream has no ctrl-d, so end of input finishes the block. */\nexport const FALLBACK_EDITOR_HINT = '(end of input finishes)'\n\n/** Holds the hint the non-TTY `confirm` fallback shows — a piped stream sends a whole line, so the answer is typed rather than pressed. */\nexport const FALLBACK_CONFIRM_HINT = '(y/n)'\n\n/**\n * Holds the format cue appended to a field's label for each control the walk reads as a line of text —\n * the terminal has no date picker, no color well, and no file chooser, so the accepted shape is\n * stated instead. A control with no entry needs none: `text` and `editor` accept any line,\n * `password` masks one, and `confirm`, `select`, and `checkbox` are answered by key rather than by\n * format. The form's own rules still decide whether the typed value is acceptable.\n */\nexport const CONTROL_HINTS: Readonly<Partial<Record<FieldControl, string>>> = Object.freeze({\n\tnumber: '(number)',\n\tdate: '(YYYY-MM-DD)',\n\ttime: '(HH:MM)',\n\tdatetime: '(YYYY-MM-DDTHH:MM)',\n\tcolor: '(#rrggbb)',\n\tfile: '(path)',\n})\n\n/** Holds the instruction a `file` field with `multiple` shows before its entries — one path per line, and a blank line ends the list. */\nexport const FILE_HINT = 'One path per line, blank to finish'\n\n/**\n * Holds the lead on the line listing an open `select`'s offered values, which a typed answer can\n * ignore.\n */\nexport const SUGGESTION_LEAD = 'Suggestions'\n\n/**\n * Holds the lead on the line listing the choices a `select` or `checkbox` shows but refuses, so a\n * reader sees why one is missing from the list it heads.\n */\nexport const UNAVAILABLE_LEAD = 'Unavailable'\n\n/** Holds the mark on a locked field's line — the walk renders its value and moves on, because the form refuses an edit there. */\nexport const LOCKED_MARK = '(locked)'\n\n/**\n * States what a field is told when the walk read an answer the control cannot hold — a word typed into a\n * `number`, an off-list value typed into an open `select` whose choice is refused. The value binds\n * as absence and this message is invalidated onto the field, so the walk re-asks it with the reason\n * on screen.\n */\nexport const REFUSAL_MESSAGE = 'Enter a value this field accepts'\n","// Pure helpers for the server terminal driver — every function here is exported and unit-tested.\n// The families here are all total: the stream-boundary guards that narrow `process.stdin` / any\n// injected stream without an assertion; the cursor math the driver uses to redraw a field view IN\n// PLACE (count a view's lines, build the cursor-up sequence, assemble the reposition-and-clear\n// prefix); and the projections and line renderers the whole-form walk needs that no reducer owns —\n// a control read as text, a value shown read-only, the choices a field actually offers, and the\n// group, locked, suggestion, unavailable, and numbered-list lines. The impure driver only feeds\n// bytes into the reducers and writes the strings these helpers build. The output boundary is\n// narrowed by the console module's own `isStreamTarget`, which this module does not redeclare.\n\nimport type { FieldChoice, FieldValue, FormField, TextField } from '@orkestrel/form'\nimport type { PromptTheme } from '@src/core'\nimport type { StylerInterface } from '@orkestrel/console'\nimport type { InputStreamInterface } from './types.js'\nimport { RETURN } from '@src/core'\nimport {\n\tCLEAR_DOWN,\n\tCONTROL_HINTS,\n\tCSI_UP,\n\tLOCKED_MARK,\n\tSUGGESTION_LEAD,\n\tUNAVAILABLE_LEAD,\n} from './constants.js'\nimport { isBoolean, isFunction, isNumber, isObject, isString } from '@orkestrel/contract'\n\n/**\n * Checks whether `value` is a usable {@link InputStreamInterface} — a record with callable `on` /\n * `off` `'data'` subscription methods. A total type guard: it never throws and returns `false` for\n * anything off-shape, so it narrows the one unavoidable input boundary (the real `process.stdin`,\n * or a fake TTY a test injects) to the exact slice the driver reads, never an assertion.\n *\n * @remarks\n * Only `on` / `off` are required (the irreducible event seam); `setRawMode` / `resume` / `pause` /\n * `isTTY` are optional on {@link InputStreamInterface}, so their absence does not disqualify a stream\n * — a piped, non-TTY stream is still a valid input, one the driver reads through the readline\n * fallback rather than raw mode.\n *\n * @param value - Any value crossing the boundary (a process stream, an injected fake, `unknown`)\n * @returns True if `value` has callable `on` and `off`; false otherwise\n */\nexport function isInputStream(value: unknown): value is InputStreamInterface {\n\treturn (\n\t\tisObject(value) &&\n\t\t'on' in value &&\n\t\tisFunction(value.on) &&\n\t\t'off' in value &&\n\t\tisFunction(value.off)\n\t)\n}\n\n/**\n * Checks whether `value` is a Node {@link NodeJS.ReadableStream} — a total structural guard\n * checking for the callable `read` / `pipe` / `on` that `node:readline`'s `createInterface`\n * requires as its `input`. The non-TTY fallback narrows the resolved input stream through this\n * before handing it to readline, never through an assertion, so a real piped `process.stdin` (or a\n * `PassThrough` a test injects) crosses into the readline boundary honestly. Never throws; returns\n * `false` for a minimal fake that isn't a full readable.\n *\n * @param value - The resolved input stream (or any value crossing the boundary)\n * @returns True if `value` has the readable methods readline needs; false otherwise\n */\nexport function isReadable(value: unknown): value is NodeJS.ReadableStream {\n\treturn (\n\t\tisObject(value) &&\n\t\t'read' in value &&\n\t\tisFunction(value.read) &&\n\t\t'pipe' in value &&\n\t\tisFunction(value.pipe)\n\t)\n}\n\n/**\n * Checks whether an input stream can be driven in raw mode — it reports `isTTY === true` and\n * exposes a callable `setRawMode`. The {@link import('./Terminal.js').Terminal} probes this to\n * choose its path: true selects the interactive raw-mode fields, with arrow-key navigation and a\n * live re-render; false selects the `node:readline` line-input fallback, because a piped or\n * non-terminal stream cannot enter raw mode. Total — never throws.\n *\n * @param input - The resolved {@link InputStreamInterface}\n * @returns True if the stream is a TTY with `setRawMode`; false otherwise\n */\nexport function supportsRawMode(input: InputStreamInterface): boolean {\n\treturn input.isTTY === true && isFunction(input.setRawMode)\n}\n\n/**\n * Counts the terminal lines a rendered prompt `view` occupies — one more than its newline count, so\n * a view with no newline is a single line and a view with N newlines spans N+1 lines. The basis of\n * the in-place re-render: the driver records the line count of the view it wrote so the next redraw\n * knows how far up to move the cursor before overwriting. Total; an empty string is one empty line.\n *\n * @param view - The rendered (possibly multi-line, possibly ANSI-styled) view string\n * @returns The number of lines the view spans (always at least 1)\n */\nexport function lineCount(view: string): number {\n\tlet lines = 1\n\tfor (const character of view) {\n\t\tif (character === '\\n') lines += 1\n\t}\n\treturn lines\n}\n\n/**\n * Returns the cursor-up control sequence that moves the cursor up `count` lines (`ESC[{count}A`),\n * or the empty string when `count` is zero or negative, because no movement is needed and `ESC[0A`\n * is a wasted write. The pure step the in-place re-render uses to climb back over the previous view\n * before clearing it. Total.\n *\n * @param count - How many lines to move the cursor up\n * @returns The `ESC[{count}A` sequence, or `''` when `count <= 0`\n */\nexport function renderCursorUp(count: number): string {\n\tif (count <= 0) return ''\n\treturn `${CSI_UP.replace('{count}', String(count))}`\n}\n\n/**\n * Returns the full reposition-and-clear prefix to write before re-rendering a prompt view in place\n * — given the line count of the previous view, it moves the cursor up over those lines, returns it\n * to column 0, and erases everything from there to the end of the screen, so the next view is drawn\n * on a clean region and a taller previous view leaves no orphaned rows. Pure; the driver writes\n * this immediately followed by the new view.\n *\n * @remarks\n * For the first render `previousLines` is `1` (the cursor sits on the line the prompt opened on) so\n * the prefix is a carriage return + clear-down — the prompt draws from the current line. For a\n * subsequent render it climbs `previousLines - 1` lines (the cursor is on the last line of the prior\n * view) before clearing. Keeping the math here (not in the driver) makes the re-render unit-testable\n * without a real terminal.\n *\n * @param previousLines - The line count of the view on screen (from {@link lineCount})\n * @returns The control-sequence prefix to write before the new view\n */\nexport function redrawPrefix(previousLines: number): string {\n\treturn `${renderCursorUp(previousLines - 1)}${RETURN}${CLEAR_DOWN}`\n}\n\n/**\n * Projects any field the walk reads as a line of text into the {@link TextField} the text reducer\n * takes — `text` itself, and the controls a terminal has no widget for: `number`, `date`, `time`,\n * `datetime`, `color`, and one `file` entry. The label carries that control's format cue from\n * {@link CONTROL_HINTS}, and a declared `default` becomes the line a bare return submits. The\n * projection carries no rule, because the authoritative form still evaluates the answer this line\n * binds; it exists only so one reducer covers every one of them.\n *\n * @param field - The field being read\n * @returns The text field the reducer renders for it\n *\n * @example\n * ```ts\n * fieldToText({ control: 'date', name: 'born', label: 'Birthday' })\n * // { control: 'text', name: 'born', label: 'Birthday (YYYY-MM-DD)' }\n * ```\n */\nexport function fieldToText(field: FormField): TextField {\n\tconst label = field.label ?? field.name\n\tconst hint = CONTROL_HINTS[field.control]\n\tconst seed = 'default' in field ? field.default : undefined\n\tconst text = isNumber(seed) ? String(seed) : seed\n\treturn {\n\t\tcontrol: 'text',\n\t\tname: field.name,\n\t\tlabel: hint === undefined ? label : `${label} ${hint}`,\n\t\t...(isString(text) ? { default: text } : {}),\n\t}\n}\n\n/**\n * Projects one held answer into the text a read-only line shows — a scalar as itself, a boolean as\n * `yes` / `no` (the word the confirm reducer commits), and a list joined by commas. Absence renders\n * as nothing, because a locked field nobody has answered has nothing to show.\n *\n * @param value - The answer the form holds for a field, or absence\n * @returns The text to render for it\n */\nexport function valueToText(value: FieldValue | undefined): string {\n\tif (value === undefined) return ''\n\tif (isString(value)) return value\n\tif (isNumber(value)) return String(value)\n\tif (isBoolean(value)) return value ? 'yes' : 'no'\n\treturn value.join(', ')\n}\n\n/**\n * Returns the choices a `select` or `checkbox` field actually offers — the form refuses a disabled\n * choice's value at every door, including a fill, so the walk never puts one in front of the\n * cursor. Pair with {@link filterDisabled} to tell the reader what was withheld.\n *\n * @param choices - The field's declared choices\n * @returns The choices the walk offers, in declared order\n */\nexport function filterEnabled(choices: readonly FieldChoice[]): readonly FieldChoice[] {\n\treturn choices.filter((choice) => choice.disabled !== true)\n}\n\n/**\n * Returns the choices a `select` or `checkbox` field shows but refuses — the complement of\n * {@link filterEnabled}, rendered by {@link renderUnavailableLine} above the list so a reader sees\n * why a declared choice is missing from it.\n *\n * @param choices - The field's declared choices\n * @returns The refused choices, in declared order\n */\nexport function filterDisabled(choices: readonly FieldChoice[]): readonly FieldChoice[] {\n\treturn choices.filter((choice) => choice.disabled === true)\n}\n\n/**\n * Renders the section header the walk writes when it enters a new field group, painted by the\n * `message` role.\n *\n * @param styler - The console styler that renders each role\n * @param theme - The resolved prompt theme\n * @param label - The group's declared label, falling back to its own name\n * @returns The rendered section header\n */\nexport function renderGroupHeader(\n\tstyler: StylerInterface,\n\ttheme: PromptTheme,\n\tlabel: string,\n): string {\n\treturn styler.render(theme.roles.message, label)\n}\n\n/**\n * Renders the read-only line a locked field shows — its label, the {@link LOCKED_MARK}, and the\n * answer the form already holds. The walk writes this instead of a prompt, because the field is\n * still validated and still submitted but must not be edited here.\n *\n * @param styler - The console styler that renders each role\n * @param theme - The resolved prompt theme\n * @param label - The field's label\n * @param value - The held answer, from {@link valueToText}\n * @returns The rendered line, with no trailing space when there is nothing to show\n */\nexport function renderLockedLine(\n\tstyler: StylerInterface,\n\ttheme: PromptTheme,\n\tlabel: string,\n\tvalue: string,\n): string {\n\tconst head = `${styler.render(theme.roles.muted, theme.icons.dot)} ${styler.render(theme.roles.message, label)} ${styler.render(theme.roles.hint, LOCKED_MARK)}`\n\treturn value.length === 0 ? head : `${head} ${styler.render(theme.roles.content, value)}`\n}\n\n/**\n * Renders the line listing an open select's offered values above its text prompt — a suggestion\n * list, because an open select admits an answer the list does not offer.\n *\n * @param styler - The console styler that renders each role\n * @param theme - The resolved prompt theme\n * @param choices - The choices the open select offers, from {@link filterEnabled}\n * @returns The rendered suggestion line\n */\nexport function renderSuggestionLine(\n\tstyler: StylerInterface,\n\ttheme: PromptTheme,\n\tchoices: readonly FieldChoice[],\n): string {\n\tconst values = choices.map((choice) => choice.value).join(', ')\n\treturn styler.render(theme.roles.hint, `${SUGGESTION_LEAD}: ${values}`)\n}\n\n/**\n * Renders the line naming the choices a field shows but refuses, written above the list the walk\n * drives.\n *\n * @param styler - The console styler that renders each role\n * @param theme - The resolved prompt theme\n * @param choices - The refused choices, from {@link filterDisabled}\n * @returns The rendered unavailable line\n */\nexport function renderUnavailableLine(\n\tstyler: StylerInterface,\n\ttheme: PromptTheme,\n\tchoices: readonly FieldChoice[],\n): string {\n\tconst labels = choices.map((choice) => choice.label).join(', ')\n\treturn styler.render(theme.roles.muted, `${UNAVAILABLE_LEAD}: ${labels}`)\n}\n\n/**\n * Renders the numbered choice list the non-TTY fallback prints — a piped stream cannot navigate\n * with arrow keys, so each offered choice is printed with the number the reader types back. One\n * line per choice, with no trailing newline.\n *\n * @param styler - The console styler that renders each role\n * @param theme - The resolved prompt theme\n * @param choices - The choices the walk offers, from {@link filterEnabled}\n * @returns The rendered list\n */\nexport function renderNumberedList(\n\tstyler: StylerInterface,\n\ttheme: PromptTheme,\n\tchoices: readonly FieldChoice[],\n): string {\n\treturn choices\n\t\t.map(\n\t\t\t(choice, index) =>\n\t\t\t\t`  ${styler.render(theme.roles.muted, `${String(index + 1)})`)} ${styler.render(theme.roles.content, choice.label)}`,\n\t\t)\n\t\t.join('\\n')\n}\n","import type {\n\tFieldChoice,\n\tFieldError,\n\tFieldValue,\n\tFormField,\n\tFormInterface,\n\tFormValues,\n} from '@orkestrel/form'\nimport type {\n\tCheckboxField,\n\tConfirmField,\n\tEditorField,\n\tFileField,\n\tPasswordField,\n\tSelectField,\n} from '@orkestrel/form'\nimport type { KeyEvent, PromptStep, PromptTheme, TerminalInterface } from '@src/core'\nimport type { StylerInterface } from '@orkestrel/console'\nimport type { StreamTargetInterface } from '@orkestrel/console/server'\nimport type { Interface } from 'node:readline'\nimport type { InputStreamInterface, TerminalOptions } from './types.js'\nimport {\n\tcreateCheckboxState,\n\tcreateConfirmState,\n\tcreateEditorState,\n\tcreateInputState,\n\tcreatePasswordState,\n\tcreatePromptTheme,\n\tcreateSelectState,\n\tNEWLINE,\n\tparseKey,\n\treduceCheckbox,\n\treduceConfirm,\n\treduceEditor,\n\treduceInput,\n\treducePassword,\n\treduceSelect,\n\trenderErrorLine,\n\trenderHintedHeader,\n\trenderPromptHeader,\n\tsanitizeDisplayText,\n\tTerminalError,\n} from '@src/core'\nimport { matchesAnswer, parseValue } from '@orkestrel/form'\nimport { createStyler } from '@orkestrel/console'\nimport { isStreamTarget } from '@orkestrel/console/server'\nimport { createInterface } from 'node:readline'\nimport { stdin, stdout } from 'node:process'\nimport {\n\tCURSOR_HIDE,\n\tCURSOR_SHOW,\n\tFALLBACK_CHECKBOX_HINT,\n\tFALLBACK_CONFIRM_HINT,\n\tFALLBACK_EDITOR_HINT,\n\tFALLBACK_SELECT_HINT,\n\tFILE_HINT,\n\tREFUSAL_MESSAGE,\n} from './constants.js'\nimport {\n\tfieldToText,\n\tfilterDisabled,\n\tfilterEnabled,\n\tisInputStream,\n\tisReadable,\n\tlineCount,\n\tredrawPrefix,\n\trenderGroupHeader,\n\trenderLockedLine,\n\trenderNumberedList,\n\trenderSuggestionLine,\n\trenderUnavailableLine,\n\tsupportsRawMode,\n\tvalueToText,\n} from './helpers.js'\n\n/**\n * Implements {@link TerminalInterface} for a human at this machine's keyboard — the interactive\n * form driver, and the only impure part of the terminal stack. {@link ask} walks one form's fields\n * in schema order, feeds raw-mode stdin bytes through `parseKey` into the matching pure reducer,\n * renders each returned view in place, binds every answer through the form's own `fill`, and\n * re-asks what the form refused. It owns no form logic: the schema, the rules, the values, and the\n * settlement all belong to the form it is given, and this class owns only raw mode, the cursor, and\n * the re-render.\n *\n * @remarks\n * See {@link TerminalInterface} for the driving contract. The walk itself:\n *\n * - **Controls and reducers.** `text`, `number`, `date`, `time`, `datetime`, `color`, and\n *   each `file` entry are read as one line of text through {@link fieldToText}, which appends that\n *   control's format cue to the label. `password`, `confirm`, `editor`, `select`, and `checkbox`\n *   each drive their own reducer. An open `select` is a suggestion list plus a typed line, because\n *   `open` means the answer need not come from the list.\n * - **The binding projects through `matchesAnswer`.** Every answer is filled as\n *   `fill(name, matchesAnswer(value) ? value : undefined)` after `parseValue` has coerced it to the\n *   control's own shape, so a bare return on a field with no default binds as absence and the\n *   form's `required` rule refuses it. A typed answer the control cannot hold binds as absence and\n *   invalidates the field, so the walk asks again with the reason on screen.\n * - **Visibility is honored.** A `hidden` field and a field in `form.disabled` are skipped; a\n *   `locked` field renders read-only; entering a new group writes its label as a section header.\n * - **Refusal re-asks.** After the walk the form is submitted. A refusal re-walks only the erroring\n *   fields the walk can edit and submits again. When every erroring field is one the walk cannot\n *   edit — hidden, locked, or disabled — the form is abandoned instead, because asking again could\n *   not change the answer.\n * - **Raw-mode leak-free.** Raw mode is entered once per field and always cleaned up: on submit, on\n *   cancel, on a throw, and when the form is abandoned under an active read.\n * - **Non-TTY fallback.** When `input` is not a TTY, the same walk runs over `node:readline` line\n *   input: `select` and `checkbox` print a numbered list, and `editor` reads to end of input.\n */\nexport class Terminal implements TerminalInterface {\n\treadonly #input: InputStreamInterface\n\treadonly #output: StreamTargetInterface\n\treadonly #styler: StylerInterface\n\treadonly #theme: PromptTheme\n\treadonly #handlers = new Map<object, (chunk: string | Uint8Array) => void>()\n\treadonly #queue: string[] = []\n\t#interface: Interface | undefined\n\t#taker: ((line: string | undefined) => void) | undefined\n\t#ended = false\n\n\tconstructor(options?: TerminalOptions) {\n\t\t// Resolve each stream through its guard: a present, well-shaped injected stream is used as is;\n\t\t// otherwise the real process stream — no assertion, and an absent option falls through.\n\t\tthis.#input = isInputStream(options?.input) ? options.input : stdin\n\t\tthis.#output = isStreamTarget(options?.output) ? options.output : stdout\n\t\tthis.#styler = createStyler()\n\t\tthis.#theme = createPromptTheme(options?.theme)\n\t}\n\n\t// === The contract\n\n\tasync ask(form: FormInterface): Promise<FormValues> {\n\t\ttry {\n\t\t\tthis.#report(form, form.errors)\n\t\t\tawait this.#walk(form, form.schema.fields)\n\t\t\tfor (;;) {\n\t\t\t\tif (form.status !== 'editing') return await form.answer\n\t\t\t\tconst result = form.submit()\n\t\t\t\tif (result.success) return await form.answer\n\t\t\t\tthis.#report(form, result.error)\n\t\t\t\tconst again = this.#collectEditable(form, result.error)\n\t\t\t\t// Nothing the walk can edit, or an input stream that has already ended: asking again would\n\t\t\t\t// render the same fields and read the same answers forever, so abandon the form instead.\n\t\t\t\t// The failures are on screen either way, so the reader sees what could not be answered.\n\t\t\t\tif (again.length === 0 || this.#ended) {\n\t\t\t\t\tform.destroy()\n\t\t\t\t\treturn await form.answer\n\t\t\t\t}\n\t\t\t\tawait this.#walk(form, again)\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.#close()\n\t\t}\n\t}\n\n\t// === The walk\n\n\t/**\n\t * Asks `fields` in the order given, skipping what the walk must not touch and rendering what it\n\t * must not edit. Returns early the moment the form stops being editable, so an abandoned form\n\t * ends the walk between fields as well as under an active read.\n\t */\n\tasync #walk(form: FormInterface, fields: readonly FormField[]): Promise<void> {\n\t\tlet group: string | undefined\n\t\tfor (const field of fields) {\n\t\t\tif (form.status !== 'editing') return\n\t\t\tif (field.hidden === true) continue\n\t\t\tif (form.disabled.has(field.name)) continue\n\t\t\tif (field.group !== group) {\n\t\t\t\tgroup = field.group\n\t\t\t\tif (group !== undefined) this.#writeGroup(form, group)\n\t\t\t}\n\t\t\tif (field.locked === true) {\n\t\t\t\tthis.#writeLocked(form, field)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst raw = await this.#read(form, field)\n\t\t\tif (form.status !== 'editing') return\n\t\t\tthis.#bind(form, field, raw)\n\t\t}\n\t}\n\n\t/** Writes a group's label as a section header, resolving the schema's declared label and falling back to the group's own name. */\n\t#writeGroup(form: FormInterface, name: string): void {\n\t\tconst label = form.schema.groups?.find((group) => group.name === name)?.label ?? name\n\t\tthis.#output.write(\n\t\t\t`${NEWLINE}${renderGroupHeader(this.#styler, this.#theme, sanitizeDisplayText(label))}${NEWLINE}`,\n\t\t)\n\t}\n\n\t/** Renders a locked field read-only — its label, its mark, and the answer the form already holds. */\n\t#writeLocked(form: FormInterface, field: FormField): void {\n\t\tconst line = renderLockedLine(\n\t\t\tthis.#styler,\n\t\t\tthis.#theme,\n\t\t\tsanitizeDisplayText(field.label ?? field.name),\n\t\t\tsanitizeDisplayText(valueToText(form.values[field.name])),\n\t\t)\n\t\tthis.#output.write(`${line}${NEWLINE}`)\n\t}\n\n\t/** Reads one field through the reducer its control names, resolving the raw answer the binding projects. */\n\t#read(form: FormInterface, field: FormField): Promise<FieldValue | undefined> {\n\t\tif (field.control === 'password') return this.#askPassword(form, field)\n\t\tif (field.control === 'confirm') return this.#confirm(form, field)\n\t\tif (field.control === 'editor') return this.#askEditor(form, field)\n\t\tif (field.control === 'select') return this.#select(form, field)\n\t\tif (field.control === 'checkbox') return this.#checkbox(form, field)\n\t\tif (field.control === 'file') return this.#file(form, field)\n\t\treturn this.#askText(form, field)\n\t}\n\n\t/**\n\t * Binds one raw answer to the form — the single binding, and the only place this driver writes a\n\t * value. `parseValue` coerces the raw answer to the control's own shape and `matchesAnswer`\n\t * projects a blank one to absence, which is what keeps `required` refusing a bare return. A raw\n\t * answer the control cannot hold binds as absence and invalidates the field, so the field comes\n\t * back on the next pass carrying the reason rather than vanishing silently.\n\t */\n\t#bind(form: FormInterface, field: FormField, raw: FieldValue | undefined): void {\n\t\tform.touch(field.name)\n\t\tconst value = raw === undefined ? undefined : parseValue(field, raw)\n\t\tform.fill(field.name, matchesAnswer(value) ? value : undefined)\n\t\tif (value === undefined && matchesAnswer(raw)) form.invalidate(field.name, REFUSAL_MESSAGE)\n\t}\n\n\t/** Collects the erroring fields the walk can ask again — every field the walk skips or renders read-only is excluded, because a second pass could not change its answer. */\n\t#collectEditable(form: FormInterface, errors: readonly FieldError[]): readonly FormField[] {\n\t\tconst fields: FormField[] = []\n\t\tfor (const error of errors) {\n\t\t\tconst field = form.field(error.field)\n\t\t\tif (field === undefined) continue\n\t\t\tif (field.hidden === true || field.locked === true) continue\n\t\t\tif (form.disabled.has(field.name)) continue\n\t\t\tif (fields.some((held) => held.name === field.name)) continue\n\t\t\tfields.push(field)\n\t\t}\n\t\treturn fields\n\t}\n\n\t/** Writes every supplied failure against its field's label. */\n\t#report(form: FormInterface, errors: readonly FieldError[]): void {\n\t\tfor (const error of errors) {\n\t\t\tconst label = sanitizeDisplayText(form.field(error.field)?.label ?? error.field)\n\t\t\tconst message = sanitizeDisplayText(error.message)\n\t\t\tconst line = renderErrorLine(this.#styler, this.#theme, `${label}: ${message}`)\n\t\t\tthis.#output.write(`${line}${NEWLINE}`)\n\t\t}\n\t}\n\n\t// === The controls\n\n\t/** Reads a field as one line of text — `text` itself and the controls a terminal has no widget for. */\n\t#askText(form: FormInterface, field: FormField): Promise<string> {\n\t\tconst state = createInputState(fieldToText(field), this.#styler, this.#theme)\n\t\tif (supportsRawMode(this.#input)) return this.#drive(form, state, reduceInput)\n\t\treturn this.#line(form, state.message, state.default)\n\t}\n\n\t/** Reads a secret — masked live in raw mode, and read without echo through readline on a stream that cannot enter it. */\n\t#askPassword(form: FormInterface, field: PasswordField): Promise<string> {\n\t\tconst state = createPasswordState(field, this.#styler, this.#theme)\n\t\tif (supportsRawMode(this.#input)) return this.#drive(form, state, reducePassword)\n\t\treturn this.#prompt(form, renderPromptHeader(this.#styler, this.#theme, state.message))\n\t}\n\n\t/**\n\t * Reads a yes or no. The fallback accepts `y` / `yes` / `n` / `no` in any case and takes the\n\t * field's default for a bare line; anything else is returned as typed, so the binding refuses it\n\t * and the walk asks again rather than silently reading it as no.\n\t */\n\tasync #confirm(form: FormInterface, field: ConfirmField): Promise<FieldValue> {\n\t\tconst state = createConfirmState(field, this.#styler, this.#theme)\n\t\tif (supportsRawMode(this.#input)) return this.#drive(form, state, reduceConfirm)\n\t\tconst header = renderHintedHeader(\n\t\t\tthis.#styler,\n\t\t\tthis.#theme,\n\t\t\tstate.message,\n\t\t\tFALLBACK_CONFIRM_HINT,\n\t\t)\n\t\tconst line = await this.#prompt(form, header)\n\t\tconst answer = line.trim().toLowerCase()\n\t\tif (answer.length === 0) return state.default\n\t\tif (answer === 'y' || answer === 'yes') return true\n\t\tif (answer === 'n' || answer === 'no') return false\n\t\treturn line.trim()\n\t}\n\n\t/** Reads text over many lines — ctrl-d finishes in raw mode, and end of input finishes on a piped stream. */\n\t#askEditor(form: FormInterface, field: EditorField): Promise<string> {\n\t\tconst state = createEditorState(field, this.#styler, this.#theme)\n\t\tif (supportsRawMode(this.#input)) return this.#drive(form, state, reduceEditor)\n\t\treturn this.#block(form, state.message, state.default)\n\t}\n\n\t/**\n\t * Reads one choice. A disabled choice is named above the list and never offered, because the form\n\t * refuses its value at every door. An open select is a suggestion list plus a typed line, since\n\t * `open` admits an answer the list does not offer; a closed select with nothing left to offer\n\t * resolves absence and lets the form's own rules report it.\n\t */\n\tasync #select(form: FormInterface, field: SelectField): Promise<FieldValue | undefined> {\n\t\tconst choices = filterEnabled(field.choices)\n\t\tthis.#writeUnavailable(field.choices)\n\t\tif (field.open === true) {\n\t\t\tif (choices.length > 0) {\n\t\t\t\tconst display = choices.map((choice) => ({\n\t\t\t\t\t...choice,\n\t\t\t\t\tvalue: sanitizeDisplayText(choice.value),\n\t\t\t\t}))\n\t\t\t\tthis.#output.write(`${renderSuggestionLine(this.#styler, this.#theme, display)}${NEWLINE}`)\n\t\t\t}\n\t\t\treturn this.#askText(form, field)\n\t\t}\n\t\tif (choices.length === 0) return undefined\n\t\tconst state = createSelectState({ ...field, choices }, this.#styler, this.#theme)\n\t\tif (supportsRawMode(this.#input)) return this.#drive(form, state, reduceSelect)\n\t\tthis.#writeList(state.message, choices)\n\t\tconst line = await this.#prompt(form, this.#formatHint(`${FALLBACK_SELECT_HINT}:`))\n\t\treturn choices[Number.parseInt(line.trim(), 10) - 1]?.value\n\t}\n\n\t/**\n\t * Reads any number of choices. Disabled choices are named above the list and never offered, so a\n\t * box the form would refuse can never be ticked. An empty answer is an answered \"none of them\",\n\t * which is what `matchesAnswer` says an empty list means.\n\t */\n\tasync #checkbox(form: FormInterface, field: CheckboxField): Promise<FieldValue> {\n\t\tconst choices = filterEnabled(field.choices)\n\t\tthis.#writeUnavailable(field.choices)\n\t\tconst state = createCheckboxState({ ...field, choices }, this.#styler, this.#theme)\n\t\tif (supportsRawMode(this.#input)) return this.#drive(form, state, reduceCheckbox)\n\t\tthis.#writeList(state.message, choices)\n\t\tconst line = await this.#prompt(form, this.#formatHint(`${FALLBACK_CHECKBOX_HINT}:`))\n\t\treturn line\n\t\t\t.split(',')\n\t\t\t.map((part) => choices[Number.parseInt(part.trim(), 10) - 1]?.value)\n\t\t\t.filter((value): value is string => value !== undefined)\n\t}\n\n\t/**\n\t * Reads file paths — names only, because bytes never enter a form. A `multiple` field collects one\n\t * path per line until a blank one, and a single field takes one. No path at all is absence rather\n\t * than an empty list, because the reader answered a blank line.\n\t */\n\tasync #file(form: FormInterface, field: FileField): Promise<FieldValue | undefined> {\n\t\tif (field.multiple === true) this.#output.write(`${this.#formatHint(FILE_HINT)}${NEWLINE}`)\n\t\tconst paths: string[] = []\n\t\tfor (;;) {\n\t\t\tconst entry = await this.#askText(form, field)\n\t\t\tif (entry.length === 0) break\n\t\t\tpaths.push(entry)\n\t\t\tif (field.multiple !== true || this.#ended) break\n\t\t}\n\t\treturn paths.length > 0 ? paths : undefined\n\t}\n\n\t/** Names the choices a field shows but refuses, above the list the walk drives. */\n\t#writeUnavailable(choices: readonly FieldChoice[]): void {\n\t\tconst refused = filterDisabled(choices)\n\t\tif (refused.length === 0) return\n\t\tthis.#output.write(`${renderUnavailableLine(this.#styler, this.#theme, refused)}${NEWLINE}`)\n\t}\n\n\t/** Writes a field's header above its numbered choice list — the non-TTY presentation of a choice field. */\n\t#writeList(message: string, choices: readonly FieldChoice[]): void {\n\t\tconst header = renderPromptHeader(this.#styler, this.#theme, message)\n\t\tconst list = renderNumberedList(this.#styler, this.#theme, choices)\n\t\tthis.#output.write(`${header}${NEWLINE}${list}${NEWLINE}`)\n\t}\n\n\t/** Paints one line of supplementary instruction through the `hint` role. */\n\t#formatHint(text: string): string {\n\t\treturn this.#styler.render(this.#theme.roles.hint, text)\n\t}\n\n\t// === The raw-mode kernel\n\n\t/**\n\t * Isolates the irreducible Node raw-mode primitive — the ONLY place raw mode is touched. Switches the input\n\t * into raw mode (each keypress delivered immediately, no echo), resumes its flow, and subscribes\n\t * `handler` to `'data'`. The paired {@link #leaveRaw} operation unsubscribes the exact handler,\n\t * leaves raw mode, and pauses the stream on submit, cancel, abandon, or throw.\n\t */\n\t#enterRaw(token: object, handler: (chunk: string | Uint8Array) => void): void {\n\t\tthis.#handlers.set(token, handler)\n\t\tthis.#input.setRawMode?.(true)\n\t\tthis.#input.resume?.()\n\t\tthis.#input.on('data', handler)\n\t}\n\n\t#leaveRaw(token: object): void {\n\t\tconst handler = this.#handlers.get(token)\n\t\tif (handler === undefined) return\n\t\tthis.#handlers.delete(token)\n\t\tthis.#input.off('data', handler)\n\t\tthis.#input.setRawMode?.(false)\n\t\tthis.#input.pause?.()\n\t}\n\n\t/**\n\t * Drives ONE field over raw-mode stdin — the generic engine every interactive control shares.\n\t * Renders the reducer's initial view, enters raw mode once, and on each keypress runs `parseKey` →\n\t * `reduce` → an in-place re-render; on `submit` it cleans up and resolves the reducer's value, on\n\t * `cancel` (ctrl-c) it cleans up and rejects a {@link TerminalError} coded `CANCEL`. Abandoning\n\t * the form ends the read too, through the rejection of its own `answer`. Raw mode is entered\n\t * exactly once and cleaned up on every exit path, so no raw mode and no `'data'` listener ever\n\t * leaks. The cursor is hidden for the duration and restored on exit.\n\t */\n\t#drive<T, S>(\n\t\tform: FormInterface,\n\t\tinitial: S,\n\t\treduce: (state: S, key: KeyEvent) => PromptStep<T, S>,\n\t): Promise<T> {\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\t// Render the first view, tracking how many lines it spans so the next redraw climbs over them.\n\t\t\tthis.#output.write(CURSOR_HIDE)\n\t\t\tlet firstView: string\n\t\t\ttry {\n\t\t\t\tfirstView = reduce(initial, parseKey('')).view\n\t\t\t\tthis.#output.write(firstView)\n\t\t\t} catch (error) {\n\t\t\t\t// Raw mode was never entered yet, but the cursor was hidden — restore it before rejecting.\n\t\t\t\tthis.#output.write(`${CURSOR_SHOW}${NEWLINE}`)\n\t\t\t\treject(error)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst token = {}\n\t\t\tconst handler = this.#createHandler(\n\t\t\t\ttoken,\n\t\t\t\tinitial,\n\t\t\t\tlineCount(firstView),\n\t\t\t\treduce,\n\t\t\t\tresolve,\n\t\t\t\treject,\n\t\t\t)\n\t\t\tthis.#enterRaw(token, handler)\n\t\t\t// An abandoned form ends the read: its own `answer` rejects, so release the terminal and fail\n\t\t\t// this field with the form's error. A read that already finished holds no token and is a no-op.\n\t\t\tvoid form.answer.catch((error: unknown) => this.#interrupt(token, reject, error))\n\t\t})\n\t}\n\n\t#createHandler<T, S>(\n\t\ttoken: object,\n\t\tinitial: S,\n\t\tinitialLines: number,\n\t\treduce: (state: S, key: KeyEvent) => PromptStep<T, S>,\n\t\tresolve: (value: T | PromiseLike<T>) => void,\n\t\treject: (reason?: unknown) => void,\n\t): (chunk: string | Uint8Array) => void {\n\t\tlet state = initial\n\t\tlet lines = initialLines\n\t\treturn (chunk) => {\n\t\t\ttry {\n\t\t\t\tconst step = reduce(state, parseKey(chunk))\n\t\t\t\tstate = step.state\n\t\t\t\tif (step.status === 'active') {\n\t\t\t\t\tthis.#render(step.view, lines)\n\t\t\t\t\tlines = lineCount(step.view)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t// Terminal step (submit / cancel): paint the final committed view, then tear down.\n\t\t\t\tthis.#render(step.view, lines)\n\t\t\t\tthis.#leaveRaw(token)\n\t\t\t\tthis.#output.write(`${CURSOR_SHOW}${NEWLINE}`)\n\t\t\t\tif (step.status === 'cancel') reject(new TerminalError('CANCEL', 'Prompt cancelled'))\n\t\t\t\telse if (step.status === 'submit' && step.value !== undefined) resolve(step.value)\n\t\t\t\telse reject(new TerminalError('DRIVER', 'submit produced no value'))\n\t\t\t} catch (error) {\n\t\t\t\t// A throw inside the reducer/styler: tear down raw mode + the listener, restore the cursor\n\t\t\t\t// exactly as the normal exit path does, then reject.\n\t\t\t\tthis.#leaveRaw(token)\n\t\t\t\tthis.#output.write(`${CURSOR_SHOW}${NEWLINE}`)\n\t\t\t\treject(error)\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Ends an active read that the form outlived — releases raw mode exactly as a submit does, then fails the read with the form's own error. */\n\t#interrupt(token: object, reject: (reason?: unknown) => void, error: unknown): void {\n\t\tif (!this.#handlers.has(token)) return\n\t\tthis.#leaveRaw(token)\n\t\tthis.#output.write(`${CURSOR_SHOW}${NEWLINE}`)\n\t\treject(error)\n\t}\n\n\t/** Redraws a field view in place — climbs over the previous view's `previousLines`, clears, and writes the new view (the pure cursor-math is {@link redrawPrefix}). */\n\t#render(view: string, previousLines: number): void {\n\t\tthis.#output.write(`${redrawPrefix(previousLines)}${view}`)\n\t}\n\n\t// === Non-TTY fallbacks (node:readline line input)\n\n\t/** Reads one line for a text-shaped field, taking the field's default when the line is bare. */\n\tasync #line(form: FormInterface, message: string, seed: string): Promise<string> {\n\t\tconst answer = await this.#prompt(form, renderPromptHeader(this.#styler, this.#theme, message))\n\t\treturn answer.length > 0 ? answer : seed\n\t}\n\n\t/**\n\t * Reads a whole block for an `editor` field — a piped stream has no ctrl-d keypress, so end of\n\t * input is the terminator. It drains every remaining line, which is why nothing after an `editor`\n\t * field can be asked on the same stream.\n\t */\n\tasync #block(form: FormInterface, message: string, seed: string): Promise<string> {\n\t\tconst header = renderHintedHeader(this.#styler, this.#theme, message, FALLBACK_EDITOR_HINT)\n\t\tthis.#output.write(`${header}${NEWLINE}`)\n\t\tconst collected: string[] = []\n\t\tfor (;;) {\n\t\t\tconst line = await this.#next(form)\n\t\t\tif (line === undefined) break\n\t\t\tcollected.push(line)\n\t\t}\n\t\tconst text = collected.join('\\n')\n\t\treturn text.length > 0 ? text : seed\n\t}\n\n\t/** Writes one field's header and reads back the line the reader answers it with, or `''` once the stream has ended. */\n\tasync #prompt(form: FormInterface, header: string): Promise<string> {\n\t\tthis.#output.write(`${header} `)\n\t\tconst line = await this.#next(form)\n\t\treturn line ?? ''\n\t}\n\n\t/**\n\t * Takes the next line the input carries — from the buffer when the reader has already read ahead,\n\t * and otherwise by waiting for one. It resolves ABSENCE once the stream has ended, so a walk over\n\t * an exhausted stream settles instead of waiting forever, and it rejects when the form is\n\t * abandoned, so an unanswerable read ends with the form rather than outliving it.\n\t */\n\t#next(form: FormInterface): Promise<string | undefined> {\n\t\tconst buffered = this.#queue.shift()\n\t\tif (buffered !== undefined) return Promise.resolve(buffered)\n\t\tif (this.#ended) return Promise.resolve(undefined)\n\t\tthis.#startReader()\n\t\treturn new Promise<string | undefined>((resolve, reject) => {\n\t\t\tthis.#taker = resolve\n\t\t\tvoid form.answer.catch((error: unknown) => {\n\t\t\t\tif (this.#taker !== resolve) return\n\t\t\t\tthis.#taker = undefined\n\t\t\t\treject(error)\n\t\t\t})\n\t\t})\n\t}\n\n\t/**\n\t * Opens the walk's ONE readline interface, or keeps the open one. A whole form is many questions\n\t * over one stream, and an interface reads ahead: a fresh interface per question would swallow\n\t * every line it read past the one it was asked for, so the walk holds a single reader and buffers\n\t * what arrives early. It is closed when the walk ends, so the process is free to exit.\n\t */\n\t#startReader(): void {\n\t\tif (this.#interface !== undefined) return\n\t\tconst rl = createInterface(this.#openReadline())\n\t\trl.on('line', (line) => this.#accept(line))\n\t\trl.on('close', () => this.#finish())\n\t\tthis.#interface = rl\n\t}\n\n\t/** Hands a line to whoever is waiting for it, or buffers it for the next question. */\n\t#accept(line: string): void {\n\t\tconst taker = this.#taker\n\t\tif (taker === undefined) {\n\t\t\tthis.#queue.push(line)\n\t\t\treturn\n\t\t}\n\t\tthis.#taker = undefined\n\t\ttaker(line)\n\t}\n\n\t/** Records that no further line can arrive and releases whoever was waiting for one. */\n\t#finish(): void {\n\t\tthis.#ended = true\n\t\tconst taker = this.#taker\n\t\tif (taker === undefined) return\n\t\tthis.#taker = undefined\n\t\ttaker(undefined)\n\t}\n\n\t/** Closes the walk's reader and releases a waiting question — the walk is over, so the stream must stop holding the process open. */\n\t#close(): void {\n\t\tconst taker = this.#taker\n\t\tthis.#taker = undefined\n\t\tif (taker !== undefined) taker(undefined)\n\t\tconst rl = this.#interface\n\t\tif (rl === undefined) return\n\t\tthis.#interface = undefined\n\t\t// Drop the close listener first: this close is the walk ending, not the stream ending, and\n\t\t// recording it as end of input would refuse the next walk its input.\n\t\trl.removeAllListeners('close')\n\t\trl.close()\n\t}\n\n\t/**\n\t * Narrows the resolved input to the `node:readline` `createInterface` boundary, never an assertion.\n\t * The fallback only runs on a real piped `process.stdin` (or a `PassThrough` a test injects), both\n\t * genuine readables; a minimal non-readable fake reaching here means the walk was driven with a\n\t * stream it cannot use, which fails loudly rather than silently. `terminal: false` leaves readline\n\t * as a line decoder and nothing else: the walk writes every prompt itself, through the same output\n\t * every other line goes to, so nothing is written twice and a secret is never echoed.\n\t */\n\t#openReadline(): { input: NodeJS.ReadableStream; terminal: boolean } {\n\t\t// Bind to a local first — a guard narrows a local, not a `#private` field access.\n\t\tconst input = this.#input\n\t\tif (!isReadable(input))\n\t\t\tthrow new TerminalError('DRIVER', 'Terminal fallback requires a readable input stream')\n\t\treturn { input, terminal: false }\n\t}\n}\n","import type { TerminalInterface } from '@src/core'\nimport type { TerminalOptions } from './types.js'\nimport { Terminal } from './Terminal.js'\n\n/**\n * Creates the interactive terminal form driver — the local-keyboard arm of the terminal trio,\n * beside the core headless `createPrompt` broker and the SSE `createPromptClient` bridge. Where the\n * broker parks a live form until somebody elsewhere answers it, a `Terminal` answers one here: it\n * walks the form's fields in schema order, drives each control's pure reducer over raw-mode stdin,\n * binds every answer through the form's own `fill`, and submits. It is the only impure part of the\n * terminal stack.\n *\n * @param options - See {@link TerminalOptions}\n * @returns A {@link TerminalInterface} whose `ask` drives one whole form over the resolved streams\n *\n * @remarks\n * - **The form is the unit.** `ask` takes the caller's live form and returns its settled values. The\n *   returned promise is that form's own `answer`, so a caller holding the form can await either one.\n * - **Every control renders.** The line-read controls are read as a line of text with their format cue,\n *   `password` masks, `confirm` takes a key, `editor` takes a block, `select` and `checkbox` drive a\n *   list, and an open `select` accepts a value its list does not offer.\n * - **The form decides.** A blank answer binds as absence, the form evaluates, and a refusal\n *   re-walks only the fields the walk can still edit.\n * - **Injectable and guard-narrowed.** `input` and `output` default to `process.stdin` and\n *   `process.stdout` but accept any stream of the declared minimal shape, resolved through their\n *   guards rather than an assertion, so a test drives a whole form with a fake TTY that emits\n *   scripted key chunks and records every rendered byte.\n * - **Non-TTY fallback.** A piped stream cannot enter raw mode, so the same walk runs over\n *   `node:readline` line input.\n *\n * @example Ask one form at this keyboard\n * ```ts\n * import { createForm } from '@orkestrel/form'\n * import { isTerminalError } from '@orkestrel/terminal'\n * import { createTerminal } from '@orkestrel/terminal/server'\n *\n * const terminal = createTerminal() // process.stdin / process.stdout by default\n * const form = createForm({\n * \tlabel: 'Sign up',\n * \tfields: [\n * \t\t{ control: 'text', name: 'name', label: 'Your name', rule: { required: true, minimum: 2 } },\n * \t\t{ control: 'text', name: 'email', label: 'Email', rule: { required: true, email: true } },\n * \t\t{ control: 'password', name: 'token', label: 'Token' },\n * \t\t{ control: 'confirm', name: 'terms', label: 'Accept the terms', rule: { required: true } },\n * \t\t{\n * \t\t\tcontrol: 'select',\n * \t\t\tname: 'role',\n * \t\t\tlabel: 'Role',\n * \t\t\tchoices: [\n * \t\t\t\t{ value: 'admin', label: 'Admin' },\n * \t\t\t\t{ value: 'viewer', label: 'Viewer', help: 'read-only' },\n * \t\t\t],\n * \t\t},\n * \t],\n * })\n *\n * try {\n * \tconst values = await terminal.ask(form)\n * \tdeploy(values)\n * } catch (error) {\n * \t// Ctrl-c: the walk ended, and the form is still `editing` for whoever owns it.\n * \tif (isTerminalError(error) && error.code === 'CANCEL') form.destroy()\n * }\n * ```\n */\nexport function createTerminal(options?: TerminalOptions): TerminalInterface {\n\treturn new Terminal(options)\n}\n"],"mappings":"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"}