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.74 to 0.0.75

2

dist/mps3.js

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

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

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

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc