objectmodel 4.3.1 → 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.js +13 -13
- package/build/bundle-entry.dev.js +2 -2
- package/build/bundle-entry.js +11 -11
- package/dist/object-model.cjs +462 -469
- package/dist/object-model.js +462 -469
- 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 +4 -4
- package/package.json +9 -3
- 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/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/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 -1346
- 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/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;
|
|
@@ -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
|
})
|