@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.
- package/README.md +86 -92
- package/dist/common.types.d.ts +14 -14
- package/dist/common.types.js +2 -1
- package/dist/common.types.js.map +1 -6
- package/dist/env.d.ts +8 -1
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +13 -9
- package/dist/env.js.map +1 -6
- package/dist/errors/argument-error.d.ts +10 -10
- package/dist/errors/argument-error.d.ts.map +1 -1
- package/dist/errors/argument-error.js +31 -14
- package/dist/errors/argument-error.js.map +1 -6
- package/dist/errors/not-implemented-error.d.ts +8 -8
- package/dist/errors/not-implemented-error.js +30 -12
- package/dist/errors/not-implemented-error.js.map +1 -6
- package/dist/errors/sd-error.d.ts +10 -10
- package/dist/errors/sd-error.d.ts.map +1 -1
- package/dist/errors/sd-error.js +45 -24
- package/dist/errors/sd-error.js.map +1 -6
- package/dist/errors/timeout-error.d.ts +10 -10
- package/dist/errors/timeout-error.js +34 -15
- package/dist/errors/timeout-error.js.map +1 -6
- package/dist/extensions/arr-ext.d.ts +2 -2
- package/dist/extensions/arr-ext.helpers.d.ts +10 -10
- package/dist/extensions/arr-ext.helpers.js +112 -89
- package/dist/extensions/arr-ext.helpers.js.map +1 -6
- package/dist/extensions/arr-ext.js +458 -422
- package/dist/extensions/arr-ext.js.map +1 -6
- package/dist/extensions/arr-ext.types.d.ts +57 -57
- package/dist/extensions/arr-ext.types.d.ts.map +1 -1
- package/dist/extensions/arr-ext.types.js +6 -1
- package/dist/extensions/arr-ext.types.js.map +1 -6
- package/dist/extensions/map-ext.d.ts +16 -16
- package/dist/extensions/map-ext.js +27 -22
- package/dist/extensions/map-ext.js.map +1 -6
- package/dist/extensions/set-ext.d.ts +11 -11
- package/dist/extensions/set-ext.js +32 -25
- package/dist/extensions/set-ext.js.map +1 -6
- package/dist/features/debounce-queue.d.ts +17 -17
- package/dist/features/debounce-queue.js +98 -70
- package/dist/features/debounce-queue.js.map +1 -6
- package/dist/features/event-emitter.d.ts +20 -20
- package/dist/features/event-emitter.js +101 -78
- package/dist/features/event-emitter.js.map +1 -6
- package/dist/features/serial-queue.d.ts +11 -11
- package/dist/features/serial-queue.js +78 -57
- package/dist/features/serial-queue.js.map +1 -6
- package/dist/globals.d.ts +4 -4
- package/dist/globals.js +9 -1
- package/dist/globals.js.map +1 -6
- package/dist/index.js +28 -27
- package/dist/index.js.map +1 -6
- package/dist/types/date-only.d.ts +64 -64
- package/dist/types/date-only.d.ts.map +1 -1
- package/dist/types/date-only.js +263 -252
- package/dist/types/date-only.js.map +1 -6
- package/dist/types/date-time.d.ts +36 -36
- package/dist/types/date-time.d.ts.map +1 -1
- package/dist/types/date-time.js +196 -288
- package/dist/types/date-time.js.map +1 -6
- package/dist/types/lazy-gc-map.d.ts +26 -26
- package/dist/types/lazy-gc-map.d.ts.map +1 -1
- package/dist/types/lazy-gc-map.js +202 -159
- package/dist/types/lazy-gc-map.js.map +1 -6
- package/dist/types/time.d.ts +23 -23
- package/dist/types/time.d.ts.map +1 -1
- package/dist/types/time.js +169 -158
- package/dist/types/time.js.map +1 -6
- package/dist/types/uuid.d.ts +11 -11
- package/dist/types/uuid.d.ts.map +1 -1
- package/dist/types/uuid.js +95 -70
- package/dist/types/uuid.js.map +1 -6
- package/dist/utils/bytes.d.ts +17 -17
- package/dist/utils/bytes.js +137 -81
- package/dist/utils/bytes.js.map +1 -6
- package/dist/utils/date-format.d.ts +40 -40
- package/dist/utils/date-format.js +187 -101
- package/dist/utils/date-format.js.map +1 -6
- package/dist/utils/error.d.ts +4 -4
- package/dist/utils/error.js +11 -6
- package/dist/utils/error.js.map +1 -6
- package/dist/utils/json.d.ts +19 -19
- package/dist/utils/json.js +187 -135
- package/dist/utils/json.js.map +1 -6
- package/dist/utils/num.d.ts +20 -20
- package/dist/utils/num.js +76 -34
- package/dist/utils/num.js.map +1 -6
- package/dist/utils/obj.d.ts +111 -111
- package/dist/utils/obj.d.ts.map +1 -1
- package/dist/utils/obj.js +706 -496
- package/dist/utils/obj.js.map +1 -6
- package/dist/utils/path.d.ts +10 -10
- package/dist/utils/path.js +35 -18
- package/dist/utils/path.js.map +1 -6
- package/dist/utils/primitive.d.ts +5 -5
- package/dist/utils/primitive.js +34 -14
- package/dist/utils/primitive.js.map +1 -6
- package/dist/utils/str.d.ts +38 -38
- package/dist/utils/str.js +217 -113
- package/dist/utils/str.js.map +1 -6
- package/dist/utils/template-strings.d.ts +26 -26
- package/dist/utils/template-strings.js +113 -40
- package/dist/utils/template-strings.js.map +1 -6
- package/dist/utils/transferable.d.ts +18 -18
- package/dist/utils/transferable.js +218 -151
- package/dist/utils/transferable.js.map +1 -6
- package/dist/utils/wait.d.ts +9 -9
- package/dist/utils/wait.js +30 -15
- package/dist/utils/wait.js.map +1 -6
- package/dist/utils/xml.d.ts +13 -13
- package/dist/utils/xml.js +84 -46
- package/dist/utils/xml.js.map +1 -6
- package/dist/utils/zip.d.ts +22 -22
- package/dist/utils/zip.js +172 -148
- package/dist/utils/zip.js.map +1 -6
- package/docs/array-extensions.md +430 -0
- package/docs/env.md +52 -0
- package/docs/errors.md +41 -56
- package/docs/features.md +82 -97
- package/docs/type-utilities.md +91 -0
- package/docs/types.md +221 -201
- package/docs/utils.md +319 -435
- package/package.json +7 -5
- package/src/common.types.ts +14 -14
- package/src/env.ts +12 -3
- package/src/errors/argument-error.ts +15 -15
- package/src/errors/not-implemented-error.ts +9 -9
- package/src/errors/sd-error.ts +12 -12
- package/src/errors/timeout-error.ts +12 -12
- package/src/extensions/arr-ext.helpers.ts +16 -16
- package/src/extensions/arr-ext.ts +35 -35
- package/src/extensions/arr-ext.types.ts +57 -57
- package/src/extensions/map-ext.ts +16 -16
- package/src/extensions/set-ext.ts +11 -11
- package/src/features/debounce-queue.ts +23 -23
- package/src/features/event-emitter.ts +25 -25
- package/src/features/serial-queue.ts +13 -13
- package/src/globals.ts +4 -4
- package/src/index.ts +5 -5
- package/src/types/date-only.ts +84 -83
- package/src/types/date-time.ts +43 -42
- package/src/types/lazy-gc-map.ts +44 -44
- package/src/types/time.ts +29 -29
- package/src/types/uuid.ts +15 -15
- package/src/utils/bytes.ts +35 -35
- package/src/utils/date-format.ts +59 -59
- package/src/utils/error.ts +4 -4
- package/src/utils/json.ts +41 -41
- package/src/utils/num.ts +20 -20
- package/src/utils/obj.ts +138 -138
- package/src/utils/path.ts +10 -10
- package/src/utils/primitive.ts +6 -6
- package/src/utils/str.ts +48 -48
- package/src/utils/template-strings.ts +29 -29
- package/src/utils/transferable.ts +38 -38
- package/src/utils/wait.ts +10 -10
- package/src/utils/xml.ts +19 -19
- package/src/utils/zip.ts +25 -25
- package/docs/extensions.md +0 -387
- package/tests/errors/errors.spec.ts +0 -80
- package/tests/extensions/array-extension.spec.ts +0 -654
- package/tests/extensions/map-extension.spec.ts +0 -117
- package/tests/extensions/set-extension.spec.ts +0 -67
- package/tests/types/date-only.spec.ts +0 -533
- package/tests/types/date-time.spec.ts +0 -246
- package/tests/types/lazy-gc-map.spec.ts +0 -606
- package/tests/types/time.spec.ts +0 -428
- package/tests/types/uuid.spec.ts +0 -74
- package/tests/utils/bytes-utils.spec.ts +0 -197
- package/tests/utils/date-format.spec.ts +0 -350
- package/tests/utils/debounce-queue.spec.ts +0 -226
- package/tests/utils/json.spec.ts +0 -400
- package/tests/utils/number.spec.ts +0 -136
- package/tests/utils/object.spec.ts +0 -810
- package/tests/utils/path.spec.ts +0 -70
- package/tests/utils/primitive.spec.ts +0 -43
- package/tests/utils/sd-event-emitter.spec.ts +0 -189
- package/tests/utils/serial-queue.spec.ts +0 -305
- package/tests/utils/string.spec.ts +0 -265
- package/tests/utils/template-strings.spec.ts +0 -48
- package/tests/utils/transferable.spec.ts +0 -639
- package/tests/utils/wait.spec.ts +0 -123
- package/tests/utils/xml.spec.ts +0 -146
- package/tests/utils/zip.spec.ts +0 -221
|
@@ -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
|
-
|
|
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
|
-
|
|
7
|
+
Base error class with cause-chain support. Messages are joined in reverse order with ` => `.
|
|
12
8
|
|
|
13
9
|
```typescript
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
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("
|
|
35
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
55
|
+
// message: "잘못된 인자입니다.\n\nuserId: 123\nname: null"
|
|
58
56
|
|
|
59
57
|
throw new ArgumentError("Invalid user", { userId: 123 });
|
|
60
|
-
//
|
|
58
|
+
// message: "Invalid user\n\nuserId: 123"
|
|
61
59
|
```
|
|
62
60
|
|
|
63
|
-
---
|
|
64
|
-
|
|
65
61
|
## `NotImplementedError`
|
|
66
62
|
|
|
67
|
-
|
|
63
|
+
Error for unimplemented features. Extends `SdError`.
|
|
68
64
|
|
|
69
65
|
```typescript
|
|
70
|
-
|
|
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
|
-
|
|
71
|
+
| Parameter | Type | Description |
|
|
72
|
+
|-----------|------|-------------|
|
|
73
|
+
| `message` | `string \| undefined` | Optional description of what is not implemented |
|
|
79
74
|
|
|
80
75
|
```typescript
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
throw new NotImplementedError("Implementation required in subclass");
|
|
84
|
-
}
|
|
85
|
-
}
|
|
76
|
+
throw new NotImplementedError();
|
|
77
|
+
// message: "미구현"
|
|
86
78
|
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
85
|
+
Error for timeout conditions. Extends `SdError`.
|
|
98
86
|
|
|
99
87
|
```typescript
|
|
100
|
-
|
|
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
|
-
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
```
|