Socket
Socket
Sign inDemoInstall

mps3

Package Overview
Dependencies
0
Maintainers
1
Versions
41
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.0.66 to 0.0.67

2

dist/mps3.js

@@ -1,1 +0,1 @@

async function M(J,$){const W=await crypto.subtle.importKey("raw",typeof J==="string"?h.encode(J):J,{name:"HMAC",hash:{name:"SHA-256"}},!1,["sign"]);return crypto.subtle.sign("HMAC",W,h.encode($))}async function c(J){return crypto.subtle.digest("SHA-256",typeof J==="string"?h.encode(J):J)}var R=function(J){return Array.prototype.map.call(new Uint8Array(J),($)=>("0"+$.toString(16)).slice(-2)).join("")},i=function(J){return J.replace(/[!'()*]/g,($)=>"%"+$.charCodeAt(0).toString(16).toUpperCase())},Q0=function(J,$){const{hostname:W,pathname:X}=J;if(W.endsWith(".r2.cloudflarestorage.com"))return["s3","auto"];if(W.endsWith(".backblazeb2.com")){const Y=W.match(/^(?:[^.]+\.)?s3\.([^.]+)\.backblazeb2\.com$/);return Y!=null?["s3",Y[1]]:["",""]}const Z=W.replace("dualstack.","").match(/([^.]+)\.(?:([^.]*)\.)?amazonaws\.com(?:\.cn)?$/);let[z,Q]=(Z||["",""]).slice(1,3);if(Q==="us-gov")Q="us-gov-west-1";else if(Q==="s3"||Q==="s3-accelerate")Q="us-east-1",z="s3";else if(z==="iot")if(W.startsWith("iot."))z="execute-api";else if(W.startsWith("data.jobs.iot."))z="iot-jobs-data";else z=X==="/mqtt"?"iotdevicegateway":"iotdata";else if(z==="autoscaling"){const Y=($.get("X-Amz-Target")||"").split(".")[0];if(Y==="AnyScaleFrontendService")z="application-autoscaling";else if(Y==="AnyScaleScalingPlannerFrontendService")z="autoscaling-plans"}else if(Q==null&&z.startsWith("s3-"))Q=z.slice(3).replace(/^fips-|^external-1/,""),z="s3";else if(z.endsWith("-fips"))z=z.slice(0,-5);else if(Q&&/-\d$/.test(z)&&!/-\d$/.test(Q))[z,Q]=[Q,z];return[z0[z]||z,Q]},h=new TextEncoder,z0={appstream2:"appstream",cloudhsmv2:"cloudhsm",email:"ses",marketplace:"aws-marketplace",mobile:"AWSMobileHubService",pinpoint:"mobiletargeting",queue:"sqs","git-codecommit":"codecommit","mturk-requester-sandbox":"mturk-requester","personalize-runtime":"personalize"},Z0=new Set(["authorization","content-type","content-length","user-agent","presigned-expires","expect","x-amzn-trace-id","range","connection"]);class S{constructor({accessKeyId:J,secretAccessKey:$,sessionToken:W,service:X,region:Z,cache:z,retries:Q,initRetryMs:Y}){if(J==null)throw new TypeError("accessKeyId is a required option");if($==null)throw new TypeError("secretAccessKey is a required option");this.accessKeyId=J,this.secretAccessKey=$,this.sessionToken=W,this.service=X,this.region=Z,this.cache=z||new Map,this.retries=Q!=null?Q:10,this.initRetryMs=Y||50}async sign(J,$){if(J instanceof Request){const{method:Z,url:z,headers:Q,body:Y}=J;if($=Object.assign({method:Z,url:z,headers:Q},$),$.body==null&&Q.has("Content-Type"))$.body=Y!=null&&Q.has("X-Amz-Content-Sha256")?Y:await J.clone().arrayBuffer();J=z}const W=new n(Object.assign({url:J},$,this,$&&$.aws)),X=Object.assign({},$,await W.sign());delete X.aws;try{return new Request(X.url.toString(),X)}catch(Z){if(Z instanceof TypeError)return new Request(X.url.toString(),Object.assign({duplex:"half"},X));throw Z}}async fetch(J,$){for(let W=0;W<=this.retries;W++){const X=fetch(await this.sign(J,$));if(W===this.retries)return X;const Z=await X;if(Z.status<500&&Z.status!==429)return Z;await new Promise((z)=>setTimeout(z,Math.random()*this.initRetryMs*Math.pow(2,W)))}throw new Error("An unknown error occurred, ensure retries is not negative")}}class n{constructor({method:J,url:$,headers:W,body:X,accessKeyId:Z,secretAccessKey:z,sessionToken:Q,service:Y,region:B,cache:P,datetime:O,signQuery:U,appendSessionToken:_,allHeaders:L,singleEncode:X0}){if($==null)throw new TypeError("url is a required option");if(Z==null)throw new TypeError("accessKeyId is a required option");if(z==null)throw new TypeError("secretAccessKey is a required option");this.method=J||(X?"POST":"GET"),this.url=new URL($),this.headers=new Headers(W||{}),this.body=X,this.accessKeyId=Z,this.secretAccessKey=z,this.sessionToken=Q;let f,y;if(!Y||!B)[f,y]=Q0(this.url,this.headers);if(this.service=Y||f||"",this.region=B||y||"us-east-1",this.cache=P||new Map,this.datetime=O||(new Date()).toISOString().replace(/[:-]|\.\d{3}/g,""),this.signQuery=U,this.appendSessionToken=_||this.service==="iotdevicegateway",this.headers.delete("Host"),this.service==="s3"&&!this.signQuery&&!this.headers.has("X-Amz-Content-Sha256"))this.headers.set("X-Amz-Content-Sha256","UNSIGNED-PAYLOAD");const H=this.signQuery?this.url.searchParams:this.headers;if(H.set("X-Amz-Date",this.datetime),this.sessionToken&&!this.appendSessionToken)H.set("X-Amz-Security-Token",this.sessionToken);if(this.signableHeaders=["host",...this.headers.keys()].filter((D)=>L||!Z0.has(D)).sort(),this.signedHeaders=this.signableHeaders.join(";"),this.canonicalHeaders=this.signableHeaders.map((D)=>D+":"+(D==="host"?this.url.host:(this.headers.get(D)||"").replace(/\s+/g," "))).join("\n"),this.credentialString=[this.datetime.slice(0,8),this.region,this.service,"aws4_request"].join("/"),this.signQuery){if(this.service==="s3"&&!H.has("X-Amz-Expires"))H.set("X-Amz-Expires","86400");H.set("X-Amz-Algorithm","AWS4-HMAC-SHA256"),H.set("X-Amz-Credential",this.accessKeyId+"/"+this.credentialString),H.set("X-Amz-SignedHeaders",this.signedHeaders)}if(this.service==="s3")try{this.encodedPath=decodeURIComponent(this.url.pathname.replace(/\+/g," "))}catch(D){this.encodedPath=this.url.pathname}else this.encodedPath=this.url.pathname.replace(/\/+/g,"/");if(!X0)this.encodedPath=encodeURIComponent(this.encodedPath).replace(/%2F/g,"/");this.encodedPath=i(this.encodedPath);const u=new Set;this.encodedSearch=[...this.url.searchParams].filter(([D])=>{if(!D)return!1;if(this.service==="s3"){if(u.has(D))return!1;u.add(D)}return!0}).map((D)=>D.map((x)=>i(encodeURIComponent(x)))).sort(([D,x],[d,l])=>D<d?-1:D>d?1:x<l?-1:x>l?1:0).map((D)=>D.join("=")).join("&")}async sign(){if(this.signQuery){if(this.url.searchParams.set("X-Amz-Signature",await this.signature()),this.sessionToken&&this.appendSessionToken)this.url.searchParams.set("X-Amz-Security-Token",this.sessionToken)}else this.headers.set("Authorization",await this.authHeader());return{method:this.method,url:this.url,headers:this.headers,body:this.body}}async authHeader(){return["AWS4-HMAC-SHA256 Credential="+this.accessKeyId+"/"+this.credentialString,"SignedHeaders="+this.signedHeaders,"Signature="+await this.signature()].join(", ")}async signature(){const J=this.datetime.slice(0,8),$=[this.secretAccessKey,J,this.region,this.service].join();let W=this.cache.get($);if(!W){const X=await M("AWS4"+this.secretAccessKey,J),Z=await M(X,this.region),z=await M(Z,this.service);W=await M(z,"aws4_request"),this.cache.set($,W)}return R(await M(W,await this.stringToSign()))}async stringToSign(){return["AWS4-HMAC-SHA256",this.datetime,this.credentialString,R(await c(await this.canonicalString()))].join("\n")}async canonicalString(){return[this.method.toUpperCase(),this.encodedPath,this.encodedSearch,this.canonicalHeaders+"\n",this.signedHeaders,await this.hexBodyHash()].join("\n")}async hexBodyHash(){let J=this.headers.get("X-Amz-Content-Sha256")||(this.service==="s3"&&this.signQuery?"UNSIGNED-PAYLOAD":null);if(J==null){if(this.body&&typeof this.body!=="string"&&!("byteLength"in this.body))throw new Error("body must be a string, ArrayBuffer or ArrayBufferView, unless you include the X-Amz-Content-Sha256 header");J=R(await c(this.body||""))}return J}}var a=(J,$)=>{const W=$.parseFromString(J,"text/xml"),X=W.getElementsByTagName("ListBucketResult")[0],Z=W.getElementsByTagName("Contents");if(!X||!Z)throw new Error(`Invalid XML: ${J}`);const z=(Q,Y)=>Q.getElementsByTagName(Y)[0]?.textContent;return{$metadata:{},IsTruncated:z(X,"IsTruncated")==="true",Contents:Array.from(Z).map((Q)=>({ChecksumAlgorithm:[z(Q,"ChecksumAlgorithm")],ETag:z(Q,"ETag"),Key:z(Q,"Key"),LastModified:new Date(z(Q,"LastModified")),Owner:{DisplayName:z(Q,"DisplayName"),ID:z(Q,"ID")},Size:parseInt(z(Q,"Size")),StorageClass:z(Q,"StorageClass")})),Name:z(W,"Name"),Prefix:z(W,"Prefix"),Delimiter:z(W,"Delimiter"),MaxKeys:parseInt(z(W,"MaxKeys")),CommonPrefixes:Array.from(W.getElementsByTagName("CommonPrefixes")[0]?.getElementsByTagName("Prefix")||[]).map((Q)=>({Prefix:Q.textContent})),EncodingType:z(W,"EncodingType"),KeyCount:parseInt(z(W,"KeyCount")),ContinuationToken:z(W,"ContinuationToken"),NextContinuationToken:z(W,"NextContinuationToken"),StartAfter:z(W,"StartAfter")}};var N=async(J,{retries:$=Number.MAX_VALUE,delay:W=100}={})=>{try{return await J()}catch(X){if($>0)return await new Promise((Z)=>setTimeout(Z,W)),N(J,{retries:$-1,delay:W});throw X}};class b{J;$;W;constructor(J,$,W){this.fetch=J;this.endpoint=$;this.parser=W}getUrl(J,$,W){return`${this.endpoint}/${J}${$?`/${$}`:""}${W||""}`}async listObjectV2(J){for(let $=0;$<10;$++){const W=this.getUrl(J.Bucket,void 0,`/?list-type=2&prefix=${J.Prefix}`),X=await N(()=>this.fetch(W,{}));if(X.status===200)return a(await X.text(),this.parser);else if(X.status===429)console.warn("listObjectV2: 429, retrying"),await new Promise((Z)=>setTimeout(Z,1000));else throw new Error(`Unexpected response: ${X.status} ${await X.text()}`)}throw new Error("Cannot contact server")}async putObject({Bucket:J,Key:$,Body:W,ChecksumSHA256:X}){const Z=this.getUrl(J,$),z=await N(()=>this.fetch(Z,{method:"PUT",body:W,headers:{"Content-Type":"application/json",...X&&{"x-amz-content-sha256":X}}}));if(z.status!==200)throw new Error(`Failed to PUT: ${await z.text()}`);return{$metadata:{httpStatusCode:z.status},ETag:z.headers.get("ETag"),...z.headers.get("x-amz-version-id")&&{VersionId:z.headers.get("x-amz-version-id")}}}async deleteObject({Bucket:J,Key:$}){return{$metadata:{httpStatusCode:(await N(()=>this.fetch(this.getUrl(J,$),{method:"DELETE"}))).status}}}async getObject({Bucket:J,Key:$,VersionId:W,IfNoneMatch:X}){const Z=this.getUrl(J,$,W?`?versionId=${W}`:""),z=await N(()=>this.fetch(Z,{method:"GET",headers:{"If-None-Match":X}}));switch(z.status){case 304:throw new Error("304");case 404:return{$metadata:{httpStatusCode:404}};case 403:throw new Error("Access denied");default:{let Q;const Y=z.headers.get("content-type"),B=await z.text();if(Y==="application/json"||B&&B!=="")try{Q=JSON.parse(B)}catch(P){throw new Error(`Failed to parse response as JSON ${Z}`)}return{$metadata:{httpStatusCode:z.status},Body:Q,ETag:z.headers.get("ETag"),...z.headers.get("x-amz-version-id")&&{VersionId:z.headers.get("x-amz-version-id")}}}}}}class V{key;_vals;_keys;constructor(J,$){if(this.key=J,this._vals=new Map,this._keys=new Map,$)for(let[W,X]of $)this.set(W,X)}get size(){return this._vals.size}set(J,$){const W=this.key(J);return this._vals.set(W,$),this._keys.set(W,J),this}get(J){return this._vals.get(this.key(J))}delete(J){const $=this.key(J);return this._keys.delete($),this._vals.delete($)}has(J){return this._vals.has(this.key(J))}values(){return this._vals.values()}keys(){return this._keys.values()}forEach(J){return this._vals.forEach(($,W,X)=>J($,this._keys.get(W)))}}var o=()=>`${Date.now()-200}`.padStart(14,"0"),t=()=>`${Date.now()+200}`.padStart(14,"0");var E=()=>crypto.randomUUID();var F=(J)=>`${J.bucket}/${J.key}`;var T=(J)=>JSON.parse(JSON.stringify(J));var C=function(J){return new Promise(($,W)=>{J.oncomplete=J.onsuccess=()=>$(J.result),J.onabort=J.onerror=()=>W(J.error)})},I=function(J,$){const W=indexedDB.open(J);W.onupgradeneeded=()=>W.result.createObjectStore($);const X=C(W);return(Z,z)=>X.then((Q)=>z(Q.transaction($,Z).objectStore($)))},w=function(){if(!v)v=I("keyval-store","keyval");return v},G=function(J,$=w()){return $("readonly",(W)=>C(W.get(J)))},j=function(J,$,W=w()){return W("readwrite",(X)=>{return X.put($,J),C(X.transaction)})};var s=function(J,$=w()){return $("readonly",(W)=>Promise.all(J.map((X)=>C(W.get(X)))))};var K=function(J,$=w()){return $("readwrite",(W)=>{return J.forEach((X)=>W.delete(X)),C(W.transaction)})};var Y0=function(J,$){return J.openCursor().onsuccess=function(){if(!this.result)return;$(this.result),this.result.continue()},C(J.transaction)},e=function(J=w()){return J("readonly",($)=>{if($.getAllKeys)return C($.getAllKeys());const W=[];return Y0($,(X)=>W.push(X.key)).then(()=>W)})};var v;var D0=6,J0=(J)=>`write-${J.toString().padStart(D0,"0")}`;class g{session=E();proposedOperations=new Map;operationLabels=new Map;db;lastIndex=0;load=void 0;constructor(J){this.db=J}async propose(J,$,W=!1){if(this.proposedOperations.set(J,$),this.db){if(this.load&&!W)await this.load,this.proposedOperations.delete(J),this.proposedOperations.set(J,$);this.lastIndex++;const X=J0(this.lastIndex);J[this.session]=this.lastIndex,await j(X,[...$.entries()].map(([Z,z])=>[JSON.stringify(Z),z]),this.db),console.log(`STORE ${X} ${JSON.stringify([...$.entries()])}`)}}async label(J,$,W=!1){if(this.operationLabels.set($,J),this.db){if(this.load&&!W)await this.load;const X=J[this.session];if(X===void 0)throw new Error("Cannot label an unproposed operation");const Z=`label-${X}`;await j(Z,$,this.db),console.log(`STORE ${Z} ${$}`)}}async confirm(J,$=!1){if(this.operationLabels.has(J)){const W=this.operationLabels.get(J);if(this.proposedOperations.delete(W),this.operationLabels.delete(J),this.db){if(this.load&&!$)await this.load;const X=W[this.session],Z=[J0(X),`label-${X}`];await K(Z,this.db),console.log(`DEL ${Z}`)}}}async cancel(J,$=!1){if(this.operationLabels.forEach((W,X)=>{if(W===J)this.operationLabels.delete(X)}),this.proposedOperations.delete(J),this.db){if(this.load&&!$)await this.load;const W=J[this.session];await K([`write-${W}`,`label-${W}`],this.db)}}async flatten(){if(this.load)await this.load;const J=new V(F);return this.proposedOperations.forEach(($)=>{$.forEach((W,X)=>{J.set(X,W)})}),J}async restore(J,$){return this.db=J,this.proposedOperations.clear(),this.operationLabels.clear(),this.lastIndex=0,this.load=new Promise(async(W)=>{const Z=(await e(this.db)).filter((Q)=>Q.startsWith("write-")).sort();console.log("RESTORE",Z);const z=await s(Z,this.db);for(let Q=0;Q<Z.length;Q++){const Y=parseInt(Z[Q].split("-")[1]);this.lastIndex=Math.max(this.lastIndex,Y)}for(let Q=0;Q<Z.length;Q++){const Y=Z[Q],B=parseInt(Y.split("-")[1]),P=z[Q].map(([_,L])=>[JSON.parse(_),L]),O=await G(`label-${B}`,this.db);if(!P)continue;const U=new Map(P);await $(U,O),await K([`write-${B}`,`label-${B}`],this.db)}W(void 0)}),this.load}}function A(J,$){if(Array.isArray($)||typeof $!=="object"||$===null)return $;if(typeof J!=="object"||J===null)J={};for(let W in $)if($[W]===null)delete J[W];else J[W]=A(J[W],$[W]);return J}var k="manifest",q={previous:".",files:{},update:{}};class p{J;authoritative_key="";authoritative_state=T(q);optimistic_state=T(q);loading;cache;db;constructor(J){this.manifest=J}async restore(J){this.db=J,this.loading=G(k,J).then(($)=>{if($)this.authoritative_state=$,this.optimistic_state=$,console.log(`${this.manifest.service.config.label} RESTORE ${k}`)})}async getLatest(){if(this.loading)await this.loading;if(this.loading=void 0,!this.manifest.service.config.online)return this.authoritative_state;try{const J=await this.manifest.service._getObject({operation:"POLL_TIME",ref:this.manifest.ref,ifNoneMatch:this.cache?.etag});if(J.$metadata.httpStatusCode===304)return this.authoritative_state;if(J.data===void 0)this.authoritative_key=".";else this.authoritative_key=J.data;const $=await this.manifest.service.s3ClientLite.listObjectV2({Bucket:this.manifest.ref.bucket,Prefix:this.manifest.ref.key,StartAfter:this.authoritative_key});if($.Contents===void 0)return this.authoritative_state=T(q),this.optimistic_state=T(q),this.authoritative_state;const W=`${this.manifest.ref.key}@${o()}`;for(let X=$.Contents.length-1;X>=0;X--){const Z=$.Contents[X].Key;if(Z==this.manifest.ref.key)continue;const z={bucket:this.manifest.ref.bucket,key:Z},Q=await this.manifest.service._getObject({operation:"LOOK_BACK",ref:z});if(Q.data===void 0){await this.manifest.service._deleteObject({operation:"CLEANUP",ref:z});continue}if(Q.data.previous<W){this.authoritative_key=Q.data.previous,this.authoritative_state=Q.data;break}}for(let X=0;X<$.Contents.length;X++){const Z=$.Contents[X].Key;if(Z==this.manifest.ref.key)continue;if(Z<this.authoritative_key)continue;const z=await this.manifest.service._getObject({operation:"SWEEP",ref:{bucket:this.manifest.ref.bucket,key:Z}}),Q=Z.substring(Z.lastIndexOf("@")+1);if(Q>=W)console.log("Optimistic update"),this.optimistic_state=A(this.optimistic_state,z.data?.update);else this.authoritative_state=A(this.authoritative_state,z.data?.update),this.optimistic_state=A(this.optimistic_state,z.data?.update),this.authoritative_key=Z;this.manifest.observeVersionId(Q)}if(this.db)j(k,this.authoritative_state,this.db);return this.authoritative_state}catch(J){if(J.name==="NoSuchKey")return this.authoritative_state=q,this.authoritative_state;else throw J}}}class $0{J;$;W;queue=Promise.resolve();constructor(J,$,W){this.ref=J;this.handler=$;this.lastVersion=W}notify(J,$,W){this.queue=this.queue.then(()=>W).then((X)=>{if($!==this.lastVersion)console.log(`${J} NOTIFY ${F(this.ref)} ${$}`),this.lastVersion=$,this.handler(X)})}}class m{J;$;subscribers=new Set;poller;pollInProgress=!1;manifestState=new p(this);operationQueue=new g;constructor(J,$){this.service=J;this.ref=$;console.log("Create manifest",F($))}load(J){this.manifestState.restore(J),this.operationQueue.restore(J,async($,W)=>{if(!W)await this.service._putAll($,{manifests:[this.ref],await:"local",isLoad:!0});else await this.updateContent($,Promise.resolve(new Map([[this.ref,W]])),{await:"local",isLoad:!0})})}observeVersionId(J){this.operationQueue.confirm(J)}async poll(){if(this.pollInProgress)return;if(this.pollInProgress=!0,this.subscriberCount===0&&this.poller)clearInterval(this.poller),this.poller=void 0;if(this.subscriberCount>0&&!this.poller)this.poller=setInterval(()=>this.poll(),this.service.config.pollFrequency);const J=await this.manifestState.getLatest();if(J===void 0){this.pollInProgress=!1;return}const $=await this.operationQueue.flatten();this.subscribers.forEach(async(W)=>{if($.has(W.ref))W.notify(this.service.config.label,"local",Promise.resolve($.get(W.ref)));else{const X=J.files[F(W.ref)];if(X){const Z=this.service._getObject({operation:"GET_CONTENT",ref:W.ref,version:X.version});W.notify(this.service.config.label,X.version,Z.then((z)=>z.data))}else if(X===null)W.notify(this.service.config.label,void 0,Promise.resolve(void 0))}}),this.pollInProgress=!1}updateContent(J,$,W){const X=this.operationQueue.propose($,J,W.isLoad),Z=X.then(async()=>{try{const z=await $,Q=await this.manifestState.getLatest();Q.previous=this.manifestState.authoritative_key,Q.update={files:{}};for(let[O,U]of z){const _=F(O);if(U){const L={version:U};Q.update.files[_]=L}else Q.update.files[_]=null}const Y=t()+"_"+E().substring(0,2),B=this.ref.key+"@"+Y;this.operationQueue.label($,Y,W.isLoad),await this.service._putObject({operation:"PUT_MANIFEST",ref:{key:B,bucket:this.ref.bucket},value:Q});const P=await this.service._putObject({operation:"PUT_POLL",ref:{key:this.ref.key,bucket:this.ref.bucket},value:this.manifestState.authoritative_key});return this.poll(),P}catch(z){throw console.error(z),this.operationQueue.cancel($,W.isLoad),z}});if(W.await==="local")return X;else return Z}async getOptimisticVersion(J){return await this.manifestState.getLatest(),this.manifestState.optimistic_state.files[F(J)]?.version}subscribe(J,$){console.log(`SUBSCRIBE ${F(J)} ${this.subscriberCount+1}`);const W=new $0(J,$);return this.subscribers.add(W),()=>this.subscribers.delete(W)}get subscriberCount(){return this.subscribers.size}}async function W0(J){const $=(new TextEncoder()).encode(J),W=await crypto.subtle.digest("SHA-256",$);return[...new Uint8Array(W)].map((X)=>X.toString(16).padStart(2,"0")).join("")}class B0{config;s3ClientLite;manifests=new V(F);memCache=new V((J)=>`${J.Bucket}${J.Key}${J.VersionId}${J.IfNoneMatch}`);diskCache;endpoint;constructor(J){if(this.config={...J,label:J.label||"default",useChecksum:J.useChecksum===!1?!1:!0,online:J.online===!1?!1:!0,offlineStorage:J.offlineStorage===!1?!1:!0,useVersioning:J.useVersioning||!1,pollFrequency:J.pollFrequency||1000,defaultManifest:{bucket:J.defaultManifest?.bucket||J.defaultBucket,key:typeof J.defaultManifest=="string"?J.defaultManifest:J.defaultManifest?.key||"manifest.json"}},this.config.s3Config?.credentials instanceof Function)throw Error("We can't do that yet");this.endpoint=J.s3Config.endpoint||`https://s3.${J.s3Config.region}.amazonaws.com`;let $;if(this.config.s3Config?.credentials){const W=new S({accessKeyId:this.config.s3Config.credentials.accessKeyId,secretAccessKey:this.config.s3Config.credentials.secretAccessKey,sessionToken:this.config.s3Config.credentials.sessionToken,region:this.config.s3Config.region||"us-east-1",service:"s3",retries:0});$=(...X)=>W.fetch(...X)}else $=(global||window).fetch.bind(global||window);if(this.config.offlineStorage){const W=`mps3-${this.config.label}`;this.diskCache=I(W,"v0")}this.s3ClientLite=new b(this.config.online?$:()=>new Promise(()=>{}),this.endpoint,J.parser||new DOMParser)}getOrCreateManifest(J){if(!this.manifests.has(J)){const $=new m(this,J);if(this.manifests.set(J,$),this.config.offlineStorage){const W=`mps3-${this.config.label}-${J.bucket}-${J.key}`,X=I(W,"v0");console.log(`${this.config.label} Restoring manifest from ${W}`),$.load(X)}}return this.manifests.get(J)}async get(J,$={}){const W={...this.config.defaultManifest,...$.manifest},X=this.getOrCreateManifest(W),Z={bucket:J.bucket||this.config.defaultBucket||this.config.defaultManifest.bucket,key:typeof J==="string"?J:J.key},z=await X.operationQueue.flatten();if(z.has(Z))return console.log(`${this.config.label} GET (cached) ${Z} ${z.get(Z)}`),z.get(Z);const Q=await X.getOptimisticVersion(Z);if(Q===void 0)return;return(await this._getObject({operation:"GET",ref:Z,version:Q})).data}async _getObject(J){let $;if(this.config.useVersioning)$={Bucket:J.ref.bucket,Key:J.ref.key,IfNoneMatch:J.ifNoneMatch,...J.version&&{VersionId:J.version}};else $={Bucket:J.ref.bucket,Key:`${J.ref.key}${J.version?`@${J.version}`:""}`,IfNoneMatch:J.ifNoneMatch};if(this.memCache.has($))return console.log(`${this.config.label} ${J.operation} (mem cached) ${$.Bucket}/${$.Key}`),this.memCache.get($);const W=`${$.Bucket}${$.Key}${$.VersionId}`;if(this.diskCache){const Z=await G(W,this.diskCache);if(Z)return console.log(`${this.config.label} ${J.operation} (disk cached) ${W}`),this.memCache.set($,Promise.resolve(Z)),Z}if(!this.config.online)throw new Error(`${this.config.label} Offline and value not cached for ${W}`);const X=this.s3ClientLite.getObject($).then(async(Z)=>{const z={$metadata:Z.$metadata,ETag:Z.ETag,data:Z.Body};return console.log(`${this.config.label} ${J.operation} ${J.ref.bucket}/${J.ref.key}@${J.version} => ${z.VersionId}`),z}).catch((Z)=>{if(Z?.name==="304")return{$metadata:{httpStatusCode:304},data:void 0};else throw Z});if(this.memCache.set($,X),this.diskCache)X.then((Z)=>{j(`${$.Bucket}${$.Key}${$.VersionId}`,Z,this.diskCache).then(()=>console.log(`${this.config.label} STORE ${$.Bucket}${$.Key}`))});return X}async delete(J,$={}){return this.putAll(new Map([[J,void 0]]),$)}async put(J,$,W={}){if(!this.diskCache)throw new Error("No store");return this.putAll(new Map([[J,$]]),W)}async putAll(J,$={}){const W=new Map([...J].map(([Z,z])=>[{bucket:Z.bucket||this.config.defaultBucket||this.config.defaultManifest.bucket,key:typeof Z==="string"?Z:Z.key},z])),X=($?.manifests||[this.config.defaultManifest]).map((Z)=>({...this.config.defaultManifest,...Z}));return this._putAll(W,{manifests:X,await:$.await||this.config.online?"remote":"local"})}async _putAll(J,$){const W=new Map,X=new Promise(async(Z,z)=>{const Q=new Map,Y=[];J.forEach((B,P)=>{if(B!==void 0){let O=this.config.useVersioning?void 0:E();W.set(P,B),Y.push(this._putObject({operation:"PUT_CONTENT",ref:P,value:B,version:O}).then((U)=>{if(this.config.useVersioning)if(U.VersionId===void 0)throw console.error(U),Error(`Bucket ${P.bucket} is not version enabled!`);else O=U.VersionId;Q.set(P,O)}))}else Y.push(this._deleteObject({ref:P}).then((O)=>{Q.set(P,void 0)}))}),await Promise.all(Y).catch(z),Z(Q)});return Promise.all($.manifests.map((Z)=>{return this.getOrCreateManifest(Z).updateContent(W,X,{await:$.await,isLoad:$.isLoad===!0})}))}async _putObject(J){const $=JSON.stringify(J.value,null,2);let W;if(this.config.useVersioning)W={Bucket:J.ref.bucket,Key:J.ref.key,ContentType:"application/json",Body:$,...this.config.useChecksum&&{ChecksumSHA256:await W0($)}};else W={Bucket:J.ref.bucket,Key:`${J.ref.key}${J.version?`@${J.version}`:""}`,ContentType:"application/json",Body:$,...this.config.useChecksum&&{ChecksumSHA256:await W0($)}};const X=await this.s3ClientLite.putObject(W);if(console.log(`${this.config.label} ${J.operation} ${W.Bucket}/${W.Key} => ${X.VersionId}`),this.diskCache){const Z=`${W.Bucket}${W.Key}${J.version||X.VersionId}`;await j(Z,{$metadata:{httpStatusCode:200},etag:X.ETag,data:JSON.parse($)},this.diskCache).then(()=>console.log(`${this.config.label} STORE ${Z}`))}return X}async _deleteObject(J){const $={Bucket:J.ref.bucket,Key:J.ref.key},W=await this.s3ClientLite.deleteObject($);return console.log(`${this.config.label} ${J.operation||"DELETE"} ${J.ref.bucket}/${J.ref.key} => ${W.VersionId}`),W}subscribe(J,$,W){const X={...this.config.defaultManifest,...W?.manifest},Z={key:typeof J==="string"?J:J.key,bucket:J.bucket||this.config.defaultBucket||X.bucket},z=this.getOrCreateManifest(X),Q=z.subscribe(Z,$);return this.get(Z,{manifest:X}).then((Y)=>{console.log(`${this.config.label} NOTIFY (initial) ${F(Z)}`),queueMicrotask(()=>{$(Y,void 0),z.poll()})}).catch((Y)=>{$(void 0,Y)}),Q}refresh(){return Promise.all([...this.manifests.values()].map((J)=>J.poll()))}get subscriberCount(){return[...this.manifests.values()].reduce((J,$)=>J+$.subscriberCount,0)}}export{B0 as MPS3};
async function M(J,$){const W=await crypto.subtle.importKey("raw",typeof J==="string"?h.encode(J):J,{name:"HMAC",hash:{name:"SHA-256"}},!1,["sign"]);return crypto.subtle.sign("HMAC",W,h.encode($))}async function c(J){return crypto.subtle.digest("SHA-256",typeof J==="string"?h.encode(J):J)}var R=function(J){return Array.prototype.map.call(new Uint8Array(J),($)=>("0"+$.toString(16)).slice(-2)).join("")},i=function(J){return J.replace(/[!'()*]/g,($)=>"%"+$.charCodeAt(0).toString(16).toUpperCase())},Q0=function(J,$){const{hostname:W,pathname:X}=J;if(W.endsWith(".r2.cloudflarestorage.com"))return["s3","auto"];if(W.endsWith(".backblazeb2.com")){const Y=W.match(/^(?:[^.]+\.)?s3\.([^.]+)\.backblazeb2\.com$/);return Y!=null?["s3",Y[1]]:["",""]}const Z=W.replace("dualstack.","").match(/([^.]+)\.(?:([^.]*)\.)?amazonaws\.com(?:\.cn)?$/);let[z,Q]=(Z||["",""]).slice(1,3);if(Q==="us-gov")Q="us-gov-west-1";else if(Q==="s3"||Q==="s3-accelerate")Q="us-east-1",z="s3";else if(z==="iot")if(W.startsWith("iot."))z="execute-api";else if(W.startsWith("data.jobs.iot."))z="iot-jobs-data";else z=X==="/mqtt"?"iotdevicegateway":"iotdata";else if(z==="autoscaling"){const Y=($.get("X-Amz-Target")||"").split(".")[0];if(Y==="AnyScaleFrontendService")z="application-autoscaling";else if(Y==="AnyScaleScalingPlannerFrontendService")z="autoscaling-plans"}else if(Q==null&&z.startsWith("s3-"))Q=z.slice(3).replace(/^fips-|^external-1/,""),z="s3";else if(z.endsWith("-fips"))z=z.slice(0,-5);else if(Q&&/-\d$/.test(z)&&!/-\d$/.test(Q))[z,Q]=[Q,z];return[z0[z]||z,Q]},h=new TextEncoder,z0={appstream2:"appstream",cloudhsmv2:"cloudhsm",email:"ses",marketplace:"aws-marketplace",mobile:"AWSMobileHubService",pinpoint:"mobiletargeting",queue:"sqs","git-codecommit":"codecommit","mturk-requester-sandbox":"mturk-requester","personalize-runtime":"personalize"},Z0=new Set(["authorization","content-type","content-length","user-agent","presigned-expires","expect","x-amzn-trace-id","range","connection"]);class S{constructor({accessKeyId:J,secretAccessKey:$,sessionToken:W,service:X,region:Z,cache:z,retries:Q,initRetryMs:Y}){if(J==null)throw new TypeError("accessKeyId is a required option");if($==null)throw new TypeError("secretAccessKey is a required option");this.accessKeyId=J,this.secretAccessKey=$,this.sessionToken=W,this.service=X,this.region=Z,this.cache=z||new Map,this.retries=Q!=null?Q:10,this.initRetryMs=Y||50}async sign(J,$){if(J instanceof Request){const{method:Z,url:z,headers:Q,body:Y}=J;if($=Object.assign({method:Z,url:z,headers:Q},$),$.body==null&&Q.has("Content-Type"))$.body=Y!=null&&Q.has("X-Amz-Content-Sha256")?Y:await J.clone().arrayBuffer();J=z}const W=new n(Object.assign({url:J},$,this,$&&$.aws)),X=Object.assign({},$,await W.sign());delete X.aws;try{return new Request(X.url.toString(),X)}catch(Z){if(Z instanceof TypeError)return new Request(X.url.toString(),Object.assign({duplex:"half"},X));throw Z}}async fetch(J,$){for(let W=0;W<=this.retries;W++){const X=fetch(await this.sign(J,$));if(W===this.retries)return X;const Z=await X;if(Z.status<500&&Z.status!==429)return Z;await new Promise((z)=>setTimeout(z,Math.random()*this.initRetryMs*Math.pow(2,W)))}throw new Error("An unknown error occurred, ensure retries is not negative")}}class n{constructor({method:J,url:$,headers:W,body:X,accessKeyId:Z,secretAccessKey:z,sessionToken:Q,service:Y,region:B,cache:P,datetime:O,signQuery:U,appendSessionToken:_,allHeaders:L,singleEncode:X0}){if($==null)throw new TypeError("url is a required option");if(Z==null)throw new TypeError("accessKeyId is a required option");if(z==null)throw new TypeError("secretAccessKey is a required option");this.method=J||(X?"POST":"GET"),this.url=new URL($),this.headers=new Headers(W||{}),this.body=X,this.accessKeyId=Z,this.secretAccessKey=z,this.sessionToken=Q;let f,y;if(!Y||!B)[f,y]=Q0(this.url,this.headers);if(this.service=Y||f||"",this.region=B||y||"us-east-1",this.cache=P||new Map,this.datetime=O||(new Date()).toISOString().replace(/[:-]|\.\d{3}/g,""),this.signQuery=U,this.appendSessionToken=_||this.service==="iotdevicegateway",this.headers.delete("Host"),this.service==="s3"&&!this.signQuery&&!this.headers.has("X-Amz-Content-Sha256"))this.headers.set("X-Amz-Content-Sha256","UNSIGNED-PAYLOAD");const H=this.signQuery?this.url.searchParams:this.headers;if(H.set("X-Amz-Date",this.datetime),this.sessionToken&&!this.appendSessionToken)H.set("X-Amz-Security-Token",this.sessionToken);if(this.signableHeaders=["host",...this.headers.keys()].filter((D)=>L||!Z0.has(D)).sort(),this.signedHeaders=this.signableHeaders.join(";"),this.canonicalHeaders=this.signableHeaders.map((D)=>D+":"+(D==="host"?this.url.host:(this.headers.get(D)||"").replace(/\s+/g," "))).join("\n"),this.credentialString=[this.datetime.slice(0,8),this.region,this.service,"aws4_request"].join("/"),this.signQuery){if(this.service==="s3"&&!H.has("X-Amz-Expires"))H.set("X-Amz-Expires","86400");H.set("X-Amz-Algorithm","AWS4-HMAC-SHA256"),H.set("X-Amz-Credential",this.accessKeyId+"/"+this.credentialString),H.set("X-Amz-SignedHeaders",this.signedHeaders)}if(this.service==="s3")try{this.encodedPath=decodeURIComponent(this.url.pathname.replace(/\+/g," "))}catch(D){this.encodedPath=this.url.pathname}else this.encodedPath=this.url.pathname.replace(/\/+/g,"/");if(!X0)this.encodedPath=encodeURIComponent(this.encodedPath).replace(/%2F/g,"/");this.encodedPath=i(this.encodedPath);const u=new Set;this.encodedSearch=[...this.url.searchParams].filter(([D])=>{if(!D)return!1;if(this.service==="s3"){if(u.has(D))return!1;u.add(D)}return!0}).map((D)=>D.map((x)=>i(encodeURIComponent(x)))).sort(([D,x],[d,l])=>D<d?-1:D>d?1:x<l?-1:x>l?1:0).map((D)=>D.join("=")).join("&")}async sign(){if(this.signQuery){if(this.url.searchParams.set("X-Amz-Signature",await this.signature()),this.sessionToken&&this.appendSessionToken)this.url.searchParams.set("X-Amz-Security-Token",this.sessionToken)}else this.headers.set("Authorization",await this.authHeader());return{method:this.method,url:this.url,headers:this.headers,body:this.body}}async authHeader(){return["AWS4-HMAC-SHA256 Credential="+this.accessKeyId+"/"+this.credentialString,"SignedHeaders="+this.signedHeaders,"Signature="+await this.signature()].join(", ")}async signature(){const J=this.datetime.slice(0,8),$=[this.secretAccessKey,J,this.region,this.service].join();let W=this.cache.get($);if(!W){const X=await M("AWS4"+this.secretAccessKey,J),Z=await M(X,this.region),z=await M(Z,this.service);W=await M(z,"aws4_request"),this.cache.set($,W)}return R(await M(W,await this.stringToSign()))}async stringToSign(){return["AWS4-HMAC-SHA256",this.datetime,this.credentialString,R(await c(await this.canonicalString()))].join("\n")}async canonicalString(){return[this.method.toUpperCase(),this.encodedPath,this.encodedSearch,this.canonicalHeaders+"\n",this.signedHeaders,await this.hexBodyHash()].join("\n")}async hexBodyHash(){let J=this.headers.get("X-Amz-Content-Sha256")||(this.service==="s3"&&this.signQuery?"UNSIGNED-PAYLOAD":null);if(J==null){if(this.body&&typeof this.body!=="string"&&!("byteLength"in this.body))throw new Error("body must be a string, ArrayBuffer or ArrayBufferView, unless you include the X-Amz-Content-Sha256 header");J=R(await c(this.body||""))}return J}}var a=(J,$)=>{const W=$.parseFromString(J,"text/xml"),X=W.getElementsByTagName("ListBucketResult")[0],Z=W.getElementsByTagName("Contents");if(!X||!Z)throw new Error(`Invalid XML: ${J}`);const z=(Q,Y)=>Q.getElementsByTagName(Y)[0]?.textContent;return{$metadata:{},IsTruncated:z(X,"IsTruncated")==="true",Contents:Array.from(Z).map((Q)=>({ChecksumAlgorithm:[z(Q,"ChecksumAlgorithm")],ETag:z(Q,"ETag"),Key:z(Q,"Key"),LastModified:new Date(z(Q,"LastModified")),Owner:{DisplayName:z(Q,"DisplayName"),ID:z(Q,"ID")},Size:parseInt(z(Q,"Size")),StorageClass:z(Q,"StorageClass")})),Name:z(W,"Name"),Prefix:z(W,"Prefix"),Delimiter:z(W,"Delimiter"),MaxKeys:parseInt(z(W,"MaxKeys")),CommonPrefixes:Array.from(W.getElementsByTagName("CommonPrefixes")[0]?.getElementsByTagName("Prefix")||[]).map((Q)=>({Prefix:Q.textContent})),EncodingType:z(W,"EncodingType"),KeyCount:parseInt(z(W,"KeyCount")),ContinuationToken:z(W,"ContinuationToken"),NextContinuationToken:z(W,"NextContinuationToken"),StartAfter:z(W,"StartAfter")}};var N=async(J,{retries:$=Number.MAX_VALUE,delay:W=1000}={})=>{try{return await J()}catch(X){if($>0)return await new Promise((Z)=>setTimeout(Z,W)),N(J,{retries:$-1,delay:W});throw X}};class b{J;$;W;constructor(J,$,W){this.fetch=J;this.endpoint=$;this.parser=W}getUrl(J,$,W){return`${this.endpoint}/${J}${$?`/${$}`:""}${W||""}`}async listObjectV2(J){for(let $=0;$<10;$++){const W=this.getUrl(J.Bucket,void 0,`/?list-type=2&prefix=${J.Prefix}`),X=await N(()=>this.fetch(W,{}));if(X.status===200)return a(await X.text(),this.parser);else if(X.status===429)console.warn("listObjectV2: 429, retrying"),await new Promise((Z)=>setTimeout(Z,1000));else throw new Error(`Unexpected response: ${X.status} ${await X.text()}`)}throw new Error("Cannot contact server")}async putObject({Bucket:J,Key:$,Body:W,ChecksumSHA256:X}){const Z=this.getUrl(J,$),z=await N(()=>this.fetch(Z,{method:"PUT",body:W,headers:{"Content-Type":"application/json",...X&&{"x-amz-content-sha256":X}}}));if(z.status!==200)throw new Error(`Failed to PUT: ${await z.text()}`);return{$metadata:{httpStatusCode:z.status},ETag:z.headers.get("ETag"),...z.headers.get("x-amz-version-id")&&{VersionId:z.headers.get("x-amz-version-id")}}}async deleteObject({Bucket:J,Key:$}){return{$metadata:{httpStatusCode:(await N(()=>this.fetch(this.getUrl(J,$),{method:"DELETE"}))).status}}}async getObject({Bucket:J,Key:$,VersionId:W,IfNoneMatch:X}){const Z=this.getUrl(J,$,W?`?versionId=${W}`:""),z=await N(()=>this.fetch(Z,{method:"GET",headers:{"If-None-Match":X}}));switch(z.status){case 304:throw new Error("304");case 404:return{$metadata:{httpStatusCode:404}};case 403:throw new Error("Access denied");default:{let Q;const Y=z.headers.get("content-type"),B=await z.text();if(Y==="application/json"||B&&B!=="")try{Q=JSON.parse(B)}catch(P){throw new Error(`Failed to parse response as JSON ${Z}`)}return{$metadata:{httpStatusCode:z.status},Body:Q,ETag:z.headers.get("ETag"),...z.headers.get("x-amz-version-id")&&{VersionId:z.headers.get("x-amz-version-id")}}}}}}class V{key;_vals;_keys;constructor(J,$){if(this.key=J,this._vals=new Map,this._keys=new Map,$)for(let[W,X]of $)this.set(W,X)}get size(){return this._vals.size}set(J,$){const W=this.key(J);return this._vals.set(W,$),this._keys.set(W,J),this}get(J){return this._vals.get(this.key(J))}delete(J){const $=this.key(J);return this._keys.delete($),this._vals.delete($)}has(J){return this._vals.has(this.key(J))}values(){return this._vals.values()}keys(){return this._keys.values()}forEach(J){return this._vals.forEach(($,W,X)=>J($,this._keys.get(W)))}}var o=()=>`${Date.now()-200}`.padStart(14,"0"),t=()=>`${Date.now()+200}`.padStart(14,"0");var E=()=>crypto.randomUUID();var F=(J)=>`${J.bucket}/${J.key}`;var T=(J)=>JSON.parse(JSON.stringify(J));var C=function(J){return new Promise(($,W)=>{J.oncomplete=J.onsuccess=()=>$(J.result),J.onabort=J.onerror=()=>W(J.error)})},I=function(J,$){const W=indexedDB.open(J);W.onupgradeneeded=()=>W.result.createObjectStore($);const X=C(W);return(Z,z)=>X.then((Q)=>z(Q.transaction($,Z).objectStore($)))},w=function(){if(!v)v=I("keyval-store","keyval");return v},G=function(J,$=w()){return $("readonly",(W)=>C(W.get(J)))},j=function(J,$,W=w()){return W("readwrite",(X)=>{return X.put($,J),C(X.transaction)})};var s=function(J,$=w()){return $("readonly",(W)=>Promise.all(J.map((X)=>C(W.get(X)))))};var K=function(J,$=w()){return $("readwrite",(W)=>{return J.forEach((X)=>W.delete(X)),C(W.transaction)})};var Y0=function(J,$){return J.openCursor().onsuccess=function(){if(!this.result)return;$(this.result),this.result.continue()},C(J.transaction)},e=function(J=w()){return J("readonly",($)=>{if($.getAllKeys)return C($.getAllKeys());const W=[];return Y0($,(X)=>W.push(X.key)).then(()=>W)})};var v;var D0=6,J0=(J)=>`write-${J.toString().padStart(D0,"0")}`;class g{session=E();proposedOperations=new Map;operationLabels=new Map;db;lastIndex=0;load=void 0;constructor(J){this.db=J}async propose(J,$,W=!1){if(this.proposedOperations.set(J,$),this.db){if(this.load&&!W)await this.load,this.proposedOperations.delete(J),this.proposedOperations.set(J,$);this.lastIndex++;const X=J0(this.lastIndex);J[this.session]=this.lastIndex,await j(X,[...$.entries()].map(([Z,z])=>[JSON.stringify(Z),z]),this.db),console.log(`STORE ${X} ${JSON.stringify([...$.entries()])}`)}}async label(J,$,W=!1){if(this.operationLabels.set($,J),this.db){if(this.load&&!W)await this.load;const X=J[this.session];if(X===void 0)throw new Error("Cannot label an unproposed operation");const Z=`label-${X}`;await j(Z,$,this.db),console.log(`STORE ${Z} ${$}`)}}async confirm(J,$=!1){if(this.operationLabels.has(J)){const W=this.operationLabels.get(J);if(this.proposedOperations.delete(W),this.operationLabels.delete(J),this.db){if(this.load&&!$)await this.load;const X=W[this.session],Z=[J0(X),`label-${X}`];await K(Z,this.db),console.log(`DEL ${Z}`)}}}async cancel(J,$=!1){if(this.operationLabels.forEach((W,X)=>{if(W===J)this.operationLabels.delete(X)}),this.proposedOperations.delete(J),this.db){if(this.load&&!$)await this.load;const W=J[this.session];await K([`write-${W}`,`label-${W}`],this.db)}}async flatten(){if(this.load)await this.load;const J=new V(F);return this.proposedOperations.forEach(($)=>{$.forEach((W,X)=>{J.set(X,W)})}),J}async restore(J,$){return this.db=J,this.proposedOperations.clear(),this.operationLabels.clear(),this.lastIndex=0,this.load=new Promise(async(W)=>{const Z=(await e(this.db)).filter((Q)=>Q.startsWith("write-")).sort();console.log("RESTORE",Z);const z=await s(Z,this.db);for(let Q=0;Q<Z.length;Q++){const Y=parseInt(Z[Q].split("-")[1]);this.lastIndex=Math.max(this.lastIndex,Y)}for(let Q=0;Q<Z.length;Q++){const Y=Z[Q],B=parseInt(Y.split("-")[1]),P=z[Q].map(([_,L])=>[JSON.parse(_),L]),O=await G(`label-${B}`,this.db);if(!P)continue;const U=new Map(P);await $(U,O),await K([`write-${B}`,`label-${B}`],this.db)}W(void 0)}),this.load}}function A(J,$){if(Array.isArray($)||typeof $!=="object"||$===null)return $;if(typeof J!=="object"||J===null)J={};for(let W in $)if($[W]===null)delete J[W];else J[W]=A(J[W],$[W]);return J}var k="manifest",q={previous:".",files:{},update:{}};class p{J;authoritative_key="";authoritative_state=T(q);optimistic_state=T(q);loading;cache;db;constructor(J){this.manifest=J}async restore(J){this.db=J,this.loading=G(k,J).then(($)=>{if($)this.authoritative_state=$,this.optimistic_state=$,console.log(`${this.manifest.service.config.label} RESTORE ${k}`)})}async getLatest(){if(this.loading)await this.loading;if(this.loading=void 0,!this.manifest.service.config.online)return this.authoritative_state;try{const J=await this.manifest.service._getObject({operation:"POLL_TIME",ref:this.manifest.ref,ifNoneMatch:this.cache?.etag});if(J.$metadata.httpStatusCode===304)return this.authoritative_state;if(J.data===void 0)this.authoritative_key=".";else this.authoritative_key=J.data;const $=await this.manifest.service.s3ClientLite.listObjectV2({Bucket:this.manifest.ref.bucket,Prefix:this.manifest.ref.key,StartAfter:this.authoritative_key});if($.Contents===void 0)return this.authoritative_state=T(q),this.optimistic_state=T(q),this.authoritative_state;const W=`${this.manifest.ref.key}@${o()}`;for(let X=$.Contents.length-1;X>=0;X--){const Z=$.Contents[X].Key;if(Z==this.manifest.ref.key)continue;const z={bucket:this.manifest.ref.bucket,key:Z},Q=await this.manifest.service._getObject({operation:"LOOK_BACK",ref:z});if(Q.data===void 0){await this.manifest.service._deleteObject({operation:"CLEANUP",ref:z});continue}if(Q.data.previous<W){this.authoritative_key=Q.data.previous,this.authoritative_state=Q.data;break}}for(let X=0;X<$.Contents.length;X++){const Z=$.Contents[X].Key;if(Z==this.manifest.ref.key)continue;if(Z<this.authoritative_key)continue;const z=await this.manifest.service._getObject({operation:"SWEEP",ref:{bucket:this.manifest.ref.bucket,key:Z}}),Q=Z.substring(Z.lastIndexOf("@")+1);if(Q>=W)console.log("Optimistic update"),this.optimistic_state=A(this.optimistic_state,z.data?.update);else this.authoritative_state=A(this.authoritative_state,z.data?.update),this.optimistic_state=A(this.optimistic_state,z.data?.update),this.authoritative_key=Z;this.manifest.observeVersionId(Q)}if(this.db)j(k,this.authoritative_state,this.db);return this.authoritative_state}catch(J){if(J.name==="NoSuchKey")return this.authoritative_state=q,this.authoritative_state;else throw J}}}class $0{J;$;W;queue=Promise.resolve();constructor(J,$,W){this.ref=J;this.handler=$;this.lastVersion=W}notify(J,$,W){this.queue=this.queue.then(()=>W).then((X)=>{if($!==this.lastVersion)console.log(`${J} NOTIFY ${F(this.ref)} ${$}`),this.lastVersion=$,this.handler(X)})}}class m{J;$;subscribers=new Set;poller;pollInProgress=!1;manifestState=new p(this);operationQueue=new g;constructor(J,$){this.service=J;this.ref=$;console.log("Create manifest",F($))}load(J){this.manifestState.restore(J),this.operationQueue.restore(J,async($,W)=>{if(!W)await this.service._putAll($,{manifests:[this.ref],await:"local",isLoad:!0});else await this.updateContent($,Promise.resolve(new Map([[this.ref,W]])),{await:"local",isLoad:!0})})}observeVersionId(J){this.operationQueue.confirm(J)}async poll(){if(this.pollInProgress)return;if(this.pollInProgress=!0,this.subscriberCount===0&&this.poller)clearInterval(this.poller),this.poller=void 0;if(this.subscriberCount>0&&!this.poller)this.poller=setInterval(()=>this.poll(),this.service.config.pollFrequency);const J=await this.manifestState.getLatest();if(J===void 0){this.pollInProgress=!1;return}const $=await this.operationQueue.flatten();this.subscribers.forEach(async(W)=>{if($.has(W.ref))W.notify(this.service.config.label,"local",Promise.resolve($.get(W.ref)));else{const X=J.files[F(W.ref)];if(X){const Z=this.service._getObject({operation:"GET_CONTENT",ref:W.ref,version:X.version});W.notify(this.service.config.label,X.version,Z.then((z)=>z.data))}else if(X===null)W.notify(this.service.config.label,void 0,Promise.resolve(void 0))}}),this.pollInProgress=!1}updateContent(J,$,W){const X=this.operationQueue.propose($,J,W.isLoad),Z=X.then(async()=>{try{const z=await $,Q=await this.manifestState.getLatest();Q.previous=this.manifestState.authoritative_key,Q.update={files:{}};for(let[O,U]of z){const _=F(O);if(U){const L={version:U};Q.update.files[_]=L}else Q.update.files[_]=null}const Y=t()+"_"+E().substring(0,2),B=this.ref.key+"@"+Y;this.operationQueue.label($,Y,W.isLoad),await this.service._putObject({operation:"PUT_MANIFEST",ref:{key:B,bucket:this.ref.bucket},value:Q});const P=await this.service._putObject({operation:"PUT_POLL",ref:{key:this.ref.key,bucket:this.ref.bucket},value:this.manifestState.authoritative_key});return this.poll(),P}catch(z){throw console.error(z),this.operationQueue.cancel($,W.isLoad),z}});if(W.await==="local")return X;else return Z}async getOptimisticVersion(J){return await this.manifestState.getLatest(),this.manifestState.optimistic_state.files[F(J)]?.version}subscribe(J,$){console.log(`SUBSCRIBE ${F(J)} ${this.subscriberCount+1}`);const W=new $0(J,$);return this.subscribers.add(W),()=>this.subscribers.delete(W)}get subscriberCount(){return this.subscribers.size}}async function W0(J){const $=(new TextEncoder()).encode(J),W=await crypto.subtle.digest("SHA-256",$);return[...new Uint8Array(W)].map((X)=>X.toString(16).padStart(2,"0")).join("")}class B0{config;s3ClientLite;manifests=new V(F);memCache=new V((J)=>`${J.Bucket}${J.Key}${J.VersionId}${J.IfNoneMatch}`);diskCache;endpoint;constructor(J){if(this.config={...J,label:J.label||"default",useChecksum:J.useChecksum===!1?!1:!0,online:J.online===!1?!1:!0,offlineStorage:J.offlineStorage===!1?!1:!0,useVersioning:J.useVersioning||!1,pollFrequency:J.pollFrequency||1000,defaultManifest:{bucket:J.defaultManifest?.bucket||J.defaultBucket,key:typeof J.defaultManifest=="string"?J.defaultManifest:J.defaultManifest?.key||"manifest.json"}},this.config.s3Config?.credentials instanceof Function)throw Error("We can't do that yet");this.endpoint=J.s3Config.endpoint||`https://s3.${J.s3Config.region}.amazonaws.com`;let $;if(this.config.s3Config?.credentials){const W=new S({accessKeyId:this.config.s3Config.credentials.accessKeyId,secretAccessKey:this.config.s3Config.credentials.secretAccessKey,sessionToken:this.config.s3Config.credentials.sessionToken,region:this.config.s3Config.region||"us-east-1",service:"s3",retries:0});$=(...X)=>W.fetch(...X)}else $=(global||window).fetch.bind(global||window);if(this.config.offlineStorage){const W=`mps3-${this.config.label}`;this.diskCache=I(W,"v0")}this.s3ClientLite=new b(this.config.online?$:()=>new Promise(()=>{}),this.endpoint,J.parser||new DOMParser)}getOrCreateManifest(J){if(!this.manifests.has(J)){const $=new m(this,J);if(this.manifests.set(J,$),this.config.offlineStorage){const W=`mps3-${this.config.label}-${J.bucket}-${J.key}`,X=I(W,"v0");console.log(`${this.config.label} Restoring manifest from ${W}`),$.load(X)}}return this.manifests.get(J)}async get(J,$={}){const W={...this.config.defaultManifest,...$.manifest},X=this.getOrCreateManifest(W),Z={bucket:J.bucket||this.config.defaultBucket||this.config.defaultManifest.bucket,key:typeof J==="string"?J:J.key},z=await X.operationQueue.flatten();if(z.has(Z))return console.log(`${this.config.label} GET (cached) ${Z} ${z.get(Z)}`),z.get(Z);const Q=await X.getOptimisticVersion(Z);if(Q===void 0)return;return(await this._getObject({operation:"GET",ref:Z,version:Q})).data}async _getObject(J){let $;if(this.config.useVersioning)$={Bucket:J.ref.bucket,Key:J.ref.key,IfNoneMatch:J.ifNoneMatch,...J.version&&{VersionId:J.version}};else $={Bucket:J.ref.bucket,Key:`${J.ref.key}${J.version?`@${J.version}`:""}`,IfNoneMatch:J.ifNoneMatch};if(this.memCache.has($))return console.log(`${this.config.label} ${J.operation} (mem cached) ${$.Bucket}/${$.Key}`),this.memCache.get($);const W=`${$.Bucket}${$.Key}${$.VersionId}`;if(this.diskCache){const Z=await G(W,this.diskCache);if(Z)return console.log(`${this.config.label} ${J.operation} (disk cached) ${W}`),this.memCache.set($,Promise.resolve(Z)),Z}if(!this.config.online)throw new Error(`${this.config.label} Offline and value not cached for ${W}`);const X=this.s3ClientLite.getObject($).then(async(Z)=>{const z={$metadata:Z.$metadata,ETag:Z.ETag,data:Z.Body};return console.log(`${this.config.label} ${J.operation} ${J.ref.bucket}/${J.ref.key}@${J.version} => ${z.VersionId}`),z}).catch((Z)=>{if(Z?.name==="304")return{$metadata:{httpStatusCode:304},data:void 0};else throw Z});if(this.memCache.set($,X),this.diskCache)X.then((Z)=>{j(`${$.Bucket}${$.Key}${$.VersionId}`,Z,this.diskCache).then(()=>console.log(`${this.config.label} STORE ${$.Bucket}${$.Key}`))});return X}async delete(J,$={}){return this.putAll(new Map([[J,void 0]]),$)}async put(J,$,W={}){if(!this.diskCache)throw new Error("No store");return this.putAll(new Map([[J,$]]),W)}async putAll(J,$={}){const W=new Map([...J].map(([Z,z])=>[{bucket:Z.bucket||this.config.defaultBucket||this.config.defaultManifest.bucket,key:typeof Z==="string"?Z:Z.key},z])),X=($?.manifests||[this.config.defaultManifest]).map((Z)=>({...this.config.defaultManifest,...Z}));return this._putAll(W,{manifests:X,await:$.await||this.config.online?"remote":"local"})}async _putAll(J,$){const W=new Map,X=new Promise(async(Z,z)=>{const Q=new Map,Y=[];J.forEach((B,P)=>{if(B!==void 0){let O=this.config.useVersioning?void 0:E();W.set(P,B),Y.push(this._putObject({operation:"PUT_CONTENT",ref:P,value:B,version:O}).then((U)=>{if(this.config.useVersioning)if(U.VersionId===void 0)throw console.error(U),Error(`Bucket ${P.bucket} is not version enabled!`);else O=U.VersionId;Q.set(P,O)}))}else Y.push(this._deleteObject({ref:P}).then((O)=>{Q.set(P,void 0)}))}),await Promise.all(Y).catch(z),Z(Q)});return Promise.all($.manifests.map((Z)=>{return this.getOrCreateManifest(Z).updateContent(W,X,{await:$.await,isLoad:$.isLoad===!0})}))}async _putObject(J){const $=JSON.stringify(J.value,null,2);let W;if(this.config.useVersioning)W={Bucket:J.ref.bucket,Key:J.ref.key,ContentType:"application/json",Body:$,...this.config.useChecksum&&{ChecksumSHA256:await W0($)}};else W={Bucket:J.ref.bucket,Key:`${J.ref.key}${J.version?`@${J.version}`:""}`,ContentType:"application/json",Body:$,...this.config.useChecksum&&{ChecksumSHA256:await W0($)}};const X=await this.s3ClientLite.putObject(W);if(console.log(`${this.config.label} ${J.operation} ${W.Bucket}/${W.Key} => ${X.VersionId}`),this.diskCache){const Z=`${W.Bucket}${W.Key}${J.version||X.VersionId}`;await j(Z,{$metadata:{httpStatusCode:200},etag:X.ETag,data:JSON.parse($)},this.diskCache).then(()=>console.log(`${this.config.label} STORE ${Z}`))}return X}async _deleteObject(J){const $={Bucket:J.ref.bucket,Key:J.ref.key},W=await this.s3ClientLite.deleteObject($);return console.log(`${this.config.label} ${J.operation||"DELETE"} ${J.ref.bucket}/${J.ref.key} => ${W.VersionId}`),W}subscribe(J,$,W){const X={...this.config.defaultManifest,...W?.manifest},Z={key:typeof J==="string"?J:J.key,bucket:J.bucket||this.config.defaultBucket||X.bucket},z=this.getOrCreateManifest(X),Q=z.subscribe(Z,$);return this.get(Z,{manifest:X}).then((Y)=>{console.log(`${this.config.label} NOTIFY (initial) ${F(Z)}`),queueMicrotask(()=>{$(Y,void 0),z.poll()})}).catch((Y)=>{$(void 0,Y)}),Q}refresh(){return Promise.all([...this.manifests.values()].map((J)=>J.poll()))}get subscriberCount(){return[...this.manifests.values()].reduce((J,$)=>J+$.subscriberCount,0)}}export{B0 as MPS3};
{
"name": "mps3",
"description": "Provide clientside multiplayer and optimistic updates over any s3-compatible storage API",
"version": "0.0.66",
"version": "0.0.67",
"license": "MIT",

@@ -6,0 +6,0 @@ "author": {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc