@jsopen/objects 1.2.0 → 1.3.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 CHANGED
@@ -1,6 +1,6 @@
1
- # v1.2.0
2
- [2024-11-21]
1
+ # v1.3.0
2
+ [2024-11-22]
3
3
 
4
4
  ### Changes
5
5
 
6
- * feat: Added isConstructor, isIterable and isAsyncIterable type guards ([`b2251c1`](https://github.com/panates/jsopen-objects/commit/b2251c1a780a632d7eaf8bd8e7f3205f73c43c52))
6
+ * feat: Added ability to merge non plain objects ([`3d32279`](https://github.com/panates/jsopen-objects/commit/3d3227998dbd8b345c24f4d7a0d9ab9bc3cd7b52))
package/cjs/merge.js CHANGED
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.merge = merge;
4
4
  exports.getMergeFunction = getMergeFunction;
5
5
  const is_object_js_1 = require("./is-object.js");
6
+ const type_guards_js_1 = require("./type-guards.js");
6
7
  function merge(target, source, options) {
7
8
  if (!((0, is_object_js_1.isObject)(target) || typeof target === 'function')) {
8
9
  throw new TypeError('"target" argument must be an object');
@@ -12,7 +13,7 @@ function merge(target, source, options) {
12
13
  throw new TypeError('"target" argument must be an object');
13
14
  }
14
15
  const fn = getMergeFunction(options);
15
- return fn(target, source, '', options, fn, is_object_js_1.isPlainObject, is_object_js_1.isObject, arrayClone);
16
+ return fn(target, source, '', options, fn, type_guards_js_1.isBuiltIn, is_object_js_1.isObject, is_object_js_1.isPlainObject, arrayClone);
16
17
  }
17
18
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
18
19
  const functionCache = new Map();
@@ -49,14 +50,15 @@ function buildMerge(options) {
49
50
  'curPath',
50
51
  'options',
51
52
  'mergeFunction',
52
- 'isPlainObject',
53
+ 'isBuiltIn',
53
54
  'isObject',
55
+ 'isPlainObject',
54
56
  'arrayClone',
55
57
  ];
56
58
  const scriptL0 = [
57
59
  `
58
60
  const _merge = (_trgVal, _srcVal, _curPath) =>
59
- mergeFunction(_trgVal, _srcVal, _curPath, options, mergeFunction, isPlainObject, isObject, arrayClone);
61
+ mergeFunction(_trgVal, _srcVal, _curPath, options, mergeFunction, isBuiltIn, isObject, isPlainObject, arrayClone);
60
62
  const keys = Object.getOwnPropertyNames(source);
61
63
  keys.push(...Object.getOwnPropertySymbols(source));
62
64
  let key;
@@ -66,7 +68,7 @@ let trgVal;
66
68
  `,
67
69
  ];
68
70
  if (options?.deep) {
69
- scriptL0.push(`let subPath;`, `let _isPlain;`, `let _isArray;`);
71
+ scriptL0.push(`let subPath;`, `let _isArray;`);
70
72
  if (typeof options?.deep === 'function') {
71
73
  scriptL0.push(`const deepCallback = options.deep;`);
72
74
  }
@@ -84,6 +86,7 @@ let trgVal;
84
86
  scriptL0.push(`const moveArraysCallback = options.moveArrays;`);
85
87
  }
86
88
  scriptL0.push(`
89
+ if (isPlainObject(target)) Object.setPrototypeOf(target, Object.getPrototypeOf(source));
87
90
  let i = 0;
88
91
  const len = keys.length;
89
92
  for (i = 0; i < len; i++) {
@@ -133,7 +136,7 @@ if (
133
136
  srcVal = source[key];`);
134
137
  }
135
138
  else {
136
- scriptL1For.push(`descriptor = {enumerable: true, configurable: true, writable: true}`, `srcVal = source[key];`);
139
+ scriptL1For.push(`descriptor = {enumerable: true, configurable: true, writable: true}`, `srcVal = source[key];`);
137
140
  }
138
141
  /** ************* keepExisting *****************/
139
142
  if (options?.keepExisting) {
@@ -147,36 +150,32 @@ if (
147
150
  if (options?.ignoreNulls) {
148
151
  scriptL1For.push(`if (srcVal === null) continue;`);
149
152
  }
153
+ const deepArray = !options?.moveArrays || typeof options?.moveArrays === 'function';
150
154
  /** ************* deep *****************/
151
155
  if (options?.deep) {
152
- scriptL1For.push(`
153
- _isPlain = isPlainObject(srcVal);
156
+ if (deepArray) {
157
+ scriptL1For.push(`
154
158
  _isArray = Array.isArray(srcVal);
155
- if (_isPlain || _isArray) {`);
159
+ if (_isArray || (typeof srcVal === 'object' && !isBuiltIn(srcVal))) {`);
160
+ }
161
+ else {
162
+ scriptL1For.push(`
163
+ if (typeof srcVal === 'object' && !isBuiltIn(srcVal)) {
164
+ subPath = curPath + (curPath ? '.' : '') + key;`);
165
+ }
166
+ scriptL1For.push(`subPath = curPath + (curPath ? '.' : '') + key;`);
156
167
  const scriptL2Deep = [];
157
168
  scriptL1For.push(scriptL2Deep);
158
169
  scriptL1For.push('}');
159
170
  let scriptL3Deep = scriptL2Deep;
160
171
  if (typeof options?.deep === 'function') {
161
172
  scriptL2Deep.push(`
162
- subPath = curPath + (curPath ? '.' : '') + key;
163
173
  if (deepCallback(key, subPath, target, source)) {`);
164
174
  scriptL3Deep = [];
165
175
  scriptL2Deep.push(scriptL3Deep);
166
176
  scriptL2Deep.push('}');
167
177
  }
168
- /** ************* _isPlain *****************/
169
- scriptL3Deep.push(`
170
- if (_isPlain) {
171
- trgVal = target[key];
172
- if (!isObject(trgVal)) {
173
- descriptor.value = trgVal = {};
174
- Object.defineProperty(target, key, descriptor);
175
- }
176
- _merge(trgVal, srcVal, subPath, options);
177
- continue;
178
- }`);
179
- /** ************* moveArrays *****************/
178
+ /** ************* Array *****************/
180
179
  if (!options?.moveArrays || typeof options?.moveArrays === 'function') {
181
180
  scriptL3Deep.push(`if (_isArray) {`);
182
181
  const scriptL4IsArray = [];
@@ -184,7 +183,12 @@ if (_isPlain) {
184
183
  scriptL3Deep.push('}');
185
184
  let scriptL5CloneArrays = scriptL4IsArray;
186
185
  if (typeof options?.moveArrays === 'function') {
187
- scriptL4IsArray.push(`if (!moveArraysCallback(key, subPath, target, source)) {`);
186
+ scriptL4IsArray.push(`
187
+ if (moveArraysCallback(key, subPath, target, source)) {
188
+ descriptor.value = srcVal;
189
+ Object.defineProperty(target, key, descriptor);
190
+ continue;
191
+ } else {`);
188
192
  scriptL5CloneArrays = [];
189
193
  scriptL4IsArray.push(scriptL5CloneArrays);
190
194
  scriptL4IsArray.push('}');
@@ -195,6 +199,15 @@ Object.defineProperty(target, key, descriptor);
195
199
  continue;
196
200
  `);
197
201
  }
202
+ /** ************* object *****************/
203
+ scriptL3Deep.push(`
204
+ trgVal = target[key];
205
+ if (!isObject(trgVal)) {
206
+ descriptor.value = trgVal = {};
207
+ Object.defineProperty(target, key, descriptor);
208
+ }
209
+ _merge(trgVal, srcVal, subPath, options);
210
+ continue;`);
198
211
  }
199
212
  /** ************* finalize *****************/
200
213
  scriptL1For.push(`
@@ -209,7 +222,7 @@ function arrayClone(arr, _merge, curPath) {
209
222
  return arr.map((x) => {
210
223
  if (Array.isArray(x))
211
224
  return arrayClone(x, _merge, curPath);
212
- if ((0, is_object_js_1.isPlainObject)(x))
225
+ if (typeof x === 'object' && !(0, type_guards_js_1.isBuiltIn)(x))
213
226
  return _merge({}, x, curPath);
214
227
  return x;
215
228
  });
package/esm/merge.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { isObject, isPlainObject } from './is-object.js';
2
+ import { isBuiltIn } from './type-guards.js';
2
3
  export function merge(target, source, options) {
3
4
  if (!(isObject(target) || typeof target === 'function')) {
4
5
  throw new TypeError('"target" argument must be an object');
@@ -8,7 +9,7 @@ export function merge(target, source, options) {
8
9
  throw new TypeError('"target" argument must be an object');
9
10
  }
10
11
  const fn = getMergeFunction(options);
11
- return fn(target, source, '', options, fn, isPlainObject, isObject, arrayClone);
12
+ return fn(target, source, '', options, fn, isBuiltIn, isObject, isPlainObject, arrayClone);
12
13
  }
13
14
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
14
15
  const functionCache = new Map();
@@ -45,14 +46,15 @@ function buildMerge(options) {
45
46
  'curPath',
46
47
  'options',
47
48
  'mergeFunction',
48
- 'isPlainObject',
49
+ 'isBuiltIn',
49
50
  'isObject',
51
+ 'isPlainObject',
50
52
  'arrayClone',
51
53
  ];
52
54
  const scriptL0 = [
53
55
  `
54
56
  const _merge = (_trgVal, _srcVal, _curPath) =>
55
- mergeFunction(_trgVal, _srcVal, _curPath, options, mergeFunction, isPlainObject, isObject, arrayClone);
57
+ mergeFunction(_trgVal, _srcVal, _curPath, options, mergeFunction, isBuiltIn, isObject, isPlainObject, arrayClone);
56
58
  const keys = Object.getOwnPropertyNames(source);
57
59
  keys.push(...Object.getOwnPropertySymbols(source));
58
60
  let key;
@@ -62,7 +64,7 @@ let trgVal;
62
64
  `,
63
65
  ];
64
66
  if (options?.deep) {
65
- scriptL0.push(`let subPath;`, `let _isPlain;`, `let _isArray;`);
67
+ scriptL0.push(`let subPath;`, `let _isArray;`);
66
68
  if (typeof options?.deep === 'function') {
67
69
  scriptL0.push(`const deepCallback = options.deep;`);
68
70
  }
@@ -80,6 +82,7 @@ let trgVal;
80
82
  scriptL0.push(`const moveArraysCallback = options.moveArrays;`);
81
83
  }
82
84
  scriptL0.push(`
85
+ if (isPlainObject(target)) Object.setPrototypeOf(target, Object.getPrototypeOf(source));
83
86
  let i = 0;
84
87
  const len = keys.length;
85
88
  for (i = 0; i < len; i++) {
@@ -129,7 +132,7 @@ if (
129
132
  srcVal = source[key];`);
130
133
  }
131
134
  else {
132
- scriptL1For.push(`descriptor = {enumerable: true, configurable: true, writable: true}`, `srcVal = source[key];`);
135
+ scriptL1For.push(`descriptor = {enumerable: true, configurable: true, writable: true}`, `srcVal = source[key];`);
133
136
  }
134
137
  /** ************* keepExisting *****************/
135
138
  if (options?.keepExisting) {
@@ -143,36 +146,32 @@ if (
143
146
  if (options?.ignoreNulls) {
144
147
  scriptL1For.push(`if (srcVal === null) continue;`);
145
148
  }
149
+ const deepArray = !options?.moveArrays || typeof options?.moveArrays === 'function';
146
150
  /** ************* deep *****************/
147
151
  if (options?.deep) {
148
- scriptL1For.push(`
149
- _isPlain = isPlainObject(srcVal);
152
+ if (deepArray) {
153
+ scriptL1For.push(`
150
154
  _isArray = Array.isArray(srcVal);
151
- if (_isPlain || _isArray) {`);
155
+ if (_isArray || (typeof srcVal === 'object' && !isBuiltIn(srcVal))) {`);
156
+ }
157
+ else {
158
+ scriptL1For.push(`
159
+ if (typeof srcVal === 'object' && !isBuiltIn(srcVal)) {
160
+ subPath = curPath + (curPath ? '.' : '') + key;`);
161
+ }
162
+ scriptL1For.push(`subPath = curPath + (curPath ? '.' : '') + key;`);
152
163
  const scriptL2Deep = [];
153
164
  scriptL1For.push(scriptL2Deep);
154
165
  scriptL1For.push('}');
155
166
  let scriptL3Deep = scriptL2Deep;
156
167
  if (typeof options?.deep === 'function') {
157
168
  scriptL2Deep.push(`
158
- subPath = curPath + (curPath ? '.' : '') + key;
159
169
  if (deepCallback(key, subPath, target, source)) {`);
160
170
  scriptL3Deep = [];
161
171
  scriptL2Deep.push(scriptL3Deep);
162
172
  scriptL2Deep.push('}');
163
173
  }
164
- /** ************* _isPlain *****************/
165
- scriptL3Deep.push(`
166
- if (_isPlain) {
167
- trgVal = target[key];
168
- if (!isObject(trgVal)) {
169
- descriptor.value = trgVal = {};
170
- Object.defineProperty(target, key, descriptor);
171
- }
172
- _merge(trgVal, srcVal, subPath, options);
173
- continue;
174
- }`);
175
- /** ************* moveArrays *****************/
174
+ /** ************* Array *****************/
176
175
  if (!options?.moveArrays || typeof options?.moveArrays === 'function') {
177
176
  scriptL3Deep.push(`if (_isArray) {`);
178
177
  const scriptL4IsArray = [];
@@ -180,7 +179,12 @@ if (_isPlain) {
180
179
  scriptL3Deep.push('}');
181
180
  let scriptL5CloneArrays = scriptL4IsArray;
182
181
  if (typeof options?.moveArrays === 'function') {
183
- scriptL4IsArray.push(`if (!moveArraysCallback(key, subPath, target, source)) {`);
182
+ scriptL4IsArray.push(`
183
+ if (moveArraysCallback(key, subPath, target, source)) {
184
+ descriptor.value = srcVal;
185
+ Object.defineProperty(target, key, descriptor);
186
+ continue;
187
+ } else {`);
184
188
  scriptL5CloneArrays = [];
185
189
  scriptL4IsArray.push(scriptL5CloneArrays);
186
190
  scriptL4IsArray.push('}');
@@ -191,6 +195,15 @@ Object.defineProperty(target, key, descriptor);
191
195
  continue;
192
196
  `);
193
197
  }
198
+ /** ************* object *****************/
199
+ scriptL3Deep.push(`
200
+ trgVal = target[key];
201
+ if (!isObject(trgVal)) {
202
+ descriptor.value = trgVal = {};
203
+ Object.defineProperty(target, key, descriptor);
204
+ }
205
+ _merge(trgVal, srcVal, subPath, options);
206
+ continue;`);
194
207
  }
195
208
  /** ************* finalize *****************/
196
209
  scriptL1For.push(`
@@ -205,7 +218,7 @@ function arrayClone(arr, _merge, curPath) {
205
218
  return arr.map((x) => {
206
219
  if (Array.isArray(x))
207
220
  return arrayClone(x, _merge, curPath);
208
- if (isPlainObject(x))
221
+ if (typeof x === 'object' && !isBuiltIn(x))
209
222
  return _merge({}, x, curPath);
210
223
  return x;
211
224
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jsopen/objects",
3
3
  "description": "Helper utilities for working with JavaScript objects and arrays",
4
- "version": "1.2.0",
4
+ "version": "1.3.0",
5
5
  "author": "Panates",
6
6
  "license": "MIT",
7
7
  "dependencies": {