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,236 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* A key-value storage station backed by a single JSON file.
|
|
5
|
+
*
|
|
6
|
+
* Each instance manages one JSON file on disk. All read/write operations
|
|
7
|
+
* are asynchronous and serialised internally — concurrent callers never
|
|
8
|
+
* interleave. The file is loaded lazily on the first access, and writes
|
|
9
|
+
* use atomic rename (write to `.tmp` then rename) to prevent data
|
|
10
|
+
* corruption from partial writes or crashes.
|
|
11
|
+
*
|
|
12
|
+
* Instances are created via {@link createStorage}, not directly.
|
|
13
|
+
*/
|
|
14
|
+
export class Storage {
|
|
15
|
+
options;
|
|
16
|
+
data = null;
|
|
17
|
+
pending = Promise.resolve();
|
|
18
|
+
filePath;
|
|
19
|
+
constructor(options) {
|
|
20
|
+
this.options = {
|
|
21
|
+
dir: options?.dir ?? './data',
|
|
22
|
+
file: options?.file ?? 'config.json',
|
|
23
|
+
flush: options?.flush ?? true,
|
|
24
|
+
};
|
|
25
|
+
this.filePath = path.resolve(this.options.dir, this.options.file);
|
|
26
|
+
this.ensureDir();
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Typed write methods.
|
|
30
|
+
*
|
|
31
|
+
* Each method writes a value of the corresponding type to the given key.
|
|
32
|
+
* The write is serialised: it waits for any pending writes to complete,
|
|
33
|
+
* then atomically persists the updated JSON to disk.
|
|
34
|
+
*
|
|
35
|
+
* `any` is the untyped escape hatch — it accepts any value and performs
|
|
36
|
+
* no type-checking on subsequent reads unless you use a typed read method.
|
|
37
|
+
*/
|
|
38
|
+
write = {
|
|
39
|
+
/** Persist a numeric value under `key`. */
|
|
40
|
+
num: (key, value) => this.setValue(key, value),
|
|
41
|
+
/** Persist a string value under `key`. */
|
|
42
|
+
str: (key, value) => this.setValue(key, value),
|
|
43
|
+
/** Persist a boolean value under `key`. */
|
|
44
|
+
b: (key, value) => this.setValue(key, value),
|
|
45
|
+
/** Persist a plain object under `key`. */
|
|
46
|
+
obj: (key, value) => this.setValue(key, value),
|
|
47
|
+
/** Persist an array under `key`. */
|
|
48
|
+
arr: (key, value) => this.setValue(key, value),
|
|
49
|
+
/** Persist any value under `key`. No type constraint. */
|
|
50
|
+
any: (key, value) => this.setValue(key, value),
|
|
51
|
+
/** Persist any value under `key`. Symmetric alias for `any`. */
|
|
52
|
+
schema: (key, value) => this.setValue(key, value),
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Typed read methods.
|
|
56
|
+
*
|
|
57
|
+
* Each method reads the value at `key` and validates that it matches the
|
|
58
|
+
* expected type. If the key is missing or the stored value has a different
|
|
59
|
+
* type, `defaultValue` is returned **and the file is repaired** so that
|
|
60
|
+
* subsequent reads hit the correct value.
|
|
61
|
+
*/
|
|
62
|
+
read = {
|
|
63
|
+
/** Read a number. Returns `defaultValue` if missing or wrong type. */
|
|
64
|
+
num: (key, defaultValue) => this.getValue(key, defaultValue, 'number'),
|
|
65
|
+
/** Read a string. Returns `defaultValue` if missing or wrong type. */
|
|
66
|
+
str: (key, defaultValue) => this.getValue(key, defaultValue, 'string'),
|
|
67
|
+
/** Read a boolean. Returns `defaultValue` if missing or wrong type. */
|
|
68
|
+
b: (key, defaultValue) => this.getValue(key, defaultValue, 'boolean'),
|
|
69
|
+
/** Read a plain object (generic). Returns `defaultValue` if missing or wrong type. */
|
|
70
|
+
obj: (key, defaultValue) => this.getValue(key, defaultValue, 'object'),
|
|
71
|
+
/** Read an array (generic). Returns `defaultValue` if missing or wrong type. */
|
|
72
|
+
arr: (key, defaultValue) => this.getValue(key, defaultValue, 'array'),
|
|
73
|
+
/** Read any value. Returns `defaultValue` if missing. No type validation. */
|
|
74
|
+
any: (key, defaultValue) => this.getValue(key, defaultValue, 'any'),
|
|
75
|
+
/** Read a value validated against a zod schema. Auto-repairs on parse failure. */
|
|
76
|
+
schema: (key, schema, defaultValue) => this.getValueWithSchema(key, schema, defaultValue),
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Check whether a key exists in the store.
|
|
80
|
+
*
|
|
81
|
+
* @returns `true` if the key has an entry (even if its value is `null`
|
|
82
|
+
* or `undefined` — it checks own-property presence).
|
|
83
|
+
*/
|
|
84
|
+
async has(key) {
|
|
85
|
+
await this.ensureLoaded();
|
|
86
|
+
return Object.prototype.hasOwnProperty.call(this.data, key);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Remove a key and its value from the store.
|
|
90
|
+
*
|
|
91
|
+
* If the key does not exist this is a no-op (no error thrown).
|
|
92
|
+
*/
|
|
93
|
+
async delete(key) {
|
|
94
|
+
await this.ensureLoaded();
|
|
95
|
+
if (Object.prototype.hasOwnProperty.call(this.data, key)) {
|
|
96
|
+
delete this.data[key];
|
|
97
|
+
await this.flush();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Remove all keys from the store, resetting it to an empty object.
|
|
102
|
+
*/
|
|
103
|
+
async clear() {
|
|
104
|
+
this.data = {};
|
|
105
|
+
await this.flush();
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Return a shallow copy of the entire raw data object.
|
|
109
|
+
*
|
|
110
|
+
* Modifications to the returned object do **not** affect the store
|
|
111
|
+
* (use the write methods to persist changes).
|
|
112
|
+
*/
|
|
113
|
+
async getAll() {
|
|
114
|
+
await this.ensureLoaded();
|
|
115
|
+
return { ...this.data };
|
|
116
|
+
}
|
|
117
|
+
ensureDir() {
|
|
118
|
+
fs.mkdirSync(this.options.dir, { recursive: true });
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Serialise access so concurrent callers never interleave.
|
|
122
|
+
*
|
|
123
|
+
* Each task is chained onto `this.pending` using `.then(task, task)`.
|
|
124
|
+
* The second argument ensures that even if a previous task rejects,
|
|
125
|
+
* the next task still runs (the chain is never broken).
|
|
126
|
+
*/
|
|
127
|
+
enqueue(task) {
|
|
128
|
+
this.pending = this.pending.then(task, task);
|
|
129
|
+
return this.pending;
|
|
130
|
+
}
|
|
131
|
+
setValue(key, value) {
|
|
132
|
+
return this.enqueue(async () => {
|
|
133
|
+
await this.ensureLoaded();
|
|
134
|
+
this.data[key] = value;
|
|
135
|
+
await this.flush();
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Read a value with type validation and automatic repair.
|
|
140
|
+
*
|
|
141
|
+
* If the key is missing the default is written to disk so that
|
|
142
|
+
* subsequent reads return it directly. If the stored value has a
|
|
143
|
+
* different type than expected, the default replaces it on disk.
|
|
144
|
+
*/
|
|
145
|
+
async getValue(key, defaultValue, expectedType) {
|
|
146
|
+
await this.ensureLoaded();
|
|
147
|
+
const stored = this.data[key];
|
|
148
|
+
if (stored === undefined) {
|
|
149
|
+
this.data[key] = defaultValue;
|
|
150
|
+
await this.flush();
|
|
151
|
+
return defaultValue;
|
|
152
|
+
}
|
|
153
|
+
let valid = false;
|
|
154
|
+
if (expectedType === 'number')
|
|
155
|
+
valid = typeof stored === 'number';
|
|
156
|
+
else if (expectedType === 'string')
|
|
157
|
+
valid = typeof stored === 'string';
|
|
158
|
+
else if (expectedType === 'boolean')
|
|
159
|
+
valid = typeof stored === 'boolean';
|
|
160
|
+
else if (expectedType === 'array')
|
|
161
|
+
valid = Array.isArray(stored);
|
|
162
|
+
else if (expectedType === 'object')
|
|
163
|
+
valid = typeof stored === 'object' && stored !== null && !Array.isArray(stored);
|
|
164
|
+
else
|
|
165
|
+
valid = true;
|
|
166
|
+
if (!valid) {
|
|
167
|
+
this.data[key] = defaultValue;
|
|
168
|
+
await this.flush();
|
|
169
|
+
return defaultValue;
|
|
170
|
+
}
|
|
171
|
+
return stored;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Read a value and validate it against a zod schema.
|
|
175
|
+
*
|
|
176
|
+
* On success the parsed value is returned (including any transforms
|
|
177
|
+
* or coercions the schema applies). On failure — missing key or
|
|
178
|
+
* schema parse error — `defaultValue` is written to disk and returned.
|
|
179
|
+
*/
|
|
180
|
+
async getValueWithSchema(key, schema, defaultValue) {
|
|
181
|
+
await this.ensureLoaded();
|
|
182
|
+
const stored = this.data[key];
|
|
183
|
+
if (stored === undefined) {
|
|
184
|
+
this.data[key] = defaultValue;
|
|
185
|
+
await this.flush();
|
|
186
|
+
return defaultValue;
|
|
187
|
+
}
|
|
188
|
+
const result = schema.safeParse(stored);
|
|
189
|
+
if (result.success) {
|
|
190
|
+
return result.data;
|
|
191
|
+
}
|
|
192
|
+
this.data[key] = defaultValue;
|
|
193
|
+
await this.flush();
|
|
194
|
+
return defaultValue;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Load data from disk on first access (lazy initialisation).
|
|
198
|
+
*
|
|
199
|
+
* Once loaded the data stays in memory for the lifetime of the
|
|
200
|
+
* instance. File-not-found and corrupt-JSON errors are silently
|
|
201
|
+
* swallowed — in both cases we start with an empty store.
|
|
202
|
+
*/
|
|
203
|
+
async ensureLoaded() {
|
|
204
|
+
if (this.data !== null)
|
|
205
|
+
return;
|
|
206
|
+
try {
|
|
207
|
+
const raw = fs.readFileSync(this.filePath, 'utf-8');
|
|
208
|
+
const parsed = JSON.parse(raw);
|
|
209
|
+
this.data =
|
|
210
|
+
typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)
|
|
211
|
+
? parsed
|
|
212
|
+
: {};
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
this.data = {};
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Atomically persist the in-memory data to disk.
|
|
220
|
+
*
|
|
221
|
+
* Writes to a `.tmp` file first, then renames it over the target
|
|
222
|
+
* file. This guarantees that the on-disk file is always either the
|
|
223
|
+
* complete previous version or the complete new version — never a
|
|
224
|
+
* partially-written mess.
|
|
225
|
+
*
|
|
226
|
+
* No-op when `options.flush` is `false`.
|
|
227
|
+
*/
|
|
228
|
+
async flush() {
|
|
229
|
+
if (!this.options.flush)
|
|
230
|
+
return;
|
|
231
|
+
const tmpPath = this.filePath + '.tmp';
|
|
232
|
+
const content = JSON.stringify(this.data, null, 2);
|
|
233
|
+
fs.writeFileSync(tmpPath, content, 'utf-8');
|
|
234
|
+
fs.renameSync(tmpPath, this.filePath);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import type { ZodType } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for {@link createStorage}.
|
|
4
|
+
*
|
|
5
|
+
* All properties are optional — sensible defaults are provided so that
|
|
6
|
+
* calling `createStorage()` with no arguments just works.
|
|
7
|
+
*/
|
|
8
|
+
export interface StorageOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Directory where the JSON file lives.
|
|
11
|
+
*
|
|
12
|
+
* Relative paths are resolved against `process.cwd()`.
|
|
13
|
+
* The directory (and any missing parents) are created automatically
|
|
14
|
+
* on construction via `fs.mkdirSync(dir, { recursive: true })`.
|
|
15
|
+
*
|
|
16
|
+
* @default './data'
|
|
17
|
+
*/
|
|
18
|
+
dir?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Name of the JSON file backing this storage station.
|
|
21
|
+
*
|
|
22
|
+
* @default 'config.json'
|
|
23
|
+
*/
|
|
24
|
+
file?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Whether to write changes to disk immediately after each operation.
|
|
27
|
+
*
|
|
28
|
+
* When `false`, in-memory mutations are not persisted until you
|
|
29
|
+
* manually trigger a flush (or set this back to `true` on a subsequent
|
|
30
|
+
* write). Useful for batch writes where you want to avoid multiple
|
|
31
|
+
* disk I/O round-trips.
|
|
32
|
+
*
|
|
33
|
+
* @default true
|
|
34
|
+
*/
|
|
35
|
+
flush?: boolean;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Resolved storage configuration with every default filled in.
|
|
39
|
+
*
|
|
40
|
+
* Internal use only — you never need to construct this manually.
|
|
41
|
+
*/
|
|
42
|
+
export interface ResolvedStorageOptions {
|
|
43
|
+
dir: string;
|
|
44
|
+
file: string;
|
|
45
|
+
flush: boolean;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The public API returned by {@link createStorage}.
|
|
49
|
+
*
|
|
50
|
+
* Provides typed read/write accessors, key management helpers, and
|
|
51
|
+
* a method to dump the entire store. All methods are async and
|
|
52
|
+
* serialised internally — callers never need to worry about concurrent
|
|
53
|
+
* access to the same file.
|
|
54
|
+
*/
|
|
55
|
+
export interface StorageAPI {
|
|
56
|
+
/**
|
|
57
|
+
* Typed write methods.
|
|
58
|
+
*
|
|
59
|
+
* Each method persists a value of the corresponding type.
|
|
60
|
+
* Writes are serialised: calling `write.num('a', 1)` followed
|
|
61
|
+
* immediately by `write.num('b', 2)` will reliably write both keys
|
|
62
|
+
* in order.
|
|
63
|
+
*/
|
|
64
|
+
write: {
|
|
65
|
+
/** Write a numeric value. */
|
|
66
|
+
num(key: string, value: number): Promise<void>;
|
|
67
|
+
/** Write a string value. */
|
|
68
|
+
str(key: string, value: string): Promise<void>;
|
|
69
|
+
/** Write a boolean value. */
|
|
70
|
+
b(key: string, value: boolean): Promise<void>;
|
|
71
|
+
/** Write a plain object (generic — preserves the type for reads). */
|
|
72
|
+
obj<T extends object>(key: string, value: T): Promise<void>;
|
|
73
|
+
/** Write an array (generic — preserves the element type for reads). */
|
|
74
|
+
arr<T>(key: string, value: T[]): Promise<void>;
|
|
75
|
+
/** Write any value. No type constraint; use with `read.any`. */
|
|
76
|
+
any(key: string, value: unknown): Promise<void>;
|
|
77
|
+
/** Write any value (alias for `any` — kept symmetric with `read.schema`). */
|
|
78
|
+
schema<T>(key: string, value: T): Promise<void>;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Typed read methods.
|
|
82
|
+
*
|
|
83
|
+
* Each method validates the stored value against the expected type.
|
|
84
|
+
* If the key is missing or the type is wrong, `defaultValue` is
|
|
85
|
+
* returned and the file is automatically repaired.
|
|
86
|
+
*/
|
|
87
|
+
read: {
|
|
88
|
+
/** Read a number. Returns `defaultValue` on missing key or type mismatch. */
|
|
89
|
+
num(key: string, defaultValue: number): Promise<number>;
|
|
90
|
+
/** Read a string. Returns `defaultValue` on missing key or type mismatch. */
|
|
91
|
+
str(key: string, defaultValue: string): Promise<string>;
|
|
92
|
+
/** Read a boolean. Returns `defaultValue` on missing key or type mismatch. */
|
|
93
|
+
b(key: string, defaultValue: boolean): Promise<boolean>;
|
|
94
|
+
/** Read a plain object. Returns `defaultValue` on missing key or type mismatch. */
|
|
95
|
+
obj<T extends object>(key: string, defaultValue: T): Promise<T>;
|
|
96
|
+
/** Read an array. Returns `defaultValue` on missing key or type mismatch. */
|
|
97
|
+
arr<T>(key: string, defaultValue: T[]): Promise<T[]>;
|
|
98
|
+
/** Read any value. Returns `defaultValue` on missing key (no type validation). */
|
|
99
|
+
any<T>(key: string, defaultValue: T): Promise<T>;
|
|
100
|
+
/**
|
|
101
|
+
* Read a value validated against a zod schema.
|
|
102
|
+
*
|
|
103
|
+
* On success the parsed value is returned (including any zod transforms
|
|
104
|
+
* or coercions applied by the schema). On failure — missing key, schema
|
|
105
|
+
* parse error, or wrong shape — `defaultValue` is returned and the file
|
|
106
|
+
* is automatically repaired.
|
|
107
|
+
*
|
|
108
|
+
* @param key The key to read.
|
|
109
|
+
* @param schema A zod schema to validate the stored value against.
|
|
110
|
+
* @param defaultValue Fallback value used when validation fails.
|
|
111
|
+
*/
|
|
112
|
+
schema<T>(key: string, schema: ZodType<T>, defaultValue: T): Promise<T>;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Check whether a key exists in the store.
|
|
116
|
+
*
|
|
117
|
+
* @returns `true` if the key has an own-property entry, even if
|
|
118
|
+
* its value is `null` or `undefined`.
|
|
119
|
+
*/
|
|
120
|
+
has(key: string): Promise<boolean>;
|
|
121
|
+
/**
|
|
122
|
+
* Remove a key and its value.
|
|
123
|
+
*
|
|
124
|
+
* No-op when the key does not exist.
|
|
125
|
+
*/
|
|
126
|
+
delete(key: string): Promise<void>;
|
|
127
|
+
/**
|
|
128
|
+
* Remove all keys, resetting the store to an empty object.
|
|
129
|
+
*/
|
|
130
|
+
clear(): Promise<void>;
|
|
131
|
+
/**
|
|
132
|
+
* Return a shallow copy of the entire data object.
|
|
133
|
+
*
|
|
134
|
+
* Changes to the returned object are **not** persisted — use the
|
|
135
|
+
* write methods for that.
|
|
136
|
+
*/
|
|
137
|
+
getAll(): Promise<Record<string, unknown>>;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Internal data store — a flat key-value map serialised as JSON.
|
|
141
|
+
*
|
|
142
|
+
* The top-level JSON structure is always an object. Arrays and
|
|
143
|
+
* primitives at the top level are rejected on load (treated as corrupt).
|
|
144
|
+
*/
|
|
145
|
+
export type StoreData = Record<string, unknown>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ThemeContextValue } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Internal React context for the theme system.
|
|
4
|
+
* Consumers should use the {@link useTheme} hook instead of accessing this
|
|
5
|
+
* context directly.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ThemeContext: import("react").Context<ThemeContextValue | null>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ThemeContextValue } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Access the theme API from within a component tree wrapped by
|
|
4
|
+
* {@link ThemeProvider}.
|
|
5
|
+
*
|
|
6
|
+
* Returns `{ color, style, themeId, themes, setTheme, mergeTheme }`.
|
|
7
|
+
*
|
|
8
|
+
* Must be used inside `<ThemeProvider>`. Throws with a clear error
|
|
9
|
+
* message if no provider is found in the component tree.
|
|
10
|
+
*/
|
|
11
|
+
export declare function useTheme(): ThemeContextValue;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
import { ThemeContext } from './context.js';
|
|
3
|
+
/**
|
|
4
|
+
* Access the theme API from within a component tree wrapped by
|
|
5
|
+
* {@link ThemeProvider}.
|
|
6
|
+
*
|
|
7
|
+
* Returns `{ color, style, themeId, themes, setTheme, mergeTheme }`.
|
|
8
|
+
*
|
|
9
|
+
* Must be used inside `<ThemeProvider>`. Throws with a clear error
|
|
10
|
+
* message if no provider is found in the component tree.
|
|
11
|
+
*/
|
|
12
|
+
export function useTheme() {
|
|
13
|
+
const ctx = useContext(ThemeContext);
|
|
14
|
+
if (!ctx) {
|
|
15
|
+
throw new Error('[Ink-Cartridge] useTheme() must be called inside a <ThemeProvider>.');
|
|
16
|
+
}
|
|
17
|
+
return ctx;
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ThemeDefinition } from './types.js';
|
|
3
|
+
export interface ThemeProviderProps {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
themes?: ThemeDefinition[];
|
|
6
|
+
path?: string;
|
|
7
|
+
defaultTheme?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Context provider for theming.
|
|
11
|
+
*
|
|
12
|
+
* Loads theme definitions either from a directory of `{id}.json` files
|
|
13
|
+
* (via the `path` prop) or from pre-built inline objects (via `themes`).
|
|
14
|
+
*
|
|
15
|
+
* Descendant components can use the {@link useTheme} hook to access
|
|
16
|
+
* `color()` and `style()` functions, and `setTheme()` to switch themes.
|
|
17
|
+
*/
|
|
18
|
+
export declare function ThemeProvider({ children, themes: inlineThemes, path, defaultTheme, }: ThemeProviderProps): React.JSX.Element;
|