miragejs-orm 0.1.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/LICENSE +21 -0
- package/README.md +17 -0
- package/lib/dist/index.cjs +17 -0
- package/lib/dist/index.cjs.map +1 -0
- package/lib/dist/index.d.cts +3044 -0
- package/lib/dist/index.d.ts +3044 -0
- package/lib/dist/index.js +17 -0
- package/lib/dist/index.js.map +1 -0
- package/package.json +84 -0
|
@@ -0,0 +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}'.
|
|
2
|
+
|
|
3
|
+
Supported relationship types:
|
|
4
|
+
- hasMany: One-to-many relationship (e.g., user.posts)
|
|
5
|
+
- belongsTo: Many-to-one relationship (e.g., post.author)
|
|
6
|
+
|
|
7
|
+
Use hasMany() or belongsTo() helpers to create relationships.`);if(!o.targetModel)throw new h(`Relationship '${s}' is missing model reference. Ensure the relationship was created with hasMany(model) or belongsTo(model).`)}let i=new c;return i._template=this._template,i._factory=this._factory,i._relationships=e,i._identityManager=this._identityManager,i._serializerConfig=this._serializerConfig,i._serializerInstance=this._serializerInstance,i._seeds=this._seeds,i._fixtures=this._fixtures,i}serializer(e){let t=new c;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,e instanceof _?t._serializerInstance=e:t._serializerConfig=e,t}identityManager(e){let t=new c;return t._template=this._template,t._factory=this._factory,t._relationships=this._relationships,t._identityManager=e,t._serializerConfig=this._serializerConfig,t._serializerInstance=this._serializerInstance,t._seeds=this._seeds,t._fixtures=this._fixtures,t}seeds(e){if(typeof e=="object"&&!Array.isArray(e)&&"default"in e)throw new h("The 'default' scenario name is reserved. Please use a different name for your seed scenario.");let t=new c;return t._template=this._template,t._factory=this._factory,t._relationships=this._relationships,t._identityManager=this._identityManager,t._serializerConfig=this._serializerConfig,t._serializerInstance=this._serializerInstance,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((s,o)=>{if(!s||typeof s!="object")throw new h(`Fixture at index ${o} is invalid. Expected an object with model attributes.`);if(s.id===void 0||s.id===null)throw new h(`Fixture at index ${o} is missing required 'id' property. All fixtures must have explicit IDs.`)});let i=new c;return i._template=this._template,i._factory=this._factory,i._relationships=this._relationships,i._identityManager=this._identityManager,i._serializerConfig=this._serializerConfig,i._serializerInstance=this._serializerInstance,i._seeds=this._seeds,i._fixtures={records:e,strategy:t?.strategy??"manual"},i}create(){if(!this._template)throw new h("Model template must be set before creating collection. Call .model() first.");return{model:this._template,relationships:this._relationships,factory:this._factory,identityManager:this._identityManager,serializerConfig:this._serializerConfig,serializerInstance:this._serializerInstance,seeds:this._seeds,fixtures:this._fixtures}}};function ie(){return new W}var k=class{db;identityManager;logger;_collections=new Map;_globalSerializerConfig;constructor(e,t){this.db=H(),this.identityManager=t?.identityManager??new C,this._globalSerializerConfig=t?.globalSerializerConfig,t?.logging?.enabled&&(this.logger=new R(t.logging),this.logger.debug("Schema initialized",{collections:Object.keys(e)})),this._registerCollections(e)}getCollection(e){let t=this._collections.get(e);if(!t)throw new h(`Collection '${String(e)}' not found`);return t}async loadSeeds(){this.logger?.info("Loading seeds for all collections",{collections:Array.from(this._collections.keys())});for(let e of this._collections.values())await e.loadSeeds();this.logger?.info("All seeds loaded successfully")}async loadFixtures(){this.logger?.info("Loading fixtures for all collections",{collections:Array.from(this._collections.keys())});for(let e of this._collections.values())await e.loadFixtures();this.logger?.info("All fixtures loaded successfully")}_registerCollections(e){this.logger?.debug("Registering collections",{count:Object.keys(e).length,names:Object.keys(e)});let t=[];for(let i in e){let s=e[i],{model:o,factory:a,relationships:r,serializerConfig:l,serializerInstance:n,seeds:d,fixtures:T}=s,y=s.identityManager??this.identityManager,m;if(n)m=n;else{let g=this._mergeConfigs(o,l);g&&(m=new _(o,g))}let p=J(this,{model:o,factory:a,identityManager:y,relationships:r,serializer:m,seeds:d,fixtures:T});this._collections.set(i,p),Object.defineProperty(this,i,{configurable:!0,enumerable:!0,get:()=>this._collections.get(i)}),T?.strategy==="auto"&&t.push(p)}if(this.logger?.debug("Collections registered successfully",{count:this._collections.size}),this._validateInverseRelationships(e),t.length>0){this.logger?.info("Auto-loading fixtures",{collections:t.map(i=>i.collectionName)});for(let i of t)i.loadFixtures()}}_validateInverseRelationships(e){for(let t in e){let i=e[t],s=i.relationships;if(s)for(let o in s){let a=s[o];if(a.inverse===void 0||a.inverse===null)continue;let r=a.inverse,l=a.targetModel.collectionName,n=e[l];if(!n)throw new h(`Invalid inverse relationship: '${t}.${o}' declares inverse '${r}' but target collection '${l}' does not exist.`);let d=n.relationships;if(!d||!d[r])throw new h(`Invalid inverse relationship: '${t}.${o}' declares inverse '${r}' but '${l}.${r}' does not exist.`);let T=d[r];if(T.targetModel.collectionName!==i.model.collectionName)throw new h(`Invalid inverse relationship: '${t}.${o}' declares inverse '${r}', but '${l}.${r}' points to '${T.targetModel.collectionName}', not '${t}'.`);T.inverse!==void 0&&T.inverse!==null&&T.inverse!==o&&this.logger?.warn(`Asymmetric inverse relationship: '${t}.${o}' \u2192 '${r}', but '${l}.${r}' \u2192 '${T.inverse||"auto"}'. Consider making inverses mutual for consistency.`)}}}_mergeConfigs(e,t){let i=this._globalSerializerConfig;if(!(!i&&!t))return{root:t?.root??i?.root,embed:t?.embed??i?.embed,attrs:t?.attrs,include:t?.include}}};var G=class c{_collections;_identityManager;_globalSerializerConfig;_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","identityManager","getCollection","loadSeeds","loadFixtures"];for(let s of Object.keys(e)){if(t.includes(s))throw new h(`Collection name '${s}' conflicts with existing Schema property or method.
|
|
8
|
+
|
|
9
|
+
The Schema instance has the following built-in properties and methods:
|
|
10
|
+
- schema.db: Database instance
|
|
11
|
+
- schema.identityManager: ID generation manager
|
|
12
|
+
- schema.getCollection(): Method to access collections
|
|
13
|
+
- schema.loadSeeds(): Method to load seed data
|
|
14
|
+
- schema.loadFixtures(): Method to load fixture data
|
|
15
|
+
|
|
16
|
+
Please use a different collection name. Reserved names: ${t.join(", ")}`);if(!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(s))throw new h(`Collection name '${s}' is not a valid JavaScript identifier. Use only letters, numbers, underscores, and dollar signs.`)}let i=new c;return i._collections=e,i._identityManager=this._identityManager,i._globalSerializerConfig=this._globalSerializerConfig,i._loggingConfig=this._loggingConfig,i}identityManager(e){let t=new c;return t._collections=this._collections,t._identityManager=e,t._globalSerializerConfig=this._globalSerializerConfig,t._loggingConfig=this._loggingConfig,t}serializer(e){let t=new c;return t._collections=this._collections,t._identityManager=this._identityManager,t._globalSerializerConfig=e,t._loggingConfig=this._loggingConfig,t}logging(e){let t=new c;return t._collections=this._collections,t._identityManager=this._identityManager,t._globalSerializerConfig=this._globalSerializerConfig,t._loggingConfig=e,t}setup(){if(!this._collections)throw new h("SchemaBuilder: collections are required. Call .collections() before .setup()");let e={identityManager:this._identityManager,globalSerializerConfig:this._globalSerializerConfig,logging:this._loggingConfig};return new k(this._collections,e)}};function se(){return new G}export{q as NumberIdentityManager,_ as Serializer,C as StringIdentityManager,te as associations,P as belongsTo,ie as collection,B as create,j as createMany,ee as factory,L as hasMany,E as link,V as linkMany,X as model,se as schema};
|
|
17
|
+
//# sourceMappingURL=index.js.map
|