offline-data-manager 1.0.11 → 1.0.13

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",J=1,_=null,s={REGISTRY:"registry",DOWNLOAD_QUEUE:"downloadQueue"};async function tt(t,e){Z=t??"offline-data-manager",J=e??1}async function T(){return _||(_=await new Promise((t,e)=>{let r=indexedDB.open(Z,J);r.onupgradeneeded=o=>{let n=o.target.result;if(!n.objectStoreNames.contains(s.REGISTRY)){let a=n.createObjectStore(s.REGISTRY,{keyPath:"id"});a.createIndex("protected","protected",{unique:!1}),a.createIndex("priority","priority",{unique:!1})}if(!n.objectStoreNames.contains(s.DOWNLOAD_QUEUE)){let a=n.createObjectStore(s.DOWNLOAD_QUEUE,{keyPath:"id"});a.createIndex("status","status",{unique:!1}),a.createIndex("priority","priority",{unique:!1})}},r.onsuccess=()=>t(r.result),r.onerror=()=>e(r.error)}),_)}async function p(t,e){let r=await T();return new Promise((o,n)=>{let a=r.transaction(t,"readonly").objectStore(t).get(e);a.onsuccess=()=>o(a.result),a.onerror=()=>n(a.error)})}async function D(t){let e=await T();return new Promise((r,o)=>{let n=e.transaction(t,"readonly").objectStore(t).getAll();n.onsuccess=()=>r(n.result),n.onerror=()=>o(n.error)})}async function L(t){let e=await T();return new Promise((r,o)=>{let n=e.transaction(t,"readonly").objectStore(t).getAllKeys();n.onsuccess=()=>r(n.result),n.onerror=()=>o(n.error)})}async function m(t,e){let r=await T();return new Promise((o,n)=>{let a=r.transaction(t,"readwrite").objectStore(t).put(e);a.onsuccess=()=>o(),a.onerror=()=>n(a.error),a.onerror=()=>n(a.error)})}async function S(t,e){let r=await T();return new Promise((o,n)=>{let a=r.transaction(t,"readwrite").objectStore(t).delete(e);a.onsuccess=()=>o(),a.onerror=()=>n(a.error)})}var U=new Map;function q(t,e){return U.has(t)||U.set(t,new Set),U.get(t).add(e),()=>M(t,e)}function M(t,e){U.get(t)?.delete(e)}function u(t,e){U.get(t)?.forEach(r=>{try{r(e)}catch(o){console.error(`[offline-data-manager] Error in "${t}" listener:`,o)}})}function et(t,e){let r=o=>{e(o),M(t,r)};q(t,r)}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 rt(t){let{available:e,quota:r}=await I();return e-r*.1>=t}async function ot(){return navigator?.storage?.persist?navigator.storage.persist():!1}async function nt(){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 C=null,B=null,v=!1,Y=!0;function at(){u("connectivity",{online:!1}),C?.()}function st(){u("connectivity",{online:!0}),B?.()}function it({pauseAll:t,resumeAll:e}){v||(C=t,B=e,window&&(window.addEventListener("offline",at),window.addEventListener("online",st)),v=!0)}function $(){globalThis.window&&(window.removeEventListener("offline",at),window.removeEventListener("online",st)),C=null,B=null,v=!1}function N(){return globalThis.window?navigator.onLine??!0:Y}function k(){return v}function lt(t){Y=t,v&&(Y?B?.():C?.())}var Ot=2*1024*1024,Tt=5*1024*1024,Ut=2,ut=5,It=1e3,E=new Map,b=!1,Q=null;function dt(){return new Promise(t=>{Q=t})}function h(){if(Q){let t=Q;Q=null,t()}}var vt=t=>new Promise(e=>setTimeout(e,t)),Nt=t=>It*Math.pow(2,t);async function y(t,e){let r=await p(s.DOWNLOAD_QUEUE,t);if(!r)return;await m(s.DOWNLOAD_QUEUE,{...r,...e});let{data:o,...n}=e;Object.keys(n).length>0&&await W(t,n)}async function Pt(t,e){try{let r=await fetch(t,{method:"HEAD",signal:e}),o=r.headers.get("Accept-Ranges")==="bytes",n=r.headers.get("Content-Encoding"),a=!!n&&n!=="identity",d=r.headers.get("Content-Length"),i=d&&!a?parseInt(d,10):null,c=ct(r.headers.get("Content-Type"));return{supportsRange:o,totalBytes:i,mimeType:c}}catch{return{supportsRange:!1,totalBytes:null,mimeType:null}}}function ct(t){return t&&t.split(";")[0].trim()||null}function ft(t){let e=t.reduce((n,a)=>n+a.byteLength,0),r=new Uint8Array(e),o=0;for(let n of t)r.set(n,o),o+=n.byteLength;return r}async function _t(t){let{id:e,downloadUrl:r,ttl:o}=t,n=new AbortController;E.set(e,n);let a=await p(s.DOWNLOAD_QUEUE,e),d=a?.retryCount??0;for(;d<=ut;)try{await y(e,{status:l.IN_PROGRESS,lastAttemptAt:Date.now(),retryCount:d,errorMessage:null}),u("status",{id:e,status:l.IN_PROGRESS}),a=await p(s.DOWNLOAD_QUEUE,e);let i=a?.byteOffset??0,c=!1,f=a?.totalBytes??t.totalBytes??null,w=t.mimeType??null;if(i===0){let R=await Pt(r,n.signal);c=R.supportsRange,R.totalBytes&&(f=R.totalBytes,await y(e,{totalBytes:f})),!w&&R.mimeType&&(w=R.mimeType)}else c=!0;let g=c&&f&&f>Tt,A,O=null;if(g)A=await Mt(e,r,i,f,n.signal);else{let R=await Lt(e,r,n.signal);A=R.uint8,O=R.mimeType}let z=w??O??"application/octet-stream",P=A.buffer,V=Date.now(),xt=Et(V,o);await y(e,{status:l.COMPLETE,data:P,mimeType:z,bytesDownloaded:P.byteLength,byteOffset:P.byteLength,storedBytes:P?.byteLength,completedAt:V,expiresAt:xt,errorMessage:null,deferredReason:null}),u("complete",{id:e,mimeType:z}),E.delete(e);return}catch(i){if(i?.name==="QuotaExceededError"){await j(),await y(e,{status:l.DEFERRED,deferredReason:"insufficient-storage"}),u("error",{id:e,reason:"insufficient-storage",willRetry:!1});return}else if(i?.name==="AbortError"){await y(e,{status:l.PAUSED}),u("status",{id:e,status:l.PAUSED}),E.delete(e);return}if(d++,d>ut){await y(e,{status:l.FAILED,retryCount:d,errorMessage:i.message}),u("error",{id:e,error:i,retryCount:d}),E.delete(e);return}let c=Nt(d-1);console.warn(`[offline-data-manager] "${e}" failed (attempt ${d}), retrying in ${c}ms:`,i.message),u("error",{id:e,error:i,retryCount:d,willRetry:!0}),await y(e,{status:l.PENDING,retryCount:d,errorMessage:i.message}),await vt(c)}}async function Lt(t,e,r){let o=await fetch(e,{signal:r});if(!o.ok)throw new Error(`HTTP ${o.status} ${o.statusText}`);let n=o.headers.get("Content-Encoding"),a=!!n&&n!=="identity",d=o.headers.get("Content-Length"),i=d&&!a?parseInt(d,10):null,c=ct(o.headers.get("Content-Type")),f=o.body.getReader(),w=[],g=0;for(;;){let{done:A,value:O}=await f.read();if(A)break;w.push(O),g+=O.byteLength,await y(t,{bytesDownloaded:g,totalBytes:i}),u("progress",{id:t,bytesDownloaded:g,totalBytes:i,percent:i?Math.round(g/i*100):null})}return{uint8:ft(w),mimeType:c}}async function Mt(t,e,r,o,n){let a=r,d=[],i=r;for(;a<o;){let c=Math.min(a+Ot-1,o-1),f=await fetch(e,{signal:n,headers:{Range:`bytes=${a}-${c}`}});if(!f.ok&&f.status!==206)throw new Error(`HTTP ${f.status} on Range bytes=${a}-${c}`);let w=new Uint8Array(await f.arrayBuffer());d.push(w),a+=w.byteLength,i+=w.byteLength,await y(t,{bytesDownloaded:i,byteOffset:a}),u("progress",{id:t,bytesDownloaded:i,totalBytes:o,percent:Math.round(i/o*100)})}return ft(d)}async function Gt(t){await gt();let[e,r]=await Promise.all([D(s.REGISTRY),D(s.DOWNLOAD_QUEUE)]),o=new Map(e.map(i=>[i.id,i])),n=r.filter(i=>[l.PENDING,l.IN_PROGRESS,l.PAUSED,l.DEFERRED,l.EXPIRED].includes(i.status)).sort((i,c)=>(o.get(i.id)?.priority??10)-(o.get(c.id)?.priority??10));if(n.length===0)return;let a=[...n],d=new Set;await new Promise(i=>{function c(){if(!b){i();return}if(a.length===0){d.size===0&&i();return}if(d.size>=t)return;let f=a.shift(),w=o.get(f.id);if(!w){c();return}let g=(async()=>{let A=w.totalBytes??f.totalBytes??0;if(A>0&&!await rt(A)){await y(f.id,{status:l.DEFERRED,deferredReason:"insufficient-storage"}),u("deferred",{id:f.id,reason:"insufficient-storage"});return}await _t(w)})().finally(()=>{d.delete(g),c()});d.add(g),c()}c()})}function pt({concurrency:t=Ut}={}){b||(b=!0,(async()=>{for(;b;){if(!N()){let e=await D(s.DOWNLOAD_QUEUE);for(let r of e)r.status===l.IN_PROGRESS&&(E.get(r.id)?.abort(),E.delete(r.id),await y(r.id,{status:l.PAUSED,deferredReason:"network-offline"}));u("connectivity",{online:!1}),await dt();continue}await Gt(t),b&&await dt()}})())}async function j(){b=!1,h(),await x(),u("stopped",{})}async function wt(){let t=await D(s.DOWNLOAD_QUEUE);for(let e of t)e.status===l.FAILED&&await y(e.id,{status:l.PENDING,retryCount:0,errorMessage:null});h()}function mt(){return b}async function F(t){E.get(t)?.abort(),E.delete(t)}async function x(){for(let[t,e]of E)e.abort(),E.delete(t)}function yt(){it({pauseAll:x,resumeAll:h})}var l={PENDING:"pending",IN_PROGRESS:"in-progress",PAUSED:"paused",COMPLETE:"complete",EXPIRED:"expired",FAILED:"failed",DEFERRED:"deferred"},H=new Set([l.COMPLETE,l.EXPIRED]);function Ct(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 Dt(t){return{id:t,status:l.PENDING,data:null,bytesDownloaded:0,totalBytes:null,byteOffset:0,retryCount:0,lastAttemptAt:null,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}}async function W(t,e){let r=await p(s.REGISTRY,t);r&&await m(s.REGISTRY,{...r,...e})}function Et(t,e){return e?t+e*1e3:null}function Bt(t){return t?Date.now()>=t:!1}async function X(t){try{Ct(t);let e=Date.now(),r=await p(s.REGISTRY,t.id),o=await p(s.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:r?.registeredAt??e,updatedAt:e,...r?{}:{status:l.PENDING,bytesDownloaded:0,retryCount:0,lastAttemptAt:null,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}};if(r){if(t.version>r.version){await m(s.REGISTRY,n);let a=o?{...o,status:l.PENDING,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}:Dt(t.id);await m(s.DOWNLOAD_QUEUE,a),await W(t.id,{status:l.PENDING,bytesDownloaded:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}),u("registered",{id:t.id,reason:"version-updated"}),h()}return}await m(s.REGISTRY,n),await m(s.DOWNLOAD_QUEUE,Dt(t.id)),u("registered",{id:t.id,reason:"new"}),h()}catch(e){if(e?.name==="QuotaExceededError"){u("error",{id,reason:"insufficient-storage",willRetry:!1});return}else u("error",{id,reason:e?.message??e,willRetry:!1})}}async function At(t){if(!Array.isArray(t))throw new Error("registerFiles expects an array.");let e=new Set(t.map(n=>n.id)),r=await D(s.REGISTRY),o=[];for(let n of r)!e.has(n.id)&&!n.protected&&(await S(s.REGISTRY,n.id),await S(s.DOWNLOAD_QUEUE,n.id),o.push(n.id),u("deleted",{id:n.id,registryRemoved:!0}));for(let n of t)await X(n);return{registered:t.map(n=>n.id),removed:o}}async function Qt(t,e){try{if(t&&e){let r=await p(s.REGISTRY,entry.id);r&&(r.metadata={...r.metadata??{},...e},await m(s.REGISTRY,r))}}catch(r){if(r?.name==="QuotaExceededError"){u("error",{id:t,reason:"insufficient-storage",willRetry:!1});return}else u("error",{id:t,reason:r?.message??r,willRetry:!1})}}async function gt(){let t=await D(s.DOWNLOAD_QUEUE),e=[];for(let r of t)r.status===l.COMPLETE&&Bt(r.expiresAt)&&(await m(s.DOWNLOAD_QUEUE,{...r,status:l.EXPIRED}),await W(r.id,{status:l.EXPIRED}),e.push(r.id),u("expired",{id:r.id}));return e}async function Rt(){let[t,e]=await Promise.all([D(s.REGISTRY),I()]);return{items:t.map(o=>({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:o.status??null,bytesDownloaded:o.bytesDownloaded??0,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})).sort((o,n)=>o.priority-n.priority),storage:{usageBytes:e.usage,quotaBytes:e.quota,availableBytes:e.available,usageFormatted:G(e.usage),quotaFormatted:G(e.quota),availableFormatted:G(e.available)}}}async function bt(t){let e=await p(s.REGISTRY,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:e.status??null,bytesDownloaded:e.bytesDownloaded??0,progress:e.totalBytes&&e.bytesDownloaded?Math.round(e.bytesDownloaded/e.totalBytes*100):null,retryCount:e.retryCount??0,lastAttemptAt:e.lastAttemptAt??null,errorMessage:e.errorMessage??null,deferredReason:e.deferredReason??null,completedAt:e.completedAt??null,expiresAt:e.expiresAt??null}:null}async function St(t){let e=await p(s.DOWNLOAD_QUEUE,t);return H.has(e?.status)}async function Ft(t){let e=await p(s.DOWNLOAD_QUEUE,t);e&&await m(s.DOWNLOAD_QUEUE,{...e,status:l.PENDING,data:null,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null})}async function K(t,{removeProtected:e=!1}={}){let r=await p(s.REGISTRY,t);if(!r)throw new Error(`deleteFile: No registered file with id "${t}".`);await F(t);let o=e||!r.protected;return o?(await S(s.REGISTRY,t),await S(s.DOWNLOAD_QUEUE,t)):await Ft(t),u("deleted",{id:t,registryRemoved:o}),{id:t,registryRemoved:o}}async function ht({removeProtected:t=!1}={}){await x();let e=await L(s.REGISTRY);return Promise.all(e.map(r=>K(r,{removeProtected:t})))}async function Wt(t){let[e,r]=await Promise.all([p(s.REGISTRY,t),p(s.DOWNLOAD_QUEUE,t)]);if(!e)throw new Error(`retrieve: No registered file with id "${t}".`);if(!H.has(r?.status)||!r?.data)throw new Error(`retrieve: File "${t}" has no data yet (status: ${r?.status??"unknown"}).`);return{data:r.data,mimeType:r.mimeType}}var qt={setDBInfo:tt,dbGetAllIds:L,registerFile:X,registerFiles:At,startDownloads:pt,stopDownloads:j,retryFailed:wt,isDownloading:mt,abortDownload:F,abortAllDownloads:x,startMonitoring:yt,stopMonitoring:$,isOnline:N,isMonitoring:k,updateConnectivityStatus:lt,retrieve:Wt,getAllStatus:Rt,getStatus:bt,isReady:St,delete:K,deleteAll:ht,on:q,off:M,once:et,getStorageEstimate:I,requestPersistentStorage:ot,isPersistentStorage:nt},Ae=qt;export{x as abortAllDownloads,F as abortDownload,Ae as default,ht as deleteAllFiles,K as deleteFile,u as emit,Rt as getAllStatus,bt as getStatus,I as getStorageEstimate,mt as isDownloading,k as isMonitoring,N as isOnline,nt as isPersistentStorage,St as isReady,M as off,q as on,et as once,X as registerFile,At as registerFiles,ot as requestPersistentStorage,Wt as retrieve,wt as retryFailed,pt as startDownloads,yt as startMonitoring,j as stopDownloads,$ as stopMonitoring,lt as updateConnectivityStatus,Qt as updateRegistryMetadata};
1
+ var Z="offline-data-manager",J=1,L=null,i={REGISTRY:"registry",DOWNLOAD_QUEUE:"downloadQueue"};async function tt(t,e){Z=t??"offline-data-manager",J=e??1}async function T(){return L||(L=await new Promise((t,e)=>{let n=indexedDB.open(Z,J);n.onupgradeneeded=r=>{let o=r.target.result;if(!o.objectStoreNames.contains(i.REGISTRY)){let a=o.createObjectStore(i.REGISTRY,{keyPath:"id"});a.createIndex("protected","protected",{unique:!1}),a.createIndex("priority","priority",{unique:!1})}if(!o.objectStoreNames.contains(i.DOWNLOAD_QUEUE)){let a=o.createObjectStore(i.DOWNLOAD_QUEUE,{keyPath:"id"});a.createIndex("status","status",{unique:!1}),a.createIndex("priority","priority",{unique:!1})}},n.onsuccess=()=>t(n.result),n.onerror=()=>e(n.error)}),L)}async function f(t,e){let n=await T();return new Promise((r,o)=>{let a=n.transaction(t,"readonly").objectStore(t).get(e);a.onsuccess=()=>r(a.result),a.onerror=()=>o(a.error)})}async function D(t){let e=await T();return new Promise((n,r)=>{let o=e.transaction(t,"readonly").objectStore(t).getAll();o.onsuccess=()=>n(o.result),o.onerror=()=>r(o.error)})}async function N(t){let e=await T();return new Promise((n,r)=>{let o=e.transaction(t,"readonly").objectStore(t).getAllKeys();o.onsuccess=()=>n(o.result),o.onerror=()=>r(o.error)})}async function w(t,e){let n=await T();return new Promise((r,o)=>{let a=n.transaction(t,"readwrite").objectStore(t).put(e);a.onsuccess=()=>r(),a.onerror=()=>o(a.error),a.onerror=()=>o(a.error)})}async function A(t,e){let n=await T();return new Promise((r,o)=>{let a=n.transaction(t,"readwrite").objectStore(t).delete(e);a.onsuccess=()=>r(),a.onerror=()=>o(a.error)})}var v=new Map;function W(t,e){return v.has(t)||v.set(t,new Set),v.get(t).add(e),()=>M(t,e)}function M(t,e){v.get(t)?.delete(e)}function u(t,e){v.get(t)?.forEach(n=>{try{n(e)}catch(r){console.error(`[offline-data-manager] Error in "${t}" listener:`,r)}})}function et(t,e){let n=r=>{e(r),M(t,n)};W(t,n)}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 nt(t){let{available:e,quota:n}=await I();return e-n*.1>=t}async function ot(){return navigator?.storage?.persist?navigator.storage.persist():!1}async function rt(){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 C=null,Q=null,U=!1,Y=!0;function at(){u("connectivity",{online:!1}),C?.()}function it(){u("connectivity",{online:!0}),Q?.()}function st({pauseAll:t,resumeAll:e}){U||(C=t,Q=e,window&&(window.addEventListener("offline",at),window.addEventListener("online",it)),U=!0)}function k(){globalThis.window&&(window.removeEventListener("offline",at),window.removeEventListener("online",it)),C=null,Q=null,U=!1}function P(){return globalThis.window?navigator.onLine??!0:Y}function $(){return U}function lt(t){Y=t,U&&(Y?Q?.():C?.())}var It={png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",webp:"image/webp",svg:"image/svg+xml",ico:"image/x-icon",bmp:"image/bmp",gif:"image/gif",tif:"image/tiff",tiff:"image/tiff",avif:"image/avif",apng:"image/apng",mp4:"video/mp4",webm:"video/webm",mpeg:"video/mpeg",mp3:"audio/mpeg",wav:"audio/wav",ttf:"font/ttf",woff:"font/woff",woff2:"font/woff2",otf:"font/otf",json:"application/json",geojson:"application/json",geojsonseq:"application/json",topojson:"application/json",gpx:"application/xml",georss:"application/xml",gml:"application/xml",citygml:"application/xml",czml:"application/xml",xml:"application/xml",kml:"application/vnd.google-earth.kml+xml",xls:"application/vnd.ms-excel",xlsx:"application/vnd.ms-excel",gltf:"model/gltf+json",glb:"model/gltf-binary",dae:"model/vnd.collada+xml",zip:"application/zip",pbf:"application/x-protobuf",mvt:"application/vnd.mapbox-vector-tile",pdf:"application/pdf",terrian:"application/vnd.quantized-mesh",pmtiles:"application/vnd.pmtiles",htm:"text/html",html:"text/html",xhtml:"application/xhtml+xml",js:"text/javascript",css:"text/css",csv:"text/csv",md:"text/markdown",plain:"text/plain",txt:"text/plain",wat:"text/plain",wsv:"text/wsv",wasm:"application/wasm"};function ut(t){if(t&&typeof t=="string"&&t.includes(".")){let e=t.split(".").pop().toLowerCase(),n=It[e];if(n)return n}return"application/octet-stream"}var Ut=2*1024*1024,Pt=5*1024*1024,_t=2,dt=5,Lt=1e3,y=new Map,b=!1,B=null;function ct(){return new Promise(t=>{B=t})}function S(){if(B){let t=B;B=null,t()}}var Nt=t=>new Promise(e=>setTimeout(e,t)),Mt=t=>Lt*Math.pow(2,t);async function g(t,e){let n=await f(i.DOWNLOAD_QUEUE,t);if(!n)return;await w(i.DOWNLOAD_QUEUE,{...n,...e});let{data:r,...o}=e;Object.keys(o).length>0&&await q(t,o)}async function Gt(t,e){try{let n=await fetch(t,{method:"HEAD",signal:e}),r=n.headers.get("Accept-Ranges")==="bytes",o=n.headers.get("Content-Encoding"),a=!!o&&o!=="identity",d=n.headers.get("Content-Length"),s=d&&!a?parseInt(d,10):null,c=ft(n.headers.get("Content-Type"));return{supportsRange:r,totalBytes:s,mimeType:c}}catch{return{supportsRange:!1,totalBytes:null,mimeType:null}}}function ft(t){return t&&t.split(";")[0].trim()||null}function pt(t){let e=t.reduce((o,a)=>o+a.byteLength,0),n=new Uint8Array(e),r=0;for(let o of t)n.set(o,r),r+=o.byteLength;return n}async function Ct(t){let{id:e,downloadUrl:n,ttl:r}=t,o=new AbortController;y.set(e,o);let a=await f(i.DOWNLOAD_QUEUE,e),d=a?.retryCount??0;for(;d<=dt;)try{await g(e,{status:l.IN_PROGRESS,lastAttemptAt:Date.now(),retryCount:d,errorMessage:null}),u("status",{id:e,status:l.IN_PROGRESS}),a=await f(i.DOWNLOAD_QUEUE,e);let s=a?.byteOffset??0,c=!1,p=a?.totalBytes??t.totalBytes??null,m=t.mimeType??null;if(s===0){let x=await Gt(n,o.signal);c=x.supportsRange,x.totalBytes&&(p=x.totalBytes,await g(e,{totalBytes:p})),!m&&x.mimeType&&(m=x.mimeType)}else c=!0;let E=c&&p&&p>Pt,R,O=null;if(E)R=await Bt(e,n,s,p,o.signal);else{let x=await Qt(e,n,o.signal);R=x.uint8,O=x.mimeType}let Tt=ut(n),K=m??O??Tt,_=R.buffer,V=Date.now(),vt=Et(V,r);await g(e,{status:l.COMPLETE,data:_,mimeType:K,bytesDownloaded:_.byteLength,byteOffset:_.byteLength,storedBytes:_?.byteLength,completedAt:V,expiresAt:vt,errorMessage:null,deferredReason:null}),u("complete",{id:e,mimeType:K}),y.delete(e);return}catch(s){if(s?.name==="QuotaExceededError"){await z(),await g(e,{status:l.DEFERRED,deferredReason:"insufficient-storage"}),u("error",{id:e,reason:"insufficient-storage",willRetry:!1});return}else if(s?.name==="AbortError"){await g(e,{status:l.PAUSED}),u("status",{id:e,status:l.PAUSED}),y.delete(e);return}if(d++,d>dt){await g(e,{status:l.FAILED,retryCount:d,errorMessage:s.message}),u("error",{id:e,error:s,retryCount:d}),y.delete(e);return}let c=Mt(d-1);console.warn(`[offline-data-manager] "${e}" failed (attempt ${d}), retrying in ${c}ms:`,s.message),u("error",{id:e,error:s,retryCount:d,willRetry:!0}),await g(e,{status:l.PENDING,retryCount:d,errorMessage:s.message}),await Nt(c)}}async function Qt(t,e,n){let r=await fetch(e,{signal:n});if(!r.ok)throw new Error(`HTTP ${r.status} ${r.statusText}`);let o=r.headers.get("Content-Encoding"),a=!!o&&o!=="identity",d=r.headers.get("Content-Length"),s=d&&!a?parseInt(d,10):null,c=ft(r.headers.get("Content-Type")),p=r.body.getReader(),m=[],E=0;for(;;){let{done:R,value:O}=await p.read();if(R)break;m.push(O),E+=O.byteLength,await g(t,{bytesDownloaded:E,totalBytes:s}),u("progress",{id:t,bytesDownloaded:E,totalBytes:s,percent:s?Math.round(E/s*100):null})}return{uint8:pt(m),mimeType:c}}async function Bt(t,e,n,r,o){let a=n,d=[],s=n;for(;a<r;){let c=Math.min(a+Ut-1,r-1),p=await fetch(e,{signal:o,headers:{Range:`bytes=${a}-${c}`}});if(!p.ok&&p.status!==206)throw new Error(`HTTP ${p.status} on Range bytes=${a}-${c}`);let m=new Uint8Array(await p.arrayBuffer());d.push(m),a+=m.byteLength,s+=m.byteLength,await g(t,{bytesDownloaded:s,byteOffset:a}),u("progress",{id:t,bytesDownloaded:s,totalBytes:r,percent:Math.round(s/r*100)})}return pt(d)}async function Ft(t){await Dt();let[e,n]=await Promise.all([D(i.REGISTRY),D(i.DOWNLOAD_QUEUE)]),r=new Map(e.map(s=>[s.id,s])),o=n.filter(s=>[l.PENDING,l.IN_PROGRESS,l.PAUSED,l.DEFERRED,l.EXPIRED].includes(s.status)).sort((s,c)=>(r.get(s.id)?.priority??10)-(r.get(c.id)?.priority??10));if(o.length===0)return;let a=[...o],d=new Set;await new Promise(s=>{function c(){if(!b){s();return}if(a.length===0){d.size===0&&s();return}if(d.size>=t)return;let p=a.shift(),m=r.get(p.id);if(!m){c();return}let E=(async()=>{let R=m.totalBytes??p.totalBytes??0;if(R>0&&!await nt(R)){await g(p.id,{status:l.DEFERRED,deferredReason:"insufficient-storage"}),u("deferred",{id:p.id,reason:"insufficient-storage"});return}await Ct(m)})().finally(()=>{d.delete(E),c()});d.add(E),c()}c()})}function mt({concurrency:t=_t}={}){b||(b=!0,(async()=>{for(;b;){if(!P()){let e=await D(i.DOWNLOAD_QUEUE);for(let n of e)n.status===l.IN_PROGRESS&&(y.get(n.id)?.abort(),y.delete(n.id),await g(n.id,{status:l.PAUSED,deferredReason:"network-offline"}));u("connectivity",{online:!1}),await ct();continue}await Ft(t),b&&await ct()}})())}async function z(){b=!1,S(),await h(),u("stopped",{})}async function wt(){let t=await D(i.DOWNLOAD_QUEUE);for(let e of t)e.status===l.FAILED&&await g(e.id,{status:l.PENDING,retryCount:0,errorMessage:null});S()}function gt(){return b}async function F(t){y.get(t)?.abort(),y.delete(t)}async function h(){for(let[t,e]of y)e.abort(),y.delete(t)}function yt(){st({pauseAll:h,resumeAll:S})}var l={PENDING:"pending",IN_PROGRESS:"in-progress",PAUSED:"paused",COMPLETE:"complete",EXPIRED:"expired",FAILED:"failed",DEFERRED:"deferred"},j=new Set([l.COMPLETE,l.EXPIRED]);function qt(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 Rt(t){return{id:t,status:l.PENDING,data:null,bytesDownloaded:0,totalBytes:null,byteOffset:0,retryCount:0,lastAttemptAt:null,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}}async function q(t,e){let n=await f(i.REGISTRY,t);n&&await w(i.REGISTRY,{...n,...e})}function Et(t,e){return e?t+e*1e3:null}function jt(t){return t?Date.now()>=t:!1}async function H(t){try{qt(t);let e=Date.now(),n=await f(i.REGISTRY,t.id),r=await f(i.DOWNLOAD_QUEUE,t.id),o={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:n?.registeredAt??e,updatedAt:e,...n?{}:{status:l.PENDING,bytesDownloaded:0,retryCount:0,lastAttemptAt:null,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}};if(n){if(t.version>n.version){await w(i.REGISTRY,o);let a=r?{...r,status:l.PENDING,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}:Rt(t.id);await w(i.DOWNLOAD_QUEUE,a),await q(t.id,{status:l.PENDING,bytesDownloaded:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}),u("registered",{id:t.id,reason:"version-updated"}),S()}return}await w(i.REGISTRY,o),await w(i.DOWNLOAD_QUEUE,Rt(t.id)),u("registered",{id:t.id,reason:"new"}),S()}catch(e){if(e?.name==="QuotaExceededError"){u("error",{id,reason:"insufficient-storage",willRetry:!1});return}else u("error",{id,reason:e?.message??e,willRetry:!1})}}async function xt(t){if(!Array.isArray(t))throw new Error("registerFiles expects an array.");let e=new Set(t.map(o=>o.id)),n=await D(i.REGISTRY),r=[];for(let o of n)!e.has(o.id)&&!o.protected&&(await A(i.REGISTRY,o.id),await A(i.DOWNLOAD_QUEUE,o.id),r.push(o.id),u("deleted",{id:o.id,registryRemoved:!0}));for(let o of t)await H(o);return{registered:t.map(o=>o.id),removed:r}}async function Wt(t,e){try{if(t&&e){let n=await f(i.REGISTRY,entry.id);n&&(n.metadata={...n.metadata??{},...e},await w(i.REGISTRY,n))}}catch(n){if(n?.name==="QuotaExceededError"){u("error",{id:t,reason:"insufficient-storage",willRetry:!1});return}else u("error",{id:t,reason:n?.message??n,willRetry:!1})}}async function Dt(){let t=await D(i.DOWNLOAD_QUEUE),e=[];for(let n of t)n.status===l.COMPLETE&&jt(n.expiresAt)&&(await w(i.DOWNLOAD_QUEUE,{...n,status:l.EXPIRED}),await q(n.id,{status:l.EXPIRED}),e.push(n.id),u("expired",{id:n.id}));return e}async function bt(){let[t,e]=await Promise.all([D(i.REGISTRY),I()]);return{items:t.map(r=>St(r)).sort((r,o)=>r.priority-o.priority),storage:{usageBytes:e.usage,quotaBytes:e.quota,availableBytes:e.available,usageFormatted:G(e.usage),quotaFormatted:G(e.quota),availableFormatted:G(e.available)}}}async function At(t){let e=await f(i.REGISTRY,t);return e?St(e):null}function St(t){return{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:t.status??null,bytesDownloaded:t.bytesDownloaded??0,progress:t.totalBytes&&t.bytesDownloaded?Math.round(t.bytesDownloaded/t.totalBytes*100):null,retryCount:t.retryCount??0,lastAttemptAt:t.lastAttemptAt??null,errorMessage:t.errorMessage??null,deferredReason:t.deferredReason??null,completedAt:t.completedAt??null,expiresAt:t.expiresAt??null}}async function ht(t){let e=await f(i.REGISTRY,t);if(e?.status)return j.has(e?.status);let n=await f(i.DOWNLOAD_QUEUE,t);return j.has(n?.status)}async function Yt(t){let e=await f(i.DOWNLOAD_QUEUE,t);e&&await w(i.DOWNLOAD_QUEUE,{...e,status:l.PENDING,data:null,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null})}async function X(t,{removeProtected:e=!1}={}){let n=await f(i.REGISTRY,t);if(!n)throw new Error(`deleteFile: No registered file with id "${t}".`);await F(t);let r=e||!n.protected;return r?(await A(i.REGISTRY,t),await A(i.DOWNLOAD_QUEUE,t)):await Yt(t),u("deleted",{id:t,registryRemoved:r}),{id:t,registryRemoved:r}}async function Ot({removeProtected:t=!1}={}){await h();let e=await N(i.REGISTRY);return Promise.all(e.map(n=>X(n,{removeProtected:t})))}async function kt(t){let[e,n]=await Promise.all([f(i.REGISTRY,t),f(i.DOWNLOAD_QUEUE,t)]);if(!e)throw new Error(`retrieve: No registered file with id "${t}".`);if(!j.has(n?.status)||!n?.data)throw new Error(`retrieve: File "${t}" has no data yet (status: ${n?.status??"unknown"}).`);return{data:n.data,mimeType:n.mimeType}}var $t={setDBInfo:tt,dbGetAllIds:N,registerFile:H,registerFiles:xt,startDownloads:mt,stopDownloads:z,retryFailed:wt,isDownloading:gt,abortDownload:F,abortAllDownloads:h,startMonitoring:yt,stopMonitoring:k,isOnline:P,isMonitoring:$,updateConnectivityStatus:lt,retrieve:kt,getAllStatus:bt,getStatus:At,isReady:ht,delete:X,deleteAll:Ot,on:W,off:M,once:et,getStorageEstimate:I,requestPersistentStorage:ot,isPersistentStorage:rt},Oe=$t;export{h as abortAllDownloads,F as abortDownload,Oe as default,Ot as deleteAllFiles,X as deleteFile,u as emit,bt as getAllStatus,At as getStatus,I as getStorageEstimate,gt as isDownloading,$ as isMonitoring,P as isOnline,rt as isPersistentStorage,ht as isReady,M as off,W as on,et as once,H as registerFile,xt as registerFiles,ot as requestPersistentStorage,kt as retrieve,wt as retryFailed,mt as startDownloads,yt as startMonitoring,z as stopDownloads,k as stopMonitoring,lt as updateConnectivityStatus,Wt as updateRegistryMetadata};
@@ -1 +1 @@
1
- "use strict";var offlineMapData=(()=>{var X=Object.defineProperty;var It=Object.getOwnPropertyDescriptor;var vt=Object.getOwnPropertyNames;var Nt=Object.prototype.hasOwnProperty;var Pt=(t,e)=>{for(var r in e)X(t,r,{get:e[r],enumerable:!0})},_t=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of vt(e))!Nt.call(t,n)&&n!==r&&X(t,n,{get:()=>e[n],enumerable:!(o=It(e,n))||o.enumerable});return t};var Lt=t=>_t(X({},"__esModule",{value:!0}),t);var Vt={};Pt(Vt,{abortAllDownloads:()=>S,abortDownload:()=>_,default:()=>zt,deleteAllFiles:()=>ut,deleteFile:()=>H,emit:()=>u,getAllStatus:()=>st,getStatus:()=>it,getStorageEstimate:()=>x,isDownloading:()=>rt,isMonitoring:()=>q,isOnline:()=>O,isPersistentStorage:()=>V,isReady:()=>lt,off:()=>N,on:()=>C,once:()=>K,registerFile:()=>j,registerFiles:()=>at,requestPersistentStorage:()=>z,retrieve:()=>Tt,retryFailed:()=>et,startDownloads:()=>tt,startMonitoring:()=>ot,stopDownloads:()=>$,stopMonitoring:()=>W,updateConnectivityStatus:()=>J,updateRegistryMetadata:()=>Ot});var ft="offline-data-manager",pt=1,M=null,s={REGISTRY:"registry",DOWNLOAD_QUEUE:"downloadQueue"};async function wt(t,e){ft=t??"offline-data-manager",pt=e??1}async function I(){return M||(M=await new Promise((t,e)=>{let r=indexedDB.open(ft,pt);r.onupgradeneeded=o=>{let n=o.target.result;if(!n.objectStoreNames.contains(s.REGISTRY)){let a=n.createObjectStore(s.REGISTRY,{keyPath:"id"});a.createIndex("protected","protected",{unique:!1}),a.createIndex("priority","priority",{unique:!1})}if(!n.objectStoreNames.contains(s.DOWNLOAD_QUEUE)){let a=n.createObjectStore(s.DOWNLOAD_QUEUE,{keyPath:"id"});a.createIndex("status","status",{unique:!1}),a.createIndex("priority","priority",{unique:!1})}},r.onsuccess=()=>t(r.result),r.onerror=()=>e(r.error)}),M)}async function p(t,e){let r=await I();return new Promise((o,n)=>{let a=r.transaction(t,"readonly").objectStore(t).get(e);a.onsuccess=()=>o(a.result),a.onerror=()=>n(a.error)})}async function D(t){let e=await I();return new Promise((r,o)=>{let n=e.transaction(t,"readonly").objectStore(t).getAll();n.onsuccess=()=>r(n.result),n.onerror=()=>o(n.error)})}async function G(t){let e=await I();return new Promise((r,o)=>{let n=e.transaction(t,"readonly").objectStore(t).getAllKeys();n.onsuccess=()=>r(n.result),n.onerror=()=>o(n.error)})}async function m(t,e){let r=await I();return new Promise((o,n)=>{let a=r.transaction(t,"readwrite").objectStore(t).put(e);a.onsuccess=()=>o(),a.onerror=()=>n(a.error),a.onerror=()=>n(a.error)})}async function h(t,e){let r=await I();return new Promise((o,n)=>{let a=r.transaction(t,"readwrite").objectStore(t).delete(e);a.onsuccess=()=>o(),a.onerror=()=>n(a.error)})}var v=new Map;function C(t,e){return v.has(t)||v.set(t,new Set),v.get(t).add(e),()=>N(t,e)}function N(t,e){v.get(t)?.delete(e)}function u(t,e){v.get(t)?.forEach(r=>{try{r(e)}catch(o){console.error(`[offline-data-manager] Error in "${t}" listener:`,o)}})}function K(t,e){let r=o=>{e(o),N(t,r)};C(t,r)}async function x(){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 mt(t){let{available:e,quota:r}=await x();return e-r*.1>=t}async function z(){return navigator?.storage?.persist?navigator.storage.persist():!1}async function V(){return navigator?.storage?.persisted?navigator.storage.persisted():!1}function B(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 Q=null,F=null,P=!1,Z=!0;function yt(){u("connectivity",{online:!1}),Q?.()}function Et(){u("connectivity",{online:!0}),F?.()}function gt({pauseAll:t,resumeAll:e}){P||(Q=t,F=e,window&&(window.addEventListener("offline",yt),window.addEventListener("online",Et)),P=!0)}function W(){globalThis.window&&(window.removeEventListener("offline",yt),window.removeEventListener("online",Et)),Q=null,F=null,P=!1}function O(){return globalThis.window?navigator.onLine??!0:Z}function q(){return P}function J(t){Z=t,P&&(Z?F?.():Q?.())}var Mt=2*1024*1024,Gt=5*1024*1024,Ct=2,Dt=5,Bt=1e3,E=new Map,b=!1,Y=null;function At(){return new Promise(t=>{Y=t})}function T(){if(Y){let t=Y;Y=null,t()}}var Qt=t=>new Promise(e=>setTimeout(e,t)),Ft=t=>Bt*Math.pow(2,t);async function y(t,e){let r=await p(s.DOWNLOAD_QUEUE,t);if(!r)return;await m(s.DOWNLOAD_QUEUE,{...r,...e});let{data:o,...n}=e;Object.keys(n).length>0&&await k(t,n)}async function Wt(t,e){try{let r=await fetch(t,{method:"HEAD",signal:e}),o=r.headers.get("Accept-Ranges")==="bytes",n=r.headers.get("Content-Encoding"),a=!!n&&n!=="identity",d=r.headers.get("Content-Length"),i=d&&!a?parseInt(d,10):null,c=Rt(r.headers.get("Content-Type"));return{supportsRange:o,totalBytes:i,mimeType:c}}catch{return{supportsRange:!1,totalBytes:null,mimeType:null}}}function Rt(t){return t&&t.split(";")[0].trim()||null}function bt(t){let e=t.reduce((n,a)=>n+a.byteLength,0),r=new Uint8Array(e),o=0;for(let n of t)r.set(n,o),o+=n.byteLength;return r}async function qt(t){let{id:e,downloadUrl:r,ttl:o}=t,n=new AbortController;E.set(e,n);let a=await p(s.DOWNLOAD_QUEUE,e),d=a?.retryCount??0;for(;d<=Dt;)try{await y(e,{status:l.IN_PROGRESS,lastAttemptAt:Date.now(),retryCount:d,errorMessage:null}),u("status",{id:e,status:l.IN_PROGRESS}),a=await p(s.DOWNLOAD_QUEUE,e);let i=a?.byteOffset??0,c=!1,f=a?.totalBytes??t.totalBytes??null,w=t.mimeType??null;if(i===0){let R=await Wt(r,n.signal);c=R.supportsRange,R.totalBytes&&(f=R.totalBytes,await y(e,{totalBytes:f})),!w&&R.mimeType&&(w=R.mimeType)}else c=!0;let g=c&&f&&f>Gt,A,U=null;if(g)A=await $t(e,r,i,f,n.signal);else{let R=await Yt(e,r,n.signal);A=R.uint8,U=R.mimeType}let dt=w??U??"application/octet-stream",L=A.buffer,ct=Date.now(),Ut=St(ct,o);await y(e,{status:l.COMPLETE,data:L,mimeType:dt,bytesDownloaded:L.byteLength,byteOffset:L.byteLength,storedBytes:L?.byteLength,completedAt:ct,expiresAt:Ut,errorMessage:null,deferredReason:null}),u("complete",{id:e,mimeType:dt}),E.delete(e);return}catch(i){if(i?.name==="QuotaExceededError"){await $(),await y(e,{status:l.DEFERRED,deferredReason:"insufficient-storage"}),u("error",{id:e,reason:"insufficient-storage",willRetry:!1});return}else if(i?.name==="AbortError"){await y(e,{status:l.PAUSED}),u("status",{id:e,status:l.PAUSED}),E.delete(e);return}if(d++,d>Dt){await y(e,{status:l.FAILED,retryCount:d,errorMessage:i.message}),u("error",{id:e,error:i,retryCount:d}),E.delete(e);return}let c=Ft(d-1);console.warn(`[offline-data-manager] "${e}" failed (attempt ${d}), retrying in ${c}ms:`,i.message),u("error",{id:e,error:i,retryCount:d,willRetry:!0}),await y(e,{status:l.PENDING,retryCount:d,errorMessage:i.message}),await Qt(c)}}async function Yt(t,e,r){let o=await fetch(e,{signal:r});if(!o.ok)throw new Error(`HTTP ${o.status} ${o.statusText}`);let n=o.headers.get("Content-Encoding"),a=!!n&&n!=="identity",d=o.headers.get("Content-Length"),i=d&&!a?parseInt(d,10):null,c=Rt(o.headers.get("Content-Type")),f=o.body.getReader(),w=[],g=0;for(;;){let{done:A,value:U}=await f.read();if(A)break;w.push(U),g+=U.byteLength,await y(t,{bytesDownloaded:g,totalBytes:i}),u("progress",{id:t,bytesDownloaded:g,totalBytes:i,percent:i?Math.round(g/i*100):null})}return{uint8:bt(w),mimeType:c}}async function $t(t,e,r,o,n){let a=r,d=[],i=r;for(;a<o;){let c=Math.min(a+Mt-1,o-1),f=await fetch(e,{signal:n,headers:{Range:`bytes=${a}-${c}`}});if(!f.ok&&f.status!==206)throw new Error(`HTTP ${f.status} on Range bytes=${a}-${c}`);let w=new Uint8Array(await f.arrayBuffer());d.push(w),a+=w.byteLength,i+=w.byteLength,await y(t,{bytesDownloaded:i,byteOffset:a}),u("progress",{id:t,bytesDownloaded:i,totalBytes:o,percent:Math.round(i/o*100)})}return bt(d)}async function kt(t){await ht();let[e,r]=await Promise.all([D(s.REGISTRY),D(s.DOWNLOAD_QUEUE)]),o=new Map(e.map(i=>[i.id,i])),n=r.filter(i=>[l.PENDING,l.IN_PROGRESS,l.PAUSED,l.DEFERRED,l.EXPIRED].includes(i.status)).sort((i,c)=>(o.get(i.id)?.priority??10)-(o.get(c.id)?.priority??10));if(n.length===0)return;let a=[...n],d=new Set;await new Promise(i=>{function c(){if(!b){i();return}if(a.length===0){d.size===0&&i();return}if(d.size>=t)return;let f=a.shift(),w=o.get(f.id);if(!w){c();return}let g=(async()=>{let A=w.totalBytes??f.totalBytes??0;if(A>0&&!await mt(A)){await y(f.id,{status:l.DEFERRED,deferredReason:"insufficient-storage"}),u("deferred",{id:f.id,reason:"insufficient-storage"});return}await qt(w)})().finally(()=>{d.delete(g),c()});d.add(g),c()}c()})}function tt({concurrency:t=Ct}={}){b||(b=!0,(async()=>{for(;b;){if(!O()){let e=await D(s.DOWNLOAD_QUEUE);for(let r of e)r.status===l.IN_PROGRESS&&(E.get(r.id)?.abort(),E.delete(r.id),await y(r.id,{status:l.PAUSED,deferredReason:"network-offline"}));u("connectivity",{online:!1}),await At();continue}await kt(t),b&&await At()}})())}async function $(){b=!1,T(),await S(),u("stopped",{})}async function et(){let t=await D(s.DOWNLOAD_QUEUE);for(let e of t)e.status===l.FAILED&&await y(e.id,{status:l.PENDING,retryCount:0,errorMessage:null});T()}function rt(){return b}async function _(t){E.get(t)?.abort(),E.delete(t)}async function S(){for(let[t,e]of E)e.abort(),E.delete(t)}function ot(){gt({pauseAll:S,resumeAll:T})}var l={PENDING:"pending",IN_PROGRESS:"in-progress",PAUSED:"paused",COMPLETE:"complete",EXPIRED:"expired",FAILED:"failed",DEFERRED:"deferred"},nt=new Set([l.COMPLETE,l.EXPIRED]);function jt(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 xt(t){return{id:t,status:l.PENDING,data:null,bytesDownloaded:0,totalBytes:null,byteOffset:0,retryCount:0,lastAttemptAt:null,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}}async function k(t,e){let r=await p(s.REGISTRY,t);r&&await m(s.REGISTRY,{...r,...e})}function St(t,e){return e?t+e*1e3:null}function Ht(t){return t?Date.now()>=t:!1}async function j(t){try{jt(t);let e=Date.now(),r=await p(s.REGISTRY,t.id),o=await p(s.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:r?.registeredAt??e,updatedAt:e,...r?{}:{status:l.PENDING,bytesDownloaded:0,retryCount:0,lastAttemptAt:null,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}};if(r){if(t.version>r.version){await m(s.REGISTRY,n);let a=o?{...o,status:l.PENDING,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}:xt(t.id);await m(s.DOWNLOAD_QUEUE,a),await k(t.id,{status:l.PENDING,bytesDownloaded:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}),u("registered",{id:t.id,reason:"version-updated"}),T()}return}await m(s.REGISTRY,n),await m(s.DOWNLOAD_QUEUE,xt(t.id)),u("registered",{id:t.id,reason:"new"}),T()}catch(e){if(e?.name==="QuotaExceededError"){u("error",{id,reason:"insufficient-storage",willRetry:!1});return}else u("error",{id,reason:e?.message??e,willRetry:!1})}}async function at(t){if(!Array.isArray(t))throw new Error("registerFiles expects an array.");let e=new Set(t.map(n=>n.id)),r=await D(s.REGISTRY),o=[];for(let n of r)!e.has(n.id)&&!n.protected&&(await h(s.REGISTRY,n.id),await h(s.DOWNLOAD_QUEUE,n.id),o.push(n.id),u("deleted",{id:n.id,registryRemoved:!0}));for(let n of t)await j(n);return{registered:t.map(n=>n.id),removed:o}}async function Ot(t,e){try{if(t&&e){let r=await p(s.REGISTRY,entry.id);r&&(r.metadata={...r.metadata??{},...e},await m(s.REGISTRY,r))}}catch(r){if(r?.name==="QuotaExceededError"){u("error",{id:t,reason:"insufficient-storage",willRetry:!1});return}else u("error",{id:t,reason:r?.message??r,willRetry:!1})}}async function ht(){let t=await D(s.DOWNLOAD_QUEUE),e=[];for(let r of t)r.status===l.COMPLETE&&Ht(r.expiresAt)&&(await m(s.DOWNLOAD_QUEUE,{...r,status:l.EXPIRED}),await k(r.id,{status:l.EXPIRED}),e.push(r.id),u("expired",{id:r.id}));return e}async function st(){let[t,e]=await Promise.all([D(s.REGISTRY),x()]);return{items:t.map(o=>({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:o.status??null,bytesDownloaded:o.bytesDownloaded??0,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})).sort((o,n)=>o.priority-n.priority),storage:{usageBytes:e.usage,quotaBytes:e.quota,availableBytes:e.available,usageFormatted:B(e.usage),quotaFormatted:B(e.quota),availableFormatted:B(e.available)}}}async function it(t){let e=await p(s.REGISTRY,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:e.status??null,bytesDownloaded:e.bytesDownloaded??0,progress:e.totalBytes&&e.bytesDownloaded?Math.round(e.bytesDownloaded/e.totalBytes*100):null,retryCount:e.retryCount??0,lastAttemptAt:e.lastAttemptAt??null,errorMessage:e.errorMessage??null,deferredReason:e.deferredReason??null,completedAt:e.completedAt??null,expiresAt:e.expiresAt??null}:null}async function lt(t){let e=await p(s.DOWNLOAD_QUEUE,t);return nt.has(e?.status)}async function Xt(t){let e=await p(s.DOWNLOAD_QUEUE,t);e&&await m(s.DOWNLOAD_QUEUE,{...e,status:l.PENDING,data:null,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null})}async function H(t,{removeProtected:e=!1}={}){let r=await p(s.REGISTRY,t);if(!r)throw new Error(`deleteFile: No registered file with id "${t}".`);await _(t);let o=e||!r.protected;return o?(await h(s.REGISTRY,t),await h(s.DOWNLOAD_QUEUE,t)):await Xt(t),u("deleted",{id:t,registryRemoved:o}),{id:t,registryRemoved:o}}async function ut({removeProtected:t=!1}={}){await S();let e=await G(s.REGISTRY);return Promise.all(e.map(r=>H(r,{removeProtected:t})))}async function Tt(t){let[e,r]=await Promise.all([p(s.REGISTRY,t),p(s.DOWNLOAD_QUEUE,t)]);if(!e)throw new Error(`retrieve: No registered file with id "${t}".`);if(!nt.has(r?.status)||!r?.data)throw new Error(`retrieve: File "${t}" has no data yet (status: ${r?.status??"unknown"}).`);return{data:r.data,mimeType:r.mimeType}}var Kt={setDBInfo:wt,dbGetAllIds:G,registerFile:j,registerFiles:at,startDownloads:tt,stopDownloads:$,retryFailed:et,isDownloading:rt,abortDownload:_,abortAllDownloads:S,startMonitoring:ot,stopMonitoring:W,isOnline:O,isMonitoring:q,updateConnectivityStatus:J,retrieve:Tt,getAllStatus:st,getStatus:it,isReady:lt,delete:H,deleteAll:ut,on:C,off:N,once:K,getStorageEstimate:x,requestPersistentStorage:z,isPersistentStorage:V},zt=Kt;return Lt(Vt);})();
1
+ "use strict";var offlineMapData=(()=>{var X=Object.defineProperty;var _t=Object.getOwnPropertyDescriptor;var Lt=Object.getOwnPropertyNames;var Nt=Object.prototype.hasOwnProperty;var Mt=(t,e)=>{for(var n in e)X(t,n,{get:e[n],enumerable:!0})},Gt=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Lt(e))!Nt.call(t,o)&&o!==n&&X(t,o,{get:()=>e[o],enumerable:!(r=_t(e,o))||r.enumerable});return t};var Ct=t=>Gt(X({},"__esModule",{value:!0}),t);var ee={};Mt(ee,{abortAllDownloads:()=>A,abortDownload:()=>L,default:()=>te,deleteAllFiles:()=>ut,deleteFile:()=>H,emit:()=>u,getAllStatus:()=>it,getStatus:()=>st,getStorageEstimate:()=>h,isDownloading:()=>ot,isMonitoring:()=>j,isOnline:()=>O,isPersistentStorage:()=>Z,isReady:()=>lt,off:()=>P,on:()=>C,once:()=>K,registerFile:()=>z,registerFiles:()=>at,requestPersistentStorage:()=>V,retrieve:()=>It,retryFailed:()=>nt,startDownloads:()=>et,startMonitoring:()=>rt,stopDownloads:()=>Y,stopMonitoring:()=>q,updateConnectivityStatus:()=>tt,updateRegistryMetadata:()=>Tt});var ft="offline-data-manager",pt=1,M=null,i={REGISTRY:"registry",DOWNLOAD_QUEUE:"downloadQueue"};async function mt(t,e){ft=t??"offline-data-manager",pt=e??1}async function I(){return M||(M=await new Promise((t,e)=>{let n=indexedDB.open(ft,pt);n.onupgradeneeded=r=>{let o=r.target.result;if(!o.objectStoreNames.contains(i.REGISTRY)){let a=o.createObjectStore(i.REGISTRY,{keyPath:"id"});a.createIndex("protected","protected",{unique:!1}),a.createIndex("priority","priority",{unique:!1})}if(!o.objectStoreNames.contains(i.DOWNLOAD_QUEUE)){let a=o.createObjectStore(i.DOWNLOAD_QUEUE,{keyPath:"id"});a.createIndex("status","status",{unique:!1}),a.createIndex("priority","priority",{unique:!1})}},n.onsuccess=()=>t(n.result),n.onerror=()=>e(n.error)}),M)}async function f(t,e){let n=await I();return new Promise((r,o)=>{let a=n.transaction(t,"readonly").objectStore(t).get(e);a.onsuccess=()=>r(a.result),a.onerror=()=>o(a.error)})}async function D(t){let e=await I();return new Promise((n,r)=>{let o=e.transaction(t,"readonly").objectStore(t).getAll();o.onsuccess=()=>n(o.result),o.onerror=()=>r(o.error)})}async function G(t){let e=await I();return new Promise((n,r)=>{let o=e.transaction(t,"readonly").objectStore(t).getAllKeys();o.onsuccess=()=>n(o.result),o.onerror=()=>r(o.error)})}async function w(t,e){let n=await I();return new Promise((r,o)=>{let a=n.transaction(t,"readwrite").objectStore(t).put(e);a.onsuccess=()=>r(),a.onerror=()=>o(a.error),a.onerror=()=>o(a.error)})}async function S(t,e){let n=await I();return new Promise((r,o)=>{let a=n.transaction(t,"readwrite").objectStore(t).delete(e);a.onsuccess=()=>r(),a.onerror=()=>o(a.error)})}var U=new Map;function C(t,e){return U.has(t)||U.set(t,new Set),U.get(t).add(e),()=>P(t,e)}function P(t,e){U.get(t)?.delete(e)}function u(t,e){U.get(t)?.forEach(n=>{try{n(e)}catch(r){console.error(`[offline-data-manager] Error in "${t}" listener:`,r)}})}function K(t,e){let n=r=>{e(r),P(t,n)};C(t,n)}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 wt(t){let{available:e,quota:n}=await h();return e-n*.1>=t}async function V(){return navigator?.storage?.persist?navigator.storage.persist():!1}async function Z(){return navigator?.storage?.persisted?navigator.storage.persisted():!1}function Q(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 B=null,F=null,_=!1,J=!0;function gt(){u("connectivity",{online:!1}),B?.()}function yt(){u("connectivity",{online:!0}),F?.()}function Et({pauseAll:t,resumeAll:e}){_||(B=t,F=e,window&&(window.addEventListener("offline",gt),window.addEventListener("online",yt)),_=!0)}function q(){globalThis.window&&(window.removeEventListener("offline",gt),window.removeEventListener("online",yt)),B=null,F=null,_=!1}function O(){return globalThis.window?navigator.onLine??!0:J}function j(){return _}function tt(t){J=t,_&&(J?F?.():B?.())}var Qt={png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",webp:"image/webp",svg:"image/svg+xml",ico:"image/x-icon",bmp:"image/bmp",gif:"image/gif",tif:"image/tiff",tiff:"image/tiff",avif:"image/avif",apng:"image/apng",mp4:"video/mp4",webm:"video/webm",mpeg:"video/mpeg",mp3:"audio/mpeg",wav:"audio/wav",ttf:"font/ttf",woff:"font/woff",woff2:"font/woff2",otf:"font/otf",json:"application/json",geojson:"application/json",geojsonseq:"application/json",topojson:"application/json",gpx:"application/xml",georss:"application/xml",gml:"application/xml",citygml:"application/xml",czml:"application/xml",xml:"application/xml",kml:"application/vnd.google-earth.kml+xml",xls:"application/vnd.ms-excel",xlsx:"application/vnd.ms-excel",gltf:"model/gltf+json",glb:"model/gltf-binary",dae:"model/vnd.collada+xml",zip:"application/zip",pbf:"application/x-protobuf",mvt:"application/vnd.mapbox-vector-tile",pdf:"application/pdf",terrian:"application/vnd.quantized-mesh",pmtiles:"application/vnd.pmtiles",htm:"text/html",html:"text/html",xhtml:"application/xhtml+xml",js:"text/javascript",css:"text/css",csv:"text/csv",md:"text/markdown",plain:"text/plain",txt:"text/plain",wat:"text/plain",wsv:"text/wsv",wasm:"application/wasm"};function Dt(t){if(t&&typeof t=="string"&&t.includes(".")){let e=t.split(".").pop().toLowerCase(),n=Qt[e];if(n)return n}return"application/octet-stream"}var Bt=2*1024*1024,Ft=5*1024*1024,qt=2,Rt=5,jt=1e3,y=new Map,b=!1,W=null;function xt(){return new Promise(t=>{W=t})}function T(){if(W){let t=W;W=null,t()}}var Wt=t=>new Promise(e=>setTimeout(e,t)),Yt=t=>jt*Math.pow(2,t);async function g(t,e){let n=await f(i.DOWNLOAD_QUEUE,t);if(!n)return;await w(i.DOWNLOAD_QUEUE,{...n,...e});let{data:r,...o}=e;Object.keys(o).length>0&&await k(t,o)}async function kt(t,e){try{let n=await fetch(t,{method:"HEAD",signal:e}),r=n.headers.get("Accept-Ranges")==="bytes",o=n.headers.get("Content-Encoding"),a=!!o&&o!=="identity",d=n.headers.get("Content-Length"),s=d&&!a?parseInt(d,10):null,c=bt(n.headers.get("Content-Type"));return{supportsRange:r,totalBytes:s,mimeType:c}}catch{return{supportsRange:!1,totalBytes:null,mimeType:null}}}function bt(t){return t&&t.split(";")[0].trim()||null}function At(t){let e=t.reduce((o,a)=>o+a.byteLength,0),n=new Uint8Array(e),r=0;for(let o of t)n.set(o,r),r+=o.byteLength;return n}async function $t(t){let{id:e,downloadUrl:n,ttl:r}=t,o=new AbortController;y.set(e,o);let a=await f(i.DOWNLOAD_QUEUE,e),d=a?.retryCount??0;for(;d<=Rt;)try{await g(e,{status:l.IN_PROGRESS,lastAttemptAt:Date.now(),retryCount:d,errorMessage:null}),u("status",{id:e,status:l.IN_PROGRESS}),a=await f(i.DOWNLOAD_QUEUE,e);let s=a?.byteOffset??0,c=!1,p=a?.totalBytes??t.totalBytes??null,m=t.mimeType??null;if(s===0){let x=await kt(n,o.signal);c=x.supportsRange,x.totalBytes&&(p=x.totalBytes,await g(e,{totalBytes:p})),!m&&x.mimeType&&(m=x.mimeType)}else c=!0;let E=c&&p&&p>Ft,R,v=null;if(E)R=await Ht(e,n,s,p,o.signal);else{let x=await zt(e,n,o.signal);R=x.uint8,v=x.mimeType}let Ut=Dt(n),dt=m??v??Ut,N=R.buffer,ct=Date.now(),Pt=St(ct,r);await g(e,{status:l.COMPLETE,data:N,mimeType:dt,bytesDownloaded:N.byteLength,byteOffset:N.byteLength,storedBytes:N?.byteLength,completedAt:ct,expiresAt:Pt,errorMessage:null,deferredReason:null}),u("complete",{id:e,mimeType:dt}),y.delete(e);return}catch(s){if(s?.name==="QuotaExceededError"){await Y(),await g(e,{status:l.DEFERRED,deferredReason:"insufficient-storage"}),u("error",{id:e,reason:"insufficient-storage",willRetry:!1});return}else if(s?.name==="AbortError"){await g(e,{status:l.PAUSED}),u("status",{id:e,status:l.PAUSED}),y.delete(e);return}if(d++,d>Rt){await g(e,{status:l.FAILED,retryCount:d,errorMessage:s.message}),u("error",{id:e,error:s,retryCount:d}),y.delete(e);return}let c=Yt(d-1);console.warn(`[offline-data-manager] "${e}" failed (attempt ${d}), retrying in ${c}ms:`,s.message),u("error",{id:e,error:s,retryCount:d,willRetry:!0}),await g(e,{status:l.PENDING,retryCount:d,errorMessage:s.message}),await Wt(c)}}async function zt(t,e,n){let r=await fetch(e,{signal:n});if(!r.ok)throw new Error(`HTTP ${r.status} ${r.statusText}`);let o=r.headers.get("Content-Encoding"),a=!!o&&o!=="identity",d=r.headers.get("Content-Length"),s=d&&!a?parseInt(d,10):null,c=bt(r.headers.get("Content-Type")),p=r.body.getReader(),m=[],E=0;for(;;){let{done:R,value:v}=await p.read();if(R)break;m.push(v),E+=v.byteLength,await g(t,{bytesDownloaded:E,totalBytes:s}),u("progress",{id:t,bytesDownloaded:E,totalBytes:s,percent:s?Math.round(E/s*100):null})}return{uint8:At(m),mimeType:c}}async function Ht(t,e,n,r,o){let a=n,d=[],s=n;for(;a<r;){let c=Math.min(a+Bt-1,r-1),p=await fetch(e,{signal:o,headers:{Range:`bytes=${a}-${c}`}});if(!p.ok&&p.status!==206)throw new Error(`HTTP ${p.status} on Range bytes=${a}-${c}`);let m=new Uint8Array(await p.arrayBuffer());d.push(m),a+=m.byteLength,s+=m.byteLength,await g(t,{bytesDownloaded:s,byteOffset:a}),u("progress",{id:t,bytesDownloaded:s,totalBytes:r,percent:Math.round(s/r*100)})}return At(d)}async function Xt(t){await ht();let[e,n]=await Promise.all([D(i.REGISTRY),D(i.DOWNLOAD_QUEUE)]),r=new Map(e.map(s=>[s.id,s])),o=n.filter(s=>[l.PENDING,l.IN_PROGRESS,l.PAUSED,l.DEFERRED,l.EXPIRED].includes(s.status)).sort((s,c)=>(r.get(s.id)?.priority??10)-(r.get(c.id)?.priority??10));if(o.length===0)return;let a=[...o],d=new Set;await new Promise(s=>{function c(){if(!b){s();return}if(a.length===0){d.size===0&&s();return}if(d.size>=t)return;let p=a.shift(),m=r.get(p.id);if(!m){c();return}let E=(async()=>{let R=m.totalBytes??p.totalBytes??0;if(R>0&&!await wt(R)){await g(p.id,{status:l.DEFERRED,deferredReason:"insufficient-storage"}),u("deferred",{id:p.id,reason:"insufficient-storage"});return}await $t(m)})().finally(()=>{d.delete(E),c()});d.add(E),c()}c()})}function et({concurrency:t=qt}={}){b||(b=!0,(async()=>{for(;b;){if(!O()){let e=await D(i.DOWNLOAD_QUEUE);for(let n of e)n.status===l.IN_PROGRESS&&(y.get(n.id)?.abort(),y.delete(n.id),await g(n.id,{status:l.PAUSED,deferredReason:"network-offline"}));u("connectivity",{online:!1}),await xt();continue}await Xt(t),b&&await xt()}})())}async function Y(){b=!1,T(),await A(),u("stopped",{})}async function nt(){let t=await D(i.DOWNLOAD_QUEUE);for(let e of t)e.status===l.FAILED&&await g(e.id,{status:l.PENDING,retryCount:0,errorMessage:null});T()}function ot(){return b}async function L(t){y.get(t)?.abort(),y.delete(t)}async function A(){for(let[t,e]of y)e.abort(),y.delete(t)}function rt(){Et({pauseAll:A,resumeAll:T})}var l={PENDING:"pending",IN_PROGRESS:"in-progress",PAUSED:"paused",COMPLETE:"complete",EXPIRED:"expired",FAILED:"failed",DEFERRED:"deferred"},$=new Set([l.COMPLETE,l.EXPIRED]);function Kt(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 Ot(t){return{id:t,status:l.PENDING,data:null,bytesDownloaded:0,totalBytes:null,byteOffset:0,retryCount:0,lastAttemptAt:null,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}}async function k(t,e){let n=await f(i.REGISTRY,t);n&&await w(i.REGISTRY,{...n,...e})}function St(t,e){return e?t+e*1e3:null}function Vt(t){return t?Date.now()>=t:!1}async function z(t){try{Kt(t);let e=Date.now(),n=await f(i.REGISTRY,t.id),r=await f(i.DOWNLOAD_QUEUE,t.id),o={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:n?.registeredAt??e,updatedAt:e,...n?{}:{status:l.PENDING,bytesDownloaded:0,retryCount:0,lastAttemptAt:null,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}};if(n){if(t.version>n.version){await w(i.REGISTRY,o);let a=r?{...r,status:l.PENDING,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}:Ot(t.id);await w(i.DOWNLOAD_QUEUE,a),await k(t.id,{status:l.PENDING,bytesDownloaded:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null}),u("registered",{id:t.id,reason:"version-updated"}),T()}return}await w(i.REGISTRY,o),await w(i.DOWNLOAD_QUEUE,Ot(t.id)),u("registered",{id:t.id,reason:"new"}),T()}catch(e){if(e?.name==="QuotaExceededError"){u("error",{id,reason:"insufficient-storage",willRetry:!1});return}else u("error",{id,reason:e?.message??e,willRetry:!1})}}async function at(t){if(!Array.isArray(t))throw new Error("registerFiles expects an array.");let e=new Set(t.map(o=>o.id)),n=await D(i.REGISTRY),r=[];for(let o of n)!e.has(o.id)&&!o.protected&&(await S(i.REGISTRY,o.id),await S(i.DOWNLOAD_QUEUE,o.id),r.push(o.id),u("deleted",{id:o.id,registryRemoved:!0}));for(let o of t)await z(o);return{registered:t.map(o=>o.id),removed:r}}async function Tt(t,e){try{if(t&&e){let n=await f(i.REGISTRY,entry.id);n&&(n.metadata={...n.metadata??{},...e},await w(i.REGISTRY,n))}}catch(n){if(n?.name==="QuotaExceededError"){u("error",{id:t,reason:"insufficient-storage",willRetry:!1});return}else u("error",{id:t,reason:n?.message??n,willRetry:!1})}}async function ht(){let t=await D(i.DOWNLOAD_QUEUE),e=[];for(let n of t)n.status===l.COMPLETE&&Vt(n.expiresAt)&&(await w(i.DOWNLOAD_QUEUE,{...n,status:l.EXPIRED}),await k(n.id,{status:l.EXPIRED}),e.push(n.id),u("expired",{id:n.id}));return e}async function it(){let[t,e]=await Promise.all([D(i.REGISTRY),h()]);return{items:t.map(r=>vt(r)).sort((r,o)=>r.priority-o.priority),storage:{usageBytes:e.usage,quotaBytes:e.quota,availableBytes:e.available,usageFormatted:Q(e.usage),quotaFormatted:Q(e.quota),availableFormatted:Q(e.available)}}}async function st(t){let e=await f(i.REGISTRY,t);return e?vt(e):null}function vt(t){return{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:t.status??null,bytesDownloaded:t.bytesDownloaded??0,progress:t.totalBytes&&t.bytesDownloaded?Math.round(t.bytesDownloaded/t.totalBytes*100):null,retryCount:t.retryCount??0,lastAttemptAt:t.lastAttemptAt??null,errorMessage:t.errorMessage??null,deferredReason:t.deferredReason??null,completedAt:t.completedAt??null,expiresAt:t.expiresAt??null}}async function lt(t){let e=await f(i.REGISTRY,t);if(e?.status)return $.has(e?.status);let n=await f(i.DOWNLOAD_QUEUE,t);return $.has(n?.status)}async function Zt(t){let e=await f(i.DOWNLOAD_QUEUE,t);e&&await w(i.DOWNLOAD_QUEUE,{...e,status:l.PENDING,data:null,bytesDownloaded:0,byteOffset:0,retryCount:0,errorMessage:null,deferredReason:null,completedAt:null,expiresAt:null})}async function H(t,{removeProtected:e=!1}={}){let n=await f(i.REGISTRY,t);if(!n)throw new Error(`deleteFile: No registered file with id "${t}".`);await L(t);let r=e||!n.protected;return r?(await S(i.REGISTRY,t),await S(i.DOWNLOAD_QUEUE,t)):await Zt(t),u("deleted",{id:t,registryRemoved:r}),{id:t,registryRemoved:r}}async function ut({removeProtected:t=!1}={}){await A();let e=await G(i.REGISTRY);return Promise.all(e.map(n=>H(n,{removeProtected:t})))}async function It(t){let[e,n]=await Promise.all([f(i.REGISTRY,t),f(i.DOWNLOAD_QUEUE,t)]);if(!e)throw new Error(`retrieve: No registered file with id "${t}".`);if(!$.has(n?.status)||!n?.data)throw new Error(`retrieve: File "${t}" has no data yet (status: ${n?.status??"unknown"}).`);return{data:n.data,mimeType:n.mimeType}}var Jt={setDBInfo:mt,dbGetAllIds:G,registerFile:z,registerFiles:at,startDownloads:et,stopDownloads:Y,retryFailed:nt,isDownloading:ot,abortDownload:L,abortAllDownloads:A,startMonitoring:rt,stopMonitoring:q,isOnline:O,isMonitoring:j,updateConnectivityStatus:tt,retrieve:It,getAllStatus:it,getStatus:st,isReady:lt,delete:H,deleteAll:ut,on:C,off:P,once:K,getStorageEstimate:h,requestPersistentStorage:V,isPersistentStorage:Z},te=Jt;return Ct(ee);})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "offline-data-manager",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
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",
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Helper function that tries to determine the content mimi type for a url or file name string by inspecting the file extension of the request.
3
+ * If all else fails, returns 'application/octet-stream' as that is considered the best default content type for media to fail over to.
4
+ * @param {string} urlOrFileName The url or file name.
5
+ * @returns
6
+ */
7
+ export function getMimeType(urlOrFileName: string): any;