objwalk 1.8.0 → 1.9.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/README.md +16 -0
- package/SPEC.md +40 -9
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts +20 -4
- package/dist/index.d.ts +20 -4
- package/dist/index.js +3 -3
- package/package.json +1 -1
- package/skills/objwalk/SKILL.md +16 -2
package/README.md
CHANGED
|
@@ -125,6 +125,21 @@ Return `false` to stop the entire walk. For more control, `each` also accepts
|
|
|
125
125
|
`root` and `descend` options and provides literal path segments as a fourth
|
|
126
126
|
callback argument. [Traversal details](SPEC.md#each).
|
|
127
127
|
|
|
128
|
+
Use `{ shallow: true }` to visit dictionary entries as whole values:
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
import { each } from 'objwalk'
|
|
132
|
+
|
|
133
|
+
each({ first: { count: 1 }, second: { count: 2 } }, (key, value) => {
|
|
134
|
+
console.log(key, value.count)
|
|
135
|
+
}, { shallow: true })
|
|
136
|
+
// first 1
|
|
137
|
+
// second 2
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Here, `key` is inferred as `string` and `value` as `{ count: number }`.
|
|
141
|
+
Shallow array visits infer a numeric index and the array's element type.
|
|
142
|
+
|
|
128
143
|
Use `map` to transform values while keeping the object and array structure:
|
|
129
144
|
|
|
130
145
|
```ts
|
|
@@ -154,6 +169,7 @@ const counts = map(
|
|
|
154
169
|
```
|
|
155
170
|
|
|
156
171
|
Shallow dictionary keys are typed as `string`; shallow array indexes are `number`.
|
|
172
|
+
Both `each` and `map` also infer the original value type in shallow mode.
|
|
157
173
|
For selective traversal, pass `descend` in the third argument.
|
|
158
174
|
[Mapping options](SPEC.md#map).
|
|
159
175
|
|
package/SPEC.md
CHANGED
|
@@ -163,9 +163,9 @@ does not provide an independent deep snapshot.
|
|
|
163
163
|
## each
|
|
164
164
|
|
|
165
165
|
```ts
|
|
166
|
-
type EachCallback<TKey extends WalkKey | undefined = WalkKey> = (
|
|
166
|
+
type EachCallback<TKey extends WalkKey | undefined = WalkKey, TValue = any> = (
|
|
167
167
|
key: TKey,
|
|
168
|
-
value:
|
|
168
|
+
value: TValue,
|
|
169
169
|
path: string,
|
|
170
170
|
segments: WalkKey[]
|
|
171
171
|
) => unknown
|
|
@@ -180,6 +180,7 @@ type EachEntry = {
|
|
|
180
180
|
type EachOptions = {
|
|
181
181
|
root?: boolean
|
|
182
182
|
descend?: (entry: EachEntry) => boolean
|
|
183
|
+
shallow?: boolean
|
|
183
184
|
}
|
|
184
185
|
```
|
|
185
186
|
|
|
@@ -194,8 +195,9 @@ are leaves, and built-in collection internals are not traversed.
|
|
|
194
195
|
`root` defaults to `false`. When enabled, the root is visited first with key
|
|
195
196
|
`undefined`, path `''`, and segments `[]`, even for primitive, nullish, or empty
|
|
196
197
|
inputs. Otherwise a primitive or nullish root has no visits. Object keys are
|
|
197
|
-
strings and array indexes are numbers.
|
|
198
|
-
typed as `WalkKey
|
|
198
|
+
strings and array indexes are numbers. In the default deep mode, callback keys
|
|
199
|
+
are typed as `WalkKey` without root visits; enabled or dynamic root options use
|
|
200
|
+
`WalkKey | undefined`. Shallow key and value types are described below.
|
|
199
201
|
|
|
200
202
|
Returning exactly `false` from the callback stops the entire traversal, including
|
|
201
203
|
siblings and remaining ancestor branches. Other return values, including other
|
|
@@ -207,6 +209,28 @@ both completion and early stopping.
|
|
|
207
209
|
an excluded root container. Returning `false` skips that container's children and
|
|
208
210
|
continues with siblings. It does not stop the entire traversal.
|
|
209
211
|
|
|
212
|
+
`shallow` defaults to `false`. With `shallow: true`, only immediate root children
|
|
213
|
+
are visited, plus the root when requested. Child values are passed by reference;
|
|
214
|
+
their contents are not read. `descend` is evaluated only for the root because
|
|
215
|
+
child containers are already at the shallow limit. Root pruning and stopping via
|
|
216
|
+
callback `false` keep their existing meanings. Cyclic child values are safe when
|
|
217
|
+
the shallow limit prevents following them.
|
|
218
|
+
|
|
219
|
+
With literal `shallow: true` and root visits disabled, dictionary keys are typed
|
|
220
|
+
as `string` and values as the dictionary's value type; readonly array keys are
|
|
221
|
+
`number` and values are the element type. Heterogeneous inputs produce the union
|
|
222
|
+
of their immediate value types. With root visits enabled or a dynamic root flag,
|
|
223
|
+
the key type additionally includes `undefined`, and the value type additionally
|
|
224
|
+
includes the root container's type. These key/value unions are not correlated
|
|
225
|
+
for control-flow narrowing; narrow a union value before accessing its fields.
|
|
226
|
+
|
|
227
|
+
Deep traversal, dynamic shallow flags, and unknown or mixed array/dictionary inputs retain the
|
|
228
|
+
general key and value types. An arbitrary `descend` predicate does not narrow
|
|
229
|
+
them. `EachCallback<TKey, TValue>` supports explicitly typed callbacks; `TValue`
|
|
230
|
+
defaults to `any` to preserve existing callback type declarations.
|
|
231
|
+
`EachEntry.value` in `descend` remains general because the predicate can see
|
|
232
|
+
different container levels, including the root.
|
|
233
|
+
|
|
210
234
|
Object keys are collected when entering a container; values are read as visited.
|
|
211
235
|
For arrays, native iteration captures the starting length: appended slots beyond
|
|
212
236
|
that length are not visited. Callback and `descend` receive separate copies of
|
|
@@ -217,9 +241,9 @@ not share stop state.
|
|
|
217
241
|
## map
|
|
218
242
|
|
|
219
243
|
```ts
|
|
220
|
-
type MapCallback<TResult = unknown, TKey extends WalkKey = WalkKey> = (
|
|
244
|
+
type MapCallback<TResult = unknown, TKey extends WalkKey = WalkKey, TValue = any> = (
|
|
221
245
|
key: TKey,
|
|
222
|
-
value:
|
|
246
|
+
value: TValue,
|
|
223
247
|
path: string
|
|
224
248
|
) => TResult
|
|
225
249
|
|
|
@@ -240,7 +264,8 @@ Callback replacements are not traversed again, including returned objects and ar
|
|
|
240
264
|
The callback receives `(key, value, path)`. Object keys are strings, array indexes
|
|
241
265
|
are numbers, and paths follow `each`'s descriptive string format. No accumulator or
|
|
242
266
|
store argument exists. `MapCallback`'s first generic argument is the return value
|
|
243
|
-
rather than the former store type; the optional second argument is the key type
|
|
267
|
+
rather than the former store type; the optional second argument is the key type,
|
|
268
|
+
and the optional third argument is the input value type (default `any`).
|
|
244
269
|
Array results are typed as `TResult[]`; dictionary results as
|
|
245
270
|
`Record<string, TResult>`. A dictionary-or-array union input produces the matching
|
|
246
271
|
union result type. Readonly input arrays are accepted and produce mutable new arrays.
|
|
@@ -274,8 +299,14 @@ visits. This timing differs from `each`, which calls its callback before `descen
|
|
|
274
299
|
|
|
275
300
|
`shallow` defaults to `false`. With literal `shallow: true`, only immediate root
|
|
276
301
|
children are mapped: dictionary callback keys are typed as `string`, and statically
|
|
277
|
-
known array keys as `number`.
|
|
278
|
-
|
|
302
|
+
known array keys as `number`. The input value type is inferred from the dictionary
|
|
303
|
+
values or array elements, including readonly and heterogeneous inputs. A shallow
|
|
304
|
+
`Record<string, T>` or readonly `T[]` passes `T` to its callback. Deep calls, dynamic
|
|
305
|
+
shallow flags, and union inputs keep `WalkKey` and general callback values. An
|
|
306
|
+
arbitrary `descend` predicate does not narrow these types. The shallow overloads
|
|
307
|
+
use `<TResult, TValue = any>`: calls that explicitly provide only `TResult` retain
|
|
308
|
+
the default `any` value type for compatibility. Omit explicit type arguments for
|
|
309
|
+
full inference, or provide both result and value types. When both
|
|
279
310
|
options are present, `descend` is evaluated only for the root, because child
|
|
280
311
|
containers are already at the shallow limit.
|
|
281
312
|
|
package/dist/index.cjs
CHANGED
|
@@ -49,10 +49,10 @@ var isWalkable = (value) => {
|
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
// src/each.ts
|
|
52
|
-
var each = (data, callback, { root = false, descend } = {}) => {
|
|
52
|
+
var each = (data, callback, { root = false, descend, shallow = false } = {}) => {
|
|
53
53
|
const walk = (value, path, segments, key) => {
|
|
54
54
|
const proceed = segments.length > 0 || root ? callback(key, value, path, [...segments]) !== false : true;
|
|
55
|
-
if (proceed && isWalkable(value) && (descend === void 0 || descend({ key, value, path, segments: [...segments] }))) {
|
|
55
|
+
if (proceed && (segments.length === 0 || shallow === false) && isWalkable(value) && (descend === void 0 || descend({ key, value, path, segments: [...segments] }))) {
|
|
56
56
|
if (Array.isArray(value)) {
|
|
57
57
|
return value.every(
|
|
58
58
|
(item, index) => walk(item, createPath(path, index, true), [...segments, index], index)
|
|
@@ -251,7 +251,7 @@ var map = (data, callback, { descend, shallow = false } = {}) => {
|
|
|
251
251
|
enumerable: true,
|
|
252
252
|
configurable: true
|
|
253
253
|
});
|
|
254
|
-
}, {
|
|
254
|
+
}, { shallow: true });
|
|
255
255
|
}
|
|
256
256
|
return key !== void 0 ? callback(key, mapped, path) : mapped;
|
|
257
257
|
};
|
package/dist/index.d.cts
CHANGED
|
@@ -23,7 +23,7 @@ type StringifyOptions = {
|
|
|
23
23
|
space?: string | number;
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
type EachCallback<TKey extends WalkKey | undefined = WalkKey> = (key: TKey, value:
|
|
26
|
+
type EachCallback<TKey extends WalkKey | undefined = WalkKey, TValue = any> = (key: TKey, value: TValue, path: string, segments: WalkKey[]) => unknown;
|
|
27
27
|
type EachEntry = {
|
|
28
28
|
key: WalkKey | undefined;
|
|
29
29
|
value: any;
|
|
@@ -33,8 +33,24 @@ type EachEntry = {
|
|
|
33
33
|
type EachOptions = {
|
|
34
34
|
root?: boolean;
|
|
35
35
|
descend?: (entry: EachEntry) => boolean;
|
|
36
|
+
shallow?: boolean;
|
|
36
37
|
};
|
|
38
|
+
type DictionaryValue<TData> = TData extends unknown ? TData[keyof TData] : never;
|
|
37
39
|
type Each = {
|
|
40
|
+
<TData extends readonly unknown[]>(data: TData, callback: EachCallback<number, TData[number]>, options: EachOptions & {
|
|
41
|
+
shallow: true;
|
|
42
|
+
root?: false;
|
|
43
|
+
}): void;
|
|
44
|
+
<TData extends Record<string, unknown>>(data: TData, callback: EachCallback<string, DictionaryValue<TData>>, options: EachOptions & {
|
|
45
|
+
shallow: true;
|
|
46
|
+
root?: false;
|
|
47
|
+
}): void;
|
|
48
|
+
<TData extends readonly unknown[]>(data: TData, callback: EachCallback<number | undefined, TData[number] | TData>, options: EachOptions & {
|
|
49
|
+
shallow: true;
|
|
50
|
+
}): void;
|
|
51
|
+
<TData extends Record<string, unknown>>(data: TData, callback: EachCallback<string | undefined, DictionaryValue<TData> | TData>, options: EachOptions & {
|
|
52
|
+
shallow: true;
|
|
53
|
+
}): void;
|
|
38
54
|
(data: any, callback: EachCallback, options?: EachOptions & {
|
|
39
55
|
root?: false;
|
|
40
56
|
}): void;
|
|
@@ -48,16 +64,16 @@ declare const pick: (data?: ObjwalkObject$1, path?: string, options?: PickOption
|
|
|
48
64
|
type ExtractMapping = Record<string, string | string[]>;
|
|
49
65
|
declare const extract: (source: ObjwalkObject$1, mapping: ExtractMapping) => ObjwalkObject$1;
|
|
50
66
|
|
|
51
|
-
type MapCallback<TResult = unknown, TKey extends WalkKey = WalkKey> = (key: TKey, value:
|
|
67
|
+
type MapCallback<TResult = unknown, TKey extends WalkKey = WalkKey, TValue = any> = (key: TKey, value: TValue, path: string) => TResult;
|
|
52
68
|
type MapOptions = {
|
|
53
69
|
descend?: EachOptions['descend'];
|
|
54
70
|
shallow?: boolean;
|
|
55
71
|
};
|
|
56
72
|
type Map = {
|
|
57
|
-
<TResult>(data: readonly
|
|
73
|
+
<TResult, TValue = any>(data: readonly TValue[], callback: MapCallback<TResult, number, TValue>, options: MapOptions & {
|
|
58
74
|
shallow: true;
|
|
59
75
|
}): TResult[];
|
|
60
|
-
<TResult>(data: Record<string,
|
|
76
|
+
<TResult, TValue = any>(data: Record<string, TValue>, callback: MapCallback<TResult, string, TValue>, options: MapOptions & {
|
|
61
77
|
shallow: true;
|
|
62
78
|
}): Record<string, TResult>;
|
|
63
79
|
<TResult>(data: readonly unknown[], callback: MapCallback<TResult>, options?: MapOptions): TResult[];
|
package/dist/index.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ type StringifyOptions = {
|
|
|
23
23
|
space?: string | number;
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
type EachCallback<TKey extends WalkKey | undefined = WalkKey> = (key: TKey, value:
|
|
26
|
+
type EachCallback<TKey extends WalkKey | undefined = WalkKey, TValue = any> = (key: TKey, value: TValue, path: string, segments: WalkKey[]) => unknown;
|
|
27
27
|
type EachEntry = {
|
|
28
28
|
key: WalkKey | undefined;
|
|
29
29
|
value: any;
|
|
@@ -33,8 +33,24 @@ type EachEntry = {
|
|
|
33
33
|
type EachOptions = {
|
|
34
34
|
root?: boolean;
|
|
35
35
|
descend?: (entry: EachEntry) => boolean;
|
|
36
|
+
shallow?: boolean;
|
|
36
37
|
};
|
|
38
|
+
type DictionaryValue<TData> = TData extends unknown ? TData[keyof TData] : never;
|
|
37
39
|
type Each = {
|
|
40
|
+
<TData extends readonly unknown[]>(data: TData, callback: EachCallback<number, TData[number]>, options: EachOptions & {
|
|
41
|
+
shallow: true;
|
|
42
|
+
root?: false;
|
|
43
|
+
}): void;
|
|
44
|
+
<TData extends Record<string, unknown>>(data: TData, callback: EachCallback<string, DictionaryValue<TData>>, options: EachOptions & {
|
|
45
|
+
shallow: true;
|
|
46
|
+
root?: false;
|
|
47
|
+
}): void;
|
|
48
|
+
<TData extends readonly unknown[]>(data: TData, callback: EachCallback<number | undefined, TData[number] | TData>, options: EachOptions & {
|
|
49
|
+
shallow: true;
|
|
50
|
+
}): void;
|
|
51
|
+
<TData extends Record<string, unknown>>(data: TData, callback: EachCallback<string | undefined, DictionaryValue<TData> | TData>, options: EachOptions & {
|
|
52
|
+
shallow: true;
|
|
53
|
+
}): void;
|
|
38
54
|
(data: any, callback: EachCallback, options?: EachOptions & {
|
|
39
55
|
root?: false;
|
|
40
56
|
}): void;
|
|
@@ -48,16 +64,16 @@ declare const pick: (data?: ObjwalkObject$1, path?: string, options?: PickOption
|
|
|
48
64
|
type ExtractMapping = Record<string, string | string[]>;
|
|
49
65
|
declare const extract: (source: ObjwalkObject$1, mapping: ExtractMapping) => ObjwalkObject$1;
|
|
50
66
|
|
|
51
|
-
type MapCallback<TResult = unknown, TKey extends WalkKey = WalkKey> = (key: TKey, value:
|
|
67
|
+
type MapCallback<TResult = unknown, TKey extends WalkKey = WalkKey, TValue = any> = (key: TKey, value: TValue, path: string) => TResult;
|
|
52
68
|
type MapOptions = {
|
|
53
69
|
descend?: EachOptions['descend'];
|
|
54
70
|
shallow?: boolean;
|
|
55
71
|
};
|
|
56
72
|
type Map = {
|
|
57
|
-
<TResult>(data: readonly
|
|
73
|
+
<TResult, TValue = any>(data: readonly TValue[], callback: MapCallback<TResult, number, TValue>, options: MapOptions & {
|
|
58
74
|
shallow: true;
|
|
59
75
|
}): TResult[];
|
|
60
|
-
<TResult>(data: Record<string,
|
|
76
|
+
<TResult, TValue = any>(data: Record<string, TValue>, callback: MapCallback<TResult, string, TValue>, options: MapOptions & {
|
|
61
77
|
shallow: true;
|
|
62
78
|
}): Record<string, TResult>;
|
|
63
79
|
<TResult>(data: readonly unknown[], callback: MapCallback<TResult>, options?: MapOptions): TResult[];
|
package/dist/index.js
CHANGED
|
@@ -12,10 +12,10 @@ var isWalkable = (value) => {
|
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
// src/each.ts
|
|
15
|
-
var each = (data, callback, { root = false, descend } = {}) => {
|
|
15
|
+
var each = (data, callback, { root = false, descend, shallow = false } = {}) => {
|
|
16
16
|
const walk = (value, path, segments, key) => {
|
|
17
17
|
const proceed = segments.length > 0 || root ? callback(key, value, path, [...segments]) !== false : true;
|
|
18
|
-
if (proceed && isWalkable(value) && (descend === void 0 || descend({ key, value, path, segments: [...segments] }))) {
|
|
18
|
+
if (proceed && (segments.length === 0 || shallow === false) && isWalkable(value) && (descend === void 0 || descend({ key, value, path, segments: [...segments] }))) {
|
|
19
19
|
if (Array.isArray(value)) {
|
|
20
20
|
return value.every(
|
|
21
21
|
(item, index) => walk(item, createPath(path, index, true), [...segments, index], index)
|
|
@@ -214,7 +214,7 @@ var map = (data, callback, { descend, shallow = false } = {}) => {
|
|
|
214
214
|
enumerable: true,
|
|
215
215
|
configurable: true
|
|
216
216
|
});
|
|
217
|
-
}, {
|
|
217
|
+
}, { shallow: true });
|
|
218
218
|
}
|
|
219
219
|
return key !== void 0 ? callback(key, mapped, path) : mapped;
|
|
220
220
|
};
|
package/package.json
CHANGED
package/skills/objwalk/SKILL.md
CHANGED
|
@@ -92,7 +92,7 @@ pick(data, 'user.name', {
|
|
|
92
92
|
Object keys are strings; array indexes are numbers. Prefer segments when keys may
|
|
93
93
|
contain dots, brackets, or empty strings; the string `path` can be ambiguous.
|
|
94
94
|
|
|
95
|
-
`EachOptions` accepts `root` (default `false`) and
|
|
95
|
+
`EachOptions` accepts `root` and `shallow` (both default `false`), and
|
|
96
96
|
`descend: ({ key, value, path, segments }) => boolean`.
|
|
97
97
|
With `root: true`, the root is visited first, including primitive/nullish values,
|
|
98
98
|
with key `undefined`, path `''`, and segments `[]`. Callback keys are then typed
|
|
@@ -100,6 +100,16 @@ with key `undefined`, path `''`, and segments `[]`. Callback keys are then typed
|
|
|
100
100
|
`EachCallback<WalkKey | undefined>` for an explicitly typed root-aware callback.
|
|
101
101
|
`EachEntry` and `EachOptions` are also public named exports.
|
|
102
102
|
|
|
103
|
+
Use `each(data, callback, { shallow: true })` to visit only immediate entries.
|
|
104
|
+
Literal shallow mode infers string dictionary keys, numeric array indexes, and
|
|
105
|
+
the input value type. With root visits enabled or a dynamic root flag, key types
|
|
106
|
+
also include `undefined` and value types include the root container. Narrow the
|
|
107
|
+
value union explicitly; key/value parameters are not correlated. `descend` runs
|
|
108
|
+
only at the shallow root. Callback `false` still stops the entire traversal.
|
|
109
|
+
`EachCallback<TKey, TValue>` adds an optional value type parameter, defaulting
|
|
110
|
+
to `any` for existing explicit callback declarations. Dynamic shallow flags and
|
|
111
|
+
unknown inputs retain general callback types.
|
|
112
|
+
|
|
103
113
|
`descend` is called only for containers, after their callback, and returning false
|
|
104
114
|
skips their children. It also runs for a root container excluded from callbacks.
|
|
105
115
|
For example, `descend: ({ value }) => Array.isArray(value) === false` visits arrays
|
|
@@ -131,7 +141,11 @@ result of the same kind. Literal `shallow: true` visits only immediate children,
|
|
|
131
141
|
typing dictionary keys as `string` and array keys as `number`. When both options
|
|
132
142
|
are present, `descend` is evaluated only for the root. Deep/dynamic calls keep
|
|
133
143
|
`WalkKey`; a custom descend predicate alone cannot narrow keys.
|
|
134
|
-
|
|
144
|
+
Shallow map also infers the input value type; deep/dynamic callback values stay
|
|
145
|
+
general. `MapCallback<TResult, TKey, TValue>` describes the callback's result,
|
|
146
|
+
key, and input value types. Calls that specify only `map<TResult>` retain the
|
|
147
|
+
default `any` input value type; omit explicit generics for full inference or
|
|
148
|
+
provide both result and value types.
|
|
135
149
|
This is a breaking replacement of the old store-based map, not an overload.
|
|
136
150
|
|
|
137
151
|
## Differences
|