@peter.naydenov/walk-async 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Changelog.md +8 -0
- package/LICENSE +21 -0
- package/README.md +253 -0
- package/dist/walk-async.min.js +1 -0
- package/package.json +45 -0
- package/src/main.js +191 -0
- package/test/01-deepCopy.test.js +79 -0
- package/test/02-keyCallback.test.js +151 -0
- package/test/03-objectCallback.test.js +249 -0
- package/test/04-async.test.js +83 -0
- package/webpack.config.js +26 -0
package/Changelog.md
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Peter Naydenov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# Walk-async (@peter.naydenov/walk-async)
|
|
2
|
+
|
|
3
|
+
Creates an immutable copies of javascript data structures(objects, arrays or mixed). Can execute callback functions on every object property(objectCallback) and/or every primitive property(keyCallback). Callbacks can modify result object during the walk process. Mask, filter or substitute values during the copy process.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
|
|
7
|
+
walk ({
|
|
8
|
+
data // (required) Any JS object structure
|
|
9
|
+
, objectCallback // (optional) Function executed on each object property
|
|
10
|
+
, keyCallback // (optional) Function executed on each primitive property
|
|
11
|
+
})
|
|
12
|
+
.then ( result => {
|
|
13
|
+
// Result will become a exact deep copy of "data"
|
|
14
|
+
// - if callbacks are not defined
|
|
15
|
+
// - if callbacks are resolved with "value" without modification
|
|
16
|
+
})
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
It is very simular to [`@peter.naydenov/walk`](https://github.com/PeterNaydenov/walk) but there are some differences:
|
|
20
|
+
- `walk-async` returns a result as a promise;
|
|
21
|
+
- `walk-async` can execute async operations inside callback methods;
|
|
22
|
+
- `walk-async` keyCallback can return as a result object, array or primitives.
|
|
23
|
+
- `walk` keyCallback can return only primitives;
|
|
24
|
+
- `walk` can not execute another walk call inside callback functions;
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
## кeyCallback
|
|
29
|
+
Function **keyCallback** of the `walk-async` could be used also as a deep '**forEach**' method no matter of the type of the object(object or array).
|
|
30
|
+
|
|
31
|
+
```js
|
|
32
|
+
function keyCallbackFn ({ value, key, breadcrumbs, resolve, reject }) {
|
|
33
|
+
// value: value of the property. Only primitives;
|
|
34
|
+
// key: key of the property;
|
|
35
|
+
// breadcrumbs: location of the property;
|
|
36
|
+
// resolve: function that will resolve the callback promise. Provide the result as argument;
|
|
37
|
+
// reject: function that can cancel the copy of that property;
|
|
38
|
+
// Important: key callback should be resolved or rejected.
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const result = await walk ({ data, keyCallback : keyCallbackFn }); // It's the short way to provide only key-callback. Callback functions are optional.
|
|
42
|
+
// walk ({ data, keyCallback, objectCallback }); // If both callbacks are available
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
## Object-callback
|
|
47
|
+
|
|
48
|
+
Optional callback function that is started on each object property. Function should resolve or reject. Rejection of the property will remove it from the result.
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
function objectCallbackFn ({ value, key, breadcrumbs, resolve, reject }) {
|
|
52
|
+
// value: each object property during the walk;
|
|
53
|
+
// key: key of the object property;
|
|
54
|
+
// breadcrumbs: location of the object;
|
|
55
|
+
// resolve: function that will resolve the callback promise. Provide the result as argument;
|
|
56
|
+
// reject: function that can cancel the copy of that property;
|
|
57
|
+
// Important: Object callback should be resolved or rejected.
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
walk ({
|
|
61
|
+
data
|
|
62
|
+
, keyCallback: keyCallbackFn
|
|
63
|
+
, objectCallback : objectCallbackFn
|
|
64
|
+
})
|
|
65
|
+
.then ( resultOfWalk => {
|
|
66
|
+
// do something with the result of walk
|
|
67
|
+
})
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**IMPORTANT: Object-callbacks are executed always before key-callbacks. If we have both callbacks, then key-callbacks will be executed on the result of object-callback.**
|
|
71
|
+
|
|
72
|
+
Skip key-callbacks by not providing a keyCallback function.
|
|
73
|
+
```js
|
|
74
|
+
let result = await walk ({ data }) // ignore key-callbacks
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
## Installation
|
|
79
|
+
|
|
80
|
+
Install for node.js projects by writing in your terminal:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
npm install @peter.naydenov/walk-async
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Once it has been installed, it can be used by writing this line of JavaScript:
|
|
87
|
+
```js
|
|
88
|
+
let walk = require ( '@peter.naydenov/walk-async' )
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
or
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
import walk from '@peter.naydenov/walk-async'
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Installation for browsers**: Get the file `"dist/walk-async.min.js"` and put it inside the project. Request the file from HTML page. Global variable 'walk' is available for use.
|
|
98
|
+
|
|
99
|
+
Note:
|
|
100
|
+
Library is using 'generator functions'. If support for old browsers
|
|
101
|
+
is required, add a polyfill for 'generators'.
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
## How to use it
|
|
108
|
+
|
|
109
|
+
### Deep copy
|
|
110
|
+
```js
|
|
111
|
+
const myCopy = await walk ({ data:x }) // where x is some javascript data structure
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
### Deep 'forEach'
|
|
117
|
+
```js
|
|
118
|
+
let x = {
|
|
119
|
+
ls : [ 1,2,3 ]
|
|
120
|
+
, name : 'Peter'
|
|
121
|
+
, props : {
|
|
122
|
+
eyeColor: 'blue'
|
|
123
|
+
, age : 47
|
|
124
|
+
, height : 176
|
|
125
|
+
, sizes : [12,33,12,21]
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
function keyFn ({value,key, breadcrumbs, resolve}) {
|
|
130
|
+
console.log (`${key} ----> ${value}`) // Show each each primitive couples key->value
|
|
131
|
+
console.log ( `Property location >> ${breadcrumbs}`)
|
|
132
|
+
// example for breadcrumbs: 'age' will looks like this : 'root/props/age'
|
|
133
|
+
resolve ( value )
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
walk ({ data:x, keyCallback: keyFn })
|
|
137
|
+
.then ( result => {
|
|
138
|
+
// result is a deep copy of x
|
|
139
|
+
})
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
### Ignore a key
|
|
144
|
+
|
|
145
|
+
```js
|
|
146
|
+
let x = {
|
|
147
|
+
ls : [ 1,2,3 ]
|
|
148
|
+
, name : 'Peter'
|
|
149
|
+
, props : {
|
|
150
|
+
eyeColor: 'blue'
|
|
151
|
+
, age : 47
|
|
152
|
+
, height : 176
|
|
153
|
+
, sizes : [12,33,12,21]
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
function keyFn ({value,key,resolve,reject}) {
|
|
157
|
+
if ( key === 'name' ) reject ()
|
|
158
|
+
else resolve ( value )
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
walk ({
|
|
162
|
+
data : x
|
|
163
|
+
, keyCallback : keyFn
|
|
164
|
+
})
|
|
165
|
+
.then ( result => {
|
|
166
|
+
// result will copy all properties from x without the property 'name'.
|
|
167
|
+
// result.name === undefined
|
|
168
|
+
})
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
### Mask values
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
let x = {
|
|
176
|
+
ls : [ 1,2,3 ]
|
|
177
|
+
, name : 'Peter'
|
|
178
|
+
, props : {
|
|
179
|
+
eyeColor: 'blue'
|
|
180
|
+
, age : 47
|
|
181
|
+
, height : 176
|
|
182
|
+
, sizes : [12,33,12,21]
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
walk ({
|
|
186
|
+
data:x
|
|
187
|
+
, keyCallback : ({resolve}) => resolve('xxx')
|
|
188
|
+
})
|
|
189
|
+
.then ( result => {
|
|
190
|
+
// 'result' will have the same structure as 'x' but all values are 'xxx'
|
|
191
|
+
// {
|
|
192
|
+
// ls : [ 'xxx','xxx','xxx' ]
|
|
193
|
+
// , name : 'xxx'
|
|
194
|
+
// , props : {
|
|
195
|
+
// eyeColor: 'xxx'
|
|
196
|
+
// , age : 'xxx'
|
|
197
|
+
// , height : 'xxx'
|
|
198
|
+
// , sizes : ['xxx','xxx','xxx','xxx']
|
|
199
|
+
// }
|
|
200
|
+
// }
|
|
201
|
+
})
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Change object on condition
|
|
205
|
+
|
|
206
|
+
```js
|
|
207
|
+
let x = {
|
|
208
|
+
ls : [ 1,2,3 ]
|
|
209
|
+
, name : 'Peter'
|
|
210
|
+
, props : {
|
|
211
|
+
eyeColor: 'blue'
|
|
212
|
+
, age : 48
|
|
213
|
+
, height : 176
|
|
214
|
+
, sizes : [12,33,12,21]
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
function objectCallback ({ value:obj, key, resolve }) {
|
|
219
|
+
const {age, height} = obj;
|
|
220
|
+
if ( age && age > 30 ) {
|
|
221
|
+
resolve ({ age, height })
|
|
222
|
+
return
|
|
223
|
+
}
|
|
224
|
+
resolve ( obj )
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
walk ({
|
|
228
|
+
data: x
|
|
229
|
+
, objectCallback
|
|
230
|
+
})
|
|
231
|
+
.then ( result => {
|
|
232
|
+
// 'result.props' will have only 'age' and 'height' properties.
|
|
233
|
+
// {
|
|
234
|
+
// ls : [ 1,2,3 ]
|
|
235
|
+
// , name : 'Peter'
|
|
236
|
+
// , props : {
|
|
237
|
+
// age : 48
|
|
238
|
+
// , height : 176
|
|
239
|
+
// }
|
|
240
|
+
// }
|
|
241
|
+
})
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
## Links
|
|
247
|
+
- [Release history](Changelog.md)
|
|
248
|
+
|
|
249
|
+
## Credits
|
|
250
|
+
'@peter.naydenov/walk-async' was created and supported by Peter Naydenov.
|
|
251
|
+
|
|
252
|
+
## License
|
|
253
|
+
'@peter.naydenov/walk-async' is released under the MIT License.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var walk;(()=>{var e={406:e=>{"use strict";function n(){let e,n;const t=new Promise(((o,t)=>{e=o,n=t}));return{promise:t,done:e,cancel:n,onComplete:o(t)}}function o(e){return function(n){e.then((e=>n(e)))}}e.exports=function(e){let t,r=!1;return e?(t=function(e){let t=e.map((e=>n())),r=t.map((e=>e.promise));return t.promises=r,t.onComplete=o(Promise.all(r)),t}(e),r=!0):t=n(),t.timeout=function(e,n){let t;return t=e?Promise.all(n.promises):n.promise,function(e,r){let s,l=new Promise(((n,o)=>{s=setTimeout((()=>{n(r),Promise.resolve(t)}),e)}));return t.then((()=>clearTimeout(s))),n.onComplete=o(Promise.race([t,l])),n}}(r,t),t}},880:(e,n,o)=>{const t=o(406);async function r(e,n,o){for await(const n of e)await n.next();o.done(n)}function s(e){return e instanceof Array?"array":"object"==typeof e?"object":"simple"}async function*l(e,n,o,t,r){yield await a(e,n,o,t,r)}function a(e,n,o,r,a){let[c,i]=r,u=Object.keys(e),p=t(u),m=t();return u.forEach(((u,m)=>{let d=s(e[u]),f=e[u],$="simple"!==d&&null!=i,y=t(),b=t(),h=t(),k="array"===s(n),v=!isNaN(u);$?i({resolve:y.done,reject:()=>y.done(null),value:f,key:u,breadcrumbs:`${a}/${u}`}):y.done("$$cancel"),y.onComplete((e=>{"$$cancel"!==e&&(f=e,d=s(f)),null!=f?"simple"===d?(c||b.done("$$noUpdates"),c({resolve:b.done,reject:()=>b.done(null),value:f,key:u,breadcrumbs:`${a}/${u}`})):b.done("$$cancel"):p[m].done()})),b.onComplete((e=>{if(null!=e)if("$$cancel"!==e){if("$$noUpdates"!==e&&(f=e,d=s(f)),"simple"===d){const o=function(e,n){return n instanceof Array&&!isNaN(e)}(u,n);return o?n.push(e):n[u]=e,void p[m].done("key")}h.done()}else h.done();else p[m].done("nulls")})),h.onComplete((()=>{if("object"===d){const e={};k&&v?n.push(e):n[u]=e,o.push(l(f,e,o,r,`${a}/${u}`)),p[m].done("object")}if("array"===d){const e=[];k&&v?n.push(e):n[u]=e,o.push(l(f,e,o,r,`${a}/${u}`)),p[m].done("array")}}))})),p.onComplete((e=>m.done())),m.promise}e.exports=function(e){let n,{data:o,objectCallback:l=null,keyCallback:c=null}=e,i=s(o),u=[],p="root",m=[c,l],d=t();switch(i){case"array":n=[],a(o,n,u,m,p).then((()=>r(u,n,d)));break;case"object":n={},a(o,n,u,m,p).then((()=>{r(u,n,d)}));break;case"simple":d.done(o)}return d.promise}}},n={},o=function o(t){var r=n[t];if(void 0!==r)return r.exports;var s=n[t]={exports:{}};return e[t](s,s.exports,o),s.exports}(880);walk=o})();
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@peter.naydenov/walk-async",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Deep copy with fine control during the process. Can be used also as a deep forEach function",
|
|
5
|
+
"main": "src/main.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "mocha test",
|
|
8
|
+
"cover": "nyc mocha test",
|
|
9
|
+
"build": "webpack --config ./webpack.config.js"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/PeterNaydenov/walk-async.git"
|
|
14
|
+
},
|
|
15
|
+
"author": "Peter Naydenov",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"ask-for-promise": "1.3.1"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@babel/core": "^7.19.1",
|
|
22
|
+
"@babel/preset-env": "^7.19.1",
|
|
23
|
+
"babel-loader": "^8.2.5",
|
|
24
|
+
"chai": "^4.3.6",
|
|
25
|
+
"mocha": "^10.0.0",
|
|
26
|
+
"nyc": "^15.1.0",
|
|
27
|
+
"webpack": "^5.74.0",
|
|
28
|
+
"webpack-cli": "^4.10.0"
|
|
29
|
+
},
|
|
30
|
+
"nyc": {
|
|
31
|
+
"include": [
|
|
32
|
+
"src/**/*.js"
|
|
33
|
+
],
|
|
34
|
+
"exclude": [
|
|
35
|
+
"node_modules",
|
|
36
|
+
"test",
|
|
37
|
+
"test-data"
|
|
38
|
+
],
|
|
39
|
+
"reporter": [
|
|
40
|
+
"lcov",
|
|
41
|
+
"text-summary"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
"browserslist": "> 2%, not dead"
|
|
45
|
+
}
|
package/src/main.js
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* walk-async
|
|
4
|
+
*
|
|
5
|
+
* Alternative of deep-copy that provides much better control during creation of immutable
|
|
6
|
+
* copies of javascript data structures.
|
|
7
|
+
* Library is using 'generator functions'. If support for old browsers is required,
|
|
8
|
+
* add a polyfill for 'generators'.
|
|
9
|
+
*
|
|
10
|
+
* History notes:
|
|
11
|
+
* - Walk-async was born on September 18th, 2022
|
|
12
|
+
*
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
const askForPromise = require ( "ask-for-promise" );
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
function walk ({
|
|
22
|
+
data:origin
|
|
23
|
+
, objectCallback = null
|
|
24
|
+
, keyCallback = null
|
|
25
|
+
}) {
|
|
26
|
+
let
|
|
27
|
+
type = findType ( origin )
|
|
28
|
+
, result
|
|
29
|
+
, extend = []
|
|
30
|
+
, breadcrumbs = 'root'
|
|
31
|
+
, cb = [ keyCallback, objectCallback ]
|
|
32
|
+
, end = askForPromise ()
|
|
33
|
+
;
|
|
34
|
+
switch ( type ) {
|
|
35
|
+
case 'array' :
|
|
36
|
+
result = []
|
|
37
|
+
copyObject ( origin, result, extend, cb, breadcrumbs )
|
|
38
|
+
.then ( () => goNext ( extend, result, end ))
|
|
39
|
+
break
|
|
40
|
+
case 'object' :
|
|
41
|
+
result = {}
|
|
42
|
+
copyObject ( origin, result, extend, cb, breadcrumbs )
|
|
43
|
+
.then ( () => {
|
|
44
|
+
goNext ( extend, result, end )
|
|
45
|
+
})
|
|
46
|
+
break
|
|
47
|
+
case 'simple' :
|
|
48
|
+
end.done ( origin )
|
|
49
|
+
} // switch type
|
|
50
|
+
return end.promise
|
|
51
|
+
} // walk func.
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
async function goNext ( extend, result, end ) {
|
|
56
|
+
for await ( const plus of extend ) {
|
|
57
|
+
await plus.next ()
|
|
58
|
+
}
|
|
59
|
+
end.done ( result )
|
|
60
|
+
} // goNext func.
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
function findType ( x ) {
|
|
65
|
+
if ( x instanceof Array ) return 'array'
|
|
66
|
+
if ( typeof x === 'object' ) return 'object'
|
|
67
|
+
return 'simple'
|
|
68
|
+
} // findType func.
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
async function* generateList ( data, location, ex, cb, breadcrumbs ) {
|
|
73
|
+
yield await copyObject ( data , location, ex, cb, breadcrumbs )
|
|
74
|
+
} // generateList func.
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
function validateForInsertion ( k, result ) {
|
|
78
|
+
const inArray = result instanceof Array;
|
|
79
|
+
if ( !inArray ) return false
|
|
80
|
+
const isNumber = !isNaN ( k );
|
|
81
|
+
if ( isNumber ) return true
|
|
82
|
+
else return false
|
|
83
|
+
} // insertInArray func.
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
function copyObject ( origin, result, extend, cb, breadcrumbs ) {
|
|
88
|
+
let
|
|
89
|
+
[ keyCallback, objectCallback ] = cb
|
|
90
|
+
, keys = Object.keys ( origin )
|
|
91
|
+
, executeCallback = askForPromise ( keys )
|
|
92
|
+
, finish = askForPromise ()
|
|
93
|
+
;
|
|
94
|
+
keys.forEach ( (k,i) => {
|
|
95
|
+
let
|
|
96
|
+
type = findType(origin[k])
|
|
97
|
+
, item = origin[k]
|
|
98
|
+
, hasObjectCallback = ( type !== 'simple' && objectCallback != null )
|
|
99
|
+
, objectCallbackTask = askForPromise ()
|
|
100
|
+
, keyCallbackTask = askForPromise ()
|
|
101
|
+
, finishWithCallbacks = askForPromise ()
|
|
102
|
+
, resultIsArray = (findType (result) === 'array')
|
|
103
|
+
, keyNumber = !isNaN ( k )
|
|
104
|
+
;
|
|
105
|
+
|
|
106
|
+
if ( hasObjectCallback ) {
|
|
107
|
+
objectCallback ({
|
|
108
|
+
resolve : objectCallbackTask.done
|
|
109
|
+
, reject : () => objectCallbackTask.done ( null )
|
|
110
|
+
, value : item
|
|
111
|
+
, key : k
|
|
112
|
+
, breadcrumbs : `${breadcrumbs}/${k}`
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
objectCallbackTask.done ( '$$cancel' )
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
objectCallbackTask.onComplete ( res => {
|
|
120
|
+
if ( res !== '$$cancel' ) {
|
|
121
|
+
item = res
|
|
122
|
+
type = findType ( item )
|
|
123
|
+
}
|
|
124
|
+
if ( item == null ) {
|
|
125
|
+
executeCallback[i].done ()
|
|
126
|
+
return
|
|
127
|
+
}
|
|
128
|
+
if ( type === 'simple' ) {
|
|
129
|
+
if ( !keyCallback ) keyCallbackTask.done ( '$$noUpdates' )
|
|
130
|
+
keyCallback ({
|
|
131
|
+
resolve : keyCallbackTask.done
|
|
132
|
+
, reject : () => keyCallbackTask.done ( null )
|
|
133
|
+
, value : item
|
|
134
|
+
, key : k
|
|
135
|
+
, breadcrumbs : `${breadcrumbs}/${k}`
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
keyCallbackTask.done ( '$$cancel' )
|
|
140
|
+
}
|
|
141
|
+
}) // objectCallbackTask complete
|
|
142
|
+
|
|
143
|
+
keyCallbackTask.onComplete ( value => {
|
|
144
|
+
if ( value == null ) {
|
|
145
|
+
executeCallback[i].done ( 'nulls' )
|
|
146
|
+
return
|
|
147
|
+
}
|
|
148
|
+
if ( value === '$$cancel' ) {
|
|
149
|
+
finishWithCallbacks.done ()
|
|
150
|
+
return
|
|
151
|
+
}
|
|
152
|
+
if ( value !== '$$noUpdates' ) {
|
|
153
|
+
item = value
|
|
154
|
+
type = findType ( item )
|
|
155
|
+
}
|
|
156
|
+
if ( type === 'simple' ) {
|
|
157
|
+
const canInsert = validateForInsertion ( k, result )
|
|
158
|
+
if ( canInsert ) result.push ( value )
|
|
159
|
+
else result [k] = value
|
|
160
|
+
executeCallback[i].done ('key')
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
finishWithCallbacks.done ()
|
|
164
|
+
}) // keyCallbackTask complete
|
|
165
|
+
|
|
166
|
+
finishWithCallbacks.onComplete ( () => {
|
|
167
|
+
if ( type === 'object' ) {
|
|
168
|
+
const newObject = {};
|
|
169
|
+
if ( resultIsArray && keyNumber ) result.push ( newObject )
|
|
170
|
+
else result[k] = newObject
|
|
171
|
+
extend.push ( generateList( item, newObject, extend, cb, `${breadcrumbs}/${k}` ) )
|
|
172
|
+
executeCallback[i].done ('object')
|
|
173
|
+
}
|
|
174
|
+
if ( type === 'array' ) {
|
|
175
|
+
const newArray = [];
|
|
176
|
+
if ( resultIsArray && keyNumber ) result.push ( newArray )
|
|
177
|
+
else result[k] = newArray
|
|
178
|
+
extend.push ( generateList( item, newArray, extend, cb, `${breadcrumbs}/${k}` ) )
|
|
179
|
+
executeCallback[i].done ('array')
|
|
180
|
+
}
|
|
181
|
+
})
|
|
182
|
+
}) // forEach k
|
|
183
|
+
executeCallback.onComplete ( r => finish.done () )
|
|
184
|
+
return finish.promise
|
|
185
|
+
} // copyObject func.
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
module.exports = walk
|
|
190
|
+
|
|
191
|
+
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
|
|
3
|
+
const
|
|
4
|
+
chai = require ( 'chai' )
|
|
5
|
+
, expect = chai.expect
|
|
6
|
+
, walk = require ( '../src/main.js' )
|
|
7
|
+
;
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
describe ( 'Walk-async -> Deep copy', () => {
|
|
11
|
+
|
|
12
|
+
it ( 'Copy a primitive value', () => {
|
|
13
|
+
let x = 12;
|
|
14
|
+
walk ({data:x})
|
|
15
|
+
.then ( r => {
|
|
16
|
+
x = 64
|
|
17
|
+
expect ( r ).to.be.equal ( 12 )
|
|
18
|
+
expect ( r !== x )
|
|
19
|
+
})
|
|
20
|
+
}) // it copy a primitives
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
it ( 'Copy array of strings', () => {
|
|
25
|
+
let x = [ 'one', 'two', 'three' ];
|
|
26
|
+
walk ({data:x})
|
|
27
|
+
.then ( r => {
|
|
28
|
+
x.push ( 'four' )
|
|
29
|
+
expect ( r ).to.have.length ( 3 )
|
|
30
|
+
})
|
|
31
|
+
}) // it copy array of strings
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
it ( 'Copy a single level deep object', () => {
|
|
36
|
+
let
|
|
37
|
+
x = { name:'Peter', age: 47 }
|
|
38
|
+
, z = x
|
|
39
|
+
;
|
|
40
|
+
walk ( {data:x})
|
|
41
|
+
.then ( r => {
|
|
42
|
+
x.test = 'hello'
|
|
43
|
+
expect ( r ).to.not.have.property ( 'test' )
|
|
44
|
+
expect ( z ).to.have.property ( 'test' )
|
|
45
|
+
})
|
|
46
|
+
}) // it copy a single level deep object
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
it ( 'Copy a mixed structure', () => {
|
|
51
|
+
let
|
|
52
|
+
x = {
|
|
53
|
+
ls : [ 1,2,3 ]
|
|
54
|
+
, name : 'Peter'
|
|
55
|
+
, props : {
|
|
56
|
+
eyeColor: 'blue'
|
|
57
|
+
, age : 47
|
|
58
|
+
, height : 176
|
|
59
|
+
, sizes : [12,33,12,21]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
;
|
|
63
|
+
walk ( x )
|
|
64
|
+
.then ( r => {
|
|
65
|
+
r.props.sizes.push ( 66 )
|
|
66
|
+
x.props.sizes[0] = 222222
|
|
67
|
+
x.props.test = 'hello'
|
|
68
|
+
|
|
69
|
+
expect ( x.props.sizes ).to.have.length ( 4 )
|
|
70
|
+
expect ( r.props.sizes ).to.have.length ( 5 )
|
|
71
|
+
expect ( x.props.sizes[0] !== r.props.sizes[0])
|
|
72
|
+
|
|
73
|
+
expect ( r.props ).to.not.have.property ( 'test' )
|
|
74
|
+
})
|
|
75
|
+
}) // it Copy a mixed structure
|
|
76
|
+
|
|
77
|
+
}) // describe
|
|
78
|
+
|
|
79
|
+
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
|
|
3
|
+
const
|
|
4
|
+
chai = require ( 'chai' )
|
|
5
|
+
, expect = chai.expect
|
|
6
|
+
, walk = require ( '../src/main.js' )
|
|
7
|
+
;
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
describe ( 'Walk-async -> keyCallback function', () => {
|
|
11
|
+
|
|
12
|
+
it ( 'Hide a property', () => {
|
|
13
|
+
let
|
|
14
|
+
x = {
|
|
15
|
+
ls : [ 1,2,3 ]
|
|
16
|
+
, name : 'Peter'
|
|
17
|
+
, props : {
|
|
18
|
+
eyeColor: 'blue'
|
|
19
|
+
, age : 47
|
|
20
|
+
, height : 176
|
|
21
|
+
, sizes : [12,33,12,21]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
;
|
|
25
|
+
walk ({
|
|
26
|
+
data : x
|
|
27
|
+
, keyCallback : ({
|
|
28
|
+
key : k
|
|
29
|
+
, value
|
|
30
|
+
, resolve
|
|
31
|
+
, reject
|
|
32
|
+
}) => {
|
|
33
|
+
if ( k === 'name' ) reject ()
|
|
34
|
+
else resolve ( value )
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
.then ( r => {
|
|
38
|
+
expect ( r ).to.not.have.property ( 'name' )
|
|
39
|
+
})
|
|
40
|
+
}) // it Hide a property
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
it ( 'Provide a structure. Hide values approaches', () => {
|
|
45
|
+
let
|
|
46
|
+
x = {
|
|
47
|
+
ls : [ 1,2,3 ]
|
|
48
|
+
, name : 'Peter'
|
|
49
|
+
, props : {
|
|
50
|
+
eyeColor: 'blue'
|
|
51
|
+
, age : 47
|
|
52
|
+
, height : 176
|
|
53
|
+
, sizes : [12,33,12,21]
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
walk ({
|
|
57
|
+
data:x
|
|
58
|
+
, keyCallback : ({ resolve, reject, breadcrumbs }) => {
|
|
59
|
+
const hasSizes = breadcrumbs.includes('root/props/sizes');
|
|
60
|
+
if ( hasSizes ) reject ()
|
|
61
|
+
else resolve ( 'xxx' )
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
.then ( r => {
|
|
65
|
+
expect ( r.name ).to.be.equal ( 'xxx' )
|
|
66
|
+
expect ( r.props.age ).to.be.equal ( 'xxx' )
|
|
67
|
+
expect ( r.props.sizes.length ).to.be.equal ( 0 )
|
|
68
|
+
})
|
|
69
|
+
}) // it Provide a structure
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
it ( 'No properties. Just structures', () => {
|
|
73
|
+
let
|
|
74
|
+
x = {
|
|
75
|
+
ls : [ 1,2,3 ]
|
|
76
|
+
, name : 'Peter'
|
|
77
|
+
, props : {
|
|
78
|
+
eyeColor: 'blue'
|
|
79
|
+
, age : 47
|
|
80
|
+
, height : 176
|
|
81
|
+
, sizes : [12,33,12,21]
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
walk ({
|
|
85
|
+
data : x
|
|
86
|
+
, keyCallback : ({reject}) => reject ()
|
|
87
|
+
})
|
|
88
|
+
.then ( r => {
|
|
89
|
+
expect ( r ).to.have.property ( 'ls' )
|
|
90
|
+
expect ( r ).to.have.property ( 'props' )
|
|
91
|
+
expect ( r.props ).to.have.property ( 'sizes' )
|
|
92
|
+
|
|
93
|
+
expect ( r ).to.not.have.property ( 'name' )
|
|
94
|
+
expect ( r.props ).to.not.have.property ( 'age' )
|
|
95
|
+
|
|
96
|
+
expect ( r.ls.length ).to.be.equal ( 0 )
|
|
97
|
+
expect ( r.props.sizes.length ).to.be.equal ( 0 )
|
|
98
|
+
})
|
|
99
|
+
}) // it No properties
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
it ( 'Convert primitive property to object', () => {
|
|
103
|
+
let
|
|
104
|
+
x = [ 'peter', 'ivan', 'petkan', 'rosica' ]
|
|
105
|
+
, data = {
|
|
106
|
+
"ivan" : { name: 'Ivan', age: 45, gender: 'male' }
|
|
107
|
+
, "petkan" : { name: 'Petkan', age: 32, gender: 'male' }
|
|
108
|
+
, "rosica" : { name: "Rosica", age: 75, gender: 'female'}
|
|
109
|
+
}
|
|
110
|
+
;
|
|
111
|
+
function keyCallback ({ value, resolve, reject }) {
|
|
112
|
+
const person= data[value];
|
|
113
|
+
if ( person ) {
|
|
114
|
+
if ( person.age > 33 ) resolve ( person )
|
|
115
|
+
else reject ()
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
else resolve ( value )
|
|
119
|
+
}
|
|
120
|
+
walk ({
|
|
121
|
+
data : x
|
|
122
|
+
, keyCallback
|
|
123
|
+
})
|
|
124
|
+
.then ( r => {
|
|
125
|
+
expect ( r.length ).to.be.equal ( 3 ) // ignore 'petkan'
|
|
126
|
+
expect ( r[0] ).to.be.equal ( 'Peter' ) // no description for Peter available
|
|
127
|
+
expect ( r[1]['name']).to.be.equal ( 'Ivan' )
|
|
128
|
+
expect ( r[2]['name']).to.be.equal ( 'Rosica' )
|
|
129
|
+
})
|
|
130
|
+
}) // it Convert primitive property to object
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
it ( 'Properties of the array object', () => {
|
|
135
|
+
let data = [ 'peter', 'ivan' ];
|
|
136
|
+
data.group = 'work'
|
|
137
|
+
|
|
138
|
+
function keyCallback ({value, resolve }) {
|
|
139
|
+
resolve ( value )
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
walk ({ data, keyCallback })
|
|
143
|
+
.then ( r => {
|
|
144
|
+
expect ( r.length ).to.be.equal ( 2 )
|
|
145
|
+
expect ( r.group ).to.be.equal ( 'work' )
|
|
146
|
+
})
|
|
147
|
+
}) // it Properties of the array
|
|
148
|
+
|
|
149
|
+
}) // describe
|
|
150
|
+
|
|
151
|
+
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
|
|
3
|
+
const
|
|
4
|
+
chai = require ( 'chai' )
|
|
5
|
+
, expect = chai.expect
|
|
6
|
+
, walk = require ( '../src/main.js' )
|
|
7
|
+
;
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
describe ( 'Walk-async -> objectCallback function', () => {
|
|
11
|
+
|
|
12
|
+
it ( 'Object callback function only', () => {
|
|
13
|
+
let
|
|
14
|
+
x = {
|
|
15
|
+
ls : [ 1,2,3 ]
|
|
16
|
+
, name : 'Peter'
|
|
17
|
+
, props : {
|
|
18
|
+
eyeColor: 'blue'
|
|
19
|
+
, age : 47
|
|
20
|
+
, height : 176
|
|
21
|
+
, sizes : [12,33,12,21]
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function oCallbackFn ({value,resolve}) {
|
|
26
|
+
const { age, height } = value;
|
|
27
|
+
if ( age === 47 ) resolve ({ eyeColor:'dark', height })
|
|
28
|
+
else resolve ( value )
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
walk ( {
|
|
32
|
+
data : x
|
|
33
|
+
, objectCallback : oCallbackFn
|
|
34
|
+
})
|
|
35
|
+
.then ( r => {
|
|
36
|
+
expect ( r.props ).to.not.have.property ( 'age' )
|
|
37
|
+
expect ( r.props ).to.not.have.property ( 'sizes' )
|
|
38
|
+
expect ( r.props.eyeColor ).to.be.equal ( 'dark' )
|
|
39
|
+
})
|
|
40
|
+
}) // it object callback
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
it ( 'Object callback returns null', () => {
|
|
45
|
+
let
|
|
46
|
+
x = {
|
|
47
|
+
ls : [ 1,2,3 ]
|
|
48
|
+
, name : 'Peter'
|
|
49
|
+
, props : {
|
|
50
|
+
eyeColor: 'blue'
|
|
51
|
+
, age : 47
|
|
52
|
+
, height : 176
|
|
53
|
+
, sizes : [12,33,12,21]
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
function oCallbackFn ({ value:o, resolve, reject }) {
|
|
58
|
+
const { sizes } = o;
|
|
59
|
+
if ( sizes ) reject ()
|
|
60
|
+
else resolve (o)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
walk ({
|
|
64
|
+
data : x
|
|
65
|
+
, objectCallback : oCallbackFn
|
|
66
|
+
})
|
|
67
|
+
.then ( r => {
|
|
68
|
+
expect ( r ).to.not.have.property ( 'props' )
|
|
69
|
+
})
|
|
70
|
+
}) // it object callback null
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
it ( 'Object callback returns a string', () => {
|
|
75
|
+
let
|
|
76
|
+
x = {
|
|
77
|
+
ls : [ 1,2,3 ]
|
|
78
|
+
, name : 'Peter'
|
|
79
|
+
, props : {
|
|
80
|
+
eyeColor: 'blue'
|
|
81
|
+
, age : 47
|
|
82
|
+
, height : 176
|
|
83
|
+
, sizes : [12,33,12,21]
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
function oCallbackFn ({ value:o, resolve }) {
|
|
88
|
+
const { sizes } = o;
|
|
89
|
+
if ( sizes ) resolve ( 'list' )
|
|
90
|
+
else resolve ( o )
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
walk ({
|
|
94
|
+
data: x
|
|
95
|
+
, objectCallback : oCallbackFn
|
|
96
|
+
})
|
|
97
|
+
.then ( r => {
|
|
98
|
+
expect ( r ).to.have.property ( 'props' )
|
|
99
|
+
expect ( r.props ).to.be.equal ( 'list' )
|
|
100
|
+
})
|
|
101
|
+
}) // it object callback null
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
it ( 'Object callback changes the data', () => {
|
|
106
|
+
let
|
|
107
|
+
x = {
|
|
108
|
+
ls : [ 1,2,3 ]
|
|
109
|
+
, name : 'Peter'
|
|
110
|
+
, props : {
|
|
111
|
+
eyeColor: 'blue'
|
|
112
|
+
, age : 47
|
|
113
|
+
, height : 176
|
|
114
|
+
, sizes : [12,33,12,21]
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
function oCallbackFn ({ value:o, resolve }) {
|
|
119
|
+
const { sizes } = o;
|
|
120
|
+
if ( sizes ) o.sizes = [ 'list of sizes' ]
|
|
121
|
+
resolve ( o )
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
walk ({
|
|
125
|
+
data : x
|
|
126
|
+
, objectCallback : oCallbackFn
|
|
127
|
+
})
|
|
128
|
+
.then ( r => {
|
|
129
|
+
expect ( r ).to.have.property ( 'props' )
|
|
130
|
+
expect ( r.props ).to.have.property ( 'sizes' )
|
|
131
|
+
expect ( r.props.sizes ).to.have.length ( 1 )
|
|
132
|
+
expect ( r.props.sizes[0]).to.be.equal ( 'list of sizes' )
|
|
133
|
+
})
|
|
134
|
+
}) // it object callback changes the data
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
it ( 'Object callback checks key', () => {
|
|
139
|
+
let
|
|
140
|
+
x = {
|
|
141
|
+
ls : [ 1,2,3 ]
|
|
142
|
+
, name : 'Peter'
|
|
143
|
+
, props : {
|
|
144
|
+
eyeColor: 'blue'
|
|
145
|
+
, age : 47
|
|
146
|
+
, height : 176
|
|
147
|
+
, sizes : [12,33,12,21]
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
function oCallbackFn ({ value:o, key, resolve, reject }) {
|
|
152
|
+
if ( key === 'props' ) reject ()
|
|
153
|
+
resolve ( o )
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
walk ({
|
|
157
|
+
data: x
|
|
158
|
+
, objectCallback: oCallbackFn
|
|
159
|
+
})
|
|
160
|
+
.then ( r => {
|
|
161
|
+
expect ( r ).to.not.have.property ( 'props' )
|
|
162
|
+
})
|
|
163
|
+
}) // it Object callback checks key
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
it ( 'Object callback checks breadcrumbs', () => {
|
|
168
|
+
let
|
|
169
|
+
x = {
|
|
170
|
+
ls : [ 1,2,3 ]
|
|
171
|
+
, name : 'Peter'
|
|
172
|
+
, props : {
|
|
173
|
+
eyeColor: 'blue'
|
|
174
|
+
, age : 47
|
|
175
|
+
, height : 176
|
|
176
|
+
, sizes : [12,33,12,21]
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
function oCallbackFn ({ value:o, breadcrumbs, resolve, reject } ) {
|
|
181
|
+
if ( breadcrumbs === 'root/props' ) reject ()
|
|
182
|
+
resolve ( o )
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
walk ({
|
|
186
|
+
data : x
|
|
187
|
+
, objectCallback : oCallbackFn
|
|
188
|
+
})
|
|
189
|
+
.then ( r => {
|
|
190
|
+
expect ( r ).to.not.have.property ( 'props' )
|
|
191
|
+
})
|
|
192
|
+
}) // it Object callback checks breadcrumbs
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
it ( 'Prevent array empty items', () => {
|
|
197
|
+
let
|
|
198
|
+
x = [
|
|
199
|
+
{ id: 1 }
|
|
200
|
+
, { id: 2 }
|
|
201
|
+
, { id: 3 }
|
|
202
|
+
, { id: 5 }
|
|
203
|
+
];
|
|
204
|
+
|
|
205
|
+
function oCallbackFn ({ value:o, resolve, reject }) {
|
|
206
|
+
if ( o.id === 5 ) resolve ( o )
|
|
207
|
+
reject ()
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
walk ({
|
|
211
|
+
data : x
|
|
212
|
+
, objectCallback : oCallbackFn
|
|
213
|
+
})
|
|
214
|
+
.then ( r => {
|
|
215
|
+
expect ( r.length ).to.be.equal ( 1 )
|
|
216
|
+
})
|
|
217
|
+
}) // it Prevent array empty items
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
it ( 'Prevent array empty items 2', () => {
|
|
222
|
+
let
|
|
223
|
+
x = [
|
|
224
|
+
[1]
|
|
225
|
+
, [2]
|
|
226
|
+
, [3]
|
|
227
|
+
, [5]
|
|
228
|
+
];
|
|
229
|
+
|
|
230
|
+
function oCallbackFn ({ value:o, resolve, reject }) {
|
|
231
|
+
if ( o[0] === 5 ) resolve ( o )
|
|
232
|
+
reject ()
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
walk ({
|
|
236
|
+
data : x
|
|
237
|
+
, objectCallback : oCallbackFn
|
|
238
|
+
})
|
|
239
|
+
.then ( r => {
|
|
240
|
+
expect ( r.length ).to.be.equal ( 1 )
|
|
241
|
+
expect ( r[0] ).to.be.equal ( 5 )
|
|
242
|
+
})
|
|
243
|
+
}) // it Prevent array empty items 2
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
}) // describe
|
|
248
|
+
|
|
249
|
+
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
|
|
3
|
+
const
|
|
4
|
+
chai = require ( 'chai' )
|
|
5
|
+
, expect = chai.expect
|
|
6
|
+
, walk = require ( '../src/main.js' )
|
|
7
|
+
, askForPromise = require ( 'ask-for-promise' )
|
|
8
|
+
;
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
describe ( 'Walk-async -> Asynchronous tests', () => {
|
|
12
|
+
|
|
13
|
+
it ( 'Call walk inside other walk', () => {
|
|
14
|
+
let data = {
|
|
15
|
+
users : [
|
|
16
|
+
{
|
|
17
|
+
name: 'Peter'
|
|
18
|
+
, friends : ['Tisho', 'Radostin', 'Tony', 'Kalin' ]
|
|
19
|
+
}
|
|
20
|
+
, {
|
|
21
|
+
name: 'Joro'
|
|
22
|
+
, friends : [ 'Katya', 'Ivan', 'Stefan', 'Valentin' ]
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
, friendsWithPermition = [ 'Kalin', 'Aleks', 'Tony', 'Ivan' ]
|
|
27
|
+
;
|
|
28
|
+
|
|
29
|
+
async function filterObj ({value:obj, task, breadcrumbs }) {
|
|
30
|
+
if ( obj.friends ) {
|
|
31
|
+
function filterNames ({value:person, key, breadcrumbs, task:scanning} ) {
|
|
32
|
+
let validated = friendsWithPermition.includes(person)
|
|
33
|
+
if ( validated ) scanning.done ( person )
|
|
34
|
+
else scanning.done ( null )
|
|
35
|
+
} // filterNames func.
|
|
36
|
+
walk ({
|
|
37
|
+
data: obj.friends
|
|
38
|
+
, keyCallback : filterNames
|
|
39
|
+
})
|
|
40
|
+
.then ( r => {
|
|
41
|
+
obj.friends = r
|
|
42
|
+
task.done ( obj )
|
|
43
|
+
})
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
// if ( obj. ) {
|
|
47
|
+
// function filterNames ({value:user, key, breadcrumbs, task:scanning} ) {
|
|
48
|
+
// let valid = friendsWithPermition.includes(user) ;
|
|
49
|
+
// // if ( valid ) console.log ( user )
|
|
50
|
+
// if ( valid ) scanning ( user )
|
|
51
|
+
// else scanning ( null )
|
|
52
|
+
// } // filterNames func.
|
|
53
|
+
// walk ({
|
|
54
|
+
// data : obj
|
|
55
|
+
// , keyCallback : filterNames
|
|
56
|
+
// }).then ( r => {
|
|
57
|
+
// // console.log ( r )
|
|
58
|
+
// task.done ( r )
|
|
59
|
+
// })
|
|
60
|
+
// return
|
|
61
|
+
// }
|
|
62
|
+
// console.log ( 'Object callback' )
|
|
63
|
+
// console.log ( obj )
|
|
64
|
+
task.done (obj)
|
|
65
|
+
} // filterObj func.
|
|
66
|
+
|
|
67
|
+
// let res = walk ( data, [null, filterObj])
|
|
68
|
+
// console.log ( res.users[0] )
|
|
69
|
+
// console.log ( )
|
|
70
|
+
// walk ( data )
|
|
71
|
+
walk ({
|
|
72
|
+
data
|
|
73
|
+
, objectCallback : filterObj
|
|
74
|
+
})
|
|
75
|
+
.then ( x => {
|
|
76
|
+
console.log ( x.users[0] )
|
|
77
|
+
})
|
|
78
|
+
// console.log ( x )
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
}) // it call walk inside other walk
|
|
83
|
+
}) // describe
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
entry: './src/main.js'
|
|
5
|
+
, mode: 'production'
|
|
6
|
+
, output: {
|
|
7
|
+
filename: "walk-async.min.js"
|
|
8
|
+
, path: __dirname + "/dist"
|
|
9
|
+
, library: 'walk'
|
|
10
|
+
, libraryTarget: "var"
|
|
11
|
+
, umdNamedDefine : true
|
|
12
|
+
}
|
|
13
|
+
, optimization: {}
|
|
14
|
+
, module: {
|
|
15
|
+
rules: [
|
|
16
|
+
{
|
|
17
|
+
test: /\.js$/
|
|
18
|
+
, exclude: /node_modules/
|
|
19
|
+
, use : {
|
|
20
|
+
loader: 'babel-loader'
|
|
21
|
+
, options : { presets: ['@babel/preset-env']}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
}
|