miragejs-orm 0.1.0 → 1.0.0
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/README.md +1780 -9
- package/lib/dist/index.cjs +4 -4
- package/lib/dist/index.cjs.map +1 -1
- package/lib/dist/index.d.cts +1928 -1450
- package/lib/dist/index.d.ts +1928 -1450
- package/lib/dist/index.js +4 -4
- package/lib/dist/index.js.map +1 -1
- package/package.json +30 -27
package/lib/dist/index.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
var h=class extends Error{constructor(e){super(`[Mirage]: ${e}`)}};var R=class{_config;constructor(e){this._config={prefix:"[Mirage]",...e}}debug(e,t){this._log("debug",e,t)}info(e,t){this._log("info",e,t)}warn(e,t){this._log("warn",e,t)}error(e,t){this._log("error",e,t)}_log(e,t,i){if(!this._config.enabled||Z[e]<Z[this._config.level])return;let s=this._config.prefix,o=e.toUpperCase(),a=`${s} ${o}: ${t}`;switch(e){case"debug":case"info":console.log(a,i||"");break;case"warn":console.warn(a,i||"");break;case"error":console.error(a,i||"");break}}},Z={debug:0,info:1,warn:2,error:3,silent:4};var x=class{_counter;_idGenerator;_initialCounter;_usedIds;constructor(e){this._initialCounter=e.initialCounter,this._counter=this._initialCounter,this._usedIds=e.initialUsedIds?new Set(e.initialUsedIds):new Set,this._idGenerator=e.idGenerator??this.getDefaultGenerator()}get(){let e=this._counter;for(;this._usedIds.has(e);)e=this._idGenerator(e);return e}fetch(){let e=this.get();return this._usedIds.add(e),this._counter=this._idGenerator(e),e}set(e){this._usedIds.add(e)}inc(){this._counter=this._idGenerator(this._counter)}reset(){this._counter=this._initialCounter,this._usedIds.clear()}getDefaultGenerator(){if(typeof this._initialCounter=="string"){if(isNaN(Number(this._initialCounter)))throw new h("Default ID generator only works with numeric string IDs");return e=>{if(isNaN(Number(e)))throw new h("Default ID generator only works with numeric string IDs");return String(Number(e)+1)}}else{if(typeof this._initialCounter=="number")return e=>e+1;throw new h("Unknown ID type. Please provide a custom idGenerator.")}}},C=class extends x{constructor(e){super({initialCounter:"1",...e})}},q=class extends x{constructor(e){super({initialCounter:1,...e})}};var I=class{query(e,t){let i=e,{cursor:s,limit:o,offset:a,orderBy:r,where:l}=t;if(l)if(typeof l=="function"){let n=this._buildWhereHelpers();i=i.filter(d=>l(d,n))}else i=i.filter(n=>this.matchesWhere(n,l));if(r&&(i=this._applyOrder(i,r)),s&&r&&(i=this._applyCursor(i,r,s)),typeof a=="number"&&a>0&&(i=i.slice(a)),typeof o=="number"){if(o===0)return[];o>0&&(i=i.slice(0,o))}return i}matchesPredicateObject(e,t){return Object.entries(t).every(([i,s])=>String(e[i])===String(s))}matchesWhere(e,t){let{AND:i,OR:s,NOT:o,...a}=t;for(let r in a){let l=e[r],n=a[r];if(n!==null&&typeof n=="object"&&!Array.isArray(n)){if(!this._matchesField(l,n))return!1}else if(l!==n)return!1}return!(Array.isArray(i)&&!i.every(r=>this.matchesWhere(e,r))||Array.isArray(s)&&!s.some(r=>this.matchesWhere(e,r))||o&&this.matchesWhere(e,o))}_matchesField(e,t){if("eq"in t&&e!==t.eq||"ne"in t&&e===t.ne||"in"in t&&t.in&&!t.in.includes(e)||"nin"in t&&t.nin&&t.nin.includes(e))return!1;if("isNull"in t){let i=e==null;if(t.isNull&&!i||!t.isNull&&i)return!1}if("lt"in t&&t.lt!=null&&!this._compareValues(e,t.lt,"<")||"lte"in t&&t.lte!=null&&!this._compareValues(e,t.lte,"<=")||"gt"in t&&t.gt!=null&&!this._compareValues(e,t.gt,">")||"gte"in t&&t.gte!=null&&!this._compareValues(e,t.gte,">="))return!1;if("between"in t&&t.between&&Array.isArray(t.between)&&t.between.length===2){let[i,s]=t.between;if(!this._compareValues(e,i,">=")||!this._compareValues(e,s,"<="))return!1}if("like"in t&&typeof t.like=="string"&&!this._likeToRegex(t.like,!1).test(String(e))||"ilike"in t&&typeof t.ilike=="string"&&!this._likeToRegex(t.ilike,!0).test(String(e))||"startsWith"in t&&typeof t.startsWith=="string"&&!String(e).startsWith(t.startsWith)||"endsWith"in t&&typeof t.endsWith=="string"&&!String(e).endsWith(t.endsWith)||"contains"in t&&t.contains&&typeof t.contains=="string"&&!String(e).includes(t.contains))return!1;if("contains"in t&&Array.isArray(e)){let i=t.contains;if(Array.isArray(i)){if(!i.every(s=>e.includes(s)))return!1}else if(!e.includes(i))return!1}return!("length"in t&&t.length&&Array.isArray(e)&&!this._matchesField(e.length,t.length))}_compareValues(e,t,i){if(e==null||t==null)return!1;if(e instanceof Date&&t instanceof Date){let s=e.getTime(),o=t.getTime();switch(i){case"<":return s<o;case"<=":return s<=o;case">":return s>o;case">=":return s>=o}}switch(i){case"<":return e<t;case"<=":return e<=t;case">":return e>t;case">=":return e>=t}}_likeToRegex(e,t){let s="^"+e.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/%/g,".*")+"$";return new RegExp(s,t?"i":"")}_applyOrder(e,t){let i=Array.isArray(t)?t:(()=>{let s=[];for(let o in t){let a=t[o];a&&s.push([o,a])}return s})();return[...e].sort((s,o)=>{for(let[a,r]of i){let l=s[a],n=o[a];if(!(l==null&&n==null)){if(l==null)return 1;if(n==null)return-1;if(l instanceof Date&&n instanceof Date){let d=l.getTime()-n.getTime();if(d!==0)return r==="desc"?-d:d;continue}if(l<n)return r==="desc"?1:-1;if(l>n)return r==="desc"?-1:1}}return 0})}_applyCursor(e,t,i){let s=Array.isArray(t)?t:(()=>{let o=[];for(let a in t){let r=t[a];r&&o.push([a,r])}return o})();return e.filter(o=>{for(let[a,r]of s){let l=o[a],n=i[a];if(n!==void 0&&!(l==null&&n==null)){if(l==null)return!1;if(n==null)return!0;if(l instanceof Date&&n instanceof Date){let d=l.getTime()-n.getTime();if(d===0)continue;return r==="desc"?d<0:d>0}if(l!==n){if(l<n)return r==="desc";if(l>n)return r==="asc"}}}return!1})}_buildWhereHelpers(){return{and:(...e)=>e.every(t=>t),or:(...e)=>e.some(t=>t),not:e=>!e,eq:(e,t)=>e===t,ne:(e,t)=>e!==t,gt:(e,t)=>e!=null&&t!=null&&e>t,gte:(e,t)=>e!=null&&t!=null&&e>=t,lt:(e,t)=>e!=null&&t!=null&&e<t,lte:(e,t)=>e!=null&&t!=null&&e<=t,between:(e,t,i)=>e!=null&&t!=null&&i!=null&&e>=t&&e<=i,like:(e,t)=>this._likeToRegex(t,!1).test(String(e)),ilike:(e,t)=>this._likeToRegex(t,!0).test(String(e)),startsWith:(e,t)=>String(e).startsWith(t),endsWith:(e,t)=>String(e).endsWith(t),containsText:(e,t)=>String(e).includes(t),inArray:(e,t)=>t.some(i=>i===e),notInArray:(e,t)=>!t.some(i=>i===e),isNull:e=>e==null,isNotNull:e=>e!=null}}};var b=class{name;identityManager;_records=new Map;_queryManager=new I;constructor(e,t){this.name=e,this.identityManager=t?.identityManager??new C,t?.initialData&&this.insertMany(t.initialData)}get nextId(){return this.identityManager.fetch()}get size(){return this._records.size}get isEmpty(){return this._records.size===0}all(){return Array.from(this._records.values())}at(e){return this.all()[e]}first(){return this.all()[0]}last(){let e=this.all();return e[e.length-1]}has(e){return this._records.has(e)}find(e){if(typeof e=="string"||typeof e=="number")return this._records.get(e)??null;if(typeof e=="object"&&("where"in e||"orderBy"in e||"cursor"in e||"offset"in e||"limit"in e))return this._queryManager.query(this.all(),{...e,limit:1})[0]??null;let i=e;return this.all().find(s=>this._queryManager.matchesPredicateObject(s,i))??null}findMany(e){if(Array.isArray(e))return e.map(s=>this._records.get(s)).filter(Boolean);if(typeof e=="object"&&("where"in e||"orderBy"in e||"cursor"in e||"offset"in e||"limit"in e)){let s=e;return this._queryManager.query(this.all(),s)}let i=e;return this.all().filter(s=>this._queryManager.matchesPredicateObject(s,i))}count(e){return e?this._queryManager.query(this.all(),{where:e}).length:this.size}exists(e){return e?this._queryManager.query(this.all(),{where:e,limit:1}).length>0:!this.isEmpty}insert(e){let t=this._prepareRecord(e);return this._records.set(t.id,t),t}insertMany(e){return e.map(t=>this.insert(t))}update(e,t){let i=this._records.get(e);if(!i)return null;let s={...i,...t};return this._records.set(e,s),s}updateMany(e,t){return this.findMany(e).map(o=>{let a={...o,...t};return this._records.set(o.id,a),a})}delete(e){return this._records.delete(e)}deleteMany(e){let t=this.findMany(e);return t.forEach(i=>this.delete(i.id)),t.length}clear(){this._records.clear(),this.identityManager.reset()}_prepareRecord(e){let t={...e};return t.id?this.identityManager.set(t.id):t.id=this.identityManager.fetch(),t}};var O=class{_collections=new Map;constructor(e={}){let{initialData:t}=e;t&&this.loadData(t),this.initCollectionAccessors()}hasCollection(e){return this._collections.has(e)}createCollection(e,t){let i=String(e);if(this._collections.has(i))throw new h(`Collection ${i} already exists`);let s=new b(i,{identityManager:t?.identityManager,initialData:t?.initialData});return this._collections.set(i,s),this.initCollectionAccessors(),this}getCollection(e){let t=this._collections.get(e);if(!t)throw new h(`Collection ${String(e)} does not exist`);return t}identityManagerFor(e){return this.getCollection(e).identityManager}loadData(e){for(let t in e){let i=e[t],s=t;this.hasCollection(s)?this.getCollection(s).insertMany(i):this.createCollection(s,{initialData:i})}return this}emptyData(){this._collections.forEach(e=>e.clear())}dump(){let e={};return this._collections.forEach((t,i)=>{e[i]=t.all()}),e}initCollectionAccessors(){this._collections.forEach((e,t)=>{Object.prototype.hasOwnProperty.call(this,t)||Object.defineProperty(this,t,{get:()=>e,enumerable:!0,configurable:!0})})}};function H(c){return new O(c)}var w=class{modelName;collectionName;_attrs;_dbCollection;_serializer;_status;constructor(e,t,i,s,o){this.modelName=e,this.collectionName=t,this._attrs={...i,id:i.id??null},this._dbCollection=s??new b(t),this._serializer=o,this._status=this._checkStatus()}get id(){return this._attrs.id}get attrs(){return{...this._attrs}}save(){if(this.isNew()||!this.id){let e=this._dbCollection.insert(this._attrs);this._attrs=e,this._status="saved"}else this._dbCollection.update(this.id,this._attrs);return this}update(e){return Object.assign(this._attrs,e),this.save()}reload(){if(this._attrs.id){let e=this._dbCollection.find(this.id);e&&(this._attrs=e,this._status="saved")}else return this.save();return this}destroy(){return this.isSaved()&&this.id&&(this._dbCollection.delete(this.id),this._attrs={...this._attrs,id:null},this._status="new"),this}isNew(){return this._status==="new"}isSaved(){return this._status==="saved"}toJSON(){return this._serializer&&typeof this._serializer=="object"&&"serialize"in this._serializer&&typeof this._serializer.serialize=="function"?this._serializer.serialize(this):{...this._attrs}}toString(){let e=this.id?`(${this.id})`:"";return`model:${this.modelName}${e}`}_checkStatus(){return this.id&&this._dbCollection.find(this.id)?"saved":"new"}};var f=class c{_template;collectionName;models;_serializer;constructor(e,t,i){this._template=e,this._serializer=i,this.collectionName=e.collectionName,this.models=[...t??[]]}get length(){return this.models.length}get isEmpty(){return this.models.length===0}at(e){return this.models[e]}first(){return this.models[0]||null}last(){return this.models[this.models.length-1]||null}forEach(e){this.models.forEach((t,i)=>e(t,i,this))}map(e){let t=this.models.map((i,s)=>e(i,s,this));return new c(this._template,t,this._serializer)}filter(e){let t=this.models.filter((i,s)=>e(i,s,this));return new c(this._template,t,this._serializer)}find(e){return this.models.find((t,i)=>e(t,i,this))}some(e){return this.models.some((t,i)=>e(t,i,this))}every(e){return this.models.every((t,i)=>e(t,i,this))}concat(...e){let t=[...this.models,...e.flatMap(i=>Array.isArray(i)?i:i.models)];return new c(this._template,t,this._serializer)}includes(e){return this.models.includes(e)}indexOf(e){return this.models.indexOf(e)}sort(e){let t=[...this.models].sort(e);return new c(this._template,t,this._serializer)}reverse(){let e=[...this.models].reverse();return new c(this._template,e,this._serializer)}add(e){this.models.push(e)}remove(e){let t=this.indexOf(e);return t!==-1?(this.models.splice(t,1),!0):!1}save(){return this.models=this.models.map(e=>e.save()),this}destroy(){return this.models.forEach(e=>e.destroy()),this.models=[],this}reload(){return this.models=this.models.map(e=>e.reload()),this}update(e){return this.models=this.models.map(t=>t.update(e)),this}toArray(){return[...this.models]}toString(){return`collection:${this.collectionName}(${this.models.map(e=>e.toString()).join(", ")})`}toJSON(){return this._serializer&&typeof this._serializer=="object"&&"serializeCollection"in this._serializer&&typeof this._serializer.serializeCollection=="function"?this._serializer.serializeCollection(this):this.models.map(e=>e.attrs)}[Symbol.iterator](){return this.models[Symbol.iterator]()}};function u(c){return c!==null&&typeof c=="object"&&"id"in c&&"modelName"in c}function Y(c){return Array.isArray(c)&&c.every(e=>u(e))}function S(c){return c!==null&&typeof c=="object"&&"models"in c&&Array.isArray(c.models)}function z(c){return Array.isArray(c)}var N=class{isApplyingPendingUpdates=!1;_model;_pendingRelationshipOperations=[];_relationshipDefs;_inverseMap=new Map;_schema;constructor(e,t,i){this._model=e,this._schema=t,this._relationshipDefs=this._parseRelationshipDefs(i)}get relationshipDefs(){return this._relationshipDefs}get schema(){return this._schema}setPendingRelationshipUpdates(e){for(let t in e){let i=this._relationshipDefs?.[t];if(!i)continue;let s=i.relationship,{foreignKey:o,type:a,targetModel:r}=s,l=e[t],n=l;if(typeof l=="string"||typeof l=="number"||z(l)&&l.every(m=>typeof m=="string"||typeof m=="number")){let m=this._schema.getCollection(r.collectionName);if(a==="belongsTo"){let p=l;n=m.find(p)}else if(a==="hasMany"){let g=l.map(M=>m.find(M)).filter(M=>u(M));n=new f(r,g)}}let d=this._getForeignKeyValue(o),T=this._extractForeignKeyFromValue(s,n),y=this._hasForeignKeyChanged(d,T);if(this._model.isSaved()){if(y){let m=this.related(t);this._pendingRelationshipOperations.push({relationshipName:t,link:!1,unlink:!0,value:m})}this._hasForeignKeyValue(T)&&this._pendingRelationshipOperations.push({relationshipName:t,link:!0,unlink:!1,value:n})}else this._model.isNew()&&this._hasForeignKeyValue(T)&&this._pendingRelationshipOperations.push({relationshipName:t,link:!0,unlink:!1,value:n})}}applyPendingInverseUpdates(){if(this._pendingRelationshipOperations.length!==0){this.isApplyingPendingUpdates=!0;try{for(let e of this._pendingRelationshipOperations)e.unlink&&e.value!==void 0&&(u(e.value)?this._updateInverseRelationship(e.relationshipName,e.value,"unlink"):S(e.value)&&e.value.models.forEach(t=>{this._updateInverseRelationship(e.relationshipName,t,"unlink")}));for(let e of this._pendingRelationshipOperations)if(e.link&&e.value!==void 0){if(!this._relationshipDefs?.[e.relationshipName])continue;u(e.value)?this._updateInverseRelationship(e.relationshipName,e.value,"link"):S(e.value)?e.value.models.forEach(i=>{this._updateInverseRelationship(e.relationshipName,i,"link")}):z(e.value)&&e.value.filter(s=>u(s)).forEach(s=>{this._updateInverseRelationship(e.relationshipName,s,"link")})}this._pendingRelationshipOperations=[]}finally{this.isApplyingPendingUpdates=!1}}}link(e,t){let i={},s=String(e);if(!this._relationshipDefs||!this._schema)return{foreignKeyUpdates:i};let o=this._getRelationshipDef(s);if(!o)return{foreignKeyUpdates:i};let a=o.relationship,{type:r,foreignKey:l}=a;if(r==="belongsTo"){let n=this._getForeignKeyValue(l),d=u(t)?t.id:null;if(n&&n!==d){let T=a.targetModel.collectionName,m=this._schema.getCollection(T).find(n);m&&u(m)&&this._updateInverseRelationship(s,m,"unlink")}i[l]=d,u(t)&&this._updateInverseRelationship(s,t,"link")}else if(r==="hasMany"){let n=[],d=[];S(t)?(d=t.models,n=d.map(p=>p.id)):z(t)&&(d=t.filter(p=>u(p)),n=d.map(p=>p.id));let T=this._getForeignKeyValue(l),y=this._extractIdsArray(T),m=y.length!==n.length||!y.every((p,g)=>p===n[g]);if(y.length>0&&m){let p=a.targetModel.collectionName,g=this._schema.getCollection(p);y.forEach(M=>{let F=g.find(M);F&&u(F)&&this._updateInverseRelationship(s,F,"unlink")})}i[l]=n,d.forEach(p=>{this._updateInverseRelationship(s,p,"link")})}return{foreignKeyUpdates:i}}unlink(e,t){let i={},s=String(e);if(!this._relationshipDefs||!this._schema)return{foreignKeyUpdates:i};let o=this._getRelationshipDef(s);if(!o)return{foreignKeyUpdates:i};let a=o.relationship,{type:r,foreignKey:l}=a;if(r==="belongsTo"){let n=this.related(s);i[l]=null,u(n)&&this._updateInverseRelationship(s,n,"unlink")}else if(r==="hasMany")if(t){let n=this._extractIdsArray(this._getForeignKeyValue(l)),d=[];u(t)?d=[t]:S(t)?d=t.models:z(t)&&(d=t.filter(m=>u(m)));let T=new Set(d.map(m=>m.id)),y=n.filter(m=>!T.has(m));i[l]=y,d.forEach(m=>{this._updateInverseRelationship(s,m,"unlink")})}else{let n=this.related(s);i[l]=[],S(n)&&n.models.forEach(d=>{this._updateInverseRelationship(s,d,"unlink")})}return{foreignKeyUpdates:i}}related(e){if(!this._schema||!this._relationshipDefs)return null;let t=this._getRelationshipDef(e);if(!t)return null;let i=t.relationship,{type:s,foreignKey:o,targetModel:a}=i,r=this._schema.getCollection(a.collectionName);if(!r)throw new h(`Collection for model ${a.modelName} not found in schema`);if(s==="belongsTo"){let l=this._getForeignKeyValue(o),n=this._extractSingleId(l);return n===null?null:r.find(n)}if(s==="hasMany"){let l=this._getForeignKeyValue(o),n=this._extractIdsArray(l);if(n.length===0)return new f(a,[]);let d=n.map(T=>r.find(T)).filter(T=>T!==null);return new f(a,d)}return null}_getRelationshipDef(e){if(this._relationshipDefs)return this._relationshipDefs[e]}_getModelAttrs(){return this._model.attrs}_getForeignKeyValue(e){return this._getModelAttrs()[e]}_extractSingleId(e){return e==null||Array.isArray(e)?null:e}_extractIdsArray(e){return Array.isArray(e)?e:[]}_parseRelationshipDefs(e){if(!e||!this._schema)return;let t={};for(let i in e){let s=e[i],o={relationship:s};"inverse"in s&&this._inverseMap.set(i,s.inverse);let a="inverse"in s?s.inverse:void 0;if(a===null)o.inverse=void 0;else if(typeof a=="string"){let r=s.targetModel.collectionName,l=this._schema.getCollection(r);if(l.relationships&&l.relationships[a]){let n=l.relationships[a];o.inverse={foreignKey:n.foreignKey,relationshipName:a,targetModel:s.targetModel,type:n.type}}}else{let r=s.targetModel.collectionName,l=this._schema.getCollection(r);if(l.relationships)for(let n in l.relationships){let d=l.relationships[n];if(d.targetModel.modelName===this._model.modelName){o.inverse={foreignKey:d.foreignKey,relationshipName:n,targetModel:s.targetModel,type:d.type};break}}}t[i]=o}return t}_updateInverseRelationship(e,t,i){if(!this._relationshipDefs||!this._schema)return;let s=this._relationshipDefs[e];if(!s?.inverse)return;let o=this._model.id;if(!o)return;let{inverse:a}=s,{type:r,foreignKey:l,relationshipName:n}=a,d=t._relationshipsManager;if(d?._inverseMap.has(n)&&d._inverseMap.get(n)===null)return;let T=t.id;if(!T)return;let y=s.relationship.targetModel.collectionName,m=this._schema.db.getCollection(y).find(T);if(!m)return;let p={};if(r==="hasMany"){let g=m[l],M=this._extractIdsArray(g);i==="link"?M.includes(o)||(p[l]=[...M,o]):p[l]=M.filter(F=>F!==o)}else r==="belongsTo"&&(p[l]=i==="link"?o:null);Object.keys(p).length>0&&this._schema.db.getCollection(y).update(T,p)}_extractForeignKeyFromValue(e,t){let{type:i}=e;return i==="belongsTo"?u(t)?t.id:null:i==="hasMany"?S(t)?t.models.map(s=>s.id):z(t)?t.filter(s=>u(s)).map(s=>s.id):[]:null}_hasForeignKeyValue(e){return e==null?!1:Array.isArray(e)?e.length>0:!0}_hasForeignKeyChanged(e,t){return!this._hasForeignKeyValue(e)&&!this._hasForeignKeyValue(t)?!1:!this._hasForeignKeyValue(e)||!this._hasForeignKeyValue(t)?!0:Array.isArray(e)&&Array.isArray(t)?!this._arraysEqual(e,t):e!==t}_arraysEqual(e,t){return e.length!==t.length?!1:e.every((i,s)=>i===t[s])}};var A=class c extends w{relationships;_relationshipsManager;constructor(e,t){let{attrs:i,relationships:s,schema:o,serializer:a}=t,r=o.db.getCollection(e.collectionName),{modelAttrs:l,relationshipUpdates:n}=c._processAttrs(i,s);super(e.modelName,e.collectionName,l,r,a),this.relationships=s,o&&s?(this._relationshipsManager=new N(this,o,s),this._status==="new"&&Object.keys(n).length>0&&this._relationshipsManager.setPendingRelationshipUpdates(n),this._initAttributeAccessors(),this._initForeignKeys(),this._initRelationshipAccessors()):this._initAttributeAccessors()}static define(e){return class extends c{constructor(t){super(e,t)}}}save(){return super.save(),this._relationshipsManager&&this._relationshipsManager.applyPendingInverseUpdates(),this}update(e){let{modelAttrs:t,relationshipUpdates:i}=c._processAttrs(e,this.relationships);return this._relationshipsManager&&Object.keys(i).length>0&&this._relationshipsManager.setPendingRelationshipUpdates(i),super.update(t)}reload(){return super.reload()}destroy(){return super.destroy()}link(e,t){if(this._relationshipsManager){let i=this._relationshipsManager.link(e,t);Object.assign(this._attrs,i.foreignKeyUpdates),this.isSaved()&&this.save()}return this}unlink(e,t){if(this._relationshipsManager){let i=this._relationshipsManager.unlink(e,t);Object.assign(this._attrs,i.foreignKeyUpdates),this.isSaved()&&this.save()}return this}related(e){return this._relationshipsManager?.related(e)??null}static _extractForeignKey(e,t){let{type:i}=e;return i==="belongsTo"?u(t)?t.id:null:i==="hasMany"?Y(t)?t.map(s=>s.id):S(t)?t.models.map(s=>s.id):[]:null}static _separateAttrs(e,t){let i={},s={},o={};for(let a in t){let r=t[a],{type:l,foreignKey:n}=r;o[n]=l==="belongsTo"?null:[]}for(let a in e){let r=e[a];if(a in t){let l=t[a];s[a]=r;let n=c._extractForeignKey(l,r);n!==null&&(o[l.foreignKey]=n)}else{let l=!1;for(let n in t)if(t[n].foreignKey===a){l=!0,o[a]=r,s[n]=r;break}l||(i[a]=r)}}return{regularAttrs:i,relationshipValues:s,foreignKeys:o}}static _processAttrs(e,t){if(!t)return{modelAttrs:e,relationshipUpdates:{}};let{regularAttrs:i,relationshipValues:s,foreignKeys:o}=c._separateAttrs(e,t);return{modelAttrs:{...o,...i},relationshipUpdates:s}}_initAttributeAccessors(){for(let e in this._attrs)e!=="id"&&Object.hasOwn(this,e)&&delete this[e];for(let e in this._attrs){let t=e;t!=="id"&&!Object.hasOwn(this,t)&&Object.defineProperty(this,e,{get:()=>this._attrs[t],set:i=>{this._attrs[t]=i},enumerable:!1,configurable:!0})}}_initForeignKeys(){if(this._relationshipsManager?.relationshipDefs)for(let e in this._relationshipsManager.relationshipDefs){let t=e,i=this._relationshipsManager.relationshipDefs[t],{foreignKey:s,type:o}=i.relationship;s in this._attrs||(o==="belongsTo"?this._attrs[s]=null:o==="hasMany"&&(this._attrs[s]=[]))}}_initRelationshipAccessors(){if(this._relationshipsManager?.relationshipDefs)for(let e in this._relationshipsManager.relationshipDefs){let t=e;Object.hasOwn(this,t)||Object.defineProperty(this,t,{get:()=>this.related(t),set:i=>{this.link(t,i)},enumerable:!1,configurable:!0})}}};var K=class c{_modelName;_collectionName;name(e){if(!e||typeof e!="string"||e.trim()==="")throw new h("Model name must be a non-empty string.");let t=new c;return t._modelName=e,t._collectionName=this._collectionName,t}collection(e){if(!e||typeof e!="string"||e.trim()==="")throw new h("Collection name must be a non-empty string.");let t=new c;return t._modelName=this._modelName,t._collectionName=e,t}attrs(){let e=new c;return e._modelName=this._modelName,e._collectionName=this._collectionName,e}json(){let e=new c;return e._modelName=this._modelName,e._collectionName=this._collectionName,e}create(){if(!this._modelName)throw new h("Model name is required. Call .name() before .create()");if(!this._collectionName)throw new h("Collection name is required. Call .collection() before .create()");return{key:Symbol(`Model:${this._modelName}`),modelName:this._modelName,collectionName:this._collectionName,__attrs:void 0,__json:void 0}}};function X(){return new K}var v=class{processAssociations(e,t,i){let s={},o=new Set(i||[]);for(let a in t){let r=t[a];if(!r||o.has(a))continue;let l=r.model.collectionName,n=e.getCollection(l);if(!n)throw new h(`Collection '${l}' not found in schema during associations processing`);switch(r.type){case"create":s[a]=this._processCreate(n,r.traitsAndDefaults);break;case"createMany":s[a]=this._processCreateMany(n,r.count,r.traitsAndDefaults);break;case"link":s[a]=this._processLink(n,r.query,r.traitsAndDefaults);break;case"linkMany":s[a]=this._processLinkMany(n,r.model,r.count,r.query,r.traitsAndDefaults);break}}return s}_processCreate(e,t){return e.create(...t??[])}_processCreateMany(e,t,i){return e.createList(t,...i??[])}_processLink(e,t,i){let s=null;if(t){let o=typeof t=="function"?e.findMany({where:t}):e.findMany(t);o.length>0&&(s=this._shuffle(o.models)[0])}else{let o=e.all();o.length>0&&(s=this._shuffle(o.models)[0])}return s||(s=e.create(...i??[])),s}_processLinkMany(e,t,i,s,o){let a;s?a=typeof s=="function"?e.findMany({where:s}):e.findMany(s):a=e.all();let r=this._shuffle(a.models),l=i-r.length;if(l>0){let n=e.createList(l,...o??[]),d=[...r,...n.models];return new f(t,d)}else{let n=r.slice(0,i);return new f(t,n)}}_shuffle(e){let t=[...e];for(let i=t.length-1;i>0;i--){let s=Math.floor(Math.random()*(i+1));[t[i],t[s]]=[t[s],t[i]]}return t}};var D=class{attributes;traits;associations;afterCreate;_template;_associationsManager;constructor(e,t,i={},s,o){this._template=e,this.attributes=t,this.traits=i,this.associations=s,this.afterCreate=o,this._associationsManager=new v}get template(){return this._template}build(e,...t){let i=[],s={};t.forEach(l=>{typeof l=="string"?i.push(l):Object.assign(s,l)});let o=this._processAttributes(this.attributes,e),a=this._buildWithTraits(i,e);return{...this._mergeAttributes(o,a),...s,id:e}}processAssociations(e,t,i){let o={...this._getTraitAssociations(i),...this.associations||{}};return Object.keys(o).length===0?{}:this._associationsManager.processAssociations(e,o,t)}processAfterCreateHooks(e,t,...i){let s=i.filter(a=>typeof a=="string"),o=[];return this.afterCreate&&o.push(this.afterCreate),s.forEach(a=>{let r=this.traits[a];r?.afterCreate&&o.push(r.afterCreate)}),o.forEach(a=>{a(t,e)}),t}_processAttributes(e,t){let i=e;return this._sortAttrs(i,t).reduce((a,r)=>{let l=i[r];return typeof l=="function"?{...a,[r]:l.call(e,t)}:a},i)}_buildWithTraits(e,t){return e.reduce((s,o)=>{let a=this.traits[o];if(a){let{afterCreate:r,...l}=a;for(let n in l){let d=l[n];n!=="id"&&!this._isAssociation(d)&&(s[n]=typeof d=="function"?d.call(this.attributes,t):d)}}return s},{})}_isAssociation(e){return typeof e=="object"&&e!==null&&"type"in e&&"model"in e&&["create","createMany","link","linkMany"].includes(e.type)}_getTraitAssociations(e){if(!e)return{};let t=e.filter(s=>typeof s=="string"),i={};return t.forEach(s=>{let o=this.traits[s];if(o)for(let a in o){let r=o[a];this._isAssociation(r)&&(i[a]=r)}}),i}_mergeAttributes(e,t){return{...e,...t}}_sortAttrs(e,t){let i=new Set,s=new Set,o=a=>{if(s.has(a))throw new h(`Circular dependency detected: ${String(a)}`);if(i.has(a))return!1;s.add(a);let r=e[a];if(typeof r=="function"){let l=new Proxy(e,{get(n,d){return typeof d=="string"&&d in n&&o(d),n[d]}});r.call(l,t)}return s.delete(a),i.add(a),!1};return Object.keys(e).forEach(o),Object.keys(e)}};var $=class c{_template;_attributes={};_traits={};_associations;_afterCreate;constructor(){}model(e){let t=new c;return t._template=e,t}attrs(e){return this._attributes={...this._attributes,...e},this}traits(e){let t=new c;return t._template=this._template,t._attributes=this._attributes,t._traits={...this._traits,...e},t._afterCreate=this._afterCreate,t._associations=this._associations,t}afterCreate(e){return this._afterCreate=e,this}associations(e){return this._associations=e,this}extend(e){let t=new c;return t._template=e.template,t._attributes={...e.attributes},t._traits={...e.traits},t._associations={...e.associations},t._afterCreate=e.afterCreate,t}create(){if(!this._template)throw new h("Model template must be set before creating factory. Call .model() first.");return new D(this._template,this._attributes,this._traits,this._associations,this._afterCreate)}};function ee(){return new $}function P(c,e){let t=`${c.modelName}Id`;return{foreignKey:e?.foreignKey??t,targetModel:c,type:"belongsTo",inverse:e?.inverse}}function B(c,...e){return{type:"create",model:c,traitsAndDefaults:e.length>0?e:void 0}}function j(c,e,...t){return{type:"createMany",model:c,count:e,traitsAndDefaults:t.length>0?t:void 0}}function L(c,e){let t=`${c.modelName}Ids`;return{foreignKey:e?.foreignKey??t,targetModel:c,type:"hasMany",inverse:e?.inverse}}function E(c,e,...t){return{type:"link",model:c,query:e,traitsAndDefaults:t.length>0?t:void 0}}function V(c,e,t,...i){return{type:"linkMany",model:c,count:e,query:t,traitsAndDefaults:i.length>0?i:void 0}}var oe={belongsTo:P,hasMany:L,create:B,createMany:j,link:E,linkMany:V},te=oe;var Q=class{modelName;collectionName;Model;_template;_schema;_dbCollection;_identityManager;_logger;_factory;_relationships;_serializer;_seeds;_fixtures;constructor(e,t){let{factory:i,identityManager:s,model:o,relationships:a={},serializer:r,seeds:l,fixtures:n}=t;this.modelName=o.modelName,this.collectionName=o.collectionName,this.Model=A.define(o),this._template=o,this._schema=e,this._logger=e.logger,this._dbCollection=this._initializeDbCollection(s),this._identityManager=this._dbCollection.identityManager,this._relationships=a,this._factory=i,this._serializer=r,this._seeds=l,this._fixtures=n,this._logger?.debug(`Collection '${this.collectionName}' initialized`,{modelName:this.modelName,hasFactory:!!i,hasRelationships:!!a&&Object.keys(a).length>0,hasSeeds:!!l,hasFixtures:!!n})}get relationships(){return this._relationships}get serializer(){return this._serializer}at(e){let t=this._dbCollection.at(e);return t?this._createModelFromRecord(t):void 0}all(){this._logger?.debug(`Query '${this.collectionName}': all()`,{operation:"all"});let e=this._dbCollection.all();this._logger?.debug(`Query '${this.collectionName}' returned ${e.length} records`);let t=e.map(i=>this._createModelFromRecord(i));return new f(this._template,t,this._serializer)}first(){this._logger?.debug(`Query '${this.collectionName}': first()`);let e=this._dbCollection.first();return e&&this._logger?.debug(`Query '${this.collectionName}' found record`,{id:e.id}),e?this._createModelFromRecord(e):null}last(){this._logger?.debug(`Query '${this.collectionName}': last()`);let e=this._dbCollection.last();return e&&this._logger?.debug(`Query '${this.collectionName}' found record`,{id:e.id}),e?this._createModelFromRecord(e):null}find(e){if(this._logger?.debug(`Find in '${this.collectionName}'`,{query:typeof e=="object"&&"where"in e?"QueryOptions":e}),typeof e=="object"&&"where"in e&&typeof e.where=="function"){let i=this._convertQueryOptionsCallback(e),s=this._dbCollection.find(i);return s&&this._logger?.debug(`Find in '${this.collectionName}' found record`,{id:s.id}),s?this._createModelFromRecord(s):null}let t=this._dbCollection.find(e);return t&&this._logger?.debug(`Find in '${this.collectionName}' found record`,{id:t.id}),t?this._createModelFromRecord(t):null}findMany(e){if(this._logger?.debug(`Query '${this.collectionName}': findMany`,{query:Array.isArray(e)?`${e.length} IDs`:typeof e=="object"&&"where"in e?"QueryOptions":e}),typeof e=="object"&&"where"in e&&typeof e.where=="function"){let s=this._convertQueryOptionsCallback(e),o=this._dbCollection.findMany(s);this._logger?.debug(`Query '${this.collectionName}' returned ${o.length} records`);let a=o.map(r=>this._createModelFromRecord(r));return new f(this._template,a,this._serializer)}let t=this._dbCollection.findMany(e);this._logger?.debug(`Query '${this.collectionName}' returned ${t.length} records`);let i=t.map(s=>this._createModelFromRecord(s));return new f(this._template,i,this._serializer)}delete(e){this._logger?.debug(`Delete from '${this.collectionName}'`,{id:e}),this._dbCollection.delete(e)}deleteMany(e){if(this._logger?.debug(`Delete many from '${this.collectionName}'`,{query:Array.isArray(e)?`${e.length} IDs`:e}),typeof e=="object"&&"where"in e&&typeof e.where=="function"){let i=this._convertQueryOptionsCallback(e),s=this._dbCollection.deleteMany(i);return this._logger?.debug(`Deleted ${s} records from '${this.collectionName}'`),s}let t=this._dbCollection.deleteMany(e);return this._logger?.debug(`Deleted ${t} records from '${this.collectionName}'`),t}_convertQueryOptionsCallback(e){if(!e.where||typeof e.where!="function")return e;let t=e.where;return{...e,where:(s,o)=>{let a=this._createModelFromRecord(s);return t(a,o)}}}_createModelFromRecord(e){return new this.Model({attrs:e,relationships:this._relationships,schema:this._schema,serializer:this._serializer})}_initializeDbCollection(e){return this._schema.db.hasCollection(this.collectionName)||this._schema.db.createCollection(this.collectionName,{identityManager:e}),this._schema.db.getCollection(this._template.collectionName)}};var U=class extends Q{new(e){return new this.Model({attrs:e,relationships:this._relationships,schema:this._schema,serializer:this._serializer})}create(...e){this._logger?.debug(`Creating ${this.modelName}`,{collection:this.collectionName,traitsAndDefaults:e});let t=[],i={};e.forEach(n=>{typeof n=="string"?t.push(n):i={...i,...n}});let{modelAttrs:s,relationshipUpdates:o}=A._processAttrs(i,this._relationships),a=s.id??this._dbCollection.nextId;if(s.id&&this._identityManager?.set(s.id),this._factory){let n=this._factory.build(a,...t,s),d=Object.keys(o),T=this._factory.processAssociations(this._schema,d,e),y={...n,...T,...o},m=this.new(y).save();return this._logger?.debug(`Created ${this.modelName} with factory`,{id:m.id,collection:this.collectionName}),this._factory.processAfterCreateHooks(this._schema,m,...e)}let r={...s,...o,id:a},l=this.new(r).save();return this._logger?.debug(`Created ${this.modelName}`,{id:l.id,collection:this.collectionName}),l}createList(e,...t){let i=Array.from({length:e},()=>this.create(...t));return new f(this._template,i,this._serializer)}findOrCreateBy(e,...t){let i=this.find(e);return i||this.create(...t,e)}findManyOrCreateBy(e,t,...i){let s=typeof t=="function"?this.findMany({where:t}):this.findMany(t);if(s.length>=e)return new f(this._template,s.models.slice(0,e),this._serializer);let o=e-s.length,a=typeof t=="function"?{}:t,r=Array.from({length:o},()=>this.create(...i,a));return new f(this._template,[...s.models,...r],this._serializer)}async loadSeeds(e){if(!this._seeds){this._logger?.debug(`No seeds configured for collection '${this.collectionName}'`);return}let t=typeof this._seeds=="function"?{default:this._seeds}:this._seeds;if(!e){this._logger?.info(`Loading all seeds for collection '${this.collectionName}'`,{scenarios:Object.keys(t)});for(let i in t){let s=t[i];this._logger?.debug(`Running seed scenario '${i}' for '${this.collectionName}'`),await s(this._schema)}this._logger?.info(`Seeds loaded successfully for '${this.collectionName}'`);return}if(!(e in t)){let i=Object.keys(t).join(", ");throw this._logger?.error(`Seed scenario '${e}' not found`,{collection:this.collectionName,requested:e,available:Object.keys(t)}),new h(`Seed scenario '${e}' does not exist in collection '${this.collectionName}'. Available scenarios: ${i}`)}this._logger?.info(`Loading seed scenario '${e}' for '${this.collectionName}'`),await t[e](this._schema),this._logger?.info(`Seed scenario '${e}' loaded successfully`)}async loadFixtures(){if(!this._fixtures||!this._fixtures.records.length){this._logger?.debug(`No fixtures configured for collection '${this.collectionName}'`);return}this._logger?.info(`Loading fixtures for collection '${this.collectionName}'`,{count:this._fixtures.records.length});let e=this._fixtures.records.map(s=>s.id),t=this._dbCollection.all().map(s=>s.id),i=e.filter(s=>t.includes(s));if(i.length>0)throw this._logger?.error("Fixture loading failed: ID conflicts detected",{collection:this.collectionName,conflicts:i}),new h(`Cannot load fixtures for '${this.collectionName}': ID conflicts detected. The following fixture IDs already exist in the database: ${i.join(", ")}. Clear the database with db.emptyData() before loading fixtures, or use different IDs.`);this._dbCollection.insertMany(this._fixtures.records),this._logger?.info(`Fixtures loaded successfully for '${this.collectionName}'`,{count:this._fixtures.records.length})}};function J(c,e){return new U(c,e)}var _=class{_template;_modelName;_collectionName;_attrs;_root;_embed;_include;constructor(e,t){this._template=e,this._modelName=e.modelName,this._collectionName=e.collectionName,this._attrs=t?.attrs,this._root=t?.root,this._embed=t?.embed,this._include=t?.include}get modelName(){return this._modelName}get collectionName(){return this._collectionName}serializeData(e){let t=this._getAttributes(e);if(this._embed){let{embedded:i,foreignKeys:s}=this._getRelationships(e),o={...t};for(let a of s)delete o[a];return{...o,...i}}return t}serialize(e){let t=this.serializeData(e),{sideLoaded:i}=this._embed?{sideLoaded:{}}:this._getRelationships(e);return this._root?{[typeof this._root=="string"?this._root:this._modelName]:t,...i}:{...t,...i}}serializeCollectionData(e){return e.models.map(t=>this.serializeData(t))}serializeCollection(e){let t=this.serializeCollectionData(e),i={};if(!this._embed&&this._include)for(let s of e.models){let{sideLoaded:o}=this._getRelationships(s);for(let a in o){let r=o[a];if(i[a]||(i[a]=[]),Array.isArray(r))for(let l of r)i[a].some(n=>n.id===l.id)||i[a].push(l);else r&&!i[a].some(l=>l.id===r.id)&&i[a].push(r)}}return this._root?{[typeof this._root=="string"?this._root:this._collectionName]:t,...i}:t}_getAttributes(e){return this._attrs&&this._attrs.length>0?this._attrs.reduce((t,i)=>(t[i]=e.attrs[i],t),{}):{...e.attrs}}_getRelationships(e){if(!this._include||this._include.length===0)return{embedded:{},sideLoaded:{},foreignKeys:[]};let t={},i={},s=[];for(let o of this._include){let a=e[o];if(a===void 0)continue;if(a===null){this._embed?(t[o]=null,s.push(`${o}Id`)):i[o]=null;continue}let r=a&&typeof a=="object"&&"models"in a;this._embed?r?(t[o]=a.models.map(l=>({...l.attrs})),s.push(`${o.replace(/s$/,"")}Ids`)):(t[o]={...a.attrs},s.push(`${o}Id`)):r?i[o]=a.models.map(l=>({...l.attrs})):i[o]={...a.attrs}}return{embedded:t,sideLoaded:i,foreignKeys:s}}};var W=class c{_template;_factory;_relationships;_identityManager;_serializerConfig;_serializerInstance;_seeds;_fixtures;constructor(){}model(e){if(!e||typeof e!="object")throw new h("Invalid model template. Expected a ModelTemplate object created with model().name(...).collection(...).create().");if(!e.modelName)throw new h("Model template is missing modelName property. Ensure you called .name() when building the model.");if(!e.collectionName)throw new h("Model template is missing collectionName property. Ensure you called .collection() when building the model.");let t=new c;return t._template=e,t._factory=this._factory,t._relationships=this._relationships,t._serializerConfig=this._serializerConfig,t._serializerInstance=this._serializerInstance,t._identityManager=this._identityManager,t._seeds=this._seeds,t._fixtures=this._fixtures,t}factory(e){let t=new c;return t._template=this._template,t._factory=e,t._relationships=this._relationships,t._identityManager=this._identityManager,t._serializerConfig=this._serializerConfig,t._serializerInstance=this._serializerInstance,t._seeds=this._seeds,t._fixtures=this._fixtures,t}relationships(e){if(!e||typeof e!="object")throw new h("Invalid relationships configuration. Expected an object with relationship definitions.");let t=["hasMany","belongsTo"];for(let s in e){let o=e[s];if(!o||typeof o!="object")throw new h(`Invalid relationship '${s}'. Expected a relationship object created with hasMany() or belongsTo().`);if(!o.type)throw new h(`Relationship '${s}' is missing type property. Use hasMany() or belongsTo() to create relationships.`);if(!t.includes(o.type))throw new h(`Relationship '${s}' has unsupported type '${o.type}'.
|
|
1
|
+
var h=class extends Error{constructor(e){super(`[Mirage]: ${e}`)}};var C={reset:"\x1B[0m",green:"\x1B[32m",gray:"\x1B[90m",blue:"\x1B[34m",yellow:"\x1B[33m",red:"\x1B[31m"},b=class{_config;constructor(e){this._config={prefix:"[Mirage]",...e}}debug(e,t){this._log(0,e,t)}log(e,t){this._log(1,e,t)}info(e,t){this._log(2,e,t)}warn(e,t){this._log(3,e,t)}error(e,t){this._log(4,e,t)}_log(e,t,i){if(!this._config.enabled)return;let o=typeof this._config.level=="string"?se[this._config.level]:this._config.level;if(e<o)return;let r=this._config.prefix,s=W[e],n=this._getLevelColor(e),a=`${r} ${n}${s}${C.reset}: ${t}`;switch(e){case 0:case 1:case 2:console.log(a,i||"");break;case 3:console.warn(a,i||"");break;case 4:console.error(a,i||"");break}}_getLevelColor(e){switch(e){case 0:return C.green;case 1:return C.gray;case 2:return C.blue;case 3:return C.yellow;case 4:return C.red;default:return C.reset}}},W=(s=>(s[s.DEBUG=0]="DEBUG",s[s.LOG=1]="LOG",s[s.INFO=2]="INFO",s[s.WARN=3]="WARN",s[s.ERROR=4]="ERROR",s[s.SILENT=5]="SILENT",s))(W||{}),se={debug:0,log:1,info:2,warn:3,error:4,silent:5};function G(d,e){return typeof d=="function"?d(e):d}var g=class{_counter;_idGenerator;_initialCounter;_usedIds;constructor(e){this._initialCounter=e.initialCounter,this._counter=this._initialCounter,this._usedIds=e.initialUsedIds?new Set(e.initialUsedIds):new Set,this._idGenerator=e.idGenerator??this.getDefaultGenerator()}get(){let e=this._counter;for(;this._usedIds.has(e);)e=this._idGenerator(e);return e}fetch(){let e=this.get();return this._usedIds.add(e),this._counter=this._idGenerator(e),e}set(e){this._usedIds.add(e)}inc(){this._counter=this._idGenerator(this._counter)}reset(){this._counter=this._initialCounter,this._usedIds.clear()}getDefaultGenerator(){if(typeof this._initialCounter=="string"){if(isNaN(Number(this._initialCounter)))throw new h("Default ID generator only works with numeric string IDs");return e=>{if(isNaN(Number(e)))throw new h("Default ID generator only works with numeric string IDs");return String(Number(e)+1)}}else{if(typeof this._initialCounter=="number")return e=>e+1;throw new h("Unknown ID type. Please provide a custom idGenerator.")}}};var R=class{query(e,t){let i=e,{cursor:o,limit:r,offset:s,orderBy:n,where:a}=t;if(a)if(typeof a=="function"){let c=this._buildWhereHelpers();i=i.filter(m=>a(m,c))}else i=i.filter(c=>this.matchesWhere(c,a));n&&(i=this._applyOrder(i,n));let l=i.length;if(o&&n&&(i=this._applyCursor(i,n,o)),typeof s=="number"&&s>0&&(i=i.slice(s)),typeof r=="number"){if(r===0)return{records:[],total:l};r>0&&(i=i.slice(0,r))}return{records:i,total:l}}matchesPredicateObject(e,t){return Object.entries(t).every(([i,o])=>String(e[i])===String(o))}matchesWhere(e,t){let{AND:i,OR:o,NOT:r,...s}=t;for(let n in s){let a=e[n],l=s[n];if(l!==null&&typeof l=="object"&&!Array.isArray(l)){if(!this._matchesField(a,l))return!1}else if(a!==l)return!1}return!(Array.isArray(i)&&!i.every(n=>this.matchesWhere(e,n))||Array.isArray(o)&&!o.some(n=>this.matchesWhere(e,n))||r&&this.matchesWhere(e,r))}_matchesField(e,t){if("eq"in t&&e!==t.eq||"ne"in t&&e===t.ne||"in"in t&&t.in&&!t.in.includes(e)||"nin"in t&&t.nin&&t.nin.includes(e))return!1;if("isNull"in t){let i=e==null;if(t.isNull&&!i||!t.isNull&&i)return!1}if("lt"in t&&t.lt!=null&&!this._compareValues(e,t.lt,"<")||"lte"in t&&t.lte!=null&&!this._compareValues(e,t.lte,"<=")||"gt"in t&&t.gt!=null&&!this._compareValues(e,t.gt,">")||"gte"in t&&t.gte!=null&&!this._compareValues(e,t.gte,">="))return!1;if("between"in t&&t.between&&Array.isArray(t.between)&&t.between.length===2){let[i,o]=t.between;if(!this._compareValues(e,i,">=")||!this._compareValues(e,o,"<="))return!1}if("like"in t&&typeof t.like=="string"&&!this._likeToRegex(t.like,!1).test(String(e))||"ilike"in t&&typeof t.ilike=="string"&&!this._likeToRegex(t.ilike,!0).test(String(e))||"startsWith"in t&&typeof t.startsWith=="string"&&!String(e).startsWith(t.startsWith)||"endsWith"in t&&typeof t.endsWith=="string"&&!String(e).endsWith(t.endsWith)||"contains"in t&&t.contains&&typeof t.contains=="string"&&!String(e).includes(t.contains))return!1;if("contains"in t&&Array.isArray(e)){let i=t.contains;if(Array.isArray(i)){if(!i.every(o=>e.includes(o)))return!1}else if(!e.includes(i))return!1}return!("length"in t&&t.length&&Array.isArray(e)&&!this._matchesField(e.length,t.length))}_compareValues(e,t,i){if(e==null||t==null)return!1;if(e instanceof Date&&t instanceof Date){let o=e.getTime(),r=t.getTime();switch(i){case"<":return o<r;case"<=":return o<=r;case">":return o>r;case">=":return o>=r}}switch(i){case"<":return e<t;case"<=":return e<=t;case">":return e>t;case">=":return e>=t}}_likeToRegex(e,t){let o="^"+e.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/%/g,".*")+"$";return new RegExp(o,t?"i":"")}_applyOrder(e,t){let i=Array.isArray(t)?t:(()=>{let o=[];for(let r in t){let s=t[r];s&&o.push([r,s])}return o})();return[...e].sort((o,r)=>{for(let[s,n]of i){let a=o[s],l=r[s];if(!(a==null&&l==null)){if(a==null)return 1;if(l==null)return-1;if(a instanceof Date&&l instanceof Date){let c=a.getTime()-l.getTime();if(c!==0)return n==="desc"?-c:c;continue}if(a<l)return n==="desc"?1:-1;if(a>l)return n==="desc"?-1:1}}return 0})}_applyCursor(e,t,i){let o=Array.isArray(t)?t:(()=>{let r=[];for(let s in t){let n=t[s];n&&r.push([s,n])}return r})();return e.filter(r=>{for(let[s,n]of o){let a=r[s],l=i[s];if(l!==void 0&&!(a==null&&l==null)){if(a==null)return!1;if(l==null)return!0;if(a instanceof Date&&l instanceof Date){let c=a.getTime()-l.getTime();if(c===0)continue;return n==="desc"?c<0:c>0}if(a!==l){if(a<l)return n==="desc";if(a>l)return n==="asc"}}}return!1})}_buildWhereHelpers(){return{and:(...e)=>e.every(t=>t),or:(...e)=>e.some(t=>t),not:e=>!e,eq:(e,t)=>e===t,ne:(e,t)=>e!==t,gt:(e,t)=>e!=null&&t!=null&&e>t,gte:(e,t)=>e!=null&&t!=null&&e>=t,lt:(e,t)=>e!=null&&t!=null&&e<t,lte:(e,t)=>e!=null&&t!=null&&e<=t,between:(e,t,i)=>e!=null&&t!=null&&i!=null&&e>=t&&e<=i,like:(e,t)=>this._likeToRegex(t,!1).test(String(e)),ilike:(e,t)=>this._likeToRegex(t,!0).test(String(e)),startsWith:(e,t)=>String(e).startsWith(t),endsWith:(e,t)=>String(e).endsWith(t),containsText:(e,t)=>String(e).includes(t),inArray:(e,t)=>t.some(i=>i===e),notInArray:(e,t)=>!t.some(i=>i===e),isNull:e=>e==null,isNotNull:e=>e!=null}}};var S=class{name;identityManager;_records=new Map;_queryManager=new R;_logger;constructor(e,t){this.name=e,this.identityManager=this._resolveIdentityManager(t),this._logger=t?.logger,t?.initialData&&this.insertMany(t.initialData)}get nextId(){return this.identityManager.fetch()}get size(){return this._records.size}get isEmpty(){return this._records.size===0}all(){return Array.from(this._records.values())}at(e){return this.all()[e]}first(){return this.all()[0]}last(){let e=this.all();return e[e.length-1]}has(e){return this._records.has(e)}find(e){if(typeof e=="string"||typeof e=="number"){let r=this._records.get(e)??null;return this._logger?.debug(`Found ${r?1:0} records in '${this.name}'`,{query:e,operation:"find"}),r}if(typeof e=="object"&&("where"in e||"orderBy"in e||"cursor"in e||"offset"in e||"limit"in e)){let r={...e,limit:1},{records:s}=this._queryManager.query(this.all(),r);return this._logger?.debug(`Found ${s.length} records in '${this.name}'`,{query:r,operation:"find"}),s[0]??null}let i=e,o=this.all().find(r=>this._queryManager.matchesPredicateObject(r,i))??null;return this._logger?.debug(`Found ${o?1:0} records in '${this.name}'`,{query:i,operation:"find"}),o}findMany(e){if(Array.isArray(e)){let r=e.map(s=>this._records.get(s)).filter(Boolean);return this._logger?.debug(`Found ${r.length} records in '${this.name}'`,{query:e,total:r.length,operation:"findMany"}),r}if(typeof e=="object"&&("where"in e||"orderBy"in e||"cursor"in e||"offset"in e||"limit"in e)){let r=e,s=this._queryManager.query(this.all(),r);return this._logger?.debug(`Found ${s.records.length} records in '${this.name}'`,{query:r,total:s.total,operation:"findMany"}),s}let i=e,o=this.all().filter(r=>this._queryManager.matchesPredicateObject(r,i));return this._logger?.debug(`Found ${o.length} records in '${this.name}'`,{query:i,total:o.length,operation:"findMany"}),o}count(e){return e?this._queryManager.query(this.all(),{where:e}).total:this.size}exists(e){return e?this._queryManager.query(this.all(),{where:e,limit:1}).records.length>0:!this.isEmpty}insert(e){let t=this._prepareRecord(e);return this._records.set(t.id,t),this._logger?.debug(`Inserted record into '${this.name}'`,{id:t.id,record:t}),t}insertMany(e){let t=e.map(o=>this.insert(o)),i=t.map(o=>o.id);return this._logger?.debug(`Inserted ${t.length} records into '${this.name}'`,{ids:i,operation:"insertMany"}),t}update(e,t){let i=this._records.get(e);if(!i)return null;let o={...i,...t};return this._records.set(e,o),this._logger?.debug(`Updated record in '${this.name}'`,{id:e,patch:t}),o}updateMany(e,t){let o=this._getRecordsFromFindMany(e).map(s=>{let n={...s,...t};return this._records.set(s.id,n),n}),r=o.map(s=>s.id);return this._logger?.debug(`${r.length} records updated in '${this.name}'`,{ids:r,patch:t}),o}delete(e){let t=this._records.delete(e);return t&&this._logger?.debug(`Deleted record from '${this.name}'`,{id:e}),t}deleteMany(e){let t=this._getRecordsFromFindMany(e),i=t.map(o=>o.id);return t.forEach(o=>this._records.delete(o.id)),this._logger?.debug(`${i.length} records deleted from '${this.name}'`,{ids:i}),t.length}clear(){this._records.clear(),this.identityManager.reset(),this._logger?.debug(`Cleared collection '${this.name}'`,{size:this.size})}_resolveIdentityManager(e){return e?.identityManager??new g({initialCounter:"1"})}_getRecordsFromFindMany(e){return Array.isArray(e)?this.findMany(e):typeof e=="object"&&("where"in e||"orderBy"in e||"cursor"in e||"offset"in e||"limit"in e)?this.findMany(e).records:this.findMany(e)}_prepareRecord(e){let t={...e};return t.id?this.identityManager.set(t.id):t.id=this.identityManager.fetch(),t}};var v=class{_collections=new Map;_logger;constructor(e={}){let{initialData:t,logger:i}=e;this._logger=i,t&&this.loadData(t),this.initCollectionAccessors()}hasCollection(e){return this._collections.has(e)}createCollection(e,t){let i=String(e);if(this._collections.has(i))throw new h(`Collection ${i} already exists`);let o=new S(i,{identityManager:t?.identityManager,initialData:t?.initialData,logger:this._logger});return this._collections.set(i,o),this.initCollectionAccessors(),this}getCollection(e){let t=this._collections.get(e);if(!t)throw new h(`Collection ${String(e)} does not exist`);return t}identityManagerFor(e){return this.getCollection(e).identityManager}loadData(e){for(let t in e){let i=e[t],o=t;this.hasCollection(o)?this.getCollection(o).insertMany(i):this.createCollection(o,{initialData:i})}return this}emptyData(){this._collections.forEach(e=>e.clear())}dump(){let e={};return this._collections.forEach((t,i)=>{e[i]=t.all()}),e}initCollectionAccessors(){this._collections.forEach((e,t)=>{Object.prototype.hasOwnProperty.call(this,t)||Object.defineProperty(this,t,{get:()=>e,enumerable:!0,configurable:!0})})}};function U(d){return new v(d)}var A=class{modelName;collectionName;_attrs;_dbCollection;_serializer;_status;constructor(e,t,i,o,r){this.modelName=e,this.collectionName=t,this._attrs={...i,id:i.id??null},this._dbCollection=o??new S(t),this._serializer=r,this._status=this._checkStatus()}get id(){return this._attrs.id}get attrs(){return{...this._attrs}}save(){if(this.isNew()||!this.id){let e=this._dbCollection.insert(this._attrs);this._attrs=e,this._status="saved"}else this._dbCollection.update(this.id,this._attrs);return this}update(e){return Object.assign(this._attrs,e),this.save()}reload(){if(this._attrs.id){let e=this._dbCollection.find(this.id);e&&(this._attrs=e,this._status="saved")}else return this.save();return this}destroy(){return this.isSaved()&&this.id&&(this._dbCollection.delete(this.id),this._attrs={...this._attrs,id:null},this._status="new"),this}isNew(){return this._status==="new"}isSaved(){return this._status==="saved"}toJSON(){return this._serializer?this._serializer.serialize(this):{...this._attrs}}toString(){let e=this.id?`(${this.id})`:"";return`model:${this.modelName}${e}`}_checkStatus(){return this.id&&this._dbCollection.find(this.id)?"saved":"new"}};var u=class{modelName;collectionName;_options;constructor(e,t){this.modelName=e.modelName,this.collectionName=e.collectionName,this._options=t??{}}serialize(e,t){let i=this._resolveOptions(t),o=this.serializeModel(e,t),s=this._getWithNames(i.with).length>0,n=i.relationsMode==="sideLoaded"||i.relationsMode==="sideLoaded+foreignKey";if(s&&n){let{sideLoaded:a}=this._getRelationships(e,i),l=this._getAttributes(e,i);return i.root?{[typeof i.root=="string"?i.root:this.modelName]:l,...a}:{...l,...a}}return i.root?{[typeof i.root=="string"?i.root:this.modelName]:o}:o}serializeCollection(e,t){let i=this._resolveOptions(t),o=this.serializeCollectionModels(e,t);return i.root?{[typeof i.root=="string"?i.root:this.collectionName]:o}:o}serializeAttrs(e){let t=this._resolveOptions(),i=this._getAttributes(e,t),o=e.relationships;if(o)for(let r in o){let s=o[r];if(s?.foreignKey){let n=e.attrs[s.foreignKey];n!==void 0&&(i[s.foreignKey]=n)}}return i}serializeCollectionAttrs(e){return e.models.map(t=>this.serializeAttrs(t))}_resolveOptions(e){let t={select:e?.select??this._options.select,with:e?.with??this._options.with,relationsMode:e?.relationsMode??this._options.relationsMode,root:e?.root??this._options.root};return!t.relationsMode&&t.with&&this._getWithNames(t.with).length>0&&(t.relationsMode="foreignKey"),t.relationsMode==="sideLoaded"&&(t.root===!1&&console.warn("[Mirage Serializer]: 'root' cannot be disabled when 'relationsMode' is 'sideLoaded'. Side-loaded relationships require root wrapping. The 'root=false' setting will be ignored and 'root=true' will be used instead."),t.root=t.root===!1?!0:t.root??!0),t}_getWithNames(e){return e?Array.isArray(e)?e:Object.entries(e).filter(([,t])=>t!==!1).map(([t])=>t):[]}_getNestedOptions(e,t){if(!e||Array.isArray(e))return;let i=e[t];if(typeof i=="object"&&i!==null)return i}serializeModel(e,t){let i=this._resolveOptions(t),o=this._getAttributes(e,i),r=this._getWithNames(i.with);if(r.length===0)return this._removeForeignKeys(o,e);let{embedded:s,sideLoaded:n}=this._getRelationships(e,i);if(i.relationsMode==="embedded"){let a={...o},l=e.relationships;if(l)for(let c in l){let m=l[c];m?.foreignKey&&this._getNestedOptions(i.with,c)?.mode!=="foreignKey"&&delete a[m.foreignKey]}return{...a,...s,...n}}if(i.relationsMode==="embedded+foreignKey"){let a={...o},l=e.relationships;if(l){for(let c in l)if(!r.includes(c)){let m=l[c];(m.type==="hasMany"||m.type==="belongsTo")&&delete a[m.foreignKey]}}return{...a,...s,...n}}if(i.relationsMode==="sideLoaded"||i.relationsMode==="sideLoaded+foreignKey")return o;if(i.relationsMode==="foreignKey"||!i.relationsMode){let a={...o},l=e.relationships;if(l)for(let c in l){let m=l[c];r.includes(c)?this._getNestedOptions(i.with,c)?.mode==="embedded"&&delete a[m.foreignKey]:(m.type==="hasMany"||m.type==="belongsTo")&&delete a[m.foreignKey]}return{...a,...s,...n}}throw new Error(`[Mirage Serializer]: Unknown relationsMode '${i.relationsMode}'. Valid values are: 'foreignKey', 'embedded', 'sideLoaded', 'embedded+foreignKey', 'sideLoaded+foreignKey'.`)}serializeCollectionModels(e,t){let i=this._resolveOptions(t),o=this._getWithNames(i.with);return(i.relationsMode==="sideLoaded"||i.relationsMode==="sideLoaded+foreignKey")&&o.length>0?e.models.map(r=>{let s=this._getAttributes(r,i),{sideLoaded:n}=this._getRelationships(r,i);return{...s,...n}}):e.models.map(r=>this.serializeModel(r,t))}_getAttributes(e,t){let i=t.select;if(!i)return{...e.attrs};if(Array.isArray(i))return i.length===0?{...e.attrs}:i.reduce((a,l)=>(a[l]=e.attrs[l],a),{});let o=Object.entries(i);if(o.length===0)return{...e.attrs};let r=o.some(([,a])=>a===!0);if(o.some(([,a])=>a===!1)&&!r){let a=o.filter(([,l])=>l===!1).map(([l])=>l);return Object.entries(e.attrs).reduce((l,[c,m])=>(a.includes(c)||(l[c]=m),l),{})}return o.filter(([,a])=>a===!0).map(([a])=>a).reduce((a,l)=>(a[l]=e.attrs[l],a),{})}_getRelationships(e,t){let i={},o={},r=this._getWithNames(t.with);if(r.length===0)return{embedded:i,sideLoaded:o};for(let s of r){let n=e[s];if(n===void 0)continue;let a=this._getNestedOptions(t.with,s),l=a?.mode??t.relationsMode??"foreignKey",c=n!==null&&typeof n=="object"&&"models"in n;if(n===null){if(l==="embedded"||l==="embedded+foreignKey")i[s]=null;else if(l==="sideLoaded"||l==="sideLoaded+foreignKey"){let p=e.relationships?.[s]?.collectionName||s;o[p]=[]}continue}if(l==="embedded"||l==="embedded+foreignKey")if(c){let m=n;i[s]=m.models.map(T=>this._serializeRelatedModel(T,a))}else{let m=n;i[s]=this._serializeRelatedModel(m,a)}else if(l==="sideLoaded"||l==="sideLoaded+foreignKey")if(c){let p=e.relationships?.[s]?.collectionName||s,y=n;o[p]=y.models.map(F=>this._serializeRelatedModel(F,a))}else{let p=e.relationships?.[s]?.collectionName||s,y=n;o[p]=[this._serializeRelatedModel(y,a)]}}return{embedded:i,sideLoaded:o}}_serializeRelatedModel(e,t){let i=e.serializer?e.serializer.serializeAttrs(e):{...e.attrs};if(t?.select&&(i=this._applySelectToAttrs(i,t.select)),t?.with){let o=e;for(let[r,s]of Object.entries(t.with))if(s===!0){let n=o[r];if(n!=null)if(typeof n=="object"&&"models"in n){let l=n;i[r]=l.models.map(c=>c.serializer?c.serializer.serializeAttrs(c):{...c.attrs})}else{let l=n;i[r]=l.serializer?l.serializer.serializeAttrs(l):{...l.attrs}}else n===null&&(i[r]=null)}}return i}_applySelectToAttrs(e,t){if(Array.isArray(t))return t.length===0?e:t.reduce((n,a)=>(a in e&&(n[a]=e[a]),n),{});let i=Object.entries(t);if(i.length===0)return e;let o=i.some(([,n])=>n===!0);if(i.some(([,n])=>n===!1)&&!o){let n=i.filter(([,a])=>a===!1).map(([a])=>a);return Object.entries(e).reduce((a,[l,c])=>(n.includes(l)||(a[l]=c),a),{})}return i.filter(([,n])=>n===!0).map(([n])=>n).reduce((n,a)=>(a in e&&(n[a]=e[a]),n),{})}_removeForeignKeys(e,t){let i={...e},o=t.relationships;if(!o)return i;for(let r in o){let s=o[r];(s.type==="hasMany"||s.type==="belongsTo")&&delete i[s.foreignKey]}return i}};var f=class d{models;collectionName;serializer;meta;_template;constructor(e,t,i,o){this.collectionName=e.collectionName,this.models=[...t??[]],this.serializer=i,this.meta=o,this._template=e}[Symbol.iterator](){return this.models[Symbol.iterator]()}get length(){return this.models.length}get isEmpty(){return this.models.length===0}at(e){return this.models[e]}first(){return this.models[0]||null}last(){return this.models[this.models.length-1]||null}forEach(e){this.models.forEach((t,i)=>e(t,i,this))}map(e){let t=this.models.map((i,o)=>e(i,o,this));return new d(this._template,t,this.serializer)}filter(e){let t=this.models.filter((i,o)=>e(i,o,this));return new d(this._template,t,this.serializer)}find(e){return this.models.find((t,i)=>e(t,i,this))}some(e){return this.models.some((t,i)=>e(t,i,this))}every(e){return this.models.every((t,i)=>e(t,i,this))}concat(...e){let t=[...this.models,...e.flatMap(i=>Array.isArray(i)?i:i.models)];return new d(this._template,t,this.serializer)}includes(e){return this.models.includes(e)}indexOf(e){return this.models.indexOf(e)}sort(e){let t=[...this.models].sort(e);return new d(this._template,t,this.serializer)}reverse(){let e=[...this.models].reverse();return new d(this._template,e,this.serializer)}add(e){this.models.push(e)}remove(e){let t=this.indexOf(e);return t!==-1?(this.models.splice(t,1),!0):!1}save(){return this.models=this.models.map(e=>e.save()),this}destroy(){return this.models.forEach(e=>e.destroy()),this.models=[],this}reload(){return this.models=this.models.map(e=>e.reload()),this}update(e){return this.models=this.models.map(t=>t.update(e)),this}serialize(e){return e instanceof u?e.serializeCollection(this):this.serializer instanceof u?this.serializer.serializeCollection(this,e):this.models.map(t=>t.attrs)}toArray(){return[...this.models]}toString(){return`collection:${this.collectionName}(${this.models.map(e=>e.toString()).join(", ")})`}toJSON(){return this.serialize()}};function x(d){return d!==null&&typeof d=="object"&&"id"in d&&"modelName"in d}function H(d){return Array.isArray(d)&&d.every(e=>x(e))}function Q(d){return d!==null&&typeof d=="object"&&"models"in d&&Array.isArray(d.models)}function J(d){return Array.isArray(d)}var w=class{isApplyingPendingUpdates=!1;_model;_pendingRelationshipOperations=[];_relationshipDefs;_inverseMap=new Map;_schema;constructor(e,t,i){this._model=e,this._schema=t,this._relationshipDefs=this._parseRelationshipDefs(i)}get relationshipDefs(){return this._relationshipDefs}get schema(){return this._schema}setPendingRelationshipUpdates(e){for(let t in e){let i=this._relationshipDefs?.[t];if(!i)continue;let o=i.relationship,{foreignKey:r}=o,s=i.inverse;if(!s)continue;let n=e[t],a=this._getForeignKeyValue(r),l=this._hasForeignKeyChanged(a,n);this._model.isSaved()?(l&&this._hasForeignKeyValue(a)&&this._pendingRelationshipOperations.push({relationshipName:t,type:"unlink",foreignKeyValue:a,targetCollectionName:o.targetModel.collectionName,inverseForeignKey:s.foreignKey,inverseRelationshipName:s.relationshipName,inverseType:s.type}),this._hasForeignKeyValue(n)&&this._pendingRelationshipOperations.push({relationshipName:t,type:"link",foreignKeyValue:n,targetCollectionName:o.targetModel.collectionName,inverseForeignKey:s.foreignKey,inverseRelationshipName:s.relationshipName,inverseType:s.type})):this._model.isNew()&&this._hasForeignKeyValue(n)&&this._pendingRelationshipOperations.push({relationshipName:t,type:"link",foreignKeyValue:n,targetCollectionName:o.targetModel.collectionName,inverseForeignKey:s.foreignKey,inverseRelationshipName:s.relationshipName,inverseType:s.type})}}applyPendingInverseUpdates(){if(this._pendingRelationshipOperations.length!==0){this.isApplyingPendingUpdates=!0;try{for(let e of this._pendingRelationshipOperations){if(!e.inverseForeignKey||!e.inverseRelationshipName)continue;let t=this._extractTargetIds(e.foreignKeyValue);this._updateInverseRelationship(e.type,{targetCollectionName:e.targetCollectionName,targetIds:t,inverseForeignKey:e.inverseForeignKey,inverseType:e.inverseType,sourceModelId:this._model.id,inverseRelationshipName:e.inverseRelationshipName})}this._pendingRelationshipOperations=[]}finally{this.isApplyingPendingUpdates=!1}}}link(e,t){let i={},o=String(e);if(!this._relationshipDefs||!this._schema)return{foreignKeyUpdates:i};let r=this._getRelationshipDef(o);if(!r)return{foreignKeyUpdates:i};let s=r.relationship,{type:n,foreignKey:a}=s,l=s.targetModel.collectionName,c=r.inverse;if(n==="belongsTo"){let T=this._extractIdsFromValue("belongsTo",t)[0]??null,p=this._getForeignKeyValue(a),y=this._extractSingleId(p);c&&y&&y!==T&&this._updateInverseRelationship("unlink",{targetCollectionName:l,targetIds:[y],inverseForeignKey:c.foreignKey,inverseType:c.type,sourceModelId:this._model.id,inverseRelationshipName:c.relationshipName}),i[a]=T,c&&T!==null&&this._updateInverseRelationship("link",{targetCollectionName:l,targetIds:[T],inverseForeignKey:c.foreignKey,inverseType:c.type,sourceModelId:this._model.id,inverseRelationshipName:c.relationshipName})}else if(n==="hasMany"){let m=this._extractIdsFromValue("hasMany",t),T=this._getForeignKeyValue(a),p=this._extractIdsArray(T);this._arraysEqual(p,m)||(c&&p.length>0&&this._updateInverseRelationship("unlink",{targetCollectionName:l,targetIds:p,inverseForeignKey:c.foreignKey,inverseType:c.type,sourceModelId:this._model.id,inverseRelationshipName:c.relationshipName}),c&&m.length>0&&this._updateInverseRelationship("link",{targetCollectionName:l,targetIds:m,inverseForeignKey:c.foreignKey,inverseType:c.type,sourceModelId:this._model.id,inverseRelationshipName:c.relationshipName})),i[a]=m}return{foreignKeyUpdates:i}}unlink(e,t){let i={},o=String(e);if(!this._relationshipDefs||!this._schema)return{foreignKeyUpdates:i};let r=this._getRelationshipDef(o);if(!r)return{foreignKeyUpdates:i};let{inverse:s,relationship:n}=r,{type:a,foreignKey:l}=n,c=n.targetModel.collectionName;if(a==="belongsTo"){let m=this._extractSingleId(this._getForeignKeyValue(l));s&&m&&this._updateInverseRelationship("unlink",{targetCollectionName:c,targetIds:[m],inverseForeignKey:s.foreignKey,inverseType:s.type,sourceModelId:this._model.id,inverseRelationshipName:s.relationshipName}),i[l]=null}else if(a==="hasMany"){let m=this._extractIdsArray(this._getForeignKeyValue(l));if(t){let T=this._extractIdsFromValue("hasMany",t),p=m.filter(y=>!T.includes(y));s&&T.length>0&&this._updateInverseRelationship("unlink",{targetCollectionName:c,targetIds:T,inverseForeignKey:s.foreignKey,inverseType:s.type,sourceModelId:this._model.id,inverseRelationshipName:s.relationshipName}),i[l]=p}else s&&m.length>0&&this._updateInverseRelationship("unlink",{targetCollectionName:c,targetIds:m,inverseForeignKey:s.foreignKey,inverseType:s.type,sourceModelId:this._model.id,inverseRelationshipName:s.relationshipName}),i[l]=[]}return{foreignKeyUpdates:i}}related(e){if(!this._schema||!this._relationshipDefs)return null;let t=this._getRelationshipDef(e);if(!t)return null;let i=t.relationship,{type:o,foreignKey:r,targetModel:s}=i,n=this._schema.getCollection(s.collectionName);if(!n)throw new h(`Collection for model ${s.modelName} not found in schema`);if(o==="belongsTo"){let a=this._getForeignKeyValue(r),l=this._extractSingleId(a);return l===null?null:n.find(l)}if(o==="hasMany"){let a=this._getForeignKeyValue(r),l=this._extractIdsArray(a),c=n.serializer;if(l.length===0)return new f(s,[],c);let m=l.map(T=>n.find(T)).filter(T=>T!==null);return new f(s,m,c)}return null}_getRelationshipDef(e){if(this._relationshipDefs)return this._relationshipDefs[e]}_getModelAttrs(){return this._model.attrs}_getForeignKeyValue(e){return this._getModelAttrs()[e]}_extractSingleId(e){return e==null||Array.isArray(e)?null:e}_extractIdsArray(e){return Array.isArray(e)?e:[]}_parseRelationshipDefs(e){if(!e||!this._schema)return;let t={};for(let i in e){let o=e[i],r={relationship:o};"inverse"in o&&this._inverseMap.set(i,o.inverse);let s="inverse"in o?o.inverse:void 0;if(s===null)r.inverse=void 0;else if(typeof s=="string"){let n=o.targetModel.collectionName,a=this._schema.getCollection(n);if(a.relationships&&a.relationships[s]){let l=a.relationships[s];r.inverse={foreignKey:l.foreignKey,relationshipName:s,targetModel:o.targetModel,type:l.type}}}else{let n=o.targetModel.collectionName,a=this._schema.getCollection(n);if(a.relationships)for(let l in a.relationships){let c=a.relationships[l];if(c.targetModel.modelName===this._model.modelName){r.inverse={foreignKey:c.foreignKey,relationshipName:l,targetModel:o.targetModel,type:c.type};break}}}t[i]=r}return t}_updateInverseRelationship(e,t){let{inverseForeignKey:i,inverseRelationshipName:o,inverseType:r,sourceModelId:s,targetCollectionName:n,targetIds:a}=t;if(o){let m=this._schema.getCollection(n).relationships?.[o];if(m&&"inverse"in m&&m.inverse===null)return}let l=this._schema.db.getCollection(n);for(let c of a){let m=c,T=l.find(m);if(!T)continue;let p={};if(r==="hasMany"){let y=T[i],F=this._extractIdsArray(y);e==="link"?F.includes(s)||(p[i]=[...F,s]):p[i]=F.filter(oe=>oe!==s)}else r==="belongsTo"&&(p[i]=e==="link"?s:null);Object.keys(p).length>0&&l.update(m,p)}}_hasForeignKeyValue(e){return e==null?!1:Array.isArray(e)?e.length>0:!0}_hasForeignKeyChanged(e,t){return!this._hasForeignKeyValue(e)&&!this._hasForeignKeyValue(t)?!1:!this._hasForeignKeyValue(e)||!this._hasForeignKeyValue(t)?!0:Array.isArray(e)&&Array.isArray(t)?!this._arraysEqual(e,t):e!==t}_arraysEqual(e,t){return e.length!==t.length?!1:e.every((i,o)=>i===t[o])}_extractTargetIds(e){return e==null?[]:Array.isArray(e)?e:[e]}_extractIdsFromValue(e,t){return e==="belongsTo"?x(t)?[t.id]:[]:Q(t)?t.models.map(i=>i.id):J(t)?t.filter(i=>x(i)).map(i=>i.id):[]}};var M=class d extends A{relationships;serializer;_relationshipsManager;constructor(e,t){let{attrs:i,relationships:o,serializer:r,schema:s}=t,n=s.db.getCollection(e.collectionName),{modelAttrs:a,relationshipUpdates:l}=d.processAttrs(i,o,!0);super(e.modelName,e.collectionName,a,n,r),this.serializer=r,this.relationships=o,s&&o?(this._relationshipsManager=new w(this,s,o),this._status==="new"&&Object.keys(l).length>0&&this._relationshipsManager.setPendingRelationshipUpdates(l),this._initAttributeAccessors(),this._initForeignKeys(),this._initRelationshipAccessors()):this._initAttributeAccessors()}static define(e){return class extends d{constructor(t){super(e,t)}}}static processAttrs(e,t,i=!1){if(!t)return{modelAttrs:e,relationshipUpdates:{}};let o={},r={},s=e;if(i)for(let n in t){let a=t[n],{type:l,foreignKey:c}=a;o[c]=l==="belongsTo"?null:[]}for(let n in s){let a=s[n];if(n in t){let l=t[n];if(a===null||Array.isArray(a)&&a.length===0)o[l.foreignKey]=a,r[n]=a;else{let m=d.extractForeignKey(l,a);m!==null&&(o[l.foreignKey]=m,r[n]=m)}}else{let l=!1;for(let c in t)if(t[c].foreignKey===n){l=!0,o[n]=a,r[c]=a;break}l||(o[n]=a)}}return{modelAttrs:o,relationshipUpdates:r}}static extractForeignKey(e,t){let{type:i}=e;return i==="belongsTo"?x(t)?t.id:null:i==="hasMany"?H(t)?t.map(o=>o.id):Q(t)?t.models.map(o=>o.id):[]:null}save(){return super.save(),this._relationshipsManager&&this._relationshipsManager.applyPendingInverseUpdates(),this}update(e){let{modelAttrs:t,relationshipUpdates:i}=d.processAttrs(e,this.relationships);this._relationshipsManager&&Object.keys(i).length>0&&this._relationshipsManager.setPendingRelationshipUpdates(i);let o=super.update(t);return this._initAttributeAccessors(),o}reload(){return super.reload()}destroy(){return super.destroy()}related(e){return this._relationshipsManager?.related(e)}link(e,t){if(this._relationshipsManager){let i=this._relationshipsManager.link(e,t);Object.assign(this._attrs,i.foreignKeyUpdates),this.isSaved()&&this.save()}return this}unlink(e,t){if(this._relationshipsManager){let i=this._relationshipsManager.unlink(e,t);Object.assign(this._attrs,i.foreignKeyUpdates),this.isSaved()&&this.save()}return this}serialize(e){return e instanceof u?e.serialize(this):this.serializer instanceof u?this.serializer.serialize(this,e):{...this._attrs}}_initAttributeAccessors(){for(let e in this._attrs)e!=="id"&&Object.hasOwn(this,e)&&delete this[e];for(let e in this._attrs){let t=e;t!=="id"&&!Object.hasOwn(this,t)&&Object.defineProperty(this,e,{get:()=>this._attrs[t],set:i=>{this._attrs[t]=i},enumerable:!1,configurable:!0})}}_initForeignKeys(){if(this._relationshipsManager?.relationshipDefs)for(let e in this._relationshipsManager.relationshipDefs){let t=e,i=this._relationshipsManager.relationshipDefs[t],{foreignKey:o,type:r}=i.relationship;o in this._attrs||(r==="belongsTo"?this._attrs[o]=null:r==="hasMany"&&(this._attrs[o]=[]))}}_initRelationshipAccessors(){if(this._relationshipsManager?.relationshipDefs)for(let e in this._relationshipsManager.relationshipDefs){let t=e;Object.hasOwn(this,t)||Object.defineProperty(this,t,{get:()=>this.related(t),set:i=>{this.link(t,i)},enumerable:!1,configurable:!0})}}};var z=class d{_modelName;_collectionName;name(e){if(!e||typeof e!="string"||e.trim()==="")throw new h("Model name must be a non-empty string.");let t=new d;return t._modelName=e,t._collectionName=this._collectionName,t}collection(e){if(!e||typeof e!="string"||e.trim()==="")throw new h("Collection name must be a non-empty string.");let t=new d;return t._modelName=this._modelName,t._collectionName=e,t}attrs(){let e=new d;return e._modelName=this._modelName,e._collectionName=this._collectionName,e}json(){let e=new d;return e._modelName=this._modelName,e._collectionName=this._collectionName,e}build(){if(!this._modelName)throw new h("Model name is required. Call .name() before .build()");if(!this._collectionName)throw new h("Collection name is required. Call .collection() before .build()");return{key:Symbol(`Model:${this._modelName}`),modelName:this._modelName,collectionName:this._collectionName,__attrs:void 0,__json:void 0}}};function Z(){return new z}var N=class{processAssociations(e,t,i,o){let r={};for(let s in t){let n=t[s];if(!n)continue;let a=n.model.collectionName,l=e.getCollection(a);if(!l)throw new h(`Collection '${a}' not found in schema during associations processing`);let c=this._getInverseDefaults(s,i,l.relationships,o);switch(n.type){case"create":r[s]=this._processCreate(l,n.traitsAndDefaults,c);break;case"createMany":r[s]=this._processCreateMany(l,n.count,n.traitsAndDefaults,n.models,c);break;case"link":r[s]=this._processLink(l,n.query,n.traitsAndDefaults);break;case"linkMany":r[s]=this._processLinkMany(l,n.model,n.count,n.query,n.traitsAndDefaults);break}}return r}_getInverseDefaults(e,t,i,o){if(!t||!i||o===void 0)return{};let r=t[e];if(!r||!r.inverse)return{};let s=r.inverse,n=i[s];return n?r.type==="hasMany"&&n.type==="belongsTo"?{[n.foreignKey]:o}:{}:{}}_processCreate(e,t=[],i={}){let o=Object.keys(i).length>0?[i,...t]:t;return e.create(...o)}_processCreateMany(e,t,i,o,r={}){let s=Object.keys(r).length>0;if(o){let n=s?o.map(a=>[r,...a]):o;return e.createMany(n)}else{let n=s?[r,...i??[]]:i??[];return e.createMany(t,...n)}}_processLink(e,t,i){let o=null;if(t){let r=typeof t=="function"?e.findMany({where:t}):e.findMany(t);r.length>0&&(o=this._shuffle(r.models)[0])}else{let r=e.all();r.length>0&&(o=this._shuffle(r.models)[0])}return o||(o=e.create(...i??[])),o}_processLinkMany(e,t,i,o,r){let s;o?s=typeof o=="function"?e.findMany({where:o}):e.findMany(o):s=e.all();let n=this._shuffle(s.models),a=i-n.length;if(a>0){let l=e.createMany(a,...r??[]),c=[...n,...l.models];return new f(t,c)}else{let l=n.slice(0,i);return new f(t,l)}}_shuffle(e){let t=[...e];for(let i=t.length-1;i>0;i--){let o=Math.floor(Math.random()*(i+1));[t[i],t[o]]=[t[o],t[i]]}return t}};var _=class{template;attributes;traits;associations;afterCreate;_associationsManager;constructor(e,t={},i={},o,r){this.template=e,this.attributes=t,this.traits=i,this.associations=o,this.afterCreate=r,this._associationsManager=new N}build(e,...t){let i=e[this.template.collectionName],{defaults:o,traitNames:r}=this._processTraitsAndDefaults(...t),{modelAttrs:s}=M.processAttrs(o,i.relationships),n=s.id??i.dbCollection.nextId;return s.id&&i.identityManager?.set(s.id),this._processAttributes(n,s,r)}runAfterCreateHooks(e,t,...i){let o=i.filter(s=>typeof s=="string"),r=[];return this.afterCreate&&r.push(this.afterCreate),o.forEach(s=>{let n=this.traits?.[s];if(n){let{afterCreate:a}=n;a&&r.push(a)}}),r.forEach(s=>{s(t,e)}),t}runAssociations(e,t,...i){let o=e[this.template.collectionName],{defaults:r,traitNames:s}=this._processTraitsAndDefaults(...i),{relationshipUpdates:n}=M.processAttrs(r,o.relationships),a=this._getAssociations(s,n);return this._associationsManager.processAssociations(e,a,o.relationships,t.id)}_processTraitsAndDefaults(...e){return e.reduce((t,i)=>(typeof i=="string"?t.traitNames.push(i):t.defaults={...t.defaults,...i},t),{defaults:{},traitNames:[]})}_collectTraitAttributes(e){return e.reduce((t,i)=>{let o=this.traits?.[i];if(o){let{afterCreate:r,...s}=o;return{...t,...s}}return t},{})}_evaluateAttributes(e,t){let i=this.template.modelName,o={...t},r=new Set,s=n=>new Proxy(n,{get(a,l){let c=a[l];if(r.has(l))throw new h(`Circular dependency detected in ${i} factory: ${Array.from(r).join(" -> ")} -> ${l}`);return l in a&&typeof c=="function"&&(r.add(l),c=c.call(s(n),e)),n[l]=c,c},set(a,l,c){return a[l]=c,!0}});for(let n in o){let a=o[n];typeof a=="function"&&(r.add(n),o[n]=a.call(s(o),e),r.clear())}return o}_processAttributes(e,t,i){let o=this._collectTraitAttributes(i);return{...this._evaluateAttributes(e,{...this.attributes,...t,...o}),id:e}}_isAssociation(e){return typeof e=="object"&&e!==null&&"type"in e&&"model"in e&&["create","createMany","link","linkMany"].includes(e.type)}_getAssociations(e,t){let i={...this.associations};for(let r of e){let s=this.traits?.[r];if(s){let n=s;for(let a in n){let l=n[a];this._isAssociation(l)&&!(a in i)&&(i[a]=l)}}}let o={};for(let r in i)r in t||(o[r]=i[r]);return o}};var k=class d{_template;_attributes={};_traits={};_associations;_afterCreate;constructor(){}model(e){let t=new d;return t._template=e,t}attrs(e){return this._attributes={...this._attributes,...e},this}traits(e){let t=new d;return t._template=this._template,t._attributes=this._attributes,t._traits={...this._traits,...e},t._afterCreate=this._afterCreate,t._associations=this._associations,t}afterCreate(e){return this._afterCreate=e,this}associations(e){return this._associations=e,this}extend(e){let t=new d;return t._template=e.template,t._attributes={...e.attributes},t._traits={...e.traits},t._associations={...e.associations},t._afterCreate=e.afterCreate,t}build(){if(!this._template)throw new h("Model template must be set before building factory. Call .model() first.");return new _(this._template,this._attributes,this._traits,this._associations,this._afterCreate)}};function Y(){return new k}function D(d,e){let t=`${d.modelName}Id`,i=e?.foreignKey??t;return{collectionName:e?.collectionName??d.collectionName,foreignKey:i,inverse:e?.inverse,targetModel:d,type:"belongsTo"}}function K(d,e){let t=`${d.modelName}Ids`,i=e?.foreignKey??t;return{collectionName:e?.collectionName??d.collectionName,foreignKey:i,inverse:e?.inverse,targetModel:d,type:"hasMany"}}var re={belongsTo:D,hasMany:K},X=re;function $(d,...e){return{type:"create",model:d,traitsAndDefaults:e.length>0?e:void 0}}function O(d,e,...t){return typeof e=="number"?{type:"createMany",model:d,count:e,traitsAndDefaults:t.length>0?t:void 0}:{type:"createMany",model:d,models:e}}function L(d,e,...t){return{type:"link",model:d,query:e,traitsAndDefaults:t.length>0?t:void 0}}function P(d,e,t,...i){return{type:"linkMany",model:d,count:e,query:t,traitsAndDefaults:i.length>0?i:void 0}}var ne={create:$,createMany:O,link:L,linkMany:P},ee=ne;var B=class{template;modelName;collectionName;Model;dbCollection;identityManager;relationships;serializer;_schema;_factory;_fixtures;_seeds;_logger;_loadedSeeds=new Map;constructor(e,t){let{factory:i,identityManager:o,model:r,relationships:s={},serializer:n,seeds:a,fixtures:l}=t;this.template=r,this.modelName=r.modelName,this.collectionName=r.collectionName,this.relationships=s,this.serializer=this._resolveSerializer(r,n),this._schema=e,this._logger=e.logger,this._factory=i??new _(r),this._fixtures=l,this._seeds=a,this.Model=M.define(r);let c=this._resolveIdentityManager(o);this.dbCollection=this._initializeDbCollection(c),this.identityManager=this.dbCollection.identityManager,this._logger?.debug(`Collection '${this.collectionName}' initialized`,{modelName:this.modelName,hasFactory:!!i,hasRelationships:!!s&&Object.keys(s).length>0,hasSeeds:!!a,hasFixtures:!!l})}at(e){this._logger?.log(`Accessing model at index ${e} in '${this.collectionName}'`);let t=this.dbCollection.at(e),i=t?this._createModelFromRecord(t):void 0;return this._logger?.log(`Accessed model at index ${e} in '${this.collectionName}'`,{found:!!i}),i}all(){this._logger?.log(`Fetching all models from '${this.collectionName}'`);let t=this.dbCollection.all().map(i=>this._createModelFromRecord(i));return this._logger?.log(`Fetched ${t.length} models from '${this.collectionName}'`),new f(this.template,t,this.serializer)}first(){this._logger?.log(`Fetching first model from '${this.collectionName}'`);let e=this.dbCollection.first(),t=e?this._createModelFromRecord(e):null;return this._logger?.log(`Fetched first model from '${this.collectionName}'`,{found:!!t}),t}last(){this._logger?.log(`Fetching last model from '${this.collectionName}'`);let e=this.dbCollection.last(),t=e?this._createModelFromRecord(e):null;return this._logger?.log(`Fetched last model from '${this.collectionName}'`,{found:!!t}),t}find(e){this._logger?.log(`Finding model in '${this.collectionName}'`,{input:e});let t=null;if(typeof e=="object"&&"where"in e&&typeof e.where=="function"){let i=this._convertQueryOptionsCallback(e),o=this.dbCollection.find(i);t=o?this._createModelFromRecord(o):null}else{let i=this.dbCollection.find(e);t=i?this._createModelFromRecord(i):null}return this._logger?.log(`Found ${t?1:0} model in '${this.collectionName}'`,{id:t?.id}),t}findMany(e){this._logger?.log(`Finding models in '${this.collectionName}'`,{input:e});let t;if(Array.isArray(e)){let o=this.dbCollection.findMany(e).map(r=>this._createModelFromRecord(r));t=new f(this.template,o,this.serializer)}else if(typeof e=="object"&&("where"in e||"orderBy"in e||"cursor"in e||"offset"in e||"limit"in e)){let o=typeof e.where=="function"?this._convertQueryOptionsCallback(e):e,r=this.dbCollection.findMany(o),s=r.records.map(n=>this._createModelFromRecord(n));t=new f(this.template,s,this.serializer,{query:o,total:r.total})}else{let r=this.dbCollection.findMany(e).map(s=>this._createModelFromRecord(s));t=new f(this.template,r,this.serializer)}return this._logger?.log(`Found ${t.length} models in '${this.collectionName}'`,{ids:t.models.map(i=>i.id)}),t}count(e){this._logger?.log(`Counting models in '${this.collectionName}'`,{where:e});let t=this.dbCollection.count(e);return this._logger?.log(`Counted ${t} models in '${this.collectionName}'`),t}exists(e){this._logger?.log(`Checking existence in '${this.collectionName}'`,{where:e});let t=this.dbCollection.exists(e);return this._logger?.log(`Existence check in '${this.collectionName}': ${t}`),t}delete(e){this._logger?.log(`Deleting model ${e} from '${this.collectionName}'`),this.dbCollection.delete(e),this._logger?.log(`Deleted model ${e} from '${this.collectionName}'`)}deleteMany(e){this._logger?.log(`Deleting models from '${this.collectionName}'`,{input:e});let t;if(typeof e=="object"&&"where"in e&&typeof e.where=="function"){let i=this._convertQueryOptionsCallback(e);t=this.dbCollection.deleteMany(i)}else t=this.dbCollection.deleteMany(e);return this._logger?.log(`Deleted ${t} models from '${this.collectionName}'`),t}resetSeedTracking(){this._loadedSeeds.clear(),this._logger?.debug(`Seed tracking reset for '${this.collectionName}'`)}_convertQueryOptionsCallback(e){if(!e.where||typeof e.where!="function")return e;let t=e.where;return{...e,where:(o,r)=>{let s=this._createModelFromRecord(o);return t(s,r)}}}_createModelFromRecord(e){return new this.Model({attrs:e,relationships:this.relationships,schema:this._schema,serializer:this.serializer})}_resolveSerializer(e,t){if(t)return t instanceof u?t:new u(e,t)}_resolveIdentityManager(e){if(e)return e instanceof g?e:new g(e)}_initializeDbCollection(e){return this._schema.db.hasCollection(this.collectionName)||this._schema.db.createCollection(this.collectionName,{identityManager:e}),this._schema.db.getCollection(this.template.collectionName)}};var j=class extends B{new(e){let t=new this.Model({attrs:e,relationships:this.relationships,schema:this._schema,serializer:this.serializer});return this._logger?.debug(`New model instance created for '${this.collectionName}'`,{id:t.id,attrs:t.attrs}),t}create(...e){this._logger?.log(`Creating model for '${this.collectionName}'`,{collection:this.collectionName,traitsAndDefaults:e});let t=this._factory.build(this._schema,...e);this._logger?.debug(`Built attributes for '${this.collectionName}'`,{id:t.id,attrs:t});let i=this.new(t).save();this._logger?.debug(`Saved model for '${this.collectionName}'`,{id:i.id});let o=this._factory.runAssociations(this._schema,i,...e);return this._logger?.debug(`Processed associations for '${this.collectionName}'`,{id:i.id,relValues:o}),i=i.reload(),Object.keys(o).length>0&&i.update(o),this._factory.runAfterCreateHooks(this._schema,i,...e),i=i.reload(),this._logger?.info(`Created model for '${this.collectionName}'`,{id:i.id,attrs:i.attrs}),i}createMany(e,...t){let i=typeof e=="number"?e:e.length;this._logger?.log(`Creating ${i} models for '${this.collectionName}'`);let o;return typeof e=="number"?o=Array.from({length:e},()=>this.create(...t)):o=e.map(r=>this.create(...r)),this._logger?.info(`Created ${o.length} models for '${this.collectionName}'`,{ids:o.map(r=>r.id)}),new f(this.template,o,this.serializer)}findOrCreateBy(e,...t){let i=this.find(e);return i||this.create(...t,e)}findManyOrCreateBy(e,t,...i){let o=typeof t=="function"?this.findMany({where:t}):this.findMany(t);if(o.length>=e)return this._logger?.info(`Found ${e} existing models for '${this.collectionName}'`,{ids:o.models.slice(0,e).map(a=>a.id)}),new f(this.template,o.models.slice(0,e),this.serializer);let r=e-o.length,s=typeof t=="function"?{}:t,n=Array.from({length:r},()=>this.create(...i,s));return this._logger?.info(`Found ${o.length} and created ${n.length} models for '${this.collectionName}'`,{ids:[...o.models.map(a=>a.id),...n.map(a=>a.id)]}),new f(this.template,[...o.models,...n],this.serializer)}async loadSeeds(e){if(!this._seeds){this._logger?.debug(`No seeds configured for '${this.collectionName}'`);return}let t=typeof this._seeds=="function"?{default:this._seeds}:this._seeds;if(!e){this._logger?.log(`Loading seeds for '${this.collectionName}'`,{scenarios:Object.keys(t)});for(let i in t){if(this._loadedSeeds.has(i)){this._logger?.warn(`Seed scenario '${i}' for '${this.collectionName}' has already been loaded, skipping`,{loadCount:this._loadedSeeds.get(i)});continue}let o=t[i];this._logger?.debug(`Loading seed scenario '${i}' for '${this.collectionName}'`),await o(this._schema),this._loadedSeeds.set(i,(this._loadedSeeds.get(i)||0)+1)}this._logger?.info(`Seeds loaded for '${this.collectionName}'`);return}if(!(e in t)){let i=Object.keys(t).join(", ");throw this._logger?.error(`Seed scenario '${e}' not found`,{collection:this.collectionName,requested:e,available:Object.keys(t)}),new h(`Seed scenario '${e}' does not exist in collection '${this.collectionName}'. Available scenarios: ${i}`)}if(this._loadedSeeds.has(e)){this._logger?.warn(`Seed scenario '${e}' for '${this.collectionName}' has already been loaded, skipping`,{loadCount:this._loadedSeeds.get(e)});return}this._logger?.log(`Loading seed scenario '${e}' for '${this.collectionName}'`),await t[e](this._schema),this._loadedSeeds.set(e,(this._loadedSeeds.get(e)||0)+1),this._logger?.info(`Seed scenario '${e}' loaded for '${this.collectionName}'`)}async loadFixtures(){if(!this._fixtures||!this._fixtures.records.length){this._logger?.debug(`No fixtures configured for '${this.collectionName}'`);return}this._logger?.log(`Loading fixtures for '${this.collectionName}'`,{count:this._fixtures.records.length});let e=this._fixtures.records.map(o=>o.id),t=this.dbCollection.all().map(o=>o.id),i=e.filter(o=>t.includes(o));if(i.length>0)throw this._logger?.error("Fixture loading failed: ID conflicts detected",{collection:this.collectionName,conflicts:i}),new h(`Cannot load fixtures for '${this.collectionName}': ID conflicts detected. The following fixture IDs already exist in the database: ${i.join(", ")}. Clear the database with db.emptyData() before loading fixtures, or use different IDs.`);this.dbCollection.insertMany(this._fixtures.records),this._logger?.info(`Fixtures loaded for '${this.collectionName}'`,{count:this._fixtures.records.length})}};function q(d,e){return new j(d,e)}var ae=["hasMany","belongsTo"],E=class d{_factory;_fixtures;_identityManager;_relationships;_seeds;_serializer;_template;constructor(){}model(e){if(!e||typeof e!="object")throw new h("Invalid model template. Expected a ModelTemplate object created with model().name(...).collection(...).build().");if(!e.modelName)throw new h("Model template is missing modelName property. Ensure you called .name() when building the model.");if(!e.collectionName)throw new h("Model template is missing collectionName property. Ensure you called .collection() when building the model.");let t=new d;return t._template=e,t._factory=this._factory,t._relationships=this._relationships,t._serializer=this._serializer,t._identityManager=this._identityManager,t._seeds=this._seeds,t._fixtures=this._fixtures,t}factory(e){let t=new d;return t._template=this._template,t._factory=e,t._relationships=this._relationships,t._identityManager=this._identityManager,t._serializer=this._serializer,t._seeds=this._seeds,t._fixtures=this._fixtures,t}relationships(e){if(!e||typeof e!="object")throw new h("Invalid relationships configuration. Expected an object with relationship definitions.");for(let i in e){let o=e[i];if(!o||typeof o!="object")throw new h(`Invalid relationship '${i}'. Expected a relationship object created with hasMany() or belongsTo().`);if(!o.type)throw new h(`Relationship '${i}' is missing type property. Use hasMany() or belongsTo() to create relationships.`);if(!ae.includes(o.type))throw new h(`Relationship '${i}' has unsupported type '${o.type}'.
|
|
2
2
|
|
|
3
3
|
Supported relationship types:
|
|
4
4
|
- hasMany: One-to-many relationship (e.g., user.posts)
|
|
5
5
|
- belongsTo: Many-to-one relationship (e.g., post.author)
|
|
6
6
|
|
|
7
|
-
Use hasMany() or belongsTo() helpers to create relationships.`);if(!o.targetModel)throw new h(`Relationship '${
|
|
7
|
+
Use hasMany() or belongsTo() helpers to create relationships.`);if(!o.targetModel)throw new h(`Relationship '${i}' is missing model reference. Ensure the relationship was created with hasMany(model) or belongsTo(model).`)}let t=new d;return t._template=this._template,t._factory=this._factory,t._relationships=e,t._identityManager=this._identityManager,t._serializer=this._serializer,t._seeds=this._seeds,t._fixtures=this._fixtures,t}serializer(e){let t=new d;return t._template=this._template,t._factory=this._factory,t._relationships=this._relationships,t._identityManager=this._identityManager,t._seeds=this._seeds,t._fixtures=this._fixtures,t._serializer=e,t}identityManager(e){let t=new d;return t._template=this._template,t._factory=this._factory,t._relationships=this._relationships,t._identityManager=e,t._serializer=this._serializer,t._seeds=this._seeds,t._fixtures=this._fixtures,t}seeds(e){let t=new d;return t._template=this._template,t._factory=this._factory,t._relationships=this._relationships,t._identityManager=this._identityManager,t._serializer=this._serializer,t._seeds=e,t._fixtures=this._fixtures,t}fixtures(e,t){if(!Array.isArray(e))throw new h("Fixtures must be an array of records. Pass an array of fixture objects with model attributes.");e.forEach((o,r)=>{if(!o||typeof o!="object")throw new h(`Fixture at index ${r} is invalid. Expected an object with model attributes.`);if(o.id===void 0||o.id===null)throw new h(`Fixture at index ${r} is missing required 'id' property. All fixtures must have explicit IDs.`)});let i=new d;return i._template=this._template,i._factory=this._factory,i._relationships=this._relationships,i._identityManager=this._identityManager,i._serializer=this._serializer,i._seeds=this._seeds,i._fixtures={records:e,strategy:t?.strategy??"manual"},i}build(){if(!this._template)throw new h("Model template must be set before building collection. Call .model() first.");return{model:this._template,relationships:this._relationships,factory:this._factory,identityManager:this._identityManager,serializer:this._serializer,seeds:this._seeds,fixtures:this._fixtures}}};function te(){return new E}var I=class{db;logger;_collections=new Map;_defaultIdentityManagerConfig;constructor(e,t){t?.logging?.enabled&&(this.logger=new b(t.logging)),this._defaultIdentityManagerConfig=t?.identityManager,this.db=U({logger:this.logger}),this._registerCollections(e),this.logger&&this.logger.debug("Schema initialized",this.db.dump())}getCollection(e){let t=this._collections.get(e);if(!t)throw new h(`Collection '${String(e)}' not found`);return t}async loadSeeds(e){let t,i=!1;if(typeof e=="object"?(t=e.collectionName,i=e.onlyDefault??!1):t=e,t)this.logger?.log(`Loading seeds for '${String(t)}'${i?" (default only)":""}`),await this.getCollection(t).loadSeeds(i?"default":void 0),this.logger?.info(`Seeds loaded for '${String(t)}'`,this.db.dump());else{this.logger?.log(`Loading all seeds${i?" (default only)":""}`,{collections:Array.from(this._collections.keys())});for(let[o,r]of this._collections)await r.loadSeeds(i?"default":void 0);this.logger?.info("All seeds loaded",this.db.dump())}}async loadFixtures(e){if(e)this.logger?.log(`Loading fixtures for '${String(e)}'`),await this.getCollection(e).loadFixtures(),this.logger?.info(`Fixtures loaded for '${String(e)}'`,this.db.dump());else{this.logger?.log("Loading all fixtures",{collections:Array.from(this._collections.keys())});for(let[t,i]of this._collections)await i.loadFixtures();this.logger?.info("All fixtures loaded",this.db.dump())}}resetSeedTracking(){for(let[e,t]of this._collections)t.resetSeedTracking();this.logger?.log("Seed tracking reset for all collections")}_registerCollections(e){this.logger?.log("Registering collections",{count:Object.keys(e).length,names:Object.keys(e)});let t=[];for(let i in e){let o=e[i],{factory:r,fixtures:s,identityManager:n,model:a,relationships:l,seeds:c,serializer:m}=o,T=this._mergeIdentityManager(n),p=q(this,{model:a,relationships:l,factory:r,identityManager:T,serializer:m,seeds:c,fixtures:s});this._collections.set(i,p),Object.defineProperty(this,i,{configurable:!0,enumerable:!0,get:()=>this._collections.get(i)}),s?.strategy==="auto"&&t.push(p)}if(this.logger?.info("All collections registered",{count:Object.keys(e).length,names:Object.keys(e)}),this._validateInverseRelationships(e),t.length>0){this.logger?.log("Auto-loading fixtures",{collections:t.map(i=>i.collectionName)});for(let i of t)i.loadFixtures()}}_mergeIdentityManager(e){return e instanceof g||e?e:this._defaultIdentityManagerConfig}_validateInverseRelationships(e){for(let t in e){let i=e[t],o=i.relationships;if(o)for(let r in o){let s=o[r];if(s.inverse===void 0||s.inverse===null)continue;let n=s.inverse,a=s.targetModel.collectionName,l=e[a];if(!l)throw new h(`Invalid inverse relationship: '${t}.${r}' declares inverse '${n}' but target collection '${a}' does not exist.`);let c=l.relationships;if(!c||!c[n])throw new h(`Invalid inverse relationship: '${t}.${r}' declares inverse '${n}' but '${a}.${n}' does not exist.`);let m=c[n];if(m.targetModel.collectionName!==i.model.collectionName)throw new h(`Invalid inverse relationship: '${t}.${r}' declares inverse '${n}', but '${a}.${n}' points to '${m.targetModel.collectionName}', not '${t}'.`);m.inverse!==void 0&&m.inverse!==null&&m.inverse!==r&&this.logger?.warn(`Asymmetric inverse relationship: '${t}.${r}' \u2192 '${n}', but '${a}.${n}' \u2192 '${m.inverse||"auto"}'. Consider making inverses mutual for consistency.`)}}}};var V=class d{_collections;_identityManagerConfig;_loggingConfig;constructor(){}collections(e){if(Object.keys(e).length===0)throw new h("Schema must have at least one collection. Provide collection configurations in the collections() method.");let t=["db","getCollection","loadSeeds","loadFixtures","logger"];for(let o of Object.keys(e)){if(t.includes(o))throw new h(`Collection name '${o}' conflicts with existing Schema property or method.
|
|
8
8
|
|
|
9
9
|
The Schema instance has the following built-in properties and methods:
|
|
10
10
|
- schema.db: Database instance
|
|
11
|
-
- schema.
|
|
11
|
+
- schema.logger: Logger instance (if logging enabled)
|
|
12
12
|
- schema.getCollection(): Method to access collections
|
|
13
13
|
- schema.loadSeeds(): Method to load seed data
|
|
14
14
|
- schema.loadFixtures(): Method to load fixture data
|
|
15
15
|
|
|
16
|
-
Please use a different collection name. Reserved names: ${t.join(", ")}`);if(!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(
|
|
16
|
+
Please use a different collection name. Reserved names: ${t.join(", ")}`);if(!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(o))throw new h(`Collection name '${o}' is not a valid JavaScript identifier. Use only letters, numbers, underscores, and dollar signs.`)}let i=new d;return i._collections=e,i._identityManagerConfig=this._identityManagerConfig,i._loggingConfig=this._loggingConfig,i}identityManager(e){let t=new d;return t._collections=this._collections,t._identityManagerConfig=e,t._loggingConfig=this._loggingConfig,t}logging(e){let t=new d;return t._collections=this._collections,t._identityManagerConfig=this._identityManagerConfig,t._loggingConfig=e??this._loggingConfig,t}build(){if(!this._collections)throw new h("SchemaBuilder: collections are required. Call .collections() before .build()");let e={identityManager:this._identityManagerConfig,logging:this._loggingConfig};return new I(this._collections,e)}};function ie(){return new V}export{g as IdentityManager,W as LogLevel,b as Logger,u as Serializer,ee as associations,D as belongsTo,te as collection,$ as create,O as createMany,Y as factory,K as hasMany,L as link,P as linkMany,Z as model,X as relations,G as resolveFactoryAttr,ie as schema};
|
|
17
17
|
//# sourceMappingURL=index.js.map
|