@dxos/random-access-storage 0.1.55-main.ff36828 → 0.1.55

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.
@@ -55,7 +55,7 @@ var Directory = class {
55
55
  // packages/common/random-access-storage/src/common/file.ts
56
56
  import pify from "pify";
57
57
  import { log } from "@dxos/log";
58
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/common/random-access-storage/src/common/file.ts";
58
+ var __dxlog_file = "/mnt/ramdisk/work/packages/common/random-access-storage/src/common/file.ts";
59
59
  var pifyFields = (object, type, fields) => {
60
60
  for (const field of fields) {
61
61
  if (!object[field]) {
@@ -100,7 +100,7 @@ var wrapFile = (native, type) => {
100
100
  };
101
101
 
102
102
  // packages/common/random-access-storage/src/common/abstract-storage.ts
103
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/common/random-access-storage/src/common/abstract-storage.ts";
103
+ var __dxlog_file2 = "/mnt/ramdisk/work/packages/common/random-access-storage/src/common/abstract-storage.ts";
104
104
  var AbstractStorage = class {
105
105
  // TODO(burdon): Make required.
106
106
  constructor(path) {
@@ -328,6 +328,98 @@ import { callbackify } from "@dxos/node-std/util";
328
328
  import invariant from "tiny-invariant";
329
329
  import { synchronized } from "@dxos/async";
330
330
  import { log as log3 } from "@dxos/log";
331
+
332
+ // packages/common/random-access-storage/src/monitor.ts
333
+ import { unrefTimeout } from "@dxos/async";
334
+ var BUCKET_COLLECTION_INTERVAL = 1e3;
335
+ var StorageMonitor = class {
336
+ constructor() {
337
+ this._enabled = false;
338
+ /**
339
+ * By resource.
340
+ */
341
+ this._buckets = /* @__PURE__ */ new Map();
342
+ }
343
+ enable() {
344
+ this._enabled = true;
345
+ const timer = setInterval(() => {
346
+ this._finalizeBuckets();
347
+ }, BUCKET_COLLECTION_INTERVAL);
348
+ unrefTimeout(timer);
349
+ }
350
+ beginOp(op) {
351
+ if (!this._enabled) {
352
+ return {
353
+ end: () => {
354
+ }
355
+ };
356
+ }
357
+ const beginTime = performance.now();
358
+ return {
359
+ end: () => {
360
+ var _a2, _b;
361
+ const endTime = performance.now();
362
+ const duration = endTime - beginTime;
363
+ const bucket = this._getOrInitBucket(op.resource);
364
+ switch (op.type) {
365
+ case "read":
366
+ bucket.readOps++;
367
+ bucket.readBytes += (_a2 = op.size) != null ? _a2 : 0;
368
+ bucket.readTime += duration;
369
+ break;
370
+ case "write":
371
+ bucket.writeOps++;
372
+ bucket.writeBytes += (_b = op.size) != null ? _b : 0;
373
+ bucket.writeTime += duration;
374
+ break;
375
+ default:
376
+ bucket.otherOps++;
377
+ bucket.otherTime += duration;
378
+ }
379
+ }
380
+ };
381
+ }
382
+ _getOrInitBucket(resource) {
383
+ const bucket = this._buckets.get(resource);
384
+ if (bucket) {
385
+ return bucket;
386
+ }
387
+ const newBucket = {
388
+ resource,
389
+ beginTime: performance.now(),
390
+ endTime: 0,
391
+ usage: 0,
392
+ readOps: 0,
393
+ readBytes: 0,
394
+ readTime: 0,
395
+ writeOps: 0,
396
+ writeBytes: 0,
397
+ writeTime: 0,
398
+ otherOps: 0,
399
+ otherTime: 0
400
+ };
401
+ this._buckets.set(resource, newBucket);
402
+ return newBucket;
403
+ }
404
+ _finalizeBuckets() {
405
+ var _a2;
406
+ const now = performance.now();
407
+ const toEmit = [];
408
+ for (const bucket of this._buckets.values()) {
409
+ bucket.endTime = now;
410
+ bucket.usage = (bucket.readTime + bucket.writeTime + bucket.otherTime) / (bucket.endTime - bucket.beginTime);
411
+ toEmit.push(bucket);
412
+ }
413
+ this._buckets.clear();
414
+ for (const bucket of toEmit) {
415
+ this._getOrInitBucket(bucket.resource);
416
+ }
417
+ ((_a2 = globalThis.__STORAGE_METRICS) != null ? _a2 : globalThis.__STORAGE_METRICS = []).push(...toEmit);
418
+ }
419
+ };
420
+ var STORAGE_MONITOR = new StorageMonitor();
421
+
422
+ // packages/common/random-access-storage/src/browser/web-fs.ts
331
423
  function _ts_decorate(decorators, target, key, desc) {
332
424
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
333
425
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
@@ -338,7 +430,7 @@ function _ts_decorate(decorators, target, key, desc) {
338
430
  r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
339
431
  return c > 3 && r && Object.defineProperty(target, key, r), r;
340
432
  }
341
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/common/random-access-storage/src/browser/web-fs.ts";
433
+ var __dxlog_file3 = "/mnt/ramdisk/work/packages/common/random-access-storage/src/browser/web-fs.ts";
342
434
  var WebFS = class {
343
435
  constructor(path) {
344
436
  this.path = path;
@@ -388,6 +480,7 @@ var WebFS = class {
388
480
  }
389
481
  _createFile(fullName) {
390
482
  return new WebFile({
483
+ fileName: fullName,
391
484
  file: this._initialize().then((root) => root.getFileHandle(fullName, {
392
485
  create: true
393
486
  })),
@@ -402,7 +495,7 @@ var WebFS = class {
402
495
  await Promise.all(Array.from(this._getFiles(path)).map(async ([path2, file]) => {
403
496
  await file.destroy().catch((err) => log3.warn(err, void 0, {
404
497
  F: __dxlog_file3,
405
- L: 105,
498
+ L: 107,
406
499
  S: this,
407
500
  C: (f, a) => f(...a)
408
501
  }));
@@ -417,7 +510,7 @@ var WebFS = class {
417
510
  recursive: true
418
511
  }).catch((err) => log3.warn(err, void 0, {
419
512
  F: __dxlog_file3,
420
- L: 115,
513
+ L: 117,
421
514
  S: this,
422
515
  C: (f, a) => f(...a)
423
516
  }));
@@ -460,7 +553,7 @@ _ts_decorate([
460
553
  ], WebFS.prototype, "_initialize", null);
461
554
  var _a;
462
555
  var WebFile = class extends EventEmitter {
463
- constructor({ file, destroy }) {
556
+ constructor({ fileName, file, destroy }) {
464
557
  super();
465
558
  this.opened = true;
466
559
  this.suspended = false;
@@ -474,6 +567,7 @@ var WebFile = class extends EventEmitter {
474
567
  this.statable = true;
475
568
  this.destroyed = false;
476
569
  this.directory = "";
570
+ // TODO(dmaretskyi): is this used?
477
571
  this.filename = "";
478
572
  this.type = StorageType.WEBFS;
479
573
  this.native = {
@@ -484,60 +578,115 @@ var WebFile = class extends EventEmitter {
484
578
  destroy: callbackify(this.destroy.bind(this)),
485
579
  truncate: callbackify((_a = this.truncate) == null ? void 0 : _a.bind(this))
486
580
  };
581
+ this._fileName = fileName;
487
582
  this._fileHandle = file;
488
583
  this._destroy = destroy;
489
584
  }
490
585
  async write(offset, data) {
491
- const fileHandle = await this._fileHandle;
492
- const writable = await fileHandle.createWritable({
493
- keepExistingData: true
494
- });
495
- await writable.write({
586
+ const metric = STORAGE_MONITOR.beginOp({
587
+ resource: this._fileName,
496
588
  type: "write",
497
- data,
498
- position: offset
589
+ size: data.length
499
590
  });
500
- await writable.close();
591
+ try {
592
+ const fileHandle = await this._fileHandle;
593
+ const writable = await fileHandle.createWritable({
594
+ keepExistingData: true
595
+ });
596
+ await writable.write({
597
+ type: "write",
598
+ data,
599
+ position: offset
600
+ });
601
+ await writable.close();
602
+ } finally {
603
+ metric.end();
604
+ }
501
605
  }
502
606
  async read(offset, size) {
503
- const fileHandle = await this._fileHandle;
504
- const file = await fileHandle.getFile();
505
- if (offset + size > file.size) {
506
- throw new Error("Read out of bounds");
607
+ const metric = STORAGE_MONITOR.beginOp({
608
+ resource: this._fileName,
609
+ type: "read",
610
+ size
611
+ });
612
+ try {
613
+ const fileHandle = await this._fileHandle;
614
+ const file = await fileHandle.getFile();
615
+ if (offset + size > file.size) {
616
+ throw new Error("Read out of bounds");
617
+ }
618
+ return Buffer.from(await file.slice(offset, offset + size).arrayBuffer());
619
+ } finally {
620
+ metric.end();
507
621
  }
508
- return Buffer.from(await file.slice(offset, offset + size).arrayBuffer());
509
622
  }
510
623
  async del(offset, size) {
511
- if (offset < 0 || size < 0) {
512
- return;
513
- }
514
- const fileHandle = await this._fileHandle;
515
- const writable = await fileHandle.createWritable({
516
- keepExistingData: true
624
+ const metric = STORAGE_MONITOR.beginOp({
625
+ resource: this._fileName,
626
+ type: "delete",
627
+ size
517
628
  });
518
- const file = await fileHandle.getFile();
519
- let leftoverSize = 0;
520
- if (offset + size < file.size) {
521
- const leftover = Buffer.from(await file.slice(offset + size, file.size).arrayBuffer());
522
- leftoverSize = leftover.length;
629
+ try {
630
+ if (offset < 0 || size < 0) {
631
+ return;
632
+ }
633
+ const fileHandle = await this._fileHandle;
634
+ const writable = await fileHandle.createWritable({
635
+ keepExistingData: true
636
+ });
637
+ const file = await fileHandle.getFile();
638
+ let leftoverSize = 0;
639
+ if (offset + size < file.size) {
640
+ const leftover = Buffer.from(await file.slice(offset + size, file.size).arrayBuffer());
641
+ leftoverSize = leftover.length;
642
+ await writable.write({
643
+ type: "write",
644
+ data: leftover,
645
+ position: offset
646
+ });
647
+ }
523
648
  await writable.write({
524
- type: "write",
525
- data: leftover,
526
- position: offset
649
+ type: "truncate",
650
+ size: offset + leftoverSize
527
651
  });
652
+ await writable.close();
653
+ } finally {
654
+ metric.end();
528
655
  }
529
- await writable.write({
530
- type: "truncate",
531
- size: offset + leftoverSize
532
- });
533
- await writable.close();
534
656
  }
535
657
  async stat() {
536
- const fileHandle = await this._fileHandle;
537
- const file = await fileHandle.getFile();
538
- return {
539
- size: file.size
540
- };
658
+ const metric = STORAGE_MONITOR.beginOp({
659
+ resource: this._fileName,
660
+ type: "stat"
661
+ });
662
+ try {
663
+ const fileHandle = await this._fileHandle;
664
+ const file = await fileHandle.getFile();
665
+ return {
666
+ size: file.size
667
+ };
668
+ } finally {
669
+ metric.end();
670
+ }
671
+ }
672
+ async truncate(offset) {
673
+ const metric = STORAGE_MONITOR.beginOp({
674
+ resource: this._fileName,
675
+ type: "truncate"
676
+ });
677
+ try {
678
+ const fileHandle = await this._fileHandle;
679
+ const writable = await fileHandle.createWritable({
680
+ keepExistingData: true
681
+ });
682
+ await writable.write({
683
+ type: "truncate",
684
+ size: offset
685
+ });
686
+ await writable.close();
687
+ } finally {
688
+ metric.end();
689
+ }
541
690
  }
542
691
  async close() {
543
692
  }
@@ -545,17 +694,6 @@ var WebFile = class extends EventEmitter {
545
694
  this.destroyed = true;
546
695
  return await this._destroy();
547
696
  }
548
- async truncate(offset) {
549
- const fileHandle = await this._fileHandle;
550
- const writable = await fileHandle.createWritable({
551
- keepExistingData: true
552
- });
553
- await writable.write({
554
- type: "truncate",
555
- size: offset
556
- });
557
- await writable.close();
558
- }
559
697
  };
560
698
  _ts_decorate([
561
699
  synchronized
@@ -571,10 +709,10 @@ _ts_decorate([
571
709
  ], WebFile.prototype, "stat", null);
572
710
  _ts_decorate([
573
711
  synchronized
574
- ], WebFile.prototype, "destroy", null);
712
+ ], WebFile.prototype, "truncate", null);
575
713
  _ts_decorate([
576
714
  synchronized
577
- ], WebFile.prototype, "truncate", null);
715
+ ], WebFile.prototype, "destroy", null);
578
716
 
579
717
  // packages/common/random-access-storage/src/browser/storage.ts
580
718
  var createStorage = ({ type, root = "" } = {}) => {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../src/common/abstract-storage.ts", "../../../src/common/utils.ts", "../../../src/common/directory.ts", "../../../src/common/file.ts", "../../../src/common/memory-storage.ts", "../../../src/common/storage.ts", "../../../src/browser/firefox-storage.ts", "../../../src/browser/browser-storage.ts", "../../../src/browser/idb-storage.ts", "../../../src/browser/web-fs.ts", "../../../src/browser/storage.ts"],
4
- "sourcesContent": ["//\n// Copyright 2021 DXOS.org\n//\n\nimport { join } from 'node:path';\nimport { inspect } from 'node:util';\nimport type { RandomAccessStorage } from 'random-access-storage';\n\nimport { inspectObject } from '@dxos/debug';\nimport { log } from '@dxos/log';\n\nimport { Directory } from './directory';\nimport { File, wrapFile } from './file';\nimport { Storage, StorageType } from './storage';\nimport { getFullPath } from './utils';\n\n/**\n * Base class for all storage implementations.\n * https://github.com/random-access-storage\n * https://github.com/random-access-storage/random-access-storage\n */\nexport abstract class AbstractStorage implements Storage {\n protected readonly _files = new Map<string, File>();\n\n public abstract readonly type: StorageType;\n\n // TODO(burdon): Make required.\n constructor(public readonly path: string) {}\n\n [inspect.custom]() {\n return inspectObject(this);\n }\n\n toJSON() {\n return { type: this.type, path: this.path };\n }\n\n public get size() {\n return this._files.size;\n }\n\n // TODO(burdon): Make required.\n public createDirectory(sub = ''): Directory {\n // invariant(sub.length);\n return new Directory(\n this.type,\n getFullPath(this.path, sub),\n this._list.bind(this),\n (...args) => this.getOrCreateFile(...args),\n () => this._delete(sub),\n );\n }\n\n /**\n * Delete all files.\n */\n async reset() {\n try {\n log.info('Erasing all data...');\n await this._closeFilesInPath('');\n await this._delete('');\n await this._destroy();\n log('Erased...');\n } catch (err: any) {\n log.catch(err);\n }\n }\n\n protected async _list(path: string): Promise<string[]> {\n // TODO(dmaretskyi): Fix me.\n return Array.from(this._getFiles(path).keys()).map((filename) => {\n let name = filename.replace(path, '');\n if (name.startsWith('/')) {\n name = name.substring(1);\n }\n return name;\n });\n }\n\n protected getOrCreateFile(path: string, filename: string, opts?: any): File {\n const fullPath = join(path, filename);\n\n let native;\n let file = this._getFileIfExists(fullPath);\n if (file) {\n if (!file.closed) {\n return file;\n }\n\n native = this._openFile(file.native);\n }\n\n if (!native) {\n native = this._createFile(path, filename, opts);\n }\n\n file = wrapFile(native, this.type);\n this._files.set(fullPath, file);\n return file;\n }\n\n protected _destroy(): Promise<void> | undefined {\n return undefined;\n }\n\n /**\n * Attempt to reopen file.\n */\n protected _openFile(file: RandomAccessStorage): RandomAccessStorage | undefined {\n return undefined;\n }\n\n protected abstract _createFile(path: string, filename: string, opts?: any): RandomAccessStorage;\n\n private _getFileIfExists(filename: string): File | undefined {\n if (this._files.has(filename)) {\n const file = this._files.get(filename);\n if (file && !file.destroyed) {\n return file;\n }\n }\n }\n\n private _getFiles(path: string): Map<string, File> {\n const fullPath = getFullPath(this.path, path);\n return new Map(\n [...this._files.entries()].filter(([path, file]) => path.includes(fullPath) && file.destroyed !== true),\n );\n }\n\n private async _closeFilesInPath(path: string): Promise<void> {\n await Promise.all(\n Array.from(this._getFiles(path).values()).map((file) => file.close().catch((err: any) => log.catch(err))),\n );\n }\n\n // TODO(burdon): Delete directory (not just listed files).\n protected async _delete(path: string): Promise<void> {\n await Promise.all(\n Array.from(this._getFiles(path)).map(([path, file]) => {\n return file\n .destroy()\n .then(() => this._files.delete(path))\n .catch((err: any) => log.error(err.message));\n }),\n );\n }\n}\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { join } from 'node:path';\n\n// TODO(burdon): Document.\nexport const stringDiff = (first: string, second: string) => first.split(second).join('');\n\nexport const getFullPath = (root: string, path: string) => join(root, stringDiff(path, root));\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { File } from './file';\nimport { StorageType } from './storage';\nimport { getFullPath } from './utils';\n\n/**\n * Wraps a directory in the storage file system.\n */\nexport class Directory {\n constructor(\n public readonly type: StorageType,\n public readonly path: string,\n // TODO(burdon): Create interface for these methods (shared with AbstractStorage).\n private readonly _list: (path: string) => Promise<string[]>,\n private readonly _getOrCreateFile: (path: string, filename: string, opts?: any) => File,\n private readonly _delete: () => Promise<void>,\n ) {}\n\n toString() {\n return `Directory(${JSON.stringify({ type: this.type, path: this.path })})`;\n }\n\n /**\n * Create a new sub-directory.\n */\n createDirectory(path: string): Directory {\n return new Directory(this.type, getFullPath(this.path, path), this._list, this._getOrCreateFile, this._delete);\n }\n\n /**\n * Get all files in the current directory.\n */\n list(): Promise<string[]> {\n return this._list(this.path);\n }\n\n /**\n * Get or create a new file.\n */\n getOrCreateFile(filename: string, opts?: any): File {\n return this._getOrCreateFile(this.path, filename, opts);\n }\n\n /**\n * Close and delete all files in the directory and all its sub-directories.\n */\n async delete() {\n await this._delete();\n }\n}\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport pify from 'pify';\nimport type { FileStat, RandomAccessStorage, RandomAccessStorageProperties } from 'random-access-storage';\n\nimport { log } from '@dxos/log';\n\nimport { StorageType } from './storage';\n\n/**\n * Random access file wrapper.\n * https://github.com/random-access-storage/random-access-storage\n */\nexport interface File extends RandomAccessStorageProperties {\n readonly destroyed: boolean;\n\n // TODO(burdon): Can we remove these since they are not standard across implementations?\n readonly directory: string;\n readonly filename: string;\n\n // Added by factory.\n readonly type: StorageType;\n readonly native: RandomAccessStorage;\n\n write(offset: number, data: Buffer): Promise<void>;\n read(offset: number, size: number): Promise<Buffer>;\n del(offset: number, size: number): Promise<void>;\n stat(): Promise<FileStat>;\n close(): Promise<Error | void>;\n destroy(): Promise<Error | void>;\n\n // Not supported in node, memory.\n truncate?(offset: number): Promise<void>;\n\n // random-access-memory only.\n clone?(): RandomAccessStorage;\n}\n\nconst pifyFields = (object: any, type: StorageType, fields: string[]) => {\n for (const field of fields) {\n if (!object[field]) {\n // TODO(burdon): Suppress warning and throw error if used.\n // console.warn(`Field not supported for type: ${JSON.stringify({ type, field })}`);\n } else {\n const fn = pify(object[field].bind(object));\n object[field] = async (...args: any) => {\n const before = performance.now();\n\n const res = await fn(...args);\n\n const elapsed = performance.now() - before;\n if (elapsed > 10) {\n log.warn('Slow storage operation', { type, operation: field, elapsed });\n }\n\n return res;\n };\n }\n }\n\n return object;\n};\n\n/**\n * Construct async File wrapper.\n * NOTE: This is safe since these are interface methods only (not used internally).\n */\nexport const wrapFile = (native: RandomAccessStorage, type: StorageType): File => {\n const file = pifyFields(native, type, ['write', 'read', 'del', 'stat', 'close', 'destroy', 'truncate']);\n return Object.assign(file, { type, native });\n};\n", "//\n// Copyright 2021 DXOS.org\n//\n\nimport ram from 'random-access-memory';\nimport { Callback, RandomAccessStorage } from 'random-access-storage';\n\nimport { arrayToBuffer } from '@dxos/util';\n\nimport { AbstractStorage } from './abstract-storage';\nimport { StorageType } from './storage';\n\n/**\n * Storage interface implementation for RAM.\n * https://github.com/random-access-storage/random-access-memory\n */\nexport class MemoryStorage extends AbstractStorage {\n public override type: StorageType = StorageType.RAM;\n\n protected override _createFile(path: string, filename: string): RandomAccessStorage {\n return this._patchFile(ram());\n }\n\n protected override _openFile(file: RandomAccessStorage): RandomAccessStorage {\n const newFile = file.clone!();\n (newFile as any).closed = false;\n return this._patchFile(newFile);\n }\n\n private _patchFile(file: RandomAccessStorage): RandomAccessStorage {\n // Patch required to make consistent across platforms.\n const trueRead = file.read.bind(file);\n\n file.read = (offset: number, size: number, cb: Callback<Buffer>) =>\n trueRead(offset, size, (err: Error | null, data?: Buffer) => {\n if (err) {\n return cb(err);\n } else {\n return cb(err, arrayToBuffer(data!));\n }\n });\n\n return file;\n }\n}\n", "//\n// Copyright 2021 DXOS.org\n//\n\nimport { Directory } from './directory';\n\n// TODO(burdon): Reconcile with ConfigProto.\nexport enum StorageType {\n RAM = 'ram',\n IDB = 'idb',\n CHROME = 'chrome',\n FIREFOX = 'firefox',\n NODE = 'node',\n WEBFS = 'webfs',\n}\n\nexport type DiskInfo = {\n /**\n * Bytes.\n */\n used: number;\n};\n\nexport interface Storage {\n readonly path: string;\n readonly type: StorageType;\n readonly size: number;\n\n getDiskInfo?(): Promise<DiskInfo>;\n\n // TODO(burdon): Make required.\n createDirectory: (path?: string) => Directory;\n reset: () => Promise<void>;\n}\n\nexport type StorageConstructor = (params?: { type?: StorageType; root?: string }) => Storage;\n", "//\n// Copyright 2021 DXOS.org\n//\n\n// NOTE: Removing the .js extension here breaks usage in create-react-app.\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport raw from 'random-access-web/mutable-file-wrapper.js';\n\nimport { StorageType } from '../common';\nimport { BrowserStorage } from './browser-storage';\n\n/**\n * Storage interface implementation for Firefox browser.\n * https://github.com/random-access-storage/random-access-web\n */\nexport class FirefoxStorage extends BrowserStorage {\n public override type: StorageType = StorageType.FIREFOX;\n\n protected override _createFileStorage(path: string) {\n return raw({ name: path });\n }\n}\n", "//\n// Copyright 2021 DXOS.org\n//\n\nimport { join } from 'node:path';\nimport type { RandomAccessStorage } from 'random-access-storage';\n\nimport { AbstractStorage } from '../common';\n\n/**\n * Base class for random access files based on IDB.\n */\nexport abstract class BrowserStorage extends AbstractStorage {\n private readonly _fileStorage: (filename: string, opts?: {}) => RandomAccessStorage;\n\n constructor(path: string) {\n super(path);\n this._fileStorage = this._createFileStorage(path);\n }\n\n protected _createFile(path: string, filename: string): RandomAccessStorage {\n const fullPath = join(path, filename);\n return this._fileStorage(fullPath);\n }\n\n protected abstract _createFileStorage(path: string): (filename: string, opts?: {}) => RandomAccessStorage;\n\n protected override async _destroy() {\n // eslint-disable-next-line no-undef\n return new Promise<void>((resolve, reject) => {\n const request = indexedDB.deleteDatabase(this.path);\n request.onsuccess = () => {\n resolve();\n };\n request.onupgradeneeded = () => {\n reject(new Error('Upgrade needed.'));\n };\n request.onblocked = () => {\n reject(new Error('Blocked.'));\n };\n request.onerror = (err: any) => {\n reject(err);\n };\n });\n }\n}\n", "//\n// Copyright 2021 DXOS.org\n//\n\nimport idb from 'random-access-idb';\n\nimport { StorageType } from '../common';\nimport { BrowserStorage } from './browser-storage';\n\n/**\n * Storage interface implementation for index DB.\n * https://github.com/random-access-storage/random-access-idb\n */\nexport class IDbStorage extends BrowserStorage {\n public override type: StorageType = StorageType.IDB;\n\n protected override _createFileStorage(path: string) {\n return idb(path);\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { EventEmitter } from 'node:events';\nimport { callbackify } from 'node:util';\nimport { RandomAccessStorage } from 'random-access-storage';\nimport invariant from 'tiny-invariant';\n\nimport { synchronized } from '@dxos/async';\nimport { log } from '@dxos/log';\n\nimport { Directory, File, Storage, StorageType, getFullPath, DiskInfo } from '../common';\n\n/**\n * Web file systems.\n */\nexport class WebFS implements Storage {\n readonly type = StorageType.WEBFS;\n\n protected readonly _files = new Map<string, File>();\n protected _root?: FileSystemDirectoryHandle;\n\n constructor(public readonly path: string) {}\n\n public get size() {\n return this._files.size;\n }\n\n private _getFiles(path: string): Map<string, File> {\n const fullName = this._getFullFilename(this.path, path);\n return new Map(\n [...this._files.entries()].filter(([path, file]) => path.includes(fullName) && file.destroyed !== true),\n );\n }\n\n private async _list(path: string): Promise<string[]> {\n const fullName = this._getFullFilename(path);\n\n const root = await this._initialize();\n\n // TODO(dmaretskyi): While we're storing all files in flat namespace we just iterate the root.\n // console.log({ path, fullName })\n // let dir: FileSystemDirectoryHandle;\n // if (path === '') {\n // dir = root;\n // } else {\n // dir = await root.getDirectoryHandle(fullName, { create: true });\n // }\n const entries: string[] = [];\n\n for await (const entry of (root as any).keys()) {\n if (entry.startsWith(fullName + '_')) {\n entries.push(entry.slice(fullName.length + 1));\n }\n }\n return entries;\n }\n\n @synchronized\n private async _initialize() {\n if (this._root) {\n return this._root;\n }\n this._root = await navigator.storage.getDirectory();\n invariant(this._root, 'Root is undefined');\n return this._root;\n }\n\n createDirectory(sub = '') {\n return new Directory(\n this.type,\n getFullPath(this.path, sub),\n (path) => this._list(path),\n (...args) => this.getOrCreateFile(...args),\n () => this._delete(sub),\n );\n }\n\n getOrCreateFile(path: string, filename: string, opts?: any): File {\n const fullName = this._getFullFilename(path, filename);\n const existingFile = this._files.get(fullName);\n if (existingFile) {\n return existingFile;\n }\n const file = this._createFile(fullName);\n this._files.set(fullName, file);\n return file;\n }\n\n private _createFile(fullName: string) {\n return new WebFile({\n file: this._initialize().then((root) => root.getFileHandle(fullName, { create: true })),\n destroy: async () => {\n this._files.delete(fullName);\n const root = await this._initialize();\n return root.removeEntry(fullName);\n },\n });\n }\n\n private async _delete(path: string): Promise<void> {\n await Promise.all(\n Array.from(this._getFiles(path)).map(async ([path, file]) => {\n await file.destroy().catch((err: any) => log.warn(err));\n this._files.delete(path);\n }),\n );\n }\n\n async reset() {\n await this._initialize();\n for await (const filename of await (this._root as any).keys()) {\n this._files.delete(filename);\n await this._root!.removeEntry(filename, { recursive: true }).catch((err: any) => log.warn(err));\n }\n this._root = undefined;\n }\n\n private _getFullFilename(path: string, filename?: string) {\n // Replace slashes with underscores. Because we can't have slashes in filenames in Browser File Handle API.\n if (filename) {\n return getFullPath(path, filename).split('/').join('_');\n } else {\n return path.split('/').join('_');\n }\n }\n\n async getDiskInfo(): Promise<DiskInfo> {\n let used = 0;\n\n const recurse = async (handle: FileSystemDirectoryHandle) => {\n const promises = [];\n\n for await (const entry of (handle as any).values()) {\n promises.push(\n (async () => {\n switch (entry.kind) {\n case 'file':\n used += await (entry as FileSystemFileHandle).getFile().then((f) => (used += f.size));\n break;\n case 'directory':\n await recurse(entry as FileSystemDirectoryHandle);\n break;\n }\n })(),\n );\n }\n await Promise.all(promises);\n };\n\n await recurse(this._root!);\n\n return {\n used,\n };\n }\n}\n\n// TODO(mykola): Remove EventEmitter.\nexport class WebFile extends EventEmitter implements File {\n readonly opened: boolean = true;\n readonly suspended: boolean = false;\n readonly closed: boolean = false;\n readonly unlinked: boolean = false;\n readonly writing: boolean = false;\n readonly readable: boolean = true;\n readonly writable: boolean = true;\n readonly deletable: boolean = true;\n readonly truncatable: boolean = true;\n readonly statable: boolean = true;\n\n private readonly _fileHandle: Promise<FileSystemFileHandle>;\n private readonly _destroy: () => Promise<void>;\n\n constructor({ file, destroy }: { file: Promise<FileSystemFileHandle>; destroy: () => Promise<void> }) {\n super();\n this._fileHandle = file;\n this._destroy = destroy;\n }\n\n destroyed = false;\n directory = '';\n filename = '';\n type: StorageType = StorageType.WEBFS;\n native: RandomAccessStorage = {\n write: callbackify(this.write.bind(this)),\n read: callbackify(this.read.bind(this)),\n del: callbackify(this.del.bind(this)),\n stat: callbackify(this.stat.bind(this)),\n destroy: callbackify(this.destroy.bind(this)),\n truncate: callbackify(this.truncate?.bind(this)),\n } as RandomAccessStorage;\n\n @synchronized\n async write(offset: number, data: Buffer) {\n // TODO(mykola): Fix types.\n const fileHandle: any = await this._fileHandle;\n const writable = await fileHandle.createWritable({ keepExistingData: true });\n await writable.write({ type: 'write', data, position: offset });\n await writable.close();\n }\n\n @synchronized\n async read(offset: number, size: number) {\n const fileHandle: any = await this._fileHandle;\n const file = await fileHandle.getFile();\n if (offset + size > file.size) {\n throw new Error('Read out of bounds');\n }\n // does not copy the buffer\n return Buffer.from(await file.slice(offset, offset + size).arrayBuffer());\n }\n\n @synchronized\n async del(offset: number, size: number) {\n if (offset < 0 || size < 0) {\n return;\n }\n const fileHandle: any = await this._fileHandle;\n const writable = await fileHandle.createWritable({ keepExistingData: true });\n const file = await fileHandle.getFile();\n let leftoverSize = 0;\n if (offset + size < file.size) {\n // does not copy the buffer\n const leftover = Buffer.from(await file.slice(offset + size, file.size).arrayBuffer());\n leftoverSize = leftover.length;\n await writable.write({ type: 'write', data: leftover, position: offset });\n }\n\n await writable.write({ type: 'truncate', size: offset + leftoverSize });\n await writable.close();\n }\n\n @synchronized\n async stat() {\n const fileHandle: any = await this._fileHandle;\n const file = await fileHandle.getFile();\n return {\n size: file.size,\n };\n }\n\n async close(): Promise<void> {}\n\n @synchronized\n async destroy() {\n this.destroyed = true;\n return await this._destroy();\n }\n\n @synchronized\n async truncate(offset: number) {\n const fileHandle: any = await this._fileHandle;\n const writable = await fileHandle.createWritable({ keepExistingData: true });\n await writable.write({ type: 'truncate', size: offset });\n await writable.close();\n }\n}\n", "//\n// Copyright 2021 DXOS.org\n//\n\nimport { MemoryStorage, Storage, StorageConstructor, StorageType } from '../common';\nimport { FirefoxStorage } from './firefox-storage';\nimport { IDbStorage } from './idb-storage';\nimport { WebFS } from './web-fs';\n\nexport const createStorage: StorageConstructor = ({ type, root = '' } = {}): Storage => {\n if (type === undefined) {\n if (\n navigator &&\n navigator.storage &&\n typeof navigator.storage.getDirectory === 'function' &&\n FileSystemFileHandle &&\n typeof (FileSystemFileHandle.prototype as any).createWritable === 'function'\n ) {\n return new WebFS(root);\n } else {\n return new IDbStorage(root);\n }\n }\n\n switch (type) {\n case StorageType.RAM: {\n return new MemoryStorage(root);\n }\n\n case StorageType.IDB:\n case StorageType.CHROME: {\n return new IDbStorage(root);\n }\n\n case StorageType.FIREFOX: {\n return new FirefoxStorage(root);\n }\n\n case StorageType.WEBFS: {\n return new WebFS(root);\n }\n\n default: {\n throw new Error(`Invalid type: ${type}`);\n }\n }\n};\n"],
5
- "mappings": "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",
6
- "names": ["join", "inspect", "inspectObject", "log", "join", "stringDiff", "first", "second", "split", "join", "getFullPath", "root", "path", "Directory", "constructor", "type", "path", "_list", "_getOrCreateFile", "_delete", "toString", "JSON", "stringify", "createDirectory", "getFullPath", "list", "getOrCreateFile", "filename", "opts", "delete", "pify", "log", "pifyFields", "object", "type", "fields", "field", "fn", "bind", "args", "before", "performance", "now", "res", "elapsed", "warn", "operation", "wrapFile", "native", "file", "Object", "assign", "AbstractStorage", "constructor", "path", "_files", "Map", "inspect", "custom", "inspectObject", "toJSON", "type", "size", "createDirectory", "sub", "Directory", "getFullPath", "_list", "bind", "args", "getOrCreateFile", "_delete", "reset", "log", "info", "_closeFilesInPath", "_destroy", "err", "catch", "Array", "from", "_getFiles", "keys", "map", "filename", "name", "replace", "startsWith", "substring", "opts", "fullPath", "join", "native", "file", "_getFileIfExists", "closed", "_openFile", "_createFile", "wrapFile", "set", "undefined", "has", "get", "destroyed", "entries", "filter", "includes", "Promise", "all", "values", "close", "destroy", "then", "delete", "error", "message", "ram", "arrayToBuffer", "StorageType", "RAM", "IDB", "CHROME", "FIREFOX", "NODE", "WEBFS", "MemoryStorage", "AbstractStorage", "type", "StorageType", "RAM", "_createFile", "path", "filename", "_patchFile", "ram", "_openFile", "file", "newFile", "clone", "closed", "trueRead", "read", "bind", "offset", "size", "cb", "err", "data", "arrayToBuffer", "raw", "join", "BrowserStorage", "AbstractStorage", "constructor", "path", "_fileStorage", "_createFileStorage", "_createFile", "filename", "fullPath", "join", "_destroy", "Promise", "resolve", "reject", "request", "indexedDB", "deleteDatabase", "onsuccess", "onupgradeneeded", "Error", "onblocked", "onerror", "err", "FirefoxStorage", "BrowserStorage", "type", "StorageType", "FIREFOX", "_createFileStorage", "path", "raw", "name", "idb", "IDbStorage", "BrowserStorage", "type", "StorageType", "IDB", "_createFileStorage", "path", "idb", "EventEmitter", "callbackify", "invariant", "synchronized", "log", "WebFS", "constructor", "path", "type", "StorageType", "WEBFS", "_files", "Map", "size", "_getFiles", "fullName", "_getFullFilename", "entries", "filter", "file", "includes", "destroyed", "_list", "root", "_initialize", "entry", "keys", "startsWith", "push", "slice", "length", "_root", "navigator", "storage", "getDirectory", "invariant", "createDirectory", "sub", "Directory", "getFullPath", "args", "getOrCreateFile", "_delete", "filename", "opts", "existingFile", "get", "_createFile", "set", "WebFile", "then", "getFileHandle", "create", "destroy", "delete", "removeEntry", "Promise", "all", "Array", "from", "map", "catch", "err", "log", "warn", "reset", "recursive", "undefined", "split", "join", "getDiskInfo", "used", "recurse", "handle", "promises", "values", "kind", "getFile", "f", "synchronized", "EventEmitter", "opened", "suspended", "closed", "unlinked", "writing", "readable", "writable", "deletable", "truncatable", "statable", "directory", "native", "write", "callbackify", "bind", "read", "del", "stat", "truncate", "_fileHandle", "_destroy", "offset", "data", "fileHandle", "createWritable", "keepExistingData", "position", "close", "Error", "Buffer", "arrayBuffer", "leftoverSize", "leftover", "createStorage", "type", "root", "undefined", "navigator", "storage", "getDirectory", "FileSystemFileHandle", "prototype", "createWritable", "WebFS", "IDbStorage", "StorageType", "RAM", "MemoryStorage", "IDB", "CHROME", "FIREFOX", "FirefoxStorage", "WEBFS", "Error"]
3
+ "sources": ["../../../src/common/abstract-storage.ts", "../../../src/common/utils.ts", "../../../src/common/directory.ts", "../../../src/common/file.ts", "../../../src/common/memory-storage.ts", "../../../src/common/storage.ts", "../../../src/browser/firefox-storage.ts", "../../../src/browser/browser-storage.ts", "../../../src/browser/idb-storage.ts", "../../../src/browser/web-fs.ts", "../../../src/monitor.ts", "../../../src/browser/storage.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2021 DXOS.org\n//\n\nimport { join } from 'node:path';\nimport { inspect } from 'node:util';\nimport type { RandomAccessStorage } from 'random-access-storage';\n\nimport { inspectObject } from '@dxos/debug';\nimport { log } from '@dxos/log';\n\nimport { Directory } from './directory';\nimport { File, wrapFile } from './file';\nimport { Storage, StorageType } from './storage';\nimport { getFullPath } from './utils';\n\n/**\n * Base class for all storage implementations.\n * https://github.com/random-access-storage\n * https://github.com/random-access-storage/random-access-storage\n */\nexport abstract class AbstractStorage implements Storage {\n protected readonly _files = new Map<string, File>();\n\n public abstract readonly type: StorageType;\n\n // TODO(burdon): Make required.\n constructor(public readonly path: string) {}\n\n [inspect.custom]() {\n return inspectObject(this);\n }\n\n toJSON() {\n return { type: this.type, path: this.path };\n }\n\n public get size() {\n return this._files.size;\n }\n\n // TODO(burdon): Make required.\n public createDirectory(sub = ''): Directory {\n // invariant(sub.length);\n return new Directory(\n this.type,\n getFullPath(this.path, sub),\n this._list.bind(this),\n (...args) => this.getOrCreateFile(...args),\n () => this._delete(sub),\n );\n }\n\n /**\n * Delete all files.\n */\n async reset() {\n try {\n log.info('Erasing all data...');\n await this._closeFilesInPath('');\n await this._delete('');\n await this._destroy();\n log('Erased...');\n } catch (err: any) {\n log.catch(err);\n }\n }\n\n protected async _list(path: string): Promise<string[]> {\n // TODO(dmaretskyi): Fix me.\n return Array.from(this._getFiles(path).keys()).map((filename) => {\n let name = filename.replace(path, '');\n if (name.startsWith('/')) {\n name = name.substring(1);\n }\n return name;\n });\n }\n\n protected getOrCreateFile(path: string, filename: string, opts?: any): File {\n const fullPath = join(path, filename);\n\n let native;\n let file = this._getFileIfExists(fullPath);\n if (file) {\n if (!file.closed) {\n return file;\n }\n\n native = this._openFile(file.native);\n }\n\n if (!native) {\n native = this._createFile(path, filename, opts);\n }\n\n file = wrapFile(native, this.type);\n this._files.set(fullPath, file);\n return file;\n }\n\n protected _destroy(): Promise<void> | undefined {\n return undefined;\n }\n\n /**\n * Attempt to reopen file.\n */\n protected _openFile(file: RandomAccessStorage): RandomAccessStorage | undefined {\n return undefined;\n }\n\n protected abstract _createFile(path: string, filename: string, opts?: any): RandomAccessStorage;\n\n private _getFileIfExists(filename: string): File | undefined {\n if (this._files.has(filename)) {\n const file = this._files.get(filename);\n if (file && !file.destroyed) {\n return file;\n }\n }\n }\n\n private _getFiles(path: string): Map<string, File> {\n const fullPath = getFullPath(this.path, path);\n return new Map(\n [...this._files.entries()].filter(([path, file]) => path.includes(fullPath) && file.destroyed !== true),\n );\n }\n\n private async _closeFilesInPath(path: string): Promise<void> {\n await Promise.all(\n Array.from(this._getFiles(path).values()).map((file) => file.close().catch((err: any) => log.catch(err))),\n );\n }\n\n // TODO(burdon): Delete directory (not just listed files).\n protected async _delete(path: string): Promise<void> {\n await Promise.all(\n Array.from(this._getFiles(path)).map(([path, file]) => {\n return file\n .destroy()\n .then(() => this._files.delete(path))\n .catch((err: any) => log.error(err.message));\n }),\n );\n }\n}\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { join } from 'node:path';\n\n// TODO(burdon): Document.\nexport const stringDiff = (first: string, second: string) => first.split(second).join('');\n\nexport const getFullPath = (root: string, path: string) => join(root, stringDiff(path, root));\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { File } from './file';\nimport { StorageType } from './storage';\nimport { getFullPath } from './utils';\n\n/**\n * Wraps a directory in the storage file system.\n */\nexport class Directory {\n constructor(\n public readonly type: StorageType,\n public readonly path: string,\n // TODO(burdon): Create interface for these methods (shared with AbstractStorage).\n private readonly _list: (path: string) => Promise<string[]>,\n private readonly _getOrCreateFile: (path: string, filename: string, opts?: any) => File,\n private readonly _delete: () => Promise<void>,\n ) {}\n\n toString() {\n return `Directory(${JSON.stringify({ type: this.type, path: this.path })})`;\n }\n\n /**\n * Create a new sub-directory.\n */\n createDirectory(path: string): Directory {\n return new Directory(this.type, getFullPath(this.path, path), this._list, this._getOrCreateFile, this._delete);\n }\n\n /**\n * Get all files in the current directory.\n */\n list(): Promise<string[]> {\n return this._list(this.path);\n }\n\n /**\n * Get or create a new file.\n */\n getOrCreateFile(filename: string, opts?: any): File {\n return this._getOrCreateFile(this.path, filename, opts);\n }\n\n /**\n * Close and delete all files in the directory and all its sub-directories.\n */\n async delete() {\n await this._delete();\n }\n}\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport pify from 'pify';\nimport type { FileStat, RandomAccessStorage, RandomAccessStorageProperties } from 'random-access-storage';\n\nimport { log } from '@dxos/log';\n\nimport { StorageType } from './storage';\n\n/**\n * Random access file wrapper.\n * https://github.com/random-access-storage/random-access-storage\n */\nexport interface File extends RandomAccessStorageProperties {\n readonly destroyed: boolean;\n\n // TODO(burdon): Can we remove these since they are not standard across implementations?\n readonly directory: string;\n readonly filename: string;\n\n // Added by factory.\n readonly type: StorageType;\n readonly native: RandomAccessStorage;\n\n write(offset: number, data: Buffer): Promise<void>;\n read(offset: number, size: number): Promise<Buffer>;\n del(offset: number, size: number): Promise<void>;\n stat(): Promise<FileStat>;\n close(): Promise<Error | void>;\n destroy(): Promise<Error | void>;\n\n // Not supported in node, memory.\n truncate?(offset: number): Promise<void>;\n\n // random-access-memory only.\n clone?(): RandomAccessStorage;\n}\n\nconst pifyFields = (object: any, type: StorageType, fields: string[]) => {\n for (const field of fields) {\n if (!object[field]) {\n // TODO(burdon): Suppress warning and throw error if used.\n // console.warn(`Field not supported for type: ${JSON.stringify({ type, field })}`);\n } else {\n const fn = pify(object[field].bind(object));\n object[field] = async (...args: any) => {\n const before = performance.now();\n\n const res = await fn(...args);\n\n const elapsed = performance.now() - before;\n if (elapsed > 10) {\n log.warn('Slow storage operation', { type, operation: field, elapsed });\n }\n\n return res;\n };\n }\n }\n\n return object;\n};\n\n/**\n * Construct async File wrapper.\n * NOTE: This is safe since these are interface methods only (not used internally).\n */\nexport const wrapFile = (native: RandomAccessStorage, type: StorageType): File => {\n const file = pifyFields(native, type, ['write', 'read', 'del', 'stat', 'close', 'destroy', 'truncate']);\n return Object.assign(file, { type, native });\n};\n", "//\n// Copyright 2021 DXOS.org\n//\n\nimport ram from 'random-access-memory';\nimport { Callback, RandomAccessStorage } from 'random-access-storage';\n\nimport { arrayToBuffer } from '@dxos/util';\n\nimport { AbstractStorage } from './abstract-storage';\nimport { StorageType } from './storage';\n\n/**\n * Storage interface implementation for RAM.\n * https://github.com/random-access-storage/random-access-memory\n */\nexport class MemoryStorage extends AbstractStorage {\n public override type: StorageType = StorageType.RAM;\n\n protected override _createFile(path: string, filename: string): RandomAccessStorage {\n return this._patchFile(ram());\n }\n\n protected override _openFile(file: RandomAccessStorage): RandomAccessStorage {\n const newFile = file.clone!();\n (newFile as any).closed = false;\n return this._patchFile(newFile);\n }\n\n private _patchFile(file: RandomAccessStorage): RandomAccessStorage {\n // Patch required to make consistent across platforms.\n const trueRead = file.read.bind(file);\n\n file.read = (offset: number, size: number, cb: Callback<Buffer>) =>\n trueRead(offset, size, (err: Error | null, data?: Buffer) => {\n if (err) {\n return cb(err);\n } else {\n return cb(err, arrayToBuffer(data!));\n }\n });\n\n return file;\n }\n}\n", "//\n// Copyright 2021 DXOS.org\n//\n\nimport { Directory } from './directory';\n\n// TODO(burdon): Reconcile with ConfigProto.\nexport enum StorageType {\n RAM = 'ram',\n IDB = 'idb',\n CHROME = 'chrome',\n FIREFOX = 'firefox',\n NODE = 'node',\n WEBFS = 'webfs',\n}\n\nexport type DiskInfo = {\n /**\n * Bytes.\n */\n used: number;\n};\n\nexport interface Storage {\n readonly path: string;\n readonly type: StorageType;\n readonly size: number;\n\n getDiskInfo?(): Promise<DiskInfo>;\n\n // TODO(burdon): Make required.\n createDirectory: (path?: string) => Directory;\n reset: () => Promise<void>;\n}\n\nexport type StorageConstructor = (params?: { type?: StorageType; root?: string }) => Storage;\n", "//\n// Copyright 2021 DXOS.org\n//\n\n// NOTE: Removing the .js extension here breaks usage in create-react-app.\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport raw from 'random-access-web/mutable-file-wrapper.js';\n\nimport { StorageType } from '../common';\nimport { BrowserStorage } from './browser-storage';\n\n/**\n * Storage interface implementation for Firefox browser.\n * https://github.com/random-access-storage/random-access-web\n */\nexport class FirefoxStorage extends BrowserStorage {\n public override type: StorageType = StorageType.FIREFOX;\n\n protected override _createFileStorage(path: string) {\n return raw({ name: path });\n }\n}\n", "//\n// Copyright 2021 DXOS.org\n//\n\nimport { join } from 'node:path';\nimport type { RandomAccessStorage } from 'random-access-storage';\n\nimport { AbstractStorage } from '../common';\n\n/**\n * Base class for random access files based on IDB.\n */\nexport abstract class BrowserStorage extends AbstractStorage {\n private readonly _fileStorage: (filename: string, opts?: {}) => RandomAccessStorage;\n\n constructor(path: string) {\n super(path);\n this._fileStorage = this._createFileStorage(path);\n }\n\n protected _createFile(path: string, filename: string): RandomAccessStorage {\n const fullPath = join(path, filename);\n return this._fileStorage(fullPath);\n }\n\n protected abstract _createFileStorage(path: string): (filename: string, opts?: {}) => RandomAccessStorage;\n\n protected override async _destroy() {\n // eslint-disable-next-line no-undef\n return new Promise<void>((resolve, reject) => {\n const request = indexedDB.deleteDatabase(this.path);\n request.onsuccess = () => {\n resolve();\n };\n request.onupgradeneeded = () => {\n reject(new Error('Upgrade needed.'));\n };\n request.onblocked = () => {\n reject(new Error('Blocked.'));\n };\n request.onerror = (err: any) => {\n reject(err);\n };\n });\n }\n}\n", "//\n// Copyright 2021 DXOS.org\n//\n\nimport idb from 'random-access-idb';\n\nimport { StorageType } from '../common';\nimport { BrowserStorage } from './browser-storage';\n\n/**\n * Storage interface implementation for index DB.\n * https://github.com/random-access-storage/random-access-idb\n */\nexport class IDbStorage extends BrowserStorage {\n public override type: StorageType = StorageType.IDB;\n\n protected override _createFileStorage(path: string) {\n return idb(path);\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { EventEmitter } from 'node:events';\nimport { callbackify } from 'node:util';\nimport { RandomAccessStorage } from 'random-access-storage';\nimport invariant from 'tiny-invariant';\n\nimport { synchronized } from '@dxos/async';\nimport { log } from '@dxos/log';\n\nimport { Directory, File, Storage, StorageType, getFullPath, DiskInfo } from '../common';\nimport { STORAGE_MONITOR } from '../monitor';\n\n/**\n * Web file systems.\n */\nexport class WebFS implements Storage {\n readonly type = StorageType.WEBFS;\n\n protected readonly _files = new Map<string, File>();\n protected _root?: FileSystemDirectoryHandle;\n\n constructor(public readonly path: string) {}\n\n public get size() {\n return this._files.size;\n }\n\n private _getFiles(path: string): Map<string, File> {\n const fullName = this._getFullFilename(this.path, path);\n return new Map(\n [...this._files.entries()].filter(([path, file]) => path.includes(fullName) && file.destroyed !== true),\n );\n }\n\n private async _list(path: string): Promise<string[]> {\n const fullName = this._getFullFilename(path);\n\n const root = await this._initialize();\n\n // TODO(dmaretskyi): While we're storing all files in flat namespace we just iterate the root.\n // console.log({ path, fullName })\n // let dir: FileSystemDirectoryHandle;\n // if (path === '') {\n // dir = root;\n // } else {\n // dir = await root.getDirectoryHandle(fullName, { create: true });\n // }\n const entries: string[] = [];\n\n for await (const entry of (root as any).keys()) {\n if (entry.startsWith(fullName + '_')) {\n entries.push(entry.slice(fullName.length + 1));\n }\n }\n return entries;\n }\n\n @synchronized\n private async _initialize() {\n if (this._root) {\n return this._root;\n }\n this._root = await navigator.storage.getDirectory();\n invariant(this._root, 'Root is undefined');\n return this._root;\n }\n\n createDirectory(sub = '') {\n return new Directory(\n this.type,\n getFullPath(this.path, sub),\n (path) => this._list(path),\n (...args) => this.getOrCreateFile(...args),\n () => this._delete(sub),\n );\n }\n\n getOrCreateFile(path: string, filename: string, opts?: any): File {\n const fullName = this._getFullFilename(path, filename);\n const existingFile = this._files.get(fullName);\n if (existingFile) {\n return existingFile;\n }\n const file = this._createFile(fullName);\n this._files.set(fullName, file);\n return file;\n }\n\n private _createFile(fullName: string) {\n return new WebFile({\n fileName: fullName,\n file: this._initialize().then((root) => root.getFileHandle(fullName, { create: true })),\n destroy: async () => {\n this._files.delete(fullName);\n const root = await this._initialize();\n return root.removeEntry(fullName);\n },\n });\n }\n\n private async _delete(path: string): Promise<void> {\n await Promise.all(\n Array.from(this._getFiles(path)).map(async ([path, file]) => {\n await file.destroy().catch((err: any) => log.warn(err));\n this._files.delete(path);\n }),\n );\n }\n\n async reset() {\n await this._initialize();\n for await (const filename of await (this._root as any).keys()) {\n this._files.delete(filename);\n await this._root!.removeEntry(filename, { recursive: true }).catch((err: any) => log.warn(err));\n }\n this._root = undefined;\n }\n\n private _getFullFilename(path: string, filename?: string) {\n // Replace slashes with underscores. Because we can't have slashes in filenames in Browser File Handle API.\n if (filename) {\n return getFullPath(path, filename).split('/').join('_');\n } else {\n return path.split('/').join('_');\n }\n }\n\n async getDiskInfo(): Promise<DiskInfo> {\n let used = 0;\n\n const recurse = async (handle: FileSystemDirectoryHandle) => {\n const promises = [];\n\n for await (const entry of (handle as any).values()) {\n promises.push(\n (async () => {\n switch (entry.kind) {\n case 'file':\n used += await (entry as FileSystemFileHandle).getFile().then((f) => (used += f.size));\n break;\n case 'directory':\n await recurse(entry as FileSystemDirectoryHandle);\n break;\n }\n })(),\n );\n }\n await Promise.all(promises);\n };\n\n await recurse(this._root!);\n\n return {\n used,\n };\n }\n}\n\n// TODO(mykola): Remove EventEmitter.\nexport class WebFile extends EventEmitter implements File {\n readonly opened: boolean = true;\n readonly suspended: boolean = false;\n readonly closed: boolean = false;\n readonly unlinked: boolean = false;\n readonly writing: boolean = false;\n readonly readable: boolean = true;\n readonly writable: boolean = true;\n readonly deletable: boolean = true;\n readonly truncatable: boolean = true;\n readonly statable: boolean = true;\n private readonly _fileName: string;\n\n private readonly _fileHandle: Promise<FileSystemFileHandle>;\n private readonly _destroy: () => Promise<void>;\n\n constructor({\n fileName,\n file,\n destroy,\n }: {\n file: Promise<FileSystemFileHandle>;\n fileName: string;\n destroy: () => Promise<void>;\n }) {\n super();\n this._fileName = fileName;\n this._fileHandle = file;\n this._destroy = destroy;\n }\n\n destroyed = false;\n directory = '';\n // TODO(dmaretskyi): is this used?\n filename = '';\n type: StorageType = StorageType.WEBFS;\n native: RandomAccessStorage = {\n write: callbackify(this.write.bind(this)),\n read: callbackify(this.read.bind(this)),\n del: callbackify(this.del.bind(this)),\n stat: callbackify(this.stat.bind(this)),\n destroy: callbackify(this.destroy.bind(this)),\n truncate: callbackify(this.truncate?.bind(this)),\n } as RandomAccessStorage;\n\n @synchronized\n async write(offset: number, data: Buffer) {\n const metric = STORAGE_MONITOR.beginOp({ resource: this._fileName, type: 'write', size: data.length });\n try {\n // TODO(mykola): Fix types.\n const fileHandle: any = await this._fileHandle;\n const writable = await fileHandle.createWritable({ keepExistingData: true });\n await writable.write({ type: 'write', data, position: offset });\n await writable.close();\n } finally {\n metric.end();\n }\n }\n\n @synchronized\n async read(offset: number, size: number) {\n const metric = STORAGE_MONITOR.beginOp({ resource: this._fileName, type: 'read', size });\n try {\n const fileHandle: any = await this._fileHandle;\n const file = await fileHandle.getFile();\n if (offset + size > file.size) {\n throw new Error('Read out of bounds');\n }\n // does not copy the buffer\n return Buffer.from(await file.slice(offset, offset + size).arrayBuffer());\n } finally {\n metric.end();\n }\n }\n\n @synchronized\n async del(offset: number, size: number) {\n const metric = STORAGE_MONITOR.beginOp({ resource: this._fileName, type: 'delete', size });\n try {\n if (offset < 0 || size < 0) {\n return;\n }\n const fileHandle: any = await this._fileHandle;\n const writable = await fileHandle.createWritable({ keepExistingData: true });\n const file = await fileHandle.getFile();\n let leftoverSize = 0;\n if (offset + size < file.size) {\n // does not copy the buffer\n const leftover = Buffer.from(await file.slice(offset + size, file.size).arrayBuffer());\n leftoverSize = leftover.length;\n await writable.write({ type: 'write', data: leftover, position: offset });\n }\n\n await writable.write({ type: 'truncate', size: offset + leftoverSize });\n await writable.close();\n } finally {\n metric.end();\n }\n }\n\n @synchronized\n async stat() {\n const metric = STORAGE_MONITOR.beginOp({ resource: this._fileName, type: 'stat' });\n try {\n const fileHandle: any = await this._fileHandle;\n const file = await fileHandle.getFile();\n return {\n size: file.size,\n };\n } finally {\n metric.end();\n }\n }\n\n @synchronized\n async truncate(offset: number) {\n const metric = STORAGE_MONITOR.beginOp({ resource: this._fileName, type: 'truncate' });\n try {\n const fileHandle: any = await this._fileHandle;\n const writable = await fileHandle.createWritable({ keepExistingData: true });\n await writable.write({ type: 'truncate', size: offset });\n await writable.close();\n } finally {\n metric.end();\n }\n }\n\n async close(): Promise<void> {}\n\n @synchronized\n async destroy() {\n this.destroyed = true;\n return await this._destroy();\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { unrefTimeout } from '@dxos/async';\n\nexport type StorageOperation = {\n resource: string;\n type: 'read' | 'write' | 'stat' | 'delete' | 'truncate';\n size?: number;\n};\n\nexport type OpHandle = {\n end: () => void;\n};\n\nexport type StatsBucket = {\n resource: string;\n beginTime: number;\n endTime: number;\n\n /**\n * Fraction of time spent in storage operations.\n */\n usage: number;\n\n readOps: number;\n readBytes: number;\n readTime: number;\n\n writeOps: number;\n writeBytes: number;\n writeTime: number;\n\n otherOps: number;\n otherTime: number;\n};\n\nconst BUCKET_COLLECTION_INTERVAL = 1_000;\n\n/**\n * Storage performance metrics.\n */\nexport class StorageMonitor {\n private _enabled = false;\n\n /**\n * By resource.\n */\n private readonly _buckets = new Map<string, StatsBucket>();\n\n enable() {\n this._enabled = true;\n\n const timer = setInterval(() => {\n this._finalizeBuckets();\n }, BUCKET_COLLECTION_INTERVAL);\n unrefTimeout(timer);\n }\n\n beginOp(op: StorageOperation): OpHandle {\n if (!this._enabled) {\n return {\n end: () => {},\n };\n }\n\n const beginTime = performance.now();\n return {\n end: () => {\n const endTime = performance.now();\n const duration = endTime - beginTime;\n\n const bucket = this._getOrInitBucket(op.resource);\n switch (op.type) {\n case 'read':\n bucket.readOps++;\n bucket.readBytes += op.size ?? 0;\n bucket.readTime += duration;\n break;\n case 'write':\n bucket.writeOps++;\n bucket.writeBytes += op.size ?? 0;\n bucket.writeTime += duration;\n break;\n default:\n bucket.otherOps++;\n bucket.otherTime += duration;\n }\n },\n };\n }\n\n private _getOrInitBucket(resource: string): StatsBucket {\n const bucket = this._buckets.get(resource);\n if (bucket) {\n return bucket;\n }\n\n const newBucket = {\n resource,\n beginTime: performance.now(),\n endTime: 0,\n usage: 0,\n readOps: 0,\n readBytes: 0,\n readTime: 0,\n writeOps: 0,\n writeBytes: 0,\n writeTime: 0,\n otherOps: 0,\n otherTime: 0,\n };\n this._buckets.set(resource, newBucket);\n return newBucket;\n }\n\n private _finalizeBuckets() {\n const now = performance.now();\n const toEmit = [];\n for (const bucket of this._buckets.values()) {\n bucket.endTime = now;\n bucket.usage = (bucket.readTime + bucket.writeTime + bucket.otherTime) / (bucket.endTime - bucket.beginTime);\n toEmit.push(bucket);\n }\n\n // Clear the buckets.\n this._buckets.clear();\n for (const bucket of toEmit) {\n this._getOrInitBucket(bucket.resource);\n }\n\n ((globalThis as any).__STORAGE_METRICS ??= []).push(...toEmit);\n }\n}\n\nexport const STORAGE_MONITOR = new StorageMonitor();\n\n// TODO(dmaretskyi): Disabled due to performance concerns.\n// STORAGE_MONITOR.enable();\n", "//\n// Copyright 2021 DXOS.org\n//\n\nimport { MemoryStorage, Storage, StorageConstructor, StorageType } from '../common';\nimport { FirefoxStorage } from './firefox-storage';\nimport { IDbStorage } from './idb-storage';\nimport { WebFS } from './web-fs';\n\nexport const createStorage: StorageConstructor = ({ type, root = '' } = {}): Storage => {\n if (type === undefined) {\n if (\n navigator &&\n navigator.storage &&\n typeof navigator.storage.getDirectory === 'function' &&\n FileSystemFileHandle &&\n typeof (FileSystemFileHandle.prototype as any).createWritable === 'function'\n ) {\n return new WebFS(root);\n } else {\n return new IDbStorage(root);\n }\n }\n\n switch (type) {\n case StorageType.RAM: {\n return new MemoryStorage(root);\n }\n\n case StorageType.IDB:\n case StorageType.CHROME: {\n return new IDbStorage(root);\n }\n\n case StorageType.FIREFOX: {\n return new FirefoxStorage(root);\n }\n\n case StorageType.WEBFS: {\n return new WebFS(root);\n }\n\n default: {\n throw new Error(`Invalid type: ${type}`);\n }\n }\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["join", "inspect", "inspectObject", "log", "join", "stringDiff", "first", "second", "split", "join", "getFullPath", "root", "path", "Directory", "constructor", "type", "path", "_list", "_getOrCreateFile", "_delete", "toString", "JSON", "stringify", "createDirectory", "getFullPath", "list", "getOrCreateFile", "filename", "opts", "delete", "pify", "log", "pifyFields", "object", "type", "fields", "field", "fn", "bind", "args", "before", "performance", "now", "res", "elapsed", "warn", "operation", "wrapFile", "native", "file", "Object", "assign", "AbstractStorage", "constructor", "path", "_files", "Map", "inspect", "custom", "inspectObject", "toJSON", "type", "size", "createDirectory", "sub", "Directory", "getFullPath", "_list", "bind", "args", "getOrCreateFile", "_delete", "reset", "log", "info", "_closeFilesInPath", "_destroy", "err", "catch", "Array", "from", "_getFiles", "keys", "map", "filename", "name", "replace", "startsWith", "substring", "opts", "fullPath", "join", "native", "file", "_getFileIfExists", "closed", "_openFile", "_createFile", "wrapFile", "set", "undefined", "has", "get", "destroyed", "entries", "filter", "includes", "Promise", "all", "values", "close", "destroy", "then", "delete", "error", "message", "ram", "arrayToBuffer", "StorageType", "RAM", "IDB", "CHROME", "FIREFOX", "NODE", "WEBFS", "MemoryStorage", "AbstractStorage", "type", "StorageType", "RAM", "_createFile", "path", "filename", "_patchFile", "ram", "_openFile", "file", "newFile", "clone", "closed", "trueRead", "read", "bind", "offset", "size", "cb", "err", "data", "arrayToBuffer", "raw", "join", "BrowserStorage", "AbstractStorage", "constructor", "path", "_fileStorage", "_createFileStorage", "_createFile", "filename", "fullPath", "join", "_destroy", "Promise", "resolve", "reject", "request", "indexedDB", "deleteDatabase", "onsuccess", "onupgradeneeded", "Error", "onblocked", "onerror", "err", "FirefoxStorage", "BrowserStorage", "type", "StorageType", "FIREFOX", "_createFileStorage", "path", "raw", "name", "idb", "IDbStorage", "BrowserStorage", "type", "StorageType", "IDB", "_createFileStorage", "path", "idb", "EventEmitter", "callbackify", "invariant", "synchronized", "log", "unrefTimeout", "BUCKET_COLLECTION_INTERVAL", "StorageMonitor", "_enabled", "_buckets", "Map", "enable", "timer", "setInterval", "_finalizeBuckets", "unrefTimeout", "beginOp", "op", "end", "beginTime", "performance", "now", "_a", "endTime", "duration", "bucket", "_getOrInitBucket", "resource", "type", "readOps", "readBytes", "size", "readTime", "writeOps", "writeBytes", "writeTime", "otherOps", "otherTime", "get", "newBucket", "usage", "set", "toEmit", "values", "push", "clear", "globalThis", "__STORAGE_METRICS", "STORAGE_MONITOR", "WebFS", "constructor", "path", "type", "StorageType", "WEBFS", "_files", "Map", "size", "_getFiles", "fullName", "_getFullFilename", "entries", "filter", "file", "includes", "destroyed", "_list", "root", "_initialize", "entry", "keys", "startsWith", "push", "slice", "length", "_root", "navigator", "storage", "getDirectory", "invariant", "createDirectory", "sub", "Directory", "getFullPath", "args", "getOrCreateFile", "_delete", "filename", "opts", "existingFile", "get", "_createFile", "set", "WebFile", "fileName", "then", "getFileHandle", "create", "destroy", "delete", "removeEntry", "Promise", "all", "Array", "from", "map", "catch", "err", "log", "warn", "reset", "recursive", "undefined", "split", "join", "getDiskInfo", "used", "recurse", "handle", "promises", "values", "kind", "getFile", "f", "synchronized", "EventEmitter", "opened", "suspended", "closed", "unlinked", "writing", "readable", "writable", "deletable", "truncatable", "statable", "directory", "native", "write", "callbackify", "bind", "read", "del", "stat", "truncate", "_fileName", "_fileHandle", "_destroy", "offset", "data", "metric", "STORAGE_MONITOR", "beginOp", "resource", "fileHandle", "createWritable", "keepExistingData", "position", "close", "end", "Error", "Buffer", "arrayBuffer", "leftoverSize", "leftover", "createStorage", "type", "root", "undefined", "navigator", "storage", "getDirectory", "FileSystemFileHandle", "prototype", "createWritable", "WebFS", "IDbStorage", "StorageType", "RAM", "MemoryStorage", "IDB", "CHROME", "FIREFOX", "FirefoxStorage", "WEBFS", "Error"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"packages/common/random-access-storage/src/common/utils.ts":{"bytes":1295,"imports":[{"path":"@dxos/node-std/path","kind":"import-statement","external":true}]},"packages/common/random-access-storage/src/common/directory.ts":{"bytes":4648,"imports":[{"path":"packages/common/random-access-storage/src/common/utils.ts","kind":"import-statement","original":"./utils"}]},"packages/common/random-access-storage/src/common/file.ts":{"bytes":6051,"imports":[{"path":"pify","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true}]},"packages/common/random-access-storage/src/common/abstract-storage.ts":{"bytes":14201,"imports":[{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"@dxos/node-std/util","kind":"import-statement","external":true},{"path":"@dxos/debug","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"packages/common/random-access-storage/src/common/directory.ts","kind":"import-statement","original":"./directory"},{"path":"packages/common/random-access-storage/src/common/file.ts","kind":"import-statement","original":"./file"},{"path":"packages/common/random-access-storage/src/common/utils.ts","kind":"import-statement","original":"./utils"}]},"packages/common/random-access-storage/src/common/storage.ts":{"bytes":1866,"imports":[]},"packages/common/random-access-storage/src/common/memory-storage.ts":{"bytes":4348,"imports":[{"path":"random-access-memory","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"packages/common/random-access-storage/src/common/abstract-storage.ts","kind":"import-statement","original":"./abstract-storage"},{"path":"packages/common/random-access-storage/src/common/storage.ts","kind":"import-statement","original":"./storage"}]},"packages/common/random-access-storage/src/common/index.ts":{"bytes":947,"imports":[{"path":"packages/common/random-access-storage/src/common/abstract-storage.ts","kind":"import-statement","original":"./abstract-storage"},{"path":"packages/common/random-access-storage/src/common/directory.ts","kind":"import-statement","original":"./directory"},{"path":"packages/common/random-access-storage/src/common/file.ts","kind":"import-statement","original":"./file"},{"path":"packages/common/random-access-storage/src/common/memory-storage.ts","kind":"import-statement","original":"./memory-storage"},{"path":"packages/common/random-access-storage/src/common/storage.ts","kind":"import-statement","original":"./storage"},{"path":"packages/common/random-access-storage/src/common/utils.ts","kind":"import-statement","original":"./utils"}]},"packages/common/random-access-storage/src/browser/browser-storage.ts":{"bytes":4379,"imports":[{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"packages/common/random-access-storage/src/common/index.ts","kind":"import-statement","original":"../common"}]},"packages/common/random-access-storage/src/browser/firefox-storage.ts":{"bytes":2391,"imports":[{"path":"random-access-web/mutable-file-wrapper.js","kind":"import-statement","external":true},{"path":"packages/common/random-access-storage/src/common/index.ts","kind":"import-statement","original":"../common"},{"path":"packages/common/random-access-storage/src/browser/browser-storage.ts","kind":"import-statement","original":"./browser-storage"}]},"packages/common/random-access-storage/src/browser/idb-storage.ts":{"bytes":1799,"imports":[{"path":"random-access-idb","kind":"import-statement","external":true},{"path":"packages/common/random-access-storage/src/common/index.ts","kind":"import-statement","original":"../common"},{"path":"packages/common/random-access-storage/src/browser/browser-storage.ts","kind":"import-statement","original":"./browser-storage"}]},"packages/common/random-access-storage/src/browser/web-fs.ts":{"bytes":28918,"imports":[{"path":"@dxos/node-std/events","kind":"import-statement","external":true},{"path":"@dxos/node-std/util","kind":"import-statement","external":true},{"path":"tiny-invariant","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"packages/common/random-access-storage/src/common/index.ts","kind":"import-statement","original":"../common"}]},"packages/common/random-access-storage/src/browser/storage.ts":{"bytes":4396,"imports":[{"path":"packages/common/random-access-storage/src/common/index.ts","kind":"import-statement","original":"../common"},{"path":"packages/common/random-access-storage/src/browser/firefox-storage.ts","kind":"import-statement","original":"./firefox-storage"},{"path":"packages/common/random-access-storage/src/browser/idb-storage.ts","kind":"import-statement","original":"./idb-storage"},{"path":"packages/common/random-access-storage/src/browser/web-fs.ts","kind":"import-statement","original":"./web-fs"}]},"packages/common/random-access-storage/src/browser/index.ts":{"bytes":571,"imports":[{"path":"packages/common/random-access-storage/src/common/index.ts","kind":"import-statement","original":"../common"},{"path":"packages/common/random-access-storage/src/browser/storage.ts","kind":"import-statement","original":"./storage"}]}},"outputs":{"packages/common/random-access-storage/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":36715},"packages/common/random-access-storage/dist/lib/browser/index.mjs":{"imports":[{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"@dxos/node-std/util","kind":"import-statement","external":true},{"path":"@dxos/debug","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"pify","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"random-access-memory","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"random-access-web/mutable-file-wrapper.js","kind":"import-statement","external":true},{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"random-access-idb","kind":"import-statement","external":true},{"path":"@dxos/node-std/events","kind":"import-statement","external":true},{"path":"@dxos/node-std/util","kind":"import-statement","external":true},{"path":"tiny-invariant","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true}],"exports":["AbstractStorage","Directory","MemoryStorage","StorageType","createStorage","getFullPath","stringDiff","wrapFile"],"entryPoint":"packages/common/random-access-storage/src/browser/index.ts","inputs":{"packages/common/random-access-storage/src/common/abstract-storage.ts":{"bytesInOutput":3348},"packages/common/random-access-storage/src/common/utils.ts":{"bytesInOutput":180},"packages/common/random-access-storage/src/common/directory.ts":{"bytesInOutput":923},"packages/common/random-access-storage/src/common/file.ts":{"bytesInOutput":1088},"packages/common/random-access-storage/src/common/index.ts":{"bytesInOutput":0},"packages/common/random-access-storage/src/common/memory-storage.ts":{"bytesInOutput":693},"packages/common/random-access-storage/src/common/storage.ts":{"bytesInOutput":288},"packages/common/random-access-storage/src/browser/index.ts":{"bytesInOutput":0},"packages/common/random-access-storage/src/browser/firefox-storage.ts":{"bytesInOutput":275},"packages/common/random-access-storage/src/browser/browser-storage.ts":{"bytesInOutput":769},"packages/common/random-access-storage/src/browser/idb-storage.ts":{"bytesInOutput":223},"packages/common/random-access-storage/src/browser/web-fs.ts":{"bytesInOutput":7374},"packages/common/random-access-storage/src/browser/storage.ts":{"bytesInOutput":765}},"bytes":17085}}}
1
+ {"inputs":{"packages/common/random-access-storage/src/common/utils.ts":{"bytes":1285,"imports":[{"path":"@dxos/node-std/path","kind":"import-statement","external":true}]},"packages/common/random-access-storage/src/common/directory.ts":{"bytes":4638,"imports":[{"path":"packages/common/random-access-storage/src/common/utils.ts","kind":"import-statement","original":"./utils"}]},"packages/common/random-access-storage/src/common/file.ts":{"bytes":6041,"imports":[{"path":"pify","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true}]},"packages/common/random-access-storage/src/common/abstract-storage.ts":{"bytes":14191,"imports":[{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"@dxos/node-std/util","kind":"import-statement","external":true},{"path":"@dxos/debug","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"packages/common/random-access-storage/src/common/directory.ts","kind":"import-statement","original":"./directory"},{"path":"packages/common/random-access-storage/src/common/file.ts","kind":"import-statement","original":"./file"},{"path":"packages/common/random-access-storage/src/common/utils.ts","kind":"import-statement","original":"./utils"}]},"packages/common/random-access-storage/src/common/storage.ts":{"bytes":1856,"imports":[]},"packages/common/random-access-storage/src/common/memory-storage.ts":{"bytes":4338,"imports":[{"path":"random-access-memory","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"packages/common/random-access-storage/src/common/abstract-storage.ts","kind":"import-statement","original":"./abstract-storage"},{"path":"packages/common/random-access-storage/src/common/storage.ts","kind":"import-statement","original":"./storage"}]},"packages/common/random-access-storage/src/common/index.ts":{"bytes":937,"imports":[{"path":"packages/common/random-access-storage/src/common/abstract-storage.ts","kind":"import-statement","original":"./abstract-storage"},{"path":"packages/common/random-access-storage/src/common/directory.ts","kind":"import-statement","original":"./directory"},{"path":"packages/common/random-access-storage/src/common/file.ts","kind":"import-statement","original":"./file"},{"path":"packages/common/random-access-storage/src/common/memory-storage.ts","kind":"import-statement","original":"./memory-storage"},{"path":"packages/common/random-access-storage/src/common/storage.ts","kind":"import-statement","original":"./storage"},{"path":"packages/common/random-access-storage/src/common/utils.ts","kind":"import-statement","original":"./utils"}]},"packages/common/random-access-storage/src/browser/browser-storage.ts":{"bytes":4369,"imports":[{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"packages/common/random-access-storage/src/common/index.ts","kind":"import-statement","original":"../common"}]},"packages/common/random-access-storage/src/browser/firefox-storage.ts":{"bytes":2381,"imports":[{"path":"random-access-web/mutable-file-wrapper.js","kind":"import-statement","external":true},{"path":"packages/common/random-access-storage/src/common/index.ts","kind":"import-statement","original":"../common"},{"path":"packages/common/random-access-storage/src/browser/browser-storage.ts","kind":"import-statement","original":"./browser-storage"}]},"packages/common/random-access-storage/src/browser/idb-storage.ts":{"bytes":1789,"imports":[{"path":"random-access-idb","kind":"import-statement","external":true},{"path":"packages/common/random-access-storage/src/common/index.ts","kind":"import-statement","original":"../common"},{"path":"packages/common/random-access-storage/src/browser/browser-storage.ts","kind":"import-statement","original":"./browser-storage"}]},"packages/common/random-access-storage/src/monitor.ts":{"bytes":10173,"imports":[{"path":"@dxos/async","kind":"import-statement","external":true}]},"packages/common/random-access-storage/src/browser/web-fs.ts":{"bytes":32944,"imports":[{"path":"@dxos/node-std/events","kind":"import-statement","external":true},{"path":"@dxos/node-std/util","kind":"import-statement","external":true},{"path":"tiny-invariant","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"packages/common/random-access-storage/src/common/index.ts","kind":"import-statement","original":"../common"},{"path":"packages/common/random-access-storage/src/monitor.ts","kind":"import-statement","original":"../monitor"}]},"packages/common/random-access-storage/src/browser/storage.ts":{"bytes":4386,"imports":[{"path":"packages/common/random-access-storage/src/common/index.ts","kind":"import-statement","original":"../common"},{"path":"packages/common/random-access-storage/src/browser/firefox-storage.ts","kind":"import-statement","original":"./firefox-storage"},{"path":"packages/common/random-access-storage/src/browser/idb-storage.ts","kind":"import-statement","original":"./idb-storage"},{"path":"packages/common/random-access-storage/src/browser/web-fs.ts","kind":"import-statement","original":"./web-fs"}]},"packages/common/random-access-storage/src/browser/index.ts":{"bytes":561,"imports":[{"path":"packages/common/random-access-storage/src/common/index.ts","kind":"import-statement","original":"../common"},{"path":"packages/common/random-access-storage/src/browser/storage.ts","kind":"import-statement","original":"./storage"}]}},"outputs":{"packages/common/random-access-storage/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":43766},"packages/common/random-access-storage/dist/lib/browser/index.mjs":{"imports":[{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"@dxos/node-std/util","kind":"import-statement","external":true},{"path":"@dxos/debug","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"pify","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"random-access-memory","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"random-access-web/mutable-file-wrapper.js","kind":"import-statement","external":true},{"path":"@dxos/node-std/path","kind":"import-statement","external":true},{"path":"random-access-idb","kind":"import-statement","external":true},{"path":"@dxos/node-std/events","kind":"import-statement","external":true},{"path":"@dxos/node-std/util","kind":"import-statement","external":true},{"path":"tiny-invariant","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true}],"exports":["AbstractStorage","Directory","MemoryStorage","StorageType","createStorage","getFullPath","stringDiff","wrapFile"],"entryPoint":"packages/common/random-access-storage/src/browser/index.ts","inputs":{"packages/common/random-access-storage/src/common/abstract-storage.ts":{"bytesInOutput":3338},"packages/common/random-access-storage/src/common/utils.ts":{"bytesInOutput":180},"packages/common/random-access-storage/src/common/directory.ts":{"bytesInOutput":923},"packages/common/random-access-storage/src/common/file.ts":{"bytesInOutput":1078},"packages/common/random-access-storage/src/common/index.ts":{"bytesInOutput":0},"packages/common/random-access-storage/src/common/memory-storage.ts":{"bytesInOutput":693},"packages/common/random-access-storage/src/common/storage.ts":{"bytesInOutput":288},"packages/common/random-access-storage/src/browser/index.ts":{"bytesInOutput":0},"packages/common/random-access-storage/src/browser/firefox-storage.ts":{"bytesInOutput":275},"packages/common/random-access-storage/src/browser/browser-storage.ts":{"bytesInOutput":769},"packages/common/random-access-storage/src/browser/idb-storage.ts":{"bytesInOutput":223},"packages/common/random-access-storage/src/browser/web-fs.ts":{"bytesInOutput":8412},"packages/common/random-access-storage/src/monitor.ts":{"bytesInOutput":2332},"packages/common/random-access-storage/src/browser/storage.ts":{"bytesInOutput":765}},"bytes":20556}}}
@@ -96,7 +96,7 @@ var Directory = class {
96
96
  // packages/common/random-access-storage/src/common/file.ts
97
97
  var import_pify = __toESM(require("pify"));
98
98
  var import_log = require("@dxos/log");
99
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/common/random-access-storage/src/common/file.ts";
99
+ var __dxlog_file = "/mnt/ramdisk/work/packages/common/random-access-storage/src/common/file.ts";
100
100
  var pifyFields = (object, type, fields) => {
101
101
  for (const field of fields) {
102
102
  if (!object[field]) {
@@ -141,7 +141,7 @@ var wrapFile = (native, type) => {
141
141
  };
142
142
 
143
143
  // packages/common/random-access-storage/src/common/abstract-storage.ts
144
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/common/random-access-storage/src/common/abstract-storage.ts";
144
+ var __dxlog_file2 = "/mnt/ramdisk/work/packages/common/random-access-storage/src/common/abstract-storage.ts";
145
145
  var AbstractStorage = class {
146
146
  // TODO(burdon): Make required.
147
147
  constructor(path) {
@@ -1 +1 @@
1
- {"inputs":{"packages/common/random-access-storage/src/common/utils.ts":{"bytes":1295,"imports":[{"path":"node:path","kind":"import-statement","external":true}]},"packages/common/random-access-storage/src/common/directory.ts":{"bytes":4648,"imports":[{"path":"packages/common/random-access-storage/src/common/utils.ts","kind":"import-statement","original":"./utils"}]},"packages/common/random-access-storage/src/common/file.ts":{"bytes":6051,"imports":[{"path":"pify","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true}]},"packages/common/random-access-storage/src/common/abstract-storage.ts":{"bytes":14201,"imports":[{"path":"node:path","kind":"import-statement","external":true},{"path":"node:util","kind":"import-statement","external":true},{"path":"@dxos/debug","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"packages/common/random-access-storage/src/common/directory.ts","kind":"import-statement","original":"./directory"},{"path":"packages/common/random-access-storage/src/common/file.ts","kind":"import-statement","original":"./file"},{"path":"packages/common/random-access-storage/src/common/utils.ts","kind":"import-statement","original":"./utils"}]},"packages/common/random-access-storage/src/common/storage.ts":{"bytes":1866,"imports":[]},"packages/common/random-access-storage/src/common/memory-storage.ts":{"bytes":4348,"imports":[{"path":"random-access-memory","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"packages/common/random-access-storage/src/common/abstract-storage.ts","kind":"import-statement","original":"./abstract-storage"},{"path":"packages/common/random-access-storage/src/common/storage.ts","kind":"import-statement","original":"./storage"}]},"packages/common/random-access-storage/src/common/index.ts":{"bytes":947,"imports":[{"path":"packages/common/random-access-storage/src/common/abstract-storage.ts","kind":"import-statement","original":"./abstract-storage"},{"path":"packages/common/random-access-storage/src/common/directory.ts","kind":"import-statement","original":"./directory"},{"path":"packages/common/random-access-storage/src/common/file.ts","kind":"import-statement","original":"./file"},{"path":"packages/common/random-access-storage/src/common/memory-storage.ts","kind":"import-statement","original":"./memory-storage"},{"path":"packages/common/random-access-storage/src/common/storage.ts","kind":"import-statement","original":"./storage"},{"path":"packages/common/random-access-storage/src/common/utils.ts","kind":"import-statement","original":"./utils"}]},"packages/common/random-access-storage/src/node/node-storage.ts":{"bytes":4787,"imports":[{"path":"del","kind":"import-statement","external":true},{"path":"node:fs/promises","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"random-access-file","kind":"import-statement","external":true},{"path":"packages/common/random-access-storage/src/common/index.ts","kind":"import-statement","original":"../common"}]},"packages/common/random-access-storage/src/node/storage.ts":{"bytes":2425,"imports":[{"path":"packages/common/random-access-storage/src/common/index.ts","kind":"import-statement","original":"../common"},{"path":"packages/common/random-access-storage/src/node/node-storage.ts","kind":"import-statement","original":"./node-storage"}]},"packages/common/random-access-storage/src/node/index.ts":{"bytes":568,"imports":[{"path":"packages/common/random-access-storage/src/common/index.ts","kind":"import-statement","original":"../common"},{"path":"packages/common/random-access-storage/src/node/storage.ts","kind":"import-statement","original":"./storage"}]},"packages/common/random-access-storage/src/index.ts":{"bytes":469,"imports":[{"path":"packages/common/random-access-storage/src/node/index.ts","kind":"import-statement","original":"./node"}]}},"outputs":{"packages/common/random-access-storage/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":19901},"packages/common/random-access-storage/dist/lib/node/index.cjs":{"imports":[{"path":"node:path","kind":"require-call","external":true},{"path":"node:util","kind":"require-call","external":true},{"path":"@dxos/debug","kind":"require-call","external":true},{"path":"@dxos/log","kind":"require-call","external":true},{"path":"node:path","kind":"require-call","external":true},{"path":"pify","kind":"require-call","external":true},{"path":"@dxos/log","kind":"require-call","external":true},{"path":"random-access-memory","kind":"require-call","external":true},{"path":"@dxos/util","kind":"require-call","external":true},{"path":"del","kind":"require-call","external":true},{"path":"node:fs/promises","kind":"require-call","external":true},{"path":"node:path","kind":"require-call","external":true},{"path":"random-access-file","kind":"require-call","external":true}],"exports":[],"entryPoint":"packages/common/random-access-storage/src/index.ts","inputs":{"packages/common/random-access-storage/src/index.ts":{"bytesInOutput":369},"packages/common/random-access-storage/src/common/abstract-storage.ts":{"bytesInOutput":3453},"packages/common/random-access-storage/src/common/utils.ts":{"bytesInOutput":203},"packages/common/random-access-storage/src/common/directory.ts":{"bytesInOutput":923},"packages/common/random-access-storage/src/common/file.ts":{"bytesInOutput":1144},"packages/common/random-access-storage/src/common/index.ts":{"bytesInOutput":0},"packages/common/random-access-storage/src/common/memory-storage.ts":{"bytesInOutput":780},"packages/common/random-access-storage/src/common/storage.ts":{"bytesInOutput":288},"packages/common/random-access-storage/src/node/index.ts":{"bytesInOutput":0},"packages/common/random-access-storage/src/node/node-storage.ts":{"bytesInOutput":1114},"packages/common/random-access-storage/src/node/storage.ts":{"bytesInOutput":369}},"bytes":11011}}}
1
+ {"inputs":{"packages/common/random-access-storage/src/common/utils.ts":{"bytes":1285,"imports":[{"path":"node:path","kind":"import-statement","external":true}]},"packages/common/random-access-storage/src/common/directory.ts":{"bytes":4638,"imports":[{"path":"packages/common/random-access-storage/src/common/utils.ts","kind":"import-statement","original":"./utils"}]},"packages/common/random-access-storage/src/common/file.ts":{"bytes":6041,"imports":[{"path":"pify","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true}]},"packages/common/random-access-storage/src/common/abstract-storage.ts":{"bytes":14191,"imports":[{"path":"node:path","kind":"import-statement","external":true},{"path":"node:util","kind":"import-statement","external":true},{"path":"@dxos/debug","kind":"import-statement","external":true},{"path":"@dxos/log","kind":"import-statement","external":true},{"path":"packages/common/random-access-storage/src/common/directory.ts","kind":"import-statement","original":"./directory"},{"path":"packages/common/random-access-storage/src/common/file.ts","kind":"import-statement","original":"./file"},{"path":"packages/common/random-access-storage/src/common/utils.ts","kind":"import-statement","original":"./utils"}]},"packages/common/random-access-storage/src/common/storage.ts":{"bytes":1856,"imports":[]},"packages/common/random-access-storage/src/common/memory-storage.ts":{"bytes":4338,"imports":[{"path":"random-access-memory","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"packages/common/random-access-storage/src/common/abstract-storage.ts","kind":"import-statement","original":"./abstract-storage"},{"path":"packages/common/random-access-storage/src/common/storage.ts","kind":"import-statement","original":"./storage"}]},"packages/common/random-access-storage/src/common/index.ts":{"bytes":937,"imports":[{"path":"packages/common/random-access-storage/src/common/abstract-storage.ts","kind":"import-statement","original":"./abstract-storage"},{"path":"packages/common/random-access-storage/src/common/directory.ts","kind":"import-statement","original":"./directory"},{"path":"packages/common/random-access-storage/src/common/file.ts","kind":"import-statement","original":"./file"},{"path":"packages/common/random-access-storage/src/common/memory-storage.ts","kind":"import-statement","original":"./memory-storage"},{"path":"packages/common/random-access-storage/src/common/storage.ts","kind":"import-statement","original":"./storage"},{"path":"packages/common/random-access-storage/src/common/utils.ts","kind":"import-statement","original":"./utils"}]},"packages/common/random-access-storage/src/node/node-storage.ts":{"bytes":4777,"imports":[{"path":"del","kind":"import-statement","external":true},{"path":"node:fs/promises","kind":"import-statement","external":true},{"path":"node:path","kind":"import-statement","external":true},{"path":"random-access-file","kind":"import-statement","external":true},{"path":"packages/common/random-access-storage/src/common/index.ts","kind":"import-statement","original":"../common"}]},"packages/common/random-access-storage/src/node/storage.ts":{"bytes":2415,"imports":[{"path":"packages/common/random-access-storage/src/common/index.ts","kind":"import-statement","original":"../common"},{"path":"packages/common/random-access-storage/src/node/node-storage.ts","kind":"import-statement","original":"./node-storage"}]},"packages/common/random-access-storage/src/node/index.ts":{"bytes":558,"imports":[{"path":"packages/common/random-access-storage/src/common/index.ts","kind":"import-statement","original":"../common"},{"path":"packages/common/random-access-storage/src/node/storage.ts","kind":"import-statement","original":"./storage"}]},"packages/common/random-access-storage/src/index.ts":{"bytes":459,"imports":[{"path":"packages/common/random-access-storage/src/node/index.ts","kind":"import-statement","original":"./node"}]}},"outputs":{"packages/common/random-access-storage/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":19901},"packages/common/random-access-storage/dist/lib/node/index.cjs":{"imports":[{"path":"node:path","kind":"require-call","external":true},{"path":"node:util","kind":"require-call","external":true},{"path":"@dxos/debug","kind":"require-call","external":true},{"path":"@dxos/log","kind":"require-call","external":true},{"path":"node:path","kind":"require-call","external":true},{"path":"pify","kind":"require-call","external":true},{"path":"@dxos/log","kind":"require-call","external":true},{"path":"random-access-memory","kind":"require-call","external":true},{"path":"@dxos/util","kind":"require-call","external":true},{"path":"del","kind":"require-call","external":true},{"path":"node:fs/promises","kind":"require-call","external":true},{"path":"node:path","kind":"require-call","external":true},{"path":"random-access-file","kind":"require-call","external":true}],"exports":[],"entryPoint":"packages/common/random-access-storage/src/index.ts","inputs":{"packages/common/random-access-storage/src/index.ts":{"bytesInOutput":369},"packages/common/random-access-storage/src/common/abstract-storage.ts":{"bytesInOutput":3443},"packages/common/random-access-storage/src/common/utils.ts":{"bytesInOutput":203},"packages/common/random-access-storage/src/common/directory.ts":{"bytesInOutput":923},"packages/common/random-access-storage/src/common/file.ts":{"bytesInOutput":1134},"packages/common/random-access-storage/src/common/index.ts":{"bytesInOutput":0},"packages/common/random-access-storage/src/common/memory-storage.ts":{"bytesInOutput":780},"packages/common/random-access-storage/src/common/storage.ts":{"bytesInOutput":288},"packages/common/random-access-storage/src/node/index.ts":{"bytesInOutput":0},"packages/common/random-access-storage/src/node/node-storage.ts":{"bytesInOutput":1114},"packages/common/random-access-storage/src/node/storage.ts":{"bytesInOutput":369}},"bytes":10991}}}
@@ -35,10 +35,12 @@ export declare class WebFile extends EventEmitter implements File {
35
35
  readonly deletable: boolean;
36
36
  readonly truncatable: boolean;
37
37
  readonly statable: boolean;
38
+ private readonly _fileName;
38
39
  private readonly _fileHandle;
39
40
  private readonly _destroy;
40
- constructor({ file, destroy }: {
41
+ constructor({ fileName, file, destroy, }: {
41
42
  file: Promise<FileSystemFileHandle>;
43
+ fileName: string;
42
44
  destroy: () => Promise<void>;
43
45
  });
44
46
  destroyed: boolean;
@@ -52,8 +54,8 @@ export declare class WebFile extends EventEmitter implements File {
52
54
  stat(): Promise<{
53
55
  size: any;
54
56
  }>;
57
+ truncate(offset: number): Promise<void>;
55
58
  close(): Promise<void>;
56
59
  destroy(): Promise<void>;
57
- truncate(offset: number): Promise<void>;
58
60
  }
59
61
  //# sourceMappingURL=web-fs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"web-fs.d.ts","sourceRoot":"","sources":["../../../../src/browser/web-fs.ts"],"names":[],"mappings":";;AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAM5D,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAe,QAAQ,EAAE,MAAM,WAAW,CAAC;AAEzF;;GAEG;AACH,qBAAa,KAAM,YAAW,OAAO;aAMP,IAAI,EAAE,MAAM;IALxC,QAAQ,CAAC,IAAI,qBAAqB;IAElC,SAAS,CAAC,QAAQ,CAAC,MAAM,oBAA2B;IACpD,SAAS,CAAC,KAAK,CAAC,EAAE,yBAAyB,CAAC;gBAEhB,IAAI,EAAE,MAAM;IAExC,IAAW,IAAI,WAEd;IAED,OAAO,CAAC,SAAS;YAOH,KAAK;YAwBL,WAAW;IASzB,eAAe,CAAC,GAAG,SAAK;IAUxB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAWjE,OAAO,CAAC,WAAW;YAWL,OAAO;IASf,KAAK;IASX,OAAO,CAAC,gBAAgB;IASlB,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC;CA6BvC;AAGD,qBAAa,OAAQ,SAAQ,YAAa,YAAW,IAAI;IACvD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAQ;IAChC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAS;IACpC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAS;IACjC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAS;IACnC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAS;IAClC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAQ;IAClC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAQ;IAClC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAQ;IACnC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAQ;IACrC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAQ;IAElC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAgC;IAC5D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsB;gBAEnC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE;IAMpG,SAAS,UAAS;IAClB,SAAS,SAAM;IACf,QAAQ,SAAM;IACd,IAAI,EAAE,WAAW,CAAqB;IACtC,MAAM,EAAE,mBAAmB,CAOF;IAGnB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IASlC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAWjC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAoBhC,IAAI;;;IAQJ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAGtB,OAAO;IAMP,QAAQ,CAAC,MAAM,EAAE,MAAM;CAM9B"}
1
+ {"version":3,"file":"web-fs.d.ts","sourceRoot":"","sources":["../../../../src/browser/web-fs.ts"],"names":[],"mappings":";;AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAM5D,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAe,QAAQ,EAAE,MAAM,WAAW,CAAC;AAGzF;;GAEG;AACH,qBAAa,KAAM,YAAW,OAAO;aAMP,IAAI,EAAE,MAAM;IALxC,QAAQ,CAAC,IAAI,qBAAqB;IAElC,SAAS,CAAC,QAAQ,CAAC,MAAM,oBAA2B;IACpD,SAAS,CAAC,KAAK,CAAC,EAAE,yBAAyB,CAAC;gBAEhB,IAAI,EAAE,MAAM;IAExC,IAAW,IAAI,WAEd;IAED,OAAO,CAAC,SAAS;YAOH,KAAK;YAwBL,WAAW;IASzB,eAAe,CAAC,GAAG,SAAK;IAUxB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAWjE,OAAO,CAAC,WAAW;YAYL,OAAO;IASf,KAAK;IASX,OAAO,CAAC,gBAAgB;IASlB,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC;CA6BvC;AAGD,qBAAa,OAAQ,SAAQ,YAAa,YAAW,IAAI;IACvD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAQ;IAChC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAS;IACpC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAS;IACjC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAS;IACnC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAS;IAClC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAQ;IAClC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAQ;IAClC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAQ;IACnC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAQ;IACrC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAgC;IAC5D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsB;gBAEnC,EACV,QAAQ,EACR,IAAI,EACJ,OAAO,GACR,EAAE;QACD,IAAI,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;QACpC,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;KAC9B;IAOD,SAAS,UAAS;IAClB,SAAS,SAAM;IAEf,QAAQ,SAAM;IACd,IAAI,EAAE,WAAW,CAAqB;IACtC,MAAM,EAAE,mBAAmB,CAOF;IAGnB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAclC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAgBjC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAyBhC,IAAI;;;IAcJ,QAAQ,CAAC,MAAM,EAAE,MAAM;IAYvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAGtB,OAAO;CAId"}
@@ -0,0 +1,41 @@
1
+ export type StorageOperation = {
2
+ resource: string;
3
+ type: 'read' | 'write' | 'stat' | 'delete' | 'truncate';
4
+ size?: number;
5
+ };
6
+ export type OpHandle = {
7
+ end: () => void;
8
+ };
9
+ export type StatsBucket = {
10
+ resource: string;
11
+ beginTime: number;
12
+ endTime: number;
13
+ /**
14
+ * Fraction of time spent in storage operations.
15
+ */
16
+ usage: number;
17
+ readOps: number;
18
+ readBytes: number;
19
+ readTime: number;
20
+ writeOps: number;
21
+ writeBytes: number;
22
+ writeTime: number;
23
+ otherOps: number;
24
+ otherTime: number;
25
+ };
26
+ /**
27
+ * Storage performance metrics.
28
+ */
29
+ export declare class StorageMonitor {
30
+ private _enabled;
31
+ /**
32
+ * By resource.
33
+ */
34
+ private readonly _buckets;
35
+ enable(): void;
36
+ beginOp(op: StorageOperation): OpHandle;
37
+ private _getOrInitBucket;
38
+ private _finalizeBuckets;
39
+ }
40
+ export declare const STORAGE_MONITOR: StorageMonitor;
41
+ //# sourceMappingURL=monitor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitor.d.ts","sourceRoot":"","sources":["../../../src/monitor.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;IACxD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,GAAG,EAAE,MAAM,IAAI,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IAEjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAElB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAIF;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAS;IAEzB;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;IAE3D,MAAM;IASN,OAAO,CAAC,EAAE,EAAE,gBAAgB,GAAG,QAAQ;IAiCvC,OAAO,CAAC,gBAAgB;IAwBxB,OAAO,CAAC,gBAAgB;CAiBzB;AAED,eAAO,MAAM,eAAe,gBAAuB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/random-access-storage",
3
- "version": "0.1.55-main.ff36828",
3
+ "version": "0.1.55",
4
4
  "description": "Multiple random storage types.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -25,11 +25,11 @@
25
25
  "random-access-storage": "^3.0.0",
26
26
  "random-access-web": "^2.0.3",
27
27
  "tiny-invariant": "^1.3.1",
28
- "@dxos/async": "0.1.55-main.ff36828",
29
- "@dxos/debug": "0.1.55-main.ff36828",
30
- "@dxos/log": "0.1.55-main.ff36828",
31
- "@dxos/node-std": "0.1.55-main.ff36828",
32
- "@dxos/util": "0.1.55-main.ff36828"
28
+ "@dxos/async": "0.1.55",
29
+ "@dxos/debug": "0.1.55",
30
+ "@dxos/log": "0.1.55",
31
+ "@dxos/node-std": "0.1.55",
32
+ "@dxos/util": "0.1.55"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@types/pify": "^3.0.2",
@@ -11,6 +11,7 @@ import { synchronized } from '@dxos/async';
11
11
  import { log } from '@dxos/log';
12
12
 
13
13
  import { Directory, File, Storage, StorageType, getFullPath, DiskInfo } from '../common';
14
+ import { STORAGE_MONITOR } from '../monitor';
14
15
 
15
16
  /**
16
17
  * Web file systems.
@@ -90,6 +91,7 @@ export class WebFS implements Storage {
90
91
 
91
92
  private _createFile(fullName: string) {
92
93
  return new WebFile({
94
+ fileName: fullName,
93
95
  file: this._initialize().then((root) => root.getFileHandle(fullName, { create: true })),
94
96
  destroy: async () => {
95
97
  this._files.delete(fullName);
@@ -169,18 +171,29 @@ export class WebFile extends EventEmitter implements File {
169
171
  readonly deletable: boolean = true;
170
172
  readonly truncatable: boolean = true;
171
173
  readonly statable: boolean = true;
174
+ private readonly _fileName: string;
172
175
 
173
176
  private readonly _fileHandle: Promise<FileSystemFileHandle>;
174
177
  private readonly _destroy: () => Promise<void>;
175
178
 
176
- constructor({ file, destroy }: { file: Promise<FileSystemFileHandle>; destroy: () => Promise<void> }) {
179
+ constructor({
180
+ fileName,
181
+ file,
182
+ destroy,
183
+ }: {
184
+ file: Promise<FileSystemFileHandle>;
185
+ fileName: string;
186
+ destroy: () => Promise<void>;
187
+ }) {
177
188
  super();
189
+ this._fileName = fileName;
178
190
  this._fileHandle = file;
179
191
  this._destroy = destroy;
180
192
  }
181
193
 
182
194
  destroyed = false;
183
195
  directory = '';
196
+ // TODO(dmaretskyi): is this used?
184
197
  filename = '';
185
198
  type: StorageType = StorageType.WEBFS;
186
199
  native: RandomAccessStorage = {
@@ -194,51 +207,84 @@ export class WebFile extends EventEmitter implements File {
194
207
 
195
208
  @synchronized
196
209
  async write(offset: number, data: Buffer) {
197
- // TODO(mykola): Fix types.
198
- const fileHandle: any = await this._fileHandle;
199
- const writable = await fileHandle.createWritable({ keepExistingData: true });
200
- await writable.write({ type: 'write', data, position: offset });
201
- await writable.close();
210
+ const metric = STORAGE_MONITOR.beginOp({ resource: this._fileName, type: 'write', size: data.length });
211
+ try {
212
+ // TODO(mykola): Fix types.
213
+ const fileHandle: any = await this._fileHandle;
214
+ const writable = await fileHandle.createWritable({ keepExistingData: true });
215
+ await writable.write({ type: 'write', data, position: offset });
216
+ await writable.close();
217
+ } finally {
218
+ metric.end();
219
+ }
202
220
  }
203
221
 
204
222
  @synchronized
205
223
  async read(offset: number, size: number) {
206
- const fileHandle: any = await this._fileHandle;
207
- const file = await fileHandle.getFile();
208
- if (offset + size > file.size) {
209
- throw new Error('Read out of bounds');
224
+ const metric = STORAGE_MONITOR.beginOp({ resource: this._fileName, type: 'read', size });
225
+ try {
226
+ const fileHandle: any = await this._fileHandle;
227
+ const file = await fileHandle.getFile();
228
+ if (offset + size > file.size) {
229
+ throw new Error('Read out of bounds');
230
+ }
231
+ // does not copy the buffer
232
+ return Buffer.from(await file.slice(offset, offset + size).arrayBuffer());
233
+ } finally {
234
+ metric.end();
210
235
  }
211
- // does not copy the buffer
212
- return Buffer.from(await file.slice(offset, offset + size).arrayBuffer());
213
236
  }
214
237
 
215
238
  @synchronized
216
239
  async del(offset: number, size: number) {
217
- if (offset < 0 || size < 0) {
218
- return;
219
- }
220
- const fileHandle: any = await this._fileHandle;
221
- const writable = await fileHandle.createWritable({ keepExistingData: true });
222
- const file = await fileHandle.getFile();
223
- let leftoverSize = 0;
224
- if (offset + size < file.size) {
225
- // does not copy the buffer
226
- const leftover = Buffer.from(await file.slice(offset + size, file.size).arrayBuffer());
227
- leftoverSize = leftover.length;
228
- await writable.write({ type: 'write', data: leftover, position: offset });
229
- }
240
+ const metric = STORAGE_MONITOR.beginOp({ resource: this._fileName, type: 'delete', size });
241
+ try {
242
+ if (offset < 0 || size < 0) {
243
+ return;
244
+ }
245
+ const fileHandle: any = await this._fileHandle;
246
+ const writable = await fileHandle.createWritable({ keepExistingData: true });
247
+ const file = await fileHandle.getFile();
248
+ let leftoverSize = 0;
249
+ if (offset + size < file.size) {
250
+ // does not copy the buffer
251
+ const leftover = Buffer.from(await file.slice(offset + size, file.size).arrayBuffer());
252
+ leftoverSize = leftover.length;
253
+ await writable.write({ type: 'write', data: leftover, position: offset });
254
+ }
230
255
 
231
- await writable.write({ type: 'truncate', size: offset + leftoverSize });
232
- await writable.close();
256
+ await writable.write({ type: 'truncate', size: offset + leftoverSize });
257
+ await writable.close();
258
+ } finally {
259
+ metric.end();
260
+ }
233
261
  }
234
262
 
235
263
  @synchronized
236
264
  async stat() {
237
- const fileHandle: any = await this._fileHandle;
238
- const file = await fileHandle.getFile();
239
- return {
240
- size: file.size,
241
- };
265
+ const metric = STORAGE_MONITOR.beginOp({ resource: this._fileName, type: 'stat' });
266
+ try {
267
+ const fileHandle: any = await this._fileHandle;
268
+ const file = await fileHandle.getFile();
269
+ return {
270
+ size: file.size,
271
+ };
272
+ } finally {
273
+ metric.end();
274
+ }
275
+ }
276
+
277
+ @synchronized
278
+ async truncate(offset: number) {
279
+ const metric = STORAGE_MONITOR.beginOp({ resource: this._fileName, type: 'truncate' });
280
+ try {
281
+ const fileHandle: any = await this._fileHandle;
282
+ const writable = await fileHandle.createWritable({ keepExistingData: true });
283
+ await writable.write({ type: 'truncate', size: offset });
284
+ await writable.close();
285
+ } finally {
286
+ metric.end();
287
+ }
242
288
  }
243
289
 
244
290
  async close(): Promise<void> {}
@@ -248,12 +294,4 @@ export class WebFile extends EventEmitter implements File {
248
294
  this.destroyed = true;
249
295
  return await this._destroy();
250
296
  }
251
-
252
- @synchronized
253
- async truncate(offset: number) {
254
- const fileHandle: any = await this._fileHandle;
255
- const writable = await fileHandle.createWritable({ keepExistingData: true });
256
- await writable.write({ type: 'truncate', size: offset });
257
- await writable.close();
258
- }
259
297
  }
package/src/monitor.ts ADDED
@@ -0,0 +1,140 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { unrefTimeout } from '@dxos/async';
6
+
7
+ export type StorageOperation = {
8
+ resource: string;
9
+ type: 'read' | 'write' | 'stat' | 'delete' | 'truncate';
10
+ size?: number;
11
+ };
12
+
13
+ export type OpHandle = {
14
+ end: () => void;
15
+ };
16
+
17
+ export type StatsBucket = {
18
+ resource: string;
19
+ beginTime: number;
20
+ endTime: number;
21
+
22
+ /**
23
+ * Fraction of time spent in storage operations.
24
+ */
25
+ usage: number;
26
+
27
+ readOps: number;
28
+ readBytes: number;
29
+ readTime: number;
30
+
31
+ writeOps: number;
32
+ writeBytes: number;
33
+ writeTime: number;
34
+
35
+ otherOps: number;
36
+ otherTime: number;
37
+ };
38
+
39
+ const BUCKET_COLLECTION_INTERVAL = 1_000;
40
+
41
+ /**
42
+ * Storage performance metrics.
43
+ */
44
+ export class StorageMonitor {
45
+ private _enabled = false;
46
+
47
+ /**
48
+ * By resource.
49
+ */
50
+ private readonly _buckets = new Map<string, StatsBucket>();
51
+
52
+ enable() {
53
+ this._enabled = true;
54
+
55
+ const timer = setInterval(() => {
56
+ this._finalizeBuckets();
57
+ }, BUCKET_COLLECTION_INTERVAL);
58
+ unrefTimeout(timer);
59
+ }
60
+
61
+ beginOp(op: StorageOperation): OpHandle {
62
+ if (!this._enabled) {
63
+ return {
64
+ end: () => {},
65
+ };
66
+ }
67
+
68
+ const beginTime = performance.now();
69
+ return {
70
+ end: () => {
71
+ const endTime = performance.now();
72
+ const duration = endTime - beginTime;
73
+
74
+ const bucket = this._getOrInitBucket(op.resource);
75
+ switch (op.type) {
76
+ case 'read':
77
+ bucket.readOps++;
78
+ bucket.readBytes += op.size ?? 0;
79
+ bucket.readTime += duration;
80
+ break;
81
+ case 'write':
82
+ bucket.writeOps++;
83
+ bucket.writeBytes += op.size ?? 0;
84
+ bucket.writeTime += duration;
85
+ break;
86
+ default:
87
+ bucket.otherOps++;
88
+ bucket.otherTime += duration;
89
+ }
90
+ },
91
+ };
92
+ }
93
+
94
+ private _getOrInitBucket(resource: string): StatsBucket {
95
+ const bucket = this._buckets.get(resource);
96
+ if (bucket) {
97
+ return bucket;
98
+ }
99
+
100
+ const newBucket = {
101
+ resource,
102
+ beginTime: performance.now(),
103
+ endTime: 0,
104
+ usage: 0,
105
+ readOps: 0,
106
+ readBytes: 0,
107
+ readTime: 0,
108
+ writeOps: 0,
109
+ writeBytes: 0,
110
+ writeTime: 0,
111
+ otherOps: 0,
112
+ otherTime: 0,
113
+ };
114
+ this._buckets.set(resource, newBucket);
115
+ return newBucket;
116
+ }
117
+
118
+ private _finalizeBuckets() {
119
+ const now = performance.now();
120
+ const toEmit = [];
121
+ for (const bucket of this._buckets.values()) {
122
+ bucket.endTime = now;
123
+ bucket.usage = (bucket.readTime + bucket.writeTime + bucket.otherTime) / (bucket.endTime - bucket.beginTime);
124
+ toEmit.push(bucket);
125
+ }
126
+
127
+ // Clear the buckets.
128
+ this._buckets.clear();
129
+ for (const bucket of toEmit) {
130
+ this._getOrInitBucket(bucket.resource);
131
+ }
132
+
133
+ ((globalThis as any).__STORAGE_METRICS ??= []).push(...toEmit);
134
+ }
135
+ }
136
+
137
+ export const STORAGE_MONITOR = new StorageMonitor();
138
+
139
+ // TODO(dmaretskyi): Disabled due to performance concerns.
140
+ // STORAGE_MONITOR.enable();