@simplysm/core-common 13.0.0-beta.3 → 13.0.0-beta.30

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 (89) hide show
  1. package/README.md +191 -815
  2. package/dist/common.types.js +4 -4
  3. package/dist/errors/argument-error.js +1 -1
  4. package/dist/errors/not-implemented-error.js +1 -1
  5. package/dist/errors/timeout-error.js +1 -1
  6. package/dist/extensions/arr-ext.helpers.js +4 -4
  7. package/dist/extensions/arr-ext.js +9 -9
  8. package/dist/features/debounce-queue.js +2 -2
  9. package/dist/features/serial-queue.js +3 -3
  10. package/dist/index.js +30 -30
  11. package/dist/types/date-only.js +2 -2
  12. package/dist/types/date-time.js +2 -2
  13. package/dist/types/time.js +2 -2
  14. package/dist/types/uuid.js +1 -1
  15. package/dist/utils/bytes.js +1 -1
  16. package/dist/utils/json.js +8 -8
  17. package/dist/utils/obj.js +5 -5
  18. package/dist/utils/primitive.js +5 -5
  19. package/dist/utils/transferable.js +4 -4
  20. package/dist/utils/wait.js +1 -1
  21. package/docs/extensions.md +381 -0
  22. package/docs/features.md +94 -0
  23. package/docs/types.md +338 -0
  24. package/docs/utils.md +631 -0
  25. package/package.json +8 -4
  26. package/.cache/typecheck-browser.tsbuildinfo +0 -1
  27. package/.cache/typecheck-node.tsbuildinfo +0 -1
  28. package/.cache/typecheck-tests-browser.tsbuildinfo +0 -1
  29. package/.cache/typecheck-tests-node.tsbuildinfo +0 -1
  30. package/src/common.types.ts +0 -91
  31. package/src/env.ts +0 -11
  32. package/src/errors/argument-error.ts +0 -40
  33. package/src/errors/not-implemented-error.ts +0 -32
  34. package/src/errors/sd-error.ts +0 -53
  35. package/src/errors/timeout-error.ts +0 -36
  36. package/src/extensions/arr-ext.helpers.ts +0 -53
  37. package/src/extensions/arr-ext.ts +0 -777
  38. package/src/extensions/arr-ext.types.ts +0 -258
  39. package/src/extensions/map-ext.ts +0 -86
  40. package/src/extensions/set-ext.ts +0 -68
  41. package/src/features/debounce-queue.ts +0 -116
  42. package/src/features/event-emitter.ts +0 -112
  43. package/src/features/serial-queue.ts +0 -94
  44. package/src/globals.ts +0 -12
  45. package/src/index.ts +0 -55
  46. package/src/types/date-only.ts +0 -329
  47. package/src/types/date-time.ts +0 -294
  48. package/src/types/lazy-gc-map.ts +0 -244
  49. package/src/types/time.ts +0 -210
  50. package/src/types/uuid.ts +0 -113
  51. package/src/utils/bytes.ts +0 -160
  52. package/src/utils/date-format.ts +0 -239
  53. package/src/utils/json.ts +0 -230
  54. package/src/utils/num.ts +0 -97
  55. package/src/utils/obj.ts +0 -956
  56. package/src/utils/path.ts +0 -40
  57. package/src/utils/primitive.ts +0 -33
  58. package/src/utils/str.ts +0 -252
  59. package/src/utils/template-strings.ts +0 -132
  60. package/src/utils/transferable.ts +0 -269
  61. package/src/utils/wait.ts +0 -40
  62. package/src/utils/xml.ts +0 -105
  63. package/src/zip/sd-zip.ts +0 -218
  64. package/tests/errors/errors.spec.ts +0 -196
  65. package/tests/extensions/array-extension.spec.ts +0 -790
  66. package/tests/extensions/map-extension.spec.ts +0 -147
  67. package/tests/extensions/set-extension.spec.ts +0 -74
  68. package/tests/types/date-only.spec.ts +0 -636
  69. package/tests/types/date-time.spec.ts +0 -391
  70. package/tests/types/lazy-gc-map.spec.ts +0 -692
  71. package/tests/types/time.spec.ts +0 -559
  72. package/tests/types/types.spec.ts +0 -55
  73. package/tests/types/uuid.spec.ts +0 -91
  74. package/tests/utils/bytes-utils.spec.ts +0 -230
  75. package/tests/utils/date-format.spec.ts +0 -371
  76. package/tests/utils/debounce-queue.spec.ts +0 -272
  77. package/tests/utils/json.spec.ts +0 -475
  78. package/tests/utils/number.spec.ts +0 -184
  79. package/tests/utils/object.spec.ts +0 -827
  80. package/tests/utils/path.spec.ts +0 -78
  81. package/tests/utils/primitive.spec.ts +0 -55
  82. package/tests/utils/sd-event-emitter.spec.ts +0 -216
  83. package/tests/utils/serial-queue.spec.ts +0 -365
  84. package/tests/utils/string.spec.ts +0 -294
  85. package/tests/utils/template-strings.spec.ts +0 -96
  86. package/tests/utils/transferable.spec.ts +0 -698
  87. package/tests/utils/wait.spec.ts +0 -145
  88. package/tests/utils/xml.spec.ts +0 -146
  89. package/tests/zip/sd-zip.spec.ts +0 -234
@@ -0,0 +1,94 @@
1
+ # Features
2
+
3
+ Async operation control and event handling classes. All support `using` statements or `dispose()`.
4
+
5
+ ## DebounceQueue
6
+
7
+ Async debounce queue (executes only last request).
8
+
9
+ ```typescript
10
+ import { DebounceQueue } from "@simplysm/core-common";
11
+
12
+ using queue = new DebounceQueue(300); // 300ms debounce
13
+
14
+ // Error handling
15
+ queue.on("error", (err) => console.error(err));
16
+
17
+ // Only last call is executed
18
+ queue.run(() => console.log("1")); // Ignored
19
+ queue.run(() => console.log("2")); // Ignored
20
+ queue.run(() => console.log("3")); // Executed after 300ms
21
+ ```
22
+
23
+ ---
24
+
25
+ ## SerialQueue
26
+
27
+ Async serial queue (sequential execution).
28
+
29
+ ```typescript
30
+ import { SerialQueue } from "@simplysm/core-common";
31
+
32
+ using queue = new SerialQueue(100); // 100ms interval between tasks
33
+
34
+ queue.on("error", (err) => console.error(err));
35
+
36
+ queue.run(async () => { await fetch("/api/1"); });
37
+ queue.run(async () => { await fetch("/api/2"); }); // Runs after #1 completes
38
+ queue.run(async () => { await fetch("/api/3"); }); // Runs after #2 completes
39
+ ```
40
+
41
+ ---
42
+
43
+ ## EventEmitter
44
+
45
+ EventTarget wrapper with type-safe events.
46
+
47
+ ```typescript
48
+ import { EventEmitter } from "@simplysm/core-common";
49
+
50
+ interface MyEvents {
51
+ data: string;
52
+ error: Error;
53
+ done: void;
54
+ }
55
+
56
+ class MyService extends EventEmitter<MyEvents> {
57
+ process(): void {
58
+ this.emit("data", "result data");
59
+ this.emit("done"); // void type called without arguments
60
+ }
61
+ }
62
+
63
+ const service = new MyService();
64
+ service.on("data", (data) => console.log(data)); // data: string (type inferred)
65
+ service.off("data", listener); // Remove listener
66
+ service.listenerCount("data"); // Number of registered listeners
67
+ service.dispose(); // Remove all listeners
68
+ ```
69
+
70
+ ---
71
+
72
+ ## ZipArchive
73
+
74
+ ZIP file compression/decompression utility. Resources can be auto-cleaned with `await using`.
75
+
76
+ ```typescript
77
+ import { ZipArchive } from "@simplysm/core-common";
78
+
79
+ // Read ZIP file
80
+ await using archive = new ZipArchive(zipBytes);
81
+ const content = await archive.get("file.txt");
82
+ const exists = await archive.exists("data.json");
83
+
84
+ // Extract all (with progress)
85
+ const files = await archive.extractAll((progress) => {
86
+ console.log(`${progress.fileName}: ${progress.extractedSize}/${progress.totalSize}`);
87
+ });
88
+
89
+ // Create ZIP file
90
+ await using newArchive = new ZipArchive();
91
+ newArchive.write("file.txt", textBytes);
92
+ newArchive.write("data.json", jsonBytes);
93
+ const zipBytes = await newArchive.compress();
94
+ ```
package/docs/types.md ADDED
@@ -0,0 +1,338 @@
1
+ # Types
2
+
3
+ ## Errors
4
+
5
+ Custom error classes. All are based on `SdError` and support cause chaining.
6
+
7
+ ### SdError
8
+
9
+ Base error class with cause chain tracking and automatic nested stack integration.
10
+
11
+ ```typescript
12
+ import { SdError } from "@simplysm/core-common";
13
+
14
+ // Track errors with cause chain
15
+ try {
16
+ await fetch(url);
17
+ } catch (err) {
18
+ throw new SdError(err, "API call failed", "Failed to load user");
19
+ // Result message: "Failed to load user => API call failed => original error message"
20
+ }
21
+ ```
22
+
23
+ ### ArgumentError
24
+
25
+ Argument validation error with YAML formatting.
26
+
27
+ ```typescript
28
+ import { ArgumentError } from "@simplysm/core-common";
29
+
30
+ throw new ArgumentError("Invalid user", { userId: 123 });
31
+ // Result message: "Invalid user\n\nuserId: 123"
32
+ ```
33
+
34
+ ### NotImplementedError
35
+
36
+ Indicates unimplemented functionality.
37
+
38
+ ```typescript
39
+ import { NotImplementedError } from "@simplysm/core-common";
40
+
41
+ switch (type) {
42
+ case "A": return handleA();
43
+ case "B": throw new NotImplementedError(`Handling type ${type}`);
44
+ }
45
+ ```
46
+
47
+ ### TimeoutError
48
+
49
+ Timeout error.
50
+
51
+ ```typescript
52
+ import { TimeoutError } from "@simplysm/core-common";
53
+
54
+ throw new TimeoutError(5, "API response wait exceeded");
55
+ // Result message: "Wait time exceeded(5): API response wait exceeded"
56
+ ```
57
+
58
+ ---
59
+
60
+ ## Custom Types
61
+
62
+ Immutable custom type classes. All transformation methods return new instances.
63
+
64
+ ### DateTime
65
+
66
+ Date + time (millisecond precision, local timezone).
67
+
68
+ ```typescript
69
+ import { DateTime } from "@simplysm/core-common";
70
+
71
+ // Creation
72
+ const now = new DateTime(); // Current time
73
+ const dt = new DateTime(2025, 1, 15, 10, 30, 0); // Year, month, day, hour, minute, second
74
+ const fromTick = new DateTime(1705312200000); // Tick (milliseconds)
75
+ const fromDate = new DateTime(new Date()); // Date object
76
+
77
+ // Parsing
78
+ DateTime.parse("2025-01-15 10:30:00"); // yyyy-MM-dd HH:mm:ss
79
+ DateTime.parse("2025-01-15 10:30:00.123"); // yyyy-MM-dd HH:mm:ss.fff
80
+ DateTime.parse("20250115103000"); // yyyyMMddHHmmss
81
+ DateTime.parse("2025-01-15 오전 10:30:00"); // Korean AM/PM
82
+ DateTime.parse("2025-01-15T10:30:00Z"); // ISO 8601
83
+
84
+ // Properties (read-only)
85
+ dt.year; // 2025
86
+ dt.month; // 1 (1-12)
87
+ dt.day; // 15
88
+ dt.hour; // 10
89
+ dt.minute; // 30
90
+ dt.second; // 0
91
+ dt.millisecond; // 0
92
+ dt.tick; // Millisecond timestamp
93
+ dt.dayOfWeek; // Day of week (Sun~Sat: 0~6)
94
+ dt.isValid; // Validity check
95
+
96
+ // Immutable transformations (return new instances)
97
+ dt.setYear(2026); // Change year
98
+ dt.setMonth(3); // Change month (day auto-adjusted)
99
+ dt.addDays(7); // 7 days later
100
+ dt.addHours(-2); // 2 hours ago
101
+ dt.addMonths(1); // 1 month later
102
+
103
+ // Formatting
104
+ dt.toFormatString("yyyy-MM-dd"); // "2025-01-15"
105
+ dt.toFormatString("yyyy년 M월 d일 (ddd)"); // "2025년 1월 15일 (수)"
106
+ dt.toFormatString("tt h:mm:ss"); // "오전 10:30:00"
107
+ dt.toString(); // "2025-01-15T10:30:00.000+09:00"
108
+ ```
109
+
110
+ ### DateOnly
111
+
112
+ Date only (no time).
113
+
114
+ ```typescript
115
+ import { DateOnly } from "@simplysm/core-common";
116
+
117
+ // Creation and parsing
118
+ const today = new DateOnly();
119
+ const d = new DateOnly(2025, 1, 15);
120
+ DateOnly.parse("2025-01-15"); // No timezone influence
121
+ DateOnly.parse("20250115"); // No timezone influence
122
+
123
+ // Immutable transformations
124
+ d.addDays(30);
125
+ d.addMonths(-1);
126
+ d.setMonth(2); // Jan 31 -> Feb 28 (auto-adjusted)
127
+
128
+ // Week calculation (ISO 8601 standard)
129
+ d.getWeekSeqOfYear(); // { year: 2025, weekSeq: 3 }
130
+ d.getWeekSeqOfMonth(); // { year: 2025, monthSeq: 1, weekSeq: 3 }
131
+
132
+ // US-style week (Sunday start, first week with 1+ days)
133
+ d.getWeekSeqOfYear(0, 1);
134
+
135
+ // Reverse calculate date from week
136
+ DateOnly.getDateByYearWeekSeq({ year: 2025, weekSeq: 2 }); // 2025-01-06 (Monday)
137
+
138
+ // Formatting
139
+ d.toFormatString("yyyy년 MM월 dd일"); // "2025년 01월 15일"
140
+ d.toString(); // "2025-01-15"
141
+ ```
142
+
143
+ ### Time
144
+
145
+ Time only (no date, 24-hour cycle).
146
+
147
+ ```typescript
148
+ import { Time } from "@simplysm/core-common";
149
+
150
+ // Creation and parsing
151
+ const now = new Time();
152
+ const t = new Time(14, 30, 0);
153
+ Time.parse("14:30:00"); // HH:mm:ss
154
+ Time.parse("14:30:00.123"); // HH:mm:ss.fff
155
+ Time.parse("오후 2:30:00"); // Korean AM/PM
156
+
157
+ // 24-hour cycle
158
+ t.addHours(12); // 14:30 + 12 hours = 02:30 (cycles, not next day)
159
+ t.addMinutes(-60); // 14:30 - 60 minutes = 13:30
160
+
161
+ // Formatting
162
+ t.toFormatString("tt h:mm"); // "오후 2:30"
163
+ t.toString(); // "14:30:00.000"
164
+ ```
165
+
166
+ ### Uuid
167
+
168
+ UUID v4 (based on `crypto.getRandomValues`).
169
+
170
+ ```typescript
171
+ import { Uuid } from "@simplysm/core-common";
172
+
173
+ // Generate new UUID (cryptographically secure)
174
+ const id = Uuid.new();
175
+
176
+ // Create from string
177
+ const fromStr = new Uuid("550e8400-e29b-41d4-a716-446655440000");
178
+
179
+ // Byte conversion
180
+ const bytes = id.toBytes(); // Uint8Array (16 bytes)
181
+ const fromBytes = Uuid.fromBytes(bytes);
182
+
183
+ id.toString(); // "550e8400-e29b-41d4-a716-446655440000"
184
+ ```
185
+
186
+ ### LazyGcMap
187
+
188
+ Map with auto-expiration (LRU style).
189
+
190
+ ```typescript
191
+ import { LazyGcMap } from "@simplysm/core-common";
192
+
193
+ // using statement (recommended)
194
+ using map = new LazyGcMap<string, object>({
195
+ gcInterval: 10000, // GC execution interval: 10 seconds
196
+ expireTime: 60000, // Item expiration time: 60 seconds
197
+ onExpire: (key, value) => {
198
+ console.log(`Expired: ${key}`);
199
+ },
200
+ });
201
+
202
+ map.set("key1", { data: "hello" });
203
+ map.get("key1"); // Refreshes access time (LRU)
204
+ map.getOrCreate("key2", () => ({})); // Create and return if not exists
205
+ map.has("key1"); // Does not refresh access time
206
+ map.delete("key1");
207
+ ```
208
+
209
+ ---
210
+
211
+ ## Type Utilities
212
+
213
+ TypeScript utility types.
214
+
215
+ ### Bytes
216
+
217
+ Alias for `Uint8Array` (`Buffer` replacement).
218
+
219
+ ```typescript
220
+ import type { Bytes } from "@simplysm/core-common";
221
+
222
+ const data: Bytes = new Uint8Array([1, 2, 3]);
223
+ ```
224
+
225
+ ### PrimitiveTypeStr
226
+
227
+ Primitive type string keys.
228
+
229
+ ```typescript
230
+ type PrimitiveTypeStr = "string" | "number" | "boolean" | "DateTime" | "DateOnly" | "Time" | "Uuid" | "Bytes";
231
+ ```
232
+
233
+ ### PrimitiveTypeMap
234
+
235
+ Mapping from `PrimitiveTypeStr` to actual type.
236
+
237
+ ```typescript
238
+ type PrimitiveTypeMap = {
239
+ string: string;
240
+ number: number;
241
+ boolean: boolean;
242
+ DateTime: DateTime;
243
+ DateOnly: DateOnly;
244
+ Time: Time;
245
+ Uuid: Uuid;
246
+ Bytes: Bytes;
247
+ };
248
+ ```
249
+
250
+ ### PrimitiveType
251
+
252
+ Union of all Primitive types.
253
+
254
+ ```typescript
255
+ type PrimitiveType = string | number | boolean | DateTime | DateOnly | Time | Uuid | Bytes;
256
+ ```
257
+
258
+ ### DeepPartial
259
+
260
+ Recursively convert all properties to optional.
261
+
262
+ ```typescript
263
+ import type { DeepPartial } from "@simplysm/core-common";
264
+
265
+ interface Config {
266
+ db: { host: string; port: number };
267
+ }
268
+ const partial: DeepPartial<Config> = { db: { host: "localhost" } };
269
+ ```
270
+
271
+ ### Type
272
+
273
+ Constructor type (for dependency injection, factory patterns).
274
+
275
+ ```typescript
276
+ import type { Type } from "@simplysm/core-common";
277
+
278
+ function create<T>(ctor: Type<T>): T {
279
+ return new ctor();
280
+ }
281
+ ```
282
+
283
+ ### ObjUndefToOptional
284
+
285
+ Convert properties with `undefined` to optional.
286
+
287
+ ```typescript
288
+ import type { ObjUndefToOptional } from "@simplysm/core-common";
289
+
290
+ type Input = { a: string; b: number | undefined };
291
+ type Output = ObjUndefToOptional<Input>; // { a: string; b?: number }
292
+ ```
293
+
294
+ ### ObjOptionalToUndef
295
+
296
+ Convert optional properties to `required + undefined` union.
297
+
298
+ ```typescript
299
+ import type { ObjOptionalToUndef } from "@simplysm/core-common";
300
+
301
+ type Input = { a: string; b?: number };
302
+ type Output = ObjOptionalToUndef<Input>; // { a: string; b: number | undefined }
303
+ ```
304
+
305
+ ### ArrayDiffsResult
306
+
307
+ Result of `Array.diffs()` — insert / delete / update entries.
308
+
309
+ ```typescript
310
+ import type { ArrayDiffsResult } from "@simplysm/core-common";
311
+
312
+ const diffs: ArrayDiffsResult<User, User>[] = oldUsers.diffs(newUsers, { keys: ["id"] });
313
+ for (const diff of diffs) {
314
+ if (diff.source === undefined) { /* INSERT */ }
315
+ else if (diff.target === undefined) { /* DELETE */ }
316
+ else { /* UPDATE */ }
317
+ }
318
+ ```
319
+
320
+ ### ArrayDiffs2Result
321
+
322
+ Result of `Array.oneWayDiffs()` — create / update / same entries.
323
+
324
+ ```typescript
325
+ import type { ArrayDiffs2Result } from "@simplysm/core-common";
326
+ ```
327
+
328
+ ### TreeArray
329
+
330
+ Result of `Array.toTree()` — `T & { children: TreeArray<T>[] }`.
331
+
332
+ ```typescript
333
+ import type { TreeArray } from "@simplysm/core-common";
334
+
335
+ interface Category { id: number; parentId: number | undefined; name: string }
336
+ const tree: TreeArray<Category>[] = categories.toTree("id", "parentId");
337
+ // Each node has a `children` array of the same type
338
+ ```