@simplysm/core-common 13.0.100 → 14.0.4

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 (184) hide show
  1. package/README.md +86 -92
  2. package/dist/common.types.d.ts +14 -14
  3. package/dist/common.types.js +2 -1
  4. package/dist/common.types.js.map +1 -6
  5. package/dist/env.d.ts +8 -1
  6. package/dist/env.d.ts.map +1 -1
  7. package/dist/env.js +13 -9
  8. package/dist/env.js.map +1 -6
  9. package/dist/errors/argument-error.d.ts +10 -10
  10. package/dist/errors/argument-error.d.ts.map +1 -1
  11. package/dist/errors/argument-error.js +31 -14
  12. package/dist/errors/argument-error.js.map +1 -6
  13. package/dist/errors/not-implemented-error.d.ts +8 -8
  14. package/dist/errors/not-implemented-error.js +30 -12
  15. package/dist/errors/not-implemented-error.js.map +1 -6
  16. package/dist/errors/sd-error.d.ts +10 -10
  17. package/dist/errors/sd-error.d.ts.map +1 -1
  18. package/dist/errors/sd-error.js +45 -24
  19. package/dist/errors/sd-error.js.map +1 -6
  20. package/dist/errors/timeout-error.d.ts +10 -10
  21. package/dist/errors/timeout-error.js +34 -15
  22. package/dist/errors/timeout-error.js.map +1 -6
  23. package/dist/extensions/arr-ext.d.ts +2 -2
  24. package/dist/extensions/arr-ext.helpers.d.ts +10 -10
  25. package/dist/extensions/arr-ext.helpers.js +112 -89
  26. package/dist/extensions/arr-ext.helpers.js.map +1 -6
  27. package/dist/extensions/arr-ext.js +458 -422
  28. package/dist/extensions/arr-ext.js.map +1 -6
  29. package/dist/extensions/arr-ext.types.d.ts +57 -57
  30. package/dist/extensions/arr-ext.types.d.ts.map +1 -1
  31. package/dist/extensions/arr-ext.types.js +6 -1
  32. package/dist/extensions/arr-ext.types.js.map +1 -6
  33. package/dist/extensions/map-ext.d.ts +16 -16
  34. package/dist/extensions/map-ext.js +27 -22
  35. package/dist/extensions/map-ext.js.map +1 -6
  36. package/dist/extensions/set-ext.d.ts +11 -11
  37. package/dist/extensions/set-ext.js +32 -25
  38. package/dist/extensions/set-ext.js.map +1 -6
  39. package/dist/features/debounce-queue.d.ts +17 -17
  40. package/dist/features/debounce-queue.js +98 -70
  41. package/dist/features/debounce-queue.js.map +1 -6
  42. package/dist/features/event-emitter.d.ts +20 -20
  43. package/dist/features/event-emitter.js +101 -78
  44. package/dist/features/event-emitter.js.map +1 -6
  45. package/dist/features/serial-queue.d.ts +11 -11
  46. package/dist/features/serial-queue.js +78 -57
  47. package/dist/features/serial-queue.js.map +1 -6
  48. package/dist/globals.d.ts +4 -4
  49. package/dist/globals.js +9 -1
  50. package/dist/globals.js.map +1 -6
  51. package/dist/index.js +28 -27
  52. package/dist/index.js.map +1 -6
  53. package/dist/types/date-only.d.ts +64 -64
  54. package/dist/types/date-only.d.ts.map +1 -1
  55. package/dist/types/date-only.js +263 -252
  56. package/dist/types/date-only.js.map +1 -6
  57. package/dist/types/date-time.d.ts +36 -36
  58. package/dist/types/date-time.d.ts.map +1 -1
  59. package/dist/types/date-time.js +196 -288
  60. package/dist/types/date-time.js.map +1 -6
  61. package/dist/types/lazy-gc-map.d.ts +26 -26
  62. package/dist/types/lazy-gc-map.d.ts.map +1 -1
  63. package/dist/types/lazy-gc-map.js +202 -159
  64. package/dist/types/lazy-gc-map.js.map +1 -6
  65. package/dist/types/time.d.ts +23 -23
  66. package/dist/types/time.d.ts.map +1 -1
  67. package/dist/types/time.js +169 -158
  68. package/dist/types/time.js.map +1 -6
  69. package/dist/types/uuid.d.ts +11 -11
  70. package/dist/types/uuid.d.ts.map +1 -1
  71. package/dist/types/uuid.js +95 -70
  72. package/dist/types/uuid.js.map +1 -6
  73. package/dist/utils/bytes.d.ts +17 -17
  74. package/dist/utils/bytes.js +137 -81
  75. package/dist/utils/bytes.js.map +1 -6
  76. package/dist/utils/date-format.d.ts +40 -40
  77. package/dist/utils/date-format.js +187 -101
  78. package/dist/utils/date-format.js.map +1 -6
  79. package/dist/utils/error.d.ts +4 -4
  80. package/dist/utils/error.js +11 -6
  81. package/dist/utils/error.js.map +1 -6
  82. package/dist/utils/json.d.ts +19 -19
  83. package/dist/utils/json.js +187 -135
  84. package/dist/utils/json.js.map +1 -6
  85. package/dist/utils/num.d.ts +20 -20
  86. package/dist/utils/num.js +76 -34
  87. package/dist/utils/num.js.map +1 -6
  88. package/dist/utils/obj.d.ts +111 -111
  89. package/dist/utils/obj.d.ts.map +1 -1
  90. package/dist/utils/obj.js +706 -496
  91. package/dist/utils/obj.js.map +1 -6
  92. package/dist/utils/path.d.ts +10 -10
  93. package/dist/utils/path.js +35 -18
  94. package/dist/utils/path.js.map +1 -6
  95. package/dist/utils/primitive.d.ts +5 -5
  96. package/dist/utils/primitive.js +34 -14
  97. package/dist/utils/primitive.js.map +1 -6
  98. package/dist/utils/str.d.ts +38 -38
  99. package/dist/utils/str.js +217 -113
  100. package/dist/utils/str.js.map +1 -6
  101. package/dist/utils/template-strings.d.ts +26 -26
  102. package/dist/utils/template-strings.js +113 -40
  103. package/dist/utils/template-strings.js.map +1 -6
  104. package/dist/utils/transferable.d.ts +18 -18
  105. package/dist/utils/transferable.js +218 -151
  106. package/dist/utils/transferable.js.map +1 -6
  107. package/dist/utils/wait.d.ts +9 -9
  108. package/dist/utils/wait.js +30 -15
  109. package/dist/utils/wait.js.map +1 -6
  110. package/dist/utils/xml.d.ts +13 -13
  111. package/dist/utils/xml.js +84 -46
  112. package/dist/utils/xml.js.map +1 -6
  113. package/dist/utils/zip.d.ts +22 -22
  114. package/dist/utils/zip.js +172 -148
  115. package/dist/utils/zip.js.map +1 -6
  116. package/docs/array-extensions.md +430 -0
  117. package/docs/env.md +52 -0
  118. package/docs/errors.md +41 -56
  119. package/docs/features.md +82 -97
  120. package/docs/type-utilities.md +91 -0
  121. package/docs/types.md +221 -201
  122. package/docs/utils.md +319 -435
  123. package/package.json +7 -5
  124. package/src/common.types.ts +14 -14
  125. package/src/env.ts +12 -3
  126. package/src/errors/argument-error.ts +15 -15
  127. package/src/errors/not-implemented-error.ts +9 -9
  128. package/src/errors/sd-error.ts +12 -12
  129. package/src/errors/timeout-error.ts +12 -12
  130. package/src/extensions/arr-ext.helpers.ts +16 -16
  131. package/src/extensions/arr-ext.ts +35 -35
  132. package/src/extensions/arr-ext.types.ts +57 -57
  133. package/src/extensions/map-ext.ts +16 -16
  134. package/src/extensions/set-ext.ts +11 -11
  135. package/src/features/debounce-queue.ts +23 -23
  136. package/src/features/event-emitter.ts +25 -25
  137. package/src/features/serial-queue.ts +13 -13
  138. package/src/globals.ts +4 -4
  139. package/src/index.ts +5 -5
  140. package/src/types/date-only.ts +84 -83
  141. package/src/types/date-time.ts +43 -42
  142. package/src/types/lazy-gc-map.ts +44 -44
  143. package/src/types/time.ts +29 -29
  144. package/src/types/uuid.ts +15 -15
  145. package/src/utils/bytes.ts +35 -35
  146. package/src/utils/date-format.ts +59 -59
  147. package/src/utils/error.ts +4 -4
  148. package/src/utils/json.ts +41 -41
  149. package/src/utils/num.ts +20 -20
  150. package/src/utils/obj.ts +138 -138
  151. package/src/utils/path.ts +10 -10
  152. package/src/utils/primitive.ts +6 -6
  153. package/src/utils/str.ts +48 -48
  154. package/src/utils/template-strings.ts +29 -29
  155. package/src/utils/transferable.ts +38 -38
  156. package/src/utils/wait.ts +10 -10
  157. package/src/utils/xml.ts +19 -19
  158. package/src/utils/zip.ts +25 -25
  159. package/docs/extensions.md +0 -387
  160. package/tests/errors/errors.spec.ts +0 -80
  161. package/tests/extensions/array-extension.spec.ts +0 -654
  162. package/tests/extensions/map-extension.spec.ts +0 -117
  163. package/tests/extensions/set-extension.spec.ts +0 -67
  164. package/tests/types/date-only.spec.ts +0 -533
  165. package/tests/types/date-time.spec.ts +0 -246
  166. package/tests/types/lazy-gc-map.spec.ts +0 -606
  167. package/tests/types/time.spec.ts +0 -428
  168. package/tests/types/uuid.spec.ts +0 -74
  169. package/tests/utils/bytes-utils.spec.ts +0 -197
  170. package/tests/utils/date-format.spec.ts +0 -350
  171. package/tests/utils/debounce-queue.spec.ts +0 -226
  172. package/tests/utils/json.spec.ts +0 -400
  173. package/tests/utils/number.spec.ts +0 -136
  174. package/tests/utils/object.spec.ts +0 -810
  175. package/tests/utils/path.spec.ts +0 -70
  176. package/tests/utils/primitive.spec.ts +0 -43
  177. package/tests/utils/sd-event-emitter.spec.ts +0 -189
  178. package/tests/utils/serial-queue.spec.ts +0 -305
  179. package/tests/utils/string.spec.ts +0 -265
  180. package/tests/utils/template-strings.spec.ts +0 -48
  181. package/tests/utils/transferable.spec.ts +0 -639
  182. package/tests/utils/wait.spec.ts +0 -123
  183. package/tests/utils/xml.spec.ts +0 -146
  184. package/tests/utils/zip.spec.ts +0 -221
@@ -1,350 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { dt } from "@simplysm/core-common";
3
- import { normalizeMonth } from "../../src/utils/date-format";
4
-
5
- describe("formatDateTime", () => {
6
- //#region Year pattern
7
-
8
- describe("Year pattern", () => {
9
- it("outputs 4-digit year with yyyy format", () => {
10
- expect(dt.format("yyyy", { year: 2025 })).toBe("2025");
11
- });
12
-
13
- it("outputs 2-digit year with yy format", () => {
14
- expect(dt.format("yy", { year: 2025 })).toBe("25");
15
- expect(dt.format("yy", { year: 2000 })).toBe("00");
16
- expect(dt.format("yy", { year: 1999 })).toBe("99");
17
- });
18
- });
19
-
20
- //#endregion
21
-
22
- //#region Month pattern
23
-
24
- describe("Month pattern", () => {
25
- it("outputs 2-digit month with MM format", () => {
26
- expect(dt.format("MM", { month: 1 })).toBe("01");
27
- expect(dt.format("MM", { month: 9 })).toBe("09");
28
- expect(dt.format("MM", { month: 12 })).toBe("12");
29
- });
30
-
31
- it("outputs month without padding with M format", () => {
32
- expect(dt.format("M", { month: 1 })).toBe("1");
33
- expect(dt.format("M", { month: 9 })).toBe("9");
34
- expect(dt.format("M", { month: 12 })).toBe("12");
35
- });
36
- });
37
-
38
- //#endregion
39
-
40
- //#region Day pattern
41
-
42
- describe("Day pattern", () => {
43
- it("outputs 2-digit day with dd format", () => {
44
- expect(dt.format("dd", { day: 1 })).toBe("01");
45
- expect(dt.format("dd", { day: 9 })).toBe("09");
46
- expect(dt.format("dd", { day: 31 })).toBe("31");
47
- });
48
-
49
- it("outputs day without padding with d format", () => {
50
- expect(dt.format("d", { day: 1 })).toBe("1");
51
- expect(dt.format("d", { day: 9 })).toBe("9");
52
- expect(dt.format("d", { day: 31 })).toBe("31");
53
- });
54
- });
55
-
56
- //#endregion
57
-
58
- //#region Day of week pattern
59
-
60
- describe("Day of week pattern", () => {
61
- it("outputs day of week in Korean with ddd format", () => {
62
- // 2025-01-18 is Saturday
63
- expect(dt.format("ddd", { year: 2025, month: 1, day: 18 })).toBe("토");
64
- // 2025-01-19 is Sunday
65
- expect(dt.format("ddd", { year: 2025, month: 1, day: 19 })).toBe("일");
66
- // 2025-01-20 is Monday
67
- expect(dt.format("ddd", { year: 2025, month: 1, day: 20 })).toBe("월");
68
- });
69
- });
70
-
71
- //#endregion
72
-
73
- //#region Hour pattern
74
-
75
- describe("Hour pattern", () => {
76
- it("outputs 12-hour format with padding using hh format", () => {
77
- expect(dt.format("hh", { hour: 0 })).toBe("12");
78
- expect(dt.format("hh", { hour: 1 })).toBe("01");
79
- expect(dt.format("hh", { hour: 12 })).toBe("12");
80
- expect(dt.format("hh", { hour: 13 })).toBe("01");
81
- });
82
-
83
- it("outputs 12-hour format without padding using h format", () => {
84
- expect(dt.format("h", { hour: 0 })).toBe("12");
85
- expect(dt.format("h", { hour: 1 })).toBe("1");
86
- expect(dt.format("h", { hour: 9 })).toBe("9");
87
- expect(dt.format("h", { hour: 10 })).toBe("10");
88
- expect(dt.format("h", { hour: 12 })).toBe("12");
89
- expect(dt.format("h", { hour: 13 })).toBe("1");
90
- expect(dt.format("h", { hour: 23 })).toBe("11");
91
- });
92
-
93
- it("outputs 24-hour format with padding using HH format", () => {
94
- expect(dt.format("HH", { hour: 0 })).toBe("00");
95
- expect(dt.format("HH", { hour: 9 })).toBe("09");
96
- expect(dt.format("HH", { hour: 23 })).toBe("23");
97
- });
98
-
99
- it("outputs 24-hour format without padding using H format", () => {
100
- expect(dt.format("H", { hour: 0 })).toBe("0");
101
- expect(dt.format("H", { hour: 9 })).toBe("9");
102
- expect(dt.format("H", { hour: 23 })).toBe("23");
103
- });
104
-
105
- it("outputs AM/PM with tt format", () => {
106
- expect(dt.format("tt", { hour: 0 })).toBe("AM");
107
- expect(dt.format("tt", { hour: 11 })).toBe("AM");
108
- expect(dt.format("tt", { hour: 12 })).toBe("PM");
109
- expect(dt.format("tt", { hour: 23 })).toBe("PM");
110
- });
111
- });
112
-
113
- //#endregion
114
-
115
- //#region Minute pattern
116
-
117
- describe("Minute pattern", () => {
118
- it("outputs 2-digit minute with mm format", () => {
119
- expect(dt.format("mm", { minute: 0 })).toBe("00");
120
- expect(dt.format("mm", { minute: 5 })).toBe("05");
121
- expect(dt.format("mm", { minute: 59 })).toBe("59");
122
- });
123
-
124
- it("outputs minute without padding with m format", () => {
125
- expect(dt.format("m", { minute: 0 })).toBe("0");
126
- expect(dt.format("m", { minute: 5 })).toBe("5");
127
- expect(dt.format("m", { minute: 59 })).toBe("59");
128
- });
129
- });
130
-
131
- //#endregion
132
-
133
- //#region Second pattern
134
-
135
- describe("Second pattern", () => {
136
- it("outputs 2-digit second with ss format", () => {
137
- expect(dt.format("ss", { second: 0 })).toBe("00");
138
- expect(dt.format("ss", { second: 5 })).toBe("05");
139
- expect(dt.format("ss", { second: 59 })).toBe("59");
140
- });
141
-
142
- it("outputs second without padding with s format", () => {
143
- expect(dt.format("s", { second: 0 })).toBe("0");
144
- expect(dt.format("s", { second: 5 })).toBe("5");
145
- expect(dt.format("s", { second: 59 })).toBe("59");
146
- });
147
- });
148
-
149
- //#endregion
150
-
151
- //#region Millisecond pattern
152
-
153
- describe("Millisecond pattern", () => {
154
- it("outputs 3-digit millisecond with fff format", () => {
155
- expect(dt.format("fff", { millisecond: 0 })).toBe("000");
156
- expect(dt.format("fff", { millisecond: 5 })).toBe("005");
157
- expect(dt.format("fff", { millisecond: 50 })).toBe("050");
158
- expect(dt.format("fff", { millisecond: 500 })).toBe("500");
159
- expect(dt.format("fff", { millisecond: 999 })).toBe("999");
160
- });
161
-
162
- it("outputs 2-digit millisecond with ff format", () => {
163
- expect(dt.format("ff", { millisecond: 0 })).toBe("00");
164
- expect(dt.format("ff", { millisecond: 5 })).toBe("00");
165
- expect(dt.format("ff", { millisecond: 50 })).toBe("05");
166
- expect(dt.format("ff", { millisecond: 500 })).toBe("50");
167
- expect(dt.format("ff", { millisecond: 999 })).toBe("99");
168
- });
169
-
170
- it("outputs 1-digit millisecond with f format", () => {
171
- expect(dt.format("f", { millisecond: 0 })).toBe("0");
172
- expect(dt.format("f", { millisecond: 5 })).toBe("0");
173
- expect(dt.format("f", { millisecond: 100 })).toBe("1");
174
- expect(dt.format("f", { millisecond: 500 })).toBe("5");
175
- expect(dt.format("f", { millisecond: 999 })).toBe("9");
176
- });
177
- });
178
-
179
- //#endregion
180
-
181
- //#region Timezone pattern
182
-
183
- describe("Timezone pattern", () => {
184
- describe("Positive offset (East)", () => {
185
- it("outputs +HH:mm format with zzz format", () => {
186
- // UTC+9 (540 minutes)
187
- expect(dt.format("zzz", { timezoneOffsetMinutes: 540 })).toBe("+09:00");
188
- // UTC+5:30 (330 minutes)
189
- expect(dt.format("zzz", { timezoneOffsetMinutes: 330 })).toBe("+05:30");
190
- });
191
-
192
- it("outputs +HH format with zz format", () => {
193
- expect(dt.format("zz", { timezoneOffsetMinutes: 540 })).toBe("+09");
194
- expect(dt.format("zz", { timezoneOffsetMinutes: 60 })).toBe("+01");
195
- });
196
-
197
- it("outputs +H format without padding with z format", () => {
198
- expect(dt.format("z", { timezoneOffsetMinutes: 540 })).toBe("+9");
199
- expect(dt.format("z", { timezoneOffsetMinutes: 60 })).toBe("+1");
200
- expect(dt.format("z", { timezoneOffsetMinutes: 600 })).toBe("+10");
201
- });
202
- });
203
-
204
- describe("Negative offset (West)", () => {
205
- it("outputs -HH:mm format with zzz format", () => {
206
- // UTC-5 (-300 minutes) - Integer hour offset
207
- expect(dt.format("zzz", { timezoneOffsetMinutes: -300 })).toBe("-05:00");
208
- // UTC-8 (-480 minutes) - Integer hour offset
209
- expect(dt.format("zzz", { timezoneOffsetMinutes: -480 })).toBe("-08:00");
210
- // UTC-3:30 (-210 minutes) - Newfoundland Standard Time
211
- expect(dt.format("zzz", { timezoneOffsetMinutes: -210 })).toBe("-03:30");
212
- // UTC-9:30 (-570 minutes) - Marquesas Islands
213
- expect(dt.format("zzz", { timezoneOffsetMinutes: -570 })).toBe("-09:30");
214
- });
215
-
216
- it("outputs -HH format with zz format", () => {
217
- expect(dt.format("zz", { timezoneOffsetMinutes: -300 })).toBe("-05");
218
- expect(dt.format("zz", { timezoneOffsetMinutes: -60 })).toBe("-01");
219
- });
220
-
221
- it("outputs -H format without padding with z format", () => {
222
- expect(dt.format("z", { timezoneOffsetMinutes: -300 })).toBe("-5");
223
- expect(dt.format("z", { timezoneOffsetMinutes: -60 })).toBe("-1");
224
- expect(dt.format("z", { timezoneOffsetMinutes: -720 })).toBe("-12");
225
- });
226
- });
227
-
228
- describe("UTC (0 offset)", () => {
229
- it("outputs +00:00 with zzz format", () => {
230
- expect(dt.format("zzz", { timezoneOffsetMinutes: 0 })).toBe("+00:00");
231
- });
232
- });
233
- });
234
-
235
- //#endregion
236
-
237
- //#endregion
238
-
239
- //#region Complex format
240
-
241
- describe("Complex format", () => {
242
- it("handles full date/time format", () => {
243
- const result = dt.format("yyyy-MM-dd HH:mm:ss.fff", {
244
- year: 2025,
245
- month: 1,
246
- day: 18,
247
- hour: 14,
248
- minute: 30,
249
- second: 45,
250
- millisecond: 123,
251
- });
252
- expect(result).toBe("2025-01-18 14:30:45.123");
253
- });
254
-
255
- it("handles 12-hour format", () => {
256
- const result = dt.format("yyyy-MM-dd tt h:mm:ss", {
257
- year: 2025,
258
- month: 1,
259
- day: 18,
260
- hour: 14,
261
- minute: 5,
262
- second: 9,
263
- });
264
- expect(result).toBe("2025-01-18 PM 2:05:09");
265
- });
266
-
267
- it("handles format with timezone", () => {
268
- const result = dt.format("yyyy-MM-ddTHH:mm:sszzz", {
269
- year: 2025,
270
- month: 1,
271
- day: 18,
272
- hour: 14,
273
- minute: 30,
274
- second: 0,
275
- timezoneOffsetMinutes: 540,
276
- });
277
- expect(result).toBe("2025-01-18T14:30:00+09:00");
278
- });
279
- });
280
-
281
- //#endregion
282
- });
283
-
284
- describe("normalizeMonth", () => {
285
- //#region Normal range
286
-
287
- describe("Normal range (1-12)", () => {
288
- it("returns unchanged if month is within 1-12 range", () => {
289
- expect(normalizeMonth(2025, 1, 15)).toEqual({ year: 2025, month: 1, day: 15 });
290
- expect(normalizeMonth(2025, 6, 15)).toEqual({ year: 2025, month: 6, day: 15 });
291
- expect(normalizeMonth(2025, 12, 15)).toEqual({ year: 2025, month: 12, day: 15 });
292
- });
293
- });
294
-
295
- //#endregion
296
-
297
- //#region Month overflow
298
-
299
- describe("Month overflow (13 or more)", () => {
300
- it("month 13 becomes January next year", () => {
301
- expect(normalizeMonth(2025, 13, 15)).toEqual({ year: 2026, month: 1, day: 15 });
302
- });
303
-
304
- it("month 25 becomes January 2 years later", () => {
305
- expect(normalizeMonth(2025, 25, 15)).toEqual({ year: 2027, month: 1, day: 15 });
306
- });
307
- });
308
-
309
- //#endregion
310
-
311
- //#region Month underflow
312
-
313
- describe("Month underflow (0 or less)", () => {
314
- it("month 0 becomes December previous year", () => {
315
- expect(normalizeMonth(2025, 0, 15)).toEqual({ year: 2024, month: 12, day: 15 });
316
- });
317
-
318
- it("month -1 becomes November previous year", () => {
319
- expect(normalizeMonth(2025, -1, 15)).toEqual({ year: 2024, month: 11, day: 15 });
320
- });
321
-
322
- it("month -13 becomes November 2 years ago", () => {
323
- expect(normalizeMonth(2025, -13, 15)).toEqual({ year: 2023, month: 11, day: 15 });
324
- });
325
- });
326
-
327
- //#endregion
328
-
329
- //#region Day adjustment
330
-
331
- describe("Day adjustment (target month's last day)", () => {
332
- it("day 31 adjusted to 28 when changing to February (non-leap year)", () => {
333
- expect(normalizeMonth(2025, 2, 31)).toEqual({ year: 2025, month: 2, day: 28 });
334
- });
335
-
336
- it("day 31 adjusted to 29 when changing to February (leap year)", () => {
337
- expect(normalizeMonth(2024, 2, 31)).toEqual({ year: 2024, month: 2, day: 29 });
338
- });
339
-
340
- it("day 31 adjusted to 30 when changing to April", () => {
341
- expect(normalizeMonth(2025, 4, 31)).toEqual({ year: 2025, month: 4, day: 30 });
342
- });
343
-
344
- it("day unchanged if less than target month's day count", () => {
345
- expect(normalizeMonth(2025, 3, 15)).toEqual({ year: 2025, month: 3, day: 15 });
346
- });
347
- });
348
-
349
- //#endregion
350
- });
@@ -1,226 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { DebounceQueue, wait, SdError } from "@simplysm/core-common";
3
-
4
- const time = wait.time;
5
-
6
- describe("DebounceQueue", () => {
7
- //#region Debounce behavior
8
-
9
- describe("Debounce behavior", () => {
10
- it("Executes only last request", async () => {
11
- const queue = new DebounceQueue(50);
12
- const calls: number[] = [];
13
-
14
- queue.run(() => {
15
- calls.push(1);
16
- });
17
- queue.run(() => {
18
- calls.push(2);
19
- });
20
- queue.run(() => {
21
- calls.push(3);
22
- });
23
-
24
- // Wait for debounce
25
- await time(100);
26
-
27
- // Only last request executed
28
- expect(calls).toEqual([3]);
29
- });
30
-
31
- it("Executes after delay", async () => {
32
- const queue = new DebounceQueue(100);
33
- const calls: number[] = [];
34
-
35
- queue.run(() => {
36
- calls.push(1);
37
- });
38
-
39
- // After 50ms not yet executed
40
- await time(50);
41
- expect(calls).toEqual([]);
42
-
43
- // After 100ms executed
44
- await time(100);
45
- expect(calls).toEqual([1]);
46
- });
47
-
48
- it("Executes immediately if no delay", async () => {
49
- const queue = new DebounceQueue();
50
- const calls: number[] = [];
51
-
52
- queue.run(() => {
53
- calls.push(1);
54
- });
55
-
56
- // Small wait (event loop)
57
- await time(10);
58
-
59
- expect(calls).toEqual([1]);
60
- });
61
-
62
- it("If new request arrives during execution, executes after completion", async () => {
63
- const queue = new DebounceQueue(10);
64
- const calls: number[] = [];
65
-
66
- queue.run(async () => {
67
- calls.push(1);
68
- await time(50); // Wait during execution
69
- });
70
-
71
- // Wait for first execution start
72
- await time(20);
73
-
74
- // Add new request during execution
75
- queue.run(() => {
76
- calls.push(2);
77
- });
78
-
79
- // Wait for all work to complete
80
- await time(100);
81
-
82
- expect(calls).toEqual([1, 2]);
83
- });
84
- });
85
-
86
- //#endregion
87
-
88
- //#region Error handling
89
-
90
- describe("Error handling", () => {
91
- it("Emits error event on error", async () => {
92
- const queue = new DebounceQueue(10);
93
- const errors: SdError[] = [];
94
-
95
- queue.on("error", (err) => {
96
- errors.push(err);
97
- });
98
-
99
- queue.run(() => {
100
- throw new Error("test error");
101
- });
102
-
103
- await time(50);
104
-
105
- expect(errors).toHaveLength(1);
106
- expect(errors[0]).toBeInstanceOf(SdError);
107
- expect(errors[0].message).toContain("Error occurred while executing task");
108
- expect(errors[0].message).toContain("test error");
109
- });
110
-
111
- it("Next request executes normally even if error occurred", async () => {
112
- const queue = new DebounceQueue(10);
113
- const calls: number[] = [];
114
- const errors: SdError[] = [];
115
-
116
- // Add error listener to prevent unhandled rejection
117
- queue.on("error", (err) => {
118
- errors.push(err);
119
- });
120
-
121
- queue.run(() => {
122
- throw new Error("error");
123
- });
124
-
125
- await time(50);
126
-
127
- queue.run(() => {
128
- calls.push(1);
129
- });
130
-
131
- await time(50);
132
-
133
- expect(calls).toEqual([1]);
134
- expect(errors).toHaveLength(1);
135
- });
136
-
137
- it("pendingFn executes even if error occurred during execution", async () => {
138
- const queue = new DebounceQueue(10);
139
- const calls: number[] = [];
140
- const errors: SdError[] = [];
141
-
142
- queue.on("error", (err) => {
143
- errors.push(err);
144
- });
145
-
146
- // First request: error occurs
147
- queue.run(() => {
148
- calls.push(1);
149
- throw new Error("error 1");
150
- });
151
-
152
- await time(20);
153
-
154
- // Add new request during execution
155
- queue.run(() => {
156
- calls.push(2);
157
- });
158
-
159
- await time(100);
160
-
161
- expect(calls).toEqual([1, 2]);
162
- expect(errors).toHaveLength(1);
163
- });
164
- });
165
-
166
- //#endregion
167
-
168
- //#region dispose
169
-
170
- describe("dispose()", () => {
171
- it("Clears pending tasks and timers", async () => {
172
- const queue = new DebounceQueue(100);
173
- const calls: number[] = [];
174
-
175
- queue.run(() => {
176
- calls.push(1);
177
- });
178
-
179
- // Dispose during debounce wait
180
- await time(50);
181
- queue.dispose();
182
-
183
- // After debounce time passes, still not executed
184
- await time(100);
185
-
186
- expect(calls).toEqual([]);
187
- });
188
-
189
- it("New tasks ignored after dispose", async () => {
190
- const queue = new DebounceQueue(50);
191
- const calls: number[] = [];
192
-
193
- queue.run(() => {
194
- calls.push(1);
195
- });
196
- queue.dispose();
197
-
198
- // Add new task after dispose - ignored
199
- queue.run(() => {
200
- calls.push(2);
201
- });
202
-
203
- await time(100);
204
-
205
- // Tasks after dispose not executed
206
- expect(calls).toEqual([]);
207
- });
208
-
209
- it("Auto-disposed with using statement", async () => {
210
- const calls: number[] = [];
211
- {
212
- using queue = new DebounceQueue(100);
213
- queue.run(() => {
214
- calls.push(1);
215
- });
216
- await time(50);
217
- } // dispose automatically called at using block end
218
- await time(100);
219
- // Disposed during debounce wait, not executed
220
- expect(calls).toEqual([]);
221
- });
222
- });
223
-
224
- //#endregion
225
-
226
- });