@orkestrel/terminal 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -33
- package/dist/src/core/index.cjs +785 -869
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +627 -862
- package/dist/src/core/index.d.ts +627 -862
- package/dist/src/core/index.js +777 -841
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +555 -205
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +232 -129
- package/dist/src/server/index.d.ts +232 -129
- package/dist/src/server/index.js +540 -206
- package/dist/src/server/index.js.map +1 -1
- package/package.json +8 -6
package/dist/src/core/index.d.ts
CHANGED
|
@@ -1,139 +1,71 @@
|
|
|
1
|
+
import { CheckboxField } from '@orkestrel/form';
|
|
2
|
+
import { ConfirmField } from '@orkestrel/form';
|
|
1
3
|
import { DriverInterface } from '@orkestrel/database';
|
|
4
|
+
import { EditorField } from '@orkestrel/form';
|
|
2
5
|
import { EmitterErrorHandler } from '@orkestrel/emitter';
|
|
3
6
|
import { EmitterHooks } from '@orkestrel/emitter';
|
|
4
7
|
import { EmitterInterface } from '@orkestrel/emitter';
|
|
8
|
+
import { FieldChoice } from '@orkestrel/form';
|
|
9
|
+
import { FieldError } from '@orkestrel/form';
|
|
10
|
+
import { FormInterface } from '@orkestrel/form';
|
|
11
|
+
import { FormSchema } from '@orkestrel/form';
|
|
12
|
+
import { FormValues } from '@orkestrel/form';
|
|
5
13
|
import { Guard } from '@orkestrel/contract';
|
|
14
|
+
import { JSONRecord } from '@orkestrel/contract';
|
|
15
|
+
import { PasswordField } from '@orkestrel/form';
|
|
16
|
+
import { Result } from '@orkestrel/contract';
|
|
17
|
+
import { SelectField } from '@orkestrel/form';
|
|
18
|
+
import { Style } from '@orkestrel/console';
|
|
6
19
|
import { StylerInterface } from '@orkestrel/console';
|
|
7
20
|
import { TableInterface } from '@orkestrel/database';
|
|
21
|
+
import { TextField } from '@orkestrel/form';
|
|
8
22
|
|
|
9
23
|
/** The `Accept` header value that opens the broker's SSE stream. */
|
|
10
24
|
export declare const ACCEPT_EVENT_STREAM = "text/event-stream";
|
|
11
25
|
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Why {@link PromptInterface.answer} refused. Names its axis with `reason`.
|
|
28
|
+
*
|
|
29
|
+
* @remarks
|
|
30
|
+
* - `unknown` — no form is parked under that id, or the one that was has already settled.
|
|
31
|
+
* - `rejected` — the authoritative form refused the values, and `errors` is exactly what it
|
|
32
|
+
* reported. A client seeds its local form with the values it sent, applies each failure through
|
|
33
|
+
* the form's `invalidate`, and asks again; the parked form stays parked until it accepts or
|
|
34
|
+
* expires. This is the retry loop that makes a server-side `custom` rule enforceable, because
|
|
35
|
+
* that rule never crossed the wire and the client could not have checked it.
|
|
36
|
+
*/
|
|
37
|
+
export declare type AnswerError = {
|
|
38
|
+
readonly reason: 'unknown';
|
|
22
39
|
} | {
|
|
23
|
-
readonly
|
|
24
|
-
readonly
|
|
40
|
+
readonly reason: 'rejected';
|
|
41
|
+
readonly errors: readonly FieldError[];
|
|
25
42
|
};
|
|
26
43
|
|
|
27
|
-
/**
|
|
28
|
-
* Append a rule-backed {@link Validator} to `validators` when the rule is enabled — a `false` /
|
|
29
|
-
* `undefined` `check` is skipped, a function `check` is added verbatim (the custom override), and
|
|
30
|
-
* a primitive `check` is wrapped via {@link buildRuleValidator}. Mutates `validators` in place.
|
|
31
|
-
*/
|
|
32
|
-
export declare function appendRule(validators: Validator[], rule: string, check: boolean | number | string | Validator | undefined): void;
|
|
33
|
-
|
|
34
44
|
/** Backspace (BS, U+0008) — Ctrl+H / some terminals' Backspace. */
|
|
35
45
|
export declare const BACKSPACE: string;
|
|
36
46
|
|
|
37
|
-
/** Wrap a named rule + its primitive check into a {@link Validator} (returns `true` or the rule's message). */
|
|
38
|
-
export declare function buildRuleValidator(rule: string, check: boolean | number | string): Validator;
|
|
39
|
-
|
|
40
|
-
/** A choice item in a {@link CheckboxOptions} prompt — a {@link PromptChoice} plus an optional initial `checked` state. */
|
|
41
|
-
export declare interface CheckboxChoice {
|
|
42
|
-
readonly name: string;
|
|
43
|
-
readonly value: string;
|
|
44
|
-
readonly description?: string;
|
|
45
|
-
readonly checked?: boolean;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Options for a multi-selection {@link import('./helpers.js').checkboxReduce} prompt.
|
|
50
|
-
*
|
|
51
|
-
* @remarks
|
|
52
|
-
* `choices` accepts bare strings or full {@link CheckboxChoice} objects (with an optional
|
|
53
|
-
* initial `checked`); {@link import('./helpers.js').createCheckboxState} normalizes them.
|
|
54
|
-
* `min` / `max` gate submission — a submit with fewer than `min` or more than `max` selected
|
|
55
|
-
* is rejected (the prompt stays active with the reason in the view).
|
|
56
|
-
*/
|
|
57
|
-
export declare interface CheckboxOptions {
|
|
58
|
-
readonly message: string;
|
|
59
|
-
readonly choices: ReadonlyArray<string | CheckboxChoice>;
|
|
60
|
-
readonly min?: number;
|
|
61
|
-
readonly max?: number;
|
|
62
|
-
readonly styler?: StylerInterface;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
47
|
/**
|
|
66
48
|
* Advance a checkbox prompt by one {@link KeyEvent} — the pure
|
|
67
49
|
* `(state, key) → PromptStep<readonly string[]>` reducer. `up` / `down` (and `k` / `j`) move the
|
|
68
50
|
* focus (wrapping); `space` toggles the focused index in the checked set; return submits the
|
|
69
|
-
* checked values in
|
|
70
|
-
* the reason in the view); ctrl-c cancels.
|
|
51
|
+
* checked values in choice order; ctrl-c cancels. The form applies selection-count rules.
|
|
71
52
|
*/
|
|
72
|
-
export declare function checkboxReduce(state:
|
|
53
|
+
export declare function checkboxReduce(state: ReturnType<typeof createCheckboxState>, key: KeyEvent): PromptStep<readonly string[], ReturnType<typeof createCheckboxState>>;
|
|
73
54
|
|
|
74
|
-
/**
|
|
75
|
-
|
|
76
|
-
* index, the set of `checked` indices, the optional `min` / `max` gate, and the current `error`.
|
|
77
|
-
*
|
|
78
|
-
* @remarks
|
|
79
|
-
* Built by {@link import('./helpers.js').createCheckboxState}; advanced by
|
|
80
|
-
* {@link import('./helpers.js').checkboxReduce}. `up` / `down` move `focus` (wrapping); `space`
|
|
81
|
-
* toggles the focused index in `checked`; `return` submits the checked values in choice order
|
|
82
|
-
* (rejected, with `error`, when the count is outside `[min, max]`). `checked` is modelled as a
|
|
83
|
-
* readonly index array (plain JSON data, copy-on-write — no `Set` to clone).
|
|
84
|
-
*/
|
|
85
|
-
export declare interface CheckboxState {
|
|
86
|
-
readonly message: string;
|
|
87
|
-
readonly choices: readonly CheckboxChoice[];
|
|
88
|
-
readonly styler: StylerInterface;
|
|
89
|
-
readonly focused: number;
|
|
90
|
-
readonly checked: readonly number[];
|
|
91
|
-
readonly min?: number;
|
|
92
|
-
readonly max?: number;
|
|
93
|
-
readonly error?: string;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/** Render a {@link CheckboxState} as a MULTI-LINE styled view — the header, one box per choice (focused + checked marked), a count, and any error. */
|
|
97
|
-
export declare function checkboxView(state: CheckboxState): string;
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Compose several {@link Validator}s into ONE short-circuiting validator — it runs them in order
|
|
101
|
-
* and returns the FIRST error message, or `true` when all pass. The empty composition always
|
|
102
|
-
* passes.
|
|
103
|
-
*/
|
|
104
|
-
export declare function composeValidators(...validators: Validator[]): Validator;
|
|
105
|
-
|
|
106
|
-
/** Options for a yes/no {@link import('./helpers.js').confirmReduce} confirmation prompt. */
|
|
107
|
-
export declare interface ConfirmOptions {
|
|
108
|
-
readonly message: string;
|
|
109
|
-
readonly default?: boolean;
|
|
110
|
-
readonly styler?: StylerInterface;
|
|
111
|
-
}
|
|
55
|
+
/** Render a checkbox-field key state as a multi-line styled view. */
|
|
56
|
+
export declare function checkboxView(state: ReturnType<typeof createCheckboxState>): string;
|
|
112
57
|
|
|
113
58
|
/**
|
|
114
59
|
* Advance a confirm prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<boolean>`
|
|
115
60
|
* reducer. `y` / `Y` submits `true`, `n` / `N` submits `false`, return on an empty line submits
|
|
116
61
|
* the `default`, ctrl-c cancels; any other key is ignored (stays active).
|
|
117
62
|
*/
|
|
118
|
-
export declare function confirmReduce(state:
|
|
63
|
+
export declare function confirmReduce(state: ReturnType<typeof createConfirmState>, key: KeyEvent): PromptStep<boolean, ReturnType<typeof createConfirmState>>;
|
|
119
64
|
|
|
120
65
|
/**
|
|
121
|
-
*
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
* Built by {@link import('./helpers.js').createConfirmState}; advanced by
|
|
125
|
-
* {@link import('./helpers.js').confirmReduce}. `y` / `Y` submits `true`, `n` / `N` submits
|
|
126
|
-
* `false`, and `enter` takes the `default` (rendered with the active letter capitalized in the
|
|
127
|
-
* `(Y/n)` hint).
|
|
128
|
-
*/
|
|
129
|
-
export declare interface ConfirmState {
|
|
130
|
-
readonly message: string;
|
|
131
|
-
readonly default: boolean;
|
|
132
|
-
readonly styler: StylerInterface;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/** Render a {@link ConfirmState} as a styled view — the header plus a `(Y/n)` hint with the default letter emphasized. */
|
|
136
|
-
export declare function confirmView(state: ConfirmState): string;
|
|
66
|
+
* Render a confirm-field key state as a styled view. The selected role paints the default letter.
|
|
67
|
+
*/
|
|
68
|
+
export declare function confirmView(state: ReturnType<typeof createConfirmState>): string;
|
|
137
69
|
|
|
138
70
|
/**
|
|
139
71
|
* The single control BYTE → key descriptor table {@link import('./helpers.js').parseKey}
|
|
@@ -151,11 +83,37 @@ export declare const CONTROL_NAMES: Readonly<Record<string, {
|
|
|
151
83
|
readonly ctrl: boolean;
|
|
152
84
|
}>>;
|
|
153
85
|
|
|
154
|
-
/**
|
|
155
|
-
|
|
86
|
+
/**
|
|
87
|
+
* Build the initial checkbox-field key state.
|
|
88
|
+
*
|
|
89
|
+
* @param field - The checkbox field to render
|
|
90
|
+
* @param styler - The styler used to render the view
|
|
91
|
+
* @param theme - The optional terminal theme
|
|
92
|
+
* @returns The initial immutable key state
|
|
93
|
+
*/
|
|
94
|
+
export declare function createCheckboxState(field: CheckboxField, styler?: StylerInterface, theme?: PromptThemeOptions): {
|
|
95
|
+
message: string;
|
|
96
|
+
choices: FieldChoice[];
|
|
97
|
+
styler: StylerInterface;
|
|
98
|
+
theme: PromptTheme;
|
|
99
|
+
focused: number;
|
|
100
|
+
checked: readonly number[];
|
|
101
|
+
};
|
|
156
102
|
|
|
157
|
-
/**
|
|
158
|
-
|
|
103
|
+
/**
|
|
104
|
+
* Build the initial confirm-field key state.
|
|
105
|
+
*
|
|
106
|
+
* @param field - The confirm field to render
|
|
107
|
+
* @param styler - The styler used to render the view
|
|
108
|
+
* @param theme - The optional terminal theme
|
|
109
|
+
* @returns The initial immutable key state
|
|
110
|
+
*/
|
|
111
|
+
export declare function createConfirmState(field: ConfirmField, styler?: StylerInterface, theme?: PromptThemeOptions): {
|
|
112
|
+
message: string;
|
|
113
|
+
default: boolean;
|
|
114
|
+
styler: StylerInterface;
|
|
115
|
+
theme: PromptTheme;
|
|
116
|
+
};
|
|
159
117
|
|
|
160
118
|
/**
|
|
161
119
|
* Create a {@link TerminalStoreInterface} backed by one table of the `databases` layer — the
|
|
@@ -174,11 +132,38 @@ export declare function createConfirmState(options: ConfirmOptions): ConfirmStat
|
|
|
174
132
|
*/
|
|
175
133
|
export declare function createDatabaseTerminalStore(driver?: DriverInterface): TerminalStoreInterface;
|
|
176
134
|
|
|
177
|
-
/**
|
|
178
|
-
|
|
135
|
+
/**
|
|
136
|
+
* Build the initial editor-field key state.
|
|
137
|
+
*
|
|
138
|
+
* @param field - The editor field to render
|
|
139
|
+
* @param styler - The styler used to render the view
|
|
140
|
+
* @param theme - The optional terminal theme
|
|
141
|
+
* @returns The initial immutable key state
|
|
142
|
+
*/
|
|
143
|
+
export declare function createEditorState(field: EditorField, styler?: StylerInterface, theme?: PromptThemeOptions): {
|
|
144
|
+
message: string;
|
|
145
|
+
default: string;
|
|
146
|
+
styler: StylerInterface;
|
|
147
|
+
theme: PromptTheme;
|
|
148
|
+
lines: readonly string[];
|
|
149
|
+
current: string;
|
|
150
|
+
};
|
|
179
151
|
|
|
180
|
-
/**
|
|
181
|
-
|
|
152
|
+
/**
|
|
153
|
+
* Build the initial text-field key state.
|
|
154
|
+
*
|
|
155
|
+
* @param field - The text field to render
|
|
156
|
+
* @param styler - The styler used to render the view
|
|
157
|
+
* @param theme - The optional terminal theme
|
|
158
|
+
* @returns The initial immutable key state
|
|
159
|
+
*/
|
|
160
|
+
export declare function createInputState(field: TextField, styler?: StylerInterface, theme?: PromptThemeOptions): {
|
|
161
|
+
message: string;
|
|
162
|
+
default: string;
|
|
163
|
+
styler: StylerInterface;
|
|
164
|
+
theme: PromptTheme;
|
|
165
|
+
value: string;
|
|
166
|
+
};
|
|
182
167
|
|
|
183
168
|
/**
|
|
184
169
|
* Create the in-memory {@link TerminalStoreInterface} — a process-lifetime `Map` of endpoint
|
|
@@ -195,43 +180,51 @@ export declare function createInputState(options: InputOptions): InputState;
|
|
|
195
180
|
*/
|
|
196
181
|
export declare function createMemoryTerminalStore(): TerminalStoreInterface;
|
|
197
182
|
|
|
198
|
-
/**
|
|
199
|
-
|
|
183
|
+
/**
|
|
184
|
+
* Build the initial password-field key state.
|
|
185
|
+
*
|
|
186
|
+
* @param field - The password field to render
|
|
187
|
+
* @param styler - The styler used to render the view
|
|
188
|
+
* @param theme - The optional terminal theme
|
|
189
|
+
* @returns The initial immutable key state
|
|
190
|
+
*/
|
|
191
|
+
export declare function createPasswordState(field: PasswordField, styler?: StylerInterface, theme?: PromptThemeOptions): {
|
|
192
|
+
message: string;
|
|
193
|
+
mask: string;
|
|
194
|
+
styler: StylerInterface;
|
|
195
|
+
theme: PromptTheme;
|
|
196
|
+
value: string;
|
|
197
|
+
};
|
|
200
198
|
|
|
201
199
|
/**
|
|
202
|
-
* Create the headless
|
|
203
|
-
*
|
|
204
|
-
* timeout). The tri-surface's headless arm: subscribe `emitter.on('pending', …)` to forward each
|
|
205
|
-
* prompt to whoever can answer (an SSE transport, a remote terminal), then route the answer back
|
|
206
|
-
* through `answer(id, value)`.
|
|
200
|
+
* Create the headless {@link PromptInterface} broker. It parks live forms and applies remote
|
|
201
|
+
* answers to the authoritative instances.
|
|
207
202
|
*
|
|
208
203
|
* @param options - See {@link PromptOptions}
|
|
209
204
|
* @returns A {@link PromptInterface}
|
|
210
205
|
*
|
|
211
206
|
* @remarks
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
* `options.timeout` (default {@link import('./constants.js').DEFAULT_PROMPT_TIMEOUT_MS}) and its
|
|
216
|
-
* Promise rejects with a {@link import('./errors.js').TerminalError}; inject `options.timer` to
|
|
217
|
-
* drive expiry without real time.
|
|
207
|
+
* The caller awaits the parked form's own `answer`. Timeout or teardown destroys the form, so that
|
|
208
|
+
* promise rejects with the Form package's `ABANDONED` error. Inject `options.timer` to drive
|
|
209
|
+
* expiry without real time.
|
|
218
210
|
*
|
|
219
211
|
* @example
|
|
220
212
|
* ```ts
|
|
221
213
|
* import { createPrompt } from '@src/core'
|
|
214
|
+
* import { createForm } from '@orkestrel/form'
|
|
222
215
|
*
|
|
223
216
|
* const prompt = createPrompt()
|
|
224
|
-
*
|
|
225
|
-
* const
|
|
217
|
+
* const form = createForm({ fields: [{ control: 'text', name: 'name' }] })
|
|
218
|
+
* const id = prompt.park(form)
|
|
219
|
+
* prompt.answer(id, { name: 'Ada' })
|
|
226
220
|
* ```
|
|
227
221
|
*/
|
|
228
222
|
export declare function createPrompt(options?: PromptOptions): PromptInterface;
|
|
229
223
|
|
|
230
224
|
/**
|
|
231
225
|
* Create the SSE prompt {@link PromptClientInterface} BRIDGE — it connects to a remote broker's SSE
|
|
232
|
-
* endpoint, dispatches each received
|
|
233
|
-
*
|
|
234
|
-
* back. Universal — `fetch` / SSE are web-standard.
|
|
226
|
+
* endpoint, dispatches each received form to a local {@link import('./types.js').TerminalInterface},
|
|
227
|
+
* and POSTs the answer back. Universal — `fetch` / SSE are web-standard.
|
|
235
228
|
*
|
|
236
229
|
* @param options - See {@link PromptClientOptions} (`url` + `terminal` required)
|
|
237
230
|
* @returns A {@link PromptClientInterface}
|
|
@@ -253,16 +246,51 @@ export declare function createPrompt(options?: PromptOptions): PromptInterface;
|
|
|
253
246
|
*/
|
|
254
247
|
export declare function createPromptClient(options: PromptClientOptions): PromptClientInterface;
|
|
255
248
|
|
|
256
|
-
/**
|
|
257
|
-
|
|
249
|
+
/**
|
|
250
|
+
* Build a complete {@link PromptTheme} by merging a partial one over
|
|
251
|
+
* {@link DEFAULT_PROMPT_THEME}, leaf by leaf — each supplied icon replaces that glyph, each
|
|
252
|
+
* supplied role replaces that {@link Style}, and everything else keeps its default. Each supplied
|
|
253
|
+
* style is snapshotted through the console module's own
|
|
254
|
+
* {@link import('@orkestrel/console').freezeStyle}, so the result is deeply frozen and a caller
|
|
255
|
+
* mutating its own attribute list afterwards cannot reach into a built theme.
|
|
256
|
+
*
|
|
257
|
+
* @param options - The partial theme to merge, or `undefined` for the defaults
|
|
258
|
+
* @returns The resolved, deeply frozen theme every prompt state carries
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* ```ts
|
|
262
|
+
* createPromptTheme() // the defaults
|
|
263
|
+
* createPromptTheme({
|
|
264
|
+
* icons: { pointer: '=>' },
|
|
265
|
+
* roles: { message: { foreground: 'magenta', attributes: ['bold'] } },
|
|
266
|
+
* })
|
|
267
|
+
* ```
|
|
268
|
+
*/
|
|
269
|
+
export declare function createPromptTheme(options?: PromptThemeOptions): PromptTheme;
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Build the initial select-field key state.
|
|
273
|
+
*
|
|
274
|
+
* @param field - The select field to render
|
|
275
|
+
* @param styler - The styler used to render the view
|
|
276
|
+
* @param theme - The optional terminal theme
|
|
277
|
+
* @returns The initial immutable key state
|
|
278
|
+
*/
|
|
279
|
+
export declare function createSelectState(field: SelectField, styler?: StylerInterface, theme?: PromptThemeOptions): {
|
|
280
|
+
message: string;
|
|
281
|
+
choices: FieldChoice[];
|
|
282
|
+
styler: StylerInterface;
|
|
283
|
+
theme: PromptTheme;
|
|
284
|
+
focused: number;
|
|
285
|
+
};
|
|
258
286
|
|
|
259
287
|
/**
|
|
260
|
-
* Create the multi-endpoint {@link
|
|
288
|
+
* Create the multi-endpoint {@link TerminalManager} — a named registry of
|
|
261
289
|
* {@link PromptInterface} brokers so several parties can `ask` prompts of each other by name,
|
|
262
290
|
* with a transitive DEADLOCK check across every in-flight ask.
|
|
263
291
|
*
|
|
264
292
|
* @param options - See {@link TerminalManagerOptions}
|
|
265
|
-
* @returns A {@link
|
|
293
|
+
* @returns A {@link TerminalManager}
|
|
266
294
|
*
|
|
267
295
|
* @example
|
|
268
296
|
* ```ts
|
|
@@ -348,9 +376,26 @@ export declare class DatabaseTerminalStore implements TerminalStoreInterface {
|
|
|
348
376
|
delete(id: string): Promise<void>;
|
|
349
377
|
}
|
|
350
378
|
|
|
351
|
-
/** The default mask glyph
|
|
379
|
+
/** The default mask glyph {@link import('./helpers.js').createPasswordState} uses — `*`. */
|
|
352
380
|
export declare const DEFAULT_MASK = "*";
|
|
353
381
|
|
|
382
|
+
/**
|
|
383
|
+
* The {@link import('./types.js').PromptTheme} every prompt renders with unless its options supply
|
|
384
|
+
* another — the glyph set assembled from {@link PROMPT_ICONS} plus the console
|
|
385
|
+
* {@link import('@orkestrel/console').STATUS_ICONS} `success` / `error` marks, and the console
|
|
386
|
+
* {@link import('@orkestrel/console').Style} each role is painted with. Deeply frozen through the
|
|
387
|
+
* console module's own {@link import('@orkestrel/console').freezeStyle}; the baseline
|
|
388
|
+
* {@link import('./helpers.js').createPromptTheme} merges a partial theme over.
|
|
389
|
+
*
|
|
390
|
+
* @remarks
|
|
391
|
+
* The default roles reproduce the views' historical coloring exactly: `question` / `pointer` cyan,
|
|
392
|
+
* `message` / `focus` bold, `success` / `selected` green, `error` red, `hint` / `muted` /
|
|
393
|
+
* `description` dim, and `content` the EMPTY style — an empty style renders bare text, so primary
|
|
394
|
+
* content keeps the bytes it had before it became themeable.
|
|
395
|
+
* Two roles sharing a style today are still two roles — re-mapping one leaves the other alone.
|
|
396
|
+
*/
|
|
397
|
+
export declare const DEFAULT_PROMPT_THEME: PromptTheme;
|
|
398
|
+
|
|
354
399
|
/** How long (ms) the {@link import('./types.js').PromptInterface} broker parks an unanswered prompt before it expires — 5 minutes. */
|
|
355
400
|
export declare const DEFAULT_PROMPT_TIMEOUT_MS = 300000;
|
|
356
401
|
|
|
@@ -369,19 +414,6 @@ export declare function defaultTimer(callback: () => void, ms: number): TimerCan
|
|
|
369
414
|
/** Delete (DEL, U+007F) — the usual Backspace byte on a Unix TTY. */
|
|
370
415
|
export declare const DELETE: string;
|
|
371
416
|
|
|
372
|
-
/**
|
|
373
|
-
* Dispatch a {@link PendingPrompt} to the matching {@link PromptFormInterface} method — the bridge
|
|
374
|
-
* step a {@link PromptClient} runs to drive a LOCAL terminal with a prompt issued elsewhere.
|
|
375
|
-
* Reconstructs typed options from the wire-safe {@link PendingPrompt.options} (every field
|
|
376
|
-
* §14-narrowed, never an `as`; the validator rebuilt from rules via {@link reconstructValidationRules}),
|
|
377
|
-
* then calls the matching prompt form and returns its resolved value.
|
|
378
|
-
*
|
|
379
|
-
* @param terminal - The local {@link PromptFormInterface} to drive
|
|
380
|
-
* @param pending - The decoded pending prompt to dispatch
|
|
381
|
-
* @returns The prompt's resolved value (a `string` / `boolean` / `readonly string[]` per form)
|
|
382
|
-
*/
|
|
383
|
-
export declare function dispatchPendingPrompt(terminal: PromptFormInterface, pending: PendingPrompt): Promise<string | boolean | readonly string[]>;
|
|
384
|
-
|
|
385
417
|
/**
|
|
386
418
|
* Apply a single line-editing {@link KeyEvent} to a text buffer — the editing shared by input /
|
|
387
419
|
* password / editor. A printable key appends its character; `backspace` drops the last character;
|
|
@@ -390,85 +422,35 @@ export declare function dispatchPendingPrompt(terminal: PromptFormInterface, pen
|
|
|
390
422
|
*/
|
|
391
423
|
export declare function editLine(value: string, key: KeyEvent): string | undefined;
|
|
392
424
|
|
|
393
|
-
/** Options for a multi-line {@link import('./helpers.js').editorReduce} editor prompt (terminated by ctrl-d). */
|
|
394
|
-
export declare interface EditorOptions {
|
|
395
|
-
readonly message: string;
|
|
396
|
-
readonly default?: string;
|
|
397
|
-
readonly validate?: Validator | ValidationRules;
|
|
398
|
-
readonly styler?: StylerInterface;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
425
|
/**
|
|
402
426
|
* Advance an editor prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`
|
|
403
427
|
* reducer. Printable characters extend the current line; backspace shrinks it; return commits the
|
|
404
428
|
* current line and starts a fresh one; ctrl-d FINISHES (joining all lines, falling back to the
|
|
405
|
-
* default when empty)
|
|
406
|
-
* the error.
|
|
429
|
+
* default when empty); ctrl-c cancels. The form validates the candidate after the driver fills it.
|
|
407
430
|
*/
|
|
408
|
-
export declare function editorReduce(state:
|
|
431
|
+
export declare function editorReduce(state: ReturnType<typeof createEditorState>, key: KeyEvent): PromptStep<string, ReturnType<typeof createEditorState>>;
|
|
409
432
|
|
|
410
433
|
/**
|
|
411
|
-
*
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
* @remarks
|
|
415
|
-
* Built by {@link import('./helpers.js').createEditorState}; advanced by
|
|
416
|
-
* {@link import('./helpers.js').editorReduce}. A printable key appends to `current`; `return`
|
|
417
|
-
* commits `current` to `lines` and starts a fresh line; ctrl-d finishes, submitting
|
|
418
|
-
* `lines + current` joined by newlines (or `default` when empty). The whole text is validated
|
|
419
|
-
* on finish.
|
|
420
|
-
*/
|
|
421
|
-
export declare interface EditorState {
|
|
422
|
-
readonly message: string;
|
|
423
|
-
readonly default: string;
|
|
424
|
-
readonly validator: Validator;
|
|
425
|
-
readonly styler: StylerInterface;
|
|
426
|
-
readonly lines: readonly string[];
|
|
427
|
-
readonly current: string;
|
|
428
|
-
readonly error?: string;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
/** Render an {@link EditorState} as a MULTI-LINE styled view — the header (with a Ctrl+D hint), the committed lines, the in-progress line, and any error. */
|
|
432
|
-
export declare function editorView(state: EditorState): string;
|
|
433
|
-
|
|
434
|
-
/** Matches an email address — a non-trivial `local@domain.tld` shape. The `email` rule tests against this. */
|
|
435
|
-
export declare const EMAIL_PATTERN: RegExp;
|
|
434
|
+
* Render an editor-field key state as a multi-line styled view with its finish hint.
|
|
435
|
+
*/
|
|
436
|
+
export declare function editorView(state: ReturnType<typeof createEditorState>): string;
|
|
436
437
|
|
|
437
|
-
/** The styled error line (`✖ message`)
|
|
438
|
-
export declare function errorLine(styler: StylerInterface, message: string): string;
|
|
438
|
+
/** The styled error line (`✖ message`) a form driver appends for a field failure. */
|
|
439
|
+
export declare function errorLine(styler: StylerInterface, theme: PromptTheme, message: string): string;
|
|
439
440
|
|
|
440
441
|
/** Escape (ESC, U+001B) — the lone byte, and the lead byte of every CSI / SS3 sequence. */
|
|
441
442
|
export declare const ESCAPE: string;
|
|
442
443
|
|
|
443
444
|
/**
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
*
|
|
447
|
-
*
|
|
448
|
-
* @remarks
|
|
449
|
-
* A function `check` is the custom-override path: it is called and its `true` ⇒ pass, a string
|
|
450
|
-
* ⇒ that message, anything else ⇒ the generic {@link RULE_MESSAGES.invalid}. A primitive `check`
|
|
451
|
-
* runs the named built-in: `required` (non-empty trimmed), `minimum` / `maximum` (length
|
|
452
|
-
* bounds, the message interpolated with the count), `pattern` (a regex source), and the
|
|
453
|
-
* `email` / `url` / `numeric` / `integer` / `alphanumeric` pattern tests.
|
|
454
|
-
*
|
|
455
|
-
* @param rule - The rule name (`'required'`, `'minimum'`, …)
|
|
456
|
-
* @param check - The configured value (a primitive toggle / bound / pattern, or a custom {@link Validator})
|
|
457
|
-
* @param input - The input string to test
|
|
458
|
-
* @returns The error message when the rule fails, else `undefined`
|
|
459
|
-
*/
|
|
460
|
-
export declare function evaluateRule(rule: string, check: boolean | number | string | Validator, input: string): string | undefined;
|
|
461
|
-
|
|
462
|
-
/**
|
|
463
|
-
* A minimal `fetch` — the subset of the global `fetch` the {@link PromptClient} uses (open the
|
|
464
|
-
* SSE stream, POST an answer). Injected so a test drives the client with a controlled
|
|
465
|
-
* `Response` (a scripted SSE `ReadableStream`) instead of a real network.
|
|
445
|
+
* A minimal `fetch` — the subset of the global `fetch` a {@link PromptClientInterface} uses: open
|
|
446
|
+
* the SSE stream, POST an answer. Injected so a test drives the client with a scripted `Response`
|
|
447
|
+
* instead of a real network.
|
|
466
448
|
*/
|
|
467
449
|
export declare type FetchHandler = (input: string, init?: FetchInit) => Promise<Response>;
|
|
468
450
|
|
|
469
451
|
/**
|
|
470
|
-
* The request init
|
|
471
|
-
* `RequestInit` fields it actually sets
|
|
452
|
+
* The request init a {@link PromptClientInterface} passes to its {@link FetchHandler} — the
|
|
453
|
+
* `RequestInit` fields it actually sets.
|
|
472
454
|
*/
|
|
473
455
|
export declare interface FetchInit {
|
|
474
456
|
readonly method?: string;
|
|
@@ -477,55 +459,33 @@ export declare interface FetchInit {
|
|
|
477
459
|
readonly signal?: AbortSignal;
|
|
478
460
|
}
|
|
479
461
|
|
|
480
|
-
/** The min/max gate for a checkbox submit — the rejection message when `count` is out of range, else `undefined`. */
|
|
481
|
-
export declare function gateSelection(count: number, min?: number, max?: number): string | undefined;
|
|
482
|
-
|
|
483
462
|
/** The default {@link import('./types.js').FetchHandler} — the global `fetch`, adapted to the minimal injected shape the {@link import('./PromptClient.js').PromptClient} uses. */
|
|
484
463
|
export declare function globalFetch(input: string, init?: FetchInit): Promise<Response>;
|
|
485
464
|
|
|
486
|
-
/** The auth-token request header the {@link import('./types.js').
|
|
465
|
+
/** The auth-token request header the {@link import('./types.js').PromptClientInterface} sends. */
|
|
487
466
|
export declare const HEADER_TOKEN = "x-orkestrel-token";
|
|
488
467
|
|
|
489
|
-
/**
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
468
|
+
/**
|
|
469
|
+
* Render a prompt header followed by a key hint painted with the `hint` role, or the header alone
|
|
470
|
+
* when no hint is supplied.
|
|
471
|
+
*
|
|
472
|
+
* @param styler - The console styler that renders each role
|
|
473
|
+
* @param theme - The resolved prompt theme
|
|
474
|
+
* @param message - The prompt's question text
|
|
475
|
+
* @param hint - The optional key hint to append
|
|
476
|
+
* @returns The rendered header with the optional hint
|
|
477
|
+
*/
|
|
478
|
+
export declare function hintedHeader(styler: StylerInterface, theme: PromptTheme, message: string, hint?: string): string;
|
|
496
479
|
|
|
497
480
|
/**
|
|
498
481
|
* Advance an input prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`
|
|
499
482
|
* reducer. Printable characters extend the value; backspace shrinks it; ctrl-u clears it; ctrl-c
|
|
500
|
-
* cancels; return
|
|
501
|
-
* invalid submit stays active with the error in the view.
|
|
483
|
+
* cancels; return produces the candidate value, with an empty line falling back to the default.
|
|
502
484
|
*/
|
|
503
|
-
export declare function inputReduce(state:
|
|
485
|
+
export declare function inputReduce(state: ReturnType<typeof createInputState>, key: KeyEvent): PromptStep<string, ReturnType<typeof createInputState>>;
|
|
504
486
|
|
|
505
|
-
/**
|
|
506
|
-
|
|
507
|
-
* the accumulated `value`, and the current `error` (when the last submit failed validation).
|
|
508
|
-
*
|
|
509
|
-
* @remarks
|
|
510
|
-
* Built by {@link import('./helpers.js').createInputState}; advanced by
|
|
511
|
-
* {@link import('./helpers.js').inputReduce}. `value` accumulates printable characters and
|
|
512
|
-
* shrinks on backspace; `error` holds the validation message shown in the view after a
|
|
513
|
-
* rejected submit (cleared on the next keystroke).
|
|
514
|
-
*/
|
|
515
|
-
export declare interface InputState {
|
|
516
|
-
readonly message: string;
|
|
517
|
-
readonly default: string;
|
|
518
|
-
readonly validator: Validator;
|
|
519
|
-
readonly styler: StylerInterface;
|
|
520
|
-
readonly value: string;
|
|
521
|
-
readonly error?: string;
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
/** Render an {@link InputState} as a styled view — the header, the typed value (or dimmed default hint), and any error. */
|
|
525
|
-
export declare function inputView(state: InputState): string;
|
|
526
|
-
|
|
527
|
-
/** Matches an integer (optional sign). The `integer` rule tests against this. */
|
|
528
|
-
export declare const INTEGER_PATTERN: RegExp;
|
|
487
|
+
/** Render a text-field key state as a styled view. */
|
|
488
|
+
export declare function inputView(state: ReturnType<typeof createInputState>): string;
|
|
529
489
|
|
|
530
490
|
/**
|
|
531
491
|
* Whether a caught value is an `AbortError` — the {@link import('./PromptClient.js').PromptClient}
|
|
@@ -534,15 +494,6 @@ export declare const INTEGER_PATTERN: RegExp;
|
|
|
534
494
|
*/
|
|
535
495
|
export declare function isAbortError(error: unknown): boolean;
|
|
536
496
|
|
|
537
|
-
/** Narrow an unknown wire payload to an answer POST body — a non-empty `id` string plus a `value` key (of any shape) present. */
|
|
538
|
-
export declare function isAnswerPayload(value: unknown): value is {
|
|
539
|
-
readonly id: string;
|
|
540
|
-
readonly value: unknown;
|
|
541
|
-
};
|
|
542
|
-
|
|
543
|
-
/** Narrow an unknown value to a {@link CheckboxChoice} — the `recordOf` shape inlined so no non-exported member lingers (§5). */
|
|
544
|
-
export declare function isCheckboxChoice(value: unknown): value is CheckboxChoice;
|
|
545
|
-
|
|
546
497
|
/**
|
|
547
498
|
* Whether `url` is an INSECURE remote endpoint — a plain `http://` URL whose host is NOT a
|
|
548
499
|
* loopback address. Pure string parsing (no `URL` global), so it stays total on malformed input.
|
|
@@ -565,25 +516,23 @@ export declare function isCheckboxChoice(value: unknown): value is CheckboxChoic
|
|
|
565
516
|
export declare function isInsecureRemote(url: string): boolean;
|
|
566
517
|
|
|
567
518
|
/**
|
|
568
|
-
* Narrow an unknown wire value to a {@link
|
|
519
|
+
* Narrow an unknown wire value to a {@link PendingForm} envelope.
|
|
520
|
+
*
|
|
521
|
+
* @remarks
|
|
522
|
+
* This guard checks the transport record and proves only that `schema` is a record. The Form
|
|
523
|
+
* package's `parseForm` owns the schema payload and its semantic audit.
|
|
569
524
|
*
|
|
570
525
|
* @param value - The decoded wire value to inspect
|
|
571
|
-
* @returns Whether
|
|
526
|
+
* @returns Whether the value is a complete pending-form envelope
|
|
572
527
|
*/
|
|
573
|
-
export declare
|
|
528
|
+
export declare function isPendingForm(value: unknown): value is PendingForm;
|
|
574
529
|
|
|
575
|
-
/** Narrow an unknown value to a {@link
|
|
576
|
-
export declare const
|
|
530
|
+
/** Narrow an unknown value to a {@link PendingFormStatus}. */
|
|
531
|
+
export declare const isPendingFormStatus: Guard<PendingFormStatus>;
|
|
577
532
|
|
|
578
533
|
/** Whether a single character is a printable (non-control) character — used by {@link parseKey}'s char fallback. */
|
|
579
534
|
export declare function isPrintable(character: string): boolean;
|
|
580
535
|
|
|
581
|
-
/** Narrow an unknown value to a {@link PromptChoice} — the `recordOf` shape inlined so no non-exported member lingers (§5). */
|
|
582
|
-
export declare function isPromptChoice(value: unknown): value is PromptChoice;
|
|
583
|
-
|
|
584
|
-
/** Narrow an unknown value to a {@link PromptType} — one of the six prompt forms. */
|
|
585
|
-
export declare const isPromptType: Guard<PromptType>;
|
|
586
|
-
|
|
587
536
|
/**
|
|
588
537
|
* Narrow an unknown caught value to a {@link TerminalError}.
|
|
589
538
|
*
|
|
@@ -593,9 +542,11 @@ export declare const isPromptType: Guard<PromptType>;
|
|
|
593
542
|
* @example
|
|
594
543
|
* ```ts
|
|
595
544
|
* try {
|
|
596
|
-
*
|
|
545
|
+
* await terminal.ask(form)
|
|
597
546
|
* } catch (error) {
|
|
598
|
-
* if (isTerminalError(error) && error.code === '
|
|
547
|
+
* if (isTerminalError(error) && error.code === 'CANCEL') {
|
|
548
|
+
* // the person aborted
|
|
549
|
+
* }
|
|
599
550
|
* }
|
|
600
551
|
* ```
|
|
601
552
|
*/
|
|
@@ -604,6 +555,14 @@ export declare function isTerminalError(value: unknown): value is TerminalError;
|
|
|
604
555
|
/** Narrow an unknown value to a {@link TerminalSnapshot}. */
|
|
605
556
|
export declare const isTerminalSnapshot: Guard<TerminalSnapshot>;
|
|
606
557
|
|
|
558
|
+
/**
|
|
559
|
+
* Narrow an unknown value to a transport-neutral {@link WireEvent}.
|
|
560
|
+
*
|
|
561
|
+
* @param value - The candidate wire event
|
|
562
|
+
* @returns Whether the value carries an event name, serialized data, and an optional id
|
|
563
|
+
*/
|
|
564
|
+
export declare const isWireEvent: Guard<WireEvent>;
|
|
565
|
+
|
|
607
566
|
/**
|
|
608
567
|
* The Control Sequence Introducer lead (`ESC[`) for the navigation keys — the prefix of the
|
|
609
568
|
* arrow / home / end / delete sequences {@link SEQUENCE_NAMES} is keyed by. Named `KEY_CSI`
|
|
@@ -616,23 +575,21 @@ export declare const KEY_CSI: string;
|
|
|
616
575
|
export declare const KEY_SS3: string;
|
|
617
576
|
|
|
618
577
|
/**
|
|
619
|
-
* One decoded keypress — the
|
|
620
|
-
*
|
|
621
|
-
*
|
|
622
|
-
*
|
|
578
|
+
* One decoded keypress — the TTY-agnostic representation of a single key, the output of
|
|
579
|
+
* {@link import('./helpers.js').parseKey}. A driver reads `name` and the modifier flags to decide
|
|
580
|
+
* its transition; `sequence` is preserved so a printable character round-trips and an unknown
|
|
581
|
+
* escape is never lost.
|
|
623
582
|
*
|
|
624
583
|
* @remarks
|
|
625
|
-
* - `name` — the canonical key name: a control
|
|
626
|
-
* `
|
|
627
|
-
*
|
|
628
|
-
*
|
|
629
|
-
*
|
|
630
|
-
* - `sequence` — the exact input bytes as a string (a `Uint8Array` is decoded UTF-8). The
|
|
631
|
-
*
|
|
632
|
-
*
|
|
633
|
-
* -
|
|
634
|
-
* (ctrl-c / ctrl-d / ctrl-u / ctrl-a / ctrl-e and the like); `meta` is `true` for an
|
|
635
|
-
* ESC-prefixed (Alt) sequence; `shift` is `true` for an uppercase-letter printable.
|
|
584
|
+
* - `name` — the canonical key name: a control or navigation key (`return`, `backspace`, `tab`,
|
|
585
|
+
* `escape`, `up` / `down` / `left` / `right`, `space`, `home`, `end`, `delete`), a named ctrl
|
|
586
|
+
* combo (`c` with `ctrl` true for ctrl-c, likewise `d` / `u` / `a` / `e`), or the printable
|
|
587
|
+
* character itself (`'a'`, `'7'`, `'?'`). An unrecognized sequence yields `name: ''`; the decoder
|
|
588
|
+
* is total and never throws.
|
|
589
|
+
* - `sequence` — the exact input bytes as a string (a `Uint8Array` is decoded UTF-8). The driver
|
|
590
|
+
* writes this verbatim for a printable key.
|
|
591
|
+
* - `ctrl` / `meta` / `shift` — the modifier flags. `ctrl` is true for a C0 control byte, `meta`
|
|
592
|
+
* for an ESC-prefixed (Alt) sequence, `shift` for an uppercase-letter printable.
|
|
636
593
|
*/
|
|
637
594
|
export declare interface KeyEvent {
|
|
638
595
|
readonly name: string;
|
|
@@ -684,43 +641,31 @@ export declare class MemoryTerminalStore implements TerminalStoreInterface {
|
|
|
684
641
|
/** Line feed (`\n`, U+000A) — Enter on some terminals / pasted input. */
|
|
685
642
|
export declare const NEWLINE: string;
|
|
686
643
|
|
|
687
|
-
/** Normalize a checkbox choice input into a full {@link CheckboxChoice} (a bare string becomes both name and value). */
|
|
688
|
-
export declare function normalizeCheckboxChoice(choice: string | CheckboxChoice): CheckboxChoice;
|
|
689
|
-
|
|
690
|
-
/** Normalize a select choice input into a full {@link PromptChoice} (a bare string becomes both name and value). */
|
|
691
|
-
export declare function normalizeChoice(choice: string | PromptChoice): PromptChoice;
|
|
692
|
-
|
|
693
|
-
/** Matches a numeric value (integer or decimal, optional sign). The `numeric` rule tests against this. */
|
|
694
|
-
export declare const NUMERIC_PATTERN: RegExp;
|
|
695
|
-
|
|
696
644
|
/**
|
|
697
|
-
* One parked
|
|
698
|
-
*
|
|
699
|
-
*
|
|
700
|
-
*
|
|
701
|
-
*
|
|
702
|
-
*
|
|
645
|
+
* One parked form's runtime state inside the broker — the live form, the wire-safe record the
|
|
646
|
+
* broker exposes, and the cancel for its expiry timer.
|
|
647
|
+
*
|
|
648
|
+
* @remarks
|
|
649
|
+
* `form` is the AUTHORITATIVE form the caller parked, not a copy: an answer fills and submits this
|
|
650
|
+
* one, so a `custom` rule that never crossed the wire still decides. Expiry destroys it, which
|
|
651
|
+
* abandons it and settles the caller's promise through the form's own lifecycle. `pending` is the
|
|
652
|
+
* wire record, whose `status` tracks the ticket.
|
|
703
653
|
*/
|
|
704
654
|
export declare interface Parked {
|
|
705
|
-
readonly
|
|
706
|
-
readonly
|
|
707
|
-
readonly expire: () => void;
|
|
655
|
+
readonly form: FormInterface;
|
|
656
|
+
readonly pending: PendingForm;
|
|
708
657
|
readonly cancel: TimerCancel;
|
|
709
658
|
}
|
|
710
659
|
|
|
711
660
|
/**
|
|
712
|
-
* The
|
|
713
|
-
*
|
|
661
|
+
* The parking envelope — everything the broker needs about a park that the form itself does not
|
|
662
|
+
* say.
|
|
714
663
|
*
|
|
715
664
|
* @remarks
|
|
716
|
-
*
|
|
717
|
-
*
|
|
718
|
-
* - `from` / `to` — set ONLY by a {@link TerminalManagerInterface} (the attribution edge); a
|
|
719
|
-
* direct broker caller leaves both `undefined`.
|
|
665
|
+
* `from` and `to` are the attribution edge, set ONLY by a {@link TerminalManagerInterface}: which
|
|
666
|
+
* endpoint asked, which endpoint must answer. A direct broker caller passes no request at all.
|
|
720
667
|
*/
|
|
721
668
|
export declare interface ParkRequest {
|
|
722
|
-
readonly form: PromptType;
|
|
723
|
-
readonly options: PromptFormOptions;
|
|
724
669
|
readonly from?: string;
|
|
725
670
|
readonly to?: string;
|
|
726
671
|
}
|
|
@@ -758,127 +703,70 @@ export declare interface ParkRequest {
|
|
|
758
703
|
*/
|
|
759
704
|
export declare function parseKey(input: string | Uint8Array): KeyEvent;
|
|
760
705
|
|
|
761
|
-
/**
|
|
762
|
-
* Parse a JSON wire string TOTAL — a malformed / empty payload yields `undefined` (the caller's
|
|
763
|
-
* guard then rejects it), never a throw. The {@link import('./PromptClient.js').PromptClient}
|
|
764
|
-
* decodes every SSE `data` field through this before §14-narrowing it.
|
|
765
|
-
*/
|
|
766
|
-
export declare function parseWireJSON(text: string): unknown;
|
|
767
|
-
|
|
768
|
-
/** The always-passing {@link Validator} — the resolved validator when no rules were supplied. */
|
|
769
|
-
export declare function passing(_input: string): true;
|
|
770
|
-
|
|
771
|
-
/** Options for a masked password {@link import('./helpers.js').passwordReduce} prompt. */
|
|
772
|
-
export declare interface PasswordOptions {
|
|
773
|
-
readonly message: string;
|
|
774
|
-
readonly mask?: string;
|
|
775
|
-
readonly validate?: Validator | ValidationRules;
|
|
776
|
-
readonly styler?: StylerInterface;
|
|
777
|
-
}
|
|
778
|
-
|
|
779
706
|
/**
|
|
780
707
|
* Advance a password prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`
|
|
781
708
|
* reducer. Identical line-editing to {@link inputReduce} (printable extends, backspace shrinks,
|
|
782
|
-
* ctrl-u clears, ctrl-c cancels) but the view masks the value
|
|
783
|
-
* validator (no default fallback — a password has no echoed default).
|
|
709
|
+
* ctrl-u clears, ctrl-c cancels) but the view masks the value. Return produces the candidate value.
|
|
784
710
|
*/
|
|
785
|
-
export declare function passwordReduce(state:
|
|
786
|
-
|
|
787
|
-
/**
|
|
788
|
-
* The immutable state of a password prompt — like {@link InputState} but with a `mask`
|
|
789
|
-
* character the view renders in place of each input character.
|
|
790
|
-
*
|
|
791
|
-
* @remarks
|
|
792
|
-
* Built by {@link import('./helpers.js').createPasswordState}; advanced by
|
|
793
|
-
* {@link import('./helpers.js').passwordReduce}. The `value` is the real (unmasked) input;
|
|
794
|
-
* the view shows `mask` repeated `value.length` times.
|
|
795
|
-
*/
|
|
796
|
-
export declare interface PasswordState {
|
|
797
|
-
readonly message: string;
|
|
798
|
-
readonly mask: string;
|
|
799
|
-
readonly validator: Validator;
|
|
800
|
-
readonly styler: StylerInterface;
|
|
801
|
-
readonly value: string;
|
|
802
|
-
readonly error?: string;
|
|
803
|
-
}
|
|
711
|
+
export declare function passwordReduce(state: ReturnType<typeof createPasswordState>, key: KeyEvent): PromptStep<string, ReturnType<typeof createPasswordState>>;
|
|
804
712
|
|
|
805
|
-
/** Render a
|
|
806
|
-
export declare function passwordView(state:
|
|
713
|
+
/** Render a password-field key state as a styled view. */
|
|
714
|
+
export declare function passwordView(state: ReturnType<typeof createPasswordState>): string;
|
|
807
715
|
|
|
808
716
|
/**
|
|
809
|
-
* One
|
|
810
|
-
*
|
|
811
|
-
*
|
|
717
|
+
* One form PARKED by the broker — an id-keyed, wire-safe record of a live form awaiting a remote
|
|
718
|
+
* answer. The value a `pending` listener receives and the broker serializes over SSE to a
|
|
719
|
+
* {@link PromptClientInterface}.
|
|
812
720
|
*
|
|
813
721
|
* @remarks
|
|
814
|
-
* - `id` — the unique id
|
|
815
|
-
*
|
|
816
|
-
*
|
|
817
|
-
*
|
|
818
|
-
* -
|
|
819
|
-
*
|
|
820
|
-
*
|
|
821
|
-
*
|
|
822
|
-
*
|
|
823
|
-
*
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
* {@link PromptInterface} used directly (no manager attribution).
|
|
827
|
-
*/
|
|
828
|
-
export declare interface PendingPrompt {
|
|
722
|
+
* - `id` — the unique id, minted with `crypto.randomUUID()`; the key for
|
|
723
|
+
* {@link PromptInterface.answer}.
|
|
724
|
+
* - `schema` — the parked form's schema projected to JSON by the dependency's own `serializeForm`.
|
|
725
|
+
* Every `custom` validator is dropped on the way out, so an authoritative rule the wire cannot
|
|
726
|
+
* carry stays server-side and is enforced when the answer comes back.
|
|
727
|
+
* - `status` — the ticket's {@link PendingFormStatus}.
|
|
728
|
+
* - `time` — the creation timestamp, ms since epoch.
|
|
729
|
+
* - `from` / `to` — the attribution edge a {@link TerminalManagerInterface} stamps on a parked
|
|
730
|
+
* form: which endpoint asked, which endpoint must answer. Both absent for a bare broker used
|
|
731
|
+
* directly.
|
|
732
|
+
*/
|
|
733
|
+
export declare interface PendingForm {
|
|
829
734
|
readonly id: string;
|
|
830
|
-
readonly
|
|
831
|
-
readonly
|
|
832
|
-
readonly options: Readonly<Record<string, unknown>>;
|
|
833
|
-
readonly status: PendingPromptStatus;
|
|
735
|
+
readonly schema: JSONRecord;
|
|
736
|
+
readonly status: PendingFormStatus;
|
|
834
737
|
readonly time: number;
|
|
835
738
|
readonly from?: string;
|
|
836
739
|
readonly to?: string;
|
|
837
740
|
}
|
|
838
741
|
|
|
839
742
|
/**
|
|
840
|
-
* The lifecycle status of a parked {@link
|
|
841
|
-
*
|
|
743
|
+
* The lifecycle status of a parked {@link PendingForm} — where the TICKET stands, which is not
|
|
744
|
+
* where the form stands. A ticket is `pending` until somebody answers it; the form it carries has
|
|
745
|
+
* its own status, and the two are separate facts about separate entities.
|
|
842
746
|
*
|
|
843
747
|
* @remarks
|
|
844
|
-
* - `pending` — parked, awaiting
|
|
845
|
-
* - `answered` — answered and accepted
|
|
846
|
-
* - `expired` — timed out
|
|
748
|
+
* - `pending` — parked, awaiting {@link PromptInterface.answer}.
|
|
749
|
+
* - `answered` — answered and accepted, so the parked form settled.
|
|
750
|
+
* - `expired` — timed out, or torn down by `destroy`, before an answer.
|
|
847
751
|
*/
|
|
848
|
-
export declare type
|
|
752
|
+
export declare type PendingFormStatus = 'pending' | 'answered' | 'expired';
|
|
849
753
|
|
|
850
754
|
/**
|
|
851
|
-
* The headless
|
|
852
|
-
*
|
|
853
|
-
* rejects on timeout / teardown). The tri-surface's headless arm: there is no terminal here, so a
|
|
854
|
-
* transport forwards each `pending` event to whoever can answer, and {@link answer} resolves the
|
|
855
|
-
* parked Promise — for environments where direct user access is unavailable (a headless server on
|
|
856
|
-
* stdio, a browser with no TTY, a prompt issued on one machine answered on another).
|
|
755
|
+
* The headless form broker. It parks live forms, exposes their serialized schemas, and applies
|
|
756
|
+
* remote answers to the authoritative form.
|
|
857
757
|
*
|
|
858
758
|
* @remarks
|
|
859
|
-
*
|
|
860
|
-
*
|
|
861
|
-
*
|
|
862
|
-
* ({@link serializePromptOptions}) so a transport can forward them as-is.
|
|
863
|
-
* - **Answer validates + type-checks.** {@link answer} runs the prompt's per-form gate: it
|
|
864
|
-
* type-checks `value` to the form (string / boolean / string[]) AND, for the text forms, runs
|
|
865
|
-
* the validator resolved from the original `validate` rules. A rejected answer returns `false`
|
|
866
|
-
* and the prompt stays `pending`; an accepted answer resolves the Promise, emits `answer`, and
|
|
867
|
-
* removes the prompt.
|
|
868
|
-
* - **Timeout → expire → reject.** An unanswered prompt expires after `timeout` ms (via the
|
|
869
|
-
* INJECTED timer): `expire` fires and the parked Promise rejects with a {@link TerminalError}
|
|
870
|
-
* (`code: 'EXPIRE'`). {@link destroy} expires every still-pending prompt the same way.
|
|
871
|
-
* - **Deterministic.** The timer is injectable ({@link import('./types.js').TimerHandler}); a test
|
|
872
|
-
* supplies one that fires on demand, so expiry is driven without real time.
|
|
759
|
+
* A parked record carries one call to `serializeForm`. A failed fill or submit leaves the record
|
|
760
|
+
* parked for another answer. A successful submit settles the form once, emits `answer`, and removes
|
|
761
|
+
* the record. Timeout and teardown abandon every unsettled form through its own `destroy` method.
|
|
873
762
|
*
|
|
874
763
|
* @example
|
|
875
764
|
* ```ts
|
|
876
|
-
* const
|
|
877
|
-
* prompt
|
|
878
|
-
*
|
|
879
|
-
*
|
|
880
|
-
*
|
|
881
|
-
* prompt.answer(id, 'Ada') // resolves the awaited input() above
|
|
765
|
+
* const form = createForm({ fields: [{ control: 'text', name: 'name' }] })
|
|
766
|
+
* const prompt = createPrompt()
|
|
767
|
+
* const id = prompt.park(form)
|
|
768
|
+
* prompt.answer(id, { name: 'Ada' })
|
|
769
|
+
* await form.answer // { name: 'Ada' }
|
|
882
770
|
* ```
|
|
883
771
|
*/
|
|
884
772
|
export declare class Prompt implements PromptInterface {
|
|
@@ -886,25 +774,16 @@ export declare class Prompt implements PromptInterface {
|
|
|
886
774
|
constructor(options?: PromptOptions);
|
|
887
775
|
get emitter(): EmitterInterface<PromptEventMap>;
|
|
888
776
|
get count(): number;
|
|
889
|
-
pending(): readonly
|
|
890
|
-
pending(id: string):
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
input(options: InputOptions): Promise<string>;
|
|
894
|
-
password(options: PasswordOptions): Promise<string>;
|
|
895
|
-
confirm(options: ConfirmOptions): Promise<boolean>;
|
|
896
|
-
select(options: SelectOptions): Promise<string>;
|
|
897
|
-
checkbox(options: CheckboxOptions): Promise<readonly string[]>;
|
|
898
|
-
editor(options: EditorOptions): Promise<string>;
|
|
777
|
+
pending(): readonly PendingForm[];
|
|
778
|
+
pending(id: string): PendingForm | undefined;
|
|
779
|
+
park(form: FormInterface, request?: ParkRequest): string;
|
|
780
|
+
answer(id: string, values: FormValues): Result<FormValues, AnswerError>;
|
|
899
781
|
destroy(): void;
|
|
900
782
|
}
|
|
901
783
|
|
|
902
784
|
/**
|
|
903
|
-
* The
|
|
904
|
-
*
|
|
905
|
-
* {@link import('@orkestrel/console').StylerInterface} at render time, never baked into the
|
|
906
|
-
* constant (AGENTS — styling orthogonal to data; the rework fixes the terminal's ANSI-in-the-icon).
|
|
907
|
-
* Frozen.
|
|
785
|
+
* The six default glyphs {@link DEFAULT_PROMPT_THEME} assembles its `icons` from. Read only when
|
|
786
|
+
* the default theme is assembled; a view reads its resolved theme and never this constant. Frozen.
|
|
908
787
|
*
|
|
909
788
|
* @remarks
|
|
910
789
|
* - `question` — the leading mark on a prompt's message line.
|
|
@@ -921,49 +800,39 @@ export declare const PROMPT_ICONS: Readonly<{
|
|
|
921
800
|
unchecked: "☐";
|
|
922
801
|
}>;
|
|
923
802
|
|
|
924
|
-
/**
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
803
|
+
/**
|
|
804
|
+
* Every {@link import('./types.js').PromptRole}, in one frozen list — the role axis's source of
|
|
805
|
+
* truth. {@link import('./helpers.js').createPromptTheme} walks it to merge a partial theme, and
|
|
806
|
+
* a consumer building a complete role map reads it rather than retyping every name.
|
|
807
|
+
*/
|
|
808
|
+
export declare const PROMPT_ROLES: readonly PromptRole[];
|
|
930
809
|
|
|
931
810
|
/**
|
|
932
|
-
* The SSE
|
|
933
|
-
*
|
|
934
|
-
* serialized pending prompts, dispatches EACH to a LOCAL {@link PromptFormInterface} terminal (so
|
|
935
|
-
* a human at THIS machine answers a prompt parked elsewhere), and POSTs the answer back.
|
|
936
|
-
* Universal — `fetch` + SSE are web-standard, so it runs in a browser or on a server; the
|
|
937
|
-
* injected `fetch` / timer make it fully deterministic in tests.
|
|
811
|
+
* The SSE form bridge. It ingests serialized forms from a remote broker, renders them through a
|
|
812
|
+
* local terminal, and posts answers back without blocking the event stream.
|
|
938
813
|
*
|
|
939
814
|
* @remarks
|
|
940
|
-
* - **Connect + reconnect.** {@link connect} opens the SSE stream
|
|
941
|
-
*
|
|
942
|
-
*
|
|
943
|
-
*
|
|
944
|
-
*
|
|
945
|
-
*
|
|
946
|
-
*
|
|
947
|
-
*
|
|
948
|
-
*
|
|
949
|
-
*
|
|
950
|
-
*
|
|
951
|
-
*
|
|
952
|
-
*
|
|
953
|
-
* `shutdown` event calls {@link disconnect} (not {@link destroy}) — the client stops streaming
|
|
954
|
-
* without auto-reconnect but stays reusable; a later {@link connect} recovers it.
|
|
955
|
-
* - **Lean events (§13).** `connect` / `disconnect` / `expire` / `error` — errors are `unknown`.
|
|
956
|
-
* `disconnect` fires exactly once per connected-to-disconnected transition, whether triggered by
|
|
957
|
-
* the server ending the stream cleanly or by a deliberate {@link disconnect} / {@link destroy}.
|
|
815
|
+
* - **Connect + reconnect.** {@link connect} opens the SSE stream and reconnects after a transport
|
|
816
|
+
* drop with the injected backoff unless reconnect is disabled, the client was destroyed, or
|
|
817
|
+
* {@link disconnect} deliberately stopped it.
|
|
818
|
+
* - **Ingest + render.** Each `pending` envelope passes through `isPendingForm`, Form's `parseForm`,
|
|
819
|
+
* and terminal's `sanitizeSchema`, then enters a serial render queue. The SSE reader never awaits
|
|
820
|
+
* that queue, so `expire` and `shutdown` remain live while a person is answering.
|
|
821
|
+
* - **Safe local form.** The rendering copy omits every wire `pattern`, because Form compiles a
|
|
822
|
+
* pattern during local evaluation. The broker's parked form retains it and remains authoritative.
|
|
823
|
+
* - **Refusal retry.** A structured `rejected` response seeds a new rendering form with the values
|
|
824
|
+
* just submitted, applies every {@link FieldError} through `invalidate`, and asks again. No retry
|
|
825
|
+
* counter truncates the loop; acceptance, expiry, and shutdown are its bounds.
|
|
826
|
+
* - **Replay safety.** A replayed id is skipped while it is queued, rendering, or posting. Once an
|
|
827
|
+
* attempt ends, a later delivery of that id may be rendered again.
|
|
958
828
|
*
|
|
959
829
|
* @example
|
|
960
830
|
* ```ts
|
|
961
831
|
* const client = createPromptClient({
|
|
962
832
|
* url: 'http://localhost:3001/prompts',
|
|
963
|
-
* terminal: createTerminal(),
|
|
964
|
-
* on: { connect: () => log('connected') },
|
|
833
|
+
* terminal: createTerminal(),
|
|
965
834
|
* })
|
|
966
|
-
* await client.connect()
|
|
835
|
+
* await client.connect()
|
|
967
836
|
* ```
|
|
968
837
|
*/
|
|
969
838
|
export declare class PromptClient implements PromptClientInterface {
|
|
@@ -978,13 +847,15 @@ export declare class PromptClient implements PromptClientInterface {
|
|
|
978
847
|
}
|
|
979
848
|
|
|
980
849
|
/**
|
|
981
|
-
* The client's event map
|
|
850
|
+
* The client's event map — lean, errors `unknown`, no listener-error event.
|
|
982
851
|
*
|
|
983
852
|
* @remarks
|
|
984
853
|
* - `connect` — the SSE stream opened.
|
|
985
|
-
* - `disconnect` — the SSE stream closed
|
|
986
|
-
*
|
|
987
|
-
* - `
|
|
854
|
+
* - `disconnect` — the SSE stream closed, by the server or by
|
|
855
|
+
* {@link PromptClientInterface.disconnect}.
|
|
856
|
+
* - `expire` — the remote broker signalled that a parked form expired, carrying its id. The client
|
|
857
|
+
* destroys the local form rendering it, or drops it from the queue if it has not started.
|
|
858
|
+
* - `error` — a connection, render, or POST fault.
|
|
988
859
|
*/
|
|
989
860
|
export declare type PromptClientEventMap = {
|
|
990
861
|
readonly connect: readonly [];
|
|
@@ -994,17 +865,22 @@ export declare type PromptClientEventMap = {
|
|
|
994
865
|
};
|
|
995
866
|
|
|
996
867
|
/**
|
|
997
|
-
* The SSE
|
|
998
|
-
*
|
|
999
|
-
*
|
|
1000
|
-
*
|
|
868
|
+
* The SSE form BRIDGE — the client-side counterpart to {@link PromptInterface}. It receives
|
|
869
|
+
* serialized {@link PendingForm} records from a remote broker, rebuilds each schema locally, drives
|
|
870
|
+
* it through a {@link TerminalInterface}, and POSTs the answer back, so a human at this machine
|
|
871
|
+
* answers forms a broker parked elsewhere.
|
|
1001
872
|
*
|
|
1002
873
|
* @remarks
|
|
1003
|
-
* - **Connect.** {@link connect} opens the SSE stream
|
|
1004
|
-
*
|
|
1005
|
-
*
|
|
1006
|
-
* - **
|
|
1007
|
-
*
|
|
874
|
+
* - **Connect.** {@link connect} opens the SSE stream through the injected `fetch` and resolves
|
|
875
|
+
* when the stream ends. It reconnects on the `delay` backoff unless `reconnect` is false or the
|
|
876
|
+
* client was destroyed.
|
|
877
|
+
* - **Ingest, then render.** Ingestion never waits on a render. Each decoded record is narrowed,
|
|
878
|
+
* its schema parsed and sanitized, and queued; one form is driven at a time while the stream
|
|
879
|
+
* keeps reading, so an unanswered form never starves the connection.
|
|
880
|
+
* - **Never trust the wire.** Every rendered string is sanitized, and a `pattern` that arrived over
|
|
881
|
+
* the wire is never executed locally. The authoritative form decides.
|
|
882
|
+
* - **Refusal retries.** A rejected answer comes back with the parked form's own errors; the client
|
|
883
|
+
* applies them to the local form and asks again until the answer is accepted or the form expires.
|
|
1008
884
|
* - **`connected`** reflects whether the stream is currently open.
|
|
1009
885
|
*/
|
|
1010
886
|
export declare interface PromptClientInterface {
|
|
@@ -1017,27 +893,27 @@ export declare interface PromptClientInterface {
|
|
|
1017
893
|
}
|
|
1018
894
|
|
|
1019
895
|
/**
|
|
1020
|
-
* Options for {@link import('./factories.js').createPromptClient}
|
|
896
|
+
* Options for {@link import('./factories.js').createPromptClient} and the
|
|
897
|
+
* {@link PromptClientInterface}.
|
|
1021
898
|
*
|
|
1022
899
|
* @remarks
|
|
1023
|
-
* - `url` — the remote broker's SSE endpoint
|
|
1024
|
-
* - `terminal` — the LOCAL {@link
|
|
1025
|
-
*
|
|
1026
|
-
* - `token` — an optional auth token, sent as the
|
|
1027
|
-
*
|
|
1028
|
-
* - `reconnect` — whether to reconnect after the stream drops
|
|
900
|
+
* - `url` — the remote broker's SSE endpoint. A GET opens the stream; answers POST back to it.
|
|
901
|
+
* - `terminal` — the LOCAL {@link TerminalInterface} each remote form is driven through, so a human
|
|
902
|
+
* at THIS machine answers a form parked elsewhere.
|
|
903
|
+
* - `token` — an optional auth token, sent as the {@link import('./constants.js').HEADER_TOKEN}
|
|
904
|
+
* header on every request.
|
|
905
|
+
* - `reconnect` — whether to reconnect after the stream drops, default true.
|
|
1029
906
|
* - `delay` — ms to wait before each reconnect attempt (default
|
|
1030
907
|
* {@link import('./constants.js').DEFAULT_RECONNECT_DELAY_MS}).
|
|
1031
|
-
* - `on` — initial {@link PromptClientEventMap} listeners
|
|
1032
|
-
* - `error` — the emitter's listener-error handler
|
|
1033
|
-
* - `fetch` — the injected {@link FetchHandler}
|
|
1034
|
-
*
|
|
1035
|
-
*
|
|
1036
|
-
* `setTimeout`); supply a deterministic timer to drive reconnection without real time.
|
|
908
|
+
* - `on` — initial {@link PromptClientEventMap} listeners.
|
|
909
|
+
* - `error` — the emitter's listener-error handler.
|
|
910
|
+
* - `fetch` — the injected {@link FetchHandler}, default the global `fetch`.
|
|
911
|
+
* - `timer` — the injected {@link TimerHandler} for the reconnect backoff, default the host
|
|
912
|
+
* `setTimeout`.
|
|
1037
913
|
*/
|
|
1038
914
|
export declare interface PromptClientOptions {
|
|
1039
915
|
readonly url: string;
|
|
1040
|
-
readonly terminal:
|
|
916
|
+
readonly terminal: TerminalInterface;
|
|
1041
917
|
readonly token?: string;
|
|
1042
918
|
readonly reconnect?: boolean;
|
|
1043
919
|
readonly delay?: number;
|
|
@@ -1048,98 +924,77 @@ export declare interface PromptClientOptions {
|
|
|
1048
924
|
}
|
|
1049
925
|
|
|
1050
926
|
/**
|
|
1051
|
-
* The broker's event map
|
|
927
|
+
* The broker's event map — lean, errors `unknown`, no listener-error event.
|
|
1052
928
|
*
|
|
1053
929
|
* @remarks
|
|
1054
|
-
* - `pending` — a
|
|
1055
|
-
*
|
|
1056
|
-
* - `
|
|
1057
|
-
* - `expire` — a parked prompt timed out (or was torn down) unanswered (carries its `id`).
|
|
930
|
+
* - `pending` — a form was parked; a transport forwards the wire record to remote clients.
|
|
931
|
+
* - `answer` — a parked form was answered and accepted, carrying its id and the settled values.
|
|
932
|
+
* - `expire` — a parked form timed out or was torn down unanswered, carrying its id.
|
|
1058
933
|
*/
|
|
1059
934
|
export declare type PromptEventMap = {
|
|
1060
|
-
readonly pending: readonly [
|
|
1061
|
-
readonly answer: readonly [id: string,
|
|
935
|
+
readonly pending: readonly [form: PendingForm];
|
|
936
|
+
readonly answer: readonly [id: string, values: FormValues];
|
|
1062
937
|
readonly expire: readonly [id: string];
|
|
1063
938
|
};
|
|
1064
939
|
|
|
940
|
+
/** The styled prompt-message header (`? message`) — the leading line every active prompt view shares, themed by the `question` + `message` roles. */
|
|
941
|
+
export declare function promptHeader(styler: StylerInterface, theme: PromptTheme, message: string): string;
|
|
942
|
+
|
|
1065
943
|
/**
|
|
1066
|
-
*
|
|
1067
|
-
*
|
|
1068
|
-
* `Terminal` driver (T-c) implement, so a prompt issued through this surface resolves the same
|
|
1069
|
-
* way on every surface (local TTY, headless broker, remote bridge).
|
|
944
|
+
* One glyph slot a rendered field draws — the icon axis of a {@link PromptTheme}. A named value
|
|
945
|
+
* set, not a toggle, so it stays a union.
|
|
1070
946
|
*
|
|
1071
947
|
* @remarks
|
|
1072
|
-
*
|
|
1073
|
-
* - `
|
|
1074
|
-
* - `
|
|
1075
|
-
* - `
|
|
1076
|
-
*
|
|
1077
|
-
* This is a behavioral CONTRACT (the method surface), not an observable entity — the broker and
|
|
1078
|
-
* the driver add their own emitter / lifecycle on top. The {@link PromptClient} dispatches a
|
|
1079
|
-
* remote {@link PendingPrompt} to a LOCAL `PromptFormInterface` (so a human at this machine
|
|
1080
|
-
* answers a prompt parked elsewhere).
|
|
1081
|
-
*/
|
|
1082
|
-
export declare interface PromptFormInterface {
|
|
1083
|
-
input(options: InputOptions): Promise<string>;
|
|
1084
|
-
password(options: PasswordOptions): Promise<string>;
|
|
1085
|
-
confirm(options: ConfirmOptions): Promise<boolean>;
|
|
1086
|
-
select(options: SelectOptions): Promise<string>;
|
|
1087
|
-
checkbox(options: CheckboxOptions): Promise<readonly string[]>;
|
|
1088
|
-
editor(options: EditorOptions): Promise<string>;
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
/**
|
|
1092
|
-
* The union of every prompt form's options bag — the `options` a {@link ParkRequest} carries,
|
|
1093
|
-
* narrowed at the call site by the paired {@link PromptType}.
|
|
948
|
+
* - `question` — the leading mark on a field's label line.
|
|
949
|
+
* - `pointer` — the cursor before the input or the focused choice row.
|
|
950
|
+
* - `dot` / `selected` — an unfocused / focused row marker in a choice list.
|
|
951
|
+
* - `checked` / `unchecked` — a checked / unchecked box in a multi-choice list.
|
|
952
|
+
* - `success` / `error` — the mark on a settled field's line / on its failure line.
|
|
1094
953
|
*/
|
|
1095
|
-
export declare type
|
|
1096
|
-
|
|
1097
|
-
/** The styled prompt-message header (`? message`) — the leading line every active prompt view shares. */
|
|
1098
|
-
export declare function promptHeader(styler: StylerInterface, message: string): string;
|
|
954
|
+
export declare type PromptIcon = 'question' | 'pointer' | 'dot' | 'selected' | 'checked' | 'unchecked' | 'success' | 'error';
|
|
1099
955
|
|
|
1100
956
|
/**
|
|
1101
|
-
* The headless
|
|
1102
|
-
*
|
|
1103
|
-
*
|
|
1104
|
-
*
|
|
1105
|
-
* can answer, and {@link answer} resolves the parked Promise.
|
|
957
|
+
* The headless form BROKER — parks a live form until somebody elsewhere answers it. The headless
|
|
958
|
+
* arm of the local-TTY / headless / remote trio: there is no terminal here, so a transport forwards
|
|
959
|
+
* each `pending` record to whoever can answer, and {@link answer} drives the parked form to
|
|
960
|
+
* settlement.
|
|
1106
961
|
*
|
|
1107
962
|
* @remarks
|
|
1108
|
-
* - **
|
|
1109
|
-
*
|
|
1110
|
-
*
|
|
1111
|
-
* - **
|
|
1112
|
-
*
|
|
1113
|
-
*
|
|
1114
|
-
* - **Timeout
|
|
1115
|
-
*
|
|
1116
|
-
*
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
export declare interface PromptInterface extends PromptFormInterface {
|
|
963
|
+
* - **The form is the unit.** {@link park} takes a live form, mints an id, emits `pending`, and
|
|
964
|
+
* returns the id. It wraps no promise, because the caller already holds one: the form's own
|
|
965
|
+
* `answer`.
|
|
966
|
+
* - **The parked form is authoritative.** {@link answer} fills and submits THAT form, so every rule
|
|
967
|
+
* it carries decides, including a `custom` validator the wire dropped. A refusal returns the
|
|
968
|
+
* form's own errors and leaves the form parked.
|
|
969
|
+
* - **Timeout abandons.** An unanswered form is destroyed after `timeout` ms; `expire` fires and
|
|
970
|
+
* the caller's promise rejects on the form's own lifecycle. The timer is injectable.
|
|
971
|
+
* - **Accessors.** `pending()` lists the parked records; `pending(id)` looks one up.
|
|
972
|
+
*/
|
|
973
|
+
export declare interface PromptInterface {
|
|
1120
974
|
readonly emitter: EmitterInterface<PromptEventMap>;
|
|
1121
975
|
readonly count: number;
|
|
1122
|
-
park(
|
|
1123
|
-
pending(): readonly
|
|
1124
|
-
pending(id: string):
|
|
1125
|
-
answer(id: string,
|
|
976
|
+
park(form: FormInterface, request?: ParkRequest): string;
|
|
977
|
+
pending(): readonly PendingForm[];
|
|
978
|
+
pending(id: string): PendingForm | undefined;
|
|
979
|
+
answer(id: string, values: FormValues): Result<FormValues, AnswerError>;
|
|
1126
980
|
destroy(): void;
|
|
1127
981
|
}
|
|
1128
982
|
|
|
1129
983
|
/**
|
|
1130
|
-
* Options for {@link import('./factories.js').createPrompt}
|
|
984
|
+
* Options for {@link import('./factories.js').createPrompt} and every {@link PromptInterface}
|
|
985
|
+
* broker, including one a {@link TerminalManagerInterface} mounts per endpoint.
|
|
1131
986
|
*
|
|
1132
987
|
* @remarks
|
|
1133
|
-
* - `on` — initial {@link PromptEventMap} listeners
|
|
1134
|
-
* - `error` — the emitter's listener-error handler
|
|
1135
|
-
* - `timeout` — ms a parked
|
|
988
|
+
* - `on` — initial {@link PromptEventMap} listeners.
|
|
989
|
+
* - `error` — the emitter's listener-error handler.
|
|
990
|
+
* - `timeout` — ms a parked form waits before it expires and is abandoned (default
|
|
1136
991
|
* {@link import('./constants.js').DEFAULT_PROMPT_TIMEOUT_MS}).
|
|
1137
|
-
* - `timer` — the injected {@link TimerHandler}
|
|
992
|
+
* - `timer` — the injected {@link TimerHandler}, default the host `setTimeout`; supply a
|
|
1138
993
|
* deterministic timer to drive expiry in tests without real time.
|
|
1139
|
-
* - `cap` — the maximum number of
|
|
1140
|
-
*
|
|
1141
|
-
*
|
|
1142
|
-
*
|
|
994
|
+
* - `cap` — the maximum number of forms this broker holds parked at once, default unbounded. Once
|
|
995
|
+
* `count` reaches `cap` a new park is refused with a
|
|
996
|
+
* {@link import('./errors.js').TerminalError} coded `LIMIT`, without parking, minting an id,
|
|
997
|
+
* emitting `pending`, or arming a timer. The runaway-asker memory ceiling.
|
|
1143
998
|
*/
|
|
1144
999
|
export declare interface PromptOptions {
|
|
1145
1000
|
readonly on?: EmitterHooks<PromptEventMap>;
|
|
@@ -1150,33 +1005,50 @@ export declare interface PromptOptions {
|
|
|
1150
1005
|
}
|
|
1151
1006
|
|
|
1152
1007
|
/**
|
|
1153
|
-
*
|
|
1154
|
-
*
|
|
1155
|
-
*
|
|
1156
|
-
*
|
|
1008
|
+
* One styling slot a rendered field paints through — the semantic axis of a {@link PromptTheme}. A
|
|
1009
|
+
* role says what a fragment MEANS; the theme decides what that meaning looks like, so a consumer
|
|
1010
|
+
* re-maps styled output by naming roles rather than reimplementing a renderer.
|
|
1011
|
+
*
|
|
1012
|
+
* @remarks
|
|
1013
|
+
* - `question` — the leading mark on an active field's line.
|
|
1014
|
+
* - `pointer` — the cursor before the input or the focused choice row.
|
|
1015
|
+
* - `message` — the field's own label text.
|
|
1016
|
+
* - `content` — the field's primary content: the typed value, the mask run, an unfocused choice
|
|
1017
|
+
* label, or a committed editor line. Its default is the EMPTY style, so unthemed content renders
|
|
1018
|
+
* as bare text.
|
|
1019
|
+
* - `success` / `error` — a settled field's mark / a failure mark and its message.
|
|
1020
|
+
* - `selected` — a chosen value: the checked box, the focused choice marker, the confirm default
|
|
1021
|
+
* letter.
|
|
1022
|
+
* - `focus` — the label of the row the cursor is on.
|
|
1023
|
+
* - `hint` — dim supplementary text: a default value, a key hint, a selection count, a committed
|
|
1024
|
+
* answer.
|
|
1025
|
+
* - `muted` — a dim off-state mark: an unfocused choice marker, an unchecked box, a fallback index.
|
|
1026
|
+
* - `description` — a choice's one-line help text.
|
|
1027
|
+
*/
|
|
1028
|
+
export declare type PromptRole = 'question' | 'pointer' | 'message' | 'content' | 'success' | 'error' | 'selected' | 'focus' | 'hint' | 'muted' | 'description';
|
|
1029
|
+
|
|
1030
|
+
/**
|
|
1031
|
+
* Where one field's reducer stands after a key. `active`: keep asking, because the key was
|
|
1032
|
+
* consumed or the answer was refused. `submit`: the field resolved with its `value`. `cancel`: the
|
|
1033
|
+
* user aborted with ctrl-c. Names its axis, never `kind`.
|
|
1157
1034
|
*/
|
|
1158
1035
|
export declare type PromptStatus = 'active' | 'submit' | 'cancel';
|
|
1159
1036
|
|
|
1160
1037
|
/**
|
|
1161
|
-
* The result of one reducer step — the next `state`, the rendered `view`, the `status`, and,
|
|
1162
|
-
*
|
|
1163
|
-
*
|
|
1164
|
-
* is `submit` — reads `value`.
|
|
1038
|
+
* The result of one reducer step — the next `state`, the rendered `view`, the `status`, and, on
|
|
1039
|
+
* `submit`, the resolved `value`. The whole contract between a pure reducer and the impure driver:
|
|
1040
|
+
* the driver applies the next `state`, writes the `view`, and reads `value` on `submit`.
|
|
1165
1041
|
*
|
|
1166
|
-
* @typeParam T - The
|
|
1167
|
-
*
|
|
1168
|
-
*
|
|
1169
|
-
* carried directly so `state` stays precisely typed with no union narrowing or assertion.
|
|
1042
|
+
* @typeParam T - The value this field resolves to, as its control admits it.
|
|
1043
|
+
* @typeParam S - The reducer's concrete state shape, carried directly so `state` stays precisely
|
|
1044
|
+
* typed with no union narrowing and no assertion.
|
|
1170
1045
|
*
|
|
1171
1046
|
* @remarks
|
|
1172
|
-
* - `state` — the next immutable
|
|
1173
|
-
*
|
|
1174
|
-
* - `view` — the styled string to render
|
|
1175
|
-
*
|
|
1176
|
-
*
|
|
1177
|
-
* - `status` — the {@link PromptStatus}: `active` to continue, `submit` when resolved, `cancel`
|
|
1178
|
-
* on abort.
|
|
1179
|
-
* - `value` — present ONLY on a `submit` step, carrying the prompt's resolved value.
|
|
1047
|
+
* - `state` — the next immutable state; feed it to the next reduce call. On `submit` or `cancel` it
|
|
1048
|
+
* is the final state.
|
|
1049
|
+
* - `view` — the styled string to render now, possibly multi-line. On a refused `submit` it carries
|
|
1050
|
+
* the failure; the driver re-renders it each step.
|
|
1051
|
+
* - `value` — present ONLY on a `submit` step.
|
|
1180
1052
|
*/
|
|
1181
1053
|
export declare interface PromptStep<T, S> {
|
|
1182
1054
|
readonly state: S;
|
|
@@ -1186,105 +1058,81 @@ export declare interface PromptStep<T, S> {
|
|
|
1186
1058
|
}
|
|
1187
1059
|
|
|
1188
1060
|
/**
|
|
1189
|
-
*
|
|
1190
|
-
*
|
|
1191
|
-
|
|
1192
|
-
|
|
1061
|
+
* A resolved PRESENTATION — the glyph for every {@link PromptIcon} and the console {@link Style}
|
|
1062
|
+
* for every {@link PromptRole}. Plain JSON data with no functions, so it crosses the wire with the
|
|
1063
|
+
* form it decorates. Built by {@link import('./helpers.js').createPromptTheme}.
|
|
1064
|
+
*
|
|
1065
|
+
* @remarks
|
|
1066
|
+
* A role's value is the console module's own {@link Style} — the one style model the whole console
|
|
1067
|
+
* and terminal system shares — so a renderer paints a role through
|
|
1068
|
+
* {@link import('@orkestrel/console').StylerInterface} and this package holds no second style
|
|
1069
|
+
* vocabulary. A `Style` carries a foreground, a background, and an attribute list, so a role can
|
|
1070
|
+
* express a background color, which a styler's accessor chain cannot name.
|
|
1071
|
+
*/
|
|
1072
|
+
export declare interface PromptTheme {
|
|
1073
|
+
readonly icons: Readonly<Record<PromptIcon, string>>;
|
|
1074
|
+
readonly roles: Readonly<Record<PromptRole, Style>>;
|
|
1075
|
+
}
|
|
1193
1076
|
|
|
1194
1077
|
/**
|
|
1195
|
-
* The
|
|
1196
|
-
*
|
|
1197
|
-
*
|
|
1078
|
+
* The PARTIAL {@link PromptTheme} an option bag carries — every icon and every role is optional,
|
|
1079
|
+
* and {@link import('./helpers.js').createPromptTheme} merges what is supplied over
|
|
1080
|
+
* {@link import('./constants.js').DEFAULT_PROMPT_THEME} leaf by leaf. Supplying one icon or one
|
|
1081
|
+
* role leaves every other slot at its default.
|
|
1198
1082
|
*/
|
|
1199
|
-
export declare
|
|
1083
|
+
export declare interface PromptThemeOptions {
|
|
1084
|
+
readonly icons?: Readonly<Partial<Record<PromptIcon, string>>>;
|
|
1085
|
+
readonly roles?: Readonly<Partial<Record<PromptRole, Style>>>;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
/** Carriage return (`\r`, U+000D) — Enter on most terminals. */
|
|
1089
|
+
export declare const RETURN: string;
|
|
1200
1090
|
|
|
1201
1091
|
/**
|
|
1202
|
-
*
|
|
1203
|
-
* {@link
|
|
1204
|
-
*
|
|
1205
|
-
*
|
|
1092
|
+
* Sanitize text for one single-line display slot. Composes console's ANSI {@link strip} and C0
|
|
1093
|
+
* {@link stripControls} passes with removal of tab, line feed, and carriage return.
|
|
1094
|
+
*
|
|
1095
|
+
* @param text - The text to sanitize for a glyph or hint slot
|
|
1096
|
+
* @returns The text with ANSI sequences, every C0 control character, and DEL removed
|
|
1097
|
+
*
|
|
1098
|
+
* @example
|
|
1099
|
+
* ```ts
|
|
1100
|
+
* sanitizeDisplayText('Q\rOVERWRITE\nNEXT\tX') // 'QOVERWRITENEXTX'
|
|
1101
|
+
* ```
|
|
1206
1102
|
*/
|
|
1207
|
-
export declare function
|
|
1208
|
-
|
|
1209
|
-
/** Read a `choices` option as a list of bare strings / full choices — each element narrowed by `guard`, off-shape elements stringified. */
|
|
1210
|
-
export declare function resolveChoices<TChoice extends PromptChoice | CheckboxChoice>(options: Readonly<Record<string, unknown>>, guard: Guard<TChoice>): ReadonlyArray<string | TChoice>;
|
|
1211
|
-
|
|
1212
|
-
/** Read one option by key, narrowed by `guard` — `undefined` when absent or off-shape (§14, never an `as`). */
|
|
1213
|
-
export declare function resolveOption<T>(options: Readonly<Record<string, unknown>>, key: string, guard: Guard<T>): T | undefined;
|
|
1103
|
+
export declare function sanitizeDisplayText(text: string): string;
|
|
1214
1104
|
|
|
1215
1105
|
/**
|
|
1216
|
-
*
|
|
1217
|
-
* composed {@link Validator}. A bare validator passes through; rules are appended in the fixed
|
|
1218
|
-
* order (required → minimum → maximum → pattern → email → url → numeric → integer → alphanumeric
|
|
1219
|
-
* → custom) and composed; absent / empty input yields an always-passing validator. Pure.
|
|
1106
|
+
* Sanitize every terminal-readable string in a parsed form schema.
|
|
1220
1107
|
*
|
|
1221
1108
|
* @remarks
|
|
1222
|
-
*
|
|
1223
|
-
*
|
|
1224
|
-
*
|
|
1225
|
-
*
|
|
1109
|
+
* Display strings pass through {@link sanitizeDisplayText}: labels, help, placeholders, masks,
|
|
1110
|
+
* choice labels and help, file accept entries, and pattern sources. Identity and answer strings
|
|
1111
|
+
* stay verbatim: schema, group, and field names, group references, choice values, and defaults.
|
|
1112
|
+
* Rewriting those would sever the rendering copy from the authoritative form. Field metadata is
|
|
1113
|
+
* removed because terminal neither renders nor interprets it. Pattern sources are sanitized as
|
|
1114
|
+
* text only and are never compiled or executed here.
|
|
1226
1115
|
*
|
|
1227
|
-
* @param
|
|
1228
|
-
* @returns
|
|
1116
|
+
* @param schema - A schema already accepted by the Form package's `parseForm`
|
|
1117
|
+
* @returns A new schema with terminal-readable strings sanitized and field metadata omitted
|
|
1229
1118
|
*
|
|
1230
1119
|
* @example
|
|
1231
1120
|
* ```ts
|
|
1232
|
-
*
|
|
1233
|
-
*
|
|
1234
|
-
* v('ab') // 'Must be at least 3 characters'
|
|
1235
|
-
* v('abc') // true
|
|
1121
|
+
* sanitizeSchema({ fields: [{ control: 'text', name: 'na\u001bme', label: 'N\u0000ame' }] })
|
|
1122
|
+
* // { fields: [{ control: 'text', name: 'na\u001bme', label: 'Name' }] }
|
|
1236
1123
|
* ```
|
|
1237
1124
|
*/
|
|
1238
|
-
export declare function
|
|
1239
|
-
|
|
1240
|
-
/** Carriage return (`\r`, U+000D) — Enter on most terminals. */
|
|
1241
|
-
export declare const RETURN: string;
|
|
1125
|
+
export declare function sanitizeSchema(schema: FormSchema): FormSchema;
|
|
1242
1126
|
|
|
1243
1127
|
/**
|
|
1244
|
-
*
|
|
1245
|
-
*
|
|
1246
|
-
*
|
|
1247
|
-
* truth for the rule-failure copy.
|
|
1248
|
-
*/
|
|
1249
|
-
export declare const RULE_MESSAGES: Readonly<{
|
|
1250
|
-
required: "This field is required";
|
|
1251
|
-
minimum: "Must be at least {count} characters";
|
|
1252
|
-
maximum: "Must be at most {count} characters";
|
|
1253
|
-
pattern: "Must match pattern: {pattern}";
|
|
1254
|
-
email: "Must be a valid email address";
|
|
1255
|
-
url: "Must be a valid URL";
|
|
1256
|
-
numeric: "Must be a numeric value";
|
|
1257
|
-
integer: "Must be an integer";
|
|
1258
|
-
alphanumeric: "Must contain only letters and digits";
|
|
1259
|
-
invalid: "Invalid input";
|
|
1260
|
-
}>;
|
|
1261
|
-
|
|
1262
|
-
/**
|
|
1263
|
-
* Sanitize a list of resolved choices' human-readable labels (`name` + `description`) with
|
|
1264
|
-
* {@link stripControls} — shared by the `select` and `checkbox` branches of
|
|
1265
|
-
* {@link dispatchPendingPrompt} so a remote-supplied choice can never inject raw control bytes
|
|
1266
|
-
* into the local terminal's rendered view.
|
|
1128
|
+
* Sanitize every glyph a wire-supplied {@link PromptThemeOptions} carries for a single-line display
|
|
1129
|
+
* slot. Only the icons need it: a role is guard-narrowed to a console {@link Style}, whose colors
|
|
1130
|
+
* and attributes are fixed name sets, so no role can carry a byte a terminal would act on.
|
|
1267
1131
|
*
|
|
1268
|
-
* @param
|
|
1269
|
-
*
|
|
1270
|
-
* @returns The same choices with every `name` / `description` control-stripped
|
|
1132
|
+
* @param theme - The narrowed theme options a remote prompt supplied
|
|
1133
|
+
* @returns The same theme with every supplied glyph sanitized for a single-line display slot
|
|
1271
1134
|
*/
|
|
1272
|
-
export declare function
|
|
1273
|
-
|
|
1274
|
-
/**
|
|
1275
|
-
* Options for a single-selection {@link import('./helpers.js').selectReduce} prompt.
|
|
1276
|
-
*
|
|
1277
|
-
* @remarks
|
|
1278
|
-
* `choices` accepts bare strings (used as both `name` and `value`) or full {@link PromptChoice}
|
|
1279
|
-
* objects; {@link import('./helpers.js').createSelectState} normalizes them. `default` pre-focuses
|
|
1280
|
-
* the choice whose `value` matches it.
|
|
1281
|
-
*/
|
|
1282
|
-
export declare interface SelectOptions {
|
|
1283
|
-
readonly message: string;
|
|
1284
|
-
readonly choices: ReadonlyArray<string | PromptChoice>;
|
|
1285
|
-
readonly default?: string;
|
|
1286
|
-
readonly styler?: StylerInterface;
|
|
1287
|
-
}
|
|
1135
|
+
export declare function sanitizeThemeIcons(theme: PromptThemeOptions): PromptThemeOptions;
|
|
1288
1136
|
|
|
1289
1137
|
/**
|
|
1290
1138
|
* Advance a select prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`
|
|
@@ -1292,26 +1140,10 @@ export declare interface SelectOptions {
|
|
|
1292
1140
|
* focused choice's `value`; ctrl-c cancels. An empty choice list can never submit (a higher layer
|
|
1293
1141
|
* guards against it); any other key is ignored.
|
|
1294
1142
|
*/
|
|
1295
|
-
export declare function selectReduce(state:
|
|
1143
|
+
export declare function selectReduce(state: ReturnType<typeof createSelectState>, key: KeyEvent): PromptStep<string, ReturnType<typeof createSelectState>>;
|
|
1296
1144
|
|
|
1297
|
-
/**
|
|
1298
|
-
|
|
1299
|
-
* `focused` index (the highlighted row).
|
|
1300
|
-
*
|
|
1301
|
-
* @remarks
|
|
1302
|
-
* Built by {@link import('./helpers.js').createSelectState}; advanced by
|
|
1303
|
-
* {@link import('./helpers.js').selectReduce}. `up` / `down` move `focused` (wrapping at the
|
|
1304
|
-
* ends); `return` submits the focused choice's `value`.
|
|
1305
|
-
*/
|
|
1306
|
-
export declare interface SelectState {
|
|
1307
|
-
readonly message: string;
|
|
1308
|
-
readonly choices: readonly PromptChoice[];
|
|
1309
|
-
readonly styler: StylerInterface;
|
|
1310
|
-
readonly focused: number;
|
|
1311
|
-
}
|
|
1312
|
-
|
|
1313
|
-
/** Render a {@link SelectState} as a MULTI-LINE styled view — the header followed by one row per choice, the focused row marked. */
|
|
1314
|
-
export declare function selectView(state: SelectState): string;
|
|
1145
|
+
/** Render a select-field key state as a multi-line styled view. */
|
|
1146
|
+
export declare function selectView(state: ReturnType<typeof createSelectState>): string;
|
|
1315
1147
|
|
|
1316
1148
|
/**
|
|
1317
1149
|
* The exact escape SEQUENCE → canonical key NAME table {@link import('./helpers.js').parseKey}
|
|
@@ -1327,53 +1159,20 @@ export declare function selectView(state: SelectState): string;
|
|
|
1327
1159
|
*/
|
|
1328
1160
|
export declare const SEQUENCE_NAMES: Readonly<Record<string, string>>;
|
|
1329
1161
|
|
|
1330
|
-
/** Strip functions from a `choices` option — each choice keeps its plain fields; a bare string passes through. */
|
|
1331
|
-
export declare function serializeChoices(choices: unknown): readonly unknown[];
|
|
1332
|
-
|
|
1333
1162
|
/** Serialize a parked prompt's expiry into a {@link WireEvent} — event `'expire'`, `data` the JSON-stringified `{ id }` payload. */
|
|
1334
1163
|
export declare function serializeExpire(id: string): WireEvent;
|
|
1335
1164
|
|
|
1336
|
-
/** Serialize a parked {@link
|
|
1337
|
-
export declare function serializePending(
|
|
1338
|
-
|
|
1339
|
-
/**
|
|
1340
|
-
* Produce the WIRE-SAFE form of a prompt's options — the {@link PendingPrompt.options} a broker
|
|
1341
|
-
* serializes over SSE. Drops everything that cannot cross the wire (a `styler`, and any
|
|
1342
|
-
* function-valued `validate` rule), while KEEPING the declarative data a remote client needs to
|
|
1343
|
-
* reconstruct the prompt: the {@link ValidationRules} as data, plus `message` / `choices` /
|
|
1344
|
-
* `default` / `mask` / `min` / `max`. This is WHY T-a's validation is rules-as-data: a `Validator`
|
|
1345
|
-
* FUNCTION can't be serialized, but its declarative rules can — the client rebuilds the validator
|
|
1346
|
-
* from them via {@link resolveValidation}.
|
|
1347
|
-
*
|
|
1348
|
-
* @remarks
|
|
1349
|
-
* - **Functions are dropped.** A top-level function value (e.g. a bare-`Validator` `validate`) is
|
|
1350
|
-
* omitted entirely; the `styler` (a fluent function-bearing object) is dropped by key.
|
|
1351
|
-
* - **`validate` rules are flattened.** A {@link ValidationRules} bag is copied with each
|
|
1352
|
-
* function rule replaced by `true` (the rule's INTENT survives as the built-in check; its
|
|
1353
|
-
* custom function does not). A bare-function `validate` is dropped (no declarative form to keep).
|
|
1354
|
-
* - **`choices` are function-stripped.** Each choice keeps its plain fields (`name` / `value` /
|
|
1355
|
-
* `description` / `checked`); a bare string passes through.
|
|
1356
|
-
*
|
|
1357
|
-
* @param options - The raw prompt options bag (may hold functions / a styler)
|
|
1358
|
-
* @returns A JSON-safe options record — only serializable, declarative data
|
|
1359
|
-
*/
|
|
1360
|
-
export declare function serializePromptOptions(options: object): Readonly<Record<string, unknown>>;
|
|
1165
|
+
/** Serialize a parked {@link PendingForm} into a {@link WireEvent}. */
|
|
1166
|
+
export declare function serializePending(form: PendingForm): WireEvent;
|
|
1361
1167
|
|
|
1362
1168
|
/** The {@link WireEvent} a broker/manager sends when it is going away — event `'shutdown'`, no payload. */
|
|
1363
1169
|
export declare function serializeShutdown(): WireEvent;
|
|
1364
1170
|
|
|
1365
|
-
/**
|
|
1366
|
-
* Flatten a `validate` option to its wire-safe {@link ValidationRules} DATA — a function rule
|
|
1367
|
-
* becomes `true` (its built-in check survives; its body cannot cross the wire). A bare-function
|
|
1368
|
-
* `validate` (no rules object) has no declarative form, so it yields `undefined` (dropped).
|
|
1369
|
-
*/
|
|
1370
|
-
export declare function serializeValidationRules(validate: unknown): Readonly<Record<string, unknown>> | undefined;
|
|
1371
|
-
|
|
1372
1171
|
/** Space (U+0020). */
|
|
1373
1172
|
export declare const SPACE = " ";
|
|
1374
1173
|
|
|
1375
1174
|
/**
|
|
1376
|
-
* The maximum number of characters the {@link import('./types.js').
|
|
1175
|
+
* The maximum number of characters the {@link import('./types.js').PromptClientInterface} lets its
|
|
1377
1176
|
* SSE parser buffer before treating the stream as hostile — 1 MiB, comfortably above any
|
|
1378
1177
|
* legitimate prompt payload. Passed as the `limit` to `createSSEParser` so an unterminated
|
|
1379
1178
|
* or oversized `data:` field cannot grow the buffer without bound (a memory-exhaustion guard).
|
|
@@ -1381,11 +1180,11 @@ export declare const SPACE = " ";
|
|
|
1381
1180
|
export declare const SSE_BUFFER_LIMIT = 1048576;
|
|
1382
1181
|
|
|
1383
1182
|
/**
|
|
1384
|
-
* The SSE `event:` names the broker emits and the {@link import('./types.js').
|
|
1183
|
+
* The SSE `event:` names the broker emits and the {@link import('./types.js').PromptClientInterface}
|
|
1385
1184
|
* dispatches on. Frozen; the source of truth for the wire event vocabulary.
|
|
1386
1185
|
*
|
|
1387
1186
|
* @remarks
|
|
1388
|
-
* - `pending` — a serialized {@link import('./types.js').
|
|
1187
|
+
* - `pending` — a serialized {@link import('./types.js').PendingForm} to dispatch and answer.
|
|
1389
1188
|
* - `expire` — an `{ id }` payload: the broker expired a parked prompt (the client drops it).
|
|
1390
1189
|
* - `shutdown` — the broker is going away; the client disconnects (no auto-reconnect) but stays reusable.
|
|
1391
1190
|
*/
|
|
@@ -1395,62 +1194,87 @@ export declare const SSE_EVENTS: Readonly<{
|
|
|
1395
1194
|
shutdown: "shutdown";
|
|
1396
1195
|
}>;
|
|
1397
1196
|
|
|
1398
|
-
/** The styled submit line (`✔ message`) — the committed header an interactive prompt shows once resolved. */
|
|
1399
|
-
export declare function submitHeader(styler: StylerInterface, message: string): string;
|
|
1197
|
+
/** The styled submit line (`✔ message`) — the committed header an interactive prompt shows once resolved, themed by the `success` + `message` roles. */
|
|
1198
|
+
export declare function submitHeader(styler: StylerInterface, theme: PromptTheme, message: string): string;
|
|
1400
1199
|
|
|
1401
1200
|
/** Tab (`\t`, U+0009). */
|
|
1402
1201
|
export declare const TAB: string;
|
|
1403
1202
|
|
|
1404
|
-
/**
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
readonly
|
|
1411
|
-
} | {
|
|
1412
|
-
readonly success: false;
|
|
1413
|
-
readonly error: TerminalAnswerError;
|
|
1203
|
+
/**
|
|
1204
|
+
* Why a {@link TerminalManagerInterface.answer} call refused — an {@link AnswerError} from the
|
|
1205
|
+
* endpoint's own broker, or `terminal` when no endpoint is mounted under that name. One
|
|
1206
|
+
* discriminant, `reason`, across both.
|
|
1207
|
+
*/
|
|
1208
|
+
export declare type TerminalAnswerError = AnswerError | {
|
|
1209
|
+
readonly reason: 'terminal';
|
|
1414
1210
|
};
|
|
1415
1211
|
|
|
1416
1212
|
/**
|
|
1417
|
-
*
|
|
1213
|
+
* The error the terminal surfaces for its own refusals: parking on a destroyed or full broker, an
|
|
1214
|
+
* unusable driver stream, a manager routing fault, or a ctrl-c cancellation. A parked form's own
|
|
1215
|
+
* lifecycle failures reject through the form's `answer` with the form package's error, never with
|
|
1216
|
+
* this one.
|
|
1418
1217
|
*
|
|
1419
1218
|
* @remarks
|
|
1420
|
-
* Carries a {@link TerminalErrorCode} and an optional `context` bag
|
|
1421
|
-
*
|
|
1422
|
-
*
|
|
1423
|
-
* `EXPIRE`); or when the user aborts an interactive server-`Terminal` prompt with ctrl-c
|
|
1424
|
-
* (`CANCEL`). Narrow a caught value with {@link isTerminalError} and branch on `error.code`.
|
|
1219
|
+
* Carries a {@link TerminalErrorCode} and an optional `context` bag naming the offending values:
|
|
1220
|
+
* `{ cap }` on `LIMIT`, `{ to, known }` on `TARGET`, and `{ from, to, path }` on `DEADLOCK`. Narrow
|
|
1221
|
+
* a caught value with {@link isTerminalError} and branch on `error.code`.
|
|
1425
1222
|
*/
|
|
1426
1223
|
export declare class TerminalError extends Error {
|
|
1427
1224
|
/** The machine-readable condition — see {@link TerminalErrorCode}. */
|
|
1428
1225
|
readonly code: TerminalErrorCode;
|
|
1429
|
-
/** An optional context bag naming the offending
|
|
1226
|
+
/** An optional context bag naming the offending values — see the class {@link TerminalError remarks}. */
|
|
1430
1227
|
readonly context?: Readonly<Record<string, unknown>>;
|
|
1431
1228
|
constructor(code: TerminalErrorCode, message: string, context?: Readonly<Record<string, unknown>>);
|
|
1432
1229
|
}
|
|
1433
1230
|
|
|
1434
1231
|
/**
|
|
1435
1232
|
* The machine-readable condition carried by a {@link import('./errors.js').TerminalError} — the
|
|
1436
|
-
* axis a `catch` branches on. Names its axis (the failure condition), never `kind
|
|
1233
|
+
* axis a `catch` branches on. Names its axis (the failure condition), never `kind`.
|
|
1437
1234
|
*
|
|
1438
1235
|
* @remarks
|
|
1439
|
-
*
|
|
1440
|
-
*
|
|
1441
|
-
*
|
|
1442
|
-
*
|
|
1443
|
-
* - `
|
|
1444
|
-
*
|
|
1445
|
-
*
|
|
1446
|
-
*
|
|
1236
|
+
* Every code here is terminal's own. A refusal that belongs to the form — a malformed schema, a
|
|
1237
|
+
* value a control cannot hold, a write to a settled form — arrives as the dependency's own
|
|
1238
|
+
* `FormError` and is never re-coded.
|
|
1239
|
+
*
|
|
1240
|
+
* - `EXPIRE` — `park` was called on an already-`destroy`ed broker: the given form is destroyed and
|
|
1241
|
+
* the call throws before minting an id. A parked form that times out is abandoned instead, not
|
|
1242
|
+
* coded `EXPIRE` — the broker destroys it and the caller's `answer` promise rejects on the
|
|
1243
|
+
* form's own lifecycle with the Form package's `ABANDONED` error.
|
|
1244
|
+
* - `CANCEL` — the user aborted at the server `Terminal` driver with ctrl-c.
|
|
1245
|
+
* - `DRIVER` — the driver could not read the terminal it was given.
|
|
1246
|
+
* - `DEADLOCK` — an endpoint was asked to answer its own question.
|
|
1247
|
+
* - `TARGET` — the named endpoint cannot be reached.
|
|
1248
|
+
* - `LIMIT` — the broker's optional `cap` on concurrently parked forms was already reached. The
|
|
1249
|
+
* new call is refused WITHOUT parking: no id, no `pending` event, no timer.
|
|
1250
|
+
* - `DESTROYED` — a call reached an already-destroyed {@link TerminalManagerInterface}.
|
|
1447
1251
|
*/
|
|
1448
1252
|
export declare type TerminalErrorCode = 'EXPIRE' | 'CANCEL' | 'DRIVER' | 'DEADLOCK' | 'TARGET' | 'LIMIT' | 'DESTROYED';
|
|
1449
1253
|
|
|
1254
|
+
/**
|
|
1255
|
+
* The contract for asking a form of a human at a keyboard — one method, because a form is one
|
|
1256
|
+
* question however many fields it holds. The server `Terminal` implements it against a real TTY;
|
|
1257
|
+
* a {@link PromptClientInterface} holds one to answer forms parked elsewhere.
|
|
1258
|
+
*
|
|
1259
|
+
* @remarks
|
|
1260
|
+
* `ask` drives the form the caller passes: it walks the schema's fields in order, binds each
|
|
1261
|
+
* keystroke through the form's own `fill`, submits, and returns the settled values. The returned
|
|
1262
|
+
* promise is the form's `answer`, so a caller holding the form can await either one. Ctrl-c at an
|
|
1263
|
+
* interactive driver is the one exception: it rejects THIS promise with a `TerminalError` coded
|
|
1264
|
+
* `CANCEL` and leaves the form `editing`, so the form's own `answer` stays pending for its owner.
|
|
1265
|
+
*
|
|
1266
|
+
* A driver never owns the form's lifetime. To interrupt an active walk, destroy the form: it
|
|
1267
|
+
* abandons, `answer` rejects, and the driver stops rendering on the form's `abandon` event. That
|
|
1268
|
+
* is the only cancellation channel, which is why this contract needs no second method.
|
|
1269
|
+
*/
|
|
1270
|
+
export declare interface TerminalInterface {
|
|
1271
|
+
ask(form: FormInterface): Promise<FormValues>;
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1450
1274
|
/**
|
|
1451
1275
|
* The multi-endpoint terminal MANAGER — a registry of named {@link PromptInterface} brokers (one
|
|
1452
|
-
* per endpoint), so several parties can `ask`
|
|
1453
|
-
* attribution edge on every parked
|
|
1276
|
+
* per endpoint), so several parties can `ask` forms of each other by NAME with a `from` → `to`
|
|
1277
|
+
* attribution edge on every parked form, and a transitive DEADLOCK check across all in-flight
|
|
1454
1278
|
* asks.
|
|
1455
1279
|
*
|
|
1456
1280
|
* @remarks
|
|
@@ -1461,22 +1285,23 @@ export declare type TerminalErrorCode = 'EXPIRE' | 'CANCEL' | 'DRIVER' | 'DEADLO
|
|
|
1461
1285
|
* - **`ask`.** The target must already be mounted via {@link add} — `ask` never auto-adds it;
|
|
1462
1286
|
* rejects `TARGET` for an unknown `to` (listing the known names). Rejects `DEADLOCK` when parking
|
|
1463
1287
|
* `from → to` would close a cycle over the CURRENT in-flight edge set (walked transitively);
|
|
1464
|
-
* otherwise parks through the target's broker and
|
|
1465
|
-
*
|
|
1288
|
+
* otherwise parks the caller's live form through the target's broker and returns that form's own
|
|
1289
|
+
* `answer` promise. Edge cleanup never alters the value or rejection the caller observes.
|
|
1466
1290
|
* - **Durable open / save.** `open(name)` restores an EMPTY broker from the `store` (parked
|
|
1467
1291
|
* Promises are process-bound and never resurrected); `save(name)` persists the endpoint's
|
|
1468
1292
|
* configured `timeout`.
|
|
1469
|
-
* - **Removal.** `remove` drops one endpoint
|
|
1470
|
-
*
|
|
1471
|
-
* idempotent.
|
|
1293
|
+
* - **Removal.** `remove` drops one endpoint, a batch (§9.2, array overload FIRST), or every
|
|
1294
|
+
* endpoint when called without an argument. It destroys each broker, which expires every form
|
|
1295
|
+
* still parked on it. `destroy` is idempotent.
|
|
1472
1296
|
*
|
|
1473
1297
|
* @example
|
|
1474
1298
|
* ```ts
|
|
1299
|
+
* const form = createForm({ fields: [{ control: 'text', name: 'name' }] })
|
|
1475
1300
|
* const manager = new TerminalManager()
|
|
1476
1301
|
* manager.add('agent')
|
|
1477
|
-
* const
|
|
1478
|
-
* manager.answer('agent', manager.pending('agent')[0].id, 'Ada')
|
|
1479
|
-
* await
|
|
1302
|
+
* const answer = manager.ask('user', 'agent', form)
|
|
1303
|
+
* manager.answer('agent', manager.pending('agent')[0].id, { name: 'Ada' })
|
|
1304
|
+
* await answer // { name: 'Ada' }
|
|
1480
1305
|
* ```
|
|
1481
1306
|
*/
|
|
1482
1307
|
export declare class TerminalManager implements TerminalManagerInterface {
|
|
@@ -1486,91 +1311,83 @@ export declare class TerminalManager implements TerminalManagerInterface {
|
|
|
1486
1311
|
get count(): number;
|
|
1487
1312
|
terminal(name: string): PromptInterface | undefined;
|
|
1488
1313
|
terminals(): readonly string[];
|
|
1489
|
-
add(name: string, options?:
|
|
1490
|
-
ask(from: string, to: string, form:
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
pending(): readonly PendingPrompt[];
|
|
1495
|
-
pending(to: string): readonly PendingPrompt[];
|
|
1496
|
-
answer(to: string, id: string, value: unknown): TerminalAnswerResult;
|
|
1314
|
+
add(name: string, options?: PromptOptions): PromptInterface;
|
|
1315
|
+
ask(from: string, to: string, form: FormInterface): Promise<FormValues>;
|
|
1316
|
+
pending(): readonly PendingForm[];
|
|
1317
|
+
pending(to: string): readonly PendingForm[];
|
|
1318
|
+
answer(to: string, id: string, values: FormValues): Result<FormValues, TerminalAnswerError>;
|
|
1497
1319
|
open(name: string): Promise<PromptInterface | undefined>;
|
|
1498
1320
|
save(name: string): Promise<boolean>;
|
|
1499
1321
|
remove(names: readonly string[]): boolean;
|
|
1500
1322
|
remove(name: string): boolean;
|
|
1501
|
-
|
|
1323
|
+
remove(): void;
|
|
1502
1324
|
destroy(): void;
|
|
1503
1325
|
}
|
|
1504
1326
|
|
|
1505
1327
|
/**
|
|
1506
|
-
* The manager's event map
|
|
1507
|
-
*
|
|
1328
|
+
* The manager's event map — the name-attributed re-emission of every mounted broker's events, so a
|
|
1329
|
+
* caller subscribes once for ALL endpoints instead of once per broker.
|
|
1508
1330
|
*
|
|
1509
1331
|
* @remarks
|
|
1510
|
-
* - `pending` — an endpoint parked a
|
|
1511
|
-
*
|
|
1512
|
-
* - `
|
|
1513
|
-
* - `expire` — an endpoint's parked prompt timed out (`to` names the endpoint).
|
|
1332
|
+
* - `pending` — an endpoint parked a form; the record itself carries `from` and `to`.
|
|
1333
|
+
* - `answer` — an endpoint's parked form was answered; `to` names the endpoint.
|
|
1334
|
+
* - `expire` — an endpoint's parked form expired; `to` names the endpoint.
|
|
1514
1335
|
*/
|
|
1515
1336
|
export declare type TerminalManagerEventMap = {
|
|
1516
|
-
readonly pending: readonly [
|
|
1517
|
-
readonly answer: readonly [to: string, id: string,
|
|
1337
|
+
readonly pending: readonly [form: PendingForm];
|
|
1338
|
+
readonly answer: readonly [to: string, id: string, values: FormValues];
|
|
1518
1339
|
readonly expire: readonly [to: string, id: string];
|
|
1519
1340
|
};
|
|
1520
1341
|
|
|
1521
1342
|
/**
|
|
1522
|
-
* The multi-endpoint terminal MANAGER
|
|
1523
|
-
*
|
|
1524
|
-
*
|
|
1343
|
+
* The multi-endpoint terminal MANAGER — a registry of named {@link PromptInterface} brokers, one
|
|
1344
|
+
* per endpoint, so several parties (agents, tools, humans) can ask forms of each other BY NAME,
|
|
1345
|
+
* attributed with a `from` → `to` edge on every parked record.
|
|
1525
1346
|
*
|
|
1526
1347
|
* @remarks
|
|
1527
|
-
* - **Accessors
|
|
1528
|
-
*
|
|
1529
|
-
* - **`add`** mints
|
|
1530
|
-
*
|
|
1531
|
-
* - **`ask`** is the attributed convenience: parks
|
|
1532
|
-
*
|
|
1533
|
-
* - **`pending()`** lists every endpoint's parked
|
|
1348
|
+
* - **Accessors.** `terminal(name)` looks up one endpoint's broker; `terminals()` lists every
|
|
1349
|
+
* mounted endpoint name.
|
|
1350
|
+
* - **`add`** mints, or returns, the broker for `name`. Idempotent; it never clobbers a live
|
|
1351
|
+
* endpoint.
|
|
1352
|
+
* - **`ask`** is the attributed convenience: it parks `form` from `from` to `to`, adding `to` if it
|
|
1353
|
+
* is absent, and resolves with the settled values.
|
|
1354
|
+
* - **`pending()`** lists every endpoint's parked records; `pending(to)` scopes to one endpoint.
|
|
1534
1355
|
* - **`answer`** routes to the named endpoint's broker.
|
|
1535
|
-
* - **`open`** restores
|
|
1536
|
-
* - **`save`** persists an endpoint's config snapshot
|
|
1537
|
-
*
|
|
1538
|
-
* - **Batch `remove
|
|
1539
|
-
*
|
|
1540
|
-
*
|
|
1541
|
-
*
|
|
1356
|
+
* - **`open`** restores, or returns the live, broker for `name` from the `store`.
|
|
1357
|
+
* - **`save`** persists an endpoint's config snapshot; false when there is no store, or `name` is
|
|
1358
|
+
* unknown.
|
|
1359
|
+
* - **Batch `remove`.** The array overload is declared FIRST: `remove(names)` removes each listed
|
|
1360
|
+
* endpoint and reports whether any named terminal was removed; `remove(name)` removes one;
|
|
1361
|
+
* `remove()` removes every endpoint without destroying the manager.
|
|
1362
|
+
* - **`destroy`** tears down every broker, then the manager's own emitter.
|
|
1542
1363
|
*/
|
|
1543
1364
|
export declare interface TerminalManagerInterface {
|
|
1544
1365
|
readonly emitter: EmitterInterface<TerminalManagerEventMap>;
|
|
1545
1366
|
readonly count: number;
|
|
1546
1367
|
terminal(name: string): PromptInterface | undefined;
|
|
1547
1368
|
terminals(): readonly string[];
|
|
1548
|
-
add(name: string, options?:
|
|
1549
|
-
ask(from: string, to: string, form:
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
pending(): readonly PendingPrompt[];
|
|
1554
|
-
pending(to: string): readonly PendingPrompt[];
|
|
1555
|
-
answer(to: string, id: string, value: unknown): TerminalAnswerResult;
|
|
1369
|
+
add(name: string, options?: PromptOptions): PromptInterface;
|
|
1370
|
+
ask(from: string, to: string, form: FormInterface): Promise<FormValues>;
|
|
1371
|
+
pending(): readonly PendingForm[];
|
|
1372
|
+
pending(to: string): readonly PendingForm[];
|
|
1373
|
+
answer(to: string, id: string, values: FormValues): Result<FormValues, TerminalAnswerError>;
|
|
1556
1374
|
open(name: string): Promise<PromptInterface | undefined>;
|
|
1557
1375
|
save(name: string): Promise<boolean>;
|
|
1558
1376
|
remove(names: readonly string[]): boolean;
|
|
1559
1377
|
remove(name: string): boolean;
|
|
1560
|
-
|
|
1378
|
+
remove(): void;
|
|
1561
1379
|
destroy(): void;
|
|
1562
1380
|
}
|
|
1563
1381
|
|
|
1564
1382
|
/**
|
|
1565
|
-
* Options for {@link import('./factories.js').createTerminalManager}
|
|
1383
|
+
* Options for {@link import('./factories.js').createTerminalManager} and the
|
|
1566
1384
|
* {@link TerminalManagerInterface}.
|
|
1567
1385
|
*
|
|
1568
1386
|
* @remarks
|
|
1569
|
-
* - `store` — the optional {@link TerminalStoreInterface} backing `open`
|
|
1570
|
-
* - `timeout` / `timer` / `cap` — the manager-wide default for each endpoint's broker
|
|
1571
|
-
* per {@link TerminalManagerInterface.add} call
|
|
1572
|
-
*
|
|
1573
|
-
* - `on` / `error` — the manager's {@link EmitterHooks} + {@link EmitterErrorHandler} (AGENTS §13).
|
|
1387
|
+
* - `store` — the optional {@link TerminalStoreInterface} backing `open` and `save`.
|
|
1388
|
+
* - `timeout` / `timer` / `cap` — the manager-wide default for each endpoint's broker, overridable
|
|
1389
|
+
* per {@link TerminalManagerInterface.add} call.
|
|
1390
|
+
* - `on` / `error` — the manager's own emitter hooks and listener-error handler.
|
|
1574
1391
|
*/
|
|
1575
1392
|
export declare interface TerminalManagerOptions {
|
|
1576
1393
|
readonly store?: TerminalStoreInterface;
|
|
@@ -1581,28 +1398,29 @@ export declare interface TerminalManagerOptions {
|
|
|
1581
1398
|
readonly error?: EmitterErrorHandler;
|
|
1582
1399
|
}
|
|
1583
1400
|
|
|
1584
|
-
/**
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
}
|
|
1590
|
-
|
|
1591
|
-
/** One endpoint's persisted CONFIG snapshot — `id` is the endpoint name; `timeout` its configured default. Parked Promises are process-bound and are never resurrected — `open` always restores an EMPTY broker. */
|
|
1401
|
+
/**
|
|
1402
|
+
* One endpoint's persisted CONFIG snapshot — `id` is the endpoint name and `timeout` its configured
|
|
1403
|
+
* default. Parked forms are process-bound and are never resurrected, so `open` always restores an
|
|
1404
|
+
* EMPTY broker.
|
|
1405
|
+
*/
|
|
1592
1406
|
export declare interface TerminalSnapshot {
|
|
1593
1407
|
readonly id: string;
|
|
1594
1408
|
readonly timeout?: number;
|
|
1595
1409
|
}
|
|
1596
1410
|
|
|
1597
|
-
/**
|
|
1411
|
+
/**
|
|
1412
|
+
* One opaque persisted row — the shape a `TableInterface<TerminalSnapshotRow>`-backed store reads
|
|
1413
|
+
* and writes. `snapshot` is narrowed with {@link import('./validators.js').isTerminalSnapshot} on
|
|
1414
|
+
* read.
|
|
1415
|
+
*/
|
|
1598
1416
|
export declare interface TerminalSnapshotRow {
|
|
1599
1417
|
readonly id: string;
|
|
1600
1418
|
readonly snapshot: unknown;
|
|
1601
1419
|
}
|
|
1602
1420
|
|
|
1603
1421
|
/**
|
|
1604
|
-
* The point-access persistence seam
|
|
1605
|
-
*
|
|
1422
|
+
* The point-access persistence seam for a {@link TerminalManagerInterface}'s endpoint configs.
|
|
1423
|
+
* Every primitive is async; deleting an absent id is a no-op.
|
|
1606
1424
|
*/
|
|
1607
1425
|
export declare interface TerminalStoreInterface {
|
|
1608
1426
|
get(id: string): Promise<TerminalSnapshot | undefined>;
|
|
@@ -1610,20 +1428,14 @@ export declare interface TerminalStoreInterface {
|
|
|
1610
1428
|
delete(id: string): Promise<void>;
|
|
1611
1429
|
}
|
|
1612
1430
|
|
|
1613
|
-
/** The handle {@link PromptInterface.park} returns — the parked prompt's `id` plus the Promise that resolves (or rejects) with its {@link PromptValue}. */
|
|
1614
|
-
export declare interface Ticket {
|
|
1615
|
-
readonly id: string;
|
|
1616
|
-
readonly value: Promise<PromptValue>;
|
|
1617
|
-
}
|
|
1618
|
-
|
|
1619
1431
|
/** Cancel a pending {@link TimerHandler} deadline — idempotent, safe to call after the timer fired. */
|
|
1620
1432
|
export declare type TimerCancel = () => void;
|
|
1621
1433
|
|
|
1622
1434
|
/**
|
|
1623
1435
|
* One injected timer — arms a deadline `callback` to fire after `ms`, returning a
|
|
1624
1436
|
* {@link TimerCancel} that cancels it. The broker's timeout seam: the default wraps the host
|
|
1625
|
-
* `setTimeout`
|
|
1626
|
-
* and fires it on demand
|
|
1437
|
+
* `setTimeout` and `clearTimeout`; a test injects a deterministic timer that captures the callback
|
|
1438
|
+
* and fires it on demand, with no real time and no global patching.
|
|
1627
1439
|
*/
|
|
1628
1440
|
declare type TimerHandler_2 = (callback: () => void, ms: number) => TimerCancel;
|
|
1629
1441
|
export { TimerHandler_2 as TimerHandler }
|
|
@@ -1631,59 +1443,12 @@ export { TimerHandler_2 as TimerHandler }
|
|
|
1631
1443
|
/** Toggle `index` in a readonly index list — copy-on-write, returning the new sorted-by-insertion list. */
|
|
1632
1444
|
export declare function toggleIndex(indices: readonly number[], index: number): readonly number[];
|
|
1633
1445
|
|
|
1634
|
-
/** Matches an HTTP(S) URL. The `url` rule tests against this. */
|
|
1635
|
-
export declare const URL_PATTERN: RegExp;
|
|
1636
|
-
|
|
1637
1446
|
/**
|
|
1638
|
-
*
|
|
1639
|
-
*
|
|
1640
|
-
*
|
|
1641
|
-
*
|
|
1642
|
-
* @remarks
|
|
1643
|
-
* Each rule is EITHER a primitive that turns on the built-in check, OR a {@link Validator}
|
|
1644
|
-
* that replaces it with custom logic:
|
|
1645
|
-
*
|
|
1646
|
-
* - `required` — `true` ⇒ input must be non-empty after trimming.
|
|
1647
|
-
* - `minimum` — a number ⇒ input must be at least that many characters.
|
|
1648
|
-
* - `maximum` — a number ⇒ input must be at most that many characters.
|
|
1649
|
-
* - `pattern` — a string ⇒ input must match that regex source.
|
|
1650
|
-
* - `email` — `true` ⇒ input must look like an email address.
|
|
1651
|
-
* - `url` — `true` ⇒ input must look like an HTTP(S) URL.
|
|
1652
|
-
* - `numeric` — `true` ⇒ input must be a number (integer or decimal).
|
|
1653
|
-
* - `integer` — `true` ⇒ input must be an integer.
|
|
1654
|
-
* - `alphanumeric` — `true` ⇒ input must contain only letters and digits.
|
|
1655
|
-
* - `custom` — an arbitrary {@link Validator} escape hatch.
|
|
1656
|
-
*
|
|
1657
|
-
* Rules compose in the fixed order above; the FIRST failing rule short-circuits and its
|
|
1658
|
-
* message is returned. A `false` / `undefined` rule is skipped.
|
|
1659
|
-
*/
|
|
1660
|
-
export declare interface ValidationRules {
|
|
1661
|
-
readonly required?: boolean | Validator;
|
|
1662
|
-
readonly minimum?: number | Validator;
|
|
1663
|
-
readonly maximum?: number | Validator;
|
|
1664
|
-
readonly pattern?: string | Validator;
|
|
1665
|
-
readonly email?: boolean | Validator;
|
|
1666
|
-
readonly url?: boolean | Validator;
|
|
1667
|
-
readonly numeric?: boolean | Validator;
|
|
1668
|
-
readonly integer?: boolean | Validator;
|
|
1669
|
-
readonly alphanumeric?: boolean | Validator;
|
|
1670
|
-
readonly custom?: Validator;
|
|
1671
|
-
}
|
|
1672
|
-
|
|
1673
|
-
/**
|
|
1674
|
-
* A single input validator — given the current input string, returns `true` when the input
|
|
1675
|
-
* is valid, or an error MESSAGE string when it is not. The atomic unit the validation engine
|
|
1676
|
-
* composes and the prompts apply on submit.
|
|
1677
|
-
*
|
|
1678
|
-
* @remarks
|
|
1679
|
-
* A `Validator` is total and pure — it never throws and never mutates. The `true | string`
|
|
1680
|
-
* shape (not `boolean`) is deliberate: an invalid result CARRIES its message, so a prompt
|
|
1681
|
-
* can render the exact reason. {@link import('./helpers.js').composeValidators} runs several
|
|
1682
|
-
* in order and returns the FIRST error (short-circuiting), so the most specific rule wins.
|
|
1447
|
+
* One SSE-shaped wire frame — the `event` name, its already-stringified `data` payload, and an
|
|
1448
|
+
* optional `id`. The transport-neutral shape {@link import('./helpers.js').serializePending},
|
|
1449
|
+
* {@link import('./helpers.js').serializeExpire}, and
|
|
1450
|
+
* {@link import('./helpers.js').serializeShutdown} build, with no `http` dependency.
|
|
1683
1451
|
*/
|
|
1684
|
-
export declare type Validator = (input: string) => true | string;
|
|
1685
|
-
|
|
1686
|
-
/** One SSE-shaped wire frame — the `event` name, its `data` payload (already JSON-stringified), and an optional `id`. The transport-neutral shape {@link import('./helpers.js').serializePending} / {@link import('./helpers.js').serializeExpire} / {@link import('./helpers.js').serializeShutdown} build, with no `http` dependency. */
|
|
1687
1452
|
export declare interface WireEvent {
|
|
1688
1453
|
readonly event: string;
|
|
1689
1454
|
readonly data: string;
|