@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
@@ -0,0 +1,430 @@
1
+ # Array / Set / Map Extensions
2
+
3
+ Prototype extensions added to `Array`, `Set`, and `Map` at import time. Importing `@simplysm/core-common` automatically installs these extensions.
4
+
5
+ ## Array -- Readonly Extensions
6
+
7
+ These methods return new arrays/values without mutating the original.
8
+
9
+ ### `single(predicate?)`
10
+
11
+ Returns the single matching element, or `undefined` if none. Throws `ArgumentError` if more than one element matches.
12
+
13
+ ```typescript
14
+ single(predicate?: (item: T, index: number) => boolean): T | undefined;
15
+ ```
16
+
17
+ ### `first(predicate?)`
18
+
19
+ Returns the first matching element, or `undefined` if none.
20
+
21
+ ```typescript
22
+ first(predicate?: (item: T, index: number) => boolean): T | undefined;
23
+ ```
24
+
25
+ ### `last(predicate?)`
26
+
27
+ Returns the last matching element, or `undefined` if none.
28
+
29
+ ```typescript
30
+ last(predicate?: (item: T, index: number) => boolean): T | undefined;
31
+ ```
32
+
33
+ ### `filterAsync(predicate)`
34
+
35
+ Async sequential filter.
36
+
37
+ ```typescript
38
+ filterAsync(predicate: (item: T, index: number) => Promise<boolean>): Promise<T[]>;
39
+ ```
40
+
41
+ ### `filterExists()`
42
+
43
+ Removes `null` and `undefined` elements. Returns `NonNullable<T>[]`.
44
+
45
+ ```typescript
46
+ filterExists(): NonNullable<T>[];
47
+ ```
48
+
49
+ ### `ofType(type)`
50
+
51
+ Filters elements by type. Accepts a `PrimitiveTypeStr` (`"string"`, `"number"`, `"boolean"`, `"DateTime"`, `"DateOnly"`, `"Time"`, `"Uuid"`, `"Bytes"`) or a constructor function.
52
+
53
+ ```typescript
54
+ ofType<K extends PrimitiveTypeStr>(type: K): Extract<T, PrimitiveTypeMap[K]>[];
55
+ ofType<N extends T>(type: Type<N>): N[];
56
+ ```
57
+
58
+ ### `mapAsync(selector)`
59
+
60
+ Async sequential map.
61
+
62
+ ```typescript
63
+ mapAsync<R>(selector: (item: T, index: number) => Promise<R>): Promise<R[]>;
64
+ ```
65
+
66
+ ### `mapMany(selector?)`
67
+
68
+ Maps then flattens one level. Removes `null`/`undefined` from results.
69
+
70
+ ```typescript
71
+ mapMany(): T extends readonly (infer U)[] ? U[] : T;
72
+ mapMany<R>(selector: (item: T, index: number) => R[]): R[];
73
+ ```
74
+
75
+ ### `mapManyAsync(selector?)`
76
+
77
+ Async version of `mapMany`.
78
+
79
+ ```typescript
80
+ mapManyAsync<R>(selector: (item: T, index: number) => Promise<R[]>): Promise<R[]>;
81
+ ```
82
+
83
+ ### `parallelAsync(fn)`
84
+
85
+ Runs `fn` for all items in parallel via `Promise.all`. If any rejects, the entire result rejects.
86
+
87
+ ```typescript
88
+ parallelAsync<R>(fn: (item: T, index: number) => Promise<R>): Promise<R[]>;
89
+ ```
90
+
91
+ ### `groupBy(keySelector, valueSelector?)`
92
+
93
+ Groups items by key. Supports both primitive keys (O(n) via Map) and object keys (O(n^2) via deep equality).
94
+
95
+ ```typescript
96
+ groupBy<K>(keySelector: (item: T, index: number) => K): { key: K; values: T[] }[];
97
+ groupBy<K, V>(
98
+ keySelector: (item: T, index: number) => K,
99
+ valueSelector: (item: T, index: number) => V,
100
+ ): { key: K; values: V[] }[];
101
+ ```
102
+
103
+ ### `toMap(keySelector, valueSelector?)`
104
+
105
+ Converts array to `Map`. Throws `ArgumentError` on duplicate keys.
106
+
107
+ ```typescript
108
+ toMap<K>(keySelector: (item: T, index: number) => K): Map<K, T>;
109
+ toMap<K, V>(
110
+ keySelector: (item: T, index: number) => K,
111
+ valueSelector: (item: T, index: number) => V,
112
+ ): Map<K, V>;
113
+ ```
114
+
115
+ ### `toMapAsync(keySelector, valueSelector?)`
116
+
117
+ Async version of `toMap`.
118
+
119
+ ```typescript
120
+ toMapAsync<K>(keySelector: (item: T, index: number) => Promise<K>): Promise<Map<K, T>>;
121
+ toMapAsync<K, V>(
122
+ keySelector: (item: T, index: number) => Promise<K> | K,
123
+ valueSelector: (item: T, index: number) => Promise<V> | V,
124
+ ): Promise<Map<K, V>>;
125
+ ```
126
+
127
+ ### `toArrayMap(keySelector, valueSelector?)`
128
+
129
+ Converts array to `Map<K, V[]>` (groups values into arrays per key).
130
+
131
+ ```typescript
132
+ toArrayMap<K>(keySelector: (item: T, index: number) => K): Map<K, T[]>;
133
+ toArrayMap<K, V>(
134
+ keySelector: (item: T, index: number) => K,
135
+ valueSelector: (item: T, index: number) => V,
136
+ ): Map<K, V[]>;
137
+ ```
138
+
139
+ ### `toSetMap(keySelector, valueSelector?)`
140
+
141
+ Converts array to `Map<K, Set<V>>`.
142
+
143
+ ```typescript
144
+ toSetMap<K>(keySelector: (item: T, index: number) => K): Map<K, Set<T>>;
145
+ toSetMap<K, V>(
146
+ keySelector: (item: T, index: number) => K,
147
+ valueSelector: (item: T, index: number) => V,
148
+ ): Map<K, Set<V>>;
149
+ ```
150
+
151
+ ### `toMapValues(keySelector, valueSelector)`
152
+
153
+ Groups by key, then applies `valueSelector` to the group array to produce the final value.
154
+
155
+ ```typescript
156
+ toMapValues<K, V>(
157
+ keySelector: (item: T, index: number) => K,
158
+ valueSelector: (items: T[]) => V,
159
+ ): Map<K, V>;
160
+ ```
161
+
162
+ ### `toObject(keySelector, valueSelector?)`
163
+
164
+ Converts array to a plain object. Throws `ArgumentError` on duplicate keys.
165
+
166
+ ```typescript
167
+ toObject(keySelector: (item: T, index: number) => string): Record<string, T>;
168
+ toObject<V>(
169
+ keySelector: (item: T, index: number) => string,
170
+ valueSelector: (item: T, index: number) => V,
171
+ ): Record<string, V>;
172
+ ```
173
+
174
+ ### `toTree(keyProp, parentKey)`
175
+
176
+ Converts a flat array to a tree structure. Items where `parentKey` is `null`/`undefined` become roots. O(n) complexity.
177
+
178
+ ```typescript
179
+ toTree<K extends keyof T, P extends keyof T>(keyProp: K, parentKey: P): TreeArray<T>[];
180
+ ```
181
+
182
+ ```typescript
183
+ const items = [
184
+ { id: 1, parentId: undefined, name: "root" },
185
+ { id: 2, parentId: 1, name: "child" },
186
+ ];
187
+ const tree = items.toTree("id", "parentId");
188
+ // [{ id: 1, name: "root", children: [{ id: 2, name: "child", children: [] }] }]
189
+ ```
190
+
191
+ ### `distinct(options?)`
192
+
193
+ Returns a new array with duplicates removed.
194
+
195
+ ```typescript
196
+ distinct(options?: boolean | {
197
+ matchAddress?: boolean;
198
+ keyFn?: (item: T) => string | number;
199
+ }): T[];
200
+ ```
201
+
202
+ | Option | Description |
203
+ |--------|-------------|
204
+ | `true` or `{ matchAddress: true }` | Use reference equality (Set-based, O(n)) |
205
+ | `{ keyFn }` | Use custom key function (O(n)) |
206
+ | No options | Deep equality comparison (O(n^2) for objects) |
207
+
208
+ ### `orderBy(selector?)` / `orderByDesc(selector?)`
209
+
210
+ Returns a sorted copy. Supports `string`, `number`, `DateTime`, `DateOnly`, `Time`.
211
+
212
+ ```typescript
213
+ orderBy(selector?: (item: T) => string | number | DateTime | DateOnly | Time | undefined): T[];
214
+ orderByDesc(selector?: (item: T) => string | number | DateTime | DateOnly | Time | undefined): T[];
215
+ ```
216
+
217
+ ### `diffs(target, options?)`
218
+
219
+ Compares two arrays and returns INSERT/DELETE/UPDATE diff results.
220
+
221
+ ```typescript
222
+ diffs<P>(target: P[], options?: {
223
+ keys?: string[];
224
+ excludes?: string[];
225
+ }): ArrayDiffsResult<T, P>[];
226
+ ```
227
+
228
+ Result items:
229
+ - `{ source: T, target: undefined }` -- item exists only in source (DELETE)
230
+ - `{ source: undefined, target: P }` -- item exists only in target (INSERT)
231
+ - `{ source: T, target: P }` -- item exists in both but differs (UPDATE)
232
+
233
+ ### `oneWayDiffs(orgItems, keyPropNameOrGetValFn, options?)`
234
+
235
+ One-way diff: compares current array against original items.
236
+
237
+ ```typescript
238
+ oneWayDiffs<K extends keyof T>(
239
+ orgItems: T[] | Map<T[K], T>,
240
+ keyPropNameOrGetValFn: K | ((item: T) => string | number | undefined),
241
+ options?: { includeSame?: boolean; excludes?: string[]; includes?: string[] },
242
+ ): ArrayOneWayDiffResult<T>[];
243
+ ```
244
+
245
+ Result types: `"create"`, `"update"`, `"same"` (only if `includeSame: true`).
246
+
247
+ ### `merge(target, options?)`
248
+
249
+ Merges two arrays using deep merge on matched items and appends unmatched target items.
250
+
251
+ ```typescript
252
+ merge<P>(target: P[], options?: {
253
+ keys?: string[];
254
+ excludes?: string[];
255
+ }): (T | P | (T & P))[];
256
+ ```
257
+
258
+ ### `sum(selector?)`
259
+
260
+ Returns the sum of elements. Returns `0` for empty arrays.
261
+
262
+ ```typescript
263
+ sum(selector?: (item: T, index: number) => number): number;
264
+ ```
265
+
266
+ ### `min(selector?)` / `max(selector?)`
267
+
268
+ Returns the minimum/maximum element. Returns `undefined` for empty arrays.
269
+
270
+ ```typescript
271
+ min(selector?: (item: T, index: number) => string | number): string | number | undefined;
272
+ max(selector?: (item: T, index: number) => string | number): string | number | undefined;
273
+ ```
274
+
275
+ ### `shuffle()`
276
+
277
+ Returns a new array with elements in random order (Fisher-Yates algorithm).
278
+
279
+ ```typescript
280
+ shuffle(): T[];
281
+ ```
282
+
283
+ ## Array -- Mutable Extensions
284
+
285
+ These methods mutate the original array in place.
286
+
287
+ ### `distinctThis(options?)`
288
+
289
+ Removes duplicates from the original array in place. Same options as `distinct()`.
290
+
291
+ ```typescript
292
+ distinctThis(options?: boolean | {
293
+ matchAddress?: boolean;
294
+ keyFn?: (item: T) => string | number;
295
+ }): T[];
296
+ ```
297
+
298
+ ### `orderByThis(selector?)` / `orderByDescThis(selector?)`
299
+
300
+ Sorts the original array in place.
301
+
302
+ ```typescript
303
+ orderByThis(selector?: (item: T) => string | number | DateTime | DateOnly | Time | undefined): T[];
304
+ orderByDescThis(selector?: (item: T) => string | number | DateTime | DateOnly | Time | undefined): T[];
305
+ ```
306
+
307
+ ### `insert(index, ...items)`
308
+
309
+ Inserts items at the given index in place.
310
+
311
+ ```typescript
312
+ insert(index: number, ...items: T[]): this;
313
+ ```
314
+
315
+ ### `remove(itemOrSelector)`
316
+
317
+ Removes matching items in place.
318
+
319
+ ```typescript
320
+ remove(item: T): this;
321
+ remove(selector: (item: T, index: number) => boolean): this;
322
+ ```
323
+
324
+ ### `toggle(item)`
325
+
326
+ Toggles an item: removes if present, adds if absent.
327
+
328
+ ```typescript
329
+ toggle(item: T): this;
330
+ ```
331
+
332
+ ### `clear()`
333
+
334
+ Removes all items from the array.
335
+
336
+ ```typescript
337
+ clear(): this;
338
+ ```
339
+
340
+ ## Set Extensions
341
+
342
+ ### `adds(...values)`
343
+
344
+ Adds multiple values at once. Returns `this` for chaining.
345
+
346
+ ```typescript
347
+ adds(...values: T[]): this;
348
+ ```
349
+
350
+ ### `toggle(value, addOrDel?)`
351
+
352
+ Toggles a value in the Set. Optionally force add or delete.
353
+
354
+ ```typescript
355
+ toggle(value: T, addOrDel?: "add" | "del"): this;
356
+ ```
357
+
358
+ | Parameter | Type | Description |
359
+ |-----------|------|-------------|
360
+ | `value` | `T` | Value to toggle |
361
+ | `addOrDel` | `"add" \| "del" \| undefined` | Force add or delete. Omit for auto-toggle |
362
+
363
+ ```typescript
364
+ const set = new Set([1, 2, 3]);
365
+ set.toggle(2); // removes 2 -> {1, 3}
366
+ set.toggle(4); // adds 4 -> {1, 3, 4}
367
+ set.toggle(5, "add"); // force add -> {1, 3, 4, 5}
368
+ set.toggle(5, "del"); // force del -> {1, 3, 4}
369
+ ```
370
+
371
+ ## Map Extensions
372
+
373
+ ### `getOrCreate(key, newValue)`
374
+
375
+ Returns the value for `key`. If the key does not exist, creates it with `newValue` (or calls `newValue` as a factory function if it is a function).
376
+
377
+ ```typescript
378
+ getOrCreate(key: K, newValue: V): V;
379
+ getOrCreate(key: K, newValueFn: () => V): V;
380
+ ```
381
+
382
+ **Note:** If `V` is a function type, wrap it in a factory to avoid it being called:
383
+ ```typescript
384
+ fnMap.getOrCreate("key", () => myFunction);
385
+ ```
386
+
387
+ ### `update(key, updateFn)`
388
+
389
+ Updates a key's value using a function. If the key does not exist, `updateFn` receives `undefined`.
390
+
391
+ ```typescript
392
+ update(key: K, updateFn: (v: V | undefined) => V): void;
393
+ ```
394
+
395
+ ```typescript
396
+ const counts = new Map<string, number>();
397
+ counts.update("hits", (v) => (v ?? 0) + 1);
398
+ ```
399
+
400
+ ## Exported Types
401
+
402
+ ### `ArrayDiffsResult<TOriginal, TOther>`
403
+
404
+ ```typescript
405
+ type ArrayDiffsResult<TOriginal, TOther> =
406
+ | { source: undefined; target: TOther } // INSERT
407
+ | { source: TOriginal; target: undefined } // DELETE
408
+ | { source: TOriginal; target: TOther }; // UPDATE
409
+ ```
410
+
411
+ ### `ArrayOneWayDiffResult<TItem>`
412
+
413
+ ```typescript
414
+ type ArrayOneWayDiffResult<TItem> =
415
+ | { type: "create"; item: TItem; orgItem: undefined }
416
+ | { type: "update"; item: TItem; orgItem: TItem }
417
+ | { type: "same"; item: TItem; orgItem: TItem };
418
+ ```
419
+
420
+ ### `TreeArray<TNode>`
421
+
422
+ ```typescript
423
+ type TreeArray<TNode> = TNode & { children: TreeArray<TNode>[] };
424
+ ```
425
+
426
+ ### `ComparableType`
427
+
428
+ ```typescript
429
+ type ComparableType = string | number | boolean | DateTime | DateOnly | Time | undefined;
430
+ ```
package/docs/env.md ADDED
@@ -0,0 +1,52 @@
1
+ # Environment
2
+
3
+ Unified access to environment variables from both `import.meta.env` (Vite/browser) and `process.env` (Node.js). `process.env` takes precedence when both are available.
4
+
5
+ ## `parseBoolEnv`
6
+
7
+ Parses an unknown value to a boolean. Returns `true` for `"true"`, `"1"`, `"yes"`, `"on"` (case-insensitive), `false` for everything else.
8
+
9
+ ```typescript
10
+ function parseBoolEnv(value: unknown): boolean;
11
+ ```
12
+
13
+ | Parameter | Type | Description |
14
+ |-----------|------|-------------|
15
+ | `value` | `unknown` | The value to parse |
16
+
17
+ **Returns:** `boolean`
18
+
19
+ ```typescript
20
+ parseBoolEnv("true"); // true
21
+ parseBoolEnv("1"); // true
22
+ parseBoolEnv("yes"); // true
23
+ parseBoolEnv("on"); // true
24
+ parseBoolEnv("false"); // false
25
+ parseBoolEnv(undefined); // false
26
+ ```
27
+
28
+ ## `env`
29
+
30
+ A pre-built environment object that merges `import.meta.env` and `process.env`.
31
+
32
+ ```typescript
33
+ const env: {
34
+ DEV: boolean;
35
+ VER?: string;
36
+ [key: string]: unknown;
37
+ };
38
+ ```
39
+
40
+ | Property | Type | Description |
41
+ |----------|------|-------------|
42
+ | `DEV` | `boolean` | Whether in development mode (parsed via `parseBoolEnv` from `DEV` env var) |
43
+ | `VER` | `string \| undefined` | Version string from `VER` env var |
44
+ | `[key]` | `unknown` | Any other environment variable |
45
+
46
+ ```typescript
47
+ import { env } from "@simplysm/core-common";
48
+
49
+ if (env.DEV) {
50
+ // development-only logic
51
+ }
52
+ ```
package/docs/errors.md CHANGED
@@ -1,119 +1,104 @@
1
1
  # Errors
2
2
 
3
- Error classes for the Simplysm framework. All classes extend `SdError`, which itself extends `Error`.
4
-
5
- Source: `src/errors/*.ts`
6
-
7
- ---
3
+ A hierarchy of error classes built on `SdError`, which supports tree-structured cause chaining via the ES2024 `cause` property.
8
4
 
9
5
  ## `SdError`
10
6
 
11
- Error class supporting tree-structured cause chaining. Utilizes ES2024 `cause` property. Messages are joined in reverse order with ` => ` separator, and cause stack traces are appended.
7
+ Base error class with cause-chain support. Messages are joined in reverse order with ` => `.
12
8
 
13
9
  ```typescript
14
- export class SdError extends Error {
15
- override cause?: Error;
10
+ class SdError extends Error {
11
+ cause?: Error;
16
12
 
17
- /** Create by wrapping a cause error. Messages are joined in reverse order (upper message => lower message => cause message) */
18
13
  constructor(cause: Error, ...messages: string[]);
19
- /** Create with messages only. Messages are joined in reverse order (upper message => lower message) */
20
14
  constructor(...messages: string[]);
21
15
  }
22
16
  ```
23
17
 
24
- **Example:**
18
+ | Constructor Overload | Description |
19
+ |---------------------|-------------|
20
+ | `new SdError(cause, ...messages)` | Wraps an existing error. Message becomes `"messages[n] => ... => messages[0] => cause.message"` |
21
+ | `new SdError(...messages)` | Creates without cause. Message becomes `"messages[n] => ... => messages[0]"` |
22
+
23
+ When a cause error is provided, its stack trace is appended under a `---- cause stack ----` separator.
25
24
 
26
25
  ```typescript
27
26
  try {
28
27
  await fetch(url);
29
28
  } catch (err) {
30
29
  throw new SdError(err, "API call failed", "User load failed");
30
+ // message: "User load failed => API call failed => <original message>"
31
31
  }
32
- // Result message: "User load failed => API call failed => original error message"
33
32
 
34
- throw new SdError("invalid state", "processing not possible");
35
- // Result message: "processing not possible => invalid state"
33
+ throw new SdError("Invalid state", "Cannot process");
34
+ // message: "Cannot process => Invalid state"
36
35
  ```
37
36
 
38
- ---
39
-
40
37
  ## `ArgumentError`
41
38
 
42
- An error thrown when invalid arguments are received. Includes the argument object in YAML format in the message to facilitate debugging. Extends `SdError`.
39
+ Error for invalid arguments. Extends `SdError`. Formats the argument object as YAML in the message for easy debugging.
43
40
 
44
41
  ```typescript
45
- export class ArgumentError extends SdError {
46
- /** Output argument object in YAML format with default message ("Invalid arguments.") */
42
+ class ArgumentError extends SdError {
47
43
  constructor(argObj: Record<string, unknown>);
48
- /** Output argument object in YAML format with a custom message */
49
44
  constructor(message: string, argObj: Record<string, unknown>);
50
45
  }
51
46
  ```
52
47
 
53
- **Example:**
48
+ | Constructor Overload | Description |
49
+ |---------------------|-------------|
50
+ | `new ArgumentError(argObj)` | Default message + YAML-formatted args |
51
+ | `new ArgumentError(message, argObj)` | Custom message + YAML-formatted args |
54
52
 
55
53
  ```typescript
56
54
  throw new ArgumentError({ userId: 123, name: null });
57
- // Result message: "Invalid arguments.\n\nuserId: 123\nname: null"
55
+ // message: "잘못된 인자입니다.\n\nuserId: 123\nname: null"
58
56
 
59
57
  throw new ArgumentError("Invalid user", { userId: 123 });
60
- // Result message: "Invalid user\n\nuserId: 123"
58
+ // message: "Invalid user\n\nuserId: 123"
61
59
  ```
62
60
 
63
- ---
64
-
65
61
  ## `NotImplementedError`
66
62
 
67
- An error thrown when a feature that has not yet been implemented is called. Extends `SdError`.
63
+ Error for unimplemented features. Extends `SdError`.
68
64
 
69
65
  ```typescript
70
- export class NotImplementedError extends SdError {
71
- /**
72
- * @param message Additional description message
73
- */
66
+ class NotImplementedError extends SdError {
74
67
  constructor(message?: string);
75
68
  }
76
69
  ```
77
70
 
78
- **Example:**
71
+ | Parameter | Type | Description |
72
+ |-----------|------|-------------|
73
+ | `message` | `string \| undefined` | Optional description of what is not implemented |
79
74
 
80
75
  ```typescript
81
- class BaseService {
82
- process(): void {
83
- throw new NotImplementedError("Implementation required in subclass");
84
- }
85
- }
76
+ throw new NotImplementedError();
77
+ // message: "미구현"
86
78
 
87
- switch (type) {
88
- case "A": return handleA();
89
- case "B": throw new NotImplementedError(`Handling for type ${type}`);
90
- }
79
+ throw new NotImplementedError("Subclass must override");
80
+ // message: "미구현: Subclass must override"
91
81
  ```
92
82
 
93
- ---
94
-
95
83
  ## `TimeoutError`
96
84
 
97
- An error that occurs when the waiting time is exceeded. Automatically thrown when the maximum number of attempts is exceeded in `wait.until()`. Extends `SdError`.
85
+ Error for timeout conditions. Extends `SdError`.
98
86
 
99
87
  ```typescript
100
- export class TimeoutError extends SdError {
101
- /**
102
- * @param count Number of attempts
103
- * @param message Additional message
104
- */
88
+ class TimeoutError extends SdError {
105
89
  constructor(count?: number, message?: string);
106
90
  }
107
91
  ```
108
92
 
109
- **Example:**
93
+ | Parameter | Type | Description |
94
+ |-----------|------|-------------|
95
+ | `count` | `number \| undefined` | Number of attempts made |
96
+ | `message` | `string \| undefined` | Additional description |
110
97
 
111
98
  ```typescript
112
- try {
113
- await wait.until(() => isReady, 100, 50);
114
- } catch (err) {
115
- if (err instanceof TimeoutError) {
116
- // "Waiting time exceeded(50 attempts)"
117
- }
118
- }
99
+ throw new TimeoutError(50);
100
+ // message: "대기 시간 초과(50회 시도)"
101
+
102
+ throw new TimeoutError(undefined, "API response wait exceeded");
103
+ // message: "대기 시간 초과: API response wait exceeded"
119
104
  ```