@pablozaiden/terminatui 0.2.0 → 0.3.0-beta-1
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/AGENTS.md +14 -2
- package/CLAUDE.md +1 -0
- package/README.md +64 -43
- package/bun.lock +85 -0
- package/examples/tui-app/commands/config/app/get.ts +6 -10
- package/examples/tui-app/commands/config/app/index.ts +2 -6
- package/examples/tui-app/commands/config/app/set.ts +23 -13
- package/examples/tui-app/commands/config/index.ts +2 -6
- package/examples/tui-app/commands/config/user/get.ts +6 -10
- package/examples/tui-app/commands/config/user/index.ts +2 -6
- package/examples/tui-app/commands/config/user/set.ts +6 -10
- package/examples/tui-app/commands/greet.ts +13 -11
- package/examples/tui-app/commands/math.ts +5 -9
- package/examples/tui-app/commands/status.ts +21 -12
- package/examples/tui-app/index.ts +6 -3
- package/guides/01-hello-world.md +7 -2
- package/guides/02-adding-options.md +2 -2
- package/guides/03-multiple-commands.md +6 -8
- package/guides/04-subcommands.md +8 -8
- package/guides/05-interactive-tui.md +45 -30
- package/guides/06-config-validation.md +4 -12
- package/guides/07-async-cancellation.md +14 -16
- package/guides/08-complete-application.md +12 -42
- package/guides/README.md +7 -3
- package/package.json +4 -8
- package/src/__tests__/application.test.ts +87 -68
- package/src/__tests__/buildCliCommand.test.ts +99 -119
- package/src/__tests__/builtins.test.ts +27 -75
- package/src/__tests__/command.test.ts +100 -131
- package/src/__tests__/context.test.ts +1 -26
- package/src/__tests__/helpCore.test.ts +227 -0
- package/src/__tests__/parser.test.ts +98 -244
- package/src/__tests__/registry.test.ts +33 -160
- package/src/__tests__/schemaToFields.test.ts +75 -158
- package/src/builtins/help.ts +12 -4
- package/src/builtins/settings.ts +18 -32
- package/src/builtins/version.ts +4 -4
- package/src/cli/output/colors.ts +1 -1
- package/src/cli/parser.ts +26 -95
- package/src/core/application.ts +192 -110
- package/src/core/command.ts +26 -9
- package/src/core/context.ts +31 -20
- package/src/core/help.ts +24 -18
- package/src/core/knownCommands.ts +13 -0
- package/src/core/logger.ts +39 -42
- package/src/core/registry.ts +5 -12
- package/src/tui/TuiApplication.tsx +63 -120
- package/src/tui/TuiRoot.tsx +135 -0
- package/src/tui/adapters/factory.ts +19 -0
- package/src/tui/adapters/ink/InkRenderer.tsx +135 -0
- package/src/tui/adapters/ink/components/Button.tsx +12 -0
- package/src/tui/adapters/ink/components/Code.tsx +6 -0
- package/src/tui/adapters/ink/components/CodeHighlight.tsx +6 -0
- package/src/tui/adapters/ink/components/Container.tsx +5 -0
- package/src/tui/adapters/ink/components/Field.tsx +12 -0
- package/src/tui/adapters/ink/components/Label.tsx +24 -0
- package/src/tui/adapters/ink/components/MenuButton.tsx +12 -0
- package/src/tui/adapters/ink/components/MenuItem.tsx +17 -0
- package/src/tui/adapters/ink/components/Overlay.tsx +5 -0
- package/src/tui/adapters/ink/components/Panel.tsx +15 -0
- package/src/tui/adapters/ink/components/ScrollView.tsx +5 -0
- package/src/tui/adapters/ink/components/Select.tsx +44 -0
- package/src/tui/adapters/ink/components/Spacer.tsx +15 -0
- package/src/tui/adapters/ink/components/Spinner.tsx +5 -0
- package/src/tui/adapters/ink/components/TextInput.tsx +22 -0
- package/src/tui/adapters/ink/components/Value.tsx +7 -0
- package/src/tui/adapters/ink/keyboard.ts +97 -0
- package/src/tui/adapters/ink/utils.ts +16 -0
- package/src/tui/adapters/opentui/OpenTuiRenderer.tsx +115 -0
- package/src/tui/adapters/opentui/components/Button.tsx +13 -0
- package/src/tui/adapters/opentui/components/Code.tsx +12 -0
- package/src/tui/adapters/opentui/components/CodeHighlight.tsx +24 -0
- package/src/tui/adapters/opentui/components/Container.tsx +56 -0
- package/src/tui/adapters/opentui/components/Field.tsx +18 -0
- package/src/tui/adapters/opentui/components/Label.tsx +15 -0
- package/src/tui/adapters/opentui/components/MenuButton.tsx +14 -0
- package/src/tui/adapters/opentui/components/MenuItem.tsx +29 -0
- package/src/tui/adapters/opentui/components/Overlay.tsx +21 -0
- package/src/tui/adapters/opentui/components/Panel.tsx +78 -0
- package/src/tui/adapters/opentui/components/ScrollView.tsx +85 -0
- package/src/tui/adapters/opentui/components/Select.tsx +59 -0
- package/src/tui/adapters/opentui/components/Spacer.tsx +5 -0
- package/src/tui/adapters/opentui/components/Spinner.tsx +12 -0
- package/src/tui/adapters/opentui/components/TextInput.tsx +13 -0
- package/src/tui/adapters/opentui/components/Value.tsx +13 -0
- package/src/tui/{hooks → adapters/opentui/hooks}/useSpinner.ts +2 -11
- package/src/tui/adapters/opentui/keyboard.ts +61 -0
- package/src/tui/adapters/types.ts +70 -0
- package/src/tui/components/ActionButton.tsx +0 -36
- package/src/tui/components/CommandSelector.tsx +45 -92
- package/src/tui/components/ConfigForm.tsx +68 -42
- package/src/tui/components/FieldRow.tsx +0 -30
- package/src/tui/components/Header.tsx +14 -13
- package/src/tui/components/JsonHighlight.tsx +10 -17
- package/src/tui/components/ModalBase.tsx +38 -0
- package/src/tui/components/ResultsPanel.tsx +27 -36
- package/src/tui/components/StatusBar.tsx +24 -39
- package/src/tui/components/logColors.ts +12 -0
- package/src/tui/context/ClipboardContext.tsx +87 -0
- package/src/tui/context/ExecutorContext.tsx +139 -0
- package/src/tui/context/KeyboardContext.tsx +85 -71
- package/src/tui/context/LogsContext.tsx +35 -0
- package/src/tui/context/NavigationContext.tsx +194 -0
- package/src/tui/context/RendererContext.tsx +20 -0
- package/src/tui/context/TuiAppContext.tsx +58 -0
- package/src/tui/hooks/useActiveKeyHandler.ts +75 -0
- package/src/tui/hooks/useBackHandler.ts +34 -0
- package/src/tui/hooks/useClipboard.ts +40 -25
- package/src/tui/hooks/useClipboardProvider.ts +42 -0
- package/src/tui/hooks/useGlobalKeyHandler.ts +54 -0
- package/src/tui/modals/CliModal.tsx +82 -0
- package/src/tui/modals/EditorModal.tsx +207 -0
- package/src/tui/modals/LogsModal.tsx +98 -0
- package/src/tui/registry.ts +102 -0
- package/src/tui/screens/CommandSelectScreen.tsx +162 -0
- package/src/tui/screens/ConfigScreen.tsx +160 -0
- package/src/tui/screens/ErrorScreen.tsx +58 -0
- package/src/tui/screens/ResultsScreen.tsx +60 -0
- package/src/tui/screens/RunningScreen.tsx +72 -0
- package/src/tui/screens/ScreenBase.ts +6 -0
- package/src/tui/semantic/Button.tsx +7 -0
- package/src/tui/semantic/Code.tsx +7 -0
- package/src/tui/semantic/CodeHighlight.tsx +7 -0
- package/src/tui/semantic/Container.tsx +7 -0
- package/src/tui/semantic/Field.tsx +7 -0
- package/src/tui/semantic/Label.tsx +7 -0
- package/src/tui/semantic/MenuButton.tsx +7 -0
- package/src/tui/semantic/MenuItem.tsx +7 -0
- package/src/tui/semantic/Overlay.tsx +7 -0
- package/src/tui/semantic/Panel.tsx +7 -0
- package/src/tui/semantic/ScrollView.tsx +9 -0
- package/src/tui/semantic/Select.tsx +7 -0
- package/src/tui/semantic/Spacer.tsx +7 -0
- package/src/tui/semantic/Spinner.tsx +7 -0
- package/src/tui/semantic/TextInput.tsx +7 -0
- package/src/tui/semantic/Value.tsx +7 -0
- package/src/tui/semantic/types.ts +195 -0
- package/src/tui/theme.ts +25 -14
- package/src/tui/utils/buildCliCommand.ts +1 -0
- package/src/tui/utils/getEnumKeys.ts +3 -0
- package/src/tui/utils/parameterPersistence.ts +1 -0
- package/src/types/command.ts +0 -60
- package/examples/tui-app/commands/index.ts +0 -4
- package/src/__tests__/colors.test.ts +0 -127
- package/src/__tests__/commandClass.test.ts +0 -130
- package/src/__tests__/help.test.ts +0 -412
- package/src/__tests__/registryNew.test.ts +0 -160
- package/src/__tests__/table.test.ts +0 -146
- package/src/__tests__/tui.test.ts +0 -26
- package/src/builtins/index.ts +0 -4
- package/src/cli/help.ts +0 -174
- package/src/cli/index.ts +0 -3
- package/src/cli/output/index.ts +0 -2
- package/src/cli/output/table.ts +0 -141
- package/src/commands/help.ts +0 -50
- package/src/commands/index.ts +0 -1
- package/src/components/index.ts +0 -147
- package/src/core/index.ts +0 -15
- package/src/hooks/index.ts +0 -131
- package/src/index.ts +0 -137
- package/src/registry/commandRegistry.ts +0 -77
- package/src/registry/index.ts +0 -1
- package/src/tui/TuiApp.tsx +0 -619
- package/src/tui/app.ts +0 -29
- package/src/tui/components/CliModal.tsx +0 -81
- package/src/tui/components/EditorModal.tsx +0 -177
- package/src/tui/components/LogsPanel.tsx +0 -86
- package/src/tui/components/index.ts +0 -13
- package/src/tui/context/index.ts +0 -7
- package/src/tui/hooks/index.ts +0 -35
- package/src/tui/hooks/useKeyboardHandler.ts +0 -91
- package/src/tui/hooks/useLogStream.ts +0 -96
- package/src/tui/index.ts +0 -65
- package/src/tui/utils/index.ts +0 -13
- package/src/types/index.ts +0 -1
package/AGENTS.md
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
## General guidelines
|
|
2
|
+
|
|
3
|
+
- Never use `git` operations. That's up to the user.
|
|
4
|
+
- Always prefer simplicity, usability and top level type safety over cleverness.
|
|
5
|
+
- Don't create index.ts files that re-export things from other files. Always import directly from the file you need.
|
|
6
|
+
- Prefer classes over standalone functions when it makes sense.
|
|
7
|
+
- Before doing something, check the patterns used in the rest of the codebase.
|
|
8
|
+
- Never use `import("...")` dynamic imports. Always use static imports (unless absolutely necessary).
|
|
9
|
+
|
|
10
|
+
## Bun specifics
|
|
11
|
+
This is a Bun-only project. Never check if something might not be supported in another environment. You can assume Bun is always available.
|
|
12
|
+
|
|
13
|
+
Always use Bun features and APIs where possible.
|
|
2
14
|
|
|
3
15
|
- Use `bun <file>` instead of `node <file>` or `ts-node <file>`
|
|
4
16
|
- Use `bun test` instead of `jest` or `vitest`
|
|
@@ -28,4 +40,4 @@ test("hello world", () => {
|
|
|
28
40
|
});
|
|
29
41
|
```
|
|
30
42
|
|
|
31
|
-
For more information, read the Bun API docs in `node_modules/bun-types/docs/**.mdx`.
|
|
43
|
+
For more information, read the Bun API docs in `node_modules/bun-types/docs/**.mdx`.
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ A type-safe, class-based framework for building CLI and TUI applications in Type
|
|
|
12
12
|
- **Nested subcommands** - Hierarchical command structures with path resolution
|
|
13
13
|
- **Lifecycle hooks** - `beforeExecute()` and `afterExecute()` hooks on commands
|
|
14
14
|
- **Service container** - `AppContext` provides dependency injection for services
|
|
15
|
-
- **Integrated logging** - Logger with TUI-aware output handling
|
|
15
|
+
- **Integrated logging** - Logger with TUI-aware output handling (live log modal with global copy shortcut)
|
|
16
16
|
- **Cancellation support** - AbortSignal-based cancellation for long-running commands
|
|
17
17
|
- **Config validation** - `buildConfig()` hook for transforming and validating options
|
|
18
18
|
|
|
@@ -27,7 +27,12 @@ bun add @pablozaiden/terminatui
|
|
|
27
27
|
### 1. Define a Command
|
|
28
28
|
|
|
29
29
|
```typescript
|
|
30
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
Command,
|
|
32
|
+
type OptionSchema,
|
|
33
|
+
type CommandResult,
|
|
34
|
+
type CommandExecutionContext,
|
|
35
|
+
} from "@pablozaiden/terminatui";
|
|
31
36
|
|
|
32
37
|
const greetOptions = {
|
|
33
38
|
name: {
|
|
@@ -48,7 +53,10 @@ class GreetCommand extends Command<typeof greetOptions> {
|
|
|
48
53
|
readonly description = "Greet someone";
|
|
49
54
|
readonly options = greetOptions;
|
|
50
55
|
|
|
51
|
-
override execute(
|
|
56
|
+
override execute(
|
|
57
|
+
config: { name: string; loud: boolean },
|
|
58
|
+
_execCtx: CommandExecutionContext
|
|
59
|
+
): CommandResult {
|
|
52
60
|
const message = `Hello, ${config.name}!`;
|
|
53
61
|
console.log(config.loud ? message.toUpperCase() : message);
|
|
54
62
|
return { success: true, message };
|
|
@@ -77,7 +85,11 @@ class MyApp extends Application {
|
|
|
77
85
|
|
|
78
86
|
```typescript
|
|
79
87
|
// index.ts
|
|
88
|
+
// Recommended: let Terminatui read `Bun.argv.slice(2)`
|
|
80
89
|
await new MyApp().run();
|
|
90
|
+
|
|
91
|
+
// For tests or programmatic invocation:
|
|
92
|
+
// await new MyApp().runFromArgs(["greet", "--name", "World"]);
|
|
81
93
|
```
|
|
82
94
|
|
|
83
95
|
```bash
|
|
@@ -121,9 +133,8 @@ abstract class Command<TOptions extends OptionSchema = OptionSchema, TConfig = u
|
|
|
121
133
|
|
|
122
134
|
// Required: Main execution method
|
|
123
135
|
abstract execute(
|
|
124
|
-
ctx: AppContext,
|
|
125
136
|
config: TConfig,
|
|
126
|
-
execCtx
|
|
137
|
+
execCtx: CommandExecutionContext
|
|
127
138
|
): Promise<CommandResult | void> | CommandResult | void;
|
|
128
139
|
|
|
129
140
|
// Optional: Transform/validate options before execute
|
|
@@ -170,10 +181,15 @@ The `Application` class manages command registration and execution:
|
|
|
170
181
|
```typescript
|
|
171
182
|
class Application {
|
|
172
183
|
constructor(config: ApplicationConfig);
|
|
173
|
-
|
|
174
|
-
|
|
184
|
+
|
|
185
|
+
// Recommended entrypoint (reads `Bun.argv.slice(2)`)
|
|
186
|
+
run(): Promise<void>;
|
|
187
|
+
|
|
188
|
+
// Useful for tests or programmatic invocation
|
|
189
|
+
runFromArgs(argv: string[]): Promise<void>;
|
|
190
|
+
|
|
175
191
|
getContext(): AppContext;
|
|
176
|
-
|
|
192
|
+
|
|
177
193
|
// Lifecycle hooks (override in subclass)
|
|
178
194
|
onBeforeRun?(command: Command, options: Record<string, unknown>): void;
|
|
179
195
|
onAfterRun?(command: Command, result: unknown): void;
|
|
@@ -196,6 +212,8 @@ Access application-wide services and configuration:
|
|
|
196
212
|
|
|
197
213
|
```typescript
|
|
198
214
|
import { AppContext } from "@pablozaiden/terminatui";
|
|
215
|
+
import type { CommandExecutionContext } from "@pablozaiden/terminatui";
|
|
216
|
+
import { AbortError } from "@pablozaiden/terminatui";
|
|
199
217
|
|
|
200
218
|
// Get the current context (set during Application.run())
|
|
201
219
|
const ctx = AppContext.current;
|
|
@@ -234,7 +252,7 @@ interface OptionDef {
|
|
|
234
252
|
tuiHidden?: boolean; // Hide from TUI form
|
|
235
253
|
}
|
|
236
254
|
|
|
237
|
-
type OptionSchema = Record<string, OptionDef>;
|
|
255
|
+
type OptionSchema = Record<string, OptionDef>; // See library types
|
|
238
256
|
```
|
|
239
257
|
|
|
240
258
|
## Config Validation with buildConfig
|
|
@@ -242,7 +260,7 @@ type OptionSchema = Record<string, OptionDef>;
|
|
|
242
260
|
Use `buildConfig()` to transform and validate options before execution:
|
|
243
261
|
|
|
244
262
|
```typescript
|
|
245
|
-
import { Command, ConfigValidationError, type
|
|
263
|
+
import { Command, ConfigValidationError, type OptionValues } from "@pablozaiden/terminatui";
|
|
246
264
|
|
|
247
265
|
interface MyConfig {
|
|
248
266
|
resolvedPath: string;
|
|
@@ -254,7 +272,7 @@ class MyCommand extends Command<typeof myOptions, MyConfig> {
|
|
|
254
272
|
readonly description = "Do something";
|
|
255
273
|
readonly options = myOptions;
|
|
256
274
|
|
|
257
|
-
override buildConfig(
|
|
275
|
+
override buildConfig(opts: OptionValues<typeof myOptions>): MyConfig {
|
|
258
276
|
const pathRaw = opts["path"] as string | undefined;
|
|
259
277
|
if (!pathRaw) {
|
|
260
278
|
throw new ConfigValidationError("Missing required option: path", "path");
|
|
@@ -271,9 +289,16 @@ class MyCommand extends Command<typeof myOptions, MyConfig> {
|
|
|
271
289
|
};
|
|
272
290
|
}
|
|
273
291
|
|
|
274
|
-
override async execute(
|
|
292
|
+
override async execute(
|
|
293
|
+
config: MyConfig,
|
|
294
|
+
execCtx: CommandExecutionContext
|
|
295
|
+
): Promise<CommandResult> {
|
|
275
296
|
// config is now typed as MyConfig
|
|
276
|
-
|
|
297
|
+
if (execCtx.signal.aborted) {
|
|
298
|
+
throw new AbortError("Command was cancelled");
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
AppContext.current.logger.info(`Processing ${config.count} items from ${config.resolvedPath}`);
|
|
277
302
|
return { success: true };
|
|
278
303
|
}
|
|
279
304
|
}
|
|
@@ -288,19 +313,18 @@ class LongRunningCommand extends Command<typeof options> {
|
|
|
288
313
|
// ...
|
|
289
314
|
|
|
290
315
|
override async execute(
|
|
291
|
-
ctx: AppContext,
|
|
292
316
|
config: Config,
|
|
293
|
-
execCtx
|
|
317
|
+
execCtx: CommandExecutionContext
|
|
294
318
|
): Promise<CommandResult> {
|
|
295
319
|
for (const item of items) {
|
|
296
320
|
// Check for cancellation
|
|
297
|
-
if (execCtx
|
|
321
|
+
if (execCtx.signal.aborted) {
|
|
298
322
|
throw new AbortError("Command was cancelled");
|
|
299
323
|
}
|
|
300
|
-
|
|
301
|
-
await processItem(item, execCtx
|
|
324
|
+
|
|
325
|
+
await processItem(item, execCtx.signal);
|
|
302
326
|
}
|
|
303
|
-
|
|
327
|
+
|
|
304
328
|
return { success: true };
|
|
305
329
|
}
|
|
306
330
|
}
|
|
@@ -350,6 +374,9 @@ Extend `TuiApplication` instead of `Application` to get automatic TUI support:
|
|
|
350
374
|
import { TuiApplication, Command } from "@pablozaiden/terminatui";
|
|
351
375
|
|
|
352
376
|
class MyApp extends TuiApplication {
|
|
377
|
+
// Each app decides what "default" means.
|
|
378
|
+
protected override defaultRenderer = "opentui" as const;
|
|
379
|
+
|
|
353
380
|
constructor() {
|
|
354
381
|
super({
|
|
355
382
|
name: "myapp",
|
|
@@ -362,11 +389,13 @@ class MyApp extends TuiApplication {
|
|
|
362
389
|
}
|
|
363
390
|
```
|
|
364
391
|
|
|
365
|
-
|
|
392
|
+
Execution mode is controlled only by the selected mode (`--mode`) or the app’s configured default mode.
|
|
366
393
|
|
|
367
394
|
```bash
|
|
368
|
-
myapp
|
|
369
|
-
myapp
|
|
395
|
+
myapp # Uses app default mode
|
|
396
|
+
myapp --mode opentui # Forces TUI (OpenTUI)
|
|
397
|
+
myapp --mode ink # Forces TUI (Ink)
|
|
398
|
+
myapp --mode cli run --verbose # Forces CLI
|
|
370
399
|
```
|
|
371
400
|
|
|
372
401
|
### TUI Metadata
|
|
@@ -412,14 +441,15 @@ class RunCommand extends Command<typeof runOptions, RunConfig> {
|
|
|
412
441
|
override readonly immediateExecution = false; // Run immediately on selection
|
|
413
442
|
|
|
414
443
|
// Return structured results for display
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
444
|
+
override async execute(config: RunConfig, _execCtx: CommandExecutionContext): Promise<CommandResult> {
|
|
445
|
+
const result = await runTask(config);
|
|
446
|
+
return {
|
|
447
|
+
success: true,
|
|
448
|
+
data: result,
|
|
449
|
+
message: "Task completed",
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
|
|
423
453
|
|
|
424
454
|
// Custom result rendering (React/TSX)
|
|
425
455
|
override renderResult(result: CommandResult): ReactNode {
|
|
@@ -452,7 +482,7 @@ The built-in TUI provides:
|
|
|
452
482
|
- **Command Selector** - Navigate and select commands with arrow keys
|
|
453
483
|
- **Config Form** - Auto-generated forms from option schemas with field groups
|
|
454
484
|
- **Field Editor** - Edit field values (text, number, boolean, enum)
|
|
455
|
-
- **CLI
|
|
485
|
+
- **CLI Args Button** - View equivalent CLI command from the config form
|
|
456
486
|
- **Results Panel** - Display command results with custom rendering
|
|
457
487
|
- **Logs Panel** - View application logs in real-time
|
|
458
488
|
- **Clipboard Support** - Centralized copy with Ctrl+Y
|
|
@@ -464,9 +494,8 @@ The built-in TUI provides:
|
|
|
464
494
|
| Key | Action |
|
|
465
495
|
|-----|--------|
|
|
466
496
|
| ↑/↓ | Navigate fields/commands |
|
|
467
|
-
| Enter | Edit field / Execute command |
|
|
497
|
+
| Enter | Edit field / Execute command / Press button |
|
|
468
498
|
| Tab | Cycle focus between panels |
|
|
469
|
-
| C | Show CLI command modal |
|
|
470
499
|
| L | Toggle logs panel |
|
|
471
500
|
| Ctrl+Y | Copy current content to clipboard |
|
|
472
501
|
| Esc | Back / Cancel running command |
|
|
@@ -486,7 +515,7 @@ import {
|
|
|
486
515
|
useKeyboardHandler, // Register keyboard handlers with priority
|
|
487
516
|
useClipboard, // Clipboard operations with OSC 52
|
|
488
517
|
useLogStream, // Stream logs from logger
|
|
489
|
-
|
|
518
|
+
// (renderer-specific) Spinner UI lives in adapters
|
|
490
519
|
useCommandExecutor, // Execute commands with cancellation
|
|
491
520
|
|
|
492
521
|
// Context
|
|
@@ -494,7 +523,6 @@ import {
|
|
|
494
523
|
KeyboardPriority, // Global < Focused < Modal
|
|
495
524
|
|
|
496
525
|
// Components
|
|
497
|
-
Theme, // TUI color theme
|
|
498
526
|
JsonHighlight, // Syntax-highlighted JSON display
|
|
499
527
|
} from "@pablozaiden/terminatui";
|
|
500
528
|
```
|
|
@@ -504,19 +532,12 @@ import {
|
|
|
504
532
|
Terminatui includes utilities for formatted CLI output:
|
|
505
533
|
|
|
506
534
|
```typescript
|
|
507
|
-
import { colors
|
|
535
|
+
import { colors } from "@pablozaiden/terminatui";
|
|
508
536
|
|
|
509
537
|
// Colors
|
|
510
538
|
console.log(colors.red("Error!"));
|
|
511
539
|
console.log(colors.success("Done!")); // ✓ Done!
|
|
512
540
|
console.log(colors.bold(colors.blue("Title")));
|
|
513
|
-
|
|
514
|
-
// Tables
|
|
515
|
-
console.log(table(data, ["name", "value", "status"]));
|
|
516
|
-
|
|
517
|
-
// Lists
|
|
518
|
-
console.log(bulletList(["Item 1", "Item 2", "Item 3"]));
|
|
519
|
-
console.log(keyValueList({ name: "Test", count: 42 }));
|
|
520
541
|
```
|
|
521
542
|
|
|
522
543
|
## License
|
package/bun.lock
CHANGED
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
"name": "@pablozaiden/terminatui",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"@opentui/react": "0.1.68",
|
|
9
|
+
"ink": "^6.6.0",
|
|
10
|
+
"ink-select-input": "^6.2.0",
|
|
11
|
+
"ink-text-input": "^6.0.0",
|
|
9
12
|
"tslog": "^4.9.3",
|
|
10
13
|
},
|
|
11
14
|
"devDependencies": {
|
|
@@ -19,6 +22,8 @@
|
|
|
19
22
|
},
|
|
20
23
|
},
|
|
21
24
|
"packages": {
|
|
25
|
+
"@alcalzone/ansi-tokenize": ["@alcalzone/ansi-tokenize@0.2.3", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-jsElTJ0sQ4wHRz+C45tfect76BwbTbgkgKByOzpCN9xG61N5V6u/glvg1CsNJhq2xJIFpKHSwG3D2wPPuEYOrQ=="],
|
|
26
|
+
|
|
22
27
|
"@dimforge/rapier2d-simd-compat": ["@dimforge/rapier2d-simd-compat@0.17.3", "", {}, "sha512-bijvwWz6NHsNj5e5i1vtd3dU2pDhthSaTUZSh14DUGGKJfw8eMnlWZsxwHBxB/a3AXVNDjL9abuHw1k9FGR+jg=="],
|
|
23
28
|
|
|
24
29
|
"@jimp/core": ["@jimp/core@1.6.0", "", { "dependencies": { "@jimp/file-ops": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0", "await-to-js": "^3.0.0", "exif-parser": "^0.1.12", "file-type": "^16.0.0", "mime": "3" } }, "sha512-EQQlKU3s9QfdJqiSrZWNTxBs3rKXgO2W+GxNXDtwchF3a4IqxDheFX1ti+Env9hdJXDiYLp2jTRjlxhPthsk8w=="],
|
|
@@ -105,8 +110,16 @@
|
|
|
105
110
|
|
|
106
111
|
"abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="],
|
|
107
112
|
|
|
113
|
+
"ansi-escapes": ["ansi-escapes@7.2.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw=="],
|
|
114
|
+
|
|
115
|
+
"ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
|
116
|
+
|
|
117
|
+
"ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
|
|
118
|
+
|
|
108
119
|
"any-base": ["any-base@1.1.0", "", {}, "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg=="],
|
|
109
120
|
|
|
121
|
+
"auto-bind": ["auto-bind@5.0.1", "", {}, "sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg=="],
|
|
122
|
+
|
|
110
123
|
"await-to-js": ["await-to-js@3.0.0", "", {}, "sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g=="],
|
|
111
124
|
|
|
112
125
|
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
|
@@ -129,32 +142,74 @@
|
|
|
129
142
|
|
|
130
143
|
"bun-webgpu-win32-x64": ["bun-webgpu-win32-x64@0.1.4", "", { "os": "win32", "cpu": "x64" }, "sha512-Z5yAK28xrcm8Wb5k7TZ8FJKpOI/r+aVCRdlHYAqI2SDJFN3nD4mJs900X6kNVmG/xFzb5yOuKVYWGg+6ZXWbyA=="],
|
|
131
144
|
|
|
145
|
+
"chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
|
146
|
+
|
|
147
|
+
"cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="],
|
|
148
|
+
|
|
149
|
+
"cli-cursor": ["cli-cursor@4.0.0", "", { "dependencies": { "restore-cursor": "^4.0.0" } }, "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg=="],
|
|
150
|
+
|
|
151
|
+
"cli-truncate": ["cli-truncate@5.1.1", "", { "dependencies": { "slice-ansi": "^7.1.0", "string-width": "^8.0.0" } }, "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A=="],
|
|
152
|
+
|
|
153
|
+
"code-excerpt": ["code-excerpt@4.0.0", "", { "dependencies": { "convert-to-spaces": "^2.0.1" } }, "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA=="],
|
|
154
|
+
|
|
155
|
+
"convert-to-spaces": ["convert-to-spaces@2.0.1", "", {}, "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ=="],
|
|
156
|
+
|
|
132
157
|
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
|
133
158
|
|
|
134
159
|
"diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="],
|
|
135
160
|
|
|
161
|
+
"emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
|
|
162
|
+
|
|
163
|
+
"environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="],
|
|
164
|
+
|
|
165
|
+
"es-toolkit": ["es-toolkit@1.43.0", "", {}, "sha512-SKCT8AsWvYzBBuUqMk4NPwFlSdqLpJwmy6AP322ERn8W2YLIB6JBXnwMI2Qsh2gfphT3q7EKAxKb23cvFHFwKA=="],
|
|
166
|
+
|
|
167
|
+
"escape-string-regexp": ["escape-string-regexp@2.0.0", "", {}, "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="],
|
|
168
|
+
|
|
136
169
|
"event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="],
|
|
137
170
|
|
|
138
171
|
"events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="],
|
|
139
172
|
|
|
140
173
|
"exif-parser": ["exif-parser@0.1.12", "", {}, "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw=="],
|
|
141
174
|
|
|
175
|
+
"figures": ["figures@6.1.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0" } }, "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg=="],
|
|
176
|
+
|
|
142
177
|
"file-type": ["file-type@16.5.4", "", { "dependencies": { "readable-web-to-node-stream": "^3.0.0", "strtok3": "^6.2.4", "token-types": "^4.1.1" } }, "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw=="],
|
|
143
178
|
|
|
179
|
+
"get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="],
|
|
180
|
+
|
|
144
181
|
"gifwrap": ["gifwrap@0.10.1", "", { "dependencies": { "image-q": "^4.0.0", "omggif": "^1.0.10" } }, "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw=="],
|
|
145
182
|
|
|
146
183
|
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
|
147
184
|
|
|
148
185
|
"image-q": ["image-q@4.0.0", "", { "dependencies": { "@types/node": "16.9.1" } }, "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw=="],
|
|
149
186
|
|
|
187
|
+
"indent-string": ["indent-string@5.0.0", "", {}, "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg=="],
|
|
188
|
+
|
|
189
|
+
"ink": ["ink@6.6.0", "", { "dependencies": { "@alcalzone/ansi-tokenize": "^0.2.1", "ansi-escapes": "^7.2.0", "ansi-styles": "^6.2.1", "auto-bind": "^5.0.1", "chalk": "^5.6.0", "cli-boxes": "^3.0.0", "cli-cursor": "^4.0.0", "cli-truncate": "^5.1.1", "code-excerpt": "^4.0.0", "es-toolkit": "^1.39.10", "indent-string": "^5.0.0", "is-in-ci": "^2.0.0", "patch-console": "^2.0.0", "react-reconciler": "^0.33.0", "signal-exit": "^3.0.7", "slice-ansi": "^7.1.0", "stack-utils": "^2.0.6", "string-width": "^8.1.0", "type-fest": "^4.27.0", "widest-line": "^5.0.0", "wrap-ansi": "^9.0.0", "ws": "^8.18.0", "yoga-layout": "~3.2.1" }, "peerDependencies": { "@types/react": ">=19.0.0", "react": ">=19.0.0", "react-devtools-core": "^6.1.2" }, "optionalPeers": ["@types/react", "react-devtools-core"] }, "sha512-QDt6FgJxgmSxAelcOvOHUvFxbIUjVpCH5bx+Slvc5m7IEcpGt3dYwbz/L+oRnqEGeRvwy1tineKK4ect3nW1vQ=="],
|
|
190
|
+
|
|
191
|
+
"ink-select-input": ["ink-select-input@6.2.0", "", { "dependencies": { "figures": "^6.1.0", "to-rotated": "^1.0.0" }, "peerDependencies": { "ink": ">=5.0.0", "react": ">=18.0.0" } }, "sha512-304fZXxkpYxJ9si5lxRCaX01GNlmPBgOZumXXRnPYbHW/iI31cgQynqk2tRypGLOF1cMIwPUzL2LSm6q4I5rQQ=="],
|
|
192
|
+
|
|
193
|
+
"ink-text-input": ["ink-text-input@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "type-fest": "^4.18.2" }, "peerDependencies": { "ink": ">=5", "react": ">=18" } }, "sha512-Fw64n7Yha5deb1rHY137zHTAbSTNelUKuB5Kkk2HACXEtwIHBCf9OH2tP/LQ9fRYTl1F0dZgbW0zPnZk6FA9Lw=="],
|
|
194
|
+
|
|
195
|
+
"is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="],
|
|
196
|
+
|
|
197
|
+
"is-in-ci": ["is-in-ci@2.0.0", "", { "bin": { "is-in-ci": "cli.js" } }, "sha512-cFeerHriAnhrQSbpAxL37W1wcJKUUX07HyLWZCW1URJT/ra3GyUTzBgUnh24TMVfNTV2Hij2HLxkPHFZfOZy5w=="],
|
|
198
|
+
|
|
199
|
+
"is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="],
|
|
200
|
+
|
|
150
201
|
"jimp": ["jimp@1.6.0", "", { "dependencies": { "@jimp/core": "1.6.0", "@jimp/diff": "1.6.0", "@jimp/js-bmp": "1.6.0", "@jimp/js-gif": "1.6.0", "@jimp/js-jpeg": "1.6.0", "@jimp/js-png": "1.6.0", "@jimp/js-tiff": "1.6.0", "@jimp/plugin-blit": "1.6.0", "@jimp/plugin-blur": "1.6.0", "@jimp/plugin-circle": "1.6.0", "@jimp/plugin-color": "1.6.0", "@jimp/plugin-contain": "1.6.0", "@jimp/plugin-cover": "1.6.0", "@jimp/plugin-crop": "1.6.0", "@jimp/plugin-displace": "1.6.0", "@jimp/plugin-dither": "1.6.0", "@jimp/plugin-fisheye": "1.6.0", "@jimp/plugin-flip": "1.6.0", "@jimp/plugin-hash": "1.6.0", "@jimp/plugin-mask": "1.6.0", "@jimp/plugin-print": "1.6.0", "@jimp/plugin-quantize": "1.6.0", "@jimp/plugin-resize": "1.6.0", "@jimp/plugin-rotate": "1.6.0", "@jimp/plugin-threshold": "1.6.0", "@jimp/types": "1.6.0", "@jimp/utils": "1.6.0" } }, "sha512-YcwCHw1kiqEeI5xRpDlPPBGL2EOpBKLwO4yIBJcXWHPj5PnA5urGq0jbyhM5KoNpypQ6VboSoxc9D8HyfvngSg=="],
|
|
151
202
|
|
|
152
203
|
"jpeg-js": ["jpeg-js@0.4.4", "", {}, "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg=="],
|
|
153
204
|
|
|
154
205
|
"mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="],
|
|
155
206
|
|
|
207
|
+
"mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
|
|
208
|
+
|
|
156
209
|
"omggif": ["omggif@1.0.10", "", {}, "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw=="],
|
|
157
210
|
|
|
211
|
+
"onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
|
|
212
|
+
|
|
158
213
|
"pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="],
|
|
159
214
|
|
|
160
215
|
"parse-bmfont-ascii": ["parse-bmfont-ascii@1.0.6", "", {}, "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA=="],
|
|
@@ -163,6 +218,8 @@
|
|
|
163
218
|
|
|
164
219
|
"parse-bmfont-xml": ["parse-bmfont-xml@1.1.6", "", { "dependencies": { "xml-parse-from-string": "^1.0.0", "xml2js": "^0.5.0" } }, "sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA=="],
|
|
165
220
|
|
|
221
|
+
"patch-console": ["patch-console@2.0.0", "", {}, "sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA=="],
|
|
222
|
+
|
|
166
223
|
"peek-readable": ["peek-readable@4.1.0", "", {}, "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg=="],
|
|
167
224
|
|
|
168
225
|
"pixelmatch": ["pixelmatch@5.3.0", "", { "dependencies": { "pngjs": "^6.0.0" }, "bin": { "pixelmatch": "bin/pixelmatch" } }, "sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q=="],
|
|
@@ -183,6 +240,8 @@
|
|
|
183
240
|
|
|
184
241
|
"readable-web-to-node-stream": ["readable-web-to-node-stream@3.0.4", "", { "dependencies": { "readable-stream": "^4.7.0" } }, "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw=="],
|
|
185
242
|
|
|
243
|
+
"restore-cursor": ["restore-cursor@4.0.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg=="],
|
|
244
|
+
|
|
186
245
|
"safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
|
|
187
246
|
|
|
188
247
|
"sax": ["sax@1.4.4", "", {}, "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw=="],
|
|
@@ -191,22 +250,36 @@
|
|
|
191
250
|
|
|
192
251
|
"shell-quote": ["shell-quote@1.8.3", "", {}, "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw=="],
|
|
193
252
|
|
|
253
|
+
"signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
|
254
|
+
|
|
194
255
|
"simple-xml-to-json": ["simple-xml-to-json@1.2.3", "", {}, "sha512-kWJDCr9EWtZ+/EYYM5MareWj2cRnZGF93YDNpH4jQiHB+hBIZnfPFSQiVMzZOdk+zXWqTZ/9fTeQNu2DqeiudA=="],
|
|
195
256
|
|
|
257
|
+
"slice-ansi": ["slice-ansi@7.1.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w=="],
|
|
258
|
+
|
|
259
|
+
"stack-utils": ["stack-utils@2.0.6", "", { "dependencies": { "escape-string-regexp": "^2.0.0" } }, "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ=="],
|
|
260
|
+
|
|
196
261
|
"stage-js": ["stage-js@1.0.0-alpha.17", "", {}, "sha512-AzlMO+t51v6cFvKZ+Oe9DJnL1OXEH5s9bEy6di5aOrUpcP7PCzI/wIeXF0u3zg0L89gwnceoKxrLId0ZpYnNXw=="],
|
|
197
262
|
|
|
263
|
+
"string-width": ["string-width@8.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.0", "strip-ansi": "^7.1.0" } }, "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg=="],
|
|
264
|
+
|
|
198
265
|
"string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
|
|
199
266
|
|
|
267
|
+
"strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
|
|
268
|
+
|
|
200
269
|
"strtok3": ["strtok3@6.3.0", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "peek-readable": "^4.1.0" } }, "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw=="],
|
|
201
270
|
|
|
202
271
|
"three": ["three@0.177.0", "", {}, "sha512-EiXv5/qWAaGI+Vz2A+JfavwYCMdGjxVsrn3oBwllUoqYeaBO75J63ZfyaQKoiLrqNHoTlUc6PFgMXnS0kI45zg=="],
|
|
203
272
|
|
|
204
273
|
"tinycolor2": ["tinycolor2@1.6.0", "", {}, "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="],
|
|
205
274
|
|
|
275
|
+
"to-rotated": ["to-rotated@1.0.0", "", {}, "sha512-KsEID8AfgUy+pxVRLsWp0VzCa69wxzUDZnzGbyIST/bcgcrMvTYoFBX/QORH4YApoD89EDuUovx4BTdpOn319Q=="],
|
|
276
|
+
|
|
206
277
|
"token-types": ["token-types@4.2.1", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ=="],
|
|
207
278
|
|
|
208
279
|
"tslog": ["tslog@4.10.2", "", {}, "sha512-XuELoRpMR+sq8fuWwX7P0bcj+PRNiicOKDEb3fGNURhxWVyykCi9BNq7c4uVz7h7P0sj8qgBsr5SWS6yBClq3g=="],
|
|
209
280
|
|
|
281
|
+
"type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
|
|
282
|
+
|
|
210
283
|
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
|
211
284
|
|
|
212
285
|
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
|
@@ -215,6 +288,10 @@
|
|
|
215
288
|
|
|
216
289
|
"web-tree-sitter": ["web-tree-sitter@0.25.10", "", { "peerDependencies": { "@types/emscripten": "^1.40.0" }, "optionalPeers": ["@types/emscripten"] }, "sha512-Y09sF44/13XvgVKgO2cNDw5rGk6s26MgoZPXLESvMXeefBf7i6/73eFurre0IsTW6E14Y0ArIzhUMmjoc7xyzA=="],
|
|
217
290
|
|
|
291
|
+
"widest-line": ["widest-line@5.0.0", "", { "dependencies": { "string-width": "^7.0.0" } }, "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA=="],
|
|
292
|
+
|
|
293
|
+
"wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
|
|
294
|
+
|
|
218
295
|
"ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="],
|
|
219
296
|
|
|
220
297
|
"xml-parse-from-string": ["xml-parse-from-string@1.0.1", "", {}, "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g=="],
|
|
@@ -229,8 +306,16 @@
|
|
|
229
306
|
|
|
230
307
|
"image-q/@types/node": ["@types/node@16.9.1", "", {}, "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g=="],
|
|
231
308
|
|
|
309
|
+
"ink/react-reconciler": ["react-reconciler@0.33.0", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.0" } }, "sha512-KetWRytFv1epdpJc3J4G75I4WrplZE5jOL7Yq0p34+OVOKF4Se7WrdIdVC45XsSSmUTlht2FM/fM1FZb1mfQeA=="],
|
|
310
|
+
|
|
232
311
|
"pixelmatch/pngjs": ["pngjs@6.0.0", "", {}, "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg=="],
|
|
233
312
|
|
|
234
313
|
"react-devtools-core/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
|
|
314
|
+
|
|
315
|
+
"widest-line/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
|
316
|
+
|
|
317
|
+
"wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
|
318
|
+
|
|
319
|
+
"ink/react-reconciler/scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
|
|
235
320
|
}
|
|
236
321
|
}
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
type OptionSchema,
|
|
5
|
-
type OptionValues,
|
|
6
|
-
type CommandResult
|
|
7
|
-
} from "../../../../../src/index.ts";
|
|
1
|
+
import { Command, type CommandResult } from "../../../../../src/core/command";
|
|
2
|
+
import { AppContext } from "../../../../../src/core/context";
|
|
3
|
+
import type { OptionSchema, OptionValues } from "../../../../../src/types/command";
|
|
8
4
|
|
|
9
5
|
const options = {
|
|
10
6
|
key: {
|
|
@@ -31,7 +27,7 @@ export class AppGetCommand extends Command<typeof options> {
|
|
|
31
27
|
{ command: "config app get --key logLevel", description: "Get log level" },
|
|
32
28
|
];
|
|
33
29
|
|
|
34
|
-
override async execute(
|
|
30
|
+
override async execute(opts: OptionValues<typeof options>): Promise<CommandResult> {
|
|
35
31
|
// Simulated app config store
|
|
36
32
|
const appConfig: Record<string, string | number | boolean> = {
|
|
37
33
|
port: 3000,
|
|
@@ -44,14 +40,14 @@ export class AppGetCommand extends Command<typeof options> {
|
|
|
44
40
|
const value = appConfig[opts.key];
|
|
45
41
|
|
|
46
42
|
if (value === undefined) {
|
|
47
|
-
|
|
43
|
+
AppContext.current.logger.warn(`Key "${opts.key}" not found in application configuration`);
|
|
48
44
|
return {
|
|
49
45
|
success: false,
|
|
50
46
|
message: `Key "${opts.key}" not found`,
|
|
51
47
|
};
|
|
52
48
|
}
|
|
53
49
|
|
|
54
|
-
|
|
50
|
+
AppContext.current.logger.info(`Retrieved app.${opts.key} = ${value}`);
|
|
55
51
|
return {
|
|
56
52
|
success: true,
|
|
57
53
|
data: { key: opts.key, value },
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Command,
|
|
3
|
-
type AppContext,
|
|
4
|
-
type CommandResult
|
|
5
|
-
} from "../../../../../src/index.ts";
|
|
1
|
+
import { Command, type CommandResult } from "../../../../../src/core/command.ts";
|
|
6
2
|
import { AppGetCommand } from "./get.ts";
|
|
7
3
|
import { AppSetCommand } from "./set.ts";
|
|
8
4
|
|
|
@@ -17,7 +13,7 @@ export class AppConfigCommand extends Command {
|
|
|
17
13
|
new AppSetCommand(),
|
|
18
14
|
];
|
|
19
15
|
|
|
20
|
-
override execute(
|
|
16
|
+
override execute(): CommandResult {
|
|
21
17
|
console.log("Use 'config app <command>' for application configuration.");
|
|
22
18
|
console.log("Available: get, set");
|
|
23
19
|
return { success: true };
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
type OptionSchema,
|
|
5
|
-
type OptionValues,
|
|
6
|
-
type CommandResult
|
|
7
|
-
} from "../../../../../src/index.ts";
|
|
1
|
+
import { Command, type CommandExecutionContext, type CommandResult } from "../../../../../src/core/command";
|
|
2
|
+
import { AppContext } from "../../../../../src/core/context";
|
|
3
|
+
import type { OptionSchema, OptionValues } from "../../../../../src/types/command";
|
|
8
4
|
|
|
9
5
|
const options = {
|
|
10
6
|
key: {
|
|
@@ -49,14 +45,14 @@ export class AppSetCommand extends Command<typeof options> {
|
|
|
49
45
|
{ command: "config app set --key debug --value false --type boolean", description: "Disable debug" },
|
|
50
46
|
];
|
|
51
47
|
|
|
52
|
-
override async execute(
|
|
48
|
+
override async execute(opts: OptionValues<typeof options>, execCtx: CommandExecutionContext): Promise<CommandResult> {
|
|
53
49
|
let parsedValue: string | number | boolean = opts.value;
|
|
54
50
|
|
|
55
51
|
// Parse value based on type
|
|
56
52
|
if (opts.type === "number") {
|
|
57
53
|
parsedValue = Number(opts.value);
|
|
58
54
|
if (isNaN(parsedValue)) {
|
|
59
|
-
|
|
55
|
+
AppContext.current.logger.error(`Invalid number value: "${opts.value}"`);
|
|
60
56
|
return {
|
|
61
57
|
success: false,
|
|
62
58
|
message: `Invalid number: "${opts.value}"`,
|
|
@@ -66,12 +62,26 @@ export class AppSetCommand extends Command<typeof options> {
|
|
|
66
62
|
parsedValue = opts.value.toLowerCase() === "true";
|
|
67
63
|
}
|
|
68
64
|
|
|
69
|
-
|
|
65
|
+
AppContext.current.logger.info(`Setting app.${opts.key} = ${JSON.stringify(parsedValue)}`);
|
|
70
66
|
|
|
71
|
-
|
|
72
|
-
|
|
67
|
+
|
|
68
|
+
// Simulate setting the value on the 5th iteration
|
|
69
|
+
await new Promise(resolve => {
|
|
70
|
+
let count = 0;
|
|
71
|
+
let interval = setInterval(() => {
|
|
72
|
+
count++;
|
|
73
|
+
AppContext.current.logger.info(`Applying configuration... (${count}/5)`);
|
|
74
|
+
if (count >= 5 || execCtx.signal.aborted) {
|
|
75
|
+
if (count < 5) {
|
|
76
|
+
AppContext.current.logger.warn("Configuration update aborted");
|
|
77
|
+
}
|
|
78
|
+
clearInterval(interval);
|
|
79
|
+
resolve(undefined);
|
|
80
|
+
}
|
|
81
|
+
}, 1000);
|
|
82
|
+
});
|
|
73
83
|
|
|
74
|
-
|
|
84
|
+
AppContext.current.logger.info(`Successfully updated application configuration`);
|
|
75
85
|
return {
|
|
76
86
|
success: true,
|
|
77
87
|
data: { key: opts.key, value: parsedValue, type: opts.type },
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Command,
|
|
3
|
-
type AppContext,
|
|
4
|
-
type CommandResult
|
|
5
|
-
} from "../../../../src/index.ts";
|
|
6
1
|
import { UserConfigCommand } from "./user/index.ts";
|
|
7
2
|
import { AppConfigCommand } from "./app/index.ts";
|
|
3
|
+
import { Command, type CommandResult } from "../../../../src/core/command.ts";
|
|
8
4
|
|
|
9
5
|
export class ConfigCommand extends Command {
|
|
10
6
|
readonly name = "config";
|
|
@@ -24,7 +20,7 @@ export class ConfigCommand extends Command {
|
|
|
24
20
|
{ command: "config app set --key debug --value true --type boolean", description: "Enable debug mode" },
|
|
25
21
|
];
|
|
26
22
|
|
|
27
|
-
override execute(
|
|
23
|
+
override execute(): CommandResult {
|
|
28
24
|
console.log("Use 'config <category> <command>' to manage settings.");
|
|
29
25
|
console.log("Categories: user, app");
|
|
30
26
|
return { success: true };
|