-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
103 lines (95 loc) · 2.58 KB
/
index.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
96
97
98
99
100
101
102
103
// Natively supported datatypes
let datatypes = [Number, Object, Array, String, Boolean, Date];
function Coerce() {
let cases = [];
function cast(pattern, promisedValue) {
return Promise.resolve(promisedValue).then(value => {
// check special cases first before casting plain objects
for (let instance of cases) {
if (instance.condition(pattern, value)) {
return instance.creator(pattern, value);
}
}
if (pattern == undefined) {
// no pattern specified
// just return the value given
return value;
} else if (datatypes.includes(pattern)) {
if (value == undefined) {
return;
} else if (value instanceof pattern) {
// No need to perform casting
return value;
} else if (pattern == Date) {
// calling Date returns a Number, use keyword new to return a Date object
return new pattern(value);
} else {
// cast value to Number, Object, Array, Boolean, String, Date
return pattern(value);
}
} else if (pattern instanceof Array) {
if (value instanceof Array) {
// recursively cast array elements
return Promise.all(value.map((data) => cast(pattern[0], data)));
} else {
if (value == undefined) {
return [];
} else {
return cast(pattern[0], value).then(value => [value]);
}
}
} else if (pattern.constructor == Object) {
if (value == undefined) {
return;
} else if (value.constructor == Object) {
let keys = [], promises = [];
for (let key in pattern) {
// recursively cast object values
// keep undefined for casting
keys.push(key);
promises.push(cast(pattern[key], value[key]));
}
return Promise.all(promises).then(values => {
let result = {};
for (let index in keys) {
// ignore undefined on output
if (values[index] != undefined) {
result[keys[index]] = values[index];
}
}
return result;
});
} else {
// type error
// fail silently
return;
}
} else {
// what is this?
return value;
}
});
}
this.cast = function(pattern, promisedValue, callback) {
if (callback && typeof callback == 'function') {
cast(pattern, promisedValue).then(result => {
callback(null, result);
}).catch(error => {
callback(error);
});
} else {
return cast(pattern, promisedValue);
}
}
// Adds a user defined case
this.addRule = function(condition, creator) {
cases.unshift({ condition, creator });
}
// Set a getter for cases
Object.assign(this, {
get cases() {
return cases;
}
})
}
module.exports = Coerce;