@dxos/random-access-storage 0.8.4-main.84f28bd → 0.8.4-main.937b3ca

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 (41) hide show
  1. package/dist/lib/browser/browser/index.mjs +807 -0
  2. package/dist/lib/browser/browser/index.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-QQKT3REB.mjs +341 -0
  4. package/dist/lib/browser/chunk-QQKT3REB.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +2 -1110
  6. package/dist/lib/browser/index.mjs.map +4 -4
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/node/index.mjs +105 -0
  9. package/dist/lib/browser/node/index.mjs.map +7 -0
  10. package/dist/lib/node-esm/browser/index.mjs +801 -0
  11. package/dist/lib/node-esm/browser/index.mjs.map +7 -0
  12. package/dist/lib/node-esm/chunk-OW63I6TJ.mjs +341 -0
  13. package/dist/lib/node-esm/chunk-OW63I6TJ.mjs.map +7 -0
  14. package/dist/lib/node-esm/index.mjs +2 -390
  15. package/dist/lib/node-esm/index.mjs.map +4 -4
  16. package/dist/lib/node-esm/meta.json +1 -1
  17. package/dist/lib/node-esm/node/index.mjs +105 -0
  18. package/dist/lib/node-esm/node/index.mjs.map +7 -0
  19. package/dist/types/src/browser/storage.d.ts.map +1 -1
  20. package/dist/types/src/browser/web-fs.d.ts.map +1 -1
  21. package/dist/types/src/common/abstract-storage.d.ts.map +1 -1
  22. package/dist/types/src/common/directory.d.ts +2 -2
  23. package/dist/types/src/common/directory.d.ts.map +1 -1
  24. package/dist/types/src/index.d.ts +1 -1
  25. package/dist/types/src/index.d.ts.map +1 -1
  26. package/dist/types/src/node/node-storage.d.ts.map +1 -1
  27. package/dist/types/src/node/storage.d.ts.map +1 -1
  28. package/dist/types/tsconfig.tsbuildinfo +1 -1
  29. package/package.json +25 -12
  30. package/src/browser/bench.browser.test.ts +2 -1
  31. package/src/browser/idb-storage.ts +1 -1
  32. package/src/browser/storage.browser.test.ts +3 -2
  33. package/src/browser/storage.ts +2 -1
  34. package/src/browser/web-fs.ts +2 -1
  35. package/src/common/abstract-storage.ts +1 -0
  36. package/src/common/directory.ts +2 -2
  37. package/src/index.ts +1 -1
  38. package/src/node/bench.node.test.ts +4 -2
  39. package/src/node/node-storage.ts +2 -1
  40. package/src/node/storage.node.test.ts +5 -3
  41. package/src/node/storage.ts +2 -1
@@ -1,1113 +1,5 @@
1
1
  import "@dxos/node-std/globals";
2
- import import$random_access_storage from 'random-access-storage';
3
- import import$inherits from 'inherits';
4
- import import$next_tick from 'next-tick';
5
- import import$once from 'once';
6
- import import$buffer_from from 'buffer-from';
7
- import import$buffer_alloc from 'buffer-alloc';
8
- var __create = Object.create;
9
- var __defProp = Object.defineProperty;
10
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
11
- var __getOwnPropNames = Object.getOwnPropertyNames;
12
- var __getProtoOf = Object.getPrototypeOf;
13
- var __hasOwnProp = Object.prototype.hasOwnProperty;
14
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
15
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
16
- }) : x)(function(x) {
17
- if (typeof require !== "undefined") return require.apply(this, arguments);
18
- throw Error('Dynamic require of "' + x + '" is not supported');
19
- });
20
- var __commonJS = (cb, mod) => function __require2() {
21
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
22
- };
23
- var __copyProps = (to, from, except, desc) => {
24
- if (from && typeof from === "object" || typeof from === "function") {
25
- for (let key of __getOwnPropNames(from))
26
- if (!__hasOwnProp.call(to, key) && key !== except)
27
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
28
- }
29
- return to;
30
- };
31
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
32
- // If the importer is in node compatibility mode or this is not an ESM
33
- // file that has been converted to a CommonJS file using a Babel-
34
- // compatible transform (i.e. "__esModule" has not been set), then set
35
- // "default" to the CommonJS "module.exports" for node compatibility.
36
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
37
- mod
38
- ));
39
2
 
40
- // ../../../node_modules/.pnpm/random-access-idb@1.2.2_patch_hash=207ec2404ef8b5e9e6d9de8ce83586d215ef77b94a7d0cadced03125874a1d9e/node_modules/random-access-idb/lib/blocks.js
41
- var require_blocks = __commonJS({
42
- "../../../node_modules/.pnpm/random-access-idb@1.2.2_patch_hash=207ec2404ef8b5e9e6d9de8ce83586d215ef77b94a7d0cadced03125874a1d9e/node_modules/random-access-idb/lib/blocks.js"(exports, module) {
43
- module.exports = function(size, start, end) {
44
- var result = [];
45
- for (var n = Math.floor(start / size) * size; n < end; n += size) {
46
- result.push({
47
- block: Math.floor(n / size),
48
- start: Math.max(n, start) % size,
49
- end: Math.min(n + size, end) % size || size
50
- });
51
- }
52
- return result;
53
- };
54
- }
55
- });
56
-
57
- // ../../../node_modules/.pnpm/random-access-idb@1.2.2_patch_hash=207ec2404ef8b5e9e6d9de8ce83586d215ef77b94a7d0cadced03125874a1d9e/node_modules/random-access-idb/index.js
58
- var require_random_access_idb = __commonJS({
59
- "../../../node_modules/.pnpm/random-access-idb@1.2.2_patch_hash=207ec2404ef8b5e9e6d9de8ce83586d215ef77b94a7d0cadced03125874a1d9e/node_modules/random-access-idb/index.js"(exports, module) {
60
- var RandomAccess = import$random_access_storage;
61
- var inherits = import$inherits;
62
- var nextTick = import$next_tick;
63
- var once = import$once;
64
- var blocks = require_blocks();
65
- var bufferFrom = import$buffer_from;
66
- var bufferAlloc = import$buffer_alloc;
67
- var DELIM2 = "\0";
68
- var win = typeof window !== "undefined" ? window : typeof self !== "undefined" ? self : {};
69
- module.exports = function(dbname, xopts) {
70
- if (!xopts) xopts = {};
71
- var idb2 = xopts.idb || (typeof win !== "undefined" ? win.indexedDB || win.mozIndexedDB || win.webkitIndexedDB || win.msIndexedDB : null);
72
- if (!idb2) throw new Error("indexedDB not present and not given");
73
- var db = null, dbqueue = [];
74
- if (typeof idb2.open === "function") {
75
- var req = idb2.open(dbname);
76
- req.addEventListener("upgradeneeded", function() {
77
- db = req.result;
78
- db.createObjectStore("data");
79
- });
80
- req.addEventListener("success", function() {
81
- db = req.result;
82
- dbqueue.forEach(function(cb) {
83
- cb(db);
84
- });
85
- dbqueue = null;
86
- });
87
- } else {
88
- db = idb2;
89
- }
90
- function getdb(cb) {
91
- if (db) nextTick(function() {
92
- cb(db);
93
- });
94
- else dbqueue.push(cb);
95
- }
96
- return {
97
- create: function(name, opts) {
98
- if (typeof name === "object") {
99
- opts = name;
100
- name = opts.name;
101
- }
102
- if (!opts) opts = {};
103
- opts.name = name;
104
- return new Store(Object.assign({ db: getdb }, xopts, opts));
105
- },
106
- getdb
107
- };
108
- };
109
- function Store(opts) {
110
- if (!(this instanceof Store)) return new Store(opts);
111
- RandomAccess.call(this);
112
- if (!opts) opts = {};
113
- if (typeof opts === "string") opts = { name: opts };
114
- this.size = opts.size || 4096;
115
- this.name = opts.name;
116
- this.length = opts.length || 0;
117
- this._getdb = opts.db;
118
- }
119
- inherits(Store, RandomAccess);
120
- Store.prototype._blocks = function(i, j) {
121
- return blocks(this.size, i, j);
122
- };
123
- Store.prototype._read = function(req) {
124
- var self2 = this;
125
- var buffers = [];
126
- self2._store("readonly", function(err, store) {
127
- if ((self2.length || 0) < req.offset + req.size) {
128
- return req.callback(new Error("Could not satisfy length"));
129
- }
130
- if (err) return req.callback(err);
131
- var offsets = self2._blocks(req.offset, req.offset + req.size);
132
- var pending = offsets.length + 1;
133
- var firstBlock = offsets.length > 0 ? offsets[0].block : 0;
134
- var j = 0;
135
- for (var i = 0; i < offsets.length; i++) (function(o) {
136
- var key = self2.name + DELIM2 + o.block;
137
- backify(store.get(key), function(err2, ev) {
138
- if (err2) return req.callback(err2);
139
- buffers[o.block - firstBlock] = ev.target.result ? bufferFrom(ev.target.result.subarray(o.start, o.end)) : bufferAlloc(o.end - o.start);
140
- if (--pending === 0) req.callback(null, Buffer.concat(buffers));
141
- });
142
- })(offsets[i]);
143
- if (--pending === 0) req.callback(null, Buffer.concat(buffers));
144
- });
145
- };
146
- Store.prototype._write = function(req) {
147
- var self2 = this;
148
- self2._store("readwrite", function(err, store) {
149
- if (err) return req.callback(err);
150
- var offsets = self2._blocks(req.offset, req.offset + req.data.length);
151
- var pending = 1;
152
- var buffers = {};
153
- for (var i = 0; i < offsets.length; i++) (function(o, i2) {
154
- if (o.end - o.start === self2.size) return;
155
- pending++;
156
- var key = self2.name + DELIM2 + o.block;
157
- backify(store.get(key), function(err2, ev) {
158
- if (err2) return req.callback(err2);
159
- buffers[i2] = bufferFrom(ev.target.result || bufferAlloc(self2.size));
160
- if (--pending === 0) write(store, offsets, buffers);
161
- });
162
- })(offsets[i], i);
163
- if (--pending === 0) write(store, offsets, buffers);
164
- });
165
- function write(store, offsets, buffers) {
166
- var block;
167
- for (var i = 0, j = 0; i < offsets.length; i++) {
168
- var o = offsets[i];
169
- var len = o.end - o.start;
170
- if (len === self2.size) {
171
- block = bufferFrom(req.data.slice(j, j + len));
172
- } else {
173
- block = buffers[i];
174
- req.data.copy(block, o.start, j, j + len);
175
- }
176
- store.put(block, self2.name + DELIM2 + o.block);
177
- j += len;
178
- }
179
- var length = Math.max(self2.length || 0, req.offset + req.data.length);
180
- store.put(length, self2.name + DELIM2 + "length");
181
- store.transaction.addEventListener("complete", function() {
182
- self2.length = length;
183
- req.callback(null);
184
- });
185
- store.transaction.addEventListener("error", function(err) {
186
- req.callback(err);
187
- });
188
- }
189
- };
190
- Store.prototype._store = function(mode, cb) {
191
- cb = once(cb);
192
- var self2 = this;
193
- self2._getdb(function(db) {
194
- var tx = db.transaction(["data"], mode);
195
- var store = tx.objectStore("data");
196
- tx.addEventListener("error", cb);
197
- cb(null, store);
198
- });
199
- };
200
- Store.prototype._open = function(req) {
201
- var self2 = this;
202
- this._getdb(function(db) {
203
- self2._store("readonly", function(err, store) {
204
- backify(store.get(self2.name + DELIM2 + "length"), function(err2, ev) {
205
- self2.length = ev.target.result || 0;
206
- req.callback(null);
207
- });
208
- });
209
- });
210
- };
211
- Store.prototype._close = function(req) {
212
- this._getdb(function(db) {
213
- req.callback();
214
- });
215
- };
216
- Store.prototype._stat = function(req) {
217
- var self2 = this;
218
- nextTick(function() {
219
- req.callback(null, { size: self2.length });
220
- });
221
- };
222
- function backify(r, cb) {
223
- r.addEventListener("success", function(ev) {
224
- cb(null, ev);
225
- });
226
- r.addEventListener("error", cb);
227
- }
228
- }
229
- });
230
-
231
- // src/common/abstract-storage.ts
232
- import { join as join2 } from "@dxos/node-std/path";
233
- import { inspect } from "@dxos/node-std/util";
234
- import { inspectObject } from "@dxos/debug";
235
- import { log as log2 } from "@dxos/log";
236
-
237
- // src/common/utils.ts
238
- import { join } from "@dxos/node-std/path";
239
- var stringDiff = (first, second) => first.split(second).join("");
240
- var getFullPath = (root, path) => join(root, stringDiff(path, root));
241
-
242
- // src/common/directory.ts
243
- var Directory = class _Directory {
244
- constructor({ type, path, list, getOrCreateFile, remove, onFlush }) {
245
- this.type = type;
246
- this.path = path;
247
- this._list = list;
248
- this._getOrCreateFile = getOrCreateFile;
249
- this._remove = remove;
250
- this._onFlush = onFlush;
251
- }
252
- toString() {
253
- return `Directory(${JSON.stringify({
254
- type: this.type,
255
- path: this.path
256
- })})`;
257
- }
258
- /**
259
- * Create a new sub-directory.
260
- */
261
- createDirectory(path) {
262
- return new _Directory({
263
- type: this.type,
264
- path: getFullPath(this.path, path),
265
- list: this._list,
266
- getOrCreateFile: this._getOrCreateFile,
267
- remove: this._remove
268
- });
269
- }
270
- /**
271
- * Get all files in the current directory.
272
- */
273
- list() {
274
- return this._list(this.path);
275
- }
276
- /**
277
- * Get or create a new file.
278
- */
279
- getOrCreateFile(filename, opts) {
280
- return this._getOrCreateFile(this.path, filename, opts);
281
- }
282
- async flush() {
283
- await this._onFlush?.();
284
- }
285
- /**
286
- * Close and delete all files in the directory and all its sub-directories.
287
- */
288
- async delete() {
289
- await this._remove();
290
- }
291
- };
292
-
293
- // src/common/file.ts
294
- import pify from "pify";
295
- import { log } from "@dxos/log";
296
- var __dxlog_file = "/__w/dxos/dxos/packages/common/random-access-storage/src/common/file.ts";
297
- var MAX_STORAGE_OPERATION_TIME = 50;
298
- var pifyFields = (object, type, fields) => {
299
- for (const field of fields) {
300
- if (!object[field]) {
301
- } else {
302
- const fn = pify(object[field].bind(object));
303
- object[field] = async (...args) => {
304
- const before = performance.now();
305
- const res = await fn(...args);
306
- const elapsed = performance.now() - before;
307
- if (elapsed > MAX_STORAGE_OPERATION_TIME) {
308
- log("Slow storage operation", {
309
- type,
310
- operation: field,
311
- elapsed
312
- }, {
313
- F: __dxlog_file,
314
- L: 62,
315
- S: void 0,
316
- C: (f, a) => f(...a)
317
- });
318
- }
319
- return res;
320
- };
321
- }
322
- }
323
- return object;
324
- };
325
- var wrapFile = (native, type) => {
326
- const file = pifyFields(native, type, [
327
- "write",
328
- "read",
329
- "del",
330
- "stat",
331
- "close",
332
- "destroy",
333
- "truncate"
334
- ]);
335
- return Object.assign(file, {
336
- type,
337
- native
338
- });
339
- };
340
-
341
- // src/common/abstract-storage.ts
342
- var __dxlog_file2 = "/__w/dxos/dxos/packages/common/random-access-storage/src/common/abstract-storage.ts";
343
- var AbstractStorage = class {
344
- // TODO(burdon): Make required.
345
- constructor(path) {
346
- this.path = path;
347
- this._files = /* @__PURE__ */ new Map();
348
- }
349
- [inspect.custom]() {
350
- return inspectObject(this);
351
- }
352
- toJSON() {
353
- return {
354
- type: this.type,
355
- path: this.path
356
- };
357
- }
358
- get size() {
359
- return this._files.size;
360
- }
361
- // TODO(burdon): Make required.
362
- createDirectory(sub = "") {
363
- return new Directory({
364
- type: this.type,
365
- path: getFullPath(this.path, sub),
366
- list: this._list.bind(this),
367
- getOrCreateFile: (...args) => this.getOrCreateFile(...args),
368
- remove: () => this._remove(sub)
369
- });
370
- }
371
- /**
372
- * Delete all files.
373
- */
374
- async reset() {
375
- try {
376
- log2.info("Erasing all data...", void 0, {
377
- F: __dxlog_file2,
378
- L: 60,
379
- S: this,
380
- C: (f, a) => f(...a)
381
- });
382
- await this._closeFilesInPath("");
383
- await this._remove("");
384
- await this._destroy();
385
- log2("Erased...", void 0, {
386
- F: __dxlog_file2,
387
- L: 64,
388
- S: this,
389
- C: (f, a) => f(...a)
390
- });
391
- } catch (err) {
392
- log2.catch(err, void 0, {
393
- F: __dxlog_file2,
394
- L: 66,
395
- S: this,
396
- C: (f, a) => f(...a)
397
- });
398
- }
399
- }
400
- async _list(path) {
401
- return Array.from((await this._getFiles(path)).keys()).map((filename) => {
402
- let name = filename.replace(path, "");
403
- if (name.startsWith("/")) {
404
- name = name.substring(1);
405
- }
406
- return name;
407
- });
408
- }
409
- getOrCreateFile(path, filename, opts) {
410
- const fullPath = join2(path, filename);
411
- let native;
412
- let file = this._getFileIfExists(fullPath);
413
- if (file) {
414
- if (!file.closed) {
415
- return file;
416
- }
417
- native = this._openFile(file.native);
418
- }
419
- if (!native) {
420
- native = this._createFile(path, filename, opts);
421
- }
422
- file = wrapFile(native, this.type);
423
- this._files.set(fullPath, file);
424
- return file;
425
- }
426
- _destroy() {
427
- return void 0;
428
- }
429
- /**
430
- * Attempt to reopen file.
431
- */
432
- _openFile(file) {
433
- return void 0;
434
- }
435
- _getFileIfExists(filename) {
436
- if (this._files.has(filename)) {
437
- const file = this._files.get(filename);
438
- if (file && !file.destroyed) {
439
- return file;
440
- }
441
- }
442
- }
443
- async _getFiles(path) {
444
- const fullPath = getFullPath(this.path, path);
445
- return new Map([
446
- ...this._files.entries()
447
- ].filter(([path2, file]) => path2.includes(fullPath) && file.destroyed !== true));
448
- }
449
- async _closeFilesInPath(path) {
450
- await Promise.all(Array.from((await this._getFiles(path)).values()).map((file) => file.close().catch((err) => log2.catch(err, void 0, {
451
- F: __dxlog_file2,
452
- L: 134,
453
- S: this,
454
- C: (f, a) => f(...a)
455
- }))));
456
- }
457
- async close() {
458
- await this._closeFilesInPath("");
459
- }
460
- // TODO(burdon): Delete directory (not just listed files).
461
- async _remove(path) {
462
- await Promise.all(Array.from(await this._getFiles(path)).map(([path2, file]) => {
463
- return file.destroy().then(() => this._files.delete(path2)).catch((err) => log2.error(err.message, void 0, {
464
- F: __dxlog_file2,
465
- L: 149,
466
- S: this,
467
- C: (f, a) => f(...a)
468
- }));
469
- }));
470
- }
471
- };
472
-
473
- // src/common/memory-storage.ts
474
- import ram from "random-access-memory";
475
- import { arrayToBuffer } from "@dxos/util";
476
-
477
- // src/common/storage.ts
478
- var StorageType = /* @__PURE__ */ function(StorageType2) {
479
- StorageType2["RAM"] = "ram";
480
- StorageType2["IDB"] = "idb";
481
- StorageType2["CHROME"] = "chrome";
482
- StorageType2["FIREFOX"] = "firefox";
483
- StorageType2["NODE"] = "node";
484
- StorageType2["WEBFS"] = "webfs";
485
- return StorageType2;
486
- }({});
487
-
488
- // src/common/memory-storage.ts
489
- var MemoryStorage = class extends AbstractStorage {
490
- constructor() {
491
- super(...arguments);
492
- this.type = StorageType.RAM;
493
- }
494
- _createFile(path, filename) {
495
- return this._patchFile(ram());
496
- }
497
- _openFile(file) {
498
- const newFile = file.clone();
499
- newFile.closed = false;
500
- return this._patchFile(newFile);
501
- }
502
- _patchFile(file) {
503
- const trueRead = file.read.bind(file);
504
- file.read = (offset, size, cb) => trueRead(offset, size, (err, data) => {
505
- if (err) {
506
- return cb(err);
507
- } else {
508
- return cb(err, arrayToBuffer(data));
509
- }
510
- });
511
- return file;
512
- }
513
- async getDiskInfo() {
514
- let used = 0;
515
- for (const file of this._files.values()) {
516
- const size = file.length;
517
- used += Number.isNaN(size) ? 0 : size;
518
- }
519
- return {
520
- used
521
- };
522
- }
523
- };
524
-
525
- // src/browser/idb-storage.ts
526
- var import_random_access_idb = __toESM(require_random_access_idb(), 1);
527
- import { invariant } from "@dxos/invariant";
528
- var __dxlog_file3 = "/__w/dxos/dxos/packages/common/random-access-storage/src/browser/idb-storage.ts";
529
- var DELIM = "\0";
530
- var IDbStorage = class extends AbstractStorage {
531
- constructor(path) {
532
- super(path);
533
- this.type = StorageType.IDB;
534
- this._store = "data";
535
- this._initialized = false;
536
- this._fileStorage = this._createFileStorage(path);
537
- }
538
- _createFileStorage(path) {
539
- const database = (0, import_random_access_idb.default)(path);
540
- let res;
541
- this._db = new Promise((resolve) => {
542
- res = resolve;
543
- });
544
- database.getdb(res);
545
- return database.create;
546
- }
547
- async close() {
548
- await this._closeFilesInPath("");
549
- }
550
- async reset() {
551
- await this._closeFilesInPath("");
552
- await this._remove("");
553
- }
554
- async _destroy() {
555
- throw new Error("Unreachable");
556
- }
557
- _createFile(path, filename) {
558
- const file = this._fileStorage(getFullPath(path, filename));
559
- file.destroy = (cb) => {
560
- void this._db.then((db) => {
561
- const lowerBound = getFullPath(path, filename);
562
- const upperBound = `${lowerBound}\uFFFF`;
563
- const range = IDBKeyRange.bound(lowerBound, upperBound);
564
- const transaction = db.transaction(this._store, "readwrite");
565
- const objectStore = transaction.objectStore(this._store);
566
- objectStore.delete(range);
567
- transaction.oncomplete = () => {
568
- file.destroyed = true;
569
- file.unlinked = true;
570
- file.closed = true;
571
- cb(null);
572
- };
573
- transaction.onerror = () => cb(transaction.error);
574
- });
575
- };
576
- file.deletable = true;
577
- return file;
578
- }
579
- async _loadFiles(path) {
580
- const db = await this._db;
581
- invariant(db, "Database is not initialized.", {
582
- F: __dxlog_file3,
583
- L: 85,
584
- S: this,
585
- A: [
586
- "db",
587
- "'Database is not initialized.'"
588
- ]
589
- });
590
- const lowerBound = path;
591
- const upperBound = `${path}\uFFFF`;
592
- const range = IDBKeyRange.bound(lowerBound, upperBound);
593
- const transaction = db.transaction(this._store);
594
- const objectStore = transaction.objectStore(this._store);
595
- const request = objectStore.openCursor(range);
596
- return new Promise((resolve, reject) => {
597
- transaction.onerror = () => {
598
- reject(request.error);
599
- };
600
- request.onsuccess = (event) => {
601
- const cursor = event.target.result;
602
- if (cursor) {
603
- const filename = String(cursor.key).split(DELIM)[0];
604
- if (filename && !this._files.has(getFullPath(this.path, filename))) {
605
- const file = this._createFile(path, filename);
606
- this._files.set(getFullPath(this.path, filename), wrapFile(file, this.type));
607
- }
608
- cursor.continue();
609
- } else {
610
- resolve();
611
- }
612
- };
613
- });
614
- }
615
- async _getFiles(path) {
616
- if (!this._initialized) {
617
- await this._loadFiles(this.path);
618
- this._initialized = true;
619
- }
620
- return super._getFiles(path);
621
- }
622
- };
623
-
624
- // src/browser/web-fs.ts
625
- import { EventEmitter } from "@dxos/node-std/events";
626
- import { callbackify } from "@dxos/node-std/util";
627
- import { synchronized } from "@dxos/async";
628
- import { invariant as invariant2 } from "@dxos/invariant";
629
- import { log as log3 } from "@dxos/log";
630
- import { TimeSeriesCounter, trace } from "@dxos/tracing";
631
- function _ts_decorate(decorators, target, key, desc) {
632
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
633
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
634
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
635
- return c > 3 && r && Object.defineProperty(target, key, r), r;
636
- }
637
- var __dxlog_file4 = "/__w/dxos/dxos/packages/common/random-access-storage/src/browser/web-fs.ts";
638
- var WebFS = class {
639
- constructor(path) {
640
- this.path = path;
641
- this._files = /* @__PURE__ */ new Map();
642
- this.type = StorageType.WEBFS;
643
- }
644
- get size() {
645
- return this._files.size;
646
- }
647
- _getFiles(path) {
648
- const fullName = this._getFullFilename(this.path, path);
649
- return new Map([
650
- ...this._files.entries()
651
- ].filter(([path2, file]) => {
652
- return path2.includes(fullName) && !file.destroyed;
653
- }));
654
- }
655
- async _list(path) {
656
- const fullName = this._getFullFilename(path);
657
- const root = await this._initialize();
658
- const entries = [];
659
- for await (const entry of root.keys()) {
660
- if (entry.startsWith(fullName + "_") && !entry.endsWith(".crswap")) {
661
- entries.push(entry.slice(fullName.length + 1));
662
- }
663
- }
664
- return entries;
665
- }
666
- async _initialize() {
667
- if (this._root) {
668
- return this._root;
669
- }
670
- this._root = await navigator.storage.getDirectory();
671
- invariant2(this._root, "Root is undefined", {
672
- F: __dxlog_file4,
673
- L: 73,
674
- S: this,
675
- A: [
676
- "this._root",
677
- "'Root is undefined'"
678
- ]
679
- });
680
- return this._root;
681
- }
682
- createDirectory(sub = "") {
683
- return new Directory({
684
- type: this.type,
685
- path: getFullPath(this.path, sub),
686
- list: (path) => this._list(path),
687
- getOrCreateFile: (...args) => this.getOrCreateFile(...args),
688
- remove: () => this._delete(sub),
689
- onFlush: async () => {
690
- await Promise.all(Array.from(this._getFiles(sub)).map(([_, file]) => file.flush()));
691
- }
692
- });
693
- }
694
- getOrCreateFile(path, filename, opts) {
695
- const fullName = this._getFullFilename(path, filename);
696
- const existingFile = this._files.get(fullName);
697
- if (existingFile) {
698
- return existingFile;
699
- }
700
- const file = this._createFile(fullName);
701
- this._files.set(fullName, file);
702
- return file;
703
- }
704
- _createFile(fullName) {
705
- return new WebFile({
706
- fileName: fullName,
707
- file: this._initialize().then((root) => root.getFileHandle(fullName, {
708
- create: true
709
- })),
710
- destroy: async () => {
711
- this._files.delete(fullName);
712
- const root = await this._initialize();
713
- return root.removeEntry(fullName);
714
- }
715
- });
716
- }
717
- async _delete(path) {
718
- await Promise.all(Array.from(this._getFiles(path)).map(async ([path2, file]) => {
719
- await file.destroy().catch((err) => log3.warn(err, void 0, {
720
- F: __dxlog_file4,
721
- L: 116,
722
- S: this,
723
- C: (f, a) => f(...a)
724
- }));
725
- this._files.delete(path2);
726
- }));
727
- }
728
- async reset() {
729
- await this._initialize();
730
- for await (const filename of await this._root.keys()) {
731
- await this._root.removeEntry(filename, {
732
- recursive: true
733
- }).catch((err) => log3.warn("failed to remove an entry", {
734
- filename,
735
- err
736
- }, {
737
- F: __dxlog_file4,
738
- L: 126,
739
- S: this,
740
- C: (f, a) => f(...a)
741
- }));
742
- this._files.delete(filename);
743
- }
744
- this._root = void 0;
745
- }
746
- async close() {
747
- await Promise.all(Array.from(this._files.values()).map((file) => {
748
- return file.close().catch((e) => log3.warn("failed to close a file", {
749
- file: file.fileName,
750
- e
751
- }, {
752
- F: __dxlog_file4,
753
- L: 136,
754
- S: this,
755
- C: (f, a) => f(...a)
756
- }));
757
- }));
758
- }
759
- _getFullFilename(path, filename) {
760
- if (filename) {
761
- return getFullPath(path, filename).replace(/\//g, "_");
762
- } else {
763
- return path.replace(/\//g, "_");
764
- }
765
- }
766
- async getDiskInfo() {
767
- let used = 0;
768
- const recurse = async (handle) => {
769
- const promises = [];
770
- for await (const entry of handle.values()) {
771
- promises.push((async () => {
772
- switch (entry.kind) {
773
- case "file":
774
- used += await entry.getFile().then((f) => f.size);
775
- break;
776
- case "directory":
777
- await recurse(entry);
778
- break;
779
- }
780
- })());
781
- }
782
- await Promise.all(promises);
783
- };
784
- await recurse(this._root);
785
- return {
786
- used
787
- };
788
- }
789
- };
790
- _ts_decorate([
791
- synchronized
792
- ], WebFS.prototype, "_initialize", null);
793
- var WebFile = class extends EventEmitter {
794
- constructor({ fileName, file, destroy }) {
795
- super();
796
- /**
797
- * Current view of the file contents.
798
- */
799
- this._buffer = null;
800
- this._loadBufferPromise = null;
801
- this._flushScheduled = false;
802
- this._flushPromise = Promise.resolve();
803
- /**
804
- * Used to discard unnecessary scheduled flushes.
805
- * If _flushNow() is called with a lower sequence number it should early exit.
806
- */
807
- this._flushSequence = 0;
808
- //
809
- // Metrics
810
- //
811
- this._flushes = new TimeSeriesCounter();
812
- this._operations = new TimeSeriesCounter();
813
- this._reads = new TimeSeriesCounter();
814
- this._readBytes = new TimeSeriesCounter();
815
- this._writes = new TimeSeriesCounter();
816
- this._writeBytes = new TimeSeriesCounter();
817
- this.type = StorageType.WEBFS;
818
- //
819
- // random-access-storage library compatibility
820
- //
821
- // TODO(dmaretskyi): Are those all needed?
822
- this.opened = true;
823
- this.suspended = false;
824
- this.closed = false;
825
- this.unlinked = false;
826
- this.writing = false;
827
- this.readable = true;
828
- this.writable = true;
829
- this.deletable = true;
830
- this.truncatable = true;
831
- this.statable = true;
832
- this.destroyed = false;
833
- this.directory = "";
834
- // TODO(dmaretskyi): is this used?
835
- this.filename = "";
836
- this.native = {
837
- write: callbackify(this.write.bind(this)),
838
- read: callbackify(this.read.bind(this)),
839
- del: callbackify(this.del.bind(this)),
840
- stat: callbackify(this.stat.bind(this)),
841
- destroy: callbackify(this.destroy.bind(this)),
842
- truncate: callbackify(this.truncate?.bind(this))
843
- };
844
- this.fileName = fileName;
845
- this._fileHandle = file;
846
- this._destroy = destroy;
847
- void this._loadBufferGuarded();
848
- }
849
- get _bufferSize() {
850
- return this._buffer?.length;
851
- }
852
- async _loadBuffer() {
853
- const fileHandle = await this._fileHandle;
854
- const file = await fileHandle.getFile();
855
- this._buffer = new Uint8Array(await file.arrayBuffer());
856
- }
857
- async _loadBufferGuarded() {
858
- await (this._loadBufferPromise ??= this._loadBuffer());
859
- }
860
- // Do not call directly, use _flushLater or _flushNow.
861
- async _flushCache(sequence) {
862
- if (this.destroyed || sequence < this._flushSequence) {
863
- return;
864
- }
865
- this._flushSequence = sequence + 1;
866
- this._flushes.inc();
867
- await this._loadBufferGuarded();
868
- invariant2(this._buffer, void 0, {
869
- F: __dxlog_file4,
870
- L: 300,
871
- S: this,
872
- A: [
873
- "this._buffer",
874
- ""
875
- ]
876
- });
877
- const fileHandle = await this._fileHandle;
878
- const writable = await fileHandle.createWritable({
879
- keepExistingData: true
880
- });
881
- await writable.write({
882
- type: "write",
883
- data: this._buffer,
884
- position: 0
885
- });
886
- await writable.close();
887
- }
888
- _flushLater() {
889
- if (this._flushScheduled) {
890
- return;
891
- }
892
- const sequence = this._flushSequence;
893
- setTimeout(async () => {
894
- await this._flushPromise;
895
- this._flushScheduled = false;
896
- this._flushPromise = this._flushCache(sequence).catch((err) => log3.warn(err, void 0, {
897
- F: __dxlog_file4,
898
- L: 318,
899
- S: this,
900
- C: (f, a) => f(...a)
901
- }));
902
- });
903
- this._flushScheduled = true;
904
- }
905
- async _flushNow() {
906
- await this._flushPromise;
907
- this._flushPromise = this._flushCache(this._flushSequence).catch((err) => log3.warn(err, void 0, {
908
- F: __dxlog_file4,
909
- L: 326,
910
- S: this,
911
- C: (f, a) => f(...a)
912
- }));
913
- await this._flushPromise;
914
- }
915
- async read(offset, size) {
916
- this.assertNotDestroyed("Read");
917
- this._operations.inc();
918
- this._reads.inc();
919
- this._readBytes.inc(size);
920
- if (!this._buffer) {
921
- await this._loadBufferGuarded();
922
- invariant2(this._buffer, void 0, {
923
- F: __dxlog_file4,
924
- L: 339,
925
- S: this,
926
- A: [
927
- "this._buffer",
928
- ""
929
- ]
930
- });
931
- }
932
- if (offset + size > this._buffer.length) {
933
- throw new Error("Read out of bounds");
934
- }
935
- return Buffer.from(this._buffer.slice(offset, offset + size));
936
- }
937
- async write(offset, data) {
938
- this.assertNotDestroyed("Write");
939
- this._operations.inc();
940
- this._writes.inc();
941
- this._writeBytes.inc(data.length);
942
- if (!this._buffer) {
943
- await this._loadBufferGuarded();
944
- invariant2(this._buffer, void 0, {
945
- F: __dxlog_file4,
946
- L: 359,
947
- S: this,
948
- A: [
949
- "this._buffer",
950
- ""
951
- ]
952
- });
953
- }
954
- if (offset + data.length <= this._buffer.length) {
955
- this._buffer.set(data, offset);
956
- } else {
957
- const newCache = new Uint8Array(offset + data.length);
958
- newCache.set(this._buffer);
959
- newCache.set(data, offset);
960
- this._buffer = newCache;
961
- }
962
- this._flushLater();
963
- }
964
- async del(offset, size) {
965
- this.assertNotDestroyed("Del");
966
- this._operations.inc();
967
- if (offset < 0 || size <= 0) {
968
- return;
969
- }
970
- if (!this._buffer) {
971
- await this._loadBufferGuarded();
972
- invariant2(this._buffer, void 0, {
973
- F: __dxlog_file4,
974
- L: 386,
975
- S: this,
976
- A: [
977
- "this._buffer",
978
- ""
979
- ]
980
- });
981
- }
982
- let leftoverSize = 0;
983
- if (offset + size < this._buffer.length) {
984
- leftoverSize = this._buffer.length - (offset + size);
985
- this._buffer.set(this._buffer.slice(offset + size, offset + size + leftoverSize), offset);
986
- }
987
- this._buffer = this._buffer.slice(0, offset + leftoverSize);
988
- this._flushLater();
989
- }
990
- async stat() {
991
- this.assertNotDestroyed("Truncate");
992
- this._operations.inc();
993
- if (!this._buffer) {
994
- await this._loadBufferGuarded();
995
- invariant2(this._buffer, void 0, {
996
- F: __dxlog_file4,
997
- L: 408,
998
- S: this,
999
- A: [
1000
- "this._buffer",
1001
- ""
1002
- ]
1003
- });
1004
- }
1005
- return {
1006
- size: this._buffer.length
1007
- };
1008
- }
1009
- async truncate(offset) {
1010
- this.assertNotDestroyed("Truncate");
1011
- this._operations.inc();
1012
- if (!this._buffer) {
1013
- await this._loadBufferGuarded();
1014
- invariant2(this._buffer, void 0, {
1015
- F: __dxlog_file4,
1016
- L: 423,
1017
- S: this,
1018
- A: [
1019
- "this._buffer",
1020
- ""
1021
- ]
1022
- });
1023
- }
1024
- this._buffer = this._buffer.slice(0, offset);
1025
- this._flushLater();
1026
- }
1027
- async flush() {
1028
- this.assertNotDestroyed("Flush");
1029
- await this._flushNow();
1030
- }
1031
- /**
1032
- * It's best to avoid using this method as it doesn't really close a file.
1033
- * We could update the _opened flag and add a guard like for destroyed, but this would break
1034
- * the FileSystemFileHandle sharing required for browser tests to run, where writes are
1035
- * not immediately visible if using different file handles.
1036
- */
1037
- async close() {
1038
- await this._flushNow();
1039
- }
1040
- async destroy() {
1041
- if (!this.destroyed) {
1042
- await this._flushNow();
1043
- this.destroyed = true;
1044
- return await this._destroy();
1045
- }
1046
- }
1047
- assertNotDestroyed(operation) {
1048
- if (this.destroyed) {
1049
- throw new Error(`${operation} on a destroyed or closed file`);
1050
- }
1051
- }
1052
- };
1053
- _ts_decorate([
1054
- trace.info()
1055
- ], WebFile.prototype, "fileName", void 0);
1056
- _ts_decorate([
1057
- trace.metricsCounter()
1058
- ], WebFile.prototype, "_flushes", void 0);
1059
- _ts_decorate([
1060
- trace.metricsCounter()
1061
- ], WebFile.prototype, "_operations", void 0);
1062
- _ts_decorate([
1063
- trace.metricsCounter()
1064
- ], WebFile.prototype, "_reads", void 0);
1065
- _ts_decorate([
1066
- trace.metricsCounter()
1067
- ], WebFile.prototype, "_readBytes", void 0);
1068
- _ts_decorate([
1069
- trace.metricsCounter()
1070
- ], WebFile.prototype, "_writes", void 0);
1071
- _ts_decorate([
1072
- trace.metricsCounter()
1073
- ], WebFile.prototype, "_writeBytes", void 0);
1074
- _ts_decorate([
1075
- trace.info()
1076
- ], WebFile.prototype, "_bufferSize", null);
1077
- _ts_decorate([
1078
- synchronized
1079
- ], WebFile.prototype, "destroy", null);
1080
-
1081
- // src/browser/storage.ts
1082
- var createStorage = ({ type, root = "" } = {}) => {
1083
- if (type === void 0) {
1084
- return new IDbStorage(root);
1085
- }
1086
- switch (type) {
1087
- case StorageType.RAM: {
1088
- return new MemoryStorage(root);
1089
- }
1090
- case StorageType.IDB:
1091
- case StorageType.CHROME:
1092
- case StorageType.FIREFOX: {
1093
- return new IDbStorage(root);
1094
- }
1095
- case StorageType.WEBFS: {
1096
- return new WebFS(root);
1097
- }
1098
- default: {
1099
- throw new Error(`Invalid type: ${type}`);
1100
- }
1101
- }
1102
- };
1103
- export {
1104
- AbstractStorage,
1105
- Directory,
1106
- MemoryStorage,
1107
- StorageType,
1108
- createStorage,
1109
- getFullPath,
1110
- stringDiff,
1111
- wrapFile
1112
- };
3
+ // src/index.ts
4
+ export * from "#storage";
1113
5
  //# sourceMappingURL=index.mjs.map