@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,70 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { path } from "@simplysm/core-common";
3
-
4
- describe("path utils", () => {
5
- describe("join()", () => {
6
- it("Combines path segments", () => {
7
- expect(path.join("a", "b", "c")).toBe("a/b/c");
8
- });
9
-
10
- it("Preserves leading slash", () => {
11
- expect(path.join("/a", "b")).toBe("/a/b");
12
- });
13
-
14
- it("Removes duplicate slashes", () => {
15
- expect(path.join("a/", "/b/", "/c")).toBe("a/b/c");
16
- });
17
-
18
- it("Ignores empty segments", () => {
19
- expect(path.join("a", "", "b")).toBe("a/b");
20
- });
21
-
22
- it("Empty input returns empty string", () => {
23
- expect(path.join()).toBe("");
24
- });
25
- });
26
-
27
- describe("basename()", () => {
28
- it("Extracts filename", () => {
29
- expect(path.basename("a/b/file.txt")).toBe("file.txt");
30
- });
31
-
32
- it("Removes extension", () => {
33
- expect(path.basename("a/b/file.txt", ".txt")).toBe("file");
34
- });
35
-
36
- it("Ignores non-matching extension", () => {
37
- expect(path.basename("a/b/file.txt", ".md")).toBe("file.txt");
38
- });
39
-
40
- it("Handles filename without path", () => {
41
- expect(path.basename("file.txt")).toBe("file.txt");
42
- });
43
- });
44
-
45
- describe("extname()", () => {
46
- it("Extracts extension", () => {
47
- expect(path.extname("file.txt")).toBe(".txt");
48
- });
49
-
50
- it("Extracts only last extension", () => {
51
- expect(path.extname("archive.tar.gz")).toBe(".gz");
52
- });
53
-
54
- it("File without extension returns empty string", () => {
55
- expect(path.extname("Makefile")).toBe("");
56
- });
57
-
58
- it("Hidden file returns empty string", () => {
59
- expect(path.extname(".gitignore")).toBe("");
60
- });
61
-
62
- it("Extracts extension from file with path", () => {
63
- expect(path.extname("a/b/file.ts")).toBe(".ts");
64
- });
65
-
66
- it("Empty string returns empty string", () => {
67
- expect(path.extname("")).toBe("");
68
- });
69
- });
70
- });
@@ -1,43 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { primitive, DateTime, DateOnly, Time, Uuid } from "@simplysm/core-common";
3
-
4
- describe("primitive utils", () => {
5
- describe("typeStr()", () => {
6
- it("Returns string", () => {
7
- expect(primitive.typeStr("hello")).toBe("string");
8
- });
9
-
10
- it("Returns number", () => {
11
- expect(primitive.typeStr(42)).toBe("number");
12
- });
13
-
14
- it("Returns boolean", () => {
15
- expect(primitive.typeStr(true)).toBe("boolean");
16
- expect(primitive.typeStr(false)).toBe("boolean");
17
- });
18
-
19
- it("Returns DateTime", () => {
20
- expect(primitive.typeStr(new DateTime())).toBe("DateTime");
21
- });
22
-
23
- it("Returns DateOnly", () => {
24
- expect(primitive.typeStr(new DateOnly())).toBe("DateOnly");
25
- });
26
-
27
- it("Returns Time", () => {
28
- expect(primitive.typeStr(new Time())).toBe("Time");
29
- });
30
-
31
- it("Returns Uuid", () => {
32
- expect(primitive.typeStr(Uuid.generate())).toBe("Uuid");
33
- });
34
-
35
- it("Uint8Array returns Bytes", () => {
36
- expect(primitive.typeStr(new Uint8Array([1, 2]))).toBe("Bytes");
37
- });
38
-
39
- it("Unsupported type throws error", () => {
40
- expect(() => primitive.typeStr({} as never)).toThrow();
41
- });
42
- });
43
- });
@@ -1,189 +0,0 @@
1
- import { describe, it, expect, vi } from "vitest";
2
- import { EventEmitter } from "@simplysm/core-common";
3
-
4
- interface TestEvents {
5
- message: string;
6
- count: number;
7
- data: { id: number; name: string };
8
- empty: void;
9
- }
10
-
11
- describe("SdEventEmitter", () => {
12
- //#region on/emit
13
-
14
- describe("on() / emit()", () => {
15
- it("Emits and receives event", () => {
16
- const emitter = new EventEmitter<TestEvents>();
17
- const listener = vi.fn();
18
-
19
- emitter.on("message", listener);
20
- emitter.emit("message", "hello");
21
-
22
- expect(listener).toHaveBeenCalledWith("hello");
23
- expect(listener).toHaveBeenCalledTimes(1);
24
- });
25
-
26
- it("Listener called multiple times on multiple emit", () => {
27
- const emitter = new EventEmitter<TestEvents>();
28
- const listener = vi.fn();
29
-
30
- emitter.on("count", listener);
31
- emitter.emit("count", 1);
32
- emitter.emit("count", 2);
33
- emitter.emit("count", 3);
34
-
35
- expect(listener).toHaveBeenCalledTimes(3);
36
- expect(listener).toHaveBeenNthCalledWith(1, 1);
37
- expect(listener).toHaveBeenNthCalledWith(2, 2);
38
- expect(listener).toHaveBeenNthCalledWith(3, 3);
39
- });
40
-
41
- it("Can register multiple listeners for same event", () => {
42
- const emitter = new EventEmitter<TestEvents>();
43
- const listener1 = vi.fn();
44
- const listener2 = vi.fn();
45
-
46
- emitter.on("message", listener1);
47
- emitter.on("message", listener2);
48
- emitter.emit("message", "test");
49
-
50
- expect(listener1).toHaveBeenCalledWith("test");
51
- expect(listener2).toHaveBeenCalledWith("test");
52
- });
53
- });
54
-
55
- //#endregion
56
-
57
- //#region off
58
-
59
- describe("off()", () => {
60
- it("Removes listener", () => {
61
- const emitter = new EventEmitter<TestEvents>();
62
- const listener = vi.fn();
63
-
64
- emitter.on("message", listener);
65
- emitter.off("message", listener);
66
- emitter.emit("message", "test");
67
-
68
- expect(listener).not.toHaveBeenCalled();
69
- });
70
-
71
- it("Removes only specified listener, others remain", () => {
72
- const emitter = new EventEmitter<TestEvents>();
73
- const listener1 = vi.fn();
74
- const listener2 = vi.fn();
75
-
76
- emitter.on("message", listener1);
77
- emitter.on("message", listener2);
78
- emitter.off("message", listener1);
79
- emitter.emit("message", "test");
80
-
81
- expect(listener1).not.toHaveBeenCalled();
82
- expect(listener2).toHaveBeenCalledWith("test");
83
- });
84
-
85
- it("No error removing unregistered listener", () => {
86
- const emitter = new EventEmitter<TestEvents>();
87
- const listener = vi.fn();
88
-
89
- // Should run without error
90
- expect(() => {
91
- emitter.off("message", listener);
92
- }).not.toThrow();
93
- });
94
- });
95
-
96
- //#endregion
97
-
98
- //#region listenerCount
99
-
100
- describe("listenerCount()", () => {
101
- it("Accurately counts listeners", () => {
102
- const emitter = new EventEmitter<TestEvents>();
103
-
104
- expect(emitter.listenerCount("message")).toBe(0);
105
-
106
- emitter.on("message", () => {});
107
- expect(emitter.listenerCount("message")).toBe(1);
108
-
109
- emitter.on("message", () => {});
110
- expect(emitter.listenerCount("message")).toBe(2);
111
- });
112
-
113
- it("Count decreases after off", () => {
114
- const emitter = new EventEmitter<TestEvents>();
115
- const listener = vi.fn();
116
-
117
- emitter.on("message", listener);
118
- expect(emitter.listenerCount("message")).toBe(1);
119
-
120
- emitter.off("message", listener);
121
- expect(emitter.listenerCount("message")).toBe(0);
122
- });
123
-
124
- it("Different event types have independent counts", () => {
125
- const emitter = new EventEmitter<TestEvents>();
126
-
127
- emitter.on("message", () => {});
128
- emitter.on("message", () => {});
129
- emitter.on("count", () => {});
130
-
131
- expect(emitter.listenerCount("message")).toBe(2);
132
- expect(emitter.listenerCount("count")).toBe(1);
133
- });
134
- });
135
-
136
- //#endregion
137
-
138
- //#region Prevent duplicate registration
139
-
140
- describe("Prevent duplicate registration", () => {
141
- it("Duplicate registration of same listener is ignored", () => {
142
- const emitter = new EventEmitter<TestEvents>();
143
- const listener = vi.fn();
144
-
145
- emitter.on("message", listener);
146
- emitter.on("message", listener); // duplicate registration attempt
147
- emitter.on("message", listener); // duplicate registration attempt
148
-
149
- expect(emitter.listenerCount("message")).toBe(1);
150
-
151
- emitter.emit("message", "test");
152
- expect(listener).toHaveBeenCalledTimes(1);
153
- });
154
-
155
- it("Can register same listener to different events", () => {
156
- const emitter = new EventEmitter<TestEvents>();
157
- const listener = vi.fn();
158
-
159
- emitter.on("message", listener);
160
- emitter.on("count", listener as any);
161
-
162
- expect(emitter.listenerCount("message")).toBe(1);
163
- expect(emitter.listenerCount("count")).toBe(1);
164
-
165
- emitter.emit("message", "test");
166
- emitter.emit("count", 123);
167
-
168
- expect(listener).toHaveBeenCalledTimes(2);
169
- expect(listener).toHaveBeenNthCalledWith(1, "test");
170
- expect(listener).toHaveBeenNthCalledWith(2, 123);
171
- });
172
-
173
- it("Single off call removes after duplicate registration", () => {
174
- const emitter = new EventEmitter<TestEvents>();
175
- const listener = vi.fn();
176
-
177
- emitter.on("message", listener);
178
- emitter.on("message", listener); // duplicate registration attempt
179
-
180
- emitter.off("message", listener);
181
- expect(emitter.listenerCount("message")).toBe(0);
182
-
183
- emitter.emit("message", "test");
184
- expect(listener).not.toHaveBeenCalled();
185
- });
186
- });
187
-
188
- //#endregion
189
- });
@@ -1,305 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
- import { SerialQueue, SdError } from "@simplysm/core-common";
3
-
4
- describe("SerialQueue", () => {
5
- beforeEach(() => {
6
- vi.useFakeTimers();
7
- });
8
-
9
- afterEach(() => {
10
- vi.useRealTimers();
11
- });
12
-
13
- //#region Sequential execution
14
-
15
- describe("Sequential execution", () => {
16
- it("Executes queued functions in order", async () => {
17
- const queue = new SerialQueue();
18
- const calls: number[] = [];
19
-
20
- queue.run(() => {
21
- calls.push(1);
22
- });
23
- queue.run(() => {
24
- calls.push(2);
25
- });
26
- queue.run(() => {
27
- calls.push(3);
28
- });
29
-
30
- await vi.advanceTimersByTimeAsync(50);
31
-
32
- expect(calls).toEqual([1, 2, 3]);
33
- });
34
-
35
- it("Executes next task after previous task completes", async () => {
36
- const queue = new SerialQueue();
37
- const calls: number[] = [];
38
- const timestamps: number[] = [];
39
-
40
- queue.run(async () => {
41
- timestamps.push(Date.now());
42
- calls.push(1);
43
- await new Promise((r) => setTimeout(r, 50));
44
- });
45
- queue.run(async () => {
46
- timestamps.push(Date.now());
47
- calls.push(2);
48
- await new Promise((r) => setTimeout(r, 50));
49
- });
50
-
51
- await vi.advanceTimersByTimeAsync(200);
52
-
53
- expect(calls).toEqual([1, 2]);
54
- // Second task starts after first task completes (exactly 50ms)
55
- expect(timestamps[1] - timestamps[0]).toBe(50);
56
- });
57
-
58
- it("Executes tasks added during execution sequentially", async () => {
59
- const queue = new SerialQueue();
60
- const calls: number[] = [];
61
-
62
- queue.run(async () => {
63
- calls.push(1);
64
- await new Promise((r) => setTimeout(r, 50));
65
- });
66
-
67
- // Wait for first task to start
68
- await vi.advanceTimersByTimeAsync(10);
69
-
70
- // Add task during execution
71
- queue.run(() => {
72
- calls.push(2);
73
- });
74
-
75
- await vi.advanceTimersByTimeAsync(100);
76
-
77
- expect(calls).toEqual([1, 2]);
78
- });
79
- });
80
-
81
- //#endregion
82
-
83
- //#region Gap interval
84
-
85
- describe("Gap interval", () => {
86
- it("Waits gap duration between tasks when set", async () => {
87
- const queue = new SerialQueue(50);
88
- const timestamps: number[] = [];
89
-
90
- queue.run(() => {
91
- timestamps.push(Date.now());
92
- });
93
- queue.run(() => {
94
- timestamps.push(Date.now());
95
- });
96
-
97
- await vi.advanceTimersByTimeAsync(150);
98
-
99
- expect(timestamps).toHaveLength(2);
100
- // Exactly 50ms gap between two tasks
101
- expect(timestamps[1] - timestamps[0]).toBe(50);
102
- });
103
-
104
- it("Executes next task immediately when gap is 0", async () => {
105
- const queue = new SerialQueue(0);
106
- const timestamps: number[] = [];
107
-
108
- queue.run(() => {
109
- timestamps.push(Date.now());
110
- });
111
- queue.run(() => {
112
- timestamps.push(Date.now());
113
- });
114
-
115
- await vi.advanceTimersByTimeAsync(50);
116
-
117
- expect(timestamps).toHaveLength(2);
118
- // Gap is 0
119
- expect(timestamps[1] - timestamps[0]).toBe(0);
120
- });
121
-
122
- });
123
-
124
- //#endregion
125
-
126
- //#region Error handling
127
-
128
- describe("Error handling", () => {
129
- it("Emits error event when error occurs", async () => {
130
- const queue = new SerialQueue();
131
- const errors: SdError[] = [];
132
-
133
- queue.on("error", (err) => {
134
- errors.push(err);
135
- });
136
-
137
- queue.run(() => {
138
- throw new Error("test error");
139
- });
140
-
141
- await vi.advanceTimersByTimeAsync(50);
142
-
143
- expect(errors).toHaveLength(1);
144
- expect(errors[0]).toBeInstanceOf(SdError);
145
- expect(errors[0].message).toContain("Error occurred while executing queue task");
146
- expect(errors[0].message).toContain("test error");
147
- });
148
-
149
- it("Continues executing next task even after error", async () => {
150
- const queue = new SerialQueue();
151
- const calls: number[] = [];
152
- const errors: SdError[] = [];
153
-
154
- // Add error listener to prevent unhandled rejection
155
- queue.on("error", (err) => {
156
- errors.push(err);
157
- });
158
-
159
- queue.run(() => {
160
- calls.push(1);
161
- throw new Error("error");
162
- });
163
- queue.run(() => {
164
- calls.push(2);
165
- });
166
- queue.run(() => {
167
- calls.push(3);
168
- });
169
-
170
- await vi.advanceTimersByTimeAsync(100);
171
-
172
- expect(calls).toEqual([1, 2, 3]);
173
- expect(errors).toHaveLength(1);
174
- });
175
-
176
- it("Executes all tasks even if multiple errors occur", async () => {
177
- const queue = new SerialQueue();
178
- const calls: number[] = [];
179
- const errors: SdError[] = [];
180
-
181
- queue.on("error", (err) => {
182
- errors.push(err);
183
- });
184
-
185
- queue.run(() => {
186
- calls.push(1);
187
- throw new Error("error 1");
188
- });
189
- queue.run(() => {
190
- calls.push(2);
191
- });
192
- queue.run(() => {
193
- calls.push(3);
194
- throw new Error("error 3");
195
- });
196
-
197
- await vi.advanceTimersByTimeAsync(100);
198
-
199
- expect(calls).toEqual([1, 2, 3]);
200
- expect(errors).toHaveLength(2);
201
- expect(errors[0].message).toContain("error 1");
202
- expect(errors[1].message).toContain("error 3");
203
- });
204
- });
205
-
206
- //#endregion
207
-
208
- //#region dispose
209
-
210
- describe("dispose()", () => {
211
- it("Clears pending queue", async () => {
212
- const queue = new SerialQueue();
213
- const calls: number[] = [];
214
-
215
- // First task is executing
216
- queue.run(async () => {
217
- calls.push(1);
218
- await new Promise((r) => setTimeout(r, 100));
219
- });
220
-
221
- // Add pending tasks
222
- queue.run(() => {
223
- calls.push(2);
224
- });
225
- queue.run(() => {
226
- calls.push(3);
227
- });
228
-
229
- // Call dispose after first task starts
230
- await vi.advanceTimersByTimeAsync(20);
231
- queue.dispose();
232
-
233
- // Wait for all tasks to complete
234
- await vi.advanceTimersByTimeAsync(150);
235
-
236
- // Only first task executes (running tasks complete)
237
- expect(calls).toEqual([1]);
238
- });
239
-
240
- it("New tasks execute normally after dispose", async () => {
241
- const queue = new SerialQueue();
242
- const calls: number[] = [];
243
-
244
- queue.run(() => {
245
- calls.push(1);
246
- });
247
- queue.dispose();
248
-
249
- // Add new task after dispose
250
- queue.run(() => {
251
- calls.push(2);
252
- });
253
-
254
- await vi.advanceTimersByTimeAsync(50);
255
-
256
- expect(calls).toContain(2);
257
- });
258
-
259
- it("Automatically disposes with using statement", async () => {
260
- const calls: number[] = [];
261
- {
262
- using queue = new SerialQueue();
263
- queue.run(async () => {
264
- calls.push(1);
265
- await new Promise((r) => setTimeout(r, 100));
266
- });
267
- queue.run(() => {
268
- calls.push(2);
269
- });
270
- await vi.advanceTimersByTimeAsync(20);
271
- } // dispose called automatically when using block ends
272
- await vi.advanceTimersByTimeAsync(150);
273
- // First task (running) completes, but pending tasks don't execute
274
- expect(calls).toEqual([1]);
275
- });
276
- });
277
-
278
- //#endregion
279
-
280
- //#region Synchronous function support
281
-
282
- describe("Synchronous function support", () => {
283
- it("Can mix synchronous and asynchronous functions", async () => {
284
- const queue = new SerialQueue();
285
- const calls: number[] = [];
286
-
287
- queue.run(() => {
288
- calls.push(1);
289
- });
290
- queue.run(async () => {
291
- await new Promise((r) => setTimeout(r, 10));
292
- calls.push(2);
293
- });
294
- queue.run(() => {
295
- calls.push(3);
296
- });
297
-
298
- await vi.advanceTimersByTimeAsync(100);
299
-
300
- expect(calls).toEqual([1, 2, 3]);
301
- });
302
- });
303
-
304
- //#endregion
305
- });