@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,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
|
-
});
|