@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 +335 -0
- package/dist/browser/index.cjs +696 -0
- package/dist/browser/index.cjs.map +1 -0
- package/dist/browser/index.d.cts +232 -0
- package/dist/browser/index.d.ts +232 -0
- package/dist/browser/index.js +686 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/index.cjs +435 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +329 -0
- package/dist/index.d.ts +329 -0
- package/dist/index.js +364 -0
- package/dist/index.js.map +1 -0
- package/dist/node/index.cjs +827 -0
- package/dist/node/index.cjs.map +1 -0
- package/dist/node/index.d.cts +235 -0
- package/dist/node/index.d.ts +235 -0
- package/dist/node/index.js +790 -0
- package/dist/node/index.js.map +1 -0
- package/dist/types-FB6TYMn5.d.cts +443 -0
- package/dist/types-FB6TYMn5.d.ts +443 -0
- package/package.json +95 -0
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
|