objectmodel 4.3.0 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +8 -8
- package/.eslintrc.json +25 -25
- package/.travis.yml +2 -2
- package/LICENSE +22 -22
- package/README.md +67 -67
- package/build/{add-banner.cjs → add-banner.js} +13 -13
- package/build/bundle-entry.dev.js +2 -2
- package/build/bundle-entry.js +11 -11
- package/build/{update-docs.cjs → update-docs.js} +7 -5
- package/dist/object-model.cjs +466 -472
- package/dist/object-model.js +466 -472
- package/dist/object-model.js.map +1 -1
- package/dist/object-model.min.js +2 -2
- package/dist/object-model.min.js.map +1 -1
- package/index.html +1603 -1603
- package/package.json +20 -10
- package/rollup.config.js +13 -13
- package/src/array-model.d.ts +16 -0
- package/src/array-model.js +68 -68
- package/src/devtool-formatter.js +198 -198
- package/src/function-model.d.ts +24 -0
- package/src/function-model.js +58 -65
- package/src/helpers.js +43 -43
- package/src/index.js +4 -4
- package/src/list-model.js +43 -43
- package/src/map-model.d.ts +18 -0
- package/src/map-model.js +48 -48
- package/src/object-model.d.ts +74 -0
- package/src/object-model.js +4 -3
- package/src/set-model.d.ts +16 -0
- package/src/set-model.js +41 -41
- package/test/array-model.spec.cjs +291 -291
- package/test/array-model.test-d.ts +24 -0
- package/test/basic-model.spec.cjs +263 -263
- package/test/basic-model.test-d.ts +30 -0
- package/test/bench/array.html +51 -51
- package/test/bench/bench-lib.js +49 -49
- package/test/bench/map-no-cast.html +53 -53
- package/test/bench/map-set.html +52 -52
- package/test/bench/map.html +51 -51
- package/test/bench/object-models.html +87 -87
- package/test/function-model.spec.cjs +161 -162
- package/test/function-model.test-d.ts +18 -0
- package/test/index.cjs +13 -13
- package/test/index.html +27 -27
- package/test/map-model.spec.cjs +224 -224
- package/test/map-model.test-d.ts +21 -0
- package/test/model.spec.cjs +30 -30
- package/test/object-model.spec.cjs +1345 -1327
- package/test/object-model.test-d.ts +53 -0
- package/test/set-model.spec.cjs +213 -213
- package/test/set-model.test-d.ts +17 -0
- package/test/umd.html +25 -25
- package/types/definitions.d.ts +43 -0
- package/types/helpers.d.ts +4 -0
- package/types/index.d.ts +6 -128
- package/test/lib/qunit.css +0 -436
- package/test/lib/qunit.js +0 -6582
- package/tsconfig.json +0 -10
package/src/function-model.js
CHANGED
|
@@ -1,66 +1,59 @@
|
|
|
1
|
-
import {
|
|
2
|
-
_check, _original, Any, checkAssertions, checkDefinition, extendDefinition, extendModel,
|
|
3
|
-
formatDefinition, initModel, Model, stackError, unstackErrors
|
|
4
|
-
} from "./object-model.js"
|
|
5
|
-
import { extend, is, isFunction } from "./helpers.js"
|
|
6
|
-
|
|
7
|
-
export default function FunctionModel(...argsDef) {
|
|
8
|
-
return initModel({ arguments: argsDef }, FunctionModel, Function, null, model => ({
|
|
9
|
-
getPrototypeOf: () => model.prototype,
|
|
10
|
-
|
|
11
|
-
get(fn, key) {
|
|
12
|
-
return key === _original ? fn : fn[key]
|
|
13
|
-
},
|
|
14
|
-
|
|
15
|
-
apply(fn, ctx, args) {
|
|
16
|
-
const def = model.definition
|
|
17
|
-
const remainingArgDef = def.arguments.find(argDef => is(Any.remaining, argDef))
|
|
18
|
-
const nbArgsToCheck = remainingArgDef ? Math.max(args.length, def.arguments.length - 1) : def.arguments.length
|
|
19
|
-
|
|
20
|
-
for (let i = 0; i < nbArgsToCheck; i++) {
|
|
21
|
-
const argDef = remainingArgDef && i >= def.arguments.length - 1 ? remainingArgDef.definition : def.arguments[i]
|
|
22
|
-
args[i] = checkDefinition(args[i], argDef, `arguments[${i}]`, model.errors, [], true)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
checkAssertions(args, model, "arguments")
|
|
26
|
-
|
|
27
|
-
let result
|
|
28
|
-
if (!model.errors.length) {
|
|
29
|
-
result = Reflect.apply(fn, ctx, args)
|
|
30
|
-
if ("return" in def)
|
|
31
|
-
result = checkDefinition(result, def.return, "return value", model.errors, [], true)
|
|
32
|
-
}
|
|
33
|
-
unstackErrors(model)
|
|
34
|
-
return result
|
|
35
|
-
}
|
|
36
|
-
}))
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
extend(FunctionModel, Model, {
|
|
40
|
-
toString(stack = []) {
|
|
41
|
-
let out = `Function(${this.definition.arguments.map(
|
|
42
|
-
argDef => formatDefinition(argDef, [...stack])
|
|
43
|
-
).join(", ")})`
|
|
44
|
-
|
|
45
|
-
if ("return" in this.definition) {
|
|
46
|
-
out += " => " + formatDefinition(this.definition.return, stack)
|
|
47
|
-
}
|
|
48
|
-
return out
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
return(def) {
|
|
52
|
-
this.definition.return = def
|
|
53
|
-
return this
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
mixedReturns = extendDefinition(this.definition.return, newReturns)
|
|
60
|
-
return extendModel(new FunctionModel(...mixedArgs).return(mixedReturns), this)
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
[_check](f, path, errors) {
|
|
64
|
-
if (!isFunction(f)) stackError(errors, "Function", f, path)
|
|
65
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
_check, _original, Any, checkAssertions, checkDefinition, extendDefinition, extendModel,
|
|
3
|
+
formatDefinition, initModel, Model, stackError, unstackErrors
|
|
4
|
+
} from "./object-model.js"
|
|
5
|
+
import { extend, is, isFunction } from "./helpers.js"
|
|
6
|
+
|
|
7
|
+
export default function FunctionModel(...argsDef) {
|
|
8
|
+
return initModel({ arguments: argsDef }, FunctionModel, Function, null, model => ({
|
|
9
|
+
getPrototypeOf: () => model.prototype,
|
|
10
|
+
|
|
11
|
+
get(fn, key) {
|
|
12
|
+
return key === _original ? fn : fn[key]
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
apply(fn, ctx, args) {
|
|
16
|
+
const def = model.definition
|
|
17
|
+
const remainingArgDef = def.arguments.find(argDef => is(Any.remaining, argDef))
|
|
18
|
+
const nbArgsToCheck = remainingArgDef ? Math.max(args.length, def.arguments.length - 1) : def.arguments.length
|
|
19
|
+
|
|
20
|
+
for (let i = 0; i < nbArgsToCheck; i++) {
|
|
21
|
+
const argDef = remainingArgDef && i >= def.arguments.length - 1 ? remainingArgDef.definition : def.arguments[i]
|
|
22
|
+
args[i] = checkDefinition(args[i], argDef, `arguments[${i}]`, model.errors, [], true)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
checkAssertions(args, model, "arguments")
|
|
26
|
+
|
|
27
|
+
let result
|
|
28
|
+
if (!model.errors.length) {
|
|
29
|
+
result = Reflect.apply(fn, ctx, args)
|
|
30
|
+
if ("return" in def)
|
|
31
|
+
result = checkDefinition(result, def.return, "return value", model.errors, [], true)
|
|
32
|
+
}
|
|
33
|
+
unstackErrors(model)
|
|
34
|
+
return result
|
|
35
|
+
}
|
|
36
|
+
}))
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
extend(FunctionModel, Model, {
|
|
40
|
+
toString(stack = []) {
|
|
41
|
+
let out = `Function(${this.definition.arguments.map(
|
|
42
|
+
argDef => formatDefinition(argDef, [...stack])
|
|
43
|
+
).join(", ")})`
|
|
44
|
+
|
|
45
|
+
if ("return" in this.definition) {
|
|
46
|
+
out += " => " + formatDefinition(this.definition.return, stack)
|
|
47
|
+
}
|
|
48
|
+
return out
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
return(def) {
|
|
52
|
+
this.definition.return = def
|
|
53
|
+
return this
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
[_check](f, path, errors) {
|
|
57
|
+
if (!isFunction(f)) stackError(errors, "Function", f, path)
|
|
58
|
+
}
|
|
66
59
|
})
|
package/src/helpers.js
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
export const
|
|
2
|
-
ObjectProto = Object.prototype,
|
|
3
|
-
bettertypeof = x => ObjectProto.toString.call(x).match(/\s([a-zA-Z]+)/)[1],
|
|
4
|
-
getProto = Object.getPrototypeOf,
|
|
5
|
-
setProto = Object.setPrototypeOf,
|
|
6
|
-
|
|
7
|
-
has = (o, prop) => ObjectProto.hasOwnProperty.call(o, prop),
|
|
8
|
-
is = (Constructor, obj) => obj instanceof Constructor,
|
|
9
|
-
isFunction = f => typeof f === "function",
|
|
10
|
-
isObject = o => o && typeof o === "object",
|
|
11
|
-
isString = s => typeof s === "string",
|
|
12
|
-
isPlainObject = o => isObject(o) && getProto(o) === ObjectProto,
|
|
13
|
-
isIterable = x => x && isFunction(x[Symbol.iterator]),
|
|
14
|
-
|
|
15
|
-
proxify = (val, traps) => new Proxy(val, traps),
|
|
16
|
-
|
|
17
|
-
merge = (target, src = {}) => {
|
|
18
|
-
for (let key in src) {
|
|
19
|
-
if (isPlainObject(src[key])) {
|
|
20
|
-
const o = {}
|
|
21
|
-
merge(o, target[key])
|
|
22
|
-
merge(o, src[key])
|
|
23
|
-
target[key] = o
|
|
24
|
-
} else {
|
|
25
|
-
target[key] = src[key]
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return target
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
define = (obj, key, value, enumerable = false) => {
|
|
32
|
-
Object.defineProperty(obj, key, { value, enumerable, writable: true, configurable: true })
|
|
33
|
-
},
|
|
34
|
-
|
|
35
|
-
extend = (child, parent, props) => {
|
|
36
|
-
child.prototype = Object.assign(Object.create(parent.prototype, {
|
|
37
|
-
constructor: {
|
|
38
|
-
value: child,
|
|
39
|
-
writable: true,
|
|
40
|
-
configurable: true
|
|
41
|
-
}
|
|
42
|
-
}), props)
|
|
43
|
-
setProto(child, parent)
|
|
1
|
+
export const
|
|
2
|
+
ObjectProto = Object.prototype,
|
|
3
|
+
bettertypeof = x => ObjectProto.toString.call(x).match(/\s([a-zA-Z]+)/)[1],
|
|
4
|
+
getProto = Object.getPrototypeOf,
|
|
5
|
+
setProto = Object.setPrototypeOf,
|
|
6
|
+
|
|
7
|
+
has = (o, prop) => ObjectProto.hasOwnProperty.call(o, prop),
|
|
8
|
+
is = (Constructor, obj) => obj instanceof Constructor,
|
|
9
|
+
isFunction = f => typeof f === "function",
|
|
10
|
+
isObject = o => o && typeof o === "object",
|
|
11
|
+
isString = s => typeof s === "string",
|
|
12
|
+
isPlainObject = o => isObject(o) && getProto(o) === ObjectProto,
|
|
13
|
+
isIterable = x => x && isFunction(x[Symbol.iterator]),
|
|
14
|
+
|
|
15
|
+
proxify = (val, traps) => new Proxy(val, traps),
|
|
16
|
+
|
|
17
|
+
merge = (target, src = {}) => {
|
|
18
|
+
for (let key in src) {
|
|
19
|
+
if (isPlainObject(src[key])) {
|
|
20
|
+
const o = {}
|
|
21
|
+
merge(o, target[key])
|
|
22
|
+
merge(o, src[key])
|
|
23
|
+
target[key] = o
|
|
24
|
+
} else {
|
|
25
|
+
target[key] = src[key]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return target
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
define = (obj, key, value, enumerable = false) => {
|
|
32
|
+
Object.defineProperty(obj, key, { value, enumerable, writable: true, configurable: true })
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
extend = (child, parent, props) => {
|
|
36
|
+
child.prototype = Object.assign(Object.create(parent.prototype, {
|
|
37
|
+
constructor: {
|
|
38
|
+
value: child,
|
|
39
|
+
writable: true,
|
|
40
|
+
configurable: true
|
|
41
|
+
}
|
|
42
|
+
}), props)
|
|
43
|
+
setProto(child, parent)
|
|
44
44
|
}
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { Model, BasicModel, ObjectModel, Any } from "./object-model.js"
|
|
2
|
-
export { default as ArrayModel } from "./array-model.js"
|
|
3
|
-
export { default as FunctionModel } from "./function-model.js"
|
|
4
|
-
export { default as MapModel } from "./map-model.js"
|
|
1
|
+
export { Model, BasicModel, ObjectModel, Any } from "./object-model.js"
|
|
2
|
+
export { default as ArrayModel } from "./array-model.js"
|
|
3
|
+
export { default as FunctionModel } from "./function-model.js"
|
|
4
|
+
export { default as MapModel } from "./map-model.js"
|
|
5
5
|
export { default as SetModel } from "./set-model.js"
|
package/src/list-model.js
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
|
|
2
|
-
import { _original, checkAssertions, checkDefinition, initModel, unstackErrors } from "./object-model.js"
|
|
3
|
-
import { has, isFunction, proxify } from "./helpers.js"
|
|
4
|
-
|
|
5
|
-
export const initListModel = (base, constructor, def, init, clone, mutators, otherTraps) => {
|
|
6
|
-
|
|
7
|
-
return initModel(def, constructor, base, init, model => Object.assign({
|
|
8
|
-
getPrototypeOf: () => model.prototype,
|
|
9
|
-
get(l, key) {
|
|
10
|
-
if (key === _original) return l
|
|
11
|
-
|
|
12
|
-
const val = l[key]
|
|
13
|
-
return isFunction(val) ? proxify(val, {
|
|
14
|
-
apply(fn, ctx, args) {
|
|
15
|
-
if (has(mutators, key)) {
|
|
16
|
-
// indexes of arguments to check def + cast
|
|
17
|
-
const [begin, end = args.length - 1, getArgDef] = mutators[key]
|
|
18
|
-
for (let i = begin; i <= end; i++) {
|
|
19
|
-
const argDef = getArgDef ? getArgDef(i) : model.definition
|
|
20
|
-
args[i] = checkDefinition(
|
|
21
|
-
args[i],
|
|
22
|
-
argDef,
|
|
23
|
-
`${base.name}.${key} arguments[${i}]`,
|
|
24
|
-
model.errors,
|
|
25
|
-
[],
|
|
26
|
-
true
|
|
27
|
-
)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (model.assertions.length > 0) {
|
|
31
|
-
const testingClone = clone(l)
|
|
32
|
-
fn.apply(testingClone, args)
|
|
33
|
-
checkAssertions(testingClone, model, `after ${key} mutation`)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
unstackErrors(model)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return fn.apply(l, args)
|
|
40
|
-
}
|
|
41
|
-
}) : val
|
|
42
|
-
}
|
|
43
|
-
}, otherTraps))
|
|
1
|
+
|
|
2
|
+
import { _original, checkAssertions, checkDefinition, initModel, unstackErrors } from "./object-model.js"
|
|
3
|
+
import { has, isFunction, proxify } from "./helpers.js"
|
|
4
|
+
|
|
5
|
+
export const initListModel = (base, constructor, def, init, clone, mutators, otherTraps) => {
|
|
6
|
+
|
|
7
|
+
return initModel(def, constructor, base, init, model => Object.assign({
|
|
8
|
+
getPrototypeOf: () => model.prototype,
|
|
9
|
+
get(l, key) {
|
|
10
|
+
if (key === _original) return l
|
|
11
|
+
|
|
12
|
+
const val = l[key]
|
|
13
|
+
return isFunction(val) ? proxify(val, {
|
|
14
|
+
apply(fn, ctx, args) {
|
|
15
|
+
if (has(mutators, key)) {
|
|
16
|
+
// indexes of arguments to check def + cast
|
|
17
|
+
const [begin, end = args.length - 1, getArgDef] = mutators[key]
|
|
18
|
+
for (let i = begin; i <= end; i++) {
|
|
19
|
+
const argDef = getArgDef ? getArgDef(i) : model.definition
|
|
20
|
+
args[i] = checkDefinition(
|
|
21
|
+
args[i],
|
|
22
|
+
argDef,
|
|
23
|
+
`${base.name}.${key} arguments[${i}]`,
|
|
24
|
+
model.errors,
|
|
25
|
+
[],
|
|
26
|
+
true
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (model.assertions.length > 0) {
|
|
31
|
+
const testingClone = clone(l)
|
|
32
|
+
fn.apply(testingClone, args)
|
|
33
|
+
checkAssertions(testingClone, model, `after ${key} mutation`)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
unstackErrors(model)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return fn.apply(l, args)
|
|
40
|
+
}
|
|
41
|
+
}) : val
|
|
42
|
+
}
|
|
43
|
+
}, otherTraps))
|
|
44
44
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FromDefinition, ModelDefinition } from "../types/definitions";
|
|
2
|
+
import { Model } from "./object-model";
|
|
3
|
+
|
|
4
|
+
export interface MapModel<Key extends ModelDefinition, Value extends ModelDefinition> extends Model<{ key: Key, value: Value}> {
|
|
5
|
+
(iterable: Map<FromDefinition<Key>, FromDefinition<Value>> | Array<[FromDefinition<Key>, FromDefinition<Value>]>): Map<FromDefinition<Key>, FromDefinition<Value>>;
|
|
6
|
+
new(iterable: Map<FromDefinition<Key>, FromDefinition<Value>> | Array<[FromDefinition<Key>, FromDefinition<Value>]>): Map<FromDefinition<Key>, FromDefinition<Value>>;
|
|
7
|
+
|
|
8
|
+
definition: { key: Key, value: Value };
|
|
9
|
+
|
|
10
|
+
extend<Keys extends ModelDefinition[], Values extends ModelDefinition[]>(otherKeys: Keys, otherValues: Values): MapModel<[Key, ...Keys], [Value, ...Values]>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface MapModelConstructor {
|
|
14
|
+
<Key extends ModelDefinition, Value extends ModelDefinition>(keyDefinition: Key, valueDefinition: Value): MapModel<Key, Value>;
|
|
15
|
+
new<Key extends ModelDefinition, Value extends ModelDefinition>(keyDefinition: Key, valueDefinition: Value): MapModel<Key, Value>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const MapModel: MapModelConstructor;
|
package/src/map-model.js
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import {
|
|
2
|
-
_check, cast, checkAssertions, checkDefinition,
|
|
3
|
-
extendDefinition, extendModel, format, formatDefinition, Model, stackError
|
|
4
|
-
} from "./object-model.js"
|
|
5
|
-
import { initListModel } from "./list-model.js"
|
|
6
|
-
import { extend, is, isIterable } from "./helpers.js"
|
|
7
|
-
|
|
8
|
-
export default function MapModel(initialKeyDefinition, initialValueDefinition) {
|
|
9
|
-
const getDef = i => i === 0 ? model.definition.key : model.definition.value;
|
|
10
|
-
const model = initListModel(
|
|
11
|
-
Map,
|
|
12
|
-
MapModel,
|
|
13
|
-
{ key: initialKeyDefinition, value: initialValueDefinition },
|
|
14
|
-
it => isIterable(it) ? new Map([...it].map(pair => pair.map((x, i) => cast(x, getDef(i))))) : it,
|
|
15
|
-
map => new Map(map),
|
|
16
|
-
{
|
|
17
|
-
"set": [0, 1, getDef],
|
|
18
|
-
"delete": [],
|
|
19
|
-
"clear": []
|
|
20
|
-
}
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
return model
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
extend(MapModel, Model, {
|
|
27
|
-
toString(stack) {
|
|
28
|
-
return `Map of ${formatDefinition(this.definition.key, stack)} : ${formatDefinition(this.definition.value, stack)}`
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
[_check](map, path, errors, stack) {
|
|
32
|
-
if (is(Map, map)) {
|
|
33
|
-
path = path || "Map"
|
|
34
|
-
for (let [key, value] of map) {
|
|
35
|
-
checkDefinition(key, this.definition.key, `${path} key`, errors, stack)
|
|
36
|
-
checkDefinition(value, this.definition.value, `${path}[${format(key)}]`, errors, stack)
|
|
37
|
-
}
|
|
38
|
-
} else stackError(errors, this, map, path)
|
|
39
|
-
|
|
40
|
-
checkAssertions(map, this, path, errors)
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
extend(keyParts, valueParts) {
|
|
44
|
-
return extendModel(new MapModel(
|
|
45
|
-
extendDefinition(this.definition.key, keyParts),
|
|
46
|
-
extendDefinition(this.definition.value, valueParts)
|
|
47
|
-
), this)
|
|
48
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
_check, cast, checkAssertions, checkDefinition,
|
|
3
|
+
extendDefinition, extendModel, format, formatDefinition, Model, stackError
|
|
4
|
+
} from "./object-model.js"
|
|
5
|
+
import { initListModel } from "./list-model.js"
|
|
6
|
+
import { extend, is, isIterable } from "./helpers.js"
|
|
7
|
+
|
|
8
|
+
export default function MapModel(initialKeyDefinition, initialValueDefinition) {
|
|
9
|
+
const getDef = i => i === 0 ? model.definition.key : model.definition.value;
|
|
10
|
+
const model = initListModel(
|
|
11
|
+
Map,
|
|
12
|
+
MapModel,
|
|
13
|
+
{ key: initialKeyDefinition, value: initialValueDefinition },
|
|
14
|
+
it => isIterable(it) ? new Map([...it].map(pair => pair.map((x, i) => cast(x, getDef(i))))) : it,
|
|
15
|
+
map => new Map(map),
|
|
16
|
+
{
|
|
17
|
+
"set": [0, 1, getDef],
|
|
18
|
+
"delete": [],
|
|
19
|
+
"clear": []
|
|
20
|
+
}
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
return model
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
extend(MapModel, Model, {
|
|
27
|
+
toString(stack) {
|
|
28
|
+
return `Map of ${formatDefinition(this.definition.key, stack)} : ${formatDefinition(this.definition.value, stack)}`
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
[_check](map, path, errors, stack) {
|
|
32
|
+
if (is(Map, map)) {
|
|
33
|
+
path = path || "Map"
|
|
34
|
+
for (let [key, value] of map) {
|
|
35
|
+
checkDefinition(key, this.definition.key, `${path} key`, errors, stack)
|
|
36
|
+
checkDefinition(value, this.definition.value, `${path}[${format(key)}]`, errors, stack)
|
|
37
|
+
}
|
|
38
|
+
} else stackError(errors, this, map, path)
|
|
39
|
+
|
|
40
|
+
checkAssertions(map, this, path, errors)
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
extend(keyParts, valueParts) {
|
|
44
|
+
return extendModel(new MapModel(
|
|
45
|
+
extendDefinition(this.definition.key, keyParts),
|
|
46
|
+
extendDefinition(this.definition.value, valueParts)
|
|
47
|
+
), this)
|
|
48
|
+
}
|
|
49
49
|
})
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { ExtendObjectDefinition, FromDefinition, FromObjectModelDefinition, ModelDefinition, ObjectModelDefinition } from '../types/definitions';
|
|
2
|
+
|
|
3
|
+
export type Assertion = (variable: unknown) => boolean
|
|
4
|
+
|
|
5
|
+
export interface ModelError {
|
|
6
|
+
message: string;
|
|
7
|
+
expected: any;
|
|
8
|
+
received: any;
|
|
9
|
+
path: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface Model<D> {
|
|
13
|
+
definition: D;
|
|
14
|
+
assertions: Assertion[];
|
|
15
|
+
name: string;
|
|
16
|
+
|
|
17
|
+
conventionForConstant(variableName: string): boolean;
|
|
18
|
+
conventionForPrivate(variableName: string): boolean;
|
|
19
|
+
|
|
20
|
+
toString(stack?: any[]): string;
|
|
21
|
+
|
|
22
|
+
as(name: string): this;
|
|
23
|
+
|
|
24
|
+
defaultTo<Default>(defaultValue: Default): ModelWithDefault<D,Default>;
|
|
25
|
+
|
|
26
|
+
test(value: any, errorCollector?: (errors: ModelError[]) => void): boolean;
|
|
27
|
+
|
|
28
|
+
errorCollector(errors: ModelError[]): void;
|
|
29
|
+
|
|
30
|
+
assert(assertion: Assertion, description?: string | Function): this;
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface ModelWithDefault<D,Default> extends Model<D> {
|
|
35
|
+
default: Default
|
|
36
|
+
|
|
37
|
+
(): Default
|
|
38
|
+
new(): Default
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface ModelConstructor {
|
|
42
|
+
<D>(definition: D): D extends ObjectModelDefinition ? ObjectModel<D> : BasicModel<D>;
|
|
43
|
+
new<D>(definition: D): D extends ObjectModelDefinition ? ObjectModel<D> : BasicModel<D>;
|
|
44
|
+
CHECK_ONCE: symbol;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface BasicModel<D> extends Model<D> {
|
|
48
|
+
(value: FromDefinition<D>): FromDefinition<D>
|
|
49
|
+
new(value: FromDefinition<D>): FromDefinition<D>
|
|
50
|
+
|
|
51
|
+
extend<E extends ModelDefinition[]>(...extensions: E): BasicModel<E extends [] ? D : [D, ...E]>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface BasicModelConstructor {
|
|
55
|
+
<D>(definition: D): BasicModel<D>
|
|
56
|
+
new<D>(definition: D): BasicModel<D>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface ObjectModel<D extends ObjectModelDefinition> extends Model<D> {
|
|
60
|
+
(value: Partial<FromObjectModelDefinition<D>>): FromObjectModelDefinition<D>;
|
|
61
|
+
new(value: Partial<FromObjectModelDefinition<D>>): FromObjectModelDefinition<D>;
|
|
62
|
+
|
|
63
|
+
extend<Extensions extends (ObjectModelDefinition | ObjectModel<any>)[]>(...ext: Extensions) : ObjectModel<ExtendObjectDefinition<D, Extensions>>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface ObjectModelConstructor {
|
|
67
|
+
<D extends ObjectModelDefinition>(definition: D): ObjectModel<D>;
|
|
68
|
+
new<D extends ObjectModelDefinition>(definition: D): ObjectModel<D>;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const Any: any;
|
|
72
|
+
export const Model: ModelConstructor;
|
|
73
|
+
export const BasicModel: BasicModelConstructor;
|
|
74
|
+
export const ObjectModel: ObjectModelConstructor;
|
package/src/object-model.js
CHANGED
|
@@ -33,7 +33,8 @@ export const
|
|
|
33
33
|
if (is(model, obj)) return obj
|
|
34
34
|
|
|
35
35
|
if (!isObject(obj) && !isFunction(obj) && obj !== undefined) {
|
|
36
|
-
|
|
36
|
+
// short circuit validation if not receiving an object as expected
|
|
37
|
+
return obj
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
merge(_this, model.default)
|
|
@@ -325,8 +326,8 @@ export const
|
|
|
325
326
|
}
|
|
326
327
|
|
|
327
328
|
|
|
328
|
-
export function Model(def
|
|
329
|
-
return isPlainObject(def) ? new ObjectModel(def
|
|
329
|
+
export function Model(def) {
|
|
330
|
+
return isPlainObject(def) ? new ObjectModel(def) : new BasicModel(def)
|
|
330
331
|
}
|
|
331
332
|
|
|
332
333
|
Object.assign(Model.prototype, {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { FromDefinition, ModelDefinition } from "../types/definitions";
|
|
2
|
+
import { Model } from "./object-model";
|
|
3
|
+
|
|
4
|
+
export interface SetModel<D extends ModelDefinition> extends Model<D> {
|
|
5
|
+
(set: Set<FromDefinition<D>> | FromDefinition<D>[]): Set<FromDefinition<D>>;
|
|
6
|
+
new(set: Set<FromDefinition<D>> | FromDefinition<D>[]): Set<FromDefinition<D>>;
|
|
7
|
+
|
|
8
|
+
extend<E extends ModelDefinition[]>(...extensions: E): SetModel<E extends [] ? D : [D, ...E]>
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface SetModelConstructor {
|
|
12
|
+
<D extends ModelDefinition>(itemDefinition: D): SetModel<D>;
|
|
13
|
+
new<D extends ModelDefinition>(itemDefinition: D): SetModel<D>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const SetModel: SetModelConstructor;
|
package/src/set-model.js
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
import {
|
|
2
|
-
_check, cast, checkAssertions, checkDefinition,
|
|
3
|
-
extendDefinition, extendModel, formatDefinition, Model, stackError
|
|
4
|
-
} from "./object-model.js"
|
|
5
|
-
import { initListModel } from "./list-model.js"
|
|
6
|
-
import { extend, is, isIterable } from "./helpers.js"
|
|
7
|
-
|
|
8
|
-
export default function SetModel(initialDefinition) {
|
|
9
|
-
const model = initListModel(
|
|
10
|
-
Set,
|
|
11
|
-
SetModel,
|
|
12
|
-
initialDefinition,
|
|
13
|
-
it => isIterable(it) ? new Set([...it].map(val => cast(val, model.definition))) : it,
|
|
14
|
-
set => new Set(set),
|
|
15
|
-
{
|
|
16
|
-
"add": [0, 0],
|
|
17
|
-
"delete": [],
|
|
18
|
-
"clear": []
|
|
19
|
-
}
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
return model
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
extend(SetModel, Model, {
|
|
26
|
-
toString(stack) {
|
|
27
|
-
return "Set of " + formatDefinition(this.definition, stack)
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
[_check](set, path, errors, stack) {
|
|
31
|
-
if (is(Set, set)) {
|
|
32
|
-
for (let item of set.values()) {
|
|
33
|
-
checkDefinition(item, this.definition, `${path || "Set"} value`, errors, stack)
|
|
34
|
-
}
|
|
35
|
-
} else stackError(errors, this, set, path)
|
|
36
|
-
checkAssertions(set, this, path, errors)
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
extend(...newParts) {
|
|
40
|
-
return extendModel(new SetModel(extendDefinition(this.definition, newParts)), this)
|
|
41
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
_check, cast, checkAssertions, checkDefinition,
|
|
3
|
+
extendDefinition, extendModel, formatDefinition, Model, stackError
|
|
4
|
+
} from "./object-model.js"
|
|
5
|
+
import { initListModel } from "./list-model.js"
|
|
6
|
+
import { extend, is, isIterable } from "./helpers.js"
|
|
7
|
+
|
|
8
|
+
export default function SetModel(initialDefinition) {
|
|
9
|
+
const model = initListModel(
|
|
10
|
+
Set,
|
|
11
|
+
SetModel,
|
|
12
|
+
initialDefinition,
|
|
13
|
+
it => isIterable(it) ? new Set([...it].map(val => cast(val, model.definition))) : it,
|
|
14
|
+
set => new Set(set),
|
|
15
|
+
{
|
|
16
|
+
"add": [0, 0],
|
|
17
|
+
"delete": [],
|
|
18
|
+
"clear": []
|
|
19
|
+
}
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
return model
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
extend(SetModel, Model, {
|
|
26
|
+
toString(stack) {
|
|
27
|
+
return "Set of " + formatDefinition(this.definition, stack)
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
[_check](set, path, errors, stack) {
|
|
31
|
+
if (is(Set, set)) {
|
|
32
|
+
for (let item of set.values()) {
|
|
33
|
+
checkDefinition(item, this.definition, `${path || "Set"} value`, errors, stack)
|
|
34
|
+
}
|
|
35
|
+
} else stackError(errors, this, set, path)
|
|
36
|
+
checkAssertions(set, this, path, errors)
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
extend(...newParts) {
|
|
40
|
+
return extendModel(new SetModel(extendDefinition(this.definition, newParts)), this)
|
|
41
|
+
}
|
|
42
42
|
})
|