verso-db 0.1.5 → 0.2.0
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/CHANGELOG.md +13 -0
- package/README.md +13 -7
- package/dist/BinaryHeap.d.ts +11 -1
- package/dist/BinaryHeap.d.ts.map +1 -1
- package/dist/BinaryHeap.js +138 -0
- package/dist/BinaryHeap.js.map +1 -0
- package/dist/Collection.d.ts +30 -4
- package/dist/Collection.d.ts.map +1 -1
- package/dist/Collection.js +1186 -0
- package/dist/Collection.js.map +1 -0
- package/dist/HNSWIndex.d.ts +59 -0
- package/dist/HNSWIndex.d.ts.map +1 -1
- package/dist/HNSWIndex.js +2818 -0
- package/dist/HNSWIndex.js.map +1 -0
- package/dist/MaxBinaryHeap.d.ts +2 -64
- package/dist/MaxBinaryHeap.d.ts.map +1 -1
- package/dist/MaxBinaryHeap.js +5 -0
- package/dist/MaxBinaryHeap.js.map +1 -0
- package/dist/SearchWorker.d.ts +57 -4
- package/dist/SearchWorker.d.ts.map +1 -1
- package/dist/SearchWorker.js +573 -0
- package/dist/SearchWorker.js.map +1 -0
- package/dist/VectorDB.d.ts.map +1 -1
- package/dist/VectorDB.js +246 -0
- package/dist/VectorDB.js.map +1 -0
- package/dist/WorkerPool.d.ts +32 -2
- package/dist/WorkerPool.d.ts.map +1 -1
- package/dist/WorkerPool.js +266 -0
- package/dist/WorkerPool.js.map +1 -0
- package/dist/backends/JsDistanceBackend.d.ts.map +1 -1
- package/dist/backends/JsDistanceBackend.js +163 -0
- package/dist/backends/JsDistanceBackend.js.map +1 -0
- package/dist/encoding/DeltaEncoder.d.ts +2 -2
- package/dist/encoding/DeltaEncoder.d.ts.map +1 -1
- package/dist/encoding/DeltaEncoder.js +199 -0
- package/dist/encoding/DeltaEncoder.js.map +1 -0
- package/dist/errors.js +97 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +61 -42
- package/dist/index.js.map +1 -9
- package/dist/presets.js +205 -0
- package/dist/presets.js.map +1 -0
- package/dist/quantization/ScalarQuantizer.d.ts +0 -34
- package/dist/quantization/ScalarQuantizer.d.ts.map +1 -1
- package/dist/quantization/ScalarQuantizer.js +346 -0
- package/dist/quantization/ScalarQuantizer.js.map +1 -0
- package/dist/storage/BatchWriter.js +351 -0
- package/dist/storage/BatchWriter.js.map +1 -0
- package/dist/storage/BunStorageBackend.d.ts +7 -3
- package/dist/storage/BunStorageBackend.d.ts.map +1 -1
- package/dist/storage/BunStorageBackend.js +182 -0
- package/dist/storage/BunStorageBackend.js.map +1 -0
- package/dist/storage/MemoryBackend.js +109 -0
- package/dist/storage/MemoryBackend.js.map +1 -0
- package/dist/storage/OPFSBackend.d.ts.map +1 -1
- package/dist/storage/OPFSBackend.js +325 -0
- package/dist/storage/OPFSBackend.js.map +1 -0
- package/dist/storage/StorageBackend.js +12 -0
- package/dist/storage/StorageBackend.js.map +1 -0
- package/dist/storage/WriteAheadLog.js +321 -0
- package/dist/storage/WriteAheadLog.js.map +1 -0
- package/dist/storage/createStorageBackend.d.ts +4 -0
- package/dist/storage/createStorageBackend.d.ts.map +1 -1
- package/dist/storage/createStorageBackend.js +119 -0
- package/dist/storage/createStorageBackend.js.map +1 -0
- package/{src/storage/index.ts → dist/storage/index.js} +7 -27
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/nodeFsRuntime.d.ts +14 -0
- package/dist/storage/nodeFsRuntime.d.ts.map +1 -0
- package/dist/storage/nodeFsRuntime.js +105 -0
- package/dist/storage/nodeFsRuntime.js.map +1 -0
- package/package.json +9 -7
- package/src/BinaryHeap.ts +0 -136
- package/src/Collection.ts +0 -1262
- package/src/HNSWIndex.ts +0 -2894
- package/src/MaxBinaryHeap.ts +0 -181
- package/src/SearchWorker.ts +0 -264
- package/src/VectorDB.ts +0 -319
- package/src/WorkerPool.ts +0 -222
- package/src/backends/JsDistanceBackend.ts +0 -171
- package/src/encoding/DeltaEncoder.ts +0 -236
- package/src/errors.ts +0 -110
- package/src/index.ts +0 -106
- package/src/presets.ts +0 -229
- package/src/quantization/ScalarQuantizer.ts +0 -487
- package/src/storage/BatchWriter.ts +0 -420
- package/src/storage/BunStorageBackend.ts +0 -199
- package/src/storage/MemoryBackend.ts +0 -122
- package/src/storage/OPFSBackend.ts +0 -348
- package/src/storage/StorageBackend.ts +0 -74
- package/src/storage/WriteAheadLog.ts +0 -379
- package/src/storage/createStorageBackend.ts +0 -137
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Write-Ahead Log (WAL) for Incremental Index Updates
|
|
3
|
+
*
|
|
4
|
+
* Provides durability and efficient incremental writes for HNSW index operations.
|
|
5
|
+
* Instead of rewriting the entire index on each update, operations are appended
|
|
6
|
+
* to a log file. The log can be compacted into a full snapshot periodically.
|
|
7
|
+
*
|
|
8
|
+
* Benefits:
|
|
9
|
+
* - Fast appends (no full serialization)
|
|
10
|
+
* - Crash recovery (replay log after restart)
|
|
11
|
+
* - Reduced I/O for frequent updates
|
|
12
|
+
*/
|
|
13
|
+
export var WALOperationType;
|
|
14
|
+
(function (WALOperationType) {
|
|
15
|
+
WALOperationType[WALOperationType["ADD_VECTOR"] = 1] = "ADD_VECTOR";
|
|
16
|
+
WALOperationType[WALOperationType["ADD_NEIGHBORS"] = 2] = "ADD_NEIGHBORS";
|
|
17
|
+
WALOperationType[WALOperationType["UPDATE_ENTRY_POINT"] = 3] = "UPDATE_ENTRY_POINT";
|
|
18
|
+
WALOperationType[WALOperationType["CHECKPOINT"] = 4] = "CHECKPOINT";
|
|
19
|
+
})(WALOperationType || (WALOperationType = {}));
|
|
20
|
+
/**
|
|
21
|
+
* WriteAheadLog - Append-only log for incremental index updates
|
|
22
|
+
*/
|
|
23
|
+
export class WriteAheadLog {
|
|
24
|
+
storage;
|
|
25
|
+
logKey;
|
|
26
|
+
pendingEntries = [];
|
|
27
|
+
flushThreshold;
|
|
28
|
+
entryCount = 0;
|
|
29
|
+
flushPromise = null;
|
|
30
|
+
/**
|
|
31
|
+
* Create a new WAL
|
|
32
|
+
* @param storage StorageBackend for persistence
|
|
33
|
+
* @param logKey Storage key for the WAL data (e.g., "myindex.wal")
|
|
34
|
+
* @param flushThreshold Number of entries before auto-flush (default: 100)
|
|
35
|
+
*/
|
|
36
|
+
constructor(storage, logKey, flushThreshold = 100) {
|
|
37
|
+
this.storage = storage;
|
|
38
|
+
this.logKey = logKey;
|
|
39
|
+
this.flushThreshold = flushThreshold;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get the WAL storage key
|
|
43
|
+
*/
|
|
44
|
+
getKey() {
|
|
45
|
+
return this.logKey;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Check if WAL data exists
|
|
49
|
+
*/
|
|
50
|
+
async exists() {
|
|
51
|
+
return this.storage.exists(this.logKey);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Append a vector addition operation to the log
|
|
55
|
+
*/
|
|
56
|
+
async appendVector(id, vector) {
|
|
57
|
+
// Format: [id (4 bytes)] [vector length (4 bytes)] [vector data]
|
|
58
|
+
const dataSize = 4 + 4 + vector.length * 4;
|
|
59
|
+
const buffer = new ArrayBuffer(dataSize);
|
|
60
|
+
const view = new DataView(buffer);
|
|
61
|
+
view.setUint32(0, id, true);
|
|
62
|
+
view.setUint32(4, vector.length, true);
|
|
63
|
+
const floatView = new Float32Array(buffer, 8);
|
|
64
|
+
floatView.set(vector);
|
|
65
|
+
const entry = {
|
|
66
|
+
type: WALOperationType.ADD_VECTOR,
|
|
67
|
+
timestamp: Date.now(),
|
|
68
|
+
data: buffer,
|
|
69
|
+
};
|
|
70
|
+
this.pendingEntries.push(entry);
|
|
71
|
+
this.entryCount++;
|
|
72
|
+
if (this.pendingEntries.length >= this.flushThreshold) {
|
|
73
|
+
await this.flush();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Append a neighbor update operation to the log
|
|
78
|
+
*/
|
|
79
|
+
async appendNeighbors(nodeId, layer, neighbors) {
|
|
80
|
+
// Format: [nodeId (4)] [layer (4)] [neighborCount (4)] [neighbors...]
|
|
81
|
+
const dataSize = 4 + 4 + 4 + neighbors.length * 4;
|
|
82
|
+
const buffer = new ArrayBuffer(dataSize);
|
|
83
|
+
const view = new DataView(buffer);
|
|
84
|
+
view.setUint32(0, nodeId, true);
|
|
85
|
+
view.setUint32(4, layer, true);
|
|
86
|
+
view.setUint32(8, neighbors.length, true);
|
|
87
|
+
let offset = 12;
|
|
88
|
+
for (const neighbor of neighbors) {
|
|
89
|
+
view.setUint32(offset, neighbor, true);
|
|
90
|
+
offset += 4;
|
|
91
|
+
}
|
|
92
|
+
const entry = {
|
|
93
|
+
type: WALOperationType.ADD_NEIGHBORS,
|
|
94
|
+
timestamp: Date.now(),
|
|
95
|
+
data: buffer,
|
|
96
|
+
};
|
|
97
|
+
this.pendingEntries.push(entry);
|
|
98
|
+
this.entryCount++;
|
|
99
|
+
if (this.pendingEntries.length >= this.flushThreshold) {
|
|
100
|
+
await this.flush();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Append entry point update to the log
|
|
105
|
+
*/
|
|
106
|
+
async appendEntryPointUpdate(entryPointId, maxLevel) {
|
|
107
|
+
const buffer = new ArrayBuffer(8);
|
|
108
|
+
const view = new DataView(buffer);
|
|
109
|
+
view.setInt32(0, entryPointId, true);
|
|
110
|
+
view.setInt32(4, maxLevel, true);
|
|
111
|
+
const entry = {
|
|
112
|
+
type: WALOperationType.UPDATE_ENTRY_POINT,
|
|
113
|
+
timestamp: Date.now(),
|
|
114
|
+
data: buffer,
|
|
115
|
+
};
|
|
116
|
+
this.pendingEntries.push(entry);
|
|
117
|
+
this.entryCount++;
|
|
118
|
+
if (this.pendingEntries.length >= this.flushThreshold) {
|
|
119
|
+
await this.flush();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Write a checkpoint marker to the log
|
|
124
|
+
*/
|
|
125
|
+
async checkpoint() {
|
|
126
|
+
const buffer = new ArrayBuffer(8);
|
|
127
|
+
const view = new DataView(buffer);
|
|
128
|
+
view.setFloat64(0, Date.now(), true);
|
|
129
|
+
const entry = {
|
|
130
|
+
type: WALOperationType.CHECKPOINT,
|
|
131
|
+
timestamp: Date.now(),
|
|
132
|
+
data: buffer,
|
|
133
|
+
};
|
|
134
|
+
this.pendingEntries.push(entry);
|
|
135
|
+
this.entryCount++;
|
|
136
|
+
await this.flush();
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Serialize a WAL entry to bytes
|
|
140
|
+
*/
|
|
141
|
+
serializeEntry(entry) {
|
|
142
|
+
// Format: [type (1)] [timestamp (8)] [dataLength (4)] [data...]
|
|
143
|
+
const headerSize = 1 + 8 + 4;
|
|
144
|
+
const totalSize = headerSize + entry.data.byteLength;
|
|
145
|
+
const buffer = new ArrayBuffer(totalSize);
|
|
146
|
+
const view = new DataView(buffer);
|
|
147
|
+
view.setUint8(0, entry.type);
|
|
148
|
+
view.setFloat64(1, entry.timestamp, true);
|
|
149
|
+
view.setUint32(9, entry.data.byteLength, true);
|
|
150
|
+
const dataView = new Uint8Array(buffer, headerSize);
|
|
151
|
+
dataView.set(new Uint8Array(entry.data));
|
|
152
|
+
return new Uint8Array(buffer);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Flush pending entries to storage
|
|
156
|
+
* Uses append for efficient O(1) writes
|
|
157
|
+
*/
|
|
158
|
+
async flush() {
|
|
159
|
+
while (true) {
|
|
160
|
+
if (this.flushPromise) {
|
|
161
|
+
await this.flushPromise;
|
|
162
|
+
}
|
|
163
|
+
if (this.pendingEntries.length === 0) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
// Capture and clear atomically before async work to avoid losing
|
|
167
|
+
// entries added by concurrent appendVector() calls during the await.
|
|
168
|
+
const toFlush = this.pendingEntries;
|
|
169
|
+
this.pendingEntries = [];
|
|
170
|
+
const currentFlush = this.flushEntries(toFlush);
|
|
171
|
+
this.flushPromise = currentFlush;
|
|
172
|
+
try {
|
|
173
|
+
await currentFlush;
|
|
174
|
+
}
|
|
175
|
+
finally {
|
|
176
|
+
if (this.flushPromise === currentFlush) {
|
|
177
|
+
this.flushPromise = null;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
async flushEntries(toFlush) {
|
|
183
|
+
// Serialize captured entries
|
|
184
|
+
const serializedEntries = toFlush.map(e => this.serializeEntry(e));
|
|
185
|
+
// Calculate total size
|
|
186
|
+
let totalSize = 0;
|
|
187
|
+
for (const entry of serializedEntries) {
|
|
188
|
+
totalSize += entry.length;
|
|
189
|
+
}
|
|
190
|
+
// Combine into single buffer
|
|
191
|
+
const combined = new Uint8Array(totalSize);
|
|
192
|
+
let offset = 0;
|
|
193
|
+
for (const entry of serializedEntries) {
|
|
194
|
+
combined.set(entry, offset);
|
|
195
|
+
offset += entry.length;
|
|
196
|
+
}
|
|
197
|
+
// Append to storage
|
|
198
|
+
try {
|
|
199
|
+
await this.storage.append(this.logKey, combined);
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
// Restore entries on failure so they aren't lost
|
|
203
|
+
this.pendingEntries = [...toFlush, ...this.pendingEntries];
|
|
204
|
+
throw err;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Read all entries from the WAL
|
|
209
|
+
*/
|
|
210
|
+
async readEntries() {
|
|
211
|
+
const data = await this.storage.read(this.logKey);
|
|
212
|
+
if (!data || data.byteLength === 0) {
|
|
213
|
+
return [];
|
|
214
|
+
}
|
|
215
|
+
const buffer = data;
|
|
216
|
+
const view = new DataView(buffer);
|
|
217
|
+
const entries = [];
|
|
218
|
+
const headerSize = 13; // 1 (type) + 8 (timestamp) + 4 (dataLength)
|
|
219
|
+
let offset = 0;
|
|
220
|
+
while (offset < buffer.byteLength) {
|
|
221
|
+
// Check we can read the header
|
|
222
|
+
if (offset + headerSize > buffer.byteLength) {
|
|
223
|
+
console.warn(`WAL: truncated entry header at offset ${offset}, stopping replay`);
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
// Read header
|
|
227
|
+
const type = view.getUint8(offset);
|
|
228
|
+
const timestamp = view.getFloat64(offset + 1, true);
|
|
229
|
+
const dataLength = view.getUint32(offset + 9, true);
|
|
230
|
+
// Validate data length
|
|
231
|
+
if (dataLength > buffer.byteLength - offset - headerSize) {
|
|
232
|
+
console.warn(`WAL: truncated entry data at offset ${offset} (expected ${dataLength} bytes, only ${buffer.byteLength - offset - headerSize} available), stopping replay`);
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
// Validate operation type
|
|
236
|
+
if (type < 1 || type > 4) {
|
|
237
|
+
console.warn(`WAL: unknown operation type ${type} at offset ${offset}, stopping replay`);
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
// Read data
|
|
241
|
+
const entryData = buffer.slice(offset + headerSize, offset + headerSize + dataLength);
|
|
242
|
+
entries.push({ type, timestamp, data: entryData });
|
|
243
|
+
offset += headerSize + dataLength;
|
|
244
|
+
}
|
|
245
|
+
this.entryCount = entries.length + this.pendingEntries.length;
|
|
246
|
+
return entries;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Parse a vector addition entry
|
|
250
|
+
*/
|
|
251
|
+
static parseVectorEntry(data) {
|
|
252
|
+
const view = new DataView(data);
|
|
253
|
+
const id = view.getUint32(0, true);
|
|
254
|
+
const vectorLength = view.getUint32(4, true);
|
|
255
|
+
const vector = new Float32Array(data, 8, vectorLength);
|
|
256
|
+
return { id, vector };
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Parse a neighbor update entry
|
|
260
|
+
*/
|
|
261
|
+
static parseNeighborsEntry(data) {
|
|
262
|
+
const view = new DataView(data);
|
|
263
|
+
const nodeId = view.getUint32(0, true);
|
|
264
|
+
const layer = view.getUint32(4, true);
|
|
265
|
+
const neighborCount = view.getUint32(8, true);
|
|
266
|
+
const neighbors = [];
|
|
267
|
+
for (let i = 0; i < neighborCount; i++) {
|
|
268
|
+
neighbors.push(view.getUint32(12 + i * 4, true));
|
|
269
|
+
}
|
|
270
|
+
return { nodeId, layer, neighbors };
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Parse an entry point update entry
|
|
274
|
+
*/
|
|
275
|
+
static parseEntryPointEntry(data) {
|
|
276
|
+
const view = new DataView(data);
|
|
277
|
+
return {
|
|
278
|
+
entryPointId: view.getInt32(0, true),
|
|
279
|
+
maxLevel: view.getInt32(4, true),
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Get entry count since last compact
|
|
284
|
+
*/
|
|
285
|
+
getEntryCount() {
|
|
286
|
+
return this.entryCount;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Clear the WAL (after successful compaction)
|
|
290
|
+
*/
|
|
291
|
+
async clear() {
|
|
292
|
+
if (this.flushPromise) {
|
|
293
|
+
await this.flushPromise.catch(() => { });
|
|
294
|
+
}
|
|
295
|
+
// Clear in-memory state first to prevent flush() from writing entries
|
|
296
|
+
// after we truncate the on-disk WAL.
|
|
297
|
+
this.pendingEntries = [];
|
|
298
|
+
this.entryCount = 0;
|
|
299
|
+
if (await this.storage.exists(this.logKey)) {
|
|
300
|
+
await this.storage.write(this.logKey, new Uint8Array(0));
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Delete the WAL data
|
|
305
|
+
*/
|
|
306
|
+
async delete() {
|
|
307
|
+
if (this.flushPromise) {
|
|
308
|
+
await this.flushPromise.catch(() => { });
|
|
309
|
+
}
|
|
310
|
+
// Clear in-memory state first to prevent race with concurrent appends
|
|
311
|
+
this.pendingEntries = [];
|
|
312
|
+
this.entryCount = 0;
|
|
313
|
+
try {
|
|
314
|
+
await this.storage.delete(this.logKey);
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
// Key may not exist
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
//# sourceMappingURL=WriteAheadLog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WriteAheadLog.js","sourceRoot":"","sources":["../../src/storage/WriteAheadLog.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,10 @@ export interface CreateStorageOptions extends StorageOptions {
|
|
|
12
12
|
/** Force a specific storage type */
|
|
13
13
|
type?: StorageType;
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Detect the current runtime environment
|
|
17
|
+
*/
|
|
18
|
+
export declare function detectEnvironment(): 'bun' | 'browser' | 'node' | 'unknown';
|
|
15
19
|
/**
|
|
16
20
|
* Create the optimal storage backend for the current environment
|
|
17
21
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createStorageBackend.d.ts","sourceRoot":"","sources":["../../src/storage/createStorageBackend.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"createStorageBackend.d.ts","sourceRoot":"","sources":["../../src/storage/createStorageBackend.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAMvE,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE7D,MAAM,WAAW,oBAAqB,SAAQ,cAAc;IAC1D,oCAAoC;IACpC,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAiB1E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,CA+ClG;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,WAAW,CAYvD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAajE"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage Backend Factory
|
|
3
|
+
*
|
|
4
|
+
* Auto-detects the best storage backend for the current environment:
|
|
5
|
+
* - Bun/Node.js: BunStorageBackend (file system)
|
|
6
|
+
* - Modern browsers: OPFSBackend (Origin Private File System)
|
|
7
|
+
* - Fallback: MemoryBackend (in-memory)
|
|
8
|
+
*/
|
|
9
|
+
import { BunStorageBackend } from './BunStorageBackend.js';
|
|
10
|
+
import { MemoryBackend } from './MemoryBackend.js';
|
|
11
|
+
import { OPFSBackend } from './OPFSBackend.js';
|
|
12
|
+
import { StorageError } from '../errors.js';
|
|
13
|
+
/**
|
|
14
|
+
* Detect the current runtime environment
|
|
15
|
+
*/
|
|
16
|
+
export function detectEnvironment() {
|
|
17
|
+
// Check for Bun
|
|
18
|
+
if (typeof Bun !== 'undefined') {
|
|
19
|
+
return 'bun';
|
|
20
|
+
}
|
|
21
|
+
// Check for browser
|
|
22
|
+
if (typeof window !== 'undefined' && typeof navigator !== 'undefined') {
|
|
23
|
+
return 'browser';
|
|
24
|
+
}
|
|
25
|
+
// Check for Node.js
|
|
26
|
+
if (typeof process !== 'undefined' && !!process.versions?.node) {
|
|
27
|
+
return 'node';
|
|
28
|
+
}
|
|
29
|
+
return 'unknown';
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Create the optimal storage backend for the current environment
|
|
33
|
+
*
|
|
34
|
+
* @param options Configuration options
|
|
35
|
+
* @returns Initialized storage backend
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* // Auto-detect best backend
|
|
40
|
+
* const storage = await createStorageBackend();
|
|
41
|
+
*
|
|
42
|
+
* // Force specific backend
|
|
43
|
+
* const bunStorage = await createStorageBackend({ type: 'bun', path: './data' });
|
|
44
|
+
* const memStorage = await createStorageBackend({ type: 'memory' });
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export async function createStorageBackend(options) {
|
|
48
|
+
const type = options?.type ?? 'auto';
|
|
49
|
+
// Force specific backend type
|
|
50
|
+
if (type === 'bun') {
|
|
51
|
+
const backend = new BunStorageBackend(options?.path ?? './vectordb_data');
|
|
52
|
+
await backend.init();
|
|
53
|
+
return backend;
|
|
54
|
+
}
|
|
55
|
+
if (type === 'opfs') {
|
|
56
|
+
if (!OPFSBackend.isAvailable()) {
|
|
57
|
+
throw new StorageError('init', 'OPFS not available in this environment');
|
|
58
|
+
}
|
|
59
|
+
const backend = new OPFSBackend();
|
|
60
|
+
await backend.init();
|
|
61
|
+
return backend;
|
|
62
|
+
}
|
|
63
|
+
if (type === 'memory') {
|
|
64
|
+
return new MemoryBackend();
|
|
65
|
+
}
|
|
66
|
+
// Auto-detect
|
|
67
|
+
const env = detectEnvironment();
|
|
68
|
+
if (env === 'bun' || env === 'node') {
|
|
69
|
+
const backend = new BunStorageBackend(options?.path ?? './vectordb_data');
|
|
70
|
+
await backend.init();
|
|
71
|
+
return backend;
|
|
72
|
+
}
|
|
73
|
+
if (env === 'browser') {
|
|
74
|
+
// Try OPFS first (modern browsers)
|
|
75
|
+
if (OPFSBackend.isAvailable()) {
|
|
76
|
+
try {
|
|
77
|
+
const backend = new OPFSBackend();
|
|
78
|
+
await backend.init();
|
|
79
|
+
return backend;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// Fall through to memory backend
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Fallback to memory backend
|
|
87
|
+
return new MemoryBackend();
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Get the recommended storage type for the current environment
|
|
91
|
+
*/
|
|
92
|
+
export function getRecommendedStorageType() {
|
|
93
|
+
const env = detectEnvironment();
|
|
94
|
+
if (env === 'bun' || env === 'node') {
|
|
95
|
+
return 'bun';
|
|
96
|
+
}
|
|
97
|
+
if (env === 'browser' && OPFSBackend.isAvailable()) {
|
|
98
|
+
return 'opfs';
|
|
99
|
+
}
|
|
100
|
+
return 'memory';
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Check if a specific storage type is available
|
|
104
|
+
*/
|
|
105
|
+
export function isStorageTypeAvailable(type) {
|
|
106
|
+
switch (type) {
|
|
107
|
+
case 'bun':
|
|
108
|
+
return typeof Bun !== 'undefined' || (typeof process !== 'undefined' && !!process.versions?.node);
|
|
109
|
+
case 'opfs':
|
|
110
|
+
return OPFSBackend.isAvailable();
|
|
111
|
+
case 'memory':
|
|
112
|
+
return true;
|
|
113
|
+
case 'auto':
|
|
114
|
+
return true;
|
|
115
|
+
default:
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=createStorageBackend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createStorageBackend.js","sourceRoot":"","sources":["../../src/storage/createStorageBackend.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AASzC;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,gBAAgB;IAChB,IAAI,OAAO,GAAG,KAAK,WAAW,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,oBAAoB;IACpB,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,SAAS,KAAK,WAAW,EAAE,CAAC;QACtE,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,oBAAoB;IACpB,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC/D,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAA8B;IACvE,MAAM,IAAI,GAAG,OAAO,EAAE,IAAI,IAAI,MAAM,CAAC;IAErC,8BAA8B;IAC9B,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACnB,MAAM,OAAO,GAAG,IAAI,iBAAiB,CAAC,OAAO,EAAE,IAAI,IAAI,iBAAiB,CAAC,CAAC;QAC1E,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;QACrB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,EAAE,CAAC;YAC/B,MAAM,IAAI,YAAY,CAAC,MAAM,EAAE,wCAAwC,CAAC,CAAC;QAC3E,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAClC,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;QACrB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,OAAO,IAAI,aAAa,EAAE,CAAC;IAC7B,CAAC;IAED,cAAc;IACd,MAAM,GAAG,GAAG,iBAAiB,EAAE,CAAC;IAEhC,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,IAAI,iBAAiB,CAAC,OAAO,EAAE,IAAI,IAAI,iBAAiB,CAAC,CAAC;QAC1E,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;QACrB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,mCAAmC;QACnC,IAAI,WAAW,CAAC,WAAW,EAAE,EAAE,CAAC;YAC9B,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;gBAClC,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;gBACrB,OAAO,OAAO,CAAC;YACjB,CAAC;YAAC,MAAM,CAAC;gBACP,iCAAiC;YACnC,CAAC;QACH,CAAC;IACH,CAAC;IAED,6BAA6B;IAC7B,OAAO,IAAI,aAAa,EAAE,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB;IACvC,MAAM,GAAG,GAAG,iBAAiB,EAAE,CAAC;IAEhC,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACpC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,GAAG,KAAK,SAAS,IAAI,WAAW,CAAC,WAAW,EAAE,EAAE,CAAC;QACnD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAiB;IACtD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,KAAK;YACR,OAAO,OAAO,GAAG,KAAK,WAAW,IAAI,CAAC,OAAO,OAAO,KAAK,WAAW,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACpG,KAAK,MAAM;YACT,OAAO,WAAW,CAAC,WAAW,EAAE,CAAC;QACnC,KAAK,QAAQ;YACX,OAAO,IAAI,CAAC;QACd,KAAK,MAAM;YACT,OAAO,IAAI,CAAC;QACd;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC"}
|
|
@@ -20,34 +20,14 @@
|
|
|
20
20
|
* await wal.flush();
|
|
21
21
|
* ```
|
|
22
22
|
*/
|
|
23
|
-
|
|
24
|
-
// Storage backend interface and types
|
|
25
|
-
export type { StorageBackend, StorageOptions } from './StorageBackend';
|
|
26
|
-
|
|
27
23
|
// Storage backend implementations
|
|
28
|
-
export { BunStorageBackend } from './BunStorageBackend';
|
|
29
|
-
export { MemoryBackend } from './MemoryBackend';
|
|
30
|
-
export { OPFSBackend } from './OPFSBackend';
|
|
31
|
-
|
|
24
|
+
export { BunStorageBackend } from './BunStorageBackend.js';
|
|
25
|
+
export { MemoryBackend } from './MemoryBackend.js';
|
|
26
|
+
export { OPFSBackend } from './OPFSBackend.js';
|
|
32
27
|
// Factory function and utilities
|
|
33
|
-
export {
|
|
34
|
-
createStorageBackend,
|
|
35
|
-
getRecommendedStorageType,
|
|
36
|
-
isStorageTypeAvailable,
|
|
37
|
-
type StorageType,
|
|
38
|
-
type CreateStorageOptions,
|
|
39
|
-
} from './createStorageBackend';
|
|
40
|
-
|
|
28
|
+
export { createStorageBackend, getRecommendedStorageType, isStorageTypeAvailable, } from './createStorageBackend.js';
|
|
41
29
|
// Write-ahead log for incremental updates
|
|
42
|
-
export {
|
|
43
|
-
WriteAheadLog,
|
|
44
|
-
WALOperationType,
|
|
45
|
-
type WALEntry,
|
|
46
|
-
} from './WriteAheadLog';
|
|
47
|
-
|
|
30
|
+
export { WriteAheadLog, WALOperationType, } from './WriteAheadLog.js';
|
|
48
31
|
// Batch write coalescing for reduced I/O
|
|
49
|
-
export {
|
|
50
|
-
|
|
51
|
-
createBatchWriter,
|
|
52
|
-
type BatchWriterOptions,
|
|
53
|
-
} from './BatchWriter';
|
|
32
|
+
export { BatchWriter, createBatchWriter, } from './BatchWriter.js';
|
|
33
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAKH,kCAAkC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,iCAAiC;AACjC,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,sBAAsB,GAGvB,MAAM,wBAAwB,CAAC;AAEhC,0CAA0C;AAC1C,OAAO,EACL,aAAa,EACb,gBAAgB,GAEjB,MAAM,iBAAiB,CAAC;AAEzB,yCAAyC;AACzC,OAAO,EACL,WAAW,EACX,iBAAiB,GAElB,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare function resolveBasePath(basePath: string): string;
|
|
2
|
+
export declare function resolveStoragePath(basePath: string, key: string): string;
|
|
3
|
+
export declare function dirname(fullPath: string): string;
|
|
4
|
+
export declare function ensureDir(dir: string): Promise<void>;
|
|
5
|
+
export declare function read(fullPath: string): Promise<ArrayBuffer | null>;
|
|
6
|
+
export declare function writeAtomic(fullPath: string, data: ArrayBuffer | Uint8Array): Promise<void>;
|
|
7
|
+
export declare function append(fullPath: string, data: ArrayBuffer | Uint8Array): Promise<void>;
|
|
8
|
+
export declare function deleteFile(fullPath: string): Promise<void>;
|
|
9
|
+
export declare function exists(fullPath: string): Promise<boolean>;
|
|
10
|
+
export declare function list(basePath: string, searchPath: string): Promise<string[]>;
|
|
11
|
+
export declare function clear(basePath: string): Promise<string>;
|
|
12
|
+
export declare function size(fullPath: string): Promise<number>;
|
|
13
|
+
export declare function stream(fullPath: string): ReadableStream<Uint8Array>;
|
|
14
|
+
//# sourceMappingURL=nodeFsRuntime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodeFsRuntime.d.ts","sourceRoot":"","sources":["../../src/storage/nodeFsRuntime.ts"],"names":[],"mappings":"AAMA,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAOxE;AAED,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1D;AAED,wBAAsB,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAUxE;AAED,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAIjG;AAED,wBAAsB,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAG5F;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQhE;AAED,wBAAsB,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAU/D;AAED,wBAAsB,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAelF;AAED,wBAAsB,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAK7D;AAED,wBAAsB,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAU5D;AAED,wBAAgB,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,CAEnE"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { mkdir, readdir, unlink, rm, appendFile, rename, readFile, writeFile, stat } from 'node:fs/promises';
|
|
2
|
+
import { createReadStream } from 'node:fs';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { Readable } from 'node:stream';
|
|
5
|
+
import { StorageError } from '../errors.js';
|
|
6
|
+
export function resolveBasePath(basePath) {
|
|
7
|
+
return path.resolve(basePath);
|
|
8
|
+
}
|
|
9
|
+
export function resolveStoragePath(basePath, key) {
|
|
10
|
+
const fullPath = path.resolve(basePath, key);
|
|
11
|
+
const resolvedBase = resolveBasePath(basePath);
|
|
12
|
+
if (!fullPath.startsWith(resolvedBase + path.sep) && fullPath !== resolvedBase) {
|
|
13
|
+
throw new StorageError('validate', `Path traversal detected: key '${key}' resolves outside storage directory`);
|
|
14
|
+
}
|
|
15
|
+
return fullPath;
|
|
16
|
+
}
|
|
17
|
+
export function dirname(fullPath) {
|
|
18
|
+
return path.dirname(fullPath);
|
|
19
|
+
}
|
|
20
|
+
export async function ensureDir(dir) {
|
|
21
|
+
await mkdir(dir, { recursive: true });
|
|
22
|
+
}
|
|
23
|
+
export async function read(fullPath) {
|
|
24
|
+
try {
|
|
25
|
+
const data = await readFile(fullPath);
|
|
26
|
+
return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
if (err?.code === 'ENOENT') {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
throw err;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export async function writeAtomic(fullPath, data) {
|
|
36
|
+
const tmpPath = fullPath + '.tmp';
|
|
37
|
+
await writeFile(tmpPath, data instanceof ArrayBuffer ? new Uint8Array(data) : data);
|
|
38
|
+
await rename(tmpPath, fullPath);
|
|
39
|
+
}
|
|
40
|
+
export async function append(fullPath, data) {
|
|
41
|
+
const appendData = data instanceof ArrayBuffer ? new Uint8Array(data) : data;
|
|
42
|
+
await appendFile(fullPath, appendData);
|
|
43
|
+
}
|
|
44
|
+
export async function deleteFile(fullPath) {
|
|
45
|
+
try {
|
|
46
|
+
await unlink(fullPath);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
if (err?.code !== 'ENOENT') {
|
|
50
|
+
throw err;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export async function exists(fullPath) {
|
|
55
|
+
try {
|
|
56
|
+
await stat(fullPath);
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
if (err?.code === 'ENOENT') {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
throw err;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export async function list(basePath, searchPath) {
|
|
67
|
+
try {
|
|
68
|
+
const entries = await readdir(searchPath, { recursive: true, withFileTypes: true });
|
|
69
|
+
const resolvedBase = resolveBasePath(basePath);
|
|
70
|
+
const results = [];
|
|
71
|
+
for (const entry of entries) {
|
|
72
|
+
if (!entry.isFile())
|
|
73
|
+
continue;
|
|
74
|
+
const entryDir = entry.parentPath ?? entry.path ?? searchPath;
|
|
75
|
+
const fullPath = path.join(entryDir, entry.name);
|
|
76
|
+
results.push(path.relative(resolvedBase, fullPath));
|
|
77
|
+
}
|
|
78
|
+
return results;
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
export async function clear(basePath) {
|
|
85
|
+
const resolvedBase = resolveBasePath(basePath);
|
|
86
|
+
await rm(resolvedBase, { recursive: true, force: true }).catch(() => { });
|
|
87
|
+
await mkdir(resolvedBase, { recursive: true }).catch(() => { });
|
|
88
|
+
return resolvedBase;
|
|
89
|
+
}
|
|
90
|
+
export async function size(fullPath) {
|
|
91
|
+
try {
|
|
92
|
+
const stats = await stat(fullPath);
|
|
93
|
+
return stats.size;
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
if (err?.code === 'ENOENT') {
|
|
97
|
+
return 0;
|
|
98
|
+
}
|
|
99
|
+
throw err;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
export function stream(fullPath) {
|
|
103
|
+
return Readable.toWeb(createReadStream(fullPath));
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=nodeFsRuntime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodeFsRuntime.js","sourceRoot":"","sources":["../../src/storage/nodeFsRuntime.ts"],"names":[],"mappings":"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"}
|