forked from gcanti/tcomb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dict.js
95 lines (78 loc) · 3.04 KB
/
dict.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
var assert = require('./assert');
var isTypeName = require('./isTypeName');
var isFunction = require('./isFunction');
var getTypeName = require('./getTypeName');
var isIdentity = require('./isIdentity');
var isObject = require('./isObject');
var create = require('./create');
var is = require('./is');
function getDefaultName(domain, codomain) {
return '{[key: ' + getTypeName(domain) + ']: ' + getTypeName(codomain) + '}';
}
function dict(domain, codomain, name) {
if (process.env.NODE_ENV !== 'production') {
assert(isFunction(domain), function () { return 'Invalid argument domain ' + assert.stringify(domain) + ' supplied to dict(domain, codomain, [name]) combinator (expected a type)'; });
assert(isFunction(codomain), function () { return 'Invalid argument codomain ' + assert.stringify(codomain) + ' supplied to dict(domain, codomain, [name]) combinator (expected a type)'; });
assert(isTypeName(name), function () { return 'Invalid argument name ' + assert.stringify(name) + ' supplied to dict(domain, codomain, [name]) combinator (expected a string)'; });
}
var displayName = name || getDefaultName(domain, codomain);
var domainNameCache = getTypeName(domain);
var codomainNameCache = getTypeName(codomain);
var identity = isIdentity(domain) && isIdentity(codomain);
function Dict(value, path) {
if (process.env.NODE_ENV === 'production') {
if (identity) {
return value; // just trust the input if elements must not be hydrated
}
}
if (process.env.NODE_ENV !== 'production') {
path = path || [displayName];
assert(isObject(value), function () { return 'Invalid value ' + assert.stringify(value) + ' supplied to ' + path.join('/'); });
}
var idempotent = true; // will remain true if I can reutilise the input
var ret = {}; // make a temporary copy, will be discarded if idempotent remains true
for (var k in value) {
if (value.hasOwnProperty(k)) {
k = create(domain, k, ( process.env.NODE_ENV !== 'production' ? path.concat(domainNameCache) : null ));
var actual = value[k];
var instance = create(codomain, actual, ( process.env.NODE_ENV !== 'production' ? path.concat(k + ': ' + codomainNameCache) : null ));
idempotent = idempotent && ( actual === instance );
ret[k] = instance;
}
}
if (idempotent) { // implements idempotency
ret = value;
}
if (process.env.NODE_ENV !== 'production') {
Object.freeze(ret);
}
return ret;
}
Dict.meta = {
kind: 'dict',
domain: domain,
codomain: codomain,
name: name,
identity: identity
};
Dict.displayName = displayName;
Dict.is = function (x) {
if (!isObject(x)) {
return false;
}
for (var k in x) {
if (x.hasOwnProperty(k)) {
if (!is(k, domain) || !is(x[k], codomain)) {
return false;
}
}
}
return true;
};
Dict.update = function (instance, patch) {
return Dict(assert.update(instance, patch));
};
return Dict;
}
dict.getDefaultName = getDefaultName;
module.exports = dict;