opfs-worker 2.1.1 → 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/README.md +21 -20
  2. package/dist/BaseOPFS-Bu7FZtCb.cjs +2 -0
  3. package/dist/BaseOPFS-Bu7FZtCb.cjs.map +1 -0
  4. package/dist/{BaseOPFS-BusBkyJX.js → BaseOPFS-C3NE4BKr.js} +790 -548
  5. package/dist/BaseOPFS-C3NE4BKr.js.map +1 -0
  6. package/dist/OPFSAsync-C0RsxCX5.cjs +2 -0
  7. package/dist/OPFSAsync-C0RsxCX5.cjs.map +1 -0
  8. package/dist/{OPFSAsync-CO44W23e.js → OPFSAsync-aeLUdIqd.js} +19 -19
  9. package/dist/OPFSAsync-aeLUdIqd.js.map +1 -0
  10. package/dist/{OPFSFacade-hrNXCn6w.cjs → OPFSFacade-BJv2yuWU.cjs} +2 -2
  11. package/dist/{OPFSFacade-hrNXCn6w.cjs.map → OPFSFacade-BJv2yuWU.cjs.map} +1 -1
  12. package/dist/{OPFSFacade-CEaSqTut.js → OPFSFacade-DiogtQoq.js} +2 -2
  13. package/dist/{OPFSFacade-CEaSqTut.js.map → OPFSFacade-DiogtQoq.js.map} +1 -1
  14. package/dist/OPFSSync-3qlSBYmz.cjs +2 -0
  15. package/dist/OPFSSync-3qlSBYmz.cjs.map +1 -0
  16. package/dist/{OPFSSync-D7obTsl3.js → OPFSSync-CvSOswhW.js} +57 -57
  17. package/dist/OPFSSync-CvSOswhW.js.map +1 -0
  18. package/dist/assets/dedicated.worker-Bqqr9UBA.js.map +1 -0
  19. package/dist/core/BaseOPFS.d.ts +23 -3
  20. package/dist/core/BaseOPFS.d.ts.map +1 -1
  21. package/dist/core/OPFSAsync.d.ts.map +1 -1
  22. package/dist/core/OPFSSync.d.ts.map +1 -1
  23. package/dist/createOPFSAsync-B611B63X.js +10 -0
  24. package/dist/{createOPFSAsync-DdhJYoC0.js.map → createOPFSAsync-B611B63X.js.map} +1 -1
  25. package/dist/createOPFSAsync-BATjJg8k.cjs +2 -0
  26. package/dist/{createOPFSAsync-DyWpvmL-.cjs.map → createOPFSAsync-BATjJg8k.cjs.map} +1 -1
  27. package/dist/{createOPFSDedicated-BwTc0NV5.js → createOPFSDedicated-DgudPTB8.js} +1086 -817
  28. package/dist/createOPFSDedicated-DgudPTB8.js.map +1 -0
  29. package/dist/{createOPFSDedicated-CEeRexom.cjs → createOPFSDedicated-EmIwluQo.cjs} +1037 -797
  30. package/dist/createOPFSDedicated-EmIwluQo.cjs.map +1 -0
  31. package/dist/{createOPFSShared-BSFWsoLe.js → createOPFSShared-BWYln8jJ.js} +2 -2
  32. package/dist/{createOPFSShared-BSFWsoLe.js.map → createOPFSShared-BWYln8jJ.js.map} +1 -1
  33. package/dist/{createOPFSShared-BoCft_BS.cjs → createOPFSShared-DPJpCd7z.cjs} +2 -2
  34. package/dist/{createOPFSShared-BoCft_BS.cjs.map → createOPFSShared-DPJpCd7z.cjs.map} +1 -1
  35. package/dist/dedicated.worker.js +1034 -794
  36. package/dist/dedicated.worker.js.map +1 -1
  37. package/dist/facade/createOPFSDedicated.d.ts +4 -2
  38. package/dist/facade/createOPFSDedicated.d.ts.map +1 -1
  39. package/dist/index.async.cjs +1 -1
  40. package/dist/index.async.js +33 -32
  41. package/dist/index.cjs +1 -1
  42. package/dist/index.d.ts +1 -5
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +44 -43
  45. package/dist/index.pure.cjs +1 -1
  46. package/dist/index.pure.js +38 -37
  47. package/dist/index.sharedworker.cjs +1 -1
  48. package/dist/index.sharedworker.js +34 -33
  49. package/dist/index.sync.cjs +1 -1
  50. package/dist/index.sync.d.ts +2 -0
  51. package/dist/index.sync.d.ts.map +1 -1
  52. package/dist/index.sync.js +34 -32
  53. package/dist/shared.worker.js +1056 -820
  54. package/dist/shared.worker.js.map +1 -1
  55. package/dist/types.d.ts +5 -5
  56. package/dist/types.d.ts.map +1 -1
  57. package/dist/utils/helpers.d.ts +13 -3
  58. package/dist/utils/helpers.d.ts.map +1 -1
  59. package/dist/worker/createDedicatedWorker.d.ts +8 -3
  60. package/dist/worker/createDedicatedWorker.d.ts.map +1 -1
  61. package/docs/README.md +18 -0
  62. package/docs/api/README.md +221 -0
  63. package/docs/{file-descriptors.md → api/file-descriptors.md} +13 -13
  64. package/docs/guides/async.md +2 -2
  65. package/docs/guides/dedicated.md +6 -4
  66. package/docs/guides/hashing.md +1 -1
  67. package/docs/guides/pure.md +1 -1
  68. package/docs/guides/sharedworker.md +1 -1
  69. package/docs/guides/streaming.md +2 -2
  70. package/docs/migration.md +8 -9
  71. package/docs/types.md +4 -4
  72. package/package.json +10 -9
  73. package/src/core/BaseOPFS.ts +46 -4
  74. package/src/core/OPFSAsync.ts +4 -5
  75. package/src/core/OPFSSync.ts +6 -7
  76. package/src/facade/createOPFSDedicated.ts +4 -2
  77. package/src/index.sync.ts +2 -0
  78. package/src/index.ts +1 -5
  79. package/src/types.ts +5 -3
  80. package/src/utils/helpers.ts +32 -6
  81. package/src/worker/createDedicatedWorker.ts +85 -7
  82. package/src/worker/dedicated.worker.ts +12 -1
  83. package/dist/BaseOPFS-BusBkyJX.js.map +0 -1
  84. package/dist/BaseOPFS-CYwrD7-q.cjs +0 -4
  85. package/dist/BaseOPFS-CYwrD7-q.cjs.map +0 -1
  86. package/dist/OPFSAsync-B2dR-2VR.cjs +0 -2
  87. package/dist/OPFSAsync-B2dR-2VR.cjs.map +0 -1
  88. package/dist/OPFSAsync-CO44W23e.js.map +0 -1
  89. package/dist/OPFSSync-BPrNtvFS.cjs +0 -2
  90. package/dist/OPFSSync-BPrNtvFS.cjs.map +0 -1
  91. package/dist/OPFSSync-D7obTsl3.js.map +0 -1
  92. package/dist/assets/dedicated.worker-DW6UqFo0.js.map +0 -1
  93. package/dist/createOPFSAsync-DdhJYoC0.js +0 -10
  94. package/dist/createOPFSAsync-DyWpvmL-.cjs +0 -2
  95. package/dist/createOPFSDedicated-BwTc0NV5.js.map +0 -1
  96. package/dist/createOPFSDedicated-CEeRexom.cjs.map +0 -1
  97. package/docs/api/backend.md +0 -36
  98. package/docs/api/create.md +0 -82
  99. package/docs/api/facade.md +0 -53
  100. package/docs/choosing-a-mode.md +0 -41
@@ -0,0 +1,2 @@
1
+ "use strict";const f=require("comlink"),r=require("./BaseOPFS-Bu7FZtCb.cjs"),s="file descriptors are not available in the async backend, use the dedicated worker backend (`createOPFSDedicated`) for positional I/O";class d extends r.BaseOPFS{async readFile(t){await this.mount();try{return await this.withPathLock(t,async()=>{const i=await(await this.getFileHandle(t,!1)).getFile(),e=new Uint8Array(await i.arrayBuffer());return f.transfer(e,[e.buffer])})}catch(a){throw a instanceof r.OPFSError?a:r.mapDomError(a,{path:t,isDirectory:a?.name==="TypeMismatchError"})}}async writeFile(t,a){await this.mount();const i=a instanceof Uint8Array?a:new Uint8Array(a);try{await this.withPathLock(t,async()=>{const e=await this.exists(t),o=await this.getFileHandle(t,!0);await this._writeStream(o,async n=>n.write(i)),await this.notifyChange({path:t,type:e?r.WatchEventType.Changed:r.WatchEventType.Added,isDirectory:!1})})}catch(e){throw e instanceof r.OPFSError?e:r.mapDomError(e,{path:t,isDirectory:e?.name==="TypeMismatchError"})}}async appendFile(t,a){await this.mount();const i=a instanceof Uint8Array?a:new Uint8Array(a);try{await this.withPathLock(t,async()=>{const e=await this.getFileHandle(t,!0),{size:o}=await e.getFile();await this._writeStream(e,async n=>n.write({type:"write",position:o,data:i}),{keepExistingData:!0}),await this.notifyChange({path:t,type:r.WatchEventType.Changed,isDirectory:!1})})}catch(e){throw e instanceof r.OPFSError?e:r.mapDomError(e,{path:t,isDirectory:e?.name==="TypeMismatchError"})}}async writeStream(t,a,i){await this.mount();try{return await this.withPathLock(t,async()=>{const e=await this.exists(t),o=await this.getFileHandle(t,!0),n=a.getReader();let w=0;try{await this._writeStream(o,async c=>{for(;;){const{done:y,value:h}=await n.read();if(y)break;await c.write(h),w+=h.byteLength,await i?.(w)}})}catch(c){throw await n.cancel(c).catch(()=>{}),c}finally{n.releaseLock()}return await this.notifyChange({path:t,type:e?r.WatchEventType.Changed:r.WatchEventType.Added,isDirectory:!1}),w})}catch(e){throw e instanceof r.OPFSError?e:r.mapDomError(e,{path:t,isDirectory:e?.name==="TypeMismatchError"})}}async _writeStream(t,a,i){if(typeof t.createWritable!="function")throw new r.OperationNotSupportedError("createWritable() is not available in this browser (Safari supports it since version 26), use the dedicated worker backend (`createOPFSDedicated`) instead");const e=await t.createWritable(i);try{await a(e)}catch(o){throw await e.abort().catch(()=>{}),o}await e.close()}async open(t,a){throw new r.OperationNotSupportedError(s)}async close(t){throw new r.OperationNotSupportedError(s)}async read(t,a,i,e,o){throw new r.OperationNotSupportedError(s)}async write(t,a,i,e,o,n){throw new r.OperationNotSupportedError(s)}async fstat(t){throw new r.OperationNotSupportedError(s)}async ftruncate(t,a){throw new r.OperationNotSupportedError(s)}async fsync(t){throw new r.OperationNotSupportedError(s)}}exports.OPFSAsync=d;
2
+ //# sourceMappingURL=OPFSAsync-C0RsxCX5.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OPFSAsync-C0RsxCX5.cjs","sources":["../src/core/OPFSAsync.ts"],"sourcesContent":["import { transfer } from 'comlink';\n\nimport { BaseOPFS } from './BaseOPFS';\nimport { WatchEventType } from '../types';\nimport { OPFSError, OperationNotSupportedError, mapDomError } from '../utils/errors';\n\nimport type { FileOpenOptions, FileStat } from '../types';\n\nconst FD_UNSUPPORTED = 'file descriptors are not available in the async backend, use the dedicated worker backend (`createOPFSDedicated`) for positional I/O';\n\n/**\n * Async OPFS backend using the promise-based File System API\n * (`getFile()` / `createWritable()`).\n *\n * Unlike `OPFSSync`, it does not require a dedicated worker: it works on the\n * main thread and inside any worker type (including SharedWorker).\n *\n * Requirements and limitations:\n * - Writing needs `FileSystemFileHandle.createWritable()` — Chrome, Firefox, Safari 26+.\n * Reading works in older Safari too.\n * - No file descriptors / positional I/O: `open`, `read`, `write`, `close`,\n * `fstat`, `ftruncate` and `fsync` always throw `OperationNotSupportedError`.\n *\n * @example\n * ```typescript\n * import { OPFSAsync } from 'opfs-worker/pure';\n * // or: 'opfs-worker' / 'opfs-worker/async'\n *\n * const fs = new OPFSAsync({ root: '/my-app' });\n * await fs.writeFile('/config.json', new TextEncoder().encode('{}'));\n * const config = await fs.readFile('/config.json');\n * ```\n */\nexport class OPFSAsync extends BaseOPFS {\n async readFile(path: string): Promise<Uint8Array> {\n await this.mount();\n\n try {\n return await this.withPathLock(path, async() => {\n const fileHandle = await this.getFileHandle(path, false);\n const file = await fileHandle.getFile();\n const buffer = new Uint8Array(await file.arrayBuffer());\n\n return transfer(buffer, [buffer.buffer]);\n });\n }\n catch (error: any) {\n if (error instanceof OPFSError) {\n throw error;\n }\n\n throw mapDomError(error, { path, isDirectory: error?.name === 'TypeMismatchError' });\n }\n }\n\n async writeFile(\n path: string,\n data: Uint8Array | ArrayBuffer\n ): Promise<void> {\n await this.mount();\n\n const buffer = data instanceof Uint8Array ? data : new Uint8Array(data);\n\n try {\n await this.withPathLock(path, async() => {\n const existed = await this.exists(path);\n const fileHandle = await this.getFileHandle(path, true);\n\n // Default createWritable() starts from an empty swap file,\n // so close() atomically replaces the content (truncate + write).\n await this._writeStream(fileHandle, async writable => writable.write(buffer as Uint8Array<ArrayBuffer>));\n\n await this.notifyChange({ path, type: existed ? WatchEventType.Changed : WatchEventType.Added, isDirectory: false });\n });\n }\n catch (error: any) {\n if (error instanceof OPFSError) {\n throw error;\n }\n\n throw mapDomError(error, { path, isDirectory: error?.name === 'TypeMismatchError' });\n }\n }\n\n async appendFile(\n path: string,\n data: Uint8Array | ArrayBuffer\n ): Promise<void> {\n await this.mount();\n\n const buffer = data instanceof Uint8Array ? data : new Uint8Array(data);\n\n try {\n await this.withPathLock(path, async() => {\n const fileHandle = await this.getFileHandle(path, true);\n const { size } = await fileHandle.getFile();\n\n await this._writeStream(\n fileHandle,\n async writable => writable.write({ type: 'write', position: size, data: buffer as Uint8Array<ArrayBuffer> }),\n { keepExistingData: true }\n );\n\n await this.notifyChange({ path, type: WatchEventType.Changed, isDirectory: false });\n });\n }\n catch (error: any) {\n if (error instanceof OPFSError) {\n throw error;\n }\n\n throw mapDomError(error, { path, isDirectory: error?.name === 'TypeMismatchError' });\n }\n }\n\n async writeStream(\n path: string,\n stream: ReadableStream<Uint8Array>,\n onProgress?: (bytesWritten: number) => unknown\n ): Promise<number> {\n await this.mount();\n\n try {\n return await this.withPathLock(path, async() => {\n const existed = await this.exists(path);\n const fileHandle = await this.getFileHandle(path, true);\n const reader = stream.getReader();\n let totalBytes = 0;\n\n try {\n await this._writeStream(fileHandle, async(writable) => {\n while (true) {\n const { done, value: chunk } = await reader.read();\n\n if (done) {\n break;\n }\n\n await writable.write(chunk as Uint8Array<ArrayBuffer>);\n totalBytes += chunk.byteLength;\n await onProgress?.(totalBytes);\n }\n });\n }\n catch (error) {\n await reader.cancel(error).catch(() => {});\n\n throw error;\n }\n finally {\n reader.releaseLock();\n }\n\n await this.notifyChange({\n path,\n type: existed ? WatchEventType.Changed : WatchEventType.Added,\n isDirectory: false,\n });\n\n return totalBytes;\n });\n }\n catch (error: any) {\n if (error instanceof OPFSError) {\n throw error;\n }\n\n throw mapDomError(error, { path, isDirectory: error?.name === 'TypeMismatchError' });\n }\n }\n\n /**\n * Open a writable stream, run the write callback and commit via close().\n * Aborts the stream (discarding the swap file) if the callback fails.\n * @private\n */\n private async _writeStream(\n fileHandle: FileSystemFileHandle,\n write: (writable: FileSystemWritableFileStream) => Promise<void>,\n options?: { keepExistingData?: boolean }\n ): Promise<void> {\n if (typeof fileHandle.createWritable !== 'function') {\n throw new OperationNotSupportedError('createWritable() is not available in this browser (Safari supports it since version 26), use the dedicated worker backend (`createOPFSDedicated`) instead');\n }\n\n const writable = await fileHandle.createWritable(options);\n\n try {\n await write(writable);\n }\n catch (error) {\n await writable.abort().catch(() => {});\n\n throw error;\n }\n\n await writable.close();\n }\n\n /** @throws {OperationNotSupportedError} Always — no FD support in the async backend */\n async open(_path: string, _options?: FileOpenOptions): Promise<number> {\n throw new OperationNotSupportedError(FD_UNSUPPORTED);\n }\n\n /** @throws {OperationNotSupportedError} Always — no FD support in the async backend */\n async close(_fd: number): Promise<void> {\n throw new OperationNotSupportedError(FD_UNSUPPORTED);\n }\n\n /** @throws {OperationNotSupportedError} Always — no FD support in the async backend */\n async read(\n _fd: number,\n _buffer: Uint8Array,\n _offset: number,\n _length: number,\n _position: number | null | undefined\n ): Promise<{ bytesRead: number; buffer: Uint8Array }> {\n throw new OperationNotSupportedError(FD_UNSUPPORTED);\n }\n\n /** @throws {OperationNotSupportedError} Always — no FD support in the async backend */\n async write(\n _fd: number,\n _buffer: Uint8Array,\n _offset?: number,\n _length?: number,\n _position?: number | null | undefined,\n _emitEvent?: boolean\n ): Promise<number> {\n throw new OperationNotSupportedError(FD_UNSUPPORTED);\n }\n\n /** @throws {OperationNotSupportedError} Always — no FD support in the async backend */\n async fstat(_fd: number): Promise<FileStat> {\n throw new OperationNotSupportedError(FD_UNSUPPORTED);\n }\n\n /** @throws {OperationNotSupportedError} Always — no FD support in the async backend */\n async ftruncate(_fd: number, _size?: number): Promise<void> {\n throw new OperationNotSupportedError(FD_UNSUPPORTED);\n }\n\n /** @throws {OperationNotSupportedError} Always — no FD support in the async backend */\n async fsync(_fd: number): Promise<void> {\n throw new OperationNotSupportedError(FD_UNSUPPORTED);\n }\n}\n"],"names":["FD_UNSUPPORTED","OPFSAsync","BaseOPFS","path","file","buffer","transfer","error","OPFSError","mapDomError","data","existed","fileHandle","writable","WatchEventType","size","stream","onProgress","reader","totalBytes","done","chunk","write","options","OperationNotSupportedError","_path","_options","_fd","_buffer","_offset","_length","_position","_emitEvent","_size"],"mappings":"6EAQMA,EAAiB,uIAyBhB,MAAMC,UAAkBC,EAAAA,QAAS,CACpC,MAAM,SAASC,EAAmC,CAC9C,MAAM,KAAK,MAAA,EAEX,GAAI,CACA,OAAO,MAAM,KAAK,aAAaA,EAAM,SAAW,CAE5C,MAAMC,EAAO,MADM,MAAM,KAAK,cAAcD,EAAM,EAAK,GACzB,QAAA,EACxBE,EAAS,IAAI,WAAW,MAAMD,EAAK,aAAa,EAEtD,OAAOE,EAAAA,SAASD,EAAQ,CAACA,EAAO,MAAM,CAAC,CAC3C,CAAC,CACL,OACOE,EAAY,CACf,MAAIA,aAAiBC,EAAAA,UACXD,EAGJE,EAAAA,YAAYF,EAAO,CAAE,KAAAJ,EAAM,YAAaI,GAAO,OAAS,oBAAqB,CACvF,CACJ,CAEA,MAAM,UACFJ,EACAO,EACa,CACb,MAAM,KAAK,MAAA,EAEX,MAAML,EAASK,aAAgB,WAAaA,EAAO,IAAI,WAAWA,CAAI,EAEtE,GAAI,CACA,MAAM,KAAK,aAAaP,EAAM,SAAW,CACrC,MAAMQ,EAAU,MAAM,KAAK,OAAOR,CAAI,EAChCS,EAAa,MAAM,KAAK,cAAcT,EAAM,EAAI,EAItD,MAAM,KAAK,aAAaS,EAAY,MAAMC,GAAYA,EAAS,MAAMR,CAAiC,CAAC,EAEvG,MAAM,KAAK,aAAa,CAAE,KAAAF,EAAM,KAAMQ,EAAUG,iBAAe,QAAUA,EAAAA,eAAe,MAAO,YAAa,EAAA,CAAO,CACvH,CAAC,CACL,OACOP,EAAY,CACf,MAAIA,aAAiBC,EAAAA,UACXD,EAGJE,EAAAA,YAAYF,EAAO,CAAE,KAAAJ,EAAM,YAAaI,GAAO,OAAS,oBAAqB,CACvF,CACJ,CAEA,MAAM,WACFJ,EACAO,EACa,CACb,MAAM,KAAK,MAAA,EAEX,MAAML,EAASK,aAAgB,WAAaA,EAAO,IAAI,WAAWA,CAAI,EAEtE,GAAI,CACA,MAAM,KAAK,aAAaP,EAAM,SAAW,CACrC,MAAMS,EAAa,MAAM,KAAK,cAAcT,EAAM,EAAI,EAChD,CAAE,KAAAY,CAAA,EAAS,MAAMH,EAAW,QAAA,EAElC,MAAM,KAAK,aACPA,EACA,MAAMC,GAAYA,EAAS,MAAM,CAAE,KAAM,QAAS,SAAUE,EAAM,KAAMV,EAAmC,EAC3G,CAAE,iBAAkB,EAAA,CAAK,EAG7B,MAAM,KAAK,aAAa,CAAE,KAAAF,EAAM,KAAMW,EAAAA,eAAe,QAAS,YAAa,GAAO,CACtF,CAAC,CACL,OACOP,EAAY,CACf,MAAIA,aAAiBC,EAAAA,UACXD,EAGJE,EAAAA,YAAYF,EAAO,CAAE,KAAAJ,EAAM,YAAaI,GAAO,OAAS,oBAAqB,CACvF,CACJ,CAEA,MAAM,YACFJ,EACAa,EACAC,EACe,CACf,MAAM,KAAK,MAAA,EAEX,GAAI,CACA,OAAO,MAAM,KAAK,aAAad,EAAM,SAAW,CAC5C,MAAMQ,EAAU,MAAM,KAAK,OAAOR,CAAI,EAChCS,EAAa,MAAM,KAAK,cAAcT,EAAM,EAAI,EAChDe,EAASF,EAAO,UAAA,EACtB,IAAIG,EAAa,EAEjB,GAAI,CACA,MAAM,KAAK,aAAaP,EAAY,MAAMC,GAAa,CACnD,OAAa,CACT,KAAM,CAAE,KAAAO,EAAM,MAAOC,GAAU,MAAMH,EAAO,KAAA,EAE5C,GAAIE,EACA,MAGJ,MAAMP,EAAS,MAAMQ,CAAgC,EACrDF,GAAcE,EAAM,WACpB,MAAMJ,IAAaE,CAAU,CACjC,CACJ,CAAC,CACL,OACOZ,EAAO,CACV,YAAMW,EAAO,OAAOX,CAAK,EAAE,MAAM,IAAM,CAAC,CAAC,EAEnCA,CACV,QAAA,CAEIW,EAAO,YAAA,CACX,CAEA,aAAM,KAAK,aAAa,CACpB,KAAAf,EACA,KAAMQ,EAAUG,EAAAA,eAAe,QAAUA,EAAAA,eAAe,MACxD,YAAa,EAAA,CAChB,EAEMK,CACX,CAAC,CACL,OACOZ,EAAY,CACf,MAAIA,aAAiBC,EAAAA,UACXD,EAGJE,EAAAA,YAAYF,EAAO,CAAE,KAAAJ,EAAM,YAAaI,GAAO,OAAS,oBAAqB,CACvF,CACJ,CAOA,MAAc,aACVK,EACAU,EACAC,EACa,CACb,GAAI,OAAOX,EAAW,gBAAmB,WACrC,MAAM,IAAIY,EAAAA,2BAA2B,2JAA2J,EAGpM,MAAMX,EAAW,MAAMD,EAAW,eAAeW,CAAO,EAExD,GAAI,CACA,MAAMD,EAAMT,CAAQ,CACxB,OACON,EAAO,CACV,YAAMM,EAAS,QAAQ,MAAM,IAAM,CAAC,CAAC,EAE/BN,CACV,CAEA,MAAMM,EAAS,MAAA,CACnB,CAGA,MAAM,KAAKY,EAAeC,EAA6C,CACnE,MAAM,IAAIF,EAAAA,2BAA2BxB,CAAc,CACvD,CAGA,MAAM,MAAM2B,EAA4B,CACpC,MAAM,IAAIH,EAAAA,2BAA2BxB,CAAc,CACvD,CAGA,MAAM,KACF2B,EACAC,EACAC,EACAC,EACAC,EACkD,CAClD,MAAM,IAAIP,EAAAA,2BAA2BxB,CAAc,CACvD,CAGA,MAAM,MACF2B,EACAC,EACAC,EACAC,EACAC,EACAC,EACe,CACf,MAAM,IAAIR,EAAAA,2BAA2BxB,CAAc,CACvD,CAGA,MAAM,MAAM2B,EAAgC,CACxC,MAAM,IAAIH,EAAAA,2BAA2BxB,CAAc,CACvD,CAGA,MAAM,UAAU2B,EAAaM,EAA+B,CACxD,MAAM,IAAIT,EAAAA,2BAA2BxB,CAAc,CACvD,CAGA,MAAM,MAAM2B,EAA4B,CACpC,MAAM,IAAIH,EAAAA,2BAA2BxB,CAAc,CACvD,CACJ"}
@@ -1,35 +1,35 @@
1
- import { transfer as m } from "comlink";
2
- import { B as _, w as f, O as y, m as h, W as c, e as s } from "./BaseOPFS-BusBkyJX.js";
1
+ import { transfer as u } from "comlink";
2
+ import { B as m, O as h, m as f, W as c, e as s } from "./BaseOPFS-C3NE4BKr.js";
3
3
  const o = "file descriptors are not available in the async backend, use the dedicated worker backend (`createOPFSDedicated`) for positional I/O";
4
- class F extends _ {
4
+ class p extends m {
5
5
  async readFile(t) {
6
6
  await this.mount();
7
7
  try {
8
- return await f(t, async () => {
8
+ return await this.withPathLock(t, async () => {
9
9
  const r = await (await this.getFileHandle(t, !1)).getFile(), e = new Uint8Array(await r.arrayBuffer());
10
- return m(e, [e.buffer]);
10
+ return u(e, [e.buffer]);
11
11
  });
12
12
  } catch (a) {
13
- throw a instanceof y ? a : h(a, { path: t, isDirectory: a?.name === "TypeMismatchError" });
13
+ throw a instanceof h ? a : f(a, { path: t, isDirectory: a?.name === "TypeMismatchError" });
14
14
  }
15
15
  }
16
16
  async writeFile(t, a) {
17
17
  await this.mount();
18
18
  const r = a instanceof Uint8Array ? a : new Uint8Array(a);
19
19
  try {
20
- await f(t, async () => {
20
+ await this.withPathLock(t, async () => {
21
21
  const e = await this.exists(t), i = await this.getFileHandle(t, !0);
22
22
  await this._writeStream(i, async (n) => n.write(r)), await this.notifyChange({ path: t, type: e ? c.Changed : c.Added, isDirectory: !1 });
23
23
  });
24
24
  } catch (e) {
25
- throw e instanceof y ? e : h(e, { path: t, isDirectory: e?.name === "TypeMismatchError" });
25
+ throw e instanceof h ? e : f(e, { path: t, isDirectory: e?.name === "TypeMismatchError" });
26
26
  }
27
27
  }
28
28
  async appendFile(t, a) {
29
29
  await this.mount();
30
30
  const r = a instanceof Uint8Array ? a : new Uint8Array(a);
31
31
  try {
32
- await f(t, async () => {
32
+ await this.withPathLock(t, async () => {
33
33
  const e = await this.getFileHandle(t, !0), { size: i } = await e.getFile();
34
34
  await this._writeStream(
35
35
  e,
@@ -38,22 +38,22 @@ class F extends _ {
38
38
  ), await this.notifyChange({ path: t, type: c.Changed, isDirectory: !1 });
39
39
  });
40
40
  } catch (e) {
41
- throw e instanceof y ? e : h(e, { path: t, isDirectory: e?.name === "TypeMismatchError" });
41
+ throw e instanceof h ? e : f(e, { path: t, isDirectory: e?.name === "TypeMismatchError" });
42
42
  }
43
43
  }
44
44
  async writeStream(t, a, r) {
45
45
  await this.mount();
46
46
  try {
47
- return await f(t, async () => {
47
+ return await this.withPathLock(t, async () => {
48
48
  const e = await this.exists(t), i = await this.getFileHandle(t, !0), n = a.getReader();
49
- let l = 0;
49
+ let y = 0;
50
50
  try {
51
51
  await this._writeStream(i, async (w) => {
52
52
  for (; ; ) {
53
- const { done: u, value: d } = await n.read();
54
- if (u)
53
+ const { done: d, value: l } = await n.read();
54
+ if (d)
55
55
  break;
56
- await w.write(d), l += d.byteLength, await r?.(l);
56
+ await w.write(l), y += l.byteLength, await r?.(y);
57
57
  }
58
58
  });
59
59
  } catch (w) {
@@ -66,10 +66,10 @@ class F extends _ {
66
66
  path: t,
67
67
  type: e ? c.Changed : c.Added,
68
68
  isDirectory: !1
69
- }), l;
69
+ }), y;
70
70
  });
71
71
  } catch (e) {
72
- throw e instanceof y ? e : h(e, { path: t, isDirectory: e?.name === "TypeMismatchError" });
72
+ throw e instanceof h ? e : f(e, { path: t, isDirectory: e?.name === "TypeMismatchError" });
73
73
  }
74
74
  }
75
75
  /**
@@ -119,6 +119,6 @@ class F extends _ {
119
119
  }
120
120
  }
121
121
  export {
122
- F as O
122
+ p as O
123
123
  };
124
- //# sourceMappingURL=OPFSAsync-CO44W23e.js.map
124
+ //# sourceMappingURL=OPFSAsync-aeLUdIqd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OPFSAsync-aeLUdIqd.js","sources":["../src/core/OPFSAsync.ts"],"sourcesContent":["import { transfer } from 'comlink';\n\nimport { BaseOPFS } from './BaseOPFS';\nimport { WatchEventType } from '../types';\nimport { OPFSError, OperationNotSupportedError, mapDomError } from '../utils/errors';\n\nimport type { FileOpenOptions, FileStat } from '../types';\n\nconst FD_UNSUPPORTED = 'file descriptors are not available in the async backend, use the dedicated worker backend (`createOPFSDedicated`) for positional I/O';\n\n/**\n * Async OPFS backend using the promise-based File System API\n * (`getFile()` / `createWritable()`).\n *\n * Unlike `OPFSSync`, it does not require a dedicated worker: it works on the\n * main thread and inside any worker type (including SharedWorker).\n *\n * Requirements and limitations:\n * - Writing needs `FileSystemFileHandle.createWritable()` — Chrome, Firefox, Safari 26+.\n * Reading works in older Safari too.\n * - No file descriptors / positional I/O: `open`, `read`, `write`, `close`,\n * `fstat`, `ftruncate` and `fsync` always throw `OperationNotSupportedError`.\n *\n * @example\n * ```typescript\n * import { OPFSAsync } from 'opfs-worker/pure';\n * // or: 'opfs-worker' / 'opfs-worker/async'\n *\n * const fs = new OPFSAsync({ root: '/my-app' });\n * await fs.writeFile('/config.json', new TextEncoder().encode('{}'));\n * const config = await fs.readFile('/config.json');\n * ```\n */\nexport class OPFSAsync extends BaseOPFS {\n async readFile(path: string): Promise<Uint8Array> {\n await this.mount();\n\n try {\n return await this.withPathLock(path, async() => {\n const fileHandle = await this.getFileHandle(path, false);\n const file = await fileHandle.getFile();\n const buffer = new Uint8Array(await file.arrayBuffer());\n\n return transfer(buffer, [buffer.buffer]);\n });\n }\n catch (error: any) {\n if (error instanceof OPFSError) {\n throw error;\n }\n\n throw mapDomError(error, { path, isDirectory: error?.name === 'TypeMismatchError' });\n }\n }\n\n async writeFile(\n path: string,\n data: Uint8Array | ArrayBuffer\n ): Promise<void> {\n await this.mount();\n\n const buffer = data instanceof Uint8Array ? data : new Uint8Array(data);\n\n try {\n await this.withPathLock(path, async() => {\n const existed = await this.exists(path);\n const fileHandle = await this.getFileHandle(path, true);\n\n // Default createWritable() starts from an empty swap file,\n // so close() atomically replaces the content (truncate + write).\n await this._writeStream(fileHandle, async writable => writable.write(buffer as Uint8Array<ArrayBuffer>));\n\n await this.notifyChange({ path, type: existed ? WatchEventType.Changed : WatchEventType.Added, isDirectory: false });\n });\n }\n catch (error: any) {\n if (error instanceof OPFSError) {\n throw error;\n }\n\n throw mapDomError(error, { path, isDirectory: error?.name === 'TypeMismatchError' });\n }\n }\n\n async appendFile(\n path: string,\n data: Uint8Array | ArrayBuffer\n ): Promise<void> {\n await this.mount();\n\n const buffer = data instanceof Uint8Array ? data : new Uint8Array(data);\n\n try {\n await this.withPathLock(path, async() => {\n const fileHandle = await this.getFileHandle(path, true);\n const { size } = await fileHandle.getFile();\n\n await this._writeStream(\n fileHandle,\n async writable => writable.write({ type: 'write', position: size, data: buffer as Uint8Array<ArrayBuffer> }),\n { keepExistingData: true }\n );\n\n await this.notifyChange({ path, type: WatchEventType.Changed, isDirectory: false });\n });\n }\n catch (error: any) {\n if (error instanceof OPFSError) {\n throw error;\n }\n\n throw mapDomError(error, { path, isDirectory: error?.name === 'TypeMismatchError' });\n }\n }\n\n async writeStream(\n path: string,\n stream: ReadableStream<Uint8Array>,\n onProgress?: (bytesWritten: number) => unknown\n ): Promise<number> {\n await this.mount();\n\n try {\n return await this.withPathLock(path, async() => {\n const existed = await this.exists(path);\n const fileHandle = await this.getFileHandle(path, true);\n const reader = stream.getReader();\n let totalBytes = 0;\n\n try {\n await this._writeStream(fileHandle, async(writable) => {\n while (true) {\n const { done, value: chunk } = await reader.read();\n\n if (done) {\n break;\n }\n\n await writable.write(chunk as Uint8Array<ArrayBuffer>);\n totalBytes += chunk.byteLength;\n await onProgress?.(totalBytes);\n }\n });\n }\n catch (error) {\n await reader.cancel(error).catch(() => {});\n\n throw error;\n }\n finally {\n reader.releaseLock();\n }\n\n await this.notifyChange({\n path,\n type: existed ? WatchEventType.Changed : WatchEventType.Added,\n isDirectory: false,\n });\n\n return totalBytes;\n });\n }\n catch (error: any) {\n if (error instanceof OPFSError) {\n throw error;\n }\n\n throw mapDomError(error, { path, isDirectory: error?.name === 'TypeMismatchError' });\n }\n }\n\n /**\n * Open a writable stream, run the write callback and commit via close().\n * Aborts the stream (discarding the swap file) if the callback fails.\n * @private\n */\n private async _writeStream(\n fileHandle: FileSystemFileHandle,\n write: (writable: FileSystemWritableFileStream) => Promise<void>,\n options?: { keepExistingData?: boolean }\n ): Promise<void> {\n if (typeof fileHandle.createWritable !== 'function') {\n throw new OperationNotSupportedError('createWritable() is not available in this browser (Safari supports it since version 26), use the dedicated worker backend (`createOPFSDedicated`) instead');\n }\n\n const writable = await fileHandle.createWritable(options);\n\n try {\n await write(writable);\n }\n catch (error) {\n await writable.abort().catch(() => {});\n\n throw error;\n }\n\n await writable.close();\n }\n\n /** @throws {OperationNotSupportedError} Always — no FD support in the async backend */\n async open(_path: string, _options?: FileOpenOptions): Promise<number> {\n throw new OperationNotSupportedError(FD_UNSUPPORTED);\n }\n\n /** @throws {OperationNotSupportedError} Always — no FD support in the async backend */\n async close(_fd: number): Promise<void> {\n throw new OperationNotSupportedError(FD_UNSUPPORTED);\n }\n\n /** @throws {OperationNotSupportedError} Always — no FD support in the async backend */\n async read(\n _fd: number,\n _buffer: Uint8Array,\n _offset: number,\n _length: number,\n _position: number | null | undefined\n ): Promise<{ bytesRead: number; buffer: Uint8Array }> {\n throw new OperationNotSupportedError(FD_UNSUPPORTED);\n }\n\n /** @throws {OperationNotSupportedError} Always — no FD support in the async backend */\n async write(\n _fd: number,\n _buffer: Uint8Array,\n _offset?: number,\n _length?: number,\n _position?: number | null | undefined,\n _emitEvent?: boolean\n ): Promise<number> {\n throw new OperationNotSupportedError(FD_UNSUPPORTED);\n }\n\n /** @throws {OperationNotSupportedError} Always — no FD support in the async backend */\n async fstat(_fd: number): Promise<FileStat> {\n throw new OperationNotSupportedError(FD_UNSUPPORTED);\n }\n\n /** @throws {OperationNotSupportedError} Always — no FD support in the async backend */\n async ftruncate(_fd: number, _size?: number): Promise<void> {\n throw new OperationNotSupportedError(FD_UNSUPPORTED);\n }\n\n /** @throws {OperationNotSupportedError} Always — no FD support in the async backend */\n async fsync(_fd: number): Promise<void> {\n throw new OperationNotSupportedError(FD_UNSUPPORTED);\n }\n}\n"],"names":["FD_UNSUPPORTED","OPFSAsync","BaseOPFS","path","file","buffer","transfer","error","OPFSError","mapDomError","data","existed","fileHandle","writable","WatchEventType","size","stream","onProgress","reader","totalBytes","done","chunk","write","options","OperationNotSupportedError","_path","_options","_fd","_buffer","_offset","_length","_position","_emitEvent","_size"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";const h=require("comlink"),o=require("./BaseOPFS-CYwrD7-q.cjs");function i(c){return c instanceof URL?c.pathname:c}let d=!1;function l(){d||(d=!0,console.warn("[opfs-worker] createIndex() is deprecated; use importFiles() instead"))}class y{#e;#r;backend;worker;promises=this;constructor(e){this.#e=e.fs,this.backend=e.fs,this.worker=e.worker,this.#r=e.dispose}watch(e,r){const t=i(e);return this.#e.watch(t,r),()=>this.unwatch(t)}unwatch(e){const r=i(e);this.#e.unwatch(r)}async setOptions(e){return this.#e.setOptions(e)}async index(){return this.#e.index()}async readFile(e,r){const t=i(e);let n;typeof r=="string"?n=r:r&&typeof r=="object"&&(n=r.encoding);const s=await this.#e.readFile(t);return n||(n=o.isBinaryFileExtension(t)?"binary":"utf-8"),n==="binary"?s:o.decodeBuffer(s,n)}async#t(e,r,t){return r instanceof Blob?new Uint8Array(await r.arrayBuffer()):(t||(t=typeof r!="string"||o.isBinaryFileExtension(e)?"binary":"utf-8"),typeof r=="string"?o.encodeString(r,t):r instanceof Uint8Array?r:new Uint8Array(r))}async writeFile(e,r,t){const n=i(e);let s;typeof t=="string"?s=t:t&&typeof t=="object"&&(s=t.encoding);const a=await this.#t(n,r,s);return this.#e.writeFile(n,a)}async appendFile(e,r,t){const n=i(e),s=await this.#t(n,r,t);return this.#e.appendFile(n,s)}async importStream(e,r,t){const n=i(e),s=r instanceof Blob?r.stream():r,a=h.transfer(s,[s]),u=t?.onProgress?h.proxy(f=>t.onProgress(f)):void 0;return this.#e.writeStream(n,a,u)}async mkdir(e,r){const t=i(e);let n;return typeof r=="number"?n={recursive:!1}:n=r,this.#e.mkdir(t,n)}async stat(e){const r=i(e);return this.#e.stat(r)}async readDir(e){const r=i(e);return this.#e.readDir(r)}async exists(e){const r=i(e);return this.#e.exists(r)}async clear(e){const r=e?i(e):void 0;return this.#e.clear(r)}async remove(e,r){const t=i(e);return this.#e.remove(t,r)}async unlink(e){return this.remove(e)}async rm(e,r){return this.remove(e,r)}async rmdir(e){return this.remove(e)}async readdir(e,r){return this.readDir(e)}async lstat(e){return this.stat(e)}async chmod(e,r){return Promise.resolve()}async realpath(e){const r=i(e);return this.#e.realpath(r)}async rename(e,r,t){const n=i(e),s=i(r);return this.#e.rename(n,s,t)}async copy(e,r,t){const n=i(e),s=i(r);return this.#e.copy(n,s,t)}async open(e,r){const t=i(e);return this.#e.open(t,r)}async close(e){return this.#e.close(e)}async read(e,r,t,n,s){const{bytesRead:a,buffer:u}=await this.#e.read(e,new Uint8Array(n),0,n,s);return a>0&&r.set(u.subarray(0,a),t),{bytesRead:a,buffer:r}}async write(e,r,t,n,s,a){return this.#e.write(e,r,t,n,s,a)}async fstat(e){return this.#e.fstat(e)}async ftruncate(e,r){return this.#e.ftruncate(e,r)}async fsync(e){return this.#e.fsync(e)}async readBlob(e){return this.#e.readBlob(i(e))}async importFiles(e,r){const t=[...e].map(([s,a])=>[i(s),a]),n=r?.onProgress?h.proxy(s=>r.onProgress(s)):void 0;return this.#e.importFiles(t,n)}async createIndex(e){l(),await this.importFiles(e)}async readText(e,r="utf-8"){const t=i(e),n=await this.#e.readFile(t);return o.decodeBuffer(n,r)}async writeText(e,r,t="utf-8"){const n=i(e),s=o.encodeString(r,t);return this.#e.writeFile(n,s)}async appendText(e,r,t="utf-8"){const n=i(e),s=o.encodeString(r,t);return this.#e.appendFile(n,s)}dispose(){this.#r()}}exports.OPFSFacade=y;
2
- //# sourceMappingURL=OPFSFacade-hrNXCn6w.cjs.map
1
+ "use strict";const h=require("comlink"),o=require("./BaseOPFS-Bu7FZtCb.cjs");function i(c){return c instanceof URL?c.pathname:c}let d=!1;function l(){d||(d=!0,console.warn("[opfs-worker] createIndex() is deprecated; use importFiles() instead"))}class y{#e;#r;backend;worker;promises=this;constructor(e){this.#e=e.fs,this.backend=e.fs,this.worker=e.worker,this.#r=e.dispose}watch(e,r){const t=i(e);return this.#e.watch(t,r),()=>this.unwatch(t)}unwatch(e){const r=i(e);this.#e.unwatch(r)}async setOptions(e){return this.#e.setOptions(e)}async index(){return this.#e.index()}async readFile(e,r){const t=i(e);let n;typeof r=="string"?n=r:r&&typeof r=="object"&&(n=r.encoding);const s=await this.#e.readFile(t);return n||(n=o.isBinaryFileExtension(t)?"binary":"utf-8"),n==="binary"?s:o.decodeBuffer(s,n)}async#t(e,r,t){return r instanceof Blob?new Uint8Array(await r.arrayBuffer()):(t||(t=typeof r!="string"||o.isBinaryFileExtension(e)?"binary":"utf-8"),typeof r=="string"?o.encodeString(r,t):r instanceof Uint8Array?r:new Uint8Array(r))}async writeFile(e,r,t){const n=i(e);let s;typeof t=="string"?s=t:t&&typeof t=="object"&&(s=t.encoding);const a=await this.#t(n,r,s);return this.#e.writeFile(n,a)}async appendFile(e,r,t){const n=i(e),s=await this.#t(n,r,t);return this.#e.appendFile(n,s)}async importStream(e,r,t){const n=i(e),s=r instanceof Blob?r.stream():r,a=h.transfer(s,[s]),u=t?.onProgress?h.proxy(f=>t.onProgress(f)):void 0;return this.#e.writeStream(n,a,u)}async mkdir(e,r){const t=i(e);let n;return typeof r=="number"?n={recursive:!1}:n=r,this.#e.mkdir(t,n)}async stat(e){const r=i(e);return this.#e.stat(r)}async readDir(e){const r=i(e);return this.#e.readDir(r)}async exists(e){const r=i(e);return this.#e.exists(r)}async clear(e){const r=e?i(e):void 0;return this.#e.clear(r)}async remove(e,r){const t=i(e);return this.#e.remove(t,r)}async unlink(e){return this.remove(e)}async rm(e,r){return this.remove(e,r)}async rmdir(e){return this.remove(e)}async readdir(e,r){return this.readDir(e)}async lstat(e){return this.stat(e)}async chmod(e,r){return Promise.resolve()}async realpath(e){const r=i(e);return this.#e.realpath(r)}async rename(e,r,t){const n=i(e),s=i(r);return this.#e.rename(n,s,t)}async copy(e,r,t){const n=i(e),s=i(r);return this.#e.copy(n,s,t)}async open(e,r){const t=i(e);return this.#e.open(t,r)}async close(e){return this.#e.close(e)}async read(e,r,t,n,s){const{bytesRead:a,buffer:u}=await this.#e.read(e,new Uint8Array(n),0,n,s);return a>0&&r.set(u.subarray(0,a),t),{bytesRead:a,buffer:r}}async write(e,r,t,n,s,a){return this.#e.write(e,r,t,n,s,a)}async fstat(e){return this.#e.fstat(e)}async ftruncate(e,r){return this.#e.ftruncate(e,r)}async fsync(e){return this.#e.fsync(e)}async readBlob(e){return this.#e.readBlob(i(e))}async importFiles(e,r){const t=[...e].map(([s,a])=>[i(s),a]),n=r?.onProgress?h.proxy(s=>r.onProgress(s)):void 0;return this.#e.importFiles(t,n)}async createIndex(e){l(),await this.importFiles(e)}async readText(e,r="utf-8"){const t=i(e),n=await this.#e.readFile(t);return o.decodeBuffer(n,r)}async writeText(e,r,t="utf-8"){const n=i(e),s=o.encodeString(r,t);return this.#e.writeFile(n,s)}async appendText(e,r,t="utf-8"){const n=i(e),s=o.encodeString(r,t);return this.#e.appendFile(n,s)}dispose(){this.#r()}}exports.OPFSFacade=y;
2
+ //# sourceMappingURL=OPFSFacade-BJv2yuWU.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"OPFSFacade-hrNXCn6w.cjs","sources":["../src/facade/OPFSFacade.ts"],"sourcesContent":["import { proxy, transfer } from 'comlink';\n\nimport { decodeBuffer, encodeString, isBinaryFileExtension } from '../utils/encoder';\n\nimport type {\n BinaryEncoding,\n DirentData,\n Encoding,\n FileOpenOptions,\n FileStat,\n ImportFileData,\n ImportFilesProgress,\n ImportFilesResult,\n OPFSApi,\n OPFSOptions,\n PathLike,\n RenameOptions,\n StringEncoding,\n WatchOptions\n} from '../types';\n\n/**\n * Utility function to convert a PathLike to a string path\n * If it's a URI, extracts the pathname; otherwise returns the string as-is\n */\nfunction normalizePath(path: PathLike): string {\n if (path instanceof URL) {\n return path.pathname;\n }\n\n return path;\n}\n\nlet createIndexWarned = false;\n\nfunction warnCreateIndexDeprecated(): void {\n if (createIndexWarned) {\n return;\n }\n\n createIndexWarned = true;\n console.warn('[opfs-worker] createIndex() is deprecated; use importFiles() instead');\n}\n\n/** Backend the facade talks to: an fs implementation plus its cleanup. */\nexport interface OPFSBackend {\n fs: OPFSApi;\n /** Underlying Worker / SharedWorker when the backend lives off-thread */\n worker?: Worker | SharedWorker;\n dispose: () => void;\n}\n\n/**\n * Node-like facade with encoding helpers and string/binary auto-detection.\n *\n * Transport-agnostic: works over any {@link OPFSBackend} — a Comlink proxy to\n * a worker (`createOPFSDedicated`) or an in-process instance (`createOPFSAsync`).\n *\n * Escape hatch: {@link backend} is the raw bytes API; {@link worker} is the\n * browser Worker / SharedWorker when one was created (undefined for async).\n */\nexport class OPFSFacade {\n #fs: OPFSApi;\n #dispose: () => void;\n /** Raw backend (`OPFSApi`) — bytes in / bytes out, no encoding helpers */\n readonly backend: OPFSApi;\n /** Dedicated Worker or SharedWorker, if this facade was created with one */\n readonly worker: Worker | SharedWorker | undefined;\n promises: OPFSFacade = this;\n\n constructor(backend: OPFSBackend) {\n this.#fs = backend.fs;\n this.backend = backend.fs;\n this.worker = backend.worker;\n this.#dispose = backend.dispose;\n }\n\n /**\n * Start watching a file or directory for changes\n */\n watch(path: PathLike, options?: WatchOptions): () => void {\n const normalizedPath = normalizePath(path);\n\n void this.#fs.watch(normalizedPath, options);\n\n return () => this.unwatch(normalizedPath);\n }\n\n /**\n * Stop watching a previously watched path\n */\n unwatch(path: PathLike) {\n const normalizedPath = normalizePath(path);\n\n void this.#fs.unwatch(normalizedPath);\n }\n\n /**\n * Update configuration options\n */\n async setOptions(options: OPFSOptions) {\n return this.#fs.setOptions(options);\n }\n\n /**\n * Get a complete index of all files and directories in the file system\n */\n async index(): Promise<Map<string, FileStat>> {\n return this.#fs.index();\n }\n\n /**\n * Read a file from the file system\n */\n // Overload for explicit string encoding - returns string\n async readFile(path: PathLike, encoding: StringEncoding): Promise<string>;\n // Overload for explicit binary encoding - returns Uint8Array\n async readFile(path: PathLike, encoding: BinaryEncoding): Promise<Uint8Array>;\n // Overload for options object with string encoding - returns string\n async readFile(path: PathLike, options: { encoding: StringEncoding }): Promise<string>;\n // Overload for options object with binary encoding - returns Uint8Array\n async readFile(path: PathLike, options: { encoding: BinaryEncoding }): Promise<Uint8Array>;\n // Overload for no encoding (auto-detected) - returns string | Uint8Array based on file extension\n async readFile(path: PathLike): Promise<string | Uint8Array>;\n // Implementation\n async readFile(\n path: PathLike,\n optionsOrEncoding?: Encoding | { encoding?: Encoding }\n ): Promise<string | Uint8Array> {\n const normalizedPath = normalizePath(path);\n\n // Handle both options object and direct encoding parameter for backward compatibility\n let encoding: Encoding | undefined;\n\n if (typeof optionsOrEncoding === 'string') {\n encoding = optionsOrEncoding;\n }\n else if (optionsOrEncoding && typeof optionsOrEncoding === 'object') {\n encoding = optionsOrEncoding.encoding;\n }\n\n // Same-path reads are serialized by the worker's exclusive path lock\n const buffer = await this.#fs.readFile(normalizedPath);\n\n // If no encoding specified, auto-detect based on file extension\n if (!encoding) {\n encoding = isBinaryFileExtension(normalizedPath) ? 'binary' : 'utf-8';\n }\n\n return (encoding === 'binary') ? buffer : decodeBuffer(buffer, encoding);\n }\n\n /**\n * Normalize writable data into a Uint8Array.\n *\n * Accepts strings (encoded via `encoding`, auto-detected from the file\n * extension when omitted), raw binary (`Uint8Array` / `ArrayBuffer`), and\n * `Blob`/`File` sources (read via `arrayBuffer()`).\n */\n async #toBuffer(\n path: string,\n data: string | Uint8Array | ArrayBuffer | Blob,\n encoding?: Encoding\n ): Promise<Uint8Array> {\n if (data instanceof Blob) {\n return new Uint8Array(await data.arrayBuffer());\n }\n\n // If no encoding specified, auto-detect based on file extension\n if (!encoding) {\n encoding = (typeof data !== 'string' || isBinaryFileExtension(path)) ? 'binary' : 'utf-8';\n }\n\n if (typeof data === 'string') {\n return encodeString(data, encoding);\n }\n\n return data instanceof Uint8Array ? data : new Uint8Array(data);\n }\n\n /**\n * Write data to a file\n */\n async writeFile(\n path: PathLike,\n data: string | Uint8Array | ArrayBuffer | Blob,\n options?: { encoding?: Encoding } | Encoding\n ): Promise<void> {\n const normalizedPath = normalizePath(path);\n\n let encoding: Encoding | undefined;\n\n if (typeof options === 'string') {\n encoding = options;\n }\n else if (options && typeof options === 'object') {\n encoding = options.encoding;\n }\n\n const buffer = await this.#toBuffer(normalizedPath, data, encoding);\n\n return this.#fs.writeFile(normalizedPath, buffer);\n }\n\n /**\n * Append data to a file\n */\n async appendFile(\n path: PathLike,\n data: string | Uint8Array | ArrayBuffer | Blob,\n encoding?: Encoding\n ): Promise<void> {\n const normalizedPath = normalizePath(path);\n\n const buffer = await this.#toBuffer(normalizedPath, data, encoding);\n\n return this.#fs.appendFile(normalizedPath, buffer);\n }\n\n /**\n * Create or overwrite a file from a byte stream without buffering the\n * complete source in memory.\n *\n * Returns the total number of bytes written.\n */\n async importStream(\n path: PathLike,\n source: ReadableStream<Uint8Array> | Blob,\n options?: { onProgress?: (bytesWritten: number) => void }\n ): Promise<number> {\n const normalizedPath = normalizePath(path);\n const stream = source instanceof Blob ? source.stream() : source;\n const transferredStream = transfer(stream, [stream]) as unknown as ReadableStream<Uint8Array>;\n const onProgress = options?.onProgress\n ? proxy((bytesWritten: number) => options.onProgress!(bytesWritten))\n : undefined;\n\n return this.#fs.writeStream(normalizedPath, transferredStream, onProgress);\n }\n\n /**\n * Create a directory\n */\n async mkdir(path: PathLike, mode?: number | { recursive?: boolean }): Promise<void> {\n const normalizedPath = normalizePath(path);\n\n let options: { recursive?: boolean } | undefined;\n\n // OPFS doesn't support file modes, so we ignore the mode parameter\n if (typeof mode === 'number') {\n options = { recursive: false };\n }\n else {\n options = mode;\n }\n\n return this.#fs.mkdir(normalizedPath, options);\n }\n\n /**\n * Get file or directory statistics\n */\n async stat(path: PathLike): Promise<FileStat> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.stat(normalizedPath);\n }\n\n /**\n * Read a directory's contents\n */\n async readDir(path: PathLike): Promise<DirentData[]> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.readDir(normalizedPath);\n }\n\n /**\n * Check if a file or directory exists\n */\n async exists(path: PathLike): Promise<boolean> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.exists(normalizedPath);\n }\n\n /**\n * Clear all contents of a directory without removing the directory itself\n */\n async clear(path?: PathLike): Promise<void> {\n const normalizedPath = path ? normalizePath(path) : undefined;\n\n return this.#fs.clear(normalizedPath);\n }\n\n /**\n * Remove files and directories\n */\n async remove(path: PathLike, options?: { recursive?: boolean; force?: boolean }): Promise<void> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.remove(normalizedPath, options);\n }\n\n /**\n * Alias for remove() for NodeJS like API compatibility\n */\n async unlink(path: PathLike): Promise<void> {\n return this.remove(path);\n }\n\n /**\n * Alias for remove() for NodeJS like API compatibility\n */\n async rm(path: PathLike, options?: { recursive?: boolean; force?: boolean }): Promise<void> {\n return this.remove(path, options);\n }\n\n /**\n * Alias for remove() for NodeJS like API compatibility\n */\n async rmdir(path: PathLike): Promise<void> {\n return this.remove(path);\n }\n\n /**\n * Alias for readDir() for NodeJS like API compatibility\n */\n async readdir(path: PathLike, _options?: unknown): Promise<DirentData[]> {\n return this.readDir(path);\n }\n\n /**\n * Alias for stat() for NodeJS like API compatibility\n */\n async lstat(path: PathLike): Promise<FileStat> {\n return this.stat(path);\n }\n\n /**\n * Note: OPFS doesn't support file modes, so this is a no-op and exists only for compatibility with tools like isomorphic-git\n */\n async chmod(_path: PathLike, _mode: number): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Resolve a path to an absolute path\n */\n async realpath(path: PathLike): Promise<string> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.realpath(normalizedPath);\n }\n\n /**\n * Rename a file or directory\n */\n async rename(oldPath: PathLike, newPath: PathLike, options?: RenameOptions): Promise<void> {\n const normalizedOldPath = normalizePath(oldPath);\n const normalizedNewPath = normalizePath(newPath);\n\n return this.#fs.rename(normalizedOldPath, normalizedNewPath, options);\n }\n\n /**\n * Copy files and directories\n */\n async copy(source: PathLike, destination: PathLike, options?: { recursive?: boolean; overwrite?: boolean }): Promise<void> {\n const normalizedSource = normalizePath(source);\n const normalizedDestination = normalizePath(destination);\n\n return this.#fs.copy(normalizedSource, normalizedDestination, options);\n }\n\n /**\n * Open a file and return a file descriptor\n */\n async open(path: PathLike, options?: FileOpenOptions): Promise<number> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.open(normalizedPath, options);\n }\n\n /**\n * Close a file descriptor\n */\n async close(fd: number): Promise<void> {\n return this.#fs.close(fd);\n }\n\n /**\n * Read data from a file descriptor\n * \n * This method requires special handling due to Comlink transfer requirements.\n * The buffer is transferred to the worker and back, so the original buffer\n * becomes unusable after the call.\n */\n async read(\n fd: number,\n buffer: Uint8Array,\n offset: number,\n length: number,\n position?: number | null | undefined\n ): Promise<{ bytesRead: number; buffer: Uint8Array }> {\n const { bytesRead, buffer: transferred } = await this.#fs.read(\n fd,\n // Temp buffer to preserve the original buffer\n new Uint8Array(length),\n 0,\n length,\n position\n );\n\n // Copy the data from the transferred buffer to the original buffer\n if (bytesRead > 0) {\n buffer.set(transferred.subarray(0, bytesRead), offset);\n }\n\n return { bytesRead, buffer };\n }\n\n /**\n * Write data to a file descriptor\n */\n async write(\n fd: number,\n buffer: Uint8Array,\n offset?: number,\n length?: number,\n position?: number | null | undefined,\n emitEvent?: boolean\n ): Promise<number> {\n return this.#fs.write(fd, buffer, offset, length, position, emitEvent);\n }\n\n /**\n * Get file status information by file descriptor\n */\n async fstat(fd: number): Promise<FileStat> {\n return this.#fs.fstat(fd);\n }\n\n /**\n * Truncate file to specified size\n */\n async ftruncate(fd: number, size?: number): Promise<void> {\n return this.#fs.ftruncate(fd, size);\n }\n\n /**\n * Synchronize file data to storage (fsync equivalent)\n */\n async fsync(fd: number): Promise<void> {\n return this.#fs.fsync(fd);\n }\n\n /**\n * Read a file as a lazy, disk-backed `Blob` without copying the data to memory.\n *\n * Ideal for `URL.createObjectURL()`: the browser streams `<video>` / `<audio>`\n * on demand instead of loading the whole file first.\n */\n async readBlob(path: PathLike): Promise<Blob> {\n return this.#fs.readBlob(normalizePath(path));\n }\n\n /**\n * Bulk-import files from `[path, data]` entries (strings, bytes, Blobs, or Files).\n * Each entry is streamed via {@link importStream} / `writeStream` so large\n * Blobs/Files are not fully buffered in memory.\n *\n * Accepts an array of tuples, a `Map`, or any iterable of `[path, data]` pairs.\n * Returns written paths, count, and total bytes.\n */\n async importFiles(\n entries: Iterable<[PathLike, ImportFileData]> | Map<string, ImportFileData>,\n options?: { onProgress?: (progress: ImportFilesProgress) => void }\n ): Promise<ImportFilesResult> {\n const normalizedEntries = [...entries].map(([path, data]) => [\n normalizePath(path),\n data,\n ] as [string, ImportFileData]);\n\n const onProgress = options?.onProgress\n ? proxy((progress: ImportFilesProgress) => options.onProgress!(progress))\n : undefined;\n\n return this.#fs.importFiles(normalizedEntries, onProgress);\n }\n\n /**\n * @deprecated Use {@link importFiles} instead.\n */\n async createIndex(entries: Iterable<[PathLike, ImportFileData]> | Map<string, ImportFileData>): Promise<void> {\n warnCreateIndexDeprecated();\n await this.importFiles(entries);\n }\n\n /**\n * Read a file as text with automatic encoding detection\n */\n async readText(path: PathLike, encoding: Encoding = 'utf-8'): Promise<string> {\n const normalizedPath = normalizePath(path);\n const buffer = await this.#fs.readFile(normalizedPath);\n\n return decodeBuffer(buffer, encoding);\n }\n\n /**\n * Write text to a file with specified encoding\n */\n async writeText(path: PathLike, text: string, encoding: Encoding = 'utf-8'): Promise<void> {\n const normalizedPath = normalizePath(path);\n const buffer = encodeString(text, encoding);\n\n return this.#fs.writeFile(normalizedPath, buffer);\n }\n\n /**\n * Append text to a file with specified encoding\n */\n async appendText(path: PathLike, text: string, encoding: Encoding = 'utf-8'): Promise<void> {\n const normalizedPath = normalizePath(path);\n const buffer = encodeString(text, encoding);\n\n return this.#fs.appendFile(normalizedPath, buffer);\n }\n\n /**\n * Dispose of resources, detach the backend and clean up the file system instance\n */\n dispose() {\n this.#dispose();\n }\n}\n"],"names":["normalizePath","path","createIndexWarned","warnCreateIndexDeprecated","OPFSFacade","#fs","#dispose","backend","options","normalizedPath","optionsOrEncoding","encoding","buffer","isBinaryFileExtension","decodeBuffer","#toBuffer","data","encodeString","source","stream","transferredStream","transfer","onProgress","proxy","bytesWritten","mode","_options","_path","_mode","oldPath","newPath","normalizedOldPath","normalizedNewPath","destination","normalizedSource","normalizedDestination","fd","offset","length","position","bytesRead","transferred","emitEvent","size","entries","normalizedEntries","progress","text"],"mappings":"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"}
1
+ {"version":3,"file":"OPFSFacade-BJv2yuWU.cjs","sources":["../src/facade/OPFSFacade.ts"],"sourcesContent":["import { proxy, transfer } from 'comlink';\n\nimport { decodeBuffer, encodeString, isBinaryFileExtension } from '../utils/encoder';\n\nimport type {\n BinaryEncoding,\n DirentData,\n Encoding,\n FileOpenOptions,\n FileStat,\n ImportFileData,\n ImportFilesProgress,\n ImportFilesResult,\n OPFSApi,\n OPFSOptions,\n PathLike,\n RenameOptions,\n StringEncoding,\n WatchOptions\n} from '../types';\n\n/**\n * Utility function to convert a PathLike to a string path\n * If it's a URI, extracts the pathname; otherwise returns the string as-is\n */\nfunction normalizePath(path: PathLike): string {\n if (path instanceof URL) {\n return path.pathname;\n }\n\n return path;\n}\n\nlet createIndexWarned = false;\n\nfunction warnCreateIndexDeprecated(): void {\n if (createIndexWarned) {\n return;\n }\n\n createIndexWarned = true;\n console.warn('[opfs-worker] createIndex() is deprecated; use importFiles() instead');\n}\n\n/** Backend the facade talks to: an fs implementation plus its cleanup. */\nexport interface OPFSBackend {\n fs: OPFSApi;\n /** Underlying Worker / SharedWorker when the backend lives off-thread */\n worker?: Worker | SharedWorker;\n dispose: () => void;\n}\n\n/**\n * Node-like facade with encoding helpers and string/binary auto-detection.\n *\n * Transport-agnostic: works over any {@link OPFSBackend} — a Comlink proxy to\n * a worker (`createOPFSDedicated`) or an in-process instance (`createOPFSAsync`).\n *\n * Escape hatch: {@link backend} is the raw bytes API; {@link worker} is the\n * browser Worker / SharedWorker when one was created (undefined for async).\n */\nexport class OPFSFacade {\n #fs: OPFSApi;\n #dispose: () => void;\n /** Raw backend (`OPFSApi`) — bytes in / bytes out, no encoding helpers */\n readonly backend: OPFSApi;\n /** Dedicated Worker or SharedWorker, if this facade was created with one */\n readonly worker: Worker | SharedWorker | undefined;\n promises: OPFSFacade = this;\n\n constructor(backend: OPFSBackend) {\n this.#fs = backend.fs;\n this.backend = backend.fs;\n this.worker = backend.worker;\n this.#dispose = backend.dispose;\n }\n\n /**\n * Start watching a file or directory for changes\n */\n watch(path: PathLike, options?: WatchOptions): () => void {\n const normalizedPath = normalizePath(path);\n\n void this.#fs.watch(normalizedPath, options);\n\n return () => this.unwatch(normalizedPath);\n }\n\n /**\n * Stop watching a previously watched path\n */\n unwatch(path: PathLike) {\n const normalizedPath = normalizePath(path);\n\n void this.#fs.unwatch(normalizedPath);\n }\n\n /**\n * Update configuration options\n */\n async setOptions(options: OPFSOptions) {\n return this.#fs.setOptions(options);\n }\n\n /**\n * Get a complete index of all files and directories in the file system\n */\n async index(): Promise<Map<string, FileStat>> {\n return this.#fs.index();\n }\n\n /**\n * Read a file from the file system\n */\n // Overload for explicit string encoding - returns string\n async readFile(path: PathLike, encoding: StringEncoding): Promise<string>;\n // Overload for explicit binary encoding - returns Uint8Array\n async readFile(path: PathLike, encoding: BinaryEncoding): Promise<Uint8Array>;\n // Overload for options object with string encoding - returns string\n async readFile(path: PathLike, options: { encoding: StringEncoding }): Promise<string>;\n // Overload for options object with binary encoding - returns Uint8Array\n async readFile(path: PathLike, options: { encoding: BinaryEncoding }): Promise<Uint8Array>;\n // Overload for no encoding (auto-detected) - returns string | Uint8Array based on file extension\n async readFile(path: PathLike): Promise<string | Uint8Array>;\n // Implementation\n async readFile(\n path: PathLike,\n optionsOrEncoding?: Encoding | { encoding?: Encoding }\n ): Promise<string | Uint8Array> {\n const normalizedPath = normalizePath(path);\n\n // Handle both options object and direct encoding parameter for backward compatibility\n let encoding: Encoding | undefined;\n\n if (typeof optionsOrEncoding === 'string') {\n encoding = optionsOrEncoding;\n }\n else if (optionsOrEncoding && typeof optionsOrEncoding === 'object') {\n encoding = optionsOrEncoding.encoding;\n }\n\n // Same-path reads are serialized by the worker's exclusive path lock\n const buffer = await this.#fs.readFile(normalizedPath);\n\n // If no encoding specified, auto-detect based on file extension\n if (!encoding) {\n encoding = isBinaryFileExtension(normalizedPath) ? 'binary' : 'utf-8';\n }\n\n return (encoding === 'binary') ? buffer : decodeBuffer(buffer, encoding);\n }\n\n /**\n * Normalize writable data into a Uint8Array.\n *\n * Accepts strings (encoded via `encoding`, auto-detected from the file\n * extension when omitted), raw binary (`Uint8Array` / `ArrayBuffer`), and\n * `Blob`/`File` sources (read via `arrayBuffer()`).\n */\n async #toBuffer(\n path: string,\n data: string | Uint8Array | ArrayBuffer | Blob,\n encoding?: Encoding\n ): Promise<Uint8Array> {\n if (data instanceof Blob) {\n return new Uint8Array(await data.arrayBuffer());\n }\n\n // If no encoding specified, auto-detect based on file extension\n if (!encoding) {\n encoding = (typeof data !== 'string' || isBinaryFileExtension(path)) ? 'binary' : 'utf-8';\n }\n\n if (typeof data === 'string') {\n return encodeString(data, encoding);\n }\n\n return data instanceof Uint8Array ? data : new Uint8Array(data);\n }\n\n /**\n * Write data to a file\n */\n async writeFile(\n path: PathLike,\n data: string | Uint8Array | ArrayBuffer | Blob,\n options?: { encoding?: Encoding } | Encoding\n ): Promise<void> {\n const normalizedPath = normalizePath(path);\n\n let encoding: Encoding | undefined;\n\n if (typeof options === 'string') {\n encoding = options;\n }\n else if (options && typeof options === 'object') {\n encoding = options.encoding;\n }\n\n const buffer = await this.#toBuffer(normalizedPath, data, encoding);\n\n return this.#fs.writeFile(normalizedPath, buffer);\n }\n\n /**\n * Append data to a file\n */\n async appendFile(\n path: PathLike,\n data: string | Uint8Array | ArrayBuffer | Blob,\n encoding?: Encoding\n ): Promise<void> {\n const normalizedPath = normalizePath(path);\n\n const buffer = await this.#toBuffer(normalizedPath, data, encoding);\n\n return this.#fs.appendFile(normalizedPath, buffer);\n }\n\n /**\n * Create or overwrite a file from a byte stream without buffering the\n * complete source in memory.\n *\n * Returns the total number of bytes written.\n */\n async importStream(\n path: PathLike,\n source: ReadableStream<Uint8Array> | Blob,\n options?: { onProgress?: (bytesWritten: number) => void }\n ): Promise<number> {\n const normalizedPath = normalizePath(path);\n const stream = source instanceof Blob ? source.stream() : source;\n const transferredStream = transfer(stream, [stream]) as unknown as ReadableStream<Uint8Array>;\n const onProgress = options?.onProgress\n ? proxy((bytesWritten: number) => options.onProgress!(bytesWritten))\n : undefined;\n\n return this.#fs.writeStream(normalizedPath, transferredStream, onProgress);\n }\n\n /**\n * Create a directory\n */\n async mkdir(path: PathLike, mode?: number | { recursive?: boolean }): Promise<void> {\n const normalizedPath = normalizePath(path);\n\n let options: { recursive?: boolean } | undefined;\n\n // OPFS doesn't support file modes, so we ignore the mode parameter\n if (typeof mode === 'number') {\n options = { recursive: false };\n }\n else {\n options = mode;\n }\n\n return this.#fs.mkdir(normalizedPath, options);\n }\n\n /**\n * Get file or directory statistics\n */\n async stat(path: PathLike): Promise<FileStat> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.stat(normalizedPath);\n }\n\n /**\n * Read a directory's contents\n */\n async readDir(path: PathLike): Promise<DirentData[]> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.readDir(normalizedPath);\n }\n\n /**\n * Check if a file or directory exists\n */\n async exists(path: PathLike): Promise<boolean> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.exists(normalizedPath);\n }\n\n /**\n * Clear all contents of a directory without removing the directory itself\n */\n async clear(path?: PathLike): Promise<void> {\n const normalizedPath = path ? normalizePath(path) : undefined;\n\n return this.#fs.clear(normalizedPath);\n }\n\n /**\n * Remove files and directories\n */\n async remove(path: PathLike, options?: { recursive?: boolean; force?: boolean }): Promise<void> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.remove(normalizedPath, options);\n }\n\n /**\n * Alias for remove() for NodeJS like API compatibility\n */\n async unlink(path: PathLike): Promise<void> {\n return this.remove(path);\n }\n\n /**\n * Alias for remove() for NodeJS like API compatibility\n */\n async rm(path: PathLike, options?: { recursive?: boolean; force?: boolean }): Promise<void> {\n return this.remove(path, options);\n }\n\n /**\n * Alias for remove() for NodeJS like API compatibility\n */\n async rmdir(path: PathLike): Promise<void> {\n return this.remove(path);\n }\n\n /**\n * Alias for readDir() for NodeJS like API compatibility\n */\n async readdir(path: PathLike, _options?: unknown): Promise<DirentData[]> {\n return this.readDir(path);\n }\n\n /**\n * Alias for stat() for NodeJS like API compatibility\n */\n async lstat(path: PathLike): Promise<FileStat> {\n return this.stat(path);\n }\n\n /**\n * Note: OPFS doesn't support file modes, so this is a no-op and exists only for compatibility with tools like isomorphic-git\n */\n async chmod(_path: PathLike, _mode: number): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Resolve a path to an absolute path\n */\n async realpath(path: PathLike): Promise<string> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.realpath(normalizedPath);\n }\n\n /**\n * Rename a file or directory\n */\n async rename(oldPath: PathLike, newPath: PathLike, options?: RenameOptions): Promise<void> {\n const normalizedOldPath = normalizePath(oldPath);\n const normalizedNewPath = normalizePath(newPath);\n\n return this.#fs.rename(normalizedOldPath, normalizedNewPath, options);\n }\n\n /**\n * Copy files and directories\n */\n async copy(source: PathLike, destination: PathLike, options?: { recursive?: boolean; overwrite?: boolean }): Promise<void> {\n const normalizedSource = normalizePath(source);\n const normalizedDestination = normalizePath(destination);\n\n return this.#fs.copy(normalizedSource, normalizedDestination, options);\n }\n\n /**\n * Open a file and return a file descriptor\n */\n async open(path: PathLike, options?: FileOpenOptions): Promise<number> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.open(normalizedPath, options);\n }\n\n /**\n * Close a file descriptor\n */\n async close(fd: number): Promise<void> {\n return this.#fs.close(fd);\n }\n\n /**\n * Read data from a file descriptor\n * \n * This method requires special handling due to Comlink transfer requirements.\n * The buffer is transferred to the worker and back, so the original buffer\n * becomes unusable after the call.\n */\n async read(\n fd: number,\n buffer: Uint8Array,\n offset: number,\n length: number,\n position?: number | null | undefined\n ): Promise<{ bytesRead: number; buffer: Uint8Array }> {\n const { bytesRead, buffer: transferred } = await this.#fs.read(\n fd,\n // Temp buffer to preserve the original buffer\n new Uint8Array(length),\n 0,\n length,\n position\n );\n\n // Copy the data from the transferred buffer to the original buffer\n if (bytesRead > 0) {\n buffer.set(transferred.subarray(0, bytesRead), offset);\n }\n\n return { bytesRead, buffer };\n }\n\n /**\n * Write data to a file descriptor\n */\n async write(\n fd: number,\n buffer: Uint8Array,\n offset?: number,\n length?: number,\n position?: number | null | undefined,\n emitEvent?: boolean\n ): Promise<number> {\n return this.#fs.write(fd, buffer, offset, length, position, emitEvent);\n }\n\n /**\n * Get file status information by file descriptor\n */\n async fstat(fd: number): Promise<FileStat> {\n return this.#fs.fstat(fd);\n }\n\n /**\n * Truncate file to specified size\n */\n async ftruncate(fd: number, size?: number): Promise<void> {\n return this.#fs.ftruncate(fd, size);\n }\n\n /**\n * Synchronize file data to storage (fsync equivalent)\n */\n async fsync(fd: number): Promise<void> {\n return this.#fs.fsync(fd);\n }\n\n /**\n * Read a file as a lazy, disk-backed `Blob` without copying the data to memory.\n *\n * Ideal for `URL.createObjectURL()`: the browser streams `<video>` / `<audio>`\n * on demand instead of loading the whole file first.\n */\n async readBlob(path: PathLike): Promise<Blob> {\n return this.#fs.readBlob(normalizePath(path));\n }\n\n /**\n * Bulk-import files from `[path, data]` entries (strings, bytes, Blobs, or Files).\n * Each entry is streamed via {@link importStream} / `writeStream` so large\n * Blobs/Files are not fully buffered in memory.\n *\n * Accepts an array of tuples, a `Map`, or any iterable of `[path, data]` pairs.\n * Returns written paths, count, and total bytes.\n */\n async importFiles(\n entries: Iterable<[PathLike, ImportFileData]> | Map<string, ImportFileData>,\n options?: { onProgress?: (progress: ImportFilesProgress) => void }\n ): Promise<ImportFilesResult> {\n const normalizedEntries = [...entries].map(([path, data]) => [\n normalizePath(path),\n data,\n ] as [string, ImportFileData]);\n\n const onProgress = options?.onProgress\n ? proxy((progress: ImportFilesProgress) => options.onProgress!(progress))\n : undefined;\n\n return this.#fs.importFiles(normalizedEntries, onProgress);\n }\n\n /**\n * @deprecated Use {@link importFiles} instead.\n */\n async createIndex(entries: Iterable<[PathLike, ImportFileData]> | Map<string, ImportFileData>): Promise<void> {\n warnCreateIndexDeprecated();\n await this.importFiles(entries);\n }\n\n /**\n * Read a file as text with automatic encoding detection\n */\n async readText(path: PathLike, encoding: Encoding = 'utf-8'): Promise<string> {\n const normalizedPath = normalizePath(path);\n const buffer = await this.#fs.readFile(normalizedPath);\n\n return decodeBuffer(buffer, encoding);\n }\n\n /**\n * Write text to a file with specified encoding\n */\n async writeText(path: PathLike, text: string, encoding: Encoding = 'utf-8'): Promise<void> {\n const normalizedPath = normalizePath(path);\n const buffer = encodeString(text, encoding);\n\n return this.#fs.writeFile(normalizedPath, buffer);\n }\n\n /**\n * Append text to a file with specified encoding\n */\n async appendText(path: PathLike, text: string, encoding: Encoding = 'utf-8'): Promise<void> {\n const normalizedPath = normalizePath(path);\n const buffer = encodeString(text, encoding);\n\n return this.#fs.appendFile(normalizedPath, buffer);\n }\n\n /**\n * Dispose of resources, detach the backend and clean up the file system instance\n */\n dispose() {\n this.#dispose();\n }\n}\n"],"names":["normalizePath","path","createIndexWarned","warnCreateIndexDeprecated","OPFSFacade","#fs","#dispose","backend","options","normalizedPath","optionsOrEncoding","encoding","buffer","isBinaryFileExtension","decodeBuffer","#toBuffer","data","encodeString","source","stream","transferredStream","transfer","onProgress","proxy","bytesWritten","mode","_options","_path","_mode","oldPath","newPath","normalizedOldPath","normalizedNewPath","destination","normalizedSource","normalizedDestination","fd","offset","length","position","bytesRead","transferred","emitEvent","size","entries","normalizedEntries","progress","text"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { transfer as m, proxy as u } from "comlink";
2
- import { L as f, N as l, M as h } from "./BaseOPFS-BusBkyJX.js";
2
+ import { M as f, Q as l, N as h } from "./BaseOPFS-C3NE4BKr.js";
3
3
  function a(o) {
4
4
  return o instanceof URL ? o.pathname : o;
5
5
  }
@@ -305,4 +305,4 @@ class z {
305
305
  export {
306
306
  z as O
307
307
  };
308
- //# sourceMappingURL=OPFSFacade-CEaSqTut.js.map
308
+ //# sourceMappingURL=OPFSFacade-DiogtQoq.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"OPFSFacade-CEaSqTut.js","sources":["../src/facade/OPFSFacade.ts"],"sourcesContent":["import { proxy, transfer } from 'comlink';\n\nimport { decodeBuffer, encodeString, isBinaryFileExtension } from '../utils/encoder';\n\nimport type {\n BinaryEncoding,\n DirentData,\n Encoding,\n FileOpenOptions,\n FileStat,\n ImportFileData,\n ImportFilesProgress,\n ImportFilesResult,\n OPFSApi,\n OPFSOptions,\n PathLike,\n RenameOptions,\n StringEncoding,\n WatchOptions\n} from '../types';\n\n/**\n * Utility function to convert a PathLike to a string path\n * If it's a URI, extracts the pathname; otherwise returns the string as-is\n */\nfunction normalizePath(path: PathLike): string {\n if (path instanceof URL) {\n return path.pathname;\n }\n\n return path;\n}\n\nlet createIndexWarned = false;\n\nfunction warnCreateIndexDeprecated(): void {\n if (createIndexWarned) {\n return;\n }\n\n createIndexWarned = true;\n console.warn('[opfs-worker] createIndex() is deprecated; use importFiles() instead');\n}\n\n/** Backend the facade talks to: an fs implementation plus its cleanup. */\nexport interface OPFSBackend {\n fs: OPFSApi;\n /** Underlying Worker / SharedWorker when the backend lives off-thread */\n worker?: Worker | SharedWorker;\n dispose: () => void;\n}\n\n/**\n * Node-like facade with encoding helpers and string/binary auto-detection.\n *\n * Transport-agnostic: works over any {@link OPFSBackend} — a Comlink proxy to\n * a worker (`createOPFSDedicated`) or an in-process instance (`createOPFSAsync`).\n *\n * Escape hatch: {@link backend} is the raw bytes API; {@link worker} is the\n * browser Worker / SharedWorker when one was created (undefined for async).\n */\nexport class OPFSFacade {\n #fs: OPFSApi;\n #dispose: () => void;\n /** Raw backend (`OPFSApi`) — bytes in / bytes out, no encoding helpers */\n readonly backend: OPFSApi;\n /** Dedicated Worker or SharedWorker, if this facade was created with one */\n readonly worker: Worker | SharedWorker | undefined;\n promises: OPFSFacade = this;\n\n constructor(backend: OPFSBackend) {\n this.#fs = backend.fs;\n this.backend = backend.fs;\n this.worker = backend.worker;\n this.#dispose = backend.dispose;\n }\n\n /**\n * Start watching a file or directory for changes\n */\n watch(path: PathLike, options?: WatchOptions): () => void {\n const normalizedPath = normalizePath(path);\n\n void this.#fs.watch(normalizedPath, options);\n\n return () => this.unwatch(normalizedPath);\n }\n\n /**\n * Stop watching a previously watched path\n */\n unwatch(path: PathLike) {\n const normalizedPath = normalizePath(path);\n\n void this.#fs.unwatch(normalizedPath);\n }\n\n /**\n * Update configuration options\n */\n async setOptions(options: OPFSOptions) {\n return this.#fs.setOptions(options);\n }\n\n /**\n * Get a complete index of all files and directories in the file system\n */\n async index(): Promise<Map<string, FileStat>> {\n return this.#fs.index();\n }\n\n /**\n * Read a file from the file system\n */\n // Overload for explicit string encoding - returns string\n async readFile(path: PathLike, encoding: StringEncoding): Promise<string>;\n // Overload for explicit binary encoding - returns Uint8Array\n async readFile(path: PathLike, encoding: BinaryEncoding): Promise<Uint8Array>;\n // Overload for options object with string encoding - returns string\n async readFile(path: PathLike, options: { encoding: StringEncoding }): Promise<string>;\n // Overload for options object with binary encoding - returns Uint8Array\n async readFile(path: PathLike, options: { encoding: BinaryEncoding }): Promise<Uint8Array>;\n // Overload for no encoding (auto-detected) - returns string | Uint8Array based on file extension\n async readFile(path: PathLike): Promise<string | Uint8Array>;\n // Implementation\n async readFile(\n path: PathLike,\n optionsOrEncoding?: Encoding | { encoding?: Encoding }\n ): Promise<string | Uint8Array> {\n const normalizedPath = normalizePath(path);\n\n // Handle both options object and direct encoding parameter for backward compatibility\n let encoding: Encoding | undefined;\n\n if (typeof optionsOrEncoding === 'string') {\n encoding = optionsOrEncoding;\n }\n else if (optionsOrEncoding && typeof optionsOrEncoding === 'object') {\n encoding = optionsOrEncoding.encoding;\n }\n\n // Same-path reads are serialized by the worker's exclusive path lock\n const buffer = await this.#fs.readFile(normalizedPath);\n\n // If no encoding specified, auto-detect based on file extension\n if (!encoding) {\n encoding = isBinaryFileExtension(normalizedPath) ? 'binary' : 'utf-8';\n }\n\n return (encoding === 'binary') ? buffer : decodeBuffer(buffer, encoding);\n }\n\n /**\n * Normalize writable data into a Uint8Array.\n *\n * Accepts strings (encoded via `encoding`, auto-detected from the file\n * extension when omitted), raw binary (`Uint8Array` / `ArrayBuffer`), and\n * `Blob`/`File` sources (read via `arrayBuffer()`).\n */\n async #toBuffer(\n path: string,\n data: string | Uint8Array | ArrayBuffer | Blob,\n encoding?: Encoding\n ): Promise<Uint8Array> {\n if (data instanceof Blob) {\n return new Uint8Array(await data.arrayBuffer());\n }\n\n // If no encoding specified, auto-detect based on file extension\n if (!encoding) {\n encoding = (typeof data !== 'string' || isBinaryFileExtension(path)) ? 'binary' : 'utf-8';\n }\n\n if (typeof data === 'string') {\n return encodeString(data, encoding);\n }\n\n return data instanceof Uint8Array ? data : new Uint8Array(data);\n }\n\n /**\n * Write data to a file\n */\n async writeFile(\n path: PathLike,\n data: string | Uint8Array | ArrayBuffer | Blob,\n options?: { encoding?: Encoding } | Encoding\n ): Promise<void> {\n const normalizedPath = normalizePath(path);\n\n let encoding: Encoding | undefined;\n\n if (typeof options === 'string') {\n encoding = options;\n }\n else if (options && typeof options === 'object') {\n encoding = options.encoding;\n }\n\n const buffer = await this.#toBuffer(normalizedPath, data, encoding);\n\n return this.#fs.writeFile(normalizedPath, buffer);\n }\n\n /**\n * Append data to a file\n */\n async appendFile(\n path: PathLike,\n data: string | Uint8Array | ArrayBuffer | Blob,\n encoding?: Encoding\n ): Promise<void> {\n const normalizedPath = normalizePath(path);\n\n const buffer = await this.#toBuffer(normalizedPath, data, encoding);\n\n return this.#fs.appendFile(normalizedPath, buffer);\n }\n\n /**\n * Create or overwrite a file from a byte stream without buffering the\n * complete source in memory.\n *\n * Returns the total number of bytes written.\n */\n async importStream(\n path: PathLike,\n source: ReadableStream<Uint8Array> | Blob,\n options?: { onProgress?: (bytesWritten: number) => void }\n ): Promise<number> {\n const normalizedPath = normalizePath(path);\n const stream = source instanceof Blob ? source.stream() : source;\n const transferredStream = transfer(stream, [stream]) as unknown as ReadableStream<Uint8Array>;\n const onProgress = options?.onProgress\n ? proxy((bytesWritten: number) => options.onProgress!(bytesWritten))\n : undefined;\n\n return this.#fs.writeStream(normalizedPath, transferredStream, onProgress);\n }\n\n /**\n * Create a directory\n */\n async mkdir(path: PathLike, mode?: number | { recursive?: boolean }): Promise<void> {\n const normalizedPath = normalizePath(path);\n\n let options: { recursive?: boolean } | undefined;\n\n // OPFS doesn't support file modes, so we ignore the mode parameter\n if (typeof mode === 'number') {\n options = { recursive: false };\n }\n else {\n options = mode;\n }\n\n return this.#fs.mkdir(normalizedPath, options);\n }\n\n /**\n * Get file or directory statistics\n */\n async stat(path: PathLike): Promise<FileStat> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.stat(normalizedPath);\n }\n\n /**\n * Read a directory's contents\n */\n async readDir(path: PathLike): Promise<DirentData[]> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.readDir(normalizedPath);\n }\n\n /**\n * Check if a file or directory exists\n */\n async exists(path: PathLike): Promise<boolean> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.exists(normalizedPath);\n }\n\n /**\n * Clear all contents of a directory without removing the directory itself\n */\n async clear(path?: PathLike): Promise<void> {\n const normalizedPath = path ? normalizePath(path) : undefined;\n\n return this.#fs.clear(normalizedPath);\n }\n\n /**\n * Remove files and directories\n */\n async remove(path: PathLike, options?: { recursive?: boolean; force?: boolean }): Promise<void> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.remove(normalizedPath, options);\n }\n\n /**\n * Alias for remove() for NodeJS like API compatibility\n */\n async unlink(path: PathLike): Promise<void> {\n return this.remove(path);\n }\n\n /**\n * Alias for remove() for NodeJS like API compatibility\n */\n async rm(path: PathLike, options?: { recursive?: boolean; force?: boolean }): Promise<void> {\n return this.remove(path, options);\n }\n\n /**\n * Alias for remove() for NodeJS like API compatibility\n */\n async rmdir(path: PathLike): Promise<void> {\n return this.remove(path);\n }\n\n /**\n * Alias for readDir() for NodeJS like API compatibility\n */\n async readdir(path: PathLike, _options?: unknown): Promise<DirentData[]> {\n return this.readDir(path);\n }\n\n /**\n * Alias for stat() for NodeJS like API compatibility\n */\n async lstat(path: PathLike): Promise<FileStat> {\n return this.stat(path);\n }\n\n /**\n * Note: OPFS doesn't support file modes, so this is a no-op and exists only for compatibility with tools like isomorphic-git\n */\n async chmod(_path: PathLike, _mode: number): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Resolve a path to an absolute path\n */\n async realpath(path: PathLike): Promise<string> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.realpath(normalizedPath);\n }\n\n /**\n * Rename a file or directory\n */\n async rename(oldPath: PathLike, newPath: PathLike, options?: RenameOptions): Promise<void> {\n const normalizedOldPath = normalizePath(oldPath);\n const normalizedNewPath = normalizePath(newPath);\n\n return this.#fs.rename(normalizedOldPath, normalizedNewPath, options);\n }\n\n /**\n * Copy files and directories\n */\n async copy(source: PathLike, destination: PathLike, options?: { recursive?: boolean; overwrite?: boolean }): Promise<void> {\n const normalizedSource = normalizePath(source);\n const normalizedDestination = normalizePath(destination);\n\n return this.#fs.copy(normalizedSource, normalizedDestination, options);\n }\n\n /**\n * Open a file and return a file descriptor\n */\n async open(path: PathLike, options?: FileOpenOptions): Promise<number> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.open(normalizedPath, options);\n }\n\n /**\n * Close a file descriptor\n */\n async close(fd: number): Promise<void> {\n return this.#fs.close(fd);\n }\n\n /**\n * Read data from a file descriptor\n * \n * This method requires special handling due to Comlink transfer requirements.\n * The buffer is transferred to the worker and back, so the original buffer\n * becomes unusable after the call.\n */\n async read(\n fd: number,\n buffer: Uint8Array,\n offset: number,\n length: number,\n position?: number | null | undefined\n ): Promise<{ bytesRead: number; buffer: Uint8Array }> {\n const { bytesRead, buffer: transferred } = await this.#fs.read(\n fd,\n // Temp buffer to preserve the original buffer\n new Uint8Array(length),\n 0,\n length,\n position\n );\n\n // Copy the data from the transferred buffer to the original buffer\n if (bytesRead > 0) {\n buffer.set(transferred.subarray(0, bytesRead), offset);\n }\n\n return { bytesRead, buffer };\n }\n\n /**\n * Write data to a file descriptor\n */\n async write(\n fd: number,\n buffer: Uint8Array,\n offset?: number,\n length?: number,\n position?: number | null | undefined,\n emitEvent?: boolean\n ): Promise<number> {\n return this.#fs.write(fd, buffer, offset, length, position, emitEvent);\n }\n\n /**\n * Get file status information by file descriptor\n */\n async fstat(fd: number): Promise<FileStat> {\n return this.#fs.fstat(fd);\n }\n\n /**\n * Truncate file to specified size\n */\n async ftruncate(fd: number, size?: number): Promise<void> {\n return this.#fs.ftruncate(fd, size);\n }\n\n /**\n * Synchronize file data to storage (fsync equivalent)\n */\n async fsync(fd: number): Promise<void> {\n return this.#fs.fsync(fd);\n }\n\n /**\n * Read a file as a lazy, disk-backed `Blob` without copying the data to memory.\n *\n * Ideal for `URL.createObjectURL()`: the browser streams `<video>` / `<audio>`\n * on demand instead of loading the whole file first.\n */\n async readBlob(path: PathLike): Promise<Blob> {\n return this.#fs.readBlob(normalizePath(path));\n }\n\n /**\n * Bulk-import files from `[path, data]` entries (strings, bytes, Blobs, or Files).\n * Each entry is streamed via {@link importStream} / `writeStream` so large\n * Blobs/Files are not fully buffered in memory.\n *\n * Accepts an array of tuples, a `Map`, or any iterable of `[path, data]` pairs.\n * Returns written paths, count, and total bytes.\n */\n async importFiles(\n entries: Iterable<[PathLike, ImportFileData]> | Map<string, ImportFileData>,\n options?: { onProgress?: (progress: ImportFilesProgress) => void }\n ): Promise<ImportFilesResult> {\n const normalizedEntries = [...entries].map(([path, data]) => [\n normalizePath(path),\n data,\n ] as [string, ImportFileData]);\n\n const onProgress = options?.onProgress\n ? proxy((progress: ImportFilesProgress) => options.onProgress!(progress))\n : undefined;\n\n return this.#fs.importFiles(normalizedEntries, onProgress);\n }\n\n /**\n * @deprecated Use {@link importFiles} instead.\n */\n async createIndex(entries: Iterable<[PathLike, ImportFileData]> | Map<string, ImportFileData>): Promise<void> {\n warnCreateIndexDeprecated();\n await this.importFiles(entries);\n }\n\n /**\n * Read a file as text with automatic encoding detection\n */\n async readText(path: PathLike, encoding: Encoding = 'utf-8'): Promise<string> {\n const normalizedPath = normalizePath(path);\n const buffer = await this.#fs.readFile(normalizedPath);\n\n return decodeBuffer(buffer, encoding);\n }\n\n /**\n * Write text to a file with specified encoding\n */\n async writeText(path: PathLike, text: string, encoding: Encoding = 'utf-8'): Promise<void> {\n const normalizedPath = normalizePath(path);\n const buffer = encodeString(text, encoding);\n\n return this.#fs.writeFile(normalizedPath, buffer);\n }\n\n /**\n * Append text to a file with specified encoding\n */\n async appendText(path: PathLike, text: string, encoding: Encoding = 'utf-8'): Promise<void> {\n const normalizedPath = normalizePath(path);\n const buffer = encodeString(text, encoding);\n\n return this.#fs.appendFile(normalizedPath, buffer);\n }\n\n /**\n * Dispose of resources, detach the backend and clean up the file system instance\n */\n dispose() {\n this.#dispose();\n }\n}\n"],"names":["normalizePath","path","createIndexWarned","warnCreateIndexDeprecated","OPFSFacade","#fs","#dispose","backend","options","normalizedPath","optionsOrEncoding","encoding","buffer","isBinaryFileExtension","decodeBuffer","#toBuffer","data","encodeString","source","stream","transferredStream","transfer","onProgress","proxy","bytesWritten","mode","_options","_path","_mode","oldPath","newPath","normalizedOldPath","normalizedNewPath","destination","normalizedSource","normalizedDestination","fd","offset","length","position","bytesRead","transferred","emitEvent","size","entries","normalizedEntries","progress","text"],"mappings":";;AAyBA,SAASA,EAAcC,GAAwB;AAC3C,SAAIA,aAAgB,MACTA,EAAK,WAGTA;AACX;AAEA,IAAIC,IAAoB;AAExB,SAASC,IAAkC;AACvC,EAAID,MAIJA,IAAoB,IACpB,QAAQ,KAAK,sEAAsE;AACvF;AAmBO,MAAME,EAAW;AAAA,EACpBC;AAAA,EACAC;AAAA;AAAA,EAES;AAAA;AAAA,EAEA;AAAA,EACT,WAAuB;AAAA,EAEvB,YAAYC,GAAsB;AAC9B,SAAKF,KAAME,EAAQ,IACnB,KAAK,UAAUA,EAAQ,IACvB,KAAK,SAASA,EAAQ,QACtB,KAAKD,KAAWC,EAAQ;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAMN,GAAgBO,GAAoC;AACtD,UAAMC,IAAiBT,EAAcC,CAAI;AAEzC,WAAK,KAAKI,GAAI,MAAMI,GAAgBD,CAAO,GAEpC,MAAM,KAAK,QAAQC,CAAc;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQR,GAAgB;AACpB,UAAMQ,IAAiBT,EAAcC,CAAI;AAEzC,IAAK,KAAKI,GAAI,QAAQI,CAAc;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAWD,GAAsB;AACnC,WAAO,KAAKH,GAAI,WAAWG,CAAO;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAwC;AAC1C,WAAO,KAAKH,GAAI,MAAA;AAAA,EACpB;AAAA;AAAA,EAgBA,MAAM,SACFJ,GACAS,GAC4B;AAC5B,UAAMD,IAAiBT,EAAcC,CAAI;AAGzC,QAAIU;AAEJ,IAAI,OAAOD,KAAsB,WAC7BC,IAAWD,IAENA,KAAqB,OAAOA,KAAsB,aACvDC,IAAWD,EAAkB;AAIjC,UAAME,IAAS,MAAM,KAAKP,GAAI,SAASI,CAAc;AAGrD,WAAKE,MACDA,IAAWE,EAAsBJ,CAAc,IAAI,WAAW,UAG1DE,MAAa,WAAYC,IAASE,EAAaF,GAAQD,CAAQ;AAAA,EAC3E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAMI,GACFd,GACAe,GACAL,GACmB;AACnB,WAAIK,aAAgB,OACT,IAAI,WAAW,MAAMA,EAAK,aAAa,KAI7CL,MACDA,IAAY,OAAOK,KAAS,YAAYH,EAAsBZ,CAAI,IAAK,WAAW,UAGlF,OAAOe,KAAS,WACTC,EAAaD,GAAML,CAAQ,IAG/BK,aAAgB,aAAaA,IAAO,IAAI,WAAWA,CAAI;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UACFf,GACAe,GACAR,GACa;AACb,UAAMC,IAAiBT,EAAcC,CAAI;AAEzC,QAAIU;AAEJ,IAAI,OAAOH,KAAY,WACnBG,IAAWH,IAENA,KAAW,OAAOA,KAAY,aACnCG,IAAWH,EAAQ;AAGvB,UAAMI,IAAS,MAAM,KAAKG,GAAUN,GAAgBO,GAAML,CAAQ;AAElE,WAAO,KAAKN,GAAI,UAAUI,GAAgBG,CAAM;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WACFX,GACAe,GACAL,GACa;AACb,UAAMF,IAAiBT,EAAcC,CAAI,GAEnCW,IAAS,MAAM,KAAKG,GAAUN,GAAgBO,GAAML,CAAQ;AAElE,WAAO,KAAKN,GAAI,WAAWI,GAAgBG,CAAM;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aACFX,GACAiB,GACAV,GACe;AACf,UAAMC,IAAiBT,EAAcC,CAAI,GACnCkB,IAASD,aAAkB,OAAOA,EAAO,WAAWA,GACpDE,IAAoBC,EAASF,GAAQ,CAACA,CAAM,CAAC,GAC7CG,IAAad,GAAS,aACtBe,EAAM,CAACC,MAAyBhB,EAAQ,WAAYgB,CAAY,CAAC,IACjE;AAEN,WAAO,KAAKnB,GAAI,YAAYI,GAAgBW,GAAmBE,CAAU;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAMrB,GAAgBwB,GAAwD;AAChF,UAAMhB,IAAiBT,EAAcC,CAAI;AAEzC,QAAIO;AAGJ,WAAI,OAAOiB,KAAS,WAChBjB,IAAU,EAAE,WAAW,GAAA,IAGvBA,IAAUiB,GAGP,KAAKpB,GAAI,MAAMI,GAAgBD,CAAO;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAKP,GAAmC;AAC1C,UAAMQ,IAAiBT,EAAcC,CAAI;AAEzC,WAAO,KAAKI,GAAI,KAAKI,CAAc;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAQR,GAAuC;AACjD,UAAMQ,IAAiBT,EAAcC,CAAI;AAEzC,WAAO,KAAKI,GAAI,QAAQI,CAAc;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAOR,GAAkC;AAC3C,UAAMQ,IAAiBT,EAAcC,CAAI;AAEzC,WAAO,KAAKI,GAAI,OAAOI,CAAc;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAMR,GAAgC;AACxC,UAAMQ,IAAiBR,IAAOD,EAAcC,CAAI,IAAI;AAEpD,WAAO,KAAKI,GAAI,MAAMI,CAAc;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAOR,GAAgBO,GAAmE;AAC5F,UAAMC,IAAiBT,EAAcC,CAAI;AAEzC,WAAO,KAAKI,GAAI,OAAOI,GAAgBD,CAAO;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAOP,GAA+B;AACxC,WAAO,KAAK,OAAOA,CAAI;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,GAAGA,GAAgBO,GAAmE;AACxF,WAAO,KAAK,OAAOP,GAAMO,CAAO;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAMP,GAA+B;AACvC,WAAO,KAAK,OAAOA,CAAI;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAQA,GAAgByB,GAA2C;AACrE,WAAO,KAAK,QAAQzB,CAAI;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAMA,GAAmC;AAC3C,WAAO,KAAK,KAAKA,CAAI;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAM0B,GAAiBC,GAA8B;AACvD,WAAO,QAAQ,QAAA;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS3B,GAAiC;AAC5C,UAAMQ,IAAiBT,EAAcC,CAAI;AAEzC,WAAO,KAAKI,GAAI,SAASI,CAAc;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAOoB,GAAmBC,GAAmBtB,GAAwC;AACvF,UAAMuB,IAAoB/B,EAAc6B,CAAO,GACzCG,IAAoBhC,EAAc8B,CAAO;AAE/C,WAAO,KAAKzB,GAAI,OAAO0B,GAAmBC,GAAmBxB,CAAO;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAKU,GAAkBe,GAAuBzB,GAAuE;AACvH,UAAM0B,IAAmBlC,EAAckB,CAAM,GACvCiB,IAAwBnC,EAAciC,CAAW;AAEvD,WAAO,KAAK5B,GAAI,KAAK6B,GAAkBC,GAAuB3B,CAAO;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAKP,GAAgBO,GAA4C;AACnE,UAAMC,IAAiBT,EAAcC,CAAI;AAEzC,WAAO,KAAKI,GAAI,KAAKI,GAAgBD,CAAO;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAM4B,GAA2B;AACnC,WAAO,KAAK/B,GAAI,MAAM+B,CAAE;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,KACFA,GACAxB,GACAyB,GACAC,GACAC,GACkD;AAClD,UAAM,EAAE,WAAAC,GAAW,QAAQC,MAAgB,MAAM,KAAKpC,GAAI;AAAA,MACtD+B;AAAA;AAAA,MAEA,IAAI,WAAWE,CAAM;AAAA,MACrB;AAAA,MACAA;AAAA,MACAC;AAAA,IAAA;AAIJ,WAAIC,IAAY,KACZ5B,EAAO,IAAI6B,EAAY,SAAS,GAAGD,CAAS,GAAGH,CAAM,GAGlD,EAAE,WAAAG,GAAW,QAAA5B,EAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MACFwB,GACAxB,GACAyB,GACAC,GACAC,GACAG,GACe;AACf,WAAO,KAAKrC,GAAI,MAAM+B,GAAIxB,GAAQyB,GAAQC,GAAQC,GAAUG,CAAS;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAMN,GAA+B;AACvC,WAAO,KAAK/B,GAAI,MAAM+B,CAAE;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAUA,GAAYO,GAA8B;AACtD,WAAO,KAAKtC,GAAI,UAAU+B,GAAIO,CAAI;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAMP,GAA2B;AACnC,WAAO,KAAK/B,GAAI,MAAM+B,CAAE;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,SAASnC,GAA+B;AAC1C,WAAO,KAAKI,GAAI,SAASL,EAAcC,CAAI,CAAC;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,YACF2C,GACApC,GAC0B;AAC1B,UAAMqC,IAAoB,CAAC,GAAGD,CAAO,EAAE,IAAI,CAAC,CAAC3C,GAAMe,CAAI,MAAM;AAAA,MACzDhB,EAAcC,CAAI;AAAA,MAClBe;AAAA,IAAA,CACyB,GAEvBM,IAAad,GAAS,aACtBe,EAAM,CAACuB,MAAkCtC,EAAQ,WAAYsC,CAAQ,CAAC,IACtE;AAEN,WAAO,KAAKzC,GAAI,YAAYwC,GAAmBvB,CAAU;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAYsB,GAA4F;AAC1G,IAAAzC,EAAA,GACA,MAAM,KAAK,YAAYyC,CAAO;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS3C,GAAgBU,IAAqB,SAA0B;AAC1E,UAAMF,IAAiBT,EAAcC,CAAI,GACnCW,IAAS,MAAM,KAAKP,GAAI,SAASI,CAAc;AAErD,WAAOK,EAAaF,GAAQD,CAAQ;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAUV,GAAgB8C,GAAcpC,IAAqB,SAAwB;AACvF,UAAMF,IAAiBT,EAAcC,CAAI,GACnCW,IAASK,EAAa8B,GAAMpC,CAAQ;AAE1C,WAAO,KAAKN,GAAI,UAAUI,GAAgBG,CAAM;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAWX,GAAgB8C,GAAcpC,IAAqB,SAAwB;AACxF,UAAMF,IAAiBT,EAAcC,CAAI,GACnCW,IAASK,EAAa8B,GAAMpC,CAAQ;AAE1C,WAAO,KAAKN,GAAI,WAAWI,GAAgBG,CAAM;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU;AACN,SAAKN,GAAA;AAAA,EACT;AACJ;"}
1
+ {"version":3,"file":"OPFSFacade-DiogtQoq.js","sources":["../src/facade/OPFSFacade.ts"],"sourcesContent":["import { proxy, transfer } from 'comlink';\n\nimport { decodeBuffer, encodeString, isBinaryFileExtension } from '../utils/encoder';\n\nimport type {\n BinaryEncoding,\n DirentData,\n Encoding,\n FileOpenOptions,\n FileStat,\n ImportFileData,\n ImportFilesProgress,\n ImportFilesResult,\n OPFSApi,\n OPFSOptions,\n PathLike,\n RenameOptions,\n StringEncoding,\n WatchOptions\n} from '../types';\n\n/**\n * Utility function to convert a PathLike to a string path\n * If it's a URI, extracts the pathname; otherwise returns the string as-is\n */\nfunction normalizePath(path: PathLike): string {\n if (path instanceof URL) {\n return path.pathname;\n }\n\n return path;\n}\n\nlet createIndexWarned = false;\n\nfunction warnCreateIndexDeprecated(): void {\n if (createIndexWarned) {\n return;\n }\n\n createIndexWarned = true;\n console.warn('[opfs-worker] createIndex() is deprecated; use importFiles() instead');\n}\n\n/** Backend the facade talks to: an fs implementation plus its cleanup. */\nexport interface OPFSBackend {\n fs: OPFSApi;\n /** Underlying Worker / SharedWorker when the backend lives off-thread */\n worker?: Worker | SharedWorker;\n dispose: () => void;\n}\n\n/**\n * Node-like facade with encoding helpers and string/binary auto-detection.\n *\n * Transport-agnostic: works over any {@link OPFSBackend} — a Comlink proxy to\n * a worker (`createOPFSDedicated`) or an in-process instance (`createOPFSAsync`).\n *\n * Escape hatch: {@link backend} is the raw bytes API; {@link worker} is the\n * browser Worker / SharedWorker when one was created (undefined for async).\n */\nexport class OPFSFacade {\n #fs: OPFSApi;\n #dispose: () => void;\n /** Raw backend (`OPFSApi`) — bytes in / bytes out, no encoding helpers */\n readonly backend: OPFSApi;\n /** Dedicated Worker or SharedWorker, if this facade was created with one */\n readonly worker: Worker | SharedWorker | undefined;\n promises: OPFSFacade = this;\n\n constructor(backend: OPFSBackend) {\n this.#fs = backend.fs;\n this.backend = backend.fs;\n this.worker = backend.worker;\n this.#dispose = backend.dispose;\n }\n\n /**\n * Start watching a file or directory for changes\n */\n watch(path: PathLike, options?: WatchOptions): () => void {\n const normalizedPath = normalizePath(path);\n\n void this.#fs.watch(normalizedPath, options);\n\n return () => this.unwatch(normalizedPath);\n }\n\n /**\n * Stop watching a previously watched path\n */\n unwatch(path: PathLike) {\n const normalizedPath = normalizePath(path);\n\n void this.#fs.unwatch(normalizedPath);\n }\n\n /**\n * Update configuration options\n */\n async setOptions(options: OPFSOptions) {\n return this.#fs.setOptions(options);\n }\n\n /**\n * Get a complete index of all files and directories in the file system\n */\n async index(): Promise<Map<string, FileStat>> {\n return this.#fs.index();\n }\n\n /**\n * Read a file from the file system\n */\n // Overload for explicit string encoding - returns string\n async readFile(path: PathLike, encoding: StringEncoding): Promise<string>;\n // Overload for explicit binary encoding - returns Uint8Array\n async readFile(path: PathLike, encoding: BinaryEncoding): Promise<Uint8Array>;\n // Overload for options object with string encoding - returns string\n async readFile(path: PathLike, options: { encoding: StringEncoding }): Promise<string>;\n // Overload for options object with binary encoding - returns Uint8Array\n async readFile(path: PathLike, options: { encoding: BinaryEncoding }): Promise<Uint8Array>;\n // Overload for no encoding (auto-detected) - returns string | Uint8Array based on file extension\n async readFile(path: PathLike): Promise<string | Uint8Array>;\n // Implementation\n async readFile(\n path: PathLike,\n optionsOrEncoding?: Encoding | { encoding?: Encoding }\n ): Promise<string | Uint8Array> {\n const normalizedPath = normalizePath(path);\n\n // Handle both options object and direct encoding parameter for backward compatibility\n let encoding: Encoding | undefined;\n\n if (typeof optionsOrEncoding === 'string') {\n encoding = optionsOrEncoding;\n }\n else if (optionsOrEncoding && typeof optionsOrEncoding === 'object') {\n encoding = optionsOrEncoding.encoding;\n }\n\n // Same-path reads are serialized by the worker's exclusive path lock\n const buffer = await this.#fs.readFile(normalizedPath);\n\n // If no encoding specified, auto-detect based on file extension\n if (!encoding) {\n encoding = isBinaryFileExtension(normalizedPath) ? 'binary' : 'utf-8';\n }\n\n return (encoding === 'binary') ? buffer : decodeBuffer(buffer, encoding);\n }\n\n /**\n * Normalize writable data into a Uint8Array.\n *\n * Accepts strings (encoded via `encoding`, auto-detected from the file\n * extension when omitted), raw binary (`Uint8Array` / `ArrayBuffer`), and\n * `Blob`/`File` sources (read via `arrayBuffer()`).\n */\n async #toBuffer(\n path: string,\n data: string | Uint8Array | ArrayBuffer | Blob,\n encoding?: Encoding\n ): Promise<Uint8Array> {\n if (data instanceof Blob) {\n return new Uint8Array(await data.arrayBuffer());\n }\n\n // If no encoding specified, auto-detect based on file extension\n if (!encoding) {\n encoding = (typeof data !== 'string' || isBinaryFileExtension(path)) ? 'binary' : 'utf-8';\n }\n\n if (typeof data === 'string') {\n return encodeString(data, encoding);\n }\n\n return data instanceof Uint8Array ? data : new Uint8Array(data);\n }\n\n /**\n * Write data to a file\n */\n async writeFile(\n path: PathLike,\n data: string | Uint8Array | ArrayBuffer | Blob,\n options?: { encoding?: Encoding } | Encoding\n ): Promise<void> {\n const normalizedPath = normalizePath(path);\n\n let encoding: Encoding | undefined;\n\n if (typeof options === 'string') {\n encoding = options;\n }\n else if (options && typeof options === 'object') {\n encoding = options.encoding;\n }\n\n const buffer = await this.#toBuffer(normalizedPath, data, encoding);\n\n return this.#fs.writeFile(normalizedPath, buffer);\n }\n\n /**\n * Append data to a file\n */\n async appendFile(\n path: PathLike,\n data: string | Uint8Array | ArrayBuffer | Blob,\n encoding?: Encoding\n ): Promise<void> {\n const normalizedPath = normalizePath(path);\n\n const buffer = await this.#toBuffer(normalizedPath, data, encoding);\n\n return this.#fs.appendFile(normalizedPath, buffer);\n }\n\n /**\n * Create or overwrite a file from a byte stream without buffering the\n * complete source in memory.\n *\n * Returns the total number of bytes written.\n */\n async importStream(\n path: PathLike,\n source: ReadableStream<Uint8Array> | Blob,\n options?: { onProgress?: (bytesWritten: number) => void }\n ): Promise<number> {\n const normalizedPath = normalizePath(path);\n const stream = source instanceof Blob ? source.stream() : source;\n const transferredStream = transfer(stream, [stream]) as unknown as ReadableStream<Uint8Array>;\n const onProgress = options?.onProgress\n ? proxy((bytesWritten: number) => options.onProgress!(bytesWritten))\n : undefined;\n\n return this.#fs.writeStream(normalizedPath, transferredStream, onProgress);\n }\n\n /**\n * Create a directory\n */\n async mkdir(path: PathLike, mode?: number | { recursive?: boolean }): Promise<void> {\n const normalizedPath = normalizePath(path);\n\n let options: { recursive?: boolean } | undefined;\n\n // OPFS doesn't support file modes, so we ignore the mode parameter\n if (typeof mode === 'number') {\n options = { recursive: false };\n }\n else {\n options = mode;\n }\n\n return this.#fs.mkdir(normalizedPath, options);\n }\n\n /**\n * Get file or directory statistics\n */\n async stat(path: PathLike): Promise<FileStat> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.stat(normalizedPath);\n }\n\n /**\n * Read a directory's contents\n */\n async readDir(path: PathLike): Promise<DirentData[]> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.readDir(normalizedPath);\n }\n\n /**\n * Check if a file or directory exists\n */\n async exists(path: PathLike): Promise<boolean> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.exists(normalizedPath);\n }\n\n /**\n * Clear all contents of a directory without removing the directory itself\n */\n async clear(path?: PathLike): Promise<void> {\n const normalizedPath = path ? normalizePath(path) : undefined;\n\n return this.#fs.clear(normalizedPath);\n }\n\n /**\n * Remove files and directories\n */\n async remove(path: PathLike, options?: { recursive?: boolean; force?: boolean }): Promise<void> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.remove(normalizedPath, options);\n }\n\n /**\n * Alias for remove() for NodeJS like API compatibility\n */\n async unlink(path: PathLike): Promise<void> {\n return this.remove(path);\n }\n\n /**\n * Alias for remove() for NodeJS like API compatibility\n */\n async rm(path: PathLike, options?: { recursive?: boolean; force?: boolean }): Promise<void> {\n return this.remove(path, options);\n }\n\n /**\n * Alias for remove() for NodeJS like API compatibility\n */\n async rmdir(path: PathLike): Promise<void> {\n return this.remove(path);\n }\n\n /**\n * Alias for readDir() for NodeJS like API compatibility\n */\n async readdir(path: PathLike, _options?: unknown): Promise<DirentData[]> {\n return this.readDir(path);\n }\n\n /**\n * Alias for stat() for NodeJS like API compatibility\n */\n async lstat(path: PathLike): Promise<FileStat> {\n return this.stat(path);\n }\n\n /**\n * Note: OPFS doesn't support file modes, so this is a no-op and exists only for compatibility with tools like isomorphic-git\n */\n async chmod(_path: PathLike, _mode: number): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Resolve a path to an absolute path\n */\n async realpath(path: PathLike): Promise<string> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.realpath(normalizedPath);\n }\n\n /**\n * Rename a file or directory\n */\n async rename(oldPath: PathLike, newPath: PathLike, options?: RenameOptions): Promise<void> {\n const normalizedOldPath = normalizePath(oldPath);\n const normalizedNewPath = normalizePath(newPath);\n\n return this.#fs.rename(normalizedOldPath, normalizedNewPath, options);\n }\n\n /**\n * Copy files and directories\n */\n async copy(source: PathLike, destination: PathLike, options?: { recursive?: boolean; overwrite?: boolean }): Promise<void> {\n const normalizedSource = normalizePath(source);\n const normalizedDestination = normalizePath(destination);\n\n return this.#fs.copy(normalizedSource, normalizedDestination, options);\n }\n\n /**\n * Open a file and return a file descriptor\n */\n async open(path: PathLike, options?: FileOpenOptions): Promise<number> {\n const normalizedPath = normalizePath(path);\n\n return this.#fs.open(normalizedPath, options);\n }\n\n /**\n * Close a file descriptor\n */\n async close(fd: number): Promise<void> {\n return this.#fs.close(fd);\n }\n\n /**\n * Read data from a file descriptor\n * \n * This method requires special handling due to Comlink transfer requirements.\n * The buffer is transferred to the worker and back, so the original buffer\n * becomes unusable after the call.\n */\n async read(\n fd: number,\n buffer: Uint8Array,\n offset: number,\n length: number,\n position?: number | null | undefined\n ): Promise<{ bytesRead: number; buffer: Uint8Array }> {\n const { bytesRead, buffer: transferred } = await this.#fs.read(\n fd,\n // Temp buffer to preserve the original buffer\n new Uint8Array(length),\n 0,\n length,\n position\n );\n\n // Copy the data from the transferred buffer to the original buffer\n if (bytesRead > 0) {\n buffer.set(transferred.subarray(0, bytesRead), offset);\n }\n\n return { bytesRead, buffer };\n }\n\n /**\n * Write data to a file descriptor\n */\n async write(\n fd: number,\n buffer: Uint8Array,\n offset?: number,\n length?: number,\n position?: number | null | undefined,\n emitEvent?: boolean\n ): Promise<number> {\n return this.#fs.write(fd, buffer, offset, length, position, emitEvent);\n }\n\n /**\n * Get file status information by file descriptor\n */\n async fstat(fd: number): Promise<FileStat> {\n return this.#fs.fstat(fd);\n }\n\n /**\n * Truncate file to specified size\n */\n async ftruncate(fd: number, size?: number): Promise<void> {\n return this.#fs.ftruncate(fd, size);\n }\n\n /**\n * Synchronize file data to storage (fsync equivalent)\n */\n async fsync(fd: number): Promise<void> {\n return this.#fs.fsync(fd);\n }\n\n /**\n * Read a file as a lazy, disk-backed `Blob` without copying the data to memory.\n *\n * Ideal for `URL.createObjectURL()`: the browser streams `<video>` / `<audio>`\n * on demand instead of loading the whole file first.\n */\n async readBlob(path: PathLike): Promise<Blob> {\n return this.#fs.readBlob(normalizePath(path));\n }\n\n /**\n * Bulk-import files from `[path, data]` entries (strings, bytes, Blobs, or Files).\n * Each entry is streamed via {@link importStream} / `writeStream` so large\n * Blobs/Files are not fully buffered in memory.\n *\n * Accepts an array of tuples, a `Map`, or any iterable of `[path, data]` pairs.\n * Returns written paths, count, and total bytes.\n */\n async importFiles(\n entries: Iterable<[PathLike, ImportFileData]> | Map<string, ImportFileData>,\n options?: { onProgress?: (progress: ImportFilesProgress) => void }\n ): Promise<ImportFilesResult> {\n const normalizedEntries = [...entries].map(([path, data]) => [\n normalizePath(path),\n data,\n ] as [string, ImportFileData]);\n\n const onProgress = options?.onProgress\n ? proxy((progress: ImportFilesProgress) => options.onProgress!(progress))\n : undefined;\n\n return this.#fs.importFiles(normalizedEntries, onProgress);\n }\n\n /**\n * @deprecated Use {@link importFiles} instead.\n */\n async createIndex(entries: Iterable<[PathLike, ImportFileData]> | Map<string, ImportFileData>): Promise<void> {\n warnCreateIndexDeprecated();\n await this.importFiles(entries);\n }\n\n /**\n * Read a file as text with automatic encoding detection\n */\n async readText(path: PathLike, encoding: Encoding = 'utf-8'): Promise<string> {\n const normalizedPath = normalizePath(path);\n const buffer = await this.#fs.readFile(normalizedPath);\n\n return decodeBuffer(buffer, encoding);\n }\n\n /**\n * Write text to a file with specified encoding\n */\n async writeText(path: PathLike, text: string, encoding: Encoding = 'utf-8'): Promise<void> {\n const normalizedPath = normalizePath(path);\n const buffer = encodeString(text, encoding);\n\n return this.#fs.writeFile(normalizedPath, buffer);\n }\n\n /**\n * Append text to a file with specified encoding\n */\n async appendText(path: PathLike, text: string, encoding: Encoding = 'utf-8'): Promise<void> {\n const normalizedPath = normalizePath(path);\n const buffer = encodeString(text, encoding);\n\n return this.#fs.appendFile(normalizedPath, buffer);\n }\n\n /**\n * Dispose of resources, detach the backend and clean up the file system instance\n */\n dispose() {\n this.#dispose();\n }\n}\n"],"names":["normalizePath","path","createIndexWarned","warnCreateIndexDeprecated","OPFSFacade","#fs","#dispose","backend","options","normalizedPath","optionsOrEncoding","encoding","buffer","isBinaryFileExtension","decodeBuffer","#toBuffer","data","encodeString","source","stream","transferredStream","transfer","onProgress","proxy","bytesWritten","mode","_options","_path","_mode","oldPath","newPath","normalizedOldPath","normalizedNewPath","destination","normalizedSource","normalizedDestination","fd","offset","length","position","bytesRead","transferred","emitEvent","size","entries","normalizedEntries","progress","text"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";const w=require("comlink"),i=require("./BaseOPFS-Bu7FZtCb.cjs");class d extends i.BaseOPFS{openHandles=new Map;openFiles=new Map;nextFd=1;constructor(e){super(e)}_getFileDescriptor(e){const t=this.openFiles.get(e);if(!t)throw new i.ValidationError("descriptor",`Invalid file descriptor: ${e}`);return t}async readFile(e){await this.mount();try{return await this.withPathLock(e,async()=>{const t=await this.open(e);try{const{size:a}=await this.fstat(t),n=new Uint8Array(a);return a>0&&await this.read(t,n,0,a,0),w.transfer(n,[n.buffer])}finally{await this.close(t)}})}catch(t){throw t instanceof i.OPFSError?t:i.mapDomError(t,{path:e,isDirectory:!1})}}async writeFile(e,t){await this.mount();const a=t instanceof Uint8Array?t:new Uint8Array(t);await this.withPathLock(e,async()=>{const n=await this.exists(e),s=await this.open(e,{create:!0,truncate:!0});try{await this.write(s,a,0,a.length,null,!1),await this.fsync(s)}finally{await this.close(s)}await this.notifyChange({path:e,type:n?i.WatchEventType.Changed:i.WatchEventType.Added,isDirectory:!1})})}async appendFile(e,t){await this.mount();const a=t instanceof Uint8Array?t:new Uint8Array(t);await this.withPathLock(e,async()=>{const n=await this.open(e,{create:!0});try{const{size:s}=await this.fstat(n);await this.write(n,a,0,a.length,s,!1),await this.fsync(n)}finally{await this.close(n)}await this.notifyChange({path:e,type:i.WatchEventType.Changed,isDirectory:!1})})}async writeStream(e,t,a){return await this.mount(),this.withPathLock(e,async()=>{const n=await this.exists(e),s=await this.open(e,{create:!0,truncate:!0}),o=t.getReader();let r=0;try{for(;;){const{done:c,value:l}=await o.read();if(c)break;let h=0;for(;h<l.byteLength;)h+=await this.write(s,l,h,l.byteLength-h,null,!1);r+=l.byteLength,await a?.(r)}await this.fsync(s)}catch(c){throw await o.cancel(c).catch(()=>{}),c}finally{o.releaseLock(),await this.close(s)}return await this.notifyChange({path:e,type:n?i.WatchEventType.Changed:i.WatchEventType.Added,isDirectory:!1}),r})}async open(e,t){await this.mount();const{create:a=!1,exclusive:n=!1,truncate:s=!1}=t||{},o=i.normalizePath(i.resolvePath(e));try{return a&&n?await this.withPathLock(o,async()=>{if(await this.exists(o))throw new i.AlreadyExistsError(o);return this._openFile(o,a,s)}):await this._openFile(o,a,s)}catch(r){if(r instanceof i.OPFSError)throw r;const c=r&&r.name==="TypeMismatchError";throw i.mapDomError(r,{path:o,isDirectory:!!c})}}async _openFile(e,t,a){let n=this.openHandles.get(e);if(!n){const o=await this.getFileHandle(e,t);try{await o.getFile()}catch(c){throw i.mapDomError(c,{path:e,isDirectory:!0})}const r=await i.createSyncHandleSafe(o,e);n={fileHandle:o,syncHandle:r,refCount:0},this.openHandles.set(e,n)}n.refCount++,a&&(n.syncHandle.truncate(0),n.syncHandle.flush());const s=this.nextFd++;return this.openFiles.set(s,{path:e,fileHandle:n.fileHandle,syncHandle:n.syncHandle,position:0}),s}async close(e){const t=this._getFileDescriptor(e);this.openFiles.delete(e);const a=this.openHandles.get(t.path);a&&(a.refCount--,a.refCount<=0&&(i.safeCloseSyncHandle(e,a.syncHandle,t.path),this.openHandles.delete(t.path)))}async read(e,t,a,n,s){const o=this._getFileDescriptor(e);i.validateReadWriteArgs(t.length,a,n,s);try{const r=s??o.position,c=o.syncHandle.getSize(),{isEOF:l,actualLength:h}=i.calculateReadLength(r,n,c);if(l)return w.transfer({bytesRead:0,buffer:t},[t.buffer]);const y=t.subarray(a,a+h),f=o.syncHandle.read(y,{at:r});return s==null&&(o.position=r+f),w.transfer({bytesRead:f,buffer:t},[t.buffer])}catch(r){throw i.createFDError("read",e,o.path,r)}}async write(e,t,a=0,n,s,o=!0){const r=this._getFileDescriptor(e),c=n??t.length-a;i.validateReadWriteArgs(t.length,a,c,s);try{const l=s??r.position,h=t.subarray(a,a+c),y=r.syncHandle.write(h,{at:l});return(s==null||s===r.position)&&(r.position=l+y),o&&await this.notifyChange({path:r.path,type:i.WatchEventType.Changed,isDirectory:!1}),y}catch(l){throw i.createFDError("write",e,r.path,l)}}async fstat(e){const t=this._getFileDescriptor(e);return this.stat(t.path)}async ftruncate(e,t=0){const a=this._getFileDescriptor(e);if(t<0||!Number.isInteger(t))throw new i.ValidationError("argument","Invalid size");try{a.syncHandle.truncate(t),a.syncHandle.flush(),a.position>t&&(a.position=t),await this.notifyChange({path:a.path,type:i.WatchEventType.Changed,isDirectory:!1})}catch(n){throw i.createFDError("truncate",e,a.path,n)}}async fsync(e){const t=this._getFileDescriptor(e);try{t.syncHandle.flush()}catch(a){throw i.createFDError("sync",e,t.path,a)}}dispose(){for(const[e,t]of this.openHandles)i.safeCloseSyncHandle(-1,t.syncHandle,e);this.openHandles.clear(),this.openFiles.clear(),this.nextFd=1,super.dispose()}}exports.OPFSSync=d;
2
+ //# sourceMappingURL=OPFSSync-3qlSBYmz.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OPFSSync-3qlSBYmz.cjs","sources":["../src/core/OPFSSync.ts"],"sourcesContent":["import { transfer } from 'comlink';\n\nimport { BaseOPFS } from './BaseOPFS';\nimport { WatchEventType } from '../types';\nimport {\n AlreadyExistsError,\n OPFSError,\n ValidationError,\n createFDError,\n mapDomError\n} from '../utils/errors';\n\nimport {\n calculateReadLength,\n createSyncHandleSafe,\n normalizePath,\n resolvePath,\n safeCloseSyncHandle,\n validateReadWriteArgs\n} from '../utils/helpers';\n\nimport type { FileOpenOptions, FileStat, OPFSOptions } from '../types';\n\n/**\n * Sync OPFS backend using `FileSystemSyncAccessHandle` (dedicated worker only).\n *\n * Provides high-level file I/O and Node-like file descriptors.\n *\n * @example\n * ```typescript\n * import { OPFSSync } from 'opfs-worker/pure';\n *\n * const fs = new OPFSSync();\n * await fs.writeFile('/data/config.json', new TextEncoder().encode(JSON.stringify({ theme: 'dark' })));\n * const config = await fs.readFile('/data/config.json');\n * ```\n */\nexport class OPFSSync extends BaseOPFS {\n /** Shared sync handles per path (OPFS allows only one handle per file) */\n private openHandles = new Map<string, {\n fileHandle: FileSystemFileHandle;\n syncHandle: FileSystemSyncAccessHandle;\n refCount: number;\n }>();\n\n /** Map of open file descriptors to their metadata */\n private openFiles = new Map<number, {\n path: string;\n fileHandle: FileSystemFileHandle;\n syncHandle: FileSystemSyncAccessHandle;\n position: number;\n }>();\n\n /** Next available file descriptor number */\n private nextFd = 1;\n\n constructor(options?: OPFSOptions) {\n super(options);\n }\n\n /**\n * Get file info by descriptor with validation\n * @private\n */\n private _getFileDescriptor(fd: number): { path: string; fileHandle: FileSystemFileHandle; syncHandle: FileSystemSyncAccessHandle; position: number } {\n const fileInfo = this.openFiles.get(fd);\n\n if (!fileInfo) {\n throw new ValidationError('descriptor', `Invalid file descriptor: ${ fd }`);\n }\n\n return fileInfo;\n }\n\n async readFile(path: string): Promise<Uint8Array> {\n await this.mount();\n\n try {\n return await this.withPathLock(path, async() => {\n const fd = await this.open(path);\n\n try {\n const { size } = await this.fstat(fd);\n const buffer = new Uint8Array(size);\n\n if (size > 0) {\n await this.read(fd, buffer, 0, size, 0);\n }\n\n return transfer(buffer, [buffer.buffer]);\n }\n finally {\n await this.close(fd);\n }\n });\n }\n catch (err) {\n if (err instanceof OPFSError) {\n throw err;\n }\n\n throw mapDomError(err, { path, isDirectory: false });\n }\n }\n\n async writeFile(\n path: string,\n data: Uint8Array | ArrayBuffer\n ): Promise<void> {\n await this.mount();\n\n const buffer = data instanceof Uint8Array ? data : new Uint8Array(data);\n\n await this.withPathLock(path, async() => {\n const existed = await this.exists(path);\n const fd = await this.open(path, { create: true, truncate: true });\n\n try {\n await this.write(fd, buffer, 0, buffer.length, null, false);\n await this.fsync(fd);\n }\n finally {\n await this.close(fd);\n }\n\n await this.notifyChange({ path, type: existed ? WatchEventType.Changed : WatchEventType.Added, isDirectory: false });\n });\n }\n\n async appendFile(\n path: string,\n data: Uint8Array | ArrayBuffer\n ): Promise<void> {\n await this.mount();\n\n const buffer = data instanceof Uint8Array ? data : new Uint8Array(data);\n\n await this.withPathLock(path, async() => {\n const fd = await this.open(path, { create: true });\n\n try {\n const { size } = await this.fstat(fd);\n\n await this.write(fd, buffer, 0, buffer.length, size, false);\n await this.fsync(fd);\n }\n finally {\n await this.close(fd);\n }\n\n await this.notifyChange({ path, type: WatchEventType.Changed, isDirectory: false });\n });\n }\n\n async writeStream(\n path: string,\n stream: ReadableStream<Uint8Array>,\n onProgress?: (bytesWritten: number) => unknown\n ): Promise<number> {\n await this.mount();\n\n return this.withPathLock(path, async() => {\n const existed = await this.exists(path);\n const fd = await this.open(path, { create: true, truncate: true });\n const reader = stream.getReader();\n let totalBytes = 0;\n\n try {\n while (true) {\n const { done, value: chunk } = await reader.read();\n\n if (done) {\n break;\n }\n\n let offset = 0;\n\n while (offset < chunk.byteLength) {\n offset += await this.write(\n fd,\n chunk,\n offset,\n chunk.byteLength - offset,\n null,\n false\n );\n }\n\n totalBytes += chunk.byteLength;\n await onProgress?.(totalBytes);\n }\n\n await this.fsync(fd);\n }\n catch (error) {\n await reader.cancel(error).catch(() => {});\n\n throw error;\n }\n finally {\n reader.releaseLock();\n await this.close(fd);\n }\n\n await this.notifyChange({\n path,\n type: existed ? WatchEventType.Changed : WatchEventType.Added,\n isDirectory: false,\n });\n\n return totalBytes;\n });\n }\n\n async open(path: string, options?: FileOpenOptions): Promise<number> {\n await this.mount();\n\n const { create = false, exclusive = false, truncate = false } = options || {};\n\n // Normalize path to prevent path-related issues\n const normalizedPath = normalizePath(resolvePath(path));\n\n try {\n // Use lock for atomic operations when creating files\n if (create && exclusive) {\n return await this.withPathLock(normalizedPath, async() => {\n const exists = await this.exists(normalizedPath);\n\n if (exists) {\n throw new AlreadyExistsError(normalizedPath);\n }\n\n return this._openFile(normalizedPath, create, truncate);\n });\n }\n\n return await this._openFile(normalizedPath, create, truncate);\n }\n catch (error: any) {\n if (error instanceof OPFSError) {\n throw error;\n }\n\n // TypeMismatchError here means the path actually refers to a directory\n // so we map it as a directory-type error (EISDIR) for better Node.js parity.\n const isTypeMismatchDirectory = error && error.name === 'TypeMismatchError';\n\n throw mapDomError(error, {\n path: normalizedPath,\n isDirectory: !!isTypeMismatchDirectory,\n });\n }\n }\n\n /**\n * Internal method to open a file (without locking)\n *\n * Multiple FDs for the same path share one sync access handle (OPFS limit),\n * with independent per-FD positions — similar to Node.js.\n * @private\n */\n private async _openFile(path: string, create: boolean, truncate: boolean): Promise<number> {\n let shared = this.openHandles.get(path);\n\n if (!shared) {\n const fileHandle = await this.getFileHandle(path, create);\n\n // Verify that we got a file handle, not a directory\n try {\n await fileHandle.getFile();\n }\n catch (error: any) {\n throw mapDomError(error, { path, isDirectory: true });\n }\n\n const syncHandle = await createSyncHandleSafe(fileHandle, path);\n\n shared = { fileHandle, syncHandle, refCount: 0 };\n this.openHandles.set(path, shared);\n }\n\n shared.refCount++;\n\n if (truncate) {\n shared.syncHandle.truncate(0);\n shared.syncHandle.flush();\n }\n\n const fd = this.nextFd++;\n\n this.openFiles.set(fd, {\n path,\n fileHandle: shared.fileHandle,\n syncHandle: shared.syncHandle,\n position: 0,\n });\n\n return fd;\n }\n\n async close(fd: number): Promise<void> {\n const fileInfo = this._getFileDescriptor(fd);\n\n this.openFiles.delete(fd);\n\n const shared = this.openHandles.get(fileInfo.path);\n\n if (!shared) {\n return;\n }\n\n shared.refCount--;\n\n // Only close the underlying sync handle when the last FD for this path is gone\n if (shared.refCount <= 0) {\n safeCloseSyncHandle(fd, shared.syncHandle, fileInfo.path);\n this.openHandles.delete(fileInfo.path);\n }\n }\n\n async read(\n fd: number,\n buffer: Uint8Array,\n offset: number,\n length: number,\n position: number | null | undefined\n ): Promise<{ bytesRead: number; buffer: Uint8Array }> {\n const fileInfo = this._getFileDescriptor(fd);\n\n // Validate arguments\n validateReadWriteArgs(buffer.length, offset, length, position);\n\n try {\n const readPosition = position ?? fileInfo.position;\n\n // Get file size and calculate read length\n const fileSize = fileInfo.syncHandle.getSize();\n const { isEOF, actualLength } = calculateReadLength(readPosition, length, fileSize);\n\n if (isEOF) {\n return transfer({ bytesRead: 0, buffer }, [buffer.buffer]); // End of file\n }\n\n // Create a subarray view for the read operation\n const targetBuffer = buffer.subarray(offset, offset + actualLength);\n\n // Perform efficient positioned read\n const bytesRead = fileInfo.syncHandle.read(targetBuffer, { at: readPosition });\n\n // Update position if position was not explicitly specified (null means use current position)\n if (position == null) {\n fileInfo.position = readPosition + bytesRead;\n }\n\n return transfer({ bytesRead, buffer }, [buffer.buffer]);\n }\n catch (error) {\n throw createFDError('read', fd, fileInfo.path, error);\n }\n }\n\n async write(\n fd: number,\n buffer: Uint8Array,\n offset: number = 0,\n length?: number,\n position?: number | null | undefined,\n emitEvent: boolean = true\n ): Promise<number> {\n const fileInfo = this._getFileDescriptor(fd);\n\n // Calculate actual length to write\n const actualLength = length ?? (buffer.length - offset);\n\n // Validate arguments using helper\n validateReadWriteArgs(buffer.length, offset, actualLength, position);\n\n try {\n // Determine write position: use specified position, or current position if null/undefined\n const writePosition = position ?? fileInfo.position;\n\n // Create a subarray view for the write operation\n const sourceBuffer = buffer.subarray(offset, offset + actualLength);\n\n // Perform efficient positioned write\n const bytesWritten = fileInfo.syncHandle.write(sourceBuffer, { at: writePosition });\n\n // Update position if position was null or undefined (i.e., use current position)\n // Also update position when writing at current position (position === fileInfo.position)\n if (position == null || position === fileInfo.position) {\n fileInfo.position = writePosition + bytesWritten;\n }\n\n if (emitEvent) {\n await this.notifyChange({ path: fileInfo.path, type: WatchEventType.Changed, isDirectory: false });\n }\n\n return bytesWritten;\n }\n catch (error) {\n throw createFDError('write', fd, fileInfo.path, error);\n }\n }\n\n async fstat(fd: number): Promise<FileStat> {\n const fileInfo = this._getFileDescriptor(fd);\n\n // Simply reuse existing stat() method with the file path\n return this.stat(fileInfo.path);\n }\n\n async ftruncate(fd: number, size: number = 0): Promise<void> {\n const fileInfo = this._getFileDescriptor(fd);\n\n // Validate size parameter\n if (size < 0 || !Number.isInteger(size)) {\n throw new ValidationError('argument', 'Invalid size');\n }\n\n try {\n fileInfo.syncHandle.truncate(size);\n fileInfo.syncHandle.flush();\n\n // Adjust position if it's beyond the new file size\n if (fileInfo.position > size) {\n fileInfo.position = size;\n }\n\n await this.notifyChange({ path: fileInfo.path, type: WatchEventType.Changed, isDirectory: false });\n }\n catch (error) {\n throw createFDError('truncate', fd, fileInfo.path, error);\n }\n }\n\n async fsync(fd: number): Promise<void> {\n const fileInfo = this._getFileDescriptor(fd);\n\n try {\n fileInfo.syncHandle.flush();\n }\n catch (error) {\n throw createFDError('sync', fd, fileInfo.path, error);\n }\n }\n\n override dispose(): void {\n // Close each shared sync handle once (not per FD)\n for (const [path, shared] of this.openHandles) {\n safeCloseSyncHandle(-1, shared.syncHandle, path);\n }\n\n this.openHandles.clear();\n this.openFiles.clear();\n this.nextFd = 1;\n\n super.dispose();\n }\n}\n"],"names":["OPFSSync","BaseOPFS","options","fd","fileInfo","ValidationError","path","size","buffer","transfer","err","OPFSError","mapDomError","data","existed","WatchEventType","stream","onProgress","reader","totalBytes","done","chunk","offset","error","create","exclusive","truncate","normalizedPath","normalizePath","resolvePath","AlreadyExistsError","isTypeMismatchDirectory","shared","fileHandle","syncHandle","createSyncHandleSafe","safeCloseSyncHandle","length","position","validateReadWriteArgs","readPosition","fileSize","isEOF","actualLength","calculateReadLength","targetBuffer","bytesRead","createFDError","emitEvent","writePosition","sourceBuffer","bytesWritten"],"mappings":"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"}