offline-data-manager 1.0.3 → 1.0.5
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.
package/Readme.md
CHANGED
|
@@ -275,10 +275,10 @@ Returns data for both `complete` and `expired` entries — expiry only means a r
|
|
|
275
275
|
|
|
276
276
|
### Status
|
|
277
277
|
|
|
278
|
-
#### `
|
|
278
|
+
#### `getAllStatus()`
|
|
279
279
|
Returns all entries merged with queue state, plus a storage summary.
|
|
280
280
|
```js
|
|
281
|
-
const { items, storage } = await ODM.
|
|
281
|
+
const { items, storage } = await ODM.getAllStatus();
|
|
282
282
|
// items[n]: { id, mimeType, version, downloadStatus, storedBytes,
|
|
283
283
|
// bytesDownloaded, progress, completedAt, expiresAt, ... }
|
|
284
284
|
// storage: { usageBytes, quotaBytes, availableBytes, ...Formatted }
|
|
@@ -377,7 +377,7 @@ The build script is zero-dependency — pure Node.js 18+, no Rollup or Webpack r
|
|
|
377
377
|
## Notes
|
|
378
378
|
|
|
379
379
|
- **ArrayBuffer storage** — all file data is stored as a raw ArrayBuffer on the queue record alongside its resolved `mimeType`. There is only one IDB store to manage; no separate data store.
|
|
380
|
-
- **MIME type inference** — when `mimeType` is omitted from a registry entry, the downloader reads `Content-Type` from the HEAD probe (or GET response as a fallback) and strips any charset parameters. Falls back to `application/octet-stream` if the server returns nothing useful. The resolved type is stored with the ArrayBuffer and returned by `retrieve()`, `
|
|
380
|
+
- **MIME type inference** — when `mimeType` is omitted from a registry entry, the downloader reads `Content-Type` from the HEAD probe (or GET response as a fallback) and strips any charset parameters. Falls back to `application/octet-stream` if the server returns nothing useful. The resolved type is stored with the ArrayBuffer and returned by `retrieve()`, `getAllStatus()`, and `getStatus()`.
|
|
381
381
|
- **Persistent loop vs one-shot** — the loop waits on a Promise that resolves only when `registerFile()` or the connectivity monitor calls an internal wake function. There is no polling between drain cycles.
|
|
382
382
|
- **Chunking threshold** — files over 5 MB are downloaded in 2 MB Range request chunks. Both constants are in `downloader.js`.
|
|
383
383
|
- **Content-Encoding** — `Content-Length` is ignored for size tracking when the server applies `gzip`/`br` encoding, avoiding misleading progress numbers. Progress shows as indeterminate instead.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var K="offline-data-manager",z=1,L=null,i={REGISTRY:"registry",DOWNLOAD_QUEUE:"downloadQueue"};async function V(e,t){K=e??"offline-data-manager",z=t??1}async function U(){return L||(L=await new Promise((e,t)=>{let o=indexedDB.open(K,z);o.onupgradeneeded=a=>{let r=a.target.result;if(!r.objectStoreNames.contains(i.REGISTRY)){let n=r.createObjectStore(i.REGISTRY,{keyPath:"id"});n.createIndex("protected","protected",{unique:!1}),n.createIndex("priority","priority",{unique:!1})}if(!r.objectStoreNames.contains(i.DOWNLOAD_QUEUE)){let n=r.createObjectStore(i.DOWNLOAD_QUEUE,{keyPath:"id"});n.createIndex("status","status",{unique:!1}),n.createIndex("priority","priority",{unique:!1})}},o.onsuccess=()=>e(o.result),o.onerror=()=>t(o.error)}),L)}async function p(e,t){let o=await U();return new Promise((a,r)=>{let n=o.transaction(e,"readonly").objectStore(e).get(t);n.onsuccess=()=>a(n.result),n.onerror=()=>r(n.error)})}async function y(e){let t=await U();return new Promise((o,a)=>{let r=t.transaction(e,"readonly").objectStore(e).getAll();r.onsuccess=()=>o(r.result),r.onerror=()=>a(r.error)})}async function N(e){let t=await U();return new Promise((o,a)=>{let r=t.transaction(e,"readonly").objectStore(e).getAllKeys();r.onsuccess=()=>o(r.result),r.onerror=()=>a(r.error)})}async function E(e,t){let o=await U();return new Promise((a,r)=>{let n=o.transaction(e,"readwrite").objectStore(e).put(t);n.onsuccess=()=>a(),n.onerror=()=>r(n.error)})}async function S(e,t){let o=await U();return new Promise((a,r)=>{let n=o.transaction(e,"readwrite").objectStore(e).delete(t);n.onsuccess=()=>a(),n.onerror=()=>r(n.error)})}var T=new Map;function Q(e,t){return T.has(e)||T.set(e,new Set),T.get(e).add(t),()=>_(e,t)}function _(e,t){T.get(e)?.delete(t)}function d(e,t){T.get(e)?.forEach(o=>{try{o(t)}catch(a){console.error(`[offline-data-manager] Error in "${e}" listener:`,a)}})}function Z(e,t){let o=a=>{t(a),_(e,o)};Q(e,o)}async function I(){if(!navigator?.storage?.estimate)return{usage:0,quota:1/0,available:1/0};let{usage:e=0,quota:t=1/0}=await navigator.storage.estimate();return{usage:e,quota:t,available:t-e}}async function J(e){let{available:t,quota:o}=await I();return t-o*.1>=e}async function ee(){return navigator?.storage?.persist?navigator.storage.persist():!1}async function te(){return navigator?.storage?.persisted?navigator.storage.persisted():!1}function P(e){return e===1/0?"\u221E":e<1024?`${e} B`:e<1024**2?`${(e/1024).toFixed(1)} KB`:e<1024**3?`${(e/1024**2).toFixed(1)} MB`:`${(e/1024**3).toFixed(2)} GB`}var F=null,q=null,M=!1;function oe(){d("connectivity",{online:!1}),F?.()}function ne(){d("connectivity",{online:!0}),q?.()}function re({pauseAll:e,resumeAll:t}){M||(F=e,q=t,window.addEventListener("offline",oe),window.addEventListener("online",ne),M=!0)}function W(){window.removeEventListener("offline",oe),window.removeEventListener("online",ne),F=null,q=null,M=!1}function v(){return navigator.onLine??!0}function $(){return M}var Se=2*1024*1024,Oe=5*1024*1024,he=2,ae=5,xe=1e3,g=new Map,b=!1,G=null;function se(){return new Promise(e=>{G=e})}function O(){if(G){let e=G;G=null,e()}}var Ue=e=>new Promise(t=>setTimeout(t,e)),Te=e=>xe*Math.pow(2,e);async function m(e,t){let o=await p(i.DOWNLOAD_QUEUE,e);o&&await E(i.DOWNLOAD_QUEUE,{...o,...t})}async function Ie(e,t){try{let o=await fetch(e,{method:"HEAD",signal:t}),a=o.headers.get("Accept-Ranges")==="bytes",r=o.headers.get("Content-Encoding"),n=!!r&&r!=="identity",s=o.headers.get("Content-Length"),l=s&&!n?parseInt(s,10):null,c=ie(o.headers.get("Content-Type"));return{supportsRange:a,totalBytes:l,mimeType:c}}catch{return{supportsRange:!1,totalBytes:null,mimeType:null}}}function ie(e){return e&&e.split(";")[0].trim()||null}function le(e){let t=e.reduce((r,n)=>r+n.byteLength,0),o=new Uint8Array(t),a=0;for(let r of e)o.set(r,a),a+=r.byteLength;return o}async function ve(e){let{id:t,downloadUrl:o,ttl:a}=e,r=new AbortController;g.set(t,r);let n=await p(i.DOWNLOAD_QUEUE,t),s=n?.retryCount??0;for(;s<=ae;)try{await m(t,{status:u.IN_PROGRESS,lastAttemptAt:Date.now(),retryCount:s,errorMessage:null}),d("status",{id:t,status:u.IN_PROGRESS}),n=await p(i.DOWNLOAD_QUEUE,t);let l=n?.byteOffset??0,c=!1,f=n?.totalBytes??e.totalBytes??null,w=e.mimeType??null;if(l===0){let R=await Ie(o,r.signal);c=R.supportsRange,R.totalBytes&&(f=R.totalBytes,await m(t,{totalBytes:f})),!w&&R.mimeType&&(w=R.mimeType)}else c=!0;let D=c&&f&&f>Oe,A,x=null;if(D)A=await Ne(t,o,l,f,r.signal);else{let R=await Le(t,o,r.signal);A=R.uint8,x=R.mimeType}let H=w??x??"application/octet-stream",C=A.buffer,X=Date.now(),be=we(X,a);await m(t,{status:u.COMPLETE,data:C,mimeType:H,bytesDownloaded:C.byteLength,byteOffset:C.byteLength,completedAt:X,expiresAt:be,errorMessage:null,deferredReason:null}),d("complete",{id:t,mimeType:H}),g.delete(t);return}catch(l){if(l.name==="AbortError"){await m(t,{status:u.PAUSED}),d("status",{id:t,status:u.PAUSED}),g.delete(t);return}if(s++,s>ae){await m(t,{status:u.FAILED,retryCount:s,errorMessage:l.message}),d("error",{id:t,error:l,retryCount:s}),g.delete(t);return}let c=Te(s-1);console.warn(`[offline-data-manager] "${t}" failed (attempt ${s}), retrying in ${c}ms:`,l.message),d("error",{id:t,error:l,retryCount:s,willRetry:!0}),await m(t,{status:u.PENDING,retryCount:s,errorMessage:l.message}),await Ue(c)}}async function Le(e,t,o){let a=await fetch(t,{signal:o});if(!a.ok)throw new Error(`HTTP ${a.status} ${a.statusText}`);let r=a.headers.get("Content-Encoding"),n=!!r&&r!=="identity",s=a.headers.get("Content-Length"),l=s&&!n?parseInt(s,10):null,c=ie(a.headers.get("Content-Type")),f=a.body.getReader(),w=[],D=0;for(;;){let{done:A,value:x}=await f.read();if(A)break;w.push(x),D+=x.byteLength,await m(e,{bytesDownloaded:D,totalBytes:l}),d("progress",{id:e,bytesDownloaded:D,totalBytes:l,percent:l?Math.round(D/l*100):null})}return{uint8:le(w),mimeType:c}}async function Ne(e,t,o,a,r){let n=o,s=[],l=o;for(;n<a;){let c=Math.min(n+Se-1,a-1),f=await fetch(t,{signal:r,headers:{Range:`bytes=${n}-${c}`}});if(!f.ok&&f.status!==206)throw new Error(`HTTP ${f.status} on Range bytes=${n}-${c}`);let w=new Uint8Array(await f.arrayBuffer());s.push(w),n+=w.byteLength,l+=w.byteLength,await m(e,{bytesDownloaded:l,byteOffset:n}),d("progress",{id:e,bytesDownloaded:l,totalBytes:a,percent:Math.round(l/a*100)})}return le(s)}async function _e(e){await me();let[t,o]=await Promise.all([y(i.REGISTRY),y(i.DOWNLOAD_QUEUE)]),a=new Map(t.map(l=>[l.id,l])),r=o.filter(l=>[u.PENDING,u.IN_PROGRESS,u.PAUSED,u.DEFERRED,u.EXPIRED].includes(l.status)).sort((l,c)=>(a.get(l.id)?.priority??10)-(a.get(c.id)?.priority??10));if(r.length===0)return;let n=[...r],s=new Set;await new Promise(l=>{function c(){if(!b){l();return}if(n.length===0){s.size===0&&l();return}if(s.size>=e)return;let f=n.shift(),w=a.get(f.id);if(!w){c();return}let D=(async()=>{let A=w.totalBytes??f.totalBytes??0;if(A>0&&!await J(A)){await m(f.id,{status:u.DEFERRED,deferredReason:"insufficient-storage"}),d("deferred",{id:f.id,reason:"insufficient-storage"});return}await ve(w)})().finally(()=>{s.delete(D),c()});s.add(D),c()}c()})}function ue({concurrency:e=he}={}){b||(b=!0,(async()=>{for(;b;){if(!v()){let t=await y(i.DOWNLOAD_QUEUE);for(let o of t)o.status===u.IN_PROGRESS&&(g.get(o.id)?.abort(),g.delete(o.id),await m(o.id,{status:u.PAUSED,deferredReason:"network-offline"}));d("connectivity",{online:!1}),await se();continue}await _e(e),b&&await se()}})())}async function de(){b=!1,O(),await h(),d("stopped",{})}async function ce(){let e=await y(i.DOWNLOAD_QUEUE);for(let t of e)t.status===u.FAILED&&await m(t.id,{status:u.PENDING,retryCount:0,errorMessage:null});O()}function fe(){return b}async function B(e){g.get(e)?.abort(),g.delete(e)}async function h(){for(let[e,t]of g)t.abort(),g.delete(e)}function pe(){re({pauseAll:h,resumeAll:O})}var u={PENDING:"pending",IN_PROGRESS:"in-progress",PAUSED:"paused",COMPLETE:"complete",EXPIRED:"expired",FAILED:"failed",DEFERRED:"deferred"},k=new Set([u.COMPLETE,u.EXPIRED]);function Pe(e){if(!e||typeof e!="object")throw new Error("Registry entry must be an object.");if(!e.id||typeof e.id!="string")throw new Error('Registry entry must have a string "id".');if(!e.downloadUrl||typeof e.downloadUrl!="string")throw new Error(`Entry "${e.id}" must have a string "downloadUrl".`);if(e.mimeType!==void 0&&e.mimeType!==null&&typeof e.mimeType!="string")throw new Error(`Entry "${e.id}" mimeType must be a string or omitted.`);if(typeof e.version!="number"||!Number.isInteger(e.version)||e.version<0)throw new Error(`Entry "${e.id}" version must be a non-negative integer.`);if(e.ttl!==void 0&&(typeof e.ttl!="number"||e.ttl<0))throw new Error(`Entry "${e.id}" ttl must be a non-negative number (seconds).`)}function ye(e){return{id:e,status:u.PENDING,data:null,bytesDownloaded:0,totalBytes:null,byteOffset:0,retryCount:0,lastAttemptAt:null,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}}function we(e,t){return t?e+t*1e3:null}function Me(e){return e?Date.now()>=e:!1}async function Y(e){Pe(e);let t=Date.now(),o=await p(i.REGISTRY,e.id),a=await p(i.DOWNLOAD_QUEUE,e.id),r={id:e.id,downloadUrl:e.downloadUrl,mimeType:e.mimeType??null,version:e.version,protected:e.protected??!1,priority:e.priority??10,ttl:e.ttl??0,totalBytes:e.totalBytes??null,metadata:e.metadata??{},registeredAt:o?.registeredAt??t,updatedAt:t};if(o){if(e.version>o.version){await E(i.REGISTRY,r);let n=a?{...a,status:u.PENDING,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}:ye(e.id);await E(i.DOWNLOAD_QUEUE,n),d("registered",{id:e.id,reason:"version-updated"}),O()}return}await E(i.REGISTRY,r),await E(i.DOWNLOAD_QUEUE,ye(e.id)),d("registered",{id:e.id,reason:"new"}),O()}async function Ee(e){if(!Array.isArray(e))throw new Error("registerFiles expects an array.");let t=new Set(e.map(r=>r.id)),o=await y(i.REGISTRY),a=[];for(let r of o)!t.has(r.id)&&!r.protected&&(await S(i.REGISTRY,r.id),await S(i.DOWNLOAD_QUEUE,r.id),a.push(r.id),d("deleted",{id:r.id,registryRemoved:!0}));for(let r of e)await Y(r);return{registered:e.map(r=>r.id),removed:a}}async function me(){let e=await y(i.DOWNLOAD_QUEUE),t=[];for(let o of e)o.status===u.COMPLETE&&Me(o.expiresAt)&&(await E(i.DOWNLOAD_QUEUE,{...o,status:u.EXPIRED}),t.push(o.id),d("expired",{id:o.id}));return t}async function ge(){let[e,t,o]=await Promise.all([y(i.REGISTRY),y(i.DOWNLOAD_QUEUE),I()]),a=new Map(t.map(n=>[n.id,n]));return{items:e.map(n=>{let s=a.get(n.id)??null;return{id:n.id,downloadUrl:n.downloadUrl,mimeType:n.mimeType,version:n.version,protected:n.protected,priority:n.priority,ttl:n.ttl,totalBytes:n.totalBytes,metadata:n.metadata,registeredAt:n.registeredAt,updatedAt:n.updatedAt,downloadStatus:s?.status??null,bytesDownloaded:s?.bytesDownloaded??0,storedBytes:s?.data?.length??null,progress:s?.totalBytes&&s?.bytesDownloaded?Math.round(s.bytesDownloaded/s.totalBytes*100):null,retryCount:s?.retryCount??0,lastAttemptAt:s?.lastAttemptAt??null,errorMessage:s?.errorMessage??null,deferredReason:s?.deferredReason??null,completedAt:s?.completedAt??null,expiresAt:s?.expiresAt??null}}).sort((n,s)=>n.priority-s.priority),storage:{usageBytes:o.usage,quotaBytes:o.quota,availableBytes:o.available,usageFormatted:P(o.usage),quotaFormatted:P(o.quota),availableFormatted:P(o.available)}}}async function De(e){let[t,o]=await Promise.all([p(i.REGISTRY,e),p(i.DOWNLOAD_QUEUE,e)]);return t?{id:t.id,downloadUrl:t.downloadUrl,mimeType:t.mimeType??null,version:t.version,protected:t.protected,priority:t.priority,ttl:t.ttl,totalBytes:t.totalBytes,metadata:t.metadata,registeredAt:t.registeredAt,updatedAt:t.updatedAt,downloadStatus:o?.status??null,bytesDownloaded:o?.bytesDownloaded??0,storedBytes:o?.data?.length??null,progress:o?.totalBytes&&o?.bytesDownloaded?Math.round(o.bytesDownloaded/o.totalBytes*100):null,retryCount:o?.retryCount??0,lastAttemptAt:o?.lastAttemptAt??null,errorMessage:o?.errorMessage??null,deferredReason:o?.deferredReason??null,completedAt:o?.completedAt??null,expiresAt:o?.expiresAt??null}:null}async function Ae(e){let t=await p(i.DOWNLOAD_QUEUE,e);return k.has(t?.status)}async function Ge(e){let t=await p(i.DOWNLOAD_QUEUE,e);t&&await E(i.DOWNLOAD_QUEUE,{...t,status:u.PENDING,data:null,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null})}async function j(e,{removeRegistry:t=!1}={}){let o=await p(i.REGISTRY,e);if(!o)throw new Error(`deleteFile: No registered file with id "${e}".`);await B(e);let a=t||!o.protected;return a?(await S(i.REGISTRY,e),await S(i.DOWNLOAD_QUEUE,e)):await Ge(e),d("deleted",{id:e,registryRemoved:a}),{id:e,registryRemoved:a}}async function Re({removeRegistry:e=!1}={}){await h();let t=await N(i.REGISTRY);return Promise.all(t.map(o=>j(o,{removeRegistry:e})))}async function Be(e){let[t,o]=await Promise.all([p(i.REGISTRY,e),p(i.DOWNLOAD_QUEUE,e)]);if(!t)throw new Error(`retrieve: No registered file with id "${e}".`);if(!k.has(o?.status)||!o?.data)throw new Error(`retrieve: File "${e}" has no data yet (status: ${o?.status??"unknown"}).`);return{data:o.data,mimeType:o.mimeType}}var Ce={setDBInfo:V,dbGetAllIds:N,registerFile:Y,registerFiles:Ee,startDownloads:ue,stopDownloads:de,retryFailed:ce,isDownloading:fe,abortDownload:B,abortAllDownloads:h,startMonitoring:pe,stopMonitoring:W,isOnline:v,isMonitoring:$,retrieve:Be,view:ge,getStatus:De,isReady:Ae,delete:j,deleteAll:Re,on:Q,off:_,once:Z,getStorageEstimate:I,requestPersistentStorage:ee,isPersistentStorage:te},mt=Ce;export{h as abortAllDownloads,B as abortDownload,mt as default,Re as deleteAllFiles,j as deleteFile,d as emit,De as getStatus,I as getStorageEstimate,fe as isDownloading,$ as isMonitoring,v as isOnline,te as isPersistentStorage,Ae as isReady,_ as off,Q as on,Z as once,Y as registerFile,Ee as registerFiles,ee as requestPersistentStorage,Be as retrieve,ce as retryFailed,ue as startDownloads,pe as startMonitoring,de as stopDownloads,W as stopMonitoring,ge as view};
|
|
1
|
+
var K="offline-data-manager",z=1,L=null,i={REGISTRY:"registry",DOWNLOAD_QUEUE:"downloadQueue"};async function V(t,e){K=t??"offline-data-manager",z=e??1}async function U(){return L||(L=await new Promise((t,e)=>{let o=indexedDB.open(K,z);o.onupgradeneeded=a=>{let r=a.target.result;if(!r.objectStoreNames.contains(i.REGISTRY)){let n=r.createObjectStore(i.REGISTRY,{keyPath:"id"});n.createIndex("protected","protected",{unique:!1}),n.createIndex("priority","priority",{unique:!1})}if(!r.objectStoreNames.contains(i.DOWNLOAD_QUEUE)){let n=r.createObjectStore(i.DOWNLOAD_QUEUE,{keyPath:"id"});n.createIndex("status","status",{unique:!1}),n.createIndex("priority","priority",{unique:!1})}},o.onsuccess=()=>t(o.result),o.onerror=()=>e(o.error)}),L)}async function p(t,e){let o=await U();return new Promise((a,r)=>{let n=o.transaction(t,"readonly").objectStore(t).get(e);n.onsuccess=()=>a(n.result),n.onerror=()=>r(n.error)})}async function y(t){let e=await U();return new Promise((o,a)=>{let r=e.transaction(t,"readonly").objectStore(t).getAll();r.onsuccess=()=>o(r.result),r.onerror=()=>a(r.error)})}async function N(t){let e=await U();return new Promise((o,a)=>{let r=e.transaction(t,"readonly").objectStore(t).getAllKeys();r.onsuccess=()=>o(r.result),r.onerror=()=>a(r.error)})}async function g(t,e){let o=await U();return new Promise((a,r)=>{let n=o.transaction(t,"readwrite").objectStore(t).put(e);n.onsuccess=()=>a(),n.onerror=()=>r(n.error)})}async function S(t,e){let o=await U();return new Promise((a,r)=>{let n=o.transaction(t,"readwrite").objectStore(t).delete(e);n.onsuccess=()=>a(),n.onerror=()=>r(n.error)})}var T=new Map;function Q(t,e){return T.has(t)||T.set(t,new Set),T.get(t).add(e),()=>_(t,e)}function _(t,e){T.get(t)?.delete(e)}function d(t,e){T.get(t)?.forEach(o=>{try{o(e)}catch(a){console.error(`[offline-data-manager] Error in "${t}" listener:`,a)}})}function Z(t,e){let o=a=>{e(a),_(t,o)};Q(t,o)}async function I(){if(!navigator?.storage?.estimate)return{usage:0,quota:1/0,available:1/0};let{usage:t=0,quota:e=1/0}=await navigator.storage.estimate();return{usage:t,quota:e,available:e-t}}async function J(t){let{available:e,quota:o}=await I();return e-o*.1>=t}async function tt(){return navigator?.storage?.persist?navigator.storage.persist():!1}async function et(){return navigator?.storage?.persisted?navigator.storage.persisted():!1}function P(t){return t===1/0?"\u221E":t<1024?`${t} B`:t<1024**2?`${(t/1024).toFixed(1)} KB`:t<1024**3?`${(t/1024**2).toFixed(1)} MB`:`${(t/1024**3).toFixed(2)} GB`}var F=null,q=null,M=!1;function ot(){d("connectivity",{online:!1}),F?.()}function nt(){d("connectivity",{online:!0}),q?.()}function rt({pauseAll:t,resumeAll:e}){M||(F=t,q=e,window.addEventListener("offline",ot),window.addEventListener("online",nt),M=!0)}function W(){window.removeEventListener("offline",ot),window.removeEventListener("online",nt),F=null,q=null,M=!1}function v(){return navigator.onLine??!0}function $(){return M}var St=2*1024*1024,Ot=5*1024*1024,ht=2,at=5,xt=1e3,E=new Map,b=!1,G=null;function st(){return new Promise(t=>{G=t})}function O(){if(G){let t=G;G=null,t()}}var Ut=t=>new Promise(e=>setTimeout(e,t)),Tt=t=>xt*Math.pow(2,t);async function m(t,e){let o=await p(i.DOWNLOAD_QUEUE,t);o&&await g(i.DOWNLOAD_QUEUE,{...o,...e})}async function It(t,e){try{let o=await fetch(t,{method:"HEAD",signal:e}),a=o.headers.get("Accept-Ranges")==="bytes",r=o.headers.get("Content-Encoding"),n=!!r&&r!=="identity",s=o.headers.get("Content-Length"),l=s&&!n?parseInt(s,10):null,c=it(o.headers.get("Content-Type"));return{supportsRange:a,totalBytes:l,mimeType:c}}catch{return{supportsRange:!1,totalBytes:null,mimeType:null}}}function it(t){return t&&t.split(";")[0].trim()||null}function lt(t){let e=t.reduce((r,n)=>r+n.byteLength,0),o=new Uint8Array(e),a=0;for(let r of t)o.set(r,a),a+=r.byteLength;return o}async function vt(t){let{id:e,downloadUrl:o,ttl:a}=t,r=new AbortController;E.set(e,r);let n=await p(i.DOWNLOAD_QUEUE,e),s=n?.retryCount??0;for(;s<=at;)try{await m(e,{status:u.IN_PROGRESS,lastAttemptAt:Date.now(),retryCount:s,errorMessage:null}),d("status",{id:e,status:u.IN_PROGRESS}),n=await p(i.DOWNLOAD_QUEUE,e);let l=n?.byteOffset??0,c=!1,f=n?.totalBytes??t.totalBytes??null,w=t.mimeType??null;if(l===0){let R=await It(o,r.signal);c=R.supportsRange,R.totalBytes&&(f=R.totalBytes,await m(e,{totalBytes:f})),!w&&R.mimeType&&(w=R.mimeType)}else c=!0;let D=c&&f&&f>Ot,A,x=null;if(D)A=await Nt(e,o,l,f,r.signal);else{let R=await Lt(e,o,r.signal);A=R.uint8,x=R.mimeType}let H=w??x??"application/octet-stream",C=A.buffer,X=Date.now(),bt=wt(X,a);await m(e,{status:u.COMPLETE,data:C,mimeType:H,bytesDownloaded:C.byteLength,byteOffset:C.byteLength,completedAt:X,expiresAt:bt,errorMessage:null,deferredReason:null}),d("complete",{id:e,mimeType:H}),E.delete(e);return}catch(l){if(l.name==="AbortError"){await m(e,{status:u.PAUSED}),d("status",{id:e,status:u.PAUSED}),E.delete(e);return}if(s++,s>at){await m(e,{status:u.FAILED,retryCount:s,errorMessage:l.message}),d("error",{id:e,error:l,retryCount:s}),E.delete(e);return}let c=Tt(s-1);console.warn(`[offline-data-manager] "${e}" failed (attempt ${s}), retrying in ${c}ms:`,l.message),d("error",{id:e,error:l,retryCount:s,willRetry:!0}),await m(e,{status:u.PENDING,retryCount:s,errorMessage:l.message}),await Ut(c)}}async function Lt(t,e,o){let a=await fetch(e,{signal:o});if(!a.ok)throw new Error(`HTTP ${a.status} ${a.statusText}`);let r=a.headers.get("Content-Encoding"),n=!!r&&r!=="identity",s=a.headers.get("Content-Length"),l=s&&!n?parseInt(s,10):null,c=it(a.headers.get("Content-Type")),f=a.body.getReader(),w=[],D=0;for(;;){let{done:A,value:x}=await f.read();if(A)break;w.push(x),D+=x.byteLength,await m(t,{bytesDownloaded:D,totalBytes:l}),d("progress",{id:t,bytesDownloaded:D,totalBytes:l,percent:l?Math.round(D/l*100):null})}return{uint8:lt(w),mimeType:c}}async function Nt(t,e,o,a,r){let n=o,s=[],l=o;for(;n<a;){let c=Math.min(n+St-1,a-1),f=await fetch(e,{signal:r,headers:{Range:`bytes=${n}-${c}`}});if(!f.ok&&f.status!==206)throw new Error(`HTTP ${f.status} on Range bytes=${n}-${c}`);let w=new Uint8Array(await f.arrayBuffer());s.push(w),n+=w.byteLength,l+=w.byteLength,await m(t,{bytesDownloaded:l,byteOffset:n}),d("progress",{id:t,bytesDownloaded:l,totalBytes:a,percent:Math.round(l/a*100)})}return lt(s)}async function _t(t){await mt();let[e,o]=await Promise.all([y(i.REGISTRY),y(i.DOWNLOAD_QUEUE)]),a=new Map(e.map(l=>[l.id,l])),r=o.filter(l=>[u.PENDING,u.IN_PROGRESS,u.PAUSED,u.DEFERRED,u.EXPIRED].includes(l.status)).sort((l,c)=>(a.get(l.id)?.priority??10)-(a.get(c.id)?.priority??10));if(r.length===0)return;let n=[...r],s=new Set;await new Promise(l=>{function c(){if(!b){l();return}if(n.length===0){s.size===0&&l();return}if(s.size>=t)return;let f=n.shift(),w=a.get(f.id);if(!w){c();return}let D=(async()=>{let A=w.totalBytes??f.totalBytes??0;if(A>0&&!await J(A)){await m(f.id,{status:u.DEFERRED,deferredReason:"insufficient-storage"}),d("deferred",{id:f.id,reason:"insufficient-storage"});return}await vt(w)})().finally(()=>{s.delete(D),c()});s.add(D),c()}c()})}function ut({concurrency:t=ht}={}){b||(b=!0,(async()=>{for(;b;){if(!v()){let e=await y(i.DOWNLOAD_QUEUE);for(let o of e)o.status===u.IN_PROGRESS&&(E.get(o.id)?.abort(),E.delete(o.id),await m(o.id,{status:u.PAUSED,deferredReason:"network-offline"}));d("connectivity",{online:!1}),await st();continue}await _t(t),b&&await st()}})())}async function dt(){b=!1,O(),await h(),d("stopped",{})}async function ct(){let t=await y(i.DOWNLOAD_QUEUE);for(let e of t)e.status===u.FAILED&&await m(e.id,{status:u.PENDING,retryCount:0,errorMessage:null});O()}function ft(){return b}async function B(t){E.get(t)?.abort(),E.delete(t)}async function h(){for(let[t,e]of E)e.abort(),E.delete(t)}function pt(){rt({pauseAll:h,resumeAll:O})}var u={PENDING:"pending",IN_PROGRESS:"in-progress",PAUSED:"paused",COMPLETE:"complete",EXPIRED:"expired",FAILED:"failed",DEFERRED:"deferred"},k=new Set([u.COMPLETE,u.EXPIRED]);function Pt(t){if(!t||typeof t!="object")throw new Error("Registry entry must be an object.");if(!t.id||typeof t.id!="string")throw new Error('Registry entry must have a string "id".');if(!t.downloadUrl||typeof t.downloadUrl!="string")throw new Error(`Entry "${t.id}" must have a string "downloadUrl".`);if(t.mimeType!==void 0&&t.mimeType!==null&&typeof t.mimeType!="string")throw new Error(`Entry "${t.id}" mimeType must be a string or omitted.`);if(typeof t.version!="number"||!Number.isInteger(t.version)||t.version<0)throw new Error(`Entry "${t.id}" version must be a non-negative integer.`);if(t.ttl!==void 0&&(typeof t.ttl!="number"||t.ttl<0))throw new Error(`Entry "${t.id}" ttl must be a non-negative number (seconds).`)}function yt(t){return{id:t,status:u.PENDING,data:null,bytesDownloaded:0,totalBytes:null,byteOffset:0,retryCount:0,lastAttemptAt:null,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}}function wt(t,e){return e?t+e*1e3:null}function Mt(t){return t?Date.now()>=t:!1}async function Y(t){Pt(t);let e=Date.now(),o=await p(i.REGISTRY,t.id),a=await p(i.DOWNLOAD_QUEUE,t.id),r={id:t.id,downloadUrl:t.downloadUrl,mimeType:t.mimeType??null,version:t.version,protected:t.protected??!1,priority:t.priority??10,ttl:t.ttl??0,totalBytes:t.totalBytes??null,metadata:t.metadata??{},registeredAt:o?.registeredAt??e,updatedAt:e};if(o){if(t.version>o.version){await g(i.REGISTRY,r);let n=a?{...a,status:u.PENDING,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}:yt(t.id);await g(i.DOWNLOAD_QUEUE,n),d("registered",{id:t.id,reason:"version-updated"}),O()}return}await g(i.REGISTRY,r),await g(i.DOWNLOAD_QUEUE,yt(t.id)),d("registered",{id:t.id,reason:"new"}),O()}async function gt(t){if(!Array.isArray(t))throw new Error("registerFiles expects an array.");let e=new Set(t.map(r=>r.id)),o=await y(i.REGISTRY),a=[];for(let r of o)!e.has(r.id)&&!r.protected&&(await S(i.REGISTRY,r.id),await S(i.DOWNLOAD_QUEUE,r.id),a.push(r.id),d("deleted",{id:r.id,registryRemoved:!0}));for(let r of t)await Y(r);return{registered:t.map(r=>r.id),removed:a}}async function mt(){let t=await y(i.DOWNLOAD_QUEUE),e=[];for(let o of t)o.status===u.COMPLETE&&Mt(o.expiresAt)&&(await g(i.DOWNLOAD_QUEUE,{...o,status:u.EXPIRED}),e.push(o.id),d("expired",{id:o.id}));return e}async function Et(){let[t,e,o]=await Promise.all([y(i.REGISTRY),y(i.DOWNLOAD_QUEUE),I()]),a=new Map(e.map(n=>[n.id,n]));return{items:t.map(n=>{let s=a.get(n.id)??null;return{id:n.id,downloadUrl:n.downloadUrl,mimeType:n.mimeType,version:n.version,protected:n.protected,priority:n.priority,ttl:n.ttl,totalBytes:n.totalBytes,metadata:n.metadata,registeredAt:n.registeredAt,updatedAt:n.updatedAt,downloadStatus:s?.status??null,bytesDownloaded:s?.bytesDownloaded??0,storedBytes:s?.data?.length??null,progress:s?.totalBytes&&s?.bytesDownloaded?Math.round(s.bytesDownloaded/s.totalBytes*100):null,retryCount:s?.retryCount??0,lastAttemptAt:s?.lastAttemptAt??null,errorMessage:s?.errorMessage??null,deferredReason:s?.deferredReason??null,completedAt:s?.completedAt??null,expiresAt:s?.expiresAt??null}}).sort((n,s)=>n.priority-s.priority),storage:{usageBytes:o.usage,quotaBytes:o.quota,availableBytes:o.available,usageFormatted:P(o.usage),quotaFormatted:P(o.quota),availableFormatted:P(o.available)}}}async function Dt(t){let[e,o]=await Promise.all([p(i.REGISTRY,t),p(i.DOWNLOAD_QUEUE,t)]);return e?{id:e.id,downloadUrl:e.downloadUrl,mimeType:e.mimeType??null,version:e.version,protected:e.protected,priority:e.priority,ttl:e.ttl,totalBytes:e.totalBytes,metadata:e.metadata,registeredAt:e.registeredAt,updatedAt:e.updatedAt,downloadStatus:o?.status??null,bytesDownloaded:o?.bytesDownloaded??0,storedBytes:o?.data?.length??null,progress:o?.totalBytes&&o?.bytesDownloaded?Math.round(o.bytesDownloaded/o.totalBytes*100):null,retryCount:o?.retryCount??0,lastAttemptAt:o?.lastAttemptAt??null,errorMessage:o?.errorMessage??null,deferredReason:o?.deferredReason??null,completedAt:o?.completedAt??null,expiresAt:o?.expiresAt??null}:null}async function At(t){let e=await p(i.DOWNLOAD_QUEUE,t);return k.has(e?.status)}async function Gt(t){let e=await p(i.DOWNLOAD_QUEUE,t);e&&await g(i.DOWNLOAD_QUEUE,{...e,status:u.PENDING,data:null,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null})}async function j(t,{removeRegistry:e=!1}={}){let o=await p(i.REGISTRY,t);if(!o)throw new Error(`deleteFile: No registered file with id "${t}".`);await B(t);let a=e||!o.protected;return a?(await S(i.REGISTRY,t),await S(i.DOWNLOAD_QUEUE,t)):await Gt(t),d("deleted",{id:t,registryRemoved:a}),{id:t,registryRemoved:a}}async function Rt({removeRegistry:t=!1}={}){await h();let e=await N(i.REGISTRY);return Promise.all(e.map(o=>j(o,{removeRegistry:t})))}async function Bt(t){let[e,o]=await Promise.all([p(i.REGISTRY,t),p(i.DOWNLOAD_QUEUE,t)]);if(!e)throw new Error(`retrieve: No registered file with id "${t}".`);if(!k.has(o?.status)||!o?.data)throw new Error(`retrieve: File "${t}" has no data yet (status: ${o?.status??"unknown"}).`);return{data:o.data,mimeType:o.mimeType}}var Ct={setDBInfo:V,dbGetAllIds:N,registerFile:Y,registerFiles:gt,startDownloads:ut,stopDownloads:dt,retryFailed:ct,isDownloading:ft,abortDownload:B,abortAllDownloads:h,startMonitoring:pt,stopMonitoring:W,isOnline:v,isMonitoring:$,retrieve:Bt,getAllStatus:Et,getStatus:Dt,isReady:At,delete:j,deleteAll:Rt,on:Q,off:_,once:Z,getStorageEstimate:I,requestPersistentStorage:tt,isPersistentStorage:et},me=Ct;export{h as abortAllDownloads,B as abortDownload,me as default,Rt as deleteAllFiles,j as deleteFile,d as emit,Et as getAllStatus,Dt as getStatus,I as getStorageEstimate,ft as isDownloading,$ as isMonitoring,v as isOnline,et as isPersistentStorage,At as isReady,_ as off,Q as on,Z as once,Y as registerFile,gt as registerFiles,tt as requestPersistentStorage,Bt as retrieve,ct as retryFailed,ut as startDownloads,pt as startMonitoring,dt as stopDownloads,W as stopMonitoring};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var offlineMapData=(()=>{var k=Object.defineProperty;var he=Object.getOwnPropertyDescriptor;var xe=Object.getOwnPropertyNames;var Ue=Object.prototype.hasOwnProperty;var Te=(e,t)=>{for(var o in t)k(e,o,{get:t[o],enumerable:!0})},Ie=(e,t,o,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of xe(t))!Ue.call(e,n)&&n!==o&&k(e,n,{get:()=>t[n],enumerable:!(a=he(t,n))||a.enumerable});return e};var ve=e=>Ie(k({},"__esModule",{value:!0}),e);var He={};Te(He,{abortAllDownloads:()=>S,abortDownload:()=>N,default:()=>je,deleteAllFiles:()=>se,deleteFile:()=>W,emit:()=>d,getStatus:()=>re,getStorageEstimate:()=>h,isDownloading:()=>J,isMonitoring:()=>Q,isOnline:()=>x,isPersistentStorage:()=>H,isReady:()=>ae,off:()=>L,on:()=>M,once:()=>Y,registerFile:()=>q,registerFiles:()=>oe,requestPersistentStorage:()=>j,retrieve:()=>Se,retryFailed:()=>Z,startDownloads:()=>z,startMonitoring:()=>ee,stopDownloads:()=>V,stopMonitoring:()=>C,view:()=>ne});var ue="offline-data-manager",de=1,_=null,i={REGISTRY:"registry",DOWNLOAD_QUEUE:"downloadQueue"};async function ce(e,t){ue=e??"offline-data-manager",de=t??1}async function I(){return _||(_=await new Promise((e,t)=>{let o=indexedDB.open(ue,de);o.onupgradeneeded=a=>{let n=a.target.result;if(!n.objectStoreNames.contains(i.REGISTRY)){let r=n.createObjectStore(i.REGISTRY,{keyPath:"id"});r.createIndex("protected","protected",{unique:!1}),r.createIndex("priority","priority",{unique:!1})}if(!n.objectStoreNames.contains(i.DOWNLOAD_QUEUE)){let r=n.createObjectStore(i.DOWNLOAD_QUEUE,{keyPath:"id"});r.createIndex("status","status",{unique:!1}),r.createIndex("priority","priority",{unique:!1})}},o.onsuccess=()=>e(o.result),o.onerror=()=>t(o.error)}),_)}async function p(e,t){let o=await I();return new Promise((a,n)=>{let r=o.transaction(e,"readonly").objectStore(e).get(t);r.onsuccess=()=>a(r.result),r.onerror=()=>n(r.error)})}async function y(e){let t=await I();return new Promise((o,a)=>{let n=t.transaction(e,"readonly").objectStore(e).getAll();n.onsuccess=()=>o(n.result),n.onerror=()=>a(n.error)})}async function P(e){let t=await I();return new Promise((o,a)=>{let n=t.transaction(e,"readonly").objectStore(e).getAllKeys();n.onsuccess=()=>o(n.result),n.onerror=()=>a(n.error)})}async function E(e,t){let o=await I();return new Promise((a,n)=>{let r=o.transaction(e,"readwrite").objectStore(e).put(t);r.onsuccess=()=>a(),r.onerror=()=>n(r.error)})}async function O(e,t){let o=await I();return new Promise((a,n)=>{let r=o.transaction(e,"readwrite").objectStore(e).delete(t);r.onsuccess=()=>a(),r.onerror=()=>n(r.error)})}var v=new Map;function M(e,t){return v.has(e)||v.set(e,new Set),v.get(e).add(t),()=>L(e,t)}function L(e,t){v.get(e)?.delete(t)}function d(e,t){v.get(e)?.forEach(o=>{try{o(t)}catch(a){console.error(`[offline-data-manager] Error in "${e}" listener:`,a)}})}function Y(e,t){let o=a=>{t(a),L(e,o)};M(e,o)}async function h(){if(!navigator?.storage?.estimate)return{usage:0,quota:1/0,available:1/0};let{usage:e=0,quota:t=1/0}=await navigator.storage.estimate();return{usage:e,quota:t,available:t-e}}async function fe(e){let{available:t,quota:o}=await h();return t-o*.1>=e}async function j(){return navigator?.storage?.persist?navigator.storage.persist():!1}async function H(){return navigator?.storage?.persisted?navigator.storage.persisted():!1}function G(e){return e===1/0?"\u221E":e<1024?`${e} B`:e<1024**2?`${(e/1024).toFixed(1)} KB`:e<1024**3?`${(e/1024**2).toFixed(1)} MB`:`${(e/1024**3).toFixed(2)} GB`}var X=null,K=null,B=!1;function pe(){d("connectivity",{online:!1}),X?.()}function we(){d("connectivity",{online:!0}),K?.()}function me({pauseAll:e,resumeAll:t}){B||(X=e,K=t,window.addEventListener("offline",pe),window.addEventListener("online",we),B=!0)}function C(){window.removeEventListener("offline",pe),window.removeEventListener("online",we),X=null,K=null,B=!1}function x(){return navigator.onLine??!0}function Q(){return B}var Le=2*1024*1024,Ne=5*1024*1024,_e=2,ye=5,Pe=1e3,g=new Map,b=!1,F=null;function Ee(){return new Promise(e=>{F=e})}function U(){if(F){let e=F;F=null,e()}}var Me=e=>new Promise(t=>setTimeout(t,e)),Ge=e=>Pe*Math.pow(2,e);async function m(e,t){let o=await p(i.DOWNLOAD_QUEUE,e);o&&await E(i.DOWNLOAD_QUEUE,{...o,...t})}async function Be(e,t){try{let o=await fetch(e,{method:"HEAD",signal:t}),a=o.headers.get("Accept-Ranges")==="bytes",n=o.headers.get("Content-Encoding"),r=!!n&&n!=="identity",s=o.headers.get("Content-Length"),l=s&&!r?parseInt(s,10):null,c=ge(o.headers.get("Content-Type"));return{supportsRange:a,totalBytes:l,mimeType:c}}catch{return{supportsRange:!1,totalBytes:null,mimeType:null}}}function ge(e){return e&&e.split(";")[0].trim()||null}function De(e){let t=e.reduce((n,r)=>n+r.byteLength,0),o=new Uint8Array(t),a=0;for(let n of e)o.set(n,a),a+=n.byteLength;return o}async function Ce(e){let{id:t,downloadUrl:o,ttl:a}=e,n=new AbortController;g.set(t,n);let r=await p(i.DOWNLOAD_QUEUE,t),s=r?.retryCount??0;for(;s<=ye;)try{await m(t,{status:u.IN_PROGRESS,lastAttemptAt:Date.now(),retryCount:s,errorMessage:null}),d("status",{id:t,status:u.IN_PROGRESS}),r=await p(i.DOWNLOAD_QUEUE,t);let l=r?.byteOffset??0,c=!1,f=r?.totalBytes??e.totalBytes??null,w=e.mimeType??null;if(l===0){let R=await Be(o,n.signal);c=R.supportsRange,R.totalBytes&&(f=R.totalBytes,await m(t,{totalBytes:f})),!w&&R.mimeType&&(w=R.mimeType)}else c=!0;let D=c&&f&&f>Ne,A,T=null;if(D)A=await Fe(t,o,l,f,n.signal);else{let R=await Qe(t,o,n.signal);A=R.uint8,T=R.mimeType}let ie=w??T??"application/octet-stream",$=A.buffer,le=Date.now(),Oe=Ae(le,a);await m(t,{status:u.COMPLETE,data:$,mimeType:ie,bytesDownloaded:$.byteLength,byteOffset:$.byteLength,completedAt:le,expiresAt:Oe,errorMessage:null,deferredReason:null}),d("complete",{id:t,mimeType:ie}),g.delete(t);return}catch(l){if(l.name==="AbortError"){await m(t,{status:u.PAUSED}),d("status",{id:t,status:u.PAUSED}),g.delete(t);return}if(s++,s>ye){await m(t,{status:u.FAILED,retryCount:s,errorMessage:l.message}),d("error",{id:t,error:l,retryCount:s}),g.delete(t);return}let c=Ge(s-1);console.warn(`[offline-data-manager] "${t}" failed (attempt ${s}), retrying in ${c}ms:`,l.message),d("error",{id:t,error:l,retryCount:s,willRetry:!0}),await m(t,{status:u.PENDING,retryCount:s,errorMessage:l.message}),await Me(c)}}async function Qe(e,t,o){let a=await fetch(t,{signal:o});if(!a.ok)throw new Error(`HTTP ${a.status} ${a.statusText}`);let n=a.headers.get("Content-Encoding"),r=!!n&&n!=="identity",s=a.headers.get("Content-Length"),l=s&&!r?parseInt(s,10):null,c=ge(a.headers.get("Content-Type")),f=a.body.getReader(),w=[],D=0;for(;;){let{done:A,value:T}=await f.read();if(A)break;w.push(T),D+=T.byteLength,await m(e,{bytesDownloaded:D,totalBytes:l}),d("progress",{id:e,bytesDownloaded:D,totalBytes:l,percent:l?Math.round(D/l*100):null})}return{uint8:De(w),mimeType:c}}async function Fe(e,t,o,a,n){let r=o,s=[],l=o;for(;r<a;){let c=Math.min(r+Le-1,a-1),f=await fetch(t,{signal:n,headers:{Range:`bytes=${r}-${c}`}});if(!f.ok&&f.status!==206)throw new Error(`HTTP ${f.status} on Range bytes=${r}-${c}`);let w=new Uint8Array(await f.arrayBuffer());s.push(w),r+=w.byteLength,l+=w.byteLength,await m(e,{bytesDownloaded:l,byteOffset:r}),d("progress",{id:e,bytesDownloaded:l,totalBytes:a,percent:Math.round(l/a*100)})}return De(s)}async function qe(e){await Re();let[t,o]=await Promise.all([y(i.REGISTRY),y(i.DOWNLOAD_QUEUE)]),a=new Map(t.map(l=>[l.id,l])),n=o.filter(l=>[u.PENDING,u.IN_PROGRESS,u.PAUSED,u.DEFERRED,u.EXPIRED].includes(l.status)).sort((l,c)=>(a.get(l.id)?.priority??10)-(a.get(c.id)?.priority??10));if(n.length===0)return;let r=[...n],s=new Set;await new Promise(l=>{function c(){if(!b){l();return}if(r.length===0){s.size===0&&l();return}if(s.size>=e)return;let f=r.shift(),w=a.get(f.id);if(!w){c();return}let D=(async()=>{let A=w.totalBytes??f.totalBytes??0;if(A>0&&!await fe(A)){await m(f.id,{status:u.DEFERRED,deferredReason:"insufficient-storage"}),d("deferred",{id:f.id,reason:"insufficient-storage"});return}await Ce(w)})().finally(()=>{s.delete(D),c()});s.add(D),c()}c()})}function z({concurrency:e=_e}={}){b||(b=!0,(async()=>{for(;b;){if(!x()){let t=await y(i.DOWNLOAD_QUEUE);for(let o of t)o.status===u.IN_PROGRESS&&(g.get(o.id)?.abort(),g.delete(o.id),await m(o.id,{status:u.PAUSED,deferredReason:"network-offline"}));d("connectivity",{online:!1}),await Ee();continue}await qe(e),b&&await Ee()}})())}async function V(){b=!1,U(),await S(),d("stopped",{})}async function Z(){let e=await y(i.DOWNLOAD_QUEUE);for(let t of e)t.status===u.FAILED&&await m(t.id,{status:u.PENDING,retryCount:0,errorMessage:null});U()}function J(){return b}async function N(e){g.get(e)?.abort(),g.delete(e)}async function S(){for(let[e,t]of g)t.abort(),g.delete(e)}function ee(){me({pauseAll:S,resumeAll:U})}var u={PENDING:"pending",IN_PROGRESS:"in-progress",PAUSED:"paused",COMPLETE:"complete",EXPIRED:"expired",FAILED:"failed",DEFERRED:"deferred"},te=new Set([u.COMPLETE,u.EXPIRED]);function We(e){if(!e||typeof e!="object")throw new Error("Registry entry must be an object.");if(!e.id||typeof e.id!="string")throw new Error('Registry entry must have a string "id".');if(!e.downloadUrl||typeof e.downloadUrl!="string")throw new Error(`Entry "${e.id}" must have a string "downloadUrl".`);if(e.mimeType!==void 0&&e.mimeType!==null&&typeof e.mimeType!="string")throw new Error(`Entry "${e.id}" mimeType must be a string or omitted.`);if(typeof e.version!="number"||!Number.isInteger(e.version)||e.version<0)throw new Error(`Entry "${e.id}" version must be a non-negative integer.`);if(e.ttl!==void 0&&(typeof e.ttl!="number"||e.ttl<0))throw new Error(`Entry "${e.id}" ttl must be a non-negative number (seconds).`)}function be(e){return{id:e,status:u.PENDING,data:null,bytesDownloaded:0,totalBytes:null,byteOffset:0,retryCount:0,lastAttemptAt:null,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}}function Ae(e,t){return t?e+t*1e3:null}function $e(e){return e?Date.now()>=e:!1}async function q(e){We(e);let t=Date.now(),o=await p(i.REGISTRY,e.id),a=await p(i.DOWNLOAD_QUEUE,e.id),n={id:e.id,downloadUrl:e.downloadUrl,mimeType:e.mimeType??null,version:e.version,protected:e.protected??!1,priority:e.priority??10,ttl:e.ttl??0,totalBytes:e.totalBytes??null,metadata:e.metadata??{},registeredAt:o?.registeredAt??t,updatedAt:t};if(o){if(e.version>o.version){await E(i.REGISTRY,n);let r=a?{...a,status:u.PENDING,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}:be(e.id);await E(i.DOWNLOAD_QUEUE,r),d("registered",{id:e.id,reason:"version-updated"}),U()}return}await E(i.REGISTRY,n),await E(i.DOWNLOAD_QUEUE,be(e.id)),d("registered",{id:e.id,reason:"new"}),U()}async function oe(e){if(!Array.isArray(e))throw new Error("registerFiles expects an array.");let t=new Set(e.map(n=>n.id)),o=await y(i.REGISTRY),a=[];for(let n of o)!t.has(n.id)&&!n.protected&&(await O(i.REGISTRY,n.id),await O(i.DOWNLOAD_QUEUE,n.id),a.push(n.id),d("deleted",{id:n.id,registryRemoved:!0}));for(let n of e)await q(n);return{registered:e.map(n=>n.id),removed:a}}async function Re(){let e=await y(i.DOWNLOAD_QUEUE),t=[];for(let o of e)o.status===u.COMPLETE&&$e(o.expiresAt)&&(await E(i.DOWNLOAD_QUEUE,{...o,status:u.EXPIRED}),t.push(o.id),d("expired",{id:o.id}));return t}async function ne(){let[e,t,o]=await Promise.all([y(i.REGISTRY),y(i.DOWNLOAD_QUEUE),h()]),a=new Map(t.map(r=>[r.id,r]));return{items:e.map(r=>{let s=a.get(r.id)??null;return{id:r.id,downloadUrl:r.downloadUrl,mimeType:r.mimeType,version:r.version,protected:r.protected,priority:r.priority,ttl:r.ttl,totalBytes:r.totalBytes,metadata:r.metadata,registeredAt:r.registeredAt,updatedAt:r.updatedAt,downloadStatus:s?.status??null,bytesDownloaded:s?.bytesDownloaded??0,storedBytes:s?.data?.length??null,progress:s?.totalBytes&&s?.bytesDownloaded?Math.round(s.bytesDownloaded/s.totalBytes*100):null,retryCount:s?.retryCount??0,lastAttemptAt:s?.lastAttemptAt??null,errorMessage:s?.errorMessage??null,deferredReason:s?.deferredReason??null,completedAt:s?.completedAt??null,expiresAt:s?.expiresAt??null}}).sort((r,s)=>r.priority-s.priority),storage:{usageBytes:o.usage,quotaBytes:o.quota,availableBytes:o.available,usageFormatted:G(o.usage),quotaFormatted:G(o.quota),availableFormatted:G(o.available)}}}async function re(e){let[t,o]=await Promise.all([p(i.REGISTRY,e),p(i.DOWNLOAD_QUEUE,e)]);return t?{id:t.id,downloadUrl:t.downloadUrl,mimeType:t.mimeType??null,version:t.version,protected:t.protected,priority:t.priority,ttl:t.ttl,totalBytes:t.totalBytes,metadata:t.metadata,registeredAt:t.registeredAt,updatedAt:t.updatedAt,downloadStatus:o?.status??null,bytesDownloaded:o?.bytesDownloaded??0,storedBytes:o?.data?.length??null,progress:o?.totalBytes&&o?.bytesDownloaded?Math.round(o.bytesDownloaded/o.totalBytes*100):null,retryCount:o?.retryCount??0,lastAttemptAt:o?.lastAttemptAt??null,errorMessage:o?.errorMessage??null,deferredReason:o?.deferredReason??null,completedAt:o?.completedAt??null,expiresAt:o?.expiresAt??null}:null}async function ae(e){let t=await p(i.DOWNLOAD_QUEUE,e);return te.has(t?.status)}async function ke(e){let t=await p(i.DOWNLOAD_QUEUE,e);t&&await E(i.DOWNLOAD_QUEUE,{...t,status:u.PENDING,data:null,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null})}async function W(e,{removeRegistry:t=!1}={}){let o=await p(i.REGISTRY,e);if(!o)throw new Error(`deleteFile: No registered file with id "${e}".`);await N(e);let a=t||!o.protected;return a?(await O(i.REGISTRY,e),await O(i.DOWNLOAD_QUEUE,e)):await ke(e),d("deleted",{id:e,registryRemoved:a}),{id:e,registryRemoved:a}}async function se({removeRegistry:e=!1}={}){await S();let t=await P(i.REGISTRY);return Promise.all(t.map(o=>W(o,{removeRegistry:e})))}async function Se(e){let[t,o]=await Promise.all([p(i.REGISTRY,e),p(i.DOWNLOAD_QUEUE,e)]);if(!t)throw new Error(`retrieve: No registered file with id "${e}".`);if(!te.has(o?.status)||!o?.data)throw new Error(`retrieve: File "${e}" has no data yet (status: ${o?.status??"unknown"}).`);return{data:o.data,mimeType:o.mimeType}}var Ye={setDBInfo:ce,dbGetAllIds:P,registerFile:q,registerFiles:oe,startDownloads:z,stopDownloads:V,retryFailed:Z,isDownloading:J,abortDownload:N,abortAllDownloads:S,startMonitoring:ee,stopMonitoring:C,isOnline:x,isMonitoring:Q,retrieve:Se,view:ne,getStatus:re,isReady:ae,delete:W,deleteAll:se,on:M,off:L,once:Y,getStorageEstimate:h,requestPersistentStorage:j,isPersistentStorage:H},je=Ye;return ve(He);})();
|
|
1
|
+
"use strict";var offlineMapData=(()=>{var k=Object.defineProperty;var ht=Object.getOwnPropertyDescriptor;var xt=Object.getOwnPropertyNames;var Ut=Object.prototype.hasOwnProperty;var Tt=(t,e)=>{for(var o in e)k(t,o,{get:e[o],enumerable:!0})},It=(t,e,o,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of xt(e))!Ut.call(t,n)&&n!==o&&k(t,n,{get:()=>e[n],enumerable:!(a=ht(e,n))||a.enumerable});return t};var vt=t=>It(k({},"__esModule",{value:!0}),t);var Ht={};Tt(Ht,{abortAllDownloads:()=>S,abortDownload:()=>N,default:()=>jt,deleteAllFiles:()=>st,deleteFile:()=>W,emit:()=>d,getAllStatus:()=>nt,getStatus:()=>rt,getStorageEstimate:()=>h,isDownloading:()=>J,isMonitoring:()=>Q,isOnline:()=>x,isPersistentStorage:()=>H,isReady:()=>at,off:()=>L,on:()=>M,once:()=>Y,registerFile:()=>q,registerFiles:()=>ot,requestPersistentStorage:()=>j,retrieve:()=>St,retryFailed:()=>Z,startDownloads:()=>z,startMonitoring:()=>tt,stopDownloads:()=>V,stopMonitoring:()=>C});var ut="offline-data-manager",dt=1,_=null,i={REGISTRY:"registry",DOWNLOAD_QUEUE:"downloadQueue"};async function ct(t,e){ut=t??"offline-data-manager",dt=e??1}async function I(){return _||(_=await new Promise((t,e)=>{let o=indexedDB.open(ut,dt);o.onupgradeneeded=a=>{let n=a.target.result;if(!n.objectStoreNames.contains(i.REGISTRY)){let r=n.createObjectStore(i.REGISTRY,{keyPath:"id"});r.createIndex("protected","protected",{unique:!1}),r.createIndex("priority","priority",{unique:!1})}if(!n.objectStoreNames.contains(i.DOWNLOAD_QUEUE)){let r=n.createObjectStore(i.DOWNLOAD_QUEUE,{keyPath:"id"});r.createIndex("status","status",{unique:!1}),r.createIndex("priority","priority",{unique:!1})}},o.onsuccess=()=>t(o.result),o.onerror=()=>e(o.error)}),_)}async function p(t,e){let o=await I();return new Promise((a,n)=>{let r=o.transaction(t,"readonly").objectStore(t).get(e);r.onsuccess=()=>a(r.result),r.onerror=()=>n(r.error)})}async function y(t){let e=await I();return new Promise((o,a)=>{let n=e.transaction(t,"readonly").objectStore(t).getAll();n.onsuccess=()=>o(n.result),n.onerror=()=>a(n.error)})}async function P(t){let e=await I();return new Promise((o,a)=>{let n=e.transaction(t,"readonly").objectStore(t).getAllKeys();n.onsuccess=()=>o(n.result),n.onerror=()=>a(n.error)})}async function g(t,e){let o=await I();return new Promise((a,n)=>{let r=o.transaction(t,"readwrite").objectStore(t).put(e);r.onsuccess=()=>a(),r.onerror=()=>n(r.error)})}async function O(t,e){let o=await I();return new Promise((a,n)=>{let r=o.transaction(t,"readwrite").objectStore(t).delete(e);r.onsuccess=()=>a(),r.onerror=()=>n(r.error)})}var v=new Map;function M(t,e){return v.has(t)||v.set(t,new Set),v.get(t).add(e),()=>L(t,e)}function L(t,e){v.get(t)?.delete(e)}function d(t,e){v.get(t)?.forEach(o=>{try{o(e)}catch(a){console.error(`[offline-data-manager] Error in "${t}" listener:`,a)}})}function Y(t,e){let o=a=>{e(a),L(t,o)};M(t,o)}async function h(){if(!navigator?.storage?.estimate)return{usage:0,quota:1/0,available:1/0};let{usage:t=0,quota:e=1/0}=await navigator.storage.estimate();return{usage:t,quota:e,available:e-t}}async function ft(t){let{available:e,quota:o}=await h();return e-o*.1>=t}async function j(){return navigator?.storage?.persist?navigator.storage.persist():!1}async function H(){return navigator?.storage?.persisted?navigator.storage.persisted():!1}function G(t){return t===1/0?"\u221E":t<1024?`${t} B`:t<1024**2?`${(t/1024).toFixed(1)} KB`:t<1024**3?`${(t/1024**2).toFixed(1)} MB`:`${(t/1024**3).toFixed(2)} GB`}var X=null,K=null,B=!1;function pt(){d("connectivity",{online:!1}),X?.()}function wt(){d("connectivity",{online:!0}),K?.()}function mt({pauseAll:t,resumeAll:e}){B||(X=t,K=e,window.addEventListener("offline",pt),window.addEventListener("online",wt),B=!0)}function C(){window.removeEventListener("offline",pt),window.removeEventListener("online",wt),X=null,K=null,B=!1}function x(){return navigator.onLine??!0}function Q(){return B}var Lt=2*1024*1024,Nt=5*1024*1024,_t=2,yt=5,Pt=1e3,E=new Map,b=!1,F=null;function gt(){return new Promise(t=>{F=t})}function U(){if(F){let t=F;F=null,t()}}var Mt=t=>new Promise(e=>setTimeout(e,t)),Gt=t=>Pt*Math.pow(2,t);async function m(t,e){let o=await p(i.DOWNLOAD_QUEUE,t);o&&await g(i.DOWNLOAD_QUEUE,{...o,...e})}async function Bt(t,e){try{let o=await fetch(t,{method:"HEAD",signal:e}),a=o.headers.get("Accept-Ranges")==="bytes",n=o.headers.get("Content-Encoding"),r=!!n&&n!=="identity",s=o.headers.get("Content-Length"),l=s&&!r?parseInt(s,10):null,c=Et(o.headers.get("Content-Type"));return{supportsRange:a,totalBytes:l,mimeType:c}}catch{return{supportsRange:!1,totalBytes:null,mimeType:null}}}function Et(t){return t&&t.split(";")[0].trim()||null}function Dt(t){let e=t.reduce((n,r)=>n+r.byteLength,0),o=new Uint8Array(e),a=0;for(let n of t)o.set(n,a),a+=n.byteLength;return o}async function Ct(t){let{id:e,downloadUrl:o,ttl:a}=t,n=new AbortController;E.set(e,n);let r=await p(i.DOWNLOAD_QUEUE,e),s=r?.retryCount??0;for(;s<=yt;)try{await m(e,{status:u.IN_PROGRESS,lastAttemptAt:Date.now(),retryCount:s,errorMessage:null}),d("status",{id:e,status:u.IN_PROGRESS}),r=await p(i.DOWNLOAD_QUEUE,e);let l=r?.byteOffset??0,c=!1,f=r?.totalBytes??t.totalBytes??null,w=t.mimeType??null;if(l===0){let R=await Bt(o,n.signal);c=R.supportsRange,R.totalBytes&&(f=R.totalBytes,await m(e,{totalBytes:f})),!w&&R.mimeType&&(w=R.mimeType)}else c=!0;let D=c&&f&&f>Nt,A,T=null;if(D)A=await Ft(e,o,l,f,n.signal);else{let R=await Qt(e,o,n.signal);A=R.uint8,T=R.mimeType}let it=w??T??"application/octet-stream",$=A.buffer,lt=Date.now(),Ot=At(lt,a);await m(e,{status:u.COMPLETE,data:$,mimeType:it,bytesDownloaded:$.byteLength,byteOffset:$.byteLength,completedAt:lt,expiresAt:Ot,errorMessage:null,deferredReason:null}),d("complete",{id:e,mimeType:it}),E.delete(e);return}catch(l){if(l.name==="AbortError"){await m(e,{status:u.PAUSED}),d("status",{id:e,status:u.PAUSED}),E.delete(e);return}if(s++,s>yt){await m(e,{status:u.FAILED,retryCount:s,errorMessage:l.message}),d("error",{id:e,error:l,retryCount:s}),E.delete(e);return}let c=Gt(s-1);console.warn(`[offline-data-manager] "${e}" failed (attempt ${s}), retrying in ${c}ms:`,l.message),d("error",{id:e,error:l,retryCount:s,willRetry:!0}),await m(e,{status:u.PENDING,retryCount:s,errorMessage:l.message}),await Mt(c)}}async function Qt(t,e,o){let a=await fetch(e,{signal:o});if(!a.ok)throw new Error(`HTTP ${a.status} ${a.statusText}`);let n=a.headers.get("Content-Encoding"),r=!!n&&n!=="identity",s=a.headers.get("Content-Length"),l=s&&!r?parseInt(s,10):null,c=Et(a.headers.get("Content-Type")),f=a.body.getReader(),w=[],D=0;for(;;){let{done:A,value:T}=await f.read();if(A)break;w.push(T),D+=T.byteLength,await m(t,{bytesDownloaded:D,totalBytes:l}),d("progress",{id:t,bytesDownloaded:D,totalBytes:l,percent:l?Math.round(D/l*100):null})}return{uint8:Dt(w),mimeType:c}}async function Ft(t,e,o,a,n){let r=o,s=[],l=o;for(;r<a;){let c=Math.min(r+Lt-1,a-1),f=await fetch(e,{signal:n,headers:{Range:`bytes=${r}-${c}`}});if(!f.ok&&f.status!==206)throw new Error(`HTTP ${f.status} on Range bytes=${r}-${c}`);let w=new Uint8Array(await f.arrayBuffer());s.push(w),r+=w.byteLength,l+=w.byteLength,await m(t,{bytesDownloaded:l,byteOffset:r}),d("progress",{id:t,bytesDownloaded:l,totalBytes:a,percent:Math.round(l/a*100)})}return Dt(s)}async function qt(t){await Rt();let[e,o]=await Promise.all([y(i.REGISTRY),y(i.DOWNLOAD_QUEUE)]),a=new Map(e.map(l=>[l.id,l])),n=o.filter(l=>[u.PENDING,u.IN_PROGRESS,u.PAUSED,u.DEFERRED,u.EXPIRED].includes(l.status)).sort((l,c)=>(a.get(l.id)?.priority??10)-(a.get(c.id)?.priority??10));if(n.length===0)return;let r=[...n],s=new Set;await new Promise(l=>{function c(){if(!b){l();return}if(r.length===0){s.size===0&&l();return}if(s.size>=t)return;let f=r.shift(),w=a.get(f.id);if(!w){c();return}let D=(async()=>{let A=w.totalBytes??f.totalBytes??0;if(A>0&&!await ft(A)){await m(f.id,{status:u.DEFERRED,deferredReason:"insufficient-storage"}),d("deferred",{id:f.id,reason:"insufficient-storage"});return}await Ct(w)})().finally(()=>{s.delete(D),c()});s.add(D),c()}c()})}function z({concurrency:t=_t}={}){b||(b=!0,(async()=>{for(;b;){if(!x()){let e=await y(i.DOWNLOAD_QUEUE);for(let o of e)o.status===u.IN_PROGRESS&&(E.get(o.id)?.abort(),E.delete(o.id),await m(o.id,{status:u.PAUSED,deferredReason:"network-offline"}));d("connectivity",{online:!1}),await gt();continue}await qt(t),b&&await gt()}})())}async function V(){b=!1,U(),await S(),d("stopped",{})}async function Z(){let t=await y(i.DOWNLOAD_QUEUE);for(let e of t)e.status===u.FAILED&&await m(e.id,{status:u.PENDING,retryCount:0,errorMessage:null});U()}function J(){return b}async function N(t){E.get(t)?.abort(),E.delete(t)}async function S(){for(let[t,e]of E)e.abort(),E.delete(t)}function tt(){mt({pauseAll:S,resumeAll:U})}var u={PENDING:"pending",IN_PROGRESS:"in-progress",PAUSED:"paused",COMPLETE:"complete",EXPIRED:"expired",FAILED:"failed",DEFERRED:"deferred"},et=new Set([u.COMPLETE,u.EXPIRED]);function Wt(t){if(!t||typeof t!="object")throw new Error("Registry entry must be an object.");if(!t.id||typeof t.id!="string")throw new Error('Registry entry must have a string "id".');if(!t.downloadUrl||typeof t.downloadUrl!="string")throw new Error(`Entry "${t.id}" must have a string "downloadUrl".`);if(t.mimeType!==void 0&&t.mimeType!==null&&typeof t.mimeType!="string")throw new Error(`Entry "${t.id}" mimeType must be a string or omitted.`);if(typeof t.version!="number"||!Number.isInteger(t.version)||t.version<0)throw new Error(`Entry "${t.id}" version must be a non-negative integer.`);if(t.ttl!==void 0&&(typeof t.ttl!="number"||t.ttl<0))throw new Error(`Entry "${t.id}" ttl must be a non-negative number (seconds).`)}function bt(t){return{id:t,status:u.PENDING,data:null,bytesDownloaded:0,totalBytes:null,byteOffset:0,retryCount:0,lastAttemptAt:null,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}}function At(t,e){return e?t+e*1e3:null}function $t(t){return t?Date.now()>=t:!1}async function q(t){Wt(t);let e=Date.now(),o=await p(i.REGISTRY,t.id),a=await p(i.DOWNLOAD_QUEUE,t.id),n={id:t.id,downloadUrl:t.downloadUrl,mimeType:t.mimeType??null,version:t.version,protected:t.protected??!1,priority:t.priority??10,ttl:t.ttl??0,totalBytes:t.totalBytes??null,metadata:t.metadata??{},registeredAt:o?.registeredAt??e,updatedAt:e};if(o){if(t.version>o.version){await g(i.REGISTRY,n);let r=a?{...a,status:u.PENDING,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}:bt(t.id);await g(i.DOWNLOAD_QUEUE,r),d("registered",{id:t.id,reason:"version-updated"}),U()}return}await g(i.REGISTRY,n),await g(i.DOWNLOAD_QUEUE,bt(t.id)),d("registered",{id:t.id,reason:"new"}),U()}async function ot(t){if(!Array.isArray(t))throw new Error("registerFiles expects an array.");let e=new Set(t.map(n=>n.id)),o=await y(i.REGISTRY),a=[];for(let n of o)!e.has(n.id)&&!n.protected&&(await O(i.REGISTRY,n.id),await O(i.DOWNLOAD_QUEUE,n.id),a.push(n.id),d("deleted",{id:n.id,registryRemoved:!0}));for(let n of t)await q(n);return{registered:t.map(n=>n.id),removed:a}}async function Rt(){let t=await y(i.DOWNLOAD_QUEUE),e=[];for(let o of t)o.status===u.COMPLETE&&$t(o.expiresAt)&&(await g(i.DOWNLOAD_QUEUE,{...o,status:u.EXPIRED}),e.push(o.id),d("expired",{id:o.id}));return e}async function nt(){let[t,e,o]=await Promise.all([y(i.REGISTRY),y(i.DOWNLOAD_QUEUE),h()]),a=new Map(e.map(r=>[r.id,r]));return{items:t.map(r=>{let s=a.get(r.id)??null;return{id:r.id,downloadUrl:r.downloadUrl,mimeType:r.mimeType,version:r.version,protected:r.protected,priority:r.priority,ttl:r.ttl,totalBytes:r.totalBytes,metadata:r.metadata,registeredAt:r.registeredAt,updatedAt:r.updatedAt,downloadStatus:s?.status??null,bytesDownloaded:s?.bytesDownloaded??0,storedBytes:s?.data?.length??null,progress:s?.totalBytes&&s?.bytesDownloaded?Math.round(s.bytesDownloaded/s.totalBytes*100):null,retryCount:s?.retryCount??0,lastAttemptAt:s?.lastAttemptAt??null,errorMessage:s?.errorMessage??null,deferredReason:s?.deferredReason??null,completedAt:s?.completedAt??null,expiresAt:s?.expiresAt??null}}).sort((r,s)=>r.priority-s.priority),storage:{usageBytes:o.usage,quotaBytes:o.quota,availableBytes:o.available,usageFormatted:G(o.usage),quotaFormatted:G(o.quota),availableFormatted:G(o.available)}}}async function rt(t){let[e,o]=await Promise.all([p(i.REGISTRY,t),p(i.DOWNLOAD_QUEUE,t)]);return e?{id:e.id,downloadUrl:e.downloadUrl,mimeType:e.mimeType??null,version:e.version,protected:e.protected,priority:e.priority,ttl:e.ttl,totalBytes:e.totalBytes,metadata:e.metadata,registeredAt:e.registeredAt,updatedAt:e.updatedAt,downloadStatus:o?.status??null,bytesDownloaded:o?.bytesDownloaded??0,storedBytes:o?.data?.length??null,progress:o?.totalBytes&&o?.bytesDownloaded?Math.round(o.bytesDownloaded/o.totalBytes*100):null,retryCount:o?.retryCount??0,lastAttemptAt:o?.lastAttemptAt??null,errorMessage:o?.errorMessage??null,deferredReason:o?.deferredReason??null,completedAt:o?.completedAt??null,expiresAt:o?.expiresAt??null}:null}async function at(t){let e=await p(i.DOWNLOAD_QUEUE,t);return et.has(e?.status)}async function kt(t){let e=await p(i.DOWNLOAD_QUEUE,t);e&&await g(i.DOWNLOAD_QUEUE,{...e,status:u.PENDING,data:null,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null})}async function W(t,{removeRegistry:e=!1}={}){let o=await p(i.REGISTRY,t);if(!o)throw new Error(`deleteFile: No registered file with id "${t}".`);await N(t);let a=e||!o.protected;return a?(await O(i.REGISTRY,t),await O(i.DOWNLOAD_QUEUE,t)):await kt(t),d("deleted",{id:t,registryRemoved:a}),{id:t,registryRemoved:a}}async function st({removeRegistry:t=!1}={}){await S();let e=await P(i.REGISTRY);return Promise.all(e.map(o=>W(o,{removeRegistry:t})))}async function St(t){let[e,o]=await Promise.all([p(i.REGISTRY,t),p(i.DOWNLOAD_QUEUE,t)]);if(!e)throw new Error(`retrieve: No registered file with id "${t}".`);if(!et.has(o?.status)||!o?.data)throw new Error(`retrieve: File "${t}" has no data yet (status: ${o?.status??"unknown"}).`);return{data:o.data,mimeType:o.mimeType}}var Yt={setDBInfo:ct,dbGetAllIds:P,registerFile:q,registerFiles:ot,startDownloads:z,stopDownloads:V,retryFailed:Z,isDownloading:J,abortDownload:N,abortAllDownloads:S,startMonitoring:tt,stopMonitoring:C,isOnline:x,isMonitoring:Q,retrieve:St,getAllStatus:nt,getStatus:rt,isReady:at,delete:W,deleteAll:st,on:M,off:L,once:Y,getStorageEstimate:h,requestPersistentStorage:j,isPersistentStorage:H},jt=Yt;return vt(Ht);})();
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ declare namespace OfflineDataManager {
|
|
|
15
15
|
export { isOnline };
|
|
16
16
|
export { isMonitoring };
|
|
17
17
|
export { retrieve };
|
|
18
|
-
export {
|
|
18
|
+
export { getAllStatus };
|
|
19
19
|
export { getStatus };
|
|
20
20
|
export { isReady };
|
|
21
21
|
export { deleteFile as delete };
|
|
@@ -54,7 +54,7 @@ export function retrieve(id: string): Promise<{
|
|
|
54
54
|
data: ArrayBuffer;
|
|
55
55
|
mimeType: string;
|
|
56
56
|
}>;
|
|
57
|
-
import {
|
|
57
|
+
import { getAllStatus } from './registry.js';
|
|
58
58
|
import { getStatus } from './registry.js';
|
|
59
59
|
import { isReady } from './registry.js';
|
|
60
60
|
import { deleteFile } from './deleter.js';
|
|
@@ -68,4 +68,4 @@ import { requestPersistentStorage } from './storage.js';
|
|
|
68
68
|
import { isPersistentStorage } from './storage.js';
|
|
69
69
|
import { setDBInfo } from './db.js';
|
|
70
70
|
import { dbGetAllIds } from './db.js';
|
|
71
|
-
export { registerFile, registerFiles, startDownloads, stopDownloads, retryFailed, isDownloading, abortDownload, abortAllDownloads, startMonitoring, stopMonitoring, isOnline, isMonitoring,
|
|
71
|
+
export { registerFile, registerFiles, startDownloads, stopDownloads, retryFailed, isDownloading, abortDownload, abortAllDownloads, startMonitoring, stopMonitoring, isOnline, isMonitoring, getAllStatus, getStatus, isReady, deleteFile, deleteAllFiles, on, off, once, emit, getStorageEstimate, requestPersistentStorage, isPersistentStorage };
|
package/types/registry.d.ts
CHANGED