@boba-cli/machine 0.1.0-alpha.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/README.md ADDED
@@ -0,0 +1,335 @@
1
+ # @boba-cli/machine
2
+
3
+ Platform abstraction layer for Boba terminal UIs. This package enables Boba applications to run in both Node.js and browser environments (with xterm.js) by providing platform-agnostic interfaces for terminal I/O, clipboard access, environment detection, and signal handling.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @boba-cli/machine
9
+ ```
10
+
11
+ ### Optional Peer Dependencies
12
+
13
+ For Node.js usage:
14
+
15
+ ```bash
16
+ npm install clipboardy supports-color archiver unzipper
17
+ ```
18
+
19
+ For browser usage:
20
+
21
+ ```bash
22
+ npm install @xterm/xterm
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ ### Node.js
28
+
29
+ ```typescript
30
+ import { createNodePlatform } from '@boba-cli/machine/node'
31
+
32
+ const platform = createNodePlatform()
33
+
34
+ // Subscribe to terminal input
35
+ const inputDisposable = platform.terminal.onInput((data) => {
36
+ console.log('Received:', data)
37
+ })
38
+
39
+ // Write to terminal
40
+ platform.terminal.write('Hello, World!\n')
41
+
42
+ // Get terminal size
43
+ const { columns, rows } = platform.terminal.getSize()
44
+
45
+ // Enable raw mode for key-by-key input
46
+ platform.terminal.enableRawMode()
47
+
48
+ // Handle signals
49
+ platform.signals.onInterrupt(() => {
50
+ console.log('Interrupted!')
51
+ platform.dispose()
52
+ })
53
+
54
+ // Read from clipboard
55
+ const text = await platform.clipboard.read()
56
+
57
+ // Detect color support
58
+ const colorSupport = platform.environment.getColorSupport()
59
+ if (colorSupport.has16m) {
60
+ // Use true color
61
+ }
62
+
63
+ // Create zip archive (requires archiver package)
64
+ if (platform.archive.isAvailable()) {
65
+ await platform.archive.zip('/path/to/source', '/path/to/output.zip')
66
+ }
67
+
68
+ // Extract zip archive (requires unzipper package)
69
+ if (platform.archive.isAvailable()) {
70
+ await platform.archive.unzip('/path/to/archive.zip', '/path/to/output')
71
+ }
72
+
73
+ // File system operations
74
+ const content = await platform.filesystem.readFile('/path/to/file.txt')
75
+ await platform.filesystem.writeFile('/path/to/output.txt', 'Hello!')
76
+ const exists = await platform.filesystem.exists('/path/to/file.txt')
77
+
78
+ // Path operations
79
+ const fullPath = platform.path.join('dir', 'subdir', 'file.txt')
80
+ const baseName = platform.path.basename('/path/to/file.txt') // 'file.txt'
81
+ const dirName = platform.path.dirname('/path/to/file.txt') // '/path/to'
82
+
83
+ // Terminal styling
84
+ const { style } = platform.style
85
+ console.log(style.red.bold('Error!'))
86
+ console.log(style.green('Success'))
87
+ console.log(style.blue.underline('Link'))
88
+
89
+ // Clean up when done
90
+ platform.dispose()
91
+ ```
92
+
93
+ ### Browser (with xterm.js)
94
+
95
+ ```typescript
96
+ import { Terminal } from '@xterm/xterm'
97
+ import { createBrowserPlatform } from '@boba-cli/machine/browser'
98
+
99
+ // Create xterm.js terminal
100
+ const terminal = new Terminal()
101
+ terminal.open(document.getElementById('terminal')!)
102
+
103
+ // Create platform adapter
104
+ const platform = createBrowserPlatform({ terminal })
105
+
106
+ // Use the same API as Node.js
107
+ platform.terminal.onInput((data) => {
108
+ // Handle input
109
+ })
110
+
111
+ platform.terminal.write('Hello from the browser!')
112
+
113
+ // Clean up
114
+ platform.dispose()
115
+ ```
116
+
117
+ ### Platform-Agnostic Code
118
+
119
+ Write code that works on both platforms:
120
+
121
+ ```typescript
122
+ import type { PlatformAdapter } from '@boba-cli/machine'
123
+
124
+ function runApp(platform: PlatformAdapter) {
125
+ const { columns, rows } = platform.terminal.getSize()
126
+
127
+ platform.terminal.onInput((data) => {
128
+ // Handle input bytes
129
+ })
130
+
131
+ platform.terminal.onResize((size) => {
132
+ // Handle resize
133
+ })
134
+
135
+ platform.terminal.write(`Terminal size: ${columns}x${rows}\n`)
136
+ }
137
+ ```
138
+
139
+ ## Byte Utilities
140
+
141
+ The package provides cross-platform byte utilities as a replacement for Node.js `Buffer`:
142
+
143
+ ```typescript
144
+ import {
145
+ encodeString,
146
+ decodeString,
147
+ byteLength,
148
+ concatBytes,
149
+ decodeFirstRune,
150
+ } from '@boba-cli/machine'
151
+
152
+ // Encode string to UTF-8 bytes
153
+ const bytes = encodeString('Hello, 世界!')
154
+
155
+ // Decode bytes to string
156
+ const text = decodeString(bytes)
157
+
158
+ // Get byte length of a string
159
+ const len = byteLength('Hello') // 5
160
+
161
+ // Concatenate byte arrays
162
+ const combined = concatBytes(bytes1, bytes2, bytes3)
163
+
164
+ // Decode first UTF-8 character
165
+ const [char, byteLen] = decodeFirstRune(bytes)
166
+ ```
167
+
168
+ ## ANSI Escape Sequences
169
+
170
+ Platform-agnostic ANSI escape sequence constants and utilities:
171
+
172
+ ```typescript
173
+ import {
174
+ CURSOR_SHOW,
175
+ CURSOR_HIDE,
176
+ CLEAR_SCREEN,
177
+ ALT_SCREEN_ON,
178
+ ALT_SCREEN_OFF,
179
+ cursorTo,
180
+ fgRGB,
181
+ bgRGB,
182
+ setWindowTitle,
183
+ } from '@boba-cli/machine'
184
+
185
+ // Use constants directly
186
+ terminal.write(CURSOR_HIDE)
187
+ terminal.write(CLEAR_SCREEN)
188
+ terminal.write(ALT_SCREEN_ON)
189
+
190
+ // Use utility functions
191
+ terminal.write(cursorTo(10, 5))
192
+ terminal.write(fgRGB(255, 128, 64))
193
+ terminal.write(setWindowTitle('My App'))
194
+ ```
195
+
196
+ ## API Reference
197
+
198
+ ### Interfaces
199
+
200
+ #### `PlatformAdapter`
201
+
202
+ Complete platform adapter combining all platform-specific functionality:
203
+
204
+ - `terminal: TerminalAdapter` - Terminal I/O adapter
205
+ - `signals: SignalAdapter` - Signal handling adapter
206
+ - `clipboard: ClipboardAdapter` - Clipboard operations adapter
207
+ - `environment: EnvironmentAdapter` - Environment access adapter
208
+ - `filesystem: FileSystemAdapter` - File system operations adapter
209
+ - `path: PathAdapter` - Path operations adapter
210
+ - `archive: ArchiveAdapter` - Archive (zip/unzip) operations adapter
211
+ - `style: StyleAdapter` - Terminal text styling adapter
212
+ - `dispose(): void` - Clean up all resources
213
+
214
+ #### `TerminalAdapter`
215
+
216
+ Terminal I/O interface:
217
+
218
+ - `onInput(handler): Disposable` - Subscribe to input data
219
+ - `onResize(handler): Disposable` - Subscribe to resize events
220
+ - `write(data: string): void` - Write to terminal output
221
+ - `getSize(): TerminalSize` - Get current terminal dimensions
222
+ - `enableRawMode(): void` - Enable raw input mode
223
+ - `disableRawMode(): void` - Disable raw input mode
224
+ - `isTTY(): boolean` - Check if terminal is a TTY
225
+
226
+ #### `SignalAdapter`
227
+
228
+ Signal handling interface:
229
+
230
+ - `onInterrupt(handler): Disposable` - Handle SIGINT/beforeunload
231
+ - `onTerminate(handler): Disposable` - Handle SIGTERM/pagehide
232
+
233
+ #### `ClipboardAdapter`
234
+
235
+ Clipboard operations interface:
236
+
237
+ - `read(): Promise<string>` - Read text from clipboard
238
+ - `write(text: string): Promise<void>` - Write text to clipboard
239
+ - `isAvailable(): boolean` - Check if clipboard is available
240
+
241
+ #### `EnvironmentAdapter`
242
+
243
+ Environment access interface:
244
+
245
+ - `get(name: string): string | undefined` - Get environment variable
246
+ - `getColorSupport(): ColorSupport` - Detect color support level
247
+ - `getTerminalBackground(): TerminalBackground` - Detect dark/light mode
248
+
249
+ #### `FileSystemAdapter`
250
+
251
+ File system operations interface:
252
+
253
+ - `readdir(path, options?): Promise<DirectoryEntry[] | string[]>` - Read directory contents
254
+ - `stat(path): Promise<FileStat>` - Get file/directory stats
255
+ - `readFile(path, encoding?): Promise<string>` - Read file contents as text
256
+ - `writeFile(path, content): Promise<void>` - Write text to a file
257
+ - `exists(path): Promise<boolean>` - Check if path exists
258
+ - `mkdir(path, options?): Promise<void>` - Create directory
259
+ - `unlink(path): Promise<void>` - Delete file
260
+ - `rmdir(path, options?): Promise<void>` - Remove directory
261
+ - `rename(src, dst): Promise<void>` - Rename/move file or directory
262
+ - `copyFile(src, dst): Promise<void>` - Copy file
263
+ - `cwd(): string` - Get current working directory
264
+ - `homedir(): string` - Get user's home directory
265
+
266
+ #### `PathAdapter`
267
+
268
+ Path operations interface:
269
+
270
+ - `join(...segments): string` - Join path segments
271
+ - `dirname(path): string` - Get directory name
272
+ - `basename(path, ext?): string` - Get base name
273
+ - `extname(path): string` - Get file extension
274
+ - `resolve(...segments): string` - Resolve to absolute path
275
+ - `isAbsolute(path): boolean` - Check if path is absolute
276
+ - `normalize(path): string` - Normalize path
277
+ - `sep: string` - Platform-specific path separator
278
+
279
+ #### `ArchiveAdapter`
280
+
281
+ Archive operations interface:
282
+
283
+ - `zip(sourceDir, destPath): Promise<void>` - Create zip archive from directory
284
+ - `unzip(archivePath, destDir): Promise<void>` - Extract zip archive
285
+ - `isAvailable(): boolean` - Check if archiving is supported
286
+
287
+ **Note:** Archive operations require the `archiver` and `unzipper` packages to be installed in Node.js environments. Browser environments do not support archive operations.
288
+
289
+ #### `StyleAdapter`
290
+
291
+ Terminal text styling interface:
292
+
293
+ - `style: StyleFn` - Chainable style function
294
+ - `enabled: boolean` - Whether styling is enabled
295
+ - `level: number` - Color support level (0-3)
296
+
297
+ ### Types
298
+
299
+ #### `TerminalSize`
300
+
301
+ ```typescript
302
+ interface TerminalSize {
303
+ readonly columns: number
304
+ readonly rows: number
305
+ }
306
+ ```
307
+
308
+ #### `ColorSupport`
309
+
310
+ ```typescript
311
+ interface ColorSupport {
312
+ readonly level: number // 0-3
313
+ readonly hasBasic: boolean // 16 colors
314
+ readonly has256: boolean // 256 colors
315
+ readonly has16m: boolean // True color (16 million)
316
+ }
317
+ ```
318
+
319
+ #### `TerminalBackground`
320
+
321
+ ```typescript
322
+ type TerminalBackground = 'dark' | 'light' | 'unknown'
323
+ ```
324
+
325
+ ## Exports
326
+
327
+ The package has three entry points:
328
+
329
+ - `@boba-cli/machine` - Core interfaces, byte utilities, and ANSI sequences
330
+ - `@boba-cli/machine/node` - Node.js adapter implementations
331
+ - `@boba-cli/machine/browser` - Browser/xterm.js adapter implementations
332
+
333
+ ## License
334
+
335
+ MIT