Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@jsiqle/core

Package Overview
Dependencies
Maintainers
1
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@jsiqle/core - npm Package Compare versions

Comparing version 1.0.1 to 1.0.2

2

dist/main.js

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

!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports["@jsiqle/core"]=t():e["@jsiqle/core"]=t()}(global,(function(){return(()=>{"use strict";var e={n:t=>{var r=t&&t.__esModule?()=>t.default:()=>t;return e.d(r,{a:r}),r},d:(t,r)=>{for(var i in r)e.o(r,i)&&!e.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:r[i]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{default:()=>rt});const r=require("events");var i=e.n(r);const s=["fields","key","keyType","methods","scopes","relationships","relationshipField","validators","recordModel","recordValue","recordHandler","recordTag","defaultValue","addScope","addRelationshipAsField","addRelationshipAsMethod","getField","getMethod","removeScope","copyScopes","instances","isRecord","groupTag","get","handleExperimentalAPIMessage"].reduce(((e,t)=>(e[`$${t}`]=Symbol.for(t),e)),{});class o extends Error{constructor(e){super(e),this.name="NameError"}}class a extends Error{constructor(e){super(e),this.name="ValidationError"}}class n extends Error{constructor(e){super(e),this.name="DuplicationError"}}class d extends Error{constructor(e){super(e),this.name="DefaultValueError"}}class l extends Error{constructor(e){super(e),this.name="ExperimentalAPIUsageError"}}class h{static unique(e){return(t,r)=>r.every((r=>r[e]!==t[e]))}static length(e,[t,r]){return i=>i[e].length>=t&&i[e].length<=r}static minLength(e,t){return r=>r[e].length>=t}static maxLength(e,t){return r=>r[e].length<=t}static range(e,[t,r]){return i=>i[e]>=t&&i[e]<=r}static min(e,t){return r=>r[e]>=t}static max(e,t){return r=>r[e]<=t}static integer(e){return t=>Number.isInteger(t[e])}static regex(e,t){return r=>t.test(r[e])}static uniqueValues(e){return t=>new Set(t[e]).size===t[e].length}static sortedAscending(e){return t=>t[e].every(((r,i)=>0===i||r>=t[e][i-1]))}static sortedDescending(e){return t=>t[e].every(((r,i)=>0===i||r<=t[e][i-1]))}static custom(e,t){return(r,i)=>t(r[e],i.map((t=>t[e])))}}const c={Model:["toString","toObject","toJSON"],Field:["toString","toObject","toJSON"],Relationship:["toString","toObject","toJSON"]},m=(e,t)=>{const[r,i]=((e,t=[])=>"string"!=typeof e?[!1,"must be a string"]:e?/^\d/.test(e)?[!1,"cannot start with a number"]:t.includes(e)?[!1,"is reserved"]:[/^\w+$/.test(e),"must contain only alphanumeric characters, numbers or underscores"]:[!1,"is required"])(t,c[e]);if(!r)throw new o(`${e} name ${i}.`);return t},u=([e,...t])=>e.toUpperCase()+t.join(""),p=([e,...t])=>e.toLowerCase()+t.join(""),f=e=>{if(null===e)return null;let t=Object.assign({},e);return Object.entries(t).forEach((([r,i])=>t[r]="object"==typeof e[r]?f(i):i)),Array.isArray(e)?(t.length=e.length,Array.from(t)):t},y=({objectType:e,parentType:t,parentName:r},i,s)=>{if(!(e=>e&&"object"==typeof e)(i))throw new TypeError(`${e} ${i} is not an object.`);if(((e,t)=>e.includes(t))(s,i.name))throw new n(`${t} ${r} already has a ${e.toLowerCase()} named ${i.name}.`);return!0},g=e=>"boolean"==typeof e,w=e=>"number"==typeof e&&e==e,b=e=>"string"==typeof e,v=e=>e instanceof Date,$=(...e)=>t=>e.every((e=>e(t))),M=(...e)=>t=>e.some((e=>e(t))),R=e=>e>=0,F=e=>t=>Array.isArray(t)&&t.every(e),T=e=>{const t=Object.keys(e);return r=>null!=r&&"object"==typeof r&&(Object.keys(r).length===t.length&&t.every((t=>e[t](r[t]))))},O=e=>t=>null!=t&&"object"==typeof t&&Object.keys(t).every((r=>e(t[r]))),S=e=>null===e,j=e=>void 0===e,E=M(S,j),V={bool:g,number:w,positiveNumber:$(w,R),string:b,date:v,stringOrNumber:M(b,w),numberOrString:M(b,w),enum:(...e)=>t=>e.includes(t),boolArray:F(g),numberArray:F(w),stringArray:F(b),dateArray:F(v),oneOf:M,arrayOf:F,oneOrArrayOf:e=>t=>M(F(e),e)(t),object:T,objectOf:O,optional:e=>t=>M(E,e)(t),null:S,undefined:j,nil:E},A={boolean:{type:g,defaultValue:!1},number:{type:w,defaultValue:0},positiveNumber:{type:$(w,R),defaultValue:0},string:{type:b,defaultValue:""},date:{type:v,defaultValue:new Date},stringOrNumber:{type:M(b,w),defaultValue:""},numberOrString:{type:M(b,w),defaultValue:0},booleanArray:{type:F(g),defaultValue:[]},numberArray:{type:F(w),defaultValue:[]},stringArray:{type:F(b),defaultValue:[]},dateArray:{type:F(v),defaultValue:[]},object:{type:T({}),defaultValue:{}},booleanObject:{type:O(g),defaultValue:{a:!0}},numberObject:{type:O(w),defaultValue:{}},stringObject:{type:O(b),defaultValue:{}},dateObject:{type:O(v),defaultValue:{}},objectArray:{type:F(T({})),defaultValue:[]}},k=$(b,(e=>0!==e.trim().length)),{$defaultValue:N,$validators:x}=s;class C{#e;#t;#r;#i;#s;constructor({name:e,type:t,required:r=!1,defaultValue:i=null,validators:s={}}){this.#e=m("Field",e),this.#r=C.#o(r),this.#i=C.#a(t,r),this.#t=C.#n(i,this.#i,this.#r),this.#s=new Map,Object.entries(s).forEach((([e,t])=>{this.addValidator(e,t)}))}addValidator(e,t){this.#s.set(...C.#d(this.#e,e,t))}get name(){return this.#e}get required(){return this.#r}typeCheck(e){return this.#i(e)}get[N](){return this.#t}get[x](){return this.#s}static#a(e,t){if("function"!=typeof e)throw new TypeError("Field type must be a function.");return t?e:V.optional(e)}static#o(e){if("boolean"!=typeof e)throw new TypeError("Field required must be a boolean.");return e}static#n(e,t,r){if(r&&V.nil(e))throw new a("Default value cannot be null or undefined.");if(!t(e))throw new a("Default value must be valid.");return e}static#d(e,t,r){if(void 0!==h[t])return[`${e}${u(t)}`,h[t](e,r)];if("function"!=typeof r)throw new TypeError(`Validator ${t} is not defined.`);return[`${e}${u(t)}`,h.custom(e,r)]}}Object.entries(A).forEach((([e,t])=>{const{type:r,defaultValue:i}=t;C[e]=e=>new C("string"==typeof e?{name:e,type:r}:{...e,type:r}),C[`${e}Required`]=e=>{if("string"==typeof e)return new C({name:e,type:r,required:!0,defaultValue:i});const t=e.defaultValue||i;return new C({...e,type:r,required:!0,defaultValue:t})}})),C.enum=({name:e,values:t})=>new C({name:e,type:V.enum(...t)}),C.enumRequired=({name:e,values:t,defaultValue:r=t[0]})=>new C({name:e,type:V.enum(...t),required:!0,defaultValue:r}),C.auto=e=>{const t="string"==typeof e?e:e.name,r=function*(){let e=0;for(;;)yield e++}();let i=0;const s=new C({name:t,type:e=>e===i,required:!0,defaultValue:i});return Object.defineProperty(s,N,{get(){const e=r.next().value;return i=e,e}}),s};const{$recordValue:q,$recordHandler:z,$recordModel:P,$recordTag:K,$key:I}=s;class H{#l;#h;constructor(e,t){return this.#l=e,this.#h=t,new Proxy(this,this.#h)}get[z](){return this.#h}get[q](){return this.#l}get[P](){return this.#h.model}get[K](){const e=this[P],t=e[I].name;return`${e.name}#${this[q][t]}`}get[Symbol.toStringTag](){return this[K]}}const D=H,{$recordTag:_}=s;class J{#c;constructor(e,t){Object.keys(e).forEach((t=>{this[t]=e[t]})),this.#c=t}get[_](){return this.#c}get[Symbol.toStringTag](){return this[_]}toObject(){return{...this}}toJSON(){return this.toObject()}}const{$recordTag:U}=s;class L extends Array{#c;constructor(e,t){super(),e.forEach((e=>{this.push(e)})),this.#c=t}get[U](){return this.#c}get[Symbol.toStringTag](){return this[U]}toObject(){return[...this]}toJSON(){return this.toObject()}}const{$recordModel:B,$recordTag:G,$scopes:Q,$addScope:W,$removeScope:X,$copyScopes:Y,$isRecord:Z,$key:ee,$handleExperimentalAPIMessage:te}=s;class re extends Map{#m;#u;constructor({iterable:e=[],copyScopesFrom:t=null}={}){super();for(const[t,r]of e)this.set(t,r);this.#u=new Map,t&&this[Y](t),this.#m=!1}freeze(){return this.#m=!0,this}set(e,t){if(tt[te]("Calling RecordSet.prototype.set() is discouraged as it may cause unexpected behavior. This method may be removed in a future version of the library."),this.#m)throw new TypeError("Cannot modify a frozen RecordSet.");return super.set(e,t),this}delete(e){if(this.#m)throw new TypeError("Cannot modify a frozen RecordSet.");return super.delete(e)}clear(){if(this.#m)throw new TypeError("Cannot modify a frozen RecordSet.");super.clear()}map(e){return[...this.entries()].reduce(((t,[r,i])=>(t[r]=e(i,r,this),t)),{})}flatMap(e){return[...this.entries()].map((([t,r])=>e(r,t,this)))}reduce(e,t){return[...this.entries()].reduce(((t,[r,i])=>e(t,i,r,this)),t)}filter(e){return[...this.entries()].reduce(((t,[r,i])=>(e(i,r,this)&&t.set(r,i),t)),new re({copyScopesFrom:this})).freeze()}flatFilter(e){return[...this.entries()].reduce(((t,[r,i])=>(e(i,r,this)&&t.push(i),t)),[])}find(e){const t=[...this.entries()].find((([t,r])=>e(r,t,this)));if(t)return t[1]}findKey(e){const t=[...this.entries()].find((([t,r])=>e(r,t,this)));if(t)return t[0]}only(...e){return new re({iterable:[...this.entries()].filter((([t])=>e.includes(t))),copyScopesFrom:this}).freeze()}except(...e){return new re({iterable:[...this.entries()].filter((([t])=>!e.includes(t))),copyScopesFrom:this}).freeze()}sort(e){const t=[...this.entries()].sort((([t,r],[i,s])=>e(r,s,t,i)));return new re({iterable:t,copyScopesFrom:this}).freeze()}every(e){return 0===this.size||[...this.entries()].every((([t,r])=>e(r,t,this)))}some(e){return 0!==this.size&&[...this.entries()].some((([t,r])=>e(r,t,this)))}select(...e){return new re({iterable:[...this.entries()].map((([t,r])=>{const i={};return e.forEach((e=>i[e]=r[e])),[t,new J(i,r[G])]})),copyScopesFrom:this}).freeze()}flatSelect(...e){return[...this.values()].map((t=>e.reduce(((e,r)=>({...e,[r]:t[r]})),{})))}pluck(...e){return new re({iterable:[...this.entries()].map((([t,r])=>{const i=e.map((e=>r[e]));return[t,new L(i,r[G])]})),copyScopesFrom:this}).freeze()}flatPluck(...e){const t=1===e.length;return[...this.values()].map((r=>t?r[e[0]]:e.map((e=>r[e]))))}groupBy(e){const t=new re({copyScopesFrom:this,iterable:[]});for(const[r,i]of this.entries()){let s=i[e];null!=s&&s[Z]&&(s=i[e][ee]),t.has(s)||t.set(s,new oe({copyScopesFrom:this,iterable:[],groupName:s})),t.get(s).set(r,i)}for(const e of t.values())e.freeze();return t.freeze()}where(e){return this.filter(e)}whereNot(e){return this.filter(((t,r,i)=>!e(t,r,i)))}*batchIterator(e){let t=[];for(const[,r]of this)t.push(r),t.length===e&&(yield t,t=[]);t.length&&(yield t)}limit(e){let t=[];for(const[r,i]of this)if(t.push([r,i]),t.length===e)break;return new re({iterable:t,copyScopesFrom:this}).freeze()}offset(e){let t=0,r=[];for(const[i,s]of this)t<e?t++:r.push([i,s]);return new re({iterable:r,copyScopesFrom:this}).freeze()}get first(){for(const[,e]of this)return e}get last(){if(0!==this.size)return[...this.entries()].pop()[1]}get count(){return this.size}toArray(){return[...this.values()]}toFlatArray(){return[...this.values()].map((e=>e instanceof oe?e.toFlatArray():e.toObject()))}toObject(){return[...this.entries()].reduce(((e,[t,r])=>(e[t]=r,e)),{})}toFlatObject(){return[...this.entries()].reduce(((e,[t,r])=>(e[t]=r instanceof oe?r.toFlatArray():r.toObject(),e)),{})}toJSON(){return this.toObject()}get[Symbol.toStringTag](){const e=[...this.values()];try{const t=e[0][B].name;if(((e,t)=>{const r=t(e[0]);return e.every((e=>t(e)===r))})(e,(e=>e[B].name===t)))return t}catch(e){return""}return""}static get[Symbol.species](){return Map}[W](e,t){if(re.#p("Scope",e,t,this.#u),this[e]||Object.getOwnPropertyNames(re.prototype).includes(e))throw new o(`Scope name ${e} is already in use.`);this.#u.set(e,t),Object.defineProperty(this,e,{configurable:!0,get:()=>this.where(this.#u.get(e))})}[X](e){this.#u.delete(re.#f("Scope",e,this.#u)),delete this[e]}[Y](e){e[Q].forEach(((e,t)=>{this[W](t,e)}))}get[Q](){return this.#u}static#p(e,t,r,i){if("function"!=typeof r)throw new TypeError(`${e} ${t} is not a function.`);if(i.has(t))throw new n(`${e} ${t} already exists.`);return r}static#f(e,t,r){if(!r.has(t))throw new ReferenceError(`${e} ${t} does not exist.`);return t}}const ie=re,{$groupTag:se}=s;class oe extends ie{#y;constructor({iterable:e=[],copyScopesFrom:t=null,groupName:r=""}={}){super({iterable:e,copyScopesFrom:t}),this.#y=r}get[se](){return this.#y}get[Symbol.toStringTag](){return this[se]}}const{$fields:ae,$defaultValue:ne,$key:de,$keyType:le,$methods:he,$relationships:ce,$validators:me,$recordValue:ue,$recordModel:pe,$recordTag:fe,$isRecord:ye,$get:ge}=s;class we{#g;constructor(e){this.#g=e}get model(){return this.#g}createRecord(e){if(!e)throw new TypeError("Record data cannot be empty.");if("object"!=typeof e)throw new TypeError("Record data must be an object.");const t=this.#w(),r=we.#b(t,this.#v(),e[this.#v().name],this.#g.records),i=f(e),s=Object.keys(i).filter((e=>!this.#$(e)&&!this.#M(e)));s.length>0&&console.warn(`${t} record has extra fields: ${s.join(", ")}.`);const o=new D({[this.#v().name]:r,...s.reduce(((e,t)=>({...e,[t]:i[t]})),{})},this);return this.#R().forEach((e=>{this.set(o,e,i[e],o,!0)})),this.#F().forEach(((e,i)=>{if(!e(o,this.#g.records))throw new RangeError(`${t} record with key ${r} failed validation for ${i}.`)})),[r,o]}get(e,t){return this.#T(t)?this.#O(e,t):this.#M(t)||this.#$(t)?this.#S(e,t):this.#j(t)?this.#E(e,t):this.#V(t)?we.#A(e,this.#g,this):this.#k(t)?()=>this.#N(e):this.#x(t)?this.#C(e,t):void 0}set(e,t,r,i,s){const o=e[ue],a=this.#N(e),n=this.#g.records.except(a);if(this.#j(t))throw new TypeError(`${this.#w()} record ${a} cannot set method ${t}.`);if(this.#$(t)){const e=this.#q(t);we.#z(this.#g.name,o,e,r),e[me].forEach(((e,r)=>{if(![null,void 0].includes(o[t])&&!e(o,n))throw new RangeError(`${this.#w()} record with key ${a} failed validation for ${r}.`)}))}else console.warn(`${this.#g.name} record has extra field: ${t}.`),o[t]=r;return s||this.#F().forEach(((e,t)=>{if(!e(o,n))throw new RangeError(`${this.#w()} record with key ${a} failed validation for ${t}.`)})),!0}static#z(e,t,r,i){const s=r.required&&V.nil(i)?r[ne]:i;if(!r.typeCheck(s))throw new TypeError(`${e} record has invalid value for field ${r.name}.`);t[r.name]=s}static#A(e,t,r){const i=e[ue],s=t[ae],o=t[he],a=t[de].name,n={[a]:i[a]};return s.forEach((e=>{void 0!==i[e.name]&&(n[e.name]=i[e.name])})),({include:t=[]}={})=>{let i=n;return t.map((e=>{const[t,...r]=e.split(".");return[t,r.join(".")]})).forEach((([t,i])=>{if(n[t])if(Array.isArray(n[t])){const s=r.get(e,t);n[t]=s.map((e=>e.toObject({include:[i]})))}else n[t]=r.get(e,t).toObject({include:[i]});else o.has(t)&&(n[t]=r.get(e,t))})),i}}static#b=(e,t,r,i)=>{let s=r;if("string"===t[le]&&!t.typeCheck(s))throw new TypeError(`${e} record has invalid value for key ${t.name}.`);if("auto"===t[le]&&(s=t[ne]),i.has(s))throw new n(`${e} record with key ${s} already exists.`);return s};#w(){return this.#g.name}#R(){return[...this.#g[ae].keys()]}#F(){return this.#g[me]}#M(e){return this.#g[de].name===e}#v(){return this.#g[de]}#N(e){return e[ue][this.#g[de].name]}#$(e){return this.#g[ae].has(e)}#q(e){return this.#g[ae].get(e)}#S(e,t){return e[ue][t]}#j(e){return this.#g[he].has(e)}#E(e,t){return this.#g[he].get(t)(e[ue])}#T(e){return!!this.#$(e)&&this.#g[ce].has(`${e}.${e}`)}#O(e,t){return this.#g[ce].get(`${t}.${t}`)[ge](this.#w(),t,e[ue])}#V(e){return"toObject"===e||"toJSON"===e}#k(e){return"toString"===e}#x(e){return[pe,fe,ue,ye,de].includes(e)}#C(e,t){return t===ye||(t===de&&this.#v(),e[t])}}const be=we,{$fields:ve,$defaultValue:$e,$key:Me,$keyType:Re,$methods:Fe,$scopes:Te,$relationships:Oe,$validators:Se,$recordHandler:je,$addScope:Ee,$addRelationshipAsField:Ve,$addRelationshipAsMethod:Ae,$getField:ke,$getMethod:Ne,$removeScope:xe,$instances:Ce,$handleExperimentalAPIMessage:qe}=s,ze=[...Object.keys(A),...Object.keys(A).map((e=>`${e}Required`)),"enum","enumRequired","auto"];class Pe extends(i()){#P;#h;#K;#I;#H;#D;#s;#_=!1;static#J=new Map;constructor({name:e,fields:t=[],key:r="id",methods:i={},scopes:s={},validators:o={}}={}){if(super(),this.name=m("Model",e),Pe.#J.has(e))throw new n(`A model named ${e} already exists.`);this.#P=new ie,this.#h=new be(this),this.#I=Pe.#U(this.name,r),this.#K=new Map,this.#H=new Map,this.#D=new Map,this.#s=new Map,t.forEach((e=>this.addField(e))),Object.entries(i).forEach((([e,t])=>{this.addMethod(e,t)})),Object.entries(s).forEach((([e,t])=>{this.addScope(e,t)})),Object.entries(o).forEach((([e,t])=>{this.addValidator(e,t)})),Pe.#J.set(this.name,this)}addField(e,t){this.#_||this.emit("beforeAddField",{field:e,model:this});const r=Pe.#L(this.name,e,[...this.#K.keys(),this.#I.name,...this.#H.keys()]);return this.#K.set(e.name,r),this.#_||this.emit("fieldAdded",{field:r,model:this}),this.emit("beforeRetrofillField",{field:r,retrofill:t,model:this}),Pe.#B(r,this.#P,t),this.emit("fieldRetrofilled",{field:r,retrofill:t,model:this}),this.#_||this.emit("change",{type:"fieldAdded",field:r,model:this}),r}removeField(e){if(!Pe.#f(this.name,"Field",e,this.#K))return!1;const t=this.#K.get(e);return this.#_||this.emit("beforeRemoveField",{field:t,model:this}),this.#K.delete(e),this.#_||(this.emit("fieldRemoved",{field:{name:e},model:this}),this.emit("change",{type:"fieldRemoved",field:t,model:this})),!0}updateField(e,t,r){if(t.name!==e)throw new o(`Field name ${t.name} does not match ${e}.`);if(!Pe.#f(this.name,"Field",e,this.#K))throw new ReferenceError(`Field ${e} does not exist.`);const i=this.#K.get(e);this.#_=!0,this.emit("beforeUpdateField",{prevField:i,field:t,model:this}),this.removeField(e);const s=this.addField(t,r);this.emit("fieldUpdated",{field:s,model:this}),this.#_=!1,this.emit("change",{type:"fieldUpdated",field:s,model:this})}addMethod(e,t){this.emit("beforeAddMethod",{method:{name:e,body:t},model:this});const r=m("Method",e);this.#H.set(r,Pe.#p("Method",e,t,[...this.#K.keys(),this.#I.name,...this.#H.keys()])),this.emit("methodAdded",{method:{name:r,body:t},model:this}),this.emit("change",{type:"methodAdded",method:{name:r,body:t},model:this})}removeMethod(e){if(!Pe.#f(this.name,"Method",e,this.#H))return!1;const t=this.#H.get(e);return this.emit("beforeRemoveMethod",{method:{name:e,body:t},model:this}),this.#H.delete(e),this.emit("methodRemoved",{method:{name:e},model:this}),this.emit("change",{type:"methodRemoved",method:{name:e,body:t},model:this}),!0}addScope(e,t){this.emit("beforeAddScope",{scope:{name:e,body:t},model:this});const r=m("Scope",e);this.#P[Ee](r,t),this.emit("scopeAdded",{scope:{name:r,body:t},model:this}),this.emit("change",{type:"scopeAdded",scope:{name:r,body:t},model:this})}removeScope(e){if(!Pe.#f(this.name,"Scope",e,this.#P[Te]))return!1;const t=this.#P[Te].get(e);return this.emit("beforeRemoveScope",{scope:{name:e,body:t},model:this}),this.#P[xe](e),this.emit("scopeRemoved",{scope:{name:e},model:this}),this.emit("change",{type:"scopeRemoved",scope:{name:e,body:t},model:this}),!0}addValidator(e,t){this.emit("beforeAddValidator",{validator:{name:e,body:t},model:this}),this.#s.set(e,Pe.#p("Validator",e,t,[...this.#s.keys()])),this.emit("validatorAdded",{validator:{name:e,body:t},model:this}),this.emit("change",{type:"validatorAdded",validator:{name:e,body:t},model:this})}removeValidator(e){if(!Pe.#f(this.name,"Validator",e,this.#s))return!1;const t=this.#s.get(e);return this.emit("beforeRemoveValidator",{validator:{name:e,body:t},model:this}),this.#s.delete(e),this.emit("validatorRemoved",{validator:{name:e},model:this}),this.emit("change",{type:"validatorRemoved",validator:{name:e,body:t},model:this}),!0}createRecord(e){this.emit("beforeCreateRecord",{record:e,model:this});const[t,r]=this.#h.createRecord(e);return this.#P.set(t,r),this.emit("recordCreated",{newRecord:r,model:this}),r}removeRecord(e){if(!this.#P.has(e))return console.warn(`Record ${e} does not exist.`),!1;const t=this.#P.get(e);return this.emit("beforeRemoveRecord",{record:t,model:this}),this.#P.delete(e),this.emit("recordRemoved",{record:{[this.#I.name]:e},model:this}),!0}updateRecord(e,t){if("object"!=typeof t)throw new TypeError("Record data must be an object.");if(!this.#P.has(e))throw new ReferenceError(`Record ${e} does not exist.`);const r=this.#P.get(e);return this.emit("beforeUpdateRecord",{record:r,newRecord:{[this.#I.name]:e,...t},model:this}),Object.entries(t).forEach((([e,t])=>{r[e]=t})),this.emit("recordUpdated",{record:r,model:this}),r}get records(){return this.#P}static get[Ce](){return Pe.#J}get[je](){return this.#h}get[ve](){return this.#K}get[Me](){return this.#I}get[Fe](){return this.#H}get[Oe](){return this.#D}get[Se](){return this.#s}[Ve](e){const{name:t,type:r,fieldName:i,field:s}=e[ke](),a=`${t}.${i}`;if(this.emit("beforeAddRelationship",{relationship:{name:t,type:r},model:this}),[...this.#K.keys(),this.#I.name,...this.#H.keys()].includes(i))throw new o(`Relationship field ${i} is already in use.`);if(this.#D.has(a))throw new o(`Relationship ${a} is already in use.`);this.#K.set(i,s),this.#D.set(a,e),this.emit("relationshipAdded",{relationship:{name:t,type:r},model:this}),this.emit("change",{type:"relationshipAdded",relationship:{relationship:{name:t,type:r},model:this},model:this})}[Ae](e){const{name:t,type:r,methodName:i,method:s}=e[Ne](),a=`${t}.${i}`;if(this.emit("beforeAddRelationship",{relationship:{name:t,type:r},model:this}),[...this.#K.keys(),this.#I.name,...this.#H.keys()].includes(i))throw new o(`Relationship method ${i} is already in use.`);if(this.#D.has(a))throw new o(`Relationship ${t} is already in use.`);this.#H.set(i,s),this.#D.set(a,e),this.emit("relationshipAdded",{relationship:{name:t,type:r},model:this}),this.emit("change",{type:"relationshipAdded",relationship:{relationship:{name:t,type:r},model:this},model:this})}static#G(e){let t,r="id",i="string";return"string"==typeof e?r=e:"object"==typeof e&&(r=e.name||r,i=e.type||i),"string"===i?(t=new C({name:r,type:k,required:!0,defaultValue:"__emptyKey__"}),Object.defineProperty(t,$e,{get(){throw new d(`Key field ${r} does not have a default value.`)}})):"auto"===i&&(t=C.auto(r)),Object.defineProperty(t,Re,{get:()=>i}),t}static#U(e,t){if("string"!=typeof t&&"object"!=typeof t)throw new TypeError(`${e} key ${t} is not a string or object.`);if("object"==typeof t&&!t.name)throw new TypeError(`${e} key ${t} is missing a name.`);if("object"==typeof t&&!["auto","string"].includes(t.type))throw new TypeError(`${e} key ${t} type must be either "string" or "auto".`);return Pe.#G(t)}static#L(e,t,r){return y({objectType:"Field",parentType:"Model",parentName:e},t,r),ze.includes(t.type)?C[t.type](t):("function"==typeof t.type&&tt[qe](`The provided type for ${t.name} is not part of the standard types. Function types are experimental and may go away in a later release.`),new C(t))}static#p(e,t,r,i){if("function"!=typeof r)throw new TypeError(`${e} ${t} is not a function.`);if(i.includes(t))throw new n(`${e} ${t} already exists.`);return r}static#f(e,t,r,i){return!!i.has(r)||(console.warn(`Model ${e} does not contain a ${t.toLowerCase()} named ${r}.`),!1)}static#B(e,t,r){if(!e.required&&void 0===r)return;const i=void 0!==r?"function"==typeof r?r:()=>r:t=>t[e.name]?t[e.name]:e[$e];t.forEach((t=>{t[e.name]=i(t)}))}}const{$key:Ke,$recordValue:Ie,$fields:He,$getField:De,$getMethod:_e,$get:Je,$defaultValue:Ue,$instances:Le,$handleExperimentalAPIMessage:Be}=s,Ge={oneToOne:"oneToOne",oneToMany:"oneToMany",manyToOne:"manyToOne",manyToMany:"manyToMany"};class Qe{#i;#Q;#W;#e;#X;#Y;#Z;constructor({from:e,to:t,type:r}={}){tt[Be]("Relationships are experimental in the current version. There is neither validation of existence in foreign tables nor guarantee that associations work. Please use with caution."),this.#i=Qe.#a(r);const[i,s,o,a]=Qe.#ee(e,t,r);if(this.#Q=i,this.#W=o,this.#e=s,this.#X=a,this.#W===this.#Q&&Qe.#te(this.#i)&&this.#e===this.#X)throw new RangeError("Relationship cannot be symmetric if the from and to models are the same and no name is provided for either one.");this.#Y=Qe.#re(this.#e,this.#i,this.#W[Ke]),this.#Z=e=>this.#ie(e)}[De](){return{name:this.#e,type:this.#i,fieldName:this.#e,field:this.#Y}}[_e](){return{name:this.#e,type:this.#i,methodName:this.#X,method:this.#Z}}[Je](e,t,r){return e===this.#Q.name&&t===this.#e?this.#se(r):e===this.#W.name&&t===this.#X?(console.warn("Relationship getter called by the receiver model. This might indicate an issue with the library and should be reported."),this.#ie(r)):void 0}#se(e){if(Qe.#oe(this.#i)){const t=e[this.#e];return this.#W.records.get(t)}const t=e[this.#e]||[],r=this.#W[Ke].name;return this.#W.records.where((e=>t.includes(e[r])))}#ie(e){const t=e[this.#W[Ke].name],r=Qe.#oe(this.#i)?e=>e[Ie][this.#e]===t:e=>{const r=e[Ie][this.#e];return![void 0,null].includes(r)&&e[Ie][this.#e].includes(t)};return Qe.#ae(this.#i)?this.#Q.records.find(r):this.#Q.records.where(r)}static#oe(e){return[Ge.oneToOne,Ge.manyToOne].includes(e)}static#ne(e){return[Ge.oneToMany,Ge.manyToMany].includes(e)}static#ae(e){return[Ge.oneToMany,Ge.oneToOne].includes(e)}static#de(e){return[Ge.manyToOne,Ge.manyToMany].includes(e)}static#te(e){return[Ge.oneToOne,Ge.manyToMany].includes(e)}static#re(e,t,r){const i=Qe.#ae(t),s=Qe.#ne(t),o=s?V.arrayOf((e=>r.typeCheck(e))):e=>r.typeCheck(e),a={};i&&!s&&(a.unique=!0),s&&(a.uniqueValues=!0);const n=new C({name:e,type:o,required:!1,defaultValue:s?[]:null,validators:a});return Object.defineProperty(n,Ue,{get(){throw new d("Relationship field does not have a default value.")}}),n}static#a(e){if(!Object.values(Ge).includes(e))throw new TypeError(`Invalid relationship type: ${e}.`);return e}static#le(e){const t="string"==typeof e?e:e.model;if(!Pe[Le].has(t))throw new ReferenceError(`Model ${t} does not exist.`);return Pe[Le].get(t)}static#he(e,t){return Qe.#oe(e)?p(t):Qe.#ne(e)?`${p(t)}Set`:void 0}static#ce=(e,t)=>Qe.#ae(e)?p(t):Qe.#de(e)?`${p(t)}Set`:void 0;static#me(e){const t=Qe.#le(e),r="string"==typeof e?null:m("Field",e.name);if(null!==r&&t[He].has(r))throw new n(`Field ${r} already exists in ${t.name}.`);return[t,r]}static#ee(e,t,r){let i,s,o,a;return[i,s]=Qe.#me(e),[o,a]=Qe.#me(t),null===s&&(s=Qe.#he(r,o.name)),null===a&&(a=Qe.#ce(r,i.name)),[i,s,o,a]}}const{$addRelationshipAsField:We,$addRelationshipAsMethod:Xe,$handleExperimentalAPIMessage:Ye,$key:Ze,$keyType:et}=s;class tt extends(i()){#e;#ue;static defaultConfig={experimentalAPIMessages:"warn"};static config={...tt.defaultConfig};static#pe=new Map;constructor({name:e,models:t=[],config:r={}}={}){super(),this.#e=m("Schema",e),this.#ue=new Map,tt.#fe(r),tt.#pe.set(this.#e,this),t.forEach((e=>this.createModel(e)))}createModel(e){this.emit("beforeCreateModel",{model:e,schema:this});const t=tt.#ye(this.#e,e,this.#ue);return this.#ue.set(t.name,t),t.on("change",(({type:e,...t})=>{this.emit("change",{type:`model${u(e)}`,...t,schema:this})})),this.emit("modelCreated",{model:t,schema:this}),this.emit("change",{type:"modelCreated",model:t,schema:this}),t}getModel(e){return this.#ue.get(e)}removeModel(e){const t=this.getModel(e);if(this.emit("beforeRemoveModel",{model:t,schema:this}),!this.#ue.has(e))throw new ReferenceError(`Model ${e} does not exist in schema ${this.#e}.`);this.#ue.delete(e),this.emit("modelRemoved",{model:{name:e},schema:this}),this.emit("change",{type:"modelRemoved",model:t,schema:this})}createRelationship(e){this.emit("beforeCreateRelationship",{relationship:e,schema:this});const t=tt.#ge(this.#e,e,this.#ue);return this.emit("relationshipCreated",{relationship:t,schema:this}),this.emit("change",{type:"relationshipCreated",relationship:t,schema:this}),t}get name(){return this.#e}get models(){return this.#ue}static create(e){return new tt(e)}static get(e){return tt.#pe.get(e)}get(e){this.emit("beforeGet",{pathName:e,schema:this});const[t,r,...i]=e.split("."),s=this.getModel(t);if(!s)throw new ReferenceError(`Model ${t} does not exist in schema ${this.#e}.`);if(void 0===r)return s;const o=s[Ze][et],a=s.records.get("string"===o?r:Number.parseInt(r));if(!i.length)return a;if(!a)throw new ReferenceError(`Record ${r} does not exist in model ${t}.`);const n=i.reduce(((e,t)=>e[t]),a);return this.emit("got",{pathName:e,result:n,schema:this}),n}static[Ye](e){const{experimentalAPIMessages:t}=tt.config;if("warn"===t)console.warn(e);else if("error"===t)throw new l(e)}static#ye(e,t,r){return y({objectType:"Model",parentType:"Schema",parentName:e},t,[...r.keys()]),new Pe(t)}static#ge(e,t,r){const{from:i,to:s,type:o}=t;[i,s].forEach((e=>{if(!["string","object"].includes(typeof e))throw new TypeError(`Invalid relationship model: ${e}.`)}));const a="string"==typeof i?i:i.model,n="string"==typeof s?s:s.model,d=r.get(a),l=r.get(n);if(!d)throw new ReferenceError(`Model ${a} not found in schema ${e} when attempting to create a relationship.`);if(!l)throw new ReferenceError(`Model ${n} not found in schema ${e} when attempting to create a relationship.`);const h=new Qe({from:i,to:s,type:o});return d[We](h),l[Xe](h),h}static#fe(e={}){e&&["experimentalAPIMessages"].forEach((t=>{void 0!==e[t]&&["warn","error","off"].includes(e[t])&&(tt.config[t]=e[t])}))}}const rt=tt;return t})()}));
!function(root,factory){"object"==typeof exports&&"object"==typeof module?module.exports=factory():"function"==typeof define&&define.amd?define([],factory):"object"==typeof exports?exports["@jsiqle/core"]=factory():root["@jsiqle/core"]=factory()}(global,function(){return(()=>{"use strict";var __webpack_require__={n:module=>{var getter=module&&module.__esModule?()=>module.default:()=>module;return __webpack_require__.d(getter,{a:getter}),getter},d:(exports,definition)=>{for(var key in definition)__webpack_require__.o(definition,key)&&!__webpack_require__.o(exports,key)&&Object.defineProperty(exports,key,{enumerable:!0,get:definition[key]})},o:(obj,prop)=>Object.prototype.hasOwnProperty.call(obj,prop),r:exports=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(exports,"__esModule",{value:!0})}},__webpack_exports__={};__webpack_require__.r(__webpack_exports__),__webpack_require__.d(__webpack_exports__,{default:()=>src});var isUndefined=require("events"),external_events_default=__webpack_require__.n(isUndefined),symbols=["fields","key","keyType","methods","scopes","relationships","relationshipField","validators","recordModel","recordValue","recordHandler","recordTag","defaultValue","addScope","addRelationshipAsField","addRelationshipAsMethod","getField","getMethod","removeScope","copyScopes","instances","isRecord","groupTag","get","handleExperimentalAPIMessage"].reduce((acc,curr)=>(acc["$"+curr]=Symbol.for(curr),acc),{});class NameError extends Error{constructor(message){super(message),this.name="NameError"}}class ValidationError extends Error{constructor(message){super(message),this.name="ValidationError"}}class DuplicationError extends Error{constructor(message){super(message),this.name="DuplicationError"}}class DefaultValueError extends Error{constructor(message){super(message),this.name="DefaultValueError"}}class ExperimentalAPIUsageError extends Error{constructor(message){super(message),this.name="ExperimentalAPIUsageError"}}class Validator{static unique(field){return(value,data)=>data.every(item=>item[field]!==value[field])}static length(field,[min,max]){return value=>value[field].length>=min&&value[field].length<=max}static minLength(field,min){return value=>value[field].length>=min}static maxLength(field,max){return value=>value[field].length<=max}static range(field,[min,max]){return value=>value[field]>=min&&value[field]<=max}static min(field,min){return value=>value[field]>=min}static max(field,max){return value=>value[field]<=max}static integer(field){return value=>Number.isInteger(value[field])}static regex(field,regex){return value=>regex.test(value[field])}static uniqueValues(field){return value=>new Set(value[field]).size===value[field].length}static sortedAscending(field){return value=>value[field].every((item,index)=>0===index||item>=value[field][index-1])}static sortedDescending(field){return value=>value[field].every((item,index)=>0===index||item<=value[field][index-1])}static custom(field,fn){return(value,data)=>fn(value[field],data.map(item=>item[field]))}}const restrictedNames={Model:["toString","toObject","toJSON"],Field:["toString","toObject","toJSON"],Relationship:["toString","toObject","toJSON"]},validateName=(objectType,name)=>{var[isValid,message]=((name,restrictedNames=[])=>"string"!=typeof name?[!1,"must be a string"]:name?/^\d/.test(name)?[!1,"cannot start with a number"]:restrictedNames.includes(name)?[!1,"is reserved"]:[/^\w+$/.test(name),"must contain only alphanumeric characters, numbers or underscores"]:[!1,"is required"])(name,restrictedNames[objectType]);if(!isValid)throw new NameError(objectType+` name ${message}.`);return name},capitalize=([first,...rest])=>first.toUpperCase()+rest.join(""),reverseCapitalize=([first,...rest])=>first.toLowerCase()+rest.join(""),deepClone=obj=>{if(null===obj)return null;let clone=Object.assign({},obj);return Object.entries(clone).forEach(([key,value])=>clone[key]="object"==typeof obj[key]?deepClone(value):value),Array.isArray(obj)?(clone.length=obj.length,Array.from(clone)):clone},validateObjectWithUniqueName=({objectType,parentType,parentName},obj,collection)=>{if(!(obj=>obj&&"object"==typeof obj)(obj))throw new TypeError(objectType+` ${obj} is not an object.`);if(((collection,item)=>collection.includes(item))(collection,obj.name))throw new DuplicationError(`${parentType} ${parentName} already has a ${objectType.toLowerCase()} named ${obj.name}.`);return!0};var isBoolean=val=>"boolean"==typeof val,isNumber=val=>"number"==typeof val&&val==val,isString=val=>"string"==typeof val,isDate=val=>val instanceof Date,and=(...types)=>val=>types.every(type=>type(val));const or=(...types)=>val=>types.some(type=>type(val));var isPositive=val=>0<=val;const isArrayOf=type=>val=>Array.isArray(val)&&val.every(type);var standardTypes=shape=>{const props=Object.keys(shape);return val=>{return null!=val&&"object"==typeof val&&(Object.keys(val).length===props.length&&props.every(prop=>shape[prop](val[prop])))}},isObjectOf=type=>val=>null!=val&&"object"==typeof val&&Object.keys(val).every(prop=>type(val[prop])),isNull=val=>null===val,isUndefined=val=>void 0===val;const isNil=or(isNull,isUndefined);const types={bool:isBoolean,number:isNumber,positiveNumber:and(isNumber,isPositive),string:isString,date:isDate,stringOrNumber:or(isString,isNumber),numberOrString:or(isString,isNumber),enum:(...values)=>val=>values.includes(val),boolArray:isArrayOf(isBoolean),numberArray:isArrayOf(isNumber),stringArray:isArrayOf(isString),dateArray:isArrayOf(isDate),oneOf:or,arrayOf:isArrayOf,oneOrArrayOf:type=>val=>or(isArrayOf(type),type)(val),object:standardTypes,objectOf:isObjectOf,optional:type=>val=>or(isNil,type)(val),null:isNull,undefined:isUndefined,nil:isNil};standardTypes={boolean:{type:isBoolean,defaultValue:!1},number:{type:isNumber,defaultValue:0},positiveNumber:{type:and(isNumber,isPositive),defaultValue:0},string:{type:isString,defaultValue:""},date:{type:isDate,defaultValue:new Date},stringOrNumber:{type:or(isString,isNumber),defaultValue:""},numberOrString:{type:or(isString,isNumber),defaultValue:0},booleanArray:{type:isArrayOf(isBoolean),defaultValue:[]},numberArray:{type:isArrayOf(isNumber),defaultValue:[]},stringArray:{type:isArrayOf(isString),defaultValue:[]},dateArray:{type:isArrayOf(isDate),defaultValue:[]},object:{type:standardTypes({}),defaultValue:{}},booleanObject:{type:isObjectOf(isBoolean),defaultValue:{a:!0}},numberObject:{type:isObjectOf(isNumber),defaultValue:{}},stringObject:{type:isObjectOf(isString),defaultValue:{}},dateObject:{type:isObjectOf(isDate),defaultValue:{}},objectArray:{type:isArrayOf(standardTypes({})),defaultValue:[]}};const key=and(isString,val=>0!==val.trim().length),{$defaultValue,$validators}=symbols;class Field{#name;#defaultValue;#required;#type;#validators;constructor({name,type,required=!1,defaultValue=null,validators={}}){this.#name=validateName("Field",name),this.#required=Field.#validateRequired(required),this.#type=Field.#validateType(type,required),this.#defaultValue=Field.#validateDefaultValue(defaultValue,this.#type,this.#required),this.#validators=new Map,Object.entries(validators).forEach(([validatorName,validator])=>{this.addValidator(validatorName,validator)})}addValidator(validatorName,validator){this.#validators.set(...Field.#parseFieldValidator(this.#name,validatorName,validator))}get name(){return this.#name}get required(){return this.#required}typeCheck(value){return this.#type(value)}get[$defaultValue](){return this.#defaultValue}get[$validators](){return this.#validators}static#validateType(type,required){if("function"!=typeof type)throw new TypeError("Field type must be a function.");return required?type:types.optional(type)}static#validateRequired(required){if("boolean"!=typeof required)throw new TypeError("Field required must be a boolean.");return required}static#validateDefaultValue(defaultValue,type,required){if(required&&types.nil(defaultValue))throw new ValidationError("Default value cannot be null or undefined.");if(!type(defaultValue))throw new ValidationError("Default value must be valid.");return defaultValue}static#parseFieldValidator(fieldName,validatorName,validator){if(void 0!==Validator[validatorName])return[""+fieldName+capitalize(validatorName),Validator[validatorName](fieldName,validator)];if("function"!=typeof validator)throw new TypeError(`Validator ${validatorName} is not defined.`);return[""+fieldName+capitalize(validatorName),Validator.custom(fieldName,validator)]}}Object.entries(standardTypes).forEach(([typeName,standardType])=>{const{type,defaultValue:typeDefaultValue}=standardType;Field[typeName]=options=>"string"==typeof options?new Field({name:options,type:type}):new Field({...options,type:type}),Field[typeName+"Required"]=options=>{if("string"==typeof options)return new Field({name:options,type:type,required:!0,defaultValue:typeDefaultValue});var defaultValue=options.defaultValue||typeDefaultValue;return new Field({...options,type:type,required:!0,defaultValue:defaultValue})}}),Field.enum=({name,values})=>new Field({name:name,type:types.enum(...values)}),Field.enumRequired=({name,values,defaultValue=values[0]})=>new Field({name:name,type:types.enum(...values),required:!0,defaultValue:defaultValue}),Field.auto=autoField=>{autoField="string"==typeof autoField?autoField:autoField.name;const generator=function*(){let i=0;for(;;)yield i++}();let currentValue=0;autoField=new Field({name:autoField,type:value=>value===currentValue,required:!0,defaultValue:currentValue});return Object.defineProperty(autoField,$defaultValue,{get(){var value=generator.next().value;return currentValue=value}}),autoField};const{$recordValue,$recordHandler,$recordModel,$recordTag,$key}=symbols;class Record{#recordValue;#recordHandler;constructor(value,handler){return this.#recordValue=value,this.#recordHandler=handler,new Proxy(this,this.#recordHandler)}get[$recordHandler](){return this.#recordHandler}get[$recordValue](){return this.#recordValue}get[$recordModel](){return this.#recordHandler.model}get[$recordTag](){var model=this[$recordModel],key=model[$key].name;return model.name+"#"+this[$recordValue][key]}get[Symbol.toStringTag](){return this[$recordTag]}}const record=Record,partial_$recordTag=symbols["$recordTag"];class PartialRecord{#tag;constructor(value,tag){Object.keys(value).forEach(key=>{this[key]=value[key]}),this.#tag=tag}get[partial_$recordTag](){return this.#tag}get[Symbol.toStringTag](){return this[partial_$recordTag]}toObject(){return{...this}}toJSON(){return this.toObject()}}const fragment_$recordTag=symbols["$recordTag"];class RecordFragment extends Array{#tag;constructor(values,tag){super(),values.forEach(value=>{this.push(value)}),this.#tag=tag}get[fragment_$recordTag](){return this.#tag}get[Symbol.toStringTag](){return this[fragment_$recordTag]}toObject(){return[...this]}toJSON(){return this.toObject()}}const{$recordModel:set_$recordModel,$recordTag:set_$recordTag,$scopes,$addScope,$removeScope,$copyScopes,$isRecord,$key:set_$key}=symbols;class RecordSet extends Map{#frozen;#scopes;constructor({iterable=[],copyScopesFrom=null}={}){super();for(var[key,value]of iterable)this.set(key,value);this.#scopes=new Map,copyScopesFrom&&this[$copyScopes](copyScopesFrom),this.#frozen=!1}freeze(){return this.#frozen=!0,this}set(key,value){if(this.#frozen)throw new TypeError("Cannot modify a frozen RecordSet.");return super.set(key,value),this}delete(key){if(this.#frozen)throw new TypeError("Cannot modify a frozen RecordSet.");return super.delete(key)}clear(){if(this.#frozen)throw new TypeError("Cannot modify a frozen RecordSet.");super.clear()}map(callbackFn){return[...this.entries()].reduce((newMap,[key,value])=>(newMap[key]=callbackFn(value,key,this),newMap),{})}flatMap(callbackFn){return[...this.entries()].map(([key,value])=>callbackFn(value,key,this))}reduce(callbackFn,initialValue){return[...this.entries()].reduce((acc,[key,value])=>callbackFn(acc,value,key,this),initialValue)}filter(callbackFn){return[...this.entries()].reduce((newMap,[key,value])=>(callbackFn(value,key,this)&&newMap.set(key,value),newMap),new RecordSet({copyScopesFrom:this})).freeze()}flatFilter(callbackFn){return[...this.entries()].reduce((arr,[key,value])=>(callbackFn(value,key,this)&&arr.push(value),arr),[])}find(callbackFn){var match=[...this.entries()].find(([key,value])=>callbackFn(value,key,this));if(match)return match[1]}findKey(callbackFn){var match=[...this.entries()].find(([key,value])=>callbackFn(value,key,this));if(match)return match[0]}only(...keys){return new RecordSet({iterable:[...this.entries()].filter(([key])=>keys.includes(key)),copyScopesFrom:this}).freeze()}except(...keys){return new RecordSet({iterable:[...this.entries()].filter(([key])=>!keys.includes(key)),copyScopesFrom:this}).freeze()}sort(comparatorFn){var sorted=[...this.entries()].sort(([key1,value1],[key2,value2])=>comparatorFn(value1,value2,key1,key2));return new RecordSet({iterable:sorted,copyScopesFrom:this}).freeze()}every(callbackFn){return 0===this.size||[...this.entries()].every(([key,value])=>callbackFn(value,key,this))}some(callbackFn){return 0!==this.size&&[...this.entries()].some(([key,value])=>callbackFn(value,key,this))}select(...keys){return new RecordSet({iterable:[...this.entries()].map(([key,value])=>{const obj={};return keys.forEach(key=>obj[key]=value[key]),[key,new PartialRecord(obj,value[set_$recordTag])]}),copyScopesFrom:this}).freeze()}flatSelect(...keys){return[...this.values()].map(value=>keys.reduce((obj,key)=>({...obj,[key]:value[key]}),{}))}pluck(...keys){return new RecordSet({iterable:[...this.entries()].map(([key,value])=>{var values=keys.map(key=>value[key]);return[key,new RecordFragment(values,value[set_$recordTag])]}),copyScopesFrom:this}).freeze()}flatPluck(...keys){const isSingleKey=1===keys.length;return[...this.values()].map(value=>isSingleKey?value[keys[0]]:keys.map(key=>value[key]))}groupBy(key){const res=new RecordSet({copyScopesFrom:this,iterable:[]});for(var[recordKey,value]of this.entries()){let keyValue=value[key];void 0!==keyValue&&null!==keyValue&&keyValue[$isRecord]&&(keyValue=value[key][set_$key]),res.has(keyValue)||res.set(keyValue,new RecordGroup({copyScopesFrom:this,iterable:[],groupName:keyValue})),res.get(keyValue).set(recordKey,value)}for(const value of res.values())value.freeze();return res.freeze()}where(callbackFn){return this.filter(callbackFn)}whereNot(callbackFn){return this.filter((value,key,map)=>!callbackFn(value,key,map))}*batchIterator(batchSize){let batch=[];for(var[,value]of this)batch.push(value),batch.length===batchSize&&(yield batch,batch=[]);batch.length&&(yield batch)}limit(n){let records=[];for(var[key,value]of this)if(records.push([key,value]),records.length===n)break;return new RecordSet({iterable:records,copyScopesFrom:this}).freeze()}offset(n){let counter=0,records=[];for(var[key,value]of this)counter<n?counter++:records.push([key,value]);return new RecordSet({iterable:records,copyScopesFrom:this}).freeze()}get first(){for(var[,value]of this)return value}get last(){if(0!==this.size)return[...this.entries()].pop()[1]}get count(){return this.size}toArray(){return[...this.values()]}toFlatArray(){return[...this.values()].map(value=>value instanceof RecordGroup?value.toFlatArray():value.toObject())}toObject(){return[...this.entries()].reduce((obj,[key,value])=>(obj[key]=value,obj),{})}toFlatObject(){return[...this.entries()].reduce((obj,[key,value])=>(obj[key]=value instanceof RecordGroup?value.toFlatArray():value.toObject(),obj),{})}toJSON(){return this.toObject()}get[Symbol.toStringTag](){var records=[...this.values()];try{const firstModel=records[0][set_$recordModel].name;if(((arr,fn)=>{const eql=fn(arr[0]);return arr.every(val=>fn(val)===eql)})(records,value=>value[set_$recordModel].name===firstModel))return firstModel}catch(e){return""}return""}static get[Symbol.species](){return Map}[$addScope](name,scope){if(RecordSet.#validateMethod("Scope",name,scope,this.#scopes),this[name]||Object.getOwnPropertyNames(RecordSet.prototype).includes(name))throw new NameError(`Scope name ${name} is already in use.`);this.#scopes.set(name,scope),Object.defineProperty(this,name,{configurable:!0,get:()=>this.where(this.#scopes.get(name))})}[$removeScope](name){this.#scopes.delete(RecordSet.#validateContains("Scope",name,this.#scopes)),delete this[name]}[$copyScopes](otherRecordSet){otherRecordSet[$scopes].forEach((scope,name)=>{this[$addScope](name,scope)})}get[$scopes](){return this.#scopes}static#validateMethod(callbackType,callbackName,callback,callbacks){if("function"!=typeof callback)throw new TypeError(callbackType+` ${callbackName} is not a function.`);if(callbacks.has(callbackName))throw new DuplicationError(callbackType+` ${callbackName} already exists.`);return callback}static#validateContains(objectType,objectName,objects){if(!objects.has(objectName))throw new ReferenceError(objectType+` ${objectName} does not exist.`);return objectName}}const set=RecordSet,$groupTag=symbols["$groupTag"];class RecordGroup extends set{#groupName;constructor({iterable=[],copyScopesFrom=null,groupName=""}={}){super({iterable:iterable,copyScopesFrom:copyScopesFrom}),this.#groupName=groupName}get[$groupTag](){return this.#groupName}get[Symbol.toStringTag](){return this[$groupTag]}}const{$fields,$defaultValue:handler_$defaultValue,$key:handler_$key,$keyType,$methods,$relationships,$validators:handler_$validators,$recordValue:handler_$recordValue,$recordModel:handler_$recordModel,$recordTag:handler_$recordTag,$isRecord:handler_$isRecord,$get}=symbols;class RecordHandler{#model;constructor(model){this.#model=model}get model(){return this.#model}createRecord(recordData){if(!recordData)throw new TypeError("Record data cannot be empty.");if("object"!=typeof recordData)throw new TypeError("Record data must be an object.");const modelName=this.#getModelName(),newRecordKey=RecordHandler.#validateNewRecordKey(modelName,this.#getKey(),recordData[this.#getKey().name],this.#model.records),clonedRecord=deepClone(recordData),extraProperties=Object.keys(clonedRecord).filter(property=>!this.#hasField(property)&&!this.#isModelKey(property));0<extraProperties.length&&console.warn(`${modelName} record has extra fields: ${extraProperties.join(", ")}.`);const newRecord=new record({[this.#getKey().name]:newRecordKey,...extraProperties.reduce((obj,property)=>({...obj,[property]:clonedRecord[property]}),{})},this);return this.#getFieldNames().forEach(field=>{this.set(newRecord,field,clonedRecord[field],newRecord,!0)}),this.#getValidators().forEach((validator,validatorName)=>{if(!validator(newRecord,this.#model.records))throw new RangeError(`${modelName} record with key ${newRecordKey} failed validation for ${validatorName}.`)}),[newRecordKey,newRecord]}get(record,property){return this.#hasRelationshipField(property)?this.#getRelationship(record,property):this.#isModelKey(property)||this.#hasField(property)?this.#getFieldValue(record,property):this.#hasMethod(property)?this.#getMethod(record,property):this.#isCallToSerialize(property)?RecordHandler.#recordToObject(record,this.#model,this):this.#isCallToString(property)?()=>this.#getKeyValue(record):this.#isKnownSymbol(property)?this.#getKnownSymbol(record,property):void 0}set(record,property,value,receiver,skipValidation){const recordValue=record[handler_$recordValue],recordKey=this.#getKeyValue(record),otherRecords=this.#model.records.except(recordKey);if(this.#hasMethod(property))throw new TypeError(`${this.#getModelName()} record ${recordKey} cannot set method ${property}.`);if(this.#hasField(property)){const field=this.#getField(property);RecordHandler.#setRecordField(this.#model.name,recordValue,field,value),field[handler_$validators].forEach((validator,validatorName)=>{if(![null,void 0].includes(recordValue[property])&&!validator(recordValue,otherRecords))throw new RangeError(`${this.#getModelName()} record with key ${recordKey} failed validation for ${validatorName}.`)})}else console.warn(this.#model.name+` record has extra field: ${property}.`),recordValue[property]=value;return skipValidation||this.#getValidators().forEach((validator,validatorName)=>{if(!validator(recordValue,otherRecords))throw new RangeError(`${this.#getModelName()} record with key ${recordKey} failed validation for ${validatorName}.`)}),!0}static#setRecordField(modelName,record,field,recordValue){recordValue=field.required&&types.nil(recordValue)?field[handler_$defaultValue]:recordValue;if(!field.typeCheck(recordValue))throw new TypeError(`${modelName} record has invalid value for field ${field.name}.`);record[field.name]=recordValue}static#recordToObject(record,key,handler){const recordValue=record[handler_$recordValue],fields=key[$fields],methods=key[$methods];key=key[handler_$key].name;const object={[key]:recordValue[key]};fields.forEach(field=>{void 0!==recordValue[field.name]&&(object[field.name]=recordValue[field.name])});return({include=[]}={})=>{var result=object;const included=include.map(name=>{const[field,...props]=name.split(".");return[field,props.join(".")]});return included.forEach(([includedField,props])=>{if(object[includedField])if(Array.isArray(object[includedField])){const records=handler.get(record,includedField);object[includedField]=records.map(record=>record.toObject({include:[props]}))}else object[includedField]=handler.get(record,includedField).toObject({include:[props]});else methods.has(includedField)&&(object[includedField]=handler.get(record,includedField))}),result}}static#validateNewRecordKey=(modelName,modelKey,recordKey,records)=>{let newRecordKey=recordKey;if("string"===modelKey[$keyType]&&!modelKey.typeCheck(newRecordKey))throw new TypeError(`${modelName} record has invalid value for key ${modelKey.name}.`);if("auto"===modelKey[$keyType]&&(newRecordKey=modelKey[handler_$defaultValue]),records.has(newRecordKey))throw new DuplicationError(`${modelName} record with key ${newRecordKey} already exists.`);return newRecordKey};#getModelName(){return this.#model.name}#getFieldNames(){return[...this.#model[$fields].keys()]}#getValidators(){return this.#model[handler_$validators]}#isModelKey(property){return this.#model[handler_$key].name===property}#getKey(){return this.#model[handler_$key]}#getKeyValue(record){return record[handler_$recordValue][this.#model[handler_$key].name]}#hasField(property){return this.#model[$fields].has(property)}#getField(property){return this.#model[$fields].get(property)}#getFieldValue(record,property){return record[handler_$recordValue][property]}#hasMethod(property){return this.#model[$methods].has(property)}#getMethod(record,property){return this.#model[$methods].get(property)(record[handler_$recordValue])}#hasRelationshipField(property){return!!this.#hasField(property)&&this.#model[$relationships].has(property+"."+property)}#getRelationship(record,property){return this.#model[$relationships].get(property+"."+property)[$get](this.#getModelName(),property,record[handler_$recordValue])}#isCallToSerialize(property){return"toObject"===property||"toJSON"===property}#isCallToString(property){return"toString"===property}#isKnownSymbol(property){return[handler_$recordModel,handler_$recordTag,handler_$recordValue,handler_$isRecord,handler_$key].includes(property)}#getKnownSymbol(record,property){return property===handler_$isRecord||(property===handler_$key&&this.#getKey(),record[property])}}const handler=RecordHandler,{$fields:model_$fields,$defaultValue:model_$defaultValue,$key:model_$key,$keyType:model_$keyType,$methods:model_$methods,$scopes:model_$scopes,$relationships:model_$relationships,$validators:model_$validators,$recordHandler:model_$recordHandler,$addScope:model_$addScope,$addRelationshipAsField,$addRelationshipAsMethod,$getField,$getMethod,$removeScope:model_$removeScope,$instances,$handleExperimentalAPIMessage}=symbols,allStandardTypes=[...Object.keys(standardTypes),...Object.keys(standardTypes).map(type=>type+"Required"),"enum","enumRequired","auto"];class Model extends external_events_default(){#records;#recordHandler;#fields;#key;#methods;#relationships;#validators;#updatingField=!1;static#instances=new Map;constructor({name,fields=[],key="id",methods={},scopes={},validators={}}={}){if(super(),this.name=validateName("Model",name),Model.#instances.has(name))throw new DuplicationError(`A model named ${name} already exists.`);this.#records=new set,this.#recordHandler=new handler(this),this.#key=Model.#parseKey(this.name,key),this.#fields=new Map,this.#methods=new Map,this.#relationships=new Map,this.#validators=new Map,fields.forEach(field=>this.addField(field)),Object.entries(methods).forEach(([methodName,method])=>{this.addMethod(methodName,method)}),Object.entries(scopes).forEach(([scopeName,scope])=>{this.addScope(scopeName,scope)}),Object.entries(validators).forEach(([validatorName,validator])=>{this.addValidator(validatorName,validator)}),Model.#instances.set(this.name,this)}addField(fieldOptions,retrofill){this.#updatingField||this.emit("beforeAddField",{field:fieldOptions,model:this});var field=Model.#parseField(this.name,fieldOptions,[...this.#fields.keys(),this.#key.name,...this.#methods.keys()]);return this.#fields.set(fieldOptions.name,field),this.#updatingField||this.emit("fieldAdded",{field:field,model:this}),this.emit("beforeRetrofillField",{field:field,retrofill:retrofill,model:this}),Model.#applyFieldRetrofill(field,this.#records,retrofill),this.emit("fieldRetrofilled",{field:field,retrofill:retrofill,model:this}),this.#updatingField||this.emit("change",{type:"fieldAdded",field:field,model:this}),field}removeField(name){if(!Model.#validateContains(this.name,"Field",name,this.#fields))return!1;var field=this.#fields.get(name);return this.#updatingField||this.emit("beforeRemoveField",{field:field,model:this}),this.#fields.delete(name),this.#updatingField||(this.emit("fieldRemoved",{field:{name:name},model:this}),this.emit("change",{type:"fieldRemoved",field:field,model:this})),!0}updateField(name,field,newField){if(field.name!==name)throw new NameError(`Field name ${field.name} does not match ${name}.`);if(!Model.#validateContains(this.name,"Field",name,this.#fields))throw new ReferenceError(`Field ${name} does not exist.`);var prevField=this.#fields.get(name);this.#updatingField=!0,this.emit("beforeUpdateField",{prevField:prevField,field:field,model:this}),this.removeField(name);newField=this.addField(field,newField);this.emit("fieldUpdated",{field:newField,model:this}),this.#updatingField=!1,this.emit("change",{type:"fieldUpdated",field:newField,model:this})}addMethod(name,method){this.emit("beforeAddMethod",{method:{name:name,body:method},model:this});var methodName=validateName("Method",name);this.#methods.set(methodName,Model.#validateMethod("Method",name,method,[...this.#fields.keys(),this.#key.name,...this.#methods.keys()])),this.emit("methodAdded",{method:{name:methodName,body:method},model:this}),this.emit("change",{type:"methodAdded",method:{name:methodName,body:method},model:this})}removeMethod(name){if(!Model.#validateContains(this.name,"Method",name,this.#methods))return!1;var method=this.#methods.get(name);return this.emit("beforeRemoveMethod",{method:{name:name,body:method},model:this}),this.#methods.delete(name),this.emit("methodRemoved",{method:{name:name},model:this}),this.emit("change",{type:"methodRemoved",method:{name:name,body:method},model:this}),!0}addScope(scopeName,scope){this.emit("beforeAddScope",{scope:{name:scopeName,body:scope},model:this});scopeName=validateName("Scope",scopeName);this.#records[model_$addScope](scopeName,scope),this.emit("scopeAdded",{scope:{name:scopeName,body:scope},model:this}),this.emit("change",{type:"scopeAdded",scope:{name:scopeName,body:scope},model:this})}removeScope(name){if(!Model.#validateContains(this.name,"Scope",name,this.#records[model_$scopes]))return!1;var scope=this.#records[model_$scopes].get(name);return this.emit("beforeRemoveScope",{scope:{name:name,body:scope},model:this}),this.#records[model_$removeScope](name),this.emit("scopeRemoved",{scope:{name:name},model:this}),this.emit("change",{type:"scopeRemoved",scope:{name:name,body:scope},model:this}),!0}addValidator(name,validator){this.emit("beforeAddValidator",{validator:{name:name,body:validator},model:this}),this.#validators.set(name,Model.#validateMethod("Validator",name,validator,[...this.#validators.keys()])),this.emit("validatorAdded",{validator:{name:name,body:validator},model:this}),this.emit("change",{type:"validatorAdded",validator:{name:name,body:validator},model:this})}removeValidator(name){if(!Model.#validateContains(this.name,"Validator",name,this.#validators))return!1;var validator=this.#validators.get(name);return this.emit("beforeRemoveValidator",{validator:{name:name,body:validator},model:this}),this.#validators.delete(name),this.emit("validatorRemoved",{validator:{name:name},model:this}),this.emit("change",{type:"validatorRemoved",validator:{name:name,body:validator},model:this}),!0}createRecord(newRecord){this.emit("beforeCreateRecord",{record:newRecord,model:this});var[newRecordKey,newRecord]=this.#recordHandler.createRecord(newRecord);return this.#records.set(newRecordKey,newRecord),this.emit("recordCreated",{newRecord:newRecord,model:this}),newRecord}removeRecord(recordKey){if(!this.#records.has(recordKey))return console.warn(`Record ${recordKey} does not exist.`),!1;var record=this.#records.get(recordKey);return this.emit("beforeRemoveRecord",{record:record,model:this}),this.#records.delete(recordKey),this.emit("recordRemoved",{record:{[this.#key.name]:recordKey},model:this}),!0}updateRecord(recordKey,record){if("object"!=typeof record)throw new TypeError("Record data must be an object.");if(!this.#records.has(recordKey))throw new ReferenceError(`Record ${recordKey} does not exist.`);const oldRecord=this.#records.get(recordKey);return this.emit("beforeUpdateRecord",{record:oldRecord,newRecord:{[this.#key.name]:recordKey,...record},model:this}),Object.entries(record).forEach(([fieldName,fieldValue])=>{oldRecord[fieldName]=fieldValue}),this.emit("recordUpdated",{record:oldRecord,model:this}),oldRecord}get records(){return this.#records}static get[$instances](){return Model.#instances}get[model_$recordHandler](){return this.#recordHandler}get[model_$fields](){return this.#fields}get[model_$key](){return this.#key}get[model_$methods](){return this.#methods}get[model_$relationships](){return this.#relationships}get[model_$validators](){return this.#validators}[$addRelationshipAsField](relationship){var{name,type,fieldName,field}=relationship[$getField](),relationshipName=name+"."+fieldName;if(this.emit("beforeAddRelationship",{relationship:{name:name,type:type},model:this}),[...this.#fields.keys(),this.#key.name,...this.#methods.keys()].includes(fieldName))throw new NameError(`Relationship field ${fieldName} is already in use.`);if(this.#relationships.has(relationshipName))throw new NameError(`Relationship ${relationshipName} is already in use.`);this.#fields.set(fieldName,field),this.#relationships.set(relationshipName,relationship),this.emit("relationshipAdded",{relationship:{name:name,type:type},model:this}),this.emit("change",{type:"relationshipAdded",relationship:{relationship:{name:name,type:type},model:this},model:this})}[$addRelationshipAsMethod](relationship){var{name,type,methodName,method}=relationship[$getMethod](),relationshipName=name+"."+methodName;if(this.emit("beforeAddRelationship",{relationship:{name:name,type:type},model:this}),[...this.#fields.keys(),this.#key.name,...this.#methods.keys()].includes(methodName))throw new NameError(`Relationship method ${methodName} is already in use.`);if(this.#relationships.has(relationshipName))throw new NameError(`Relationship ${name} is already in use.`);this.#methods.set(methodName,method),this.#relationships.set(relationshipName,relationship),this.emit("relationshipAdded",{relationship:{name:name,type:type},model:this}),this.emit("change",{type:"relationshipAdded",relationship:{relationship:{name:name,type:type},model:this},model:this})}static#createKey(options){let name="id",type="string";"string"==typeof options?name=options:"object"==typeof options&&(name=options.name||name,type=options.type||type);let keyField;return"string"===type?(keyField=new Field({name:name,type:key,required:!0,defaultValue:"__emptyKey__"}),Object.defineProperty(keyField,model_$defaultValue,{get(){throw new DefaultValueError(`Key field ${name} does not have a default value.`)}})):"auto"===type&&(keyField=Field.auto(name)),Object.defineProperty(keyField,model_$keyType,{get(){return type}}),keyField}static#parseKey(modelName,key){if("string"!=typeof key&&"object"!=typeof key)throw new TypeError(modelName+` key ${key} is not a string or object.`);if("object"==typeof key&&!key.name)throw new TypeError(modelName+` key ${key} is missing a name.`);if("object"==typeof key&&!["auto","string"].includes(key.type))throw new TypeError(modelName+` key ${key} type must be either "string" or "auto".`);return Model.#createKey(key)}static#parseField(modelName,field,restrictedNames){return validateObjectWithUniqueName({objectType:"Field",parentType:"Model",parentName:modelName},field,restrictedNames),allStandardTypes.includes(field.type)?Field[field.type](field):("function"==typeof field.type&&Schema[$handleExperimentalAPIMessage](`The provided type for ${field.name} is not part of the standard types. Function types are experimental and may go away in a later release.`),new Field(field))}static#validateMethod(callbackType,callbackName,callback,restrictedNames){if("function"!=typeof callback)throw new TypeError(callbackType+` ${callbackName} is not a function.`);if(restrictedNames.includes(callbackName))throw new DuplicationError(callbackType+` ${callbackName} already exists.`);return callback}static#validateContains(modelName,objectType,objectName,objects){return!!objects.has(objectName)||(console.warn(`Model ${modelName} does not contain a ${objectType.toLowerCase()} named ${objectName}.`),!1)}static#applyFieldRetrofill(field,records,retrofill){if(field.required||void 0!==retrofill){const retrofillFunction=void 0!==retrofill?"function"==typeof retrofill?retrofill:()=>retrofill:record=>record[field.name]||field[model_$defaultValue];records.forEach(record=>{record[field.name]=retrofillFunction(record)})}}}const{$key:relationship_$key,$recordValue:relationship_$recordValue,$fields:relationship_$fields,$getField:relationship_$getField,$getMethod:relationship_$getMethod,$get:relationship_$get,$defaultValue:relationship_$defaultValue,$instances:relationship_$instances,$handleExperimentalAPIMessage:relationship_$handleExperimentalAPIMessage}=symbols,relationshipEnum={oneToOne:"oneToOne",oneToMany:"oneToMany",manyToOne:"manyToOne",manyToMany:"manyToMany"};class Relationship{#type;#from;#to;#name;#reverseName;#relationshipField;#relationshipMethod;constructor({from:fromName,to:toModel,type:toName}={}){Schema[relationship_$handleExperimentalAPIMessage]("Relationships are experimental in the current version. There is neither validation of existence in foreign tables nor guarantee that associations work. Please use with caution."),this.#type=Relationship.#validateType(toName);var[fromModel,fromName,toModel,toName]=Relationship.#parseModelsAndNames(fromName,toModel,toName);if(this.#from=fromModel,this.#to=toModel,this.#name=fromName,this.#reverseName=toName,this.#to===this.#from&&Relationship.#isSymmetric(this.#type)&&this.#name===this.#reverseName)throw new RangeError("Relationship cannot be symmetric if the from and to models are the same and no name is provided for either one.");this.#relationshipField=Relationship.#createField(this.#name,this.#type,this.#to[relationship_$key]),this.#relationshipMethod=record=>this.#getAssociatedRecordsReverse(record)}[relationship_$getField](){return{name:this.#name,type:this.#type,fieldName:this.#name,field:this.#relationshipField}}[relationship_$getMethod](){return{name:this.#name,type:this.#type,methodName:this.#reverseName,method:this.#relationshipMethod}}[relationship_$get](modelName,property,record){return modelName===this.#from.name&&property===this.#name?this.#getAssociatedRecords(record):modelName===this.#to.name&&property===this.#reverseName?(console.warn("Relationship getter called by the receiver model. This might indicate an issue with the library and should be reported."),this.#getAssociatedRecordsReverse(record)):void 0}#getAssociatedRecords(record){if(Relationship.#isToOne(this.#type)){var associationValue=record[this.#name];return this.#to.records.get(associationValue)}const associationValues=record[this.#name]||[],associatedRecordsKeyName=this.#to[relationship_$key].name;return this.#to.records.where(associatedRecord=>associationValues.includes(associatedRecord[associatedRecordsKeyName]))}#getAssociatedRecordsReverse(matcher){const associationValue=matcher[this.#to[relationship_$key].name];matcher=Relationship.#isToOne(this.#type)?associatedRecord=>associatedRecord[relationship_$recordValue][this.#name]===associationValue:associatedRecord=>{var associatedRecordValue=associatedRecord[relationship_$recordValue][this.#name];return![void 0,null].includes(associatedRecordValue)&&associatedRecord[relationship_$recordValue][this.#name].includes(associationValue)};return Relationship.#isFromOne(this.#type)?this.#from.records.find(matcher):this.#from.records.where(matcher)}static#isToOne(type){return[relationshipEnum.oneToOne,relationshipEnum.manyToOne].includes(type)}static#isToMany(type){return[relationshipEnum.oneToMany,relationshipEnum.manyToMany].includes(type)}static#isFromOne(type){return[relationshipEnum.oneToMany,relationshipEnum.oneToOne].includes(type)}static#isFromMany(type){return[relationshipEnum.manyToOne,relationshipEnum.manyToMany].includes(type)}static#isSymmetric(type){return[relationshipEnum.oneToOne,relationshipEnum.manyToMany].includes(type)}static#createField(name,type,foreignField){var isSingleSource=Relationship.#isFromOne(type),relationshipField=Relationship.#isToMany(type),type=relationshipField?types.arrayOf(value=>foreignField.typeCheck(value)):value=>foreignField.typeCheck(value);const validators={};isSingleSource&&!relationshipField&&(validators.unique=!0),relationshipField&&(validators.uniqueValues=!0);relationshipField=new Field({name:name,type:type,required:!1,defaultValue:relationshipField?[]:null,validators:validators});return Object.defineProperty(relationshipField,relationship_$defaultValue,{get(){throw new DefaultValueError("Relationship field does not have a default value.")}}),relationshipField}static#validateType(relationshipType){if(!Object.values(relationshipEnum).includes(relationshipType))throw new TypeError(`Invalid relationship type: ${relationshipType}.`);return relationshipType}static#validateModel(modelName){modelName="string"==typeof modelName?modelName:modelName.model;if(!Model[relationship_$instances].has(modelName))throw new ReferenceError(`Model ${modelName} does not exist.`);return Model[relationship_$instances].get(modelName)}static#createName(type,to){return Relationship.#isToOne(type)?reverseCapitalize(to):Relationship.#isToMany(type)?reverseCapitalize(to)+"Set":void 0}static#createReverseName=(type,from)=>Relationship.#isFromOne(type)?reverseCapitalize(from):Relationship.#isFromMany(type)?reverseCapitalize(from)+"Set":void 0;static#validateModelParams(name){const model=Relationship.#validateModel(name);name="string"==typeof name?null:validateName("Field",name.name);if(null!==name&&model[relationship_$fields].has(name))throw new DuplicationError(`Field ${name} already exists in ${model.name}.`);return[model,name]}static#parseModelsAndNames(from,to,type){let fromModel,fromName,toModel,toName;return[fromModel,fromName]=Relationship.#validateModelParams(from),[toModel,toName]=Relationship.#validateModelParams(to),null===fromName&&(fromName=Relationship.#createName(type,toModel.name)),null===toName&&(toName=Relationship.#createReverseName(type,fromModel.name)),[fromModel,fromName,toModel,toName]}}const{$addRelationshipAsField:schema_$addRelationshipAsField,$addRelationshipAsMethod:schema_$addRelationshipAsMethod,$handleExperimentalAPIMessage:schema_$handleExperimentalAPIMessage,$key:schema_$key,$keyType:schema_$keyType}=symbols;class Schema extends external_events_default(){#name;#models;static defaultConfig={experimentalAPIMessages:"warn"};static config={...Schema.defaultConfig};static#schemas=new Map;constructor({name,models=[],config={}}={}){super(),this.#name=validateName("Schema",name),this.#models=new Map,Schema.#parseConfig(config),Schema.#schemas.set(this.#name,this),models.forEach(model=>this.createModel(model))}createModel(modelData){this.emit("beforeCreateModel",{model:modelData,schema:this});const model=Schema.#parseModel(this.#name,modelData,this.#models);return this.#models.set(model.name,model),model.on("change",({type,...eventData})=>{this.emit("change",{type:"model"+capitalize(type),...eventData,schema:this})}),this.emit("modelCreated",{model:model,schema:this}),this.emit("change",{type:"modelCreated",model:model,schema:this}),model}getModel(name){return this.#models.get(name)}removeModel(name){var model=this.getModel(name);if(this.emit("beforeRemoveModel",{model:model,schema:this}),!this.#models.has(name))throw new ReferenceError(`Model ${name} does not exist in schema ${this.#name}.`);this.#models.delete(name),this.emit("modelRemoved",{model:{name:name},schema:this}),this.emit("change",{type:"modelRemoved",model:model,schema:this})}createRelationship(relationship){this.emit("beforeCreateRelationship",{relationship:relationship,schema:this});relationship=Schema.#applyRelationship(this.#name,relationship,this.#models);return this.emit("relationshipCreated",{relationship:relationship,schema:this}),this.emit("change",{type:"relationshipCreated",relationship:relationship,schema:this}),relationship}get name(){return this.#name}get models(){return this.#models}static create(schemaData){return new Schema(schemaData)}static get(name){return Schema.#schemas.get(name)}get(pathName){this.emit("beforeGet",{pathName:pathName,schema:this});const[modelName,recordKey,...rest]=pathName.split("."),model=this.getModel(modelName);if(!model)throw new ReferenceError(`Model ${modelName} does not exist in schema ${this.#name}.`);if(void 0===recordKey)return model;var result=model[schema_$key][schema_$keyType],result=model.records.get("string"===result?recordKey:Number.parseInt(recordKey));if(!rest.length)return result;if(!result)throw new ReferenceError(`Record ${recordKey} does not exist in model ${modelName}.`);result=rest.reduce((acc,key)=>acc[key],result);return this.emit("got",{pathName:pathName,result:result,schema:this}),result}static[schema_$handleExperimentalAPIMessage](message){var experimentalAPIMessages=Schema.config["experimentalAPIMessages"];if("warn"===experimentalAPIMessages)console.warn(message);else if("error"===experimentalAPIMessages)throw new ExperimentalAPIUsageError(message)}static#parseModel(schemaName,modelData,models){return validateObjectWithUniqueName({objectType:"Model",parentType:"Schema",parentName:schemaName},modelData,[...models.keys()]),new Model(modelData)}static#applyRelationship(relationship,toModelName,models){const{from,to,type}=toModelName;[from,to].forEach(model=>{if(!["string","object"].includes(typeof model))throw new TypeError(`Invalid relationship model: ${model}.`)});var fromModelName="string"==typeof from?from:from.model,toModelName="string"==typeof to?to:to.model;const fromModel=models.get(fromModelName),toModel=models.get(toModelName);if(!fromModel)throw new ReferenceError(`Model ${fromModelName} not found in schema ${relationship} when attempting to create a relationship.`);if(!toModel)throw new ReferenceError(`Model ${toModelName} not found in schema ${relationship} when attempting to create a relationship.`);relationship=new Relationship({from:from,to:to,type:type});return fromModel[schema_$addRelationshipAsField](relationship),toModel[schema_$addRelationshipAsMethod](relationship),relationship}static#parseConfig(config={}){config&&["experimentalAPIMessages"].forEach(key=>{void 0!==config[key]&&["warn","error","off"].includes(config[key])&&(Schema.config[key]=config[key])})}}const src=Schema;return __webpack_exports__})()});
{
"name": "@jsiqle/core",
"version": "1.0.1",
"version": "1.0.2",
"description": "JavaScript In-memory Query Language with Events.",

@@ -27,2 +27,3 @@ "main": "./dist/main.js",

"babel-jest": "^27.3.1",
"babel-loader": "^8.2.3",
"babel-plugin-module-resolver": "^4.1.0",

@@ -33,2 +34,3 @@ "eslint": "^8.0.1",

"prettier": "^2.4.1",
"uglifyjs-webpack-plugin": "^2.2.0",
"webpack": "^5.59.1",

@@ -35,0 +37,0 @@ "webpack-cli": "^4.9.1"

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

import { Schema } from 'src/schema';
import { allEqualBy } from 'src/utils';

@@ -18,3 +17,2 @@ import { NameError, DuplicationError } from 'src/errors';

$key,
$handleExperimentalAPIMessage,
} = symbols;

@@ -60,5 +58,7 @@

set(key, value) {
Schema[$handleExperimentalAPIMessage](
'Calling RecordSet.prototype.set() is discouraged as it may cause unexpected behavior. This method may be removed in a future version of the library.'
);
// TODO: V2 Enhancements
// Ensure this is only ever called internally (maybe symbolize it?)
// Schema[$handleExperimentalAPIMessage](
// 'Calling RecordSet.prototype.set() is discouraged as it may cause unexpected behavior. This method may be removed in a future version of the library.'
// );
if (this.#frozen) throw new TypeError('Cannot modify a frozen RecordSet.');

@@ -65,0 +65,0 @@ super.set(key, value);

const path = require('path');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');

@@ -20,2 +21,34 @@ module.exports = {

stats: 'minimal',
optimization: {
minimizer: [
new UglifyJSPlugin({
cache: true,
parallel: true,
uglifyOptions: {
compress: true,
ecma: 6,
mangle: false,
},
sourceMap: true,
}),
],
},
module: {
rules: [
{
test: /\.js$/,
include: [/src/],
use: [
{
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', { targets: { node: 'current' } }],
],
},
},
],
},
],
},
};
SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc