objwalk 0.2.0 → 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/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026 Sergey Khalilov
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15
+ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md CHANGED
@@ -13,7 +13,7 @@ npm install objwalk
13
13
  ## Usage
14
14
 
15
15
  ```ts
16
- import { each, extract, map, pick, set } from 'objwalk'
16
+ import { each, extract, map, merge, pick, set } from 'objwalk'
17
17
  ```
18
18
 
19
19
  ## pick
@@ -81,6 +81,21 @@ set(data, 'items[0].title', 'First')
81
81
 
82
82
  `set` mutates the object passed to it and returns the same object.
83
83
 
84
+ ## merge
85
+
86
+ Deeply merge plain objects into a target object.
87
+
88
+ ```ts
89
+ const target = { user: { name: 'Ada', flags: { admin: false } } }
90
+
91
+ merge(target, { user: { email: 'ada@example.com', flags: { admin: true } } })
92
+ // {
93
+ // user: { name: 'Ada', email: 'ada@example.com', flags: { admin: true } },
94
+ // }
95
+ ```
96
+
97
+ `merge` mutates and returns `target`. Sources are applied from left to right. Arrays and non-plain objects, such as `Date`, replace the existing value rather than being merged.
98
+
84
99
  ## extract
85
100
 
86
101
  Create a new object by mapping destination paths to source paths.
@@ -189,4 +204,5 @@ set(data, path, value)
189
204
  extract(data, mapping)
190
205
  each(data, callback)
191
206
  map(data, callback)
207
+ merge(target, ...sources)
192
208
  ```
package/dist/index.cjs CHANGED
@@ -23,6 +23,7 @@ __export(index_exports, {
23
23
  each: () => each,
24
24
  extract: () => extract,
25
25
  map: () => map,
26
+ merge: () => merge,
26
27
  pick: () => pick,
27
28
  set: () => set
28
29
  });
@@ -230,11 +231,42 @@ var map = (data, callback, store = {}) => {
230
231
  });
231
232
  return store;
232
233
  };
234
+
235
+ // src/merge.ts
236
+ var unsafeKeys = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
237
+ var isPlainObject = (value) => {
238
+ if (value === null || typeof value !== "object") {
239
+ return false;
240
+ }
241
+ const prototype = Object.getPrototypeOf(value);
242
+ return prototype === Object.prototype || prototype === null;
243
+ };
244
+ var merge = (target, ...sources) => {
245
+ const targetRecord = target;
246
+ for (const source of sources) {
247
+ if (!isPlainObject(source)) {
248
+ continue;
249
+ }
250
+ for (const [key, sourceValue] of Object.entries(source)) {
251
+ if (unsafeKeys.has(key)) {
252
+ continue;
253
+ }
254
+ const targetValue = targetRecord[key];
255
+ if (isPlainObject(targetValue) && isPlainObject(sourceValue)) {
256
+ merge(targetValue, sourceValue);
257
+ } else {
258
+ targetRecord[key] = sourceValue;
259
+ }
260
+ }
261
+ }
262
+ return target;
263
+ };
233
264
  // Annotate the CommonJS export names for ESM import in node:
234
265
  0 && (module.exports = {
235
266
  each,
236
267
  extract,
237
268
  map,
269
+ merge,
238
270
  pick,
239
271
  set
240
272
  });
package/dist/index.d.cts CHANGED
@@ -12,7 +12,9 @@ declare const extract: (source: ObjwalkObject$1, mapping: ExtractMapping) => Obj
12
12
  type MapCallback<TStore extends Record<string, any> = Record<string, any>> = (key: WalkKey, value: any, store: TStore, path: string) => void;
13
13
  declare const map: <TStore extends Record<string, any> = Record<string, any>>(data: any, callback: MapCallback<TStore>, store?: TStore) => TStore;
14
14
 
15
+ declare const merge: <T extends ObjwalkObject$1>(target: T, ...sources: unknown[]) => T;
16
+
15
17
  type ObjwalkObject = Record<string, any>;
16
18
  declare const set: (data: ObjwalkObject | undefined, path: string, value: any) => ObjwalkObject;
17
19
 
18
- export { type EachCallback, type ExtractMapping, type MapCallback, type ObjwalkObject$1 as ObjwalkObject, type WalkKey, each, extract, map, pick, set };
20
+ export { type EachCallback, type ExtractMapping, type MapCallback, type ObjwalkObject$1 as ObjwalkObject, type WalkKey, each, extract, map, merge, pick, set };
package/dist/index.d.ts CHANGED
@@ -12,7 +12,9 @@ declare const extract: (source: ObjwalkObject$1, mapping: ExtractMapping) => Obj
12
12
  type MapCallback<TStore extends Record<string, any> = Record<string, any>> = (key: WalkKey, value: any, store: TStore, path: string) => void;
13
13
  declare const map: <TStore extends Record<string, any> = Record<string, any>>(data: any, callback: MapCallback<TStore>, store?: TStore) => TStore;
14
14
 
15
+ declare const merge: <T extends ObjwalkObject$1>(target: T, ...sources: unknown[]) => T;
16
+
15
17
  type ObjwalkObject = Record<string, any>;
16
18
  declare const set: (data: ObjwalkObject | undefined, path: string, value: any) => ObjwalkObject;
17
19
 
18
- export { type EachCallback, type ExtractMapping, type MapCallback, type ObjwalkObject$1 as ObjwalkObject, type WalkKey, each, extract, map, pick, set };
20
+ export { type EachCallback, type ExtractMapping, type MapCallback, type ObjwalkObject$1 as ObjwalkObject, type WalkKey, each, extract, map, merge, pick, set };
package/dist/index.js CHANGED
@@ -200,10 +200,41 @@ var map = (data, callback, store = {}) => {
200
200
  });
201
201
  return store;
202
202
  };
203
+
204
+ // src/merge.ts
205
+ var unsafeKeys = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
206
+ var isPlainObject = (value) => {
207
+ if (value === null || typeof value !== "object") {
208
+ return false;
209
+ }
210
+ const prototype = Object.getPrototypeOf(value);
211
+ return prototype === Object.prototype || prototype === null;
212
+ };
213
+ var merge = (target, ...sources) => {
214
+ const targetRecord = target;
215
+ for (const source of sources) {
216
+ if (!isPlainObject(source)) {
217
+ continue;
218
+ }
219
+ for (const [key, sourceValue] of Object.entries(source)) {
220
+ if (unsafeKeys.has(key)) {
221
+ continue;
222
+ }
223
+ const targetValue = targetRecord[key];
224
+ if (isPlainObject(targetValue) && isPlainObject(sourceValue)) {
225
+ merge(targetValue, sourceValue);
226
+ } else {
227
+ targetRecord[key] = sourceValue;
228
+ }
229
+ }
230
+ }
231
+ return target;
232
+ };
203
233
  export {
204
234
  each,
205
235
  extract,
206
236
  map,
237
+ merge,
207
238
  pick,
208
239
  set
209
240
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "objwalk",
3
- "version": "0.2.0",
3
+ "version": "1.0.0",
4
4
  "description": "Small utilities for reading, writing, walking, and reshaping nested JavaScript objects.",
5
5
  "keywords": [
6
6
  "object",