@simplysm/core-common 13.0.99 → 14.0.1
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/common.types.d.ts +14 -14
- package/dist/common.types.js +2 -1
- package/dist/common.types.js.map +1 -6
- package/dist/env.d.ts +5 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +12 -8
- package/dist/env.js.map +1 -6
- package/dist/errors/argument-error.d.ts +10 -10
- package/dist/errors/argument-error.d.ts.map +1 -1
- package/dist/errors/argument-error.js +31 -14
- package/dist/errors/argument-error.js.map +1 -6
- package/dist/errors/not-implemented-error.d.ts +8 -8
- package/dist/errors/not-implemented-error.js +30 -12
- package/dist/errors/not-implemented-error.js.map +1 -6
- package/dist/errors/sd-error.d.ts +10 -10
- package/dist/errors/sd-error.d.ts.map +1 -1
- package/dist/errors/sd-error.js +45 -24
- package/dist/errors/sd-error.js.map +1 -6
- package/dist/errors/timeout-error.d.ts +10 -10
- package/dist/errors/timeout-error.js +34 -15
- package/dist/errors/timeout-error.js.map +1 -6
- package/dist/extensions/arr-ext.d.ts +2 -2
- package/dist/extensions/arr-ext.helpers.d.ts +10 -10
- package/dist/extensions/arr-ext.helpers.js +112 -89
- package/dist/extensions/arr-ext.helpers.js.map +1 -6
- package/dist/extensions/arr-ext.js +458 -422
- package/dist/extensions/arr-ext.js.map +1 -6
- package/dist/extensions/arr-ext.types.d.ts +57 -57
- package/dist/extensions/arr-ext.types.d.ts.map +1 -1
- package/dist/extensions/arr-ext.types.js +6 -1
- package/dist/extensions/arr-ext.types.js.map +1 -6
- package/dist/extensions/map-ext.d.ts +16 -16
- package/dist/extensions/map-ext.js +27 -22
- package/dist/extensions/map-ext.js.map +1 -6
- package/dist/extensions/set-ext.d.ts +11 -11
- package/dist/extensions/set-ext.js +32 -25
- package/dist/extensions/set-ext.js.map +1 -6
- package/dist/features/debounce-queue.d.ts +17 -17
- package/dist/features/debounce-queue.js +98 -70
- package/dist/features/debounce-queue.js.map +1 -6
- package/dist/features/event-emitter.d.ts +20 -20
- package/dist/features/event-emitter.js +101 -78
- package/dist/features/event-emitter.js.map +1 -6
- package/dist/features/serial-queue.d.ts +11 -11
- package/dist/features/serial-queue.js +78 -57
- package/dist/features/serial-queue.js.map +1 -6
- package/dist/globals.d.ts +4 -4
- package/dist/globals.js +9 -1
- package/dist/globals.js.map +1 -6
- package/dist/index.js +28 -27
- package/dist/index.js.map +1 -6
- package/dist/types/date-only.d.ts +64 -64
- package/dist/types/date-only.d.ts.map +1 -1
- package/dist/types/date-only.js +263 -252
- package/dist/types/date-only.js.map +1 -6
- package/dist/types/date-time.d.ts +36 -36
- package/dist/types/date-time.d.ts.map +1 -1
- package/dist/types/date-time.js +196 -288
- package/dist/types/date-time.js.map +1 -6
- package/dist/types/lazy-gc-map.d.ts +26 -26
- package/dist/types/lazy-gc-map.d.ts.map +1 -1
- package/dist/types/lazy-gc-map.js +202 -159
- package/dist/types/lazy-gc-map.js.map +1 -6
- package/dist/types/time.d.ts +23 -23
- package/dist/types/time.d.ts.map +1 -1
- package/dist/types/time.js +169 -158
- package/dist/types/time.js.map +1 -6
- package/dist/types/uuid.d.ts +11 -11
- package/dist/types/uuid.d.ts.map +1 -1
- package/dist/types/uuid.js +95 -70
- package/dist/types/uuid.js.map +1 -6
- package/dist/utils/bytes.d.ts +17 -17
- package/dist/utils/bytes.js +137 -81
- package/dist/utils/bytes.js.map +1 -6
- package/dist/utils/date-format.d.ts +40 -40
- package/dist/utils/date-format.js +187 -101
- package/dist/utils/date-format.js.map +1 -6
- package/dist/utils/error.d.ts +4 -4
- package/dist/utils/error.js +11 -6
- package/dist/utils/error.js.map +1 -6
- package/dist/utils/json.d.ts +19 -19
- package/dist/utils/json.js +187 -135
- package/dist/utils/json.js.map +1 -6
- package/dist/utils/num.d.ts +20 -20
- package/dist/utils/num.js +76 -34
- package/dist/utils/num.js.map +1 -6
- package/dist/utils/obj.d.ts +111 -111
- package/dist/utils/obj.d.ts.map +1 -1
- package/dist/utils/obj.js +706 -496
- package/dist/utils/obj.js.map +1 -6
- package/dist/utils/path.d.ts +10 -10
- package/dist/utils/path.js +35 -18
- package/dist/utils/path.js.map +1 -6
- package/dist/utils/primitive.d.ts +5 -5
- package/dist/utils/primitive.js +34 -14
- package/dist/utils/primitive.js.map +1 -6
- package/dist/utils/str.d.ts +38 -38
- package/dist/utils/str.js +217 -113
- package/dist/utils/str.js.map +1 -6
- package/dist/utils/template-strings.d.ts +26 -26
- package/dist/utils/template-strings.js +113 -40
- package/dist/utils/template-strings.js.map +1 -6
- package/dist/utils/transferable.d.ts +18 -18
- package/dist/utils/transferable.js +218 -151
- package/dist/utils/transferable.js.map +1 -6
- package/dist/utils/wait.d.ts +9 -9
- package/dist/utils/wait.js +30 -15
- package/dist/utils/wait.js.map +1 -6
- package/dist/utils/xml.d.ts +13 -13
- package/dist/utils/xml.js +84 -46
- package/dist/utils/xml.js.map +1 -6
- package/dist/utils/zip.d.ts +22 -22
- package/dist/utils/zip.js +172 -148
- package/dist/utils/zip.js.map +1 -6
- package/package.json +5 -7
- package/src/common.types.ts +14 -14
- package/src/env.ts +9 -1
- package/src/errors/argument-error.ts +15 -15
- package/src/errors/not-implemented-error.ts +9 -9
- package/src/errors/sd-error.ts +12 -12
- package/src/errors/timeout-error.ts +12 -12
- package/src/extensions/arr-ext.helpers.ts +16 -16
- package/src/extensions/arr-ext.ts +35 -35
- package/src/extensions/arr-ext.types.ts +57 -57
- package/src/extensions/map-ext.ts +16 -16
- package/src/extensions/set-ext.ts +11 -11
- package/src/features/debounce-queue.ts +23 -23
- package/src/features/event-emitter.ts +25 -25
- package/src/features/serial-queue.ts +13 -13
- package/src/globals.ts +4 -4
- package/src/index.ts +5 -5
- package/src/types/date-only.ts +84 -83
- package/src/types/date-time.ts +43 -42
- package/src/types/lazy-gc-map.ts +44 -44
- package/src/types/time.ts +29 -29
- package/src/types/uuid.ts +15 -15
- package/src/utils/bytes.ts +35 -35
- package/src/utils/date-format.ts +59 -59
- package/src/utils/error.ts +4 -4
- package/src/utils/json.ts +41 -41
- package/src/utils/num.ts +20 -20
- package/src/utils/obj.ts +138 -138
- package/src/utils/path.ts +10 -10
- package/src/utils/primitive.ts +6 -6
- package/src/utils/str.ts +48 -48
- package/src/utils/template-strings.ts +29 -29
- package/src/utils/transferable.ts +38 -38
- package/src/utils/wait.ts +10 -10
- package/src/utils/xml.ts +19 -19
- package/src/utils/zip.ts +25 -25
- package/README.md +0 -160
- package/docs/errors.md +0 -119
- package/docs/extensions.md +0 -387
- package/docs/features.md +0 -143
- package/docs/types.md +0 -287
- package/docs/utils.md +0 -757
- package/tests/errors/errors.spec.ts +0 -80
- package/tests/extensions/array-extension.spec.ts +0 -654
- package/tests/extensions/map-extension.spec.ts +0 -117
- package/tests/extensions/set-extension.spec.ts +0 -67
- package/tests/types/date-only.spec.ts +0 -533
- package/tests/types/date-time.spec.ts +0 -246
- package/tests/types/lazy-gc-map.spec.ts +0 -606
- package/tests/types/time.spec.ts +0 -428
- package/tests/types/uuid.spec.ts +0 -74
- package/tests/utils/bytes-utils.spec.ts +0 -197
- package/tests/utils/date-format.spec.ts +0 -350
- package/tests/utils/debounce-queue.spec.ts +0 -226
- package/tests/utils/json.spec.ts +0 -400
- package/tests/utils/number.spec.ts +0 -136
- package/tests/utils/object.spec.ts +0 -810
- package/tests/utils/path.spec.ts +0 -70
- package/tests/utils/primitive.spec.ts +0 -43
- package/tests/utils/sd-event-emitter.spec.ts +0 -189
- package/tests/utils/serial-queue.spec.ts +0 -305
- package/tests/utils/string.spec.ts +0 -265
- package/tests/utils/template-strings.spec.ts +0 -48
- package/tests/utils/transferable.spec.ts +0 -639
- package/tests/utils/wait.spec.ts +0 -123
- package/tests/utils/xml.spec.ts +0 -146
- package/tests/utils/zip.spec.ts +0 -221
package/tests/utils/json.spec.ts
DELETED
|
@@ -1,400 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { json, DateTime, DateOnly, Time, Uuid } from "@simplysm/core-common";
|
|
3
|
-
|
|
4
|
-
describe("JsonConvert", () => {
|
|
5
|
-
//#region stringify
|
|
6
|
-
|
|
7
|
-
describe("stringify()", () => {
|
|
8
|
-
it("Serializes Date with __type__", () => {
|
|
9
|
-
const date = new Date("2024-03-15T10:30:00.000Z");
|
|
10
|
-
const str = json.stringify(date);
|
|
11
|
-
const parsed = JSON.parse(str);
|
|
12
|
-
|
|
13
|
-
expect(parsed.__type__).toBe("Date");
|
|
14
|
-
expect(parsed.data).toBe("2024-03-15T10:30:00.000Z");
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it("Serializes DateTime with __type__", () => {
|
|
18
|
-
const dt = new DateTime(2024, 3, 15, 10, 30);
|
|
19
|
-
const str = json.stringify(dt);
|
|
20
|
-
const parsed = JSON.parse(str);
|
|
21
|
-
|
|
22
|
-
expect(parsed.__type__).toBe("DateTime");
|
|
23
|
-
expect(typeof parsed.data).toBe("string");
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("Serializes DateOnly with __type__", () => {
|
|
27
|
-
const d = new DateOnly(2024, 3, 15);
|
|
28
|
-
const str = json.stringify(d);
|
|
29
|
-
const parsed = JSON.parse(str);
|
|
30
|
-
|
|
31
|
-
expect(parsed.__type__).toBe("DateOnly");
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it("Serializes Time with __type__", () => {
|
|
35
|
-
const t = new Time(10, 30, 45);
|
|
36
|
-
const str = json.stringify(t);
|
|
37
|
-
const parsed = JSON.parse(str);
|
|
38
|
-
|
|
39
|
-
expect(parsed.__type__).toBe("Time");
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("Serializes Uuid with __type__", () => {
|
|
43
|
-
const uuid = new Uuid("12345678-9abc-def0-1234-56789abcdef0");
|
|
44
|
-
const str = json.stringify(uuid);
|
|
45
|
-
const parsed = JSON.parse(str);
|
|
46
|
-
|
|
47
|
-
expect(parsed.__type__).toBe("Uuid");
|
|
48
|
-
expect(parsed.data).toBe("12345678-9abc-def0-1234-56789abcdef0");
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it("Serializes Set with __type__", () => {
|
|
52
|
-
const set = new Set([1, 2, 3]);
|
|
53
|
-
const str = json.stringify(set);
|
|
54
|
-
const parsed = JSON.parse(str);
|
|
55
|
-
|
|
56
|
-
expect(parsed.__type__).toBe("Set");
|
|
57
|
-
expect(parsed.data).toEqual([1, 2, 3]);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it("Serializes Map with __type__", () => {
|
|
61
|
-
const map = new Map([
|
|
62
|
-
["a", 1],
|
|
63
|
-
["b", 2],
|
|
64
|
-
]);
|
|
65
|
-
const str = json.stringify(map);
|
|
66
|
-
const parsed = JSON.parse(str);
|
|
67
|
-
|
|
68
|
-
expect(parsed.__type__).toBe("Map");
|
|
69
|
-
expect(parsed.data).toEqual([
|
|
70
|
-
["a", 1],
|
|
71
|
-
["b", 2],
|
|
72
|
-
]);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it("Serializes Error with __type__", () => {
|
|
76
|
-
const error = new Error("test error");
|
|
77
|
-
const str = json.stringify(error);
|
|
78
|
-
const parsed = JSON.parse(str);
|
|
79
|
-
|
|
80
|
-
expect(parsed.__type__).toBe("Error");
|
|
81
|
-
expect(parsed.data.message).toBe("test error");
|
|
82
|
-
expect(parsed.data.name).toBe("Error");
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it("Serializes Error extended properties (code, detail, cause)", () => {
|
|
86
|
-
const cause = new Error("cause error");
|
|
87
|
-
const error = new Error("test error") as Error & { code: string; detail: object };
|
|
88
|
-
error.code = "ERR_CODE";
|
|
89
|
-
error.detail = { key: "value" };
|
|
90
|
-
(error as Error & { cause: Error }).cause = cause;
|
|
91
|
-
|
|
92
|
-
const str = json.stringify(error);
|
|
93
|
-
const parsed = JSON.parse(str);
|
|
94
|
-
|
|
95
|
-
expect(parsed.__type__).toBe("Error");
|
|
96
|
-
expect(parsed.data.message).toBe("test error");
|
|
97
|
-
expect(parsed.data.code).toBe("ERR_CODE");
|
|
98
|
-
expect(parsed.data.detail).toEqual({ key: "value" });
|
|
99
|
-
expect(parsed.data.cause.__type__).toBe("Error");
|
|
100
|
-
expect(parsed.data.cause.data.message).toBe("cause error");
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it("Hides Uint8Array with redactBytes option", () => {
|
|
104
|
-
const obj = { data: new TextEncoder().encode("hello") };
|
|
105
|
-
const str = json.stringify(obj, { redactBytes: true });
|
|
106
|
-
const parsed = JSON.parse(str);
|
|
107
|
-
|
|
108
|
-
expect(parsed.data.data).toBe("__hidden__");
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it("Transforms values with replacer option", () => {
|
|
112
|
-
const obj = { a: 1, b: 2, c: 3 };
|
|
113
|
-
const str = json.stringify(obj, {
|
|
114
|
-
replacer: (key, value) => {
|
|
115
|
-
if (key === "b") return undefined;
|
|
116
|
-
return value;
|
|
117
|
-
},
|
|
118
|
-
});
|
|
119
|
-
const parsed = JSON.parse(str);
|
|
120
|
-
|
|
121
|
-
expect(parsed.a).toBe(1);
|
|
122
|
-
expect(parsed.b).toBeUndefined();
|
|
123
|
-
expect(parsed.c).toBe(3);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it("No race condition on concurrent calls", async () => {
|
|
127
|
-
// Serialize complex objects with Date simultaneously
|
|
128
|
-
const createTestObject = (id: number) => ({
|
|
129
|
-
id,
|
|
130
|
-
date: new Date(`2024-0${(id % 9) + 1}-15T10:30:00.000Z`),
|
|
131
|
-
nested: {
|
|
132
|
-
innerDate: new Date(`2024-0${(id % 9) + 1}-20T15:45:00.000Z`),
|
|
133
|
-
},
|
|
134
|
-
array: [new Date(`2024-0${(id % 9) + 1}-25T08:00:00.000Z`)],
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
// 100 concurrent calls
|
|
138
|
-
const promises = Array.from({ length: 100 }, (_, i) =>
|
|
139
|
-
Promise.resolve().then(() => {
|
|
140
|
-
const obj = createTestObject(i);
|
|
141
|
-
const str = json.stringify(obj);
|
|
142
|
-
const parsed = json.parse<typeof obj>(str);
|
|
143
|
-
|
|
144
|
-
// Verify all Dates restored correctly
|
|
145
|
-
expect(parsed.date).toBeInstanceOf(Date);
|
|
146
|
-
expect(parsed.nested.innerDate).toBeInstanceOf(Date);
|
|
147
|
-
expect(parsed.array[0]).toBeInstanceOf(Date);
|
|
148
|
-
|
|
149
|
-
return { id: i, success: true };
|
|
150
|
-
}),
|
|
151
|
-
);
|
|
152
|
-
|
|
153
|
-
const results = await Promise.all(promises);
|
|
154
|
-
|
|
155
|
-
// Verify all calls succeeded
|
|
156
|
-
expect(results.every((r) => r.success)).toBe(true);
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it("Correctly serializes nested Date objects", () => {
|
|
160
|
-
const obj = {
|
|
161
|
-
level1: {
|
|
162
|
-
level2: {
|
|
163
|
-
level3: {
|
|
164
|
-
date: new Date("2024-06-15T12:00:00.000Z"),
|
|
165
|
-
},
|
|
166
|
-
},
|
|
167
|
-
},
|
|
168
|
-
dates: [new Date("2024-01-01T00:00:00.000Z"), new Date("2024-12-31T23:59:59.000Z")],
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
const str = json.stringify(obj);
|
|
172
|
-
const parsed = json.parse<typeof obj>(str);
|
|
173
|
-
|
|
174
|
-
expect(parsed.level1.level2.level3.date).toBeInstanceOf(Date);
|
|
175
|
-
expect(parsed.level1.level2.level3.date.toISOString()).toBe("2024-06-15T12:00:00.000Z");
|
|
176
|
-
expect(parsed.dates[0]).toBeInstanceOf(Date);
|
|
177
|
-
expect(parsed.dates[1]).toBeInstanceOf(Date);
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it("Does not modify Date.prototype.toJSON", () => {
|
|
181
|
-
const originalToJSON = Date.prototype.toJSON;
|
|
182
|
-
|
|
183
|
-
// Call stringify
|
|
184
|
-
const date = new Date("2024-03-15T10:30:00.000Z");
|
|
185
|
-
json.stringify({ date });
|
|
186
|
-
|
|
187
|
-
// Verify toJSON not changed
|
|
188
|
-
expect(Date.prototype.toJSON).toBe(originalToJSON);
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
it("Circular reference object throws TypeError", () => {
|
|
192
|
-
const obj: Record<string, unknown> = { name: "test" };
|
|
193
|
-
obj["self"] = obj; // circular reference
|
|
194
|
-
|
|
195
|
-
expect(() => json.stringify(obj)).toThrow(TypeError);
|
|
196
|
-
expect(() => json.stringify(obj)).toThrow("Converting circular structure to JSON");
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
it("Detects circular reference in array", () => {
|
|
200
|
-
const arr: unknown[] = [1, 2];
|
|
201
|
-
arr.push(arr); // array circular reference
|
|
202
|
-
|
|
203
|
-
expect(() => json.stringify(arr)).toThrow("Converting circular structure to JSON");
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
it("Serializes custom object with toJSON method", () => {
|
|
207
|
-
const obj = {
|
|
208
|
-
amount: 100,
|
|
209
|
-
toJSON() {
|
|
210
|
-
return `$${this.amount}`;
|
|
211
|
-
},
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
const str = json.stringify(obj);
|
|
215
|
-
expect(str).toBe('"$100"');
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
it("Recursively processes toJSON if returning object", () => {
|
|
219
|
-
const obj = {
|
|
220
|
-
data: "test",
|
|
221
|
-
toJSON() {
|
|
222
|
-
return { converted: true, date: new Date("2024-01-01T00:00:00.000Z") };
|
|
223
|
-
},
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
const str = json.stringify(obj);
|
|
227
|
-
const parsed = JSON.parse(str);
|
|
228
|
-
|
|
229
|
-
expect(parsed.converted).toBe(true);
|
|
230
|
-
expect(parsed.date.__type__).toBe("Date");
|
|
231
|
-
});
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
//#endregion
|
|
235
|
-
|
|
236
|
-
//#region parse
|
|
237
|
-
|
|
238
|
-
describe("parse()", () => {
|
|
239
|
-
it("Converts null to undefined", () => {
|
|
240
|
-
expect(json.parse("null")).toBe(undefined);
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
it("Restores Date", () => {
|
|
244
|
-
const str = '{"__type__":"Date","data":"2024-03-15T10:30:00.000Z"}';
|
|
245
|
-
const result = json.parse(str);
|
|
246
|
-
|
|
247
|
-
expect(result).toBeInstanceOf(Date);
|
|
248
|
-
expect((result as Date).toISOString()).toBe("2024-03-15T10:30:00.000Z");
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
it("Restores DateTime", () => {
|
|
252
|
-
const dt = new DateTime(2024, 3, 15, 10, 30);
|
|
253
|
-
const str = json.stringify(dt);
|
|
254
|
-
const result = json.parse(str);
|
|
255
|
-
|
|
256
|
-
expect(result).toBeInstanceOf(DateTime);
|
|
257
|
-
expect((result as DateTime).year).toBe(2024);
|
|
258
|
-
expect((result as DateTime).month).toBe(3);
|
|
259
|
-
expect((result as DateTime).day).toBe(15);
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
it("Restores DateOnly", () => {
|
|
263
|
-
const d = new DateOnly(2024, 3, 15);
|
|
264
|
-
const str = json.stringify(d);
|
|
265
|
-
const result = json.parse(str);
|
|
266
|
-
|
|
267
|
-
expect(result).toBeInstanceOf(DateOnly);
|
|
268
|
-
expect((result as DateOnly).year).toBe(2024);
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
it("Restores Time", () => {
|
|
272
|
-
const t = new Time(10, 30, 45);
|
|
273
|
-
const str = json.stringify(t);
|
|
274
|
-
const result = json.parse(str);
|
|
275
|
-
|
|
276
|
-
expect(result).toBeInstanceOf(Time);
|
|
277
|
-
expect((result as Time).hour).toBe(10);
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
it("Restores Uuid", () => {
|
|
281
|
-
const str = '{"__type__":"Uuid","data":"12345678-9abc-def0-1234-56789abcdef0"}';
|
|
282
|
-
const result = json.parse(str);
|
|
283
|
-
|
|
284
|
-
expect(result).toBeInstanceOf(Uuid);
|
|
285
|
-
expect((result as Uuid).toString()).toBe("12345678-9abc-def0-1234-56789abcdef0");
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
it("Restores Set", () => {
|
|
289
|
-
const str = '{"__type__":"Set","data":[1,2,3]}';
|
|
290
|
-
const result = json.parse(str);
|
|
291
|
-
|
|
292
|
-
expect(result).toBeInstanceOf(Set);
|
|
293
|
-
expect(Array.from(result as Set<number>)).toEqual([1, 2, 3]);
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
it("Restores Map", () => {
|
|
297
|
-
const str = '{"__type__":"Map","data":[["a",1],["b",2]]}';
|
|
298
|
-
const result = json.parse(str);
|
|
299
|
-
|
|
300
|
-
expect(result).toBeInstanceOf(Map);
|
|
301
|
-
expect((result as Map<string, number>).get("a")).toBe(1);
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
it("Restores Error (with extended properties)", () => {
|
|
305
|
-
const cause = new Error("cause error");
|
|
306
|
-
const error = new Error("test error") as Error & {
|
|
307
|
-
code: string;
|
|
308
|
-
detail: object;
|
|
309
|
-
cause: Error;
|
|
310
|
-
};
|
|
311
|
-
error.code = "ERR_CODE";
|
|
312
|
-
error.detail = { key: "value" };
|
|
313
|
-
error.cause = cause;
|
|
314
|
-
|
|
315
|
-
const str = json.stringify(error);
|
|
316
|
-
const result = json.parse<typeof error>(str);
|
|
317
|
-
|
|
318
|
-
expect(result).toBeInstanceOf(Error);
|
|
319
|
-
expect(result.message).toBe("test error");
|
|
320
|
-
expect(result.code).toBe("ERR_CODE");
|
|
321
|
-
expect(result.detail).toEqual({ key: "value" });
|
|
322
|
-
expect(result.cause).toBeInstanceOf(Error);
|
|
323
|
-
expect(result.cause.message).toBe("cause error");
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
it("Restores Uint8Array", () => {
|
|
327
|
-
const str = '{"__type__":"Uint8Array","data":"68656c6c6f"}';
|
|
328
|
-
const result = json.parse(str);
|
|
329
|
-
|
|
330
|
-
expect(result).toBeInstanceOf(Uint8Array);
|
|
331
|
-
expect(new TextDecoder().decode(result as Uint8Array)).toBe("hello");
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
it("stringify/parse round-trip", () => {
|
|
335
|
-
const original = {
|
|
336
|
-
date: new Date("2024-03-15T10:30:00.000Z"),
|
|
337
|
-
dateTime: new DateTime(2024, 3, 15),
|
|
338
|
-
dateOnly: new DateOnly(2024, 3, 15),
|
|
339
|
-
time: new Time(10, 30),
|
|
340
|
-
uuid: new Uuid("12345678-9abc-def0-1234-56789abcdef0"),
|
|
341
|
-
set: new Set([1, 2, 3]),
|
|
342
|
-
map: new Map([["a", 1]]),
|
|
343
|
-
bytes: new TextEncoder().encode("hello"),
|
|
344
|
-
};
|
|
345
|
-
|
|
346
|
-
const str = json.stringify(original);
|
|
347
|
-
const result = json.parse<typeof original>(str);
|
|
348
|
-
|
|
349
|
-
expect(result.date).toBeInstanceOf(Date);
|
|
350
|
-
expect(result.dateTime).toBeInstanceOf(DateTime);
|
|
351
|
-
expect(result.dateOnly).toBeInstanceOf(DateOnly);
|
|
352
|
-
expect(result.time).toBeInstanceOf(Time);
|
|
353
|
-
expect(result.uuid).toBeInstanceOf(Uuid);
|
|
354
|
-
expect(result.set).toBeInstanceOf(Set);
|
|
355
|
-
expect(result.map).toBeInstanceOf(Map);
|
|
356
|
-
expect(result.bytes).toBeInstanceOf(Uint8Array);
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
it("Data serialized with redactBytes throws error on parse", () => {
|
|
360
|
-
const obj = { data: new TextEncoder().encode("hello") };
|
|
361
|
-
const str = json.stringify(obj, { redactBytes: true });
|
|
362
|
-
|
|
363
|
-
// "__hidden__" is data serialized with redactBytes option, so parse throws error
|
|
364
|
-
expect(() => json.parse<typeof obj>(str)).toThrow(
|
|
365
|
-
"Uint8Array serialized with redactBytes option cannot be restored via parse",
|
|
366
|
-
);
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
it("Invalid JSON throws error", () => {
|
|
370
|
-
expect(() => json.parse("invalid json")).toThrow("JSON parsing error");
|
|
371
|
-
});
|
|
372
|
-
|
|
373
|
-
it("In DEV mode, full JSON included in error message", () => {
|
|
374
|
-
const longJson = "x".repeat(2000);
|
|
375
|
-
|
|
376
|
-
try {
|
|
377
|
-
json.parse(longJson);
|
|
378
|
-
expect.fail("Error should be thrown");
|
|
379
|
-
} catch (err) {
|
|
380
|
-
const message = (err as Error).message;
|
|
381
|
-
// In DEV mode, full JSON included
|
|
382
|
-
expect(message).toContain(longJson);
|
|
383
|
-
}
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
it("Error message includes JSON content", () => {
|
|
387
|
-
const shortJson = "invalid";
|
|
388
|
-
|
|
389
|
-
try {
|
|
390
|
-
json.parse(shortJson);
|
|
391
|
-
expect.fail("Error should be thrown");
|
|
392
|
-
} catch (err) {
|
|
393
|
-
const message = (err as Error).message;
|
|
394
|
-
expect(message).toContain("invalid");
|
|
395
|
-
}
|
|
396
|
-
});
|
|
397
|
-
});
|
|
398
|
-
|
|
399
|
-
//#endregion
|
|
400
|
-
});
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { num } from "@simplysm/core-common";
|
|
3
|
-
|
|
4
|
-
describe("number utils", () => {
|
|
5
|
-
//#region parseInt
|
|
6
|
-
|
|
7
|
-
describe("parseInt()", () => {
|
|
8
|
-
it("Parses negative string", () => {
|
|
9
|
-
expect(num.parseInt("-123")).toBe(-123);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it("Floating string returns only integer part", () => {
|
|
13
|
-
expect(num.parseInt("123.45")).toBe(123);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it("Number type discards decimal places", () => {
|
|
17
|
-
expect(num.parseInt(123.7)).toBe(123);
|
|
18
|
-
expect(num.parseInt(123.3)).toBe(123);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it("Removes non-numeric characters then parses", () => {
|
|
22
|
-
expect(num.parseInt("$1,234")).toBe(1234);
|
|
23
|
-
expect(num.parseInt("abc123")).toBe(123);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("Handles minus sign between characters", () => {
|
|
27
|
-
expect(num.parseInt("abc-123def")).toBe(-123);
|
|
28
|
-
expect(num.parseInt("abc-456def")).toBe(-456);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it("Empty string returns undefined", () => {
|
|
32
|
-
expect(num.parseInt("")).toBe(undefined);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it("String with no digits returns undefined", () => {
|
|
36
|
-
expect(num.parseInt("abc")).toBe(undefined);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it("Non-string type returns undefined", () => {
|
|
40
|
-
expect(num.parseInt(null)).toBe(undefined);
|
|
41
|
-
expect(num.parseInt(undefined)).toBe(undefined);
|
|
42
|
-
expect(num.parseInt({})).toBe(undefined);
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
//#endregion
|
|
47
|
-
|
|
48
|
-
//#region parseRoundedInt
|
|
49
|
-
|
|
50
|
-
describe("parseRoundedInt()", () => {
|
|
51
|
-
it("Rounds floating string to integer", () => {
|
|
52
|
-
expect(num.parseRoundedInt("123.5")).toBe(124);
|
|
53
|
-
expect(num.parseRoundedInt("123.4")).toBe(123);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("Rounds number type", () => {
|
|
57
|
-
expect(num.parseRoundedInt(123.7)).toBe(124);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it("Returns undefined if not parseable", () => {
|
|
61
|
-
expect(num.parseRoundedInt("abc")).toBe(undefined);
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
//#endregion
|
|
66
|
-
|
|
67
|
-
//#region parseFloat
|
|
68
|
-
|
|
69
|
-
describe("parseFloat()", () => {
|
|
70
|
-
it("Parses negative floating string", () => {
|
|
71
|
-
expect(num.parseFloat("-123.45")).toBe(-123.45);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it("Number type returned as-is", () => {
|
|
75
|
-
expect(num.parseFloat(123.45)).toBe(123.45);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it("Removes non-numeric characters then parses", () => {
|
|
79
|
-
expect(num.parseFloat("$1,234.56")).toBe(1234.56);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it("Empty string returns undefined", () => {
|
|
83
|
-
expect(num.parseFloat("")).toBe(undefined);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it("String with no digits returns undefined", () => {
|
|
87
|
-
expect(num.parseFloat("abc")).toBe(undefined);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it("Non-string type returns undefined", () => {
|
|
91
|
-
expect(num.parseFloat(null)).toBe(undefined);
|
|
92
|
-
expect(num.parseFloat(undefined)).toBe(undefined);
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
//#endregion
|
|
97
|
-
|
|
98
|
-
//#region format
|
|
99
|
-
|
|
100
|
-
describe("format()", () => {
|
|
101
|
-
it("Applies thousands separator", () => {
|
|
102
|
-
expect(num.format(1234567)).toBe("1,234,567");
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it("Applies thousands separator to float", () => {
|
|
106
|
-
const result = num.format(1234567.89);
|
|
107
|
-
expect(result).toContain("1,234,567");
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it("Specifies maximum decimal places", () => {
|
|
111
|
-
expect(num.format(123.456, { max: 2 })).toBe("123.46");
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it("Specifies minimum decimal places", () => {
|
|
115
|
-
expect(num.format(123, { min: 2 })).toBe("123.00");
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it("Specifies both max and min decimal places", () => {
|
|
119
|
-
expect(num.format(123.4, { max: 3, min: 2 })).toBe("123.40");
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it("Undefined returns undefined", () => {
|
|
123
|
-
expect(num.format(undefined)).toBe(undefined);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it("Formats zero", () => {
|
|
127
|
-
expect(num.format(0)).toBe("0");
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it("Formats negative number", () => {
|
|
131
|
-
expect(num.format(-1234567)).toBe("-1,234,567");
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
//#endregion
|
|
136
|
-
});
|