offline-data-manager 1.0.8 → 1.0.9

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.
@@ -1 +1 @@
1
- var z="offline-data-manager",V=1,_=null,i={REGISTRY:"registry",DOWNLOAD_QUEUE:"downloadQueue"};async function Z(e,t){z=e??"offline-data-manager",V=t??1}async function U(){return _||(_=await new Promise((e,t)=>{let r=indexedDB.open(z,V);r.onupgradeneeded=a=>{let o=a.target.result;if(!o.objectStoreNames.contains(i.REGISTRY)){let n=o.createObjectStore(i.REGISTRY,{keyPath:"id"});n.createIndex("protected","protected",{unique:!1}),n.createIndex("priority","priority",{unique:!1})}if(!o.objectStoreNames.contains(i.DOWNLOAD_QUEUE)){let n=o.createObjectStore(i.DOWNLOAD_QUEUE,{keyPath:"id"});n.createIndex("status","status",{unique:!1}),n.createIndex("priority","priority",{unique:!1})}},r.onsuccess=()=>e(r.result),r.onerror=()=>t(r.error)}),_)}async function p(e,t){let r=await U();return new Promise((a,o)=>{let n=r.transaction(e,"readonly").objectStore(e).get(t);n.onsuccess=()=>a(n.result),n.onerror=()=>o(n.error)})}async function E(e){let t=await U();return new Promise((r,a)=>{let o=t.transaction(e,"readonly").objectStore(e).getAll();o.onsuccess=()=>r(o.result),o.onerror=()=>a(o.error)})}async function L(e){let t=await U();return new Promise((r,a)=>{let o=t.transaction(e,"readonly").objectStore(e).getAllKeys();o.onsuccess=()=>r(o.result),o.onerror=()=>a(o.error)})}async function y(e,t){let r=await U();return new Promise((a,o)=>{let n=r.transaction(e,"readwrite").objectStore(e).put(t);n.onsuccess=()=>a(),n.onerror=()=>o(n.error),n.onerror=()=>o(n.error)})}async function S(e,t){let r=await U();return new Promise((a,o)=>{let n=r.transaction(e,"readwrite").objectStore(e).delete(t);n.onsuccess=()=>a(),n.onerror=()=>o(n.error)})}var T=new Map;function C(e,t){return T.has(e)||T.set(e,new Set),T.get(e).add(t),()=>N(e,t)}function N(e,t){T.get(e)?.delete(t)}function u(e,t){T.get(e)?.forEach(r=>{try{r(t)}catch(a){console.error(`[offline-data-manager] Error in "${e}" listener:`,a)}})}function J(e,t){let r=a=>{t(a),N(e,r)};C(e,r)}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 ee(e){let{available:t,quota:r}=await I();return t-r*.1>=e}async function te(){return navigator?.storage?.persist?navigator.storage.persist():!1}async function re(){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,Se=!0;function ne(){u("connectivity",{online:!1}),F?.()}function oe(){u("connectivity",{online:!0}),q?.()}function ae({pauseAll:e,resumeAll:t}){M||!window||(F=e,q=t,window&&(window.addEventListener("offline",ne),window.addEventListener("online",oe)),M=!0)}function W(){window&&(window.removeEventListener("offline",ne),window.removeEventListener("online",oe)),F=null,q=null,M=!1}function v(){return window?navigator.onLine??!0:Se}function $(){return M}var he=2*1024*1024,Oe=5*1024*1024,xe=2,ie=5,Ue=1e3,g=new Map,b=!1,G=null;function se(){return new Promise(e=>{G=e})}function h(){if(G){let e=G;G=null,e()}}var Te=e=>new Promise(t=>setTimeout(t,e)),Ie=e=>Ue*Math.pow(2,e);async function m(e,t){let r=await p(i.DOWNLOAD_QUEUE,e);r&&await y(i.DOWNLOAD_QUEUE,{...r,...t})}async function ve(e,t){try{let r=await fetch(e,{method:"HEAD",signal:t}),a=r.headers.get("Accept-Ranges")==="bytes",o=r.headers.get("Content-Encoding"),n=!!o&&o!=="identity",s=r.headers.get("Content-Length"),l=s&&!n?parseInt(s,10):null,c=le(r.headers.get("Content-Type"));return{supportsRange:a,totalBytes:l,mimeType:c}}catch{return{supportsRange:!1,totalBytes:null,mimeType:null}}}function le(e){return e&&e.split(";")[0].trim()||null}function ue(e){let t=e.reduce((o,n)=>o+n.byteLength,0),r=new Uint8Array(t),a=0;for(let o of e)r.set(o,a),a+=o.byteLength;return r}async function _e(e){let{id:t,downloadUrl:r,ttl:a}=e,o=new AbortController;g.set(t,o);let n=await p(i.DOWNLOAD_QUEUE,t),s=n?.retryCount??0;for(;s<=ie;)try{await m(t,{status:d.IN_PROGRESS,lastAttemptAt:Date.now(),retryCount:s,errorMessage:null}),u("status",{id:t,status:d.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 ve(r,o.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,r,l,f,o.signal);else{let R=await Le(t,r,o.signal);A=R.uint8,x=R.mimeType}let X=w??x??"application/octet-stream",Q=A.buffer,K=Date.now(),be=we(K,a);await m(t,{status:d.COMPLETE,data:Q,mimeType:X,bytesDownloaded:Q.byteLength,byteOffset:Q.byteLength,completedAt:K,expiresAt:be,errorMessage:null,deferredReason:null}),u("complete",{id:t,mimeType:X}),g.delete(t);return}catch(l){if(l?.name==="QuotaExceededError"){await Y(),await m(t,{status:d.DEFERRED,deferredReason:"insufficient-storage"}),u("error",{id:t,reason:"insufficient-storage",willRetry:!1});return}else if(l?.name==="AbortError"){await m(t,{status:d.PAUSED}),u("status",{id:t,status:d.PAUSED}),g.delete(t);return}if(s++,s>ie){await m(t,{status:d.FAILED,retryCount:s,errorMessage:l.message}),u("error",{id:t,error:l,retryCount:s}),g.delete(t);return}let c=Ie(s-1);console.warn(`[offline-data-manager] "${t}" failed (attempt ${s}), retrying in ${c}ms:`,l.message),u("error",{id:t,error:l,retryCount:s,willRetry:!0}),await m(t,{status:d.PENDING,retryCount:s,errorMessage:l.message}),await Te(c)}}async function Le(e,t,r){let a=await fetch(t,{signal:r});if(!a.ok)throw new Error(`HTTP ${a.status} ${a.statusText}`);let o=a.headers.get("Content-Encoding"),n=!!o&&o!=="identity",s=a.headers.get("Content-Length"),l=s&&!n?parseInt(s,10):null,c=le(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}),u("progress",{id:e,bytesDownloaded:D,totalBytes:l,percent:l?Math.round(D/l*100):null})}return{uint8:ue(w),mimeType:c}}async function Ne(e,t,r,a,o){let n=r,s=[],l=r;for(;n<a;){let c=Math.min(n+he-1,a-1),f=await fetch(t,{signal:o,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}),u("progress",{id:e,bytesDownloaded:l,totalBytes:a,percent:Math.round(l/a*100)})}return ue(s)}async function Pe(e){await me();let[t,r]=await Promise.all([E(i.REGISTRY),E(i.DOWNLOAD_QUEUE)]),a=new Map(t.map(l=>[l.id,l])),o=r.filter(l=>[d.PENDING,d.IN_PROGRESS,d.PAUSED,d.DEFERRED,d.EXPIRED].includes(l.status)).sort((l,c)=>(a.get(l.id)?.priority??10)-(a.get(c.id)?.priority??10));if(o.length===0)return;let n=[...o],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 ee(A)){await m(f.id,{status:d.DEFERRED,deferredReason:"insufficient-storage"}),u("deferred",{id:f.id,reason:"insufficient-storage"});return}await _e(w)})().finally(()=>{s.delete(D),c()});s.add(D),c()}c()})}function de({concurrency:e=xe}={}){b||(b=!0,(async()=>{for(;b;){if(!v()){let t=await E(i.DOWNLOAD_QUEUE);for(let r of t)r.status===d.IN_PROGRESS&&(g.get(r.id)?.abort(),g.delete(r.id),await m(r.id,{status:d.PAUSED,deferredReason:"network-offline"}));u("connectivity",{online:!1}),await se();continue}await Pe(e),b&&await se()}})())}async function Y(){b=!1,h(),await O(),u("stopped",{})}async function ce(){let e=await E(i.DOWNLOAD_QUEUE);for(let t of e)t.status===d.FAILED&&await m(t.id,{status:d.PENDING,retryCount:0,errorMessage:null});h()}function fe(){return b}async function B(e){g.get(e)?.abort(),g.delete(e)}async function O(){for(let[e,t]of g)t.abort(),g.delete(e)}function pe(){ae({pauseAll:O,resumeAll:h})}var d={PENDING:"pending",IN_PROGRESS:"in-progress",PAUSED:"paused",COMPLETE:"complete",EXPIRED:"expired",FAILED:"failed",DEFERRED:"deferred"},k=new Set([d.COMPLETE,d.EXPIRED]);function Me(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:d.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 Ge(e){return e?Date.now()>=e:!1}async function j(e){try{Me(e);let t=Date.now(),r=await p(i.REGISTRY,e.id),a=await p(i.DOWNLOAD_QUEUE,e.id),o={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:r?.registeredAt??t,updatedAt:t};if(r){if(e.version>r.version){await y(i.REGISTRY,o);let n=a?{...a,status:d.PENDING,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}:ye(e.id);await y(i.DOWNLOAD_QUEUE,n),u("registered",{id:e.id,reason:"version-updated"}),h()}return}await y(i.REGISTRY,o),await y(i.DOWNLOAD_QUEUE,ye(e.id)),u("registered",{id:e.id,reason:"new"}),h()}catch(t){if(t?.name==="QuotaExceededError"){u("error",{id,reason:"insufficient-storage",willRetry:!1});return}else u("error",{id,reason:t?.message??t,willRetry:!1})}}async function Ee(e){if(!Array.isArray(e))throw new Error("registerFiles expects an array.");let t=new Set(e.map(o=>o.id)),r=await E(i.REGISTRY),a=[];for(let o of r)!t.has(o.id)&&!o.protected&&(await S(i.REGISTRY,o.id),await S(i.DOWNLOAD_QUEUE,o.id),a.push(o.id),u("deleted",{id:o.id,registryRemoved:!0}));for(let o of e)await j(o);return{registered:e.map(o=>o.id),removed:a}}async function Be(e,t){try{if(e&&t){let r=await p(i.REGISTRY,entry.id);r&&(r.metadata={...r.metadata??{},...t},await y(i.REGISTRY,r))}}catch(r){if(r?.name==="QuotaExceededError"){u("error",{id:e,reason:"insufficient-storage",willRetry:!1});return}else u("error",{id:e,reason:r?.message??r,willRetry:!1})}}async function me(){let e=await E(i.DOWNLOAD_QUEUE),t=[];for(let r of e)r.status===d.COMPLETE&&Ge(r.expiresAt)&&(await y(i.DOWNLOAD_QUEUE,{...r,status:d.EXPIRED}),t.push(r.id),u("expired",{id:r.id}));return t}async function ge(){let[e,t,r]=await Promise.all([E(i.REGISTRY),E(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:r.usage,quotaBytes:r.quota,availableBytes:r.available,usageFormatted:P(r.usage),quotaFormatted:P(r.quota),availableFormatted:P(r.available)}}}async function De(e){let[t,r]=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:r?.status??null,bytesDownloaded:r?.bytesDownloaded??0,storedBytes:r?.data?.length??null,progress:r?.totalBytes&&r?.bytesDownloaded?Math.round(r.bytesDownloaded/r.totalBytes*100):null,retryCount:r?.retryCount??0,lastAttemptAt:r?.lastAttemptAt??null,errorMessage:r?.errorMessage??null,deferredReason:r?.deferredReason??null,completedAt:r?.completedAt??null,expiresAt:r?.expiresAt??null}:null}async function Ae(e){let t=await p(i.DOWNLOAD_QUEUE,e);return k.has(t?.status)}async function Qe(e){let t=await p(i.DOWNLOAD_QUEUE,e);t&&await y(i.DOWNLOAD_QUEUE,{...t,status:d.PENDING,data:null,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null})}async function H(e,{removeProtected:t=!1}={}){let r=await p(i.REGISTRY,e);if(!r)throw new Error(`deleteFile: No registered file with id "${e}".`);await B(e);let a=t||!r.protected;return a?(await S(i.REGISTRY,e),await S(i.DOWNLOAD_QUEUE,e)):await Qe(e),u("deleted",{id:e,registryRemoved:a}),{id:e,registryRemoved:a}}async function Re({removeProtected:e=!1}={}){await O();let t=await L(i.REGISTRY);return Promise.all(t.map(r=>H(r,{removeProtected:e})))}async function Ce(e){let[t,r]=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(r?.status)||!r?.data)throw new Error(`retrieve: File "${e}" has no data yet (status: ${r?.status??"unknown"}).`);return{data:r.data,mimeType:r.mimeType}}var Fe={setDBInfo:Z,dbGetAllIds:L,registerFile:j,registerFiles:Ee,startDownloads:de,stopDownloads:Y,retryFailed:ce,isDownloading:fe,abortDownload:B,abortAllDownloads:O,startMonitoring:pe,stopMonitoring:W,isOnline:v,isMonitoring:$,retrieve:Ce,getAllStatus:ge,getStatus:De,isReady:Ae,delete:H,deleteAll:Re,on:C,off:N,once:J,getStorageEstimate:I,requestPersistentStorage:te,isPersistentStorage:re},Et=Fe;export{O as abortAllDownloads,B as abortDownload,Et as default,Re as deleteAllFiles,H as deleteFile,u as emit,ge as getAllStatus,De as getStatus,I as getStorageEstimate,fe as isDownloading,$ as isMonitoring,v as isOnline,re as isPersistentStorage,Ae as isReady,N as off,C as on,J as once,j as registerFile,Ee as registerFiles,te as requestPersistentStorage,Ce as retrieve,ce as retryFailed,de as startDownloads,pe as startMonitoring,Y as stopDownloads,W as stopMonitoring,Be as updateRegistryMetadata};
1
+ var V="offline-data-manager",Z=1,L=null,i={REGISTRY:"registry",DOWNLOAD_QUEUE:"downloadQueue"};async function J(e,t){V=e??"offline-data-manager",Z=t??1}async function U(){return L||(L=await new Promise((e,t)=>{let r=indexedDB.open(V,Z);r.onupgradeneeded=a=>{let o=a.target.result;if(!o.objectStoreNames.contains(i.REGISTRY)){let n=o.createObjectStore(i.REGISTRY,{keyPath:"id"});n.createIndex("protected","protected",{unique:!1}),n.createIndex("priority","priority",{unique:!1})}if(!o.objectStoreNames.contains(i.DOWNLOAD_QUEUE)){let n=o.createObjectStore(i.DOWNLOAD_QUEUE,{keyPath:"id"});n.createIndex("status","status",{unique:!1}),n.createIndex("priority","priority",{unique:!1})}},r.onsuccess=()=>e(r.result),r.onerror=()=>t(r.error)}),L)}async function p(e,t){let r=await U();return new Promise((a,o)=>{let n=r.transaction(e,"readonly").objectStore(e).get(t);n.onsuccess=()=>a(n.result),n.onerror=()=>o(n.error)})}async function E(e){let t=await U();return new Promise((r,a)=>{let o=t.transaction(e,"readonly").objectStore(e).getAll();o.onsuccess=()=>r(o.result),o.onerror=()=>a(o.error)})}async function N(e){let t=await U();return new Promise((r,a)=>{let o=t.transaction(e,"readonly").objectStore(e).getAllKeys();o.onsuccess=()=>r(o.result),o.onerror=()=>a(o.error)})}async function y(e,t){let r=await U();return new Promise((a,o)=>{let n=r.transaction(e,"readwrite").objectStore(e).put(t);n.onsuccess=()=>a(),n.onerror=()=>o(n.error),n.onerror=()=>o(n.error)})}async function S(e,t){let r=await U();return new Promise((a,o)=>{let n=r.transaction(e,"readwrite").objectStore(e).delete(t);n.onsuccess=()=>a(),n.onerror=()=>o(n.error)})}var T=new Map;function q(e,t){return T.has(e)||T.set(e,new Set),T.get(e).add(t),()=>P(e,t)}function P(e,t){T.get(e)?.delete(t)}function u(e,t){T.get(e)?.forEach(r=>{try{r(t)}catch(a){console.error(`[offline-data-manager] Error in "${e}" listener:`,a)}})}function ee(e,t){let r=a=>{t(a),P(e,r)};q(e,r)}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 te(e){let{available:t,quota:r}=await I();return t-r*.1>=e}async function re(){return navigator?.storage?.persist?navigator.storage.persist():!1}async function ne(){return navigator?.storage?.persisted?navigator.storage.persisted():!1}function M(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 G=null,B=null,v=!1,W=!0;function oe(){u("connectivity",{online:!1}),G?.()}function ae(){u("connectivity",{online:!0}),B?.()}function ie({pauseAll:e,resumeAll:t}){v||!window||(G=e,B=t,window&&(window.addEventListener("offline",oe),window.addEventListener("online",ae)),v=!0)}function $(){window&&(window.removeEventListener("offline",oe),window.removeEventListener("online",ae)),G=null,B=null,v=!1}function _(){return window?navigator.onLine??!0:W}function Y(){return v}function se(e){W=e,v&&(W?B?.():G?.())}var Oe=2*1024*1024,xe=5*1024*1024,Ue=2,le=5,Te=1e3,g=new Map,b=!1,C=null;function ue(){return new Promise(e=>{C=e})}function h(){if(C){let e=C;C=null,e()}}var Ie=e=>new Promise(t=>setTimeout(t,e)),ve=e=>Te*Math.pow(2,e);async function m(e,t){let r=await p(i.DOWNLOAD_QUEUE,e);r&&await y(i.DOWNLOAD_QUEUE,{...r,...t})}async function _e(e,t){try{let r=await fetch(e,{method:"HEAD",signal:t}),a=r.headers.get("Accept-Ranges")==="bytes",o=r.headers.get("Content-Encoding"),n=!!o&&o!=="identity",s=r.headers.get("Content-Length"),l=s&&!n?parseInt(s,10):null,c=de(r.headers.get("Content-Type"));return{supportsRange:a,totalBytes:l,mimeType:c}}catch{return{supportsRange:!1,totalBytes:null,mimeType:null}}}function de(e){return e&&e.split(";")[0].trim()||null}function ce(e){let t=e.reduce((o,n)=>o+n.byteLength,0),r=new Uint8Array(t),a=0;for(let o of e)r.set(o,a),a+=o.byteLength;return r}async function Le(e){let{id:t,downloadUrl:r,ttl:a}=e,o=new AbortController;g.set(t,o);let n=await p(i.DOWNLOAD_QUEUE,t),s=n?.retryCount??0;for(;s<=le;)try{await m(t,{status:d.IN_PROGRESS,lastAttemptAt:Date.now(),retryCount:s,errorMessage:null}),u("status",{id:t,status:d.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 _e(r,o.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>xe,A,x=null;if(D)A=await Pe(t,r,l,f,o.signal);else{let R=await Ne(t,r,o.signal);A=R.uint8,x=R.mimeType}let K=w??x??"application/octet-stream",F=A.buffer,z=Date.now(),he=ye(z,a);await m(t,{status:d.COMPLETE,data:F,mimeType:K,bytesDownloaded:F.byteLength,byteOffset:F.byteLength,completedAt:z,expiresAt:he,errorMessage:null,deferredReason:null}),u("complete",{id:t,mimeType:K}),g.delete(t);return}catch(l){if(l?.name==="QuotaExceededError"){await k(),await m(t,{status:d.DEFERRED,deferredReason:"insufficient-storage"}),u("error",{id:t,reason:"insufficient-storage",willRetry:!1});return}else if(l?.name==="AbortError"){await m(t,{status:d.PAUSED}),u("status",{id:t,status:d.PAUSED}),g.delete(t);return}if(s++,s>le){await m(t,{status:d.FAILED,retryCount:s,errorMessage:l.message}),u("error",{id:t,error:l,retryCount:s}),g.delete(t);return}let c=ve(s-1);console.warn(`[offline-data-manager] "${t}" failed (attempt ${s}), retrying in ${c}ms:`,l.message),u("error",{id:t,error:l,retryCount:s,willRetry:!0}),await m(t,{status:d.PENDING,retryCount:s,errorMessage:l.message}),await Ie(c)}}async function Ne(e,t,r){let a=await fetch(t,{signal:r});if(!a.ok)throw new Error(`HTTP ${a.status} ${a.statusText}`);let o=a.headers.get("Content-Encoding"),n=!!o&&o!=="identity",s=a.headers.get("Content-Length"),l=s&&!n?parseInt(s,10):null,c=de(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}),u("progress",{id:e,bytesDownloaded:D,totalBytes:l,percent:l?Math.round(D/l*100):null})}return{uint8:ce(w),mimeType:c}}async function Pe(e,t,r,a,o){let n=r,s=[],l=r;for(;n<a;){let c=Math.min(n+Oe-1,a-1),f=await fetch(t,{signal:o,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}),u("progress",{id:e,bytesDownloaded:l,totalBytes:a,percent:Math.round(l/a*100)})}return ce(s)}async function Me(e){await Ee();let[t,r]=await Promise.all([E(i.REGISTRY),E(i.DOWNLOAD_QUEUE)]),a=new Map(t.map(l=>[l.id,l])),o=r.filter(l=>[d.PENDING,d.IN_PROGRESS,d.PAUSED,d.DEFERRED,d.EXPIRED].includes(l.status)).sort((l,c)=>(a.get(l.id)?.priority??10)-(a.get(c.id)?.priority??10));if(o.length===0)return;let n=[...o],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 te(A)){await m(f.id,{status:d.DEFERRED,deferredReason:"insufficient-storage"}),u("deferred",{id:f.id,reason:"insufficient-storage"});return}await Le(w)})().finally(()=>{s.delete(D),c()});s.add(D),c()}c()})}function fe({concurrency:e=Ue}={}){b||(b=!0,(async()=>{for(;b;){if(!_()){let t=await E(i.DOWNLOAD_QUEUE);for(let r of t)r.status===d.IN_PROGRESS&&(g.get(r.id)?.abort(),g.delete(r.id),await m(r.id,{status:d.PAUSED,deferredReason:"network-offline"}));u("connectivity",{online:!1}),await ue();continue}await Me(e),b&&await ue()}})())}async function k(){b=!1,h(),await O(),u("stopped",{})}async function pe(){let e=await E(i.DOWNLOAD_QUEUE);for(let t of e)t.status===d.FAILED&&await m(t.id,{status:d.PENDING,retryCount:0,errorMessage:null});h()}function we(){return b}async function Q(e){g.get(e)?.abort(),g.delete(e)}async function O(){for(let[e,t]of g)t.abort(),g.delete(e)}function me(){ie({pauseAll:O,resumeAll:h})}var d={PENDING:"pending",IN_PROGRESS:"in-progress",PAUSED:"paused",COMPLETE:"complete",EXPIRED:"expired",FAILED:"failed",DEFERRED:"deferred"},j=new Set([d.COMPLETE,d.EXPIRED]);function Ge(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 ge(e){return{id:e,status:d.PENDING,data:null,bytesDownloaded:0,totalBytes:null,byteOffset:0,retryCount:0,lastAttemptAt:null,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}}function ye(e,t){return t?e+t*1e3:null}function Be(e){return e?Date.now()>=e:!1}async function H(e){try{Ge(e);let t=Date.now(),r=await p(i.REGISTRY,e.id),a=await p(i.DOWNLOAD_QUEUE,e.id),o={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:r?.registeredAt??t,updatedAt:t};if(r){if(e.version>r.version){await y(i.REGISTRY,o);let n=a?{...a,status:d.PENDING,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}:ge(e.id);await y(i.DOWNLOAD_QUEUE,n),u("registered",{id:e.id,reason:"version-updated"}),h()}return}await y(i.REGISTRY,o),await y(i.DOWNLOAD_QUEUE,ge(e.id)),u("registered",{id:e.id,reason:"new"}),h()}catch(t){if(t?.name==="QuotaExceededError"){u("error",{id,reason:"insufficient-storage",willRetry:!1});return}else u("error",{id,reason:t?.message??t,willRetry:!1})}}async function De(e){if(!Array.isArray(e))throw new Error("registerFiles expects an array.");let t=new Set(e.map(o=>o.id)),r=await E(i.REGISTRY),a=[];for(let o of r)!t.has(o.id)&&!o.protected&&(await S(i.REGISTRY,o.id),await S(i.DOWNLOAD_QUEUE,o.id),a.push(o.id),u("deleted",{id:o.id,registryRemoved:!0}));for(let o of e)await H(o);return{registered:e.map(o=>o.id),removed:a}}async function Ce(e,t){try{if(e&&t){let r=await p(i.REGISTRY,entry.id);r&&(r.metadata={...r.metadata??{},...t},await y(i.REGISTRY,r))}}catch(r){if(r?.name==="QuotaExceededError"){u("error",{id:e,reason:"insufficient-storage",willRetry:!1});return}else u("error",{id:e,reason:r?.message??r,willRetry:!1})}}async function Ee(){let e=await E(i.DOWNLOAD_QUEUE),t=[];for(let r of e)r.status===d.COMPLETE&&Be(r.expiresAt)&&(await y(i.DOWNLOAD_QUEUE,{...r,status:d.EXPIRED}),t.push(r.id),u("expired",{id:r.id}));return t}async function Ae(){let[e,t,r]=await Promise.all([E(i.REGISTRY),E(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:r.usage,quotaBytes:r.quota,availableBytes:r.available,usageFormatted:M(r.usage),quotaFormatted:M(r.quota),availableFormatted:M(r.available)}}}async function Re(e){let[t,r]=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:r?.status??null,bytesDownloaded:r?.bytesDownloaded??0,storedBytes:r?.data?.length??null,progress:r?.totalBytes&&r?.bytesDownloaded?Math.round(r.bytesDownloaded/r.totalBytes*100):null,retryCount:r?.retryCount??0,lastAttemptAt:r?.lastAttemptAt??null,errorMessage:r?.errorMessage??null,deferredReason:r?.deferredReason??null,completedAt:r?.completedAt??null,expiresAt:r?.expiresAt??null}:null}async function be(e){let t=await p(i.DOWNLOAD_QUEUE,e);return j.has(t?.status)}async function Qe(e){let t=await p(i.DOWNLOAD_QUEUE,e);t&&await y(i.DOWNLOAD_QUEUE,{...t,status:d.PENDING,data:null,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null})}async function X(e,{removeProtected:t=!1}={}){let r=await p(i.REGISTRY,e);if(!r)throw new Error(`deleteFile: No registered file with id "${e}".`);await Q(e);let a=t||!r.protected;return a?(await S(i.REGISTRY,e),await S(i.DOWNLOAD_QUEUE,e)):await Qe(e),u("deleted",{id:e,registryRemoved:a}),{id:e,registryRemoved:a}}async function Se({removeProtected:e=!1}={}){await O();let t=await N(i.REGISTRY);return Promise.all(t.map(r=>X(r,{removeProtected:e})))}async function Fe(e){let[t,r]=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(!j.has(r?.status)||!r?.data)throw new Error(`retrieve: File "${e}" has no data yet (status: ${r?.status??"unknown"}).`);return{data:r.data,mimeType:r.mimeType}}var qe={setDBInfo:J,dbGetAllIds:N,registerFile:H,registerFiles:De,startDownloads:fe,stopDownloads:k,retryFailed:pe,isDownloading:we,abortDownload:Q,abortAllDownloads:O,startMonitoring:me,stopMonitoring:$,isOnline:_,isMonitoring:Y,updateConnectivityStatus:se,retrieve:Fe,getAllStatus:Ae,getStatus:Re,isReady:be,delete:X,deleteAll:Se,on:q,off:P,once:ee,getStorageEstimate:I,requestPersistentStorage:re,isPersistentStorage:ne},Dt=qe;export{O as abortAllDownloads,Q as abortDownload,Dt as default,Se as deleteAllFiles,X as deleteFile,u as emit,Ae as getAllStatus,Re as getStatus,I as getStorageEstimate,we as isDownloading,Y as isMonitoring,_ as isOnline,ne as isPersistentStorage,be as isReady,P as off,q as on,ee as once,H as registerFile,De as registerFiles,re as requestPersistentStorage,Fe as retrieve,pe as retryFailed,fe as startDownloads,me as startMonitoring,k as stopDownloads,$ as stopMonitoring,se as updateConnectivityStatus,Ce as updateRegistryMetadata};
@@ -1 +1 @@
1
- "use strict";var offlineMapData=(()=>{var k=Object.defineProperty;var xe=Object.getOwnPropertyDescriptor;var Ue=Object.getOwnPropertyNames;var Te=Object.prototype.hasOwnProperty;var Ie=(e,t)=>{for(var r in t)k(e,r,{get:t[r],enumerable:!0})},ve=(e,t,r,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Ue(t))!Te.call(e,n)&&n!==r&&k(e,n,{get:()=>t[n],enumerable:!(a=xe(t,n))||a.enumerable});return e};var _e=e=>ve(k({},"__esModule",{value:!0}),e);var Ke={};Ie(Ke,{abortAllDownloads:()=>S,abortDownload:()=>L,default:()=>Xe,deleteAllFiles:()=>ie,deleteFile:()=>$,emit:()=>u,getAllStatus:()=>ne,getStatus:()=>oe,getStorageEstimate:()=>O,isDownloading:()=>J,isMonitoring:()=>C,isOnline:()=>x,isPersistentStorage:()=>X,isReady:()=>ae,off:()=>_,on:()=>M,once:()=>j,registerFile:()=>W,registerFiles:()=>re,requestPersistentStorage:()=>H,retrieve:()=>he,retryFailed:()=>Z,startDownloads:()=>V,startMonitoring:()=>ee,stopDownloads:()=>q,stopMonitoring:()=>Q,updateRegistryMetadata:()=>Se});var ue="offline-data-manager",de=1,N=null,i={REGISTRY:"registry",DOWNLOAD_QUEUE:"downloadQueue"};async function ce(e,t){ue=e??"offline-data-manager",de=t??1}async function I(){return N||(N=await new Promise((e,t)=>{let r=indexedDB.open(ue,de);r.onupgradeneeded=a=>{let n=a.target.result;if(!n.objectStoreNames.contains(i.REGISTRY)){let o=n.createObjectStore(i.REGISTRY,{keyPath:"id"});o.createIndex("protected","protected",{unique:!1}),o.createIndex("priority","priority",{unique:!1})}if(!n.objectStoreNames.contains(i.DOWNLOAD_QUEUE)){let o=n.createObjectStore(i.DOWNLOAD_QUEUE,{keyPath:"id"});o.createIndex("status","status",{unique:!1}),o.createIndex("priority","priority",{unique:!1})}},r.onsuccess=()=>e(r.result),r.onerror=()=>t(r.error)}),N)}async function p(e,t){let r=await I();return new Promise((a,n)=>{let o=r.transaction(e,"readonly").objectStore(e).get(t);o.onsuccess=()=>a(o.result),o.onerror=()=>n(o.error)})}async function E(e){let t=await I();return new Promise((r,a)=>{let n=t.transaction(e,"readonly").objectStore(e).getAll();n.onsuccess=()=>r(n.result),n.onerror=()=>a(n.error)})}async function P(e){let t=await I();return new Promise((r,a)=>{let n=t.transaction(e,"readonly").objectStore(e).getAllKeys();n.onsuccess=()=>r(n.result),n.onerror=()=>a(n.error)})}async function y(e,t){let r=await I();return new Promise((a,n)=>{let o=r.transaction(e,"readwrite").objectStore(e).put(t);o.onsuccess=()=>a(),o.onerror=()=>n(o.error),o.onerror=()=>n(o.error)})}async function h(e,t){let r=await I();return new Promise((a,n)=>{let o=r.transaction(e,"readwrite").objectStore(e).delete(t);o.onsuccess=()=>a(),o.onerror=()=>n(o.error)})}var v=new Map;function M(e,t){return v.has(e)||v.set(e,new Set),v.get(e).add(t),()=>_(e,t)}function _(e,t){v.get(e)?.delete(t)}function u(e,t){v.get(e)?.forEach(r=>{try{r(t)}catch(a){console.error(`[offline-data-manager] Error in "${e}" listener:`,a)}})}function j(e,t){let r=a=>{t(a),_(e,r)};M(e,r)}async function O(){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:r}=await O();return t-r*.1>=e}async function H(){return navigator?.storage?.persist?navigator.storage.persist():!1}async function X(){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 K=null,z=null,B=!1,Le=!0;function pe(){u("connectivity",{online:!1}),K?.()}function we(){u("connectivity",{online:!0}),z?.()}function me({pauseAll:e,resumeAll:t}){B||!window||(K=e,z=t,window&&(window.addEventListener("offline",pe),window.addEventListener("online",we)),B=!0)}function Q(){window&&(window.removeEventListener("offline",pe),window.removeEventListener("online",we)),K=null,z=null,B=!1}function x(){return window?navigator.onLine??!0:Le}function C(){return B}var Ne=2*1024*1024,Pe=5*1024*1024,Me=2,ye=5,Ge=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 Be=e=>new Promise(t=>setTimeout(t,e)),Qe=e=>Ge*Math.pow(2,e);async function m(e,t){let r=await p(i.DOWNLOAD_QUEUE,e);r&&await y(i.DOWNLOAD_QUEUE,{...r,...t})}async function Ce(e,t){try{let r=await fetch(e,{method:"HEAD",signal:t}),a=r.headers.get("Accept-Ranges")==="bytes",n=r.headers.get("Content-Encoding"),o=!!n&&n!=="identity",s=r.headers.get("Content-Length"),l=s&&!o?parseInt(s,10):null,c=ge(r.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,o)=>n+o.byteLength,0),r=new Uint8Array(t),a=0;for(let n of e)r.set(n,a),a+=n.byteLength;return r}async function Fe(e){let{id:t,downloadUrl:r,ttl:a}=e,n=new AbortController;g.set(t,n);let o=await p(i.DOWNLOAD_QUEUE,t),s=o?.retryCount??0;for(;s<=ye;)try{await m(t,{status:d.IN_PROGRESS,lastAttemptAt:Date.now(),retryCount:s,errorMessage:null}),u("status",{id:t,status:d.IN_PROGRESS}),o=await p(i.DOWNLOAD_QUEUE,t);let l=o?.byteOffset??0,c=!1,f=o?.totalBytes??e.totalBytes??null,w=e.mimeType??null;if(l===0){let R=await Ce(r,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>Pe,A,T=null;if(D)A=await We(t,r,l,f,n.signal);else{let R=await qe(t,r,n.signal);A=R.uint8,T=R.mimeType}let se=w??T??"application/octet-stream",Y=A.buffer,le=Date.now(),Oe=Ae(le,a);await m(t,{status:d.COMPLETE,data:Y,mimeType:se,bytesDownloaded:Y.byteLength,byteOffset:Y.byteLength,completedAt:le,expiresAt:Oe,errorMessage:null,deferredReason:null}),u("complete",{id:t,mimeType:se}),g.delete(t);return}catch(l){if(l?.name==="QuotaExceededError"){await q(),await m(t,{status:d.DEFERRED,deferredReason:"insufficient-storage"}),u("error",{id:t,reason:"insufficient-storage",willRetry:!1});return}else if(l?.name==="AbortError"){await m(t,{status:d.PAUSED}),u("status",{id:t,status:d.PAUSED}),g.delete(t);return}if(s++,s>ye){await m(t,{status:d.FAILED,retryCount:s,errorMessage:l.message}),u("error",{id:t,error:l,retryCount:s}),g.delete(t);return}let c=Qe(s-1);console.warn(`[offline-data-manager] "${t}" failed (attempt ${s}), retrying in ${c}ms:`,l.message),u("error",{id:t,error:l,retryCount:s,willRetry:!0}),await m(t,{status:d.PENDING,retryCount:s,errorMessage:l.message}),await Be(c)}}async function qe(e,t,r){let a=await fetch(t,{signal:r});if(!a.ok)throw new Error(`HTTP ${a.status} ${a.statusText}`);let n=a.headers.get("Content-Encoding"),o=!!n&&n!=="identity",s=a.headers.get("Content-Length"),l=s&&!o?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}),u("progress",{id:e,bytesDownloaded:D,totalBytes:l,percent:l?Math.round(D/l*100):null})}return{uint8:De(w),mimeType:c}}async function We(e,t,r,a,n){let o=r,s=[],l=r;for(;o<a;){let c=Math.min(o+Ne-1,a-1),f=await fetch(t,{signal:n,headers:{Range:`bytes=${o}-${c}`}});if(!f.ok&&f.status!==206)throw new Error(`HTTP ${f.status} on Range bytes=${o}-${c}`);let w=new Uint8Array(await f.arrayBuffer());s.push(w),o+=w.byteLength,l+=w.byteLength,await m(e,{bytesDownloaded:l,byteOffset:o}),u("progress",{id:e,bytesDownloaded:l,totalBytes:a,percent:Math.round(l/a*100)})}return De(s)}async function $e(e){await Re();let[t,r]=await Promise.all([E(i.REGISTRY),E(i.DOWNLOAD_QUEUE)]),a=new Map(t.map(l=>[l.id,l])),n=r.filter(l=>[d.PENDING,d.IN_PROGRESS,d.PAUSED,d.DEFERRED,d.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 o=[...n],s=new Set;await new Promise(l=>{function c(){if(!b){l();return}if(o.length===0){s.size===0&&l();return}if(s.size>=e)return;let f=o.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:d.DEFERRED,deferredReason:"insufficient-storage"}),u("deferred",{id:f.id,reason:"insufficient-storage"});return}await Fe(w)})().finally(()=>{s.delete(D),c()});s.add(D),c()}c()})}function V({concurrency:e=Me}={}){b||(b=!0,(async()=>{for(;b;){if(!x()){let t=await E(i.DOWNLOAD_QUEUE);for(let r of t)r.status===d.IN_PROGRESS&&(g.get(r.id)?.abort(),g.delete(r.id),await m(r.id,{status:d.PAUSED,deferredReason:"network-offline"}));u("connectivity",{online:!1}),await Ee();continue}await $e(e),b&&await Ee()}})())}async function q(){b=!1,U(),await S(),u("stopped",{})}async function Z(){let e=await E(i.DOWNLOAD_QUEUE);for(let t of e)t.status===d.FAILED&&await m(t.id,{status:d.PENDING,retryCount:0,errorMessage:null});U()}function J(){return b}async function L(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 d={PENDING:"pending",IN_PROGRESS:"in-progress",PAUSED:"paused",COMPLETE:"complete",EXPIRED:"expired",FAILED:"failed",DEFERRED:"deferred"},te=new Set([d.COMPLETE,d.EXPIRED]);function Ye(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:d.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 ke(e){return e?Date.now()>=e:!1}async function W(e){try{Ye(e);let t=Date.now(),r=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:r?.registeredAt??t,updatedAt:t};if(r){if(e.version>r.version){await y(i.REGISTRY,n);let o=a?{...a,status:d.PENDING,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}:be(e.id);await y(i.DOWNLOAD_QUEUE,o),u("registered",{id:e.id,reason:"version-updated"}),U()}return}await y(i.REGISTRY,n),await y(i.DOWNLOAD_QUEUE,be(e.id)),u("registered",{id:e.id,reason:"new"}),U()}catch(t){if(t?.name==="QuotaExceededError"){u("error",{id,reason:"insufficient-storage",willRetry:!1});return}else u("error",{id,reason:t?.message??t,willRetry:!1})}}async function re(e){if(!Array.isArray(e))throw new Error("registerFiles expects an array.");let t=new Set(e.map(n=>n.id)),r=await E(i.REGISTRY),a=[];for(let n of r)!t.has(n.id)&&!n.protected&&(await h(i.REGISTRY,n.id),await h(i.DOWNLOAD_QUEUE,n.id),a.push(n.id),u("deleted",{id:n.id,registryRemoved:!0}));for(let n of e)await W(n);return{registered:e.map(n=>n.id),removed:a}}async function Se(e,t){try{if(e&&t){let r=await p(i.REGISTRY,entry.id);r&&(r.metadata={...r.metadata??{},...t},await y(i.REGISTRY,r))}}catch(r){if(r?.name==="QuotaExceededError"){u("error",{id:e,reason:"insufficient-storage",willRetry:!1});return}else u("error",{id:e,reason:r?.message??r,willRetry:!1})}}async function Re(){let e=await E(i.DOWNLOAD_QUEUE),t=[];for(let r of e)r.status===d.COMPLETE&&ke(r.expiresAt)&&(await y(i.DOWNLOAD_QUEUE,{...r,status:d.EXPIRED}),t.push(r.id),u("expired",{id:r.id}));return t}async function ne(){let[e,t,r]=await Promise.all([E(i.REGISTRY),E(i.DOWNLOAD_QUEUE),O()]),a=new Map(t.map(o=>[o.id,o]));return{items:e.map(o=>{let s=a.get(o.id)??null;return{id:o.id,downloadUrl:o.downloadUrl,mimeType:o.mimeType,version:o.version,protected:o.protected,priority:o.priority,ttl:o.ttl,totalBytes:o.totalBytes,metadata:o.metadata,registeredAt:o.registeredAt,updatedAt:o.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((o,s)=>o.priority-s.priority),storage:{usageBytes:r.usage,quotaBytes:r.quota,availableBytes:r.available,usageFormatted:G(r.usage),quotaFormatted:G(r.quota),availableFormatted:G(r.available)}}}async function oe(e){let[t,r]=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:r?.status??null,bytesDownloaded:r?.bytesDownloaded??0,storedBytes:r?.data?.length??null,progress:r?.totalBytes&&r?.bytesDownloaded?Math.round(r.bytesDownloaded/r.totalBytes*100):null,retryCount:r?.retryCount??0,lastAttemptAt:r?.lastAttemptAt??null,errorMessage:r?.errorMessage??null,deferredReason:r?.deferredReason??null,completedAt:r?.completedAt??null,expiresAt:r?.expiresAt??null}:null}async function ae(e){let t=await p(i.DOWNLOAD_QUEUE,e);return te.has(t?.status)}async function je(e){let t=await p(i.DOWNLOAD_QUEUE,e);t&&await y(i.DOWNLOAD_QUEUE,{...t,status:d.PENDING,data:null,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null})}async function $(e,{removeProtected:t=!1}={}){let r=await p(i.REGISTRY,e);if(!r)throw new Error(`deleteFile: No registered file with id "${e}".`);await L(e);let a=t||!r.protected;return a?(await h(i.REGISTRY,e),await h(i.DOWNLOAD_QUEUE,e)):await je(e),u("deleted",{id:e,registryRemoved:a}),{id:e,registryRemoved:a}}async function ie({removeProtected:e=!1}={}){await S();let t=await P(i.REGISTRY);return Promise.all(t.map(r=>$(r,{removeProtected:e})))}async function he(e){let[t,r]=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(r?.status)||!r?.data)throw new Error(`retrieve: File "${e}" has no data yet (status: ${r?.status??"unknown"}).`);return{data:r.data,mimeType:r.mimeType}}var He={setDBInfo:ce,dbGetAllIds:P,registerFile:W,registerFiles:re,startDownloads:V,stopDownloads:q,retryFailed:Z,isDownloading:J,abortDownload:L,abortAllDownloads:S,startMonitoring:ee,stopMonitoring:Q,isOnline:x,isMonitoring:C,retrieve:he,getAllStatus:ne,getStatus:oe,isReady:ae,delete:$,deleteAll:ie,on:M,off:_,once:j,getStorageEstimate:O,requestPersistentStorage:H,isPersistentStorage:X},Xe=He;return _e(Ke);})();
1
+ "use strict";var offlineMapData=(()=>{var H=Object.defineProperty;var Te=Object.getOwnPropertyDescriptor;var Ie=Object.getOwnPropertyNames;var ve=Object.prototype.hasOwnProperty;var _e=(e,t)=>{for(var r in t)H(e,r,{get:t[r],enumerable:!0})},Le=(e,t,r,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Ie(t))!ve.call(e,n)&&n!==r&&H(e,n,{get:()=>t[n],enumerable:!(a=Te(t,n))||a.enumerable});return e};var Ne=e=>Le(H({},"__esModule",{value:!0}),e);var ze={};_e(ze,{abortAllDownloads:()=>S,abortDownload:()=>N,default:()=>Ke,deleteAllFiles:()=>le,deleteFile:()=>k,emit:()=>u,getAllStatus:()=>ae,getStatus:()=>ie,getStorageEstimate:()=>O,isDownloading:()=>te,isMonitoring:()=>q,isOnline:()=>x,isPersistentStorage:()=>z,isReady:()=>se,off:()=>_,on:()=>G,once:()=>X,registerFile:()=>Y,registerFiles:()=>oe,requestPersistentStorage:()=>K,retrieve:()=>xe,retryFailed:()=>ee,startDownloads:()=>J,startMonitoring:()=>re,stopDownloads:()=>$,stopMonitoring:()=>F,updateConnectivityStatus:()=>Z,updateRegistryMetadata:()=>Oe});var ce="offline-data-manager",fe=1,P=null,i={REGISTRY:"registry",DOWNLOAD_QUEUE:"downloadQueue"};async function pe(e,t){ce=e??"offline-data-manager",fe=t??1}async function I(){return P||(P=await new Promise((e,t)=>{let r=indexedDB.open(ce,fe);r.onupgradeneeded=a=>{let n=a.target.result;if(!n.objectStoreNames.contains(i.REGISTRY)){let o=n.createObjectStore(i.REGISTRY,{keyPath:"id"});o.createIndex("protected","protected",{unique:!1}),o.createIndex("priority","priority",{unique:!1})}if(!n.objectStoreNames.contains(i.DOWNLOAD_QUEUE)){let o=n.createObjectStore(i.DOWNLOAD_QUEUE,{keyPath:"id"});o.createIndex("status","status",{unique:!1}),o.createIndex("priority","priority",{unique:!1})}},r.onsuccess=()=>e(r.result),r.onerror=()=>t(r.error)}),P)}async function p(e,t){let r=await I();return new Promise((a,n)=>{let o=r.transaction(e,"readonly").objectStore(e).get(t);o.onsuccess=()=>a(o.result),o.onerror=()=>n(o.error)})}async function E(e){let t=await I();return new Promise((r,a)=>{let n=t.transaction(e,"readonly").objectStore(e).getAll();n.onsuccess=()=>r(n.result),n.onerror=()=>a(n.error)})}async function M(e){let t=await I();return new Promise((r,a)=>{let n=t.transaction(e,"readonly").objectStore(e).getAllKeys();n.onsuccess=()=>r(n.result),n.onerror=()=>a(n.error)})}async function y(e,t){let r=await I();return new Promise((a,n)=>{let o=r.transaction(e,"readwrite").objectStore(e).put(t);o.onsuccess=()=>a(),o.onerror=()=>n(o.error),o.onerror=()=>n(o.error)})}async function h(e,t){let r=await I();return new Promise((a,n)=>{let o=r.transaction(e,"readwrite").objectStore(e).delete(t);o.onsuccess=()=>a(),o.onerror=()=>n(o.error)})}var v=new Map;function G(e,t){return v.has(e)||v.set(e,new Set),v.get(e).add(t),()=>_(e,t)}function _(e,t){v.get(e)?.delete(t)}function u(e,t){v.get(e)?.forEach(r=>{try{r(t)}catch(a){console.error(`[offline-data-manager] Error in "${e}" listener:`,a)}})}function X(e,t){let r=a=>{t(a),_(e,r)};G(e,r)}async function O(){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 we(e){let{available:t,quota:r}=await O();return t-r*.1>=e}async function K(){return navigator?.storage?.persist?navigator.storage.persist():!1}async function z(){return navigator?.storage?.persisted?navigator.storage.persisted():!1}function B(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 C=null,Q=null,L=!1,V=!0;function me(){u("connectivity",{online:!1}),C?.()}function ye(){u("connectivity",{online:!0}),Q?.()}function Ee({pauseAll:e,resumeAll:t}){L||!window||(C=e,Q=t,window&&(window.addEventListener("offline",me),window.addEventListener("online",ye)),L=!0)}function F(){window&&(window.removeEventListener("offline",me),window.removeEventListener("online",ye)),C=null,Q=null,L=!1}function x(){return window?navigator.onLine??!0:V}function q(){return L}function Z(e){V=e,L&&(V?Q?.():C?.())}var Pe=2*1024*1024,Me=5*1024*1024,Ge=2,ge=5,Be=1e3,g=new Map,b=!1,W=null;function De(){return new Promise(e=>{W=e})}function U(){if(W){let e=W;W=null,e()}}var Ce=e=>new Promise(t=>setTimeout(t,e)),Qe=e=>Be*Math.pow(2,e);async function m(e,t){let r=await p(i.DOWNLOAD_QUEUE,e);r&&await y(i.DOWNLOAD_QUEUE,{...r,...t})}async function Fe(e,t){try{let r=await fetch(e,{method:"HEAD",signal:t}),a=r.headers.get("Accept-Ranges")==="bytes",n=r.headers.get("Content-Encoding"),o=!!n&&n!=="identity",s=r.headers.get("Content-Length"),l=s&&!o?parseInt(s,10):null,c=Ae(r.headers.get("Content-Type"));return{supportsRange:a,totalBytes:l,mimeType:c}}catch{return{supportsRange:!1,totalBytes:null,mimeType:null}}}function Ae(e){return e&&e.split(";")[0].trim()||null}function Re(e){let t=e.reduce((n,o)=>n+o.byteLength,0),r=new Uint8Array(t),a=0;for(let n of e)r.set(n,a),a+=n.byteLength;return r}async function qe(e){let{id:t,downloadUrl:r,ttl:a}=e,n=new AbortController;g.set(t,n);let o=await p(i.DOWNLOAD_QUEUE,t),s=o?.retryCount??0;for(;s<=ge;)try{await m(t,{status:d.IN_PROGRESS,lastAttemptAt:Date.now(),retryCount:s,errorMessage:null}),u("status",{id:t,status:d.IN_PROGRESS}),o=await p(i.DOWNLOAD_QUEUE,t);let l=o?.byteOffset??0,c=!1,f=o?.totalBytes??e.totalBytes??null,w=e.mimeType??null;if(l===0){let R=await Fe(r,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>Me,A,T=null;if(D)A=await $e(t,r,l,f,n.signal);else{let R=await We(t,r,n.signal);A=R.uint8,T=R.mimeType}let ue=w??T??"application/octet-stream",j=A.buffer,de=Date.now(),Ue=be(de,a);await m(t,{status:d.COMPLETE,data:j,mimeType:ue,bytesDownloaded:j.byteLength,byteOffset:j.byteLength,completedAt:de,expiresAt:Ue,errorMessage:null,deferredReason:null}),u("complete",{id:t,mimeType:ue}),g.delete(t);return}catch(l){if(l?.name==="QuotaExceededError"){await $(),await m(t,{status:d.DEFERRED,deferredReason:"insufficient-storage"}),u("error",{id:t,reason:"insufficient-storage",willRetry:!1});return}else if(l?.name==="AbortError"){await m(t,{status:d.PAUSED}),u("status",{id:t,status:d.PAUSED}),g.delete(t);return}if(s++,s>ge){await m(t,{status:d.FAILED,retryCount:s,errorMessage:l.message}),u("error",{id:t,error:l,retryCount:s}),g.delete(t);return}let c=Qe(s-1);console.warn(`[offline-data-manager] "${t}" failed (attempt ${s}), retrying in ${c}ms:`,l.message),u("error",{id:t,error:l,retryCount:s,willRetry:!0}),await m(t,{status:d.PENDING,retryCount:s,errorMessage:l.message}),await Ce(c)}}async function We(e,t,r){let a=await fetch(t,{signal:r});if(!a.ok)throw new Error(`HTTP ${a.status} ${a.statusText}`);let n=a.headers.get("Content-Encoding"),o=!!n&&n!=="identity",s=a.headers.get("Content-Length"),l=s&&!o?parseInt(s,10):null,c=Ae(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}),u("progress",{id:e,bytesDownloaded:D,totalBytes:l,percent:l?Math.round(D/l*100):null})}return{uint8:Re(w),mimeType:c}}async function $e(e,t,r,a,n){let o=r,s=[],l=r;for(;o<a;){let c=Math.min(o+Pe-1,a-1),f=await fetch(t,{signal:n,headers:{Range:`bytes=${o}-${c}`}});if(!f.ok&&f.status!==206)throw new Error(`HTTP ${f.status} on Range bytes=${o}-${c}`);let w=new Uint8Array(await f.arrayBuffer());s.push(w),o+=w.byteLength,l+=w.byteLength,await m(e,{bytesDownloaded:l,byteOffset:o}),u("progress",{id:e,bytesDownloaded:l,totalBytes:a,percent:Math.round(l/a*100)})}return Re(s)}async function Ye(e){await Se();let[t,r]=await Promise.all([E(i.REGISTRY),E(i.DOWNLOAD_QUEUE)]),a=new Map(t.map(l=>[l.id,l])),n=r.filter(l=>[d.PENDING,d.IN_PROGRESS,d.PAUSED,d.DEFERRED,d.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 o=[...n],s=new Set;await new Promise(l=>{function c(){if(!b){l();return}if(o.length===0){s.size===0&&l();return}if(s.size>=e)return;let f=o.shift(),w=a.get(f.id);if(!w){c();return}let D=(async()=>{let A=w.totalBytes??f.totalBytes??0;if(A>0&&!await we(A)){await m(f.id,{status:d.DEFERRED,deferredReason:"insufficient-storage"}),u("deferred",{id:f.id,reason:"insufficient-storage"});return}await qe(w)})().finally(()=>{s.delete(D),c()});s.add(D),c()}c()})}function J({concurrency:e=Ge}={}){b||(b=!0,(async()=>{for(;b;){if(!x()){let t=await E(i.DOWNLOAD_QUEUE);for(let r of t)r.status===d.IN_PROGRESS&&(g.get(r.id)?.abort(),g.delete(r.id),await m(r.id,{status:d.PAUSED,deferredReason:"network-offline"}));u("connectivity",{online:!1}),await De();continue}await Ye(e),b&&await De()}})())}async function $(){b=!1,U(),await S(),u("stopped",{})}async function ee(){let e=await E(i.DOWNLOAD_QUEUE);for(let t of e)t.status===d.FAILED&&await m(t.id,{status:d.PENDING,retryCount:0,errorMessage:null});U()}function te(){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 re(){Ee({pauseAll:S,resumeAll:U})}var d={PENDING:"pending",IN_PROGRESS:"in-progress",PAUSED:"paused",COMPLETE:"complete",EXPIRED:"expired",FAILED:"failed",DEFERRED:"deferred"},ne=new Set([d.COMPLETE,d.EXPIRED]);function ke(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 he(e){return{id:e,status:d.PENDING,data:null,bytesDownloaded:0,totalBytes:null,byteOffset:0,retryCount:0,lastAttemptAt:null,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}}function be(e,t){return t?e+t*1e3:null}function je(e){return e?Date.now()>=e:!1}async function Y(e){try{ke(e);let t=Date.now(),r=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:r?.registeredAt??t,updatedAt:t};if(r){if(e.version>r.version){await y(i.REGISTRY,n);let o=a?{...a,status:d.PENDING,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}:he(e.id);await y(i.DOWNLOAD_QUEUE,o),u("registered",{id:e.id,reason:"version-updated"}),U()}return}await y(i.REGISTRY,n),await y(i.DOWNLOAD_QUEUE,he(e.id)),u("registered",{id:e.id,reason:"new"}),U()}catch(t){if(t?.name==="QuotaExceededError"){u("error",{id,reason:"insufficient-storage",willRetry:!1});return}else u("error",{id,reason:t?.message??t,willRetry:!1})}}async function oe(e){if(!Array.isArray(e))throw new Error("registerFiles expects an array.");let t=new Set(e.map(n=>n.id)),r=await E(i.REGISTRY),a=[];for(let n of r)!t.has(n.id)&&!n.protected&&(await h(i.REGISTRY,n.id),await h(i.DOWNLOAD_QUEUE,n.id),a.push(n.id),u("deleted",{id:n.id,registryRemoved:!0}));for(let n of e)await Y(n);return{registered:e.map(n=>n.id),removed:a}}async function Oe(e,t){try{if(e&&t){let r=await p(i.REGISTRY,entry.id);r&&(r.metadata={...r.metadata??{},...t},await y(i.REGISTRY,r))}}catch(r){if(r?.name==="QuotaExceededError"){u("error",{id:e,reason:"insufficient-storage",willRetry:!1});return}else u("error",{id:e,reason:r?.message??r,willRetry:!1})}}async function Se(){let e=await E(i.DOWNLOAD_QUEUE),t=[];for(let r of e)r.status===d.COMPLETE&&je(r.expiresAt)&&(await y(i.DOWNLOAD_QUEUE,{...r,status:d.EXPIRED}),t.push(r.id),u("expired",{id:r.id}));return t}async function ae(){let[e,t,r]=await Promise.all([E(i.REGISTRY),E(i.DOWNLOAD_QUEUE),O()]),a=new Map(t.map(o=>[o.id,o]));return{items:e.map(o=>{let s=a.get(o.id)??null;return{id:o.id,downloadUrl:o.downloadUrl,mimeType:o.mimeType,version:o.version,protected:o.protected,priority:o.priority,ttl:o.ttl,totalBytes:o.totalBytes,metadata:o.metadata,registeredAt:o.registeredAt,updatedAt:o.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((o,s)=>o.priority-s.priority),storage:{usageBytes:r.usage,quotaBytes:r.quota,availableBytes:r.available,usageFormatted:B(r.usage),quotaFormatted:B(r.quota),availableFormatted:B(r.available)}}}async function ie(e){let[t,r]=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:r?.status??null,bytesDownloaded:r?.bytesDownloaded??0,storedBytes:r?.data?.length??null,progress:r?.totalBytes&&r?.bytesDownloaded?Math.round(r.bytesDownloaded/r.totalBytes*100):null,retryCount:r?.retryCount??0,lastAttemptAt:r?.lastAttemptAt??null,errorMessage:r?.errorMessage??null,deferredReason:r?.deferredReason??null,completedAt:r?.completedAt??null,expiresAt:r?.expiresAt??null}:null}async function se(e){let t=await p(i.DOWNLOAD_QUEUE,e);return ne.has(t?.status)}async function He(e){let t=await p(i.DOWNLOAD_QUEUE,e);t&&await y(i.DOWNLOAD_QUEUE,{...t,status:d.PENDING,data:null,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null})}async function k(e,{removeProtected:t=!1}={}){let r=await p(i.REGISTRY,e);if(!r)throw new Error(`deleteFile: No registered file with id "${e}".`);await N(e);let a=t||!r.protected;return a?(await h(i.REGISTRY,e),await h(i.DOWNLOAD_QUEUE,e)):await He(e),u("deleted",{id:e,registryRemoved:a}),{id:e,registryRemoved:a}}async function le({removeProtected:e=!1}={}){await S();let t=await M(i.REGISTRY);return Promise.all(t.map(r=>k(r,{removeProtected:e})))}async function xe(e){let[t,r]=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(!ne.has(r?.status)||!r?.data)throw new Error(`retrieve: File "${e}" has no data yet (status: ${r?.status??"unknown"}).`);return{data:r.data,mimeType:r.mimeType}}var Xe={setDBInfo:pe,dbGetAllIds:M,registerFile:Y,registerFiles:oe,startDownloads:J,stopDownloads:$,retryFailed:ee,isDownloading:te,abortDownload:N,abortAllDownloads:S,startMonitoring:re,stopMonitoring:F,isOnline:x,isMonitoring:q,updateConnectivityStatus:Z,retrieve:xe,getAllStatus:ae,getStatus:ie,isReady:se,delete:k,deleteAll:le,on:G,off:_,once:X,getStorageEstimate:O,requestPersistentStorage:K,isPersistentStorage:z},Ke=Xe;return Ne(ze);})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "offline-data-manager",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Service-worker-friendly offline file download and storage manager for JavaScript.",
5
5
  "type": "module",
6
6
  "main": "dist/umd/offline-data-manager.js",
package/types/index.d.ts CHANGED
@@ -14,6 +14,7 @@ declare namespace OfflineDataManager {
14
14
  export { stopMonitoring };
15
15
  export { isOnline };
16
16
  export { isMonitoring };
17
+ export { updateConnectivityStatus };
17
18
  export { retrieve };
18
19
  export { getAllStatus };
19
20
  export { getStatus };
@@ -40,6 +41,7 @@ import { startMonitoring } from './downloader.js';
40
41
  import { stopMonitoring } from './downloader.js';
41
42
  import { isOnline } from './downloader.js';
42
43
  import { isMonitoring } from './downloader.js';
44
+ import { updateConnectivityStatus } from './connectivity.js';
43
45
  /**
44
46
  * Retrieves the stored file data for a registered file.
45
47
  * Returns the array buffer and content type.
@@ -69,4 +71,4 @@ import { requestPersistentStorage } from './storage.js';
69
71
  import { isPersistentStorage } from './storage.js';
70
72
  import { setDBInfo } from './db.js';
71
73
  import { dbGetAllIds } from './db.js';
72
- export { registerFile, registerFiles, updateRegistryMetadata, startDownloads, stopDownloads, retryFailed, isDownloading, abortDownload, abortAllDownloads, startMonitoring, stopMonitoring, isOnline, isMonitoring, getAllStatus, getStatus, isReady, deleteFile, deleteAllFiles, on, off, once, emit, getStorageEstimate, requestPersistentStorage, isPersistentStorage };
74
+ export { registerFile, registerFiles, updateRegistryMetadata, startDownloads, stopDownloads, retryFailed, isDownloading, abortDownload, abortAllDownloads, startMonitoring, stopMonitoring, isOnline, isMonitoring, updateConnectivityStatus, getAllStatus, getStatus, isReady, deleteFile, deleteAllFiles, on, off, once, emit, getStorageEstimate, requestPersistentStorage, isPersistentStorage };