@orkestrel/terminal 0.0.7 → 0.0.8
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/dist/src/core/index.cjs +336 -88
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +290 -84
- package/dist/src/core/index.d.ts +290 -84
- package/dist/src/core/index.js +330 -88
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +17 -20
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.js +18 -21
- package/dist/src/server/index.js.map +1 -1
- package/package.json +5 -5
package/dist/src/core/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { ATTRIBUTES, COLORS, STATUS_ICONS, createStyler, freezeStyle, stripControls } from "@orkestrel/console";
|
|
2
|
+
import { FORMAT_PATTERNS, arrayOf, isArray, isBoolean, isNonEmptyString, isNumber, isRecord, isString, literalOf, parseJSON, rawShape, recordOf, stringShape } from "@orkestrel/contract";
|
|
3
3
|
import { Emitter } from "@orkestrel/emitter";
|
|
4
4
|
import { createSSEParser } from "@orkestrel/sse";
|
|
5
5
|
import { createDatabase, createMemoryDriver } from "@orkestrel/database";
|
|
@@ -129,9 +129,10 @@ var CONTROL_NAMES = Object.freeze({
|
|
|
129
129
|
});
|
|
130
130
|
/** The default mask glyph a {@link import('./types.js').PasswordState} renders each input character as — `*`. */
|
|
131
131
|
var DEFAULT_MASK = "*";
|
|
132
|
-
/**
|
|
133
|
-
|
|
134
|
-
|
|
132
|
+
/**
|
|
133
|
+
* Matches an HTTP(S) URL. The `url` rule tests against this. Kept locally because it is
|
|
134
|
+
* narrower than `FORMAT_PATTERNS.uri`, which accepts other URI schemes.
|
|
135
|
+
*/
|
|
135
136
|
var URL_PATTERN = /^https?:\/\/.+/;
|
|
136
137
|
/** Matches a numeric value (integer or decimal, optional sign). The `numeric` rule tests against this. */
|
|
137
138
|
var NUMERIC_PATTERN = /^-?\d+(\.\d+)?$/;
|
|
@@ -158,11 +159,8 @@ var RULE_MESSAGES = Object.freeze({
|
|
|
158
159
|
invalid: "Invalid input"
|
|
159
160
|
});
|
|
160
161
|
/**
|
|
161
|
-
* The
|
|
162
|
-
*
|
|
163
|
-
* {@link import('@orkestrel/console').StylerInterface} at render time, never baked into the
|
|
164
|
-
* constant (AGENTS — styling orthogonal to data; the rework fixes the terminal's ANSI-in-the-icon).
|
|
165
|
-
* Frozen.
|
|
162
|
+
* The six default glyphs {@link DEFAULT_PROMPT_THEME} assembles its `icons` from. Read only when
|
|
163
|
+
* the default theme is assembled; a view reads its resolved theme and never this constant. Frozen.
|
|
166
164
|
*
|
|
167
165
|
* @remarks
|
|
168
166
|
* - `question` — the leading mark on a prompt's message line.
|
|
@@ -178,6 +176,79 @@ var PROMPT_ICONS = Object.freeze({
|
|
|
178
176
|
checked: "☑",
|
|
179
177
|
unchecked: "☐"
|
|
180
178
|
});
|
|
179
|
+
/**
|
|
180
|
+
* Every {@link import('./types.js').PromptRole}, in one frozen list — the role axis's source of
|
|
181
|
+
* truth. {@link import('./helpers.js').createPromptTheme} walks it to merge a partial theme, and
|
|
182
|
+
* a consumer building a complete role map reads it rather than retyping every name.
|
|
183
|
+
*/
|
|
184
|
+
var PROMPT_ROLES = Object.freeze([
|
|
185
|
+
"question",
|
|
186
|
+
"pointer",
|
|
187
|
+
"message",
|
|
188
|
+
"content",
|
|
189
|
+
"success",
|
|
190
|
+
"error",
|
|
191
|
+
"selected",
|
|
192
|
+
"focus",
|
|
193
|
+
"hint",
|
|
194
|
+
"muted",
|
|
195
|
+
"description"
|
|
196
|
+
]);
|
|
197
|
+
/**
|
|
198
|
+
* The {@link import('./types.js').PromptTheme} every prompt renders with unless its options supply
|
|
199
|
+
* another — the glyph set assembled from {@link PROMPT_ICONS} plus the console
|
|
200
|
+
* {@link import('@orkestrel/console').STATUS_ICONS} `success` / `error` marks, and the console
|
|
201
|
+
* {@link import('@orkestrel/console').Style} each role is painted with. Deeply frozen through the
|
|
202
|
+
* console module's own {@link import('@orkestrel/console').freezeStyle}; the baseline
|
|
203
|
+
* {@link import('./helpers.js').createPromptTheme} merges a partial theme over.
|
|
204
|
+
*
|
|
205
|
+
* @remarks
|
|
206
|
+
* The default roles reproduce the views' historical coloring exactly: `question` / `pointer` cyan,
|
|
207
|
+
* `message` / `focus` bold, `success` / `selected` green, `error` red, `hint` / `muted` /
|
|
208
|
+
* `description` dim, and `content` the EMPTY style — an empty style renders bare text, so primary
|
|
209
|
+
* content keeps the bytes it had before it became themeable.
|
|
210
|
+
* Two roles sharing a style today are still two roles — re-mapping one leaves the other alone.
|
|
211
|
+
*/
|
|
212
|
+
var DEFAULT_PROMPT_THEME = Object.freeze({
|
|
213
|
+
icons: Object.freeze({
|
|
214
|
+
question: PROMPT_ICONS.question,
|
|
215
|
+
pointer: PROMPT_ICONS.pointer,
|
|
216
|
+
dot: PROMPT_ICONS.dot,
|
|
217
|
+
selected: PROMPT_ICONS.selected,
|
|
218
|
+
checked: PROMPT_ICONS.checked,
|
|
219
|
+
unchecked: PROMPT_ICONS.unchecked,
|
|
220
|
+
success: STATUS_ICONS.success,
|
|
221
|
+
error: STATUS_ICONS.error
|
|
222
|
+
}),
|
|
223
|
+
roles: Object.freeze({
|
|
224
|
+
question: freezeStyle({
|
|
225
|
+
foreground: "cyan",
|
|
226
|
+
attributes: []
|
|
227
|
+
}),
|
|
228
|
+
pointer: freezeStyle({
|
|
229
|
+
foreground: "cyan",
|
|
230
|
+
attributes: []
|
|
231
|
+
}),
|
|
232
|
+
message: freezeStyle({ attributes: ["bold"] }),
|
|
233
|
+
content: freezeStyle({ attributes: [] }),
|
|
234
|
+
success: freezeStyle({
|
|
235
|
+
foreground: "green",
|
|
236
|
+
attributes: []
|
|
237
|
+
}),
|
|
238
|
+
error: freezeStyle({
|
|
239
|
+
foreground: "red",
|
|
240
|
+
attributes: []
|
|
241
|
+
}),
|
|
242
|
+
selected: freezeStyle({
|
|
243
|
+
foreground: "green",
|
|
244
|
+
attributes: []
|
|
245
|
+
}),
|
|
246
|
+
focus: freezeStyle({ attributes: ["bold"] }),
|
|
247
|
+
hint: freezeStyle({ attributes: ["dim"] }),
|
|
248
|
+
muted: freezeStyle({ attributes: ["dim"] }),
|
|
249
|
+
description: freezeStyle({ attributes: ["dim"] })
|
|
250
|
+
})
|
|
251
|
+
});
|
|
181
252
|
/** How long (ms) the {@link import('./types.js').PromptInterface} broker parks an unanswered prompt before it expires — 5 minutes. */
|
|
182
253
|
var DEFAULT_PROMPT_TIMEOUT_MS = 3e5;
|
|
183
254
|
/** How long (ms) the {@link import('./types.js').PromptClientInterface} waits before each reconnect attempt — 2 seconds. */
|
|
@@ -271,6 +342,63 @@ var isPendingPrompt = recordOf({
|
|
|
271
342
|
from: isString,
|
|
272
343
|
to: isString
|
|
273
344
|
}, ["from", "to"]);
|
|
345
|
+
/**
|
|
346
|
+
* Narrow an unknown value to a console {@link Style} — the value every
|
|
347
|
+
* {@link import('./types.js').PromptRole} carries, built from the console module's own
|
|
348
|
+
* {@link import('@orkestrel/console').COLORS} + {@link import('@orkestrel/console').ATTRIBUTES} so
|
|
349
|
+
* the style vocabulary has ONE source.
|
|
350
|
+
*
|
|
351
|
+
* @remarks
|
|
352
|
+
* The record is CLOSED and matches the `Style` contract exactly: `foreground` and `background` are
|
|
353
|
+
* optional and each must name a color (`default` included, as the console `Color` union has it),
|
|
354
|
+
* `attributes` is REQUIRED and must be an array over the attribute set, and any other key rejects
|
|
355
|
+
* the whole value.
|
|
356
|
+
*/
|
|
357
|
+
var isStyle = recordOf({
|
|
358
|
+
foreground: literalOf(...COLORS, "default"),
|
|
359
|
+
background: literalOf(...COLORS, "default"),
|
|
360
|
+
attributes: arrayOf(literalOf(...ATTRIBUTES))
|
|
361
|
+
}, ["foreground", "background"]);
|
|
362
|
+
/**
|
|
363
|
+
* Narrow an unknown wire value to a {@link PromptThemeOptions} — the §14 guard a remote prompt's
|
|
364
|
+
* `theme` option passes before it reaches a local prompt.
|
|
365
|
+
*
|
|
366
|
+
* @remarks
|
|
367
|
+
* The shape is CLOSED at every level: an unknown icon slot, an unknown role, a non-string glyph, or
|
|
368
|
+
* a role whose value is not a {@link isStyle}-shaped console style rejects the whole theme, so a
|
|
369
|
+
* hostile payload degrades to the default theme rather than partially applying. Glyphs still carry
|
|
370
|
+
* arbitrary text at this point — {@link import('./helpers.js').sanitizeThemeIcons} strips their
|
|
371
|
+
* control bytes on dispatch.
|
|
372
|
+
*
|
|
373
|
+
* The icons and roles shapes are checked against their complete union-keyed guard records. A slot
|
|
374
|
+
* added to either union without an entry here is a compile error rather than a wire theme that is
|
|
375
|
+
* silently refused.
|
|
376
|
+
*/
|
|
377
|
+
var isPromptThemeOptions = recordOf({
|
|
378
|
+
icons: recordOf({
|
|
379
|
+
question: isString,
|
|
380
|
+
pointer: isString,
|
|
381
|
+
dot: isString,
|
|
382
|
+
selected: isString,
|
|
383
|
+
checked: isString,
|
|
384
|
+
unchecked: isString,
|
|
385
|
+
success: isString,
|
|
386
|
+
error: isString
|
|
387
|
+
}, true),
|
|
388
|
+
roles: recordOf({
|
|
389
|
+
question: isStyle,
|
|
390
|
+
pointer: isStyle,
|
|
391
|
+
message: isStyle,
|
|
392
|
+
content: isStyle,
|
|
393
|
+
success: isStyle,
|
|
394
|
+
error: isStyle,
|
|
395
|
+
selected: isStyle,
|
|
396
|
+
focus: isStyle,
|
|
397
|
+
hint: isStyle,
|
|
398
|
+
description: isStyle,
|
|
399
|
+
muted: isStyle
|
|
400
|
+
}, true)
|
|
401
|
+
}, true);
|
|
274
402
|
/** Narrow an unknown value to a {@link TerminalSnapshot}. */
|
|
275
403
|
var isTerminalSnapshot = recordOf({
|
|
276
404
|
id: isNonEmptyString,
|
|
@@ -395,7 +523,7 @@ function evaluateRule(rule, check, input) {
|
|
|
395
523
|
}
|
|
396
524
|
break;
|
|
397
525
|
case "email":
|
|
398
|
-
if (check === true && !
|
|
526
|
+
if (check === true && !FORMAT_PATTERNS.email.test(input)) return RULE_MESSAGES.email;
|
|
399
527
|
break;
|
|
400
528
|
case "url":
|
|
401
529
|
if (check === true && !URL_PATTERN.test(input)) return RULE_MESSAGES.url;
|
|
@@ -500,33 +628,116 @@ function normalizeCheckboxChoice(choice) {
|
|
|
500
628
|
value: choice
|
|
501
629
|
} : choice;
|
|
502
630
|
}
|
|
503
|
-
/**
|
|
504
|
-
|
|
505
|
-
|
|
631
|
+
/**
|
|
632
|
+
* Build a complete {@link PromptTheme} by merging a partial one over
|
|
633
|
+
* {@link DEFAULT_PROMPT_THEME}, leaf by leaf — each supplied icon replaces that glyph, each
|
|
634
|
+
* supplied role replaces that {@link Style}, and everything else keeps its default. Each supplied
|
|
635
|
+
* style is snapshotted through the console module's own
|
|
636
|
+
* {@link import('@orkestrel/console').freezeStyle}, so the result is deeply frozen and a caller
|
|
637
|
+
* mutating its own attribute list afterwards cannot reach into a built theme.
|
|
638
|
+
*
|
|
639
|
+
* @param options - The partial theme to merge, or `undefined` for the defaults
|
|
640
|
+
* @returns The resolved, deeply frozen theme every prompt state carries
|
|
641
|
+
*
|
|
642
|
+
* @example
|
|
643
|
+
* ```ts
|
|
644
|
+
* createPromptTheme() // the defaults
|
|
645
|
+
* createPromptTheme({
|
|
646
|
+
* icons: { pointer: '=>' },
|
|
647
|
+
* roles: { message: { foreground: 'magenta', attributes: ['bold'] } },
|
|
648
|
+
* })
|
|
649
|
+
* ```
|
|
650
|
+
*/
|
|
651
|
+
function createPromptTheme(options) {
|
|
652
|
+
const icons = {
|
|
653
|
+
...DEFAULT_PROMPT_THEME.icons,
|
|
654
|
+
...options?.icons
|
|
655
|
+
};
|
|
656
|
+
const roles = { ...DEFAULT_PROMPT_THEME.roles };
|
|
657
|
+
for (const role of PROMPT_ROLES) {
|
|
658
|
+
const style = options?.roles?.[role];
|
|
659
|
+
if (style !== void 0) roles[role] = freezeStyle(style);
|
|
660
|
+
}
|
|
661
|
+
return Object.freeze({
|
|
662
|
+
icons: Object.freeze(icons),
|
|
663
|
+
roles: Object.freeze(roles)
|
|
664
|
+
});
|
|
506
665
|
}
|
|
507
|
-
/**
|
|
508
|
-
|
|
509
|
-
|
|
666
|
+
/**
|
|
667
|
+
* Sanitize text for one single-line display slot. Composes console's {@link stripControls} pass
|
|
668
|
+
* with removal of tab, line feed, and carriage return, so no C0 control or DEL survives.
|
|
669
|
+
*
|
|
670
|
+
* @param text - The text to sanitize for a glyph or hint slot
|
|
671
|
+
* @returns The text with every C0 control character and DEL removed
|
|
672
|
+
*
|
|
673
|
+
* @example
|
|
674
|
+
* ```ts
|
|
675
|
+
* sanitizeDisplayText('Q\rOVERWRITE\nNEXT\tX') // 'QOVERWRITENEXTX'
|
|
676
|
+
* ```
|
|
677
|
+
*/
|
|
678
|
+
function sanitizeDisplayText(text) {
|
|
679
|
+
return stripControls(text).replaceAll(" ", "").replaceAll("\n", "").replaceAll("\r", "");
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Sanitize every glyph a wire-supplied {@link PromptThemeOptions} carries for a single-line display
|
|
683
|
+
* slot. Only the icons need it: a role is guard-narrowed to a console {@link Style}, whose colors
|
|
684
|
+
* and attributes are fixed name sets, so no role can carry a byte a terminal would act on.
|
|
685
|
+
*
|
|
686
|
+
* @param theme - The narrowed theme options a remote prompt supplied
|
|
687
|
+
* @returns The same theme with every supplied glyph sanitized for a single-line display slot
|
|
688
|
+
*/
|
|
689
|
+
function sanitizeThemeIcons(theme) {
|
|
690
|
+
const icons = theme.icons;
|
|
691
|
+
if (icons === void 0) return theme;
|
|
692
|
+
const sanitized = {};
|
|
693
|
+
for (const [icon, glyph] of Object.entries(icons)) sanitized[icon] = sanitizeDisplayText(glyph);
|
|
694
|
+
return {
|
|
695
|
+
...theme,
|
|
696
|
+
icons: sanitized
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
/** The styled prompt-message header (`? message`) — the leading line every active prompt view shares, themed by the `question` + `message` roles. */
|
|
700
|
+
function promptHeader(styler, theme, message) {
|
|
701
|
+
return `${styler.render(theme.roles.question, theme.icons.question)} ${styler.render(theme.roles.message, message)}`;
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Render a prompt header followed by a key hint painted with the `hint` role, or the header alone
|
|
705
|
+
* when no hint is supplied.
|
|
706
|
+
*
|
|
707
|
+
* @param styler - The console styler that renders each role
|
|
708
|
+
* @param theme - The resolved prompt theme
|
|
709
|
+
* @param message - The prompt's question text
|
|
710
|
+
* @param hint - The optional key hint to append
|
|
711
|
+
* @returns The rendered header with the optional hint
|
|
712
|
+
*/
|
|
713
|
+
function hintedHeader(styler, theme, message, hint) {
|
|
714
|
+
const head = promptHeader(styler, theme, message);
|
|
715
|
+
return hint === void 0 ? head : `${head} ${styler.render(theme.roles.hint, hint)}`;
|
|
716
|
+
}
|
|
717
|
+
/** The styled submit line (`✔ message`) — the committed header an interactive prompt shows once resolved, themed by the `success` + `message` roles. */
|
|
718
|
+
function submitHeader(styler, theme, message) {
|
|
719
|
+
return `${styler.render(theme.roles.success, theme.icons.success)} ${styler.render(theme.roles.message, message)}`;
|
|
510
720
|
}
|
|
511
|
-
/** The styled error line (`✖ message`) — appended beneath a prompt view when the last submit failed validation. */
|
|
512
|
-
function errorLine(styler, message) {
|
|
513
|
-
return `${styler.
|
|
721
|
+
/** The styled error line (`✖ message`) — appended beneath a prompt view when the last submit failed validation, themed by the `error` role. */
|
|
722
|
+
function errorLine(styler, theme, message) {
|
|
723
|
+
return `${styler.render(theme.roles.error, theme.icons.error)} ${styler.render(theme.roles.error, message)}`;
|
|
514
724
|
}
|
|
515
|
-
/** Build the initial {@link InputState} from {@link InputOptions} — resolving the validator + styler, seeding an empty value. */
|
|
725
|
+
/** Build the initial {@link InputState} from {@link InputOptions} — resolving the validator + styler + theme, seeding an empty value. */
|
|
516
726
|
function createInputState(options) {
|
|
517
727
|
return {
|
|
518
728
|
message: options.message,
|
|
519
729
|
default: options.default ?? "",
|
|
520
730
|
validator: resolveValidation(options.validate),
|
|
521
731
|
styler: options.styler ?? createStyler(),
|
|
732
|
+
theme: createPromptTheme(options.theme),
|
|
522
733
|
value: ""
|
|
523
734
|
};
|
|
524
735
|
}
|
|
525
|
-
/** Render an {@link InputState} as a styled view — the header, the typed value (or
|
|
736
|
+
/** 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. */
|
|
526
737
|
function inputView(state) {
|
|
527
|
-
const shown = state.value.length > 0 ? state.value : state.styler.
|
|
528
|
-
const head = `${promptHeader(state.styler, state.message)} ${state.styler.
|
|
529
|
-
return state.error === void 0 ? head : `${head}\n${errorLine(state.styler, state.error)}`;
|
|
738
|
+
const shown = state.value.length > 0 ? state.styler.render(state.theme.roles.content, state.value) : state.styler.render(state.theme.roles.hint, state.default);
|
|
739
|
+
const head = `${promptHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.pointer, state.theme.icons.pointer)} ${shown}`;
|
|
740
|
+
return state.error === void 0 ? head : `${head}\n${errorLine(state.styler, state.theme, state.error)}`;
|
|
530
741
|
}
|
|
531
742
|
/**
|
|
532
743
|
* Advance an input prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`
|
|
@@ -560,7 +771,7 @@ function inputReduce(state, key) {
|
|
|
560
771
|
...clear,
|
|
561
772
|
value: answer
|
|
562
773
|
},
|
|
563
|
-
view: `${submitHeader(state.styler, state.message)} ${state.styler.
|
|
774
|
+
view: `${submitHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.hint, answer)}`,
|
|
564
775
|
status: "submit",
|
|
565
776
|
value: answer
|
|
566
777
|
};
|
|
@@ -581,21 +792,22 @@ function inputReduce(state, key) {
|
|
|
581
792
|
status: "active"
|
|
582
793
|
};
|
|
583
794
|
}
|
|
584
|
-
/** Build the initial {@link PasswordState} from {@link PasswordOptions} — resolving the validator + styler + mask. */
|
|
795
|
+
/** Build the initial {@link PasswordState} from {@link PasswordOptions} — resolving the validator + styler + theme + mask. */
|
|
585
796
|
function createPasswordState(options) {
|
|
586
797
|
return {
|
|
587
798
|
message: options.message,
|
|
588
799
|
mask: options.mask ?? "*",
|
|
589
800
|
validator: resolveValidation(options.validate),
|
|
590
801
|
styler: options.styler ?? createStyler(),
|
|
802
|
+
theme: createPromptTheme(options.theme),
|
|
591
803
|
value: ""
|
|
592
804
|
};
|
|
593
805
|
}
|
|
594
|
-
/** Render a {@link PasswordState} as a styled view — the header, the value masked to `mask` repeated, and any error. */
|
|
806
|
+
/** 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. */
|
|
595
807
|
function passwordView(state) {
|
|
596
|
-
const masked = state.mask.repeat(state.value.length);
|
|
597
|
-
const head = `${promptHeader(state.styler, state.message)} ${state.styler.
|
|
598
|
-
return state.error === void 0 ? head : `${head}\n${errorLine(state.styler, state.error)}`;
|
|
808
|
+
const masked = state.styler.render(state.theme.roles.content, state.mask.repeat(state.value.length));
|
|
809
|
+
const head = `${promptHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.pointer, state.theme.icons.pointer)} ${masked}`;
|
|
810
|
+
return state.error === void 0 ? head : `${head}\n${errorLine(state.styler, state.theme, state.error)}`;
|
|
599
811
|
}
|
|
600
812
|
/**
|
|
601
813
|
* Advance a password prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`
|
|
@@ -625,7 +837,7 @@ function passwordReduce(state, key) {
|
|
|
625
837
|
}
|
|
626
838
|
return {
|
|
627
839
|
state: clear,
|
|
628
|
-
view: `${submitHeader(state.styler, state.message)} ${state.styler.
|
|
840
|
+
view: `${submitHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.hint, state.mask.repeat(state.value.length))}`,
|
|
629
841
|
status: "submit",
|
|
630
842
|
value: state.value
|
|
631
843
|
};
|
|
@@ -646,18 +858,26 @@ function passwordReduce(state, key) {
|
|
|
646
858
|
status: "active"
|
|
647
859
|
};
|
|
648
860
|
}
|
|
649
|
-
/** Build the initial {@link ConfirmState} from {@link ConfirmOptions} — defaulting the answer to `false
|
|
861
|
+
/** Build the initial {@link ConfirmState} from {@link ConfirmOptions} — defaulting the answer to `false`, resolving the styler + theme, carrying any hint override. */
|
|
650
862
|
function createConfirmState(options) {
|
|
651
863
|
return {
|
|
652
864
|
message: options.message,
|
|
653
865
|
default: options.default ?? false,
|
|
654
|
-
|
|
866
|
+
...options.hint !== void 0 ? { hint: options.hint } : {},
|
|
867
|
+
styler: options.styler ?? createStyler(),
|
|
868
|
+
theme: createPromptTheme(options.theme)
|
|
655
869
|
};
|
|
656
870
|
}
|
|
657
|
-
/**
|
|
871
|
+
/**
|
|
872
|
+
* Render a {@link ConfirmState} as a styled view — the header plus the `(Y/n)` group with the
|
|
873
|
+
* default letter painted by the `selected` role. A supplied `hint` replaces that whole group,
|
|
874
|
+
* parentheses included, painted by the `hint` role.
|
|
875
|
+
*/
|
|
658
876
|
function confirmView(state) {
|
|
659
|
-
|
|
660
|
-
|
|
877
|
+
if (state.hint !== void 0) return hintedHeader(state.styler, state.theme, state.message, state.hint);
|
|
878
|
+
const head = promptHeader(state.styler, state.theme, state.message);
|
|
879
|
+
const answer = state.default ? `${state.styler.render(state.theme.roles.selected, "Y")}${state.styler.render(state.theme.roles.hint, "/n")}` : `${state.styler.render(state.theme.roles.hint, "y/")}${state.styler.render(state.theme.roles.selected, "N")}`;
|
|
880
|
+
return `${head} ${state.styler.render(state.theme.roles.hint, "(")}${answer}${state.styler.render(state.theme.roles.hint, ")")}`;
|
|
661
881
|
}
|
|
662
882
|
/**
|
|
663
883
|
* Advance a confirm prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<boolean>`
|
|
@@ -682,29 +902,31 @@ function confirmReduce(state, key) {
|
|
|
682
902
|
};
|
|
683
903
|
return {
|
|
684
904
|
state,
|
|
685
|
-
view: `${submitHeader(state.styler, state.message)} ${state.styler.
|
|
905
|
+
view: `${submitHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.hint, answer ? "yes" : "no")}`,
|
|
686
906
|
status: "submit",
|
|
687
907
|
value: answer
|
|
688
908
|
};
|
|
689
909
|
}
|
|
690
|
-
/** Build the initial {@link SelectState} from {@link SelectOptions} — normalizing choices and pre-focusing the default. */
|
|
910
|
+
/** Build the initial {@link SelectState} from {@link SelectOptions} — normalizing choices, resolving the styler + theme, carrying any hint, and pre-focusing the default. */
|
|
691
911
|
function createSelectState(options) {
|
|
692
912
|
const choices = options.choices.map(normalizeChoice);
|
|
693
913
|
const index = choices.findIndex((choice) => choice.value === options.default);
|
|
694
914
|
return {
|
|
695
915
|
message: options.message,
|
|
696
916
|
choices,
|
|
917
|
+
...options.hint !== void 0 ? { hint: options.hint } : {},
|
|
697
918
|
styler: options.styler ?? createStyler(),
|
|
919
|
+
theme: createPromptTheme(options.theme),
|
|
698
920
|
focused: index >= 0 ? index : 0
|
|
699
921
|
};
|
|
700
922
|
}
|
|
701
|
-
/** Render a {@link SelectState} as a MULTI-LINE styled view — the header followed by one row per choice, the focused row marked. */
|
|
923
|
+
/** Render a {@link SelectState} as a MULTI-LINE styled view — the header (plus any hint) followed by one row per choice, the focused row marked. */
|
|
702
924
|
function selectView(state) {
|
|
703
925
|
const lines = state.choices.map((choice, index) => {
|
|
704
926
|
const active = index === state.focused;
|
|
705
|
-
return `${active ? state.styler.
|
|
927
|
+
return `${active ? state.styler.render(state.theme.roles.pointer, state.theme.icons.pointer) : " "} ${active ? state.styler.render(state.theme.roles.selected, state.theme.icons.selected) : state.styler.render(state.theme.roles.muted, state.theme.icons.dot)} ${active ? state.styler.render(state.theme.roles.focus, choice.name) : state.styler.render(state.theme.roles.content, choice.name)}${choice.description === void 0 ? "" : ` ${state.styler.render(state.theme.roles.description, choice.description)}`}`;
|
|
706
928
|
});
|
|
707
|
-
return [
|
|
929
|
+
return [hintedHeader(state.styler, state.theme, state.message, state.hint), ...lines].join("\n");
|
|
708
930
|
}
|
|
709
931
|
/**
|
|
710
932
|
* Advance a select prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`
|
|
@@ -751,7 +973,7 @@ function selectReduce(state, key) {
|
|
|
751
973
|
const value = choice?.value ?? "";
|
|
752
974
|
return {
|
|
753
975
|
state,
|
|
754
|
-
view: `${submitHeader(state.styler, state.message)} ${state.styler.
|
|
976
|
+
view: `${submitHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.hint, choice?.name ?? "")}`,
|
|
755
977
|
status: "submit",
|
|
756
978
|
value
|
|
757
979
|
};
|
|
@@ -762,7 +984,7 @@ function selectReduce(state, key) {
|
|
|
762
984
|
status: "active"
|
|
763
985
|
};
|
|
764
986
|
}
|
|
765
|
-
/** Build the initial {@link CheckboxState} from {@link CheckboxOptions} — normalizing choices, seeding the checked set, carrying min/max. */
|
|
987
|
+
/** Build the initial {@link CheckboxState} from {@link CheckboxOptions} — normalizing choices, resolving the styler + theme, carrying any hint, seeding the checked set, carrying min/max. */
|
|
766
988
|
function createCheckboxState(options) {
|
|
767
989
|
const choices = options.choices.map(normalizeCheckboxChoice);
|
|
768
990
|
const checked = choices.reduce((indices, choice, index) => {
|
|
@@ -772,27 +994,29 @@ function createCheckboxState(options) {
|
|
|
772
994
|
return {
|
|
773
995
|
message: options.message,
|
|
774
996
|
choices,
|
|
997
|
+
...options.hint !== void 0 ? { hint: options.hint } : {},
|
|
775
998
|
styler: options.styler ?? createStyler(),
|
|
999
|
+
theme: createPromptTheme(options.theme),
|
|
776
1000
|
focused: 0,
|
|
777
1001
|
checked,
|
|
778
1002
|
...options.min !== void 0 ? { min: options.min } : {},
|
|
779
1003
|
...options.max !== void 0 ? { max: options.max } : {}
|
|
780
1004
|
};
|
|
781
1005
|
}
|
|
782
|
-
/** Render a {@link CheckboxState} as a MULTI-LINE styled view — the header, one box per choice (focused + checked marked), a count, and any error. */
|
|
1006
|
+
/** 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. */
|
|
783
1007
|
function checkboxView(state) {
|
|
784
1008
|
const lines = state.choices.map((choice, index) => {
|
|
785
1009
|
const active = index === state.focused;
|
|
786
1010
|
const ticked = state.checked.includes(index);
|
|
787
|
-
return `${active ? state.styler.
|
|
1011
|
+
return `${active ? state.styler.render(state.theme.roles.pointer, state.theme.icons.pointer) : " "} ${ticked ? state.styler.render(state.theme.roles.selected, state.theme.icons.checked) : state.styler.render(state.theme.roles.muted, state.theme.icons.unchecked)} ${active ? state.styler.render(state.theme.roles.focus, choice.name) : state.styler.render(state.theme.roles.content, choice.name)}${choice.description === void 0 ? "" : ` ${state.styler.render(state.theme.roles.description, choice.description)}`}`;
|
|
788
1012
|
});
|
|
789
|
-
const summary = state.styler.
|
|
1013
|
+
const summary = state.styler.render(state.theme.roles.hint, `${state.checked.length} selected`);
|
|
790
1014
|
const body = [
|
|
791
|
-
|
|
1015
|
+
hintedHeader(state.styler, state.theme, state.message, state.hint),
|
|
792
1016
|
...lines,
|
|
793
1017
|
summary
|
|
794
1018
|
].join("\n");
|
|
795
|
-
return state.error === void 0 ? body : `${body}\n${errorLine(state.styler, state.error)}`;
|
|
1019
|
+
return state.error === void 0 ? body : `${body}\n${errorLine(state.styler, state.theme, state.error)}`;
|
|
796
1020
|
}
|
|
797
1021
|
/**
|
|
798
1022
|
* Advance a checkbox prompt by one {@link KeyEvent} — the pure
|
|
@@ -861,7 +1085,7 @@ function checkboxReduce(state, key) {
|
|
|
861
1085
|
const summary = ordered.map((index) => state.choices[index]?.name).filter((name) => name !== void 0).join(", ");
|
|
862
1086
|
return {
|
|
863
1087
|
state: clear,
|
|
864
|
-
view: `${submitHeader(state.styler, state.message)} ${state.styler.
|
|
1088
|
+
view: `${submitHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.hint, summary)}`,
|
|
865
1089
|
status: "submit",
|
|
866
1090
|
value: values
|
|
867
1091
|
};
|
|
@@ -881,21 +1105,29 @@ function gateSelection(count, min, max) {
|
|
|
881
1105
|
if (min !== void 0 && count < min) return `Select at least ${String(min)} option${min === 1 ? "" : "s"}`;
|
|
882
1106
|
if (max !== void 0 && count > max) return `Select no more than ${String(max)} option${max === 1 ? "" : "s"}`;
|
|
883
1107
|
}
|
|
884
|
-
/** Build the initial {@link EditorState} from {@link EditorOptions} — resolving the validator + styler, seeding empty lines. */
|
|
1108
|
+
/** Build the initial {@link EditorState} from {@link EditorOptions} — resolving the validator + styler + theme, carrying any hint override, seeding empty lines. */
|
|
885
1109
|
function createEditorState(options) {
|
|
886
1110
|
return {
|
|
887
1111
|
message: options.message,
|
|
888
1112
|
default: options.default ?? "",
|
|
1113
|
+
...options.hint !== void 0 ? { hint: options.hint } : {},
|
|
889
1114
|
validator: resolveValidation(options.validate),
|
|
890
1115
|
styler: options.styler ?? createStyler(),
|
|
1116
|
+
theme: createPromptTheme(options.theme),
|
|
891
1117
|
lines: [],
|
|
892
1118
|
current: ""
|
|
893
1119
|
};
|
|
894
1120
|
}
|
|
895
|
-
/**
|
|
1121
|
+
/**
|
|
1122
|
+
* Render an {@link EditorState} as a MULTI-LINE styled view — the header with its finish hint, the
|
|
1123
|
+
* committed and in-progress lines painted by the `content` role, and any error. A supplied `hint`
|
|
1124
|
+
* replaces `(Ctrl+D to finish)` in full; the finish key stays ctrl-d.
|
|
1125
|
+
*/
|
|
896
1126
|
function editorView(state) {
|
|
897
|
-
const
|
|
898
|
-
|
|
1127
|
+
const head = hintedHeader(state.styler, state.theme, state.message, state.hint ?? "(Ctrl+D to finish)");
|
|
1128
|
+
const pointer = state.styler.render(state.theme.roles.pointer, state.theme.icons.pointer);
|
|
1129
|
+
const view = [head, ...[...state.lines.map((line) => state.styler.render(state.theme.roles.content, line)), `${pointer} ${state.styler.render(state.theme.roles.content, state.current)}`]].join("\n");
|
|
1130
|
+
return state.error === void 0 ? view : `${view}\n${errorLine(state.styler, state.theme, state.error)}`;
|
|
899
1131
|
}
|
|
900
1132
|
/**
|
|
901
1133
|
* Advance an editor prompt by one {@link KeyEvent} — the pure `(state, key) → PromptStep<string>`
|
|
@@ -929,7 +1161,7 @@ function editorReduce(state, key) {
|
|
|
929
1161
|
}
|
|
930
1162
|
return {
|
|
931
1163
|
state: clear,
|
|
932
|
-
view: `${submitHeader(state.styler, state.message)} ${state.styler.
|
|
1164
|
+
view: `${submitHeader(state.styler, state.theme, state.message)} ${state.styler.render(state.theme.roles.hint, `${String(lines.length)} line${lines.length === 1 ? "" : "s"}`)}`,
|
|
933
1165
|
status: "submit",
|
|
934
1166
|
value: answer
|
|
935
1167
|
};
|
|
@@ -979,7 +1211,8 @@ function editLine(value, key) {
|
|
|
979
1211
|
* serializes over SSE. Drops everything that cannot cross the wire (a `styler`, and any
|
|
980
1212
|
* function-valued `validate` rule), while KEEPING the declarative data a remote client needs to
|
|
981
1213
|
* reconstruct the prompt: the {@link ValidationRules} as data, plus `message` / `choices` /
|
|
982
|
-
* `default` / `mask` / `min` / `max`. This is WHY T-a's validation is
|
|
1214
|
+
* `default` / `mask` / `min` / `max` / `hint` / `theme`. This is WHY T-a's validation is
|
|
1215
|
+
* rules-as-data, and why a theme is data too: a `Validator`
|
|
983
1216
|
* FUNCTION can't be serialized, but its declarative rules can — the client rebuilds the validator
|
|
984
1217
|
* from them via {@link resolveValidation}.
|
|
985
1218
|
*
|
|
@@ -1113,6 +1346,13 @@ function sanitizeChoiceLabels(choices) {
|
|
|
1113
1346
|
* §14-narrowed, never an `as`; the validator rebuilt from rules via {@link reconstructValidationRules}),
|
|
1114
1347
|
* then calls the matching prompt form and returns its resolved value.
|
|
1115
1348
|
*
|
|
1349
|
+
* @remarks
|
|
1350
|
+
* `theme` and `hint` are plain data, so they cross the wire with the rest of the options bag and
|
|
1351
|
+
* are reconstructed here for every form that accepts them: the theme is narrowed by
|
|
1352
|
+
* {@link import('./validators.js').isPromptThemeOptions} (an off-shape theme is dropped, leaving
|
|
1353
|
+
* the defaults), then every glyph and hint is passed through {@link sanitizeDisplayText}. Choice
|
|
1354
|
+
* labels use the stream-safe {@link sanitizeChoiceLabels} treatment instead.
|
|
1355
|
+
*
|
|
1116
1356
|
* @param terminal - The local {@link PromptFormInterface} to drive
|
|
1117
1357
|
* @param pending - The decoded pending prompt to dispatch
|
|
1118
1358
|
* @returns The prompt's resolved value (a `string` / `boolean` / `readonly string[]` per form)
|
|
@@ -1121,13 +1361,18 @@ function dispatchPendingPrompt(terminal, pending) {
|
|
|
1121
1361
|
const options = pending.options;
|
|
1122
1362
|
const validate = reconstructValidationRules(options.validate);
|
|
1123
1363
|
const message = stripControls(pending.message);
|
|
1364
|
+
const supplied = resolveOption(options, "theme", isPromptThemeOptions);
|
|
1365
|
+
const theme = supplied === void 0 ? void 0 : sanitizeThemeIcons(supplied);
|
|
1366
|
+
const raw = resolveOption(options, "hint", isString);
|
|
1367
|
+
const hint = raw === void 0 ? void 0 : sanitizeDisplayText(raw);
|
|
1124
1368
|
switch (pending.form) {
|
|
1125
1369
|
case "input": {
|
|
1126
1370
|
const value = resolveOption(options, "default", isString);
|
|
1127
1371
|
return terminal.input({
|
|
1128
1372
|
message,
|
|
1129
1373
|
...value !== void 0 ? { default: stripControls(value) } : {},
|
|
1130
|
-
...validate !== void 0 ? { validate } : {}
|
|
1374
|
+
...validate !== void 0 ? { validate } : {},
|
|
1375
|
+
...theme !== void 0 ? { theme } : {}
|
|
1131
1376
|
});
|
|
1132
1377
|
}
|
|
1133
1378
|
case "password": {
|
|
@@ -1135,14 +1380,17 @@ function dispatchPendingPrompt(terminal, pending) {
|
|
|
1135
1380
|
return terminal.password({
|
|
1136
1381
|
message,
|
|
1137
1382
|
...value !== void 0 ? { mask: stripControls(value) } : {},
|
|
1138
|
-
...validate !== void 0 ? { validate } : {}
|
|
1383
|
+
...validate !== void 0 ? { validate } : {},
|
|
1384
|
+
...theme !== void 0 ? { theme } : {}
|
|
1139
1385
|
});
|
|
1140
1386
|
}
|
|
1141
1387
|
case "confirm": {
|
|
1142
1388
|
const value = resolveOption(options, "default", isBoolean);
|
|
1143
1389
|
return terminal.confirm({
|
|
1144
1390
|
message,
|
|
1145
|
-
...value !== void 0 ? { default: value } : {}
|
|
1391
|
+
...value !== void 0 ? { default: value } : {},
|
|
1392
|
+
...hint !== void 0 ? { hint } : {},
|
|
1393
|
+
...theme !== void 0 ? { theme } : {}
|
|
1146
1394
|
});
|
|
1147
1395
|
}
|
|
1148
1396
|
case "select": {
|
|
@@ -1150,7 +1398,9 @@ function dispatchPendingPrompt(terminal, pending) {
|
|
|
1150
1398
|
return terminal.select({
|
|
1151
1399
|
message,
|
|
1152
1400
|
choices: sanitizeChoiceLabels(resolveChoices(options, isPromptChoice)),
|
|
1153
|
-
...value !== void 0 ? { default: stripControls(value) } : {}
|
|
1401
|
+
...value !== void 0 ? { default: stripControls(value) } : {},
|
|
1402
|
+
...hint !== void 0 ? { hint } : {},
|
|
1403
|
+
...theme !== void 0 ? { theme } : {}
|
|
1154
1404
|
});
|
|
1155
1405
|
}
|
|
1156
1406
|
case "checkbox": {
|
|
@@ -1160,7 +1410,9 @@ function dispatchPendingPrompt(terminal, pending) {
|
|
|
1160
1410
|
message,
|
|
1161
1411
|
choices: sanitizeChoiceLabels(resolveChoices(options, isCheckboxChoice)),
|
|
1162
1412
|
...min !== void 0 ? { min } : {},
|
|
1163
|
-
...max !== void 0 ? { max } : {}
|
|
1413
|
+
...max !== void 0 ? { max } : {},
|
|
1414
|
+
...hint !== void 0 ? { hint } : {},
|
|
1415
|
+
...theme !== void 0 ? { theme } : {}
|
|
1164
1416
|
});
|
|
1165
1417
|
}
|
|
1166
1418
|
case "editor": {
|
|
@@ -1168,7 +1420,9 @@ function dispatchPendingPrompt(terminal, pending) {
|
|
|
1168
1420
|
return terminal.editor({
|
|
1169
1421
|
message,
|
|
1170
1422
|
...value !== void 0 ? { default: stripControls(value) } : {},
|
|
1171
|
-
...validate !== void 0 ? { validate } : {}
|
|
1423
|
+
...validate !== void 0 ? { validate } : {},
|
|
1424
|
+
...hint !== void 0 ? { hint } : {},
|
|
1425
|
+
...theme !== void 0 ? { theme } : {}
|
|
1172
1426
|
});
|
|
1173
1427
|
}
|
|
1174
1428
|
}
|
|
@@ -1197,19 +1451,6 @@ function isAbortError(error) {
|
|
|
1197
1451
|
return (error instanceof DOMException || error instanceof Error) && error.name === "AbortError";
|
|
1198
1452
|
}
|
|
1199
1453
|
/**
|
|
1200
|
-
* Parse a JSON wire string TOTAL — a malformed / empty payload yields `undefined` (the caller's
|
|
1201
|
-
* guard then rejects it), never a throw. The {@link import('./PromptClient.js').PromptClient}
|
|
1202
|
-
* decodes every SSE `data` field through this before §14-narrowing it.
|
|
1203
|
-
*/
|
|
1204
|
-
function parseWireJSON(text) {
|
|
1205
|
-
if (text.length === 0) return void 0;
|
|
1206
|
-
try {
|
|
1207
|
-
return JSON.parse(text);
|
|
1208
|
-
} catch {
|
|
1209
|
-
return;
|
|
1210
|
-
}
|
|
1211
|
-
}
|
|
1212
|
-
/**
|
|
1213
1454
|
* Whether `url` is an INSECURE remote endpoint — a plain `http://` URL whose host is NOT a
|
|
1214
1455
|
* loopback address. Pure string parsing (no `URL` global), so it stays total on malformed input.
|
|
1215
1456
|
*
|
|
@@ -1280,9 +1521,9 @@ function isAnswerPayload(value) {
|
|
|
1280
1521
|
* ({@link serializePromptOptions}) so a transport can forward them as-is.
|
|
1281
1522
|
* - **Answer validates + type-checks.** {@link answer} runs the prompt's per-form gate: it
|
|
1282
1523
|
* type-checks `value` to the form (string / boolean / string[]) AND, for the text forms, runs
|
|
1283
|
-
* the validator resolved from the original `validate` rules. A rejected answer returns
|
|
1284
|
-
* and the prompt stays `pending`; an accepted answer resolves the
|
|
1285
|
-
* removes the prompt.
|
|
1524
|
+
* the validator resolved from the original `validate` rules. A rejected answer returns a failure
|
|
1525
|
+
* `Result` with error `'rejected'` and the prompt stays `pending`; an accepted answer resolves the
|
|
1526
|
+
* Promise, emits `answer`, and removes the prompt.
|
|
1286
1527
|
* - **Timeout → expire → reject.** An unanswered prompt expires after `timeout` ms (via the
|
|
1287
1528
|
* INJECTED timer): `expire` fires and the parked Promise rejects with a {@link TerminalError}
|
|
1288
1529
|
* (`code: 'EXPIRE'`). {@link destroy} expires every still-pending prompt the same way.
|
|
@@ -1631,12 +1872,12 @@ var PromptClient = class {
|
|
|
1631
1872
|
}
|
|
1632
1873
|
async #handle(event) {
|
|
1633
1874
|
if (event.event === SSE_EVENTS.pending) {
|
|
1634
|
-
const parsed =
|
|
1875
|
+
const parsed = parseJSON(event.data);
|
|
1635
1876
|
if (isPendingPrompt(parsed) && !this.#seen.has(parsed.id)) await this.#dispatch(parsed.id, parsed);
|
|
1636
1877
|
return;
|
|
1637
1878
|
}
|
|
1638
1879
|
if (event.event === SSE_EVENTS.expire) {
|
|
1639
|
-
const parsed =
|
|
1880
|
+
const parsed = parseJSON(event.data);
|
|
1640
1881
|
if (isRecord(parsed) && isString(parsed.id)) {
|
|
1641
1882
|
this.#seen.delete(parsed.id);
|
|
1642
1883
|
this.#emitter.emit("expire", parsed.id);
|
|
@@ -1714,9 +1955,9 @@ var PromptClient = class {
|
|
|
1714
1955
|
* - **Durable open / save.** `open(name)` restores an EMPTY broker from the `store` (parked
|
|
1715
1956
|
* Promises are process-bound and never resurrected); `save(name)` persists the endpoint's
|
|
1716
1957
|
* configured `timeout`.
|
|
1717
|
-
* - **Removal.** `remove` drops one endpoint
|
|
1718
|
-
*
|
|
1719
|
-
* idempotent.
|
|
1958
|
+
* - **Removal.** `remove` drops one endpoint, a batch (§9.2, array overload FIRST), or every
|
|
1959
|
+
* endpoint when called without an argument. It destroys each broker, which expires every prompt
|
|
1960
|
+
* still parked on it. `destroy` is idempotent.
|
|
1720
1961
|
*
|
|
1721
1962
|
* @example
|
|
1722
1963
|
* ```ts
|
|
@@ -1855,6 +2096,10 @@ var TerminalManager = class {
|
|
|
1855
2096
|
return true;
|
|
1856
2097
|
}
|
|
1857
2098
|
remove(names) {
|
|
2099
|
+
if (names === void 0) {
|
|
2100
|
+
for (const name of [...this.#terminals.keys()]) this.#removeOne(name);
|
|
2101
|
+
return;
|
|
2102
|
+
}
|
|
1858
2103
|
if (isArray(names)) {
|
|
1859
2104
|
let removed = false;
|
|
1860
2105
|
for (const name of names) if (this.#removeOne(name)) removed = true;
|
|
@@ -1862,13 +2107,10 @@ var TerminalManager = class {
|
|
|
1862
2107
|
}
|
|
1863
2108
|
return this.#removeOne(names);
|
|
1864
2109
|
}
|
|
1865
|
-
clear() {
|
|
1866
|
-
for (const name of [...this.#terminals.keys()]) this.#removeOne(name);
|
|
1867
|
-
}
|
|
1868
2110
|
destroy() {
|
|
1869
2111
|
if (this.#destroyed) return;
|
|
1870
2112
|
this.#destroyed = true;
|
|
1871
|
-
this.
|
|
2113
|
+
this.remove();
|
|
1872
2114
|
this.#emitter.destroy();
|
|
1873
2115
|
}
|
|
1874
2116
|
#createPendingListener() {
|
|
@@ -2163,6 +2405,6 @@ function createDatabaseTerminalStore(driver = createMemoryDriver()) {
|
|
|
2163
2405
|
}).table("terminals"));
|
|
2164
2406
|
}
|
|
2165
2407
|
//#endregion
|
|
2166
|
-
export { ACCEPT_EVENT_STREAM, ALPHANUMERIC_PATTERN, BACKSPACE, CONTROL_NAMES, CTRL_A, CTRL_C, CTRL_D, CTRL_E, CTRL_U, DEFAULT_MASK, DEFAULT_PROMPT_TIMEOUT_MS, DEFAULT_RECONNECT_DELAY_MS, DELETE, DatabaseTerminalStore,
|
|
2408
|
+
export { ACCEPT_EVENT_STREAM, ALPHANUMERIC_PATTERN, BACKSPACE, CONTROL_NAMES, CTRL_A, CTRL_C, CTRL_D, CTRL_E, CTRL_U, DEFAULT_MASK, DEFAULT_PROMPT_THEME, DEFAULT_PROMPT_TIMEOUT_MS, DEFAULT_RECONNECT_DELAY_MS, DELETE, DatabaseTerminalStore, ESCAPE, HEADER_TOKEN, INTEGER_PATTERN, KEY_CSI, KEY_SS3, MemoryTerminalStore, NEWLINE, NUMERIC_PATTERN, PROMPT_ICONS, PROMPT_ROLES, Prompt, PromptClient, RETURN, RULE_MESSAGES, SEQUENCE_NAMES, SPACE, SSE_BUFFER_LIMIT, SSE_EVENTS, TAB, TerminalError, TerminalManager, URL_PATTERN, appendRule, buildRuleValidator, checkboxReduce, checkboxView, composeValidators, confirmReduce, confirmView, createCheckboxState, createConfirmState, createDatabaseTerminalStore, createEditorState, createInputState, createMemoryTerminalStore, createPasswordState, createPrompt, createPromptClient, createPromptTheme, createSelectState, createTerminalManager, defaultTimer, dispatchPendingPrompt, editLine, editorReduce, editorView, errorLine, evaluateRule, gateSelection, globalFetch, hintedHeader, inputReduce, inputView, isAbortError, isAnswerPayload, isCheckboxChoice, isInsecureRemote, isPendingPrompt, isPendingPromptStatus, isPrintable, isPromptChoice, isPromptThemeOptions, isPromptType, isStyle, isTerminalError, isTerminalSnapshot, normalizeCheckboxChoice, normalizeChoice, parseKey, passing, passwordReduce, passwordView, promptHeader, reconstructValidationRules, resolveChoices, resolveOption, resolveValidation, sanitizeChoiceLabels, sanitizeDisplayText, sanitizeThemeIcons, selectReduce, selectView, serializeChoices, serializeExpire, serializePending, serializePromptOptions, serializeShutdown, serializeValidationRules, submitHeader, toggleIndex };
|
|
2167
2409
|
|
|
2168
2410
|
//# sourceMappingURL=index.js.map
|