@cleverbrush/deep 1.1.11 → 3.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/README.md +86 -34
- package/dist/deepExtend.d.ts +20 -0
- package/dist/hashObject.d.ts +11 -1
- package/dist/index.d.ts +2 -10
- package/dist/index.js +2 -9
- package/dist/index.js.map +1 -0
- package/package.json +12 -4
- package/dist/deepEqual.js +0 -90
- package/dist/deepExtend.js +0 -37
- package/dist/deepFlatten.js +0 -41
- package/dist/hashObject.js +0 -44
package/README.md
CHANGED
|
@@ -1,46 +1,66 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @cleverbrush/deep
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://github.com/cleverbrush/framework/actions/workflows/ci.yml)
|
|
4
|
+
[](../../LICENSE)
|
|
5
|
+
<!-- coverage-badge-start -->
|
|
6
|
+

|
|
7
|
+
<!-- coverage-badge-end -->
|
|
8
|
+
|
|
9
|
+
A library for deep operations on JavaScript objects — deep equality, deep merge, and flattening.
|
|
4
10
|
|
|
5
11
|
## Installation
|
|
6
12
|
|
|
7
|
-
|
|
13
|
+
```bash
|
|
14
|
+
npm install @cleverbrush/deep
|
|
15
|
+
```
|
|
8
16
|
|
|
9
17
|
## Usage
|
|
10
18
|
|
|
11
19
|
```typescript
|
|
12
|
-
import
|
|
13
|
-
// or import functions individually
|
|
14
|
-
import { deepEqual, deepExtend } from '@cleverbrush/deep';
|
|
20
|
+
import { deepEqual, deepExtend, deepFlatten } from '@cleverbrush/deep';
|
|
15
21
|
```
|
|
16
22
|
|
|
17
|
-
##
|
|
23
|
+
## API
|
|
24
|
+
|
|
25
|
+
### `deepEqual(a, b, options?)`
|
|
26
|
+
|
|
27
|
+
Recursively compares two values and returns `true` if they are deeply equal. Supports nested objects, arrays, `Date` instances, and handles circular references.
|
|
18
28
|
|
|
19
|
-
|
|
29
|
+
**Parameters:**
|
|
20
30
|
|
|
21
|
-
|
|
31
|
+
| Name | Type | Default | Description |
|
|
32
|
+
| --- | --- | --- | --- |
|
|
33
|
+
| `a` | `any` | — | First value |
|
|
34
|
+
| `b` | `any` | — | Second value |
|
|
35
|
+
| `options.disregardArrayOrder` | `boolean` | `false` | When `true`, arrays are treated as equal regardless of element order |
|
|
22
36
|
|
|
23
37
|
```typescript
|
|
24
38
|
import { deepEqual } from '@cleverbrush/deep';
|
|
25
39
|
|
|
26
|
-
|
|
27
|
-
//
|
|
40
|
+
deepEqual({ a: { b: 1 } }, { a: { b: 1 } });
|
|
41
|
+
// => true
|
|
28
42
|
|
|
29
|
-
|
|
30
|
-
//
|
|
43
|
+
deepEqual({ a: { b: 1 } }, { a: { b: 20 } });
|
|
44
|
+
// => false
|
|
31
45
|
|
|
32
|
-
|
|
33
|
-
//
|
|
46
|
+
deepEqual({ a: { b: 1, c: 2 } }, { a: { b: 1 } });
|
|
47
|
+
// => false
|
|
48
|
+
|
|
49
|
+
// Array order can be ignored
|
|
50
|
+
deepEqual([1, 2, 3], [3, 1, 2], { disregardArrayOrder: true });
|
|
51
|
+
// => true
|
|
34
52
|
```
|
|
35
53
|
|
|
36
|
-
### deepExtend
|
|
54
|
+
### `deepExtend(...objects)`
|
|
55
|
+
|
|
56
|
+
Deeply merges multiple objects. Works like `Object.assign`, but recursively merges nested objects instead of overwriting them. All arguments must be non-null objects.
|
|
37
57
|
|
|
38
|
-
|
|
58
|
+
Returns a new object that is the deep merge of all provided objects.
|
|
39
59
|
|
|
40
60
|
```typescript
|
|
41
61
|
import { deepExtend } from '@cleverbrush/deep';
|
|
42
62
|
|
|
43
|
-
deepExtend(
|
|
63
|
+
const result = deepExtend(
|
|
44
64
|
{},
|
|
45
65
|
{
|
|
46
66
|
a: 'something',
|
|
@@ -54,25 +74,30 @@ deepExtend(
|
|
|
54
74
|
}
|
|
55
75
|
}
|
|
56
76
|
);
|
|
77
|
+
|
|
78
|
+
// result:
|
|
79
|
+
// {
|
|
80
|
+
// a: 'something',
|
|
81
|
+
// name: {
|
|
82
|
+
// first: 'Ivan',
|
|
83
|
+
// last: 'Ivanov'
|
|
84
|
+
// }
|
|
85
|
+
// }
|
|
57
86
|
```
|
|
58
87
|
|
|
59
|
-
|
|
88
|
+
The result type is inferred from the input types using the `Merge<T>` utility type, which is also exported from the library.
|
|
60
89
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
name: {
|
|
65
|
-
first: 'Ivan',
|
|
66
|
-
last: 'Ivanov'
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
```
|
|
90
|
+
### `deepFlatten(obj, delimiter?)`
|
|
91
|
+
|
|
92
|
+
Flattens a nested object to a single level, concatenating keys with the specified delimiter.
|
|
70
93
|
|
|
71
|
-
|
|
94
|
+
**Parameters:**
|
|
95
|
+
|
|
96
|
+
| Name | Type | Default | Description |
|
|
97
|
+
| --- | --- | --- | --- |
|
|
98
|
+
| `obj` | `Record<string, any>` | — | Object to flatten |
|
|
99
|
+
| `delimiter` | `string` | `'.'` | Separator used to join nested keys |
|
|
72
100
|
|
|
73
|
-
Flattens an object to a single level. Accepts an optional separator as a second parameter.
|
|
74
|
-
If no separator is provided, the default separator is `.`.
|
|
75
|
-
Supports only objects with string keys. Supports nested objects of any depth.
|
|
76
101
|
Throws an error if the object contains circular references.
|
|
77
102
|
|
|
78
103
|
```typescript
|
|
@@ -85,7 +110,6 @@ deepFlatten({
|
|
|
85
110
|
},
|
|
86
111
|
d: 3
|
|
87
112
|
});
|
|
88
|
-
|
|
89
113
|
// => { 'a.b': 1, 'a.c': 2, d: 3 }
|
|
90
114
|
|
|
91
115
|
deepFlatten(
|
|
@@ -102,6 +126,34 @@ deepFlatten(
|
|
|
102
126
|
},
|
|
103
127
|
'-'
|
|
104
128
|
);
|
|
105
|
-
|
|
106
129
|
// => { 'a-b': 1, 'a-c': 2, 'd-e-f': 3 }
|
|
107
130
|
```
|
|
131
|
+
|
|
132
|
+
### `HashObject(obj, exclude?)`
|
|
133
|
+
|
|
134
|
+
Generates a hash representation for an object. Useful for comparing objects by value.
|
|
135
|
+
|
|
136
|
+
**Parameters:**
|
|
137
|
+
|
|
138
|
+
| Name | Type | Description |
|
|
139
|
+
| --- | --- | --- |
|
|
140
|
+
| `obj` | `any` | The value to hash |
|
|
141
|
+
| `exclude` | `any[]` | Optional list of values to exclude from hashing |
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import { HashObject } from '@cleverbrush/deep';
|
|
145
|
+
|
|
146
|
+
const hash = HashObject({ name: 'John', age: 30 });
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Code Quality
|
|
150
|
+
|
|
151
|
+
- **Linting:** [Biome](https://biomejs.dev/) — enforced on every PR via CI
|
|
152
|
+
- **Type checking:** TypeScript strict mode
|
|
153
|
+
- **Unit tests:** [Vitest](https://vitest.dev/) — covering deep equality edge cases (circular references, `Date` instances, array order), deep merge, flattening, and hashing
|
|
154
|
+
- **CI:** Every pull request must pass lint + build + test before merge — see [`.github/workflows/ci.yml`](../../.github/workflows/ci.yml)
|
|
155
|
+
|
|
156
|
+
## License
|
|
157
|
+
|
|
158
|
+
BSD-3-Clause
|
|
159
|
+
|
package/dist/deepExtend.d.ts
CHANGED
|
@@ -1,9 +1,29 @@
|
|
|
1
|
+
/** Properties that exist in both `T1` and `T2`, typed as `T2`'s version. */
|
|
1
2
|
export type CommonProps<T1, T2> = {
|
|
2
3
|
[k in keyof T1 & keyof T2]: T1[k] extends never ? never : T2[k] extends never ? never : T2[k];
|
|
3
4
|
};
|
|
5
|
+
/** Properties present in `T1` but not in `T2`. */
|
|
4
6
|
export type PropsInFirstOnly<T1, T2> = Omit<T1, keyof T2>;
|
|
7
|
+
/** Recursively merges two object types. Matching keys are merged; unique keys are kept. */
|
|
5
8
|
export type MergeTwo<T1, T2> = PropsInFirstOnly<T1, T2> & PropsInFirstOnly<T2, T1> & {
|
|
6
9
|
[k in keyof CommonProps<T1, T2>]: T1[k] extends Record<string, unknown> ? T2[k] extends Record<string, unknown> ? MergeTwo<T1[k], T2[k]> : T2[k] : T2[k];
|
|
7
10
|
};
|
|
11
|
+
/** Recursively merges a tuple of object types from left to right. */
|
|
8
12
|
export type Merge<T extends unknown[]> = T['length'] extends 3 ? MergeTwo<T[0], MergeTwo<T[1], T[2]>> : T['length'] extends 2 ? MergeTwo<T[0], T[1]> : T['length'] extends 1 ? T[0] : T extends [...infer K, infer PL, infer L] ? Merge<[Merge<[...K]>, MergeTwo<PL, L>]> : never;
|
|
13
|
+
/**
|
|
14
|
+
* Deep-merges multiple objects into one. Later values override earlier ones;
|
|
15
|
+
* nested objects are merged recursively rather than replaced.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* const a = { x: 1, nested: { a: true } };
|
|
20
|
+
* const b = { y: 2, nested: { b: false } };
|
|
21
|
+
* const result = deepExtend(a, b);
|
|
22
|
+
* // { x: 1, y: 2, nested: { a: true, b: false } }
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @param args - Two or more non-null objects to merge.
|
|
26
|
+
* @returns A new object containing the deep-merged result.
|
|
27
|
+
* @throws If no arguments are provided or any argument is not a non-null object.
|
|
28
|
+
*/
|
|
9
29
|
export declare const deepExtend: <T extends unknown[]>(...args: T) => Merge<T>;
|
package/dist/hashObject.d.ts
CHANGED
|
@@ -1 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Computes a 32-bit numeric hash for any value.
|
|
3
|
+
*
|
|
4
|
+
* Objects are hashed by recursively hashing their sorted keys and values;
|
|
5
|
+
* circular references are detected via an internal exclusion list.
|
|
6
|
+
*
|
|
7
|
+
* @param unkType - The value to hash (object, string, number, etc.).
|
|
8
|
+
* @param exclude - Internal array used for circular-reference detection.
|
|
9
|
+
* @returns A 32-bit integer hash code.
|
|
10
|
+
*/
|
|
11
|
+
export declare function HashObject(unkType: any, exclude?: any[]): number;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
import { deepEqual } from './deepEqual.js';
|
|
2
|
-
import { deepExtend, type Merge } from './deepExtend.js';
|
|
2
|
+
import { deepExtend, type Merge, type MergeTwo } from './deepExtend.js';
|
|
3
3
|
import { deepFlatten } from './deepFlatten.js';
|
|
4
|
-
export { deepEqual, deepExtend, deepFlatten, type Merge };
|
|
5
|
-
declare const _default: {
|
|
6
|
-
deepEqual: (p1: any, p2: any, options?: {
|
|
7
|
-
disregardArrayOrder?: boolean;
|
|
8
|
-
}) => boolean;
|
|
9
|
-
deepExtend: <T extends unknown[]>(...args: T) => Merge<T>;
|
|
10
|
-
deepFlatten: typeof deepFlatten;
|
|
11
|
-
};
|
|
12
|
-
export default _default;
|
|
4
|
+
export { deepEqual, deepExtend, deepFlatten, type Merge, type MergeTwo };
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { deepFlatten } from './deepFlatten.js';
|
|
4
|
-
export { deepEqual, deepExtend, deepFlatten };
|
|
5
|
-
export default {
|
|
6
|
-
deepEqual,
|
|
7
|
-
deepExtend,
|
|
8
|
-
deepFlatten
|
|
9
|
-
};
|
|
1
|
+
var m=(e,f)=>{let i=e;f||(i=`string${e}`);let t=0;for(let a=0;a<i.length;a++){let n=i.charCodeAt(a);t=(t<<5)-t+n,t=t&t}return t};function k(e,f){if(f.indexOf(e)>-1)return;let i="",t=Object.keys(e).sort();for(let a=0;a<t.length;a+=1){let n=t[a],r=w(n),o=w(e[n],f);f.push(e[n]),i+=m(`object${r}${o}`,!0)}return m(i,!0)}function h(e,f){let i=f;return i===void 0&&(i=[]),!isNaN(e)&&typeof e!="string"?e:typeof e==="object"?k(e,i):m(String(e))}var w=h;var x=(e,f)=>Number.isNaN(e)&&Number.isNaN(f),b=(e,f,i)=>{let t=new Map,a=(...n)=>{let r=(l,u)=>{if(l.length!==u.length)return!1;if(l.length===0&&u.length===0)return!0;let y=i?.disregardArrayOrder?l.map(c=>c).sort((c,p)=>{let d=h(c),T=h(p);return d<T?1:-1}):l.map(c=>c),g=i?.disregardArrayOrder?u.map(c=>c).sort((c,p)=>{let d=h(c),T=h(p);return d<T?1:-1}):u.map(c=>c);for(let c=0;c<y.length;c++)if(!a(y[c],g[c]))return!1;return!0};if(n.length!==2)return!1;let[o,s]=n;if(o===s)return!0;if(typeof o!=typeof s)return!1;if(x(o,s))return!0;if(Array.isArray(o)&&!Array.isArray(s)||!Array.isArray(o)&&Array.isArray(s))return!1;if(Array.isArray(o)&&Array.isArray(s))return r(o,s);if(typeof o=="object"&&o!==null){if(t.get(o)===!0)return!1;if(t.set(o,!0),o instanceof Date&&s instanceof Date)return!isNaN(o)&&!isNaN(s)&&o.getTime()===s.getTime();let l=Object.keys(o),u=Object.keys(s);if(l.length!==u.length)return!1;l.sort(),u.sort();for(let y=0;y<l.length;y++){if(l[y]!==u[y])return!1;let g=o[l[y]],c=s[l[y]];if(!a(g,c))return!1}return!0}return!1};return a(e,f)};var A=((...e)=>{if(e.length===0)throw new Error("no arguments");if(typeof e[0]!="object"||e[0]===null)throw new Error("not a non-null object");if(e.length===1)return e[0];let f={},i=(t,a)=>{let n=Object.keys(a);for(let r=0;r<n.length;r++)!Reflect.has(t,n[r])||!(typeof t[n[r]]=="object"&&t[n[r]]!==null&&typeof a[n[r]]=="object")||t[n[r]]==null||a[n[r]]==null?t[n[r]]=a[n[r]]:i(t[n[r]],a[n[r]])};for(let t=0;t<e.length;t++)if(typeof e[t]=="object"&&e[t]!==null&&e[t])i(f,e[t]);else throw new Error("not a non-null object");return f});function O(e,f="."){let i=r=>typeof r=="object"&&r!==null&&!Array.isArray(r)&&Object.getPrototypeOf(r)===Object.prototype;if(!i(e))throw new Error("cannot flatten this object");let t=[],a={},n=(r,o="")=>{if(t.find(s=>s===r))throw new Error("circular reference detected");t.push(r),Object.keys(r).forEach(s=>{if(!i(r[s])){a[o?`${o}${f}${s}`:s]=r[s];return}n(r[s],o?`${o}${f}${s}`:s)}),t.pop()};return n(e),a}export{b as deepEqual,A as deepExtend,O as deepFlatten};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hashObject.ts","../src/deepEqual.ts","../src/deepExtend.ts","../src/deepFlatten.ts"],"sourcesContent":["const stringHash = (string: string, noType?: boolean) => {\n let hashString = string;\n if (!noType) {\n hashString = `string${string}`;\n }\n let hash = 0;\n for (let i = 0; i < hashString.length; i++) {\n const character = hashString.charCodeAt(i);\n hash = (hash << 5) - hash + character;\n hash = hash & hash; // Convert to 32bit integer\n }\n return hash;\n};\n\nfunction objectHash(\n obj: Record<string, any>,\n exclude: any[]\n): number | undefined {\n if (exclude.indexOf(obj) > -1) {\n return undefined;\n }\n let hash = '';\n const keys = Object.keys(obj).sort();\n for (let index = 0; index < keys.length; index += 1) {\n const key = keys[index];\n const keyHash = hashFunc(key);\n const attrHash = hashFunc(obj[key], exclude);\n exclude.push(obj[key]);\n hash += stringHash(`object${keyHash}${attrHash}`, true);\n }\n return stringHash(hash, true);\n}\n\n/**\n * Computes a 32-bit numeric hash for any value.\n *\n * Objects are hashed by recursively hashing their sorted keys and values;\n * circular references are detected via an internal exclusion list.\n *\n * @param unkType - The value to hash (object, string, number, etc.).\n * @param exclude - Internal array used for circular-reference detection.\n * @returns A 32-bit integer hash code.\n */\nexport function HashObject(unkType: any, exclude?: any[]): number {\n let ex = exclude;\n if (ex === undefined) {\n ex = [];\n }\n // biome-ignore lint/suspicious/noGlobalIsNan: intentional coercion — isNaN returns true for non-numeric types like objects\n if (!isNaN(unkType) && typeof unkType !== 'string') {\n return unkType;\n }\n switch (typeof unkType) {\n case 'object':\n return objectHash(unkType, ex) as number;\n default:\n return stringHash(String(unkType)) as number;\n }\n}\n\nconst hashFunc = HashObject;\n","import { HashObject } from './hashObject.js';\n\nconst isBothNaN = (v1: any, v2: any) => Number.isNaN(v1) && Number.isNaN(v2);\n\n/**\n * Compares two objects and returns true if they\n * have the same structure and values. Can work\n * with arrays and objects, nested objects,\n * recursive objects, dates, etc.\n * @param p1 first object\n * @param p2 second object\n * @param options additional options\n * @returns {boolean} `true` if the objects are equal, `false` otherwise\n */\nexport const deepEqual = (\n p1: any,\n p2: any,\n options?: {\n /**\n * if true, the order of the elements in the array will be disregarded\n * e.g. [1, 2] and [2, 1] will be considered equal\n */\n disregardArrayOrder?: boolean;\n }\n): boolean => {\n const cache = new Map();\n\n const compare = (...args: any[]) => {\n const arraysAreIdentical = (a1: any, a2: any) => {\n if (a1.length !== a2.length) return false;\n if (a1.length === 0 && a2.length === 0) return true;\n\n const c1 = options?.disregardArrayOrder\n ? a1\n .map((t: any) => t)\n .sort((l: any, r: any) => {\n const hash1 = HashObject(l);\n const hash2 = HashObject(r);\n return hash1 < hash2 ? 1 : -1;\n })\n : a1.map((t: any) => t);\n const c2 = options?.disregardArrayOrder\n ? a2\n .map((t: any) => t)\n .sort((l: any, r: any) => {\n const hash1 = HashObject(l);\n const hash2 = HashObject(r);\n return hash1 < hash2 ? 1 : -1;\n })\n : a2.map((t: any) => t);\n\n for (let i = 0; i < c1.length; i++) {\n if (!compare(c1[i], c2[i])) return false;\n }\n return true;\n };\n\n if (args.length !== 2) return false;\n const [o1, o2] = args;\n if (o1 === o2) return true;\n if (typeof o1 !== typeof o2) return false;\n if (isBothNaN(o1, o2)) return true;\n\n if (\n (Array.isArray(o1) && !Array.isArray(o2)) ||\n (!Array.isArray(o1) && Array.isArray(o2))\n ) {\n return false;\n }\n if (Array.isArray(o1) && Array.isArray(o2)) {\n return arraysAreIdentical(o1, o2);\n }\n\n if (typeof o1 === 'object' && o1 !== null) {\n if (cache.get(o1) === true) {\n return false;\n }\n\n cache.set(o1, true);\n\n if (o1 instanceof Date && o2 instanceof Date) {\n return (\n // biome-ignore lint/suspicious/noGlobalIsNan: isNaN coerces Date to number, which is the intended behavior here\n !isNaN(o1 as any) &&\n // biome-ignore lint/suspicious/noGlobalIsNan: isNaN coerces Date to number, which is the intended behavior here\n !isNaN(o2 as any) &&\n o1.getTime() === o2.getTime()\n );\n }\n\n const keys1 = Object.keys(o1);\n const keys2 = Object.keys(o2);\n if (keys1.length !== keys2.length) return false;\n\n keys1.sort();\n keys2.sort();\n for (let i = 0; i < keys1.length; i++) {\n if (keys1[i] !== keys2[i]) {\n return false;\n }\n\n const v1 = o1[keys1[i]];\n const v2 = o2[keys1[i]];\n if (!compare(v1, v2)) return false;\n }\n return true;\n }\n\n return false;\n };\n\n return compare(p1, p2);\n};\n","/** Properties that exist in both `T1` and `T2`, typed as `T2`'s version. */\nexport type CommonProps<T1, T2> = {\n [k in keyof T1 & keyof T2]: T1[k] extends never\n ? never\n : T2[k] extends never\n ? never\n : T2[k];\n};\n\n/** Properties present in `T1` but not in `T2`. */\nexport type PropsInFirstOnly<T1, T2> = Omit<T1, keyof T2>;\n\n/** Recursively merges two object types. Matching keys are merged; unique keys are kept. */\nexport type MergeTwo<T1, T2> = PropsInFirstOnly<T1, T2> &\n PropsInFirstOnly<T2, T1> & {\n [k in keyof CommonProps<T1, T2>]: T1[k] extends Record<string, unknown>\n ? T2[k] extends Record<string, unknown>\n ? MergeTwo<T1[k], T2[k]>\n : T2[k]\n : T2[k];\n };\n\n/** Recursively merges a tuple of object types from left to right. */\nexport type Merge<T extends unknown[]> = T['length'] extends 3\n ? MergeTwo<T[0], MergeTwo<T[1], T[2]>>\n : T['length'] extends 2\n ? MergeTwo<T[0], T[1]>\n : T['length'] extends 1\n ? T[0]\n : T extends [...infer K, infer PL, infer L]\n ? Merge<[Merge<[...K]>, MergeTwo<PL, L>]>\n : never;\n\n/**\n * Deep-merges multiple objects into one. Later values override earlier ones;\n * nested objects are merged recursively rather than replaced.\n *\n * @example\n * ```ts\n * const a = { x: 1, nested: { a: true } };\n * const b = { y: 2, nested: { b: false } };\n * const result = deepExtend(a, b);\n * // { x: 1, y: 2, nested: { a: true, b: false } }\n * ```\n *\n * @param args - Two or more non-null objects to merge.\n * @returns A new object containing the deep-merged result.\n * @throws If no arguments are provided or any argument is not a non-null object.\n */\nexport const deepExtend = ((...rest) => {\n if (rest.length === 0) throw new Error('no arguments');\n if (typeof rest[0] !== 'object' || rest[0] === null)\n throw new Error('not a non-null object');\n if (rest.length === 1) return rest[0];\n\n const result = {};\n\n const extendObject = (o1: any, o2: any) => {\n const keys = Object.keys(o2);\n\n for (let i = 0; i < keys.length; i++) {\n if (\n !Reflect.has(o1, keys[i]) ||\n !(\n typeof o1[keys[i]] === 'object' &&\n o1[keys[i]] !== null &&\n typeof o2[keys[i]] === 'object'\n )\n ) {\n o1[keys[i]] = o2[keys[i]];\n } else {\n if (o1[keys[i]] == null || o2[keys[i]] == null) {\n o1[keys[i]] = o2[keys[i]];\n } else {\n extendObject(o1[keys[i]], o2[keys[i]]);\n }\n }\n }\n };\n\n for (let i = 0; i < rest.length; i++) {\n if (typeof rest[i] === 'object' && rest[i] !== null && rest[i]) {\n extendObject(result, rest[i]);\n } else {\n throw new Error('not a non-null object');\n }\n }\n\n return result;\n}) as <T extends unknown[]>(...args: T) => Merge<T>;\n","/**\n * Flattens an object to a single level, with the nested keys separated by a `delimiter`.\n * @example\n * ```ts\n * deepFlatten({ a: { b: 1, c: 2 } });\n * // => { 'a.b': 1, 'a.c': 2 }\n *\n * deepFlatten({ a: { b: 1, c: 2 } }, '/');\n * // => { 'a/b': 1, 'a/c': 2 }\n *\n * deepFlatten({ a: { b: 1, c: { d: 'some val' } }, d: 3 });\n * // => { 'a.b': 1, 'a.c.d': 'some val', d: 3 }\n *\n * ```\n * @param {string} [delimiter]\n */\nexport function deepFlatten(\n obj: Record<string, any>,\n delimiter = '.'\n): Record<string, any> {\n const shouldFlatten = (obj: any) =>\n typeof obj === 'object' &&\n obj !== null &&\n !Array.isArray(obj) &&\n Object.getPrototypeOf(obj) === Object.prototype;\n\n if (!shouldFlatten(obj)) throw new Error('cannot flatten this object');\n\n const stack: any[] = [];\n\n const result: Record<string, any> = {};\n\n const deepFlattenHelper = (obj: any, prefix = '') => {\n if (stack.find(o => o === obj))\n throw new Error('circular reference detected');\n\n stack.push(obj);\n\n Object.keys(obj).forEach(key => {\n if (!shouldFlatten(obj[key])) {\n result[prefix ? `${prefix}${delimiter}${key}` : key] = obj[key];\n return;\n }\n deepFlattenHelper(\n obj[key],\n prefix ? `${prefix}${delimiter}${key}` : key\n );\n });\n\n stack.pop();\n };\n\n deepFlattenHelper(obj);\n\n return result;\n}\n"],"mappings":"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","names":["stringHash","string","noType","hashString","hash","i","character","objectHash","obj","exclude","keys","index","key","keyHash","hashFunc","attrHash","HashObject","unkType","ex","isBothNaN","v1","v2","deepEqual","p1","p2","options","cache","compare","args","arraysAreIdentical","a1","a2","c1","t","l","r","hash1","HashObject","hash2","c2","i","o1","o2","keys1","keys2","deepExtend","rest","result","extendObject","o1","o2","keys","i","deepFlatten","obj","delimiter","shouldFlatten","stack","result","deepFlattenHelper","prefix","o","key"]}
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
"dist"
|
|
10
10
|
],
|
|
11
|
-
"homepage": "https://docs.cleverbrush.com/
|
|
11
|
+
"homepage": "https://docs.cleverbrush.com/",
|
|
12
12
|
"keywords": [
|
|
13
13
|
"deep operations on objects",
|
|
14
14
|
"deep equal",
|
|
@@ -17,6 +17,13 @@
|
|
|
17
17
|
],
|
|
18
18
|
"license": "BSD 3-Clause",
|
|
19
19
|
"main": "./dist/index.js",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"import": "./dist/index.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"sideEffects": false,
|
|
20
27
|
"name": "@cleverbrush/deep",
|
|
21
28
|
"readme": "https://github.com/cleverbrush/framework/tree/master/libs/deep#readme",
|
|
22
29
|
"repository": {
|
|
@@ -24,10 +31,11 @@
|
|
|
24
31
|
"url": "github:cleverbrush/framework"
|
|
25
32
|
},
|
|
26
33
|
"scripts": {
|
|
27
|
-
"watch": "tsc --watch",
|
|
28
|
-
"build": "tsc"
|
|
34
|
+
"watch": "tsc --build --watch",
|
|
35
|
+
"build": "tsup && rm -f tsconfig.build.tsbuildinfo && tsc --project tsconfig.build.json --emitDeclarationOnly",
|
|
36
|
+
"clean": "rm -rf dist tsconfig.tsbuildinfo"
|
|
29
37
|
},
|
|
30
38
|
"type": "module",
|
|
31
39
|
"types": "./dist/index.d.ts",
|
|
32
|
-
"version": "
|
|
40
|
+
"version": "3.0.0"
|
|
33
41
|
}
|
package/dist/deepEqual.js
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { HashObject } from './hashObject.js';
|
|
2
|
-
const isBothNaN = (v1, v2) => Number.isNaN(v1) && Number.isNaN(v2);
|
|
3
|
-
/**
|
|
4
|
-
* Compares two objects and returns true if they
|
|
5
|
-
* have the same structure and values. Can work
|
|
6
|
-
* with arrays and objects, nested objects,
|
|
7
|
-
* recursive objects, dates, etc.
|
|
8
|
-
* @param p1 first object
|
|
9
|
-
* @param p2 second object
|
|
10
|
-
* @param options additional options
|
|
11
|
-
* @returns {boolean} `true` if the objects are equal, `false` otherwise
|
|
12
|
-
*/
|
|
13
|
-
export const deepEqual = function (p1, p2, options) {
|
|
14
|
-
const cache = new Map();
|
|
15
|
-
const compare = function (o1, o2) {
|
|
16
|
-
const arraysAreIdentical = function (a1, a2) {
|
|
17
|
-
if (a1.length !== a2.length)
|
|
18
|
-
return false;
|
|
19
|
-
if (a1.length === 0 && a2.length === 0)
|
|
20
|
-
return true;
|
|
21
|
-
const c1 = options?.disregardArrayOrder
|
|
22
|
-
? a1
|
|
23
|
-
.map((t) => t)
|
|
24
|
-
.sort((l, r) => {
|
|
25
|
-
const hash1 = HashObject(l);
|
|
26
|
-
const hash2 = HashObject(r);
|
|
27
|
-
return hash1 < hash2 ? 1 : -1;
|
|
28
|
-
})
|
|
29
|
-
: a1.map((t) => t);
|
|
30
|
-
const c2 = options?.disregardArrayOrder
|
|
31
|
-
? a2
|
|
32
|
-
.map((t) => t)
|
|
33
|
-
.sort((l, r) => {
|
|
34
|
-
const hash1 = HashObject(l);
|
|
35
|
-
const hash2 = HashObject(r);
|
|
36
|
-
return hash1 < hash2 ? 1 : -1;
|
|
37
|
-
})
|
|
38
|
-
: a2.map((t) => t);
|
|
39
|
-
for (let i = 0; i < c1.length; i++) {
|
|
40
|
-
if (!compare(c1[i], c2[i]))
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
|
-
return true;
|
|
44
|
-
};
|
|
45
|
-
if (arguments.length !== 2)
|
|
46
|
-
return false;
|
|
47
|
-
if (o1 === o2)
|
|
48
|
-
return true;
|
|
49
|
-
if (typeof o1 !== typeof o2)
|
|
50
|
-
return false;
|
|
51
|
-
if (isBothNaN(o1, o2))
|
|
52
|
-
return true;
|
|
53
|
-
if ((Array.isArray(o1) && !Array.isArray(o2)) ||
|
|
54
|
-
(!Array.isArray(o1) && Array.isArray(o2))) {
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
if (Array.isArray(o1) && Array.isArray(o2)) {
|
|
58
|
-
return arraysAreIdentical(o1, o2);
|
|
59
|
-
}
|
|
60
|
-
if (typeof o1 === 'object' && o1 !== null) {
|
|
61
|
-
if (cache.get(o1) === true) {
|
|
62
|
-
return false;
|
|
63
|
-
}
|
|
64
|
-
cache.set(o1, true);
|
|
65
|
-
if (o1 instanceof Date && o2 instanceof Date) {
|
|
66
|
-
return (!isNaN(o1) &&
|
|
67
|
-
!isNaN(o2) &&
|
|
68
|
-
o1.getTime() === o2.getTime());
|
|
69
|
-
}
|
|
70
|
-
const keys1 = Object.keys(o1);
|
|
71
|
-
const keys2 = Object.keys(o2);
|
|
72
|
-
if (keys1.length != keys2.length)
|
|
73
|
-
return false;
|
|
74
|
-
keys1.sort();
|
|
75
|
-
keys2.sort();
|
|
76
|
-
for (let i = 0; i < keys1.length; i++) {
|
|
77
|
-
if (keys1[i] !== keys2[i]) {
|
|
78
|
-
return false;
|
|
79
|
-
}
|
|
80
|
-
const v1 = o1[keys1[i]];
|
|
81
|
-
const v2 = o2[keys1[i]];
|
|
82
|
-
if (!compare(v1, v2))
|
|
83
|
-
return false;
|
|
84
|
-
}
|
|
85
|
-
return true;
|
|
86
|
-
}
|
|
87
|
-
return false;
|
|
88
|
-
};
|
|
89
|
-
return compare(p1, p2);
|
|
90
|
-
};
|
package/dist/deepExtend.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
export const deepExtend = ((...rest) => {
|
|
2
|
-
if (rest.length === 0)
|
|
3
|
-
throw new Error('no arguments');
|
|
4
|
-
if (typeof rest[0] !== 'object' || rest[0] === null)
|
|
5
|
-
throw new Error('not a non-null object');
|
|
6
|
-
if (rest.length === 1)
|
|
7
|
-
return rest[0];
|
|
8
|
-
const result = {};
|
|
9
|
-
const extendObject = function (o1, o2) {
|
|
10
|
-
const keys = Object.keys(o2);
|
|
11
|
-
for (let i = 0; i < keys.length; i++) {
|
|
12
|
-
if (!Reflect.has(o1, keys[i]) ||
|
|
13
|
-
!(typeof o1[keys[i]] === 'object' &&
|
|
14
|
-
o1[keys[i]] !== null &&
|
|
15
|
-
typeof o2[keys[i]] === 'object')) {
|
|
16
|
-
o1[keys[i]] = o2[keys[i]];
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
if (o1[keys[i]] == null || o2[keys[i]] == null) {
|
|
20
|
-
o1[keys[i]] = o2[keys[i]];
|
|
21
|
-
}
|
|
22
|
-
else {
|
|
23
|
-
extendObject(o1[keys[i]], o2[keys[i]]);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
for (let i = 0; i < rest.length; i++) {
|
|
29
|
-
if (typeof rest[i] === 'object' && rest[i] !== null && rest[i]) {
|
|
30
|
-
extendObject(result, rest[i]);
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
throw new Error('not a non-null object');
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return result;
|
|
37
|
-
});
|
package/dist/deepFlatten.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Flattens an object to a single level, with the nested keys separated by a `delimiter`.
|
|
3
|
-
* @example
|
|
4
|
-
* ```ts
|
|
5
|
-
* deepFlatten({ a: { b: 1, c: 2 } });
|
|
6
|
-
* // => { 'a.b': 1, 'a.c': 2 }
|
|
7
|
-
*
|
|
8
|
-
* deepFlatten({ a: { b: 1, c: 2 } }, '/');
|
|
9
|
-
* // => { 'a/b': 1, 'a/c': 2 }
|
|
10
|
-
*
|
|
11
|
-
* deepFlatten({ a: { b: 1, c: { d: 'some val' } }, d: 3 });
|
|
12
|
-
* // => { 'a.b': 1, 'a.c.d': 'some val', d: 3 }
|
|
13
|
-
*
|
|
14
|
-
* ```
|
|
15
|
-
* @param {string} [delimiter]
|
|
16
|
-
*/
|
|
17
|
-
export function deepFlatten(obj, delimiter = '.') {
|
|
18
|
-
const shouldFlatten = (obj) => typeof obj === 'object' &&
|
|
19
|
-
obj !== null &&
|
|
20
|
-
!Array.isArray(obj) &&
|
|
21
|
-
Object.getPrototypeOf(obj) === Object.prototype;
|
|
22
|
-
if (!shouldFlatten(obj))
|
|
23
|
-
throw new Error('cannot flatten this object');
|
|
24
|
-
const stack = [];
|
|
25
|
-
const result = {};
|
|
26
|
-
const deepFlattenHelper = (obj, prefix = '') => {
|
|
27
|
-
if (stack.find((o) => o === obj))
|
|
28
|
-
throw new Error('circular reference detected');
|
|
29
|
-
stack.push(obj);
|
|
30
|
-
Object.keys(obj).forEach((key) => {
|
|
31
|
-
if (!shouldFlatten(obj[key])) {
|
|
32
|
-
result[prefix ? `${prefix}${delimiter}${key}` : key] = obj[key];
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
deepFlattenHelper(obj[key], prefix ? `${prefix}${delimiter}${key}` : key);
|
|
36
|
-
});
|
|
37
|
-
stack.pop();
|
|
38
|
-
};
|
|
39
|
-
deepFlattenHelper(obj);
|
|
40
|
-
return result;
|
|
41
|
-
}
|
package/dist/hashObject.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
const stringHash = (string, noType) => {
|
|
2
|
-
let hashString = string;
|
|
3
|
-
if (!noType) {
|
|
4
|
-
hashString = `string${string}`;
|
|
5
|
-
}
|
|
6
|
-
let hash = 0;
|
|
7
|
-
for (let i = 0; i < hashString.length; i++) {
|
|
8
|
-
const character = hashString.charCodeAt(i);
|
|
9
|
-
hash = (hash << 5) - hash + character;
|
|
10
|
-
hash = hash & hash; // Convert to 32bit integer
|
|
11
|
-
}
|
|
12
|
-
return hash;
|
|
13
|
-
};
|
|
14
|
-
function objectHash(obj, exclude) {
|
|
15
|
-
if (exclude.indexOf(obj) > -1) {
|
|
16
|
-
return undefined;
|
|
17
|
-
}
|
|
18
|
-
let hash = '';
|
|
19
|
-
const keys = Object.keys(obj).sort();
|
|
20
|
-
for (let index = 0; index < keys.length; index += 1) {
|
|
21
|
-
const key = keys[index];
|
|
22
|
-
const keyHash = hashFunc(key);
|
|
23
|
-
const attrHash = hashFunc(obj[key], exclude);
|
|
24
|
-
exclude.push(obj[key]);
|
|
25
|
-
hash += stringHash(`object${keyHash}${attrHash}`, true);
|
|
26
|
-
}
|
|
27
|
-
return stringHash(hash, true);
|
|
28
|
-
}
|
|
29
|
-
export function HashObject(unkType, exclude) {
|
|
30
|
-
let ex = exclude;
|
|
31
|
-
if (ex === undefined) {
|
|
32
|
-
ex = [];
|
|
33
|
-
}
|
|
34
|
-
if (!isNaN(unkType) && typeof unkType !== 'string') {
|
|
35
|
-
return unkType;
|
|
36
|
-
}
|
|
37
|
-
switch (typeof unkType) {
|
|
38
|
-
case 'object':
|
|
39
|
-
return objectHash(unkType, ex);
|
|
40
|
-
default:
|
|
41
|
-
return stringHash(String(unkType));
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
const hashFunc = HashObject;
|