@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,654 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import "@simplysm/core-common"; // Enable $ extension
3
-
4
- describe("Array prototype extensions", () => {
5
- //#region single
6
-
7
- describe("single()", () => {
8
- it("Returns single matching element", () => {
9
- const result = [1, 2, 3].single((x) => x === 2);
10
-
11
- expect(result).toBe(2);
12
- });
13
-
14
- it("Returns undefined if no matching element", () => {
15
- const result = [1, 2, 3].single((x) => x === 4);
16
-
17
- expect(result).toBe(undefined);
18
- });
19
-
20
- it("Throws error if multiple matching elements", () => {
21
- expect(() => [1, 1, 2].single((x) => x === 1)).toThrow();
22
- });
23
-
24
- it("Without condition, targets entire array", () => {
25
- expect([1].single()).toBe(1);
26
- expect(([] as number[]).single()).toBe(undefined);
27
- expect(() => [1, 2].single()).toThrow();
28
- });
29
- });
30
-
31
- //#endregion
32
-
33
- //#region Async methods
34
-
35
- describe("parallelAsync()", () => {
36
- it("Performs parallel async execution", async () => {
37
- const result = await [1, 2, 3].parallelAsync(async (x) => Promise.resolve(x * 2));
38
-
39
- expect(result).toEqual([2, 4, 6]);
40
- });
41
- });
42
-
43
- describe("mapAsync()", () => {
44
- it("Performs sequential async mapping", async () => {
45
- const result = await [1, 2, 3].mapAsync(async (x) => Promise.resolve(x * 2));
46
-
47
- expect(result).toEqual([2, 4, 6]);
48
- });
49
- });
50
-
51
- describe("filterAsync()", () => {
52
- it("Performs async filtering", async () => {
53
- const result = await [1, 2, 3, 4, 5].filterAsync(async (x) => Promise.resolve(x > 2));
54
-
55
- expect(result).toEqual([3, 4, 5]);
56
- });
57
- });
58
-
59
- //#endregion
60
-
61
- //#region Map conversion
62
-
63
- describe("toMap()", () => {
64
- it("Creates Map with key function", () => {
65
- const result = [
66
- { id: 1, name: "a" },
67
- { id: 2, name: "b" },
68
- ].toMap((x) => x.id);
69
-
70
- expect(result.get(1)).toEqual({ id: 1, name: "a" });
71
- expect(result.get(2)).toEqual({ id: 2, name: "b" });
72
- });
73
-
74
- it("Transforms values with value function", () => {
75
- const result = [
76
- { id: 1, name: "a" },
77
- { id: 2, name: "b" },
78
- ].toMap(
79
- (x) => x.id,
80
- (x) => x.name,
81
- );
82
-
83
- expect(result.get(1)).toBe("a");
84
- expect(result.get(2)).toBe("b");
85
- });
86
-
87
- it("Throws error on duplicate keys", () => {
88
- expect(() =>
89
- [
90
- { id: 1, name: "a" },
91
- { id: 1, name: "b" },
92
- ].toMap((x) => x.id),
93
- ).toThrow("Duplicated key");
94
- });
95
- });
96
-
97
- describe("toMapAsync()", () => {
98
- it("Creates Map with async key/value functions", async () => {
99
- const result = await [
100
- { id: 1, name: "a" },
101
- { id: 2, name: "b" },
102
- ].toMapAsync(async (x) => Promise.resolve(x.id));
103
-
104
- expect(result.get(1)).toEqual({ id: 1, name: "a" });
105
- expect(result.get(2)).toEqual({ id: 2, name: "b" });
106
- });
107
- });
108
-
109
- describe("toArrayMap()", () => {
110
- it("Creates Map with array values", () => {
111
- const result = [
112
- { type: "a", v: 1 },
113
- { type: "b", v: 2 },
114
- { type: "a", v: 3 },
115
- ].toArrayMap((x) => x.type);
116
-
117
- expect(result.get("a")).toHaveLength(2);
118
- expect(result.get("b")).toHaveLength(1);
119
- });
120
-
121
- it("Transforms values with value function", () => {
122
- const result = [
123
- { type: "a", v: 1 },
124
- { type: "a", v: 2 },
125
- ].toArrayMap(
126
- (x) => x.type,
127
- (x) => x.v,
128
- );
129
-
130
- expect(result.get("a")).toEqual([1, 2]);
131
- });
132
- });
133
-
134
- describe("toSetMap()", () => {
135
- it("Creates Map with Set values", () => {
136
- const result = [
137
- { type: "a", v: 1 },
138
- { type: "a", v: 1 }, // duplicate
139
- { type: "a", v: 2 },
140
- ].toSetMap(
141
- (x) => x.type,
142
- (x) => x.v,
143
- );
144
-
145
- expect(result.get("a")?.size).toBe(2); // duplicates removed
146
- });
147
- });
148
-
149
- describe("toMapValues()", () => {
150
- it("Creates Map with aggregated results per group", () => {
151
- const result = [
152
- { type: "a", v: 10 },
153
- { type: "b", v: 20 },
154
- { type: "a", v: 30 },
155
- ].toMapValues(
156
- (x) => x.type,
157
- (items) => items.reduce((sum, x) => sum + x.v, 0),
158
- );
159
-
160
- expect(result.get("a")).toBe(40);
161
- expect(result.get("b")).toBe(20);
162
- });
163
- });
164
-
165
- //#endregion
166
-
167
- //#region Tree conversion
168
-
169
- describe("toTree()", () => {
170
- it("Converts to tree structure", () => {
171
- interface Item {
172
- id: number;
173
- parentId?: number;
174
- name: string;
175
- }
176
-
177
- const items: Item[] = [
178
- { id: 1, name: "root" },
179
- { id: 2, parentId: 1, name: "child1" },
180
- { id: 3, parentId: 1, name: "child2" },
181
- { id: 4, parentId: 2, name: "grandchild" },
182
- ];
183
-
184
- const result = items.toTree("id", "parentId");
185
-
186
- expect(result).toHaveLength(1);
187
- expect(result[0].children).toHaveLength(2);
188
- expect(result[0].children[0].children).toHaveLength(1);
189
- });
190
- });
191
-
192
- //#endregion
193
-
194
- //#region Array comparison
195
-
196
- describe("diffs()", () => {
197
- it("Analyzes differences between arrays", () => {
198
- interface Item {
199
- [key: string]: unknown;
200
- id: number;
201
- value: string;
202
- }
203
-
204
- const source: Item[] = [
205
- { id: 1, value: "a" },
206
- { id: 2, value: "b" },
207
- { id: 3, value: "c" },
208
- ];
209
-
210
- const target: Item[] = [
211
- { id: 2, value: "b" },
212
- { id: 3, value: "changed" },
213
- { id: 4, value: "d" },
214
- ];
215
-
216
- const result = source.diffs(target, { keys: ["id"] });
217
-
218
- const deleted = result.find((d) => d.source?.["id"] === 1);
219
- expect(deleted?.target).toBe(undefined);
220
-
221
- const updated = result.find((d) => d.source?.["id"] === 3);
222
- expect(updated?.target?.["value"]).toBe("changed");
223
-
224
- const inserted = result.find((d) => d.target?.["id"] === 4);
225
- expect(inserted?.source).toBe(undefined);
226
- });
227
- });
228
-
229
- describe("oneWayDiffs()", () => {
230
- it("Analyzes one-way differences", () => {
231
- interface Item {
232
- id: number;
233
- value: string;
234
- }
235
-
236
- const orgItems: Item[] = [
237
- { id: 1, value: "a" },
238
- { id: 2, value: "b" },
239
- ];
240
-
241
- const items: Item[] = [
242
- { id: 2, value: "changed" },
243
- { id: 3, value: "c" },
244
- ];
245
-
246
- const result = items.oneWayDiffs(orgItems, "id");
247
-
248
- const updated = result.find((d) => d.item.id === 2);
249
- expect(updated?.type).toBe("update");
250
-
251
- const created = result.find((d) => d.item.id === 3);
252
- expect(created?.type).toBe("create");
253
- });
254
-
255
- it("Includes unchanged items when includeSame=true", () => {
256
- interface Item {
257
- id: number;
258
- value: string;
259
- }
260
-
261
- const orgItems: Item[] = [
262
- { id: 1, value: "a" },
263
- { id: 2, value: "b" },
264
- ];
265
-
266
- const items: Item[] = [
267
- { id: 1, value: "a" }, // unchanged
268
- { id: 2, value: "changed" },
269
- ];
270
-
271
- const result = items.oneWayDiffs(orgItems, "id", { includeSame: true });
272
-
273
- const same = result.find((d) => d.item.id === 1);
274
- expect(same?.type).toBe("same");
275
-
276
- const updated = result.find((d) => d.item.id === 2);
277
- expect(updated?.type).toBe("update");
278
- });
279
- });
280
-
281
- describe("merge()", () => {
282
- it("Merges modified items", () => {
283
- interface Item {
284
- [key: string]: unknown;
285
- id: number;
286
- value: string;
287
- }
288
-
289
- const source: Item[] = [
290
- { id: 1, value: "a" },
291
- { id: 2, value: "b" },
292
- ];
293
- const target: Item[] = [
294
- { id: 1, value: "a" },
295
- { id: 2, value: "changed" },
296
- ];
297
-
298
- const result = source.merge(target, { keys: ["id"] });
299
-
300
- expect(result).toHaveLength(2);
301
- expect(result.find((r) => r["id"] === 2)?.["value"]).toBe("changed");
302
- });
303
- });
304
-
305
- //#endregion
306
-
307
- //#region first, last
308
-
309
- describe("first()", () => {
310
- it("Returns first element", () => {
311
- expect([1, 2, 3].first()).toBe(1);
312
- });
313
-
314
- it("Returns first matching element", () => {
315
- expect([1, 2, 3, 4, 5].first((x) => x > 3)).toBe(4);
316
- });
317
-
318
- it("Returns undefined for empty array", () => {
319
- expect(([] as number[]).first()).toBe(undefined);
320
- });
321
- });
322
-
323
- describe("last()", () => {
324
- it("Returns last element", () => {
325
- expect([1, 2, 3].last()).toBe(3);
326
- });
327
-
328
- it("Returns last matching element", () => {
329
- expect([1, 2, 3, 4, 5].last((x) => x < 4)).toBe(3);
330
- });
331
-
332
- it("Returns undefined for empty array", () => {
333
- expect(([] as number[]).last()).toBe(undefined);
334
- });
335
- });
336
-
337
- //#endregion
338
-
339
- //#region filterExists, ofType
340
-
341
- describe("filterExists()", () => {
342
- it("Removes null/undefined", () => {
343
- const arr = [1, null, 2, undefined, 3];
344
- const result = arr.filterExists();
345
- expect(result).toEqual([1, 2, 3]);
346
- });
347
- });
348
-
349
- describe("ofType()", () => {
350
- it("Filters string type elements only", () => {
351
- const arr = [1, "a", 2, "b", true];
352
- const result = arr.ofType("string");
353
- expect(result).toEqual(["a", "b"]);
354
- });
355
-
356
- it("Filters number type elements only", () => {
357
- const arr = [1, "a", 2, "b", 3];
358
- const result = arr.ofType("number");
359
- expect(result).toEqual([1, 2, 3]);
360
- });
361
-
362
- it("Filters boolean type elements only", () => {
363
- const arr = [1, "a", true, false, 2];
364
- const result = arr.ofType("boolean");
365
- expect(result).toEqual([true, false]);
366
- });
367
- });
368
-
369
- //#endregion
370
-
371
- //#region mapMany
372
-
373
- describe("mapMany()", () => {
374
- it("Maps then flattens", () => {
375
- const result = [1, 2, 3].mapMany((x) => [x, x * 10]);
376
- expect(result).toEqual([1, 10, 2, 20, 3, 30]);
377
- });
378
- });
379
-
380
- describe("mapManyAsync()", () => {
381
- it("Async maps then flattens", async () => {
382
- const result = await [1, 2, 3].mapManyAsync(async (x) => Promise.resolve([x, x * 10]));
383
- expect(result).toEqual([1, 10, 2, 20, 3, 30]);
384
- });
385
-
386
- it("Async maps nested Promise array then flattens", async () => {
387
- const result = await [1, 2].mapManyAsync(async (x) => Promise.resolve([x, x + 1, x + 2]));
388
- expect(result).toEqual([1, 2, 3, 2, 3, 4]);
389
- });
390
- });
391
-
392
- //#endregion
393
-
394
- //#region groupBy
395
-
396
- describe("groupBy()", () => {
397
- it("Groups by key", () => {
398
- const items = [
399
- { type: "a", value: 1 },
400
- { type: "b", value: 2 },
401
- { type: "a", value: 3 },
402
- ];
403
- const result = items.groupBy((x) => x.type);
404
-
405
- expect(result).toHaveLength(2);
406
- expect(result.find((g) => g.key === "a")?.values).toHaveLength(2);
407
- expect(result.find((g) => g.key === "b")?.values).toHaveLength(1);
408
- });
409
- });
410
-
411
- //#endregion
412
-
413
- //#region toObject
414
-
415
- describe("toObject()", () => {
416
- it("Converts array to object", () => {
417
- const items = [
418
- { key: "a", value: 1 },
419
- { key: "b", value: 2 },
420
- ];
421
- const result = items.toObject(
422
- (x) => x.key,
423
- (x) => x.value,
424
- );
425
-
426
- expect(result).toEqual({ a: 1, b: 2 });
427
- });
428
-
429
- it("Throws error on duplicate keys", () => {
430
- const items = [
431
- { key: "a", value: 1 },
432
- { key: "a", value: 2 },
433
- ];
434
- expect(() => items.toObject((x) => x.key)).toThrow();
435
- });
436
- });
437
-
438
- //#endregion
439
-
440
- //#region distinct
441
-
442
- describe("distinct()", () => {
443
- it("Removes duplicates", () => {
444
- expect([1, 2, 2, 3, 3, 3].distinct()).toEqual([1, 2, 3]);
445
- });
446
-
447
- it("Removes duplicates from object array", () => {
448
- const arr = [{ a: 1 }, { a: 2 }, { a: 1 }];
449
- const result = arr.distinct();
450
- expect(result).toHaveLength(2);
451
- });
452
-
453
- it("Can use custom key with keyFn", () => {
454
- const arr = [
455
- { id: 1, name: "a" },
456
- { id: 2, name: "b" },
457
- { id: 1, name: "c" },
458
- ];
459
- const result = arr.distinct({ keyFn: (x) => x.id });
460
- expect(result).toHaveLength(2);
461
- });
462
-
463
- it("Removes duplicates by reference with matchAddress=true", () => {
464
- const obj1 = { a: 1 };
465
- const obj2 = { a: 1 }; // same value but different reference
466
- const arr = [obj1, obj1, obj2];
467
- const result = arr.distinct({ matchAddress: true });
468
- expect(result).toHaveLength(2);
469
- expect(result).toContain(obj1);
470
- expect(result).toContain(obj2);
471
- });
472
- });
473
-
474
- //#endregion
475
-
476
- //#region orderBy, orderByDesc
477
-
478
- describe("orderBy()", () => {
479
- it("Sorts in ascending order", () => {
480
- expect([3, 1, 2].orderBy()).toEqual([1, 2, 3]);
481
- });
482
-
483
- it("Can specify sort criteria with selector", () => {
484
- const items = [
485
- { name: "b", age: 30 },
486
- { name: "a", age: 20 },
487
- { name: "c", age: 25 },
488
- ];
489
- const result = items.orderBy((x) => x.age);
490
- expect(result.map((x) => x.age)).toEqual([20, 25, 30]);
491
- });
492
- });
493
-
494
- describe("orderByDesc()", () => {
495
- it("Sorts in descending order", () => {
496
- expect([1, 3, 2].orderByDesc()).toEqual([3, 2, 1]);
497
- });
498
- });
499
-
500
- //#endregion
501
-
502
- //#region sum, min, max
503
-
504
- describe("sum()", () => {
505
- it("Returns sum", () => {
506
- expect([1, 2, 3, 4, 5].sum()).toBe(15);
507
- });
508
-
509
- it("Can extract values with selector", () => {
510
- const items = [{ value: 10 }, { value: 20 }, { value: 30 }];
511
- expect(items.sum((x) => x.value)).toBe(60);
512
- });
513
-
514
- it("Returns 0 for empty array", () => {
515
- expect(([] as number[]).sum()).toBe(0);
516
- });
517
-
518
- it("Throws error for non-number type", () => {
519
- expect(() => (["a", "b"] as unknown as number[]).sum()).toThrow("sum can only be used with numbers");
520
- });
521
- });
522
-
523
- describe("min()", () => {
524
- it("Returns minimum value", () => {
525
- expect([3, 1, 2].min()).toBe(1);
526
- });
527
-
528
- it("Returns undefined for empty array", () => {
529
- expect(([] as number[]).min()).toBe(undefined);
530
- });
531
-
532
- it("Throws error for non-number/string type", () => {
533
- expect(() => ([true, false] as unknown as number[]).min()).toThrow(
534
- "min can only be used with numbers/strings",
535
- );
536
- });
537
- });
538
-
539
- describe("max()", () => {
540
- it("Returns maximum value", () => {
541
- expect([1, 3, 2].max()).toBe(3);
542
- });
543
-
544
- it("Returns undefined for empty array", () => {
545
- expect(([] as number[]).max()).toBe(undefined);
546
- });
547
-
548
- it("Throws error for non-number/string type", () => {
549
- expect(() => ([{}, {}] as unknown as number[]).max()).toThrow(
550
- "max can only be used with numbers/strings",
551
- );
552
- });
553
- });
554
-
555
- //#endregion
556
-
557
- //#region shuffle
558
-
559
- describe("shuffle()", () => {
560
- it("Shuffles array (preserves original)", () => {
561
- const original = [1, 2, 3, 4, 5];
562
- const shuffled = original.shuffle();
563
-
564
- // original unchanged
565
- expect(original).toEqual([1, 2, 3, 4, 5]);
566
- // has same elements
567
- expect(shuffled.sort()).toEqual([1, 2, 3, 4, 5]);
568
- });
569
- });
570
-
571
- //#endregion
572
-
573
- //#region Mutating methods
574
-
575
- describe("distinctThis()", () => {
576
- it("Removes duplicates from original array", () => {
577
- const arr = [1, 2, 2, 3, 3, 3];
578
- const result = arr.distinctThis();
579
-
580
- expect(arr).toEqual([1, 2, 3]);
581
- expect(result).toEqual([1, 2, 3]);
582
- });
583
- });
584
-
585
- describe("orderByThis()", () => {
586
- it("Sorts original array in ascending order", () => {
587
- const arr = [3, 1, 2];
588
- arr.orderByThis();
589
-
590
- expect(arr).toEqual([1, 2, 3]);
591
- });
592
- });
593
-
594
- describe("orderByDescThis()", () => {
595
- it("Sorts original array in descending order", () => {
596
- const arr = [1, 3, 2];
597
- arr.orderByDescThis();
598
-
599
- expect(arr).toEqual([3, 2, 1]);
600
- });
601
- });
602
-
603
- describe("insert()", () => {
604
- it("Inserts item to original array", () => {
605
- const arr = [1, 3];
606
- arr.insert(1, 2);
607
-
608
- expect(arr).toEqual([1, 2, 3]);
609
- });
610
- });
611
-
612
- describe("remove()", () => {
613
- it("Removes item from original array", () => {
614
- const arr = [1, 2, 3];
615
- arr.remove(2);
616
-
617
- expect(arr).toEqual([1, 3]);
618
- });
619
-
620
- it("Removes item with condition function", () => {
621
- const arr = [1, 2, 3, 4];
622
- arr.remove((x) => x % 2 === 0);
623
-
624
- expect(arr).toEqual([1, 3]);
625
- });
626
- });
627
-
628
- describe("toggle()", () => {
629
- it("Removes item if exists", () => {
630
- const arr = [1, 2, 3];
631
- arr.toggle(2);
632
-
633
- expect(arr).toEqual([1, 3]);
634
- });
635
-
636
- it("Adds item if not exists", () => {
637
- const arr = [1, 3];
638
- arr.toggle(2);
639
-
640
- expect(arr).toEqual([1, 3, 2]);
641
- });
642
- });
643
-
644
- describe("clear()", () => {
645
- it("Clears original array", () => {
646
- const arr = [1, 2, 3];
647
- arr.clear();
648
-
649
- expect(arr).toEqual([]);
650
- });
651
- });
652
-
653
- //#endregion
654
- });