UNPKG

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