@simplysm/core-common 13.0.96 → 13.0.98

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/docs/utils.md ADDED
@@ -0,0 +1,708 @@
1
+ # Utilities
2
+
3
+ Utility namespaces and directly exported functions.
4
+
5
+ Source: `src/utils/*.ts`
6
+
7
+ ---
8
+
9
+ ## Namespace: `obj`
10
+
11
+ Object manipulation utilities. Source: `src/utils/obj.ts`
12
+
13
+ ### `obj.clone`
14
+
15
+ Deep clone. Supports circular references and custom types (DateTime, DateOnly, Time, Uuid, Uint8Array, Error, Map, Set, RegExp). Functions and Symbols maintain references. Prototype chain is maintained.
16
+
17
+ ```typescript
18
+ export function clone<TObj>(source: TObj): TObj;
19
+ ```
20
+
21
+ ### `obj.equal`
22
+
23
+ Deep equality comparison. Supports DateTime, DateOnly, Time, Uuid, Date, RegExp, Map, Set, Array, and plain objects.
24
+
25
+ ```typescript
26
+ export function equal(source: unknown, target: unknown, options?: EqualOptions): boolean;
27
+
28
+ export interface EqualOptions {
29
+ topLevelIncludes?: string[];
30
+ topLevelExcludes?: string[];
31
+ ignoreArrayIndex?: boolean;
32
+ shallow?: boolean;
33
+ }
34
+ ```
35
+
36
+ ### `obj.merge`
37
+
38
+ Deep merge (merge target into source as base). Returns a new object without modifying originals.
39
+
40
+ ```typescript
41
+ export function merge<TSource, TMergeTarget>(
42
+ source: TSource,
43
+ target: TMergeTarget,
44
+ opt?: MergeOptions,
45
+ ): TSource & TMergeTarget;
46
+
47
+ export interface MergeOptions {
48
+ arrayProcess?: "replace" | "concat";
49
+ useDelTargetNull?: boolean;
50
+ }
51
+ ```
52
+
53
+ ### `obj.merge3`
54
+
55
+ 3-way merge. Compares source, origin, and target to produce a merged result with conflict detection.
56
+
57
+ ```typescript
58
+ export function merge3<
59
+ S extends Record<string, unknown>,
60
+ O extends Record<string, unknown>,
61
+ T extends Record<string, unknown>,
62
+ >(
63
+ source: S,
64
+ origin: O,
65
+ target: T,
66
+ optionsObj?: Record<string, Merge3KeyOptions>,
67
+ ): { conflict: boolean; result: O & S & T };
68
+
69
+ export interface Merge3KeyOptions {
70
+ keys?: string[];
71
+ excludes?: string[];
72
+ ignoreArrayIndex?: boolean;
73
+ }
74
+ ```
75
+
76
+ ### `obj.omit`
77
+
78
+ Exclude specific keys from object.
79
+
80
+ ```typescript
81
+ export function omit<T extends Record<string, unknown>, K extends keyof T>(item: T, omitKeys: K[]): Omit<T, K>;
82
+ ```
83
+
84
+ ### `obj.omitByFilter`
85
+
86
+ Exclude keys matching condition.
87
+
88
+ ```typescript
89
+ export function omitByFilter<T extends Record<string, unknown>>(item: T, omitKeyFn: (key: keyof T) => boolean): T;
90
+ ```
91
+
92
+ ### `obj.pick`
93
+
94
+ Select specific keys from object.
95
+
96
+ ```typescript
97
+ export function pick<T extends Record<string, unknown>, K extends keyof T>(item: T, pickKeys: K[]): Pick<T, K>;
98
+ ```
99
+
100
+ ### `obj.getChainValue`
101
+
102
+ Get value by chain path (e.g., `"a.b[0].c"`).
103
+
104
+ ```typescript
105
+ export function getChainValue(obj: unknown, chain: string): unknown;
106
+ export function getChainValue(obj: unknown, chain: string, optional: true): unknown | undefined;
107
+ ```
108
+
109
+ ### `obj.getChainValueByDepth`
110
+
111
+ Descend by the same key for depth levels.
112
+
113
+ ```typescript
114
+ export function getChainValueByDepth<TObject, TKey extends keyof TObject>(
115
+ obj: TObject, key: TKey, depth: number,
116
+ ): TObject[TKey];
117
+ export function getChainValueByDepth<TObject, TKey extends keyof TObject>(
118
+ obj: TObject, key: TKey, depth: number, optional: true,
119
+ ): TObject[TKey] | undefined;
120
+ ```
121
+
122
+ ### `obj.setChainValue`
123
+
124
+ Set value by chain path.
125
+
126
+ ```typescript
127
+ export function setChainValue(obj: unknown, chain: string, value: unknown): void;
128
+ ```
129
+
130
+ ### `obj.deleteChainValue`
131
+
132
+ Delete value by chain path.
133
+
134
+ ```typescript
135
+ export function deleteChainValue(obj: unknown, chain: string): void;
136
+ ```
137
+
138
+ ### `obj.clearUndefined`
139
+
140
+ Delete keys with `undefined` values from object. Mutates the original.
141
+
142
+ ```typescript
143
+ export function clearUndefined<T extends object>(obj: T): T;
144
+ ```
145
+
146
+ ### `obj.clear`
147
+
148
+ Delete all keys from object. Mutates the original.
149
+
150
+ ```typescript
151
+ export function clear<T extends Record<string, unknown>>(obj: T): Record<string, never>;
152
+ ```
153
+
154
+ ### `obj.nullToUndefined`
155
+
156
+ Convert `null` to `undefined` recursively. Mutates the original.
157
+
158
+ ```typescript
159
+ export function nullToUndefined<TObject>(obj: TObject): TObject | undefined;
160
+ ```
161
+
162
+ ### `obj.unflatten`
163
+
164
+ Convert flattened object to nested object.
165
+
166
+ ```typescript
167
+ export function unflatten(flatObj: Record<string, unknown>): Record<string, unknown>;
168
+ // Example: unflatten({ "a.b.c": 1 }) => { a: { b: { c: 1 } } }
169
+ ```
170
+
171
+ ### `obj.keys`
172
+
173
+ Type-safe `Object.keys`.
174
+
175
+ ```typescript
176
+ export function keys<T extends object>(obj: T): (keyof T)[];
177
+ ```
178
+
179
+ ### `obj.entries`
180
+
181
+ Type-safe `Object.entries`.
182
+
183
+ ```typescript
184
+ export function entries<T extends object>(obj: T): { [K in keyof T]: [K, T[K]] }[keyof T][];
185
+ ```
186
+
187
+ ### `obj.fromEntries`
188
+
189
+ Type-safe `Object.fromEntries`.
190
+
191
+ ```typescript
192
+ export function fromEntries<T extends [string, unknown]>(entryPairs: T[]): { [K in T[0]]: T[1] };
193
+ ```
194
+
195
+ ### `obj.map`
196
+
197
+ Transform each entry of object and return new object.
198
+
199
+ ```typescript
200
+ export function map<TSource extends object, TNewKey extends string, TNewValue>(
201
+ obj: TSource,
202
+ fn: (key: keyof TSource, value: TSource[keyof TSource]) => [TNewKey | null, TNewValue],
203
+ ): Record<TNewKey | Extract<keyof TSource, string>, TNewValue>;
204
+ ```
205
+
206
+ ### Type utilities from `obj`
207
+
208
+ ```typescript
209
+ export type UndefToOptional<TObject> = { /* undefined props become optional */ };
210
+ export type OptionalToUndef<TObject> = { /* optional props become required + undefined */ };
211
+ ```
212
+
213
+ ---
214
+
215
+ ## Namespace: `str`
216
+
217
+ String utility functions. Source: `src/utils/str.ts`
218
+
219
+ ### `str.getKoreanSuffix`
220
+
221
+ Return the appropriate Korean particle based on the final consonant (jongseong).
222
+
223
+ ```typescript
224
+ export function getKoreanSuffix(
225
+ text: string,
226
+ type: "을" | "은" | "이" | "와" | "랑" | "로" | "라",
227
+ ): string;
228
+ ```
229
+
230
+ ### `str.replaceFullWidth`
231
+
232
+ Convert full-width characters to half-width (A-Z, a-z, 0-9, space, parentheses).
233
+
234
+ ```typescript
235
+ export function replaceFullWidth(str: string): string;
236
+ ```
237
+
238
+ ### `str.toPascalCase`
239
+
240
+ ```typescript
241
+ export function toPascalCase(str: string): string;
242
+ // "hello-world" -> "HelloWorld"
243
+ ```
244
+
245
+ ### `str.toCamelCase`
246
+
247
+ ```typescript
248
+ export function toCamelCase(str: string): string;
249
+ // "hello-world" -> "helloWorld"
250
+ ```
251
+
252
+ ### `str.toKebabCase`
253
+
254
+ ```typescript
255
+ export function toKebabCase(str: string): string;
256
+ // "HelloWorld" -> "hello-world"
257
+ ```
258
+
259
+ ### `str.toSnakeCase`
260
+
261
+ ```typescript
262
+ export function toSnakeCase(str: string): string;
263
+ // "HelloWorld" -> "hello_world"
264
+ ```
265
+
266
+ ### `str.isNullOrEmpty`
267
+
268
+ Check if string is `undefined`, `null`, or empty (type guard).
269
+
270
+ ```typescript
271
+ export function isNullOrEmpty(str: string | undefined): str is "" | undefined;
272
+ ```
273
+
274
+ ### `str.insert`
275
+
276
+ Insert a string at a specific position.
277
+
278
+ ```typescript
279
+ export function insert(str: string, index: number, insertString: string): string;
280
+ ```
281
+
282
+ ---
283
+
284
+ ## Namespace: `num`
285
+
286
+ Number utility functions. Source: `src/utils/num.ts`
287
+
288
+ ### `num.parseInt`
289
+
290
+ Parse string to integer. Removes non-numeric characters before parsing.
291
+
292
+ ```typescript
293
+ export function parseInt(text: unknown): number | undefined;
294
+ ```
295
+
296
+ ### `num.parseRoundedInt`
297
+
298
+ Parse string to float, then round and return integer.
299
+
300
+ ```typescript
301
+ export function parseRoundedInt(text: unknown): number | undefined;
302
+ ```
303
+
304
+ ### `num.parseFloat`
305
+
306
+ Parse string to float. Removes non-numeric characters before parsing.
307
+
308
+ ```typescript
309
+ export function parseFloat(text: unknown): number | undefined;
310
+ ```
311
+
312
+ ### `num.isNullOrEmpty`
313
+
314
+ Check `undefined`, `null`, `0` (type guard).
315
+
316
+ ```typescript
317
+ export function isNullOrEmpty(val: number | undefined): val is 0 | undefined;
318
+ ```
319
+
320
+ ### `num.format`
321
+
322
+ Format number to string with thousand separators.
323
+
324
+ ```typescript
325
+ export function format(val: number, digit?: { max?: number; min?: number }): string;
326
+ export function format(val: number | undefined, digit?: { max?: number; min?: number }): string | undefined;
327
+ // num.format(1234.567, { max: 2 }) => "1,234.57"
328
+ // num.format(1234, { min: 2 }) => "1,234.00"
329
+ ```
330
+
331
+ ---
332
+
333
+ ## Namespace: `bytes`
334
+
335
+ Uint8Array utility functions. Source: `src/utils/bytes.ts`
336
+
337
+ ### `bytes.concat`
338
+
339
+ Concatenate multiple Uint8Arrays.
340
+
341
+ ```typescript
342
+ export function concat(arrays: Bytes[]): Bytes;
343
+ ```
344
+
345
+ ### `bytes.toHex`
346
+
347
+ Convert to lowercase hex string.
348
+
349
+ ```typescript
350
+ export function toHex(bytes: Bytes): string;
351
+ ```
352
+
353
+ ### `bytes.fromHex`
354
+
355
+ Convert from hex string to Uint8Array.
356
+
357
+ ```typescript
358
+ export function fromHex(hex: string): Bytes;
359
+ ```
360
+
361
+ ### `bytes.toBase64`
362
+
363
+ Convert Bytes to base64 string.
364
+
365
+ ```typescript
366
+ export function toBase64(bytes: Bytes): string;
367
+ ```
368
+
369
+ ### `bytes.fromBase64`
370
+
371
+ Convert base64 string to Bytes.
372
+
373
+ ```typescript
374
+ export function fromBase64(base64: string): Bytes;
375
+ ```
376
+
377
+ ---
378
+
379
+ ## Namespace: `path`
380
+
381
+ Path utility functions. Replacement for Node.js `path` module (supports browser environments). POSIX style paths only (slash `/`).
382
+
383
+ Source: `src/utils/path.ts`
384
+
385
+ ### `path.join`
386
+
387
+ Combine paths.
388
+
389
+ ```typescript
390
+ export function join(...segments: string[]): string;
391
+ ```
392
+
393
+ ### `path.basename`
394
+
395
+ Extract filename.
396
+
397
+ ```typescript
398
+ export function basename(filePath: string, ext?: string): string;
399
+ ```
400
+
401
+ ### `path.extname`
402
+
403
+ Extract file extension. Hidden files (e.g., `.gitignore`) return empty string.
404
+
405
+ ```typescript
406
+ export function extname(filePath: string): string;
407
+ ```
408
+
409
+ ---
410
+
411
+ ## Namespace: `json`
412
+
413
+ JSON serialization/deserialization supporting custom types (DateTime, DateOnly, Time, Uuid, Set, Map, Error, Uint8Array).
414
+
415
+ Source: `src/utils/json.ts`
416
+
417
+ ### `json.stringify`
418
+
419
+ Serialize object to JSON string. Supports custom types via `__type__` markers.
420
+
421
+ ```typescript
422
+ export function stringify(
423
+ obj: unknown,
424
+ options?: {
425
+ space?: string | number;
426
+ replacer?: (key: string | undefined, value: unknown) => unknown;
427
+ redactBytes?: boolean;
428
+ },
429
+ ): string;
430
+ ```
431
+
432
+ ### `json.parse`
433
+
434
+ Deserialize JSON string to object. Restores custom types from `__type__` markers. All JSON `null` values are converted to `undefined`.
435
+
436
+ ```typescript
437
+ export function parse<TResult = unknown>(json: string): TResult;
438
+ ```
439
+
440
+ ---
441
+
442
+ ## Namespace: `xml`
443
+
444
+ XML conversion utility using fast-xml-parser.
445
+
446
+ Source: `src/utils/xml.ts`
447
+
448
+ ### `xml.parse`
449
+
450
+ Parse XML string into an object. Attributes grouped in `$`, text nodes in `_`, child elements as arrays.
451
+
452
+ ```typescript
453
+ export function parse(str: string, options?: { stripTagPrefix?: boolean }): unknown;
454
+ ```
455
+
456
+ ### `xml.stringify`
457
+
458
+ Serialize object to XML string.
459
+
460
+ ```typescript
461
+ export function stringify(obj: unknown, options?: XmlBuilderOptions): string;
462
+ ```
463
+
464
+ ---
465
+
466
+ ## Namespace: `wait`
467
+
468
+ Wait utility functions. Source: `src/utils/wait.ts`
469
+
470
+ ### `wait.until`
471
+
472
+ Wait until a condition becomes true.
473
+
474
+ ```typescript
475
+ export async function until(
476
+ forwarder: () => boolean | Promise<boolean>,
477
+ milliseconds?: number,
478
+ maxCount?: number,
479
+ ): Promise<void>;
480
+ ```
481
+
482
+ - `milliseconds`: Check interval (default: 100ms)
483
+ - `maxCount`: Maximum number of attempts (`undefined` for unlimited)
484
+ - Throws `TimeoutError` when maximum number of attempts is exceeded
485
+
486
+ ### `wait.time`
487
+
488
+ Wait for a specified amount of time.
489
+
490
+ ```typescript
491
+ export async function time(millisecond: number): Promise<void>;
492
+ ```
493
+
494
+ ---
495
+
496
+ ## Namespace: `transfer`
497
+
498
+ Transferable conversion utility for Worker data transfer. Handles custom types that `structuredClone` does not support.
499
+
500
+ Source: `src/utils/transferable.ts`
501
+
502
+ ### `transfer.encode`
503
+
504
+ Convert objects using Simplysm types to plain objects for Worker transfer.
505
+
506
+ ```typescript
507
+ export function encode(obj: unknown): {
508
+ result: unknown;
509
+ transferList: Transferable[];
510
+ };
511
+ ```
512
+
513
+ ### `transfer.decode`
514
+
515
+ Convert serialized objects back to Simplysm types.
516
+
517
+ ```typescript
518
+ export function decode(obj: unknown): unknown;
519
+ ```
520
+
521
+ **Example:**
522
+
523
+ ```typescript
524
+ const { result, transferList } = transfer.encode(data);
525
+ worker.postMessage(result, transferList);
526
+
527
+ // In worker:
528
+ const decoded = transfer.decode(event.data);
529
+ ```
530
+
531
+ ---
532
+
533
+ ## Namespace: `err`
534
+
535
+ Error utility. Source: `src/utils/error.ts`
536
+
537
+ ### `err.message`
538
+
539
+ Extract message from unknown type error.
540
+
541
+ ```typescript
542
+ export function message(err: unknown): string;
543
+ ```
544
+
545
+ ---
546
+
547
+ ## Namespace: `dt`
548
+
549
+ Date format utilities. Source: `src/utils/date-format.ts`
550
+
551
+ ### `dt.normalizeMonth`
552
+
553
+ Normalize year/month/day when setting month. Adjusts year for out-of-range months, clamps day to last day of month.
554
+
555
+ ```typescript
556
+ export function normalizeMonth(year: number, month: number, day: number): DtNormalizedMonth;
557
+
558
+ export interface DtNormalizedMonth {
559
+ year: number;
560
+ month: number;
561
+ day: number;
562
+ }
563
+ ```
564
+
565
+ ### `dt.convert12To24`
566
+
567
+ Convert 12-hour format to 24-hour format.
568
+
569
+ ```typescript
570
+ export function convert12To24(rawHour: number, isPM: boolean): number;
571
+ ```
572
+
573
+ ### `dt.format`
574
+
575
+ Convert date/time components to string according to format string. Supports C#-style format specifiers:
576
+
577
+ | Format | Description | Example |
578
+ |--------|-------------|---------|
579
+ | `yyyy` | 4-digit year | 2024 |
580
+ | `yy` | 2-digit year | 24 |
581
+ | `MM` | Zero-padded month | 01-12 |
582
+ | `M` | Month | 1-12 |
583
+ | `ddd` | Day of week (Korean) | 일, 월, 화, 수, 목, 금, 토 |
584
+ | `dd` | Zero-padded day | 01-31 |
585
+ | `d` | Day | 1-31 |
586
+ | `tt` | AM/PM | AM, PM |
587
+ | `hh` / `h` | 12-hour (zero-padded / plain) | 01-12 / 1-12 |
588
+ | `HH` / `H` | 24-hour (zero-padded / plain) | 00-23 / 0-23 |
589
+ | `mm` / `m` | Minute (zero-padded / plain) | 00-59 / 0-59 |
590
+ | `ss` / `s` | Second (zero-padded / plain) | 00-59 / 0-59 |
591
+ | `fff` / `ff` / `f` | Milliseconds (3/2/1 digits) | 000-999 |
592
+ | `zzz` / `zz` / `z` | Timezone offset | +09:00 / +09 / +9 |
593
+
594
+ ```typescript
595
+ export function format(
596
+ formatString: string,
597
+ args: {
598
+ year?: number;
599
+ month?: number;
600
+ day?: number;
601
+ hour?: number;
602
+ minute?: number;
603
+ second?: number;
604
+ millisecond?: number;
605
+ timezoneOffsetMinutes?: number;
606
+ },
607
+ ): string;
608
+ ```
609
+
610
+ ---
611
+
612
+ ## Namespace: `primitive`
613
+
614
+ Primitive type inference. Source: `src/utils/primitive.ts`
615
+
616
+ ### `primitive.typeStr`
617
+
618
+ Infer `PrimitiveTypeStr` from a value at runtime.
619
+
620
+ ```typescript
621
+ export function typeStr(value: PrimitiveTypeMap[PrimitiveTypeStr]): PrimitiveTypeStr;
622
+ // primitive.typeStr("hello") => "string"
623
+ // primitive.typeStr(new DateTime()) => "DateTime"
624
+ // primitive.typeStr(new Uint8Array()) => "Bytes"
625
+ ```
626
+
627
+ ---
628
+
629
+ ## Direct Exports: Template Tag Functions
630
+
631
+ Template string tag functions for IDE code highlighting support. Actual behavior is string concatenation with indent normalization (leading/trailing blank lines removed, common indentation stripped).
632
+
633
+ Source: `src/utils/template-strings.ts`
634
+
635
+ ```typescript
636
+ export function js(strings: TemplateStringsArray, ...values: unknown[]): string;
637
+ export function ts(strings: TemplateStringsArray, ...values: unknown[]): string;
638
+ export function html(strings: TemplateStringsArray, ...values: unknown[]): string;
639
+ export function tsql(strings: TemplateStringsArray, ...values: unknown[]): string;
640
+ export function mysql(strings: TemplateStringsArray, ...values: unknown[]): string;
641
+ export function pgsql(strings: TemplateStringsArray, ...values: unknown[]): string;
642
+ ```
643
+
644
+ **Example:**
645
+
646
+ ```typescript
647
+ const query = tsql`
648
+ SELECT TOP 10 *
649
+ FROM Users
650
+ WHERE Name LIKE '%${keyword}%'
651
+ `;
652
+ ```
653
+
654
+ ---
655
+
656
+ ## Direct Export: `ZipArchive`
657
+
658
+ ZIP archive processing class. Handles reading, writing, compression, and decompression of ZIP files. Uses internal caching to prevent duplicate decompression. Supports `await using` (`Symbol.asyncDispose`).
659
+
660
+ Source: `src/utils/zip.ts`
661
+
662
+ ```typescript
663
+ export class ZipArchive {
664
+ /**
665
+ * @param data ZIP data (omit to create a new archive)
666
+ */
667
+ constructor(data?: Blob | Bytes);
668
+
669
+ /** Extract all files with optional progress callback */
670
+ async extractAll(progressCallback?: (progress: ZipArchiveProgress) => void): Promise<Map<string, Bytes | undefined>>;
671
+
672
+ /** Extract specific file */
673
+ async get(fileName: string): Promise<Bytes | undefined>;
674
+
675
+ /** Check if file exists */
676
+ async exists(fileName: string): Promise<boolean>;
677
+
678
+ /** Write file (store in cache) */
679
+ write(fileName: string, bytes: Bytes): void;
680
+
681
+ /** Compress cached files to ZIP */
682
+ async compress(): Promise<Bytes>;
683
+
684
+ /** Close reader and clear cache */
685
+ async close(): Promise<void>;
686
+
687
+ async [Symbol.asyncDispose](): Promise<void>;
688
+ }
689
+
690
+ export interface ZipArchiveProgress {
691
+ fileName: string;
692
+ totalSize: number;
693
+ extractedSize: number;
694
+ }
695
+ ```
696
+
697
+ **Example:**
698
+
699
+ ```typescript
700
+ // Read
701
+ await using archive = new ZipArchive(zipBytes);
702
+ const content = await archive.get("file.txt");
703
+
704
+ // Create
705
+ await using archive = new ZipArchive();
706
+ archive.write("file.txt", textBytes);
707
+ const zipBytes = await archive.compress();
708
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/core-common",
3
- "version": "13.0.96",
3
+ "version": "13.0.98",
4
4
  "description": "Simplysm package - Core module (common)",
5
5
  "author": "simplysm",
6
6
  "license": "Apache-2.0",
@@ -31,7 +31,7 @@
31
31
  "dependencies": {
32
32
  "@zip.js/zip.js": "^2.8.23",
33
33
  "consola": "^3.4.2",
34
- "fast-xml-parser": "^5.5.5",
34
+ "fast-xml-parser": "^5.5.8",
35
35
  "yaml": "^2.8.2"
36
36
  }
37
37
  }