@pablozaiden/terminatui 0.1.2 → 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.
Files changed (175) hide show
  1. package/AGENTS.md +43 -0
  2. package/CLAUDE.md +1 -0
  3. package/README.md +64 -43
  4. package/bun.lock +85 -0
  5. package/examples/tui-app/commands/config/app/get.ts +62 -0
  6. package/examples/tui-app/commands/config/app/index.ts +23 -0
  7. package/examples/tui-app/commands/config/app/set.ts +96 -0
  8. package/examples/tui-app/commands/config/index.ts +28 -0
  9. package/examples/tui-app/commands/config/user/get.ts +61 -0
  10. package/examples/tui-app/commands/config/user/index.ts +23 -0
  11. package/examples/tui-app/commands/config/user/set.ts +57 -0
  12. package/examples/tui-app/commands/greet.ts +14 -11
  13. package/examples/tui-app/commands/math.ts +6 -9
  14. package/examples/tui-app/commands/status.ts +24 -13
  15. package/examples/tui-app/index.ts +7 -3
  16. package/guides/01-hello-world.md +7 -2
  17. package/guides/02-adding-options.md +2 -2
  18. package/guides/03-multiple-commands.md +6 -8
  19. package/guides/04-subcommands.md +8 -8
  20. package/guides/05-interactive-tui.md +45 -30
  21. package/guides/06-config-validation.md +4 -12
  22. package/guides/07-async-cancellation.md +15 -69
  23. package/guides/08-complete-application.md +13 -179
  24. package/guides/README.md +7 -3
  25. package/package.json +4 -8
  26. package/src/__tests__/application.test.ts +87 -68
  27. package/src/__tests__/buildCliCommand.test.ts +99 -119
  28. package/src/__tests__/builtins.test.ts +27 -75
  29. package/src/__tests__/command.test.ts +100 -131
  30. package/src/__tests__/context.test.ts +1 -26
  31. package/src/__tests__/helpCore.test.ts +227 -0
  32. package/src/__tests__/parser.test.ts +98 -244
  33. package/src/__tests__/registry.test.ts +33 -160
  34. package/src/__tests__/schemaToFields.test.ts +75 -158
  35. package/src/builtins/help.ts +19 -4
  36. package/src/builtins/settings.ts +18 -32
  37. package/src/builtins/version.ts +4 -4
  38. package/src/cli/output/colors.ts +1 -1
  39. package/src/cli/parser.ts +26 -95
  40. package/src/core/application.ts +192 -110
  41. package/src/core/command.ts +26 -9
  42. package/src/core/context.ts +31 -20
  43. package/src/core/help.ts +24 -18
  44. package/src/core/knownCommands.ts +13 -0
  45. package/src/core/logger.ts +39 -42
  46. package/src/core/registry.ts +5 -12
  47. package/src/tui/TuiApplication.tsx +63 -120
  48. package/src/tui/TuiRoot.tsx +135 -0
  49. package/src/tui/adapters/factory.ts +19 -0
  50. package/src/tui/adapters/ink/InkRenderer.tsx +135 -0
  51. package/src/tui/adapters/ink/components/Button.tsx +12 -0
  52. package/src/tui/adapters/ink/components/Code.tsx +6 -0
  53. package/src/tui/adapters/ink/components/CodeHighlight.tsx +6 -0
  54. package/src/tui/adapters/ink/components/Container.tsx +5 -0
  55. package/src/tui/adapters/ink/components/Field.tsx +12 -0
  56. package/src/tui/adapters/ink/components/Label.tsx +24 -0
  57. package/src/tui/adapters/ink/components/MenuButton.tsx +12 -0
  58. package/src/tui/adapters/ink/components/MenuItem.tsx +17 -0
  59. package/src/tui/adapters/ink/components/Overlay.tsx +5 -0
  60. package/src/tui/adapters/ink/components/Panel.tsx +15 -0
  61. package/src/tui/adapters/ink/components/ScrollView.tsx +5 -0
  62. package/src/tui/adapters/ink/components/Select.tsx +44 -0
  63. package/src/tui/adapters/ink/components/Spacer.tsx +15 -0
  64. package/src/tui/adapters/ink/components/Spinner.tsx +5 -0
  65. package/src/tui/adapters/ink/components/TextInput.tsx +22 -0
  66. package/src/tui/adapters/ink/components/Value.tsx +7 -0
  67. package/src/tui/adapters/ink/keyboard.ts +97 -0
  68. package/src/tui/adapters/ink/utils.ts +16 -0
  69. package/src/tui/adapters/opentui/OpenTuiRenderer.tsx +115 -0
  70. package/src/tui/adapters/opentui/components/Button.tsx +13 -0
  71. package/src/tui/adapters/opentui/components/Code.tsx +12 -0
  72. package/src/tui/adapters/opentui/components/CodeHighlight.tsx +24 -0
  73. package/src/tui/adapters/opentui/components/Container.tsx +56 -0
  74. package/src/tui/adapters/opentui/components/Field.tsx +18 -0
  75. package/src/tui/adapters/opentui/components/Label.tsx +15 -0
  76. package/src/tui/adapters/opentui/components/MenuButton.tsx +14 -0
  77. package/src/tui/adapters/opentui/components/MenuItem.tsx +29 -0
  78. package/src/tui/adapters/opentui/components/Overlay.tsx +21 -0
  79. package/src/tui/adapters/opentui/components/Panel.tsx +78 -0
  80. package/src/tui/adapters/opentui/components/ScrollView.tsx +85 -0
  81. package/src/tui/adapters/opentui/components/Select.tsx +59 -0
  82. package/src/tui/adapters/opentui/components/Spacer.tsx +5 -0
  83. package/src/tui/adapters/opentui/components/Spinner.tsx +12 -0
  84. package/src/tui/adapters/opentui/components/TextInput.tsx +13 -0
  85. package/src/tui/adapters/opentui/components/Value.tsx +13 -0
  86. package/src/tui/{hooks → adapters/opentui/hooks}/useSpinner.ts +2 -11
  87. package/src/tui/adapters/opentui/keyboard.ts +61 -0
  88. package/src/tui/adapters/types.ts +70 -0
  89. package/src/tui/components/ActionButton.tsx +0 -36
  90. package/src/tui/components/CommandSelector.tsx +52 -92
  91. package/src/tui/components/ConfigForm.tsx +68 -42
  92. package/src/tui/components/FieldRow.tsx +0 -30
  93. package/src/tui/components/Header.tsx +14 -13
  94. package/src/tui/components/JsonHighlight.tsx +10 -17
  95. package/src/tui/components/ModalBase.tsx +38 -0
  96. package/src/tui/components/ResultsPanel.tsx +27 -36
  97. package/src/tui/components/StatusBar.tsx +24 -39
  98. package/src/tui/components/logColors.ts +12 -0
  99. package/src/tui/context/ClipboardContext.tsx +87 -0
  100. package/src/tui/context/ExecutorContext.tsx +139 -0
  101. package/src/tui/context/KeyboardContext.tsx +85 -71
  102. package/src/tui/context/LogsContext.tsx +35 -0
  103. package/src/tui/context/NavigationContext.tsx +194 -0
  104. package/src/tui/context/RendererContext.tsx +20 -0
  105. package/src/tui/context/TuiAppContext.tsx +58 -0
  106. package/src/tui/hooks/useActiveKeyHandler.ts +75 -0
  107. package/src/tui/hooks/useBackHandler.ts +34 -0
  108. package/src/tui/hooks/useClipboard.ts +40 -25
  109. package/src/tui/hooks/useClipboardProvider.ts +42 -0
  110. package/src/tui/hooks/useGlobalKeyHandler.ts +54 -0
  111. package/src/tui/modals/CliModal.tsx +82 -0
  112. package/src/tui/modals/EditorModal.tsx +207 -0
  113. package/src/tui/modals/LogsModal.tsx +98 -0
  114. package/src/tui/registry.ts +102 -0
  115. package/src/tui/screens/CommandSelectScreen.tsx +162 -0
  116. package/src/tui/screens/ConfigScreen.tsx +160 -0
  117. package/src/tui/screens/ErrorScreen.tsx +58 -0
  118. package/src/tui/screens/ResultsScreen.tsx +60 -0
  119. package/src/tui/screens/RunningScreen.tsx +72 -0
  120. package/src/tui/screens/ScreenBase.ts +6 -0
  121. package/src/tui/semantic/Button.tsx +7 -0
  122. package/src/tui/semantic/Code.tsx +7 -0
  123. package/src/tui/semantic/CodeHighlight.tsx +7 -0
  124. package/src/tui/semantic/Container.tsx +7 -0
  125. package/src/tui/semantic/Field.tsx +7 -0
  126. package/src/tui/semantic/Label.tsx +7 -0
  127. package/src/tui/semantic/MenuButton.tsx +7 -0
  128. package/src/tui/semantic/MenuItem.tsx +7 -0
  129. package/src/tui/semantic/Overlay.tsx +7 -0
  130. package/src/tui/semantic/Panel.tsx +7 -0
  131. package/src/tui/semantic/ScrollView.tsx +9 -0
  132. package/src/tui/semantic/Select.tsx +7 -0
  133. package/src/tui/semantic/Spacer.tsx +7 -0
  134. package/src/tui/semantic/Spinner.tsx +7 -0
  135. package/src/tui/semantic/TextInput.tsx +7 -0
  136. package/src/tui/semantic/Value.tsx +7 -0
  137. package/src/tui/semantic/types.ts +195 -0
  138. package/src/tui/theme.ts +25 -14
  139. package/src/tui/utils/buildCliCommand.ts +1 -0
  140. package/src/tui/utils/getEnumKeys.ts +3 -0
  141. package/src/tui/utils/parameterPersistence.ts +1 -0
  142. package/src/types/command.ts +0 -60
  143. package/examples/tui-app/commands/index.ts +0 -3
  144. package/src/__tests__/colors.test.ts +0 -127
  145. package/src/__tests__/commandClass.test.ts +0 -130
  146. package/src/__tests__/help.test.ts +0 -412
  147. package/src/__tests__/registryNew.test.ts +0 -160
  148. package/src/__tests__/table.test.ts +0 -146
  149. package/src/__tests__/tui.test.ts +0 -26
  150. package/src/builtins/index.ts +0 -4
  151. package/src/cli/help.ts +0 -174
  152. package/src/cli/index.ts +0 -3
  153. package/src/cli/output/index.ts +0 -2
  154. package/src/cli/output/table.ts +0 -141
  155. package/src/commands/help.ts +0 -50
  156. package/src/commands/index.ts +0 -1
  157. package/src/components/index.ts +0 -147
  158. package/src/core/index.ts +0 -15
  159. package/src/hooks/index.ts +0 -131
  160. package/src/index.ts +0 -137
  161. package/src/registry/commandRegistry.ts +0 -77
  162. package/src/registry/index.ts +0 -1
  163. package/src/tui/TuiApp.tsx +0 -582
  164. package/src/tui/app.ts +0 -29
  165. package/src/tui/components/CliModal.tsx +0 -81
  166. package/src/tui/components/EditorModal.tsx +0 -177
  167. package/src/tui/components/LogsPanel.tsx +0 -86
  168. package/src/tui/components/index.ts +0 -13
  169. package/src/tui/context/index.ts +0 -7
  170. package/src/tui/hooks/index.ts +0 -35
  171. package/src/tui/hooks/useKeyboardHandler.ts +0 -91
  172. package/src/tui/hooks/useLogStream.ts +0 -96
  173. package/src/tui/index.ts +0 -65
  174. package/src/tui/utils/index.ts +0 -13
  175. package/src/types/index.ts +0 -1
@@ -149,12 +149,9 @@ export class NotificationService {
149
149
  Create `src/commands/add.ts`:
150
150
 
151
151
  ```typescript
152
- import React from "react";
153
- import { Text, Box } from "ink";
154
152
  import {
155
153
  Command,
156
154
  ConfigValidationError,
157
- type AppContext,
158
155
  type OptionSchema,
159
156
  type OptionValues,
160
157
  type CommandResult,
@@ -192,15 +189,10 @@ export class AddCommand extends Command<typeof options, AddConfig> {
192
189
  readonly options = options;
193
190
  readonly displayName = "Add Task";
194
191
  readonly actionLabel = "Create Task";
195
- readonly group = "Tasks";
196
- readonly order = 1;
197
192
 
198
193
  private db = new Database();
199
194
 
200
- override buildConfig(
201
- _ctx: AppContext,
202
- opts: OptionValues<typeof options>
203
- ): AddConfig {
195
+ override buildConfig(opts: OptionValues<typeof options>): AddConfig {
204
196
  const title = (opts["title"] as string)?.trim();
205
197
  if (!title) {
206
198
  throw new ConfigValidationError("Task title cannot be empty", "title");
@@ -217,13 +209,11 @@ export class AddCommand extends Command<typeof options, AddConfig> {
217
209
  return { title, priority };
218
210
  }
219
211
 
220
- async execute(ctx: AppContext, config: AddConfig): Promise<CommandResult> {
221
- ctx.logger.debug(`Creating task: ${config.title}`);
222
-
212
+ async execute(config: AddConfig): Promise<CommandResult> {
223
213
  const task = await this.db.addTask(config.title, config.priority);
224
-
225
- const notifications = new NotificationService(ctx.logger);
226
- notifications.taskAdded(task);
214
+
215
+ // (Example) optional: log to console or your own logger
216
+ console.log(`Created task: ${task.title}`);
227
217
 
228
218
  return {
229
219
  success: true,
@@ -231,52 +221,14 @@ export class AddCommand extends Command<typeof options, AddConfig> {
231
221
  message: `Created task: ${task.title} (${task.id})`,
232
222
  };
233
223
  }
234
-
235
- override renderResult(result: CommandResult): React.ReactNode {
236
- if (!result.success) {
237
- return <Text color="red">✗ {result.message}</Text>;
238
- }
239
-
240
- const task = result.data as Task;
241
- const priorityColor = {
242
- high: "red",
243
- medium: "yellow",
244
- low: "green",
245
- }[task.priority] as "red" | "yellow" | "green";
246
-
247
- return (
248
- <Box flexDirection="column" gap={1}>
249
- <Text color="green">✓ Task Created</Text>
250
- <Box>
251
- <Text dimColor>ID: </Text>
252
- <Text>{task.id}</Text>
253
- </Box>
254
- <Box>
255
- <Text dimColor>Title: </Text>
256
- <Text>{task.title}</Text>
257
- </Box>
258
- <Box>
259
- <Text dimColor>Priority: </Text>
260
- <Text color={priorityColor}>{task.priority}</Text>
261
- </Box>
262
- </Box>
263
- );
264
- }
265
-
266
- override getClipboardContent(result: CommandResult): string | undefined {
267
- return result.data?.id;
268
- }
269
224
  }
270
225
  ```
271
226
 
272
227
  Create `src/commands/list.ts`:
273
228
 
274
229
  ```typescript
275
- import React from "react";
276
- import { Text, Box } from "ink";
277
230
  import {
278
231
  Command,
279
- type AppContext,
280
232
  type OptionSchema,
281
233
  type OptionValues,
282
234
  type CommandResult,
@@ -311,27 +263,20 @@ export class ListCommand extends Command<typeof options, ListConfig> {
311
263
  readonly options = options;
312
264
  readonly displayName = "List Tasks";
313
265
  readonly actionLabel = "Show Tasks";
314
- readonly group = "Tasks";
315
- readonly order = 2;
316
266
 
317
267
  // Execute immediately when selected in TUI
318
268
  readonly immediateExecution = true;
319
269
 
320
270
  private db = new Database();
321
271
 
322
- override buildConfig(
323
- _ctx: AppContext,
324
- opts: OptionValues<typeof options>
325
- ): ListConfig {
272
+ override buildConfig(opts: OptionValues<typeof options>): ListConfig {
326
273
  return {
327
274
  filter: (opts["filter"] as ListConfig["filter"]) ?? "all",
328
275
  priority: opts["priority"] as Task["priority"] | undefined,
329
276
  };
330
277
  }
331
278
 
332
- async execute(ctx: AppContext, config: ListConfig): Promise<CommandResult> {
333
- ctx.logger.debug(`Listing tasks: filter=${config.filter}`);
334
-
279
+ async execute(config: ListConfig): Promise<CommandResult> {
335
280
  let tasks = await this.db.listTasks(config.filter);
336
281
 
337
282
  if (config.priority) {
@@ -344,49 +289,15 @@ export class ListCommand extends Command<typeof options, ListConfig> {
344
289
  message: `Found ${tasks.length} tasks`,
345
290
  };
346
291
  }
347
-
348
- override renderResult(result: CommandResult): React.ReactNode {
349
- const tasks = (result.data as Task[]) ?? [];
350
-
351
- if (tasks.length === 0) {
352
- return <Text dimColor>No tasks found</Text>;
353
- }
354
-
355
- const priorityColor = (p: string) =>
356
- ({ high: "red", medium: "yellow", low: "green" })[p] as "red" | "yellow" | "green";
357
-
358
- return (
359
- <Box flexDirection="column" gap={1}>
360
- <Text bold>Tasks ({tasks.length})</Text>
361
- {tasks.map((task) => (
362
- <Box key={task.id} gap={2}>
363
- <Text dimColor>[{task.id}]</Text>
364
- <Text color={task.status === "completed" ? "gray" : undefined}>
365
- {task.status === "completed" ? "✓" : "○"} {task.title}
366
- </Text>
367
- <Text color={priorityColor(task.priority)}>{task.priority}</Text>
368
- </Box>
369
- ))}
370
- </Box>
371
- );
372
- }
373
-
374
- override getClipboardContent(result: CommandResult): string | undefined {
375
- const tasks = result.data as Task[];
376
- return tasks?.map((t) => `${t.id}: ${t.title}`).join("\n");
377
- }
378
292
  }
379
293
  ```
380
294
 
381
295
  Create `src/commands/complete.ts`:
382
296
 
383
297
  ```typescript
384
- import React from "react";
385
- import { Text, Box } from "ink";
386
298
  import {
387
299
  Command,
388
300
  ConfigValidationError,
389
- type AppContext,
390
301
  type OptionSchema,
391
302
  type OptionValues,
392
303
  type CommandResult,
@@ -414,15 +325,10 @@ export class CompleteCommand extends Command<typeof options, CompleteConfig> {
414
325
  readonly options = options;
415
326
  readonly displayName = "Complete Task";
416
327
  readonly actionLabel = "Mark Complete";
417
- readonly group = "Tasks";
418
- readonly order = 3;
419
328
 
420
329
  private db = new Database();
421
330
 
422
- override buildConfig(
423
- _ctx: AppContext,
424
- opts: OptionValues<typeof options>
425
- ): CompleteConfig {
331
+ override buildConfig(opts: OptionValues<typeof options>): CompleteConfig {
426
332
  const id = opts["id"] as string;
427
333
  if (!id?.trim()) {
428
334
  throw new ConfigValidationError("Task ID is required", "id");
@@ -430,11 +336,9 @@ export class CompleteCommand extends Command<typeof options, CompleteConfig> {
430
336
  return { id: id.trim() };
431
337
  }
432
338
 
433
- async execute(ctx: AppContext, config: CompleteConfig): Promise<CommandResult> {
434
- ctx.logger.debug(`Completing task: ${config.id}`);
435
-
339
+ async execute(config: CompleteConfig): Promise<CommandResult> {
436
340
  const task = await this.db.completeTask(config.id);
437
-
341
+
438
342
  if (!task) {
439
343
  return {
440
344
  success: false,
@@ -442,8 +346,7 @@ export class CompleteCommand extends Command<typeof options, CompleteConfig> {
442
346
  };
443
347
  }
444
348
 
445
- const notifications = new NotificationService(ctx.logger);
446
- notifications.taskCompleted(task);
349
+ console.log(`Completed task: ${task.title}`);
447
350
 
448
351
  return {
449
352
  success: true,
@@ -451,34 +354,14 @@ export class CompleteCommand extends Command<typeof options, CompleteConfig> {
451
354
  message: `Completed: ${task.title}`,
452
355
  };
453
356
  }
454
-
455
- override renderResult(result: CommandResult): React.ReactNode {
456
- if (!result.success) {
457
- return <Text color="red">✗ {result.message}</Text>;
458
- }
459
-
460
- const task = result.data as Task;
461
- return (
462
- <Box flexDirection="column">
463
- <Text color="green">✓ Task Completed</Text>
464
- <Text>{task.title}</Text>
465
- <Text dimColor>
466
- Completed at: {task.completedAt?.toLocaleString()}
467
- </Text>
468
- </Box>
469
- );
470
- }
471
357
  }
472
358
  ```
473
359
 
474
360
  Create `src/commands/stats.ts`:
475
361
 
476
362
  ```typescript
477
- import React from "react";
478
- import { Text, Box } from "ink";
479
363
  import {
480
364
  Command,
481
- type AppContext,
482
365
  type OptionSchema,
483
366
  type CommandResult,
484
367
  } from "@pablozaiden/terminatui";
@@ -493,15 +376,11 @@ export class StatsCommand extends Command<typeof options> {
493
376
  readonly options = options;
494
377
  readonly displayName = "Statistics";
495
378
  readonly actionLabel = "Show Stats";
496
- readonly group = "Analytics";
497
- readonly order = 1;
498
379
  readonly immediateExecution = true;
499
380
 
500
381
  private db = new Database();
501
382
 
502
- async execute(ctx: AppContext): Promise<CommandResult> {
503
- ctx.logger.debug("Fetching statistics");
504
-
383
+ async execute(): Promise<CommandResult> {
505
384
  const stats = await this.db.getStats();
506
385
 
507
386
  return {
@@ -510,50 +389,6 @@ export class StatsCommand extends Command<typeof options> {
510
389
  message: `Total: ${stats.total}, Pending: ${stats.pending}, Completed: ${stats.completed}`,
511
390
  };
512
391
  }
513
-
514
- override renderResult(result: CommandResult): React.ReactNode {
515
- const stats = result.data as TaskStats;
516
-
517
- const completionRate = stats.total > 0
518
- ? Math.round((stats.completed / stats.total) * 100)
519
- : 0;
520
-
521
- return (
522
- <Box flexDirection="column" gap={1}>
523
- <Text bold>📊 Task Statistics</Text>
524
-
525
- <Box flexDirection="column">
526
- <Box gap={2}>
527
- <Text dimColor>Total:</Text>
528
- <Text>{stats.total}</Text>
529
- </Box>
530
- <Box gap={2}>
531
- <Text dimColor>Pending:</Text>
532
- <Text color="yellow">{stats.pending}</Text>
533
- </Box>
534
- <Box gap={2}>
535
- <Text dimColor>Completed:</Text>
536
- <Text color="green">{stats.completed}</Text>
537
- </Box>
538
- <Box gap={2}>
539
- <Text dimColor>Completion Rate:</Text>
540
- <Text color={completionRate >= 50 ? "green" : "yellow"}>
541
- {completionRate}%
542
- </Text>
543
- </Box>
544
- </Box>
545
-
546
- <Box flexDirection="column" marginTop={1}>
547
- <Text bold>By Priority:</Text>
548
- <Box gap={2}>
549
- <Text color="red">High: {stats.byPriority.high}</Text>
550
- <Text color="yellow">Medium: {stats.byPriority.medium}</Text>
551
- <Text color="green">Low: {stats.byPriority.low}</Text>
552
- </Box>
553
- </Box>
554
- </Box>
555
- );
556
- }
557
392
  }
558
393
  ```
559
394
 
@@ -647,7 +482,6 @@ bun start --verbose add "Debug task" --priority low
647
482
  | Display Names | `displayName = "Add Task"` |
648
483
  | Action Labels | `actionLabel = "Create Task"` |
649
484
  | Immediate Execution | `immediateExecution = true` |
650
- | Custom Results | `renderResult()` |
651
485
  | Clipboard Support | `getClipboardContent()` |
652
486
 
653
487
  ## What You Learned
@@ -655,7 +489,7 @@ bun start --verbose add "Debug task" --priority low
655
489
  - **Project Structure**: Organize code into commands, services, types
656
490
  - **Shared Services**: Database and notification services
657
491
  - **Command Groups**: Organize commands in TUI sidebar
658
- - **Full TUI Integration**: Custom rendering, clipboard, immediate execution
492
+ - **Full TUI Integration**: Clipboard, immediate execution
659
493
  - **Lifecycle Hooks**: `onBeforeRun` and `onAfterRun`
660
494
  - **Production Patterns**: Error handling, validation, logging
661
495
 
package/guides/README.md CHANGED
@@ -36,7 +36,7 @@ bun add @pablozaiden/terminatui
36
36
 
37
37
  # Create your first command
38
38
  cat > src/index.ts << 'EOF'
39
- import { Command, Application, type AppContext, type OptionSchema } from "@pablozaiden/terminatui";
39
+ import { Command, Application, type OptionSchema } from "@pablozaiden/terminatui";
40
40
 
41
41
  const options = {
42
42
  name: { type: "string", description: "Your name" },
@@ -47,7 +47,7 @@ class HelloCommand extends Command<typeof options> {
47
47
  readonly description = "Say hello";
48
48
  readonly options = options;
49
49
 
50
- async execute(ctx: AppContext, config: Record<string, unknown>) {
50
+ async execute(config: Record<string, unknown>) {
51
51
  const name = config["name"] ?? "World";
52
52
  console.log(`Hello, ${name}!`);
53
53
  return { success: true };
@@ -60,7 +60,11 @@ class MyCLI extends Application {
60
60
  }
61
61
  }
62
62
 
63
+ // Recommended: let Terminatui read `Bun.argv.slice(2)`
63
64
  await new MyCLI().run();
65
+
66
+ // For tests or programmatic invocation:
67
+ // await new MyCLI().runFromArgs(["hello", "--name", "Developer"]);
64
68
  EOF
65
69
 
66
70
  # Run it
@@ -69,6 +73,6 @@ bun src/index.ts hello --name "Developer"
69
73
 
70
74
  ## Prerequisites
71
75
 
72
- - [Bun](https://bun.sh) or Node.js 18+
76
+ - [Bun](https://bun.sh)
73
77
  - Basic TypeScript knowledge
74
78
  - Terminal/command-line familiarity
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pablozaiden/terminatui",
3
- "version": "0.1.2",
3
+ "version": "0.3.0-beta-1",
4
4
  "description": "Terminal UI and Command Line Application Framework",
5
5
  "repository": {
6
6
  "url": "https://github.com/PabloZaiden/terminatui"
@@ -8,13 +8,6 @@
8
8
  "type": "module",
9
9
  "main": "src/index.ts",
10
10
  "types": "src/index.ts",
11
- "exports": {
12
- ".": "./src/index.ts",
13
- "./cli": "./src/cli/index.ts",
14
- "./tui": "./src/tui/index.ts",
15
- "./components": "./src/components/index.ts",
16
- "./hooks": "./src/hooks/index.ts"
17
- },
18
11
  "scripts": {
19
12
  "build": "bunx tsc --noEmit",
20
13
  "test": "bun test",
@@ -22,6 +15,9 @@
22
15
  },
23
16
  "dependencies": {
24
17
  "@opentui/react": "0.1.68",
18
+ "ink": "^6.6.0",
19
+ "ink-select-input": "^6.2.0",
20
+ "ink-text-input": "^6.0.0",
25
21
  "tslog": "^4.9.3"
26
22
  },
27
23
  "devDependencies": {