UNPKG

opfs-tools

Version:

EN: A simple, high-performance, and comprehensive file system API running in the browser, built on [OPFS](https://developer.mozilla.org/en-US/docs/Web/API/File_System_API/Origin_private_file_system).

3 lines (2 loc) 12.2 kB
(function(c,o){typeof exports=="object"&&typeof module<"u"?o(exports):typeof define=="function"&&define.amd?define(["exports"],o):(c=typeof globalThis<"u"?globalThis:c||self,o(c.OPFSTools={}))})(this,function(c){"use strict";var D=c=>{throw TypeError(c)};var M=(c,o,w)=>o.has(c)||D("Cannot "+w);var n=(c,o,w)=>(M(c,o,"read from private field"),w?w.call(c):o.get(c)),f=(c,o,w)=>o.has(c)?D("Cannot add the same private member more than once"):o instanceof WeakSet?o.add(c):o.set(c,w),u=(c,o,w,R)=>(M(c,o,"write to private field"),R?R.call(c,w):o.set(c,w),w);var d,I,W,h,S,T,G,v,p,V,k,Y;const o="KGZ1bmN0aW9uKCl7InVzZSBzdHJpY3QiO2Z1bmN0aW9uIHUobil7aWYobj09PSIvIilyZXR1cm57cGFyZW50Om51bGwsbmFtZToiIn07Y29uc3QgZT1uLnNwbGl0KCIvIikuZmlsdGVyKGk9PmkubGVuZ3RoPjApO2lmKGUubGVuZ3RoPT09MCl0aHJvdyBFcnJvcigiSW52YWxpZCBwYXRoIik7Y29uc3QgYT1lW2UubGVuZ3RoLTFdLHI9Ii8iK2Uuc2xpY2UoMCwtMSkuam9pbigiLyIpO3JldHVybntuYW1lOmEscGFyZW50OnJ9fWFzeW5jIGZ1bmN0aW9uIHcobixlKXtjb25zdHtwYXJlbnQ6YSxuYW1lOnJ9PXUobik7aWYoYT09bnVsbClyZXR1cm4gYXdhaXQgbmF2aWdhdG9yLnN0b3JhZ2UuZ2V0RGlyZWN0b3J5KCk7Y29uc3QgaT1hLnNwbGl0KCIvIikuZmlsdGVyKHQ9PnQubGVuZ3RoPjApO3RyeXtsZXQgdD1hd2FpdCBuYXZpZ2F0b3Iuc3RvcmFnZS5nZXREaXJlY3RvcnkoKTtmb3IoY29uc3QgcyBvZiBpKXQ9YXdhaXQgdC5nZXREaXJlY3RvcnlIYW5kbGUocyx7Y3JlYXRlOmUuY3JlYXRlfSk7aWYoZS5pc0ZpbGUpcmV0dXJuIGF3YWl0IHQuZ2V0RmlsZUhhbmRsZShyLHtjcmVhdGU6ZS5jcmVhdGV9KX1jYXRjaCh0KXtpZih0Lm5hbWU9PT0iTm90Rm91bmRFcnJvciIpcmV0dXJuIG51bGw7dGhyb3cgdH19Y29uc3QgZj17fTtzZWxmLm9ubWVzc2FnZT1hc3luYyBuPT57dmFyIGk7Y29uc3R7ZXZ0VHlwZTplLGFyZ3M6YX09bi5kYXRhO2xldCByPWZbYS5maWxlSWRdO3RyeXtsZXQgdDtjb25zdCBzPVtdO2lmKGU9PT0icmVnaXN0ZXIiKXtjb25zdCBsPWF3YWl0IHcoYS5maWxlUGF0aCx7Y3JlYXRlOiEwLGlzRmlsZTohMH0pO2lmKGw9PW51bGwpdGhyb3cgRXJyb3IoYG5vdCBmb3VuZCBmaWxlOiAke2EuZmlsZUlkfWApO3I9YXdhaXQgbC5jcmVhdGVTeW5jQWNjZXNzSGFuZGxlKHttb2RlOmEubW9kZX0pLGZbYS5maWxlSWRdPXJ9ZWxzZSBpZihlPT09ImNsb3NlIilhd2FpdCByLmNsb3NlKCksZGVsZXRlIGZbYS5maWxlSWRdO2Vsc2UgaWYoZT09PSJ0cnVuY2F0ZSIpYXdhaXQgci50cnVuY2F0ZShhLm5ld1NpemUpO2Vsc2UgaWYoZT09PSJ3cml0ZSIpe2NvbnN0e2RhdGE6bCxvcHRzOm99PW4uZGF0YS5hcmdzO3Q9YXdhaXQgci53cml0ZShsLG8pfWVsc2UgaWYoZT09PSJyZWFkIil7Y29uc3R7b2Zmc2V0Omwsc2l6ZTpvfT1uLmRhdGEuYXJncyxnPW5ldyBVaW50OEFycmF5KG8pLGQ9YXdhaXQgci5yZWFkKGcse2F0Omx9KSxjPWcuYnVmZmVyO3Q9ZD09PW8/YzooKGk9Yy50cmFuc2Zlcik9PW51bGw/dm9pZCAwOmkuY2FsbChjLGQpKT8/Yy5zbGljZSgwLGQpLHMucHVzaCh0KX1lbHNlIGU9PT0iZ2V0U2l6ZSI/dD1hd2FpdCByLmdldFNpemUoKTplPT09ImZsdXNoIiYmYXdhaXQgci5mbHVzaCgpO3NlbGYucG9zdE1lc3NhZ2Uoe2V2dFR5cGU6ImNhbGxiYWNrIixjYklkOm4uZGF0YS5jYklkLHJldHVyblZhbDp0fSxzKX1jYXRjaCh0KXtjb25zdCBzPXQ7c2VsZi5wb3N0TWVzc2FnZSh7ZXZ0VHlwZToidGhyb3dFcnJvciIsY2JJZDpuLmRhdGEuY2JJZCxlcnJNc2c6cy5uYW1lKyI6ICIrcy5tZXNzYWdlK2AKYCtKU09OLnN0cmluZ2lmeShuLmRhdGEpfSl9fX0pKCk7Ci8vIyBzb3VyY2VNYXBwaW5nVVJMPW9wZnMtd29ya2VyLUY0UldscWNfLmpzLm1hcAo=",w=r=>Uint8Array.from(atob(r),e=>e.charCodeAt(0)),R=typeof self<"u"&&self.Blob&&new Blob([w(o)],{type:"text/javascript;charset=utf-8"});function _(r){let e;try{if(e=R&&(self.URL||self.webkitURL).createObjectURL(R),!e)throw"";const t=new Worker(e,{name:r==null?void 0:r.name});return t.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(e)}),t}catch{return new Worker("data:text/javascript;base64,"+o,{name:r==null?void 0:r.name})}finally{e&&(self.URL||self.webkitURL).revokeObjectURL(e)}}async function A(r,e,t){const a=$();return await a("register",{fileId:r,filePath:e,mode:t}),{read:async(i,s)=>await a("read",{fileId:r,offset:i,size:s}),write:async(i,s)=>await a("write",{fileId:r,data:i,opts:s},[ArrayBuffer.isView(i)?i.buffer:i]),close:async()=>await a("close",{fileId:r}),truncate:async i=>await a("truncate",{fileId:r,newSize:i}),getSize:async()=>await a("getSize",{fileId:r}),flush:async()=>await a("flush",{fileId:r})}}const L=[];let x=0;function $(){if(L.length<3){const e=r();return L.push(e),e}else{const e=L[x];return x=(x+1)%L.length,e}function r(){const e=new _;let t=0,a={};return e.onmessage=({data:i})=>{var s,l;i.evtType==="callback"?(s=a[i.cbId])==null||s.resolve(i.returnVal):i.evtType==="throwError"&&((l=a[i.cbId])==null||l.reject(Error(i.errMsg))),delete a[i.cbId]},async function(s,l,m=[]){t+=1;const y=new Promise((X,J)=>{a[t]={resolve:X,reject:J}});return e.postMessage({cbId:t,evtType:s,args:l},m),y}}}function P(r){if(r==="/")return{parent:null,name:""};const e=r.split("/").filter(i=>i.length>0);if(e.length===0)throw Error("Invalid path");const t=e[e.length-1],a="/"+e.slice(0,-1).join("/");return{name:t,parent:a}}async function b(r,e){const{parent:t,name:a}=P(r);if(t==null)return await navigator.storage.getDirectory();const i=t.split("/").filter(s=>s.length>0);try{let s=await navigator.storage.getDirectory();for(const l of i)s=await s.getDirectoryHandle(l,{create:e.create});return e.isFile?await s.getFileHandle(a,{create:e.create}):await s.getDirectoryHandle(a,{create:e.create})}catch(s){if(s.name==="NotFoundError")return null;throw s}}async function H(r){const{parent:e,name:t}=P(r);if(e==null){const i=await navigator.storage.getDirectory();for await(const s of i.keys())await i.removeEntry(s,{recursive:!0});return}const a=await b(e,{create:!1,isFile:!1});if(a!=null)try{await a.removeEntry(t,{recursive:!0})}catch(i){if(i.name==="NotFoundError")return;throw i}}function O(r,e){return`${r}/${e}`.replace("//","/")}function g(r){return new E(r)}const K=class K{constructor(e){f(this,d);f(this,I);f(this,W);u(this,d,e);const{parent:t,name:a}=P(e);u(this,I,a),u(this,W,t)}get kind(){return"dir"}get name(){return n(this,I)}get path(){return n(this,d)}get parent(){return n(this,W)==null?null:g(n(this,W))}async create(){return await b(n(this,d),{create:!0,isFile:!1}),g(n(this,d))}async exists(){return await b(n(this,d),{create:!1,isFile:!1})instanceof FileSystemDirectoryHandle}async remove(e={}){for(const t of await this.children())try{await t.remove(e)}catch(a){console.warn(a)}try{await H(n(this,d))}catch(t){console.warn(t)}}async children(){const e=await b(n(this,d),{create:!1,isFile:!1});if(e==null)return[];const t=[];for await(const a of e.values())t.push((a.kind==="file"?Z:g)(O(n(this,d),a.name)));return t}async copyTo(e){if(!await this.exists())throw Error(`dir ${this.path} not exists`);if(e instanceof K){const t=await e.exists()?g(O(e.path,this.name)):e;return await t.create(),await Promise.all((await this.children()).map(a=>a.copyTo(t))),t}else if(e instanceof FileSystemDirectoryHandle)return await Promise.all((await this.children()).map(async t=>{t.kind==="file"?await t.copyTo(await e.getFileHandle(t.name,{create:!0})):await t.copyTo(await e.getDirectoryHandle(t.name,{create:!0}))})),null;throw Error("Illegal target type")}async moveTo(e){const t=await this.copyTo(e);return await this.remove(),t}};d=new WeakMap,I=new WeakMap,W=new WeakMap;let E=K;const U=new Map;function Z(r,e="rw"){if(e==="rw"){const t=U.get(r)??new F(r,e);return U.set(r,t),t}return new F(r,e)}async function C(r,e,t={overwrite:!0}){if(e instanceof F){await C(r,await e.stream(),t);return}const a=await(r instanceof F?r:Z(r,"rw")).createWriter();try{if(t.overwrite&&await a.truncate(0),e instanceof ReadableStream){const i=e.getReader();for(;;){const{done:s,value:l}=await i.read();if(s)break;await a.write(l)}}else await a.write(e)}catch(i){throw i}finally{await a.close()}}let q=0;const ee=()=>++q,N=class N{constructor(e,t){f(this,h);f(this,S);f(this,T);f(this,G);f(this,v);f(this,p,0);f(this,V,async()=>{});f(this,k,(()=>{let e=null;return()=>(u(this,p,n(this,p)+1),e!=null||(e=new Promise(async(t,a)=>{try{const i=await A(n(this,v),n(this,h),n(this,G));u(this,V,async()=>{e!=null&&(e=null,u(this,p,0),await i.close().catch(console.error))}),t([i,async()=>{u(this,p,n(this,p)-1),!(n(this,p)>0)&&(e=null,await i.close())}])}catch(i){a(i)}})),e)})());f(this,Y,!1);u(this,v,ee()),u(this,h,e),u(this,G,{r:"read-only",rw:"readwrite","rw-unsafe":"readwrite-unsafe"}[t]);const{parent:a,name:i}=P(e);if(a==null)throw Error("Invalid path");u(this,T,i),u(this,S,a)}get kind(){return"file"}get path(){return n(this,h)}get name(){return n(this,T)}get parent(){return n(this,S)==null?null:g(n(this,S))}async createWriter(){if(n(this,G)==="read-only")throw Error("file is read-only");if(n(this,Y))throw Error("Other writer have not been closed");u(this,Y,!0);try{const e=new TextEncoder,[t,a]=await n(this,k).call(this);let i=await t.getSize(),s=!1;return{write:async(l,m={})=>{if(s)throw Error("Writer is closed");const y=typeof l=="string"?e.encode(l):l,X=m.at??i,J=y.byteLength;return i=X+J,await t.write(y,{at:X})},truncate:async l=>{if(s)throw Error("Writer is closed");await t.truncate(l),i>l&&(i=l)},flush:async()=>{if(s)throw Error("Writer is closed");await t.flush()},close:async()=>{if(s)throw Error("Writer is closed");s=!0,u(this,Y,!1),await a()}}}catch(e){throw u(this,Y,!1),e}}async createReader(){const[e,t]=await n(this,k).call(this);let a=!1,i=0;return{read:async(s,l={})=>{if(a)throw Error("Reader is closed");const m=l.at??i,y=await e.read(m,s);return i=m+y.byteLength,y},getSize:async()=>{if(a)throw Error("Reader is closed");return await e.getSize()},close:async()=>{a||(a=!0,await t())}}}async text(){return new TextDecoder().decode(await this.arrayBuffer())}async arrayBuffer(){const e=await b(n(this,h),{create:!1,isFile:!0});return e==null?new ArrayBuffer(0):(await e.getFile()).arrayBuffer()}async stream(){const e=await this.getOriginFile();return e==null?new ReadableStream({pull:t=>{t.close()}}):e.stream()}async getOriginFile(){var e;return(e=await b(n(this,h),{create:!1,isFile:!0}))==null?void 0:e.getFile()}async getSize(){const e=await b(n(this,h),{create:!1,isFile:!0});return e==null?0:(await e.getFile()).size}async exists(){return await b(n(this,h),{create:!1,isFile:!0})instanceof FileSystemFileHandle}async remove(e={}){if(e.force===!0){await n(this,V).call(this),await H(n(this,h)),U.delete(n(this,h));return}if(n(this,p)>0)throw Error("exists unclosed reader/writer");await H(n(this,h))}async copyTo(e){if(e instanceof N)return e.path===this.path?this:(await C(e,this),e);if(e instanceof E){if(!await this.exists())throw Error(`file ${this.path} not exists`);return await this.copyTo(Z(O(e.path,this.name)))}else if(e instanceof FileSystemFileHandle)return await(await this.stream()).pipeTo(await e.createWritable()),null;throw Error("Illegal target type")}async moveTo(e){const t=await this.copyTo(e);return await this.remove(),t}};h=new WeakMap,S=new WeakMap,T=new WeakMap,G=new WeakMap,v=new WeakMap,p=new WeakMap,V=new WeakMap,k=new WeakMap,Y=new WeakMap;let F=N;const j="/.opfs-tools-temp-dir";async function B(r){try{if(r.kind==="file"){if(!await r.exists())return!0;const e=await r.createWriter();await e.truncate(0),await e.close(),await r.remove()}else await r.remove();return!0}catch(e){return console.warn(e),!1}}function te(){setInterval(async()=>{for(const e of await g(j).children()){const t=/^\d+-(\d+)$/.exec(e.name);(t==null||Date.now()-Number(t[1])>2592e5)&&await B(e)}},60*1e3)}const z=[];let Q=!1;async function re(){if(globalThis.localStorage==null)return;const r="OPFS_TOOLS_EXPIRES_TMP_FILES";Q||(Q=!0,globalThis.addEventListener("unload",()=>{z.length!==0&&localStorage.setItem(r,`${localStorage.getItem(r)??""},${z.join(",")}`)}));let e=localStorage.getItem(r)??"";for(const t of e.split(","))t.length!==0&&await B(Z(`${j}/${t}`))&&(e=e.replace(t,""));localStorage.setItem(r,e.replace(/,{2,}/g,","))}(async function(){var e;globalThis.__opfs_tools_tmpfile_init__!==!0&&(globalThis.__opfs_tools_tmpfile_init__=!0,!(globalThis.FileSystemDirectoryHandle==null||globalThis.FileSystemFileHandle==null||((e=globalThis.navigator)==null?void 0:e.storage.getDirectory)==null)&&(te(),await re()))})();function ae(){const r=`${Math.random().toString().slice(2)}-${Date.now()}`;return z.push(r),Z(`${j}/${r}`)}function ie(r,e){let t=Z(r),a=0,i=t.createWriter(),s=t.createReader();const l=async m=>{const X=await(await s).read(a,{at:Math.round(a*.3)});a=await m.write(X,{at:0}),await m.truncate(a)};return{append:async m=>{const y=await i;a+=await y.write(m),a>=e&&await l(y)},text:t.text.bind(t),remove:async()=>{await(await s).close(),await(await i).close(),await t.remove()},getSize:async()=>a}}c.dir=g,c.file=Z,c.rollfile=ie,c.tmpfile=ae,c.write=C,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})}); //# sourceMappingURL=opfs-tools.umd.cjs.map