@takeshape/util 11.178.0 → 11.180.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.
@@ -9,4 +9,10 @@ export declare function mergeWithArrayConcat<TObject, TSource>(object: TObject,
9
9
  */
10
10
  export declare function mergeWithArrayMerge<TObject, TSource>(object: TObject, source: TSource): TObject & TSource;
11
11
  export declare function rebaseObject<T extends Record<string, unknown>>(to: T, base: T, from: T): T;
12
+ /**
13
+ * Deep merge two objects. Properties from `source` are merged into `target`.
14
+ * `null` values in `source` act as delete sentinels — the corresponding key
15
+ * is removed from the result. Arrays are replaced, not merged.
16
+ */
17
+ export declare function deepMergeWithNullRemoval<T extends object>(target: T, source: Record<string, unknown>): T;
12
18
  export declare function rebaseArray(to: string[], base: string[], from: string[]): string[];
@@ -2,6 +2,7 @@ import difference from 'lodash/difference.js';
2
2
  import isArray from 'lodash/isArray.js';
3
3
  import isEqual from 'lodash/isEqual.js';
4
4
  import isNull from 'lodash/isNull.js';
5
+ import isPlainObject from 'lodash/isPlainObject.js';
5
6
  import merge from 'lodash/merge.js';
6
7
  import mergeWith from 'lodash/mergeWith.js';
7
8
  import omit from 'lodash/omit.js';
@@ -47,6 +48,37 @@ export function rebaseObject(to, base, from) {
47
48
  }
48
49
  return newObj;
49
50
  }
51
+ /**
52
+ * Deep merge two objects. Properties from `source` are merged into `target`.
53
+ * `null` values in `source` act as delete sentinels — the corresponding key
54
+ * is removed from the result. Arrays are replaced, not merged.
55
+ */
56
+ export function deepMergeWithNullRemoval(target, source) {
57
+ const targetRecord = target;
58
+ const sourceRecord = source;
59
+ const result = {};
60
+ // Copy target keys, skipping any that source sets to null
61
+ for (const key of Object.keys(targetRecord)) {
62
+ if (key in sourceRecord && sourceRecord[key] === null) {
63
+ continue;
64
+ }
65
+ result[key] = targetRecord[key];
66
+ }
67
+ // Apply source on top (excluding nulls)
68
+ for (const key of Object.keys(sourceRecord)) {
69
+ const srcValue = sourceRecord[key];
70
+ if (srcValue === null) {
71
+ continue;
72
+ }
73
+ if (isPlainObject(srcValue) && isPlainObject(result[key])) {
74
+ result[key] = deepMergeWithNullRemoval(result[key], srcValue);
75
+ }
76
+ else {
77
+ result[key] = srcValue;
78
+ }
79
+ }
80
+ return result;
81
+ }
50
82
  export function rebaseArray(to, base, from) {
51
83
  const removed = difference(base, from);
52
84
  const added = difference(from, base);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takeshape/util",
3
- "version": "11.178.0",
3
+ "version": "11.180.0",
4
4
  "description": "Shared utilities",
5
5
  "homepage": "https://www.takeshape.io",
6
6
  "repository": {
@@ -45,8 +45,8 @@
45
45
  "tiny-invariant": "1.3.3",
46
46
  "uint8array-extras": "1.4.0",
47
47
  "url-parse": "1.5.3",
48
- "@takeshape/prism": "11.178.0",
49
- "@takeshape/routing": "11.178.0"
48
+ "@takeshape/prism": "11.180.0",
49
+ "@takeshape/routing": "11.180.0"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/classnames": "2.2.11",