@takeshape/util 9.103.27 → 9.104.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/clone.d.ts CHANGED
@@ -1,2 +1,29 @@
1
- export declare function deepClone<T>(input: T): T;
1
+ /**
2
+ * Clone any JSON serializable value similar to JSON.parse(JSON.stringify()) but better performance
3
+ */
4
+ export declare function deepClone<T>(value: T): T;
5
+ /**
6
+ * @param value the value to clone
7
+ * @param key the key/index this value is stored under if parent is an object or array
8
+ * @param parent the parent object or array if applicable
9
+ * @return a new value to use instead of the value argument. Return REMOVE to remove value from the parent. Return undefined to continue to clone recursively.
10
+ */
11
+ type CloneHelper = (value: unknown, key: string | number | undefined, parent: Record<string, unknown> | unknown[] | undefined) => unknown;
12
+ /**
13
+ * The callback for deepCloneWith which is called for every value in a object
14
+ * @param value the value to clone
15
+ * @param key the key/index this value is stored under if parent is an object or array
16
+ * @param parent the parent object or array if applicable
17
+ * @param clone a function used to continue to recusively clone
18
+ * @return a new value to use instead of the value argument. Return REMOVE to remove value from the parent. Return undefined to continue to clone recursively.
19
+ */
20
+ export type DeepCloneWithCustomizer = (value: unknown, key: string | number | undefined, parent: Record<string, unknown> | unknown[] | undefined, clone: CloneHelper) => unknown;
21
+ export declare const REMOVE: unique symbol;
22
+ /**
23
+ * Clone any JSON serializable value and transform using a callback
24
+ * @param value the value to clone
25
+ * @param customizer a callback that is called for every key/index
26
+ */
27
+ export declare function deepCloneWith(value: unknown, customizer: DeepCloneWithCustomizer): unknown;
28
+ export {};
2
29
  //# sourceMappingURL=clone.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"clone.d.ts","sourceRoot":"","sources":["../../src/clone.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAExC"}
1
+ {"version":3,"file":"clone.d.ts","sourceRoot":"","sources":["../../src/clone.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CA8BxC;AAED;;;;;GAKG;AACH,KAAK,WAAW,GAAG,CACjB,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,SAAS,KACpD,OAAO,CAAC;AAEb;;;;;;;GAOG;AACH,MAAM,MAAM,uBAAuB,GAAG,CACpC,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,SAAS,EACvD,KAAK,EAAE,WAAW,KACf,OAAO,CAAC;AAEb,eAAO,MAAM,MAAM,eAAmB,CAAC;AAMvC;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,uBAAuB,GAAG,OAAO,CAwC1F"}
package/dist/clone.js CHANGED
@@ -3,7 +3,100 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.REMOVE = void 0;
6
7
  exports.deepClone = deepClone;
7
- function deepClone(input) {
8
- return JSON.parse(JSON.stringify(input));
8
+ exports.deepCloneWith = deepCloneWith;
9
+ var _types = require("./types");
10
+ /**
11
+ * Clone any JSON serializable value similar to JSON.parse(JSON.stringify()) but better performance
12
+ */
13
+ function deepClone(value) {
14
+ if (!value) {
15
+ return value;
16
+ }
17
+ if (Array.isArray(value)) {
18
+ const {
19
+ length
20
+ } = value;
21
+ const result = new Array(length);
22
+ for (let i = 0; i < length; i++) {
23
+ result[i] = deepClone(value[i]);
24
+ }
25
+ return result;
26
+ }
27
+ if ((0, _types.isIterableObject)(value)) {
28
+ const obj = value;
29
+ const result = {};
30
+ for (const key of Object.keys(obj)) {
31
+ const value = obj[key];
32
+ if (value !== undefined) {
33
+ result[key] = deepClone(value);
34
+ }
35
+ }
36
+ return result;
37
+ }
38
+ return value;
39
+ }
40
+
41
+ /**
42
+ * @param value the value to clone
43
+ * @param key the key/index this value is stored under if parent is an object or array
44
+ * @param parent the parent object or array if applicable
45
+ * @return a new value to use instead of the value argument. Return REMOVE to remove value from the parent. Return undefined to continue to clone recursively.
46
+ */
47
+
48
+ /**
49
+ * The callback for deepCloneWith which is called for every value in a object
50
+ * @param value the value to clone
51
+ * @param key the key/index this value is stored under if parent is an object or array
52
+ * @param parent the parent object or array if applicable
53
+ * @param clone a function used to continue to recusively clone
54
+ * @return a new value to use instead of the value argument. Return REMOVE to remove value from the parent. Return undefined to continue to clone recursively.
55
+ */
56
+
57
+ const REMOVE = Symbol('REMOVE');
58
+ exports.REMOVE = REMOVE;
59
+ function arrayFilter(value) {
60
+ return value !== REMOVE;
61
+ }
62
+
63
+ /**
64
+ * Clone any JSON serializable value and transform using a callback
65
+ * @param value the value to clone
66
+ * @param customizer a callback that is called for every key/index
67
+ */
68
+ function deepCloneWith(value, customizer) {
69
+ const clone = (value, key, parent) => {
70
+ const newValue = customizer(value, key, parent, clone);
71
+ if (newValue !== undefined) {
72
+ return newValue;
73
+ }
74
+ if (Array.isArray(value)) {
75
+ const {
76
+ length
77
+ } = value;
78
+ const arr = new Array(length);
79
+ let edited = false;
80
+ for (let i = 0; i < length; i++) {
81
+ const newValue = clone(value[i], i, value);
82
+ if (newValue === REMOVE) {
83
+ edited = true;
84
+ }
85
+ arr[i] = newValue;
86
+ }
87
+ return edited ? arr.filter(arrayFilter) : arr;
88
+ }
89
+ if ((0, _types.isIterableObject)(value)) {
90
+ const newObject = {};
91
+ for (const key of Object.keys(value)) {
92
+ const newValue = clone(value[key], key, value);
93
+ if (newValue !== undefined && newValue !== REMOVE) {
94
+ newObject[key] = newValue;
95
+ }
96
+ }
97
+ return newObject;
98
+ }
99
+ return value;
100
+ };
101
+ return clone(value, undefined, undefined);
9
102
  }
package/dist/types.d.ts CHANGED
@@ -19,6 +19,11 @@ export type StringProps<Obj> = {
19
19
  * reasonably be typed as a Record.
20
20
  */
21
21
  export declare function isRecord(maybeRecord: unknown): maybeRecord is Record<string, unknown>;
22
+ /**
23
+ A guard for objects that ensures they are iterable records objects
24
+ not as strict as isRecord but better performance when that matters
25
+ */
26
+ export declare function isIterableObject(x: unknown): x is Record<string, unknown>;
22
27
  export type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
23
28
  export type Maybe<T> = T | undefined;
24
29
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,WAAW,CAAC;AAIzC;;;;;;;;GAQG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,EAAE,SAAS,IAAI,IAAI,CAAC,CAAC,EAAE;KAAE,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,SAAS,GAAG,GAAG,GAAG,KAAK;CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAEvH,MAAM,MAAM,WAAW,CAAC,GAAG,IAAI;KAAE,CAAC,IAAI,MAAM,QAAQ,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,CAAC,GAAG,KAAK;CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AAE1G;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,WAAW,EAAE,OAAO,GAAG,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAErF;AAED,MAAM,MAAM,SAAS,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAG/E,MAAM,MAAM,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;AAErC;;;GAGG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AAErE;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,SAAS,MAAM,EAAE,YAAY,EAAE;KAAE,GAAG,IAAI,CAAC,GAAG,KAAK;CAAC,eACtF,MAAM,mCAC1B;AAED,wBAAgB,WAAW,CAAC,cAAc,EAAE,OAAO,GAAG,cAAc,IAAI,SAAS,CAUhF;AAED,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAExD,wBAAgB,QAAQ,CAAC,WAAW,EAAE,OAAO,GAAG,WAAW,IAAI,MAAM,CAOpE;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAMlD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEpD"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,WAAW,CAAC;AAIzC;;;;;;;;GAQG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,EAAE,SAAS,IAAI,IAAI,CAAC,CAAC,EAAE;KAAE,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,SAAS,GAAG,GAAG,GAAG,KAAK;CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAEvH,MAAM,MAAM,WAAW,CAAC,GAAG,IAAI;KAAE,CAAC,IAAI,MAAM,QAAQ,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,CAAC,GAAG,KAAK;CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AAE1G;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,WAAW,EAAE,OAAO,GAAG,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAErF;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED,MAAM,MAAM,SAAS,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAG/E,MAAM,MAAM,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;AAErC;;;GAGG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AAErE;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,SAAS,MAAM,EAAE,YAAY,EAAE;KAAE,GAAG,IAAI,CAAC,GAAG,KAAK;CAAC,eACtF,MAAM,mCAC1B;AAED,wBAAgB,WAAW,CAAC,cAAc,EAAE,OAAO,GAAG,cAAc,IAAI,SAAS,CAUhF;AAED,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAExD,wBAAgB,QAAQ,CAAC,WAAW,EAAE,OAAO,GAAG,WAAW,IAAI,MAAM,CAOpE;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAMlD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEpD"}
package/dist/types.js CHANGED
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.createEnumMatcher = createEnumMatcher;
7
7
  exports.getSingle = getSingle;
8
+ exports.isIterableObject = isIterableObject;
8
9
  exports.isNumericString = isNumericString;
9
10
  exports.isPrimitive = isPrimitive;
10
11
  exports.isRecord = isRecord;
@@ -30,6 +31,14 @@ function isRecord(maybeRecord) {
30
31
  return (0, _isPlainObject.default)(maybeRecord);
31
32
  }
32
33
 
34
+ /**
35
+ A guard for objects that ensures they are iterable records objects
36
+ not as strict as isRecord but better performance when that matters
37
+ */
38
+ function isIterableObject(x) {
39
+ return Boolean(x) && typeof x === 'object';
40
+ }
41
+
33
42
  // https://stackoverflow.com/questions/50573891/maybe-a-type-in-typescript
34
43
 
35
44
  /**
package/es/clone.js CHANGED
@@ -1,3 +1,94 @@
1
- export function deepClone(input) {
2
- return JSON.parse(JSON.stringify(input));
1
+ import { isIterableObject } from './types';
2
+
3
+ /**
4
+ * Clone any JSON serializable value similar to JSON.parse(JSON.stringify()) but better performance
5
+ */
6
+ export function deepClone(value) {
7
+ if (!value) {
8
+ return value;
9
+ }
10
+ if (Array.isArray(value)) {
11
+ const {
12
+ length
13
+ } = value;
14
+ const result = new Array(length);
15
+ for (let i = 0; i < length; i++) {
16
+ result[i] = deepClone(value[i]);
17
+ }
18
+ return result;
19
+ }
20
+ if (isIterableObject(value)) {
21
+ const obj = value;
22
+ const result = {};
23
+ for (const key of Object.keys(obj)) {
24
+ const value = obj[key];
25
+ if (value !== undefined) {
26
+ result[key] = deepClone(value);
27
+ }
28
+ }
29
+ return result;
30
+ }
31
+ return value;
32
+ }
33
+
34
+ /**
35
+ * @param value the value to clone
36
+ * @param key the key/index this value is stored under if parent is an object or array
37
+ * @param parent the parent object or array if applicable
38
+ * @return a new value to use instead of the value argument. Return REMOVE to remove value from the parent. Return undefined to continue to clone recursively.
39
+ */
40
+
41
+ /**
42
+ * The callback for deepCloneWith which is called for every value in a object
43
+ * @param value the value to clone
44
+ * @param key the key/index this value is stored under if parent is an object or array
45
+ * @param parent the parent object or array if applicable
46
+ * @param clone a function used to continue to recusively clone
47
+ * @return a new value to use instead of the value argument. Return REMOVE to remove value from the parent. Return undefined to continue to clone recursively.
48
+ */
49
+
50
+ export const REMOVE = Symbol('REMOVE');
51
+ function arrayFilter(value) {
52
+ return value !== REMOVE;
53
+ }
54
+
55
+ /**
56
+ * Clone any JSON serializable value and transform using a callback
57
+ * @param value the value to clone
58
+ * @param customizer a callback that is called for every key/index
59
+ */
60
+ export function deepCloneWith(value, customizer) {
61
+ const clone = (value, key, parent) => {
62
+ const newValue = customizer(value, key, parent, clone);
63
+ if (newValue !== undefined) {
64
+ return newValue;
65
+ }
66
+ if (Array.isArray(value)) {
67
+ const {
68
+ length
69
+ } = value;
70
+ const arr = new Array(length);
71
+ let edited = false;
72
+ for (let i = 0; i < length; i++) {
73
+ const newValue = clone(value[i], i, value);
74
+ if (newValue === REMOVE) {
75
+ edited = true;
76
+ }
77
+ arr[i] = newValue;
78
+ }
79
+ return edited ? arr.filter(arrayFilter) : arr;
80
+ }
81
+ if (isIterableObject(value)) {
82
+ const newObject = {};
83
+ for (const key of Object.keys(value)) {
84
+ const newValue = clone(value[key], key, value);
85
+ if (newValue !== undefined && newValue !== REMOVE) {
86
+ newObject[key] = newValue;
87
+ }
88
+ }
89
+ return newObject;
90
+ }
91
+ return value;
92
+ };
93
+ return clone(value, undefined, undefined);
3
94
  }
package/es/types.js CHANGED
@@ -19,6 +19,14 @@ export function isRecord(maybeRecord) {
19
19
  return isPlainObject(maybeRecord);
20
20
  }
21
21
 
22
+ /**
23
+ A guard for objects that ensures they are iterable records objects
24
+ not as strict as isRecord but better performance when that matters
25
+ */
26
+ export function isIterableObject(x) {
27
+ return Boolean(x) && typeof x === 'object';
28
+ }
29
+
22
30
  // https://stackoverflow.com/questions/50573891/maybe-a-type-in-typescript
23
31
 
24
32
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takeshape/util",
3
- "version": "9.103.27",
3
+ "version": "9.104.0",
4
4
  "description": "Shared utilities",
5
5
  "homepage": "https://www.takeshape.io",
6
6
  "repository": {
@@ -33,7 +33,7 @@
33
33
  "shortid": "^2.2.16",
34
34
  "tiny-invariant": "^1.2.0",
35
35
  "url-parse": "^1.5.3",
36
- "@takeshape/routing": "9.103.27"
36
+ "@takeshape/routing": "9.104.0"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/classnames": "^2.2.9",
@@ -46,7 +46,7 @@
46
46
  "@types/prismjs": "^1.16.2",
47
47
  "@types/shortid": "^0.0.29",
48
48
  "stripe": "13.8.0",
49
- "@takeshape/typescript-jest-junit-reporter": "9.103.27"
49
+ "@takeshape/typescript-jest-junit-reporter": "9.104.0"
50
50
  },
51
51
  "engines": {
52
52
  "node": ">=16"