verso-db 0.1.4 → 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.
Files changed (110) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +81 -49
  3. package/dist/BinaryHeap.d.ts +16 -5
  4. package/dist/BinaryHeap.d.ts.map +1 -1
  5. package/dist/BinaryHeap.js +138 -0
  6. package/dist/BinaryHeap.js.map +1 -0
  7. package/dist/Collection.d.ts +98 -17
  8. package/dist/Collection.d.ts.map +1 -1
  9. package/dist/Collection.js +1186 -0
  10. package/dist/Collection.js.map +1 -0
  11. package/dist/HNSWIndex.d.ts +170 -15
  12. package/dist/HNSWIndex.d.ts.map +1 -1
  13. package/dist/HNSWIndex.js +2818 -0
  14. package/dist/HNSWIndex.js.map +1 -0
  15. package/dist/MaxBinaryHeap.d.ts +2 -60
  16. package/dist/MaxBinaryHeap.d.ts.map +1 -1
  17. package/dist/MaxBinaryHeap.js +5 -0
  18. package/dist/MaxBinaryHeap.js.map +1 -0
  19. package/dist/SearchWorker.d.ts +104 -0
  20. package/dist/SearchWorker.d.ts.map +1 -0
  21. package/dist/SearchWorker.js +573 -0
  22. package/dist/SearchWorker.js.map +1 -0
  23. package/dist/VectorDB.d.ts +19 -5
  24. package/dist/VectorDB.d.ts.map +1 -1
  25. package/dist/VectorDB.js +246 -0
  26. package/dist/VectorDB.js.map +1 -0
  27. package/dist/WorkerPool.d.ts +92 -0
  28. package/dist/WorkerPool.d.ts.map +1 -0
  29. package/dist/WorkerPool.js +266 -0
  30. package/dist/WorkerPool.js.map +1 -0
  31. package/dist/backends/JsDistanceBackend.d.ts +3 -20
  32. package/dist/backends/JsDistanceBackend.d.ts.map +1 -1
  33. package/dist/backends/JsDistanceBackend.js +163 -0
  34. package/dist/backends/JsDistanceBackend.js.map +1 -0
  35. package/dist/encoding/DeltaEncoder.d.ts +2 -2
  36. package/dist/encoding/DeltaEncoder.d.ts.map +1 -1
  37. package/dist/encoding/DeltaEncoder.js +199 -0
  38. package/dist/encoding/DeltaEncoder.js.map +1 -0
  39. package/dist/errors.js +97 -0
  40. package/dist/errors.js.map +1 -0
  41. package/dist/index.d.ts +16 -17
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +61 -3419
  44. package/dist/index.js.map +1 -0
  45. package/dist/presets.d.ts +9 -9
  46. package/dist/presets.d.ts.map +1 -1
  47. package/dist/presets.js +205 -0
  48. package/dist/presets.js.map +1 -0
  49. package/dist/quantization/ScalarQuantizer.d.ts +10 -34
  50. package/dist/quantization/ScalarQuantizer.d.ts.map +1 -1
  51. package/dist/quantization/ScalarQuantizer.js +346 -0
  52. package/dist/quantization/ScalarQuantizer.js.map +1 -0
  53. package/dist/storage/BatchWriter.d.ts.map +1 -1
  54. package/dist/storage/BatchWriter.js +351 -0
  55. package/dist/storage/BatchWriter.js.map +1 -0
  56. package/dist/storage/BunStorageBackend.d.ts +12 -5
  57. package/dist/storage/BunStorageBackend.d.ts.map +1 -1
  58. package/dist/storage/BunStorageBackend.js +182 -0
  59. package/dist/storage/BunStorageBackend.js.map +1 -0
  60. package/dist/storage/MemoryBackend.d.ts.map +1 -1
  61. package/dist/storage/MemoryBackend.js +109 -0
  62. package/dist/storage/MemoryBackend.js.map +1 -0
  63. package/dist/storage/OPFSBackend.d.ts +9 -1
  64. package/dist/storage/OPFSBackend.d.ts.map +1 -1
  65. package/dist/storage/OPFSBackend.js +325 -0
  66. package/dist/storage/OPFSBackend.js.map +1 -0
  67. package/dist/storage/StorageBackend.d.ts +1 -1
  68. package/dist/storage/StorageBackend.js +12 -0
  69. package/dist/storage/StorageBackend.js.map +1 -0
  70. package/dist/storage/WriteAheadLog.d.ts +15 -11
  71. package/dist/storage/WriteAheadLog.d.ts.map +1 -1
  72. package/dist/storage/WriteAheadLog.js +321 -0
  73. package/dist/storage/WriteAheadLog.js.map +1 -0
  74. package/dist/storage/createStorageBackend.d.ts +4 -0
  75. package/dist/storage/createStorageBackend.d.ts.map +1 -1
  76. package/dist/storage/createStorageBackend.js +119 -0
  77. package/dist/storage/createStorageBackend.js.map +1 -0
  78. package/dist/storage/index.d.ts +3 -3
  79. package/dist/storage/index.js +33 -0
  80. package/dist/storage/index.js.map +1 -0
  81. package/dist/storage/nodeFsRuntime.d.ts +14 -0
  82. package/dist/storage/nodeFsRuntime.d.ts.map +1 -0
  83. package/dist/storage/nodeFsRuntime.js +105 -0
  84. package/dist/storage/nodeFsRuntime.js.map +1 -0
  85. package/package.json +47 -23
  86. package/dist/Storage.d.ts +0 -54
  87. package/dist/Storage.d.ts.map +0 -1
  88. package/dist/backends/DistanceBackend.d.ts +0 -5
  89. package/dist/backends/DistanceBackend.d.ts.map +0 -1
  90. package/src/BinaryHeap.ts +0 -131
  91. package/src/Collection.ts +0 -695
  92. package/src/HNSWIndex.ts +0 -1839
  93. package/src/MaxBinaryHeap.ts +0 -175
  94. package/src/Storage.ts +0 -435
  95. package/src/VectorDB.ts +0 -109
  96. package/src/backends/DistanceBackend.ts +0 -17
  97. package/src/backends/JsDistanceBackend.ts +0 -227
  98. package/src/encoding/DeltaEncoder.ts +0 -217
  99. package/src/errors.ts +0 -110
  100. package/src/index.ts +0 -138
  101. package/src/presets.ts +0 -229
  102. package/src/quantization/ScalarQuantizer.ts +0 -383
  103. package/src/storage/BatchWriter.ts +0 -336
  104. package/src/storage/BunStorageBackend.ts +0 -161
  105. package/src/storage/MemoryBackend.ts +0 -120
  106. package/src/storage/OPFSBackend.ts +0 -250
  107. package/src/storage/StorageBackend.ts +0 -74
  108. package/src/storage/WriteAheadLog.ts +0 -326
  109. package/src/storage/createStorageBackend.ts +0 -137
  110. package/src/storage/index.ts +0 -53
@@ -0,0 +1,109 @@
1
+ /**
2
+ * In-Memory Storage Backend
3
+ *
4
+ * Stores all data in memory using a Map. Useful for:
5
+ * - Testing without file system
6
+ * - Small datasets that fit in memory
7
+ * - Browser environments without OPFS/IndexedDB
8
+ * - Temporary caches
9
+ */
10
+ export class MemoryBackend {
11
+ type = 'memory';
12
+ storage = new Map();
13
+ directories = new Set();
14
+ constructor() {
15
+ this.directories.add(''); // Root directory always exists
16
+ }
17
+ async read(key) {
18
+ const data = this.storage.get(key);
19
+ if (!data)
20
+ return null;
21
+ // Return a copy to prevent mutation
22
+ return data.slice(0);
23
+ }
24
+ async write(key, data) {
25
+ // Store a copy to prevent external mutation
26
+ const buffer = data instanceof ArrayBuffer ? data : data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
27
+ this.storage.set(key, buffer.slice(0));
28
+ }
29
+ async append(key, data) {
30
+ const appendData = data instanceof ArrayBuffer ? new Uint8Array(data) : data;
31
+ const existing = this.storage.get(key);
32
+ if (existing) {
33
+ const existingArray = new Uint8Array(existing);
34
+ const combined = new Uint8Array(existingArray.length + appendData.length);
35
+ combined.set(existingArray, 0);
36
+ combined.set(appendData, existingArray.length);
37
+ this.storage.set(key, combined.buffer.slice(0));
38
+ }
39
+ else {
40
+ this.storage.set(key, appendData.buffer.slice(appendData.byteOffset, appendData.byteOffset + appendData.byteLength));
41
+ }
42
+ }
43
+ async delete(key) {
44
+ this.storage.delete(key);
45
+ }
46
+ async exists(key) {
47
+ return this.storage.has(key);
48
+ }
49
+ async list(prefix) {
50
+ const keys = [];
51
+ // Match BunStorageBackend/OPFSBackend semantics: prefix is a directory path
52
+ const dirPrefix = prefix ? (prefix.endsWith('/') ? prefix : prefix + '/') : '';
53
+ for (const key of this.storage.keys()) {
54
+ if (!dirPrefix || key.startsWith(dirPrefix)) {
55
+ keys.push(key);
56
+ }
57
+ }
58
+ return keys;
59
+ }
60
+ async mkdir(path) {
61
+ this.directories.add(path);
62
+ // Also add parent directories
63
+ const parts = path.split('/');
64
+ for (let i = 1; i <= parts.length; i++) {
65
+ this.directories.add(parts.slice(0, i).join('/'));
66
+ }
67
+ }
68
+ /**
69
+ * Clear all data
70
+ */
71
+ clear() {
72
+ this.storage.clear();
73
+ this.directories.clear();
74
+ this.directories.add('');
75
+ }
76
+ /**
77
+ * Get memory usage statistics
78
+ */
79
+ getStats() {
80
+ let totalBytes = 0;
81
+ for (const value of this.storage.values()) {
82
+ totalBytes += value.byteLength;
83
+ }
84
+ return {
85
+ keyCount: this.storage.size,
86
+ totalBytes,
87
+ };
88
+ }
89
+ /**
90
+ * Export all data as a serializable object
91
+ * Useful for debugging or saving state
92
+ */
93
+ export() {
94
+ const result = {};
95
+ for (const [key, value] of this.storage.entries()) {
96
+ result[key] = value.slice(0);
97
+ }
98
+ return result;
99
+ }
100
+ /**
101
+ * Import data from a serializable object
102
+ */
103
+ import(data) {
104
+ for (const [key, value] of Object.entries(data)) {
105
+ this.storage.set(key, value.slice(0));
106
+ }
107
+ }
108
+ }
109
+ //# sourceMappingURL=MemoryBackend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MemoryBackend.js","sourceRoot":"","sources":["../../src/storage/MemoryBackend.ts"],"names":[],"mappings":"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"}
@@ -23,15 +23,22 @@ export declare class OPFSBackend implements StorageBackend {
23
23
  readonly type = "opfs";
24
24
  private root;
25
25
  private initialized;
26
+ private initPromise;
27
+ private appendLocks;
26
28
  /**
27
29
  * Initialize the OPFS backend (optional - auto-initializes on first operation)
28
30
  * @deprecated No longer required - operations auto-initialize
29
31
  */
30
32
  init(): Promise<void>;
33
+ private doInit;
31
34
  /**
32
- * Ensure backend is initialized (lazy init on first use)
35
+ * Ensure backend is initialized (lazy init on first use).
36
+ * Safe to call concurrently — only runs initialization once.
33
37
  */
34
38
  private ensureInitialized;
39
+ private isNotFoundError;
40
+ private formatError;
41
+ private validateAndSplitPath;
35
42
  /**
36
43
  * Get a file handle, creating parent directories as needed
37
44
  */
@@ -43,6 +50,7 @@ export declare class OPFSBackend implements StorageBackend {
43
50
  read(key: string): Promise<ArrayBuffer | null>;
44
51
  write(key: string, data: ArrayBuffer | Uint8Array): Promise<void>;
45
52
  append(key: string, data: ArrayBuffer | Uint8Array): Promise<void>;
53
+ private doAppend;
46
54
  delete(key: string): Promise<void>;
47
55
  exists(key: string): Promise<boolean>;
48
56
  list(prefix?: string): Promise<string[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"OPFSBackend.d.ts","sourceRoot":"","sources":["../../src/storage/OPFSBackend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,qBAAa,WAAY,YAAW,cAAc;IAChD,QAAQ,CAAC,IAAI,UAAU;IACvB,OAAO,CAAC,IAAI,CAA0C;IACtD,OAAO,CAAC,WAAW,CAAkB;IAErC;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B;;OAEG;YACW,iBAAiB;IAM/B;;OAEG;YACW,aAAa;IA0B3B;;OAEG;YACW,kBAAkB;IAkB1B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAc9C,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBjE,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAkClE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAyBlC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAOrC,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA0BxC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKxC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B;;OAEG;IACH,MAAM,CAAC,WAAW,IAAI,OAAO;CAG9B"}
1
+ {"version":3,"file":"OPFSBackend.d.ts","sourceRoot":"","sources":["../../src/storage/OPFSBackend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGvD,qBAAa,WAAY,YAAW,cAAc;IAChD,QAAQ,CAAC,IAAI,UAAU;IACvB,OAAO,CAAC,IAAI,CAA0C;IACtD,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,WAAW,CAAyC;IAE5D;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAIb,MAAM;IAWpB;;;OAGG;YACW,iBAAiB;IAY/B,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,oBAAoB;IA8B5B;;OAEG;YACW,aAAa;IA0B3B;;OAEG;YACW,kBAAkB;IAkB1B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAe9C,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBjE,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;YAmB1D,QAAQ;IAqChB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BlC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAOrC,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA6BxC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMxC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAa5B;;OAEG;IACH,MAAM,CAAC,WAAW,IAAI,OAAO;CAG9B"}
@@ -0,0 +1,325 @@
1
+ /**
2
+ * Origin Private File System (OPFS) Storage Backend
3
+ *
4
+ * High-performance browser storage using the File System Access API.
5
+ * OPFS provides file-like semantics with significantly better performance
6
+ * than IndexedDB for large binary data (up to 10x faster).
7
+ *
8
+ * Features:
9
+ * - Auto-initializing (no manual init() required)
10
+ * - High performance for large binary data
11
+ *
12
+ * Browser Support:
13
+ * - Chrome 86+
14
+ * - Safari 15.2+
15
+ * - Firefox 111+
16
+ * - Edge 86+
17
+ *
18
+ * Note: This module is designed for browser environments only.
19
+ * It will not work in Node.js/Bun server environments.
20
+ */
21
+ import { StorageError } from '../errors.js';
22
+ export class OPFSBackend {
23
+ type = 'opfs';
24
+ root = null;
25
+ initialized = false;
26
+ initPromise = null;
27
+ appendLocks = new Map();
28
+ /**
29
+ * Initialize the OPFS backend (optional - auto-initializes on first operation)
30
+ * @deprecated No longer required - operations auto-initialize
31
+ */
32
+ async init() {
33
+ return this.doInit();
34
+ }
35
+ async doInit() {
36
+ if (this.initialized)
37
+ return;
38
+ if (typeof navigator === 'undefined' || !navigator.storage?.getDirectory) {
39
+ throw new StorageError('init', 'OPFS not available in this environment. Use MemoryBackend or IndexedDBBackend instead.');
40
+ }
41
+ this.root = await navigator.storage.getDirectory();
42
+ this.initialized = true;
43
+ }
44
+ /**
45
+ * Ensure backend is initialized (lazy init on first use).
46
+ * Safe to call concurrently — only runs initialization once.
47
+ */
48
+ async ensureInitialized() {
49
+ if (this.initialized)
50
+ return;
51
+ if (!this.initPromise) {
52
+ this.initPromise = this.doInit().catch((err) => {
53
+ // Allow retry after transient initialization failures
54
+ this.initPromise = null;
55
+ throw err;
56
+ });
57
+ }
58
+ return this.initPromise;
59
+ }
60
+ isNotFoundError(err) {
61
+ return (!!err &&
62
+ typeof err === 'object' &&
63
+ 'name' in err &&
64
+ err.name === 'NotFoundError');
65
+ }
66
+ formatError(err) {
67
+ if (err instanceof Error) {
68
+ return err.message;
69
+ }
70
+ return String(err);
71
+ }
72
+ validateAndSplitPath(path, allowEmpty) {
73
+ if (typeof path !== 'string') {
74
+ throw new StorageError('validate', 'Path must be a string');
75
+ }
76
+ if (path.includes('\0')) {
77
+ throw new StorageError('validate', `Invalid path '${path}': contains null byte`);
78
+ }
79
+ if (path.length === 0) {
80
+ if (allowEmpty)
81
+ return [];
82
+ throw new StorageError('validate', 'Invalid path: empty path is not allowed');
83
+ }
84
+ const parts = [];
85
+ for (const part of path.split('/')) {
86
+ if (part === '')
87
+ continue;
88
+ if (part === '.' || part === '..') {
89
+ throw new StorageError('validate', `Path traversal detected: '${path}' contains '${part}' segment`);
90
+ }
91
+ if (part.includes('\\')) {
92
+ throw new StorageError('validate', `Invalid path '${path}': backslashes are not allowed`);
93
+ }
94
+ parts.push(part);
95
+ }
96
+ if (!allowEmpty && parts.length === 0) {
97
+ throw new StorageError('validate', `Invalid path '${path}': no file name`);
98
+ }
99
+ return parts;
100
+ }
101
+ /**
102
+ * Get a file handle, creating parent directories as needed
103
+ */
104
+ async getFileHandle(key, create = false) {
105
+ await this.ensureInitialized();
106
+ const parts = this.validateAndSplitPath(key, false);
107
+ const fileName = parts.pop();
108
+ // Navigate/create directories
109
+ let currentDir = this.root;
110
+ for (const part of parts) {
111
+ try {
112
+ currentDir = await currentDir.getDirectoryHandle(part, { create });
113
+ }
114
+ catch (err) {
115
+ if (!create && this.isNotFoundError(err))
116
+ return null;
117
+ throw new StorageError('read', `Failed to access directory '${part}' for '${key}': ${this.formatError(err)}`, key);
118
+ }
119
+ }
120
+ // Get file handle
121
+ try {
122
+ return await currentDir.getFileHandle(fileName, { create });
123
+ }
124
+ catch (err) {
125
+ if (!create && this.isNotFoundError(err))
126
+ return null;
127
+ throw new StorageError('read', `Failed to access file '${key}': ${this.formatError(err)}`, key);
128
+ }
129
+ }
130
+ /**
131
+ * Get a directory handle, creating if needed
132
+ */
133
+ async getDirectoryHandle(path, create = false) {
134
+ await this.ensureInitialized();
135
+ const parts = this.validateAndSplitPath(path, true);
136
+ let currentDir = this.root;
137
+ for (const part of parts) {
138
+ try {
139
+ currentDir = await currentDir.getDirectoryHandle(part, { create });
140
+ }
141
+ catch (err) {
142
+ if (!create && this.isNotFoundError(err))
143
+ return null;
144
+ throw new StorageError('list', `Failed to access directory '${path}': ${this.formatError(err)}`, path);
145
+ }
146
+ }
147
+ return currentDir;
148
+ }
149
+ async read(key) {
150
+ await this.ensureInitialized();
151
+ const handle = await this.getFileHandle(key, false);
152
+ if (!handle)
153
+ return null;
154
+ try {
155
+ const file = await handle.getFile();
156
+ return file.arrayBuffer();
157
+ }
158
+ catch (err) {
159
+ if (this.isNotFoundError(err))
160
+ return null;
161
+ throw new StorageError('read', `Failed to read file '${key}': ${this.formatError(err)}`, key);
162
+ }
163
+ }
164
+ async write(key, data) {
165
+ await this.ensureInitialized();
166
+ const handle = await this.getFileHandle(key, true);
167
+ if (!handle) {
168
+ throw new StorageError('write', `Failed to create file: ${key}`, key);
169
+ }
170
+ const writable = await handle.createWritable();
171
+ try {
172
+ // Convert to ArrayBuffer for FileSystemWriteChunkType compatibility
173
+ const writeData = data instanceof ArrayBuffer ? data : data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
174
+ await writable.write(writeData);
175
+ await writable.close();
176
+ }
177
+ catch (err) {
178
+ // Abort on error to discard the temp file — close() would commit partial data
179
+ try {
180
+ await writable.abort();
181
+ }
182
+ catch { /* abort best-effort */ }
183
+ throw err;
184
+ }
185
+ }
186
+ async append(key, data) {
187
+ // Serialize appends per-key to prevent TOCTOU race condition
188
+ // (concurrent appends reading the same file size would overwrite each other)
189
+ const prev = this.appendLocks.get(key) ?? Promise.resolve();
190
+ let resolve;
191
+ const lock = new Promise(r => { resolve = r; });
192
+ this.appendLocks.set(key, lock);
193
+ try {
194
+ await prev;
195
+ await this.doAppend(key, data);
196
+ }
197
+ finally {
198
+ resolve();
199
+ if (this.appendLocks.get(key) === lock) {
200
+ this.appendLocks.delete(key);
201
+ }
202
+ }
203
+ }
204
+ async doAppend(key, data) {
205
+ await this.ensureInitialized();
206
+ const handle = await this.getFileHandle(key, true);
207
+ if (!handle) {
208
+ throw new StorageError('write', `Failed to create file: ${key}`, key);
209
+ }
210
+ const appendData = data instanceof ArrayBuffer ? new Uint8Array(data) : data;
211
+ // Get current file size to seek to end
212
+ let existingSize = 0;
213
+ try {
214
+ const file = await handle.getFile();
215
+ existingSize = file.size;
216
+ }
217
+ catch {
218
+ existingSize = 0;
219
+ }
220
+ // Use keepExistingData: true for O(1) append (no full read required)
221
+ // Then seek to end and write only new data
222
+ const writable = await handle.createWritable({ keepExistingData: true });
223
+ try {
224
+ // Seek to end of file
225
+ await writable.seek(existingSize);
226
+ // Write only the new data - O(data.length) not O(existingSize + data.length)
227
+ // Convert to ArrayBuffer for FileSystemWriteChunkType compatibility
228
+ const writeData = appendData.buffer.slice(appendData.byteOffset, appendData.byteOffset + appendData.byteLength);
229
+ await writable.write(writeData);
230
+ await writable.close();
231
+ }
232
+ catch (err) {
233
+ // Abort on error to discard the temp file — close() would commit partial/corrupt data
234
+ try {
235
+ await writable.abort();
236
+ }
237
+ catch { /* abort best-effort */ }
238
+ throw err;
239
+ }
240
+ }
241
+ async delete(key) {
242
+ await this.ensureInitialized();
243
+ const parts = this.validateAndSplitPath(key, false);
244
+ const fileName = parts.pop();
245
+ // Navigate to parent directory
246
+ let currentDir = this.root;
247
+ for (const part of parts) {
248
+ try {
249
+ currentDir = await currentDir.getDirectoryHandle(part, { create: false });
250
+ }
251
+ catch (err) {
252
+ if (this.isNotFoundError(err)) {
253
+ return; // Parent doesn't exist, nothing to delete
254
+ }
255
+ throw new StorageError('delete', `Failed to access directory for '${key}': ${this.formatError(err)}`, key);
256
+ }
257
+ }
258
+ // Remove the file
259
+ try {
260
+ await currentDir.removeEntry(fileName);
261
+ }
262
+ catch (err) {
263
+ if (this.isNotFoundError(err)) {
264
+ return; // Parent doesn't exist, nothing to delete
265
+ }
266
+ throw new StorageError('delete', `Failed to delete '${key}': ${this.formatError(err)}`, key);
267
+ }
268
+ }
269
+ async exists(key) {
270
+ await this.ensureInitialized();
271
+ const handle = await this.getFileHandle(key, false);
272
+ return handle !== null;
273
+ }
274
+ async list(prefix) {
275
+ await this.ensureInitialized();
276
+ const results = [];
277
+ const basePath = prefix ?? '';
278
+ if (basePath.length > 0) {
279
+ this.validateAndSplitPath(basePath, true);
280
+ }
281
+ const dir = basePath ? await this.getDirectoryHandle(basePath, false) : this.root;
282
+ if (!dir)
283
+ return results;
284
+ // Recursive list
285
+ const listDir = async (dirHandle, pathPrefix) => {
286
+ for await (const entry of dirHandle.values()) {
287
+ const entryPath = pathPrefix ? `${pathPrefix}/${entry.name}` : entry.name;
288
+ if (entry.kind === 'file') {
289
+ results.push(entryPath);
290
+ }
291
+ else if (entry.kind === 'directory') {
292
+ await listDir(entry, entryPath);
293
+ }
294
+ }
295
+ };
296
+ await listDir(dir, basePath);
297
+ return results;
298
+ }
299
+ async mkdir(path) {
300
+ await this.ensureInitialized();
301
+ this.validateAndSplitPath(path, true);
302
+ await this.getDirectoryHandle(path, true);
303
+ }
304
+ /**
305
+ * Clear all data in OPFS
306
+ */
307
+ async clear() {
308
+ await this.ensureInitialized();
309
+ // Collect entry names first to avoid modifying directory during iteration
310
+ const names = [];
311
+ for await (const entry of this.root.values()) {
312
+ names.push(entry.name);
313
+ }
314
+ for (const name of names) {
315
+ await this.root.removeEntry(name, { recursive: true });
316
+ }
317
+ }
318
+ /**
319
+ * Check if OPFS is available in the current environment
320
+ */
321
+ static isAvailable() {
322
+ return typeof navigator !== 'undefined' && !!navigator.storage?.getDirectory;
323
+ }
324
+ }
325
+ //# sourceMappingURL=OPFSBackend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OPFSBackend.js","sourceRoot":"","sources":["../../src/storage/OPFSBackend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,OAAO,WAAW;IACb,IAAI,GAAG,MAAM,CAAC;IACf,IAAI,GAAqC,IAAI,CAAC;IAC9C,WAAW,GAAY,KAAK,CAAC;IAC7B,WAAW,GAAyB,IAAI,CAAC;IACzC,WAAW,GAA+B,IAAI,GAAG,EAAE,CAAC;IAE5D;;;OAGG;IACH,KAAK,CAAC,IAAI;QACR,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;IACvB,CAAC;IAEO,KAAK,CAAC,MAAM;QAClB,IAAI,IAAI,CAAC,WAAW;YAAE,OAAO;QAE7B,IAAI,OAAO,SAAS,KAAK,WAAW,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC;YACzE,MAAM,IAAI,YAAY,CAAC,MAAM,EAAE,wFAAwF,CAAC,CAAC;QAC3H,CAAC;QAED,IAAI,CAAC,IAAI,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;QACnD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC1B,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,iBAAiB;QAC7B,IAAI,IAAI,CAAC,WAAW;YAAE,OAAO;QAC7B,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBAC7C,sDAAsD;gBACtD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;gBACxB,MAAM,GAAG,CAAC;YACZ,CAAC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAEO,eAAe,CAAC,GAAY;QAClC,OAAO,CACL,CAAC,CAAC,GAAG;YACL,OAAO,GAAG,KAAK,QAAQ;YACvB,MAAM,IAAI,GAAG;YACZ,GAAW,CAAC,IAAI,KAAK,eAAe,CACtC,CAAC;IACJ,CAAC;IAEO,WAAW,CAAC,GAAY;QAC9B,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;YACzB,OAAO,GAAG,CAAC,OAAO,CAAC;QACrB,CAAC;QACD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IAEO,oBAAoB,CAAC,IAAY,EAAE,UAAmB;QAC5D,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,MAAM,IAAI,YAAY,CAAC,UAAU,EAAE,uBAAuB,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,YAAY,CAAC,UAAU,EAAE,iBAAiB,IAAI,uBAAuB,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,IAAI,UAAU;gBAAE,OAAO,EAAE,CAAC;YAC1B,MAAM,IAAI,YAAY,CAAC,UAAU,EAAE,yCAAyC,CAAC,CAAC;QAChF,CAAC;QAED,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YACnC,IAAI,IAAI,KAAK,EAAE;gBAAE,SAAS;YAC1B,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAClC,MAAM,IAAI,YAAY,CAAC,UAAU,EAAE,6BAA6B,IAAI,eAAe,IAAI,WAAW,CAAC,CAAC;YACtG,CAAC;YACD,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,MAAM,IAAI,YAAY,CAAC,UAAU,EAAE,iBAAiB,IAAI,gCAAgC,CAAC,CAAC;YAC5F,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;QAED,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,YAAY,CAAC,UAAU,EAAE,iBAAiB,IAAI,iBAAiB,CAAC,CAAC;QAC7E,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,aAAa,CAAC,GAAW,EAAE,SAAkB,KAAK;QAC9D,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE/B,MAAM,KAAK,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAG,CAAC;QAE9B,8BAA8B;QAC9B,IAAI,UAAU,GAAG,IAAI,CAAC,IAAK,CAAC;QAC5B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,UAAU,GAAG,MAAM,UAAU,CAAC,kBAAkB,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YACrE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC;oBAAE,OAAO,IAAI,CAAC;gBACtD,MAAM,IAAI,YAAY,CAAC,MAAM,EAAE,+BAA+B,IAAI,UAAU,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YACrH,CAAC;QACH,CAAC;QAED,kBAAkB;QAClB,IAAI,CAAC;YACH,OAAO,MAAM,UAAU,CAAC,aAAa,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAC9D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC;YACtD,MAAM,IAAI,YAAY,CAAC,MAAM,EAAE,0BAA0B,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAClG,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,kBAAkB,CAAC,IAAY,EAAE,SAAkB,KAAK;QACpE,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE/B,MAAM,KAAK,GAAG,IAAI,CAAC,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAEpD,IAAI,UAAU,GAAG,IAAI,CAAC,IAAK,CAAC;QAC5B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,UAAU,GAAG,MAAM,UAAU,CAAC,kBAAkB,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YACrE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC;oBAAE,OAAO,IAAI,CAAC;gBACtD,MAAM,IAAI,YAAY,CAAC,MAAM,EAAE,+BAA+B,IAAI,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YACzG,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAW;QACpB,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAEzB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;QAC5B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC;YAC3C,MAAM,IAAI,YAAY,CAAC,MAAM,EAAE,wBAAwB,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,GAAW,EAAE,IAA8B;QACrD,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,0BAA0B,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,cAAc,EAAE,CAAC;QAC/C,IAAI,CAAC;YACH,oEAAoE;YACpE,MAAM,SAAS,GAAG,IAAI,YAAY,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAgB,CAAC;YAC5I,MAAM,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YAChC,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;QACzB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,8EAA8E;YAC9E,IAAI,CAAC;gBAAC,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,uBAAuB,CAAC,CAAC;YACjE,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW,EAAE,IAA8B;QACtD,6DAA6D;QAC7D,6EAA6E;QAC7E,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QAC5D,IAAI,OAAmB,CAAC;QACxB,MAAM,IAAI,GAAG,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACtD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAEhC,IAAI,CAAC;YACH,MAAM,IAAI,CAAC;YACX,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACjC,CAAC;gBAAS,CAAC;YACT,OAAQ,EAAE,CAAC;YACX,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;gBACvC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,GAAW,EAAE,IAA8B;QAChE,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,0BAA0B,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,YAAY,WAAW,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAE7E,uCAAuC;QACvC,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;YACpC,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,YAAY,GAAG,CAAC,CAAC;QACnB,CAAC;QAED,qEAAqE;QACrE,2CAA2C;QAC3C,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC;QACzE,IAAI,CAAC;YACH,sBAAsB;YACtB,MAAM,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAClC,6EAA6E;YAC7E,oEAAoE;YACpE,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,GAAG,UAAU,CAAC,UAAU,CAAgB,CAAC;YAC/H,MAAM,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YAChC,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;QACzB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,sFAAsF;YACtF,IAAI,CAAC;gBAAC,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,uBAAuB,CAAC,CAAC;YACjE,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE/B,MAAM,KAAK,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAG,CAAC;QAE9B,+BAA+B;QAC/B,IAAI,UAAU,GAAG,IAAI,CAAC,IAAK,CAAC;QAC5B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,UAAU,GAAG,MAAM,UAAU,CAAC,kBAAkB,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;YAC5E,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC9B,OAAO,CAAC,0CAA0C;gBACpD,CAAC;gBACD,MAAM,IAAI,YAAY,CAAC,QAAQ,EAAE,mCAAmC,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAC7G,CAAC;QACH,CAAC;QAED,kBAAkB;QAClB,IAAI,CAAC;YACH,MAAM,UAAU,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QACzC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC9B,OAAO,CAAC,0CAA0C;YACpD,CAAC;YACD,MAAM,IAAI,YAAY,CAAC,QAAQ,EAAE,qBAAqB,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC/F,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACpD,OAAO,MAAM,KAAK,IAAI,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAe;QACxB,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE/B,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,MAAM,IAAI,EAAE,CAAC;QAC9B,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,oBAAoB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC5C,CAAC;QAED,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAK,CAAC;QACnF,IAAI,CAAC,GAAG;YAAE,OAAO,OAAO,CAAC;QAEzB,iBAAiB;QACjB,MAAM,OAAO,GAAG,KAAK,EAAE,SAAoC,EAAE,UAAkB,EAAiB,EAAE;YAChG,IAAI,KAAK,EAAE,MAAM,KAAK,IAAK,SAAiB,CAAC,MAAM,EAAE,EAAE,CAAC;gBACtD,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;gBAE1E,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBAC1B,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAC1B,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;oBACtC,MAAM,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;gBAClC,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC7B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,IAAY;QACtB,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC/B,IAAI,CAAC,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACtC,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE/B,0EAA0E;QAC1E,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAK,IAAI,CAAC,IAAY,CAAC,MAAM,EAAE,EAAE,CAAC;YACtD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,IAAI,CAAC,IAAK,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,WAAW;QAChB,OAAO,OAAO,SAAS,KAAK,WAAW,IAAI,CAAC,CAAC,SAAS,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/E,CAAC;CACF"}
@@ -2,7 +2,7 @@
2
2
  * Storage Backend Interface
3
3
  *
4
4
  * Provides a unified interface for persisting vector index data across different platforms:
5
- * - Bun/Node.js: File system storage with Bun.file APIs
5
+ * - Bun/Node.js: File system storage via BunStorageBackend
6
6
  * - Browser: OPFS (Origin Private File System) or IndexedDB
7
7
  * - Testing: In-memory storage
8
8
  *
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Storage Backend Interface
3
+ *
4
+ * Provides a unified interface for persisting vector index data across different platforms:
5
+ * - Bun/Node.js: File system storage via BunStorageBackend
6
+ * - Browser: OPFS (Origin Private File System) or IndexedDB
7
+ * - Testing: In-memory storage
8
+ *
9
+ * All operations are async to support both sync and async underlying storage.
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=StorageBackend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StorageBackend.js","sourceRoot":"","sources":["../../src/storage/StorageBackend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
@@ -10,6 +10,7 @@
10
10
  * - Crash recovery (replay log after restart)
11
11
  * - Reduced I/O for frequent updates
12
12
  */
13
+ import type { StorageBackend } from './StorageBackend';
13
14
  export declare enum WALOperationType {
14
15
  ADD_VECTOR = 1,
15
16
  ADD_NEIGHBORS = 2,
@@ -25,23 +26,25 @@ export interface WALEntry {
25
26
  * WriteAheadLog - Append-only log for incremental index updates
26
27
  */
27
28
  export declare class WriteAheadLog {
28
- private logPath;
29
+ private storage;
30
+ private logKey;
29
31
  private pendingEntries;
30
32
  private flushThreshold;
31
- private lastFlushTime;
32
33
  private entryCount;
34
+ private flushPromise;
33
35
  /**
34
36
  * Create a new WAL
35
- * @param basePath Base path for the index (WAL will be basePath.wal)
37
+ * @param storage StorageBackend for persistence
38
+ * @param logKey Storage key for the WAL data (e.g., "myindex.wal")
36
39
  * @param flushThreshold Number of entries before auto-flush (default: 100)
37
40
  */
38
- constructor(basePath: string, flushThreshold?: number);
41
+ constructor(storage: StorageBackend, logKey: string, flushThreshold?: number);
39
42
  /**
40
- * Get the WAL file path
43
+ * Get the WAL storage key
41
44
  */
42
- getPath(): string;
45
+ getKey(): string;
43
46
  /**
44
- * Check if WAL file exists
47
+ * Check if WAL data exists
45
48
  */
46
49
  exists(): Promise<boolean>;
47
50
  /**
@@ -65,12 +68,13 @@ export declare class WriteAheadLog {
65
68
  */
66
69
  private serializeEntry;
67
70
  /**
68
- * Flush pending entries to disk
69
- * Uses O(1) append instead of O(n) read-modify-write
71
+ * Flush pending entries to storage
72
+ * Uses append for efficient O(1) writes
70
73
  */
71
74
  flush(): Promise<void>;
75
+ private flushEntries;
72
76
  /**
73
- * Read all entries from the WAL file
77
+ * Read all entries from the WAL
74
78
  */
75
79
  readEntries(): Promise<WALEntry[]>;
76
80
  /**
@@ -104,7 +108,7 @@ export declare class WriteAheadLog {
104
108
  */
105
109
  clear(): Promise<void>;
106
110
  /**
107
- * Delete the WAL file
111
+ * Delete the WAL data
108
112
  */
109
113
  delete(): Promise<void>;
110
114
  }
@@ -1 +1 @@
1
- {"version":3,"file":"WriteAheadLog.d.ts","sourceRoot":"","sources":["../../src/storage/WriteAheadLog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,oBAAY,gBAAgB;IAC1B,UAAU,IAAI;IACd,aAAa,IAAI;IACjB,kBAAkB,IAAI;IACtB,UAAU,IAAI;CACf;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,gBAAgB,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,WAAW,CAAC;CACnB;AAED;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,UAAU,CAAa;IAE/B;;;;OAIG;gBACS,QAAQ,EAAE,MAAM,EAAE,cAAc,GAAE,MAAY;IAK1D;;OAEG;IACH,OAAO,IAAI,MAAM;IAIjB;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAKhC;;OAEG;IACG,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BnE;;OAEG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BxF;;OAEG;IACG,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBnF;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAejC;;OAEG;IACH,OAAO,CAAC,cAAc;IAiBtB;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgC5B;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IA4BxC;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,WAAW,GAAG;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,CAAA;KAAE;IAQhF;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,IAAI,EAAE,WAAW,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE;IAcrG;;OAEG;IACH,MAAM,CAAC,oBAAoB,CAAC,IAAI,EAAE,WAAW,GAAG;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;IAQ1F;;OAEG;IACH,aAAa,IAAI,MAAM;IAIvB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAS9B"}
1
+ {"version":3,"file":"WriteAheadLog.d.ts","sourceRoot":"","sources":["../../src/storage/WriteAheadLog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,oBAAY,gBAAgB;IAC1B,UAAU,IAAI;IACd,aAAa,IAAI;IACjB,kBAAkB,IAAI;IACtB,UAAU,IAAI;CACf;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,gBAAgB,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,WAAW,CAAC;CACnB;AAED;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,YAAY,CAA8B;IAElD;;;;;OAKG;gBACS,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAE,MAAY;IAMjF;;OAEG;IACH,MAAM,IAAI,MAAM;IAIhB;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAIhC;;OAEG;IACG,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BnE;;OAEG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BxF;;OAEG;IACG,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBnF;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBjC;;OAEG;IACH,OAAO,CAAC,cAAc;IAiBtB;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YA2Bd,YAAY;IA4B1B;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAgDxC;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,WAAW,GAAG;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,CAAA;KAAE;IAQhF;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,IAAI,EAAE,WAAW,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE;IAcrG;;OAEG;IACH,MAAM,CAAC,oBAAoB,CAAC,IAAI,EAAE,WAAW,GAAG;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;IAQ1F;;OAEG;IACH,aAAa,IAAI,MAAM;IAIvB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAa5B;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAa9B"}