@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.
Files changed (181) hide show
  1. package/dist/common.types.d.ts +14 -14
  2. package/dist/common.types.js +2 -1
  3. package/dist/common.types.js.map +1 -6
  4. package/dist/env.d.ts +5 -0
  5. package/dist/env.d.ts.map +1 -1
  6. package/dist/env.js +12 -8
  7. package/dist/env.js.map +1 -6
  8. package/dist/errors/argument-error.d.ts +10 -10
  9. package/dist/errors/argument-error.d.ts.map +1 -1
  10. package/dist/errors/argument-error.js +31 -14
  11. package/dist/errors/argument-error.js.map +1 -6
  12. package/dist/errors/not-implemented-error.d.ts +8 -8
  13. package/dist/errors/not-implemented-error.js +30 -12
  14. package/dist/errors/not-implemented-error.js.map +1 -6
  15. package/dist/errors/sd-error.d.ts +10 -10
  16. package/dist/errors/sd-error.d.ts.map +1 -1
  17. package/dist/errors/sd-error.js +45 -24
  18. package/dist/errors/sd-error.js.map +1 -6
  19. package/dist/errors/timeout-error.d.ts +10 -10
  20. package/dist/errors/timeout-error.js +34 -15
  21. package/dist/errors/timeout-error.js.map +1 -6
  22. package/dist/extensions/arr-ext.d.ts +2 -2
  23. package/dist/extensions/arr-ext.helpers.d.ts +10 -10
  24. package/dist/extensions/arr-ext.helpers.js +112 -89
  25. package/dist/extensions/arr-ext.helpers.js.map +1 -6
  26. package/dist/extensions/arr-ext.js +458 -422
  27. package/dist/extensions/arr-ext.js.map +1 -6
  28. package/dist/extensions/arr-ext.types.d.ts +57 -57
  29. package/dist/extensions/arr-ext.types.d.ts.map +1 -1
  30. package/dist/extensions/arr-ext.types.js +6 -1
  31. package/dist/extensions/arr-ext.types.js.map +1 -6
  32. package/dist/extensions/map-ext.d.ts +16 -16
  33. package/dist/extensions/map-ext.js +27 -22
  34. package/dist/extensions/map-ext.js.map +1 -6
  35. package/dist/extensions/set-ext.d.ts +11 -11
  36. package/dist/extensions/set-ext.js +32 -25
  37. package/dist/extensions/set-ext.js.map +1 -6
  38. package/dist/features/debounce-queue.d.ts +17 -17
  39. package/dist/features/debounce-queue.js +98 -70
  40. package/dist/features/debounce-queue.js.map +1 -6
  41. package/dist/features/event-emitter.d.ts +20 -20
  42. package/dist/features/event-emitter.js +101 -78
  43. package/dist/features/event-emitter.js.map +1 -6
  44. package/dist/features/serial-queue.d.ts +11 -11
  45. package/dist/features/serial-queue.js +78 -57
  46. package/dist/features/serial-queue.js.map +1 -6
  47. package/dist/globals.d.ts +4 -4
  48. package/dist/globals.js +9 -1
  49. package/dist/globals.js.map +1 -6
  50. package/dist/index.js +28 -27
  51. package/dist/index.js.map +1 -6
  52. package/dist/types/date-only.d.ts +64 -64
  53. package/dist/types/date-only.d.ts.map +1 -1
  54. package/dist/types/date-only.js +263 -252
  55. package/dist/types/date-only.js.map +1 -6
  56. package/dist/types/date-time.d.ts +36 -36
  57. package/dist/types/date-time.d.ts.map +1 -1
  58. package/dist/types/date-time.js +196 -288
  59. package/dist/types/date-time.js.map +1 -6
  60. package/dist/types/lazy-gc-map.d.ts +26 -26
  61. package/dist/types/lazy-gc-map.d.ts.map +1 -1
  62. package/dist/types/lazy-gc-map.js +202 -159
  63. package/dist/types/lazy-gc-map.js.map +1 -6
  64. package/dist/types/time.d.ts +23 -23
  65. package/dist/types/time.d.ts.map +1 -1
  66. package/dist/types/time.js +169 -158
  67. package/dist/types/time.js.map +1 -6
  68. package/dist/types/uuid.d.ts +11 -11
  69. package/dist/types/uuid.d.ts.map +1 -1
  70. package/dist/types/uuid.js +95 -70
  71. package/dist/types/uuid.js.map +1 -6
  72. package/dist/utils/bytes.d.ts +17 -17
  73. package/dist/utils/bytes.js +137 -81
  74. package/dist/utils/bytes.js.map +1 -6
  75. package/dist/utils/date-format.d.ts +40 -40
  76. package/dist/utils/date-format.js +187 -101
  77. package/dist/utils/date-format.js.map +1 -6
  78. package/dist/utils/error.d.ts +4 -4
  79. package/dist/utils/error.js +11 -6
  80. package/dist/utils/error.js.map +1 -6
  81. package/dist/utils/json.d.ts +19 -19
  82. package/dist/utils/json.js +187 -135
  83. package/dist/utils/json.js.map +1 -6
  84. package/dist/utils/num.d.ts +20 -20
  85. package/dist/utils/num.js +76 -34
  86. package/dist/utils/num.js.map +1 -6
  87. package/dist/utils/obj.d.ts +111 -111
  88. package/dist/utils/obj.d.ts.map +1 -1
  89. package/dist/utils/obj.js +706 -496
  90. package/dist/utils/obj.js.map +1 -6
  91. package/dist/utils/path.d.ts +10 -10
  92. package/dist/utils/path.js +35 -18
  93. package/dist/utils/path.js.map +1 -6
  94. package/dist/utils/primitive.d.ts +5 -5
  95. package/dist/utils/primitive.js +34 -14
  96. package/dist/utils/primitive.js.map +1 -6
  97. package/dist/utils/str.d.ts +38 -38
  98. package/dist/utils/str.js +217 -113
  99. package/dist/utils/str.js.map +1 -6
  100. package/dist/utils/template-strings.d.ts +26 -26
  101. package/dist/utils/template-strings.js +113 -40
  102. package/dist/utils/template-strings.js.map +1 -6
  103. package/dist/utils/transferable.d.ts +18 -18
  104. package/dist/utils/transferable.js +218 -151
  105. package/dist/utils/transferable.js.map +1 -6
  106. package/dist/utils/wait.d.ts +9 -9
  107. package/dist/utils/wait.js +30 -15
  108. package/dist/utils/wait.js.map +1 -6
  109. package/dist/utils/xml.d.ts +13 -13
  110. package/dist/utils/xml.js +84 -46
  111. package/dist/utils/xml.js.map +1 -6
  112. package/dist/utils/zip.d.ts +22 -22
  113. package/dist/utils/zip.js +172 -148
  114. package/dist/utils/zip.js.map +1 -6
  115. package/package.json +5 -7
  116. package/src/common.types.ts +14 -14
  117. package/src/env.ts +9 -1
  118. package/src/errors/argument-error.ts +15 -15
  119. package/src/errors/not-implemented-error.ts +9 -9
  120. package/src/errors/sd-error.ts +12 -12
  121. package/src/errors/timeout-error.ts +12 -12
  122. package/src/extensions/arr-ext.helpers.ts +16 -16
  123. package/src/extensions/arr-ext.ts +35 -35
  124. package/src/extensions/arr-ext.types.ts +57 -57
  125. package/src/extensions/map-ext.ts +16 -16
  126. package/src/extensions/set-ext.ts +11 -11
  127. package/src/features/debounce-queue.ts +23 -23
  128. package/src/features/event-emitter.ts +25 -25
  129. package/src/features/serial-queue.ts +13 -13
  130. package/src/globals.ts +4 -4
  131. package/src/index.ts +5 -5
  132. package/src/types/date-only.ts +84 -83
  133. package/src/types/date-time.ts +43 -42
  134. package/src/types/lazy-gc-map.ts +44 -44
  135. package/src/types/time.ts +29 -29
  136. package/src/types/uuid.ts +15 -15
  137. package/src/utils/bytes.ts +35 -35
  138. package/src/utils/date-format.ts +59 -59
  139. package/src/utils/error.ts +4 -4
  140. package/src/utils/json.ts +41 -41
  141. package/src/utils/num.ts +20 -20
  142. package/src/utils/obj.ts +138 -138
  143. package/src/utils/path.ts +10 -10
  144. package/src/utils/primitive.ts +6 -6
  145. package/src/utils/str.ts +48 -48
  146. package/src/utils/template-strings.ts +29 -29
  147. package/src/utils/transferable.ts +38 -38
  148. package/src/utils/wait.ts +10 -10
  149. package/src/utils/xml.ts +19 -19
  150. package/src/utils/zip.ts +25 -25
  151. package/README.md +0 -160
  152. package/docs/errors.md +0 -119
  153. package/docs/extensions.md +0 -387
  154. package/docs/features.md +0 -143
  155. package/docs/types.md +0 -287
  156. package/docs/utils.md +0 -757
  157. package/tests/errors/errors.spec.ts +0 -80
  158. package/tests/extensions/array-extension.spec.ts +0 -654
  159. package/tests/extensions/map-extension.spec.ts +0 -117
  160. package/tests/extensions/set-extension.spec.ts +0 -67
  161. package/tests/types/date-only.spec.ts +0 -533
  162. package/tests/types/date-time.spec.ts +0 -246
  163. package/tests/types/lazy-gc-map.spec.ts +0 -606
  164. package/tests/types/time.spec.ts +0 -428
  165. package/tests/types/uuid.spec.ts +0 -74
  166. package/tests/utils/bytes-utils.spec.ts +0 -197
  167. package/tests/utils/date-format.spec.ts +0 -350
  168. package/tests/utils/debounce-queue.spec.ts +0 -226
  169. package/tests/utils/json.spec.ts +0 -400
  170. package/tests/utils/number.spec.ts +0 -136
  171. package/tests/utils/object.spec.ts +0 -810
  172. package/tests/utils/path.spec.ts +0 -70
  173. package/tests/utils/primitive.spec.ts +0 -43
  174. package/tests/utils/sd-event-emitter.spec.ts +0 -189
  175. package/tests/utils/serial-queue.spec.ts +0 -305
  176. package/tests/utils/string.spec.ts +0 -265
  177. package/tests/utils/template-strings.spec.ts +0 -48
  178. package/tests/utils/transferable.spec.ts +0 -639
  179. package/tests/utils/wait.spec.ts +0 -123
  180. package/tests/utils/xml.spec.ts +0 -146
  181. 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
- });