s3db.js 3.1.0 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/s3db.cjs.js CHANGED
@@ -1365,7 +1365,7 @@ class Schema {
1365
1365
  this.reversedMap = lodashEs.invert(map);
1366
1366
  } else {
1367
1367
  const flatAttrs = flat.flatten(this.attributes, { safe: true });
1368
- this.reversedMap = { ...Object.keys(flatAttrs).filter((k) => !k.includes("$$type")) };
1368
+ this.reversedMap = { ...Object.keys(flatAttrs).filter((k) => !k.startsWith("$$")) };
1369
1369
  this.map = lodashEs.invert(this.reversedMap);
1370
1370
  }
1371
1371
  }
@@ -4,7 +4,7 @@
4
4
  Verbose:
5
5
 
6
6
  ${JSON.stringify(n,null,2)}`),super(i),typeof Error.captureStackTrace=="function"?Error.captureStackTrace(this,this.constructor):this.stack=new Error(i).stack,super.name=this.constructor.name,this.name=this.constructor.name,this.bucket=r,this.thrownAt=new Date}toJson(){return{...this}}toString(){return`${this.name} | ${this.message}`}}class ui extends We{constructor({bucket:t,...r}){super({...r,bucket:t,message:`Bucket does not exists [bucket:${t}]`})}}class or extends We{constructor({bucket:t,key:r,...i}){super({...i,bucket:t,message:`Key does not exists [bucket:${t}/${r}]`}),this.key=r}}class di extends or{}class pi extends We{constructor({bucket:t,...r}){super({...r,bucket:t,message:`Missing metadata for bucket [bucket:${t}]`})}}class Tt extends We{constructor({bucket:t,resourceName:r,attributes:i,validation:n}){super({bucket:t,message:`This item is not valid. Resource=${r} [bucket:${t}].
7
- ${JSON.stringify(n,null,2)}`}),this.resourceName=r,this.attributes=i,this.validation=n}}class _i extends We{}const wi={NotFound:di,NoSuchKey:or,UnknownError:_i,NoSuchBucket:ui,MissingMetadata:pi,InvalidResourceItem:Tt},gi="us-east-1",vi="https://s3.us-east-1.amazonaws.com";class mi{constructor(t){let r;try{r=new URL(t)}catch{throw new Error("Invalid connection string: "+t)}this.region=gi,r.protocol==="s3:"?this.defineS3(r):this.defineMinio(r);for(const[i,n]of r.searchParams.entries())this[i]=n}defineS3(t){if(this.bucket=t.hostname,this.accessKeyId=t.username,this.secretAccessKey=t.password,this.endpoint=vi,["/","",null].includes(t.pathname))this.keyPrefix="";else{let[,...r]=t.pathname.split("/");this.keyPrefix=[...r||[]].join("/")}}defineMinio(t){if(this.forcePathStyle=!0,this.endpoint=t.origin,this.accessKeyId=t.username,this.secretAccessKey=t.password,["/","",null].includes(t.pathname))this.bucket="s3db",this.keyPrefix="";else{let[,r,...i]=t.pathname.split("/");this.bucket=r,this.keyPrefix=[...i||[]].join("/")}}}class bi extends b{constructor({verbose:t=!1,id:r=null,AwsS3Client:i,connectionString:n,parallelism:a=10}){super(),this.verbose=t,this.id=r??ni.nanoid(7),this.parallelism=a,this.config=new mi(n),this.client=i||this.createClient()}createClient(){let t={region:this.config.region,endpoint:this.config.endpoint};return this.config.forcePathStyle&&(t.forcePathStyle=!0),this.config.accessKeyId&&(t.credentials={accessKeyId:this.config.accessKeyId,secretAccessKey:this.config.secretAccessKey}),new de.S3Client(t)}async sendCommand(t){this.emit("command.request",t.constructor.name,t.input);const r=console.warn;try{console.warn=n=>{n.includes("Stream of unknown length")||r(n)}}catch(n){console.error(n)}const i=await this.client.send(t);this.emit("command.response",t.constructor.name,i,t.input);try{console.warn=r}catch(n){console.error(n)}return i}errorProxy(t,r){this.verbose&&(r.bucket=this.config.bucket,r.config=this.config,r.verbose=this.verbose),t.data=r;const i=wi[t.name];return i?new i(r):t}async putObject({key:t,metadata:r,contentType:i,body:n,contentEncoding:a}){const o={Bucket:this.config.bucket,Key:this.config.keyPrefix?ne.join(this.config.keyPrefix,t):t,Metadata:{...r},Body:n||"",ContentType:i,ContentEncoding:a};try{const s=await this.sendCommand(new de.PutObjectCommand(o));return this.emit("putObject",s,o),s}catch(s){throw this.errorProxy(s,{key:t,command:o})}}async getObject(t){const r={Bucket:this.config.bucket,Key:ne.join(this.config.keyPrefix,t)};try{const i=await this.sendCommand(new de.GetObjectCommand(r));return this.emit("getObject",i,r),i}catch(i){throw this.errorProxy(i,{key:t,command:r})}}async headObject(t){const r={Bucket:this.config.bucket,Key:this.config.keyPrefix?ne.join(this.config.keyPrefix,t):t};try{const i=await this.client.send(new de.HeadObjectCommand(r));return this.emit("headObject",i,r),i}catch(i){throw this.errorProxy(i,{key:t,command:r})}}async copyObject({from:t,to:r}){const i={Bucket:this.config.bucket,Key:this.config.keyPrefix?ne.join(this.config.keyPrefix,r):r,CopySource:ne.join(this.config.bucket,this.config.keyPrefix?ne.join(this.config.keyPrefix,t):t)};try{const n=await this.client.send(new de.CopyObjectCommand(i));return this.emit("copyObject",n,i),n}catch(n){throw this.errorProxy(n,{from:t,to:r,command:i})}}async exists(t){try{return await this.headObject(t),!0}catch(r){if(r.name==="NoSuchKey")return!1;if(r.name==="NotFound")return!1;throw r}}async deleteObject(t){const r={Bucket:this.config.bucket,Key:this.config.keyPrefix?ne.join(this.config.keyPrefix,t):t};try{const i=await this.sendCommand(new de.DeleteObjectCommand(r));return this.emit("deleteObject",i,r),i}catch(i){throw this.errorProxy(i,{key:t,command:r})}}async deleteObjects(t){const r=O.chunk(t,1e3),{results:i,errors:n}=await ue.PromisePool.for(r).withConcurrency(this.parallelism).process(async o=>{const s={Bucket:this.config.bucket,Delete:{Objects:o.map(h=>({Key:this.config.keyPrefix?ne.join(this.config.keyPrefix,h):h}))}};try{return await this.sendCommand(new de.DeleteObjectsCommand(s))}catch(h){throw this.errorProxy(h,{key,command:s})}}),a={deleted:i,notFound:n};return this.emit("deleteObjects",a,t),a}async deleteAll({prefix:t}={}){const r=await this.getAllKeys({prefix:t}),i=await this.deleteObjects(r);return this.emit("deleteAll",{prefix:t,report:i}),i}async moveObject({from:t,to:r}){try{return await this.copyObject({from:t,to:r}),await this.deleteObject(t),!0}catch(i){throw this.errorProxy(i,{from:t,to:r,command:options})}}async listObjects({prefix:t,maxKeys:r=1e3,continuationToken:i}={}){const n={Bucket:this.config.bucket,MaxKeys:r,ContinuationToken:i,Prefix:this.config.keyPrefix?ne.join(this.config.keyPrefix,t||""):t||""};try{const a=await this.sendCommand(new de.ListObjectsV2Command(n));return this.emit("listObjects",a,n),a}catch(a){throw this.errorProxy(a,{command:n})}}async count({prefix:t}={}){let r=0,i=!0,n;for(;i;){const a={prefix:t,continuationToken:n},o=await this.listObjects(a);r+=o.KeyCount||0,i=o.IsTruncated||!1,n=o.NextContinuationToken}return this.emit("count",r,{prefix:t}),r}async getAllKeys({prefix:t}={}){let r=[],i=!0,n;for(;i;){const a={prefix:t,continuationToken:n},o=await this.listObjects(a);o.Contents&&(r=r.concat(o.Contents.map(s=>s.Key))),i=o.IsTruncated||!1,n=o.NextContinuationToken}return this.config.keyPrefix&&(r=r.map(a=>a.replace(this.config.keyPrefix,"")).map(a=>a.startsWith("/")?a.replace("/",""):a)),this.emit("getAllKeys",r,{prefix:t}),r}async getContinuationTokenAfterOffset(t={}){const{prefix:r,offset:i=1e3}=t;if(i===0)return null;let n=!0,a,o=0;for(;n;){let s=i<1e3?i:i-o>1e3?1e3:i-o;const h={prefix:r,maxKeys:s,continuationToken:a},f=await this.listObjects(h);if(f.Contents&&(o+=f.Contents.length),n=f.IsTruncated||!1,a=f.NextContinuationToken,o>=i)break}return this.emit("getContinuationTokenAfterOffset",a,t),a}async getKeysPage(t={}){const{prefix:r,offset:i=0,amount:n=100}=t;let a=[],o=!0,s;for(i>0&&(s=await this.getContinuationTokenAfterOffset({prefix:r,offset:i}));o;){const h={prefix:r,continuationToken:s},f=await this.listObjects(h);if(f.Contents&&(a=a.concat(f.Contents.map(l=>l.Key))),o=f.IsTruncated||!1,s=f.NextContinuationToken,a.length>n){a=a.splice(0,n);break}}return this.config.keyPrefix&&(a=a.map(h=>h.replace(this.config.keyPrefix,"")).map(h=>h.startsWith("/")?h.replace("/",""):h)),this.emit("getKeysPage",a,t),a}async moveAllObjects({prefixFrom:t,prefixTo:r}){const i=await this.getAllKeys({prefix:t}),{results:n,errors:a}=await ue.PromisePool.for(i).withConcurrency(this.parallelism).process(async o=>{const s=o.replace(t,r);try{return await this.moveObject({from:o,to:s}),s}catch(h){throw this.errorProxy(h,{from:o,to:s})}});if(this.emit("moveAllObjects",{results:n,errors:a},{prefixFrom:t,prefixTo:r}),a.length>0)throw console.log({errors:a}),new Error("Some objects could not be moved");return n}}async function Lt(){return O.isObject(process)?(await Promise.resolve().then(function(){return vh})).webcrypto:window.crypto}async function yi(e){const t=await Lt(),i=new TextEncoder().encode(e),n=await t.subtle.digest("SHA-256",i);return Array.from(new Uint8Array(n)).map(s=>s.toString(16).padStart(2,"0")).join("")}async function sr(e,t){const r=await Lt(),i=r.getRandomValues(new Uint8Array(16)),n=await Ei(t,i),a=r.getRandomValues(new Uint8Array(12)),s=new TextEncoder().encode(e),h=await r.subtle.encrypt({name:"AES-GCM",iv:a},n,s),f=new Uint8Array(i.length+a.length+h.byteLength);return f.set(i),f.set(a,i.length),f.set(new Uint8Array(h),i.length+a.length),ao(f)}async function xi(e,t){const r=await Lt(),i=oo(e),n=i.slice(0,16),a=i.slice(16,28),o=i.slice(28),s=await Ei(t,n),h=await r.subtle.decrypt({name:"AES-GCM",iv:a},s,o);return new TextDecoder().decode(h)}async function Ei(e,t){const r=await Lt(),n=new TextEncoder().encode(e),a=await r.subtle.importKey("raw",n,{name:"PBKDF2"},!1,["deriveKey"]);return await r.subtle.deriveKey({name:"PBKDF2",salt:t,iterations:1e5,hash:"SHA-256"},a,{name:"AES-GCM",length:256},!0,["encrypt","decrypt"])}function ao(e){if(O.isObject(process))return Buffer.from(e).toString("base64");{const t=String.fromCharCode.apply(null,new Uint8Array(e));return window.btoa(t)}}function oo(e){if(O.isObject(process))return new Uint8Array(Buffer.from(e,"base64"));{const t=window.atob(e),r=t.length,i=new Uint8Array(r);for(let n=0;n<r;n++)i[n]=t.charCodeAt(n);return i}}async function fr(e,t,r){if(!this.passphrase)return t.push({actual:e,type:"encryptionKeyMissing"}),e;try{return await sr(String(e),this.passphrase)}catch(i){t.push({actual:e,type:"encryptionProblem",error:i})}return e}class ki extends Za{constructor({options:t,passphrase:r,autoEncrypt:i=!0}={}){super(O.merge({},{useNewCustomCheckerFunction:!0,messages:{encryptionKeyMissing:"Missing configuration for secrets encryption.",encryptionProblem:"Problem encrypting secret. Actual: {actual}. Error: {error}"},defaults:{string:{trim:!0},object:{strict:"remove"}}},t)),this.passphrase=r,this.autoEncrypt=i,this.alias("secret",{type:"string",custom:this.autoEncrypt?fr:void 0,messages:{string:"The '{field}' field must be a string.",stringMin:"This secret '{field}' field length must be at least {expected} long."}}),this.alias("secretAny",{type:"any",custom:this.autoEncrypt?fr:void 0}),this.alias("secretNumber",{type:"number",custom:this.autoEncrypt?fr:void 0})}}const Si=new Proxy(ki,{instance:null,construct(e,t){return this.instance||(this.instance=new e(...t)),this.instance}}),so={trim:e=>e.trim(),encrypt:(e,{passphrase:t})=>sr(e,t),decrypt:(e,{passphrase:t})=>xi(e,t),toString:e=>String(e),fromArray:(e,{separator:t})=>(e||[]).join(t),toArray:(e,{separator:t})=>(e||"").split(t),toNumber:e=>O.isString(e)?e.includes(".")?parseFloat(e):parseInt(e):e,toJSON:e=>JSON.stringify(e),fromJSON:e=>JSON.parse(e)};class ti{constructor(t){const{map:r,name:i,attributes:n,passphrase:a,version:o=1,options:s={}}=t;if(this.name=i,this.version=o,this.attributes=n,this.passphrase=a??"secret",this.options=O.merge({},this.defaultOptions(),s),this.validator=new Si({autoEncrypt:!1}).compile(O.merge({$$async:!0},O.cloneDeep(this.attributes))),this.options.generateAutoHooks&&this.generateAutoHooks(),!O.isEmpty(r))this.map=r,this.reversedMap=O.invert(r);else{const h=At.flatten(this.attributes,{safe:!0});this.reversedMap={...Object.keys(h).filter(f=>!f.includes("$$type"))},this.map=O.invert(this.reversedMap)}}defaultOptions(){return{autoEncrypt:!0,autoDecrypt:!0,arraySeparator:"|",generateAutoHooks:!0,hooks:{beforeMap:{},afterMap:{},beforeUnmap:{},afterUnmap:{}}}}addHook(t,r,i){this.options.hooks[t][r]||(this.options.hooks[t][r]=[]),this.options.hooks[t][r]=O.uniq([...this.options.hooks[t][r],i])}generateAutoHooks(){const t=At.flatten(O.cloneDeep(this.attributes),{safe:!0});for(const[r,i]of Object.entries(t))i.includes("array")?(this.addHook("beforeMap",r,"fromArray"),this.addHook("afterUnmap",r,"toArray")):(i.includes("secret")&&(this.options.autoEncrypt&&this.addHook("beforeMap",r,"encrypt"),this.options.autoDecrypt&&this.addHook("afterUnmap",r,"decrypt")),i.includes("number")&&(this.addHook("beforeMap",r,"toString"),this.addHook("afterUnmap",r,"toNumber")),i.includes("boolean")&&(this.addHook("beforeMap",r,"toJson"),this.addHook("afterUnmap",r,"fromJson")))}static import(t){let{map:r,name:i,options:n,version:a,attributes:o}=O.isString(t)?JSON.parse(t):t;return new ti({map:r,name:i,options:n,version:a,attributes:o})}export(){const t={version:this.version,name:this.name,options:this.options,attributes:O.cloneDeep(this.attributes),map:this.map};for(const[r,i]of Object.entries(this.attributes))t.attributes[r]=JSON.stringify(i);return t}async applyHooksActions(t,r){for(const[i,n]of Object.entries(this.options.hooks[r]))for(const a of n){const o=O.get(t,i);o&&O.set(t,i,await so[a](o,{passphrase:this.passphrase,separator:this.options.arraySeparator}))}}async validate(t,{mutateOriginal:r=!1}={}){let i=r?t:O.cloneDeep(t);return await this.validator(i)}async mapper(t){const r=At.flatten(O.cloneDeep(t),{safe:!0});await this.applyHooksActions(r,"beforeMap");const i={_v:this.version+""};for(const[n,a]of Object.entries(r))i[this.map[n]]=a;return await this.applyHooksActions(i,"afterMap"),i}async unmapper(t){const r=O.cloneDeep(t);delete r._v,await this.applyHooksActions(r,"beforeUnmap");const i={};for(const[n,a]of Object.entries(r))i[this.reversedMap[n]]=a;return await this.applyHooksActions(i,"afterUnmap"),At.unflatten(i)}}class Ri extends b{constructor({resource:t}){super(),this.resource=t,this.client=t.client,this.stream=new rr.ReadableStream({highWaterMark:this.client.parallelism*3,start:this._start.bind(this),pull:this._pull.bind(this),cancel:this._cancel.bind(this)})}build(){return this.stream.getReader()}async _start(t){this.controller=t,this.continuationToken=null,this.closeNextIteration=!1}async _pull(t){if(this.closeNextIteration){t.close();return}const r=await this.client.listObjects({prefix:`resource=${this.resource.name}`,continuationToken:this.continuationToken}),i=r?.Contents.map(n=>n.Key).map(n=>n.replace(this.client.config.keyPrefix,"")).map(n=>n.startsWith("/")?n.replace("/",""):n).map(n=>n.replace(`resource=${this.resource.name}/id=`,""));this.continuationToken=r.NextContinuationToken,this.enqueue(i),r.IsTruncated||(this.closeNextIteration=!0)}enqueue(t){t.forEach(r=>{this.controller.enqueue(r),this.emit("id",r)})}_cancel(t){console.warn("Stream cancelled",t)}}class Ai extends Ri{enqueue(t){this.controller.enqueue(t),this.emit("page",t)}}class Ti extends b{constructor({resource:t}){super(),this.resource=t,this.client=t.client,this.input=new Ai({resource:this.resource}),this.output=new rr.TransformStream({transform:this._transform.bind(this)},{highWaterMark:this.client.parallelism*2},{highWaterMark:1}),this.stream=this.input.stream.pipeThrough(this.output)}build(){return this.stream.getReader()}async _transform(t,r){await ue.PromisePool.for(t).withConcurrency(this.client.parallelism).process(async i=>{const n=await this.resource.get(i);return r.enqueue(n),n})}}class Li extends b{constructor({resource:t}){super(),this.resource=t,this.client=t.client,this.stream=new rr.WritableStream({start:this._start.bind(this),write:this._write.bind(this),close:this._close.bind(this),abort:this._abort.bind(this)})}build(){return this.stream.getWriter()}async _start(t){this.controller=t}async _write(t,r){const i=this.resource;await ue.PromisePool.for([].concat(t)).withConcurrency(this.client.parallelism).process(async n=>{await i.insert(n)})}async _close(t){}async _abort(t){console.error("Stream aborted:",t)}}function lr(e){return new Promise((t,r)=>{const i=[];e.on("data",n=>i.push(n)),e.on("error",r),e.on("end",()=>t(Buffer.concat(i).toString("utf-8")))})}class Ci extends b{constructor({name:t,client:r,options:i={},attributes:n={},parallelism:a=10,passphrase:o="secret",observers:s=[]}){super(),this.name=t,this.client=r,this.options=i,this.observers=s,this.parallelism=a,this.passphrase=o??"secret",this.schema=new ti({name:t,attributes:n,passphrase:o})}export(){return this.schema.export()}async validate(t){const r={original:O.cloneDeep(t),isValid:!1,errors:[]},i=await this.schema.validate(t,{mutateOriginal:!0});return i===!0?r.isValid=!0:r.errors=i,r.data=t,r}async insert({id:t,...r}){const{errors:i,isValid:n,data:a}=await this.validate(r);if(!n)throw new Tt({bucket:this.client.config.bucket,resourceName:this.name,attributes:r,validation:i});!t&&t!==0&&(t=ni.nanoid());const o=await this.schema.mapper(a);await this.client.putObject({metadata:o,key:Y(`resource=${this.name}`,`id=${t}`)});const s=O.merge({id:t},a);return this.emit("insert",s),s}async get(t){const r=await this.client.headObject(Y(`resource=${this.name}`,`id=${t}`));let i=await this.schema.unmapper(r.Metadata);return i.id=t,i._length=r.ContentLength,i._createdAt=r.LastModified,r.Expiration&&(i._expiresAt=r.Expiration),this.emit("get",i),i}async update(t,r){const i=await this.get(t),n=O.merge(i,r);delete n.id;const{isValid:a,errors:o,data:s}=await this.validate(n);if(!a)throw new Tt({bucket:this.client.bucket,resourceName:this.name,attributes:r,validation:o});return await this.client.putObject({key:Y(`resource=${this.name}`,`id=${t}`),body:"",metadata:await this.schema.mapper(s)}),s.id=t,this.emit("update",r,s),s}async delete(t){const r=Y(`resource=${this.name}`,`id=${t}`),i=await this.client.deleteObject(r);return this.emit("delete",t),i}async count(){const t=await this.client.count({prefix:`resource=${this.name}`});return this.emit("count",t),t}async insertMany(t){const{results:r}=await ue.PromisePool.for(t).withConcurrency(this.parallelism).handleError(async(i,n)=>{this.emit("error",i,n),this.observers.map(a=>a.emit("error",this.name,i,n))}).process(async i=>await this.insert(i));return this.emit("insertMany",t.length),r}async deleteMany(t){const r=O.chunk(t.map(n=>Y(`resource=${this.name}`,`id=${n}`)),1e3),{results:i}=await ue.PromisePool.for(r).withConcurrency(this.parallelism).handleError(async(n,a)=>{this.emit("error",n,a),this.observers.map(o=>o.emit("error",this.name,n,a))}).process(async n=>{const a=await this.client.deleteObjects(n);return n.forEach(o=>{const s=o.split("=").pop();this.emit("deleted",s),this.observers.map(h=>h.emit("deleted",this.name,s))}),a});return this.emit("deleteMany",t.length),i}async deleteAll(){const t=await this.listIds();this.emit("deleteAll",t.length),await this.deleteMany(t)}async listIds(){const r=(await this.client.getAllKeys({prefix:`resource=${this.name}`})).map(i=>i.replace(`resource=${this.name}/id=`,""));return this.emit("listIds",r.length),r}async getMany(t){const{results:r}=await ue.PromisePool.for(t).withConcurrency(this.client.parallelism).process(async i=>{this.emit("id",i);const n=await this.get(i);return this.emit("data",n),n});return this.emit("getMany",t.length),r}async getAll(){let t=await this.listIds();if(t.length===0)return[];const{results:r}=await ue.PromisePool.for(t).withConcurrency(this.client.parallelism).process(async i=>await this.get(i));return this.emit("getAll",r.length),r}async page({offset:t=0,size:r=100}){const n=(await this.client.getKeysPage({offset:t,amount:r,prefix:`resource=${this.name}`})).map(o=>o.replace(`resource=${this.name}/id=`,""));return await this.getMany(n)}readable(){return new Ti({resource:this}).build()}writable(){return new Li({resource:this}).build()}}class Oi extends b{constructor(t){super(),this.version="1",this.resources={},this.options=t,this.verbose=t.verbose||!1,this.parallelism=parseInt(t.parallelism+"")||10,this.plugins=t.plugins||[],this.cache=t.cache,this.passphrase=t.passphrase||"secret",this.client=t.client||new bi({verbose:this.verbose,parallelism:this.parallelism,connectionString:t.connectionString}),this.bucket=this.client.bucket,this.keyPrefix=this.client.keyPrefix}async connect(){await this.startPlugins();let t=null;if(await this.client.exists("s3db.json")){const r=await this.client.getObject("s3db.json");t=JSON.parse(await lr(r?.Body)),t=this.unserializeMetadata(t)}else t=this.blankMetadataStructure(),await this.uploadMetadataFile();for(const r of Object.entries(t.resources)){const[i,n]=r;this.resources[i]=new Ci({name:i,client:this.client,options:n.options,attributes:n.schema,parallelism:this.parallelism,passphrase:this.passphrase,observers:[this]})}this.emit("connected",new Date)}async startPlugins(){const t=this;if(!O.isEmpty(this.plugins)){const r=this.plugins.map(a=>O.isFunction(a)?new a(this):a),i=r.map(async a=>{a.beforeSetup&&await a.beforeSetup(),await a.setup(t),a.afterSetup&&await a.afterSetup()});await Promise.all(i);const n=r.map(async a=>{a.beforeStart&&await a.beforeStart(),await a.start(),a.afterStart&&await a.afterStart()});await Promise.all(n)}}unserializeMetadata(t){const r={...t};if(O.isEmpty(r.resources))return r;for(const[i,n]of Object.entries(r.resources))for(const[a,o]of Object.entries(n.attributes))r.resources[i].attributes[a]=JSON.parse(o);return r}async uploadMetadataFile(){const t={version:this.version,resources:Object.entries(this.resources).reduce((r,i)=>{const[n,a]=i;return r[n]=a.export(),r},{})};await this.client.putObject({key:"s3db.json",contentType:"application/json",body:JSON.stringify(t,null,2)})}blankMetadataStructure(){return{version:"1",resources:{}}}async createResource({name:t,attributes:r,options:i={}}){const n=new Ci({name:t,attributes:r,observers:[this],client:this.client,options:{autoDecrypt:!0,cache:this.cache,...i}});return this.resources[t]=n,await this.uploadMetadataFile(),this.emit("s3db.resourceCreated",t),n}resource(t){return this.resources[t]?this.resources[t]:Promise.reject(`resource ${t} does not exist`)}}class fo extends Oi{}class hr extends b{async _set(t,r){}async _get(t){}async _del(t){}async _clear(t){}async set(t,r){return await this._set(t,r),this.emit("set",r),r}async get(t){const r=await this._get(t);return this.emit("get",r),r}async del(t){const r=await this._del(t);return this.emit("delete",r),r}async clear(){const t=await this._clear();return this.emit("clear",t),t}}class lo extends hr{constructor(){super(),this.cache={}}async _set(t,r){return this.cache[t]=r,r}async _get(t){return this.cache[t]}async _del(t){return delete this.cache[t],!0}async _clear(){return this.cache={},!0}}var Ye=typeof global<"u"?global:typeof self<"u"?self:typeof window<"u"?window:{},ee=[],q=[],ho=typeof Uint8Array<"u"?Uint8Array:Array,cr=!1;function Ii(){cr=!0;for(var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",t=0,r=e.length;t<r;++t)ee[t]=e[t],q[e.charCodeAt(t)]=t;q[45]=62,q[95]=63}function co(e){cr||Ii();var t,r,i,n,a,o,s=e.length;if(s%4>0)throw new Error("Invalid string. Length must be a multiple of 4");a=e[s-2]==="="?2:e[s-1]==="="?1:0,o=new ho(s*3/4-a),i=a>0?s-4:s;var h=0;for(t=0,r=0;t<i;t+=4,r+=3)n=q[e.charCodeAt(t)]<<18|q[e.charCodeAt(t+1)]<<12|q[e.charCodeAt(t+2)]<<6|q[e.charCodeAt(t+3)],o[h++]=n>>16&255,o[h++]=n>>8&255,o[h++]=n&255;return a===2?(n=q[e.charCodeAt(t)]<<2|q[e.charCodeAt(t+1)]>>4,o[h++]=n&255):a===1&&(n=q[e.charCodeAt(t)]<<10|q[e.charCodeAt(t+1)]<<4|q[e.charCodeAt(t+2)]>>2,o[h++]=n>>8&255,o[h++]=n&255),o}function uo(e){return ee[e>>18&63]+ee[e>>12&63]+ee[e>>6&63]+ee[e&63]}function po(e,t,r){for(var i,n=[],a=t;a<r;a+=3)i=(e[a]<<16)+(e[a+1]<<8)+e[a+2],n.push(uo(i));return n.join("")}function Mi(e){cr||Ii();for(var t,r=e.length,i=r%3,n="",a=[],o=16383,s=0,h=r-i;s<h;s+=o)a.push(po(e,s,s+o>h?h:s+o));return i===1?(t=e[r-1],n+=ee[t>>2],n+=ee[t<<4&63],n+="=="):i===2&&(t=(e[r-2]<<8)+e[r-1],n+=ee[t>>10],n+=ee[t>>4&63],n+=ee[t<<2&63],n+="="),a.push(n),a.join("")}function Ct(e,t,r,i,n){var a,o,s=n*8-i-1,h=(1<<s)-1,f=h>>1,l=-7,d=r?n-1:0,p=r?-1:1,u=e[t+d];for(d+=p,a=u&(1<<-l)-1,u>>=-l,l+=s;l>0;a=a*256+e[t+d],d+=p,l-=8);for(o=a&(1<<-l)-1,a>>=-l,l+=i;l>0;o=o*256+e[t+d],d+=p,l-=8);if(a===0)a=1-f;else{if(a===h)return o?NaN:(u?-1:1)*(1/0);o=o+Math.pow(2,i),a=a-f}return(u?-1:1)*o*Math.pow(2,a-i)}function Di(e,t,r,i,n,a){var o,s,h,f=a*8-n-1,l=(1<<f)-1,d=l>>1,p=n===23?Math.pow(2,-24)-Math.pow(2,-77):0,u=i?0:a-1,g=i?1:-1,S=t<0||t===0&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,o=l):(o=Math.floor(Math.log(t)/Math.LN2),t*(h=Math.pow(2,-o))<1&&(o--,h*=2),o+d>=1?t+=p/h:t+=p*Math.pow(2,1-d),t*h>=2&&(o++,h/=2),o+d>=l?(s=0,o=l):o+d>=1?(s=(t*h-1)*Math.pow(2,n),o=o+d):(s=t*Math.pow(2,d-1)*Math.pow(2,n),o=0));n>=8;e[r+u]=s&255,u+=g,s/=256,n-=8);for(o=o<<n|s,f+=n;f>0;e[r+u]=o&255,u+=g,o/=256,f-=8);e[r+u-g]|=S*128}var _o={}.toString,Fi=Array.isArray||function(e){return _o.call(e)=="[object Array]"};/*!
7
+ ${JSON.stringify(n,null,2)}`}),this.resourceName=r,this.attributes=i,this.validation=n}}class _i extends We{}const wi={NotFound:di,NoSuchKey:or,UnknownError:_i,NoSuchBucket:ui,MissingMetadata:pi,InvalidResourceItem:Tt},gi="us-east-1",vi="https://s3.us-east-1.amazonaws.com";class mi{constructor(t){let r;try{r=new URL(t)}catch{throw new Error("Invalid connection string: "+t)}this.region=gi,r.protocol==="s3:"?this.defineS3(r):this.defineMinio(r);for(const[i,n]of r.searchParams.entries())this[i]=n}defineS3(t){if(this.bucket=t.hostname,this.accessKeyId=t.username,this.secretAccessKey=t.password,this.endpoint=vi,["/","",null].includes(t.pathname))this.keyPrefix="";else{let[,...r]=t.pathname.split("/");this.keyPrefix=[...r||[]].join("/")}}defineMinio(t){if(this.forcePathStyle=!0,this.endpoint=t.origin,this.accessKeyId=t.username,this.secretAccessKey=t.password,["/","",null].includes(t.pathname))this.bucket="s3db",this.keyPrefix="";else{let[,r,...i]=t.pathname.split("/");this.bucket=r,this.keyPrefix=[...i||[]].join("/")}}}class bi extends b{constructor({verbose:t=!1,id:r=null,AwsS3Client:i,connectionString:n,parallelism:a=10}){super(),this.verbose=t,this.id=r??ni.nanoid(7),this.parallelism=a,this.config=new mi(n),this.client=i||this.createClient()}createClient(){let t={region:this.config.region,endpoint:this.config.endpoint};return this.config.forcePathStyle&&(t.forcePathStyle=!0),this.config.accessKeyId&&(t.credentials={accessKeyId:this.config.accessKeyId,secretAccessKey:this.config.secretAccessKey}),new de.S3Client(t)}async sendCommand(t){this.emit("command.request",t.constructor.name,t.input);const r=console.warn;try{console.warn=n=>{n.includes("Stream of unknown length")||r(n)}}catch(n){console.error(n)}const i=await this.client.send(t);this.emit("command.response",t.constructor.name,i,t.input);try{console.warn=r}catch(n){console.error(n)}return i}errorProxy(t,r){this.verbose&&(r.bucket=this.config.bucket,r.config=this.config,r.verbose=this.verbose),t.data=r;const i=wi[t.name];return i?new i(r):t}async putObject({key:t,metadata:r,contentType:i,body:n,contentEncoding:a}){const o={Bucket:this.config.bucket,Key:this.config.keyPrefix?ne.join(this.config.keyPrefix,t):t,Metadata:{...r},Body:n||"",ContentType:i,ContentEncoding:a};try{const s=await this.sendCommand(new de.PutObjectCommand(o));return this.emit("putObject",s,o),s}catch(s){throw this.errorProxy(s,{key:t,command:o})}}async getObject(t){const r={Bucket:this.config.bucket,Key:ne.join(this.config.keyPrefix,t)};try{const i=await this.sendCommand(new de.GetObjectCommand(r));return this.emit("getObject",i,r),i}catch(i){throw this.errorProxy(i,{key:t,command:r})}}async headObject(t){const r={Bucket:this.config.bucket,Key:this.config.keyPrefix?ne.join(this.config.keyPrefix,t):t};try{const i=await this.client.send(new de.HeadObjectCommand(r));return this.emit("headObject",i,r),i}catch(i){throw this.errorProxy(i,{key:t,command:r})}}async copyObject({from:t,to:r}){const i={Bucket:this.config.bucket,Key:this.config.keyPrefix?ne.join(this.config.keyPrefix,r):r,CopySource:ne.join(this.config.bucket,this.config.keyPrefix?ne.join(this.config.keyPrefix,t):t)};try{const n=await this.client.send(new de.CopyObjectCommand(i));return this.emit("copyObject",n,i),n}catch(n){throw this.errorProxy(n,{from:t,to:r,command:i})}}async exists(t){try{return await this.headObject(t),!0}catch(r){if(r.name==="NoSuchKey")return!1;if(r.name==="NotFound")return!1;throw r}}async deleteObject(t){const r={Bucket:this.config.bucket,Key:this.config.keyPrefix?ne.join(this.config.keyPrefix,t):t};try{const i=await this.sendCommand(new de.DeleteObjectCommand(r));return this.emit("deleteObject",i,r),i}catch(i){throw this.errorProxy(i,{key:t,command:r})}}async deleteObjects(t){const r=O.chunk(t,1e3),{results:i,errors:n}=await ue.PromisePool.for(r).withConcurrency(this.parallelism).process(async o=>{const s={Bucket:this.config.bucket,Delete:{Objects:o.map(h=>({Key:this.config.keyPrefix?ne.join(this.config.keyPrefix,h):h}))}};try{return await this.sendCommand(new de.DeleteObjectsCommand(s))}catch(h){throw this.errorProxy(h,{key,command:s})}}),a={deleted:i,notFound:n};return this.emit("deleteObjects",a,t),a}async deleteAll({prefix:t}={}){const r=await this.getAllKeys({prefix:t}),i=await this.deleteObjects(r);return this.emit("deleteAll",{prefix:t,report:i}),i}async moveObject({from:t,to:r}){try{return await this.copyObject({from:t,to:r}),await this.deleteObject(t),!0}catch(i){throw this.errorProxy(i,{from:t,to:r,command:options})}}async listObjects({prefix:t,maxKeys:r=1e3,continuationToken:i}={}){const n={Bucket:this.config.bucket,MaxKeys:r,ContinuationToken:i,Prefix:this.config.keyPrefix?ne.join(this.config.keyPrefix,t||""):t||""};try{const a=await this.sendCommand(new de.ListObjectsV2Command(n));return this.emit("listObjects",a,n),a}catch(a){throw this.errorProxy(a,{command:n})}}async count({prefix:t}={}){let r=0,i=!0,n;for(;i;){const a={prefix:t,continuationToken:n},o=await this.listObjects(a);r+=o.KeyCount||0,i=o.IsTruncated||!1,n=o.NextContinuationToken}return this.emit("count",r,{prefix:t}),r}async getAllKeys({prefix:t}={}){let r=[],i=!0,n;for(;i;){const a={prefix:t,continuationToken:n},o=await this.listObjects(a);o.Contents&&(r=r.concat(o.Contents.map(s=>s.Key))),i=o.IsTruncated||!1,n=o.NextContinuationToken}return this.config.keyPrefix&&(r=r.map(a=>a.replace(this.config.keyPrefix,"")).map(a=>a.startsWith("/")?a.replace("/",""):a)),this.emit("getAllKeys",r,{prefix:t}),r}async getContinuationTokenAfterOffset(t={}){const{prefix:r,offset:i=1e3}=t;if(i===0)return null;let n=!0,a,o=0;for(;n;){let s=i<1e3?i:i-o>1e3?1e3:i-o;const h={prefix:r,maxKeys:s,continuationToken:a},f=await this.listObjects(h);if(f.Contents&&(o+=f.Contents.length),n=f.IsTruncated||!1,a=f.NextContinuationToken,o>=i)break}return this.emit("getContinuationTokenAfterOffset",a,t),a}async getKeysPage(t={}){const{prefix:r,offset:i=0,amount:n=100}=t;let a=[],o=!0,s;for(i>0&&(s=await this.getContinuationTokenAfterOffset({prefix:r,offset:i}));o;){const h={prefix:r,continuationToken:s},f=await this.listObjects(h);if(f.Contents&&(a=a.concat(f.Contents.map(l=>l.Key))),o=f.IsTruncated||!1,s=f.NextContinuationToken,a.length>n){a=a.splice(0,n);break}}return this.config.keyPrefix&&(a=a.map(h=>h.replace(this.config.keyPrefix,"")).map(h=>h.startsWith("/")?h.replace("/",""):h)),this.emit("getKeysPage",a,t),a}async moveAllObjects({prefixFrom:t,prefixTo:r}){const i=await this.getAllKeys({prefix:t}),{results:n,errors:a}=await ue.PromisePool.for(i).withConcurrency(this.parallelism).process(async o=>{const s=o.replace(t,r);try{return await this.moveObject({from:o,to:s}),s}catch(h){throw this.errorProxy(h,{from:o,to:s})}});if(this.emit("moveAllObjects",{results:n,errors:a},{prefixFrom:t,prefixTo:r}),a.length>0)throw console.log({errors:a}),new Error("Some objects could not be moved");return n}}async function Lt(){return O.isObject(process)?(await Promise.resolve().then(function(){return vh})).webcrypto:window.crypto}async function yi(e){const t=await Lt(),i=new TextEncoder().encode(e),n=await t.subtle.digest("SHA-256",i);return Array.from(new Uint8Array(n)).map(s=>s.toString(16).padStart(2,"0")).join("")}async function sr(e,t){const r=await Lt(),i=r.getRandomValues(new Uint8Array(16)),n=await Ei(t,i),a=r.getRandomValues(new Uint8Array(12)),s=new TextEncoder().encode(e),h=await r.subtle.encrypt({name:"AES-GCM",iv:a},n,s),f=new Uint8Array(i.length+a.length+h.byteLength);return f.set(i),f.set(a,i.length),f.set(new Uint8Array(h),i.length+a.length),ao(f)}async function xi(e,t){const r=await Lt(),i=oo(e),n=i.slice(0,16),a=i.slice(16,28),o=i.slice(28),s=await Ei(t,n),h=await r.subtle.decrypt({name:"AES-GCM",iv:a},s,o);return new TextDecoder().decode(h)}async function Ei(e,t){const r=await Lt(),n=new TextEncoder().encode(e),a=await r.subtle.importKey("raw",n,{name:"PBKDF2"},!1,["deriveKey"]);return await r.subtle.deriveKey({name:"PBKDF2",salt:t,iterations:1e5,hash:"SHA-256"},a,{name:"AES-GCM",length:256},!0,["encrypt","decrypt"])}function ao(e){if(O.isObject(process))return Buffer.from(e).toString("base64");{const t=String.fromCharCode.apply(null,new Uint8Array(e));return window.btoa(t)}}function oo(e){if(O.isObject(process))return new Uint8Array(Buffer.from(e,"base64"));{const t=window.atob(e),r=t.length,i=new Uint8Array(r);for(let n=0;n<r;n++)i[n]=t.charCodeAt(n);return i}}async function fr(e,t,r){if(!this.passphrase)return t.push({actual:e,type:"encryptionKeyMissing"}),e;try{return await sr(String(e),this.passphrase)}catch(i){t.push({actual:e,type:"encryptionProblem",error:i})}return e}class ki extends Za{constructor({options:t,passphrase:r,autoEncrypt:i=!0}={}){super(O.merge({},{useNewCustomCheckerFunction:!0,messages:{encryptionKeyMissing:"Missing configuration for secrets encryption.",encryptionProblem:"Problem encrypting secret. Actual: {actual}. Error: {error}"},defaults:{string:{trim:!0},object:{strict:"remove"}}},t)),this.passphrase=r,this.autoEncrypt=i,this.alias("secret",{type:"string",custom:this.autoEncrypt?fr:void 0,messages:{string:"The '{field}' field must be a string.",stringMin:"This secret '{field}' field length must be at least {expected} long."}}),this.alias("secretAny",{type:"any",custom:this.autoEncrypt?fr:void 0}),this.alias("secretNumber",{type:"number",custom:this.autoEncrypt?fr:void 0})}}const Si=new Proxy(ki,{instance:null,construct(e,t){return this.instance||(this.instance=new e(...t)),this.instance}}),so={trim:e=>e.trim(),encrypt:(e,{passphrase:t})=>sr(e,t),decrypt:(e,{passphrase:t})=>xi(e,t),toString:e=>String(e),fromArray:(e,{separator:t})=>(e||[]).join(t),toArray:(e,{separator:t})=>(e||"").split(t),toNumber:e=>O.isString(e)?e.includes(".")?parseFloat(e):parseInt(e):e,toJSON:e=>JSON.stringify(e),fromJSON:e=>JSON.parse(e)};class ti{constructor(t){const{map:r,name:i,attributes:n,passphrase:a,version:o=1,options:s={}}=t;if(this.name=i,this.version=o,this.attributes=n,this.passphrase=a??"secret",this.options=O.merge({},this.defaultOptions(),s),this.validator=new Si({autoEncrypt:!1}).compile(O.merge({$$async:!0},O.cloneDeep(this.attributes))),this.options.generateAutoHooks&&this.generateAutoHooks(),!O.isEmpty(r))this.map=r,this.reversedMap=O.invert(r);else{const h=At.flatten(this.attributes,{safe:!0});this.reversedMap={...Object.keys(h).filter(f=>!f.startsWith("$$"))},this.map=O.invert(this.reversedMap)}}defaultOptions(){return{autoEncrypt:!0,autoDecrypt:!0,arraySeparator:"|",generateAutoHooks:!0,hooks:{beforeMap:{},afterMap:{},beforeUnmap:{},afterUnmap:{}}}}addHook(t,r,i){this.options.hooks[t][r]||(this.options.hooks[t][r]=[]),this.options.hooks[t][r]=O.uniq([...this.options.hooks[t][r],i])}generateAutoHooks(){const t=At.flatten(O.cloneDeep(this.attributes),{safe:!0});for(const[r,i]of Object.entries(t))i.includes("array")?(this.addHook("beforeMap",r,"fromArray"),this.addHook("afterUnmap",r,"toArray")):(i.includes("secret")&&(this.options.autoEncrypt&&this.addHook("beforeMap",r,"encrypt"),this.options.autoDecrypt&&this.addHook("afterUnmap",r,"decrypt")),i.includes("number")&&(this.addHook("beforeMap",r,"toString"),this.addHook("afterUnmap",r,"toNumber")),i.includes("boolean")&&(this.addHook("beforeMap",r,"toJson"),this.addHook("afterUnmap",r,"fromJson")))}static import(t){let{map:r,name:i,options:n,version:a,attributes:o}=O.isString(t)?JSON.parse(t):t;return new ti({map:r,name:i,options:n,version:a,attributes:o})}export(){const t={version:this.version,name:this.name,options:this.options,attributes:O.cloneDeep(this.attributes),map:this.map};for(const[r,i]of Object.entries(this.attributes))t.attributes[r]=JSON.stringify(i);return t}async applyHooksActions(t,r){for(const[i,n]of Object.entries(this.options.hooks[r]))for(const a of n){const o=O.get(t,i);o&&O.set(t,i,await so[a](o,{passphrase:this.passphrase,separator:this.options.arraySeparator}))}}async validate(t,{mutateOriginal:r=!1}={}){let i=r?t:O.cloneDeep(t);return await this.validator(i)}async mapper(t){const r=At.flatten(O.cloneDeep(t),{safe:!0});await this.applyHooksActions(r,"beforeMap");const i={_v:this.version+""};for(const[n,a]of Object.entries(r))i[this.map[n]]=a;return await this.applyHooksActions(i,"afterMap"),i}async unmapper(t){const r=O.cloneDeep(t);delete r._v,await this.applyHooksActions(r,"beforeUnmap");const i={};for(const[n,a]of Object.entries(r))i[this.reversedMap[n]]=a;return await this.applyHooksActions(i,"afterUnmap"),At.unflatten(i)}}class Ri extends b{constructor({resource:t}){super(),this.resource=t,this.client=t.client,this.stream=new rr.ReadableStream({highWaterMark:this.client.parallelism*3,start:this._start.bind(this),pull:this._pull.bind(this),cancel:this._cancel.bind(this)})}build(){return this.stream.getReader()}async _start(t){this.controller=t,this.continuationToken=null,this.closeNextIteration=!1}async _pull(t){if(this.closeNextIteration){t.close();return}const r=await this.client.listObjects({prefix:`resource=${this.resource.name}`,continuationToken:this.continuationToken}),i=r?.Contents.map(n=>n.Key).map(n=>n.replace(this.client.config.keyPrefix,"")).map(n=>n.startsWith("/")?n.replace("/",""):n).map(n=>n.replace(`resource=${this.resource.name}/id=`,""));this.continuationToken=r.NextContinuationToken,this.enqueue(i),r.IsTruncated||(this.closeNextIteration=!0)}enqueue(t){t.forEach(r=>{this.controller.enqueue(r),this.emit("id",r)})}_cancel(t){console.warn("Stream cancelled",t)}}class Ai extends Ri{enqueue(t){this.controller.enqueue(t),this.emit("page",t)}}class Ti extends b{constructor({resource:t}){super(),this.resource=t,this.client=t.client,this.input=new Ai({resource:this.resource}),this.output=new rr.TransformStream({transform:this._transform.bind(this)},{highWaterMark:this.client.parallelism*2},{highWaterMark:1}),this.stream=this.input.stream.pipeThrough(this.output)}build(){return this.stream.getReader()}async _transform(t,r){await ue.PromisePool.for(t).withConcurrency(this.client.parallelism).process(async i=>{const n=await this.resource.get(i);return r.enqueue(n),n})}}class Li extends b{constructor({resource:t}){super(),this.resource=t,this.client=t.client,this.stream=new rr.WritableStream({start:this._start.bind(this),write:this._write.bind(this),close:this._close.bind(this),abort:this._abort.bind(this)})}build(){return this.stream.getWriter()}async _start(t){this.controller=t}async _write(t,r){const i=this.resource;await ue.PromisePool.for([].concat(t)).withConcurrency(this.client.parallelism).process(async n=>{await i.insert(n)})}async _close(t){}async _abort(t){console.error("Stream aborted:",t)}}function lr(e){return new Promise((t,r)=>{const i=[];e.on("data",n=>i.push(n)),e.on("error",r),e.on("end",()=>t(Buffer.concat(i).toString("utf-8")))})}class Ci extends b{constructor({name:t,client:r,options:i={},attributes:n={},parallelism:a=10,passphrase:o="secret",observers:s=[]}){super(),this.name=t,this.client=r,this.options=i,this.observers=s,this.parallelism=a,this.passphrase=o??"secret",this.schema=new ti({name:t,attributes:n,passphrase:o})}export(){return this.schema.export()}async validate(t){const r={original:O.cloneDeep(t),isValid:!1,errors:[]},i=await this.schema.validate(t,{mutateOriginal:!0});return i===!0?r.isValid=!0:r.errors=i,r.data=t,r}async insert({id:t,...r}){const{errors:i,isValid:n,data:a}=await this.validate(r);if(!n)throw new Tt({bucket:this.client.config.bucket,resourceName:this.name,attributes:r,validation:i});!t&&t!==0&&(t=ni.nanoid());const o=await this.schema.mapper(a);await this.client.putObject({metadata:o,key:Y(`resource=${this.name}`,`id=${t}`)});const s=O.merge({id:t},a);return this.emit("insert",s),s}async get(t){const r=await this.client.headObject(Y(`resource=${this.name}`,`id=${t}`));let i=await this.schema.unmapper(r.Metadata);return i.id=t,i._length=r.ContentLength,i._createdAt=r.LastModified,r.Expiration&&(i._expiresAt=r.Expiration),this.emit("get",i),i}async update(t,r){const i=await this.get(t),n=O.merge(i,r);delete n.id;const{isValid:a,errors:o,data:s}=await this.validate(n);if(!a)throw new Tt({bucket:this.client.bucket,resourceName:this.name,attributes:r,validation:o});return await this.client.putObject({key:Y(`resource=${this.name}`,`id=${t}`),body:"",metadata:await this.schema.mapper(s)}),s.id=t,this.emit("update",r,s),s}async delete(t){const r=Y(`resource=${this.name}`,`id=${t}`),i=await this.client.deleteObject(r);return this.emit("delete",t),i}async count(){const t=await this.client.count({prefix:`resource=${this.name}`});return this.emit("count",t),t}async insertMany(t){const{results:r}=await ue.PromisePool.for(t).withConcurrency(this.parallelism).handleError(async(i,n)=>{this.emit("error",i,n),this.observers.map(a=>a.emit("error",this.name,i,n))}).process(async i=>await this.insert(i));return this.emit("insertMany",t.length),r}async deleteMany(t){const r=O.chunk(t.map(n=>Y(`resource=${this.name}`,`id=${n}`)),1e3),{results:i}=await ue.PromisePool.for(r).withConcurrency(this.parallelism).handleError(async(n,a)=>{this.emit("error",n,a),this.observers.map(o=>o.emit("error",this.name,n,a))}).process(async n=>{const a=await this.client.deleteObjects(n);return n.forEach(o=>{const s=o.split("=").pop();this.emit("deleted",s),this.observers.map(h=>h.emit("deleted",this.name,s))}),a});return this.emit("deleteMany",t.length),i}async deleteAll(){const t=await this.listIds();this.emit("deleteAll",t.length),await this.deleteMany(t)}async listIds(){const r=(await this.client.getAllKeys({prefix:`resource=${this.name}`})).map(i=>i.replace(`resource=${this.name}/id=`,""));return this.emit("listIds",r.length),r}async getMany(t){const{results:r}=await ue.PromisePool.for(t).withConcurrency(this.client.parallelism).process(async i=>{this.emit("id",i);const n=await this.get(i);return this.emit("data",n),n});return this.emit("getMany",t.length),r}async getAll(){let t=await this.listIds();if(t.length===0)return[];const{results:r}=await ue.PromisePool.for(t).withConcurrency(this.client.parallelism).process(async i=>await this.get(i));return this.emit("getAll",r.length),r}async page({offset:t=0,size:r=100}){const n=(await this.client.getKeysPage({offset:t,amount:r,prefix:`resource=${this.name}`})).map(o=>o.replace(`resource=${this.name}/id=`,""));return await this.getMany(n)}readable(){return new Ti({resource:this}).build()}writable(){return new Li({resource:this}).build()}}class Oi extends b{constructor(t){super(),this.version="1",this.resources={},this.options=t,this.verbose=t.verbose||!1,this.parallelism=parseInt(t.parallelism+"")||10,this.plugins=t.plugins||[],this.cache=t.cache,this.passphrase=t.passphrase||"secret",this.client=t.client||new bi({verbose:this.verbose,parallelism:this.parallelism,connectionString:t.connectionString}),this.bucket=this.client.bucket,this.keyPrefix=this.client.keyPrefix}async connect(){await this.startPlugins();let t=null;if(await this.client.exists("s3db.json")){const r=await this.client.getObject("s3db.json");t=JSON.parse(await lr(r?.Body)),t=this.unserializeMetadata(t)}else t=this.blankMetadataStructure(),await this.uploadMetadataFile();for(const r of Object.entries(t.resources)){const[i,n]=r;this.resources[i]=new Ci({name:i,client:this.client,options:n.options,attributes:n.schema,parallelism:this.parallelism,passphrase:this.passphrase,observers:[this]})}this.emit("connected",new Date)}async startPlugins(){const t=this;if(!O.isEmpty(this.plugins)){const r=this.plugins.map(a=>O.isFunction(a)?new a(this):a),i=r.map(async a=>{a.beforeSetup&&await a.beforeSetup(),await a.setup(t),a.afterSetup&&await a.afterSetup()});await Promise.all(i);const n=r.map(async a=>{a.beforeStart&&await a.beforeStart(),await a.start(),a.afterStart&&await a.afterStart()});await Promise.all(n)}}unserializeMetadata(t){const r={...t};if(O.isEmpty(r.resources))return r;for(const[i,n]of Object.entries(r.resources))for(const[a,o]of Object.entries(n.attributes))r.resources[i].attributes[a]=JSON.parse(o);return r}async uploadMetadataFile(){const t={version:this.version,resources:Object.entries(this.resources).reduce((r,i)=>{const[n,a]=i;return r[n]=a.export(),r},{})};await this.client.putObject({key:"s3db.json",contentType:"application/json",body:JSON.stringify(t,null,2)})}blankMetadataStructure(){return{version:"1",resources:{}}}async createResource({name:t,attributes:r,options:i={}}){const n=new Ci({name:t,attributes:r,observers:[this],client:this.client,options:{autoDecrypt:!0,cache:this.cache,...i}});return this.resources[t]=n,await this.uploadMetadataFile(),this.emit("s3db.resourceCreated",t),n}resource(t){return this.resources[t]?this.resources[t]:Promise.reject(`resource ${t} does not exist`)}}class fo extends Oi{}class hr extends b{async _set(t,r){}async _get(t){}async _del(t){}async _clear(t){}async set(t,r){return await this._set(t,r),this.emit("set",r),r}async get(t){const r=await this._get(t);return this.emit("get",r),r}async del(t){const r=await this._del(t);return this.emit("delete",r),r}async clear(){const t=await this._clear();return this.emit("clear",t),t}}class lo extends hr{constructor(){super(),this.cache={}}async _set(t,r){return this.cache[t]=r,r}async _get(t){return this.cache[t]}async _del(t){return delete this.cache[t],!0}async _clear(){return this.cache={},!0}}var Ye=typeof global<"u"?global:typeof self<"u"?self:typeof window<"u"?window:{},ee=[],q=[],ho=typeof Uint8Array<"u"?Uint8Array:Array,cr=!1;function Ii(){cr=!0;for(var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",t=0,r=e.length;t<r;++t)ee[t]=e[t],q[e.charCodeAt(t)]=t;q[45]=62,q[95]=63}function co(e){cr||Ii();var t,r,i,n,a,o,s=e.length;if(s%4>0)throw new Error("Invalid string. Length must be a multiple of 4");a=e[s-2]==="="?2:e[s-1]==="="?1:0,o=new ho(s*3/4-a),i=a>0?s-4:s;var h=0;for(t=0,r=0;t<i;t+=4,r+=3)n=q[e.charCodeAt(t)]<<18|q[e.charCodeAt(t+1)]<<12|q[e.charCodeAt(t+2)]<<6|q[e.charCodeAt(t+3)],o[h++]=n>>16&255,o[h++]=n>>8&255,o[h++]=n&255;return a===2?(n=q[e.charCodeAt(t)]<<2|q[e.charCodeAt(t+1)]>>4,o[h++]=n&255):a===1&&(n=q[e.charCodeAt(t)]<<10|q[e.charCodeAt(t+1)]<<4|q[e.charCodeAt(t+2)]>>2,o[h++]=n>>8&255,o[h++]=n&255),o}function uo(e){return ee[e>>18&63]+ee[e>>12&63]+ee[e>>6&63]+ee[e&63]}function po(e,t,r){for(var i,n=[],a=t;a<r;a+=3)i=(e[a]<<16)+(e[a+1]<<8)+e[a+2],n.push(uo(i));return n.join("")}function Mi(e){cr||Ii();for(var t,r=e.length,i=r%3,n="",a=[],o=16383,s=0,h=r-i;s<h;s+=o)a.push(po(e,s,s+o>h?h:s+o));return i===1?(t=e[r-1],n+=ee[t>>2],n+=ee[t<<4&63],n+="=="):i===2&&(t=(e[r-2]<<8)+e[r-1],n+=ee[t>>10],n+=ee[t>>4&63],n+=ee[t<<2&63],n+="="),a.push(n),a.join("")}function Ct(e,t,r,i,n){var a,o,s=n*8-i-1,h=(1<<s)-1,f=h>>1,l=-7,d=r?n-1:0,p=r?-1:1,u=e[t+d];for(d+=p,a=u&(1<<-l)-1,u>>=-l,l+=s;l>0;a=a*256+e[t+d],d+=p,l-=8);for(o=a&(1<<-l)-1,a>>=-l,l+=i;l>0;o=o*256+e[t+d],d+=p,l-=8);if(a===0)a=1-f;else{if(a===h)return o?NaN:(u?-1:1)*(1/0);o=o+Math.pow(2,i),a=a-f}return(u?-1:1)*o*Math.pow(2,a-i)}function Di(e,t,r,i,n,a){var o,s,h,f=a*8-n-1,l=(1<<f)-1,d=l>>1,p=n===23?Math.pow(2,-24)-Math.pow(2,-77):0,u=i?0:a-1,g=i?1:-1,S=t<0||t===0&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,o=l):(o=Math.floor(Math.log(t)/Math.LN2),t*(h=Math.pow(2,-o))<1&&(o--,h*=2),o+d>=1?t+=p/h:t+=p*Math.pow(2,1-d),t*h>=2&&(o++,h/=2),o+d>=l?(s=0,o=l):o+d>=1?(s=(t*h-1)*Math.pow(2,n),o=o+d):(s=t*Math.pow(2,d-1)*Math.pow(2,n),o=0));n>=8;e[r+u]=s&255,u+=g,s/=256,n-=8);for(o=o<<n|s,f+=n;f>0;e[r+u]=o&255,u+=g,o/=256,f-=8);e[r+u-g]|=S*128}var _o={}.toString,Fi=Array.isArray||function(e){return _o.call(e)=="[object Array]"};/*!
8
8
  * The buffer module from node.js, for the browser.
9
9
  *
10
10
  * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
package/dist/s3db.es.js CHANGED
@@ -1363,7 +1363,7 @@ class Schema {
1363
1363
  this.reversedMap = invert(map);
1364
1364
  } else {
1365
1365
  const flatAttrs = flatten(this.attributes, { safe: true });
1366
- this.reversedMap = { ...Object.keys(flatAttrs).filter((k) => !k.includes("$$type")) };
1366
+ this.reversedMap = { ...Object.keys(flatAttrs).filter((k) => !k.startsWith("$$")) };
1367
1367
  this.map = invert(this.reversedMap);
1368
1368
  }
1369
1369
  }
@@ -4,7 +4,7 @@ import{nanoid as ai}from"nanoid";import{chunk as oi,isObject as tr,merge as it,c
4
4
  Verbose:
5
5
 
6
6
  ${JSON.stringify(n,null,2)}`),super(i),typeof Error.captureStackTrace=="function"?Error.captureStackTrace(this,this.constructor):this.stack=new Error(i).stack,super.name=this.constructor.name,this.name=this.constructor.name,this.bucket=r,this.thrownAt=new Date}toJson(){return{...this}}toString(){return`${this.name} | ${this.message}`}}class wi extends Ke{constructor({bucket:t,...r}){super({...r,bucket:t,message:`Bucket does not exists [bucket:${t}]`})}}class sr extends Ke{constructor({bucket:t,key:r,...i}){super({...i,bucket:t,message:`Key does not exists [bucket:${t}/${r}]`}),this.key=r}}class gi extends sr{}class vi extends Ke{constructor({bucket:t,...r}){super({...r,bucket:t,message:`Missing metadata for bucket [bucket:${t}]`})}}class At extends Ke{constructor({bucket:t,resourceName:r,attributes:i,validation:n}){super({bucket:t,message:`This item is not valid. Resource=${r} [bucket:${t}].
7
- ${JSON.stringify(n,null,2)}`}),this.resourceName=r,this.attributes=i,this.validation=n}}class mi extends Ke{}const bi={NotFound:gi,NoSuchKey:sr,UnknownError:mi,NoSuchBucket:wi,MissingMetadata:vi,InvalidResourceItem:At},yi="us-east-1",xi="https://s3.us-east-1.amazonaws.com";class Ei{constructor(t){let r;try{r=new URL(t)}catch{throw new Error("Invalid connection string: "+t)}this.region=yi,r.protocol==="s3:"?this.defineS3(r):this.defineMinio(r);for(const[i,n]of r.searchParams.entries())this[i]=n}defineS3(t){if(this.bucket=t.hostname,this.accessKeyId=t.username,this.secretAccessKey=t.password,this.endpoint=xi,["/","",null].includes(t.pathname))this.keyPrefix="";else{let[,...r]=t.pathname.split("/");this.keyPrefix=[...r||[]].join("/")}}defineMinio(t){if(this.forcePathStyle=!0,this.endpoint=t.origin,this.accessKeyId=t.username,this.secretAccessKey=t.password,["/","",null].includes(t.pathname))this.bucket="s3db",this.keyPrefix="";else{let[,r,...i]=t.pathname.split("/");this.bucket=r,this.keyPrefix=[...i||[]].join("/")}}}class ki extends b{constructor({verbose:t=!1,id:r=null,AwsS3Client:i,connectionString:n,parallelism:a=10}){super(),this.verbose=t,this.id=r??ai(7),this.parallelism=a,this.config=new Ei(n),this.client=i||this.createClient()}createClient(){let t={region:this.config.region,endpoint:this.config.endpoint};return this.config.forcePathStyle&&(t.forcePathStyle=!0),this.config.accessKeyId&&(t.credentials={accessKeyId:this.config.accessKeyId,secretAccessKey:this.config.secretAccessKey}),new Ga(t)}async sendCommand(t){this.emit("command.request",t.constructor.name,t.input);const r=console.warn;try{console.warn=n=>{n.includes("Stream of unknown length")||r(n)}}catch(n){console.error(n)}const i=await this.client.send(t);this.emit("command.response",t.constructor.name,i,t.input);try{console.warn=r}catch(n){console.error(n)}return i}errorProxy(t,r){this.verbose&&(r.bucket=this.config.bucket,r.config=this.config,r.verbose=this.verbose),t.data=r;const i=bi[t.name];return i?new i(r):t}async putObject({key:t,metadata:r,contentType:i,body:n,contentEncoding:a}){const o={Bucket:this.config.bucket,Key:this.config.keyPrefix?ie.join(this.config.keyPrefix,t):t,Metadata:{...r},Body:n||"",ContentType:i,ContentEncoding:a};try{const s=await this.sendCommand(new Va(o));return this.emit("putObject",s,o),s}catch(s){throw this.errorProxy(s,{key:t,command:o})}}async getObject(t){const r={Bucket:this.config.bucket,Key:ie.join(this.config.keyPrefix,t)};try{const i=await this.sendCommand(new Xa(r));return this.emit("getObject",i,r),i}catch(i){throw this.errorProxy(i,{key:t,command:r})}}async headObject(t){const r={Bucket:this.config.bucket,Key:this.config.keyPrefix?ie.join(this.config.keyPrefix,t):t};try{const i=await this.client.send(new Ja(r));return this.emit("headObject",i,r),i}catch(i){throw this.errorProxy(i,{key:t,command:r})}}async copyObject({from:t,to:r}){const i={Bucket:this.config.bucket,Key:this.config.keyPrefix?ie.join(this.config.keyPrefix,r):r,CopySource:ie.join(this.config.bucket,this.config.keyPrefix?ie.join(this.config.keyPrefix,t):t)};try{const n=await this.client.send(new Qa(i));return this.emit("copyObject",n,i),n}catch(n){throw this.errorProxy(n,{from:t,to:r,command:i})}}async exists(t){try{return await this.headObject(t),!0}catch(r){if(r.name==="NoSuchKey")return!1;if(r.name==="NotFound")return!1;throw r}}async deleteObject(t){const r={Bucket:this.config.bucket,Key:this.config.keyPrefix?ie.join(this.config.keyPrefix,t):t};try{const i=await this.sendCommand(new eo(r));return this.emit("deleteObject",i,r),i}catch(i){throw this.errorProxy(i,{key:t,command:r})}}async deleteObjects(t){const r=oi(t,1e3),{results:i,errors:n}=await ce.for(r).withConcurrency(this.parallelism).process(async o=>{const s={Bucket:this.config.bucket,Delete:{Objects:o.map(h=>({Key:this.config.keyPrefix?ie.join(this.config.keyPrefix,h):h}))}};try{return await this.sendCommand(new to(s))}catch(h){throw this.errorProxy(h,{key,command:s})}}),a={deleted:i,notFound:n};return this.emit("deleteObjects",a,t),a}async deleteAll({prefix:t}={}){const r=await this.getAllKeys({prefix:t}),i=await this.deleteObjects(r);return this.emit("deleteAll",{prefix:t,report:i}),i}async moveObject({from:t,to:r}){try{return await this.copyObject({from:t,to:r}),await this.deleteObject(t),!0}catch(i){throw this.errorProxy(i,{from:t,to:r,command:options})}}async listObjects({prefix:t,maxKeys:r=1e3,continuationToken:i}={}){const n={Bucket:this.config.bucket,MaxKeys:r,ContinuationToken:i,Prefix:this.config.keyPrefix?ie.join(this.config.keyPrefix,t||""):t||""};try{const a=await this.sendCommand(new ro(n));return this.emit("listObjects",a,n),a}catch(a){throw this.errorProxy(a,{command:n})}}async count({prefix:t}={}){let r=0,i=!0,n;for(;i;){const a={prefix:t,continuationToken:n},o=await this.listObjects(a);r+=o.KeyCount||0,i=o.IsTruncated||!1,n=o.NextContinuationToken}return this.emit("count",r,{prefix:t}),r}async getAllKeys({prefix:t}={}){let r=[],i=!0,n;for(;i;){const a={prefix:t,continuationToken:n},o=await this.listObjects(a);o.Contents&&(r=r.concat(o.Contents.map(s=>s.Key))),i=o.IsTruncated||!1,n=o.NextContinuationToken}return this.config.keyPrefix&&(r=r.map(a=>a.replace(this.config.keyPrefix,"")).map(a=>a.startsWith("/")?a.replace("/",""):a)),this.emit("getAllKeys",r,{prefix:t}),r}async getContinuationTokenAfterOffset(t={}){const{prefix:r,offset:i=1e3}=t;if(i===0)return null;let n=!0,a,o=0;for(;n;){let s=i<1e3?i:i-o>1e3?1e3:i-o;const h={prefix:r,maxKeys:s,continuationToken:a},f=await this.listObjects(h);if(f.Contents&&(o+=f.Contents.length),n=f.IsTruncated||!1,a=f.NextContinuationToken,o>=i)break}return this.emit("getContinuationTokenAfterOffset",a,t),a}async getKeysPage(t={}){const{prefix:r,offset:i=0,amount:n=100}=t;let a=[],o=!0,s;for(i>0&&(s=await this.getContinuationTokenAfterOffset({prefix:r,offset:i}));o;){const h={prefix:r,continuationToken:s},f=await this.listObjects(h);if(f.Contents&&(a=a.concat(f.Contents.map(l=>l.Key))),o=f.IsTruncated||!1,s=f.NextContinuationToken,a.length>n){a=a.splice(0,n);break}}return this.config.keyPrefix&&(a=a.map(h=>h.replace(this.config.keyPrefix,"")).map(h=>h.startsWith("/")?h.replace("/",""):h)),this.emit("getKeysPage",a,t),a}async moveAllObjects({prefixFrom:t,prefixTo:r}){const i=await this.getAllKeys({prefix:t}),{results:n,errors:a}=await ce.for(i).withConcurrency(this.parallelism).process(async o=>{const s=o.replace(t,r);try{return await this.moveObject({from:o,to:s}),s}catch(h){throw this.errorProxy(h,{from:o,to:s})}});if(this.emit("moveAllObjects",{results:n,errors:a},{prefixFrom:t,prefixTo:r}),a.length>0)throw console.log({errors:a}),new Error("Some objects could not be moved");return n}}async function Tt(){return tr(process)?(await Promise.resolve().then(function(){return Ph})).webcrypto:window.crypto}async function Si(e){const t=await Tt(),i=new TextEncoder().encode(e),n=await t.subtle.digest("SHA-256",i);return Array.from(new Uint8Array(n)).map(s=>s.toString(16).padStart(2,"0")).join("")}async function fr(e,t){const r=await Tt(),i=r.getRandomValues(new Uint8Array(16)),n=await Ai(t,i),a=r.getRandomValues(new Uint8Array(12)),s=new TextEncoder().encode(e),h=await r.subtle.encrypt({name:"AES-GCM",iv:a},n,s),f=new Uint8Array(i.length+a.length+h.byteLength);return f.set(i),f.set(a,i.length),f.set(new Uint8Array(h),i.length+a.length),Ro(f)}async function Ri(e,t){const r=await Tt(),i=Ao(e),n=i.slice(0,16),a=i.slice(16,28),o=i.slice(28),s=await Ai(t,n),h=await r.subtle.decrypt({name:"AES-GCM",iv:a},s,o);return new TextDecoder().decode(h)}async function Ai(e,t){const r=await Tt(),n=new TextEncoder().encode(e),a=await r.subtle.importKey("raw",n,{name:"PBKDF2"},!1,["deriveKey"]);return await r.subtle.deriveKey({name:"PBKDF2",salt:t,iterations:1e5,hash:"SHA-256"},a,{name:"AES-GCM",length:256},!0,["encrypt","decrypt"])}function Ro(e){if(tr(process))return Buffer.from(e).toString("base64");{const t=String.fromCharCode.apply(null,new Uint8Array(e));return window.btoa(t)}}function Ao(e){if(tr(process))return new Uint8Array(Buffer.from(e,"base64"));{const t=window.atob(e),r=t.length,i=new Uint8Array(r);for(let n=0;n<r;n++)i[n]=t.charCodeAt(n);return i}}async function lr(e,t,r){if(!this.passphrase)return t.push({actual:e,type:"encryptionKeyMissing"}),e;try{return await fr(String(e),this.passphrase)}catch(i){t.push({actual:e,type:"encryptionProblem",error:i})}return e}class Ti extends no{constructor({options:t,passphrase:r,autoEncrypt:i=!0}={}){super(it({},{useNewCustomCheckerFunction:!0,messages:{encryptionKeyMissing:"Missing configuration for secrets encryption.",encryptionProblem:"Problem encrypting secret. Actual: {actual}. Error: {error}"},defaults:{string:{trim:!0},object:{strict:"remove"}}},t)),this.passphrase=r,this.autoEncrypt=i,this.alias("secret",{type:"string",custom:this.autoEncrypt?lr:void 0,messages:{string:"The '{field}' field must be a string.",stringMin:"This secret '{field}' field length must be at least {expected} long."}}),this.alias("secretAny",{type:"any",custom:this.autoEncrypt?lr:void 0}),this.alias("secretNumber",{type:"number",custom:this.autoEncrypt?lr:void 0})}}const Li=new Proxy(Ti,{instance:null,construct(e,t){return this.instance||(this.instance=new e(...t)),this.instance}}),To={trim:e=>e.trim(),encrypt:(e,{passphrase:t})=>fr(e,t),decrypt:(e,{passphrase:t})=>Ri(e,t),toString:e=>String(e),fromArray:(e,{separator:t})=>(e||[]).join(t),toArray:(e,{separator:t})=>(e||"").split(t),toNumber:e=>fi(e)?e.includes(".")?parseFloat(e):parseInt(e):e,toJSON:e=>JSON.stringify(e),fromJSON:e=>JSON.parse(e)};class ri{constructor(t){const{map:r,name:i,attributes:n,passphrase:a,version:o=1,options:s={}}=t;if(this.name=i,this.version=o,this.attributes=n,this.passphrase=a??"secret",this.options=it({},this.defaultOptions(),s),this.validator=new Li({autoEncrypt:!1}).compile(it({$$async:!0},Re(this.attributes))),this.options.generateAutoHooks&&this.generateAutoHooks(),!rr(r))this.map=r,this.reversedMap=si(r);else{const h=ir(this.attributes,{safe:!0});this.reversedMap={...Object.keys(h).filter(f=>!f.includes("$$type"))},this.map=si(this.reversedMap)}}defaultOptions(){return{autoEncrypt:!0,autoDecrypt:!0,arraySeparator:"|",generateAutoHooks:!0,hooks:{beforeMap:{},afterMap:{},beforeUnmap:{},afterUnmap:{}}}}addHook(t,r,i){this.options.hooks[t][r]||(this.options.hooks[t][r]=[]),this.options.hooks[t][r]=Ka([...this.options.hooks[t][r],i])}generateAutoHooks(){const t=ir(Re(this.attributes),{safe:!0});for(const[r,i]of Object.entries(t))i.includes("array")?(this.addHook("beforeMap",r,"fromArray"),this.addHook("afterUnmap",r,"toArray")):(i.includes("secret")&&(this.options.autoEncrypt&&this.addHook("beforeMap",r,"encrypt"),this.options.autoDecrypt&&this.addHook("afterUnmap",r,"decrypt")),i.includes("number")&&(this.addHook("beforeMap",r,"toString"),this.addHook("afterUnmap",r,"toNumber")),i.includes("boolean")&&(this.addHook("beforeMap",r,"toJson"),this.addHook("afterUnmap",r,"fromJson")))}static import(t){let{map:r,name:i,options:n,version:a,attributes:o}=fi(t)?JSON.parse(t):t;return new ri({map:r,name:i,options:n,version:a,attributes:o})}export(){const t={version:this.version,name:this.name,options:this.options,attributes:Re(this.attributes),map:this.map};for(const[r,i]of Object.entries(this.attributes))t.attributes[r]=JSON.stringify(i);return t}async applyHooksActions(t,r){for(const[i,n]of Object.entries(this.options.hooks[r]))for(const a of n){const o=Wa(t,i);o&&Ya(t,i,await To[a](o,{passphrase:this.passphrase,separator:this.options.arraySeparator}))}}async validate(t,{mutateOriginal:r=!1}={}){let i=r?t:Re(t);return await this.validator(i)}async mapper(t){const r=ir(Re(t),{safe:!0});await this.applyHooksActions(r,"beforeMap");const i={_v:this.version+""};for(const[n,a]of Object.entries(r))i[this.map[n]]=a;return await this.applyHooksActions(i,"afterMap"),i}async unmapper(t){const r=Re(t);delete r._v,await this.applyHooksActions(r,"beforeUnmap");const i={};for(const[n,a]of Object.entries(r))i[this.reversedMap[n]]=a;return await this.applyHooksActions(i,"afterUnmap"),io(i)}}class Oi extends b{constructor({resource:t}){super(),this.resource=t,this.client=t.client,this.stream=new ao({highWaterMark:this.client.parallelism*3,start:this._start.bind(this),pull:this._pull.bind(this),cancel:this._cancel.bind(this)})}build(){return this.stream.getReader()}async _start(t){this.controller=t,this.continuationToken=null,this.closeNextIteration=!1}async _pull(t){if(this.closeNextIteration){t.close();return}const r=await this.client.listObjects({prefix:`resource=${this.resource.name}`,continuationToken:this.continuationToken}),i=r?.Contents.map(n=>n.Key).map(n=>n.replace(this.client.config.keyPrefix,"")).map(n=>n.startsWith("/")?n.replace("/",""):n).map(n=>n.replace(`resource=${this.resource.name}/id=`,""));this.continuationToken=r.NextContinuationToken,this.enqueue(i),r.IsTruncated||(this.closeNextIteration=!0)}enqueue(t){t.forEach(r=>{this.controller.enqueue(r),this.emit("id",r)})}_cancel(t){console.warn("Stream cancelled",t)}}class Ci extends Oi{enqueue(t){this.controller.enqueue(t),this.emit("page",t)}}class Ii extends b{constructor({resource:t}){super(),this.resource=t,this.client=t.client,this.input=new Ci({resource:this.resource}),this.output=new oo({transform:this._transform.bind(this)},{highWaterMark:this.client.parallelism*2},{highWaterMark:1}),this.stream=this.input.stream.pipeThrough(this.output)}build(){return this.stream.getReader()}async _transform(t,r){await ce.for(t).withConcurrency(this.client.parallelism).process(async i=>{const n=await this.resource.get(i);return r.enqueue(n),n})}}class Mi extends b{constructor({resource:t}){super(),this.resource=t,this.client=t.client,this.stream=new so({start:this._start.bind(this),write:this._write.bind(this),close:this._close.bind(this),abort:this._abort.bind(this)})}build(){return this.stream.getWriter()}async _start(t){this.controller=t}async _write(t,r){const i=this.resource;await ce.for([].concat(t)).withConcurrency(this.client.parallelism).process(async n=>{await i.insert(n)})}async _close(t){}async _abort(t){console.error("Stream aborted:",t)}}function hr(e){return new Promise((t,r)=>{const i=[];e.on("data",n=>i.push(n)),e.on("error",r),e.on("end",()=>t(Buffer.concat(i).toString("utf-8")))})}class Fi extends b{constructor({name:t,client:r,options:i={},attributes:n={},parallelism:a=10,passphrase:o="secret",observers:s=[]}){super(),this.name=t,this.client=r,this.options=i,this.observers=s,this.parallelism=a,this.passphrase=o??"secret",this.schema=new ri({name:t,attributes:n,passphrase:o})}export(){return this.schema.export()}async validate(t){const r={original:Re(t),isValid:!1,errors:[]},i=await this.schema.validate(t,{mutateOriginal:!0});return i===!0?r.isValid=!0:r.errors=i,r.data=t,r}async insert({id:t,...r}){const{errors:i,isValid:n,data:a}=await this.validate(r);if(!n)throw new At({bucket:this.client.config.bucket,resourceName:this.name,attributes:r,validation:i});!t&&t!==0&&(t=ai());const o=await this.schema.mapper(a);await this.client.putObject({metadata:o,key:W(`resource=${this.name}`,`id=${t}`)});const s=it({id:t},a);return this.emit("insert",s),s}async get(t){const r=await this.client.headObject(W(`resource=${this.name}`,`id=${t}`));let i=await this.schema.unmapper(r.Metadata);return i.id=t,i._length=r.ContentLength,i._createdAt=r.LastModified,r.Expiration&&(i._expiresAt=r.Expiration),this.emit("get",i),i}async update(t,r){const i=await this.get(t),n=it(i,r);delete n.id;const{isValid:a,errors:o,data:s}=await this.validate(n);if(!a)throw new At({bucket:this.client.bucket,resourceName:this.name,attributes:r,validation:o});return await this.client.putObject({key:W(`resource=${this.name}`,`id=${t}`),body:"",metadata:await this.schema.mapper(s)}),s.id=t,this.emit("update",r,s),s}async delete(t){const r=W(`resource=${this.name}`,`id=${t}`),i=await this.client.deleteObject(r);return this.emit("delete",t),i}async count(){const t=await this.client.count({prefix:`resource=${this.name}`});return this.emit("count",t),t}async insertMany(t){const{results:r}=await ce.for(t).withConcurrency(this.parallelism).handleError(async(i,n)=>{this.emit("error",i,n),this.observers.map(a=>a.emit("error",this.name,i,n))}).process(async i=>await this.insert(i));return this.emit("insertMany",t.length),r}async deleteMany(t){const r=oi(t.map(n=>W(`resource=${this.name}`,`id=${n}`)),1e3),{results:i}=await ce.for(r).withConcurrency(this.parallelism).handleError(async(n,a)=>{this.emit("error",n,a),this.observers.map(o=>o.emit("error",this.name,n,a))}).process(async n=>{const a=await this.client.deleteObjects(n);return n.forEach(o=>{const s=o.split("=").pop();this.emit("deleted",s),this.observers.map(h=>h.emit("deleted",this.name,s))}),a});return this.emit("deleteMany",t.length),i}async deleteAll(){const t=await this.listIds();this.emit("deleteAll",t.length),await this.deleteMany(t)}async listIds(){const r=(await this.client.getAllKeys({prefix:`resource=${this.name}`})).map(i=>i.replace(`resource=${this.name}/id=`,""));return this.emit("listIds",r.length),r}async getMany(t){const{results:r}=await ce.for(t).withConcurrency(this.client.parallelism).process(async i=>{this.emit("id",i);const n=await this.get(i);return this.emit("data",n),n});return this.emit("getMany",t.length),r}async getAll(){let t=await this.listIds();if(t.length===0)return[];const{results:r}=await ce.for(t).withConcurrency(this.client.parallelism).process(async i=>await this.get(i));return this.emit("getAll",r.length),r}async page({offset:t=0,size:r=100}){const n=(await this.client.getKeysPage({offset:t,amount:r,prefix:`resource=${this.name}`})).map(o=>o.replace(`resource=${this.name}/id=`,""));return await this.getMany(n)}readable(){return new Ii({resource:this}).build()}writable(){return new Mi({resource:this}).build()}}class Di extends b{constructor(t){super(),this.version="1",this.resources={},this.options=t,this.verbose=t.verbose||!1,this.parallelism=parseInt(t.parallelism+"")||10,this.plugins=t.plugins||[],this.cache=t.cache,this.passphrase=t.passphrase||"secret",this.client=t.client||new ki({verbose:this.verbose,parallelism:this.parallelism,connectionString:t.connectionString}),this.bucket=this.client.bucket,this.keyPrefix=this.client.keyPrefix}async connect(){await this.startPlugins();let t=null;if(await this.client.exists("s3db.json")){const r=await this.client.getObject("s3db.json");t=JSON.parse(await hr(r?.Body)),t=this.unserializeMetadata(t)}else t=this.blankMetadataStructure(),await this.uploadMetadataFile();for(const r of Object.entries(t.resources)){const[i,n]=r;this.resources[i]=new Fi({name:i,client:this.client,options:n.options,attributes:n.schema,parallelism:this.parallelism,passphrase:this.passphrase,observers:[this]})}this.emit("connected",new Date)}async startPlugins(){const t=this;if(!rr(this.plugins)){const r=this.plugins.map(a=>qa(a)?new a(this):a),i=r.map(async a=>{a.beforeSetup&&await a.beforeSetup(),await a.setup(t),a.afterSetup&&await a.afterSetup()});await Promise.all(i);const n=r.map(async a=>{a.beforeStart&&await a.beforeStart(),await a.start(),a.afterStart&&await a.afterStart()});await Promise.all(n)}}unserializeMetadata(t){const r={...t};if(rr(r.resources))return r;for(const[i,n]of Object.entries(r.resources))for(const[a,o]of Object.entries(n.attributes))r.resources[i].attributes[a]=JSON.parse(o);return r}async uploadMetadataFile(){const t={version:this.version,resources:Object.entries(this.resources).reduce((r,i)=>{const[n,a]=i;return r[n]=a.export(),r},{})};await this.client.putObject({key:"s3db.json",contentType:"application/json",body:JSON.stringify(t,null,2)})}blankMetadataStructure(){return{version:"1",resources:{}}}async createResource({name:t,attributes:r,options:i={}}){const n=new Fi({name:t,attributes:r,observers:[this],client:this.client,options:{autoDecrypt:!0,cache:this.cache,...i}});return this.resources[t]=n,await this.uploadMetadataFile(),this.emit("s3db.resourceCreated",t),n}resource(t){return this.resources[t]?this.resources[t]:Promise.reject(`resource ${t} does not exist`)}}class Lo extends Di{}class cr extends b{async _set(t,r){}async _get(t){}async _del(t){}async _clear(t){}async set(t,r){return await this._set(t,r),this.emit("set",r),r}async get(t){const r=await this._get(t);return this.emit("get",r),r}async del(t){const r=await this._del(t);return this.emit("delete",r),r}async clear(){const t=await this._clear();return this.emit("clear",t),t}}class Oo extends cr{constructor(){super(),this.cache={}}async _set(t,r){return this.cache[t]=r,r}async _get(t){return this.cache[t]}async _del(t){return delete this.cache[t],!0}async _clear(){return this.cache={},!0}}var We=typeof global<"u"?global:typeof self<"u"?self:typeof window<"u"?window:{},Q=[],Y=[],Co=typeof Uint8Array<"u"?Uint8Array:Array,ur=!1;function Ni(){ur=!0;for(var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",t=0,r=e.length;t<r;++t)Q[t]=e[t],Y[e.charCodeAt(t)]=t;Y[45]=62,Y[95]=63}function Io(e){ur||Ni();var t,r,i,n,a,o,s=e.length;if(s%4>0)throw new Error("Invalid string. Length must be a multiple of 4");a=e[s-2]==="="?2:e[s-1]==="="?1:0,o=new Co(s*3/4-a),i=a>0?s-4:s;var h=0;for(t=0,r=0;t<i;t+=4,r+=3)n=Y[e.charCodeAt(t)]<<18|Y[e.charCodeAt(t+1)]<<12|Y[e.charCodeAt(t+2)]<<6|Y[e.charCodeAt(t+3)],o[h++]=n>>16&255,o[h++]=n>>8&255,o[h++]=n&255;return a===2?(n=Y[e.charCodeAt(t)]<<2|Y[e.charCodeAt(t+1)]>>4,o[h++]=n&255):a===1&&(n=Y[e.charCodeAt(t)]<<10|Y[e.charCodeAt(t+1)]<<4|Y[e.charCodeAt(t+2)]>>2,o[h++]=n>>8&255,o[h++]=n&255),o}function Mo(e){return Q[e>>18&63]+Q[e>>12&63]+Q[e>>6&63]+Q[e&63]}function Fo(e,t,r){for(var i,n=[],a=t;a<r;a+=3)i=(e[a]<<16)+(e[a+1]<<8)+e[a+2],n.push(Mo(i));return n.join("")}function zi(e){ur||Ni();for(var t,r=e.length,i=r%3,n="",a=[],o=16383,s=0,h=r-i;s<h;s+=o)a.push(Fo(e,s,s+o>h?h:s+o));return i===1?(t=e[r-1],n+=Q[t>>2],n+=Q[t<<4&63],n+="=="):i===2&&(t=(e[r-2]<<8)+e[r-1],n+=Q[t>>10],n+=Q[t>>4&63],n+=Q[t<<2&63],n+="="),a.push(n),a.join("")}function Lt(e,t,r,i,n){var a,o,s=n*8-i-1,h=(1<<s)-1,f=h>>1,l=-7,d=r?n-1:0,p=r?-1:1,u=e[t+d];for(d+=p,a=u&(1<<-l)-1,u>>=-l,l+=s;l>0;a=a*256+e[t+d],d+=p,l-=8);for(o=a&(1<<-l)-1,a>>=-l,l+=i;l>0;o=o*256+e[t+d],d+=p,l-=8);if(a===0)a=1-f;else{if(a===h)return o?NaN:(u?-1:1)*(1/0);o=o+Math.pow(2,i),a=a-f}return(u?-1:1)*o*Math.pow(2,a-i)}function Pi(e,t,r,i,n,a){var o,s,h,f=a*8-n-1,l=(1<<f)-1,d=l>>1,p=n===23?Math.pow(2,-24)-Math.pow(2,-77):0,u=i?0:a-1,g=i?1:-1,S=t<0||t===0&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,o=l):(o=Math.floor(Math.log(t)/Math.LN2),t*(h=Math.pow(2,-o))<1&&(o--,h*=2),o+d>=1?t+=p/h:t+=p*Math.pow(2,1-d),t*h>=2&&(o++,h/=2),o+d>=l?(s=0,o=l):o+d>=1?(s=(t*h-1)*Math.pow(2,n),o=o+d):(s=t*Math.pow(2,d-1)*Math.pow(2,n),o=0));n>=8;e[r+u]=s&255,u+=g,s/=256,n-=8);for(o=o<<n|s,f+=n;f>0;e[r+u]=o&255,u+=g,o/=256,f-=8);e[r+u-g]|=S*128}var Do={}.toString,Ui=Array.isArray||function(e){return Do.call(e)=="[object Array]"};/*!
7
+ ${JSON.stringify(n,null,2)}`}),this.resourceName=r,this.attributes=i,this.validation=n}}class mi extends Ke{}const bi={NotFound:gi,NoSuchKey:sr,UnknownError:mi,NoSuchBucket:wi,MissingMetadata:vi,InvalidResourceItem:At},yi="us-east-1",xi="https://s3.us-east-1.amazonaws.com";class Ei{constructor(t){let r;try{r=new URL(t)}catch{throw new Error("Invalid connection string: "+t)}this.region=yi,r.protocol==="s3:"?this.defineS3(r):this.defineMinio(r);for(const[i,n]of r.searchParams.entries())this[i]=n}defineS3(t){if(this.bucket=t.hostname,this.accessKeyId=t.username,this.secretAccessKey=t.password,this.endpoint=xi,["/","",null].includes(t.pathname))this.keyPrefix="";else{let[,...r]=t.pathname.split("/");this.keyPrefix=[...r||[]].join("/")}}defineMinio(t){if(this.forcePathStyle=!0,this.endpoint=t.origin,this.accessKeyId=t.username,this.secretAccessKey=t.password,["/","",null].includes(t.pathname))this.bucket="s3db",this.keyPrefix="";else{let[,r,...i]=t.pathname.split("/");this.bucket=r,this.keyPrefix=[...i||[]].join("/")}}}class ki extends b{constructor({verbose:t=!1,id:r=null,AwsS3Client:i,connectionString:n,parallelism:a=10}){super(),this.verbose=t,this.id=r??ai(7),this.parallelism=a,this.config=new Ei(n),this.client=i||this.createClient()}createClient(){let t={region:this.config.region,endpoint:this.config.endpoint};return this.config.forcePathStyle&&(t.forcePathStyle=!0),this.config.accessKeyId&&(t.credentials={accessKeyId:this.config.accessKeyId,secretAccessKey:this.config.secretAccessKey}),new Ga(t)}async sendCommand(t){this.emit("command.request",t.constructor.name,t.input);const r=console.warn;try{console.warn=n=>{n.includes("Stream of unknown length")||r(n)}}catch(n){console.error(n)}const i=await this.client.send(t);this.emit("command.response",t.constructor.name,i,t.input);try{console.warn=r}catch(n){console.error(n)}return i}errorProxy(t,r){this.verbose&&(r.bucket=this.config.bucket,r.config=this.config,r.verbose=this.verbose),t.data=r;const i=bi[t.name];return i?new i(r):t}async putObject({key:t,metadata:r,contentType:i,body:n,contentEncoding:a}){const o={Bucket:this.config.bucket,Key:this.config.keyPrefix?ie.join(this.config.keyPrefix,t):t,Metadata:{...r},Body:n||"",ContentType:i,ContentEncoding:a};try{const s=await this.sendCommand(new Va(o));return this.emit("putObject",s,o),s}catch(s){throw this.errorProxy(s,{key:t,command:o})}}async getObject(t){const r={Bucket:this.config.bucket,Key:ie.join(this.config.keyPrefix,t)};try{const i=await this.sendCommand(new Xa(r));return this.emit("getObject",i,r),i}catch(i){throw this.errorProxy(i,{key:t,command:r})}}async headObject(t){const r={Bucket:this.config.bucket,Key:this.config.keyPrefix?ie.join(this.config.keyPrefix,t):t};try{const i=await this.client.send(new Ja(r));return this.emit("headObject",i,r),i}catch(i){throw this.errorProxy(i,{key:t,command:r})}}async copyObject({from:t,to:r}){const i={Bucket:this.config.bucket,Key:this.config.keyPrefix?ie.join(this.config.keyPrefix,r):r,CopySource:ie.join(this.config.bucket,this.config.keyPrefix?ie.join(this.config.keyPrefix,t):t)};try{const n=await this.client.send(new Qa(i));return this.emit("copyObject",n,i),n}catch(n){throw this.errorProxy(n,{from:t,to:r,command:i})}}async exists(t){try{return await this.headObject(t),!0}catch(r){if(r.name==="NoSuchKey")return!1;if(r.name==="NotFound")return!1;throw r}}async deleteObject(t){const r={Bucket:this.config.bucket,Key:this.config.keyPrefix?ie.join(this.config.keyPrefix,t):t};try{const i=await this.sendCommand(new eo(r));return this.emit("deleteObject",i,r),i}catch(i){throw this.errorProxy(i,{key:t,command:r})}}async deleteObjects(t){const r=oi(t,1e3),{results:i,errors:n}=await ce.for(r).withConcurrency(this.parallelism).process(async o=>{const s={Bucket:this.config.bucket,Delete:{Objects:o.map(h=>({Key:this.config.keyPrefix?ie.join(this.config.keyPrefix,h):h}))}};try{return await this.sendCommand(new to(s))}catch(h){throw this.errorProxy(h,{key,command:s})}}),a={deleted:i,notFound:n};return this.emit("deleteObjects",a,t),a}async deleteAll({prefix:t}={}){const r=await this.getAllKeys({prefix:t}),i=await this.deleteObjects(r);return this.emit("deleteAll",{prefix:t,report:i}),i}async moveObject({from:t,to:r}){try{return await this.copyObject({from:t,to:r}),await this.deleteObject(t),!0}catch(i){throw this.errorProxy(i,{from:t,to:r,command:options})}}async listObjects({prefix:t,maxKeys:r=1e3,continuationToken:i}={}){const n={Bucket:this.config.bucket,MaxKeys:r,ContinuationToken:i,Prefix:this.config.keyPrefix?ie.join(this.config.keyPrefix,t||""):t||""};try{const a=await this.sendCommand(new ro(n));return this.emit("listObjects",a,n),a}catch(a){throw this.errorProxy(a,{command:n})}}async count({prefix:t}={}){let r=0,i=!0,n;for(;i;){const a={prefix:t,continuationToken:n},o=await this.listObjects(a);r+=o.KeyCount||0,i=o.IsTruncated||!1,n=o.NextContinuationToken}return this.emit("count",r,{prefix:t}),r}async getAllKeys({prefix:t}={}){let r=[],i=!0,n;for(;i;){const a={prefix:t,continuationToken:n},o=await this.listObjects(a);o.Contents&&(r=r.concat(o.Contents.map(s=>s.Key))),i=o.IsTruncated||!1,n=o.NextContinuationToken}return this.config.keyPrefix&&(r=r.map(a=>a.replace(this.config.keyPrefix,"")).map(a=>a.startsWith("/")?a.replace("/",""):a)),this.emit("getAllKeys",r,{prefix:t}),r}async getContinuationTokenAfterOffset(t={}){const{prefix:r,offset:i=1e3}=t;if(i===0)return null;let n=!0,a,o=0;for(;n;){let s=i<1e3?i:i-o>1e3?1e3:i-o;const h={prefix:r,maxKeys:s,continuationToken:a},f=await this.listObjects(h);if(f.Contents&&(o+=f.Contents.length),n=f.IsTruncated||!1,a=f.NextContinuationToken,o>=i)break}return this.emit("getContinuationTokenAfterOffset",a,t),a}async getKeysPage(t={}){const{prefix:r,offset:i=0,amount:n=100}=t;let a=[],o=!0,s;for(i>0&&(s=await this.getContinuationTokenAfterOffset({prefix:r,offset:i}));o;){const h={prefix:r,continuationToken:s},f=await this.listObjects(h);if(f.Contents&&(a=a.concat(f.Contents.map(l=>l.Key))),o=f.IsTruncated||!1,s=f.NextContinuationToken,a.length>n){a=a.splice(0,n);break}}return this.config.keyPrefix&&(a=a.map(h=>h.replace(this.config.keyPrefix,"")).map(h=>h.startsWith("/")?h.replace("/",""):h)),this.emit("getKeysPage",a,t),a}async moveAllObjects({prefixFrom:t,prefixTo:r}){const i=await this.getAllKeys({prefix:t}),{results:n,errors:a}=await ce.for(i).withConcurrency(this.parallelism).process(async o=>{const s=o.replace(t,r);try{return await this.moveObject({from:o,to:s}),s}catch(h){throw this.errorProxy(h,{from:o,to:s})}});if(this.emit("moveAllObjects",{results:n,errors:a},{prefixFrom:t,prefixTo:r}),a.length>0)throw console.log({errors:a}),new Error("Some objects could not be moved");return n}}async function Tt(){return tr(process)?(await Promise.resolve().then(function(){return Ph})).webcrypto:window.crypto}async function Si(e){const t=await Tt(),i=new TextEncoder().encode(e),n=await t.subtle.digest("SHA-256",i);return Array.from(new Uint8Array(n)).map(s=>s.toString(16).padStart(2,"0")).join("")}async function fr(e,t){const r=await Tt(),i=r.getRandomValues(new Uint8Array(16)),n=await Ai(t,i),a=r.getRandomValues(new Uint8Array(12)),s=new TextEncoder().encode(e),h=await r.subtle.encrypt({name:"AES-GCM",iv:a},n,s),f=new Uint8Array(i.length+a.length+h.byteLength);return f.set(i),f.set(a,i.length),f.set(new Uint8Array(h),i.length+a.length),Ro(f)}async function Ri(e,t){const r=await Tt(),i=Ao(e),n=i.slice(0,16),a=i.slice(16,28),o=i.slice(28),s=await Ai(t,n),h=await r.subtle.decrypt({name:"AES-GCM",iv:a},s,o);return new TextDecoder().decode(h)}async function Ai(e,t){const r=await Tt(),n=new TextEncoder().encode(e),a=await r.subtle.importKey("raw",n,{name:"PBKDF2"},!1,["deriveKey"]);return await r.subtle.deriveKey({name:"PBKDF2",salt:t,iterations:1e5,hash:"SHA-256"},a,{name:"AES-GCM",length:256},!0,["encrypt","decrypt"])}function Ro(e){if(tr(process))return Buffer.from(e).toString("base64");{const t=String.fromCharCode.apply(null,new Uint8Array(e));return window.btoa(t)}}function Ao(e){if(tr(process))return new Uint8Array(Buffer.from(e,"base64"));{const t=window.atob(e),r=t.length,i=new Uint8Array(r);for(let n=0;n<r;n++)i[n]=t.charCodeAt(n);return i}}async function lr(e,t,r){if(!this.passphrase)return t.push({actual:e,type:"encryptionKeyMissing"}),e;try{return await fr(String(e),this.passphrase)}catch(i){t.push({actual:e,type:"encryptionProblem",error:i})}return e}class Ti extends no{constructor({options:t,passphrase:r,autoEncrypt:i=!0}={}){super(it({},{useNewCustomCheckerFunction:!0,messages:{encryptionKeyMissing:"Missing configuration for secrets encryption.",encryptionProblem:"Problem encrypting secret. Actual: {actual}. Error: {error}"},defaults:{string:{trim:!0},object:{strict:"remove"}}},t)),this.passphrase=r,this.autoEncrypt=i,this.alias("secret",{type:"string",custom:this.autoEncrypt?lr:void 0,messages:{string:"The '{field}' field must be a string.",stringMin:"This secret '{field}' field length must be at least {expected} long."}}),this.alias("secretAny",{type:"any",custom:this.autoEncrypt?lr:void 0}),this.alias("secretNumber",{type:"number",custom:this.autoEncrypt?lr:void 0})}}const Li=new Proxy(Ti,{instance:null,construct(e,t){return this.instance||(this.instance=new e(...t)),this.instance}}),To={trim:e=>e.trim(),encrypt:(e,{passphrase:t})=>fr(e,t),decrypt:(e,{passphrase:t})=>Ri(e,t),toString:e=>String(e),fromArray:(e,{separator:t})=>(e||[]).join(t),toArray:(e,{separator:t})=>(e||"").split(t),toNumber:e=>fi(e)?e.includes(".")?parseFloat(e):parseInt(e):e,toJSON:e=>JSON.stringify(e),fromJSON:e=>JSON.parse(e)};class ri{constructor(t){const{map:r,name:i,attributes:n,passphrase:a,version:o=1,options:s={}}=t;if(this.name=i,this.version=o,this.attributes=n,this.passphrase=a??"secret",this.options=it({},this.defaultOptions(),s),this.validator=new Li({autoEncrypt:!1}).compile(it({$$async:!0},Re(this.attributes))),this.options.generateAutoHooks&&this.generateAutoHooks(),!rr(r))this.map=r,this.reversedMap=si(r);else{const h=ir(this.attributes,{safe:!0});this.reversedMap={...Object.keys(h).filter(f=>!f.startsWith("$$"))},this.map=si(this.reversedMap)}}defaultOptions(){return{autoEncrypt:!0,autoDecrypt:!0,arraySeparator:"|",generateAutoHooks:!0,hooks:{beforeMap:{},afterMap:{},beforeUnmap:{},afterUnmap:{}}}}addHook(t,r,i){this.options.hooks[t][r]||(this.options.hooks[t][r]=[]),this.options.hooks[t][r]=Ka([...this.options.hooks[t][r],i])}generateAutoHooks(){const t=ir(Re(this.attributes),{safe:!0});for(const[r,i]of Object.entries(t))i.includes("array")?(this.addHook("beforeMap",r,"fromArray"),this.addHook("afterUnmap",r,"toArray")):(i.includes("secret")&&(this.options.autoEncrypt&&this.addHook("beforeMap",r,"encrypt"),this.options.autoDecrypt&&this.addHook("afterUnmap",r,"decrypt")),i.includes("number")&&(this.addHook("beforeMap",r,"toString"),this.addHook("afterUnmap",r,"toNumber")),i.includes("boolean")&&(this.addHook("beforeMap",r,"toJson"),this.addHook("afterUnmap",r,"fromJson")))}static import(t){let{map:r,name:i,options:n,version:a,attributes:o}=fi(t)?JSON.parse(t):t;return new ri({map:r,name:i,options:n,version:a,attributes:o})}export(){const t={version:this.version,name:this.name,options:this.options,attributes:Re(this.attributes),map:this.map};for(const[r,i]of Object.entries(this.attributes))t.attributes[r]=JSON.stringify(i);return t}async applyHooksActions(t,r){for(const[i,n]of Object.entries(this.options.hooks[r]))for(const a of n){const o=Wa(t,i);o&&Ya(t,i,await To[a](o,{passphrase:this.passphrase,separator:this.options.arraySeparator}))}}async validate(t,{mutateOriginal:r=!1}={}){let i=r?t:Re(t);return await this.validator(i)}async mapper(t){const r=ir(Re(t),{safe:!0});await this.applyHooksActions(r,"beforeMap");const i={_v:this.version+""};for(const[n,a]of Object.entries(r))i[this.map[n]]=a;return await this.applyHooksActions(i,"afterMap"),i}async unmapper(t){const r=Re(t);delete r._v,await this.applyHooksActions(r,"beforeUnmap");const i={};for(const[n,a]of Object.entries(r))i[this.reversedMap[n]]=a;return await this.applyHooksActions(i,"afterUnmap"),io(i)}}class Oi extends b{constructor({resource:t}){super(),this.resource=t,this.client=t.client,this.stream=new ao({highWaterMark:this.client.parallelism*3,start:this._start.bind(this),pull:this._pull.bind(this),cancel:this._cancel.bind(this)})}build(){return this.stream.getReader()}async _start(t){this.controller=t,this.continuationToken=null,this.closeNextIteration=!1}async _pull(t){if(this.closeNextIteration){t.close();return}const r=await this.client.listObjects({prefix:`resource=${this.resource.name}`,continuationToken:this.continuationToken}),i=r?.Contents.map(n=>n.Key).map(n=>n.replace(this.client.config.keyPrefix,"")).map(n=>n.startsWith("/")?n.replace("/",""):n).map(n=>n.replace(`resource=${this.resource.name}/id=`,""));this.continuationToken=r.NextContinuationToken,this.enqueue(i),r.IsTruncated||(this.closeNextIteration=!0)}enqueue(t){t.forEach(r=>{this.controller.enqueue(r),this.emit("id",r)})}_cancel(t){console.warn("Stream cancelled",t)}}class Ci extends Oi{enqueue(t){this.controller.enqueue(t),this.emit("page",t)}}class Ii extends b{constructor({resource:t}){super(),this.resource=t,this.client=t.client,this.input=new Ci({resource:this.resource}),this.output=new oo({transform:this._transform.bind(this)},{highWaterMark:this.client.parallelism*2},{highWaterMark:1}),this.stream=this.input.stream.pipeThrough(this.output)}build(){return this.stream.getReader()}async _transform(t,r){await ce.for(t).withConcurrency(this.client.parallelism).process(async i=>{const n=await this.resource.get(i);return r.enqueue(n),n})}}class Mi extends b{constructor({resource:t}){super(),this.resource=t,this.client=t.client,this.stream=new so({start:this._start.bind(this),write:this._write.bind(this),close:this._close.bind(this),abort:this._abort.bind(this)})}build(){return this.stream.getWriter()}async _start(t){this.controller=t}async _write(t,r){const i=this.resource;await ce.for([].concat(t)).withConcurrency(this.client.parallelism).process(async n=>{await i.insert(n)})}async _close(t){}async _abort(t){console.error("Stream aborted:",t)}}function hr(e){return new Promise((t,r)=>{const i=[];e.on("data",n=>i.push(n)),e.on("error",r),e.on("end",()=>t(Buffer.concat(i).toString("utf-8")))})}class Fi extends b{constructor({name:t,client:r,options:i={},attributes:n={},parallelism:a=10,passphrase:o="secret",observers:s=[]}){super(),this.name=t,this.client=r,this.options=i,this.observers=s,this.parallelism=a,this.passphrase=o??"secret",this.schema=new ri({name:t,attributes:n,passphrase:o})}export(){return this.schema.export()}async validate(t){const r={original:Re(t),isValid:!1,errors:[]},i=await this.schema.validate(t,{mutateOriginal:!0});return i===!0?r.isValid=!0:r.errors=i,r.data=t,r}async insert({id:t,...r}){const{errors:i,isValid:n,data:a}=await this.validate(r);if(!n)throw new At({bucket:this.client.config.bucket,resourceName:this.name,attributes:r,validation:i});!t&&t!==0&&(t=ai());const o=await this.schema.mapper(a);await this.client.putObject({metadata:o,key:W(`resource=${this.name}`,`id=${t}`)});const s=it({id:t},a);return this.emit("insert",s),s}async get(t){const r=await this.client.headObject(W(`resource=${this.name}`,`id=${t}`));let i=await this.schema.unmapper(r.Metadata);return i.id=t,i._length=r.ContentLength,i._createdAt=r.LastModified,r.Expiration&&(i._expiresAt=r.Expiration),this.emit("get",i),i}async update(t,r){const i=await this.get(t),n=it(i,r);delete n.id;const{isValid:a,errors:o,data:s}=await this.validate(n);if(!a)throw new At({bucket:this.client.bucket,resourceName:this.name,attributes:r,validation:o});return await this.client.putObject({key:W(`resource=${this.name}`,`id=${t}`),body:"",metadata:await this.schema.mapper(s)}),s.id=t,this.emit("update",r,s),s}async delete(t){const r=W(`resource=${this.name}`,`id=${t}`),i=await this.client.deleteObject(r);return this.emit("delete",t),i}async count(){const t=await this.client.count({prefix:`resource=${this.name}`});return this.emit("count",t),t}async insertMany(t){const{results:r}=await ce.for(t).withConcurrency(this.parallelism).handleError(async(i,n)=>{this.emit("error",i,n),this.observers.map(a=>a.emit("error",this.name,i,n))}).process(async i=>await this.insert(i));return this.emit("insertMany",t.length),r}async deleteMany(t){const r=oi(t.map(n=>W(`resource=${this.name}`,`id=${n}`)),1e3),{results:i}=await ce.for(r).withConcurrency(this.parallelism).handleError(async(n,a)=>{this.emit("error",n,a),this.observers.map(o=>o.emit("error",this.name,n,a))}).process(async n=>{const a=await this.client.deleteObjects(n);return n.forEach(o=>{const s=o.split("=").pop();this.emit("deleted",s),this.observers.map(h=>h.emit("deleted",this.name,s))}),a});return this.emit("deleteMany",t.length),i}async deleteAll(){const t=await this.listIds();this.emit("deleteAll",t.length),await this.deleteMany(t)}async listIds(){const r=(await this.client.getAllKeys({prefix:`resource=${this.name}`})).map(i=>i.replace(`resource=${this.name}/id=`,""));return this.emit("listIds",r.length),r}async getMany(t){const{results:r}=await ce.for(t).withConcurrency(this.client.parallelism).process(async i=>{this.emit("id",i);const n=await this.get(i);return this.emit("data",n),n});return this.emit("getMany",t.length),r}async getAll(){let t=await this.listIds();if(t.length===0)return[];const{results:r}=await ce.for(t).withConcurrency(this.client.parallelism).process(async i=>await this.get(i));return this.emit("getAll",r.length),r}async page({offset:t=0,size:r=100}){const n=(await this.client.getKeysPage({offset:t,amount:r,prefix:`resource=${this.name}`})).map(o=>o.replace(`resource=${this.name}/id=`,""));return await this.getMany(n)}readable(){return new Ii({resource:this}).build()}writable(){return new Mi({resource:this}).build()}}class Di extends b{constructor(t){super(),this.version="1",this.resources={},this.options=t,this.verbose=t.verbose||!1,this.parallelism=parseInt(t.parallelism+"")||10,this.plugins=t.plugins||[],this.cache=t.cache,this.passphrase=t.passphrase||"secret",this.client=t.client||new ki({verbose:this.verbose,parallelism:this.parallelism,connectionString:t.connectionString}),this.bucket=this.client.bucket,this.keyPrefix=this.client.keyPrefix}async connect(){await this.startPlugins();let t=null;if(await this.client.exists("s3db.json")){const r=await this.client.getObject("s3db.json");t=JSON.parse(await hr(r?.Body)),t=this.unserializeMetadata(t)}else t=this.blankMetadataStructure(),await this.uploadMetadataFile();for(const r of Object.entries(t.resources)){const[i,n]=r;this.resources[i]=new Fi({name:i,client:this.client,options:n.options,attributes:n.schema,parallelism:this.parallelism,passphrase:this.passphrase,observers:[this]})}this.emit("connected",new Date)}async startPlugins(){const t=this;if(!rr(this.plugins)){const r=this.plugins.map(a=>qa(a)?new a(this):a),i=r.map(async a=>{a.beforeSetup&&await a.beforeSetup(),await a.setup(t),a.afterSetup&&await a.afterSetup()});await Promise.all(i);const n=r.map(async a=>{a.beforeStart&&await a.beforeStart(),await a.start(),a.afterStart&&await a.afterStart()});await Promise.all(n)}}unserializeMetadata(t){const r={...t};if(rr(r.resources))return r;for(const[i,n]of Object.entries(r.resources))for(const[a,o]of Object.entries(n.attributes))r.resources[i].attributes[a]=JSON.parse(o);return r}async uploadMetadataFile(){const t={version:this.version,resources:Object.entries(this.resources).reduce((r,i)=>{const[n,a]=i;return r[n]=a.export(),r},{})};await this.client.putObject({key:"s3db.json",contentType:"application/json",body:JSON.stringify(t,null,2)})}blankMetadataStructure(){return{version:"1",resources:{}}}async createResource({name:t,attributes:r,options:i={}}){const n=new Fi({name:t,attributes:r,observers:[this],client:this.client,options:{autoDecrypt:!0,cache:this.cache,...i}});return this.resources[t]=n,await this.uploadMetadataFile(),this.emit("s3db.resourceCreated",t),n}resource(t){return this.resources[t]?this.resources[t]:Promise.reject(`resource ${t} does not exist`)}}class Lo extends Di{}class cr extends b{async _set(t,r){}async _get(t){}async _del(t){}async _clear(t){}async set(t,r){return await this._set(t,r),this.emit("set",r),r}async get(t){const r=await this._get(t);return this.emit("get",r),r}async del(t){const r=await this._del(t);return this.emit("delete",r),r}async clear(){const t=await this._clear();return this.emit("clear",t),t}}class Oo extends cr{constructor(){super(),this.cache={}}async _set(t,r){return this.cache[t]=r,r}async _get(t){return this.cache[t]}async _del(t){return delete this.cache[t],!0}async _clear(){return this.cache={},!0}}var We=typeof global<"u"?global:typeof self<"u"?self:typeof window<"u"?window:{},Q=[],Y=[],Co=typeof Uint8Array<"u"?Uint8Array:Array,ur=!1;function Ni(){ur=!0;for(var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",t=0,r=e.length;t<r;++t)Q[t]=e[t],Y[e.charCodeAt(t)]=t;Y[45]=62,Y[95]=63}function Io(e){ur||Ni();var t,r,i,n,a,o,s=e.length;if(s%4>0)throw new Error("Invalid string. Length must be a multiple of 4");a=e[s-2]==="="?2:e[s-1]==="="?1:0,o=new Co(s*3/4-a),i=a>0?s-4:s;var h=0;for(t=0,r=0;t<i;t+=4,r+=3)n=Y[e.charCodeAt(t)]<<18|Y[e.charCodeAt(t+1)]<<12|Y[e.charCodeAt(t+2)]<<6|Y[e.charCodeAt(t+3)],o[h++]=n>>16&255,o[h++]=n>>8&255,o[h++]=n&255;return a===2?(n=Y[e.charCodeAt(t)]<<2|Y[e.charCodeAt(t+1)]>>4,o[h++]=n&255):a===1&&(n=Y[e.charCodeAt(t)]<<10|Y[e.charCodeAt(t+1)]<<4|Y[e.charCodeAt(t+2)]>>2,o[h++]=n>>8&255,o[h++]=n&255),o}function Mo(e){return Q[e>>18&63]+Q[e>>12&63]+Q[e>>6&63]+Q[e&63]}function Fo(e,t,r){for(var i,n=[],a=t;a<r;a+=3)i=(e[a]<<16)+(e[a+1]<<8)+e[a+2],n.push(Mo(i));return n.join("")}function zi(e){ur||Ni();for(var t,r=e.length,i=r%3,n="",a=[],o=16383,s=0,h=r-i;s<h;s+=o)a.push(Fo(e,s,s+o>h?h:s+o));return i===1?(t=e[r-1],n+=Q[t>>2],n+=Q[t<<4&63],n+="=="):i===2&&(t=(e[r-2]<<8)+e[r-1],n+=Q[t>>10],n+=Q[t>>4&63],n+=Q[t<<2&63],n+="="),a.push(n),a.join("")}function Lt(e,t,r,i,n){var a,o,s=n*8-i-1,h=(1<<s)-1,f=h>>1,l=-7,d=r?n-1:0,p=r?-1:1,u=e[t+d];for(d+=p,a=u&(1<<-l)-1,u>>=-l,l+=s;l>0;a=a*256+e[t+d],d+=p,l-=8);for(o=a&(1<<-l)-1,a>>=-l,l+=i;l>0;o=o*256+e[t+d],d+=p,l-=8);if(a===0)a=1-f;else{if(a===h)return o?NaN:(u?-1:1)*(1/0);o=o+Math.pow(2,i),a=a-f}return(u?-1:1)*o*Math.pow(2,a-i)}function Pi(e,t,r,i,n,a){var o,s,h,f=a*8-n-1,l=(1<<f)-1,d=l>>1,p=n===23?Math.pow(2,-24)-Math.pow(2,-77):0,u=i?0:a-1,g=i?1:-1,S=t<0||t===0&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,o=l):(o=Math.floor(Math.log(t)/Math.LN2),t*(h=Math.pow(2,-o))<1&&(o--,h*=2),o+d>=1?t+=p/h:t+=p*Math.pow(2,1-d),t*h>=2&&(o++,h/=2),o+d>=l?(s=0,o=l):o+d>=1?(s=(t*h-1)*Math.pow(2,n),o=o+d):(s=t*Math.pow(2,d-1)*Math.pow(2,n),o=0));n>=8;e[r+u]=s&255,u+=g,s/=256,n-=8);for(o=o<<n|s,f+=n;f>0;e[r+u]=o&255,u+=g,o/=256,f-=8);e[r+u-g]|=S*128}var Do={}.toString,Ui=Array.isArray||function(e){return Do.call(e)=="[object Array]"};/*!
8
8
  * The buffer module from node.js, for the browser.
9
9
  *
10
10
  * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
package/dist/s3db.iife.js CHANGED
@@ -1358,7 +1358,7 @@ ${JSON.stringify(validation, null, 2)}`
1358
1358
  this.reversedMap = lodashEs.invert(map);
1359
1359
  } else {
1360
1360
  const flatAttrs = flat.flatten(this.attributes, { safe: true });
1361
- this.reversedMap = { ...Object.keys(flatAttrs).filter((k) => !k.includes("$$type")) };
1361
+ this.reversedMap = { ...Object.keys(flatAttrs).filter((k) => !k.startsWith("$$")) };
1362
1362
  this.map = lodashEs.invert(this.reversedMap);
1363
1363
  }
1364
1364
  }
@@ -4,7 +4,7 @@
4
4
  Verbose:
5
5
 
6
6
  ${JSON.stringify(n,null,2)}`),super(i),typeof Error.captureStackTrace=="function"?Error.captureStackTrace(this,this.constructor):this.stack=new Error(i).stack,super.name=this.constructor.name,this.name=this.constructor.name,this.bucket=r,this.thrownAt=new Date}toJson(){return{...this}}toString(){return`${this.name} | ${this.message}`}}class ci extends Ye{constructor({bucket:t,...r}){super({...r,bucket:t,message:`Bucket does not exists [bucket:${t}]`})}}class sr extends Ye{constructor({bucket:t,key:r,...i}){super({...i,bucket:t,message:`Key does not exists [bucket:${t}/${r}]`}),this.key=r}}class ui extends sr{}class di extends Ye{constructor({bucket:t,...r}){super({...r,bucket:t,message:`Missing metadata for bucket [bucket:${t}]`})}}class Rt extends Ye{constructor({bucket:t,resourceName:r,attributes:i,validation:n}){super({bucket:t,message:`This item is not valid. Resource=${r} [bucket:${t}].
7
- ${JSON.stringify(n,null,2)}`}),this.resourceName=r,this.attributes=i,this.validation=n}}class pi extends Ye{}const _i={NotFound:ui,NoSuchKey:sr,UnknownError:pi,NoSuchBucket:ci,MissingMetadata:di,InvalidResourceItem:Rt},wi="us-east-1",gi="https://s3.us-east-1.amazonaws.com";class vi{constructor(t){let r;try{r=new URL(t)}catch{throw new Error("Invalid connection string: "+t)}this.region=wi,r.protocol==="s3:"?this.defineS3(r):this.defineMinio(r);for(const[i,n]of r.searchParams.entries())this[i]=n}defineS3(t){if(this.bucket=t.hostname,this.accessKeyId=t.username,this.secretAccessKey=t.password,this.endpoint=gi,["/","",null].includes(t.pathname))this.keyPrefix="";else{let[,...r]=t.pathname.split("/");this.keyPrefix=[...r||[]].join("/")}}defineMinio(t){if(this.forcePathStyle=!0,this.endpoint=t.origin,this.accessKeyId=t.username,this.secretAccessKey=t.password,["/","",null].includes(t.pathname))this.bucket="s3db",this.keyPrefix="";else{let[,r,...i]=t.pathname.split("/");this.bucket=r,this.keyPrefix=[...i||[]].join("/")}}}class mi extends b{constructor({verbose:t=!1,id:r=null,AwsS3Client:i,connectionString:n,parallelism:a=10}){super(),this.verbose=t,this.id=r??ii.nanoid(7),this.parallelism=a,this.config=new vi(n),this.client=i||this.createClient()}createClient(){let t={region:this.config.region,endpoint:this.config.endpoint};return this.config.forcePathStyle&&(t.forcePathStyle=!0),this.config.accessKeyId&&(t.credentials={accessKeyId:this.config.accessKeyId,secretAccessKey:this.config.secretAccessKey}),new pe.S3Client(t)}async sendCommand(t){this.emit("command.request",t.constructor.name,t.input);const r=console.warn;try{console.warn=n=>{n.includes("Stream of unknown length")||r(n)}}catch(n){console.error(n)}const i=await this.client.send(t);this.emit("command.response",t.constructor.name,i,t.input);try{console.warn=r}catch(n){console.error(n)}return i}errorProxy(t,r){this.verbose&&(r.bucket=this.config.bucket,r.config=this.config,r.verbose=this.verbose),t.data=r;const i=_i[t.name];return i?new i(r):t}async putObject({key:t,metadata:r,contentType:i,body:n,contentEncoding:a}){const o={Bucket:this.config.bucket,Key:this.config.keyPrefix?ae.join(this.config.keyPrefix,t):t,Metadata:{...r},Body:n||"",ContentType:i,ContentEncoding:a};try{const s=await this.sendCommand(new pe.PutObjectCommand(o));return this.emit("putObject",s,o),s}catch(s){throw this.errorProxy(s,{key:t,command:o})}}async getObject(t){const r={Bucket:this.config.bucket,Key:ae.join(this.config.keyPrefix,t)};try{const i=await this.sendCommand(new pe.GetObjectCommand(r));return this.emit("getObject",i,r),i}catch(i){throw this.errorProxy(i,{key:t,command:r})}}async headObject(t){const r={Bucket:this.config.bucket,Key:this.config.keyPrefix?ae.join(this.config.keyPrefix,t):t};try{const i=await this.client.send(new pe.HeadObjectCommand(r));return this.emit("headObject",i,r),i}catch(i){throw this.errorProxy(i,{key:t,command:r})}}async copyObject({from:t,to:r}){const i={Bucket:this.config.bucket,Key:this.config.keyPrefix?ae.join(this.config.keyPrefix,r):r,CopySource:ae.join(this.config.bucket,this.config.keyPrefix?ae.join(this.config.keyPrefix,t):t)};try{const n=await this.client.send(new pe.CopyObjectCommand(i));return this.emit("copyObject",n,i),n}catch(n){throw this.errorProxy(n,{from:t,to:r,command:i})}}async exists(t){try{return await this.headObject(t),!0}catch(r){if(r.name==="NoSuchKey")return!1;if(r.name==="NotFound")return!1;throw r}}async deleteObject(t){const r={Bucket:this.config.bucket,Key:this.config.keyPrefix?ae.join(this.config.keyPrefix,t):t};try{const i=await this.sendCommand(new pe.DeleteObjectCommand(r));return this.emit("deleteObject",i,r),i}catch(i){throw this.errorProxy(i,{key:t,command:r})}}async deleteObjects(t){const r=I.chunk(t,1e3),{results:i,errors:n}=await de.PromisePool.for(r).withConcurrency(this.parallelism).process(async o=>{const s={Bucket:this.config.bucket,Delete:{Objects:o.map(h=>({Key:this.config.keyPrefix?ae.join(this.config.keyPrefix,h):h}))}};try{return await this.sendCommand(new pe.DeleteObjectsCommand(s))}catch(h){throw this.errorProxy(h,{key,command:s})}}),a={deleted:i,notFound:n};return this.emit("deleteObjects",a,t),a}async deleteAll({prefix:t}={}){const r=await this.getAllKeys({prefix:t}),i=await this.deleteObjects(r);return this.emit("deleteAll",{prefix:t,report:i}),i}async moveObject({from:t,to:r}){try{return await this.copyObject({from:t,to:r}),await this.deleteObject(t),!0}catch(i){throw this.errorProxy(i,{from:t,to:r,command:options})}}async listObjects({prefix:t,maxKeys:r=1e3,continuationToken:i}={}){const n={Bucket:this.config.bucket,MaxKeys:r,ContinuationToken:i,Prefix:this.config.keyPrefix?ae.join(this.config.keyPrefix,t||""):t||""};try{const a=await this.sendCommand(new pe.ListObjectsV2Command(n));return this.emit("listObjects",a,n),a}catch(a){throw this.errorProxy(a,{command:n})}}async count({prefix:t}={}){let r=0,i=!0,n;for(;i;){const a={prefix:t,continuationToken:n},o=await this.listObjects(a);r+=o.KeyCount||0,i=o.IsTruncated||!1,n=o.NextContinuationToken}return this.emit("count",r,{prefix:t}),r}async getAllKeys({prefix:t}={}){let r=[],i=!0,n;for(;i;){const a={prefix:t,continuationToken:n},o=await this.listObjects(a);o.Contents&&(r=r.concat(o.Contents.map(s=>s.Key))),i=o.IsTruncated||!1,n=o.NextContinuationToken}return this.config.keyPrefix&&(r=r.map(a=>a.replace(this.config.keyPrefix,"")).map(a=>a.startsWith("/")?a.replace("/",""):a)),this.emit("getAllKeys",r,{prefix:t}),r}async getContinuationTokenAfterOffset(t={}){const{prefix:r,offset:i=1e3}=t;if(i===0)return null;let n=!0,a,o=0;for(;n;){let s=i<1e3?i:i-o>1e3?1e3:i-o;const h={prefix:r,maxKeys:s,continuationToken:a},f=await this.listObjects(h);if(f.Contents&&(o+=f.Contents.length),n=f.IsTruncated||!1,a=f.NextContinuationToken,o>=i)break}return this.emit("getContinuationTokenAfterOffset",a,t),a}async getKeysPage(t={}){const{prefix:r,offset:i=0,amount:n=100}=t;let a=[],o=!0,s;for(i>0&&(s=await this.getContinuationTokenAfterOffset({prefix:r,offset:i}));o;){const h={prefix:r,continuationToken:s},f=await this.listObjects(h);if(f.Contents&&(a=a.concat(f.Contents.map(l=>l.Key))),o=f.IsTruncated||!1,s=f.NextContinuationToken,a.length>n){a=a.splice(0,n);break}}return this.config.keyPrefix&&(a=a.map(h=>h.replace(this.config.keyPrefix,"")).map(h=>h.startsWith("/")?h.replace("/",""):h)),this.emit("getKeysPage",a,t),a}async moveAllObjects({prefixFrom:t,prefixTo:r}){const i=await this.getAllKeys({prefix:t}),{results:n,errors:a}=await de.PromisePool.for(i).withConcurrency(this.parallelism).process(async o=>{const s=o.replace(t,r);try{return await this.moveObject({from:o,to:s}),s}catch(h){throw this.errorProxy(h,{from:o,to:s})}});if(this.emit("moveAllObjects",{results:n,errors:a},{prefixFrom:t,prefixTo:r}),a.length>0)throw console.log({errors:a}),new Error("Some objects could not be moved");return n}}async function At(){return I.isObject(process)?(await Promise.resolve().then(function(){return mh})).webcrypto:window.crypto}async function bi(e){const t=await At(),i=new TextEncoder().encode(e),n=await t.subtle.digest("SHA-256",i);return Array.from(new Uint8Array(n)).map(s=>s.toString(16).padStart(2,"0")).join("")}async function fr(e,t){const r=await At(),i=r.getRandomValues(new Uint8Array(16)),n=await xi(t,i),a=r.getRandomValues(new Uint8Array(12)),s=new TextEncoder().encode(e),h=await r.subtle.encrypt({name:"AES-GCM",iv:a},n,s),f=new Uint8Array(i.length+a.length+h.byteLength);return f.set(i),f.set(a,i.length),f.set(new Uint8Array(h),i.length+a.length),oo(f)}async function yi(e,t){const r=await At(),i=so(e),n=i.slice(0,16),a=i.slice(16,28),o=i.slice(28),s=await xi(t,n),h=await r.subtle.decrypt({name:"AES-GCM",iv:a},s,o);return new TextDecoder().decode(h)}async function xi(e,t){const r=await At(),n=new TextEncoder().encode(e),a=await r.subtle.importKey("raw",n,{name:"PBKDF2"},!1,["deriveKey"]);return await r.subtle.deriveKey({name:"PBKDF2",salt:t,iterations:1e5,hash:"SHA-256"},a,{name:"AES-GCM",length:256},!0,["encrypt","decrypt"])}function oo(e){if(I.isObject(process))return Buffer.from(e).toString("base64");{const t=String.fromCharCode.apply(null,new Uint8Array(e));return window.btoa(t)}}function so(e){if(I.isObject(process))return new Uint8Array(Buffer.from(e,"base64"));{const t=window.atob(e),r=t.length,i=new Uint8Array(r);for(let n=0;n<r;n++)i[n]=t.charCodeAt(n);return i}}async function lr(e,t,r){if(!this.passphrase)return t.push({actual:e,type:"encryptionKeyMissing"}),e;try{return await fr(String(e),this.passphrase)}catch(i){t.push({actual:e,type:"encryptionProblem",error:i})}return e}class Ei extends ja{constructor({options:t,passphrase:r,autoEncrypt:i=!0}={}){super(I.merge({},{useNewCustomCheckerFunction:!0,messages:{encryptionKeyMissing:"Missing configuration for secrets encryption.",encryptionProblem:"Problem encrypting secret. Actual: {actual}. Error: {error}"},defaults:{string:{trim:!0},object:{strict:"remove"}}},t)),this.passphrase=r,this.autoEncrypt=i,this.alias("secret",{type:"string",custom:this.autoEncrypt?lr:void 0,messages:{string:"The '{field}' field must be a string.",stringMin:"This secret '{field}' field length must be at least {expected} long."}}),this.alias("secretAny",{type:"any",custom:this.autoEncrypt?lr:void 0}),this.alias("secretNumber",{type:"number",custom:this.autoEncrypt?lr:void 0})}}const ki=new Proxy(Ei,{instance:null,construct(e,t){return this.instance||(this.instance=new e(...t)),this.instance}}),fo={trim:e=>e.trim(),encrypt:(e,{passphrase:t})=>fr(e,t),decrypt:(e,{passphrase:t})=>yi(e,t),toString:e=>String(e),fromArray:(e,{separator:t})=>(e||[]).join(t),toArray:(e,{separator:t})=>(e||"").split(t),toNumber:e=>I.isString(e)?e.includes(".")?parseFloat(e):parseInt(e):e,toJSON:e=>JSON.stringify(e),fromJSON:e=>JSON.parse(e)};class hr{constructor(t){const{map:r,name:i,attributes:n,passphrase:a,version:o=1,options:s={}}=t;if(this.name=i,this.version=o,this.attributes=n,this.passphrase=a??"secret",this.options=I.merge({},this.defaultOptions(),s),this.validator=new ki({autoEncrypt:!1}).compile(I.merge({$$async:!0},I.cloneDeep(this.attributes))),this.options.generateAutoHooks&&this.generateAutoHooks(),!I.isEmpty(r))this.map=r,this.reversedMap=I.invert(r);else{const h=St.flatten(this.attributes,{safe:!0});this.reversedMap={...Object.keys(h).filter(f=>!f.includes("$$type"))},this.map=I.invert(this.reversedMap)}}defaultOptions(){return{autoEncrypt:!0,autoDecrypt:!0,arraySeparator:"|",generateAutoHooks:!0,hooks:{beforeMap:{},afterMap:{},beforeUnmap:{},afterUnmap:{}}}}addHook(t,r,i){this.options.hooks[t][r]||(this.options.hooks[t][r]=[]),this.options.hooks[t][r]=I.uniq([...this.options.hooks[t][r],i])}generateAutoHooks(){const t=St.flatten(I.cloneDeep(this.attributes),{safe:!0});for(const[r,i]of Object.entries(t))i.includes("array")?(this.addHook("beforeMap",r,"fromArray"),this.addHook("afterUnmap",r,"toArray")):(i.includes("secret")&&(this.options.autoEncrypt&&this.addHook("beforeMap",r,"encrypt"),this.options.autoDecrypt&&this.addHook("afterUnmap",r,"decrypt")),i.includes("number")&&(this.addHook("beforeMap",r,"toString"),this.addHook("afterUnmap",r,"toNumber")),i.includes("boolean")&&(this.addHook("beforeMap",r,"toJson"),this.addHook("afterUnmap",r,"fromJson")))}static import(t){let{map:r,name:i,options:n,version:a,attributes:o}=I.isString(t)?JSON.parse(t):t;return new hr({map:r,name:i,options:n,version:a,attributes:o})}export(){const t={version:this.version,name:this.name,options:this.options,attributes:I.cloneDeep(this.attributes),map:this.map};for(const[r,i]of Object.entries(this.attributes))t.attributes[r]=JSON.stringify(i);return t}async applyHooksActions(t,r){for(const[i,n]of Object.entries(this.options.hooks[r]))for(const a of n){const o=I.get(t,i);o&&I.set(t,i,await fo[a](o,{passphrase:this.passphrase,separator:this.options.arraySeparator}))}}async validate(t,{mutateOriginal:r=!1}={}){let i=r?t:I.cloneDeep(t);return await this.validator(i)}async mapper(t){const r=St.flatten(I.cloneDeep(t),{safe:!0});await this.applyHooksActions(r,"beforeMap");const i={_v:this.version+""};for(const[n,a]of Object.entries(r))i[this.map[n]]=a;return await this.applyHooksActions(i,"afterMap"),i}async unmapper(t){const r=I.cloneDeep(t);delete r._v,await this.applyHooksActions(r,"beforeUnmap");const i={};for(const[n,a]of Object.entries(r))i[this.reversedMap[n]]=a;return await this.applyHooksActions(i,"afterUnmap"),St.unflatten(i)}}class Si extends b{constructor({resource:t}){super(),this.resource=t,this.client=t.client,this.stream=new ir.ReadableStream({highWaterMark:this.client.parallelism*3,start:this._start.bind(this),pull:this._pull.bind(this),cancel:this._cancel.bind(this)})}build(){return this.stream.getReader()}async _start(t){this.controller=t,this.continuationToken=null,this.closeNextIteration=!1}async _pull(t){if(this.closeNextIteration){t.close();return}const r=await this.client.listObjects({prefix:`resource=${this.resource.name}`,continuationToken:this.continuationToken}),i=r?.Contents.map(n=>n.Key).map(n=>n.replace(this.client.config.keyPrefix,"")).map(n=>n.startsWith("/")?n.replace("/",""):n).map(n=>n.replace(`resource=${this.resource.name}/id=`,""));this.continuationToken=r.NextContinuationToken,this.enqueue(i),r.IsTruncated||(this.closeNextIteration=!0)}enqueue(t){t.forEach(r=>{this.controller.enqueue(r),this.emit("id",r)})}_cancel(t){console.warn("Stream cancelled",t)}}class Ri extends Si{enqueue(t){this.controller.enqueue(t),this.emit("page",t)}}class Ai extends b{constructor({resource:t}){super(),this.resource=t,this.client=t.client,this.input=new Ri({resource:this.resource}),this.output=new ir.TransformStream({transform:this._transform.bind(this)},{highWaterMark:this.client.parallelism*2},{highWaterMark:1}),this.stream=this.input.stream.pipeThrough(this.output)}build(){return this.stream.getReader()}async _transform(t,r){await de.PromisePool.for(t).withConcurrency(this.client.parallelism).process(async i=>{const n=await this.resource.get(i);return r.enqueue(n),n})}}class Ti extends b{constructor({resource:t}){super(),this.resource=t,this.client=t.client,this.stream=new ir.WritableStream({start:this._start.bind(this),write:this._write.bind(this),close:this._close.bind(this),abort:this._abort.bind(this)})}build(){return this.stream.getWriter()}async _start(t){this.controller=t}async _write(t,r){const i=this.resource;await de.PromisePool.for([].concat(t)).withConcurrency(this.client.parallelism).process(async n=>{await i.insert(n)})}async _close(t){}async _abort(t){console.error("Stream aborted:",t)}}function cr(e){return new Promise((t,r)=>{const i=[];e.on("data",n=>i.push(n)),e.on("error",r),e.on("end",()=>t(Buffer.concat(i).toString("utf-8")))})}class Li extends b{constructor({name:t,client:r,options:i={},attributes:n={},parallelism:a=10,passphrase:o="secret",observers:s=[]}){super(),this.name=t,this.client=r,this.options=i,this.observers=s,this.parallelism=a,this.passphrase=o??"secret",this.schema=new hr({name:t,attributes:n,passphrase:o})}export(){return this.schema.export()}async validate(t){const r={original:I.cloneDeep(t),isValid:!1,errors:[]},i=await this.schema.validate(t,{mutateOriginal:!0});return i===!0?r.isValid=!0:r.errors=i,r.data=t,r}async insert({id:t,...r}){const{errors:i,isValid:n,data:a}=await this.validate(r);if(!n)throw new Rt({bucket:this.client.config.bucket,resourceName:this.name,attributes:r,validation:i});!t&&t!==0&&(t=ii.nanoid());const o=await this.schema.mapper(a);await this.client.putObject({metadata:o,key:q(`resource=${this.name}`,`id=${t}`)});const s=I.merge({id:t},a);return this.emit("insert",s),s}async get(t){const r=await this.client.headObject(q(`resource=${this.name}`,`id=${t}`));let i=await this.schema.unmapper(r.Metadata);return i.id=t,i._length=r.ContentLength,i._createdAt=r.LastModified,r.Expiration&&(i._expiresAt=r.Expiration),this.emit("get",i),i}async update(t,r){const i=await this.get(t),n=I.merge(i,r);delete n.id;const{isValid:a,errors:o,data:s}=await this.validate(n);if(!a)throw new Rt({bucket:this.client.bucket,resourceName:this.name,attributes:r,validation:o});return await this.client.putObject({key:q(`resource=${this.name}`,`id=${t}`),body:"",metadata:await this.schema.mapper(s)}),s.id=t,this.emit("update",r,s),s}async delete(t){const r=q(`resource=${this.name}`,`id=${t}`),i=await this.client.deleteObject(r);return this.emit("delete",t),i}async count(){const t=await this.client.count({prefix:`resource=${this.name}`});return this.emit("count",t),t}async insertMany(t){const{results:r}=await de.PromisePool.for(t).withConcurrency(this.parallelism).handleError(async(i,n)=>{this.emit("error",i,n),this.observers.map(a=>a.emit("error",this.name,i,n))}).process(async i=>await this.insert(i));return this.emit("insertMany",t.length),r}async deleteMany(t){const r=I.chunk(t.map(n=>q(`resource=${this.name}`,`id=${n}`)),1e3),{results:i}=await de.PromisePool.for(r).withConcurrency(this.parallelism).handleError(async(n,a)=>{this.emit("error",n,a),this.observers.map(o=>o.emit("error",this.name,n,a))}).process(async n=>{const a=await this.client.deleteObjects(n);return n.forEach(o=>{const s=o.split("=").pop();this.emit("deleted",s),this.observers.map(h=>h.emit("deleted",this.name,s))}),a});return this.emit("deleteMany",t.length),i}async deleteAll(){const t=await this.listIds();this.emit("deleteAll",t.length),await this.deleteMany(t)}async listIds(){const r=(await this.client.getAllKeys({prefix:`resource=${this.name}`})).map(i=>i.replace(`resource=${this.name}/id=`,""));return this.emit("listIds",r.length),r}async getMany(t){const{results:r}=await de.PromisePool.for(t).withConcurrency(this.client.parallelism).process(async i=>{this.emit("id",i);const n=await this.get(i);return this.emit("data",n),n});return this.emit("getMany",t.length),r}async getAll(){let t=await this.listIds();if(t.length===0)return[];const{results:r}=await de.PromisePool.for(t).withConcurrency(this.client.parallelism).process(async i=>await this.get(i));return this.emit("getAll",r.length),r}async page({offset:t=0,size:r=100}){const n=(await this.client.getKeysPage({offset:t,amount:r,prefix:`resource=${this.name}`})).map(o=>o.replace(`resource=${this.name}/id=`,""));return await this.getMany(n)}readable(){return new Ai({resource:this}).build()}writable(){return new Ti({resource:this}).build()}}class Ci extends b{constructor(t){super(),this.version="1",this.resources={},this.options=t,this.verbose=t.verbose||!1,this.parallelism=parseInt(t.parallelism+"")||10,this.plugins=t.plugins||[],this.cache=t.cache,this.passphrase=t.passphrase||"secret",this.client=t.client||new mi({verbose:this.verbose,parallelism:this.parallelism,connectionString:t.connectionString}),this.bucket=this.client.bucket,this.keyPrefix=this.client.keyPrefix}async connect(){await this.startPlugins();let t=null;if(await this.client.exists("s3db.json")){const r=await this.client.getObject("s3db.json");t=JSON.parse(await cr(r?.Body)),t=this.unserializeMetadata(t)}else t=this.blankMetadataStructure(),await this.uploadMetadataFile();for(const r of Object.entries(t.resources)){const[i,n]=r;this.resources[i]=new Li({name:i,client:this.client,options:n.options,attributes:n.schema,parallelism:this.parallelism,passphrase:this.passphrase,observers:[this]})}this.emit("connected",new Date)}async startPlugins(){const t=this;if(!I.isEmpty(this.plugins)){const r=this.plugins.map(a=>I.isFunction(a)?new a(this):a),i=r.map(async a=>{a.beforeSetup&&await a.beforeSetup(),await a.setup(t),a.afterSetup&&await a.afterSetup()});await Promise.all(i);const n=r.map(async a=>{a.beforeStart&&await a.beforeStart(),await a.start(),a.afterStart&&await a.afterStart()});await Promise.all(n)}}unserializeMetadata(t){const r={...t};if(I.isEmpty(r.resources))return r;for(const[i,n]of Object.entries(r.resources))for(const[a,o]of Object.entries(n.attributes))r.resources[i].attributes[a]=JSON.parse(o);return r}async uploadMetadataFile(){const t={version:this.version,resources:Object.entries(this.resources).reduce((r,i)=>{const[n,a]=i;return r[n]=a.export(),r},{})};await this.client.putObject({key:"s3db.json",contentType:"application/json",body:JSON.stringify(t,null,2)})}blankMetadataStructure(){return{version:"1",resources:{}}}async createResource({name:t,attributes:r,options:i={}}){const n=new Li({name:t,attributes:r,observers:[this],client:this.client,options:{autoDecrypt:!0,cache:this.cache,...i}});return this.resources[t]=n,await this.uploadMetadataFile(),this.emit("s3db.resourceCreated",t),n}resource(t){return this.resources[t]?this.resources[t]:Promise.reject(`resource ${t} does not exist`)}}class lo extends Ci{}class ur extends b{async _set(t,r){}async _get(t){}async _del(t){}async _clear(t){}async set(t,r){return await this._set(t,r),this.emit("set",r),r}async get(t){const r=await this._get(t);return this.emit("get",r),r}async del(t){const r=await this._del(t);return this.emit("delete",r),r}async clear(){const t=await this._clear();return this.emit("clear",t),t}}class ho extends ur{constructor(){super(),this.cache={}}async _set(t,r){return this.cache[t]=r,r}async _get(t){return this.cache[t]}async _del(t){return delete this.cache[t],!0}async _clear(){return this.cache={},!0}}var qe=typeof global<"u"?global:typeof self<"u"?self:typeof window<"u"?window:{},te=[],G=[],co=typeof Uint8Array<"u"?Uint8Array:Array,dr=!1;function Oi(){dr=!0;for(var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",t=0,r=e.length;t<r;++t)te[t]=e[t],G[e.charCodeAt(t)]=t;G[45]=62,G[95]=63}function uo(e){dr||Oi();var t,r,i,n,a,o,s=e.length;if(s%4>0)throw new Error("Invalid string. Length must be a multiple of 4");a=e[s-2]==="="?2:e[s-1]==="="?1:0,o=new co(s*3/4-a),i=a>0?s-4:s;var h=0;for(t=0,r=0;t<i;t+=4,r+=3)n=G[e.charCodeAt(t)]<<18|G[e.charCodeAt(t+1)]<<12|G[e.charCodeAt(t+2)]<<6|G[e.charCodeAt(t+3)],o[h++]=n>>16&255,o[h++]=n>>8&255,o[h++]=n&255;return a===2?(n=G[e.charCodeAt(t)]<<2|G[e.charCodeAt(t+1)]>>4,o[h++]=n&255):a===1&&(n=G[e.charCodeAt(t)]<<10|G[e.charCodeAt(t+1)]<<4|G[e.charCodeAt(t+2)]>>2,o[h++]=n>>8&255,o[h++]=n&255),o}function po(e){return te[e>>18&63]+te[e>>12&63]+te[e>>6&63]+te[e&63]}function _o(e,t,r){for(var i,n=[],a=t;a<r;a+=3)i=(e[a]<<16)+(e[a+1]<<8)+e[a+2],n.push(po(i));return n.join("")}function Ii(e){dr||Oi();for(var t,r=e.length,i=r%3,n="",a=[],o=16383,s=0,h=r-i;s<h;s+=o)a.push(_o(e,s,s+o>h?h:s+o));return i===1?(t=e[r-1],n+=te[t>>2],n+=te[t<<4&63],n+="=="):i===2&&(t=(e[r-2]<<8)+e[r-1],n+=te[t>>10],n+=te[t>>4&63],n+=te[t<<2&63],n+="="),a.push(n),a.join("")}function Tt(e,t,r,i,n){var a,o,s=n*8-i-1,h=(1<<s)-1,f=h>>1,l=-7,d=r?n-1:0,p=r?-1:1,u=e[t+d];for(d+=p,a=u&(1<<-l)-1,u>>=-l,l+=s;l>0;a=a*256+e[t+d],d+=p,l-=8);for(o=a&(1<<-l)-1,a>>=-l,l+=i;l>0;o=o*256+e[t+d],d+=p,l-=8);if(a===0)a=1-f;else{if(a===h)return o?NaN:(u?-1:1)*(1/0);o=o+Math.pow(2,i),a=a-f}return(u?-1:1)*o*Math.pow(2,a-i)}function Mi(e,t,r,i,n,a){var o,s,h,f=a*8-n-1,l=(1<<f)-1,d=l>>1,p=n===23?Math.pow(2,-24)-Math.pow(2,-77):0,u=i?0:a-1,g=i?1:-1,S=t<0||t===0&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,o=l):(o=Math.floor(Math.log(t)/Math.LN2),t*(h=Math.pow(2,-o))<1&&(o--,h*=2),o+d>=1?t+=p/h:t+=p*Math.pow(2,1-d),t*h>=2&&(o++,h/=2),o+d>=l?(s=0,o=l):o+d>=1?(s=(t*h-1)*Math.pow(2,n),o=o+d):(s=t*Math.pow(2,d-1)*Math.pow(2,n),o=0));n>=8;e[r+u]=s&255,u+=g,s/=256,n-=8);for(o=o<<n|s,f+=n;f>0;e[r+u]=o&255,u+=g,o/=256,f-=8);e[r+u-g]|=S*128}var wo={}.toString,Di=Array.isArray||function(e){return wo.call(e)=="[object Array]"};/*!
7
+ ${JSON.stringify(n,null,2)}`}),this.resourceName=r,this.attributes=i,this.validation=n}}class pi extends Ye{}const _i={NotFound:ui,NoSuchKey:sr,UnknownError:pi,NoSuchBucket:ci,MissingMetadata:di,InvalidResourceItem:Rt},wi="us-east-1",gi="https://s3.us-east-1.amazonaws.com";class vi{constructor(t){let r;try{r=new URL(t)}catch{throw new Error("Invalid connection string: "+t)}this.region=wi,r.protocol==="s3:"?this.defineS3(r):this.defineMinio(r);for(const[i,n]of r.searchParams.entries())this[i]=n}defineS3(t){if(this.bucket=t.hostname,this.accessKeyId=t.username,this.secretAccessKey=t.password,this.endpoint=gi,["/","",null].includes(t.pathname))this.keyPrefix="";else{let[,...r]=t.pathname.split("/");this.keyPrefix=[...r||[]].join("/")}}defineMinio(t){if(this.forcePathStyle=!0,this.endpoint=t.origin,this.accessKeyId=t.username,this.secretAccessKey=t.password,["/","",null].includes(t.pathname))this.bucket="s3db",this.keyPrefix="";else{let[,r,...i]=t.pathname.split("/");this.bucket=r,this.keyPrefix=[...i||[]].join("/")}}}class mi extends b{constructor({verbose:t=!1,id:r=null,AwsS3Client:i,connectionString:n,parallelism:a=10}){super(),this.verbose=t,this.id=r??ii.nanoid(7),this.parallelism=a,this.config=new vi(n),this.client=i||this.createClient()}createClient(){let t={region:this.config.region,endpoint:this.config.endpoint};return this.config.forcePathStyle&&(t.forcePathStyle=!0),this.config.accessKeyId&&(t.credentials={accessKeyId:this.config.accessKeyId,secretAccessKey:this.config.secretAccessKey}),new pe.S3Client(t)}async sendCommand(t){this.emit("command.request",t.constructor.name,t.input);const r=console.warn;try{console.warn=n=>{n.includes("Stream of unknown length")||r(n)}}catch(n){console.error(n)}const i=await this.client.send(t);this.emit("command.response",t.constructor.name,i,t.input);try{console.warn=r}catch(n){console.error(n)}return i}errorProxy(t,r){this.verbose&&(r.bucket=this.config.bucket,r.config=this.config,r.verbose=this.verbose),t.data=r;const i=_i[t.name];return i?new i(r):t}async putObject({key:t,metadata:r,contentType:i,body:n,contentEncoding:a}){const o={Bucket:this.config.bucket,Key:this.config.keyPrefix?ae.join(this.config.keyPrefix,t):t,Metadata:{...r},Body:n||"",ContentType:i,ContentEncoding:a};try{const s=await this.sendCommand(new pe.PutObjectCommand(o));return this.emit("putObject",s,o),s}catch(s){throw this.errorProxy(s,{key:t,command:o})}}async getObject(t){const r={Bucket:this.config.bucket,Key:ae.join(this.config.keyPrefix,t)};try{const i=await this.sendCommand(new pe.GetObjectCommand(r));return this.emit("getObject",i,r),i}catch(i){throw this.errorProxy(i,{key:t,command:r})}}async headObject(t){const r={Bucket:this.config.bucket,Key:this.config.keyPrefix?ae.join(this.config.keyPrefix,t):t};try{const i=await this.client.send(new pe.HeadObjectCommand(r));return this.emit("headObject",i,r),i}catch(i){throw this.errorProxy(i,{key:t,command:r})}}async copyObject({from:t,to:r}){const i={Bucket:this.config.bucket,Key:this.config.keyPrefix?ae.join(this.config.keyPrefix,r):r,CopySource:ae.join(this.config.bucket,this.config.keyPrefix?ae.join(this.config.keyPrefix,t):t)};try{const n=await this.client.send(new pe.CopyObjectCommand(i));return this.emit("copyObject",n,i),n}catch(n){throw this.errorProxy(n,{from:t,to:r,command:i})}}async exists(t){try{return await this.headObject(t),!0}catch(r){if(r.name==="NoSuchKey")return!1;if(r.name==="NotFound")return!1;throw r}}async deleteObject(t){const r={Bucket:this.config.bucket,Key:this.config.keyPrefix?ae.join(this.config.keyPrefix,t):t};try{const i=await this.sendCommand(new pe.DeleteObjectCommand(r));return this.emit("deleteObject",i,r),i}catch(i){throw this.errorProxy(i,{key:t,command:r})}}async deleteObjects(t){const r=I.chunk(t,1e3),{results:i,errors:n}=await de.PromisePool.for(r).withConcurrency(this.parallelism).process(async o=>{const s={Bucket:this.config.bucket,Delete:{Objects:o.map(h=>({Key:this.config.keyPrefix?ae.join(this.config.keyPrefix,h):h}))}};try{return await this.sendCommand(new pe.DeleteObjectsCommand(s))}catch(h){throw this.errorProxy(h,{key,command:s})}}),a={deleted:i,notFound:n};return this.emit("deleteObjects",a,t),a}async deleteAll({prefix:t}={}){const r=await this.getAllKeys({prefix:t}),i=await this.deleteObjects(r);return this.emit("deleteAll",{prefix:t,report:i}),i}async moveObject({from:t,to:r}){try{return await this.copyObject({from:t,to:r}),await this.deleteObject(t),!0}catch(i){throw this.errorProxy(i,{from:t,to:r,command:options})}}async listObjects({prefix:t,maxKeys:r=1e3,continuationToken:i}={}){const n={Bucket:this.config.bucket,MaxKeys:r,ContinuationToken:i,Prefix:this.config.keyPrefix?ae.join(this.config.keyPrefix,t||""):t||""};try{const a=await this.sendCommand(new pe.ListObjectsV2Command(n));return this.emit("listObjects",a,n),a}catch(a){throw this.errorProxy(a,{command:n})}}async count({prefix:t}={}){let r=0,i=!0,n;for(;i;){const a={prefix:t,continuationToken:n},o=await this.listObjects(a);r+=o.KeyCount||0,i=o.IsTruncated||!1,n=o.NextContinuationToken}return this.emit("count",r,{prefix:t}),r}async getAllKeys({prefix:t}={}){let r=[],i=!0,n;for(;i;){const a={prefix:t,continuationToken:n},o=await this.listObjects(a);o.Contents&&(r=r.concat(o.Contents.map(s=>s.Key))),i=o.IsTruncated||!1,n=o.NextContinuationToken}return this.config.keyPrefix&&(r=r.map(a=>a.replace(this.config.keyPrefix,"")).map(a=>a.startsWith("/")?a.replace("/",""):a)),this.emit("getAllKeys",r,{prefix:t}),r}async getContinuationTokenAfterOffset(t={}){const{prefix:r,offset:i=1e3}=t;if(i===0)return null;let n=!0,a,o=0;for(;n;){let s=i<1e3?i:i-o>1e3?1e3:i-o;const h={prefix:r,maxKeys:s,continuationToken:a},f=await this.listObjects(h);if(f.Contents&&(o+=f.Contents.length),n=f.IsTruncated||!1,a=f.NextContinuationToken,o>=i)break}return this.emit("getContinuationTokenAfterOffset",a,t),a}async getKeysPage(t={}){const{prefix:r,offset:i=0,amount:n=100}=t;let a=[],o=!0,s;for(i>0&&(s=await this.getContinuationTokenAfterOffset({prefix:r,offset:i}));o;){const h={prefix:r,continuationToken:s},f=await this.listObjects(h);if(f.Contents&&(a=a.concat(f.Contents.map(l=>l.Key))),o=f.IsTruncated||!1,s=f.NextContinuationToken,a.length>n){a=a.splice(0,n);break}}return this.config.keyPrefix&&(a=a.map(h=>h.replace(this.config.keyPrefix,"")).map(h=>h.startsWith("/")?h.replace("/",""):h)),this.emit("getKeysPage",a,t),a}async moveAllObjects({prefixFrom:t,prefixTo:r}){const i=await this.getAllKeys({prefix:t}),{results:n,errors:a}=await de.PromisePool.for(i).withConcurrency(this.parallelism).process(async o=>{const s=o.replace(t,r);try{return await this.moveObject({from:o,to:s}),s}catch(h){throw this.errorProxy(h,{from:o,to:s})}});if(this.emit("moveAllObjects",{results:n,errors:a},{prefixFrom:t,prefixTo:r}),a.length>0)throw console.log({errors:a}),new Error("Some objects could not be moved");return n}}async function At(){return I.isObject(process)?(await Promise.resolve().then(function(){return mh})).webcrypto:window.crypto}async function bi(e){const t=await At(),i=new TextEncoder().encode(e),n=await t.subtle.digest("SHA-256",i);return Array.from(new Uint8Array(n)).map(s=>s.toString(16).padStart(2,"0")).join("")}async function fr(e,t){const r=await At(),i=r.getRandomValues(new Uint8Array(16)),n=await xi(t,i),a=r.getRandomValues(new Uint8Array(12)),s=new TextEncoder().encode(e),h=await r.subtle.encrypt({name:"AES-GCM",iv:a},n,s),f=new Uint8Array(i.length+a.length+h.byteLength);return f.set(i),f.set(a,i.length),f.set(new Uint8Array(h),i.length+a.length),oo(f)}async function yi(e,t){const r=await At(),i=so(e),n=i.slice(0,16),a=i.slice(16,28),o=i.slice(28),s=await xi(t,n),h=await r.subtle.decrypt({name:"AES-GCM",iv:a},s,o);return new TextDecoder().decode(h)}async function xi(e,t){const r=await At(),n=new TextEncoder().encode(e),a=await r.subtle.importKey("raw",n,{name:"PBKDF2"},!1,["deriveKey"]);return await r.subtle.deriveKey({name:"PBKDF2",salt:t,iterations:1e5,hash:"SHA-256"},a,{name:"AES-GCM",length:256},!0,["encrypt","decrypt"])}function oo(e){if(I.isObject(process))return Buffer.from(e).toString("base64");{const t=String.fromCharCode.apply(null,new Uint8Array(e));return window.btoa(t)}}function so(e){if(I.isObject(process))return new Uint8Array(Buffer.from(e,"base64"));{const t=window.atob(e),r=t.length,i=new Uint8Array(r);for(let n=0;n<r;n++)i[n]=t.charCodeAt(n);return i}}async function lr(e,t,r){if(!this.passphrase)return t.push({actual:e,type:"encryptionKeyMissing"}),e;try{return await fr(String(e),this.passphrase)}catch(i){t.push({actual:e,type:"encryptionProblem",error:i})}return e}class Ei extends ja{constructor({options:t,passphrase:r,autoEncrypt:i=!0}={}){super(I.merge({},{useNewCustomCheckerFunction:!0,messages:{encryptionKeyMissing:"Missing configuration for secrets encryption.",encryptionProblem:"Problem encrypting secret. Actual: {actual}. Error: {error}"},defaults:{string:{trim:!0},object:{strict:"remove"}}},t)),this.passphrase=r,this.autoEncrypt=i,this.alias("secret",{type:"string",custom:this.autoEncrypt?lr:void 0,messages:{string:"The '{field}' field must be a string.",stringMin:"This secret '{field}' field length must be at least {expected} long."}}),this.alias("secretAny",{type:"any",custom:this.autoEncrypt?lr:void 0}),this.alias("secretNumber",{type:"number",custom:this.autoEncrypt?lr:void 0})}}const ki=new Proxy(Ei,{instance:null,construct(e,t){return this.instance||(this.instance=new e(...t)),this.instance}}),fo={trim:e=>e.trim(),encrypt:(e,{passphrase:t})=>fr(e,t),decrypt:(e,{passphrase:t})=>yi(e,t),toString:e=>String(e),fromArray:(e,{separator:t})=>(e||[]).join(t),toArray:(e,{separator:t})=>(e||"").split(t),toNumber:e=>I.isString(e)?e.includes(".")?parseFloat(e):parseInt(e):e,toJSON:e=>JSON.stringify(e),fromJSON:e=>JSON.parse(e)};class hr{constructor(t){const{map:r,name:i,attributes:n,passphrase:a,version:o=1,options:s={}}=t;if(this.name=i,this.version=o,this.attributes=n,this.passphrase=a??"secret",this.options=I.merge({},this.defaultOptions(),s),this.validator=new ki({autoEncrypt:!1}).compile(I.merge({$$async:!0},I.cloneDeep(this.attributes))),this.options.generateAutoHooks&&this.generateAutoHooks(),!I.isEmpty(r))this.map=r,this.reversedMap=I.invert(r);else{const h=St.flatten(this.attributes,{safe:!0});this.reversedMap={...Object.keys(h).filter(f=>!f.startsWith("$$"))},this.map=I.invert(this.reversedMap)}}defaultOptions(){return{autoEncrypt:!0,autoDecrypt:!0,arraySeparator:"|",generateAutoHooks:!0,hooks:{beforeMap:{},afterMap:{},beforeUnmap:{},afterUnmap:{}}}}addHook(t,r,i){this.options.hooks[t][r]||(this.options.hooks[t][r]=[]),this.options.hooks[t][r]=I.uniq([...this.options.hooks[t][r],i])}generateAutoHooks(){const t=St.flatten(I.cloneDeep(this.attributes),{safe:!0});for(const[r,i]of Object.entries(t))i.includes("array")?(this.addHook("beforeMap",r,"fromArray"),this.addHook("afterUnmap",r,"toArray")):(i.includes("secret")&&(this.options.autoEncrypt&&this.addHook("beforeMap",r,"encrypt"),this.options.autoDecrypt&&this.addHook("afterUnmap",r,"decrypt")),i.includes("number")&&(this.addHook("beforeMap",r,"toString"),this.addHook("afterUnmap",r,"toNumber")),i.includes("boolean")&&(this.addHook("beforeMap",r,"toJson"),this.addHook("afterUnmap",r,"fromJson")))}static import(t){let{map:r,name:i,options:n,version:a,attributes:o}=I.isString(t)?JSON.parse(t):t;return new hr({map:r,name:i,options:n,version:a,attributes:o})}export(){const t={version:this.version,name:this.name,options:this.options,attributes:I.cloneDeep(this.attributes),map:this.map};for(const[r,i]of Object.entries(this.attributes))t.attributes[r]=JSON.stringify(i);return t}async applyHooksActions(t,r){for(const[i,n]of Object.entries(this.options.hooks[r]))for(const a of n){const o=I.get(t,i);o&&I.set(t,i,await fo[a](o,{passphrase:this.passphrase,separator:this.options.arraySeparator}))}}async validate(t,{mutateOriginal:r=!1}={}){let i=r?t:I.cloneDeep(t);return await this.validator(i)}async mapper(t){const r=St.flatten(I.cloneDeep(t),{safe:!0});await this.applyHooksActions(r,"beforeMap");const i={_v:this.version+""};for(const[n,a]of Object.entries(r))i[this.map[n]]=a;return await this.applyHooksActions(i,"afterMap"),i}async unmapper(t){const r=I.cloneDeep(t);delete r._v,await this.applyHooksActions(r,"beforeUnmap");const i={};for(const[n,a]of Object.entries(r))i[this.reversedMap[n]]=a;return await this.applyHooksActions(i,"afterUnmap"),St.unflatten(i)}}class Si extends b{constructor({resource:t}){super(),this.resource=t,this.client=t.client,this.stream=new ir.ReadableStream({highWaterMark:this.client.parallelism*3,start:this._start.bind(this),pull:this._pull.bind(this),cancel:this._cancel.bind(this)})}build(){return this.stream.getReader()}async _start(t){this.controller=t,this.continuationToken=null,this.closeNextIteration=!1}async _pull(t){if(this.closeNextIteration){t.close();return}const r=await this.client.listObjects({prefix:`resource=${this.resource.name}`,continuationToken:this.continuationToken}),i=r?.Contents.map(n=>n.Key).map(n=>n.replace(this.client.config.keyPrefix,"")).map(n=>n.startsWith("/")?n.replace("/",""):n).map(n=>n.replace(`resource=${this.resource.name}/id=`,""));this.continuationToken=r.NextContinuationToken,this.enqueue(i),r.IsTruncated||(this.closeNextIteration=!0)}enqueue(t){t.forEach(r=>{this.controller.enqueue(r),this.emit("id",r)})}_cancel(t){console.warn("Stream cancelled",t)}}class Ri extends Si{enqueue(t){this.controller.enqueue(t),this.emit("page",t)}}class Ai extends b{constructor({resource:t}){super(),this.resource=t,this.client=t.client,this.input=new Ri({resource:this.resource}),this.output=new ir.TransformStream({transform:this._transform.bind(this)},{highWaterMark:this.client.parallelism*2},{highWaterMark:1}),this.stream=this.input.stream.pipeThrough(this.output)}build(){return this.stream.getReader()}async _transform(t,r){await de.PromisePool.for(t).withConcurrency(this.client.parallelism).process(async i=>{const n=await this.resource.get(i);return r.enqueue(n),n})}}class Ti extends b{constructor({resource:t}){super(),this.resource=t,this.client=t.client,this.stream=new ir.WritableStream({start:this._start.bind(this),write:this._write.bind(this),close:this._close.bind(this),abort:this._abort.bind(this)})}build(){return this.stream.getWriter()}async _start(t){this.controller=t}async _write(t,r){const i=this.resource;await de.PromisePool.for([].concat(t)).withConcurrency(this.client.parallelism).process(async n=>{await i.insert(n)})}async _close(t){}async _abort(t){console.error("Stream aborted:",t)}}function cr(e){return new Promise((t,r)=>{const i=[];e.on("data",n=>i.push(n)),e.on("error",r),e.on("end",()=>t(Buffer.concat(i).toString("utf-8")))})}class Li extends b{constructor({name:t,client:r,options:i={},attributes:n={},parallelism:a=10,passphrase:o="secret",observers:s=[]}){super(),this.name=t,this.client=r,this.options=i,this.observers=s,this.parallelism=a,this.passphrase=o??"secret",this.schema=new hr({name:t,attributes:n,passphrase:o})}export(){return this.schema.export()}async validate(t){const r={original:I.cloneDeep(t),isValid:!1,errors:[]},i=await this.schema.validate(t,{mutateOriginal:!0});return i===!0?r.isValid=!0:r.errors=i,r.data=t,r}async insert({id:t,...r}){const{errors:i,isValid:n,data:a}=await this.validate(r);if(!n)throw new Rt({bucket:this.client.config.bucket,resourceName:this.name,attributes:r,validation:i});!t&&t!==0&&(t=ii.nanoid());const o=await this.schema.mapper(a);await this.client.putObject({metadata:o,key:q(`resource=${this.name}`,`id=${t}`)});const s=I.merge({id:t},a);return this.emit("insert",s),s}async get(t){const r=await this.client.headObject(q(`resource=${this.name}`,`id=${t}`));let i=await this.schema.unmapper(r.Metadata);return i.id=t,i._length=r.ContentLength,i._createdAt=r.LastModified,r.Expiration&&(i._expiresAt=r.Expiration),this.emit("get",i),i}async update(t,r){const i=await this.get(t),n=I.merge(i,r);delete n.id;const{isValid:a,errors:o,data:s}=await this.validate(n);if(!a)throw new Rt({bucket:this.client.bucket,resourceName:this.name,attributes:r,validation:o});return await this.client.putObject({key:q(`resource=${this.name}`,`id=${t}`),body:"",metadata:await this.schema.mapper(s)}),s.id=t,this.emit("update",r,s),s}async delete(t){const r=q(`resource=${this.name}`,`id=${t}`),i=await this.client.deleteObject(r);return this.emit("delete",t),i}async count(){const t=await this.client.count({prefix:`resource=${this.name}`});return this.emit("count",t),t}async insertMany(t){const{results:r}=await de.PromisePool.for(t).withConcurrency(this.parallelism).handleError(async(i,n)=>{this.emit("error",i,n),this.observers.map(a=>a.emit("error",this.name,i,n))}).process(async i=>await this.insert(i));return this.emit("insertMany",t.length),r}async deleteMany(t){const r=I.chunk(t.map(n=>q(`resource=${this.name}`,`id=${n}`)),1e3),{results:i}=await de.PromisePool.for(r).withConcurrency(this.parallelism).handleError(async(n,a)=>{this.emit("error",n,a),this.observers.map(o=>o.emit("error",this.name,n,a))}).process(async n=>{const a=await this.client.deleteObjects(n);return n.forEach(o=>{const s=o.split("=").pop();this.emit("deleted",s),this.observers.map(h=>h.emit("deleted",this.name,s))}),a});return this.emit("deleteMany",t.length),i}async deleteAll(){const t=await this.listIds();this.emit("deleteAll",t.length),await this.deleteMany(t)}async listIds(){const r=(await this.client.getAllKeys({prefix:`resource=${this.name}`})).map(i=>i.replace(`resource=${this.name}/id=`,""));return this.emit("listIds",r.length),r}async getMany(t){const{results:r}=await de.PromisePool.for(t).withConcurrency(this.client.parallelism).process(async i=>{this.emit("id",i);const n=await this.get(i);return this.emit("data",n),n});return this.emit("getMany",t.length),r}async getAll(){let t=await this.listIds();if(t.length===0)return[];const{results:r}=await de.PromisePool.for(t).withConcurrency(this.client.parallelism).process(async i=>await this.get(i));return this.emit("getAll",r.length),r}async page({offset:t=0,size:r=100}){const n=(await this.client.getKeysPage({offset:t,amount:r,prefix:`resource=${this.name}`})).map(o=>o.replace(`resource=${this.name}/id=`,""));return await this.getMany(n)}readable(){return new Ai({resource:this}).build()}writable(){return new Ti({resource:this}).build()}}class Ci extends b{constructor(t){super(),this.version="1",this.resources={},this.options=t,this.verbose=t.verbose||!1,this.parallelism=parseInt(t.parallelism+"")||10,this.plugins=t.plugins||[],this.cache=t.cache,this.passphrase=t.passphrase||"secret",this.client=t.client||new mi({verbose:this.verbose,parallelism:this.parallelism,connectionString:t.connectionString}),this.bucket=this.client.bucket,this.keyPrefix=this.client.keyPrefix}async connect(){await this.startPlugins();let t=null;if(await this.client.exists("s3db.json")){const r=await this.client.getObject("s3db.json");t=JSON.parse(await cr(r?.Body)),t=this.unserializeMetadata(t)}else t=this.blankMetadataStructure(),await this.uploadMetadataFile();for(const r of Object.entries(t.resources)){const[i,n]=r;this.resources[i]=new Li({name:i,client:this.client,options:n.options,attributes:n.schema,parallelism:this.parallelism,passphrase:this.passphrase,observers:[this]})}this.emit("connected",new Date)}async startPlugins(){const t=this;if(!I.isEmpty(this.plugins)){const r=this.plugins.map(a=>I.isFunction(a)?new a(this):a),i=r.map(async a=>{a.beforeSetup&&await a.beforeSetup(),await a.setup(t),a.afterSetup&&await a.afterSetup()});await Promise.all(i);const n=r.map(async a=>{a.beforeStart&&await a.beforeStart(),await a.start(),a.afterStart&&await a.afterStart()});await Promise.all(n)}}unserializeMetadata(t){const r={...t};if(I.isEmpty(r.resources))return r;for(const[i,n]of Object.entries(r.resources))for(const[a,o]of Object.entries(n.attributes))r.resources[i].attributes[a]=JSON.parse(o);return r}async uploadMetadataFile(){const t={version:this.version,resources:Object.entries(this.resources).reduce((r,i)=>{const[n,a]=i;return r[n]=a.export(),r},{})};await this.client.putObject({key:"s3db.json",contentType:"application/json",body:JSON.stringify(t,null,2)})}blankMetadataStructure(){return{version:"1",resources:{}}}async createResource({name:t,attributes:r,options:i={}}){const n=new Li({name:t,attributes:r,observers:[this],client:this.client,options:{autoDecrypt:!0,cache:this.cache,...i}});return this.resources[t]=n,await this.uploadMetadataFile(),this.emit("s3db.resourceCreated",t),n}resource(t){return this.resources[t]?this.resources[t]:Promise.reject(`resource ${t} does not exist`)}}class lo extends Ci{}class ur extends b{async _set(t,r){}async _get(t){}async _del(t){}async _clear(t){}async set(t,r){return await this._set(t,r),this.emit("set",r),r}async get(t){const r=await this._get(t);return this.emit("get",r),r}async del(t){const r=await this._del(t);return this.emit("delete",r),r}async clear(){const t=await this._clear();return this.emit("clear",t),t}}class ho extends ur{constructor(){super(),this.cache={}}async _set(t,r){return this.cache[t]=r,r}async _get(t){return this.cache[t]}async _del(t){return delete this.cache[t],!0}async _clear(){return this.cache={},!0}}var qe=typeof global<"u"?global:typeof self<"u"?self:typeof window<"u"?window:{},te=[],G=[],co=typeof Uint8Array<"u"?Uint8Array:Array,dr=!1;function Oi(){dr=!0;for(var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",t=0,r=e.length;t<r;++t)te[t]=e[t],G[e.charCodeAt(t)]=t;G[45]=62,G[95]=63}function uo(e){dr||Oi();var t,r,i,n,a,o,s=e.length;if(s%4>0)throw new Error("Invalid string. Length must be a multiple of 4");a=e[s-2]==="="?2:e[s-1]==="="?1:0,o=new co(s*3/4-a),i=a>0?s-4:s;var h=0;for(t=0,r=0;t<i;t+=4,r+=3)n=G[e.charCodeAt(t)]<<18|G[e.charCodeAt(t+1)]<<12|G[e.charCodeAt(t+2)]<<6|G[e.charCodeAt(t+3)],o[h++]=n>>16&255,o[h++]=n>>8&255,o[h++]=n&255;return a===2?(n=G[e.charCodeAt(t)]<<2|G[e.charCodeAt(t+1)]>>4,o[h++]=n&255):a===1&&(n=G[e.charCodeAt(t)]<<10|G[e.charCodeAt(t+1)]<<4|G[e.charCodeAt(t+2)]>>2,o[h++]=n>>8&255,o[h++]=n&255),o}function po(e){return te[e>>18&63]+te[e>>12&63]+te[e>>6&63]+te[e&63]}function _o(e,t,r){for(var i,n=[],a=t;a<r;a+=3)i=(e[a]<<16)+(e[a+1]<<8)+e[a+2],n.push(po(i));return n.join("")}function Ii(e){dr||Oi();for(var t,r=e.length,i=r%3,n="",a=[],o=16383,s=0,h=r-i;s<h;s+=o)a.push(_o(e,s,s+o>h?h:s+o));return i===1?(t=e[r-1],n+=te[t>>2],n+=te[t<<4&63],n+="=="):i===2&&(t=(e[r-2]<<8)+e[r-1],n+=te[t>>10],n+=te[t>>4&63],n+=te[t<<2&63],n+="="),a.push(n),a.join("")}function Tt(e,t,r,i,n){var a,o,s=n*8-i-1,h=(1<<s)-1,f=h>>1,l=-7,d=r?n-1:0,p=r?-1:1,u=e[t+d];for(d+=p,a=u&(1<<-l)-1,u>>=-l,l+=s;l>0;a=a*256+e[t+d],d+=p,l-=8);for(o=a&(1<<-l)-1,a>>=-l,l+=i;l>0;o=o*256+e[t+d],d+=p,l-=8);if(a===0)a=1-f;else{if(a===h)return o?NaN:(u?-1:1)*(1/0);o=o+Math.pow(2,i),a=a-f}return(u?-1:1)*o*Math.pow(2,a-i)}function Mi(e,t,r,i,n,a){var o,s,h,f=a*8-n-1,l=(1<<f)-1,d=l>>1,p=n===23?Math.pow(2,-24)-Math.pow(2,-77):0,u=i?0:a-1,g=i?1:-1,S=t<0||t===0&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,o=l):(o=Math.floor(Math.log(t)/Math.LN2),t*(h=Math.pow(2,-o))<1&&(o--,h*=2),o+d>=1?t+=p/h:t+=p*Math.pow(2,1-d),t*h>=2&&(o++,h/=2),o+d>=l?(s=0,o=l):o+d>=1?(s=(t*h-1)*Math.pow(2,n),o=o+d):(s=t*Math.pow(2,d-1)*Math.pow(2,n),o=0));n>=8;e[r+u]=s&255,u+=g,s/=256,n-=8);for(o=o<<n|s,f+=n;f>0;e[r+u]=o&255,u+=g,o/=256,f-=8);e[r+u-g]|=S*128}var wo={}.toString,Di=Array.isArray||function(e){return wo.call(e)=="[object Array]"};/*!
8
8
  * The buffer module from node.js, for the browser.
9
9
  *
10
10
  * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "s3db.js",
3
- "version": "3.1.0",
3
+ "version": "3.1.1",
4
4
  "description": "Use AWS S3, the world's most reliable document storage, as a database with this ORM.",
5
5
  "main": "dist/s3db.es.js",
6
6
  "type": "module",