UNPKG

6.34 kBJavaScriptView Raw
1"use strict";
2
3const EXCEPTION_MSGS = {
4 array: `Doesn't support Array in template yet. The meaning might differ in different context. Please use custom function instead.\nTreating as ${true}`,
5 mergeTypeChecking: "Using Type Checking in template but object target object doesn't match.\nReturning template Type as result.",
6 existTypeChecking: "Using Type Checking in template but object target object doesn't match.\nReturning undefined.",
7 arrayIterFirstArg: "First argument of ArrayIter must be a function of obj-filter",
8};
9
10const getExceptionMsg = (type, second = false) => `obj-filter: ${second ? second + ": " : ""}${EXCEPTION_MSGS[type]}`;
11
12function _isType (template) {
13 if (
14 (template === String)
15 || (template === Number)
16 || (template === Boolean)
17 || (template === Array)
18 || (template === Symbol)
19 || (template === Map)
20 || (template === Set)
21 || (template === WeakMap)
22 || (template === WeakSet)
23 || (template === Object)
24 || (template === Function)
25 ) {
26 return true;
27 }
28
29 return false;
30}
31
32function _sameType (template, obj) {
33 if (
34 (template === String && typeof obj === "string")
35 || (template === Number && typeof obj === "number")
36 || (template === Boolean && typeof obj === "boolean")
37 || (template === Array && Array.isArray(obj))
38 || (template === Symbol && obj instanceof Symbol)
39 || (template === Map && obj instanceof Map)
40 || (template === Set && obj instanceof Set)
41 || (template === WeakMap && obj instanceof WeakMap)
42 || (template === WeakSet && obj instanceof WeakSet)
43 || (template === Function && typeof obj === "function")
44 || (template === Object && typeof obj === "object")
45 ) {
46 return true;
47 }
48
49 return false;
50}
51
52
53function filter (template, obj, onException) {
54
55 // exclude what's undefined in template
56 if (typeof template === "undefined") {
57 return undefined;
58 }
59
60 // only check Type
61 if ( _isType(template) ) {
62 if ( _sameType(template, obj) ) {
63 return obj;
64 }
65
66 // type mismatch
67 if (onException) {
68 return onException(template, obj);
69 }
70 return undefined;
71 }
72
73 // handle Array as True
74 if (template instanceof Array) {
75 if (onException) {
76 return onException(
77 template,
78 obj,
79 getExceptionMsg("array")
80 );
81 }
82 return obj;
83 }
84
85 // filtering
86 if ( typeof template === "object" ){
87 if (typeof obj === "object") {
88 return Object.keys(template).reduce((result, key) => {
89 const tmp = filter(template[key], obj[key], onException);
90
91 if (typeof tmp !== "undefined") {
92 result[key] = tmp;
93 }
94 return result;
95 }, {});
96 }
97
98 // type mismatch
99 if (onException) {
100 return onException(template, obj);
101 }
102 return undefined;
103 }
104
105
106 if ( typeof template === "function" ) {
107 return template(obj);
108 }
109
110 return obj;
111}
112
113function merge (template, obj, onException) {
114
115 // exclude what's undefined in template
116 if (typeof template === "undefined") {
117 return undefined;
118 }
119
120 // only check Type
121 if ( _isType(template) ) {
122 if ( _sameType(template, obj) ) {
123 return obj;
124 }
125
126 // type mismatch
127 if (onException) {
128 return onException(
129 template,
130 obj,
131 getExceptionMsg("mergeTypeChecking", "merge")
132 );
133 }
134 return template;
135 }
136
137 // handle Array as True
138 if (template instanceof Array) {
139 if (onException) {
140 return onException(
141 template,
142 obj,
143 getExceptionMsg("array", "merge")
144 );
145 }
146 return obj;
147 }
148
149 // obj ? obj : template ;
150 if ( typeof template === "object" ){
151 if (typeof obj === "object") {
152 return Object.keys(template).reduce((result, key) => {
153 const ret = merge(template[key], obj[key], onException);
154
155 if (typeof ret !== "undefined") {
156 result[key] = ret;
157 } else if (typeof template[key] !== "undefined") {
158 result[key] = template[key];
159 }
160 return result;
161 }, {});
162 } else {
163 // type mismatch
164 if (onException) {
165 return onException(
166 template,
167 obj,
168 getExceptionMsg("mergeTypeChecking", "merge")
169 );
170 }
171 return template;
172 }
173 }
174
175 // must before "undefined" handling, so user can handle undefined if they wanted
176 if ( typeof template === "function" ) {
177 return template(obj);
178 }
179
180 // must after typeof template === "function", so user can handle it if they wanted
181 if (typeof obj === "undefined") {
182 return template;
183 }
184
185 return obj;
186}
187
188function exist (template, obj, onException) {
189
190 // exclude what's undefined in template
191 if (typeof template === "undefined") {
192 return undefined;
193 }
194
195 // only check Type
196 if ( _isType(template) ) {
197 if ( _sameType(template, obj) ) {
198 return obj;
199 }
200
201 // type mismatch
202 if (onException) {
203 return onException(
204 template,
205 obj,
206 getExceptionMsg("existTypeChecking")
207 );
208 }
209
210 return undefined;
211 }
212
213 // handle Array as True
214 if (template instanceof Array) {
215 if (onException) {
216 return onException(
217 template,
218 obj,
219 getExceptionMsg("array", "exist")
220 );
221 }
222 return obj;
223 }
224
225 // must before "undefined" handling, so user can handle undefined if they wanted
226 if (typeof template === "function") {
227 return template(obj);
228 }
229
230 // must after typeof template === "function", so user can handle it if they wanted
231 if (typeof obj === "undefined") {
232 return undefined;
233 }
234
235 // check if all keys exists recursively
236 if (typeof template === "object") {
237 return Object.keys(template).reduce((result, key) => {
238 if (template[key] === undefined) {
239 // value "undefined" means skip
240 return result;
241 }
242
243 const tmp = exist(template[key], obj[key], onException);
244
245 if (typeof tmp === "undefined") {
246 return undefined;
247 }
248
249 result[key] = tmp;
250
251 return result;
252 }, {});
253 }
254
255 // return whatever obj has
256 return obj;
257}
258
259
260function ArrayIter (checker, template, {min = 0, onException} = {}) {
261
262 if (typeof(checker) !== "function") {
263 if (onException) {
264 return onException(undefined, undefined, getExceptionMsg("arrayIterFirstArg"));
265 }
266
267 throw new Error(getExceptionMsg("arrayIterFirstArg"));
268 }
269
270 return function (array) {
271 if (!(array instanceof Array)) {
272 return undefined;
273 }
274
275 const result = array.map((value) => checker(template, value, onException))
276 .filter((x) => x !== undefined);
277
278 return result.length >= min ? result : undefined;
279 };
280}
281
282module.exports = filter;
283module.exports.filter = filter;
284module.exports.merge = merge;
285module.exports.exist = exist;
286module.exports.ArrayIter = ArrayIter;