UNPKG

7.37 kBMarkdownView Raw
1[![Build Status](https://travis-ci.org/BlueT/obj-filter.svg?branch=master)](https://travis-ci.org/BlueT/obj-filter)
2[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=obj-filter&metric=alert_status)](https://sonarcloud.io/dashboard?id=obj-filter)
3
4# obj-filter - JavaScript Object Filter / Merger.
5
6JavaScript Object Filter. **Deep** filtering key/content *recursively*.
7Support **type checking**, **wildcard**, **nested**, and **filter function** in *template*.
8
9## INSTALL
10
11`npm i obj-filter`
12
13Or find help from:
14- https://www.npmjs.com/package/obj-filter
15- https://github.com/BlueT/obj-filter
16
17## SYNOPSIS
18
19~~~~ js
20"use strict";
21
22var filter = require('obj-filter');
23
24var template = {
25 "runtime": {
26 "connectionState": undefined,
27 "powerState": function (args) {return "HELLO WORLD " + args},
28 "bootTime": "my boot time",
29 "paused": false,
30 "snapshotInBackground": 1111111
31 },
32 "running": Boolean
33};
34
35var clean_data = filter( template, fetchData() );
36
37var updated_data = filter.merge( clean_data, newUpdates() );
38
39var clean_full_data = filter.exist( template, fetchData() );
40~~~~
41
42## Template Object
43According to the **Template Object structure**, `obj-filter` supports the following types of value with different behaviors to build the result object.
44
45### undefined
46If the *value* of the key is `undefined`, the key will be **filtered** (skipped) and will not included in result object.
47
48### object
49If the *value* of the key is an `object`, `obj-filter` will _dive into it and check the **deeper** level of keys_.
50
51### function
52If the *value* of the key is an `function`, `obj-filter` will _pass the **value** of the same key in **input data** to the **function**_, and includes it's returned data in result.
53So it's your call to customize how you would like to handle, define what you want to do with the input data. Be sure to **return something** from your function.
54
55- If return `undefined`, the key will be **filtered** (skipped).
56- If return anything else, the key will be **included**.
57
58### DataTypes / Constructors
59`String`, `Number`, `Boolean`, `Array`, `Symbol`, `Map`, `Set`, `WeakMap`, `WeakSet`, `Object`, `Function` in template will do type checking on target object.
60
61Success if type matches and fails if they don't.
62
63### Anything else (string, array, number, etc)
64The value of the key will be **included**.
65
66### onException callback function
67You can pass an additional `onException` callback function into `filter()`, `filter.merge()`, and `filter.exist()` to handle exceptions.
68
69`onException(template, input, error_msg)` will be called when data expected but type mismatch or undefined.
70
71~~~~ js
72filter(template, data, (tpl, obj, err) => { console.dir({tpl, obj, err}); return undefined; });
73~~~~
74
75## Default Function
76
77### Keep only wanted data
78
79When fetching data through API, sometimes the returned data could be Huge. You need many of them, but there are also too many trash included in returned data.
80Copying with `result[xxx] = input[xxx];` each by each, line by line, is a hell.
81Now you can copy one returned data structure (in JSON) to your favorite text editor, delete all unwanted lines, paste it back to your code, and use it as template.
82
83~~~~ js
84"use strict";
85
86var filter = require('obj-filter');
87
88var template = {
89 "runtime": {
90 "connectionState": undefined, // In Template, when the value is undefined, the key will be ignored.
91 "powerState": function (args) {return "HELLO WORLD " + args}, // pass data into your function, and use it as result value
92 "bootTime": "my boot time", // The string is just for your own note. Will keep whatever input is in result.
93 "paused": false, // Will keep whatever input is in result.
94 "snapshotInBackground": 1111111 // Will keep whatever input is in result.
95 }
96};
97
98var data = function_or_somewhere();
99
100// Assume:
101// var data = {
102// "vm": {
103// "type": "VirtualMachine"
104// },
105// "runtime": {
106// "device": 9999,
107// "connectionState": "connected",
108// "powerState": "poweredOn",
109// "bootTime": "2017-04-20T13:56:19.377Z",
110// "paused": false,
111// "snapshotInBackground": true
112// }
113//};
114
115
116var clean_data = filter(template, data);
117
118// clean_data is:
119{
120 "runtime": {
121 "powerState": "HELLO WORLD poweredOn",
122 "bootTime": "2017-04-20T13:56:19.377Z",
123 "paused": false,
124 "snapshotInBackground": true
125 }
126};
127~~~~
128
129### User Data Checks
130
131Validate user input data in browser (before send to server), or check them at server-side.
132
133~~~~ js
134var template = {
135 email: validateEmail(email), // call function validateEmail and use it's return value as value
136 username: function (username) {
137 if (/^[a-zA-Z_]+$/.test(username)) { // check if username contains only a-z or underscore
138 return username;
139 } else {
140 throw new Error('Invalid username');
141 }
142 },
143 password: "original password" // keep whatever user inputs
144}
145
146save_or_send( filter(template, inputData) );
147~~~~
148
149### Separated template file
150
151You can save template into separated files.
152
153Say _data_template/vmInfo.js_
154
155~~~~ js
156{
157 "runtime": {
158 "connectionState": undefined,
159 "powerState": function (args) {return "HELLO WORLD " + args},
160 "bootTime": "my boot time",
161 "paused": false,
162 "snapshotInBackground": 1111111
163 }
164};
165~~~~
166
167Require it as template
168
169~~~~ js
170var vm_tpl = require('data_template/vmInfo.js');
171
172var vmData = filter(vm_tpl, yourData)
173~~~~
174
175## `merge` Function
176
177### Keep template keys when not provided in input data.
178
179~~~~ js
180"use strict";
181
182var filter = require('obj-filter');
183
184var template = {
185 "runtime": {
186 "connectionState": undefined,
187 "powerState": function (args) {return "HELLO WORLD " + args},
188 "CoffeeTeaOrMe": "Me"
189 }
190};
191
192var newUpdates = fetchChanges();
193
194// Assume:
195// var newUpdates = {
196// "runtime": {
197// "connectionState": "connected",
198// "powerState": "poweredOn"
199// }
200//};
201
202
203var updated_data = filter.merge(template, newUpdates);
204
205// updated_data is:
206{
207 "runtime": {
208 "powerState": "HELLO WORLD poweredOn",
209 "bootTime": "2017-04-20T13:56:19.377Z",
210 "CoffeeTeaOrMe": "Me"
211 }
212};
213~~~~
214
215
216## `exist` Function
217
218### Similar to default `filter`, but All Keys in template must also exists in input data.
219
220~~~~ js
221"use strict";
222
223var filter = require('obj-filter');
224
225var template = {
226 "vm": undefined,
227 "runtime": {
228 "connectionState": undefined,
229 "powerState": function (args) {return "HELLO WORLD " + args},
230 "bootTime": "my boot time",
231 "obj jj": { "kk": "yy" }
232 }
233};
234
235var data = fetch_from_somewhere();
236
237// Assume:
238// var data = {
239// "runtime": {
240// "device": 9999,
241// "connectionState": "connected",
242// "powerState": "poweredOn",
243// "bootTime": 2,
244// "obj jj": { "kk": "zz" }
245// }
246// };
247
248
249var clean_full_data = filter.exist(template, data);
250
251// clean_full_data is:
252{
253 "runtime": {
254 "powerState": "HELLO WORLD poweredOn",
255 "bootTime": 2,
256 "obj jj": { "kk": "zz" }
257 }
258};
259~~~~
260
261## Contribute
262
263PRs welcome!
264If you use/like this module, please don't hesitate to give me a **Star**. I'll be happy whole day!
265
266_Hope this module can save your time, a tree, and a kitten._