ink-cartridge 3.6.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/LICENSE +21 -0
- package/README.md +249 -0
- package/dist/binary-storage/BinaryStorage.d.ts +308 -0
- package/dist/binary-storage/BinaryStorage.js +548 -0
- package/dist/binary-storage/StreamingReader.d.ts +53 -0
- package/dist/binary-storage/StreamingReader.js +530 -0
- package/dist/binary-storage/index.d.ts +91 -0
- package/dist/binary-storage/index.js +91 -0
- package/dist/binary-storage/types.d.ts +400 -0
- package/dist/binary-storage/types.js +15 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +214 -0
- package/dist/cli/initTheme.d.ts +14 -0
- package/dist/cli/initTheme.js +124 -0
- package/dist/cli/makeLanguageType.d.ts +46 -0
- package/dist/cli/makeLanguageType.js +264 -0
- package/dist/cli/makeThemeType.d.ts +43 -0
- package/dist/cli/makeThemeType.js +222 -0
- package/dist/components/badge/Badge.d.ts +7 -0
- package/dist/components/badge/Badge.js +9 -0
- package/dist/components/dialog/ConfirmDialog.d.ts +23 -0
- package/dist/components/dialog/ConfirmDialog.js +57 -0
- package/dist/components/dialog/types.d.ts +20 -0
- package/dist/components/dialog/types.js +1 -0
- package/dist/components/divider/Divider.d.ts +8 -0
- package/dist/components/divider/Divider.js +10 -0
- package/dist/components/fold/Fold.d.ts +3 -0
- package/dist/components/fold/Fold.js +44 -0
- package/dist/components/fold/types.d.ts +28 -0
- package/dist/components/fold/types.js +1 -0
- package/dist/components/form/Field.d.ts +30 -0
- package/dist/components/form/Field.js +59 -0
- package/dist/components/form/Form.d.ts +32 -0
- package/dist/components/form/Form.js +163 -0
- package/dist/components/form/context.d.ts +14 -0
- package/dist/components/form/context.js +20 -0
- package/dist/components/form/types.d.ts +115 -0
- package/dist/components/form/types.js +1 -0
- package/dist/components/key-hint/KeyHint.d.ts +10 -0
- package/dist/components/key-hint/KeyHint.js +12 -0
- package/dist/components/multi-select/MultiSelectInput.d.ts +125 -0
- package/dist/components/multi-select/MultiSelectInput.js +287 -0
- package/dist/components/multi-select/types.d.ts +100 -0
- package/dist/components/multi-select/types.js +1 -0
- package/dist/components/number-input/NumberInput.d.ts +11 -0
- package/dist/components/number-input/NumberInput.js +44 -0
- package/dist/components/progress-bar/ProgressBar.d.ts +11 -0
- package/dist/components/progress-bar/ProgressBar.js +9 -0
- package/dist/components/search-input/SearchInput.d.ts +10 -0
- package/dist/components/search-input/SearchInput.js +15 -0
- package/dist/components/select/SelectInput.d.ts +100 -0
- package/dist/components/select/SelectInput.js +147 -0
- package/dist/components/select/types.d.ts +63 -0
- package/dist/components/select/types.js +1 -0
- package/dist/components/spinner/Spinner.d.ts +12 -0
- package/dist/components/spinner/Spinner.js +24 -0
- package/dist/components/tabs/Tabs.d.ts +3 -0
- package/dist/components/tabs/Tabs.js +57 -0
- package/dist/components/tabs/types.d.ts +32 -0
- package/dist/components/tabs/types.js +1 -0
- package/dist/components/text/TextInput.d.ts +39 -0
- package/dist/components/text/TextInput.js +233 -0
- package/dist/components/text/types.d.ts +62 -0
- package/dist/components/text/types.js +1 -0
- package/dist/dev/dev-screen.d.ts +36 -0
- package/dist/dev/dev-screen.js +142 -0
- package/dist/dev/entrance.d.ts +51 -0
- package/dist/dev/entrance.js +67 -0
- package/dist/dev/globalKey-display.d.ts +2 -0
- package/dist/dev/globalKey-display.js +8 -0
- package/dist/dev/types.d.ts +9 -0
- package/dist/dev/types.js +1 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.js +50 -0
- package/dist/keyboard/check-global-key.d.ts +18 -0
- package/dist/keyboard/check-global-key.js +52 -0
- package/dist/keyboard/context.d.ts +398 -0
- package/dist/keyboard/context.js +9 -0
- package/dist/keyboard/global-key-processor/index.d.ts +16 -0
- package/dist/keyboard/global-key-processor/index.js +75 -0
- package/dist/keyboard/global-sequence-processor/index.d.ts +14 -0
- package/dist/keyboard/global-sequence-processor/index.js +165 -0
- package/dist/keyboard/hook.d.ts +51 -0
- package/dist/keyboard/hook.js +105 -0
- package/dist/keyboard/index.d.ts +5 -0
- package/dist/keyboard/index.js +3 -0
- package/dist/keyboard/keyNormalizer.d.ts +37 -0
- package/dist/keyboard/keyNormalizer.js +119 -0
- package/dist/keyboard/layer-handler.d.ts +57 -0
- package/dist/keyboard/layer-handler.js +274 -0
- package/dist/keyboard/modal-processor/index.d.ts +16 -0
- package/dist/keyboard/modal-processor/index.js +97 -0
- package/dist/keyboard/overlay-processor/index.d.ts +16 -0
- package/dist/keyboard/overlay-processor/index.js +30 -0
- package/dist/keyboard/pipeline/chain.d.ts +10 -0
- package/dist/keyboard/pipeline/chain.js +45 -0
- package/dist/keyboard/pipeline/context.d.ts +34 -0
- package/dist/keyboard/pipeline/context.js +42 -0
- package/dist/keyboard/pipeline/index.d.ts +3 -0
- package/dist/keyboard/pipeline/index.js +2 -0
- package/dist/keyboard/provider.d.ts +32 -0
- package/dist/keyboard/provider.js +985 -0
- package/dist/keyboard/screen-stack-processor/index.d.ts +14 -0
- package/dist/keyboard/screen-stack-processor/index.js +32 -0
- package/dist/keyboard/types.d.ts +632 -0
- package/dist/keyboard/types.js +1 -0
- package/dist/language/context.d.ts +7 -0
- package/dist/language/context.js +7 -0
- package/dist/language/hook.d.ts +19 -0
- package/dist/language/hook.js +26 -0
- package/dist/language/index.d.ts +3 -0
- package/dist/language/index.js +2 -0
- package/dist/language/provider.d.ts +30 -0
- package/dist/language/provider.js +155 -0
- package/dist/language/types.d.ts +124 -0
- package/dist/language/types.js +1 -0
- package/dist/screen/ModalContext.d.ts +11 -0
- package/dist/screen/ModalContext.js +12 -0
- package/dist/screen/OverlayContext.d.ts +9 -0
- package/dist/screen/OverlayContext.js +10 -0
- package/dist/screen/context.d.ts +61 -0
- package/dist/screen/context.js +8 -0
- package/dist/screen/current-screen.d.ts +16 -0
- package/dist/screen/current-screen.js +38 -0
- package/dist/screen/hook.d.ts +13 -0
- package/dist/screen/hook.js +20 -0
- package/dist/screen/index.d.ts +7 -0
- package/dist/screen/index.js +5 -0
- package/dist/screen/provider.d.ts +112 -0
- package/dist/screen/provider.js +577 -0
- package/dist/screen/registry.d.ts +27 -0
- package/dist/screen/registry.js +71 -0
- package/dist/screen/types.d.ts +227 -0
- package/dist/screen/types.js +1 -0
- package/dist/storage/index.d.ts +45 -0
- package/dist/storage/index.js +46 -0
- package/dist/storage/storage.d.ts +139 -0
- package/dist/storage/storage.js +236 -0
- package/dist/storage/types.d.ts +145 -0
- package/dist/storage/types.js +1 -0
- package/dist/theme/context.d.ts +7 -0
- package/dist/theme/context.js +7 -0
- package/dist/theme/hook.d.ts +11 -0
- package/dist/theme/hook.js +18 -0
- package/dist/theme/index.d.ts +4 -0
- package/dist/theme/index.js +2 -0
- package/dist/theme/provider.d.ts +18 -0
- package/dist/theme/provider.js +308 -0
- package/dist/theme/types.d.ts +53 -0
- package/dist/theme/types.js +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { BinaryStorage } from './BinaryStorage.js';
|
|
2
|
+
/**
|
|
3
|
+
* Create a sequential binary storage station.
|
|
4
|
+
*
|
|
5
|
+
* Unlike {@link createStorage} (which is a key-value store backed by
|
|
6
|
+
* JSON), this creates a FIFO binary stream ideal for ordered data
|
|
7
|
+
* where keys are unnecessary overhead:
|
|
8
|
+
*
|
|
9
|
+
* - **Game replay recording** — timestamp, action, position per frame
|
|
10
|
+
* - **Sensor data logging** — time series of numeric readings
|
|
11
|
+
* - **Chat / event logs** — append-only sequential messages
|
|
12
|
+
* - **Checkpoint chains** — ordered snapshots of application state
|
|
13
|
+
*
|
|
14
|
+
* ## How it works
|
|
15
|
+
*
|
|
16
|
+
* Each value written to the stream is encoded with a 1-byte type tag
|
|
17
|
+
* followed by its payload. Reading consumes values in the same order.
|
|
18
|
+
* This guarantees type safety at the individual value level — if you
|
|
19
|
+
* call `read.num()` on a position that contains a string, you get an
|
|
20
|
+
* immediate error with the exact byte offset.
|
|
21
|
+
*
|
|
22
|
+
* The read and write cursors are independent, so you can write a
|
|
23
|
+
* sequence, `resetRead()`, and replay it immediately — all from
|
|
24
|
+
* memory, no disk I/O needed.
|
|
25
|
+
*
|
|
26
|
+
* ## Binary format
|
|
27
|
+
*
|
|
28
|
+
* ```
|
|
29
|
+
* [1 byte TypeTag] [payload...]
|
|
30
|
+
*
|
|
31
|
+
* Number: [0x01] [8 bytes float64 LE]
|
|
32
|
+
* String: [0x02] [4 bytes uint32 LE length] [UTF-8 bytes]
|
|
33
|
+
* Boolean: [0x03] [1 byte: 0x00=false, 0x01=true]
|
|
34
|
+
* Object: [0x04] [4 bytes uint32 LE length] [JSON UTF-8 bytes]
|
|
35
|
+
* Array: [0x05] [4 bytes uint32 LE length] [JSON UTF-8 bytes]
|
|
36
|
+
* Null: [0x06]
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* @param options Optional directory, file name, and flush behaviour.
|
|
40
|
+
* @returns A typed binary storage API with positional read/write
|
|
41
|
+
* cursors and full seek/truncate support.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* import { createBinaryStorage } from 'ink-cartridge';
|
|
46
|
+
*
|
|
47
|
+
* const bin = createBinaryStorage({ file: 'replay.bin' });
|
|
48
|
+
*
|
|
49
|
+
* // ── Recording phase ──
|
|
50
|
+
* await bin.write.num(Date.now()); // timestamp
|
|
51
|
+
* await bin.write.str('attack'); // action
|
|
52
|
+
* await bin.write.num(120); // damage
|
|
53
|
+
* await bin.write.b(true); // critical hit
|
|
54
|
+
*
|
|
55
|
+
* // ── Playback phase ──
|
|
56
|
+
* bin.resetRead();
|
|
57
|
+
* while (bin.tellRead() < bin.tellWrite()) {
|
|
58
|
+
* const ts = await bin.read.num();
|
|
59
|
+
* const action = await bin.read.str();
|
|
60
|
+
* const damage = await bin.read.num();
|
|
61
|
+
* const crit = await bin.read.b();
|
|
62
|
+
* console.log(`${ts}: ${action} for ${damage} (crit=${crit})`);
|
|
63
|
+
* }
|
|
64
|
+
*
|
|
65
|
+
* // ── Bookmarking ──
|
|
66
|
+
* bin.resetRead();
|
|
67
|
+
* await bin.read.num(); // skip timestamp
|
|
68
|
+
* const pos = bin.tellRead();
|
|
69
|
+
* // ... later ...
|
|
70
|
+
* bin.seekRead(pos); // re-read from action
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* @throws Never throws during construction. Read errors (type
|
|
74
|
+
* mismatch, end of stream) are thrown as Promise rejections.
|
|
75
|
+
* Write errors from the filesystem propagate as standard
|
|
76
|
+
* Node.js exceptions.
|
|
77
|
+
*/
|
|
78
|
+
export function createBinaryStorage(options) {
|
|
79
|
+
return new BinaryStorage(options);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Low-level exports for advanced use cases.
|
|
83
|
+
*
|
|
84
|
+
* `TypeTag` is the numeric enum of type markers (0x01–0x06).
|
|
85
|
+
* `TAG_NAMES` maps each tag to its human-readable name.
|
|
86
|
+
*
|
|
87
|
+
* These are useful if you need to inspect or manipulate binary
|
|
88
|
+
* storage files outside the normal read/write API.
|
|
89
|
+
*/
|
|
90
|
+
export { TAG_NAMES } from './types.js';
|
|
91
|
+
export { createStreamingReader, StreamCorruptError } from './StreamingReader.js';
|
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for {@link createBinaryStorage}.
|
|
3
|
+
*
|
|
4
|
+
* All properties are optional — defaults make `createBinaryStorage()` work
|
|
5
|
+
* with zero arguments, creating a `./data/storage.bin` file.
|
|
6
|
+
*/
|
|
7
|
+
export interface BinaryStorageOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Directory where the binary file lives.
|
|
10
|
+
*
|
|
11
|
+
* Relative paths are resolved against `process.cwd()`.
|
|
12
|
+
* The directory (and any missing parents) are created automatically
|
|
13
|
+
* on construction via `fs.mkdirSync(dir, { recursive: true })`.
|
|
14
|
+
*
|
|
15
|
+
* @default './data'
|
|
16
|
+
*/
|
|
17
|
+
dir?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Name of the binary file backing this storage station.
|
|
20
|
+
*
|
|
21
|
+
* Use the `.bin` extension by convention, but any extension works.
|
|
22
|
+
*
|
|
23
|
+
* @default 'storage.bin'
|
|
24
|
+
*/
|
|
25
|
+
file?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Whether to persist writes to disk after each operation.
|
|
28
|
+
*
|
|
29
|
+
* When `false`, written values are buffered in memory.
|
|
30
|
+
* Use {@link BinaryStorageAPI.write.flush} to manually
|
|
31
|
+
* persist the buffer at any time.
|
|
32
|
+
*
|
|
33
|
+
* This is the same pattern as {@link StorageOptions.flush} —
|
|
34
|
+
* batch mode avoids redundant disk I/O when writing many
|
|
35
|
+
* values in quick succession.
|
|
36
|
+
*
|
|
37
|
+
* @default true
|
|
38
|
+
*/
|
|
39
|
+
flush?: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Type tags — a 1-byte prefix before every value in the binary file.
|
|
43
|
+
*
|
|
44
|
+
* Each value in the binary file starts with one of these tags,
|
|
45
|
+
* followed by the type-specific payload. This enables the read
|
|
46
|
+
* methods to:
|
|
47
|
+
*
|
|
48
|
+
* 1. **Validate** that the next value matches expectations
|
|
49
|
+
* (a `read.num()` on a string position throws immediately).
|
|
50
|
+
* 2. **Skip** unknown values via `read.any()` which auto-detects
|
|
51
|
+
* the type from the tag.
|
|
52
|
+
* 3. **Detect corruption** — an unknown tag byte means the file
|
|
53
|
+
* is damaged or was written by a newer version.
|
|
54
|
+
*
|
|
55
|
+
* Tags are stored as `const enum` so they are inlined as numeric
|
|
56
|
+
* literals at compile time — zero runtime overhead.
|
|
57
|
+
*
|
|
58
|
+
* ```
|
|
59
|
+
* Byte layout for each value:
|
|
60
|
+
*
|
|
61
|
+
* [1 byte tag] [payload...]
|
|
62
|
+
*
|
|
63
|
+
* Number: [0x01] [8 bytes float64 LE]
|
|
64
|
+
* String: [0x02] [4 bytes uint32 LE length] [UTF-8 bytes]
|
|
65
|
+
* Boolean: [0x03] [1 byte: 0x00=false, 0x01=true]
|
|
66
|
+
* Object: [0x04] [4 bytes uint32 LE length] [JSON UTF-8 bytes]
|
|
67
|
+
* Array: [0x05] [4 bytes uint32 LE length] [JSON UTF-8 bytes]
|
|
68
|
+
* Null: [0x06]
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export declare const enum TypeTag {
|
|
72
|
+
/** IEEE 754 double-precision float, little-endian. 8 bytes. */
|
|
73
|
+
Number = 1,
|
|
74
|
+
/** UTF-8 encoded string with 4-byte little-endian length prefix. */
|
|
75
|
+
String = 2,
|
|
76
|
+
/** Single byte: `0x00` = false, `0x01` = true. */
|
|
77
|
+
Boolean = 3,
|
|
78
|
+
/** JSON-serialised object stored as a length-prefixed UTF-8 string. */
|
|
79
|
+
Object = 4,
|
|
80
|
+
/** JSON-serialised array stored as a length-prefixed UTF-8 string. */
|
|
81
|
+
Array = 5,
|
|
82
|
+
/** Sentinel for null/undefined. No payload bytes. */
|
|
83
|
+
Null = 6
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Options for {@link createStreamingReader}.
|
|
87
|
+
*
|
|
88
|
+
* All properties are optional — defaults are tuned for large files
|
|
89
|
+
* (1 GB+) with a 50 MB memory budget.
|
|
90
|
+
*/
|
|
91
|
+
export interface StreamingReaderOptions {
|
|
92
|
+
/**
|
|
93
|
+
* Maximum number of parsed values to buffer in the internal queue
|
|
94
|
+
* before pausing the underlying file stream (backpressure).
|
|
95
|
+
*
|
|
96
|
+
* @default 1000
|
|
97
|
+
*/
|
|
98
|
+
maxQueueSize?: number;
|
|
99
|
+
/**
|
|
100
|
+
* Passed through to `fs.createReadStream` as `highWaterMark`.
|
|
101
|
+
*
|
|
102
|
+
* This controls the size (in bytes) of each chunk read from disk.
|
|
103
|
+
* Larger values reduce `fs.read` syscall count but increase
|
|
104
|
+
* per-chunk memory. The default 64 KiB balances both.
|
|
105
|
+
*
|
|
106
|
+
* @default 65536 (64 KiB)
|
|
107
|
+
*/
|
|
108
|
+
highWaterMark?: number;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The streaming reader API returned by {@link createStreamingReader}.
|
|
112
|
+
*
|
|
113
|
+
* Unlike {@link BinaryStorageAPI} (which loads the entire file into
|
|
114
|
+
* memory), this reads values sequentially from disk via a Node.js
|
|
115
|
+
* `ReadStream`. Values are parsed one at a time and returned in
|
|
116
|
+
* complete batches — the user never sees partial / truncated data.
|
|
117
|
+
*
|
|
118
|
+
* ## Lifecycle
|
|
119
|
+
*
|
|
120
|
+
* 1. Call `createStreamingReader(filePath, options?)` to open the file.
|
|
121
|
+
* 2. Use `readBatch(count)` for manual batching or `for await` for
|
|
122
|
+
* per-value iteration.
|
|
123
|
+
* 3. Call `destroy()` when done (or let the async iterator finish).
|
|
124
|
+
*
|
|
125
|
+
* The underlying file stream is automatically closed on end-of-file
|
|
126
|
+
* or error. Calling `destroy()` is idempotent and safe from any
|
|
127
|
+
* state.
|
|
128
|
+
*/
|
|
129
|
+
export interface StreamingReaderAPI {
|
|
130
|
+
/**
|
|
131
|
+
* Read up to `count` complete values from the file.
|
|
132
|
+
*
|
|
133
|
+
* Returns fewer than `count` values only when the file has been
|
|
134
|
+
* fully consumed. The returned array is empty (`[]`) when there is
|
|
135
|
+
* no more data.
|
|
136
|
+
*
|
|
137
|
+
* Each element in the array is a fully decoded value — you never
|
|
138
|
+
* need to handle partial bytes or incomplete records.
|
|
139
|
+
*
|
|
140
|
+
* @param count — Maximum number of values to return.
|
|
141
|
+
* @returns An array of decoded values (number, string, boolean,
|
|
142
|
+
* object, array, or null), or `[]` at end-of-stream.
|
|
143
|
+
* @throws If the file is corrupt (unknown tag, truncated payload).
|
|
144
|
+
*/
|
|
145
|
+
readBatch(count: number): Promise<unknown[]>;
|
|
146
|
+
/**
|
|
147
|
+
* Close the underlying file stream and release all resources.
|
|
148
|
+
*
|
|
149
|
+
* After calling `destroy()`:
|
|
150
|
+
* - Any pending `readBatch()` call is rejected.
|
|
151
|
+
* - The async iterator stops immediately.
|
|
152
|
+
* - The file descriptor is closed — no leak.
|
|
153
|
+
*
|
|
154
|
+
* Idempotent: calling `destroy()` multiple times is safe.
|
|
155
|
+
*/
|
|
156
|
+
destroy(): void;
|
|
157
|
+
/**
|
|
158
|
+
* Async iterable protocol — iterate over every value one by one.
|
|
159
|
+
*
|
|
160
|
+
* ```ts
|
|
161
|
+
* for await (const value of reader) {
|
|
162
|
+
* console.log(value);
|
|
163
|
+
* }
|
|
164
|
+
* ```
|
|
165
|
+
*
|
|
166
|
+
* The iteration ends naturally when the file is fully consumed.
|
|
167
|
+
* Errors (corruption, truncation) are thrown inside the loop body
|
|
168
|
+
* and stop the iterator.
|
|
169
|
+
*/
|
|
170
|
+
[Symbol.asyncIterator](): AsyncIterator<unknown>;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Human-readable name for each type tag.
|
|
174
|
+
*
|
|
175
|
+
* Used in error messages so that instead of
|
|
176
|
+
* "expected 0x01, got 0x02" the user sees
|
|
177
|
+
* "Expected number, got string".
|
|
178
|
+
*/
|
|
179
|
+
export declare const TAG_NAMES: Record<TypeTag, string>;
|
|
180
|
+
/**
|
|
181
|
+
* The public API returned by {@link createBinaryStorage}.
|
|
182
|
+
*
|
|
183
|
+
* All writes are serialised through an internal promise chain,
|
|
184
|
+
* so concurrent `write.*()` calls are safe. Reads are asynchronous
|
|
185
|
+
* but execute synchronously from an in-memory buffer — the
|
|
186
|
+
* `Promise` wrapper exists for API consistency with the key-value
|
|
187
|
+
* {@link StorageAPI}.
|
|
188
|
+
*
|
|
189
|
+
* Values are consumed by `read.*()` exactly once: after reading,
|
|
190
|
+
* the internal cursor advances past the consumed value. Use
|
|
191
|
+
* `resetRead()` or `seekRead()` to re-read from a known position.
|
|
192
|
+
*/
|
|
193
|
+
export interface BinaryStorageAPI {
|
|
194
|
+
/**
|
|
195
|
+
* Typed write methods — append values to the end of the stream.
|
|
196
|
+
*
|
|
197
|
+
* Each method is internally queued, so you can fire multiple
|
|
198
|
+
* writes without `await` and they will execute in order.
|
|
199
|
+
*/
|
|
200
|
+
write: {
|
|
201
|
+
/**
|
|
202
|
+
* Append a number.
|
|
203
|
+
*
|
|
204
|
+
* Stored as IEEE 754 float64 little-endian (8 bytes).
|
|
205
|
+
* Supports all JS number values including `Infinity`,
|
|
206
|
+
* `-Infinity`, and `NaN`.
|
|
207
|
+
*/
|
|
208
|
+
num(value: number): Promise<void>;
|
|
209
|
+
/**
|
|
210
|
+
* Append a string.
|
|
211
|
+
*
|
|
212
|
+
* Stored with a 4-byte uint32 LE length prefix followed by
|
|
213
|
+
* the UTF-8 encoded bytes. Supports empty strings and
|
|
214
|
+
* multi-byte characters (emoji, CJK, etc.).
|
|
215
|
+
*/
|
|
216
|
+
str(value: string): Promise<void>;
|
|
217
|
+
/**
|
|
218
|
+
* Append a boolean.
|
|
219
|
+
*
|
|
220
|
+
* Stored as a single byte: `0x00` for `false`,
|
|
221
|
+
* `0x01` for `true`.
|
|
222
|
+
*/
|
|
223
|
+
b(value: boolean): Promise<void>;
|
|
224
|
+
/**
|
|
225
|
+
* Append an object (generic — preserves the type for reads).
|
|
226
|
+
*
|
|
227
|
+
* The object is JSON-serialised and stored with the `Object`
|
|
228
|
+
* type tag (0x04). On read, it is JSON-parsed back to the
|
|
229
|
+
* generic type `T`.
|
|
230
|
+
*/
|
|
231
|
+
obj<T extends object>(value: T): Promise<void>;
|
|
232
|
+
/**
|
|
233
|
+
* Append an array (generic — preserves the element type for reads).
|
|
234
|
+
*
|
|
235
|
+
* The array is JSON-serialised and stored with the `Array`
|
|
236
|
+
* type tag (0x05). On read, it is JSON-parsed back to `T[]`.
|
|
237
|
+
*/
|
|
238
|
+
arr<T>(value: T[]): Promise<void>;
|
|
239
|
+
/**
|
|
240
|
+
* Append any value, auto-detecting its type.
|
|
241
|
+
*
|
|
242
|
+
* Type detection follows `typeof` + `Array.isArray`:
|
|
243
|
+
* number → `TypeTag.Number`, string → `TypeTag.String`,
|
|
244
|
+
* boolean → `TypeTag.Boolean`, null/undefined → `TypeTag.Null`,
|
|
245
|
+
* Array → `TypeTag.Array`, object → `TypeTag.Object`.
|
|
246
|
+
*/
|
|
247
|
+
any(value: unknown): Promise<void>;
|
|
248
|
+
/**
|
|
249
|
+
* Append a null sentinel (`TypeTag.Null`, no payload).
|
|
250
|
+
*/
|
|
251
|
+
null(): Promise<void>;
|
|
252
|
+
/**
|
|
253
|
+
* Force-persist the in-memory write buffer to disk.
|
|
254
|
+
*
|
|
255
|
+
* Normally you don't need this — when `flush: true` (default),
|
|
256
|
+
* every write auto-flushes. Use this when you created the
|
|
257
|
+
* station with `flush: false` for batch writes.
|
|
258
|
+
*
|
|
259
|
+
* This always writes regardless of the `flush` option.
|
|
260
|
+
*/
|
|
261
|
+
flush(): Promise<void>;
|
|
262
|
+
};
|
|
263
|
+
/**
|
|
264
|
+
* Typed read methods — consume values sequentially.
|
|
265
|
+
*
|
|
266
|
+
* Each method reads the 1-byte type tag, validates it against
|
|
267
|
+
* the expected type, then reads and returns the payload.
|
|
268
|
+
* Throws if the type tag doesn't match or if there is no more
|
|
269
|
+
* data to read (end of stream).
|
|
270
|
+
*/
|
|
271
|
+
read: {
|
|
272
|
+
/**
|
|
273
|
+
* Read the next number.
|
|
274
|
+
*
|
|
275
|
+
* @throws If the next value is not a number (type mismatch).
|
|
276
|
+
* @throws If there is no more data (end of stream).
|
|
277
|
+
*/
|
|
278
|
+
num(): Promise<number>;
|
|
279
|
+
/**
|
|
280
|
+
* Read the next string.
|
|
281
|
+
*
|
|
282
|
+
* @throws If the next value is not a string (type mismatch).
|
|
283
|
+
* @throws If there is no more data (end of stream).
|
|
284
|
+
*/
|
|
285
|
+
str(): Promise<string>;
|
|
286
|
+
/**
|
|
287
|
+
* Read the next boolean.
|
|
288
|
+
*
|
|
289
|
+
* @throws If the next value is not a boolean (type mismatch).
|
|
290
|
+
* @throws If there is no more data (end of stream).
|
|
291
|
+
*/
|
|
292
|
+
b(): Promise<boolean>;
|
|
293
|
+
/**
|
|
294
|
+
* Read the next object (parsed from JSON).
|
|
295
|
+
*
|
|
296
|
+
* @typeParam T — The expected shape of the object.
|
|
297
|
+
* @throws If the next value is not an object (type mismatch).
|
|
298
|
+
* @throws If there is no more data (end of stream).
|
|
299
|
+
*/
|
|
300
|
+
obj<T extends object>(): Promise<T>;
|
|
301
|
+
/**
|
|
302
|
+
* Read the next array (parsed from JSON).
|
|
303
|
+
*
|
|
304
|
+
* @typeParam T — The expected element type.
|
|
305
|
+
* @throws If the next value is not an array (type mismatch).
|
|
306
|
+
* @throws If there is no more data (end of stream).
|
|
307
|
+
*/
|
|
308
|
+
arr<T>(): Promise<T[]>;
|
|
309
|
+
/**
|
|
310
|
+
* Read the next value and return it, auto-detecting the type
|
|
311
|
+
* from the tag byte.
|
|
312
|
+
*
|
|
313
|
+
* This is the universal read method — it accepts any type.
|
|
314
|
+
* Use it when you don't know the next value's type ahead of
|
|
315
|
+
* time (e.g. reading a mixed-type stream written with
|
|
316
|
+
* `write.any()`).
|
|
317
|
+
*
|
|
318
|
+
* @returns The value: number, string, boolean, object, array,
|
|
319
|
+
* or null.
|
|
320
|
+
* @throws If there is no more data (end of stream).
|
|
321
|
+
* @throws If the type tag is unknown (corrupt file).
|
|
322
|
+
*/
|
|
323
|
+
any(): Promise<unknown>;
|
|
324
|
+
};
|
|
325
|
+
/**
|
|
326
|
+
* Current read-cursor position in bytes.
|
|
327
|
+
*
|
|
328
|
+
* This is the byte offset from the beginning of the file
|
|
329
|
+
* where the next `read.*()` call will start reading.
|
|
330
|
+
*
|
|
331
|
+
* Use this together with `seekRead()` to bookmark positions:
|
|
332
|
+
*
|
|
333
|
+
* ```ts
|
|
334
|
+
* const bookmark = bin.tellRead();
|
|
335
|
+
* // ... read some values ...
|
|
336
|
+
* bin.seekRead(bookmark); // back to bookmarked position
|
|
337
|
+
* ```
|
|
338
|
+
*/
|
|
339
|
+
tellRead(): number;
|
|
340
|
+
/**
|
|
341
|
+
* Current write-cursor position in bytes.
|
|
342
|
+
*
|
|
343
|
+
* This equals the total number of bytes written so far
|
|
344
|
+
* (including both flushed and unflushed data). It is
|
|
345
|
+
* always `>= tellRead()`.
|
|
346
|
+
*
|
|
347
|
+
* When reading a stream, `tellRead() < tellWrite()`
|
|
348
|
+
* means there are still unread values.
|
|
349
|
+
*/
|
|
350
|
+
tellWrite(): number;
|
|
351
|
+
/**
|
|
352
|
+
* Move the read cursor to an absolute byte offset.
|
|
353
|
+
*
|
|
354
|
+
* The position must be within `[0, tellWrite()]`.
|
|
355
|
+
*
|
|
356
|
+
* @throws If `pos` is out of range.
|
|
357
|
+
*
|
|
358
|
+
* **Warning:** No validation is performed on whether `pos`
|
|
359
|
+
* aligns to a value boundary. If you seek to the middle of a
|
|
360
|
+
* value, the next `read.*()` call will read garbage and likely
|
|
361
|
+
* throw a type-mismatch or corrupt-file error. Always seek to
|
|
362
|
+
* positions previously recorded with `tellRead()` or
|
|
363
|
+
* `tellWrite()`.
|
|
364
|
+
*/
|
|
365
|
+
seekRead(pos: number): void;
|
|
366
|
+
/**
|
|
367
|
+
* Move the write cursor and truncate data beyond this point.
|
|
368
|
+
*
|
|
369
|
+
* This is how you implement "undo": seek the write cursor
|
|
370
|
+
* back to a previously recorded position, and everything
|
|
371
|
+
* written after that point is discarded permanently.
|
|
372
|
+
*
|
|
373
|
+
* If the read cursor is past the new write position, it is
|
|
374
|
+
* clamped to the write position automatically.
|
|
375
|
+
*
|
|
376
|
+
* This operation is serialised (queued) and triggers a flush.
|
|
377
|
+
*
|
|
378
|
+
* @throws If `pos < 0`.
|
|
379
|
+
*/
|
|
380
|
+
seekWrite(pos: number): Promise<void>;
|
|
381
|
+
/**
|
|
382
|
+
* Reset the read cursor to the beginning of the stream.
|
|
383
|
+
*
|
|
384
|
+
* Equivalent to `seekRead(0)`. Useful for replaying data:
|
|
385
|
+
* write a sequence, then `resetRead()` to consume it from
|
|
386
|
+
* the start.
|
|
387
|
+
*/
|
|
388
|
+
resetRead(): void;
|
|
389
|
+
/**
|
|
390
|
+
* Truncate the file at the current read cursor position.
|
|
391
|
+
*
|
|
392
|
+
* All data from the read cursor onward is discarded.
|
|
393
|
+
* This is a convenience shorthand for
|
|
394
|
+
* `seekWrite(tellRead())`.
|
|
395
|
+
*
|
|
396
|
+
* Typical use case: after consuming (reading) values you
|
|
397
|
+
* no longer need, call `truncate()` to reclaim disk space.
|
|
398
|
+
*/
|
|
399
|
+
truncate(): Promise<void>;
|
|
400
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Human-readable name for each type tag.
|
|
3
|
+
*
|
|
4
|
+
* Used in error messages so that instead of
|
|
5
|
+
* "expected 0x01, got 0x02" the user sees
|
|
6
|
+
* "Expected number, got string".
|
|
7
|
+
*/
|
|
8
|
+
export const TAG_NAMES = {
|
|
9
|
+
[1 /* TypeTag.Number */]: 'number',
|
|
10
|
+
[2 /* TypeTag.String */]: 'string',
|
|
11
|
+
[3 /* TypeTag.Boolean */]: 'boolean',
|
|
12
|
+
[4 /* TypeTag.Object */]: 'object',
|
|
13
|
+
[5 /* TypeTag.Array */]: 'array',
|
|
14
|
+
[6 /* TypeTag.Null */]: 'null',
|
|
15
|
+
};
|