UNPKG

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