@peter.naydenov/walk-async 1.0.3 → 1.2.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 +12 -0
- package/README.md +20 -2
- package/package.json +5 -11
- package/src/main.js +10 -9
- package/test/01-deepCopy.test.js +29 -0
- package/test/02-keyCallback.test.js +77 -0
- package/test/03-objectCallback.test.js +55 -1
- package/test/05-bothCallbacks.test.js +56 -0
- package/dist/walk-async.min.js +0 -1
- package/webpack.config.js +0 -26
package/Changelog.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
### 1.2.0 ( 2023-09-18)
|
|
6
|
+
- [x] HTML DOM nodes - copy by reference;
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### 1.1.0 ( 2022-11-23)
|
|
11
|
+
- [x] Resolving with `Null` and `undefined` from callback functions will be treated as value;
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
3
15
|
### 1.0.1 ( 2022-09-19)
|
|
4
16
|
- [x] Fix: Deep copy process is losing object properties that are equal to 'null';
|
|
5
17
|
|
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# Walk-async (@peter.naydenov/walk-async)
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+
|
|
3
6
|
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
7
|
|
|
5
8
|
```js
|
|
@@ -24,9 +27,24 @@ It is very simular to [`@peter.naydenov/walk`](https://github.com/PeterNaydenov/
|
|
|
24
27
|
- `walk` can not execute another walk call inside callback functions;
|
|
25
28
|
|
|
26
29
|
|
|
30
|
+
Data structure values must be one of the following data types:
|
|
31
|
+
- string;
|
|
32
|
+
- number;
|
|
33
|
+
- bigint;
|
|
34
|
+
- boolean;
|
|
35
|
+
- symbol;
|
|
36
|
+
- null;
|
|
37
|
+
- undefined;
|
|
38
|
+
- array;
|
|
39
|
+
- object(data only);
|
|
40
|
+
- function;
|
|
41
|
+
|
|
42
|
+
Other data types can compromise the results;
|
|
43
|
+
|
|
44
|
+
|
|
27
45
|
|
|
28
46
|
## к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(
|
|
47
|
+
Function **keyCallback** of the `walk-async` could be used also as a deep '**forEach**' method no matter of the type of the object(objects, array or mixed).
|
|
30
48
|
|
|
31
49
|
```js
|
|
32
50
|
function keyCallbackFn ({ value, key, breadcrumbs, resolve, reject }) {
|
|
@@ -155,7 +173,7 @@ let x = {
|
|
|
155
173
|
};
|
|
156
174
|
function keyFn ({value,key,resolve,reject}) {
|
|
157
175
|
if ( key === 'name' ) reject ()
|
|
158
|
-
else
|
|
176
|
+
else resolve ( value )
|
|
159
177
|
}
|
|
160
178
|
|
|
161
179
|
walk ({
|
package/package.json
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peter.naydenov/walk-async",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Deep copy with fine control during the process. Can be used also as a deep forEach function",
|
|
5
5
|
"main": "src/main.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "mocha test",
|
|
8
|
-
"cover": "nyc mocha test"
|
|
9
|
-
"build": "webpack --config ./webpack.config.js"
|
|
8
|
+
"cover": "nyc mocha test"
|
|
10
9
|
},
|
|
11
10
|
"repository": {
|
|
12
11
|
"type": "git",
|
|
@@ -18,14 +17,9 @@
|
|
|
18
17
|
"ask-for-promise": "1.3.1"
|
|
19
18
|
},
|
|
20
19
|
"devDependencies": {
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"chai": "^4.3.7",
|
|
25
|
-
"mocha": "^10.1.0",
|
|
26
|
-
"nyc": "^15.1.0",
|
|
27
|
-
"webpack": "^5.75.0",
|
|
28
|
-
"webpack-cli": "^4.10.0"
|
|
20
|
+
"chai": "^4.3.8",
|
|
21
|
+
"mocha": "^10.2.0",
|
|
22
|
+
"nyc": "^15.1.0"
|
|
29
23
|
},
|
|
30
24
|
"nyc": {
|
|
31
25
|
"include": [
|
package/src/main.js
CHANGED
|
@@ -62,11 +62,11 @@ async function goNext ( extend, result, end ) {
|
|
|
62
62
|
|
|
63
63
|
|
|
64
64
|
function findType ( x ) {
|
|
65
|
-
if ( x == null ) return 'simple'
|
|
66
|
-
if (
|
|
65
|
+
if ( x == null ) return 'simple' // null and undefined
|
|
66
|
+
if ( x.nodeType ) return 'simple' // DOM node
|
|
67
67
|
if ( x instanceof Array ) return 'array'
|
|
68
68
|
if ( typeof x === 'object' ) return 'object'
|
|
69
|
-
return 'simple'
|
|
69
|
+
return 'simple' // number, bigint, string, boolean, symbol, function
|
|
70
70
|
} // findType func.
|
|
71
71
|
|
|
72
72
|
|
|
@@ -104,12 +104,13 @@ function copyObject ( origin, result, extend, cb, breadcrumbs ) {
|
|
|
104
104
|
, finishWithCallbacks = askForPromise ()
|
|
105
105
|
, resultIsArray = (findType (result) === 'array')
|
|
106
106
|
, keyNumber = !isNaN ( k )
|
|
107
|
+
, IGNORE = Symbol ( 'ignore___' )
|
|
107
108
|
;
|
|
108
109
|
|
|
109
110
|
if ( hasObjectCallback ) {
|
|
110
111
|
objectCallback ({
|
|
111
112
|
resolve : objectCallbackTask.done
|
|
112
|
-
, reject : () => objectCallbackTask.done (
|
|
113
|
+
, reject : () => objectCallbackTask.done ( IGNORE )
|
|
113
114
|
, value : item
|
|
114
115
|
, key : k
|
|
115
116
|
, breadcrumbs : `${breadcrumbs}/${k}`
|
|
@@ -128,8 +129,8 @@ function copyObject ( origin, result, extend, cb, breadcrumbs ) {
|
|
|
128
129
|
item = res
|
|
129
130
|
type = findType ( item )
|
|
130
131
|
}
|
|
131
|
-
if ( item ==
|
|
132
|
-
executeCallback[i].done ()
|
|
132
|
+
if ( item == IGNORE ) {
|
|
133
|
+
executeCallback[i].done ( 'ignore object' )
|
|
133
134
|
return
|
|
134
135
|
}
|
|
135
136
|
if ( type === 'simple' ) {
|
|
@@ -139,7 +140,7 @@ function copyObject ( origin, result, extend, cb, breadcrumbs ) {
|
|
|
139
140
|
}
|
|
140
141
|
keyCallback ({
|
|
141
142
|
resolve : keyCallbackTask.done
|
|
142
|
-
, reject : () => keyCallbackTask.done (
|
|
143
|
+
, reject : () => keyCallbackTask.done ( IGNORE )
|
|
143
144
|
, value : item
|
|
144
145
|
, key : k
|
|
145
146
|
, breadcrumbs : `${breadcrumbs}/${k}`
|
|
@@ -151,8 +152,8 @@ function copyObject ( origin, result, extend, cb, breadcrumbs ) {
|
|
|
151
152
|
}) // objectCallbackTask complete
|
|
152
153
|
|
|
153
154
|
keyCallbackTask.onComplete ( value => {
|
|
154
|
-
if ( value ==
|
|
155
|
-
executeCallback[i].done ( '
|
|
155
|
+
if ( value == IGNORE ) {
|
|
156
|
+
executeCallback[i].done ( 'ignore key' )
|
|
156
157
|
return
|
|
157
158
|
}
|
|
158
159
|
if ( value === '$$cancel' ) {
|
package/test/01-deepCopy.test.js
CHANGED
|
@@ -83,6 +83,35 @@ describe ( 'Walk-async -> Deep copy', () => {
|
|
|
83
83
|
done ()
|
|
84
84
|
})
|
|
85
85
|
}) // it Data property has value null
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
it ( 'html nodes - copy by reference', done => {
|
|
90
|
+
const data = {
|
|
91
|
+
name : 'Peter'
|
|
92
|
+
, pretendHTML : { nodeType: 1 }
|
|
93
|
+
};
|
|
94
|
+
walk ({ data })
|
|
95
|
+
.then ( r => {
|
|
96
|
+
r.pretendHTML.something = 'hello'
|
|
97
|
+
expect ( data.pretendHTML.something ).to.be.equal ( 'hello' ) // Recognize html nodes and keep them as a reference
|
|
98
|
+
done ()
|
|
99
|
+
})
|
|
100
|
+
}) // html nodes - copy by reference
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
it ( 'Functions type - copy by reference', () => {
|
|
105
|
+
const data = {
|
|
106
|
+
name : 'Peter'
|
|
107
|
+
, func : () => 12
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
walk ({ data })
|
|
111
|
+
.then ( r => {
|
|
112
|
+
expect ( r.func() ).to.be.equal ( 12 )
|
|
113
|
+
})
|
|
114
|
+
}) // it Functions type - copy by reference
|
|
86
115
|
|
|
87
116
|
}) // describe
|
|
88
117
|
|
|
@@ -145,6 +145,83 @@ describe ( 'Walk-async -> keyCallback function', () => {
|
|
|
145
145
|
expect ( r.group ).to.be.equal ( 'work' )
|
|
146
146
|
})
|
|
147
147
|
}) // it Properties of the array
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
it ( 'Set a value to NULL', done => {
|
|
152
|
+
let
|
|
153
|
+
x = {
|
|
154
|
+
ls : [ 1,2,3 ]
|
|
155
|
+
, name : 'Peter'
|
|
156
|
+
, props : {
|
|
157
|
+
eyeColor: null // Use callback and return this exact value
|
|
158
|
+
, age : 47
|
|
159
|
+
, height : 176
|
|
160
|
+
, sizes : [12,33,12,21]
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
function checkNull ({ value, resolve }) {
|
|
165
|
+
resolve (value)
|
|
166
|
+
} // checkNull func.
|
|
167
|
+
|
|
168
|
+
walk ({ data:x, keyCallback:checkNull })
|
|
169
|
+
.then ( r => {
|
|
170
|
+
expect ( r.props.eyeColor ).to.be.equal ( null )
|
|
171
|
+
done ()
|
|
172
|
+
})
|
|
173
|
+
}) // it set a value to NULL
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
it ( 'Set a value to undefined', done => {
|
|
178
|
+
let
|
|
179
|
+
x = {
|
|
180
|
+
ls : [ 1,2,3 ]
|
|
181
|
+
, name : 'Peter'
|
|
182
|
+
, props : {
|
|
183
|
+
eyeColor: undefined // Use callback and return this exact value
|
|
184
|
+
, age : 47
|
|
185
|
+
, height : 176
|
|
186
|
+
, sizes : [12,33,12,21]
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
function checkNull ({ value, resolve }) {
|
|
191
|
+
resolve(value)
|
|
192
|
+
} // checkNull func.
|
|
193
|
+
|
|
194
|
+
walk ({ data:x, keyCallback:checkNull })
|
|
195
|
+
.then ( r => {
|
|
196
|
+
expect ( r.props.eyeColor ).to.be.equal ( undefined )
|
|
197
|
+
done ()
|
|
198
|
+
})
|
|
199
|
+
}) // it Set a value to undefined
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
it ( 'Copy a function', done => {
|
|
203
|
+
let
|
|
204
|
+
x = {
|
|
205
|
+
ls : [ 1,2,3 ]
|
|
206
|
+
, name : 'Peter'
|
|
207
|
+
, props : {
|
|
208
|
+
eyeColor: undefined // Use callback and return this exact value
|
|
209
|
+
, age : function age () { return 47 }
|
|
210
|
+
, height : 176
|
|
211
|
+
, sizes : [12,33,12,21]
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
function checkNull ({ value, resolve }) {
|
|
216
|
+
resolve ( value )
|
|
217
|
+
} // checkNull func.
|
|
218
|
+
|
|
219
|
+
walk ({ data:x, keyCallback:checkNull })
|
|
220
|
+
.then ( r => {
|
|
221
|
+
expect ( r.props.age() ).to.be.equal ( 47 )
|
|
222
|
+
done ()
|
|
223
|
+
})
|
|
224
|
+
}) // it Copy a function
|
|
148
225
|
|
|
149
226
|
}) // describe
|
|
150
227
|
|
|
@@ -240,7 +240,61 @@ describe ( 'Walk-async -> objectCallback function', () => {
|
|
|
240
240
|
expect ( r.length ).to.be.equal ( 1 )
|
|
241
241
|
expect ( r[0] ).to.be.equal ( 5 )
|
|
242
242
|
})
|
|
243
|
-
|
|
243
|
+
}) // it Prevent array empty items 2
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
it ( 'Set a object to NULL', done => {
|
|
248
|
+
let
|
|
249
|
+
x = {
|
|
250
|
+
ls : [ 1,2,3 ]
|
|
251
|
+
, name : 'Peter'
|
|
252
|
+
, props : {
|
|
253
|
+
eyeColor: 'blue'
|
|
254
|
+
, age : 47
|
|
255
|
+
, height : 176
|
|
256
|
+
, sizes : [12,33,12,21]
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
function objToNull ({value,key, resolve }) {
|
|
261
|
+
if ( key === 'props' ) resolve ( null )
|
|
262
|
+
else resolve (value)
|
|
263
|
+
} // objToNull func.
|
|
264
|
+
|
|
265
|
+
walk ({ data:x, objectCallback:objToNull })
|
|
266
|
+
.then ( r => {
|
|
267
|
+
expect ( r.props ).to.be.equal ( null )
|
|
268
|
+
done ()
|
|
269
|
+
})
|
|
270
|
+
}) // it Set a object to NULL
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
it ( 'Set a object to undefined', done => {
|
|
275
|
+
let
|
|
276
|
+
x = {
|
|
277
|
+
ls : [ 1,2,3 ]
|
|
278
|
+
, name : 'Peter'
|
|
279
|
+
, props : {
|
|
280
|
+
eyeColor: 'blue'
|
|
281
|
+
, age : 47
|
|
282
|
+
, height : 176
|
|
283
|
+
, sizes : [12,33,12,21]
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
function objToNull ({value,key, resolve }) {
|
|
288
|
+
if ( key === 'props' ) resolve ( undefined )
|
|
289
|
+
else resolve ( value )
|
|
290
|
+
} // objToNull func.
|
|
291
|
+
|
|
292
|
+
walk ({ data:x, objectCallback:objToNull })
|
|
293
|
+
.then ( r => {
|
|
294
|
+
expect ( r.props ).to.be.equal ( undefined )
|
|
295
|
+
done ()
|
|
296
|
+
})
|
|
297
|
+
}) // it Set a object to undefined
|
|
244
298
|
|
|
245
299
|
|
|
246
300
|
|
|
@@ -0,0 +1,56 @@
|
|
|
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 -> Both callbacks together', () => {
|
|
11
|
+
|
|
12
|
+
it ( 'Modify on object and key callback level', () => {
|
|
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
|
+
|
|
26
|
+
function keysModifier ({value, key, resolve, reject }) {
|
|
27
|
+
if ( key === 'age') reject () // remove 'age'
|
|
28
|
+
else if ( key=== 'eyeColor' ) resolve ( 'xxx' )
|
|
29
|
+
else resolve ( value )
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function objectModifier ({value, key, resolve }) {
|
|
33
|
+
if ( key === 'props' ) {
|
|
34
|
+
const { sizes, ... others } = value // remove 'sizes'
|
|
35
|
+
resolve ( others )
|
|
36
|
+
}
|
|
37
|
+
else resolve ( value )
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
walk ({
|
|
42
|
+
data : x
|
|
43
|
+
, keyCallback : keysModifier
|
|
44
|
+
, objectCallback : objectModifier
|
|
45
|
+
})
|
|
46
|
+
.then ( r => {
|
|
47
|
+
expect ( r.props ).to.not.have.property ( 'age' )
|
|
48
|
+
expect ( r.props ).to.not.have.property ( 'sizes' )
|
|
49
|
+
expect ( r.props.eyeColor ).to.be.equal ( 'xxx' )
|
|
50
|
+
})
|
|
51
|
+
}) // it Modify on object and key callback level
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
}) // describe
|
|
55
|
+
|
|
56
|
+
|
package/dist/walk-async.min.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
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 l,s=new Promise(((n,o)=>{l=setTimeout((()=>{n(r),Promise.resolve(t)}),e)}));return t.then((()=>clearTimeout(l))),n.onComplete=o(Promise.race([t,s])),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 l(e){return null==e||"boolean"==typeof e?"simple":e instanceof Array?"array":"object"==typeof e?"object":"simple"}async function*s(e,n,o,t,r){yield await a(e,n,o,t,r)}function a(e,n,o,r,a){let[i,c]=r,u=Object.keys(e),p=t(u),m=t();return u.forEach(((u,m)=>{let f=l(e[u]),d=e[u],$="simple"!==f&&null!=c,y=t(),b=t(),v=t(),h="array"===l(n),k=!isNaN(u);$?c({resolve:y.done,reject:()=>y.done(null),value:d,key:u,breadcrumbs:`${a}/${u}`}):y.done("$$cancel"),y.onComplete((e=>{if("$$cancel"!==e||null!=d)if("$$cancel"!==e&&(d=e,f=l(d)),null!=d)if("simple"===f){if(!i)return void b.done("$$noUpdates");i({resolve:b.done,reject:()=>b.done(null),value:d,key:u,breadcrumbs:`${a}/${u}`})}else b.done("$$cancel");else p[m].done();else b.done("$$noUpdates")})),b.onComplete((e=>{if(null!=e)if("$$cancel"!==e){if("$$noUpdates"!==e&&(d=e,f=l(d)),"simple"===f){const e=function(e,n){return n instanceof Array&&!isNaN(e)}(u,n);return e?n.push(d):n[u]=d,void p[m].done("key")}v.done()}else v.done();else p[m].done("nulls")})),v.onComplete((()=>{if("object"===f){const e={};h&&k?n.push(e):n[u]=e,o.push(s(d,e,o,r,`${a}/${u}`)),p[m].done("object")}if("array"===f){const e=[];h&&k?n.push(e):n[u]=e,o.push(s(d,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:s=null,keyCallback:i=null}=e,c=l(o),u=[],p="root",m=[i,s],f=t();switch(c){case"array":n=[],a(o,n,u,m,p).then((()=>r(u,n,f)));break;case"object":n={},a(o,n,u,m,p).then((()=>{r(u,n,f)}));break;case"simple":f.done(o)}return f.promise}}},n={},o=function o(t){var r=n[t];if(void 0!==r)return r.exports;var l=n[t]={exports:{}};return e[t](l,l.exports,o),l.exports}(880);walk=o})();
|
package/webpack.config.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
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
|
-
}
|