@ezez/utils 3.0.0 → 4.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/CHANGELOG.md +20 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/omit.d.ts +1 -1
- package/dist/omit.d.ts.map +1 -1
- package/dist/omit.js.map +1 -1
- package/dist/replaceDeep.d.ts +5 -1
- package/dist/replaceDeep.d.ts.map +1 -1
- package/dist/replaceDeep.js +3 -20
- package/dist/replaceDeep.js.map +1 -1
- package/dist/replaceDeepByFn.d.ts +7 -0
- package/dist/replaceDeepByFn.d.ts.map +1 -0
- package/dist/replaceDeepByFn.js +47 -0
- package/dist/replaceDeepByFn.js.map +1 -0
- package/dist/serialize.d.ts.map +1 -1
- package/dist/serialize.js +56 -18
- package/dist/serialize.js.map +1 -1
- package/dist/trim.d.ts +3 -0
- package/dist/trim.d.ts.map +1 -0
- package/dist/trim.js +10 -0
- package/dist/trim.js.map +1 -0
- package/dist/trimEnd.d.ts +3 -0
- package/dist/trimEnd.d.ts.map +1 -0
- package/dist/trimEnd.js +12 -0
- package/dist/trimEnd.js.map +1 -0
- package/dist/trimStart.d.ts +3 -0
- package/dist/trimStart.d.ts.map +1 -0
- package/dist/trimStart.js +12 -0
- package/dist/trimStart.js.map +1 -0
- package/dist/utils/utils.d.ts +6 -0
- package/dist/utils/utils.d.ts.map +1 -0
- package/dist/utils/utils.js +10 -0
- package/dist/utils/utils.js.map +1 -0
- package/docs/assets/search.js +1 -1
- package/docs/functions/cap.html +8 -5
- package/docs/functions/capitalize.html +8 -5
- package/docs/functions/coalesce.html +8 -5
- package/docs/functions/compareArrays.html +8 -5
- package/docs/functions/compareProps.html +8 -5
- package/docs/functions/deserialize.html +8 -5
- package/docs/functions/ensureArray.html +8 -5
- package/docs/functions/ensureDate.html +8 -5
- package/docs/functions/ensureError.html +8 -5
- package/docs/functions/ensurePrefix.html +8 -5
- package/docs/functions/ensureSuffix.html +8 -5
- package/docs/functions/ensureTimestamp.html +8 -5
- package/docs/functions/escapeRegExp.html +8 -5
- package/docs/functions/formatDate.html +8 -5
- package/docs/functions/get.html +8 -5
- package/docs/functions/getMultiple.html +8 -5
- package/docs/functions/insertSeparator.html +8 -5
- package/docs/functions/isEmpty.html +8 -5
- package/docs/functions/isNumericString.html +8 -5
- package/docs/functions/isPlainObject.html +8 -5
- package/docs/functions/last.html +8 -5
- package/docs/functions/later-1.html +8 -5
- package/docs/functions/mapAsync.html +8 -5
- package/docs/functions/mapValues.html +8 -5
- package/docs/functions/match.html +8 -5
- package/docs/functions/merge.html +16 -13
- package/docs/functions/mostFrequent.html +8 -5
- package/docs/functions/noop.html +8 -5
- package/docs/functions/occurrences.html +8 -5
- package/docs/functions/omit.html +14 -7
- package/docs/functions/pick.html +9 -6
- package/docs/functions/pull.html +8 -5
- package/docs/functions/remove.html +8 -5
- package/docs/functions/removeCommonProperties.html +8 -5
- package/docs/functions/replace.html +8 -5
- package/docs/functions/replaceDeep.html +19 -7
- package/docs/functions/rethrow.html +8 -5
- package/docs/functions/round.html +8 -5
- package/docs/functions/safe.html +9 -6
- package/docs/functions/sample.html +8 -5
- package/docs/functions/samples.html +8 -5
- package/docs/functions/scale.html +8 -5
- package/docs/functions/seq.html +8 -5
- package/docs/functions/seqEarlyBreak.html +8 -5
- package/docs/functions/serialize.html +8 -5
- package/docs/functions/set.html +8 -5
- package/docs/functions/setImmutable.html +8 -5
- package/docs/functions/shuffle.html +8 -5
- package/docs/functions/sortBy.html +8 -5
- package/docs/functions/sortProps.html +8 -5
- package/docs/functions/stripPrefix.html +8 -5
- package/docs/functions/stripSuffix.html +8 -5
- package/docs/functions/throttle.html +8 -5
- package/docs/functions/toggle.html +8 -5
- package/docs/functions/trim.html +152 -0
- package/docs/functions/trimEnd.html +152 -0
- package/docs/functions/trimStart.html +152 -0
- package/docs/functions/truthy.html +8 -5
- package/docs/functions/unique.html +8 -5
- package/docs/functions/wait.html +8 -5
- package/docs/functions/waitFor.html +8 -5
- package/docs/functions/waitSync.html +8 -5
- package/docs/index.html +7 -4
- package/docs/interfaces/ComparePropsOptions.html +6 -6
- package/docs/interfaces/GetMultipleSource.html +8 -5
- package/docs/interfaces/GetSource.html +8 -5
- package/docs/interfaces/IsNumericStringOptions.html +9 -9
- package/docs/interfaces/OccurencesOptions.html +6 -6
- package/docs/interfaces/SetImmutableSource.html +8 -5
- package/docs/interfaces/SetSource.html +8 -5
- package/docs/interfaces/ThrottleOptions.html +7 -7
- package/docs/interfaces/ThrottledFunctionExtras.html +7 -7
- package/docs/modules.html +10 -4
- package/docs/pages/CHANGELOG.html +113 -64
- package/docs/pages/Introduction.html +7 -4
- package/docs/types/CustomDeserializers.html +8 -5
- package/docs/types/CustomSerializers.html +8 -5
- package/docs/types/Later.html +8 -5
- package/docs/types/MapValuesFn.html +8 -5
- package/docs/types/MatchCallback.html +8 -5
- package/docs/types/SeqEarlyBreaker.html +8 -5
- package/docs/types/SeqFn.html +8 -5
- package/docs/types/SeqFunctions.html +8 -5
- package/docs/types/SetImmutablePath.html +8 -5
- package/docs/types/ThrottledFunction.html +8 -5
- package/docs/variables/mapValuesUNSET.html +8 -5
- package/docs/variables/mergeUNSET.html +8 -5
- package/esm/index.d.ts +3 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +3 -0
- package/esm/index.js.map +1 -1
- package/esm/omit.d.ts +1 -1
- package/esm/omit.d.ts.map +1 -1
- package/esm/omit.js.map +1 -1
- package/esm/replaceDeep.d.ts +5 -1
- package/esm/replaceDeep.d.ts.map +1 -1
- package/esm/replaceDeep.js +3 -20
- package/esm/replaceDeep.js.map +1 -1
- package/esm/replaceDeepByFn.d.ts +7 -0
- package/esm/replaceDeepByFn.d.ts.map +1 -0
- package/esm/replaceDeepByFn.js +44 -0
- package/esm/replaceDeepByFn.js.map +1 -0
- package/esm/serialize.d.ts.map +1 -1
- package/esm/serialize.js +56 -18
- package/esm/serialize.js.map +1 -1
- package/esm/trim.d.ts +3 -0
- package/esm/trim.d.ts.map +1 -0
- package/esm/trim.js +7 -0
- package/esm/trim.js.map +1 -0
- package/esm/trimEnd.d.ts +3 -0
- package/esm/trimEnd.d.ts.map +1 -0
- package/esm/trimEnd.js +9 -0
- package/esm/trimEnd.js.map +1 -0
- package/esm/trimStart.d.ts +3 -0
- package/esm/trimStart.d.ts.map +1 -0
- package/esm/trimStart.js +9 -0
- package/esm/trimStart.js.map +1 -0
- package/esm/utils/utils.d.ts +6 -0
- package/esm/utils/utils.d.ts.map +1 -0
- package/esm/utils/utils.js +7 -0
- package/esm/utils/utils.js.map +1 -0
- package/package.json +1 -1
- package/src/deserialize.spec.ts +12 -0
- package/src/index.ts +3 -0
- package/src/omit.ts +8 -2
- package/src/pick.ts +1 -1
- package/src/replaceDeep.spec.ts +91 -0
- package/src/replaceDeep.ts +22 -27
- package/src/replaceDeepByFn.spec.ts +162 -0
- package/src/replaceDeepByFn.ts +93 -0
- package/src/serialize.spec.ts +42 -0
- package/src/serialize.ts +65 -18
- package/src/trim.spec.ts +22 -0
- package/src/trim.ts +23 -0
- package/src/trimEnd.spec.ts +20 -0
- package/src/trimEnd.ts +22 -0
- package/src/trimStart.spec.ts +20 -0
- package/src/trimStart.ts +22 -0
- package/src/utils/utils.ts +11 -0
package/esm/serialize.js
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
import { sortProps } from "./sortProps.js";
|
|
2
|
+
import { replaceDeepByFn } from "./replaceDeepByFn.js";
|
|
3
|
+
import { isPlainObject } from "./isPlainObject.js";
|
|
4
|
+
import { DataWrapper } from "./utils/utils.js";
|
|
2
5
|
const serialize = (data, customSerializers, options) => {
|
|
6
|
+
const sourceData = Object.keys(customSerializers ?? {}).length
|
|
7
|
+
? replaceDeepByFn(data, value => {
|
|
8
|
+
if (["string", "number", "bigint", "undefined", "boolean"].includes(typeof value)) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
if (value === null || Array.isArray(value)) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
if (isPlainObject(value)) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
const serializerKeys = Object.keys(customSerializers ?? {});
|
|
18
|
+
for (const key of serializerKeys) {
|
|
19
|
+
const serialized = customSerializers[key](value);
|
|
20
|
+
if (typeof serialized === "string") {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
}, value => new DataWrapper(value))
|
|
26
|
+
: data;
|
|
3
27
|
const replacer = (_key, value) => {
|
|
4
28
|
if (typeof value === "string") {
|
|
5
29
|
return `s:${value}`;
|
|
@@ -19,40 +43,54 @@ const serialize = (data, customSerializers, options) => {
|
|
|
19
43
|
if (value === null) {
|
|
20
44
|
return "l:";
|
|
21
45
|
}
|
|
46
|
+
if (Array.isArray(value)) {
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
if (isPlainObject(value)) {
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
22
52
|
const serializerKeys = Object.keys(customSerializers ?? {});
|
|
23
53
|
for (const key of serializerKeys) {
|
|
24
|
-
const serialized = customSerializers[key](value);
|
|
54
|
+
const serialized = customSerializers[key](value instanceof DataWrapper ? value.data : value);
|
|
25
55
|
if (typeof serialized === "string") {
|
|
26
56
|
return `${key}:${serialized}`;
|
|
27
57
|
}
|
|
58
|
+
if (serialized !== null) {
|
|
59
|
+
throw new Error(`Custom serializer for key ${key} returned a non-string value: ${String(serialized)}`);
|
|
60
|
+
}
|
|
28
61
|
}
|
|
29
62
|
if (typeof value === "object") {
|
|
30
63
|
return value;
|
|
31
64
|
}
|
|
32
65
|
throw new Error(`Unsupported data type: ${typeof value}`);
|
|
33
66
|
};
|
|
34
|
-
if (
|
|
35
|
-
|| typeof
|
|
36
|
-
|| typeof
|
|
37
|
-
|| typeof
|
|
38
|
-
|| typeof
|
|
39
|
-
|| typeof
|
|
40
|
-
|| Array.isArray(
|
|
41
|
-
return JSON.stringify(
|
|
67
|
+
if (sourceData == null
|
|
68
|
+
|| typeof sourceData === "string"
|
|
69
|
+
|| typeof sourceData === "number"
|
|
70
|
+
|| typeof sourceData === "bigint"
|
|
71
|
+
|| typeof sourceData === "undefined"
|
|
72
|
+
|| typeof sourceData === "boolean"
|
|
73
|
+
|| Array.isArray(sourceData)) {
|
|
74
|
+
return JSON.stringify(sourceData, replacer);
|
|
42
75
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
76
|
+
if (!isPlainObject(sourceData)) {
|
|
77
|
+
const serializerKeysGlobal = Object.keys(customSerializers ?? {});
|
|
78
|
+
for (const key of serializerKeysGlobal) {
|
|
79
|
+
const serialized = customSerializers[key](sourceData instanceof DataWrapper ? sourceData.data : sourceData);
|
|
80
|
+
if (typeof serialized === "string") {
|
|
81
|
+
return `"${key}:${serialized}"`;
|
|
82
|
+
}
|
|
83
|
+
if (serialized !== null) {
|
|
84
|
+
throw new Error(`Custom serializer for key ${key} returned a non-string value: ${String(serialized)}`);
|
|
85
|
+
}
|
|
48
86
|
}
|
|
49
87
|
}
|
|
50
|
-
if (typeof
|
|
88
|
+
if (typeof sourceData === "object") {
|
|
51
89
|
return JSON.stringify(options?.sortProps === false
|
|
52
|
-
?
|
|
53
|
-
: sortProps(
|
|
90
|
+
? sourceData
|
|
91
|
+
: sortProps(sourceData), replacer);
|
|
54
92
|
}
|
|
55
|
-
throw new Error(`Unsupported data type: ${typeof
|
|
93
|
+
throw new Error(`Unsupported data type: ${typeof sourceData}`);
|
|
56
94
|
};
|
|
57
95
|
export { serialize };
|
|
58
96
|
//# sourceMappingURL=serialize.js.map
|
package/esm/serialize.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serialize.js","sourceRoot":"","sources":["../src/serialize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"serialize.js","sourceRoot":"","sources":["../src/serialize.ts"],"names":[],"mappings":"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"}
|
package/esm/trim.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trim.d.ts","sourceRoot":"","sources":["../src/trim.ts"],"names":[],"mappings":"AAgBA,QAAA,MAAM,IAAI,WAAY,MAAM,cAAc,MAAM,WAE/C,CAAC;AAEF,OAAO,EACH,IAAI,GACP,CAAC"}
|
package/esm/trim.js
ADDED
package/esm/trim.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trim.js","sourceRoot":"","sources":["../src/trim.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAevC,MAAM,IAAI,GAAG,CAAC,MAAc,EAAE,UAAkB,EAAE,EAAE;IAChD,OAAO,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,UAAU,CAAC,CAAC;AAC9D,CAAC,CAAC;AAEF,OAAO,EACH,IAAI,GACP,CAAC"}
|
package/esm/trimEnd.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trimEnd.d.ts","sourceRoot":"","sources":["../src/trimEnd.ts"],"names":[],"mappings":"AAWA,QAAA,MAAM,OAAO,WAAY,MAAM,cAAc,MAAM,WAMlD,CAAC;AAEF,OAAO,EACH,OAAO,GACV,CAAC"}
|
package/esm/trimEnd.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trimEnd.js","sourceRoot":"","sources":["../src/trimEnd.ts"],"names":[],"mappings":"AAWA,MAAM,OAAO,GAAG,CAAC,MAAc,EAAE,UAAkB,EAAE,EAAE;IACnD,IAAI,CAAC,GAAG,MAAM,CAAC;IACf,OAAO,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE;QAC3B,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;KACtC;IACD,OAAO,CAAC,CAAC;AACb,CAAC,CAAC;AAEF,OAAO,EACH,OAAO,GACV,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trimStart.d.ts","sourceRoot":"","sources":["../src/trimStart.ts"],"names":[],"mappings":"AAWA,QAAA,MAAM,SAAS,WAAY,MAAM,cAAc,MAAM,WAMpD,CAAC;AAEF,OAAO,EACH,SAAS,GACZ,CAAC"}
|
package/esm/trimStart.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trimStart.js","sourceRoot":"","sources":["../src/trimStart.ts"],"names":[],"mappings":"AAWA,MAAM,SAAS,GAAG,CAAC,MAAc,EAAE,UAAkB,EAAE,EAAE;IACrD,IAAI,CAAC,GAAG,MAAM,CAAC;IACf,OAAO,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;QAC7B,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;KAClC;IACD,OAAO,CAAC,CAAC;AACb,CAAC,CAAC;AAEF,OAAO,EACH,SAAS,GACZ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils/utils.ts"],"names":[],"mappings":"AAAA,cAAM,WAAW,CAAC,CAAC;IACR,IAAI,EAAE,CAAC,CAAC;gBAEI,IAAI,EAAE,CAAC;CAG7B;AAED,OAAO,EACH,WAAW,GACd,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils/utils.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW;IAGb,YAAmB,IAAO;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACrB,CAAC;CACJ;AAED,OAAO,EACH,WAAW,GACd,CAAC"}
|
package/package.json
CHANGED
package/src/deserialize.spec.ts
CHANGED
|
@@ -66,4 +66,16 @@ describe("deserialize", () => {
|
|
|
66
66
|
it("throws on unknown data type", () => {
|
|
67
67
|
must(() => deserialize(`"v:test"`)).throw("Unsupported data type: v");
|
|
68
68
|
});
|
|
69
|
+
|
|
70
|
+
it("supports deserializers with things like Date", async () => {
|
|
71
|
+
const customSerializers: CustomDeserializers = {
|
|
72
|
+
D: (value) => {
|
|
73
|
+
return new Date(Number(value));
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const result = deserialize(`"D:1714398481437"`, customSerializers);
|
|
78
|
+
must(result).be.instanceof(Date);
|
|
79
|
+
must(result.getTime()).equal(1714398481437);
|
|
80
|
+
});
|
|
69
81
|
});
|
package/src/index.ts
CHANGED
|
@@ -52,6 +52,9 @@ export * from "./stripPrefix.js";
|
|
|
52
52
|
export * from "./stripSuffix.js";
|
|
53
53
|
export * from "./throttle.js";
|
|
54
54
|
export * from "./toggle.js";
|
|
55
|
+
export * from "./trim.js";
|
|
56
|
+
export * from "./trimEnd.js";
|
|
57
|
+
export * from "./trimStart.js";
|
|
55
58
|
export * from "./truthy.js";
|
|
56
59
|
export * from "./unique.js";
|
|
57
60
|
export * from "./wait.js";
|
package/src/omit.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
// TODO verify & maybe fix typings when object is an Array
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Returns
|
|
4
|
+
* Returns a cloned source object but without specified properties.
|
|
5
|
+
*
|
|
6
|
+
* TypeScript tip: if you want to omit properties that TS think does not exist in the object, call the function like
|
|
7
|
+
* that:
|
|
8
|
+
* ```typescript
|
|
9
|
+
* omit<Record<string, unknown>>(source, ["property"]);
|
|
10
|
+
* ```
|
|
5
11
|
*
|
|
6
12
|
* @param {Object} object - source object
|
|
7
13
|
* @param {Array.<string>} props - properties to skip
|
|
@@ -13,7 +19,7 @@
|
|
|
13
19
|
* // { 1: "world" }
|
|
14
20
|
* @returns {Object} - new object without given properties
|
|
15
21
|
*/
|
|
16
|
-
const omit = <T extends object, K extends keyof T>(
|
|
22
|
+
const omit = <T extends object, K extends keyof T = keyof T>(
|
|
17
23
|
object: T | null, props: K[],
|
|
18
24
|
): T extends null ? { [key: string]: never } : Omit<T, K> => {
|
|
19
25
|
if (!object || (typeof object !== "object" && typeof object !== "function")) {
|
package/src/pick.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// TODO verify & maybe fix typings when object is an Array
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Returns new object with
|
|
4
|
+
* Returns a new object with given properties copied from a source object.
|
|
5
5
|
*
|
|
6
6
|
* @param {Object} object - source object
|
|
7
7
|
* @param {Array.<string>} props - properties to copy
|
package/src/replaceDeep.spec.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { replaceDeep } from "./replaceDeep";
|
|
2
2
|
|
|
3
|
+
class MyClass {
|
|
4
|
+
public value: number;
|
|
5
|
+
|
|
6
|
+
public constructor(value: number) {
|
|
7
|
+
this.value = value;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
3
11
|
describe("replaceDeep", () => {
|
|
4
12
|
it("should replace given value in a deep object", () => {
|
|
5
13
|
const source = [
|
|
@@ -68,4 +76,87 @@ describe("replaceDeep", () => {
|
|
|
68
76
|
b: 123,
|
|
69
77
|
});
|
|
70
78
|
});
|
|
79
|
+
|
|
80
|
+
it("should allow to replace nils", async () => {
|
|
81
|
+
must(replaceDeep(null, null, 300)).equal(300);
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
|
|
83
|
+
must(replaceDeep(undefined, undefined, 300)).equal(300);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("does not mutate original object", () => {
|
|
87
|
+
const source = {
|
|
88
|
+
a: 1,
|
|
89
|
+
b: {
|
|
90
|
+
c: 2,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
const result = replaceDeep(source, 2, 3);
|
|
94
|
+
must(result).not.equal(source);
|
|
95
|
+
must(result.b).not.equal(source.b);
|
|
96
|
+
must(result).eql({
|
|
97
|
+
a: 1,
|
|
98
|
+
b: {
|
|
99
|
+
c: 3,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("does not mutate original array", async () => {
|
|
105
|
+
const source = [1, 2, 3, [2, 3]];
|
|
106
|
+
const result = replaceDeep(source, 2, 4);
|
|
107
|
+
must(result).not.equal(source);
|
|
108
|
+
must(result[3]).not.equal(source[3]);
|
|
109
|
+
must(result).eql([1, 4, 3, [4, 3]]);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("mutates original object when enabled", () => {
|
|
113
|
+
const source = {
|
|
114
|
+
a: 1,
|
|
115
|
+
b: {
|
|
116
|
+
c: 2,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
const result = replaceDeep(source, 2, 3, { mutate: true });
|
|
120
|
+
must(result).equal(source);
|
|
121
|
+
must(result.b).equal(source.b);
|
|
122
|
+
must(result).eql({
|
|
123
|
+
a: 1,
|
|
124
|
+
b: {
|
|
125
|
+
c: 3,
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it("mutates original array when enabled", async () => {
|
|
131
|
+
const source = [1, 2, 3, [2, 3]];
|
|
132
|
+
const result = replaceDeep(source, 2, 4, { mutate: true });
|
|
133
|
+
must(result).equal(source);
|
|
134
|
+
must(result[3]).equal(source[3]);
|
|
135
|
+
must(result).eql([1, 4, 3, [4, 3]]);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("does not get into instances by default", async () => {
|
|
139
|
+
const source = new MyClass(100);
|
|
140
|
+
const result = replaceDeep(source, 100, 200);
|
|
141
|
+
must(result).equal(source);
|
|
142
|
+
must(source.value).equal(100);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("gets into instances when allowed", async () => {
|
|
146
|
+
const source = new MyClass(100);
|
|
147
|
+
const result = replaceDeep(source, 100, 200, {
|
|
148
|
+
replaceInstancesProps: true,
|
|
149
|
+
mutate: true,
|
|
150
|
+
});
|
|
151
|
+
must(result).equal(source);
|
|
152
|
+
must(source.value).equal(200);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("requires `mutate` option if `replaceInstancesProps` is defined", async () => {
|
|
156
|
+
const source = new MyClass(100);
|
|
157
|
+
must(() => replaceDeep(source, 100, 200, {
|
|
158
|
+
replaceInstancesProps: true,
|
|
159
|
+
mutate: false,
|
|
160
|
+
})).throw("`replaceInstancesProps` option requires `mutate` to be enabled");
|
|
161
|
+
});
|
|
71
162
|
});
|
package/src/replaceDeep.ts
CHANGED
|
@@ -1,8 +1,26 @@
|
|
|
1
|
+
import { replaceDeepByFn } from "./replaceDeepByFn.js";
|
|
2
|
+
|
|
3
|
+
type Options = {
|
|
4
|
+
/**
|
|
5
|
+
* If true, the source objects and arrays will be mutated. Default is false.
|
|
6
|
+
*/
|
|
7
|
+
mutate?: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* If true, the function will go into instances for replacement. Otherwise, it will only replace properties of plain
|
|
10
|
+
* objects. Default is false.
|
|
11
|
+
* Warning: This option requires `mutate` to be enabled, because we can't clone instances.
|
|
12
|
+
*/
|
|
13
|
+
replaceInstancesProps?: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
1
16
|
/**
|
|
2
17
|
* Replaces all occurrences of `search` with `value` in `source` object/array. Comparison is done with `Object.is`.
|
|
3
18
|
* If `source` is exactly the `search` a `value` will be returned. It does not do a substring replacements.
|
|
4
19
|
*
|
|
5
|
-
*
|
|
20
|
+
* Warnings:
|
|
21
|
+
* - By default, it does not mutate the `source`/deep objects/arrays, but it can be enabled with `mutate` option.
|
|
22
|
+
* - By default, it does not go into instances for replacement, only plain objects.
|
|
23
|
+
* - If your instances are cross-referenced, you may end up in an infinite loop.
|
|
6
24
|
*
|
|
7
25
|
* TypeScript users: This is way too dynamic to type properly, therefore, typing assumes the most basic form of
|
|
8
26
|
* replacement where search and value are of the same type. If that's not the case for you - you'll have to typecast.
|
|
@@ -10,33 +28,10 @@
|
|
|
10
28
|
* @param source - source object/array/value
|
|
11
29
|
* @param search - value to search for
|
|
12
30
|
* @param value - value to replace with
|
|
31
|
+
* @param options - optional options
|
|
13
32
|
*/
|
|
14
|
-
const replaceDeep = <T>(source: T, search: unknown, value: unknown): T => {
|
|
15
|
-
|
|
16
|
-
return value as T;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (source == null) {
|
|
20
|
-
return source;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (typeof source === "object") {
|
|
24
|
-
if (Array.isArray(source)) {
|
|
25
|
-
for (let i = 0; i < source.length; i++) {
|
|
26
|
-
// eslint-disable-next-line no-param-reassign,@typescript-eslint/no-unsafe-assignment
|
|
27
|
-
source[i] = replaceDeep(source[i], search, value);
|
|
28
|
-
}
|
|
29
|
-
return source;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return Object.keys(source).reduce<Record<string, unknown>>((acc, key) => {
|
|
33
|
-
// eslint-disable-next-line no-param-reassign
|
|
34
|
-
acc[key] = replaceDeep((source as Record<string, unknown>)[key], search, value);
|
|
35
|
-
return acc;
|
|
36
|
-
}, {}) as T;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return source;
|
|
33
|
+
const replaceDeep = <T>(source: T, search: unknown, value: unknown, options?: Options): T => {
|
|
34
|
+
return replaceDeepByFn(source, (v) => Object.is(v, search), () => value, options);
|
|
40
35
|
};
|
|
41
36
|
|
|
42
37
|
export {
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { replaceDeepByFn } from "./replaceDeepByFn";
|
|
2
|
+
|
|
3
|
+
class MyClass {
|
|
4
|
+
public value: number;
|
|
5
|
+
|
|
6
|
+
public constructor(value: number) {
|
|
7
|
+
this.value = value;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
describe("replaceDeepByFn", () => {
|
|
12
|
+
it("should replace given value in a deep object", () => {
|
|
13
|
+
const source = [
|
|
14
|
+
99,
|
|
15
|
+
100,
|
|
16
|
+
{
|
|
17
|
+
favouriteBook: {
|
|
18
|
+
title: "The Ring of The Lord",
|
|
19
|
+
price: 100,
|
|
20
|
+
},
|
|
21
|
+
otherBooks: [
|
|
22
|
+
{
|
|
23
|
+
title: "Parry Hotter",
|
|
24
|
+
price: 50,
|
|
25
|
+
tag: "100",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
title: "The Hobbyte 100",
|
|
29
|
+
price: [100],
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
must(replaceDeepByFn(source, v => v === 100, () => 200)).eql([
|
|
36
|
+
99,
|
|
37
|
+
200,
|
|
38
|
+
{
|
|
39
|
+
favouriteBook: {
|
|
40
|
+
title: "The Ring of The Lord",
|
|
41
|
+
price: 200,
|
|
42
|
+
},
|
|
43
|
+
otherBooks: [
|
|
44
|
+
{
|
|
45
|
+
title: "Parry Hotter",
|
|
46
|
+
price: 50,
|
|
47
|
+
tag: "100",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
title: "The Hobbyte 100",
|
|
51
|
+
price: [200],
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
]);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("should leave primitives as-is unless they equal to the search value", () => {
|
|
59
|
+
must(replaceDeepByFn(100, v => v === 200, () => 300)).equal(100);
|
|
60
|
+
must(replaceDeepByFn(200, v => v === 200, () => 300)).equal(300);
|
|
61
|
+
must(replaceDeepByFn("100", v => v === 200, () => 300)).equal("100");
|
|
62
|
+
// ESLINT BUG: (see replaceDeep.spec.ts)
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
|
|
64
|
+
must(replaceDeepByFn(undefined, v => v === 200, () => 300)).equal(undefined);
|
|
65
|
+
must(replaceDeepByFn(null, v => v === 200, () => 300)).equal(null);
|
|
66
|
+
must(replaceDeepByFn(true, v => v === 200, () => 300)).equal(true);
|
|
67
|
+
must(replaceDeepByFn(666n, v => v === 200, () => 300)).equal(666n);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("should work with nans", async () => {
|
|
71
|
+
must(replaceDeepByFn({
|
|
72
|
+
a: NaN,
|
|
73
|
+
b: 123,
|
|
74
|
+
}, v => Number.isNaN(v), () => 300)).eql({
|
|
75
|
+
a: 300,
|
|
76
|
+
b: 123,
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("should allow to replace nils", async () => {
|
|
81
|
+
must(replaceDeepByFn(null, v => v === null, () => 300)).equal(300);
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
|
|
83
|
+
must(replaceDeepByFn(undefined, v => v === undefined, () => 300)).equal(300);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("does not mutate the original object", () => {
|
|
87
|
+
const source = {
|
|
88
|
+
a: 1,
|
|
89
|
+
b: {
|
|
90
|
+
c: 2,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
const result = replaceDeepByFn(source, v => v === 2, () => 3);
|
|
94
|
+
must(result).not.equal(source);
|
|
95
|
+
must(result.b).not.equal(source.b);
|
|
96
|
+
must(result).eql({
|
|
97
|
+
a: 1,
|
|
98
|
+
b: {
|
|
99
|
+
c: 3,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("does not mutate original array", async () => {
|
|
105
|
+
const source = [1, 2, 3, [2, 3]];
|
|
106
|
+
const result = replaceDeepByFn(source, v => v === 2, () => 4);
|
|
107
|
+
must(result).not.equal(source);
|
|
108
|
+
must(result[3]).not.equal(source[3]);
|
|
109
|
+
must(result).eql([1, 4, 3, [4, 3]]);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("mutates the original object when enabled", () => {
|
|
113
|
+
const source = {
|
|
114
|
+
a: 1,
|
|
115
|
+
b: {
|
|
116
|
+
c: 2,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
const result = replaceDeepByFn(source, v => v === 2, () => 3, { mutate: true });
|
|
120
|
+
must(result).equal(source);
|
|
121
|
+
must(result.b).equal(source.b);
|
|
122
|
+
must(result).eql({
|
|
123
|
+
a: 1,
|
|
124
|
+
b: {
|
|
125
|
+
c: 3,
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it("mutates original array when enabled", async () => {
|
|
131
|
+
const source = [1, 2, 3, [2, 3]];
|
|
132
|
+
const result = replaceDeepByFn(source, v => v === 2, () => 4, { mutate: true });
|
|
133
|
+
must(result).equal(source);
|
|
134
|
+
must(result[3]).equal(source[3]);
|
|
135
|
+
must(result).eql([1, 4, 3, [4, 3]]);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("does not get into instances by default", async () => {
|
|
139
|
+
const source = new MyClass(100);
|
|
140
|
+
const result = replaceDeepByFn(source, v => v === 100, () => 200);
|
|
141
|
+
must(result).equal(source);
|
|
142
|
+
must(source.value).equal(100);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("gets into instances when allowed", async () => {
|
|
146
|
+
const source = new MyClass(100);
|
|
147
|
+
const result = replaceDeepByFn(source, v => v === 100, () => 200, {
|
|
148
|
+
replaceInstancesProps: true,
|
|
149
|
+
mutate: true,
|
|
150
|
+
});
|
|
151
|
+
must(result).equal(source);
|
|
152
|
+
must(source.value).equal(200);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("requires `mutate` option if `replaceInstancesProps` is defined", async () => {
|
|
156
|
+
const source = new MyClass(100);
|
|
157
|
+
must(() => replaceDeepByFn(source, v => v === 100, () => 200, {
|
|
158
|
+
replaceInstancesProps: true,
|
|
159
|
+
mutate: false,
|
|
160
|
+
})).throw("`replaceInstancesProps` option requires `mutate` to be enabled");
|
|
161
|
+
});
|
|
162
|
+
});
|