@peter.naydenov/walk-async 6.0.0 → 7.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 +34 -2
- package/Migration.guide.md +274 -0
- package/README.md +501 -311
- package/dist/walk-async.cjs +1 -1
- package/dist/walk-async.esm.mjs +1 -1
- package/dist/walk-async.umd.js +1 -1
- package/package.json +19 -8
- package/src/copyObject.js +145 -0
- package/src/createCallbackArgs.js +15 -0
- package/src/findType.js +28 -0
- package/src/finish.js +38 -0
- package/src/ignore.js +24 -0
- package/src/main.js +230 -285
- package/src/pass.js +36 -0
- package/src/runCallback.js +55 -0
- package/src/setKey.js +12 -0
- package/src/validateForInsertion.js +12 -0
- package/types/copyObject.d.ts +8 -0
- package/types/copyObject.d.ts.map +1 -0
- package/types/createCallbackArgs.d.ts +32 -0
- package/types/createCallbackArgs.d.ts.map +1 -0
- package/types/findType.d.ts +3 -0
- package/types/findType.d.ts.map +1 -0
- package/types/finish.d.ts +25 -0
- package/types/finish.d.ts.map +1 -0
- package/types/ignore.d.ts +10 -0
- package/types/ignore.d.ts.map +1 -0
- package/types/main.d.ts +147 -61
- package/types/main.d.ts.map +1 -1
- package/types/pass.d.ts +23 -0
- package/types/pass.d.ts.map +1 -0
- package/types/runCallback.d.ts +3 -0
- package/types/runCallback.d.ts.map +1 -0
- package/types/setKey.d.ts +3 -0
- package/types/setKey.d.ts.map +1 -0
- package/types/validateForInsertion.d.ts +3 -0
- package/types/validateForInsertion.d.ts.map +1 -0
- package/rollup.config.js +0 -41
- package/tsconfig.json +0 -11
- package/types/src/main.d.ts +0 -35
- package/types/src/main.d.ts.map +0 -1
- package/vitest.config.js +0 -8
package/Changelog.md
CHANGED
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
### 7.0.0 (2026-10-05)
|
|
5
|
+
- [x] Docs: Update the skill;
|
|
6
|
+
- [x] Feature: Added private `FINISH()` / `FINISH(value)` instructions to both callbacks. Omit and stop immediately without an argument; key callbacks include supplied values directly, while object callbacks select the final branch for key callbacks with `isFinished:true` and suppress further object callbacks. Promised payloads and explicit settlement are awaited; ordinary key callbacks receive `isFinished:false`;
|
|
7
|
+
- [x] Tests: Ported 73 FINISH cases and 832 deterministic generated tests, covering 768 transformation settings cases and 384 early-finish combinations against an independent recursive reference. Added async FINISH settlement, payload, failure, timeout, distribution, and documentation checks;
|
|
8
|
+
- [x] Benchmarks: Added fresh-process async memory measurements separating sampled extra heap, retained and released heap after GC, and process RSS high-water marks. Recorded actual async samples and methodology; excluded benchmarks from package contents;
|
|
9
|
+
- [x] Docs: Added FINISH semantics, generated test methodology, measured memory use, and historical timing provenance. Updated the helper skill and regenerated FINISH declarations and distributions;
|
|
10
|
+
- [x] Feature: Callbacks now accept ordinary returns and awaited promises, matching the synchronous API. Added callable `IGNORE()` to both callbacks; change synchronous `return IGNORE` examples to `return IGNORE()`. Existing async `resolve`/`reject` callbacks remain supported; reading either field selects explicit settlement;
|
|
11
|
+
- [x] Feature: Added optional `settings`. Callback arguments `breadcrumbs` and `parentPath` are enabled by default; only literal `false` disables their preparation. Walks without callbacks skip path preparation automatically;
|
|
12
|
+
- [x] Feature: Added `settings.copy:false` to walk without building a result. Callback order, paths, replacements, `IGNORE()`, and `PASS()` keep their traversal behaviour; the walk resolves `undefined`;
|
|
13
|
+
- [x] Feature: Added read-only `parentPath` arrays to both callbacks. Paths exclude the current key, preserve property boundaries, and use input array indexes;
|
|
14
|
+
- [x] Feature: Added the `PASS` function to `objectCallback`. Return `PASS()` to copy the current value, or `PASS(modifiedValue)` to use a replacement, without immediate key callbacks. Replacement promises are awaited. Nested objects and arrays resume normal callbacks; `IGNORE()` removes the entire branch;
|
|
15
|
+
- [x] Packaging: Added `"types":"./types/main.d.ts"` before runtime conditions in `exports["."]` so modern TypeScript consumers resolve declarations through package-name imports;
|
|
16
|
+
- [x] Fix: Read each property once before finding its type, so getters are not executed twice;
|
|
17
|
+
- [x] Fix: Recognize arrays across JavaScript contexts and preserve numeric-looking non-index properties under their original names;
|
|
18
|
+
- [x] Breaking: Callback execution now awaits each sibling in `Object.keys` order instead of starting siblings concurrently. Deferred container contents remain in scheduling order;
|
|
19
|
+
- [x] Fix: Thrown callback errors, rejected callback promises, rejected resolve values, and nested-walk failures propagate to the walk promise. Awaited finite nested walks have independent state;
|
|
20
|
+
- [x] Feature: Retained timeout diagnostics for explicit settlement and unresolved returned promises; timers are cleared on completion or failure;
|
|
21
|
+
- [x] Performance: Replaced one-use generator wrappers with a work queue. Processed entries are cleared to release container and path references earlier; callback order is preserved;
|
|
22
|
+
- [x] Cleanup: Native promises replace the runtime use of `ask-for-promise`; the declared dependency remains unchanged for the maintainer. Split source helpers to match the synchronous project and regenerated all three distributions and declarations; removed stale `types/src` output;
|
|
23
|
+
- [x] Fix: Detect circular references through the current branch's ancestors and link them to the matching ancestor copy. Without copying, stop at the circular edge. Callbacks can still ignore or replace the edge; shared containers on separate branches are copied independently;
|
|
24
|
+
- [x] Feature: Added `settings.detectCycles`, enabled by default. Only literal `false` skips circular-reference checks and all ancestor bookkeeping. Visited data and callback replacements must then have no circles, or callbacks must prune cyclic branches;
|
|
25
|
+
- [x] Docs: Rewrote the README around readable traversal rules, transformations during copying, deep forEach, branch control, paths, and reference behaviour. Updated the skill and removed the outdated restriction on finite nested walk calls;
|
|
26
|
+
- [x] Tests: Ported all 208 synchronous tests, retained all 66 existing async tests, and added awaited instruction, callback order, rejection, and nested-walk tests. Enforced 100% coverage thresholds;
|
|
27
|
+
- [x] Tests: Added regression coverage for settings, parent paths, local `PASS`, traversal without copying, circular references, getters, and array recognition and properties;
|
|
28
|
+
- [x] Verification: Added generated-format smoke checks, executable README examples, strict TypeScript consumption checks, and a repeatable benchmark for cycle detection, copying, and paths. Recorded actual async measurements without importing synchronous timing claims;
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### 6.1.0 (2026-09-01)
|
|
33
|
+
- [x] Feature: Added a skill at `.agents/skills/git-walk-async/SKILL.md`;
|
|
34
|
+
- [x] Packaging: Added `.agents/skills` to the `"files"` allow-list in `package.json` so the skill ships with the npm package. AI-agent users can discover the walk-async skill from `node_modules` directly, without needing access to the source repo. The same allow-list also drops the dev-only `rollup.config.js`, `tsconfig.json`, and `vitest.config.js` that were leaking under the previous `.npmignore`-only packaging;
|
|
35
|
+
- [x] Docs: Prefilled `Migration.guide.md` for every major release: sync-`@peter.naydenov/walk` → `walk-async` (the README's "Migrating from `@peter.naydenov/walk`" table, folded in), v3.x → v6.x (callback signatures tightened with exported `Resolve` / `Reject` typedefs), v3.0.x → v3.1.x (the `timeout` option, the built-in-type pass-by-reference fix from v3.1.2, and the v3.0.6/v3.0.7 root-callback bug fixes), the existing v2.x → v3.x root-callback entry, v1.x → v2.x (ES module + `dist` + `exports`), and v1.0.0 → v1.x (the early null/undefined, DOM-node, and collection-container fixes);
|
|
36
|
+
|
|
37
|
+
|
|
4
38
|
|
|
5
39
|
### 6.0.0 (2026-08-08)
|
|
6
40
|
- [x] Allign version numbers with `@peter.naydenov/walk`. We jumping from 3.1.3 to 6.0.0;
|
|
@@ -141,5 +175,3 @@
|
|
|
141
175
|
- [x] Test package;
|
|
142
176
|
- [x] Documentation;
|
|
143
177
|
- [ ] Bug: Deep copy is not working.
|
|
144
|
-
|
|
145
|
-
|
package/Migration.guide.md
CHANGED
|
@@ -1,8 +1,248 @@
|
|
|
1
1
|
# Migration Guides
|
|
2
2
|
|
|
3
|
+
Upgrade notes for non-trivial `walk-async` releases. For the full per-release list of changes, see the [Changelog](Changelog.md).
|
|
4
|
+
|
|
5
|
+
## From v.6.x.x - v.7.x.x (Unreleased)
|
|
6
|
+
|
|
7
|
+
### Agent skill
|
|
8
|
+
|
|
9
|
+
The skill is now named `walk-async` and lives in `skills/walk-async/`, replacing
|
|
10
|
+
`.agents/skills/git-walk-async/`. Update installers or integrations that use
|
|
11
|
+
the old path, and include the full folder with all four linked references.
|
|
12
|
+
There is one canonical portable skill; local `.claude` and `.agents` settings
|
|
13
|
+
are not maintained copies. See [skill integration](skills/README.md).
|
|
14
|
+
|
|
15
|
+
The current `package.json` `files` whitelist excludes the new folder. Replace
|
|
16
|
+
the obsolete `".agents/skills"` entry with `"skills"` to include the skill, all
|
|
17
|
+
references, and the integration README linked from the package documentation. This manifest update is left for
|
|
18
|
+
the maintainer; the skill/documentation move does not change package.json.
|
|
19
|
+
Verify the folder with `npm pack --dry-run --json` after making that change.
|
|
20
|
+
|
|
21
|
+
### Return values and awaited callbacks
|
|
22
|
+
|
|
23
|
+
Callbacks now share the synchronous library's return-value API. Change `resolve(value)` to `return value`, and `reject()` to `return IGNORE()` when adopting it:
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
// version 6: still supported in version 7
|
|
27
|
+
keyCallback : ({ value, key, resolve, reject }) => {
|
|
28
|
+
if ( key === 'password' ) reject ()
|
|
29
|
+
else resolve ( value )
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// version 7
|
|
33
|
+
keyCallback : async ({ value, key, IGNORE }) => {
|
|
34
|
+
if ( key === 'password' ) return IGNORE()
|
|
35
|
+
return await refresh ( value )
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Both plain returns and returned promises are supported. The walk itself still returns a Promise. Await it to get the copy, finish side effects, or catch an error. A thrown error or a rejected promise from either callback now rejects the walk instead of leaving internal tasks pending. Finite awaited nested walks are supported; each call has independent traversal and ancestor state.
|
|
40
|
+
|
|
41
|
+
Existing `resolve`/`reject` callbacks remain supported. Reading either field selects explicit settlement for that invocation, so settle every path with one of them. An async callback's returned promise is awaited even when it calls `resolve` early; `resolve` also awaits a supplied promise. Do not destructure or spread unused settlement fields when switching to returns. `reject()` continues to prune the current key or branch; use a throw or a rejected promise to fail the walk. The existing `timeout` option still reports pending callbacks and now covers unresolved returned promises too. It does not cancel callback I/O.
|
|
42
|
+
|
|
43
|
+
### Callable IGNORE
|
|
44
|
+
|
|
45
|
+
`IGNORE` is a function in both callbacks. When moving code from the synchronous v6 API, replace `return IGNORE` with `return IGNORE()`:
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
// synchronous version 6
|
|
49
|
+
keyCallback : ({ value, key, IGNORE }) => key === 'password' ? IGNORE : value
|
|
50
|
+
|
|
51
|
+
// version 7, synchronous or asynchronous
|
|
52
|
+
keyCallback : ({ value, key, IGNORE }) => key === 'password' ? IGNORE() : value
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Its private token removes a leaf or an entire container branch, including descendants. Ignoring the root resolves `[]` for an original array root or `{}` for an original object root when copying; without copying it resolves `undefined`. Returning the helper function itself stores ordinary function data. Async v6 used `reject()` rather than a public IGNORE constant; those callbacks do not need this change. TypeScript now includes `IgnoreFunction`, `PassFunction`, `ObjectCallbackArgs`, and `Settings` alongside `Resolve` and `Reject`. Metadata fields are optional and parent paths are read-only.
|
|
56
|
+
|
|
57
|
+
### Callback order
|
|
58
|
+
|
|
59
|
+
Sibling callbacks used to start concurrently. Version 7 awaits them one at a time in `Object.keys` order to match the synchronous library. The root object callback runs first; child object callbacks run when their properties are encountered, and those containers' contents are deferred until the current container finishes. Queued containers run in scheduling order, breadth-first over contents. There is no exit callback.
|
|
60
|
+
|
|
61
|
+
Code that depends on sibling callbacks overlapping must move that concurrency into application code. Array output, side effects, replacement handling, and ancestor lookup now follow the same defined order even when callbacks await different delays.
|
|
62
|
+
|
|
63
|
+
### Getter and array fixes
|
|
64
|
+
|
|
65
|
+
Properties are read once before classification. Getters no longer run twice. `Array.isArray` recognizes arrays from other JavaScript contexts. Only canonical indexes from `0` through `2^32 - 2` become consecutive output elements. Sparse holes and removed indexes compact; numeric-looking non-index properties such as `'01'`, `'-1'`, and `'4294967295'` retain their original names. Own `'__proto__'` properties remain ordinary data without changing the result prototype.
|
|
66
|
+
|
|
67
|
+
### Settings, parentPath and PASS
|
|
68
|
+
|
|
69
|
+
Existing calls do not need a `settings` object. Both callbacks now receive a read-only `parentPath` array by default, alongside `breadcrumbs`. The parent path excludes `key`; the root `objectCallback` receives `parentPath:[]` and `key:'root'`.
|
|
70
|
+
|
|
71
|
+
Set `settings.breadcrumbs` or `settings.parentPath` to literal `false` to skip preparing an unused argument. Omitted settings remain enabled. Disabled arguments are absent, so destructuring them gives `undefined`; TypeScript declares both metadata fields as optional.
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
let result = await walk ({
|
|
75
|
+
data
|
|
76
|
+
, settings : { breadcrumbs:false, parentPath:false }
|
|
77
|
+
, keyCallback : ({ value }) => value
|
|
78
|
+
})
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Default calls now prepare parent arrays when callbacks are present. Disable `parentPath` when the callback does not use it, particularly for deeply nested data. With no callbacks, both paths are skipped automatically.
|
|
82
|
+
|
|
83
|
+
`objectCallback` also receives the `PASS` function. Return `PASS()` to copy the current value and skip `keyCallback` only on its immediate properties, or `PASS(modifiedValue)` to use a replacement with the same rule. Nested objects and arrays still run their own callbacks normally. `IGNORE()` removes the entire branch and stops visiting its contents.
|
|
84
|
+
|
|
85
|
+
`PASS()` and `PASS(undefined)` have different meanings: the first keeps the current value; the second explicitly replaces it with `undefined`. A simple replacement is stored directly without `keyCallback`. Neither instruction appears in the result.
|
|
86
|
+
|
|
87
|
+
Walk Async also awaits promises supplied to `PASS(replacement)` before interpreting the replacement and checking its ancestors. Rejected replacements reject the walk; unresolved replacements remain in timeout diagnostics.
|
|
88
|
+
|
|
89
|
+
### Finish the entire walk
|
|
90
|
+
|
|
91
|
+
Both callbacks now receive the `FINISH` function. Like `IGNORE()` and `PASS()`, return its instruction or pass it to `resolve`. Calling it without returning or resolving the instruction has no effect on traversal.
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
let result = await walk ({
|
|
95
|
+
data : [12,22,33,44,55,66]
|
|
96
|
+
, keyCallback : ({ value, FINISH }) => {
|
|
97
|
+
if ( value === 33 ) return FINISH ( value )
|
|
98
|
+
return value
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
// [12,22,33]
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`FINISH()` omits the current value or branch and stops immediately. From `keyCallback`, `FINISH(value)` includes the supplied value directly and stops immediately, without copying or visiting its contents. An explicit argument counts even when it is `undefined`.
|
|
105
|
+
|
|
106
|
+
From `objectCallback`, `FINISH(value)` selects the final branch. If a key callback exists, it processes the supplied value's leaves with the new boolean argument `isFinished:true`, including nested containers and containers returned by key callbacks. No further object callbacks run, and unrelated pending work is discarded. Ordinary key callbacks receive `isFinished:false`. Return `value` to preserve final leaves, `IGNORE()` to drop them while continuing through the final branch, or `FINISH()` / `FINISH(value)` to stop immediately at a final leaf. Dropping leaves can leave empty nested containers. Earlier `PASS()` instructions do not suppress key callbacks in the selected final branch.
|
|
107
|
+
|
|
108
|
+
Without a key callback, `FINISH(value)` from an object callback includes the value directly. Supplied objects and arrays then keep their references. With a key callback, the final branch is copied using the normal leaf return rules and cycle detection. A simple root replacement remains a direct return without a key callback, matching the existing root contract.
|
|
109
|
+
|
|
110
|
+
When copying, the result contains work completed before stopping. Unrelated containers already allocated but waiting for traversal can remain empty or partially populated. Finishing from the root object callback without a value resolves an empty object or array matching the input root; supplying a container follows the final-branch rule. Without copying, finishing still controls traversal and walk resolves `undefined`. Collect search results externally in that mode.
|
|
111
|
+
|
|
112
|
+
Walk Async awaits callback completion and promises supplied to `FINISH(value)`, including through `resolve ( FINISH ( value ) )`. Rejected payloads reject the walk; unresolved payloads remain in timeout diagnostics.
|
|
113
|
+
|
|
114
|
+
This is an optional addition; existing callbacks do not need changes. Finishing is local to each walk, including nested calls. TypeScript declares the shared helper as `FinishFunction` and the key callback arguments as `KeyCallbackArgs`, including `isFinished:boolean`.
|
|
115
|
+
|
|
116
|
+
### Walk without a copy
|
|
117
|
+
|
|
118
|
+
Set `settings.copy` to literal `false` to run callbacks without creating result objects or arrays. Walk resolves `undefined` in this mode, including for simple, ignored, or replaced roots. Copying remains enabled when the setting is omitted or has any other value.
|
|
119
|
+
|
|
120
|
+
```js
|
|
121
|
+
let values = [];
|
|
122
|
+
await walk ({
|
|
123
|
+
data : { number:1, nested:{ number:2 } }
|
|
124
|
+
, settings : { copy:false }
|
|
125
|
+
, keyCallback : ({ value }) => { values.push ( value ) }
|
|
126
|
+
})
|
|
127
|
+
// values: [1,2]
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Callback order and path arguments stay the same. `IGNORE()` still prunes branches; `PASS()` and `PASS(value)` still skip immediate key callbacks while visiting nested objects normally. Returned replacement containers are visited without being assigned to the source.
|
|
131
|
+
|
|
132
|
+
An object callback must still return the current or replacement value to continue into it. A key callback used only for side effects may omit its return. Metadata settings are independent of copying; disable unused paths separately.
|
|
133
|
+
|
|
134
|
+
### Circular references
|
|
135
|
+
|
|
136
|
+
Walk now detects references back to an ancestor instead of following them indefinitely. When copying, the reference points to that ancestor's copy: if `data.self === data`, then `result.self === result`. With `settings.copy:false`, traversal stops at that edge and resolves `undefined` as usual.
|
|
137
|
+
|
|
138
|
+
Object callbacks still receive circular properties and can ignore or replace them. The returned container is checked against the current branch's ancestors before visiting its contents. This also applies to containers returned by `keyCallback`. Repeated references on separate branches are still copied independently. No new setting or callback argument is required; detection works with both path settings disabled.
|
|
139
|
+
|
|
140
|
+
Detection defaults to true. Set `settings.detectCycles` to literal `false` to skip the checks and all ancestor bookkeeping when the visited data and callback replacements are known to be acyclic. Omitted settings and other values keep detection enabled. Copying and metadata settings remain independent.
|
|
141
|
+
|
|
142
|
+
```js
|
|
143
|
+
let result = await walk ({
|
|
144
|
+
data : JSON.parse ( '{"nested":{"number":1}}' )
|
|
145
|
+
, settings : { detectCycles:false }
|
|
146
|
+
})
|
|
147
|
+
// { nested:{ number:1 } }
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
With detection disabled, callbacks must prune cyclic branches before revisiting them; otherwise traversal can continue indefinitely. Callback order and return rules are unchanged.
|
|
151
|
+
|
|
152
|
+
### Traversal performance
|
|
153
|
+
|
|
154
|
+
Nested containers now use a work queue instead of generator wrappers. Processed entries are cleared to release their container and path references earlier. Callback order and return behaviour stay the same; no changes to your callbacks are required for this optimization. Walk no longer uses generator functions, so a generator polyfill is no longer needed for the library itself.
|
|
155
|
+
|
|
156
|
+
Pending descendants keep links to their ancestor containers for circular-reference detection. Shallow branches use the short parent chain; deeper branches use an internal lookup containing only the current branch's ancestors. This avoids repeatedly scanning long chains. Detection adds bookkeeping even when path preparation is disabled.
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
### Package declarations
|
|
160
|
+
|
|
161
|
+
The generated declarations describe the new settings, helpers, optional metadata, and Promise return contract. The package now includes a `types` condition before the runtime conditions in `package.json` for modern TypeScript resolution:
|
|
162
|
+
|
|
163
|
+
```json
|
|
164
|
+
"exports": {
|
|
165
|
+
".": {
|
|
166
|
+
"types": "./types/main.d.ts",
|
|
167
|
+
"import": "./dist/walk-async.esm.mjs",
|
|
168
|
+
"require": "./dist/walk-async.cjs",
|
|
169
|
+
"default": "./dist/walk-async.umd.js"
|
|
170
|
+
},
|
|
171
|
+
"./package.json": "./package.json",
|
|
172
|
+
"./dist/*": "./dist/*",
|
|
173
|
+
"./src/*": "./src/*"
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Strict package-name imports now resolve declarations under `NodeNext` and `Bundler`. The package exports were verified with strict ESM, CommonJS default-import, and bundler consumers.
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
## From `@peter.naydenov/walk` (sync sibling)
|
|
182
|
+
|
|
183
|
+
For version 7 of both packages, keep the callbacks and settings, change the import, and await the walk:
|
|
184
|
+
|
|
185
|
+
```js
|
|
186
|
+
import walk from '@peter.naydenov/walk-async'
|
|
187
|
+
|
|
188
|
+
let result = await walk ({
|
|
189
|
+
data : { name:'Peter', password:'secret' }
|
|
190
|
+
, keyCallback : ({ value, key, IGNORE }) => key === 'password' ? IGNORE() : value
|
|
191
|
+
})
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Async callbacks may await I/O and return their result. Both packages share paths, replacement rules, local `PASS`, callable `IGNORE`, no-copy traversal, and ancestor-cycle handling. Walk Async additionally retains explicit `resolve`/`reject` callbacks and `timeout` diagnostics. It awaits callback results; the synchronous library does not. For pre-v7 synchronous code, change `return IGNORE` to `return IGNORE()` too.
|
|
195
|
+
|
|
196
|
+
## From v.3.x.x - v.6.x.x
|
|
197
|
+
|
|
198
|
+
v6 is a version-alignment release with `@peter.naydenov/walk` (the sync sibling). **Behaviour is unchanged from v.3.1.3** — every v3.x callback that worked in v3.1.3 still works identically in v6.x. The only user-facing change is on the TypeScript side.
|
|
199
|
+
|
|
200
|
+
### Callback signatures are now strictly typed
|
|
201
|
+
|
|
202
|
+
`keyCallback` and `objectCallback` are now typed as `KeyCallback` / `ObjectCallback` over a `CallbackArgs` shape, and `resolve` / `reject` are exported as `Resolve` / `Reject` typedefs so TypeScript users get autocomplete. If your callbacks already called `resolve(value)` / `reject()` correctly, they keep working unchanged at runtime; TypeScript will now catch signature mistakes at compile time.
|
|
203
|
+
|
|
204
|
+
```ts
|
|
205
|
+
// v3.x.x - call signatures inferred from usage; no Resolve/Reject typedefs
|
|
206
|
+
function keyCallback ({ value, key, resolve, reject }) {
|
|
207
|
+
if (key === 'password') reject()
|
|
208
|
+
else resolve(value)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// v6.x.x - same code, now type-checked against the exported Resolve / Reject
|
|
212
|
+
import type { KeyCallback, Resolve, Reject } from '@peter.naydenov/walk-async'
|
|
213
|
+
const keyCallback: KeyCallback = ({ value, key, resolve, reject }) => {
|
|
214
|
+
if (key === 'password') reject()
|
|
215
|
+
else (resolve as Resolve)(value)
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
If you're on JavaScript (not TypeScript), there is nothing to change.
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
## From v.3.0.x - v.3.1.x
|
|
224
|
+
|
|
225
|
+
A new optional `timeout` (milliseconds) was added. When set, the walk promise is rejected if any callback has not called `resolve` or `reject` in time; the error message lists the breadcrumbs of every still-pending callback so the broken code path can be found directly.
|
|
226
|
+
|
|
227
|
+
```js
|
|
228
|
+
// v3.0.x
|
|
229
|
+
const result = await walk ({ data, keyCallback }) // hangs forever if a callback forgets to resolve
|
|
230
|
+
|
|
231
|
+
// v3.1.x
|
|
232
|
+
const result = await walk ({ data, keyCallback, timeout: 5000 })
|
|
233
|
+
// if a callback never settles, the walk promise is rejected with:
|
|
234
|
+
// walk-async: timed out after 5000ms; callbacks still pending:
|
|
235
|
+
// - keyCallback at 'root/props/age'
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
This is purely additive — the option is optional, off by default, and identical to v3.0.x when omitted. The pre-existing v3.0.6 and v3.0.7 bug fixes (`__proto__` no longer replacing the copy's prototype; top-level property named `root` no longer dropped; `objectCallback` resolving the root with a primitive no longer crashes) shipped in this window. Correct code gets more lenient, not more strict.
|
|
239
|
+
|
|
240
|
+
This is also the window when `Date`, `RegExp`, `Map`, `Set`, `WeakMap`, `WeakSet`, `ArrayBuffer`, `DataView`, and typed arrays became passed by reference (v.3.1.2). They used to come out as empty `{}` — that was almost always a bug, so the fix is a no-op for working code, but if you were somehow relying on the broken behaviour, this is the release that changed it.
|
|
241
|
+
|
|
3
242
|
|
|
4
243
|
|
|
5
244
|
## From v.2.x.x - v.3.x.x
|
|
245
|
+
|
|
6
246
|
Difference between v.2.x.x and v.3.x.x is that object callbacks are triggered on 'root' object as well. So if you have object callbacks that are not working as expected after upgrade, you need to add extra line of code for version 3.
|
|
7
247
|
|
|
8
248
|
```js
|
|
@@ -21,3 +261,37 @@ function oCallbackFn ({ value:o, key, IGNORE, breadcrumbs }) {
|
|
|
21
261
|
Everything else works the same.
|
|
22
262
|
|
|
23
263
|
|
|
264
|
+
|
|
265
|
+
## From v.1.x.x - v.2.x.x
|
|
266
|
+
|
|
267
|
+
v2 converted the package to a proper ES module and added a built `dist/` (CommonJS, ESM, UMD) plus a `package.json` `exports` map and a Rollup build pipeline.
|
|
268
|
+
|
|
269
|
+
**For most users the upgrade is automatic** — your bundler / runtime picks the right build from the `exports` map. The only breaking case is if you were reaching into the package by path:
|
|
270
|
+
|
|
271
|
+
```js
|
|
272
|
+
// v1.x.x - CommonJS; the package exports a function
|
|
273
|
+
const walk = require ( '@peter.naydenov/walk-async' )
|
|
274
|
+
|
|
275
|
+
// v2.x.x - ES module; the default export is the walk function
|
|
276
|
+
import walk from '@peter.naydenov/walk-async'
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
If you were loading source directly (`require('@peter.naydenov/walk-async/src/main')` or similar), use the package's `exports` map (`@peter.naydenov/walk-async/src/main`) instead, or just import the default.
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
## From v.1.0.0 - v.1.x.x
|
|
284
|
+
|
|
285
|
+
v1.x added a series of small but important fixes. If you are still on v.1.0.0, the relevant ones are:
|
|
286
|
+
|
|
287
|
+
### v.1.1.0 - `null` and `undefined` resolution
|
|
288
|
+
|
|
289
|
+
Returning `null` or `undefined` from a callback is now stored as the literal value (not treated as "skip"). If you were relying on `null` to mean "drop this key", switch to `reject()` (in v6.x) or to whatever the v1.x equivalent was — the API has since changed.
|
|
290
|
+
|
|
291
|
+
### v.1.2.0 - DOM nodes copied by reference
|
|
292
|
+
|
|
293
|
+
`walk-async` no longer descends into HTML DOM nodes — they are passed through by reference. This is the same contract as functions, and (added later in v.3.1.2) `Date` / `Map` / `Set` / `RegExp` / typed arrays.
|
|
294
|
+
|
|
295
|
+
### v.1.3.0 - `undefined`-valued keys preserved; collection containers
|
|
296
|
+
|
|
297
|
+
Keys whose value is `undefined` are now copied (they were being dropped in v.1.0.0). Also, callbacks can now extract data into provided collection containers during iteration.
|