@johannes.latzel/terminal 0.1.0

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.
Files changed (67) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +35 -0
  3. package/dist/command-arguments.d.ts +120 -0
  4. package/dist/command-arguments.d.ts.map +1 -0
  5. package/dist/command-arguments.js +155 -0
  6. package/dist/command-arguments.js.map +1 -0
  7. package/dist/command-factory.d.ts +17 -0
  8. package/dist/command-factory.d.ts.map +1 -0
  9. package/dist/command-factory.js +43 -0
  10. package/dist/command-factory.js.map +1 -0
  11. package/dist/command-tree.d.ts +40 -0
  12. package/dist/command-tree.d.ts.map +1 -0
  13. package/dist/command-tree.js +77 -0
  14. package/dist/command-tree.js.map +1 -0
  15. package/dist/commands/clear.d.ts +10 -0
  16. package/dist/commands/clear.d.ts.map +1 -0
  17. package/dist/commands/clear.js +13 -0
  18. package/dist/commands/clear.js.map +1 -0
  19. package/dist/commands/exit.d.ts +10 -0
  20. package/dist/commands/exit.d.ts.map +1 -0
  21. package/dist/commands/exit.js +13 -0
  22. package/dist/commands/exit.js.map +1 -0
  23. package/dist/commands/help.d.ts +40 -0
  24. package/dist/commands/help.d.ts.map +1 -0
  25. package/dist/commands/help.js +136 -0
  26. package/dist/commands/help.js.map +1 -0
  27. package/dist/completion/completer.d.ts +22 -0
  28. package/dist/completion/completer.d.ts.map +1 -0
  29. package/dist/completion/completer.js +55 -0
  30. package/dist/completion/completer.js.map +1 -0
  31. package/dist/errors.d.ts +18 -0
  32. package/dist/errors.d.ts.map +1 -0
  33. package/dist/errors.js +28 -0
  34. package/dist/errors.js.map +1 -0
  35. package/dist/hook.d.ts +11 -0
  36. package/dist/hook.d.ts.map +1 -0
  37. package/dist/hook.js +16 -0
  38. package/dist/hook.js.map +1 -0
  39. package/dist/hooks.d.ts +21 -0
  40. package/dist/hooks.d.ts.map +1 -0
  41. package/dist/hooks.js +17 -0
  42. package/dist/hooks.js.map +1 -0
  43. package/dist/index.d.ts +10 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +8 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/input/args-parser.d.ts +22 -0
  48. package/dist/input/args-parser.d.ts.map +1 -0
  49. package/dist/input/args-parser.js +52 -0
  50. package/dist/input/args-parser.js.map +1 -0
  51. package/dist/input/parser.d.ts +14 -0
  52. package/dist/input/parser.d.ts.map +1 -0
  53. package/dist/input/parser.js +65 -0
  54. package/dist/input/parser.js.map +1 -0
  55. package/dist/terminal-hook-builder.d.ts +42 -0
  56. package/dist/terminal-hook-builder.d.ts.map +1 -0
  57. package/dist/terminal-hook-builder.js +48 -0
  58. package/dist/terminal-hook-builder.js.map +1 -0
  59. package/dist/terminal.d.ts +86 -0
  60. package/dist/terminal.d.ts.map +1 -0
  61. package/dist/terminal.js +274 -0
  62. package/dist/terminal.js.map +1 -0
  63. package/dist/types.d.ts +80 -0
  64. package/dist/types.d.ts.map +1 -0
  65. package/dist/types.js +85 -0
  66. package/dist/types.js.map +1 -0
  67. package/package.json +82 -0
@@ -0,0 +1,48 @@
1
+ class HookBuilder {
2
+ _reg;
3
+ constructor(_reg) {
4
+ this._reg = _reg;
5
+ }
6
+ do(callback) {
7
+ return this._reg(callback);
8
+ }
9
+ }
10
+ /**
11
+ * Entry point for registering terminal lifecycle hooks.
12
+ *
13
+ * Created by calling {@link Terminal.hook}. Select an event with one of the
14
+ * selector methods, then call {@link do} to register the callback.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * const h = term.hook()
19
+ * .beforeExecute()
20
+ * .do((command) => console.log(command.name()));
21
+ * // later: h.dispose();
22
+ * ```
23
+ */
24
+ export class TerminalHookBuilder {
25
+ _regs;
26
+ constructor(_regs) {
27
+ this._regs = _regs;
28
+ }
29
+ beforeParse() {
30
+ return new HookBuilder(this._regs.beforeParse);
31
+ }
32
+ afterParse() {
33
+ return new HookBuilder(this._regs.afterParse);
34
+ }
35
+ beforeExecute() {
36
+ return new HookBuilder(this._regs.beforeExecute);
37
+ }
38
+ afterExecute() {
39
+ return new HookBuilder(this._regs.afterExecute);
40
+ }
41
+ beforeExit() {
42
+ return new HookBuilder(this._regs.beforeExit);
43
+ }
44
+ onError() {
45
+ return new HookBuilder(this._regs.onError);
46
+ }
47
+ }
48
+ //# sourceMappingURL=terminal-hook-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal-hook-builder.js","sourceRoot":"","sources":["../src/terminal-hook-builder.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW;IACO;IAApB,YAAoB,IAAqB;QAArB,SAAI,GAAJ,IAAI,CAAiB;IAAG,CAAC;IAC7C,EAAE,CAAC,QAAW;QACV,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;CACJ;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,mBAAmB;IACR;IAApB,YAAoB,KAAwB;QAAxB,UAAK,GAAL,KAAK,CAAmB;IAAG,CAAC;IAEhD,WAAW;QACP,OAAO,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACnD,CAAC;IAED,UAAU;QACN,OAAO,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAClD,CAAC;IAED,aAAa;QAOT,OAAO,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACrD,CAAC;IAED,YAAY;QACR,OAAO,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACpD,CAAC;IAED,UAAU;QACN,OAAO,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAClD,CAAC;IAED,OAAO;QACH,OAAO,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/C,CAAC;CACJ"}
@@ -0,0 +1,86 @@
1
+ import { Command, type TerminalOptions } from './types.js';
2
+ import { TerminalHookBuilder } from './terminal-hook-builder.js';
3
+ /**
4
+ * Interactive terminal/shell that reads input, resolves commands, and
5
+ * dispatches execution through the lifecycle-hook pipeline.
6
+ *
7
+ * Create one, {@link register} commands, then call {@link start}.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * const term = new Terminal({ prompt: '> ' });
12
+ * term.register(new MyCommand());
13
+ * await term.start();
14
+ * ```
15
+ */
16
+ export declare class Terminal {
17
+ private rl;
18
+ private tree;
19
+ private _beforeParseHooks;
20
+ private _afterParseHooks;
21
+ private _beforeExecuteHooks;
22
+ private _afterExecuteHooks;
23
+ private _beforeExitHooks;
24
+ private _onErrorHooks;
25
+ private running;
26
+ private static readonly DEFAULT_OPTIONS;
27
+ private options;
28
+ private ctx;
29
+ private ctxState;
30
+ /**
31
+ * @param options - Prompt, I/O streams, history size, etc.
32
+ * Defaults to stdin/stdout with prompt `"> "`.
33
+ */
34
+ constructor(options?: TerminalOptions);
35
+ private createContext;
36
+ private registerBuiltins;
37
+ /**
38
+ * Register a command at the root level or as a subcommand of a
39
+ * parent container specified by a dot-separated path.
40
+ *
41
+ * @param command - The command to register.
42
+ * @param parentPath - Optional dot-separated path to a parent
43
+ * container (e.g. `"config.set"`). All
44
+ * intermediate containers must already exist.
45
+ * @throws When the parent path does not resolve to a container.
46
+ *
47
+ * @example
48
+ * ```
49
+ * term.register(cmd) // root level
50
+ * term.register(cmd, 'config') // under root "config"
51
+ * term.register(cmd, 'config.set') // under config > set
52
+ * ```
53
+ */
54
+ register(command: Command, parentPath?: string): void;
55
+ /**
56
+ * Create a hook builder to register lifecycle callbacks.
57
+ *
58
+ * @example
59
+ * ```
60
+ * const h = term.hook()
61
+ * .beforeExecute()
62
+ * .do((command) => console.log(command.name()));
63
+ * // later: h.dispose();
64
+ * ```
65
+ */
66
+ hook(): TerminalHookBuilder;
67
+ private _addHook;
68
+ /** Returns all root-level registered commands. */
69
+ getRootCommands(): Command[];
70
+ /**
71
+ * Start the terminal loop. Idempotent — safe to call multiple times.
72
+ */
73
+ start(): Promise<void>;
74
+ private createReadline;
75
+ private bindEvents;
76
+ /**
77
+ * Stop the terminal loop. Closes the readline interface.
78
+ */
79
+ stop(): Promise<void>;
80
+ private handleLine;
81
+ private processInput;
82
+ private resolveCommand;
83
+ private executeWithHooks;
84
+ private handleError;
85
+ }
86
+ //# sourceMappingURL=terminal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAyC,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAWlG,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAWjE;;;;;;;;;;;;GAYG;AACH,qBAAa,QAAQ;IACjB,OAAO,CAAC,EAAE,CAAmC;IAC7C,OAAO,CAAC,IAAI,CAAc;IAC1B,OAAO,CAAC,iBAAiB,CAAyB;IAClD,OAAO,CAAC,gBAAgB,CAAwB;IAChD,OAAO,CAAC,mBAAmB,CAA2B;IACtD,OAAO,CAAC,kBAAkB,CAA0B;IACpD,OAAO,CAAC,gBAAgB,CAAwB;IAChD,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAKrC;IAEF,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,GAAG,CAAiB;IAC5B,OAAO,CAAC,QAAQ,CAA+B;IAE/C;;;OAGG;gBACS,OAAO,CAAC,EAAE,eAAe;IAOrC,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,gBAAgB;IAMxB;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;IAwBrD;;;;;;;;;;OAUG;IACH,IAAI,IAAI,mBAAmB;IAW3B,OAAO,CAAC,QAAQ;IAahB,kDAAkD;IAClD,eAAe,IAAI,OAAO,EAAE;IAI5B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B,OAAO,CAAC,cAAc;IAgBtB,OAAO,CAAC,UAAU;IAsBlB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAYb,UAAU;YAqBV,YAAY;IAgB1B,OAAO,CAAC,cAAc;YAaR,gBAAgB;YAYhB,WAAW;CAmB5B"}
@@ -0,0 +1,274 @@
1
+ import * as readline from 'node:readline';
2
+ import { CommandContainer } from './types.js';
3
+ import { CommandTree } from './command-tree.js';
4
+ import { tokenize } from './input/parser.js';
5
+ import { parseFlags } from './input/args-parser.js';
6
+ import { CommandArguments } from './command-arguments.js';
7
+ import { Completer } from './completion/completer.js';
8
+ import { CommandNotFoundError } from './errors.js';
9
+ import { HelpCommand } from './commands/help.js';
10
+ import { ExitCommand } from './commands/exit.js';
11
+ import { ClearCommand } from './commands/clear.js';
12
+ import { TerminalHookBuilder } from './terminal-hook-builder.js';
13
+ import { TypedHook } from './hooks.js';
14
+ /**
15
+ * Interactive terminal/shell that reads input, resolves commands, and
16
+ * dispatches execution through the lifecycle-hook pipeline.
17
+ *
18
+ * Create one, {@link register} commands, then call {@link start}.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * const term = new Terminal({ prompt: '> ' });
23
+ * term.register(new MyCommand());
24
+ * await term.start();
25
+ * ```
26
+ */
27
+ export class Terminal {
28
+ rl = null;
29
+ tree;
30
+ _beforeParseHooks = [];
31
+ _afterParseHooks = [];
32
+ _beforeExecuteHooks = [];
33
+ _afterExecuteHooks = [];
34
+ _beforeExitHooks = [];
35
+ _onErrorHooks = [];
36
+ running = false;
37
+ static DEFAULT_OPTIONS = {
38
+ prompt: '> ',
39
+ stdin: process.stdin,
40
+ stdout: process.stdout,
41
+ historySize: 100
42
+ };
43
+ options;
44
+ ctx;
45
+ ctxState = {};
46
+ /**
47
+ * @param options - Prompt, I/O streams, history size, etc.
48
+ * Defaults to stdin/stdout with prompt `"> "`.
49
+ */
50
+ constructor(options) {
51
+ this.options = { ...Terminal.DEFAULT_OPTIONS, ...options };
52
+ this.tree = new CommandTree();
53
+ this.ctx = this.createContext();
54
+ this.registerBuiltins();
55
+ }
56
+ createContext() {
57
+ return {
58
+ terminal: this,
59
+ stdout: this.options.stdout,
60
+ stdin: this.options.stdin,
61
+ state: this.ctxState,
62
+ logger: console,
63
+ exit: () => {
64
+ void this.stop();
65
+ }
66
+ };
67
+ }
68
+ registerBuiltins() {
69
+ this.register(new HelpCommand());
70
+ this.register(new ExitCommand());
71
+ this.register(new ClearCommand());
72
+ }
73
+ /**
74
+ * Register a command at the root level or as a subcommand of a
75
+ * parent container specified by a dot-separated path.
76
+ *
77
+ * @param command - The command to register.
78
+ * @param parentPath - Optional dot-separated path to a parent
79
+ * container (e.g. `"config.set"`). All
80
+ * intermediate containers must already exist.
81
+ * @throws When the parent path does not resolve to a container.
82
+ *
83
+ * @example
84
+ * ```
85
+ * term.register(cmd) // root level
86
+ * term.register(cmd, 'config') // under root "config"
87
+ * term.register(cmd, 'config.set') // under config > set
88
+ * ```
89
+ */
90
+ register(command, parentPath) {
91
+ if (!parentPath) {
92
+ this.tree.add(command);
93
+ return;
94
+ }
95
+ const segments = parentPath.split('.');
96
+ let container = this.tree;
97
+ let level = this.tree.commands();
98
+ for (const seg of segments) {
99
+ const parent = level.find((c) => c.name() === seg);
100
+ if (!parent || !(parent instanceof CommandContainer)) {
101
+ throw new Error(`Cannot register "${command.name()}": parent path "${parentPath}" does not resolve to a container at segment "${seg}"`);
102
+ }
103
+ container = parent;
104
+ level = parent.commands();
105
+ }
106
+ container.add(command);
107
+ }
108
+ /**
109
+ * Create a hook builder to register lifecycle callbacks.
110
+ *
111
+ * @example
112
+ * ```
113
+ * const h = term.hook()
114
+ * .beforeExecute()
115
+ * .do((command) => console.log(command.name()));
116
+ * // later: h.dispose();
117
+ * ```
118
+ */
119
+ hook() {
120
+ return new TerminalHookBuilder({
121
+ beforeParse: (fn) => this._addHook(this._beforeParseHooks, fn),
122
+ afterParse: (fn) => this._addHook(this._afterParseHooks, fn),
123
+ beforeExecute: (fn) => this._addHook(this._beforeExecuteHooks, fn),
124
+ afterExecute: (fn) => this._addHook(this._afterExecuteHooks, fn),
125
+ beforeExit: (fn) => this._addHook(this._beforeExitHooks, fn),
126
+ onError: (fn) => this._addHook(this._onErrorHooks, fn)
127
+ });
128
+ }
129
+ _addHook(arr, fn) {
130
+ let hook;
131
+ hook = new TypedHook(fn, () => {
132
+ const idx = arr.indexOf(hook);
133
+ arr.splice(idx, 1);
134
+ });
135
+ arr.push(hook);
136
+ return hook;
137
+ }
138
+ /** Returns all root-level registered commands. */
139
+ getRootCommands() {
140
+ return this.tree.getRoots();
141
+ }
142
+ /**
143
+ * Start the terminal loop. Idempotent — safe to call multiple times.
144
+ */
145
+ async start() {
146
+ if (this.running)
147
+ return;
148
+ this.running = true;
149
+ this.rl = this.createReadline();
150
+ this.bindEvents(this.rl);
151
+ this.rl.prompt();
152
+ }
153
+ createReadline() {
154
+ const completer = new Completer(this.tree);
155
+ return readline.createInterface({
156
+ input: this.options.stdin,
157
+ output: this.options.stdout,
158
+ prompt: this.options.prompt,
159
+ historySize: this.options.historySize,
160
+ completer: (line) => {
161
+ const { matches, partial } = completer.complete(line);
162
+ return [matches, partial];
163
+ },
164
+ terminal: this.options.stdin.isTTY
165
+ });
166
+ }
167
+ bindEvents(rl) {
168
+ rl.on('line', (line) => {
169
+ void this.handleLine(line);
170
+ });
171
+ rl.on('SIGINT', () => {
172
+ this.options.stdout.write('^C\n');
173
+ rl.prompt();
174
+ });
175
+ rl.on('close', () => {
176
+ if (this.running) {
177
+ this.options.stdout.write('\n');
178
+ void this.stop();
179
+ }
180
+ });
181
+ rl.on('error', (err) => {
182
+ this.options.stdout.write(`Readline error: ${err.message}\n`);
183
+ });
184
+ }
185
+ /**
186
+ * Stop the terminal loop. Closes the readline interface.
187
+ */
188
+ async stop() {
189
+ if (this.running) {
190
+ for (const hook of this._beforeExitHooks) {
191
+ await hook.exec();
192
+ }
193
+ }
194
+ this.running = false;
195
+ this.rl?.close();
196
+ this.rl = null;
197
+ this.options.stdin.pause();
198
+ }
199
+ async handleLine(input) {
200
+ try {
201
+ const tokens = await this.processInput(input);
202
+ if (tokens.length === 0) {
203
+ this.rl?.prompt();
204
+ return;
205
+ }
206
+ const resolved = this.resolveCommand(tokens);
207
+ const record = parseFlags(resolved.args, resolved.command.definitions());
208
+ const args = new CommandArguments(record, this.rl, resolved.command.definitions());
209
+ await this.executeWithHooks(resolved.command, args);
210
+ }
211
+ catch (error) {
212
+ await this.handleError(error);
213
+ }
214
+ finally {
215
+ if (this.running) {
216
+ this.rl?.prompt();
217
+ }
218
+ }
219
+ }
220
+ async processInput(input) {
221
+ let processed = input;
222
+ for (const hook of this._beforeParseHooks) {
223
+ processed = await hook.exec(processed);
224
+ }
225
+ const tokens = tokenize(processed);
226
+ let finalTokens = tokens;
227
+ for (const hook of this._afterParseHooks) {
228
+ finalTokens = await hook.exec(finalTokens);
229
+ }
230
+ return finalTokens;
231
+ }
232
+ resolveCommand(tokens) {
233
+ const resolved = this.tree.find(tokens);
234
+ if (!resolved) {
235
+ const suggestions = this.tree.findSuggestions(tokens[0]);
236
+ const msg = suggestions.length > 0
237
+ ? `Unknown command: ${tokens[0]}. Did you mean: ${suggestions.join(', ')}?`
238
+ : `Unknown command: ${tokens[0]}`;
239
+ throw new CommandNotFoundError(msg, suggestions);
240
+ }
241
+ return resolved;
242
+ }
243
+ async executeWithHooks(command, args) {
244
+ for (const hook of this._beforeExecuteHooks) {
245
+ if ((await hook.exec(command, this.ctx, args)) === false)
246
+ return;
247
+ }
248
+ const result = await command.execute(this.ctx, args);
249
+ for (const hook of this._afterExecuteHooks) {
250
+ await hook.exec(result);
251
+ }
252
+ }
253
+ async handleError(error) {
254
+ for (const hook of this._onErrorHooks) {
255
+ try {
256
+ if ((await hook.exec(error)) === true)
257
+ return;
258
+ }
259
+ catch (hookError) {
260
+ this.options.stdout.write(`Error in onError hook: ${hookError.message}\n`);
261
+ }
262
+ }
263
+ if (error instanceof CommandNotFoundError) {
264
+ this.options.stdout.write(`${error.message}\n`);
265
+ }
266
+ else if (error instanceof Error) {
267
+ this.options.stdout.write(`Error: ${error.message}\n`);
268
+ }
269
+ else {
270
+ this.options.stdout.write(`Error: ${String(error)}\n`);
271
+ }
272
+ }
273
+ }
274
+ //# sourceMappingURL=terminal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.js","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ import type { Terminal } from './terminal.js';
2
+ import type { CommandArguments, CommandArgumentDefinition } from './command-arguments.js';
3
+ /**
4
+ * A leaf node in the command tree. Has no subcommand support.
5
+ * Subclasses must implement {@link execute}.
6
+ */
7
+ export declare abstract class Command {
8
+ private _name;
9
+ private _description;
10
+ private _definitions;
11
+ /**
12
+ * @param name - Command name used for matching input tokens.
13
+ * @param description - Short description shown in help output.
14
+ * @param argDefs - Argument definitions for `--name value` pairs.
15
+ */
16
+ constructor(name: string, description?: string, argDefs?: CommandArgumentDefinition[]);
17
+ private _validatePositions;
18
+ /** Command name (used for matching input tokens). */
19
+ name(): string;
20
+ /** Shown in `help` output. */
21
+ description(): string | undefined;
22
+ /** Argument definitions for this command. */
23
+ definitions(): CommandArgumentDefinition[];
24
+ /**
25
+ * Execute the command.
26
+ * @param ctx - Execution context with streams, state, and lifecycle access.
27
+ * @param args - Parsed `--name value` pairs wrapped in an Args instance.
28
+ */
29
+ abstract execute(ctx: CommandContext, args: CommandArguments): void | Promise<void>;
30
+ }
31
+ /**
32
+ * A command that acts as a namespace for subcommands.
33
+ * Subcommands are registered via {@link add} and are used for
34
+ * tree traversal and help output.
35
+ *
36
+ * The default {@link execute} implementation prints detailed help
37
+ * for this container (description, arguments, subcommands).
38
+ * Subclasses may override `execute` to provide custom behavior.
39
+ */
40
+ export declare class CommandContainer extends Command {
41
+ private _commands;
42
+ /** Register a child command. */
43
+ add(command: Command): void;
44
+ /** Returns all registered child commands. */
45
+ commands(): Command[];
46
+ execute(ctx: CommandContext, _args: CommandArguments): Promise<void>;
47
+ }
48
+ /** Context passed to every command's `execute()`. */
49
+ export interface CommandContext {
50
+ /** The running Terminal instance. */
51
+ terminal: Terminal;
52
+ /** Output stream — write command results here. */
53
+ stdout: NodeJS.WriteStream;
54
+ /** Input stream. */
55
+ stdin: NodeJS.ReadStream;
56
+ /** Shared mutable state accessible to all commands. */
57
+ state: Record<string, unknown>;
58
+ /** Console-compatible logger. */
59
+ logger: Logger;
60
+ /** Shortcut for `terminal.stop()`. */
61
+ exit: () => void;
62
+ }
63
+ /** Console-compatible logger interface. */
64
+ export interface Logger {
65
+ info(...args: unknown[]): void;
66
+ warn(...args: unknown[]): void;
67
+ error(...args: unknown[]): void;
68
+ }
69
+ /** Options for the Terminal constructor. */
70
+ export interface TerminalOptions {
71
+ /** Prompt string (default `"> "`). */
72
+ prompt?: string;
73
+ /** Input stream (default `process.stdin`). */
74
+ stdin?: NodeJS.ReadStream;
75
+ /** Output stream (default `process.stdout`). */
76
+ stdout?: NodeJS.WriteStream;
77
+ /** Readline history size (default `100`). */
78
+ historySize?: number;
79
+ }
80
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAG1F;;;GAGG;AACH,8BAAsB,OAAO;IACzB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,YAAY,CAA8B;IAElD;;;;OAIG;gBACS,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,yBAAyB,EAAE;IAarF,OAAO,CAAC,kBAAkB;IA2B1B,qDAAqD;IACrD,IAAI,IAAI,MAAM;IAId,8BAA8B;IAC9B,WAAW,IAAI,MAAM,GAAG,SAAS;IAIjC,6CAA6C;IAC7C,WAAW,IAAI,yBAAyB,EAAE;IAI1C;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;CACtF;AAED;;;;;;;;GAQG;AACH,qBAAa,gBAAiB,SAAQ,OAAO;IACzC,OAAO,CAAC,SAAS,CAAiB;IAElC,gCAAgC;IAChC,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAI3B,6CAA6C;IAC7C,QAAQ,IAAI,OAAO,EAAE;IAIf,OAAO,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;CAI7E;AAED,qDAAqD;AACrD,MAAM,WAAW,cAAc;IAC3B,qCAAqC;IACrC,QAAQ,EAAE,QAAQ,CAAC;IACnB,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC;IAC3B,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC;IACzB,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,IAAI,EAAE,MAAM,IAAI,CAAC;CACpB;AAED,2CAA2C;AAC3C,MAAM,WAAW,MAAM;IACnB,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC/B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CACnC;AAED,4CAA4C;AAC5C,MAAM,WAAW,eAAe;IAC5B,sCAAsC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAC1B,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC;IAC5B,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB"}
package/dist/types.js ADDED
@@ -0,0 +1,85 @@
1
+ import { InvalidArgumentsError } from './errors.js';
2
+ /**
3
+ * A leaf node in the command tree. Has no subcommand support.
4
+ * Subclasses must implement {@link execute}.
5
+ */
6
+ export class Command {
7
+ _name;
8
+ _description;
9
+ _definitions;
10
+ /**
11
+ * @param name - Command name used for matching input tokens.
12
+ * @param description - Short description shown in help output.
13
+ * @param argDefs - Argument definitions for `--name value` pairs.
14
+ */
15
+ constructor(name, description, argDefs) {
16
+ if (name.length === 0) {
17
+ throw new InvalidArgumentsError('Command name cannot be empty');
18
+ }
19
+ if (/\s/.test(name)) {
20
+ throw new InvalidArgumentsError(`Command name "${name}" must not contain whitespace`);
21
+ }
22
+ this._name = name;
23
+ this._description = description;
24
+ this._definitions = argDefs ?? [];
25
+ this._validatePositions(name);
26
+ }
27
+ _validatePositions(name) {
28
+ const positions = this._definitions
29
+ .map((d) => d.position)
30
+ .filter((p) => p !== undefined);
31
+ if (positions.length === 0)
32
+ return;
33
+ const seen = new Set();
34
+ for (const pos of positions) {
35
+ if (seen.has(pos)) {
36
+ throw new InvalidArgumentsError(`Duplicate position index ${pos} in command "${name}"`);
37
+ }
38
+ seen.add(pos);
39
+ }
40
+ const sorted = [...positions].sort((a, b) => a - b);
41
+ for (let i = 0; i < sorted.length; i++) {
42
+ if (sorted[i] !== i) {
43
+ throw new InvalidArgumentsError(`Positional arguments must form a contiguous sequence starting at 0. ` +
44
+ `Expected position ${i}, got ${sorted[i]} in command "${name}"`);
45
+ }
46
+ }
47
+ }
48
+ /** Command name (used for matching input tokens). */
49
+ name() {
50
+ return this._name;
51
+ }
52
+ /** Shown in `help` output. */
53
+ description() {
54
+ return this._description;
55
+ }
56
+ /** Argument definitions for this command. */
57
+ definitions() {
58
+ return this._definitions;
59
+ }
60
+ }
61
+ /**
62
+ * A command that acts as a namespace for subcommands.
63
+ * Subcommands are registered via {@link add} and are used for
64
+ * tree traversal and help output.
65
+ *
66
+ * The default {@link execute} implementation prints detailed help
67
+ * for this container (description, arguments, subcommands).
68
+ * Subclasses may override `execute` to provide custom behavior.
69
+ */
70
+ export class CommandContainer extends Command {
71
+ _commands = [];
72
+ /** Register a child command. */
73
+ add(command) {
74
+ this._commands.push(command);
75
+ }
76
+ /** Returns all registered child commands. */
77
+ commands() {
78
+ return this._commands;
79
+ }
80
+ async execute(ctx, _args) {
81
+ const { commandHelp } = await import('./commands/help.js');
82
+ ctx.stdout.write(commandHelp(this) + '\n');
83
+ }
84
+ }
85
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}