@orkestrel/terminal 0.0.8 → 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 +611 -943
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +522 -963
- package/dist/src/core/index.d.ts +522 -963
- package/dist/src/core/index.js +610 -916
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +556 -203
- 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 +541 -204
- package/dist/src/server/index.js.map +1 -1
- package/package.json +4 -2
|
@@ -1,154 +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';
|
|
6
16
|
import { Result } from '@orkestrel/contract';
|
|
17
|
+
import { SelectField } from '@orkestrel/form';
|
|
7
18
|
import { Style } from '@orkestrel/console';
|
|
8
19
|
import { StylerInterface } from '@orkestrel/console';
|
|
9
20
|
import { TableInterface } from '@orkestrel/database';
|
|
21
|
+
import { TextField } from '@orkestrel/form';
|
|
10
22
|
|
|
11
23
|
/** The `Accept` header value that opens the broker's SSE stream. */
|
|
12
24
|
export declare const ACCEPT_EVENT_STREAM = "text/event-stream";
|
|
13
25
|
|
|
14
|
-
/** Matches an alphanumeric string (letters and digits only). The `alphanumeric` rule tests against this. */
|
|
15
|
-
export declare const ALPHANUMERIC_PATTERN: RegExp;
|
|
16
|
-
|
|
17
|
-
/** The rejection reason a bare {@link PromptInterface.answer} returns — `'unknown'` (no such parked prompt) or `'rejected'` (failed validation / type-check). */
|
|
18
|
-
export declare type AnswerError = 'unknown' | 'rejected';
|
|
19
|
-
|
|
20
26
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
|
|
25
|
-
|
|
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';
|
|
39
|
+
} | {
|
|
40
|
+
readonly reason: 'rejected';
|
|
41
|
+
readonly errors: readonly FieldError[];
|
|
42
|
+
};
|
|
26
43
|
|
|
27
44
|
/** Backspace (BS, U+0008) — Ctrl+H / some terminals' Backspace. */
|
|
28
45
|
export declare const BACKSPACE: string;
|
|
29
46
|
|
|
30
|
-
/** Wrap a named rule + its primitive check into a {@link Validator} (returns `true` or the rule's message). */
|
|
31
|
-
export declare function buildRuleValidator(rule: string, check: boolean | number | string): Validator;
|
|
32
|
-
|
|
33
|
-
/** A choice item in a {@link CheckboxOptions} prompt — a {@link PromptChoice} plus an optional initial `checked` state. */
|
|
34
|
-
export declare interface CheckboxChoice {
|
|
35
|
-
readonly name: string;
|
|
36
|
-
readonly value: string;
|
|
37
|
-
readonly description?: string;
|
|
38
|
-
readonly checked?: boolean;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Options for a multi-selection {@link import('./helpers.js').checkboxReduce} prompt.
|
|
43
|
-
*
|
|
44
|
-
* @remarks
|
|
45
|
-
* `choices` accepts bare strings or full {@link CheckboxChoice} objects (with an optional
|
|
46
|
-
* initial `checked`); {@link import('./helpers.js').createCheckboxState} normalizes them.
|
|
47
|
-
* `min` / `max` gate submission — a submit with fewer than `min` or more than `max` selected
|
|
48
|
-
* is rejected (the prompt stays active with the reason in the view). `hint` adds a key hint after
|
|
49
|
-
* the message (no computed default) and reaches the server driver's numbered fallback too.
|
|
50
|
-
*/
|
|
51
|
-
export declare interface CheckboxOptions {
|
|
52
|
-
readonly message: string;
|
|
53
|
-
readonly choices: ReadonlyArray<string | CheckboxChoice>;
|
|
54
|
-
readonly min?: number;
|
|
55
|
-
readonly max?: number;
|
|
56
|
-
readonly hint?: string;
|
|
57
|
-
readonly styler?: StylerInterface;
|
|
58
|
-
readonly theme?: PromptThemeOptions;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
47
|
/**
|
|
62
48
|
* Advance a checkbox prompt by one {@link KeyEvent} — the pure
|
|
63
49
|
* `(state, key) → PromptStep<readonly string[]>` reducer. `up` / `down` (and `k` / `j`) move the
|
|
64
50
|
* focus (wrapping); `space` toggles the focused index in the checked set; return submits the
|
|
65
|
-
* checked values in
|
|
66
|
-
* the reason in the view); ctrl-c cancels.
|
|
67
|
-
*/
|
|
68
|
-
export declare function checkboxReduce(state: CheckboxState, key: KeyEvent): PromptStep<readonly string[], CheckboxState>;
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* The immutable state of a checkbox prompt — the normalized choices, the optional hint, the
|
|
72
|
-
* resolved styler + theme, the `focused` index, the set of `checked` indices, the optional
|
|
73
|
-
* `min` / `max` gate, and the current `error`.
|
|
74
|
-
*
|
|
75
|
-
* @remarks
|
|
76
|
-
* Built by {@link import('./helpers.js').createCheckboxState}; advanced by
|
|
77
|
-
* {@link import('./helpers.js').checkboxReduce}. `up` / `down` move `focus` (wrapping); `space`
|
|
78
|
-
* toggles the focused index in `checked`; `return` submits the checked values in choice order
|
|
79
|
-
* (rejected, with `error`, when the count is outside `[min, max]`). `checked` is modelled as a
|
|
80
|
-
* readonly index array (plain JSON data, copy-on-write — no `Set` to clone).
|
|
81
|
-
*/
|
|
82
|
-
export declare interface CheckboxState {
|
|
83
|
-
readonly message: string;
|
|
84
|
-
readonly choices: readonly CheckboxChoice[];
|
|
85
|
-
readonly hint?: string;
|
|
86
|
-
readonly styler: StylerInterface;
|
|
87
|
-
readonly theme: PromptTheme;
|
|
88
|
-
readonly focused: number;
|
|
89
|
-
readonly checked: readonly number[];
|
|
90
|
-
readonly min?: number;
|
|
91
|
-
readonly max?: number;
|
|
92
|
-
readonly error?: string;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/** Render a {@link CheckboxState} as a MULTI-LINE styled view — the header (plus any hint), one box per choice (focused + checked marked), a count, and any error. */
|
|
96
|
-
export declare function checkboxView(state: CheckboxState): string;
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Compose several {@link Validator}s into ONE short-circuiting validator — it runs them in order
|
|
100
|
-
* and returns the FIRST error message, or `true` when all pass. The empty composition always
|
|
101
|
-
* passes.
|
|
51
|
+
* checked values in choice order; ctrl-c cancels. The form applies selection-count rules.
|
|
102
52
|
*/
|
|
103
|
-
export declare function
|
|
53
|
+
export declare function checkboxReduce(state: ReturnType<typeof createCheckboxState>, key: KeyEvent): PromptStep<readonly string[], ReturnType<typeof createCheckboxState>>;
|
|
104
54
|
|
|
105
|
-
/**
|
|
106
|
-
|
|
107
|
-
*
|
|
108
|
-
* @remarks
|
|
109
|
-
* `hint` replaces the computed `(Y/n)` group in full, parentheses included, and is painted with
|
|
110
|
-
* the theme's `hint` role. The accepted KEYS stay `y` / `n` / `enter` whatever the hint says, so a
|
|
111
|
-
* hint that advertises other keys is the consumer's own contradiction.
|
|
112
|
-
*/
|
|
113
|
-
export declare interface ConfirmOptions {
|
|
114
|
-
readonly message: string;
|
|
115
|
-
readonly default?: boolean;
|
|
116
|
-
readonly hint?: string;
|
|
117
|
-
readonly styler?: StylerInterface;
|
|
118
|
-
readonly theme?: PromptThemeOptions;
|
|
119
|
-
}
|
|
55
|
+
/** Render a checkbox-field key state as a multi-line styled view. */
|
|
56
|
+
export declare function checkboxView(state: ReturnType<typeof createCheckboxState>): string;
|
|
120
57
|
|
|
121
58
|
/**
|
|
122
59
|
* Advance a confirm prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<boolean>`
|
|
123
60
|
* reducer. `y` / `Y` submits `true`, `n` / `N` submits `false`, return on an empty line submits
|
|
124
61
|
* the `default`, ctrl-c cancels; any other key is ignored (stays active).
|
|
125
62
|
*/
|
|
126
|
-
export declare function confirmReduce(state:
|
|
63
|
+
export declare function confirmReduce(state: ReturnType<typeof createConfirmState>, key: KeyEvent): PromptStep<boolean, ReturnType<typeof createConfirmState>>;
|
|
127
64
|
|
|
128
65
|
/**
|
|
129
|
-
*
|
|
130
|
-
* override, and the resolved styler + theme.
|
|
131
|
-
*
|
|
132
|
-
* @remarks
|
|
133
|
-
* Built by {@link import('./helpers.js').createConfirmState}; advanced by
|
|
134
|
-
* {@link import('./helpers.js').confirmReduce}. `y` / `Y` submits `true`, `n` / `N` submits
|
|
135
|
-
* `false`, and `enter` takes the `default` (rendered with the active letter emphasized in the
|
|
136
|
-
* `(Y/n)` hint, unless `hint` replaces that group).
|
|
137
|
-
*/
|
|
138
|
-
export declare interface ConfirmState {
|
|
139
|
-
readonly message: string;
|
|
140
|
-
readonly default: boolean;
|
|
141
|
-
readonly hint?: string;
|
|
142
|
-
readonly styler: StylerInterface;
|
|
143
|
-
readonly theme: PromptTheme;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Render a {@link ConfirmState} as a styled view — the header plus the `(Y/n)` group with the
|
|
148
|
-
* default letter painted by the `selected` role. A supplied `hint` replaces that whole group,
|
|
149
|
-
* parentheses included, painted by the `hint` role.
|
|
66
|
+
* Render a confirm-field key state as a styled view. The selected role paints the default letter.
|
|
150
67
|
*/
|
|
151
|
-
export declare function confirmView(state:
|
|
68
|
+
export declare function confirmView(state: ReturnType<typeof createConfirmState>): string;
|
|
152
69
|
|
|
153
70
|
/**
|
|
154
71
|
* The single control BYTE → key descriptor table {@link import('./helpers.js').parseKey}
|
|
@@ -166,11 +83,37 @@ export declare const CONTROL_NAMES: Readonly<Record<string, {
|
|
|
166
83
|
readonly ctrl: boolean;
|
|
167
84
|
}>>;
|
|
168
85
|
|
|
169
|
-
/**
|
|
170
|
-
|
|
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
|
+
};
|
|
171
102
|
|
|
172
|
-
/**
|
|
173
|
-
|
|
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
|
+
};
|
|
174
117
|
|
|
175
118
|
/**
|
|
176
119
|
* Create a {@link TerminalStoreInterface} backed by one table of the `databases` layer — the
|
|
@@ -189,11 +132,38 @@ export declare function createConfirmState(options: ConfirmOptions): ConfirmStat
|
|
|
189
132
|
*/
|
|
190
133
|
export declare function createDatabaseTerminalStore(driver?: DriverInterface): TerminalStoreInterface;
|
|
191
134
|
|
|
192
|
-
/**
|
|
193
|
-
|
|
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
|
+
};
|
|
194
151
|
|
|
195
|
-
/**
|
|
196
|
-
|
|
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
|
+
};
|
|
197
167
|
|
|
198
168
|
/**
|
|
199
169
|
* Create the in-memory {@link TerminalStoreInterface} — a process-lifetime `Map` of endpoint
|
|
@@ -210,43 +180,51 @@ export declare function createInputState(options: InputOptions): InputState;
|
|
|
210
180
|
*/
|
|
211
181
|
export declare function createMemoryTerminalStore(): TerminalStoreInterface;
|
|
212
182
|
|
|
213
|
-
/**
|
|
214
|
-
|
|
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
|
+
};
|
|
215
198
|
|
|
216
199
|
/**
|
|
217
|
-
* Create the headless
|
|
218
|
-
*
|
|
219
|
-
* timeout). The tri-surface's headless arm: subscribe `emitter.on('pending', …)` to forward each
|
|
220
|
-
* prompt to whoever can answer (an SSE transport, a remote terminal), then route the answer back
|
|
221
|
-
* through `answer(id, value)`.
|
|
200
|
+
* Create the headless {@link PromptInterface} broker. It parks live forms and applies remote
|
|
201
|
+
* answers to the authoritative instances.
|
|
222
202
|
*
|
|
223
203
|
* @param options - See {@link PromptOptions}
|
|
224
204
|
* @returns A {@link PromptInterface}
|
|
225
205
|
*
|
|
226
206
|
* @remarks
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
* `options.timeout` (default {@link import('./constants.js').DEFAULT_PROMPT_TIMEOUT_MS}) and its
|
|
231
|
-
* Promise rejects with a {@link import('./errors.js').TerminalError}; inject `options.timer` to
|
|
232
|
-
* 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.
|
|
233
210
|
*
|
|
234
211
|
* @example
|
|
235
212
|
* ```ts
|
|
236
213
|
* import { createPrompt } from '@src/core'
|
|
214
|
+
* import { createForm } from '@orkestrel/form'
|
|
237
215
|
*
|
|
238
216
|
* const prompt = createPrompt()
|
|
239
|
-
*
|
|
240
|
-
* const
|
|
217
|
+
* const form = createForm({ fields: [{ control: 'text', name: 'name' }] })
|
|
218
|
+
* const id = prompt.park(form)
|
|
219
|
+
* prompt.answer(id, { name: 'Ada' })
|
|
241
220
|
* ```
|
|
242
221
|
*/
|
|
243
222
|
export declare function createPrompt(options?: PromptOptions): PromptInterface;
|
|
244
223
|
|
|
245
224
|
/**
|
|
246
225
|
* Create the SSE prompt {@link PromptClientInterface} BRIDGE — it connects to a remote broker's SSE
|
|
247
|
-
* endpoint, dispatches each received
|
|
248
|
-
*
|
|
249
|
-
* 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.
|
|
250
228
|
*
|
|
251
229
|
* @param options - See {@link PromptClientOptions} (`url` + `terminal` required)
|
|
252
230
|
* @returns A {@link PromptClientInterface}
|
|
@@ -290,16 +268,29 @@ export declare function createPromptClient(options: PromptClientOptions): Prompt
|
|
|
290
268
|
*/
|
|
291
269
|
export declare function createPromptTheme(options?: PromptThemeOptions): PromptTheme;
|
|
292
270
|
|
|
293
|
-
/**
|
|
294
|
-
|
|
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
|
+
};
|
|
295
286
|
|
|
296
287
|
/**
|
|
297
|
-
* Create the multi-endpoint {@link
|
|
288
|
+
* Create the multi-endpoint {@link TerminalManager} — a named registry of
|
|
298
289
|
* {@link PromptInterface} brokers so several parties can `ask` prompts of each other by name,
|
|
299
290
|
* with a transitive DEADLOCK check across every in-flight ask.
|
|
300
291
|
*
|
|
301
292
|
* @param options - See {@link TerminalManagerOptions}
|
|
302
|
-
* @returns A {@link
|
|
293
|
+
* @returns A {@link TerminalManager}
|
|
303
294
|
*
|
|
304
295
|
* @example
|
|
305
296
|
* ```ts
|
|
@@ -385,7 +376,7 @@ export declare class DatabaseTerminalStore implements TerminalStoreInterface {
|
|
|
385
376
|
delete(id: string): Promise<void>;
|
|
386
377
|
}
|
|
387
378
|
|
|
388
|
-
/** The default mask glyph
|
|
379
|
+
/** The default mask glyph {@link import('./helpers.js').createPasswordState} uses — `*`. */
|
|
389
380
|
export declare const DEFAULT_MASK = "*";
|
|
390
381
|
|
|
391
382
|
/**
|
|
@@ -423,26 +414,6 @@ export declare function defaultTimer(callback: () => void, ms: number): TimerCan
|
|
|
423
414
|
/** Delete (DEL, U+007F) — the usual Backspace byte on a Unix TTY. */
|
|
424
415
|
export declare const DELETE: string;
|
|
425
416
|
|
|
426
|
-
/**
|
|
427
|
-
* Dispatch a {@link PendingPrompt} to the matching {@link PromptFormInterface} method — the bridge
|
|
428
|
-
* step a {@link PromptClient} runs to drive a LOCAL terminal with a prompt issued elsewhere.
|
|
429
|
-
* Reconstructs typed options from the wire-safe {@link PendingPrompt.options} (every field
|
|
430
|
-
* §14-narrowed, never an `as`; the validator rebuilt from rules via {@link reconstructValidationRules}),
|
|
431
|
-
* then calls the matching prompt form and returns its resolved value.
|
|
432
|
-
*
|
|
433
|
-
* @remarks
|
|
434
|
-
* `theme` and `hint` are plain data, so they cross the wire with the rest of the options bag and
|
|
435
|
-
* are reconstructed here for every form that accepts them: the theme is narrowed by
|
|
436
|
-
* {@link import('./validators.js').isPromptThemeOptions} (an off-shape theme is dropped, leaving
|
|
437
|
-
* the defaults), then every glyph and hint is passed through {@link sanitizeDisplayText}. Choice
|
|
438
|
-
* labels use the stream-safe {@link sanitizeChoiceLabels} treatment instead.
|
|
439
|
-
*
|
|
440
|
-
* @param terminal - The local {@link PromptFormInterface} to drive
|
|
441
|
-
* @param pending - The decoded pending prompt to dispatch
|
|
442
|
-
* @returns The prompt's resolved value (a `string` / `boolean` / `readonly string[]` per form)
|
|
443
|
-
*/
|
|
444
|
-
export declare function dispatchPendingPrompt(terminal: PromptFormInterface, pending: PendingPrompt): Promise<string | boolean | readonly string[]>;
|
|
445
|
-
|
|
446
417
|
/**
|
|
447
418
|
* Apply a single line-editing {@link KeyEvent} to a text buffer — the editing shared by input /
|
|
448
419
|
* password / editor. A printable key appends its character; `backspace` drops the last character;
|
|
@@ -451,98 +422,35 @@ export declare function dispatchPendingPrompt(terminal: PromptFormInterface, pen
|
|
|
451
422
|
*/
|
|
452
423
|
export declare function editLine(value: string, key: KeyEvent): string | undefined;
|
|
453
424
|
|
|
454
|
-
/**
|
|
455
|
-
* Options for a multi-line {@link import('./helpers.js').editorReduce} editor prompt (terminated
|
|
456
|
-
* by ctrl-d).
|
|
457
|
-
*
|
|
458
|
-
* @remarks
|
|
459
|
-
* `hint` replaces the computed `(Ctrl+D to finish)` group in full, parentheses included. The
|
|
460
|
-
* finish KEY stays ctrl-d whatever the hint says.
|
|
461
|
-
*/
|
|
462
|
-
export declare interface EditorOptions {
|
|
463
|
-
readonly message: string;
|
|
464
|
-
readonly default?: string;
|
|
465
|
-
readonly hint?: string;
|
|
466
|
-
readonly validate?: Validator | ValidationRules;
|
|
467
|
-
readonly styler?: StylerInterface;
|
|
468
|
-
readonly theme?: PromptThemeOptions;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
425
|
/**
|
|
472
426
|
* Advance an editor prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`
|
|
473
427
|
* reducer. Printable characters extend the current line; backspace shrinks it; return commits the
|
|
474
428
|
* current line and starts a fresh one; ctrl-d FINISHES (joining all lines, falling back to the
|
|
475
|
-
* default when empty)
|
|
476
|
-
* the error.
|
|
429
|
+
* default when empty); ctrl-c cancels. The form validates the candidate after the driver fills it.
|
|
477
430
|
*/
|
|
478
|
-
export declare function editorReduce(state:
|
|
479
|
-
|
|
480
|
-
/**
|
|
481
|
-
* The immutable state of an editor prompt — the committed `lines`, the in-progress `current`
|
|
482
|
-
* line, plus the resolved validator + styler + theme, the default, the optional hint override,
|
|
483
|
-
* and the current `error`.
|
|
484
|
-
*
|
|
485
|
-
* @remarks
|
|
486
|
-
* Built by {@link import('./helpers.js').createEditorState}; advanced by
|
|
487
|
-
* {@link import('./helpers.js').editorReduce}. A printable key appends to `current`; `return`
|
|
488
|
-
* commits `current` to `lines` and starts a fresh line; ctrl-d finishes, submitting
|
|
489
|
-
* `lines + current` joined by newlines (or `default` when empty). The whole text is validated
|
|
490
|
-
* on finish.
|
|
491
|
-
*/
|
|
492
|
-
export declare interface EditorState {
|
|
493
|
-
readonly message: string;
|
|
494
|
-
readonly default: string;
|
|
495
|
-
readonly hint?: string;
|
|
496
|
-
readonly validator: Validator;
|
|
497
|
-
readonly styler: StylerInterface;
|
|
498
|
-
readonly theme: PromptTheme;
|
|
499
|
-
readonly lines: readonly string[];
|
|
500
|
-
readonly current: string;
|
|
501
|
-
readonly error?: string;
|
|
502
|
-
}
|
|
431
|
+
export declare function editorReduce(state: ReturnType<typeof createEditorState>, key: KeyEvent): PromptStep<string, ReturnType<typeof createEditorState>>;
|
|
503
432
|
|
|
504
433
|
/**
|
|
505
|
-
* Render an
|
|
506
|
-
* committed and in-progress lines painted by the `content` role, and any error. A supplied `hint`
|
|
507
|
-
* replaces `(Ctrl+D to finish)` in full; the finish key stays ctrl-d.
|
|
434
|
+
* Render an editor-field key state as a multi-line styled view with its finish hint.
|
|
508
435
|
*/
|
|
509
|
-
export declare function editorView(state:
|
|
436
|
+
export declare function editorView(state: ReturnType<typeof createEditorState>): string;
|
|
510
437
|
|
|
511
|
-
/** The styled error line (`✖ message`)
|
|
438
|
+
/** The styled error line (`✖ message`) a form driver appends for a field failure. */
|
|
512
439
|
export declare function errorLine(styler: StylerInterface, theme: PromptTheme, message: string): string;
|
|
513
440
|
|
|
514
441
|
/** Escape (ESC, U+001B) — the lone byte, and the lead byte of every CSI / SS3 sequence. */
|
|
515
442
|
export declare const ESCAPE: string;
|
|
516
443
|
|
|
517
444
|
/**
|
|
518
|
-
*
|
|
519
|
-
*
|
|
520
|
-
*
|
|
521
|
-
*
|
|
522
|
-
* @remarks
|
|
523
|
-
* A function `check` is the custom-override path: it is called and its `true` ⇒ pass, a string
|
|
524
|
-
* ⇒ that message, anything else ⇒ the generic {@link RULE_MESSAGES.invalid}. A primitive `check`
|
|
525
|
-
* runs the named built-in: `required` (non-empty trimmed), `minimum` / `maximum` (length
|
|
526
|
-
* bounds, the message interpolated with the count), `pattern` (a regex source), and the
|
|
527
|
-
* `email` / `url` / `numeric` / `integer` / `alphanumeric` pattern tests.
|
|
528
|
-
*
|
|
529
|
-
* @param rule - The rule name (`'required'`, `'minimum'`, …)
|
|
530
|
-
* @param check - The configured value (a primitive toggle / bound / pattern, or a custom {@link Validator})
|
|
531
|
-
* @param input - The input string to test
|
|
532
|
-
* @returns The error message when the rule fails, else `undefined`
|
|
533
|
-
*/
|
|
534
|
-
export declare function evaluateRule(rule: string, check: boolean | number | string | Validator, input: string): string | undefined;
|
|
535
|
-
|
|
536
|
-
/**
|
|
537
|
-
* A minimal `fetch` — the subset of the global `fetch` the {@link PromptClient} uses (open the
|
|
538
|
-
* SSE stream, POST an answer). Injected so a test drives the client with a controlled
|
|
539
|
-
* `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.
|
|
540
448
|
*/
|
|
541
449
|
export declare type FetchHandler = (input: string, init?: FetchInit) => Promise<Response>;
|
|
542
450
|
|
|
543
451
|
/**
|
|
544
|
-
* The request init
|
|
545
|
-
* `RequestInit` fields it actually sets
|
|
452
|
+
* The request init a {@link PromptClientInterface} passes to its {@link FetchHandler} — the
|
|
453
|
+
* `RequestInit` fields it actually sets.
|
|
546
454
|
*/
|
|
547
455
|
export declare interface FetchInit {
|
|
548
456
|
readonly method?: string;
|
|
@@ -551,13 +459,10 @@ export declare interface FetchInit {
|
|
|
551
459
|
readonly signal?: AbortSignal;
|
|
552
460
|
}
|
|
553
461
|
|
|
554
|
-
/** The min/max gate for a checkbox submit — the rejection message when `count` is out of range, else `undefined`. */
|
|
555
|
-
export declare function gateSelection(count: number, min?: number, max?: number): string | undefined;
|
|
556
|
-
|
|
557
462
|
/** The default {@link import('./types.js').FetchHandler} — the global `fetch`, adapted to the minimal injected shape the {@link import('./PromptClient.js').PromptClient} uses. */
|
|
558
463
|
export declare function globalFetch(input: string, init?: FetchInit): Promise<Response>;
|
|
559
464
|
|
|
560
|
-
/** The auth-token request header the {@link import('./types.js').
|
|
465
|
+
/** The auth-token request header the {@link import('./types.js').PromptClientInterface} sends. */
|
|
561
466
|
export declare const HEADER_TOKEN = "x-orkestrel-token";
|
|
562
467
|
|
|
563
468
|
/**
|
|
@@ -572,48 +477,15 @@ export declare const HEADER_TOKEN = "x-orkestrel-token";
|
|
|
572
477
|
*/
|
|
573
478
|
export declare function hintedHeader(styler: StylerInterface, theme: PromptTheme, message: string, hint?: string): string;
|
|
574
479
|
|
|
575
|
-
/** Options for a single-line text {@link import('./helpers.js').inputReduce} prompt. */
|
|
576
|
-
export declare interface InputOptions {
|
|
577
|
-
readonly message: string;
|
|
578
|
-
readonly default?: string;
|
|
579
|
-
readonly validate?: Validator | ValidationRules;
|
|
580
|
-
readonly styler?: StylerInterface;
|
|
581
|
-
readonly theme?: PromptThemeOptions;
|
|
582
|
-
}
|
|
583
|
-
|
|
584
480
|
/**
|
|
585
481
|
* Advance an input prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`
|
|
586
482
|
* reducer. Printable characters extend the value; backspace shrinks it; ctrl-u clears it; ctrl-c
|
|
587
|
-
* cancels; return
|
|
588
|
-
* 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.
|
|
589
484
|
*/
|
|
590
|
-
export declare function inputReduce(state:
|
|
591
|
-
|
|
592
|
-
/**
|
|
593
|
-
* The immutable state of a text input prompt — its options, the resolved validator + styler +
|
|
594
|
-
* theme, the accumulated `value`, and the current `error` (when the last submit failed validation).
|
|
595
|
-
*
|
|
596
|
-
* @remarks
|
|
597
|
-
* Built by {@link import('./helpers.js').createInputState}; advanced by
|
|
598
|
-
* {@link import('./helpers.js').inputReduce}. `value` accumulates printable characters and
|
|
599
|
-
* shrinks on backspace; `error` holds the validation message shown in the view after a
|
|
600
|
-
* rejected submit (cleared on the next keystroke).
|
|
601
|
-
*/
|
|
602
|
-
export declare interface InputState {
|
|
603
|
-
readonly message: string;
|
|
604
|
-
readonly default: string;
|
|
605
|
-
readonly validator: Validator;
|
|
606
|
-
readonly styler: StylerInterface;
|
|
607
|
-
readonly theme: PromptTheme;
|
|
608
|
-
readonly value: string;
|
|
609
|
-
readonly error?: string;
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
/** Render an {@link InputState} as a styled view — the header, the typed value painted by the `content` role (or the default painted as a hint), and any error. */
|
|
613
|
-
export declare function inputView(state: InputState): string;
|
|
485
|
+
export declare function inputReduce(state: ReturnType<typeof createInputState>, key: KeyEvent): PromptStep<string, ReturnType<typeof createInputState>>;
|
|
614
486
|
|
|
615
|
-
/**
|
|
616
|
-
export declare
|
|
487
|
+
/** Render a text-field key state as a styled view. */
|
|
488
|
+
export declare function inputView(state: ReturnType<typeof createInputState>): string;
|
|
617
489
|
|
|
618
490
|
/**
|
|
619
491
|
* Whether a caught value is an `AbortError` — the {@link import('./PromptClient.js').PromptClient}
|
|
@@ -622,15 +494,6 @@ export declare const INTEGER_PATTERN: RegExp;
|
|
|
622
494
|
*/
|
|
623
495
|
export declare function isAbortError(error: unknown): boolean;
|
|
624
496
|
|
|
625
|
-
/** Narrow an unknown wire payload to an answer POST body — a non-empty `id` string plus a `value` key (of any shape) present. */
|
|
626
|
-
export declare function isAnswerPayload(value: unknown): value is {
|
|
627
|
-
readonly id: string;
|
|
628
|
-
readonly value: unknown;
|
|
629
|
-
};
|
|
630
|
-
|
|
631
|
-
/** Narrow an unknown value to a {@link CheckboxChoice} — the `recordOf` shape inlined so no non-exported member lingers (§5). */
|
|
632
|
-
export declare function isCheckboxChoice(value: unknown): value is CheckboxChoice;
|
|
633
|
-
|
|
634
497
|
/**
|
|
635
498
|
* Whether `url` is an INSECURE remote endpoint — a plain `http://` URL whose host is NOT a
|
|
636
499
|
* loopback address. Pure string parsing (no `URL` global), so it stays total on malformed input.
|
|
@@ -653,56 +516,23 @@ export declare function isCheckboxChoice(value: unknown): value is CheckboxChoic
|
|
|
653
516
|
export declare function isInsecureRemote(url: string): boolean;
|
|
654
517
|
|
|
655
518
|
/**
|
|
656
|
-
* 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.
|
|
657
524
|
*
|
|
658
525
|
* @param value - The decoded wire value to inspect
|
|
659
|
-
* @returns Whether
|
|
526
|
+
* @returns Whether the value is a complete pending-form envelope
|
|
660
527
|
*/
|
|
661
|
-
export declare
|
|
528
|
+
export declare function isPendingForm(value: unknown): value is PendingForm;
|
|
662
529
|
|
|
663
|
-
/** Narrow an unknown value to a {@link
|
|
664
|
-
export declare const
|
|
530
|
+
/** Narrow an unknown value to a {@link PendingFormStatus}. */
|
|
531
|
+
export declare const isPendingFormStatus: Guard<PendingFormStatus>;
|
|
665
532
|
|
|
666
533
|
/** Whether a single character is a printable (non-control) character — used by {@link parseKey}'s char fallback. */
|
|
667
534
|
export declare function isPrintable(character: string): boolean;
|
|
668
535
|
|
|
669
|
-
/** Narrow an unknown value to a {@link PromptChoice} — the `recordOf` shape inlined so no non-exported member lingers (§5). */
|
|
670
|
-
export declare function isPromptChoice(value: unknown): value is PromptChoice;
|
|
671
|
-
|
|
672
|
-
/**
|
|
673
|
-
* Narrow an unknown wire value to a {@link PromptThemeOptions} — the §14 guard a remote prompt's
|
|
674
|
-
* `theme` option passes before it reaches a local prompt.
|
|
675
|
-
*
|
|
676
|
-
* @remarks
|
|
677
|
-
* The shape is CLOSED at every level: an unknown icon slot, an unknown role, a non-string glyph, or
|
|
678
|
-
* a role whose value is not a {@link isStyle}-shaped console style rejects the whole theme, so a
|
|
679
|
-
* hostile payload degrades to the default theme rather than partially applying. Glyphs still carry
|
|
680
|
-
* arbitrary text at this point — {@link import('./helpers.js').sanitizeThemeIcons} strips their
|
|
681
|
-
* control bytes on dispatch.
|
|
682
|
-
*
|
|
683
|
-
* The icons and roles shapes are checked against their complete union-keyed guard records. A slot
|
|
684
|
-
* added to either union without an entry here is a compile error rather than a wire theme that is
|
|
685
|
-
* silently refused.
|
|
686
|
-
*/
|
|
687
|
-
export declare const isPromptThemeOptions: Guard<PromptThemeOptions>;
|
|
688
|
-
|
|
689
|
-
/** Narrow an unknown value to a {@link PromptType} — one of the six prompt forms. */
|
|
690
|
-
export declare const isPromptType: Guard<PromptType>;
|
|
691
|
-
|
|
692
|
-
/**
|
|
693
|
-
* Narrow an unknown value to a console {@link Style} — the value every
|
|
694
|
-
* {@link import('./types.js').PromptRole} carries, built from the console module's own
|
|
695
|
-
* {@link import('@orkestrel/console').COLORS} + {@link import('@orkestrel/console').ATTRIBUTES} so
|
|
696
|
-
* the style vocabulary has ONE source.
|
|
697
|
-
*
|
|
698
|
-
* @remarks
|
|
699
|
-
* The record is CLOSED and matches the `Style` contract exactly: `foreground` and `background` are
|
|
700
|
-
* optional and each must name a color (`default` included, as the console `Color` union has it),
|
|
701
|
-
* `attributes` is REQUIRED and must be an array over the attribute set, and any other key rejects
|
|
702
|
-
* the whole value.
|
|
703
|
-
*/
|
|
704
|
-
export declare const isStyle: Guard<Style>;
|
|
705
|
-
|
|
706
536
|
/**
|
|
707
537
|
* Narrow an unknown caught value to a {@link TerminalError}.
|
|
708
538
|
*
|
|
@@ -712,9 +542,11 @@ export declare const isStyle: Guard<Style>;
|
|
|
712
542
|
* @example
|
|
713
543
|
* ```ts
|
|
714
544
|
* try {
|
|
715
|
-
*
|
|
545
|
+
* await terminal.ask(form)
|
|
716
546
|
* } catch (error) {
|
|
717
|
-
* if (isTerminalError(error) && error.code === '
|
|
547
|
+
* if (isTerminalError(error) && error.code === 'CANCEL') {
|
|
548
|
+
* // the person aborted
|
|
549
|
+
* }
|
|
718
550
|
* }
|
|
719
551
|
* ```
|
|
720
552
|
*/
|
|
@@ -723,6 +555,14 @@ export declare function isTerminalError(value: unknown): value is TerminalError;
|
|
|
723
555
|
/** Narrow an unknown value to a {@link TerminalSnapshot}. */
|
|
724
556
|
export declare const isTerminalSnapshot: Guard<TerminalSnapshot>;
|
|
725
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
|
+
|
|
726
566
|
/**
|
|
727
567
|
* The Control Sequence Introducer lead (`ESC[`) for the navigation keys — the prefix of the
|
|
728
568
|
* arrow / home / end / delete sequences {@link SEQUENCE_NAMES} is keyed by. Named `KEY_CSI`
|
|
@@ -735,23 +575,21 @@ export declare const KEY_CSI: string;
|
|
|
735
575
|
export declare const KEY_SS3: string;
|
|
736
576
|
|
|
737
577
|
/**
|
|
738
|
-
* One decoded keypress — the
|
|
739
|
-
*
|
|
740
|
-
*
|
|
741
|
-
*
|
|
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.
|
|
742
582
|
*
|
|
743
583
|
* @remarks
|
|
744
|
-
* - `name` — the canonical key name: a control
|
|
745
|
-
* `
|
|
746
|
-
*
|
|
747
|
-
*
|
|
748
|
-
*
|
|
749
|
-
* - `sequence` — the exact input bytes as a string (a `Uint8Array` is decoded UTF-8). The
|
|
750
|
-
*
|
|
751
|
-
*
|
|
752
|
-
* -
|
|
753
|
-
* (ctrl-c / ctrl-d / ctrl-u / ctrl-a / ctrl-e and the like); `meta` is `true` for an
|
|
754
|
-
* 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.
|
|
755
593
|
*/
|
|
756
594
|
export declare interface KeyEvent {
|
|
757
595
|
readonly name: string;
|
|
@@ -803,43 +641,31 @@ export declare class MemoryTerminalStore implements TerminalStoreInterface {
|
|
|
803
641
|
/** Line feed (`\n`, U+000A) — Enter on some terminals / pasted input. */
|
|
804
642
|
export declare const NEWLINE: string;
|
|
805
643
|
|
|
806
|
-
/** Normalize a checkbox choice input into a full {@link CheckboxChoice} (a bare string becomes both name and value). */
|
|
807
|
-
export declare function normalizeCheckboxChoice(choice: string | CheckboxChoice): CheckboxChoice;
|
|
808
|
-
|
|
809
|
-
/** Normalize a select choice input into a full {@link PromptChoice} (a bare string becomes both name and value). */
|
|
810
|
-
export declare function normalizeChoice(choice: string | PromptChoice): PromptChoice;
|
|
811
|
-
|
|
812
|
-
/** Matches a numeric value (integer or decimal, optional sign). The `numeric` rule tests against this. */
|
|
813
|
-
export declare const NUMERIC_PATTERN: RegExp;
|
|
814
|
-
|
|
815
644
|
/**
|
|
816
|
-
* One parked
|
|
817
|
-
*
|
|
818
|
-
*
|
|
819
|
-
*
|
|
820
|
-
*
|
|
821
|
-
*
|
|
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.
|
|
822
653
|
*/
|
|
823
654
|
export declare interface Parked {
|
|
824
|
-
readonly
|
|
825
|
-
readonly
|
|
826
|
-
readonly expire: () => void;
|
|
655
|
+
readonly form: FormInterface;
|
|
656
|
+
readonly pending: PendingForm;
|
|
827
657
|
readonly cancel: TimerCancel;
|
|
828
658
|
}
|
|
829
659
|
|
|
830
660
|
/**
|
|
831
|
-
* The
|
|
832
|
-
*
|
|
661
|
+
* The parking envelope — everything the broker needs about a park that the form itself does not
|
|
662
|
+
* say.
|
|
833
663
|
*
|
|
834
664
|
* @remarks
|
|
835
|
-
*
|
|
836
|
-
*
|
|
837
|
-
* - `from` / `to` — set ONLY by a {@link TerminalManagerInterface} (the attribution edge); a
|
|
838
|
-
* 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.
|
|
839
667
|
*/
|
|
840
668
|
export declare interface ParkRequest {
|
|
841
|
-
readonly form: PromptType;
|
|
842
|
-
readonly options: PromptFormOptions;
|
|
843
669
|
readonly from?: string;
|
|
844
670
|
readonly to?: string;
|
|
845
671
|
}
|
|
@@ -877,122 +703,70 @@ export declare interface ParkRequest {
|
|
|
877
703
|
*/
|
|
878
704
|
export declare function parseKey(input: string | Uint8Array): KeyEvent;
|
|
879
705
|
|
|
880
|
-
/** The always-passing {@link Validator} — the resolved validator when no rules were supplied. */
|
|
881
|
-
export declare function passing(_input: string): true;
|
|
882
|
-
|
|
883
|
-
/** Options for a masked password {@link import('./helpers.js').passwordReduce} prompt. */
|
|
884
|
-
export declare interface PasswordOptions {
|
|
885
|
-
readonly message: string;
|
|
886
|
-
readonly mask?: string;
|
|
887
|
-
readonly validate?: Validator | ValidationRules;
|
|
888
|
-
readonly styler?: StylerInterface;
|
|
889
|
-
readonly theme?: PromptThemeOptions;
|
|
890
|
-
}
|
|
891
|
-
|
|
892
706
|
/**
|
|
893
707
|
* Advance a password prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`
|
|
894
708
|
* reducer. Identical line-editing to {@link inputReduce} (printable extends, backspace shrinks,
|
|
895
|
-
* ctrl-u clears, ctrl-c cancels) but the view masks the value
|
|
896
|
-
* 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.
|
|
897
710
|
*/
|
|
898
|
-
export declare function passwordReduce(state:
|
|
711
|
+
export declare function passwordReduce(state: ReturnType<typeof createPasswordState>, key: KeyEvent): PromptStep<string, ReturnType<typeof createPasswordState>>;
|
|
899
712
|
|
|
900
|
-
/**
|
|
901
|
-
|
|
902
|
-
* character the view renders in place of each input character.
|
|
903
|
-
*
|
|
904
|
-
* @remarks
|
|
905
|
-
* Built by {@link import('./helpers.js').createPasswordState}; advanced by
|
|
906
|
-
* {@link import('./helpers.js').passwordReduce}. The `value` is the real (unmasked) input;
|
|
907
|
-
* the view shows `mask` repeated `value.length` times.
|
|
908
|
-
*/
|
|
909
|
-
export declare interface PasswordState {
|
|
910
|
-
readonly message: string;
|
|
911
|
-
readonly mask: string;
|
|
912
|
-
readonly validator: Validator;
|
|
913
|
-
readonly styler: StylerInterface;
|
|
914
|
-
readonly theme: PromptTheme;
|
|
915
|
-
readonly value: string;
|
|
916
|
-
readonly error?: string;
|
|
917
|
-
}
|
|
918
|
-
|
|
919
|
-
/** Render a {@link PasswordState} as a styled view — the header, the value masked to `mask` repeated and painted by the `content` role, and any error. */
|
|
920
|
-
export declare function passwordView(state: PasswordState): string;
|
|
713
|
+
/** Render a password-field key state as a styled view. */
|
|
714
|
+
export declare function passwordView(state: ReturnType<typeof createPasswordState>): string;
|
|
921
715
|
|
|
922
716
|
/**
|
|
923
|
-
* One
|
|
924
|
-
*
|
|
925
|
-
*
|
|
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}.
|
|
926
720
|
*
|
|
927
721
|
* @remarks
|
|
928
|
-
* - `id` — the unique id
|
|
929
|
-
*
|
|
930
|
-
*
|
|
931
|
-
*
|
|
932
|
-
* -
|
|
933
|
-
*
|
|
934
|
-
*
|
|
935
|
-
*
|
|
936
|
-
*
|
|
937
|
-
*
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
* {@link PromptInterface} used directly (no manager attribution).
|
|
941
|
-
*/
|
|
942
|
-
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 {
|
|
943
734
|
readonly id: string;
|
|
944
|
-
readonly
|
|
945
|
-
readonly
|
|
946
|
-
readonly options: Readonly<Record<string, unknown>>;
|
|
947
|
-
readonly status: PendingPromptStatus;
|
|
735
|
+
readonly schema: JSONRecord;
|
|
736
|
+
readonly status: PendingFormStatus;
|
|
948
737
|
readonly time: number;
|
|
949
738
|
readonly from?: string;
|
|
950
739
|
readonly to?: string;
|
|
951
740
|
}
|
|
952
741
|
|
|
953
742
|
/**
|
|
954
|
-
* The lifecycle status of a parked {@link
|
|
955
|
-
*
|
|
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.
|
|
956
746
|
*
|
|
957
747
|
* @remarks
|
|
958
|
-
* - `pending` — parked, awaiting
|
|
959
|
-
* - `answered` — answered and accepted
|
|
960
|
-
* - `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.
|
|
961
751
|
*/
|
|
962
|
-
export declare type
|
|
752
|
+
export declare type PendingFormStatus = 'pending' | 'answered' | 'expired';
|
|
963
753
|
|
|
964
754
|
/**
|
|
965
|
-
* The headless
|
|
966
|
-
*
|
|
967
|
-
* rejects on timeout / teardown). The tri-surface's headless arm: there is no terminal here, so a
|
|
968
|
-
* transport forwards each `pending` event to whoever can answer, and {@link answer} resolves the
|
|
969
|
-
* parked Promise — for environments where direct user access is unavailable (a headless server on
|
|
970
|
-
* 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.
|
|
971
757
|
*
|
|
972
758
|
* @remarks
|
|
973
|
-
*
|
|
974
|
-
*
|
|
975
|
-
*
|
|
976
|
-
* ({@link serializePromptOptions}) so a transport can forward them as-is.
|
|
977
|
-
* - **Answer validates + type-checks.** {@link answer} runs the prompt's per-form gate: it
|
|
978
|
-
* type-checks `value` to the form (string / boolean / string[]) AND, for the text forms, runs
|
|
979
|
-
* the validator resolved from the original `validate` rules. A rejected answer returns a failure
|
|
980
|
-
* `Result` with error `'rejected'` and the prompt stays `pending`; an accepted answer resolves the
|
|
981
|
-
* Promise, emits `answer`, and removes the prompt.
|
|
982
|
-
* - **Timeout → expire → reject.** An unanswered prompt expires after `timeout` ms (via the
|
|
983
|
-
* INJECTED timer): `expire` fires and the parked Promise rejects with a {@link TerminalError}
|
|
984
|
-
* (`code: 'EXPIRE'`). {@link destroy} expires every still-pending prompt the same way.
|
|
985
|
-
* - **Deterministic.** The timer is injectable ({@link import('./types.js').TimerHandler}); a test
|
|
986
|
-
* 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.
|
|
987
762
|
*
|
|
988
763
|
* @example
|
|
989
764
|
* ```ts
|
|
990
|
-
* const
|
|
991
|
-
* prompt
|
|
992
|
-
*
|
|
993
|
-
*
|
|
994
|
-
*
|
|
995
|
-
* 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' }
|
|
996
770
|
* ```
|
|
997
771
|
*/
|
|
998
772
|
export declare class Prompt implements PromptInterface {
|
|
@@ -1000,16 +774,10 @@ export declare class Prompt implements PromptInterface {
|
|
|
1000
774
|
constructor(options?: PromptOptions);
|
|
1001
775
|
get emitter(): EmitterInterface<PromptEventMap>;
|
|
1002
776
|
get count(): number;
|
|
1003
|
-
pending(): readonly
|
|
1004
|
-
pending(id: string):
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
input(options: InputOptions): Promise<string>;
|
|
1008
|
-
password(options: PasswordOptions): Promise<string>;
|
|
1009
|
-
confirm(options: ConfirmOptions): Promise<boolean>;
|
|
1010
|
-
select(options: SelectOptions): Promise<string>;
|
|
1011
|
-
checkbox(options: CheckboxOptions): Promise<readonly string[]>;
|
|
1012
|
-
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>;
|
|
1013
781
|
destroy(): void;
|
|
1014
782
|
}
|
|
1015
783
|
|
|
@@ -1039,49 +807,32 @@ export declare const PROMPT_ICONS: Readonly<{
|
|
|
1039
807
|
*/
|
|
1040
808
|
export declare const PROMPT_ROLES: readonly PromptRole[];
|
|
1041
809
|
|
|
1042
|
-
/** A choice item in a {@link SelectOptions} prompt — its displayed `name`, its resolved `value`, and an optional one-line `description`. */
|
|
1043
|
-
export declare interface PromptChoice {
|
|
1044
|
-
readonly name: string;
|
|
1045
|
-
readonly value: string;
|
|
1046
|
-
readonly description?: string;
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
810
|
/**
|
|
1050
|
-
* The SSE
|
|
1051
|
-
*
|
|
1052
|
-
* serialized pending prompts, dispatches EACH to a LOCAL {@link PromptFormInterface} terminal (so
|
|
1053
|
-
* a human at THIS machine answers a prompt parked elsewhere), and POSTs the answer back.
|
|
1054
|
-
* Universal — `fetch` + SSE are web-standard, so it runs in a browser or on a server; the
|
|
1055
|
-
* 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.
|
|
1056
813
|
*
|
|
1057
814
|
* @remarks
|
|
1058
|
-
* - **Connect + reconnect.** {@link connect} opens the SSE stream
|
|
1059
|
-
*
|
|
1060
|
-
*
|
|
1061
|
-
*
|
|
1062
|
-
*
|
|
1063
|
-
*
|
|
1064
|
-
*
|
|
1065
|
-
*
|
|
1066
|
-
*
|
|
1067
|
-
*
|
|
1068
|
-
*
|
|
1069
|
-
*
|
|
1070
|
-
*
|
|
1071
|
-
* `shutdown` event calls {@link disconnect} (not {@link destroy}) — the client stops streaming
|
|
1072
|
-
* without auto-reconnect but stays reusable; a later {@link connect} recovers it.
|
|
1073
|
-
* - **Lean events (§13).** `connect` / `disconnect` / `expire` / `error` — errors are `unknown`.
|
|
1074
|
-
* `disconnect` fires exactly once per connected-to-disconnected transition, whether triggered by
|
|
1075
|
-
* 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.
|
|
1076
828
|
*
|
|
1077
829
|
* @example
|
|
1078
830
|
* ```ts
|
|
1079
831
|
* const client = createPromptClient({
|
|
1080
832
|
* url: 'http://localhost:3001/prompts',
|
|
1081
|
-
* terminal: createTerminal(),
|
|
1082
|
-
* on: { connect: () => log('connected') },
|
|
833
|
+
* terminal: createTerminal(),
|
|
1083
834
|
* })
|
|
1084
|
-
* await client.connect()
|
|
835
|
+
* await client.connect()
|
|
1085
836
|
* ```
|
|
1086
837
|
*/
|
|
1087
838
|
export declare class PromptClient implements PromptClientInterface {
|
|
@@ -1096,13 +847,15 @@ export declare class PromptClient implements PromptClientInterface {
|
|
|
1096
847
|
}
|
|
1097
848
|
|
|
1098
849
|
/**
|
|
1099
|
-
* The client's event map
|
|
850
|
+
* The client's event map — lean, errors `unknown`, no listener-error event.
|
|
1100
851
|
*
|
|
1101
852
|
* @remarks
|
|
1102
853
|
* - `connect` — the SSE stream opened.
|
|
1103
|
-
* - `disconnect` — the SSE stream closed
|
|
1104
|
-
*
|
|
1105
|
-
* - `
|
|
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.
|
|
1106
859
|
*/
|
|
1107
860
|
export declare type PromptClientEventMap = {
|
|
1108
861
|
readonly connect: readonly [];
|
|
@@ -1112,17 +865,22 @@ export declare type PromptClientEventMap = {
|
|
|
1112
865
|
};
|
|
1113
866
|
|
|
1114
867
|
/**
|
|
1115
|
-
* The SSE
|
|
1116
|
-
*
|
|
1117
|
-
*
|
|
1118
|
-
*
|
|
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.
|
|
1119
872
|
*
|
|
1120
873
|
* @remarks
|
|
1121
|
-
* - **Connect.** {@link connect} opens the SSE stream
|
|
1122
|
-
*
|
|
1123
|
-
*
|
|
1124
|
-
* - **
|
|
1125
|
-
*
|
|
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.
|
|
1126
884
|
* - **`connected`** reflects whether the stream is currently open.
|
|
1127
885
|
*/
|
|
1128
886
|
export declare interface PromptClientInterface {
|
|
@@ -1135,27 +893,27 @@ export declare interface PromptClientInterface {
|
|
|
1135
893
|
}
|
|
1136
894
|
|
|
1137
895
|
/**
|
|
1138
|
-
* Options for {@link import('./factories.js').createPromptClient}
|
|
896
|
+
* Options for {@link import('./factories.js').createPromptClient} and the
|
|
897
|
+
* {@link PromptClientInterface}.
|
|
1139
898
|
*
|
|
1140
899
|
* @remarks
|
|
1141
|
-
* - `url` — the remote broker's SSE endpoint
|
|
1142
|
-
* - `terminal` — the LOCAL {@link
|
|
1143
|
-
*
|
|
1144
|
-
* - `token` — an optional auth token, sent as the
|
|
1145
|
-
*
|
|
1146
|
-
* - `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.
|
|
1147
906
|
* - `delay` — ms to wait before each reconnect attempt (default
|
|
1148
907
|
* {@link import('./constants.js').DEFAULT_RECONNECT_DELAY_MS}).
|
|
1149
|
-
* - `on` — initial {@link PromptClientEventMap} listeners
|
|
1150
|
-
* - `error` — the emitter's listener-error handler
|
|
1151
|
-
* - `fetch` — the injected {@link FetchHandler}
|
|
1152
|
-
*
|
|
1153
|
-
*
|
|
1154
|
-
* `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`.
|
|
1155
913
|
*/
|
|
1156
914
|
export declare interface PromptClientOptions {
|
|
1157
915
|
readonly url: string;
|
|
1158
|
-
readonly terminal:
|
|
916
|
+
readonly terminal: TerminalInterface;
|
|
1159
917
|
readonly token?: string;
|
|
1160
918
|
readonly reconnect?: boolean;
|
|
1161
919
|
readonly delay?: number;
|
|
@@ -1166,111 +924,77 @@ export declare interface PromptClientOptions {
|
|
|
1166
924
|
}
|
|
1167
925
|
|
|
1168
926
|
/**
|
|
1169
|
-
* The broker's event map
|
|
927
|
+
* The broker's event map — lean, errors `unknown`, no listener-error event.
|
|
1170
928
|
*
|
|
1171
929
|
* @remarks
|
|
1172
|
-
* - `pending` — a
|
|
1173
|
-
*
|
|
1174
|
-
* - `
|
|
1175
|
-
* - `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.
|
|
1176
933
|
*/
|
|
1177
934
|
export declare type PromptEventMap = {
|
|
1178
|
-
readonly pending: readonly [
|
|
1179
|
-
readonly answer: readonly [id: string,
|
|
935
|
+
readonly pending: readonly [form: PendingForm];
|
|
936
|
+
readonly answer: readonly [id: string, values: FormValues];
|
|
1180
937
|
readonly expire: readonly [id: string];
|
|
1181
938
|
};
|
|
1182
939
|
|
|
1183
|
-
/**
|
|
1184
|
-
* The shared ASYNC prompt contract — the six prompt forms as Promise-returning methods. The
|
|
1185
|
-
* ONE vocabulary BOTH the headless {@link PromptInterface} broker (this module) and the server
|
|
1186
|
-
* `Terminal` driver (T-c) implement, so a prompt issued through this surface resolves the same
|
|
1187
|
-
* way on every surface (local TTY, headless broker, remote bridge).
|
|
1188
|
-
*
|
|
1189
|
-
* @remarks
|
|
1190
|
-
* Each method takes the prompt's `*Options` and resolves to that form's value type:
|
|
1191
|
-
* - `input` / `password` / `select` / `editor` → a `string`
|
|
1192
|
-
* - `confirm` → a `boolean`
|
|
1193
|
-
* - `checkbox` → a `readonly string[]` (the checked values, in choice order)
|
|
1194
|
-
*
|
|
1195
|
-
* This is a behavioral CONTRACT (the method surface), not an observable entity — the broker and
|
|
1196
|
-
* the driver add their own emitter / lifecycle on top. The {@link PromptClient} dispatches a
|
|
1197
|
-
* remote {@link PendingPrompt} to a LOCAL `PromptFormInterface` (so a human at this machine
|
|
1198
|
-
* answers a prompt parked elsewhere).
|
|
1199
|
-
*/
|
|
1200
|
-
export declare interface PromptFormInterface {
|
|
1201
|
-
input(options: InputOptions): Promise<string>;
|
|
1202
|
-
password(options: PasswordOptions): Promise<string>;
|
|
1203
|
-
confirm(options: ConfirmOptions): Promise<boolean>;
|
|
1204
|
-
select(options: SelectOptions): Promise<string>;
|
|
1205
|
-
checkbox(options: CheckboxOptions): Promise<readonly string[]>;
|
|
1206
|
-
editor(options: EditorOptions): Promise<string>;
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
/**
|
|
1210
|
-
* The union of every prompt form's options bag — the `options` a {@link ParkRequest} carries,
|
|
1211
|
-
* narrowed at the call site by the paired {@link PromptType}.
|
|
1212
|
-
*/
|
|
1213
|
-
export declare type PromptFormOptions = InputOptions | PasswordOptions | ConfirmOptions | SelectOptions | CheckboxOptions | EditorOptions;
|
|
1214
|
-
|
|
1215
940
|
/** The styled prompt-message header (`? message`) — the leading line every active prompt view shares, themed by the `question` + `message` roles. */
|
|
1216
941
|
export declare function promptHeader(styler: StylerInterface, theme: PromptTheme, message: string): string;
|
|
1217
942
|
|
|
1218
943
|
/**
|
|
1219
|
-
* One glyph slot a
|
|
1220
|
-
* set
|
|
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.
|
|
1221
946
|
*
|
|
1222
947
|
* @remarks
|
|
1223
|
-
* - `question` — the leading mark on a
|
|
1224
|
-
* - `pointer` — the cursor before the input
|
|
1225
|
-
* - `dot` / `selected` — an unfocused / focused row marker in a
|
|
1226
|
-
* - `checked` / `unchecked` — a checked / unchecked box in a
|
|
1227
|
-
* - `success` / `error` — the mark on a
|
|
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.
|
|
1228
953
|
*/
|
|
1229
954
|
export declare type PromptIcon = 'question' | 'pointer' | 'dot' | 'selected' | 'checked' | 'unchecked' | 'success' | 'error';
|
|
1230
955
|
|
|
1231
956
|
/**
|
|
1232
|
-
* The headless
|
|
1233
|
-
*
|
|
1234
|
-
*
|
|
1235
|
-
*
|
|
1236
|
-
* 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.
|
|
1237
961
|
*
|
|
1238
962
|
* @remarks
|
|
1239
|
-
* - **
|
|
1240
|
-
*
|
|
1241
|
-
*
|
|
1242
|
-
* - **
|
|
1243
|
-
*
|
|
1244
|
-
*
|
|
1245
|
-
* - **Timeout
|
|
1246
|
-
*
|
|
1247
|
-
*
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
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 {
|
|
1251
974
|
readonly emitter: EmitterInterface<PromptEventMap>;
|
|
1252
975
|
readonly count: number;
|
|
1253
|
-
park(
|
|
1254
|
-
pending(): readonly
|
|
1255
|
-
pending(id: string):
|
|
1256
|
-
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>;
|
|
1257
980
|
destroy(): void;
|
|
1258
981
|
}
|
|
1259
982
|
|
|
1260
983
|
/**
|
|
1261
|
-
* 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.
|
|
1262
986
|
*
|
|
1263
987
|
* @remarks
|
|
1264
|
-
* - `on` — initial {@link PromptEventMap} listeners
|
|
1265
|
-
* - `error` — the emitter's listener-error handler
|
|
1266
|
-
* - `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
|
|
1267
991
|
* {@link import('./constants.js').DEFAULT_PROMPT_TIMEOUT_MS}).
|
|
1268
|
-
* - `timer` — the injected {@link TimerHandler}
|
|
992
|
+
* - `timer` — the injected {@link TimerHandler}, default the host `setTimeout`; supply a
|
|
1269
993
|
* deterministic timer to drive expiry in tests without real time.
|
|
1270
|
-
* - `cap` — the maximum number of
|
|
1271
|
-
*
|
|
1272
|
-
*
|
|
1273
|
-
*
|
|
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.
|
|
1274
998
|
*/
|
|
1275
999
|
export declare interface PromptOptions {
|
|
1276
1000
|
readonly on?: EmitterHooks<PromptEventMap>;
|
|
@@ -1281,54 +1005,50 @@ export declare interface PromptOptions {
|
|
|
1281
1005
|
}
|
|
1282
1006
|
|
|
1283
1007
|
/**
|
|
1284
|
-
* One styling slot a
|
|
1285
|
-
*
|
|
1286
|
-
*
|
|
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.
|
|
1287
1011
|
*
|
|
1288
1012
|
* @remarks
|
|
1289
|
-
* - `question` — the leading
|
|
1290
|
-
* - `pointer` — the cursor before the input
|
|
1291
|
-
* - `message` — the
|
|
1292
|
-
* - `content` — the
|
|
1293
|
-
* label, a committed editor line
|
|
1294
|
-
*
|
|
1295
|
-
* - `success` / `error` — a
|
|
1296
|
-
* - `selected` — a chosen value: the checked box, the focused
|
|
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.
|
|
1297
1022
|
* - `focus` — the label of the row the cursor is on.
|
|
1298
|
-
* - `hint` — dim supplementary text: a default value, a key hint, a selection count, a committed
|
|
1299
|
-
*
|
|
1300
|
-
* - `
|
|
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.
|
|
1301
1027
|
*/
|
|
1302
1028
|
export declare type PromptRole = 'question' | 'pointer' | 'message' | 'content' | 'success' | 'error' | 'selected' | 'focus' | 'hint' | 'muted' | 'description';
|
|
1303
1029
|
|
|
1304
1030
|
/**
|
|
1305
|
-
*
|
|
1306
|
-
*
|
|
1307
|
-
*
|
|
1308
|
-
* progression), never `kind` (AGENTS §4.4).
|
|
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`.
|
|
1309
1034
|
*/
|
|
1310
1035
|
export declare type PromptStatus = 'active' | 'submit' | 'cancel';
|
|
1311
1036
|
|
|
1312
1037
|
/**
|
|
1313
|
-
* The result of one reducer step — the next `state`, the rendered `view`, the `status`, and,
|
|
1314
|
-
*
|
|
1315
|
-
*
|
|
1316
|
-
* 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`.
|
|
1317
1041
|
*
|
|
1318
|
-
* @typeParam T - The
|
|
1319
|
-
*
|
|
1320
|
-
*
|
|
1321
|
-
* 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.
|
|
1322
1045
|
*
|
|
1323
1046
|
* @remarks
|
|
1324
|
-
* - `state` — the next immutable
|
|
1325
|
-
*
|
|
1326
|
-
* - `view` — the styled string to render
|
|
1327
|
-
*
|
|
1328
|
-
*
|
|
1329
|
-
* - `status` — the {@link PromptStatus}: `active` to continue, `submit` when resolved, `cancel`
|
|
1330
|
-
* on abort.
|
|
1331
|
-
* - `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.
|
|
1332
1052
|
*/
|
|
1333
1053
|
export declare interface PromptStep<T, S> {
|
|
1334
1054
|
readonly state: S;
|
|
@@ -1338,17 +1058,16 @@ export declare interface PromptStep<T, S> {
|
|
|
1338
1058
|
}
|
|
1339
1059
|
|
|
1340
1060
|
/**
|
|
1341
|
-
* A
|
|
1342
|
-
*
|
|
1343
|
-
*
|
|
1344
|
-
* resolved on every prompt state, so a view never reads a hardcoded glyph or color.
|
|
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}.
|
|
1345
1064
|
*
|
|
1346
1065
|
* @remarks
|
|
1347
1066
|
* A role's value is the console module's own {@link Style} — the one style model the whole console
|
|
1348
|
-
*
|
|
1349
|
-
* {@link StylerInterface
|
|
1350
|
-
* carries a
|
|
1351
|
-
* color, which
|
|
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.
|
|
1352
1071
|
*/
|
|
1353
1072
|
export declare interface PromptTheme {
|
|
1354
1073
|
readonly icons: Readonly<Record<PromptIcon, string>>;
|
|
@@ -1356,8 +1075,8 @@ export declare interface PromptTheme {
|
|
|
1356
1075
|
}
|
|
1357
1076
|
|
|
1358
1077
|
/**
|
|
1359
|
-
* The PARTIAL {@link PromptTheme}
|
|
1360
|
-
*
|
|
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
|
|
1361
1080
|
* {@link import('./constants.js').DEFAULT_PROMPT_THEME} leaf by leaf. Supplying one icon or one
|
|
1362
1081
|
* role leaves every other slot at its default.
|
|
1363
1082
|
*/
|
|
@@ -1366,105 +1085,44 @@ export declare interface PromptThemeOptions {
|
|
|
1366
1085
|
readonly roles?: Readonly<Partial<Record<PromptRole, Style>>>;
|
|
1367
1086
|
}
|
|
1368
1087
|
|
|
1369
|
-
/**
|
|
1370
|
-
|
|
1371
|
-
* dispatches on. Names the prompt axis; a named value set (not a toggle), so it stays a union.
|
|
1372
|
-
*/
|
|
1373
|
-
export declare type PromptType = 'input' | 'password' | 'confirm' | 'select' | 'checkbox' | 'editor';
|
|
1374
|
-
|
|
1375
|
-
/**
|
|
1376
|
-
* The union of a resolved prompt's value shapes — a `string` (`input` / `password` / `select` /
|
|
1377
|
-
* `editor`), a `boolean` (`confirm`), or a `readonly string[]` (`checkbox`, the checked values in
|
|
1378
|
-
* choice order). The type a {@link Ticket}'s `value` Promise resolves to.
|
|
1379
|
-
*/
|
|
1380
|
-
export declare type PromptValue = string | boolean | readonly string[];
|
|
1381
|
-
|
|
1382
|
-
/**
|
|
1383
|
-
* Rebuild a wire-decoded `validate` payload into a {@link ValidationRules} bag — the inverse of
|
|
1384
|
-
* {@link serializeValidationRules}. Keeps only the primitive rule values (`boolean` / `number` /
|
|
1385
|
-
* `string`) a serialized prompt could carry; an empty / non-record / all-dropped payload yields
|
|
1386
|
-
* `undefined` (no rules to apply). The client feeds the result back through {@link resolveValidation}.
|
|
1387
|
-
*/
|
|
1388
|
-
export declare function reconstructValidationRules(value: unknown): ValidationRules | undefined;
|
|
1389
|
-
|
|
1390
|
-
/** Read a `choices` option as a list of bare strings / full choices — each element narrowed by `guard`, off-shape elements stringified. */
|
|
1391
|
-
export declare function resolveChoices<TChoice extends PromptChoice | CheckboxChoice>(options: Readonly<Record<string, unknown>>, guard: Guard<TChoice>): ReadonlyArray<string | TChoice>;
|
|
1392
|
-
|
|
1393
|
-
/** Read one option by key, narrowed by `guard` — `undefined` when absent or off-shape (§14, never an `as`). */
|
|
1394
|
-
export declare function resolveOption<T>(options: Readonly<Record<string, unknown>>, key: string, guard: Guard<T>): T | undefined;
|
|
1088
|
+
/** Carriage return (`\r`, U+000D) — Enter on most terminals. */
|
|
1089
|
+
export declare const RETURN: string;
|
|
1395
1090
|
|
|
1396
1091
|
/**
|
|
1397
|
-
*
|
|
1398
|
-
*
|
|
1399
|
-
* order (required → minimum → maximum → pattern → email → url → numeric → integer → alphanumeric
|
|
1400
|
-
* → custom) and composed; absent / empty input yields an always-passing validator. Pure.
|
|
1401
|
-
*
|
|
1402
|
-
* @remarks
|
|
1403
|
-
* Unlike a prior variant (which returned `Validator | undefined`), this ALWAYS returns a
|
|
1404
|
-
* `Validator` — an absent or empty rule set yields a validator that returns `true` for every
|
|
1405
|
-
* input. That keeps a prompt's state unconditional (it always holds a real validator to apply on
|
|
1406
|
-
* submit), with no `undefined` branch at the call site.
|
|
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.
|
|
1407
1094
|
*
|
|
1408
|
-
* @param
|
|
1409
|
-
* @returns The
|
|
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
|
|
1410
1097
|
*
|
|
1411
1098
|
* @example
|
|
1412
1099
|
* ```ts
|
|
1413
|
-
*
|
|
1414
|
-
* v('') // 'This field is required'
|
|
1415
|
-
* v('ab') // 'Must be at least 3 characters'
|
|
1416
|
-
* v('abc') // true
|
|
1100
|
+
* sanitizeDisplayText('Q\rOVERWRITE\nNEXT\tX') // 'QOVERWRITENEXTX'
|
|
1417
1101
|
* ```
|
|
1418
1102
|
*/
|
|
1419
|
-
export declare function
|
|
1420
|
-
|
|
1421
|
-
/** Carriage return (`\r`, U+000D) — Enter on most terminals. */
|
|
1422
|
-
export declare const RETURN: string;
|
|
1423
|
-
|
|
1424
|
-
/**
|
|
1425
|
-
* Each built-in validation rule's default error message — what the composed {@link
|
|
1426
|
-
* import('./types.js').Validator} returns when that rule fails (the `minimum` / `maximum`
|
|
1427
|
-
* messages are interpolated with the configured length at build time). Frozen; the source of
|
|
1428
|
-
* truth for the rule-failure copy.
|
|
1429
|
-
*/
|
|
1430
|
-
export declare const RULE_MESSAGES: Readonly<{
|
|
1431
|
-
required: "This field is required";
|
|
1432
|
-
minimum: "Must be at least {count} characters";
|
|
1433
|
-
maximum: "Must be at most {count} characters";
|
|
1434
|
-
pattern: "Must match pattern: {pattern}";
|
|
1435
|
-
email: "Must be a valid email address";
|
|
1436
|
-
url: "Must be a valid URL";
|
|
1437
|
-
numeric: "Must be a numeric value";
|
|
1438
|
-
integer: "Must be an integer";
|
|
1439
|
-
alphanumeric: "Must contain only letters and digits";
|
|
1440
|
-
invalid: "Invalid input";
|
|
1441
|
-
}>;
|
|
1103
|
+
export declare function sanitizeDisplayText(text: string): string;
|
|
1442
1104
|
|
|
1443
1105
|
/**
|
|
1444
|
-
* Sanitize
|
|
1445
|
-
* {@link stripControls} — shared by the `select` and `checkbox` branches of
|
|
1446
|
-
* {@link dispatchPendingPrompt} so a remote-supplied choice can never inject raw control bytes
|
|
1447
|
-
* into the local terminal's rendered view.
|
|
1106
|
+
* Sanitize every terminal-readable string in a parsed form schema.
|
|
1448
1107
|
*
|
|
1449
|
-
* @
|
|
1450
|
-
*
|
|
1451
|
-
*
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
* Sanitize text for one single-line display slot. Composes console's {@link stripControls} pass
|
|
1457
|
-
* with removal of tab, line feed, and carriage return, so no C0 control or DEL survives.
|
|
1108
|
+
* @remarks
|
|
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.
|
|
1458
1115
|
*
|
|
1459
|
-
* @param
|
|
1460
|
-
* @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
|
|
1461
1118
|
*
|
|
1462
1119
|
* @example
|
|
1463
1120
|
* ```ts
|
|
1464
|
-
*
|
|
1121
|
+
* sanitizeSchema({ fields: [{ control: 'text', name: 'na\u001bme', label: 'N\u0000ame' }] })
|
|
1122
|
+
* // { fields: [{ control: 'text', name: 'na\u001bme', label: 'Name' }] }
|
|
1465
1123
|
* ```
|
|
1466
1124
|
*/
|
|
1467
|
-
export declare function
|
|
1125
|
+
export declare function sanitizeSchema(schema: FormSchema): FormSchema;
|
|
1468
1126
|
|
|
1469
1127
|
/**
|
|
1470
1128
|
* Sanitize every glyph a wire-supplied {@link PromptThemeOptions} carries for a single-line display
|
|
@@ -1476,53 +1134,16 @@ export declare function sanitizeDisplayText(text: string): string;
|
|
|
1476
1134
|
*/
|
|
1477
1135
|
export declare function sanitizeThemeIcons(theme: PromptThemeOptions): PromptThemeOptions;
|
|
1478
1136
|
|
|
1479
|
-
/**
|
|
1480
|
-
* Options for a single-selection {@link import('./helpers.js').selectReduce} prompt.
|
|
1481
|
-
*
|
|
1482
|
-
* @remarks
|
|
1483
|
-
* `choices` accepts bare strings (used as both `name` and `value`) or full {@link PromptChoice}
|
|
1484
|
-
* objects; {@link import('./helpers.js').createSelectState} normalizes them. `default` pre-focuses
|
|
1485
|
-
* the choice whose `value` matches it. `hint` adds a key hint after the message — the list is
|
|
1486
|
-
* self-explanatory at a TTY, so there is no computed default; the server driver shows it on the
|
|
1487
|
-
* numbered fallback too.
|
|
1488
|
-
*/
|
|
1489
|
-
export declare interface SelectOptions {
|
|
1490
|
-
readonly message: string;
|
|
1491
|
-
readonly choices: ReadonlyArray<string | PromptChoice>;
|
|
1492
|
-
readonly default?: string;
|
|
1493
|
-
readonly hint?: string;
|
|
1494
|
-
readonly styler?: StylerInterface;
|
|
1495
|
-
readonly theme?: PromptThemeOptions;
|
|
1496
|
-
}
|
|
1497
|
-
|
|
1498
1137
|
/**
|
|
1499
1138
|
* Advance a select prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`
|
|
1500
1139
|
* reducer. `up` / `down` (and `k` / `j`) move the focus, WRAPPING at the ends; return submits the
|
|
1501
1140
|
* focused choice's `value`; ctrl-c cancels. An empty choice list can never submit (a higher layer
|
|
1502
1141
|
* guards against it); any other key is ignored.
|
|
1503
1142
|
*/
|
|
1504
|
-
export declare function selectReduce(state:
|
|
1505
|
-
|
|
1506
|
-
/**
|
|
1507
|
-
* The immutable state of a select prompt — the normalized choices, the optional hint, the
|
|
1508
|
-
* resolved styler + theme, and the `focused` index (the highlighted row).
|
|
1509
|
-
*
|
|
1510
|
-
* @remarks
|
|
1511
|
-
* Built by {@link import('./helpers.js').createSelectState}; advanced by
|
|
1512
|
-
* {@link import('./helpers.js').selectReduce}. `up` / `down` move `focused` (wrapping at the
|
|
1513
|
-
* ends); `return` submits the focused choice's `value`.
|
|
1514
|
-
*/
|
|
1515
|
-
export declare interface SelectState {
|
|
1516
|
-
readonly message: string;
|
|
1517
|
-
readonly choices: readonly PromptChoice[];
|
|
1518
|
-
readonly hint?: string;
|
|
1519
|
-
readonly styler: StylerInterface;
|
|
1520
|
-
readonly theme: PromptTheme;
|
|
1521
|
-
readonly focused: number;
|
|
1522
|
-
}
|
|
1143
|
+
export declare function selectReduce(state: ReturnType<typeof createSelectState>, key: KeyEvent): PromptStep<string, ReturnType<typeof createSelectState>>;
|
|
1523
1144
|
|
|
1524
|
-
/** Render a
|
|
1525
|
-
export declare function selectView(state:
|
|
1145
|
+
/** Render a select-field key state as a multi-line styled view. */
|
|
1146
|
+
export declare function selectView(state: ReturnType<typeof createSelectState>): string;
|
|
1526
1147
|
|
|
1527
1148
|
/**
|
|
1528
1149
|
* The exact escape SEQUENCE → canonical key NAME table {@link import('./helpers.js').parseKey}
|
|
@@ -1538,54 +1159,20 @@ export declare function selectView(state: SelectState): string;
|
|
|
1538
1159
|
*/
|
|
1539
1160
|
export declare const SEQUENCE_NAMES: Readonly<Record<string, string>>;
|
|
1540
1161
|
|
|
1541
|
-
/** Strip functions from a `choices` option — each choice keeps its plain fields; a bare string passes through. */
|
|
1542
|
-
export declare function serializeChoices(choices: unknown): readonly unknown[];
|
|
1543
|
-
|
|
1544
1162
|
/** Serialize a parked prompt's expiry into a {@link WireEvent} — event `'expire'`, `data` the JSON-stringified `{ id }` payload. */
|
|
1545
1163
|
export declare function serializeExpire(id: string): WireEvent;
|
|
1546
1164
|
|
|
1547
|
-
/** Serialize a parked {@link
|
|
1548
|
-
export declare function serializePending(
|
|
1549
|
-
|
|
1550
|
-
/**
|
|
1551
|
-
* Produce the WIRE-SAFE form of a prompt's options — the {@link PendingPrompt.options} a broker
|
|
1552
|
-
* serializes over SSE. Drops everything that cannot cross the wire (a `styler`, and any
|
|
1553
|
-
* function-valued `validate` rule), while KEEPING the declarative data a remote client needs to
|
|
1554
|
-
* reconstruct the prompt: the {@link ValidationRules} as data, plus `message` / `choices` /
|
|
1555
|
-
* `default` / `mask` / `min` / `max` / `hint` / `theme`. This is WHY T-a's validation is
|
|
1556
|
-
* rules-as-data, and why a theme is data too: a `Validator`
|
|
1557
|
-
* FUNCTION can't be serialized, but its declarative rules can — the client rebuilds the validator
|
|
1558
|
-
* from them via {@link resolveValidation}.
|
|
1559
|
-
*
|
|
1560
|
-
* @remarks
|
|
1561
|
-
* - **Functions are dropped.** A top-level function value (e.g. a bare-`Validator` `validate`) is
|
|
1562
|
-
* omitted entirely; the `styler` (a fluent function-bearing object) is dropped by key.
|
|
1563
|
-
* - **`validate` rules are flattened.** A {@link ValidationRules} bag is copied with each
|
|
1564
|
-
* function rule replaced by `true` (the rule's INTENT survives as the built-in check; its
|
|
1565
|
-
* custom function does not). A bare-function `validate` is dropped (no declarative form to keep).
|
|
1566
|
-
* - **`choices` are function-stripped.** Each choice keeps its plain fields (`name` / `value` /
|
|
1567
|
-
* `description` / `checked`); a bare string passes through.
|
|
1568
|
-
*
|
|
1569
|
-
* @param options - The raw prompt options bag (may hold functions / a styler)
|
|
1570
|
-
* @returns A JSON-safe options record — only serializable, declarative data
|
|
1571
|
-
*/
|
|
1572
|
-
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;
|
|
1573
1167
|
|
|
1574
1168
|
/** The {@link WireEvent} a broker/manager sends when it is going away — event `'shutdown'`, no payload. */
|
|
1575
1169
|
export declare function serializeShutdown(): WireEvent;
|
|
1576
1170
|
|
|
1577
|
-
/**
|
|
1578
|
-
* Flatten a `validate` option to its wire-safe {@link ValidationRules} DATA — a function rule
|
|
1579
|
-
* becomes `true` (its built-in check survives; its body cannot cross the wire). A bare-function
|
|
1580
|
-
* `validate` (no rules object) has no declarative form, so it yields `undefined` (dropped).
|
|
1581
|
-
*/
|
|
1582
|
-
export declare function serializeValidationRules(validate: unknown): Readonly<Record<string, unknown>> | undefined;
|
|
1583
|
-
|
|
1584
1171
|
/** Space (U+0020). */
|
|
1585
1172
|
export declare const SPACE = " ";
|
|
1586
1173
|
|
|
1587
1174
|
/**
|
|
1588
|
-
* The maximum number of characters the {@link import('./types.js').
|
|
1175
|
+
* The maximum number of characters the {@link import('./types.js').PromptClientInterface} lets its
|
|
1589
1176
|
* SSE parser buffer before treating the stream as hostile — 1 MiB, comfortably above any
|
|
1590
1177
|
* legitimate prompt payload. Passed as the `limit` to `createSSEParser` so an unterminated
|
|
1591
1178
|
* or oversized `data:` field cannot grow the buffer without bound (a memory-exhaustion guard).
|
|
@@ -1593,11 +1180,11 @@ export declare const SPACE = " ";
|
|
|
1593
1180
|
export declare const SSE_BUFFER_LIMIT = 1048576;
|
|
1594
1181
|
|
|
1595
1182
|
/**
|
|
1596
|
-
* 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}
|
|
1597
1184
|
* dispatches on. Frozen; the source of truth for the wire event vocabulary.
|
|
1598
1185
|
*
|
|
1599
1186
|
* @remarks
|
|
1600
|
-
* - `pending` — a serialized {@link import('./types.js').
|
|
1187
|
+
* - `pending` — a serialized {@link import('./types.js').PendingForm} to dispatch and answer.
|
|
1601
1188
|
* - `expire` — an `{ id }` payload: the broker expired a parked prompt (the client drops it).
|
|
1602
1189
|
* - `shutdown` — the broker is going away; the client disconnects (no auto-reconnect) but stays reusable.
|
|
1603
1190
|
*/
|
|
@@ -1613,47 +1200,81 @@ export declare function submitHeader(styler: StylerInterface, theme: PromptTheme
|
|
|
1613
1200
|
/** Tab (`\t`, U+0009). */
|
|
1614
1201
|
export declare const TAB: string;
|
|
1615
1202
|
|
|
1616
|
-
/**
|
|
1617
|
-
|
|
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';
|
|
1210
|
+
};
|
|
1618
1211
|
|
|
1619
1212
|
/**
|
|
1620
|
-
*
|
|
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.
|
|
1621
1217
|
*
|
|
1622
1218
|
* @remarks
|
|
1623
|
-
* Carries a {@link TerminalErrorCode} and an optional `context` bag
|
|
1624
|
-
*
|
|
1625
|
-
*
|
|
1626
|
-
* `EXPIRE`); or when the user aborts an interactive server-`Terminal` prompt with ctrl-c
|
|
1627
|
-
* (`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`.
|
|
1628
1222
|
*/
|
|
1629
1223
|
export declare class TerminalError extends Error {
|
|
1630
1224
|
/** The machine-readable condition — see {@link TerminalErrorCode}. */
|
|
1631
1225
|
readonly code: TerminalErrorCode;
|
|
1632
|
-
/** An optional context bag naming the offending
|
|
1226
|
+
/** An optional context bag naming the offending values — see the class {@link TerminalError remarks}. */
|
|
1633
1227
|
readonly context?: Readonly<Record<string, unknown>>;
|
|
1634
1228
|
constructor(code: TerminalErrorCode, message: string, context?: Readonly<Record<string, unknown>>);
|
|
1635
1229
|
}
|
|
1636
1230
|
|
|
1637
1231
|
/**
|
|
1638
1232
|
* The machine-readable condition carried by a {@link import('./errors.js').TerminalError} — the
|
|
1639
|
-
* 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`.
|
|
1640
1234
|
*
|
|
1641
1235
|
* @remarks
|
|
1642
|
-
*
|
|
1643
|
-
*
|
|
1644
|
-
*
|
|
1645
|
-
*
|
|
1646
|
-
* - `
|
|
1647
|
-
*
|
|
1648
|
-
*
|
|
1649
|
-
*
|
|
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}.
|
|
1650
1251
|
*/
|
|
1651
1252
|
export declare type TerminalErrorCode = 'EXPIRE' | 'CANCEL' | 'DRIVER' | 'DEADLOCK' | 'TARGET' | 'LIMIT' | 'DESTROYED';
|
|
1652
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
|
+
|
|
1653
1274
|
/**
|
|
1654
1275
|
* The multi-endpoint terminal MANAGER — a registry of named {@link PromptInterface} brokers (one
|
|
1655
|
-
* per endpoint), so several parties can `ask`
|
|
1656
|
-
* 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
|
|
1657
1278
|
* asks.
|
|
1658
1279
|
*
|
|
1659
1280
|
* @remarks
|
|
@@ -1664,22 +1285,23 @@ export declare type TerminalErrorCode = 'EXPIRE' | 'CANCEL' | 'DRIVER' | 'DEADLO
|
|
|
1664
1285
|
* - **`ask`.** The target must already be mounted via {@link add} — `ask` never auto-adds it;
|
|
1665
1286
|
* rejects `TARGET` for an unknown `to` (listing the known names). Rejects `DEADLOCK` when parking
|
|
1666
1287
|
* `from → to` would close a cycle over the CURRENT in-flight edge set (walked transitively);
|
|
1667
|
-
* otherwise parks through the target's broker and
|
|
1668
|
-
*
|
|
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.
|
|
1669
1290
|
* - **Durable open / save.** `open(name)` restores an EMPTY broker from the `store` (parked
|
|
1670
1291
|
* Promises are process-bound and never resurrected); `save(name)` persists the endpoint's
|
|
1671
1292
|
* configured `timeout`.
|
|
1672
1293
|
* - **Removal.** `remove` drops one endpoint, a batch (§9.2, array overload FIRST), or every
|
|
1673
|
-
* endpoint when called without an argument. It destroys each broker, which expires every
|
|
1294
|
+
* endpoint when called without an argument. It destroys each broker, which expires every form
|
|
1674
1295
|
* still parked on it. `destroy` is idempotent.
|
|
1675
1296
|
*
|
|
1676
1297
|
* @example
|
|
1677
1298
|
* ```ts
|
|
1299
|
+
* const form = createForm({ fields: [{ control: 'text', name: 'name' }] })
|
|
1678
1300
|
* const manager = new TerminalManager()
|
|
1679
1301
|
* manager.add('agent')
|
|
1680
|
-
* const
|
|
1681
|
-
* manager.answer('agent', manager.pending('agent')[0].id, 'Ada')
|
|
1682
|
-
* 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' }
|
|
1683
1305
|
* ```
|
|
1684
1306
|
*/
|
|
1685
1307
|
export declare class TerminalManager implements TerminalManagerInterface {
|
|
@@ -1689,14 +1311,11 @@ export declare class TerminalManager implements TerminalManagerInterface {
|
|
|
1689
1311
|
get count(): number;
|
|
1690
1312
|
terminal(name: string): PromptInterface | undefined;
|
|
1691
1313
|
terminals(): readonly string[];
|
|
1692
|
-
add(name: string, options?:
|
|
1693
|
-
ask(from: string, to: string, form:
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
pending(): readonly PendingPrompt[];
|
|
1698
|
-
pending(to: string): readonly PendingPrompt[];
|
|
1699
|
-
answer(to: string, id: string, value: unknown): Result<unknown, TerminalAnswerError>;
|
|
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>;
|
|
1700
1319
|
open(name: string): Promise<PromptInterface | undefined>;
|
|
1701
1320
|
save(name: string): Promise<boolean>;
|
|
1702
1321
|
remove(names: readonly string[]): boolean;
|
|
@@ -1706,40 +1325,39 @@ export declare class TerminalManager implements TerminalManagerInterface {
|
|
|
1706
1325
|
}
|
|
1707
1326
|
|
|
1708
1327
|
/**
|
|
1709
|
-
* The manager's event map
|
|
1710
|
-
*
|
|
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.
|
|
1711
1330
|
*
|
|
1712
1331
|
* @remarks
|
|
1713
|
-
* - `pending` — an endpoint parked a
|
|
1714
|
-
*
|
|
1715
|
-
* - `
|
|
1716
|
-
* - `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.
|
|
1717
1335
|
*/
|
|
1718
1336
|
export declare type TerminalManagerEventMap = {
|
|
1719
|
-
readonly pending: readonly [
|
|
1720
|
-
readonly answer: readonly [to: string, id: string,
|
|
1337
|
+
readonly pending: readonly [form: PendingForm];
|
|
1338
|
+
readonly answer: readonly [to: string, id: string, values: FormValues];
|
|
1721
1339
|
readonly expire: readonly [to: string, id: string];
|
|
1722
1340
|
};
|
|
1723
1341
|
|
|
1724
1342
|
/**
|
|
1725
|
-
* The multi-endpoint terminal MANAGER
|
|
1726
|
-
*
|
|
1727
|
-
*
|
|
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.
|
|
1728
1346
|
*
|
|
1729
1347
|
* @remarks
|
|
1730
|
-
* - **Accessors
|
|
1731
|
-
*
|
|
1732
|
-
* - **`add`** mints
|
|
1733
|
-
*
|
|
1734
|
-
* - **`ask`** is the attributed convenience: parks
|
|
1735
|
-
*
|
|
1736
|
-
* - **`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.
|
|
1737
1355
|
* - **`answer`** routes to the named endpoint's broker.
|
|
1738
|
-
* - **`open`** restores
|
|
1739
|
-
* - **`save`** persists an endpoint's config snapshot
|
|
1740
|
-
*
|
|
1741
|
-
* - **Batch `remove
|
|
1742
|
-
*
|
|
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;
|
|
1743
1361
|
* `remove()` removes every endpoint without destroying the manager.
|
|
1744
1362
|
* - **`destroy`** tears down every broker, then the manager's own emitter.
|
|
1745
1363
|
*/
|
|
@@ -1748,14 +1366,11 @@ export declare interface TerminalManagerInterface {
|
|
|
1748
1366
|
readonly count: number;
|
|
1749
1367
|
terminal(name: string): PromptInterface | undefined;
|
|
1750
1368
|
terminals(): readonly string[];
|
|
1751
|
-
add(name: string, options?:
|
|
1752
|
-
ask(from: string, to: string, form:
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
pending(): readonly PendingPrompt[];
|
|
1757
|
-
pending(to: string): readonly PendingPrompt[];
|
|
1758
|
-
answer(to: string, id: string, value: unknown): Result<unknown, TerminalAnswerError>;
|
|
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>;
|
|
1759
1374
|
open(name: string): Promise<PromptInterface | undefined>;
|
|
1760
1375
|
save(name: string): Promise<boolean>;
|
|
1761
1376
|
remove(names: readonly string[]): boolean;
|
|
@@ -1765,15 +1380,14 @@ export declare interface TerminalManagerInterface {
|
|
|
1765
1380
|
}
|
|
1766
1381
|
|
|
1767
1382
|
/**
|
|
1768
|
-
* Options for {@link import('./factories.js').createTerminalManager}
|
|
1383
|
+
* Options for {@link import('./factories.js').createTerminalManager} and the
|
|
1769
1384
|
* {@link TerminalManagerInterface}.
|
|
1770
1385
|
*
|
|
1771
1386
|
* @remarks
|
|
1772
|
-
* - `store` — the optional {@link TerminalStoreInterface} backing `open`
|
|
1773
|
-
* - `timeout` / `timer` / `cap` — the manager-wide default for each endpoint's broker
|
|
1774
|
-
* per {@link TerminalManagerInterface.add} call
|
|
1775
|
-
*
|
|
1776
|
-
* - `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.
|
|
1777
1391
|
*/
|
|
1778
1392
|
export declare interface TerminalManagerOptions {
|
|
1779
1393
|
readonly store?: TerminalStoreInterface;
|
|
@@ -1784,28 +1398,29 @@ export declare interface TerminalManagerOptions {
|
|
|
1784
1398
|
readonly error?: EmitterErrorHandler;
|
|
1785
1399
|
}
|
|
1786
1400
|
|
|
1787
|
-
/**
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
}
|
|
1793
|
-
|
|
1794
|
-
/** 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
|
+
*/
|
|
1795
1406
|
export declare interface TerminalSnapshot {
|
|
1796
1407
|
readonly id: string;
|
|
1797
1408
|
readonly timeout?: number;
|
|
1798
1409
|
}
|
|
1799
1410
|
|
|
1800
|
-
/**
|
|
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
|
+
*/
|
|
1801
1416
|
export declare interface TerminalSnapshotRow {
|
|
1802
1417
|
readonly id: string;
|
|
1803
1418
|
readonly snapshot: unknown;
|
|
1804
1419
|
}
|
|
1805
1420
|
|
|
1806
1421
|
/**
|
|
1807
|
-
* The point-access persistence seam
|
|
1808
|
-
*
|
|
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.
|
|
1809
1424
|
*/
|
|
1810
1425
|
export declare interface TerminalStoreInterface {
|
|
1811
1426
|
get(id: string): Promise<TerminalSnapshot | undefined>;
|
|
@@ -1813,20 +1428,14 @@ export declare interface TerminalStoreInterface {
|
|
|
1813
1428
|
delete(id: string): Promise<void>;
|
|
1814
1429
|
}
|
|
1815
1430
|
|
|
1816
|
-
/** The handle {@link PromptInterface.park} returns — the parked prompt's `id` plus the Promise that resolves (or rejects) with its {@link PromptValue}. */
|
|
1817
|
-
export declare interface Ticket {
|
|
1818
|
-
readonly id: string;
|
|
1819
|
-
readonly value: Promise<PromptValue>;
|
|
1820
|
-
}
|
|
1821
|
-
|
|
1822
1431
|
/** Cancel a pending {@link TimerHandler} deadline — idempotent, safe to call after the timer fired. */
|
|
1823
1432
|
export declare type TimerCancel = () => void;
|
|
1824
1433
|
|
|
1825
1434
|
/**
|
|
1826
1435
|
* One injected timer — arms a deadline `callback` to fire after `ms`, returning a
|
|
1827
1436
|
* {@link TimerCancel} that cancels it. The broker's timeout seam: the default wraps the host
|
|
1828
|
-
* `setTimeout`
|
|
1829
|
-
* 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.
|
|
1830
1439
|
*/
|
|
1831
1440
|
declare type TimerHandler_2 = (callback: () => void, ms: number) => TimerCancel;
|
|
1832
1441
|
export { TimerHandler_2 as TimerHandler }
|
|
@@ -1835,61 +1444,11 @@ export { TimerHandler_2 as TimerHandler }
|
|
|
1835
1444
|
export declare function toggleIndex(indices: readonly number[], index: number): readonly number[];
|
|
1836
1445
|
|
|
1837
1446
|
/**
|
|
1838
|
-
*
|
|
1839
|
-
*
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
/**
|
|
1844
|
-
* Declarative validation rules for a text prompt — each key toggles (or overrides) one
|
|
1845
|
-
* built-in check. {@link import('./helpers.js').resolveValidation} compiles a `ValidationRules`
|
|
1846
|
-
* (or a bare {@link Validator}) into ONE composed {@link Validator}.
|
|
1847
|
-
*
|
|
1848
|
-
* @remarks
|
|
1849
|
-
* Each rule is EITHER a primitive that turns on the built-in check, OR a {@link Validator}
|
|
1850
|
-
* that replaces it with custom logic:
|
|
1851
|
-
*
|
|
1852
|
-
* - `required` — `true` ⇒ input must be non-empty after trimming.
|
|
1853
|
-
* - `minimum` — a number ⇒ input must be at least that many characters.
|
|
1854
|
-
* - `maximum` — a number ⇒ input must be at most that many characters.
|
|
1855
|
-
* - `pattern` — a string ⇒ input must match that regex source.
|
|
1856
|
-
* - `email` — `true` ⇒ input must look like an email address.
|
|
1857
|
-
* - `url` — `true` ⇒ input must look like an HTTP(S) URL.
|
|
1858
|
-
* - `numeric` — `true` ⇒ input must be a number (integer or decimal).
|
|
1859
|
-
* - `integer` — `true` ⇒ input must be an integer.
|
|
1860
|
-
* - `alphanumeric` — `true` ⇒ input must contain only letters and digits.
|
|
1861
|
-
* - `custom` — an arbitrary {@link Validator} escape hatch.
|
|
1862
|
-
*
|
|
1863
|
-
* Rules compose in the fixed order above; the FIRST failing rule short-circuits and its
|
|
1864
|
-
* message is returned. A `false` / `undefined` rule is skipped.
|
|
1865
|
-
*/
|
|
1866
|
-
export declare interface ValidationRules {
|
|
1867
|
-
readonly required?: boolean | Validator;
|
|
1868
|
-
readonly minimum?: number | Validator;
|
|
1869
|
-
readonly maximum?: number | Validator;
|
|
1870
|
-
readonly pattern?: string | Validator;
|
|
1871
|
-
readonly email?: boolean | Validator;
|
|
1872
|
-
readonly url?: boolean | Validator;
|
|
1873
|
-
readonly numeric?: boolean | Validator;
|
|
1874
|
-
readonly integer?: boolean | Validator;
|
|
1875
|
-
readonly alphanumeric?: boolean | Validator;
|
|
1876
|
-
readonly custom?: Validator;
|
|
1877
|
-
}
|
|
1878
|
-
|
|
1879
|
-
/**
|
|
1880
|
-
* A single input validator — given the current input string, returns `true` when the input
|
|
1881
|
-
* is valid, or an error MESSAGE string when it is not. The atomic unit the validation engine
|
|
1882
|
-
* composes and the prompts apply on submit.
|
|
1883
|
-
*
|
|
1884
|
-
* @remarks
|
|
1885
|
-
* A `Validator` is total and pure — it never throws and never mutates. The `true | string`
|
|
1886
|
-
* shape (not `boolean`) is deliberate: an invalid result CARRIES its message, so a prompt
|
|
1887
|
-
* can render the exact reason. {@link import('./helpers.js').composeValidators} runs several
|
|
1888
|
-
* 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.
|
|
1889
1451
|
*/
|
|
1890
|
-
export declare type Validator = (input: string) => true | string;
|
|
1891
|
-
|
|
1892
|
-
/** 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. */
|
|
1893
1452
|
export declare interface WireEvent {
|
|
1894
1453
|
readonly event: string;
|
|
1895
1454
|
readonly data: string;
|