objwalk 1.6.0 → 1.8.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/dist/index.cjs CHANGED
@@ -51,20 +51,18 @@ var isWalkable = (value) => {
51
51
  // src/each.ts
52
52
  var each = (data, callback, { root = false, descend } = {}) => {
53
53
  const walk = (value, path, segments, key) => {
54
- if (segments.length > 0 || root) {
55
- callback(key, value, path, [...segments]);
56
- }
57
- if (isWalkable(value) && (descend === void 0 || descend({ key, value, path, segments: [...segments] }))) {
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] }))) {
58
56
  if (Array.isArray(value)) {
59
- value.forEach((item, index) => {
60
- walk(item, createPath(path, index, true), [...segments, index], index);
61
- });
62
- } else {
63
- Object.entries(value).forEach(([childKey, item]) => {
64
- walk(item, createPath(path, childKey, false), [...segments, childKey], childKey);
65
- });
57
+ return value.every(
58
+ (item, index) => walk(item, createPath(path, index, true), [...segments, index], index)
59
+ );
66
60
  }
61
+ return Object.keys(value).every(
62
+ (childKey) => walk(value[childKey], createPath(path, childKey, false), [...segments, childKey], childKey)
63
+ );
67
64
  }
65
+ return proceed;
68
66
  };
69
67
  walk(data, "", [], void 0);
70
68
  };
@@ -213,13 +211,13 @@ var extract = (source, mapping) => {
213
211
  return;
214
212
  }
215
213
  if (Array.isArray(sourcePath)) {
216
- for (const item of sourcePath) {
214
+ each(sourcePath, (_key, item) => {
217
215
  const value = pick(source, item);
218
216
  if (value !== void 0) {
219
217
  set(result, destinationPath, value);
220
- break;
218
+ return false;
221
219
  }
222
- }
220
+ });
223
221
  return;
224
222
  }
225
223
  set(result, destinationPath, pick(source, sourcePath));
@@ -227,14 +225,6 @@ var extract = (source, mapping) => {
227
225
  return result;
228
226
  };
229
227
 
230
- // src/map.ts
231
- var map = (data, callback, store = {}) => {
232
- each(data, (key, value, path) => {
233
- callback(key, value, store, path);
234
- });
235
- return store;
236
- };
237
-
238
228
  // src/helpers/isPlainObject.ts
239
229
  var isPlainObject = (value) => {
240
230
  if (value !== null && typeof value === "object") {
@@ -244,119 +234,136 @@ var isPlainObject = (value) => {
244
234
  return false;
245
235
  };
246
236
 
237
+ // src/map.ts
238
+ var map = (data, callback, { descend, shallow = false } = {}) => {
239
+ const walk = (value, key, path, segments) => {
240
+ const root = key === void 0;
241
+ let mapped = root ? Array.isArray(value) ? [] : {} : value;
242
+ if ((root || Array.isArray(value) || isPlainObject(value)) && (root || shallow === false) && (descend === void 0 || descend({ key, value, path, segments: [...segments] }))) {
243
+ mapped = Array.isArray(value) ? Array(value.length) : {};
244
+ each(value, (key2, value2) => {
245
+ const childPath = createPath(path, key2, Array.isArray(mapped));
246
+ const childSegments = [...segments, key2];
247
+ const result = walk(value2, key2, childPath, childSegments);
248
+ Object.defineProperty(mapped, key2, {
249
+ value: result,
250
+ writable: true,
251
+ enumerable: true,
252
+ configurable: true
253
+ });
254
+ }, { descend: ({ segments: segments2 }) => segments2.length === 0 });
255
+ }
256
+ return key !== void 0 ? callback(key, mapped, path) : mapped;
257
+ };
258
+ return walk(data, void 0, "", []);
259
+ };
260
+
247
261
  // src/merge.ts
248
262
  var unsafeKeys = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
249
263
  var merge = (target, ...sources) => {
250
264
  const targetRecord = target;
251
- for (const source of sources) {
252
- if (!isPlainObject(source)) {
253
- continue;
254
- }
255
- for (const [key, sourceValue] of Object.entries(source)) {
256
- if (unsafeKeys.has(key)) {
257
- continue;
258
- }
259
- const targetValue = targetRecord[key];
260
- if (isPlainObject(targetValue) && isPlainObject(sourceValue)) {
261
- merge(targetValue, sourceValue);
262
- } else {
263
- targetRecord[key] = sourceValue;
264
- }
265
+ each(sources, (_index, source) => {
266
+ if (isPlainObject(source)) {
267
+ each(Object.entries(source), (_index2, [key, sourceValue]) => {
268
+ if (unsafeKeys.has(key) === false) {
269
+ const targetValue = targetRecord[key];
270
+ if (isPlainObject(targetValue) && isPlainObject(sourceValue)) {
271
+ merge(targetValue, sourceValue);
272
+ } else {
273
+ targetRecord[key] = sourceValue;
274
+ }
275
+ }
276
+ }, { descend: ({ segments }) => segments.length === 0 });
265
277
  }
266
- }
278
+ }, { descend: ({ segments }) => segments.length === 0 });
267
279
  return target;
268
280
  };
269
281
 
270
282
  // src/flush.ts
271
283
  var flush = (data = {}, path) => {
272
- if (path.length > 0) {
273
- const keys = path.split(".");
274
- const lastKey = keys.pop() ?? "";
275
- const match = lastKey.match(/^(\w+)\[(\d+)\]$/);
276
- let parent = getValueByPath(data, keys.join("."), { inherited: false });
277
- let key = lastKey;
278
- if (match) {
279
- const [, arrayKey, index] = match;
280
- const array = getValueByKey(parent, arrayKey, { inherited: false });
281
- parent = Array.isArray(array) ? array : void 0;
282
- key = index;
283
- }
284
- if (parent !== null && typeof parent === "object" && Object.hasOwn(parent, key)) {
285
- delete parent[key];
284
+ const paths = Array.isArray(path) ? path : [path];
285
+ each(paths, (_key, path2) => {
286
+ if (path2.length > 0) {
287
+ const keys = path2.split(".");
288
+ const lastKey = keys.pop() ?? "";
289
+ const match = lastKey.match(/^(\w+)\[(\d+)\]$/);
290
+ let parent = getValueByPath(data, keys.join("."), { inherited: false });
291
+ let key = lastKey;
292
+ if (match) {
293
+ const [, arrayKey, index] = match;
294
+ const array = getValueByKey(parent, arrayKey, { inherited: false });
295
+ parent = Array.isArray(array) ? array : void 0;
296
+ key = index;
297
+ }
298
+ if (parent !== null && typeof parent === "object" && Object.hasOwn(parent, key)) {
299
+ delete parent[key];
300
+ }
286
301
  }
287
- }
302
+ });
288
303
  return data;
289
304
  };
290
305
 
291
306
  // src/deepEqual.ts
292
307
  var deepEqual = (x, y, store) => {
293
- if (Number.isNaN(x) && Number.isNaN(y)) {
294
- return true;
295
- }
296
- if (x === y) {
308
+ if (x === y || Number.isNaN(x) && Number.isNaN(y)) {
297
309
  return true;
298
310
  }
299
- if (x == null || y == null) {
300
- return false;
301
- }
302
- if (typeof x !== "object" || typeof y !== "object") {
303
- return false;
304
- }
305
- let seen = store.get(x);
306
- if (seen !== void 0 && seen.has(y)) {
307
- return true;
308
- }
309
- if (seen === void 0) {
310
- seen = /* @__PURE__ */ new WeakSet();
311
- store.set(x, seen);
312
- }
313
- seen.add(y);
314
- if (x instanceof Date && y instanceof Date) {
315
- return x.getTime() === y.getTime();
316
- }
317
- if (x instanceof RegExp && y instanceof RegExp) {
318
- return x.toString() === y.toString();
319
- }
320
- const isArrayX = Array.isArray(x);
321
- const isArrayY = Array.isArray(y);
322
- if (isArrayX !== isArrayY) {
323
- return false;
324
- }
325
- if (isArrayX) {
326
- return equalArrays(x, y, store);
327
- }
328
- return equalObjects(x, y, store);
329
- };
330
- var equalArrays = (x, y, store) => x.length === y.length && x.every((value, index) => deepEqual(value, y[index], store));
331
- var equalObjects = (x, y, store) => {
332
- const keysX = Reflect.ownKeys(x);
333
- const keysY = Reflect.ownKeys(y);
334
- if (keysX.length !== keysY.length) {
335
- return false;
336
- }
337
- return keysX.every((key) => {
338
- if (!Object.hasOwn(y, key)) {
339
- return false;
311
+ if (x !== null && y !== null && typeof x === "object" && typeof y === "object") {
312
+ let seen = store.get(x);
313
+ if (seen !== void 0 && seen.has(y)) {
314
+ return true;
340
315
  }
341
- return deepEqual(x[key], y[key], store);
342
- });
316
+ if (seen === void 0) {
317
+ seen = /* @__PURE__ */ new WeakSet();
318
+ store.set(x, seen);
319
+ }
320
+ seen.add(y);
321
+ if (x instanceof Date || y instanceof Date) {
322
+ return x instanceof Date && y instanceof Date && x.getTime() === y.getTime();
323
+ }
324
+ if (x instanceof RegExp || y instanceof RegExp) {
325
+ return x instanceof RegExp && y instanceof RegExp && x.toString() === y.toString();
326
+ }
327
+ if (Array.isArray(x) && Array.isArray(y)) {
328
+ const { length } = x;
329
+ let equal = length === y.length;
330
+ let index = 0;
331
+ while (equal && index < length) {
332
+ equal = deepEqual(x[index], y[index], store);
333
+ index += 1;
334
+ }
335
+ return equal;
336
+ } else if (Array.isArray(x) === false && Array.isArray(y) === false) {
337
+ const keysX = Reflect.ownKeys(x);
338
+ const keysY = Reflect.ownKeys(y);
339
+ return keysX.length === keysY.length && keysX.every(
340
+ (key) => Object.hasOwn(y, key) && deepEqual(x[key], y[key], store)
341
+ );
342
+ }
343
+ }
344
+ return false;
343
345
  };
344
346
 
345
347
  // src/equally.ts
346
- var equally = (a, b) => deepEqual(a, b, /* @__PURE__ */ new WeakMap());
348
+ var equally = (a, b, paths) => {
349
+ if (paths !== void 0) {
350
+ return paths.every((path) => equally(getValueByPath(a, path), getValueByPath(b, path)));
351
+ }
352
+ return deepEqual(a, b, /* @__PURE__ */ new WeakMap());
353
+ };
347
354
 
348
355
  // src/diff.ts
349
356
  var diff = (first, last) => {
350
357
  const operations = [];
351
358
  const frames = [];
352
359
  const finish = (depth) => {
353
- for (const { first: first2, last: last2, path } of frames.splice(depth).reverse()) {
354
- for (const key of Object.keys(first2)) {
360
+ each(frames.splice(depth).reverse(), (_index, { first: first2, last: last2, path }) => {
361
+ each(Object.keys(first2), (_index2, key) => {
355
362
  if (Object.prototype.propertyIsEnumerable.call(last2, key) === false) {
356
363
  operations.push({ type: "delete", path: [...path, key] });
357
364
  }
358
- }
359
- }
365
+ });
366
+ }, { descend: ({ segments }) => segments.length === 0 });
360
367
  return frames.at(-1);
361
368
  };
362
369
  let descend = false;
@@ -407,9 +414,9 @@ var clone = (value) => {
407
414
  }
408
415
  const result = {};
409
416
  store.set(obj, result);
410
- for (const key of Reflect.ownKeys(obj)) {
417
+ each(Reflect.ownKeys(obj), (_index, key) => {
411
418
  result[key] = cloneValue(obj[key]);
412
- }
419
+ });
413
420
  return result;
414
421
  };
415
422
  return cloneValue(value);
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: any, path: string, segments: WalkKey[]) => void;
26
+ type EachCallback<TKey extends WalkKey | undefined = WalkKey> = (key: TKey, value: any, path: string, segments: WalkKey[]) => unknown;
27
27
  type EachEntry = {
28
28
  key: WalkKey | undefined;
29
29
  value: any;
@@ -48,17 +48,32 @@ declare const pick: (data?: ObjwalkObject$1, path?: string, options?: PickOption
48
48
  type ExtractMapping = Record<string, string | string[]>;
49
49
  declare const extract: (source: ObjwalkObject$1, mapping: ExtractMapping) => ObjwalkObject$1;
50
50
 
51
- type MapCallback<TStore extends Record<string, any> = Record<string, any>> = (key: WalkKey, value: any, store: TStore, path: string) => void;
52
- declare const map: <TStore extends Record<string, any> = Record<string, any>>(data: any, callback: MapCallback<TStore>, store?: TStore) => TStore;
51
+ type MapCallback<TResult = unknown, TKey extends WalkKey = WalkKey> = (key: TKey, value: any, path: string) => TResult;
52
+ type MapOptions = {
53
+ descend?: EachOptions['descend'];
54
+ shallow?: boolean;
55
+ };
56
+ type Map = {
57
+ <TResult>(data: readonly unknown[], callback: MapCallback<TResult, number>, options: MapOptions & {
58
+ shallow: true;
59
+ }): TResult[];
60
+ <TResult>(data: Record<string, unknown>, callback: MapCallback<TResult, string>, options: MapOptions & {
61
+ shallow: true;
62
+ }): Record<string, TResult>;
63
+ <TResult>(data: readonly unknown[], callback: MapCallback<TResult>, options?: MapOptions): TResult[];
64
+ <TResult>(data: Record<string, unknown>, callback: MapCallback<TResult>, options?: MapOptions): Record<string, TResult>;
65
+ <TResult>(data: Record<string, unknown> | readonly unknown[], callback: MapCallback<TResult>, options?: MapOptions): Record<string, TResult> | TResult[];
66
+ };
67
+ declare const map: Map;
53
68
 
54
69
  declare const merge: <T extends ObjwalkObject$1>(target: T, ...sources: unknown[]) => T;
55
70
 
56
71
  type ObjwalkObject = Record<string, any>;
57
72
  declare const set: (data: ObjwalkObject | undefined, path: string, value: any) => ObjwalkObject;
58
73
 
59
- declare const flush: (data: ObjwalkObject$1 | undefined, path: string) => ObjwalkObject$1;
74
+ declare const flush: (data: ObjwalkObject$1 | undefined, path: string | string[]) => ObjwalkObject$1;
60
75
 
61
- declare const equally: (a: unknown, b: unknown) => boolean;
76
+ declare const equally: (a: unknown, b: unknown, paths?: string[]) => boolean;
62
77
 
63
78
  declare const diff: (first: unknown, last: unknown) => DiffOperation[];
64
79
 
@@ -68,4 +83,4 @@ declare const parse: (raw: unknown, { fallback, onError, reviver }?: ParseOption
68
83
 
69
84
  declare const stringify: (value: unknown, { fallback, onError, replacer, space }?: StringifyOptions) => string | undefined;
70
85
 
71
- export { type DiffOperation, type EachCallback, type EachEntry, type EachOptions, type ExtractMapping, type MapCallback, type ObjwalkObject$1 as ObjwalkObject, type ParseOptions, type PickOptions, type StringifyOptions, type WalkKey, clone, diff, each, equally, extract, flush, map, merge, parse, pick, set, stringify };
86
+ export { type DiffOperation, type EachCallback, type EachEntry, type EachOptions, type ExtractMapping, type MapCallback, type MapOptions, type ObjwalkObject$1 as ObjwalkObject, type ParseOptions, type PickOptions, type StringifyOptions, type WalkKey, clone, diff, each, equally, extract, flush, map, merge, parse, pick, set, stringify };
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: any, path: string, segments: WalkKey[]) => void;
26
+ type EachCallback<TKey extends WalkKey | undefined = WalkKey> = (key: TKey, value: any, path: string, segments: WalkKey[]) => unknown;
27
27
  type EachEntry = {
28
28
  key: WalkKey | undefined;
29
29
  value: any;
@@ -48,17 +48,32 @@ declare const pick: (data?: ObjwalkObject$1, path?: string, options?: PickOption
48
48
  type ExtractMapping = Record<string, string | string[]>;
49
49
  declare const extract: (source: ObjwalkObject$1, mapping: ExtractMapping) => ObjwalkObject$1;
50
50
 
51
- type MapCallback<TStore extends Record<string, any> = Record<string, any>> = (key: WalkKey, value: any, store: TStore, path: string) => void;
52
- declare const map: <TStore extends Record<string, any> = Record<string, any>>(data: any, callback: MapCallback<TStore>, store?: TStore) => TStore;
51
+ type MapCallback<TResult = unknown, TKey extends WalkKey = WalkKey> = (key: TKey, value: any, path: string) => TResult;
52
+ type MapOptions = {
53
+ descend?: EachOptions['descend'];
54
+ shallow?: boolean;
55
+ };
56
+ type Map = {
57
+ <TResult>(data: readonly unknown[], callback: MapCallback<TResult, number>, options: MapOptions & {
58
+ shallow: true;
59
+ }): TResult[];
60
+ <TResult>(data: Record<string, unknown>, callback: MapCallback<TResult, string>, options: MapOptions & {
61
+ shallow: true;
62
+ }): Record<string, TResult>;
63
+ <TResult>(data: readonly unknown[], callback: MapCallback<TResult>, options?: MapOptions): TResult[];
64
+ <TResult>(data: Record<string, unknown>, callback: MapCallback<TResult>, options?: MapOptions): Record<string, TResult>;
65
+ <TResult>(data: Record<string, unknown> | readonly unknown[], callback: MapCallback<TResult>, options?: MapOptions): Record<string, TResult> | TResult[];
66
+ };
67
+ declare const map: Map;
53
68
 
54
69
  declare const merge: <T extends ObjwalkObject$1>(target: T, ...sources: unknown[]) => T;
55
70
 
56
71
  type ObjwalkObject = Record<string, any>;
57
72
  declare const set: (data: ObjwalkObject | undefined, path: string, value: any) => ObjwalkObject;
58
73
 
59
- declare const flush: (data: ObjwalkObject$1 | undefined, path: string) => ObjwalkObject$1;
74
+ declare const flush: (data: ObjwalkObject$1 | undefined, path: string | string[]) => ObjwalkObject$1;
60
75
 
61
- declare const equally: (a: unknown, b: unknown) => boolean;
76
+ declare const equally: (a: unknown, b: unknown, paths?: string[]) => boolean;
62
77
 
63
78
  declare const diff: (first: unknown, last: unknown) => DiffOperation[];
64
79
 
@@ -68,4 +83,4 @@ declare const parse: (raw: unknown, { fallback, onError, reviver }?: ParseOption
68
83
 
69
84
  declare const stringify: (value: unknown, { fallback, onError, replacer, space }?: StringifyOptions) => string | undefined;
70
85
 
71
- export { type DiffOperation, type EachCallback, type EachEntry, type EachOptions, type ExtractMapping, type MapCallback, type ObjwalkObject$1 as ObjwalkObject, type ParseOptions, type PickOptions, type StringifyOptions, type WalkKey, clone, diff, each, equally, extract, flush, map, merge, parse, pick, set, stringify };
86
+ export { type DiffOperation, type EachCallback, type EachEntry, type EachOptions, type ExtractMapping, type MapCallback, type MapOptions, type ObjwalkObject$1 as ObjwalkObject, type ParseOptions, type PickOptions, type StringifyOptions, type WalkKey, clone, diff, each, equally, extract, flush, map, merge, parse, pick, set, stringify };