@jaysalvat/smart-model
Advanced tools
Comparing version 0.1.0 to 0.1.1
@@ -0,1 +1,10 @@ | ||
/**! | ||
* model | ||
* Javascript object model | ||
* https://github.com/jaysalvat/super-store | ||
* @version 0.1.1 built 2021-02-18 18:16:27 | ||
* @license ISC | ||
* @author Jay Salvat http://jaysalvat.com | ||
*/ | ||
function isEmpty(value) { | ||
@@ -2,0 +11,0 @@ return value === '' || value === null || typeof value === 'undefined' |
@@ -1,251 +0,2 @@ | ||
function isEmpty(value) { | ||
return value === '' || value === null || typeof value === 'undefined' | ||
} | ||
function isFn(value) { | ||
return typeof value === 'function' | ||
} | ||
function isArray(value) { | ||
return Array.isArray(value) | ||
} | ||
function isEqual(value1, value2) { | ||
return JSON.stringify(value1) === JSON.stringify(value2) | ||
} | ||
function checkErrors(entry, property, value) { | ||
const errors = []; | ||
if (entry.required) { | ||
if (isEmpty(value)) { | ||
errors.push({ | ||
message: `Invalid type 'required' on property '${property}'`, | ||
type: 'required', | ||
value: value | ||
}); | ||
} | ||
} | ||
if (entry.type) { | ||
let typeOk; | ||
const types = isArray(entry.type) ? entry.type : [ entry.type ]; | ||
if (!entry.required && isEmpty(value)) { | ||
typeOk = true; | ||
} else { | ||
typeOk = types.some((type) => { | ||
return typeof value === typeof type() || value instanceof type | ||
}); | ||
} | ||
if (!typeOk) { | ||
errors.push({ | ||
message: `Invalid type '${typeof value}' on property '${property}'`, | ||
type: 'type', | ||
value: value, | ||
expected: types | ||
}); | ||
} | ||
} | ||
if (entry.rule) { | ||
Object.keys(entry.rule).forEach((key) => { | ||
const rule = entry.rule[key]; | ||
if (!rule(value)) { | ||
errors.push({ | ||
message: `Invalid value '${key}' on property '${property}'`, | ||
type: key, | ||
value: value, | ||
expected: rule(value) | ||
}); | ||
} | ||
}); | ||
} | ||
return errors | ||
} | ||
class ModelError extends Error { | ||
constructor(data) { | ||
super(data.message); | ||
Object.assign(this, data); | ||
} | ||
} | ||
class ModelHandler { | ||
constructor(schema = {}) { | ||
this.schema = schema; | ||
} | ||
// Setter | ||
set(target, property, value) { | ||
const schema = this.schema; | ||
const entry = schema[property]; | ||
const oldValue = target[property]; | ||
const updated = !isEqual(value, oldValue); | ||
function trigger(method) { | ||
return Reflect.apply(method, target, [ property, value, oldValue, schema ]) | ||
} | ||
if (isFn(entry)) { | ||
return false | ||
} | ||
if (entry.transform) { | ||
value = entry.transform(value); | ||
} | ||
trigger(target.onBeforeSet); | ||
if (updated) { | ||
trigger(target.onBeforeUpdate); | ||
} | ||
if (Model.settings.exeptions) { | ||
const errors = checkErrors(entry, property, value); | ||
if (errors.length) { | ||
errors.forEach((error) => { | ||
throw new ModelError({ | ||
message: error.message, | ||
property: property, | ||
type: error.type, | ||
value: error.value, | ||
expected: error.expected | ||
}) | ||
}); | ||
} | ||
} | ||
target[property] = value; | ||
trigger(target.onSet); | ||
if (updated) { | ||
trigger(target.onUpdate); | ||
} | ||
return true | ||
} | ||
// Getter | ||
get(target, property) { | ||
let value = target[property]; | ||
const schema = this.schema; | ||
const entry = schema[property]; | ||
if (target.hasOwnProperty(property)) { | ||
return target[property] | ||
} | ||
if (!entry) { | ||
return target[property] | ||
} | ||
function trigger(method, args) { | ||
return Reflect.apply(method, target, args) | ||
} | ||
trigger(target.onBeforeGet, [ property, value, schema ]); | ||
if (isFn(entry)) { | ||
value = trigger(entry, [ target ]); | ||
} | ||
if (isFn(entry.format)) { | ||
value = trigger(entry.format, [ value, target ]); | ||
} | ||
trigger(target.onGet, [ property, value, schema ]); | ||
return value | ||
} | ||
} | ||
class Model { | ||
constructor(schema = {}, data = {}) { | ||
Object.keys(schema).forEach((key) => { | ||
if (schema[key].default) { | ||
this[key] = schema[key].default; | ||
} | ||
}); | ||
this.feed(data); | ||
} | ||
feed(data) { | ||
Object.keys(data).forEach((key) => { | ||
this[key] = data[key]; | ||
}); | ||
} | ||
onSet() {} | ||
onGet() {} | ||
onUpdate() {} | ||
onBeforeSet() {} | ||
onBeforeGet() {} | ||
onBeforeUpdate() {} | ||
} | ||
Model.settings = { | ||
exceptions: true | ||
}; | ||
Model.create = function (type, schema = {}, prototype = {}) { | ||
const ModelClass = { | ||
[type]: class extends Model { | ||
constructor(data) { | ||
super(schema, data); | ||
return new Proxy(this, new ModelHandler(schema)) | ||
} | ||
} | ||
}; | ||
Object.assign(ModelClass[type].prototype, prototype); | ||
return ModelClass[type] | ||
}; | ||
Model.throwExeptions = function (bool) { | ||
Model.settings.exeptions = bool; | ||
}; | ||
Model.checkErrors = function (schema, payload) { | ||
const invalidations = {}; | ||
Object.keys(schema).forEach((property) => { | ||
const value = payload[property]; | ||
const entry = schema[property]; | ||
const errors = checkErrors(entry, property, value); | ||
if (typeof entry === 'function') { | ||
return | ||
} | ||
if (errors.length) { | ||
invalidations[property] = errors; | ||
} | ||
return | ||
}); | ||
return Object.keys(invalidations).length ? invalidations : false | ||
}; | ||
Model.hydrate = function (ModelToHydrate, payload) { | ||
if (isArray(payload)) { | ||
return payload.map((item) => new ModelToHydrate(item)) | ||
} else { | ||
return new ModelToHydrate(payload) | ||
} | ||
}; | ||
export default Model; | ||
/*! model v0.1.1 */ | ||
function e(e){return""===e||null==e}function t(e){return"function"==typeof e}function r(e){return Array.isArray(e)}function n(t,n,o){const s=[];if(t.required&&e(o)&&s.push({message:`Invalid type 'required' on property '${n}'`,type:"required",value:o}),t.type){let c;const u=r(t.type)?t.type:[t.type];c=!(t.required||!e(o))||u.some((e=>typeof o==typeof e()||o instanceof e)),c||s.push({message:`Invalid type '${typeof o}' on property '${n}'`,type:"type",value:o,expected:u})}return t.rule&&Object.keys(t.rule).forEach((e=>{const r=t.rule[e];r(o)||s.push({message:`Invalid value '${e}' on property '${n}'`,type:e,value:o,expected:r(o)})})),s}class o extends Error{constructor(e){super(e.message),Object.assign(this,e)}}class s{constructor(e={}){this.schema=e}set(e,r,s){const u=this.schema,p=u[r],a=e[r],f=(i=s,y=a,!(JSON.stringify(i)===JSON.stringify(y)));var i,y;function l(t){return Reflect.apply(t,e,[r,s,a,u])}if(t(p))return!1;if(p.transform&&(s=p.transform(s)),l(e.onBeforeSet),f&&l(e.onBeforeUpdate),c.settings.exeptions){const e=n(p,r,s);e.length&&e.forEach((e=>{throw new o({message:e.message,property:r,type:e.type,value:e.value,expected:e.expected})}))}return e[r]=s,l(e.onSet),f&&l(e.onUpdate),!0}get(e,r){let n=e[r];const o=this.schema,s=o[r];if(e.hasOwnProperty(r))return e[r];if(!s)return e[r];function c(t,r){return Reflect.apply(t,e,r)}return c(e.onBeforeGet,[r,n,o]),t(s)&&(n=c(s,[e])),t(s.format)&&(n=c(s.format,[n,e])),c(e.onGet,[r,n,o]),n}}class c{constructor(e={},t={}){Object.keys(e).forEach((t=>{e[t].default&&(this[t]=e[t].default)})),this.feed(t)}feed(e){Object.keys(e).forEach((t=>{this[t]=e[t]}))}onSet(){}onGet(){}onUpdate(){}onBeforeSet(){}onBeforeGet(){}onBeforeUpdate(){}}c.settings={exceptions:!0},c.create=function(e,t={},r={}){const n={[e]:class extends c{constructor(e){return super(t,e),new Proxy(this,new s(t))}}};return Object.assign(n[e].prototype,r),n[e]},c.throwExeptions=function(e){c.settings.exeptions=e},c.checkErrors=function(e,t){const r={};return Object.keys(e).forEach((o=>{const s=t[o],c=e[o],u=n(c,o,s);"function"!=typeof c&&u.length&&(r[o]=u)})),!!Object.keys(r).length&&r},c.hydrate=function(e,t){return r(t)?t.map((t=>new e(t))):new e(t)};export default c; |
@@ -0,1 +1,10 @@ | ||
/**! | ||
* model | ||
* Javascript object model | ||
* https://github.com/jaysalvat/super-store | ||
* @version 0.1.1 built 2021-02-18 18:16:27 | ||
* @license ISC | ||
* @author Jay Salvat http://jaysalvat.com | ||
*/ | ||
(function (global, factory) { | ||
@@ -2,0 +11,0 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : |
@@ -1,261 +0,2 @@ | ||
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | ||
typeof define === 'function' && define.amd ? define(['exports'], factory) : | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Model = {})); | ||
}(this, (function (exports) { 'use strict'; | ||
function isEmpty(value) { | ||
return value === '' || value === null || typeof value === 'undefined' | ||
} | ||
function isFn(value) { | ||
return typeof value === 'function' | ||
} | ||
function isArray(value) { | ||
return Array.isArray(value) | ||
} | ||
function isEqual(value1, value2) { | ||
return JSON.stringify(value1) === JSON.stringify(value2) | ||
} | ||
function checkErrors(entry, property, value) { | ||
const errors = []; | ||
if (entry.required) { | ||
if (isEmpty(value)) { | ||
errors.push({ | ||
message: `Invalid type 'required' on property '${property}'`, | ||
type: 'required', | ||
value: value | ||
}); | ||
} | ||
} | ||
if (entry.type) { | ||
let typeOk; | ||
const types = isArray(entry.type) ? entry.type : [ entry.type ]; | ||
if (!entry.required && isEmpty(value)) { | ||
typeOk = true; | ||
} else { | ||
typeOk = types.some((type) => { | ||
return typeof value === typeof type() || value instanceof type | ||
}); | ||
} | ||
if (!typeOk) { | ||
errors.push({ | ||
message: `Invalid type '${typeof value}' on property '${property}'`, | ||
type: 'type', | ||
value: value, | ||
expected: types | ||
}); | ||
} | ||
} | ||
if (entry.rule) { | ||
Object.keys(entry.rule).forEach((key) => { | ||
const rule = entry.rule[key]; | ||
if (!rule(value)) { | ||
errors.push({ | ||
message: `Invalid value '${key}' on property '${property}'`, | ||
type: key, | ||
value: value, | ||
expected: rule(value) | ||
}); | ||
} | ||
}); | ||
} | ||
return errors | ||
} | ||
class ModelError extends Error { | ||
constructor(data) { | ||
super(data.message); | ||
Object.assign(this, data); | ||
} | ||
} | ||
class ModelHandler { | ||
constructor(schema = {}) { | ||
this.schema = schema; | ||
} | ||
// Setter | ||
set(target, property, value) { | ||
const schema = this.schema; | ||
const entry = schema[property]; | ||
const oldValue = target[property]; | ||
const updated = !isEqual(value, oldValue); | ||
function trigger(method) { | ||
return Reflect.apply(method, target, [ property, value, oldValue, schema ]) | ||
} | ||
if (isFn(entry)) { | ||
return false | ||
} | ||
if (entry.transform) { | ||
value = entry.transform(value); | ||
} | ||
trigger(target.onBeforeSet); | ||
if (updated) { | ||
trigger(target.onBeforeUpdate); | ||
} | ||
if (Model.settings.exeptions) { | ||
const errors = checkErrors(entry, property, value); | ||
if (errors.length) { | ||
errors.forEach((error) => { | ||
throw new ModelError({ | ||
message: error.message, | ||
property: property, | ||
type: error.type, | ||
value: error.value, | ||
expected: error.expected | ||
}) | ||
}); | ||
} | ||
} | ||
target[property] = value; | ||
trigger(target.onSet); | ||
if (updated) { | ||
trigger(target.onUpdate); | ||
} | ||
return true | ||
} | ||
// Getter | ||
get(target, property) { | ||
let value = target[property]; | ||
const schema = this.schema; | ||
const entry = schema[property]; | ||
if (target.hasOwnProperty(property)) { | ||
return target[property] | ||
} | ||
if (!entry) { | ||
return target[property] | ||
} | ||
function trigger(method, args) { | ||
return Reflect.apply(method, target, args) | ||
} | ||
trigger(target.onBeforeGet, [ property, value, schema ]); | ||
if (isFn(entry)) { | ||
value = trigger(entry, [ target ]); | ||
} | ||
if (isFn(entry.format)) { | ||
value = trigger(entry.format, [ value, target ]); | ||
} | ||
trigger(target.onGet, [ property, value, schema ]); | ||
return value | ||
} | ||
} | ||
class Model { | ||
constructor(schema = {}, data = {}) { | ||
Object.keys(schema).forEach((key) => { | ||
if (schema[key].default) { | ||
this[key] = schema[key].default; | ||
} | ||
}); | ||
this.feed(data); | ||
} | ||
feed(data) { | ||
Object.keys(data).forEach((key) => { | ||
this[key] = data[key]; | ||
}); | ||
} | ||
onSet() {} | ||
onGet() {} | ||
onUpdate() {} | ||
onBeforeSet() {} | ||
onBeforeGet() {} | ||
onBeforeUpdate() {} | ||
} | ||
Model.settings = { | ||
exceptions: true | ||
}; | ||
Model.create = function (type, schema = {}, prototype = {}) { | ||
const ModelClass = { | ||
[type]: class extends Model { | ||
constructor(data) { | ||
super(schema, data); | ||
return new Proxy(this, new ModelHandler(schema)) | ||
} | ||
} | ||
}; | ||
Object.assign(ModelClass[type].prototype, prototype); | ||
return ModelClass[type] | ||
}; | ||
Model.throwExeptions = function (bool) { | ||
Model.settings.exeptions = bool; | ||
}; | ||
Model.checkErrors = function (schema, payload) { | ||
const invalidations = {}; | ||
Object.keys(schema).forEach((property) => { | ||
const value = payload[property]; | ||
const entry = schema[property]; | ||
const errors = checkErrors(entry, property, value); | ||
if (typeof entry === 'function') { | ||
return | ||
} | ||
if (errors.length) { | ||
invalidations[property] = errors; | ||
} | ||
return | ||
}); | ||
return Object.keys(invalidations).length ? invalidations : false | ||
}; | ||
Model.hydrate = function (ModelToHydrate, payload) { | ||
if (isArray(payload)) { | ||
return payload.map((item) => new ModelToHydrate(item)) | ||
} else { | ||
return new ModelToHydrate(payload) | ||
} | ||
}; | ||
exports.default = Model; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
}))); | ||
/*! model v0.1.1 */ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Model={})}(this,(function(e){"use strict";function t(e){return""===e||null==e}function n(e){return"function"==typeof e}function r(e){return Array.isArray(e)}function o(e,n,o){const s=[];if(e.required&&t(o)&&s.push({message:`Invalid type 'required' on property '${n}'`,type:"required",value:o}),e.type){let c;const u=r(e.type)?e.type:[e.type];c=!(e.required||!t(o))||u.some((e=>typeof o==typeof e()||o instanceof e)),c||s.push({message:`Invalid type '${typeof o}' on property '${n}'`,type:"type",value:o,expected:u})}return e.rule&&Object.keys(e.rule).forEach((t=>{const r=e.rule[t];r(o)||s.push({message:`Invalid value '${t}' on property '${n}'`,type:t,value:o,expected:r(o)})})),s}class s extends Error{constructor(e){super(e.message),Object.assign(this,e)}}class c{constructor(e={}){this.schema=e}set(e,t,r){const c=this.schema,f=c[t],i=e[t],p=(a=r,y=i,!(JSON.stringify(a)===JSON.stringify(y)));var a,y;function l(n){return Reflect.apply(n,e,[t,r,i,c])}if(n(f))return!1;if(f.transform&&(r=f.transform(r)),l(e.onBeforeSet),p&&l(e.onBeforeUpdate),u.settings.exeptions){const e=o(f,t,r);e.length&&e.forEach((e=>{throw new s({message:e.message,property:t,type:e.type,value:e.value,expected:e.expected})}))}return e[t]=r,l(e.onSet),p&&l(e.onUpdate),!0}get(e,t){let r=e[t];const o=this.schema,s=o[t];if(e.hasOwnProperty(t))return e[t];if(!s)return e[t];function c(t,n){return Reflect.apply(t,e,n)}return c(e.onBeforeGet,[t,r,o]),n(s)&&(r=c(s,[e])),n(s.format)&&(r=c(s.format,[r,e])),c(e.onGet,[t,r,o]),r}}class u{constructor(e={},t={}){Object.keys(e).forEach((t=>{e[t].default&&(this[t]=e[t].default)})),this.feed(t)}feed(e){Object.keys(e).forEach((t=>{this[t]=e[t]}))}onSet(){}onGet(){}onUpdate(){}onBeforeSet(){}onBeforeGet(){}onBeforeUpdate(){}}u.settings={exceptions:!0},u.create=function(e,t={},n={}){const r={[e]:class extends u{constructor(e){return super(t,e),new Proxy(this,new c(t))}}};return Object.assign(r[e].prototype,n),r[e]},u.throwExeptions=function(e){u.settings.exeptions=e},u.checkErrors=function(e,t){const n={};return Object.keys(e).forEach((r=>{const s=t[r],c=e[r],u=o(c,r,s);"function"!=typeof c&&u.length&&(n[r]=u)})),!!Object.keys(n).length&&n},u.hydrate=function(e,t){return r(t)?t.map((t=>new e(t))):new e(t)},e.default=u,Object.defineProperty(e,"__esModule",{value:!0})})); |
{ | ||
"name": "@jaysalvat/smart-model", | ||
"version": "0.1.0", | ||
"version": "0.1.1", | ||
"description": "Javascript object model", | ||
@@ -8,3 +8,2 @@ "main": "./build/smart-model.umd.js", | ||
"browser": "./build/smart-model.umd.min.js", | ||
"type": "module", | ||
"scripts": { | ||
@@ -11,0 +10,0 @@ "test": "open http://localhost:5500/test/index.html && light-server -s . -p 5500", |
@@ -36,3 +36,3 @@ [![npm version](https://badge.fury.io/js/%40jaysalvat%2Fsmart-model.svg)](https://badge.fury.io/js/%40jaysalvat%2Fmodel) | ||
```html | ||
<script src="https://unpkg.com/@jaysalvat/model@latest/build/smart-model.umd.min.js"></script> | ||
<script src="https://unpkg.com/@jaysalvat/smart-model@latest/build/smart-model.umd.min.js"></script> | ||
``` | ||
@@ -39,0 +39,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
28869
815
No