UNPKG

@decaf-ts/core

Version:

Core persistence module for the decaf framework

1 lines 74.9 kB
import{InjectableRegistryImp as t,Injectables as e,inject as r,injectable as s}from"@decaf-ts/injectable-decorators";import{__decorate as i,__metadata as n}from"tslib";import{DefaultRepositoryFlags as a,InternalError as o,Context as c,OperationKeys as l,Repository as h,wrapMethodWithContext as u,wrapMethodWithContextForUpdate as d,enforceDBDecorators as p,ValidationError as g,reduceErrorsToPrint as f,NotFoundError as y,DefaultSeparator as m,BadRequestError as w,ConflictError as b,onCreateUpdate as v,timestamp as x,onCreate as A,onUpdate as E,onDelete as O,afterAny as N,DBKeys as _,BulkCrudOperationKeys as C,readonly as T,SerializationError as B,prefixMethod as P,BaseError as $}from"@decaf-ts/db-decorators";import{LoggedClass as R,Logging as D,final as I,isClass as k,toCamelCase as F}from"@decaf-ts/logging";import{Model as j,hashObj as L,required as M,sf as U,ValidationKeys as q,async as G,type as Y,list as z,model as Q}from"@decaf-ts/decorator-validation";import{Metadata as H,Decoration as V,DefaultFlavour as J,apply as W,methodMetadata as X,DecorationKeys as K,uses as Z,metadata as tt,propMetadata as et,prop as rt}from"@decaf-ts/decoration";import{MultiLock as st,Lock as it}from"@decaf-ts/transactional-decorators";var nt;(t=>{t.INDEX="index",t.UNIQUE="unique",t.ADAPTER="adapter",t.INJECTABLE="decaf_{0}_adapter_for_{1}",t.SERVICE="service",t.TABLE="table",t.COLUMN="column",t.METADATA="__metadata",t.OWNERSHIP="ownership",t.CREATED_BY="ownership.created-by",t.UPDATED_BY="ownership.updated-by",t.RELATIONS="__relations",t.RELATION="relation",t.ONE_TO_ONE="relation.one-to-one",t.ONE_TO_MANY="relation.one-to-many",t.MANY_TO_ONE="relation.many-to-one",t.MANY_TO_MANY="relation.many-to-many",t.POPULATE="populate",t.NO_VALIDATE="no-validate",t.MIGRATION="migration",t.STATEMENT="statement",t.QUERY="query",t.GENERATED="generated"})(nt||(nt={}));const at=Object.assign({},a,{allowGenerationOverride:!1,enforceUpdateValidation:!0,allowRawStatements:!0,forcePrepareSimpleQueries:!1,forcePrepareComplexQueries:!1,cacheForPopulate:{}});class ot{constructor(){this.observers=[]}count(){return this.observers.length}observe(t,e){if(-1!==this.observers.map(t=>t.observer).indexOf(t))throw new o("Observer already registered");this.observers.push({observer:t,filter:e})}unObserve(t){const e=this.observers.map(t=>t.observer).indexOf(t);if(-1===e)throw new o("Failed to find Observer");this.observers.splice(e,1)}async updateObservers(t,e,r,...s){const{log:i,ctxArgs:n}=ft.logCtx(s,this.updateObservers);(await Promise.allSettled(this.observers.filter(s=>{const{filter:a}=s;if(!a)return!0;try{return a(t,e,r,...n)}catch(t){return i.error(`Failed to filter observer ${s.observer.toString()}: ${t}`),!1}}).map(s=>{s.observer.refresh(t,e,r,...n)}))).forEach((t,e)=>{"rejected"===t.status&&i.error(`Failed to update observable ${this.observers[e].toString()}: ${t.reason}`)})}}class ct extends c{constructor(){super()}}class lt extends o{constructor(t){super(t,lt.name,500)}}class ht extends o{constructor(t,e=ht.name){super(t,e,500)}}class ut extends ht{constructor(t){super(t,ut.name)}}class dt extends R{logFor(t,...e){return t.logger.for(this)}logCtx(t,e){return dt.logCtx.call(this,t,e)}static logCtx(t,e){if(1>t.length)throw new o("No context provided");const r=t.pop();if(!(r instanceof c))throw new o("No context provided");if(t.filter(t=>t instanceof c).length>1)throw Error("here");const s=this?r.logger.for(this).for(e):r.logger.clear().for(this).for(e);return{ctx:r,log:e?s.for(e):s,ctxArgs:[...t,r]}}}function pt(t){return t.reduce((t,e)=>t.then(async t=>[...t,await e()]),Promise.resolve([]))}const gt=V.flavourResolver.bind(V);V.flavourResolver=t=>{try{const e=gt(t);if(e&&e!==J)return e;const r="function"==typeof t?t:t?.constructor,s=r&&"function"==typeof H.registeredFlavour?H.registeredFlavour(r):void 0;if(s&&s!==J)return s;const i=ft._currentFlavour;if(i){const t=ft._cache?.[i];return t?.flavour?t.flavour:i}}catch(t){return J}};class ft extends dt{static{this._cache={}}get config(){return this._config}get alias(){return this._alias||this.flavour}repository(){if(!ft._baseRepository)throw new o("This should be overridden when necessary. Otherwise it will be replaced lazily");return ft._baseRepository}async shutdownProxies(t){if(this.proxies){if(t&&!(t in this.proxies))throw new o("No proxy found for "+t);if(t)try{await this.proxies[t].shutdown(),delete this.proxies[t]}catch(e){this.log.error(`Failed to shutdown proxied adapter ${t}: ${e}`)}else for(const t in this.proxies){try{await this.proxies[t].shutdown()}catch(e){this.log.error(`Failed to shutdown proxied adapter ${t}: ${e}`);continue}delete this.proxies[t]}}}async shutdown(){await this.shutdownProxies(),this.dispatch&&await this.dispatch.close()}constructor(t,e,r){if(super(),this._config=t,this.flavour=e,this._alias=r,this.Context=ct,this.alias in ft._cache)throw new o(`${this.alias} persistence adapter ${this._alias?`(${this.flavour}) `:""} already registered`);ft._cache[this.alias]=this,this.log.info(`Created ${this.alias} persistence adapter ${this._alias?`(${this.flavour}) `:""} persistence adapter`),ft._currentFlavour||(this.log.verbose(`Defined ${this.alias} persistence adapter as current`),ft._currentFlavour=this.alias)}Dispatch(){return new ft._baseDispatch}ObserverHandler(){return new ot}isReserved(t){return!t}async initialize(...t){}async Sequence(t){return new ft._baseSequence(t,this)}async flags(t,e,r,...s){let i=r.logger||D.for(this.toString());return r.correlationId&&(i=i.for({correlationId:r.correlationId})),Object.assign({},at,r,{affectedTables:(Array.isArray(e)?e:[e]).map(j.tableName),writeOperation:t!==l.READ,timestamp:new Date,operation:t,ignoredValidationProperties:H.validationExceptions(Array.isArray(e)&&e[0]?e[0]:e,t),logger:i})}async context(t,e,r,...s){this.log.for(this.context).debug(`Creating new context for ${t} operation on ${r?Array.isArray(r)?r.map(t=>t.name):r.name:"no"} model with flag overrides: ${JSON.stringify(e)}`);const i=await this.flags(t,r,e,...s);return(new this.Context).accumulate(i)}prepare(t,...e){const{log:r}=this.logCtx(e,this.prepare),s=t.segregate(),i=Object.entries(s.model).reduce((e,[r,s])=>{if(void 0===s)return e;const i=j.columnName(t.constructor,r);if(this.isReserved(i))throw new o(`Property name ${i} is reserved`);return e[i]=s,e},{});return t[nt.METADATA]&&(r.silly("Passing along persistence metadata for "+t[nt.METADATA]),Object.defineProperty(i,nt.METADATA,{enumerable:!1,writable:!0,configurable:!0,value:t[nt.METADATA]})),{record:i,id:t[j.pk(t.constructor)],transient:s.transient}}revert(t,e,r,s,...i){const{log:n,ctx:a}=this.logCtx(i,this.revert),c={};c[j.pk(e)]=r;const l=new e(c);n.silly(`Rebuilding model ${l.constructor.name} id ${r}`);const h=t[nt.METADATA],u=Object.keys(l).reduce((r,s)=>(r[s]=t[j.columnName(e,s)],r),l);return a.get("rebuildWithTransient")&&s&&(n.verbose("re-adding transient properties: "+Object.keys(s).join(", ")),Object.entries(s).forEach(([t,e])=>{if(t in u)throw new o(`Transient property ${t} already exists on model ${l.constructor.name}. should be impossible`);u[t]=e})),h&&(n.silly(`Passing along ${this.flavour} persistence metadata for ${l.constructor.name} id ${r}: ${h}`),Object.defineProperty(u,nt.METADATA,{enumerable:!1,configurable:!0,writable:!0,value:h})),u}async createAll(t,e,r,...s){if(e.length!==r.length)throw new o("Ids and models must have the same length");const{log:i,ctxArgs:n}=this.logCtx(s,this.createAll),a=j.tableName(t);return i.debug(`Creating ${e.length} entries ${a} table`),pt(e.map((e,s)=>()=>this.create(t,e,r[s],...n)))}async readAll(t,e,...r){const{log:s,ctxArgs:i}=this.logCtx(r,this.readAll),n=j.tableName(t);return s.debug(`Reading ${e.length} entries ${n} table`),pt(e.map(e=>()=>this.read(t,e,...i)))}async updateAll(t,e,r,...s){if(e.length!==r.length)throw new o("Ids and models must have the same length");const{log:i,ctxArgs:n}=this.logCtx(s,this.updateAll),a=j.tableName(t);return i.debug(`Updating ${e.length} entries ${a} table`),pt(e.map((e,s)=>()=>this.update(t,e,r[s],...n)))}async deleteAll(t,e,...r){const{log:s,ctxArgs:i}=ft.logCtx(r,this.deleteAll);return s.debug(`Deleting ${e.length} entries from ${t} table`),pt(e.map(e=>()=>this.delete(t,e,...i)))}observe(t,e){this.observerHandler||Object.defineProperty(this,"observerHandler",{value:this.ObserverHandler(),writable:!1}),this.observerHandler.observe(t,e);const r=this.log.for(this.observe);r.verbose("Registering new observer "+t.toString()),this.dispatch||(r.info("Creating dispatch for "+this.alias),this.dispatch=this.Dispatch(),this.dispatch.observe(this))}unObserve(t){if(!this.observerHandler)throw new o("ObserverHandler not initialized. Did you register any observables?");this.observerHandler.unObserve(t),this.log.for(this.unObserve).verbose(`Observer ${t.toString()} removed`)}async updateObservers(t,e,r,...s){if(!this.observerHandler)throw new o("ObserverHandler not initialized. Did you register any observables?");const{log:i,ctxArgs:n}=ft.logCtx(s,this.updateObservers);i.verbose(`Updating ${this.observerHandler.count()} observers for adapter ${this.alias}: Event: `),await this.observerHandler.updateObservers(t,e,r,...n)}async refresh(t,e,r,...s){return this.updateObservers(t,e,r,...s)}toString(){return this.flavour+" adapter"}static flavourOf(t){return H.flavourOf(t)}static get currentFlavour(){if(!ft._currentFlavour)throw new o("No persistence flavour set. Please initialize your adapter");return ft._currentFlavour}static get current(){return ft.get(this.currentFlavour)}static get(t){if(!t)return ft.get(this._currentFlavour);if(t in this._cache)return this._cache[t];throw new o(`No Adapter registered under ${t}.`)}static setCurrent(t){this._currentFlavour=t}static models(t){try{return H.flavouredAs(t).filter(j.isModel)}catch(t){throw new o(t)}}static decoration(){}static logCtx(t,e){return super.logCtx(t,e)}get client(){return this._client||(this._client=this.getClient()),this._client}for(t,...e){this.proxies||(this.proxies={});const r=`${this.alias} - ${L(t)}`;if(r in this.proxies)return this.proxies[r];let s;const i=new Proxy(this,{get:(e,r,i)=>{if("_config"===r){const s=Reflect.get(e,r,i);return Object.assign({},s,t)}return"_client"===r?s:Reflect.get(e,r,i)},set:(t,e,r,i)=>"_client"===e?(s=r,!0):Reflect.set(t,e,r,i)});return this.proxies[r]=i,i}migrations(){return H.migrationsFor(this)}async getQueryRunner(){return this}async migrate(t=this.migrations(),...e){t instanceof ct&&(e=[t],t=this.migrations());const{ctx:r}=ft.logCtx(e,this.migrate),s=await this.getQueryRunner();for(const e of t)try{const t=new e;await t.up(s,this,r),await t.down(s,this,r)}catch(t){throw new ht(t)}}}i([I(),n("design:type",Function),n("design:paramtypes",[String]),n("design:returntype",Promise)],ft.prototype,"shutdownProxies",null),i([I(),n("design:type",Function),n("design:paramtypes",[String,Object,Object,Object]),n("design:returntype",Promise)],ft.prototype,"context",null),i([I(),n("design:type",Function),n("design:paramtypes",[Object,Function]),n("design:returntype",void 0)],ft.prototype,"observe",null),i([I(),n("design:type",Function),n("design:paramtypes",[Object]),n("design:returntype",void 0)],ft.prototype,"unObserve",null),i([I(),n("design:type",Object),n("design:paramtypes",[])],ft.prototype,"client",null);class yt extends o{constructor(t){super(t,yt.name,500)}}class mt extends o{constructor(t){super(t,mt.name,500)}}var wt,bt,vt,xt,At,Et;(t=>{t.FIND_BY="findBy",t.SELECT="Select",t.AND="And",t.OR="Or",t.GROUP_BY="GroupBy",t.ORDER_BY="OrderBy",t.THEN="Then",t.THEN_BY="ThenBy"})(wt||(wt={})),(t=>{t.EQUAL="EQUAL",t.DIFFERENT="DIFFERENT",t.BIGGER="BIGGER",t.BIGGER_EQ="BIGGER_EQ",t.SMALLER="SMALLER",t.SMALLER_EQ="SMALLER_EQ",t.NOT="NOT",t.IN="IN",t.REGEXP="REGEXP"})(bt||(bt={})),(t=>{t.AND="AND",t.OR="OR"})(vt||(vt={})),(t=>{t.LIST_BY="listBy",t.FIND_BY="findBy",t.FIND_ONE_BY="findOneBy",t.PAGE_BY="paginateBy"})(xt||(xt={}));class Ot extends j{constructor(t,e,r){super(),this.attr1=void 0,this.operator=void 0,this.comparison=void 0,e||r?(this.attr1=t,this.operator=e,this.comparison=r):j.fromModel(this,t)}and(t){return Ot.and(this,t)}or(t){return Ot.or(this,t)}not(t){return new Ot(this,bt.NOT,t)}hasErrors(...t){const e=()=>{const t=`Invalid operator ${this.operator}}`;if("string"==typeof this.attr1){if(this.comparison instanceof Ot)return{comparison:{condition:"Both sides of the comparison must be of the same type"}};if(-1===Object.values(bt).indexOf(this.operator))return{operator:{condition:t}}}if(this.attr1 instanceof Ot){if(!(this.comparison instanceof Ot)&&this.operator!==bt.NOT)return{comparison:{condition:t}};if(-1===Object.values(vt).indexOf(this.operator)&&this.operator!==bt.NOT)return{operator:{condition:t}}}},r=super.hasErrors(...t);return this.isAsync()?(async()=>await Promise.resolve(r)??e())():r??e()}static and(t,e){return Ot.group(t,vt.AND,e)}static or(t,e){return Ot.group(t,vt.OR,e)}static group(t,e,r){return new Ot(t,e,r)}static attribute(t){return(new Ot.Builder).attribute(t)}static attr(t){return this.attribute(t)}static{this.Builder=class{constructor(){this.attr1=void 0,this.operator=void 0,this.comparison=void 0}attribute(t){return this.attr1=t,this}attr(t){return this.attribute(t)}eq(t){return this.setOp(bt.EQUAL,t)}dif(t){return this.setOp(bt.DIFFERENT,t)}gt(t){return this.setOp(bt.BIGGER,t)}lt(t){return this.setOp(bt.SMALLER,t)}gte(t){return this.setOp(bt.BIGGER_EQ,t)}lte(t){return this.setOp(bt.SMALLER_EQ,t)}in(t){return this.setOp(bt.IN,t)}regexp(t){return this.setOp(bt.REGEXP,RegExp(t).source)}setOp(t,e){return this.operator=t,this.comparison=e,this.build()}build(){try{return new Ot(this.attr1,this.operator,this.comparison)}catch(t){throw new yt(t)}}}}static builder(){return new Ot.Builder}static from(t){return new Ot(t)}}i([M(),n("design:type",Object)],Ot.prototype,"attr1",void 0),i([M(),n("design:type",String)],Ot.prototype,"operator",void 0),i([M(),n("design:type",Object)],Ot.prototype,"comparison",void 0),(t=>{t.ASC="asc",t.DSC="desc"})(At||(At={})),(t=>{t.CASCADE="cascade",t.NONE="none"})(Et||(Et={}));const St={update:Et.CASCADE,delete:Et.NONE},Nt={Equals:(t,e)=>Ot.attribute(t).eq(e),Diff:(t,e)=>Ot.attribute(t).dif(e),LessThan:(t,e)=>Ot.attribute(t).lt(e),LessThanEqual:(t,e)=>Ot.attribute(t).lte(e),GreaterThan:(t,e)=>Ot.attribute(t).gt(e),GreaterThanEqual:(t,e)=>Ot.attribute(t).gte(e),In:(t,e)=>Ot.attribute(t).in(e),Matches:(t,e)=>Ot.attribute(t).regexp(e)},_t=t=>t.charAt(0).toLowerCase()+t.slice(1);class Ct extends R{static get log(){return this._logger||(this._logger=D.for(Ct.name)),this._logger}static build(t,...e){if(!t.startsWith(wt.FIND_BY))throw Error("Unsupported method "+t);const r=this.extractCore(t),s=this.extractSelect(t),i=this.extractGroupBy(t),n=this.buildWhere(r,e),{orderBy:a,limit:o,offset:c}=this.extractOrderLimitOffset(t,e);return{action:"find",select:s,where:n,groupBy:i,orderBy:a,limit:o,offset:c}}static extractCore(t){const e=t.substring(wt.FIND_BY.length),r=e.match(/(Then[A-Z]|OrderBy|GroupBy|Limit|Offset)/);return r?e.substring(0,r.index):e}static getFieldsFromMethodName(t){return(this.extractCore(t).split(/OrderBy|GroupBy/)[0]||"").split(/And|Or/).map(t=>{const{operator:e,field:r}=this.parseFieldAndOperator(t);return r+(e??"")})}static extractSelect(t){const e=t.indexOf(wt.SELECT);if(-1===e)return;const r=t.substring(e+wt.SELECT.length),s=r.match(/(Then[A-Z]|OrderBy|GroupBy|Limit|Offset)/);return(s?r.substring(0,s.index):r).split(wt.AND).map(_t).filter(Boolean)}static extractGroupBy(t){const e=t.indexOf(wt.GROUP_BY);if(-1!==e)return t.substring(e+wt.GROUP_BY.length).split(wt.ORDER_BY)[0].split(wt.THEN_BY).map(_t).filter(Boolean)}static buildWhere(t,e){if(!t&&0===e.length)return;const r=(t.split(/OrderBy|GroupBy/)[0]||"").split(/And|Or/),s=t.match(/And|Or/g)||[];let i;if(r.forEach((t,r)=>{const{field:n,operator:a}=this.parseFieldAndOperator(t),o=a?Nt[a]:Nt.Equals;if(!o)throw Error("Unsupported operator "+a);const c=e[r];if(void 0===c)throw Error("Invalid value for field "+n);const l=o(n,c);i=0===r?l:s[r-1]===wt.AND?i.and(l):i.or(l)}),0!==r.length){if(!i)throw Error("No conditions found in method name");return i}}static parseFieldAndOperator(t){for(const e of Object.keys(Nt))if(t.endsWith(e)){const r=t.slice(0,-e.length);return{field:_t(r),operator:e}}return{field:_t(t)}}static extractOrderByField(t){const e=t.match(/OrderBy(.+)$/);if(!e)return;const r=e[1];return r.charAt(0).toLowerCase()+r.slice(1)}static getProperlyOrderByOrThrow(t,e){const r=Ct.log.for(this.getProperlyOrderByOrThrow);if(e||t){if(e&&!t)throw new yt("Expected OrderBy clause, but no sortable field was found in method name.");if(e||!t){if(!Object.values(At).includes(e))throw new yt(`Invalid OrderBy direction ${e}. Expected one of: ${Object.values(At).join(", ")}.`);return[[t,e]]}r.debug("Ignoring OrderBy clause because direction is undefined.")}}static extractOrderLimitOffset(t,e){const r=this.extractCore(t).split(/And|Or/).length,s=e.slice(r)??[];let i,n,a;if(s.at(-1)instanceof c&&s.pop(),s.length>=1){const e=s[0],r=this.extractOrderByField(t);i=this.getProperlyOrderByOrThrow(r,e)}return 2>s.length||"number"!=typeof s[1]||(n=s[1]),3>s.length||"number"!=typeof s[2]||(a=s[2]),{orderBy:i,limit:n,offset:a}}}function Tt(){return V.for(nt.STATEMENT).define({decorator:()=>(t,e,r)=>W(X(H.key(nt.STATEMENT,e),!0))(t,e,r),args:[]}).apply()}function Bt(t={}){return V.for(nt.QUERY).define({decorator:t=>(e,r,s)=>{const i=Ct.getFieldsFromMethodName(r);return W(X(H.key(nt.QUERY,r),{...t,fields:i}),Tt(),(t=>(e,r,s)=>{s.value=new Proxy(s.value,{apply(e,r,s){const{select:i,where:n,groupBy:a,orderBy:o,limit:c,offset:l}=Ct.build(e.name,...s);let h=r.select(i);n&&(h=h.where(n));const{allowLimit:u,allowOffset:d,allowOrderBy:p,throws:g}={allowLimit:!0,allowOrderBy:!0,allowOffset:!0,throws:!0,...t},f=[{key:"orderBy",value:(o||[])[0],allowed:p},{key:"limit",value:c,allowed:u},{key:"offset",value:l,allowed:d}];for(const t of f)if(void 0!==t.value){if(!t.allowed&&g)throw new yt(t.key[0].toUpperCase()+t.key.slice(1)+" is not allowed for this query");t.allowed&&(h=h[t.key](t.value))}return h.execute()}})})(t))(e,r,s)},args:[t]}).apply()}class Pt extends h{static{this._cache={}}get log(){return this.logger||(this.logger=this.adapter.log.for(this.toString())),this.logger}get adapter(){if(!this._adapter)throw new o("No adapter found for this repository. did you use the @uses decorator or pass it in the constructor?");return this._adapter}get tableName(){return this._tableName||(this._tableName=j.tableName(this.class)),this._tableName}get pkProps(){return super.pkProps}constructor(t,e,...r){super(e),this.observers=[],this._overrides={allowGenerationOverride:!1,allowRawStatements:!0,forcePrepareSimpleQueries:!1,forcePrepareComplexQueries:!1,ignoreDevSafeGuards:!1,mergeForUpdate:!0,applyUpdateValidation:!0},t&&(this._adapter=t),e&&(Pt.register(e,this,this.adapter.alias),t)&&H.get(e,K.FLAVOUR)===J&&Z(t.flavour)(e);const s=this;[this.createAll,this.readAll,this.deleteAll].forEach(t=>{const e=t.name;u(s,s[e+"Prefix"],t,s[e+"Suffix"])}),d(s,s[this.updateAll.name+"Prefix"],this.updateAll,s[this.updateAll.name+"Suffix"])}logCtx(t,e){return ft.logCtx(t,e)}override(t){return new Proxy(this,{get:(e,r,s)=>{const i=Reflect.get(e,r,s);return"_overrides"!==r?i:Object.assign({},i,t)}})}for(t,...e){return new Proxy(this,{get:(r,s,i)=>"adapter"===s?this.adapter.for(t,...e):Reflect.get(r,s,i)})}ObserverHandler(){return new ot}async createPrefix(t,...e){const r=await ct.args(l.CREATE,this.class,e,this.adapter,this._overrides||{}),s=r.context.get("ignoreHandlers"),i=r.context.get("ignoreValidation");if(t=new this.class(t),s||await p(this,r.context,t,l.CREATE,l.ON),!i){const e=await Promise.resolve(t.hasErrors(...r.context.get("ignoredValidationProperties")||[]));if(e)throw new g(e.toString())}return[t,...r.args]}async create(t,...e){const{ctx:r,log:s,ctxArgs:i}=this.logCtx(e,this.create);s.debug(`Creating new ${this.class.name} in table ${j.tableName(this.class)}`);let{record:n,id:a,transient:o}=this.adapter.prepare(t,r);return n=await this.adapter.create(this.class,a,n,...i),this.adapter.revert(n,this.class,a,o,r)}async createAll(t,...e){if(!t.length)return t;const{ctx:r,log:s,ctxArgs:i}=this.logCtx(e,this.createAll);s.debug(`Creating ${t.length} new ${this.class.name} in table ${j.tableName(this.class)}`);const n=t.map(t=>this.adapter.prepare(t,r)),a=n.map(t=>t.id);let o=n.map(t=>t.record);return o=await this.adapter.createAll(this.class,a,o,...i),o.map((t,e)=>this.adapter.revert(t,this.class,a[e],r.get("rebuildWithTransient")?n[e].transient:void 0,r))}async createAllPrefix(t,...e){const r=await ct.args(l.CREATE,this.class,e,this.adapter,this._overrides||{}),s=r.context.get("ignoreHandlers"),i=r.context.get("ignoreValidation");if(!t.length)return[t,...r.args];const n=j.sequenceFor(t[0]);let a=[];if(j.generatedBySequence(this.class)?(n.name||(n.name=j.sequenceName(t[0],"pk")),a=await(await this.adapter.Sequence(n)).range(t.length,...r.args)):j.generated(this.class,this.pk)||(a=t.map((t,e)=>{if(void 0===t[this.pk])throw new o("Primary key is not defined for model in position "+e);return t[this.pk]})),t=await Promise.all(t.map(async(t,e)=>(t=new this.class(t),n.type&&(t[this.pk]="String"!==n.type||n.generated?a[e]:""+t[this.pk]),s||await p(this,r.context,t,l.CREATE,l.ON),t))),!i){const e=r.context.get("ignoredValidationProperties")||[],s=await Promise.all(t.map(t=>Promise.resolve(t.hasErrors(...e)))),i=f(s);if(i)throw new g(i)}return[t,...r.args]}async readPrefix(t,...e){const r=await ct.args(l.READ,this.class,e,this.adapter,this._overrides||{}),s=new this.class;return s[this.pk]=t,await p(this,r.context,s,l.READ,l.ON),[t,...r.args]}async read(t,...e){const{ctx:r,log:s,ctxArgs:i}=this.logCtx(e,this.read);s.debug(`reading ${this.class.name} from table ${j.tableName(this.class)} with pk ${this.pk}`);const n=await this.adapter.read(this.class,t,...i);return this.adapter.revert(n,this.class,t,void 0,r)}async readAllPrefix(t,...e){const r=await ct.args(l.READ,this.class,e,this.adapter,this._overrides||{});return await Promise.all(t.map(async t=>{const e=new this.class;return e[this.pk]=t,p(this,r.context,e,l.READ,l.ON)})),[t,...r.args]}async readAll(t,...e){const{ctx:r,log:s,ctxArgs:i}=this.logCtx(e,this.readAll);return s.debug(`reading ${t.length} ${this.class.name} in table ${j.tableName(this.class)}`),(await this.adapter.readAll(this.class,t,...i)).map((e,s)=>this.adapter.revert(e,this.class,t[s],void 0,r))}async update(t,...e){const{ctxArgs:r,log:s,ctx:i}=this.logCtx(e,this.update);let{record:n,id:a,transient:o}=this.adapter.prepare(t,i);return s.debug(`updating ${this.class.name} in table ${j.tableName(this.class)} with id ${a}`),n=await this.adapter.update(this.class,a,n,...r),this.adapter.revert(n,this.class,a,o,i)}async updatePrefix(t,...e){const r=await ct.args(l.UPDATE,this.class,e,this.adapter,this._overrides||{}),s=r.context,i=s.get("ignoreHandlers"),n=s.get("ignoreValidation"),a=t[this.pk];if(!a)throw new o("No value for the Id is defined under the property "+this.pk);let c;if(s.get("applyUpdateValidation")&&(c=await this.read(a,s),s.get("mergeForUpdate")&&(t=j.merge(c,t,this.class))),i||await p(this,r.context,t,l.UPDATE,l.ON,c),!n){const e=await Promise.resolve(t.hasErrors(c,...r.context.get("ignoredValidationProperties")||[]));if(e)throw new g(e.toString())}return[t,...r.args,c]}async updateAll(t,...e){const{ctx:r,log:s,ctxArgs:i}=this.logCtx(e,this.updateAll);s.debug(`Updating ${t.length} new ${this.class.name} in table ${j.tableName(this.class)}`);const n=t.map(t=>this.adapter.prepare(t,r));return(await this.adapter.updateAll(this.class,n.map(t=>t.id),n.map(t=>t.record),...i)).map((t,e)=>this.adapter.revert(t,this.class,n[e].id,r.get("rebuildWithTransient")?n[e].transient:void 0,r))}async updateAllPrefix(t,...e){const r=await ct.args(l.UPDATE,this.class,e,this.adapter,this._overrides||{}),s=r.context,i=s.get("ignoreHandlers"),n=s.get("ignoreValidation"),a=t.map(t=>{const e=t[this.pk];if(!e)throw new o("missing id on update operation");return e});let c;if(s.get("applyUpdateValidation")&&(c=await this.readAll(a,s),s.get("mergeForUpdate")&&(t=t.map((t,e)=>j.merge(c[e],t,this.class)))),i||await Promise.all(t.map((t,e)=>p(this,r.context,t,l.UPDATE,l.ON,c?c[e]:void 0))),!n){const e=s.get("ignoredValidationProperties")||[];let r;r=s.get("applyUpdateValidation")?await Promise.all(t.map((t,r)=>Promise.resolve(t.hasErrors(c[r],...e)))):await Promise.resolve(t.map(t=>t.hasErrors(...e)));const i=f(r);if(i)throw new g(i)}return[t,...r.args,c]}async deletePrefix(t,...e){const r=await ct.args(l.DELETE,this.class,e,this.adapter,this._overrides||{}),s=await this.read(t,...r.args);return await p(this,r.context,s,l.DELETE,l.ON),[t,...r.args]}async delete(t,...e){const{ctx:r,log:s,ctxArgs:i}=this.logCtx(e,this.delete);s.debug(`deleting new ${this.class.name} in table ${j.tableName(this.class)} with pk ${t}`);const n=await this.adapter.delete(this.class,t,...i);return this.adapter.revert(n,this.class,t,void 0,r)}async deleteAllPrefix(t,...e){const r=await ct.args(l.DELETE,this.class,e,this.adapter,this._overrides||{}),s=await this.readAll(t,...r.args);return await Promise.all(s.map(async t=>p(this,ct.childFrom(r.context),t,l.DELETE,l.ON))),[t,...r.args]}async deleteAll(t,...e){const{ctx:r,log:s,ctxArgs:i}=this.logCtx(e,this.create);return s.debug(`deleting ${t.length} ${this.class.name} in table ${j.tableName(this.class)}`),(await this.adapter.deleteAll(this.class,t,...i)).map((e,s)=>this.adapter.revert(e,this.class,t[s],void 0,r))}select(t){return this.adapter.Statement(this._overrides).select(t).from(this.class)}async query(t,e,r=At.ASC,s,i,...n){const a=await ct.args(nt.QUERY,this.class,n,this.adapter,this._overrides||{}),{ctx:o}=this.logCtx(a.args,this.query),c=[e,r],l=this.select().where(t).orderBy(c);return s&&l.limit(s),i&&l.offset(i),l.execute(o)}async listBy(t,e,...r){const s=await ct.args(xt.LIST_BY,this.class,r,this.adapter,this._overrides||{}),{log:i,ctxArgs:n}=this.logCtx(s.args,this.listBy);return i.verbose(`listing ${j.tableName(this.class)} by ${t} ${e}`),this.select().orderBy([t,e]).execute(...n)}async paginateBy(t,e,r={offset:1,limit:10},...s){let{offset:i,bookmark:n,limit:a}=r;if(!i&&!n)throw new yt("PaginateBy needs a page or a bookmark");const o=await ct.args(xt.PAGE_BY,this.class,s,this.adapter,this._overrides||{}),{log:c,ctxArgs:l}=this.logCtx(o.args,this.paginateBy);let h;if(c.verbose(`paginating ${j.tableName(this.class)} with page size ${a}`),n)h=await this.override({forcePrepareComplexQueries:!1,forcePrepareSimpleQueries:!1}).select().where(this.attr(j.pk(this.class)).gt(n)).orderBy([t,e]).paginate(a,...l),i=1;else{if(!i)throw new yt("PaginateBy needs a page or a bookmark");h=await this.override({forcePrepareComplexQueries:!1,forcePrepareSimpleQueries:!1}).select().orderBy([t,e]).paginate(a,...l)}const u=await h.page(i,...l);return h.serialize(u)}async findOneBy(t,e,...r){const s=await ct.args(xt.FIND_ONE_BY,this.class,r,this.adapter,this._overrides||{}),{log:i,ctxArgs:n}=this.logCtx(s.args,this.findOneBy);i.verbose(`finding ${j.tableName(this.class)} with ${t} ${e}`);const a=await this.select().where(this.attr(t).eq(e)).limit(1).execute(...n);if(!a.length)throw new y("No results found");return a[0]}async findBy(t,e,...r){const s=await ct.args(xt.FIND_BY,this.class,r,this.adapter,this._overrides||{}),{log:i,ctxArgs:n}=this.logCtx(s.args,this.findBy);return i.verbose(`finding ${j.tableName(this.class)} with ${t} ${e}`),this.select().where(this.attr(t).eq(e)).execute(...n)}async statement(t,...e){if(!Pt.statements(this,t))throw new yt("Invalid prepared statement requested "+t);const r=await ct.args(nt.STATEMENT,this.class,e,this.adapter,this._overrides||{}),{log:s,ctxArgs:i}=this.logCtx(r.args,this.statement);return s.verbose("Executing prepared statement "+t),this[t](...i)}attr(t){return Ot.attr(t)}observe(t,e){this.observerHandler||Object.defineProperty(this,"observerHandler",{value:this.ObserverHandler(),writable:!1});const r=this.log.for(this.observe),s=j.tableName(this.class);this.adapter.observe(this,(t,e,r,...i)=>"string"==typeof t?t===s:H.constr(t)===H.constr(this.class)),r.verbose(`now observing ${this.adapter} filtering on table === ${s}`),this.observerHandler.observe(t,e),r.verbose("Registered new observer "+t.toString())}unObserve(t){if(!this.observerHandler)throw new o("ObserverHandler not initialized. Did you register any observables?");this.observerHandler.unObserve(t),this.log.for(this.unObserve).verbose(`Observer ${t.toString()} removed`),this.observerHandler.count()||(this.log.verbose(`No more observers registered for ${this.adapter}, unsubscribing`),this.adapter.unObserve(this),this.log.verbose("No longer observing adapter "+this.adapter.flavour))}async updateObservers(t,e,r,...s){if(!this.observerHandler)throw new o("ObserverHandler not initialized. Did you register any observables?");const{log:i,ctxArgs:n}=this.logCtx(s,this.updateObservers);i.verbose(`Updating ${this.observerHandler.count()} observers for ${this}`),await this.observerHandler.updateObservers(t,e,Array.isArray(r)?r.map(t=>ft._baseSequence.parseValue(j.sequenceFor(this.class).type,t)):ft._baseSequence.parseValue(j.sequenceFor(this.class).type,r),...n)}async refresh(t,e,r,...s){return this.updateObservers(t,e,r,...s)}static forModel(t,e,...r){let s;const i=e||H.flavourOf(t)||ft.currentFlavour;try{s=this.get(t,i)}catch(t){s=void 0}if(s instanceof Pt)return s;const n=e||H.flavourOf(t)||s&&H.get(s,nt.ADAPTER)||ft.currentFlavour,a=n?ft.get(n):void 0;if(!a)throw new o("No registered persistence adapter found flavour "+n);return s=s||a.repository(),new s(a,t,...r)}static get(t,e){const r=j.tableName(t);let s=r;if(e&&(s=[r,e].join(m)),s in this._cache)return this._cache[s];if(r in this._cache)return this._cache[r];throw new o("Could not find repository registered under "+r)}static register(t,e,r){let s=j.tableName(t);if(r&&(s=[s,r].join(m)),s in this._cache&&this._cache[s]instanceof Pt)throw new o(s+" already has a registered instance");this._cache[s]=e}static statements(t,e){const r=t instanceof Pt?t.constructor:t,s=H.get(r,e?H.key(nt.STATEMENT,e):nt.STATEMENT);return(e?s:Object.keys(s))||!1}static queries(t,e){const r=t instanceof Pt?t.constructor:t;return H.get(r,e?H.key(nt.QUERY,e):nt.QUERY)}}function $t(t,e){if(!(e||(e=V.flavourResolver(t instanceof j?t.constructor:t))&&e!==J))throw new o("Could not retrieve flavour from model "+(t instanceof j?t.constructor.name:t.name));return U(nt.INJECTABLE,e,j.tableName(t))}i([Tt(),n("design:type",Function),n("design:paramtypes",[Object,String,void 0]),n("design:returntype",Promise)],Pt.prototype,"listBy",null),i([Tt(),n("design:type",Function),n("design:paramtypes",[Object,String,Object,void 0]),n("design:returntype",Promise)],Pt.prototype,"paginateBy",null),i([Tt(),n("design:type",Function),n("design:paramtypes",[Object,Object,void 0]),n("design:returntype",Promise)],Pt.prototype,"findOneBy",null),i([Tt(),n("design:type",Function),n("design:paramtypes",[Object,Object,void 0]),n("design:returntype",Promise)],Pt.prototype,"findBy",null),i([I(),n("design:type",Function),n("design:paramtypes",[Object,Function]),n("design:returntype",void 0)],Pt.prototype,"observe",null),i([I(),n("design:type",Function),n("design:paramtypes",[Object]),n("design:returntype",void 0)],Pt.prototype,"unObserve",null),ft&&(ft._baseRepository=Pt);class Rt extends t{get log(){return this.logger||(this.logger=D.for(this)),this.logger}constructor(){super()}get(t,r){const s=this.log.for(this.get);let i;try{i=super.get(t)}catch{}if(!i){let n;if("function"==typeof t?n=j.get(t.toString())||t:"symbol"!=typeof t&&"string"!=typeof t||(n=j.get(t.toString())),!n)return;const a=nt.ADAPTER,o=r||H.get(n,a);try{let t=o;try{o&&ft.get(o)}catch{const e=ft.current;e&&e.flavour===o&&(t=e.alias)}if(i=Pt.forModel(n,t),i instanceof Pt)return i;const r=o||H.get(i.constructor,a)||H.get(n,a);e.register(i,$t(n,r))}catch(t){s.debug("No registered repository or adapter found. falling back to default adapter. Error: "+(t?.message||JSON.stringify(t)));const e=Pt.get(n,o);if("function"==typeof e){const t=o?ft.get(o):ft.current;if(!t)return;return new e(t,n)}}}return i}}async function Dt(t,e,r,s){const i=e.logger.for(Dt);if(!s){const e=j.get(t.constructor.name);if(!e)throw new o("Could not find model "+t.constructor.name);s=Pt.forModel(e,r),i.info("Retrieved "+s.toString())}let n;if(void 0===t[j.pk(s.class)])i.info(`No pk found in ${j.tableName(s.class)} - creating`),n=await s.create(t,e);else{i.info(`pk found in ${j.tableName(s.class)} - attempting update`);try{n=await s.update(t,e),i.info("Updated "+j.tableName(s.class))}catch(r){if(!(r instanceof y))throw r;i.info("update Failed - creating new "+j.tableName(s.class)),n=await s.create(t,e)}i.info("After create update: "+n)}return n}async function It(t,e,r,s){const i=s[r];if(!i)return;if("object"!=typeof i){const e=zt(s,r,this.adapter.alias),n=await e.read(i);return await qt(t,s,r,i,n),void(s[r]=i)}const n=k(e.class)?e.class:e.class();if(!n)throw new o("Could not find model "+e.class);const a=Pt.forModel(n,this.adapter.alias),c=await a.create(i,t),l=j.pk(c);await qt(t,s,r,c[l],c),s[r]=c[l]}async function kt(t,e,r,s){const i=s[r];if(!i)return;if(e.cascade.update!==Et.CASCADE)return;if("object"!=typeof i){const e=zt(s,r,this.adapter.alias),n=await e.read(i,t);return await qt(t,s,r,i,n),void(s[r]=i)}const n=await Dt(s[r],t,this.adapter.alias),a=j.pk(n);await qt(t,s,r,n[a],n),s[r]=n[a]}async function Ft(t,e,r,s){const i=s[r];if(!i)return;if(e.cascade.update!==Et.CASCADE)return;const n=zt(s,r,this.adapter.alias);let a;a=i instanceof j?await n.delete(s[r][n.pk],t):await n.delete(s[r],t),await qt(t,s,r,a[n.pk],a)}async function jt(t,e,r,s){const i=s[r];if(!i||!i.length)return;const n=typeof i[0];if(!i.every(t=>typeof t===n))throw new o(`Invalid operation. All elements of property ${r} must match the same type.`);const a=t.logger.for(jt),c=new Set([...i]);if("object"!==n){const e=zt(s,r,this.adapter.alias),i=await e.readAll([...c.values()],t);for(let e=0;e<i.length;e++){const s=i[e];a.warn("FOUND ONE TO MANY VALUE: "+JSON.stringify(s)),await qt(t,s,r,[...c.values()][e],i)}return s[r]=[...c],void a.warn("SET ONE TO MANY IDS: "+s[r])}const l=j.pk(i[0].constructor),h=new Set;for(const e of i){a.info("Creating or updating one-to-many model: "+JSON.stringify(e));const i=await Dt(e,t,this.adapter.alias);a.info(`caching: ${JSON.stringify(i)} under ${i[l]}`),await qt(t,s,r,i[l],i),a.info("Creating or updating one-to-many model: "+JSON.stringify(e)),h.add(i[l])}s[r]=[...h]}async function Lt(t,e,r,s){const{cascade:i}=e;if(i.update===Et.CASCADE)return jt.call(this,t,e,r,s)}async function Mt(t,e,r,s){if(e.cascade.delete!==Et.CASCADE)return;const i=s[r];if(!i||!i.length)return;const n=typeof i[0];if(!i.every(t=>typeof t===n))throw new o(`Invalid operation. All elements of property ${r} must match the same type.`);const a="function"!=typeof e.class||e.class.name?e.class:e.class(),c="object"===n,l=c?Pt.forModel(a,this.adapter.alias):zt(s,r,this.adapter.alias),h=[...new Set([...c?i.map(t=>t[l.pk]):i]).values()];let u,d;try{u=await l.deleteAll(h,t)}catch(e){throw t.logger.error("Failed to delete all records",e),e}for(let e=0;e<u.length;e++){d=u[e];try{await qt(t,s,r,h[e],d)}catch(i){throw t.logger.error(`Failed to cache record ${h[e]} with key ${r} and model ${JSON.stringify(s,void 0,2)} `,i),i}}s[r]=h}function Ut(t,e,r){return[nt.POPULATE,t,e,r].join(".")}async function qt(t,e,r,s,i){const n=Ut(e.constructor.name,r,s),a=t.get("cacheForPopulate")||{};return a[n]=i,t.accumulate({cacheForPopulate:a})}async function Gt(t,e,r,s){if(!e.populate)return;const i=s[r],n=Array.isArray(i);if(void 0===i||n&&0===i.length)return;const a=await(async(e,r,s,i,n)=>{let a,c;const l=[],h=e.get("cacheForPopulate")||{};for(const e of i){a=Ut(r.constructor.name,s,e);try{if(c=h[a],!c)throw Error("Not found in cache")}catch(i){const a=zt(r,s,n);if(!a)throw new o("Could not find repo");c=await a.read(e,t)}l.push(c)}return l})(t,s,r,n?i:[i],this.adapter.alias);s[r]=n?a:a[0]}const Yt=["array","string","number","boolean","symbol","function","object","undefined","null","bigint"];function zt(t,e,r){if(!t)throw Error("No model was provided to get repository");let s;if(Array.isArray(t[e])||t[e]instanceof Set){const r=H.get(t instanceof j?t.constructor:t,H.key(q.REFLECT,e,q.LIST))?.clazz;if(!r)throw new o("Failed to find types decorators for property "+e);s=(Array.isArray(r)?[...r]:[r]).map(t=>"function"!=typeof t||t.name?t:t())}else s=H.getPropDesignTypes(t instanceof j?t.constructor:t,e)?.designTypes;const i=s?.find(t=>!Yt.includes((""+t.name).toLowerCase()));return Pt.forModel(i,r)}class Qt extends w{constructor(t,e=Qt.name,r=401){super(t,e,r)}}class Ht extends Qt{constructor(t,e=Ht.name){super(t,e,403)}}class Vt extends o{constructor(t){super(t,Vt.name,503)}}function Jt(t){return V.for(nt.TABLE).define({decorator:t=>e=>tt(nt.TABLE,t||e.name.toLowerCase())(e),args:[t]}).apply()}function Wt(t){return V.for(nt.COLUMN).define({decorator:t=>(e,r)=>et(H.key(nt.COLUMN,r),t||r)(e,r),args:[t]}).apply()}function Xt(t,e,r){return V.for(nt.INDEX).define({decorator:(t,e,r)=>(s,i)=>("string"==typeof t&&(r=t,t=void 0,e=void 0),"string"==typeof e&&(r=e,e=void 0),!e&&t&&t.find(t=>![At.ASC,At.DSC].includes(t))&&(e=t,t=void 0),et(H.key(`${nt.INDEX}${e&&e?.length?"."+e.join("."):""}`,i),{directions:t,compositions:e,name:r})(s,i)),args:[t,e,r]}).apply()}async function Kt(t,e,r,s){if(s[r]&&(await this.select().where(Ot.attribute(r).eq(s[r])).execute()).length)throw new b(`model already exists with property ${r} equal to ${JSON.stringify(s[r],void 0,2)}`)}function Zt(){const t=nt.UNIQUE;return V.for(t).define(G(),v(Kt),et(t,{})).apply()}async function te(t,e,r,s){throw new Qt("This adapter does not support user identification")}function ee(){return V.for(nt.CREATED_BY).define({decorator:()=>(t,e)=>W(A(te),et(nt.CREATED_BY,e),le())(t,e),args:[]}).apply()}function re(){return V.for(nt.UPDATED_BY).define({decorator:()=>(t,e)=>W(E(te),et(nt.UPDATED_BY,e),le())(t,e),args:[]}).apply()}function se(){return x([l.CREATE])}function ie(){return x()}function ne(t,e=St,r=!0,s,i){const n=nt.ONE_TO_ONE;return V.for(n).define({decorator:(t,e,r,s,i)=>{const a={class:t,cascade:e,populate:r};return s&&(a.joinTable=s),i&&(a.name=i),W(rt(),ge(n,a),Y([t,String,Number,BigInt]),A(It,a),E(kt,a),O(Ft,a),N(Gt,a))},args:[t,e,r,s,i]}).apply()}function ae(t,e=St,r=!0,s,i){const n=nt.ONE_TO_MANY;return V.for(n).define({decorator:(t,e,r,s,i)=>{const a={class:t,cascade:e,populate:r};return s&&(a.joinTable=s),i&&(a.name=i),W(rt(),ge(n,a),z([t,String,Number,BigInt]),A(jt,a),E(Lt,a),O(Mt,a),N(Gt,a))},args:[t,e,r,s,i]}).apply()}function oe(t,e=St,r=!0,s,i){const n=nt.MANY_TO_ONE;return V.for(n).define({decorator:(t,e,r,s,i)=>{const a={class:t,cascade:e,populate:r};return s&&(a.joinTable=s),i&&(a.name=i),W(rt(),ge(n,a),Y([t,String,Number,BigInt]))},args:[t,e,r,s,i]}).apply()}function ce(t,e=St,r=!0,s,i){const n=nt.MANY_TO_MANY;return V.for(n).define({decorator:(t,e,r,s,i)=>{const a={class:t,cascade:e,populate:r};return s&&(a.joinTable=s),i&&(a.name=i),W(rt(),ge(n,a),z([t,String,Number,BigInt]))},args:[t,e,r,s,i]}).apply()}function le(){return(t,e)=>et(H.key(nt.GENERATED,e),!0)(t,e)}function he(...t){return(e,r)=>{const s=H.get(e,H.key(nt.NO_VALIDATE,r))||[],i=[...new Set([...s,...t])];return W(tt(H.key(nt.NO_VALIDATE,r),i))(e,r)}}function ue(){return he(l.CREATE)}function de(){return he(l.UPDATE)}function pe(){return he(l.UPDATE,l.CREATE)}function ge(t,e){return V.for(nt.RELATIONS).define({decorator:(t,e)=>(r,s)=>(et(t,e)(r,s),et(H.key(nt.RELATIONS,s),Object.assign({},e,{key:t}))(r,s)),args:[t,e]}).apply()}V.for(_.TIMESTAMP).extend(le()).apply(),V.for(_.COMPOSED).extend(le()).apply(),H.validationExceptions=((t,e)=>{const r=H.get(t,nt.NO_VALIDATE)||[],s=Object.entries(r).filter(([,t])=>t.includes(e)).map(([t])=>t),i=j.nestedRelations(t);return[...new Set([...s,...i])]}).bind(H),H.migrationsFor=(t=>{if(!(t=t??ft.current))throw new o("Could not get adapter for migrations");return H.innerGet(Symbol.for(nt.MIGRATION),t.alias).map(t=>t.class)}).bind(H),H.relations=((t,e)=>{const r=H.get(t,nt.RELATIONS);if(r){if(!e)return Object.keys(r);if(!r[e])throw new o("No relations metadata found for property "+e);return r[e]}}).bind(H),j.relations=(t,e)=>H.relations(t instanceof j?t.constructor:t,e)||[],j.nestedRelations=(t,e)=>{e?.length||(e=j.relations(t));let r=[];const s=H.get(t,nt.RELATIONS);if(!s||!Object.keys(s).length)return[...new Set([...e])];for(const t in s){const i=s[t];if(i?.class&&j.relations(i.class)){const s=j.relations(i.class),n=s.map(e=>`${t}.${e}`);e=[...e,...s,...n],r=j.nestedRelations(i.class,e)}}return[...new Set([...e,...r])]},j.generated=((t,e)=>!!H.get("function"!=typeof t?t.constructor:t,H.key(nt.GENERATED,e))).bind(H),j.generatedBySequence=((t,e)=>{const r="function"!=typeof t?t.constructor:t;return!!j.sequenceFor(r).generated}).bind(H),H.createdBy=(t=>{const e=H.get("function"!=typeof t?t.constructor:t,nt.CREATED_BY);if(!e)throw new o("No createdBy metadata found for model. did you use @createdBy()?");return e}).bind(H),H.updatedBy=(t=>{const e=H.get("function"!=typeof t?t.constructor:t,nt.UPDATED_BY);if(!e)throw new o("No updatedBy metadata found for model. did you use @updatedBy()?");return e}).bind(H),j.tableName=t=>{if(!(t instanceof j?j.get(t.constructor.name):t))throw new o("Unable to find model "+t);return H.get(t instanceof j?t.constructor:t,nt.TABLE)||(t instanceof j?t.constructor.name:t.name)},j.columnName=(t,e)=>H.get(t instanceof j?t.constructor:t,H.key(nt.COLUMN,e))||e,j.sequenceName=(t,...e)=>[j.tableName(t),...e].join("_"),j.sequenceFor=(t,e)=>{if(e)throw new lt("not currently supported");const r=j.pkProps(t instanceof j?t.constructor:t);if(!r)throw new o("No sequence options defined for model. did you use the @pk decorator?");return r},j.indexes=t=>{const e=H.get(t instanceof j?t.constructor:t,nt.INDEX);return Object.keys(e||{}).reduce((t,r)=>(t[r]={[nt.INDEX]:e[r]},t),{})},e.services=()=>H.innerGet(Symbol.for(nt.SERVICE)),e.repositories=()=>H.innerGet(Symbol.for(_.REPOSITORY));class fe extends dt{constructor(){super()}async initialize(){if(!this.adapter)return void this.log.for(this.initialize).verbose("No adapter observed for dispatch; skipping initialization");const t=this.adapter;[l.CREATE,l.UPDATE,l.DELETE,C.CREATE_ALL,C.UPDATE_ALL,C.DELETE_ALL].forEach(e=>{if(!t[e])throw new o(`Method ${e} not found in ${t.alias} adapter to bind Observables Dispatch`);let r=Object.getOwnPropertyDescriptor(t,e),s=t;for(;!r&&s!==Object.prototype;)s=Object.getPrototypeOf(s),r=Object.getOwnPropertyDescriptor(s,e);r&&r.writable?t[e]=new Proxy(t[e],{apply:async(t,r,s)=>{const{log:i,ctxArgs:n}=r.logCtx(s,t),[a,o]=s,c=await t.apply(r,n);return this.updateObservers(a,(t=>{switch(t){case C.CREATE_ALL:return l.CREATE;case C.UPDATE_ALL:return l.UPDATE;case C.DELETE_ALL:return l.DELETE;default:return t}})(e),o,c,...n.slice(s.length)).then(()=>{i.verbose(`Observer refresh dispatched by ${e} for ${a}`),i.debug("pks: "+o)}).catch(t=>i.error(`Failed to dispatch observer refresh for ${e} on ${a}: ${t}`)),c}}):this.log.error(`Could not find method ${e} to bind Observables Dispatch`)})}async close(){}observe(t){if(!(t instanceof ft))throw new lt("Only Adapters can be observed by dispatch");this.adapter=t,this.models=ft.models(this.adapter.alias),this.initialize().then(()=>this.log.verbose(`Dispatch initialized for ${this.adapter.alias} adapter`))}unObserve(t){if(this.adapter!==t)throw new lt("Only the adapter that was used to observe can be unobserved");this.adapter=void 0}async updateObservers(t,e,r,...s){const i="string"==typeof t?t:j.tableName(t),{log:n,ctxArgs:a}=this.logCtx(s,this.updateObservers);if(this.adapter)try{n.debug(`Dispatching ${e} from table ${i} for ${e} with id: ${JSON.stringify(r)}`),await this.adapter.refresh(t,e,r,...a)}catch(t){throw new o("Failed to refresh dispatch: "+t)}else n.verbose(`No adapter observed for dispatch; skipping observer update for ${i}:${e}`)}}ft&&(ft._baseDispatch=fe);class ye{generate(t){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{const e=16*Math.random()|0;return("x"==t?e:3&e|8).toString(16)})}static get instance(){return ye._instance||(ye._instance=new ye),ye._instance}}class me{constructor(){this.count=14}generate(t){return(""+((t=(t?parseInt(t):0)||0)+1)).padStart(this.count,"0")}static get instance(){return me._instance||(me._instance=new me),me._instance}}function we(t,e,r,s){const i=async function(...t){let s;try{s=await Promise.resolve(r.call(this,...t))}catch(t){if(t instanceof ut)return;throw t}return Promise.resolve(e.apply(this,s))}.bind(t),n=s||e.name;Object.defineProperty(i,"name",{enumerable:!0,configurable:!0,writable:!1,value:n}),t[n]=i}class be extends R{constructor(){super(),this.transaction=!0,[this.up,this.down].forEach(t=>{const e=t.name;we(this,t,this.prefix(e))})}get adapter(){const t=H.get(this.constructor,nt.MIGRATION);if(!t)throw new o("No migration metadata for "+this.constructor.name);const e=t.flavour;return ft.get(e)}async enforceRules(t,e,r){const s=H.get(this.constructor,nt.MIGRATION)?.rules;if(!s||!s.length)return!0;for(const i of s)if(!await i(t,e,r))return!1;return!0}prefix(t){return async function(e){let r;e instanceof ft?r=this.getQueryRunner(e.client):(r=e,e=this.adapter);const s=await ct.args("migration",j,[t],e);if(!await this.enforceRules(r,e,s.context))throw s.context.logger.verbose(`Skipping migration ${this.constructor.name} due to rules`),new ut("Migration skipped for rule enforcement");return[r,e,s.context]}.bind(this)}}function ve(t,e){return V.for(nt.MIGRATION).define({decorator:(t,e)=>r=>{const s=H.innerGet(Symbol.for(nt.MIGRATION),t)||[];return H.set(nt.MIGRATION,t,[...s,{class:r}]),tt(nt.MIGRATION,{flavour:t,rules:e})(r)},args:[t,e]}).apply()}class xe extends j{constructor(t){super(t)}}i([se(),n("design:type",Date)],xe.prototype,"createdAt",void 0),i([ie(),n("design:type",Date)],xe.prototype,"updatedAt",void 0);const Ae={type:void 0,generated:!1,startWith:0,incrementBy:1,cycle:!1},Ee=Ae,Oe={type:"Number",generated:!0,startWith:0,incrementBy:1,cycle:!1},Se=Object.assign({},Oe,{type:"BigInt"});async function Ne(t,e,r,s){if(!e.type||!e.generated||s[r])return;let i;e.name||(e.name=j.sequenceName(s,"pk"));try{i=await this.adapter.Sequence(e)}catch(t){throw new o(`Failed to instantiate Sequence ${e.name}: ${t}`)}var n,a,c;n=s,a=r,c=await i.next(t),Reflect.set(n,a,c)}function _e(t,e){return(r,s)=>{switch(rt()(r,s),t.type){case void 0:{const e=H.type(r.constructor,s);if(![Number.name,String.name,BigInt.name].includes(e?.name||e))throw Error("Incorrrect option type");t.type=e;break}case String.name||String.name.toLowerCase():case String:t.generated=!1,t.type=String;break;case Number.name||String.name.toLowerCase():case Number:t.generated=!0,t.type=Number;break;case BigInt.name||BigInt.name.toLowerCase():case BigInt:t.type=BigInt,t.generated=!0;break;case"uuid":case"serial":t.generated=!0;break;default:throw Error("Unsupported type")}void 0===t.generated&&(t.generated=!0);const i=[Xt([At.ASC,At.DSC]),M(),T(),et(H.key(_.ID,s),t),A(Ne,t,e)];return t.generated&&i.push(le()),W(...i)(r,s)}}function Ce(t=Ee){return t=Object.assign({},Ee,t),V.for(_.ID).define({decorator:_e,args:[t,{priority:60}]}).apply()}let Te=class extends xe{constructor(t){super(t)}};i([Ce({type:"String",generated:!1}),n("design:type",String)],Te.prototype,"id",void 0),i([M(),Xt(),n("design:type",Object)],Te.prototype,"current",void 0),Te=i([Jt("??sequence"),Q(),n("design:paramtypes",[Object])],Te);class Be extends dt{static{this.lock=new st}constructor(t,e){super(),this.options=t,this.adapter=e,this.repo=Pt.forModel(Te,e.alias)}async current(...t){const e=(await ct.args(l.READ,Te,t,this.adapter)).context,{name:r,startWith:s}=this.options;try{const t=await this.repo.read(r,e);return this.parse(t.current)}catch(t){const i=e.logger.for(this.current);if(t instanceof y){if(i.debug(`Sequence.current missing ${r}, returning startWith=${s}`),void 0===s)throw new o("Starting value is not defined for a non existing sequence");try{return this.parse(s)}catch(t){throw new o(`Failed to parse initial value for sequence ${s}: ${t}`)}}throw new o(`Failed to retrieve current value for sequence ${r}: ${t}`)}}async increment(t,e){const r=e.logger.for(this.increment),{type:s,incrementBy:i,name:n}=this.options;if(!n)throw new o("Sequence name is required");return Be.lock.execute(async()=>{const a=t||i;if(a%i!==0)throw new o("Value to increment does not consider the incrementBy setting: "+i);const c="function"==typeof s&&s?.name?s.name:s,l=await this.current(e),h=async t=>{try{return await this.repo.update(new Te({id:n,current:t}),e)}catch(s){if(s instanceof y)return r.debug(`Sequence create ${n} current=${l} next=${t}`),this.repo.create(new Te({id:n,current:t}),e);throw s}};if("uuid"===c)for(;;){const t=ye.instance.generate(l);try{const e=await h(t);return r.debug(`Sequence uuid increment ${n} current=${l} next=${t}`),e.current}catch(t){if(t instanceof b)continue;throw t}}const u=(t=>{switch(c){case Number.name:return this.parse(t)+a;case BigInt.name:return this.parse(t)+BigInt(a);case String.name:return this.parse(t);case"serial":return me.instance.generate(t);default:throw new o("Should never happen")}})(l),d=await h(u);return r.debug(`Sequence.increment ${n} current=${l} next=${u}`),d.current},n)}async next(...t){const e=await ct.args(l.UPDATE,Te,t,this.adapter),{context:r}=e;return this.increment(void 0,r)}async range(t,...e){const r=await ct.args(l.UPDATE,Te,e,this.adapter),{context:s,args:i}=r,n=await this.current(...i),a=this.parse(this.options.incrementBy),c=await this.increment(this.parse(t)*a,s),h=[];for(let e=1;t>=e;e++)h.push(n+a*this.parse(e));if("uuid"===this.options.type||"serial"===this.options.type)throw new lt(`type ${this.options.type} is currently not suppported for this adapter`);const u="function"==typeof this.options.type&&