@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
|
@@ -1,639 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { transfer, DateTime, DateOnly, Time, Uuid } from "@simplysm/core-common";
|
|
3
|
-
|
|
4
|
-
describe("TransferableConvert", () => {
|
|
5
|
-
//#region encode - Special types
|
|
6
|
-
|
|
7
|
-
describe("encode() - Special types", () => {
|
|
8
|
-
it("Encodes DateTime", () => {
|
|
9
|
-
const dt = new DateTime(2025, 1, 6, 15, 30, 45, 123);
|
|
10
|
-
const { result } = transfer.encode(dt);
|
|
11
|
-
|
|
12
|
-
expect(result).toEqual({
|
|
13
|
-
__type__: "DateTime",
|
|
14
|
-
data: dt.tick,
|
|
15
|
-
});
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it("Encodes DateOnly", () => {
|
|
19
|
-
const d = new DateOnly(2025, 1, 6);
|
|
20
|
-
const { result } = transfer.encode(d);
|
|
21
|
-
|
|
22
|
-
expect(result).toEqual({
|
|
23
|
-
__type__: "DateOnly",
|
|
24
|
-
data: d.tick,
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it("Encodes Time", () => {
|
|
29
|
-
const t = new Time(15, 30, 45, 123);
|
|
30
|
-
const { result } = transfer.encode(t);
|
|
31
|
-
|
|
32
|
-
expect(result).toEqual({
|
|
33
|
-
__type__: "Time",
|
|
34
|
-
data: t.tick,
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it("Encodes Uuid", () => {
|
|
39
|
-
const uuid = Uuid.generate();
|
|
40
|
-
const { result } = transfer.encode(uuid);
|
|
41
|
-
|
|
42
|
-
expect(result).toEqual({
|
|
43
|
-
__type__: "Uuid",
|
|
44
|
-
data: uuid.toString(),
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it("Encodes Error", () => {
|
|
49
|
-
const err = new Error("test error");
|
|
50
|
-
err.stack = "test stack";
|
|
51
|
-
const { result } = transfer.encode(err);
|
|
52
|
-
|
|
53
|
-
expect(result).toEqual({
|
|
54
|
-
__type__: "Error",
|
|
55
|
-
data: {
|
|
56
|
-
name: "Error",
|
|
57
|
-
message: "test error",
|
|
58
|
-
stack: "test stack",
|
|
59
|
-
},
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it("Recursively encodes Error cause", () => {
|
|
64
|
-
const cause = new Error("cause error");
|
|
65
|
-
const err = new Error("main error", { cause });
|
|
66
|
-
const { result } = transfer.encode(err);
|
|
67
|
-
|
|
68
|
-
const typedResult = result as {
|
|
69
|
-
__type__: string;
|
|
70
|
-
data: {
|
|
71
|
-
name: string;
|
|
72
|
-
message: string;
|
|
73
|
-
cause?: {
|
|
74
|
-
__type__: string;
|
|
75
|
-
data: {
|
|
76
|
-
name: string;
|
|
77
|
-
message: string;
|
|
78
|
-
};
|
|
79
|
-
};
|
|
80
|
-
};
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
expect(typedResult.data.cause).toEqual({
|
|
84
|
-
__type__: "Error",
|
|
85
|
-
data: {
|
|
86
|
-
name: "Error",
|
|
87
|
-
message: "cause error",
|
|
88
|
-
stack: cause.stack,
|
|
89
|
-
},
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it("Encodes Error code property", () => {
|
|
94
|
-
const err = new Error("test error") as Error & { code: string };
|
|
95
|
-
err.code = "ERR_CUSTOM";
|
|
96
|
-
const { result } = transfer.encode(err);
|
|
97
|
-
|
|
98
|
-
const typedResult = result as {
|
|
99
|
-
__type__: string;
|
|
100
|
-
data: {
|
|
101
|
-
name: string;
|
|
102
|
-
message: string;
|
|
103
|
-
code?: string;
|
|
104
|
-
};
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
expect(typedResult.data.code).toBe("ERR_CUSTOM");
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it("Encodes Error detail property", () => {
|
|
111
|
-
const err = new Error("test error") as Error & { detail: unknown };
|
|
112
|
-
err.detail = { userId: 123, action: "delete" };
|
|
113
|
-
const { result } = transfer.encode(err);
|
|
114
|
-
|
|
115
|
-
const typedResult = result as {
|
|
116
|
-
__type__: string;
|
|
117
|
-
data: {
|
|
118
|
-
name: string;
|
|
119
|
-
message: string;
|
|
120
|
-
detail?: unknown;
|
|
121
|
-
};
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
expect(typedResult.data.detail).toEqual({ userId: 123, action: "delete" });
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it("Encodes special types in Error detail", () => {
|
|
128
|
-
const err = new Error("test error") as Error & { detail: unknown };
|
|
129
|
-
const dt = new DateTime(2025, 1, 6);
|
|
130
|
-
err.detail = { timestamp: dt };
|
|
131
|
-
const { result } = transfer.encode(err);
|
|
132
|
-
|
|
133
|
-
const typedResult = result as {
|
|
134
|
-
__type__: string;
|
|
135
|
-
data: {
|
|
136
|
-
name: string;
|
|
137
|
-
message: string;
|
|
138
|
-
detail?: { timestamp: { __type__: string; data: number } };
|
|
139
|
-
};
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
expect(typedResult.data.detail?.timestamp).toEqual({
|
|
143
|
-
__type__: "DateTime",
|
|
144
|
-
data: dt.tick,
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it("Encodes Uint8Array and adds to transferList", () => {
|
|
149
|
-
const bytes = new TextEncoder().encode("hello");
|
|
150
|
-
const { result, transferList } = transfer.encode(bytes);
|
|
151
|
-
|
|
152
|
-
expect(result).toBe(bytes);
|
|
153
|
-
expect(transferList).toContain(bytes.buffer);
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it("Encodes Date", () => {
|
|
157
|
-
const date = new Date(2025, 0, 6, 15, 30, 45, 123);
|
|
158
|
-
const { result } = transfer.encode(date);
|
|
159
|
-
|
|
160
|
-
expect(result).toEqual({
|
|
161
|
-
__type__: "Date",
|
|
162
|
-
data: date.getTime(),
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it("Encodes RegExp", () => {
|
|
167
|
-
const regex = /test\d+/gi;
|
|
168
|
-
const { result } = transfer.encode(regex);
|
|
169
|
-
|
|
170
|
-
expect(result).toEqual({
|
|
171
|
-
__type__: "RegExp",
|
|
172
|
-
data: { source: "test\\d+", flags: "gi" },
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
//#endregion
|
|
178
|
-
|
|
179
|
-
//#region encode - Collections
|
|
180
|
-
|
|
181
|
-
describe("encode() - Collections", () => {
|
|
182
|
-
it("Recursively encodes array", () => {
|
|
183
|
-
const arr = [new DateTime(2025, 1, 6), Uuid.generate(), "string", 123] as const;
|
|
184
|
-
const { result } = transfer.encode(arr);
|
|
185
|
-
|
|
186
|
-
expect(Array.isArray(result)).toBe(true);
|
|
187
|
-
const resultArr = result as unknown[];
|
|
188
|
-
expect(resultArr).toHaveLength(4);
|
|
189
|
-
expect(resultArr[0]).toMatchObject({ __type__: "DateTime" });
|
|
190
|
-
expect(resultArr[1]).toMatchObject({ __type__: "Uuid" });
|
|
191
|
-
expect(resultArr[2]).toBe("string");
|
|
192
|
-
expect(resultArr[3]).toBe(123);
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
it("Recursively encodes Map", () => {
|
|
196
|
-
const map = new Map<string, DateTime | Uuid>([
|
|
197
|
-
["key1", new DateTime(2025, 1, 6)],
|
|
198
|
-
["key2", Uuid.generate()],
|
|
199
|
-
]);
|
|
200
|
-
const { result } = transfer.encode(map);
|
|
201
|
-
|
|
202
|
-
expect(result instanceof Map).toBe(true);
|
|
203
|
-
const resultMap = result as Map<string, unknown>;
|
|
204
|
-
expect(resultMap.size).toBe(2);
|
|
205
|
-
expect(resultMap.get("key1")).toMatchObject({ __type__: "DateTime" });
|
|
206
|
-
expect(resultMap.get("key2")).toMatchObject({ __type__: "Uuid" });
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
it("Recursively encodes Set", () => {
|
|
210
|
-
const set = new Set([new DateTime(2025, 1, 6), Uuid.generate()]);
|
|
211
|
-
const { result } = transfer.encode(set);
|
|
212
|
-
|
|
213
|
-
expect(result instanceof Set).toBe(true);
|
|
214
|
-
const resultSet = result as Set<unknown>;
|
|
215
|
-
expect(resultSet.size).toBe(2);
|
|
216
|
-
const arr = Array.from(resultSet);
|
|
217
|
-
expect(arr[0]).toMatchObject({ __type__: "DateTime" });
|
|
218
|
-
expect(arr[1]).toMatchObject({ __type__: "Uuid" });
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
it("Recursively encodes nested object", () => {
|
|
222
|
-
const obj = {
|
|
223
|
-
dt: new DateTime(2025, 1, 6),
|
|
224
|
-
nested: {
|
|
225
|
-
uuid: Uuid.generate(),
|
|
226
|
-
arr: [new DateOnly(2025, 1, 6)],
|
|
227
|
-
},
|
|
228
|
-
};
|
|
229
|
-
const { result } = transfer.encode(obj);
|
|
230
|
-
|
|
231
|
-
const typedResult = result as {
|
|
232
|
-
dt: { __type__: string };
|
|
233
|
-
nested: {
|
|
234
|
-
uuid: { __type__: string };
|
|
235
|
-
arr: { __type__: string }[];
|
|
236
|
-
};
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
expect(typedResult.dt).toMatchObject({ __type__: "DateTime" });
|
|
240
|
-
expect(typedResult.nested.uuid).toMatchObject({ __type__: "Uuid" });
|
|
241
|
-
expect(typedResult.nested.arr[0]).toMatchObject({ __type__: "DateOnly" });
|
|
242
|
-
});
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
//#endregion
|
|
246
|
-
|
|
247
|
-
//#region encode - Circular reference detection
|
|
248
|
-
|
|
249
|
-
describe("encode() - Circular reference detection", () => {
|
|
250
|
-
it("Throws TypeError when encoding self-referencing object", () => {
|
|
251
|
-
const obj: Record<string, unknown> = { a: 1 };
|
|
252
|
-
obj["self"] = obj;
|
|
253
|
-
|
|
254
|
-
expect(() => transfer.encode(obj)).toThrow(TypeError);
|
|
255
|
-
expect(() => transfer.encode(obj)).toThrow("Circular reference detected");
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
it("Detects nested circular references", () => {
|
|
259
|
-
const a: Record<string, unknown> = { name: "a" };
|
|
260
|
-
const b: Record<string, unknown> = { name: "b", ref: a };
|
|
261
|
-
a["ref"] = b;
|
|
262
|
-
|
|
263
|
-
expect(() => transfer.encode(a)).toThrow("Circular reference detected");
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
it("Detects circular references in array", () => {
|
|
267
|
-
const arr: unknown[] = [1, 2, 3];
|
|
268
|
-
arr.push(arr);
|
|
269
|
-
|
|
270
|
-
expect(() => transfer.encode(arr)).toThrow("Circular reference detected");
|
|
271
|
-
});
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
//#endregion
|
|
275
|
-
|
|
276
|
-
//#region encode - DAG (Shared objects)
|
|
277
|
-
|
|
278
|
-
describe("encode() - DAG (Shared objects)", () => {
|
|
279
|
-
it("Encodes without error when same object is referenced from multiple places", () => {
|
|
280
|
-
const shared = { name: "shared" };
|
|
281
|
-
const data = { a: shared, b: shared };
|
|
282
|
-
const { result } = transfer.encode(data);
|
|
283
|
-
const decoded = result as Record<string, Record<string, string>>;
|
|
284
|
-
expect(decoded["a"]["name"]).toBe("shared");
|
|
285
|
-
expect(decoded["b"]["name"]).toBe("shared");
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
it("Encodes without error when same array is referenced from multiple places", () => {
|
|
289
|
-
const sharedArr = [1, 2, 3];
|
|
290
|
-
const data = { x: sharedArr, y: sharedArr };
|
|
291
|
-
const { result } = transfer.encode(data);
|
|
292
|
-
const decoded = result as Record<string, number[]>;
|
|
293
|
-
expect(decoded["x"]).toEqual([1, 2, 3]);
|
|
294
|
-
expect(decoded["y"]).toEqual([1, 2, 3]);
|
|
295
|
-
});
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
//#endregion
|
|
299
|
-
|
|
300
|
-
//#region decode - Special types
|
|
301
|
-
|
|
302
|
-
describe("decode() - Special types", () => {
|
|
303
|
-
it("Decodes DateTime", () => {
|
|
304
|
-
const tick = new DateTime(2025, 1, 6, 15, 30, 45, 123).tick;
|
|
305
|
-
const encoded = { __type__: "DateTime", data: tick };
|
|
306
|
-
const decoded = transfer.decode(encoded);
|
|
307
|
-
|
|
308
|
-
expect(decoded instanceof DateTime).toBe(true);
|
|
309
|
-
const dt = decoded as DateTime;
|
|
310
|
-
expect(dt.year).toBe(2025);
|
|
311
|
-
expect(dt.month).toBe(1);
|
|
312
|
-
expect(dt.day).toBe(6);
|
|
313
|
-
expect(dt.hour).toBe(15);
|
|
314
|
-
expect(dt.minute).toBe(30);
|
|
315
|
-
expect(dt.second).toBe(45);
|
|
316
|
-
expect(dt.millisecond).toBe(123);
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
it("Decodes DateOnly", () => {
|
|
320
|
-
const tick = new DateOnly(2025, 1, 6).tick;
|
|
321
|
-
const encoded = { __type__: "DateOnly", data: tick };
|
|
322
|
-
const decoded = transfer.decode(encoded);
|
|
323
|
-
|
|
324
|
-
expect(decoded instanceof DateOnly).toBe(true);
|
|
325
|
-
const d = decoded as DateOnly;
|
|
326
|
-
expect(d.year).toBe(2025);
|
|
327
|
-
expect(d.month).toBe(1);
|
|
328
|
-
expect(d.day).toBe(6);
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
it("Decodes Time", () => {
|
|
332
|
-
const tick = new Time(15, 30, 45, 123).tick;
|
|
333
|
-
const encoded = { __type__: "Time", data: tick };
|
|
334
|
-
const decoded = transfer.decode(encoded);
|
|
335
|
-
|
|
336
|
-
expect(decoded instanceof Time).toBe(true);
|
|
337
|
-
const t = decoded as Time;
|
|
338
|
-
expect(t.hour).toBe(15);
|
|
339
|
-
expect(t.minute).toBe(30);
|
|
340
|
-
expect(t.second).toBe(45);
|
|
341
|
-
expect(t.millisecond).toBe(123);
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
it("Decodes Uuid", () => {
|
|
345
|
-
const uuid = Uuid.generate();
|
|
346
|
-
const encoded = { __type__: "Uuid", data: uuid.toString() };
|
|
347
|
-
const decoded = transfer.decode(encoded);
|
|
348
|
-
|
|
349
|
-
expect(decoded instanceof Uuid).toBe(true);
|
|
350
|
-
expect((decoded as Uuid).toString()).toBe(uuid.toString());
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
it("Decodes Error", () => {
|
|
354
|
-
const encoded = {
|
|
355
|
-
__type__: "Error",
|
|
356
|
-
data: {
|
|
357
|
-
name: "CustomError",
|
|
358
|
-
message: "test error",
|
|
359
|
-
stack: "test stack",
|
|
360
|
-
},
|
|
361
|
-
};
|
|
362
|
-
const decoded = transfer.decode(encoded);
|
|
363
|
-
|
|
364
|
-
expect(decoded instanceof Error).toBe(true);
|
|
365
|
-
const err = decoded as Error;
|
|
366
|
-
expect(err.name).toBe("CustomError");
|
|
367
|
-
expect(err.message).toBe("test error");
|
|
368
|
-
expect(err.stack).toBe("test stack");
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
it("Recursively decodes Error cause", () => {
|
|
372
|
-
const encoded = {
|
|
373
|
-
__type__: "Error",
|
|
374
|
-
data: {
|
|
375
|
-
name: "Error",
|
|
376
|
-
message: "main error",
|
|
377
|
-
cause: {
|
|
378
|
-
__type__: "Error",
|
|
379
|
-
data: {
|
|
380
|
-
name: "Error",
|
|
381
|
-
message: "cause error",
|
|
382
|
-
},
|
|
383
|
-
},
|
|
384
|
-
},
|
|
385
|
-
};
|
|
386
|
-
const decoded = transfer.decode(encoded);
|
|
387
|
-
|
|
388
|
-
expect(decoded instanceof Error).toBe(true);
|
|
389
|
-
const err = decoded as Error;
|
|
390
|
-
expect(err.message).toBe("main error");
|
|
391
|
-
expect(err.cause instanceof Error).toBe(true);
|
|
392
|
-
expect((err.cause as Error).message).toBe("cause error");
|
|
393
|
-
});
|
|
394
|
-
|
|
395
|
-
it("Decodes Error code property", () => {
|
|
396
|
-
const encoded = {
|
|
397
|
-
__type__: "Error",
|
|
398
|
-
data: {
|
|
399
|
-
name: "Error",
|
|
400
|
-
message: "test error",
|
|
401
|
-
code: "ERR_CUSTOM",
|
|
402
|
-
},
|
|
403
|
-
};
|
|
404
|
-
const decoded = transfer.decode(encoded);
|
|
405
|
-
|
|
406
|
-
expect(decoded instanceof Error).toBe(true);
|
|
407
|
-
const err = decoded as Error & { code?: string };
|
|
408
|
-
expect(err.code).toBe("ERR_CUSTOM");
|
|
409
|
-
});
|
|
410
|
-
|
|
411
|
-
it("Decodes Error detail property", () => {
|
|
412
|
-
const encoded = {
|
|
413
|
-
__type__: "Error",
|
|
414
|
-
data: {
|
|
415
|
-
name: "Error",
|
|
416
|
-
message: "test error",
|
|
417
|
-
detail: { userId: 123, action: "delete" },
|
|
418
|
-
},
|
|
419
|
-
};
|
|
420
|
-
const decoded = transfer.decode(encoded);
|
|
421
|
-
|
|
422
|
-
expect(decoded instanceof Error).toBe(true);
|
|
423
|
-
const err = decoded as Error & { detail?: unknown };
|
|
424
|
-
expect(err.detail).toEqual({ userId: 123, action: "delete" });
|
|
425
|
-
});
|
|
426
|
-
|
|
427
|
-
it("Decodes special types in Error detail", () => {
|
|
428
|
-
const tick = new DateTime(2025, 1, 6).tick;
|
|
429
|
-
const encoded = {
|
|
430
|
-
__type__: "Error",
|
|
431
|
-
data: {
|
|
432
|
-
name: "Error",
|
|
433
|
-
message: "test error",
|
|
434
|
-
detail: { timestamp: { __type__: "DateTime", data: tick } },
|
|
435
|
-
},
|
|
436
|
-
};
|
|
437
|
-
const decoded = transfer.decode(encoded);
|
|
438
|
-
|
|
439
|
-
expect(decoded instanceof Error).toBe(true);
|
|
440
|
-
const err = decoded as Error & { detail?: { timestamp: DateTime } };
|
|
441
|
-
expect(err.detail?.timestamp instanceof DateTime).toBe(true);
|
|
442
|
-
expect(err.detail?.timestamp.tick).toBe(tick);
|
|
443
|
-
});
|
|
444
|
-
|
|
445
|
-
it("Decodes Date", () => {
|
|
446
|
-
const tick = new Date(2025, 0, 6, 15, 30, 45, 123).getTime();
|
|
447
|
-
const encoded = { __type__: "Date", data: tick };
|
|
448
|
-
const decoded = transfer.decode(encoded);
|
|
449
|
-
|
|
450
|
-
expect(decoded instanceof Date).toBe(true);
|
|
451
|
-
const date = decoded as Date;
|
|
452
|
-
expect(date.getFullYear()).toBe(2025);
|
|
453
|
-
expect(date.getMonth()).toBe(0);
|
|
454
|
-
expect(date.getDate()).toBe(6);
|
|
455
|
-
expect(date.getHours()).toBe(15);
|
|
456
|
-
expect(date.getMinutes()).toBe(30);
|
|
457
|
-
expect(date.getSeconds()).toBe(45);
|
|
458
|
-
expect(date.getMilliseconds()).toBe(123);
|
|
459
|
-
});
|
|
460
|
-
|
|
461
|
-
it("Decodes RegExp", () => {
|
|
462
|
-
const encoded = {
|
|
463
|
-
__type__: "RegExp",
|
|
464
|
-
data: { source: "test\\d+", flags: "gi" },
|
|
465
|
-
};
|
|
466
|
-
const decoded = transfer.decode(encoded);
|
|
467
|
-
|
|
468
|
-
expect(decoded instanceof RegExp).toBe(true);
|
|
469
|
-
const regex = decoded as RegExp;
|
|
470
|
-
expect(regex.source).toBe("test\\d+");
|
|
471
|
-
expect(regex.flags).toBe("gi");
|
|
472
|
-
// RegExp with g flag is stateful, so reset lastIndex before testing
|
|
473
|
-
expect(regex.test("test123")).toBe(true);
|
|
474
|
-
regex.lastIndex = 0;
|
|
475
|
-
expect(regex.test("TEST456")).toBe(true);
|
|
476
|
-
});
|
|
477
|
-
});
|
|
478
|
-
|
|
479
|
-
//#endregion
|
|
480
|
-
|
|
481
|
-
//#region decode - Collections
|
|
482
|
-
|
|
483
|
-
describe("decode() - Collections", () => {
|
|
484
|
-
it("Recursively decodes array", () => {
|
|
485
|
-
const tick = new DateTime(2025, 1, 6).tick;
|
|
486
|
-
const uuidStr = Uuid.generate().toString();
|
|
487
|
-
const encoded = [
|
|
488
|
-
{ __type__: "DateTime", data: tick },
|
|
489
|
-
{ __type__: "Uuid", data: uuidStr },
|
|
490
|
-
"string",
|
|
491
|
-
123,
|
|
492
|
-
];
|
|
493
|
-
const decoded = transfer.decode(encoded);
|
|
494
|
-
|
|
495
|
-
expect(Array.isArray(decoded)).toBe(true);
|
|
496
|
-
const arr = decoded as unknown[];
|
|
497
|
-
expect(arr[0] instanceof DateTime).toBe(true);
|
|
498
|
-
expect(arr[1] instanceof Uuid).toBe(true);
|
|
499
|
-
expect(arr[2]).toBe("string");
|
|
500
|
-
expect(arr[3]).toBe(123);
|
|
501
|
-
});
|
|
502
|
-
|
|
503
|
-
it("Recursively decodes Map", () => {
|
|
504
|
-
const tick = new DateTime(2025, 1, 6).tick;
|
|
505
|
-
const encoded = new Map<string, unknown>([
|
|
506
|
-
["key1", { __type__: "DateTime", data: tick }],
|
|
507
|
-
["key2", "value"],
|
|
508
|
-
]);
|
|
509
|
-
const decoded = transfer.decode(encoded);
|
|
510
|
-
|
|
511
|
-
expect(decoded instanceof Map).toBe(true);
|
|
512
|
-
const map = decoded as Map<string, unknown>;
|
|
513
|
-
expect(map.get("key1") instanceof DateTime).toBe(true);
|
|
514
|
-
expect(map.get("key2")).toBe("value");
|
|
515
|
-
});
|
|
516
|
-
|
|
517
|
-
it("Recursively decodes Set", () => {
|
|
518
|
-
const tick = new DateTime(2025, 1, 6).tick;
|
|
519
|
-
const encoded = new Set([{ __type__: "DateTime", data: tick }, "string"]);
|
|
520
|
-
const decoded = transfer.decode(encoded);
|
|
521
|
-
|
|
522
|
-
expect(decoded instanceof Set).toBe(true);
|
|
523
|
-
const set = decoded as Set<unknown>;
|
|
524
|
-
const arr = Array.from(set);
|
|
525
|
-
expect(arr[0] instanceof DateTime).toBe(true);
|
|
526
|
-
expect(arr[1]).toBe("string");
|
|
527
|
-
});
|
|
528
|
-
|
|
529
|
-
it("Recursively decodes nested object", () => {
|
|
530
|
-
const dtTick = new DateTime(2025, 1, 6).tick;
|
|
531
|
-
const uuidStr = Uuid.generate().toString();
|
|
532
|
-
const dTick = new DateOnly(2025, 1, 6).tick;
|
|
533
|
-
const encoded = {
|
|
534
|
-
dt: { __type__: "DateTime", data: dtTick },
|
|
535
|
-
nested: {
|
|
536
|
-
uuid: { __type__: "Uuid", data: uuidStr },
|
|
537
|
-
arr: [{ __type__: "DateOnly", data: dTick }],
|
|
538
|
-
},
|
|
539
|
-
};
|
|
540
|
-
const decoded = transfer.decode(encoded);
|
|
541
|
-
|
|
542
|
-
const obj = decoded as {
|
|
543
|
-
dt: DateTime;
|
|
544
|
-
nested: {
|
|
545
|
-
uuid: Uuid;
|
|
546
|
-
arr: DateOnly[];
|
|
547
|
-
};
|
|
548
|
-
};
|
|
549
|
-
|
|
550
|
-
expect(obj.dt instanceof DateTime).toBe(true);
|
|
551
|
-
expect(obj.nested.uuid instanceof Uuid).toBe(true);
|
|
552
|
-
expect(obj.nested.arr[0] instanceof DateOnly).toBe(true);
|
|
553
|
-
});
|
|
554
|
-
});
|
|
555
|
-
|
|
556
|
-
//#endregion
|
|
557
|
-
|
|
558
|
-
//#region decode - Preserve original
|
|
559
|
-
|
|
560
|
-
describe("decode() - Preserve original", () => {
|
|
561
|
-
it("Original object is not modified", () => {
|
|
562
|
-
const tick = new DateTime(2025, 1, 6).tick;
|
|
563
|
-
const original = {
|
|
564
|
-
dt: { __type__: "DateTime", data: tick },
|
|
565
|
-
value: 123,
|
|
566
|
-
};
|
|
567
|
-
const originalCopy = JSON.stringify(original);
|
|
568
|
-
|
|
569
|
-
transfer.decode(original);
|
|
570
|
-
|
|
571
|
-
// Verify original is not modified
|
|
572
|
-
expect(JSON.stringify(original)).toBe(originalCopy);
|
|
573
|
-
expect(original.dt).toEqual({ __type__: "DateTime", data: tick });
|
|
574
|
-
expect(original.value).toBe(123);
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
it("Decode result is a new instance (different from original)", () => {
|
|
578
|
-
const tick = new DateTime(2025, 1, 6).tick;
|
|
579
|
-
const original = [{ __type__: "DateTime", data: tick }];
|
|
580
|
-
|
|
581
|
-
const decoded = transfer.decode(original);
|
|
582
|
-
|
|
583
|
-
// Result is a new array
|
|
584
|
-
expect(decoded).not.toBe(original);
|
|
585
|
-
// Array contents are converted
|
|
586
|
-
expect(Array.isArray(decoded)).toBe(true);
|
|
587
|
-
expect((decoded as unknown[])[0] instanceof DateTime).toBe(true);
|
|
588
|
-
});
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
//#endregion
|
|
592
|
-
|
|
593
|
-
//#region Round-trip conversion (encode → decode)
|
|
594
|
-
|
|
595
|
-
describe("Round-trip conversion (encode → decode)", () => {
|
|
596
|
-
it("Round-trips DateTime", () => {
|
|
597
|
-
const original = new DateTime(2025, 1, 6, 15, 30, 45, 123);
|
|
598
|
-
const { result } = transfer.encode(original);
|
|
599
|
-
const decoded = transfer.decode(result) as DateTime;
|
|
600
|
-
|
|
601
|
-
expect(decoded.tick).toBe(original.tick);
|
|
602
|
-
});
|
|
603
|
-
|
|
604
|
-
it("Round-trips complex object", () => {
|
|
605
|
-
const original = {
|
|
606
|
-
dt: new DateTime(2025, 1, 6),
|
|
607
|
-
d: new DateOnly(2025, 1, 6),
|
|
608
|
-
t: new Time(15, 30, 45),
|
|
609
|
-
uuid: Uuid.generate(),
|
|
610
|
-
arr: [new DateTime(2024, 12, 31)],
|
|
611
|
-
map: new Map([["key", new DateOnly(2025, 1, 1)]]),
|
|
612
|
-
set: new Set([new Time(12, 0, 0)]),
|
|
613
|
-
};
|
|
614
|
-
|
|
615
|
-
const { result } = transfer.encode(original);
|
|
616
|
-
const decoded = transfer.decode(result) as typeof original;
|
|
617
|
-
|
|
618
|
-
expect(decoded.dt instanceof DateTime).toBe(true);
|
|
619
|
-
expect(decoded.d instanceof DateOnly).toBe(true);
|
|
620
|
-
expect(decoded.t instanceof Time).toBe(true);
|
|
621
|
-
expect(decoded.uuid instanceof Uuid).toBe(true);
|
|
622
|
-
expect(decoded.arr[0] instanceof DateTime).toBe(true);
|
|
623
|
-
expect(decoded.map.get("key") instanceof DateOnly).toBe(true);
|
|
624
|
-
expect(Array.from(decoded.set)[0] instanceof Time).toBe(true);
|
|
625
|
-
});
|
|
626
|
-
|
|
627
|
-
it("Round-trips RegExp", () => {
|
|
628
|
-
const original = /test\d+/gi;
|
|
629
|
-
const { result } = transfer.encode(original);
|
|
630
|
-
const decoded = transfer.decode(result) as RegExp;
|
|
631
|
-
|
|
632
|
-
expect(decoded instanceof RegExp).toBe(true);
|
|
633
|
-
expect(decoded.source).toBe(original.source);
|
|
634
|
-
expect(decoded.flags).toBe(original.flags);
|
|
635
|
-
});
|
|
636
|
-
});
|
|
637
|
-
|
|
638
|
-
//#endregion
|
|
639
|
-
});
|