@simplysm/core-common 14.0.48 → 14.0.50

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 (46) hide show
  1. package/README.md +57 -152
  2. package/dist/errors/sd-error.d.ts.map +1 -1
  3. package/dist/errors/sd-error.js +1 -1
  4. package/dist/errors/sd-error.js.map +1 -1
  5. package/dist/utils/json.js.map +1 -1
  6. package/dist/utils/obj.js.map +1 -1
  7. package/docs/errors/argument-error.md +26 -0
  8. package/docs/errors/not-implemented-error.md +33 -0
  9. package/docs/errors/sd-error.md +38 -0
  10. package/docs/errors/timeout-error.md +36 -0
  11. package/docs/extensions/array.md +125 -0
  12. package/docs/extensions/map.md +43 -0
  13. package/docs/extensions/set.md +35 -0
  14. package/docs/features/debounce-queue.md +48 -0
  15. package/docs/features/event-emitter.md +52 -0
  16. package/docs/features/serial-queue.md +44 -0
  17. package/docs/type-utils/common-types.md +100 -0
  18. package/docs/type-utils/env.md +42 -0
  19. package/docs/types/date-only.md +86 -0
  20. package/docs/types/date-time.md +106 -0
  21. package/docs/types/lazy-gc-map.md +59 -0
  22. package/docs/types/time.md +62 -0
  23. package/docs/types/uuid.md +41 -0
  24. package/docs/utils/bytes.md +36 -0
  25. package/docs/utils/dt.md +60 -0
  26. package/docs/utils/err.md +26 -0
  27. package/docs/utils/json.md +58 -0
  28. package/docs/utils/num.md +56 -0
  29. package/docs/utils/obj.md +107 -0
  30. package/docs/utils/path.md +30 -0
  31. package/docs/utils/primitive.md +28 -0
  32. package/docs/utils/str.md +63 -0
  33. package/docs/utils/template-strings.md +49 -0
  34. package/docs/utils/transfer.md +35 -0
  35. package/docs/utils/wait.md +35 -0
  36. package/docs/utils/xml.md +49 -0
  37. package/docs/utils/zip-archive.md +77 -0
  38. package/package.json +1 -1
  39. package/src/errors/sd-error.ts +1 -4
  40. package/src/utils/json.ts +1 -1
  41. package/src/utils/obj.ts +2 -2
  42. package/docs/errors.md +0 -82
  43. package/docs/extensions.md +0 -167
  44. package/docs/features.md +0 -136
  45. package/docs/types.md +0 -245
  46. package/docs/utils.md +0 -591
@@ -0,0 +1,106 @@
1
+ # DateTime
2
+
3
+ 불변 날짜시간 클래스 (밀리초 정밀도, 로컬 타임존). JavaScript `Date` 객체를 래핑하여 불변성과 편리한 API를 제공한다. 수정 메서드는 모두 새 인스턴스를 반환한다.
4
+
5
+ ```typescript
6
+ export class DateTime {
7
+ readonly date: Date;
8
+
9
+ constructor();
10
+ constructor(year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millisecond?: number);
11
+ constructor(tick: number);
12
+ constructor(date: Date);
13
+
14
+ static parse(str: string): DateTime;
15
+ }
16
+ ```
17
+
18
+ ## Members
19
+
20
+ | Member | Kind | Type | Description |
21
+ |--------|------|------|-------------|
22
+ | `date` | property | `Date` | 내부 Date 객체 |
23
+ | `year` | getter | `number` | 연도 |
24
+ | `month` | getter | `number` | 월 (1-12) |
25
+ | `day` | getter | `number` | 일 (1-31) |
26
+ | `hour` | getter | `number` | 시 (0-23) |
27
+ | `minute` | getter | `number` | 분 (0-59) |
28
+ | `second` | getter | `number` | 초 (0-59) |
29
+ | `millisecond` | getter | `number` | 밀리초 (0-999) |
30
+ | `tick` | getter | `number` | Unix 타임스탬프 (밀리초) |
31
+ | `dayOfWeek` | getter | `number` | 요일 (일요일=0 ~ 토요일=6) |
32
+ | `timezoneOffsetMinutes` | getter | `number` | 타임존 오프셋 (분) |
33
+ | `isValid` | getter | `boolean` | 날짜시간이 올바르게 설정되었는지 여부 |
34
+ | `parse` | static | `(str: string) => DateTime` | 문자열을 파싱하여 DateTime 생성 |
35
+ | `setYear` | method | `(year: number) => DateTime` | 지정된 연도로 새 인스턴스 반환 |
36
+ | `setMonth` | method | `(month: number) => DateTime` | 지정된 월로 새 인스턴스 반환. 현재 일이 대상 월의 일수보다 크면 마지막 일로 조정됨 |
37
+ | `setDay` | method | `(day: number) => DateTime` | 지정된 일로 새 인스턴스 반환 |
38
+ | `setHour` | method | `(hour: number) => DateTime` | 지정된 시로 새 인스턴스 반환 |
39
+ | `setMinute` | method | `(minute: number) => DateTime` | 지정된 분으로 새 인스턴스 반환 |
40
+ | `setSecond` | method | `(second: number) => DateTime` | 지정된 초로 새 인스턴스 반환 |
41
+ | `setMillisecond` | method | `(millisecond: number) => DateTime` | 지정된 밀리초로 새 인스턴스 반환 |
42
+ | `addYears` | method | `(years: number) => DateTime` | 지정된 연수를 더한 새 인스턴스 반환 |
43
+ | `addMonths` | method | `(months: number) => DateTime` | 지정된 월수를 더한 새 인스턴스 반환 |
44
+ | `addDays` | method | `(days: number) => DateTime` | 지정된 일수를 더한 새 인스턴스 반환 |
45
+ | `addHours` | method | `(hours: number) => DateTime` | 지정된 시간을 더한 새 인스턴스 반환 |
46
+ | `addMinutes` | method | `(minutes: number) => DateTime` | 지정된 분을 더한 새 인스턴스 반환 |
47
+ | `addSeconds` | method | `(seconds: number) => DateTime` | 지정된 초를 더한 새 인스턴스 반환 |
48
+ | `addMilliseconds` | method | `(milliseconds: number) => DateTime` | 지정된 밀리초를 더한 새 인스턴스 반환 |
49
+ | `toFormatString` | method | `(formatStr: string) => string` | 지정된 형식 문자열로 변환 |
50
+ | `toString` | method | `() => string` | ISO 형식 문자열 반환 (`yyyy-MM-ddTHH:mm:ss.fffzzz`) |
51
+
52
+ ## `parse` — 지원 형식
53
+
54
+ | 형식 | 예시 |
55
+ |------|------|
56
+ | `yyyy-MM-dd HH:mm:ss` | `"2025-01-15 10:30:00"` |
57
+ | `yyyy-MM-dd HH:mm:ss.fff` | `"2025-01-15 10:30:00.123"` |
58
+ | `yyyyMMddHHmmss` | `"20250115103000"` |
59
+ | `yyyy-MM-dd AM/PM HH:mm:ss` | `"2025-01-15 AM 10:30:00"` |
60
+ | `yyyy-MM-dd 오전/오후 HH:mm:ss` | `"2025-01-15 오전 10:30:00"` |
61
+ | ISO 8601 | `"2025-01-15T10:30:00Z"` |
62
+
63
+ ## `toFormatString` — 형식 문자열 토큰
64
+
65
+ | 토큰 | 설명 | 예시 |
66
+ |------|------|------|
67
+ | `yyyy` | 4자리 연도 | `2025` |
68
+ | `yy` | 2자리 연도 | `25` |
69
+ | `MM` | 0 채움 월 | `01`~`12` |
70
+ | `M` | 월 | `1`~`12` |
71
+ | `ddd` | 요일 | `일`, `월`, `화`, `수`, `목`, `금`, `토` |
72
+ | `dd` | 0 채움 일 | `01`~`31` |
73
+ | `d` | 일 | `1`~`31` |
74
+ | `tt` | 오전/오후 | `AM`, `PM` |
75
+ | `HH` | 0 채움 24시간 | `00`~`23` |
76
+ | `H` | 24시간 | `0`~`23` |
77
+ | `hh` | 0 채움 12시간 | `01`~`12` |
78
+ | `h` | 12시간 | `1`~`12` |
79
+ | `mm` | 0 채움 분 | `00`~`59` |
80
+ | `m` | 분 | `0`~`59` |
81
+ | `ss` | 0 채움 초 | `00`~`59` |
82
+ | `s` | 초 | `0`~`59` |
83
+ | `fff` | 밀리초 (3자리) | `000`~`999` |
84
+ | `ff` | 밀리초 (2자리) | `00`~`99` |
85
+ | `f` | 밀리초 (1자리) | `0`~`9` |
86
+ | `zzz` | 타임존 오프셋 (`±HH:mm`) | `+09:00` |
87
+ | `zz` | 타임존 오프셋 (`±HH`) | `+09` |
88
+ | `z` | 타임존 오프셋 (`±H`) | `+9` |
89
+
90
+ ## Usage
91
+
92
+ ```typescript
93
+ import { DateTime } from "@simplysm/core-common";
94
+
95
+ const now = new DateTime();
96
+ const specific = new DateTime(2025, 1, 15, 10, 30, 0);
97
+ const fromTick = new DateTime(Date.now());
98
+ const parsed = DateTime.parse("2025-01-15 10:30:00");
99
+
100
+ const formatted = now.toFormatString("yyyy-MM-dd HH:mm:ss");
101
+ const iso = now.toString(); // "2025-01-15T10:30:00.000+09:00"
102
+
103
+ // 불변 수정
104
+ const nextMonth = now.addMonths(1);
105
+ const endOfYear = now.setMonth(12).setDay(31);
106
+ ```
@@ -0,0 +1,59 @@
1
+ # LazyGcMap
2
+
3
+ 자동 만료 기능이 있는 Map. LRU 방식으로 접근 시간을 갱신하고, 지정된 시간 동안 접근하지 않으면 자동 삭제한다. 사용 후 반드시 `dispose()`를 호출해야 GC 타이머가 정리된다.
4
+
5
+ ```typescript
6
+ export class LazyGcMap<TKey, TValue> {
7
+ constructor(options: {
8
+ gcInterval?: number;
9
+ expireTime: number;
10
+ onExpire?: (key: TKey, value: TValue) => void | Promise<void>;
11
+ });
12
+ }
13
+ ```
14
+
15
+ ## Constructor Options
16
+
17
+ | Field | Type | Required | Description |
18
+ |-------|------|----------|-------------|
19
+ | `expireTime` | `number` | 필수 | 만료 시간 (밀리초). 마지막 접근 이후 이 시간이 지나면 삭제됨 |
20
+ | `gcInterval` | `number` | 선택 | GC 간격 (밀리초). 생략 시 `expireTime / 10` (최소 1000ms) |
21
+ | `onExpire` | `(key: TKey, value: TValue) => void \| Promise<void>` | 선택 | 만료 시 호출되는 콜백. 에러 발생 시 로그 출력 후 계속 실행 |
22
+
23
+ ## Members
24
+
25
+ | Member | Kind | Type | Description |
26
+ |--------|------|------|-------------|
27
+ | `size` | getter | `number` | 저장된 항목 수 |
28
+ | `has` | method | `(key: TKey) => boolean` | key 존재 여부 확인 (접근 시간 갱신하지 않음) |
29
+ | `get` | method | `(key: TKey) => TValue \| undefined` | 값 조회 (접근 시간 갱신) |
30
+ | `set` | method | `(key: TKey, value: TValue) => void` | 값 저장 (접근 시간 설정 및 GC 타이머 시작) |
31
+ | `delete` | method | `(key: TKey) => boolean` | 항목 삭제 |
32
+ | `getOrCreate` | method | `(key: TKey, factory: () => TValue) => TValue` | key가 없으면 팩토리로 생성하여 저장 후 반환 |
33
+ | `clear` | method | `() => void` | 모든 항목 삭제 (인스턴스는 계속 사용 가능) |
34
+ | `dispose` | method | `() => void` | 인스턴스 정리 (GC 타이머 중지 및 데이터 삭제). 이후 모든 작업 무시됨 |
35
+ | `values` | method | `() => IterableIterator<TValue>` | 값 순회 |
36
+ | `keys` | method | `() => IterableIterator<TKey>` | key 순회 |
37
+ | `entries` | method | `() => IterableIterator<[TKey, TValue]>` | 엔트리 순회 |
38
+
39
+ ## Usage
40
+
41
+ ```typescript
42
+ import { LazyGcMap } from "@simplysm/core-common";
43
+
44
+ const cache = new LazyGcMap<string, Data>({
45
+ expireTime: 60_000, // 60초 미접근 시 삭제
46
+ gcInterval: 10_000, // 10초마다 GC 실행 (생략 시 6000ms)
47
+ onExpire: async (key, value) => {
48
+ await value.cleanup(); // 정리 작업
49
+ },
50
+ });
51
+
52
+ try {
53
+ cache.set("key", data);
54
+ const val = cache.get("key"); // 접근 시간 갱신
55
+ const created = cache.getOrCreate("other", () => createData());
56
+ } finally {
57
+ cache.dispose(); // 반드시 호출
58
+ }
59
+ ```
@@ -0,0 +1,62 @@
1
+ # Time
2
+
3
+ 불변 시간 클래스 (날짜 제외: `HH:mm:ss.fff`). 날짜 정보 없이 시간만 저장하며 24시간을 초과하거나 음수인 값은 자동으로 정규화된다. 수정 및 산술 메서드는 새 인스턴스를 반환하며 모두 24시간 순환한다.
4
+
5
+ ```typescript
6
+ export class Time {
7
+ constructor();
8
+ constructor(hour: number, minute: number, second?: number, millisecond?: number);
9
+ constructor(tick: number);
10
+ constructor(date: Date);
11
+
12
+ static parse(str: string): Time;
13
+ }
14
+ ```
15
+
16
+ ## Members
17
+
18
+ | Member | Kind | Type | Description |
19
+ |--------|------|------|-------------|
20
+ | `hour` | getter | `number` | 시 (0-23) |
21
+ | `minute` | getter | `number` | 분 (0-59) |
22
+ | `second` | getter | `number` | 초 (0-59) |
23
+ | `millisecond` | getter | `number` | 밀리초 (0-999) |
24
+ | `tick` | getter | `number` | 자정(00:00:00.000) 기준 밀리초 |
25
+ | `isValid` | getter | `boolean` | 시간이 올바르게 설정되었는지 여부 |
26
+ | `parse` | static | `(str: string) => Time` | 문자열을 파싱하여 Time 생성 |
27
+ | `setHour` | method | `(hour: number) => Time` | 지정된 시로 새 인스턴스 반환 |
28
+ | `setMinute` | method | `(minute: number) => Time` | 지정된 분으로 새 인스턴스 반환 |
29
+ | `setSecond` | method | `(second: number) => Time` | 지정된 초로 새 인스턴스 반환 |
30
+ | `setMillisecond` | method | `(millisecond: number) => Time` | 지정된 밀리초로 새 인스턴스 반환 |
31
+ | `addHours` | method | `(hours: number) => Time` | 지정된 시간을 더한 새 인스턴스 반환 (24시간 순환) |
32
+ | `addMinutes` | method | `(minutes: number) => Time` | 지정된 분을 더한 새 인스턴스 반환 (24시간 순환) |
33
+ | `addSeconds` | method | `(seconds: number) => Time` | 지정된 초를 더한 새 인스턴스 반환 (24시간 순환) |
34
+ | `addMilliseconds` | method | `(milliseconds: number) => Time` | 지정된 밀리초를 더한 새 인스턴스 반환 (24시간 순환) |
35
+ | `toFormatString` | method | `(formatStr: string) => string` | 지정된 형식 문자열로 변환 (형식 토큰은 [`DateTime`](./date-time.md) 참조, 날짜 관련 토큰 제외) |
36
+ | `toString` | method | `() => string` | `"HH:mm:ss.fff"` 형식 문자열 반환 |
37
+
38
+ ## `parse` — 지원 형식
39
+
40
+ | 형식 | 예시 |
41
+ |------|------|
42
+ | `HH:mm:ss` | `"10:30:00"` |
43
+ | `HH:mm:ss.fff` | `"10:30:00.123"` |
44
+ | `AM/PM HH:mm:ss` | `"AM 10:30:00"`, `"PM 02:15:00"` |
45
+ | ISO 8601 | `"2025-01-15T10:30:00Z"` (시간 부분만 추출, 타임존 변환 적용) |
46
+
47
+ ## Usage
48
+
49
+ ```typescript
50
+ import { Time } from "@simplysm/core-common";
51
+
52
+ const now = new Time();
53
+ const specific = new Time(10, 30, 0);
54
+ const parsed = Time.parse("10:30:00");
55
+
56
+ // 불변 수정
57
+ const later = specific.addHours(2).addMinutes(30);
58
+ // 24시간 순환
59
+ const midnight = new Time(23, 0, 0).addHours(2); // 01:00:00
60
+
61
+ const formatted = specific.toFormatString("HH:mm:ss");
62
+ ```
@@ -0,0 +1,41 @@
1
+ # Uuid
2
+
3
+ UUID v4 클래스. `crypto.getRandomValues` 기반으로 암호학적으로 안전한 UUID를 생성한다 (Chrome 37+, Node.js 호환).
4
+
5
+ ```typescript
6
+ export class Uuid {
7
+ constructor(uuid: string);
8
+
9
+ static generate(): Uuid;
10
+ static fromBytes(bytes: Bytes): Uuid;
11
+ }
12
+ ```
13
+
14
+ ## Members
15
+
16
+ | Member | Kind | Type | Description |
17
+ |--------|------|------|-------------|
18
+ | `generate` | static | `() => Uuid` | 새 UUID v4 인스턴스 생성 |
19
+ | `fromBytes` | static | `(bytes: Bytes) => Uuid` | 16바이트 `Uint8Array`로 UUID 생성. 바이트 크기가 16이 아니면 `ArgumentError` 발생 |
20
+ | `toString` | method | `() => string` | UUID 문자열 반환 (`xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`) |
21
+ | `toBytes` | method | `() => Bytes` | UUID를 16바이트 `Uint8Array`로 변환 |
22
+
23
+ ## Related Types
24
+
25
+ ### `Bytes`
26
+
27
+ `Uint8Array` 별칭. [`Bytes`](../type-utils/common-types.md) 참조.
28
+
29
+ ## Usage
30
+
31
+ ```typescript
32
+ import { Uuid } from "@simplysm/core-common";
33
+
34
+ const id = Uuid.generate();
35
+ const fromStr = new Uuid("550e8400-e29b-41d4-a716-446655440000");
36
+
37
+ console.log(id.toString()); // "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
38
+
39
+ const bytes = id.toBytes(); // Uint8Array(16)
40
+ const restored = Uuid.fromBytes(bytes);
41
+ ```
@@ -0,0 +1,36 @@
1
+ # bytes
2
+
3
+ `Uint8Array` 유틸리티 네임스페이스. 복잡한 변환 연산을 제공한다.
4
+
5
+ ```typescript
6
+ import { bytes } from "@simplysm/core-common";
7
+ ```
8
+
9
+ ## Functions
10
+
11
+ | Function | Signature | Description |
12
+ |----------|-----------|-------------|
13
+ | `concat` | `(arrays: Bytes[]) => Bytes` | 여러 `Uint8Array` 결합 |
14
+ | `toHex` | `(bytes: Bytes) => string` | `Uint8Array`를 소문자 hex 문자열로 변환 |
15
+ | `fromHex` | `(hex: string) => Bytes` | hex 문자열을 `Uint8Array`로 변환. 홀수 길이이거나 유효하지 않은 문자가 있으면 `ArgumentError` |
16
+ | `toBase64` | `(bytes: Bytes) => string` | `Uint8Array`를 Base64 문자열로 변환 |
17
+ | `fromBase64` | `(base64: string) => Bytes` | Base64 문자열을 `Uint8Array`로 변환. 유효하지 않은 문자/길이이면 `ArgumentError` |
18
+
19
+ ## Usage
20
+
21
+ ```typescript
22
+ import { bytes } from "@simplysm/core-common";
23
+
24
+ // concat
25
+ const a = new Uint8Array([1, 2]);
26
+ const b = new Uint8Array([3, 4]);
27
+ bytes.concat([a, b]); // Uint8Array([1, 2, 3, 4])
28
+
29
+ // hex 변환
30
+ bytes.toHex(new Uint8Array([255, 0, 127])); // "ff007f"
31
+ bytes.fromHex("ff007f"); // Uint8Array([255, 0, 127])
32
+
33
+ // base64 변환
34
+ bytes.toBase64(new Uint8Array([72, 101, 108, 108, 111])); // "SGVsbG8="
35
+ bytes.fromBase64("SGVsbG8="); // Uint8Array([72, 101, 108, 108, 111])
36
+ ```
@@ -0,0 +1,60 @@
1
+ # dt
2
+
3
+ 날짜 포맷 유틸리티 네임스페이스. `DateTime`, `DateOnly`, `Time` 클래스 내부에서 사용되는 저수준 포맷/변환 함수를 제공한다.
4
+
5
+ ```typescript
6
+ import { dt } from "@simplysm/core-common";
7
+ ```
8
+
9
+ ## Functions
10
+
11
+ | Function | Signature | Description |
12
+ |----------|-----------|-------------|
13
+ | `format` | `(formatString, args) => string` | 형식 문자열에 따라 날짜/시간을 문자열로 변환 |
14
+ | `normalizeMonth` | `(year, month, day) => DtNormalizedMonth` | 월 설정 시 연/월/일 정규화 (범위 벗어난 월 처리, 마지막 일 초과 처리) |
15
+ | `convert12To24` | `(rawHour, isPM) => number` | 12시간 형식을 24시간 형식으로 변환 |
16
+
17
+ ## `format` — args
18
+
19
+ | Field | Type | Description |
20
+ |-------|------|-------------|
21
+ | `year` | `number` | 연도 |
22
+ | `month` | `number` | 월 |
23
+ | `day` | `number` | 일 |
24
+ | `hour` | `number` | 시 |
25
+ | `minute` | `number` | 분 |
26
+ | `second` | `number` | 초 |
27
+ | `millisecond` | `number` | 밀리초 |
28
+ | `timezoneOffsetMinutes` | `number` | 타임존 오프셋 (분) |
29
+
30
+ 형식 문자열 토큰은 [`DateTime.toFormatString`](../types/date-time.md)과 동일하다.
31
+
32
+ ## Related Types
33
+
34
+ ### `DtNormalizedMonth`
35
+
36
+ `normalizeMonth()` 결과 타입:
37
+
38
+ | Field | Type | Description |
39
+ |-------|------|-------------|
40
+ | `year` | `number` | 정규화된 연도 |
41
+ | `month` | `number` | 정규화된 월 (1-12) |
42
+ | `day` | `number` | 정규화된 일 |
43
+
44
+ ## Usage
45
+
46
+ ```typescript
47
+ import { dt } from "@simplysm/core-common";
48
+
49
+ // 포맷
50
+ dt.format("yyyy-MM-dd", { year: 2025, month: 1, day: 15 }); // "2025-01-15"
51
+
52
+ // 월 정규화
53
+ dt.normalizeMonth(2025, 13, 15); // { year: 2026, month: 1, day: 15 }
54
+ dt.normalizeMonth(2025, 2, 31); // { year: 2025, month: 2, day: 28 }
55
+
56
+ // 12시간 → 24시간
57
+ dt.convert12To24(12, false); // 0 (12:00 AM = 0:00)
58
+ dt.convert12To24(12, true); // 12 (12:00 PM = 12:00)
59
+ dt.convert12To24(3, true); // 15 (3:00 PM = 15:00)
60
+ ```
@@ -0,0 +1,26 @@
1
+ # err
2
+
3
+ 에러 메시지 추출 유틸리티 네임스페이스.
4
+
5
+ ```typescript
6
+ import { err } from "@simplysm/core-common";
7
+ ```
8
+
9
+ ## Functions
10
+
11
+ | Function | Signature | Description |
12
+ |----------|-----------|-------------|
13
+ | `message` | `(err: unknown) => string` | `catch` 블록의 `unknown` 에러에서 메시지 추출. `Error` 인스턴스이면 `message` 속성 반환, 그렇지 않으면 `String()` 변환 결과 반환 |
14
+
15
+ ## Usage
16
+
17
+ ```typescript
18
+ import { err } from "@simplysm/core-common";
19
+
20
+ try {
21
+ await doSomething();
22
+ } catch (e) {
23
+ const msg = err.message(e); // string
24
+ console.log(msg);
25
+ }
26
+ ```
@@ -0,0 +1,58 @@
1
+ # json
2
+
3
+ JSON 변환 유틸리티 네임스페이스. `DateTime`, `DateOnly`, `Time`, `Uuid`, `Set`, `Map`, `Error`, `Uint8Array` 등 커스텀 타입을 지원하는 직렬화/역직렬화를 제공한다.
4
+
5
+ ```typescript
6
+ import { json } from "@simplysm/core-common";
7
+ ```
8
+
9
+ ## Functions
10
+
11
+ | Function | Signature | Description |
12
+ |----------|-----------|-------------|
13
+ | `stringify` | `(obj, options?) => string` | 객체를 JSON 문자열로 직렬화 |
14
+ | `parse` | `<TResult = unknown>(json: string) => TResult` | JSON 문자열을 객체로 역직렬화. null 값은 undefined로 변환 |
15
+
16
+ ## `stringify` — options
17
+
18
+ | Field | Type | Description |
19
+ |-------|------|-------------|
20
+ | `space` | `string \| number` | JSON 들여쓰기 |
21
+ | `replacer` | `(key, value) => unknown` | 커스텀 replacer. 기본 타입 변환 전에 호출됨 |
22
+ | `redactBytes` | `boolean` | `true`이면 `Uint8Array` 내용을 `"__hidden__"`으로 대체 (로깅용). 이 옵션으로 직렬화된 결과는 `parse()`로 복원 불가 |
23
+
24
+ ## 지원 타입
25
+
26
+ | 타입 | 직렬화 형식 |
27
+ |------|-------------|
28
+ | `DateTime` | `{ __type__: "DateTime", data: "yyyy-MM-ddTHH:mm:ss.fffzzz" }` |
29
+ | `DateOnly` | `{ __type__: "DateOnly", data: "yyyy-MM-dd" }` |
30
+ | `Time` | `{ __type__: "Time", data: "HH:mm:ss.fff" }` |
31
+ | `Uuid` | `{ __type__: "Uuid", data: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }` |
32
+ | `Date` | `{ __type__: "Date", data: ISO8601 }` |
33
+ | `Set` | `{ __type__: "Set", data: [...] }` |
34
+ | `Map` | `{ __type__: "Map", data: [[k, v], ...] }` |
35
+ | `Error` | `{ __type__: "Error", data: { name, message, stack, ... } }` |
36
+ | `Uint8Array` | `{ __type__: "Uint8Array", data: "hex문자열" }` |
37
+
38
+ `parse()`는 JSON null 값을 undefined로 변환한다. 이는 simplysm 프레임워크의 null-free 규칙을 위한 의도적인 동작이다.
39
+
40
+ ## Usage
41
+
42
+ ```typescript
43
+ import { json, DateTime, Uuid } from "@simplysm/core-common";
44
+
45
+ // 커스텀 타입 지원 직렬화
46
+ const serialized = json.stringify({
47
+ date: new DateTime(),
48
+ id: Uuid.generate(),
49
+ data: new Uint8Array([1, 2, 3]),
50
+ });
51
+
52
+ // 커스텀 타입 복원
53
+ const restored = json.parse<{ date: DateTime; id: Uuid }>(serialized);
54
+ // restored.date는 DateTime 인스턴스
55
+
56
+ // 로깅용 (바이너리 숨김)
57
+ const logStr = json.stringify({ data: sensitiveBytes }, { redactBytes: true });
58
+ ```
@@ -0,0 +1,56 @@
1
+ # num
2
+
3
+ 숫자 유틸리티 네임스페이스.
4
+
5
+ ```typescript
6
+ import { num } from "@simplysm/core-common";
7
+ ```
8
+
9
+ ## Functions
10
+
11
+ | Function | Signature | Description |
12
+ |----------|-----------|-------------|
13
+ | `parseInt` | `(text: unknown) => number \| undefined` | 문자열을 정수로 파싱. 비숫자 문자 제거 후 파싱. 소수점 이하 버림 |
14
+ | `parseFloat` | `(text: unknown) => number \| undefined` | 문자열을 float로 파싱. 비숫자 문자 제거 후 파싱 |
15
+ | `parseRoundedInt` | `(text: unknown) => number \| undefined` | 문자열을 float로 파싱한 후 반올림하여 정수 반환 |
16
+ | `isNullOrEmpty` | `(val: number \| undefined) => val is 0 \| undefined` | 타입 가드: undefined, null, 0이면 true |
17
+ | `format` | `(val: number, digit?) => string` | 천 단위 구분자 포함 문자열로 포맷 |
18
+ | `format` | `(val: number \| undefined, digit?) => string \| undefined` | undefined이면 undefined 반환 |
19
+
20
+ ## `parseInt` / `parseFloat` 동작
21
+
22
+ - 숫자, `-`, `.` 이외의 문자 제거 후 파싱
23
+ - 선행 `-`만 음수 부호로 유지 (중간 `-`는 제거)
24
+ - 파싱 실패 시 `undefined` 반환
25
+
26
+ ## `format` — `digit` 옵션
27
+
28
+ | Field | Type | Description |
29
+ |-------|------|-------------|
30
+ | `max` | `number` | 최대 소수점 자릿수 |
31
+ | `min` | `number` | 최소 소수점 자릿수 (부족하면 0으로 채움) |
32
+
33
+ ## Usage
34
+
35
+ ```typescript
36
+ import { num } from "@simplysm/core-common";
37
+
38
+ num.parseInt("1,234.56"); // 1234
39
+ num.parseInt("-123"); // -123
40
+ num.parseInt("010-1234-5678"); // 1012345678 (중간 - 제거)
41
+ num.parseInt("abc"); // undefined
42
+
43
+ num.parseFloat("1,234.56"); // 1234.56
44
+ num.parseRoundedInt("1.7"); // 2
45
+
46
+ // null/zero 검사 (타입 가드)
47
+ const count: number | undefined = getValue();
48
+ if (num.isNullOrEmpty(count)) {
49
+ // count: 0 | undefined
50
+ } else {
51
+ // count: number (non-zero)
52
+ }
53
+
54
+ num.format(1234567.89, { max: 2 }); // "1,234,567.89"
55
+ num.format(1234, { min: 2 }); // "1,234.00"
56
+ ```
@@ -0,0 +1,107 @@
1
+ # obj
2
+
3
+ 객체 유틸리티 네임스페이스. 깊은 복사, 비교, 병합, key 조작 등을 제공한다.
4
+
5
+ ```typescript
6
+ import { obj } from "@simplysm/core-common";
7
+ ```
8
+
9
+ ## Functions
10
+
11
+ | Function | Signature | Description |
12
+ |----------|-----------|-------------|
13
+ | `clone` | `<T>(source: T) => T` | 깊은 복사. 순환 참조, 커스텀 타입(`DateTime`, `DateOnly`, `Time`, `Uuid`, `Uint8Array`) 지원 |
14
+ | `equal` | `(source, target, options?) => boolean` | 깊은 동등성 비교 |
15
+ | `merge` | `<S, T>(source: S, target: T, opt?) => S & T` | 깊은 병합. source를 기반으로 target을 병합하여 새 객체 반환 |
16
+ | `merge3` | `(source, origin, target, optionsObj?) => { conflict, result }` | 3-way 병합 |
17
+ | `omit` | `<T, K>(item: T, omitKeys: K[]) => Omit<T, K>` | 특정 key 제외 |
18
+ | `omitByFilter` | `<T>(item: T, omitKeyFn) => T` | 조건에 맞는 key 제외 |
19
+ | `pick` | `<T, K>(item: T, pickKeys: K[]) => Pick<T, K>` | 특정 key만 선택 |
20
+ | `getChainValue` | `(obj, chain, optional?) => unknown` | 체인 경로로 값 조회 (예: `"a.b[0].c"`) |
21
+ | `getChainValueByDepth` | `(obj, key, depth, optional?) => TObject[TKey]` | 같은 key로 지정된 깊이만큼 하강 |
22
+ | `setChainValue` | `(obj, chain, value) => void` | 체인 경로로 값 설정 |
23
+ | `deleteChainValue` | `(obj, chain) => void` | 체인 경로로 값 삭제 |
24
+ | `clearUndefined` | `<T>(obj: T) => T` | 객체에서 undefined/null 값을 가진 key 삭제 (원본 수정) |
25
+ | `clear` | `<T>(obj: T) => Record<string, never>` | 객체의 모든 key 삭제 (원본 수정) |
26
+ | `nullToUndefined` | `<T>(obj: T) => T \| undefined` | null을 undefined로 변환 (재귀, 원본 수정) |
27
+ | `unflatten` | `(flatObj) => Record<string, unknown>` | 평탄화된 객체를 중첩 객체로 변환 (`"a.b.c": 1` → `{ a: { b: { c: 1 } } }`) |
28
+ | `keys` | `<T>(obj: T) => (keyof T)[]` | 타입 안전한 `Object.keys` |
29
+ | `entries` | `<T>(obj: T) => Entries<T>` | 타입 안전한 `Object.entries` |
30
+ | `fromEntries` | `<T>(entryPairs: T[]) => { [K in T[0]]: T[1] }` | 타입 안전한 `Object.fromEntries` |
31
+ | `map` | `(obj, fn) => Record<string, TNewValue>` | 각 엔트리를 변환하여 새 객체 반환 |
32
+
33
+ ## Related Types
34
+
35
+ ### `EqualOptions`
36
+
37
+ `equal()` 옵션:
38
+
39
+ | Field | Type | Description |
40
+ |-------|------|-------------|
41
+ | `topLevelIncludes` | `string[]` | 비교할 key 목록 (최상위 레벨에만 적용) |
42
+ | `topLevelExcludes` | `string[]` | 비교에서 제외할 key 목록 (최상위 레벨에만 적용) |
43
+ | `ignoreArrayIndex` | `boolean` | 배열 순서를 무시할지 여부. `true`면 O(n²) 복잡도 |
44
+ | `shallow` | `boolean` | 얕은 비교 여부. `true`면 1단계만 비교 (참조 비교) |
45
+
46
+ ### `MergeOptions`
47
+
48
+ `merge()` 옵션:
49
+
50
+ | Field | Type | Description |
51
+ |-------|------|-------------|
52
+ | `arrayProcess` | `"replace" \| "concat"` | 배열 처리 방식. `"replace"`: target으로 교체 (기본값), `"concat"`: 병합 (중복 제거) |
53
+ | `useDelTargetNull` | `boolean` | target이 null일 때 해당 key를 삭제할지 여부 |
54
+
55
+ ### `Merge3KeyOptions`
56
+
57
+ `merge3()` key별 옵션:
58
+
59
+ | Field | Type | Description |
60
+ |-------|------|-------------|
61
+ | `keys` | `string[]` | 비교할 하위 key 목록 |
62
+ | `excludes` | `string[]` | 비교에서 제외할 하위 key 목록 |
63
+ | `ignoreArrayIndex` | `boolean` | 배열 순서를 무시할지 여부 |
64
+
65
+ ### `UndefToOptional<T>`
66
+
67
+ `undefined` 타입을 가진 속성을 optional로 변환:
68
+
69
+ ```typescript
70
+ // { a: string; b: string | undefined } → { a: string; b?: string | undefined }
71
+ export type UndefToOptional<TObject> = ...
72
+ ```
73
+
74
+ ### `OptionalToUndef<T>`
75
+
76
+ optional 속성을 필수 + `undefined` 유니온으로 변환:
77
+
78
+ ```typescript
79
+ // { a: string; b?: string } → { a: string; b: string | undefined }
80
+ export type OptionalToUndef<TObject> = ...
81
+ ```
82
+
83
+ ## Usage
84
+
85
+ ```typescript
86
+ import { obj } from "@simplysm/core-common";
87
+
88
+ // 깊은 복사
89
+ const copied = obj.clone({ nested: { data: [1, 2, 3] } });
90
+
91
+ // 깊은 비교
92
+ const isEqual = obj.equal(a, b, { topLevelExcludes: ["updatedAt"] });
93
+
94
+ // 깊은 병합
95
+ const merged = obj.merge(defaults, overrides);
96
+
97
+ // omit / pick
98
+ const noId = obj.omit(user, ["id"]);
99
+ const onlyName = obj.pick(user, ["name", "email"]);
100
+
101
+ // 체인 경로
102
+ const val = obj.getChainValue(data, "user.address[0].city");
103
+ obj.setChainValue(data, "user.name", "Alice");
104
+
105
+ // 객체 변환
106
+ const mapped = obj.map(colors, (key, rgb) => [null, `rgb(${rgb})`]);
107
+ ```
@@ -0,0 +1,30 @@
1
+ # path
2
+
3
+ 경로 유틸리티 네임스페이스. Node.js `path` 모듈 대체 (브라우저 환경 지원). POSIX 스타일 경로(슬래시 `/`)만 지원한다. Windows 백슬래시(`\`)는 지원하지 않는다.
4
+
5
+ ```typescript
6
+ import { path } from "@simplysm/core-common";
7
+ ```
8
+
9
+ ## Functions
10
+
11
+ | Function | Signature | Description |
12
+ |----------|-----------|-------------|
13
+ | `join` | `(...segments: string[]) => string` | 경로 결합 (`path.join` 대체) |
14
+ | `basename` | `(filePath: string, ext?: string) => string` | 파일명 추출 (`path.basename` 대체). ext 지정 시 해당 확장자 제거 |
15
+ | `extname` | `(filePath: string) => string` | 파일 확장자 추출 (`path.extname` 대체). 숨김 파일(`.gitignore`)은 빈 문자열 반환 |
16
+
17
+ ## Usage
18
+
19
+ ```typescript
20
+ import { path } from "@simplysm/core-common";
21
+
22
+ path.join("/foo", "bar", "baz"); // "/foo/bar/baz"
23
+ path.join("/foo/", "/bar/"); // "/foo/bar"
24
+
25
+ path.basename("/foo/bar/file.txt"); // "file.txt"
26
+ path.basename("/foo/bar/file.txt", ".txt"); // "file"
27
+
28
+ path.extname("/foo/bar/file.txt"); // ".txt"
29
+ path.extname("/foo/.gitignore"); // ""
30
+ ```
@@ -0,0 +1,28 @@
1
+ # primitive
2
+
3
+ 원시 타입 변환 유틸리티 네임스페이스.
4
+
5
+ ```typescript
6
+ import { primitive } from "@simplysm/core-common";
7
+ ```
8
+
9
+ ## Functions
10
+
11
+ | Function | Signature | Description |
12
+ |----------|-----------|-------------|
13
+ | `typeStr` | `(value: PrimitiveTypeMap[PrimitiveTypeStr]) => PrimitiveTypeStr` | 값으로부터 `PrimitiveTypeStr` 추론. 지원하지 않는 타입이면 `ArgumentError` 발생 |
14
+
15
+ ## Usage
16
+
17
+ ```typescript
18
+ import { primitive } from "@simplysm/core-common";
19
+
20
+ primitive.typeStr("hello"); // "string"
21
+ primitive.typeStr(123); // "number"
22
+ primitive.typeStr(true); // "boolean"
23
+ primitive.typeStr(new DateTime()); // "DateTime"
24
+ primitive.typeStr(new DateOnly()); // "DateOnly"
25
+ primitive.typeStr(new Time()); // "Time"
26
+ primitive.typeStr(Uuid.generate()); // "Uuid"
27
+ primitive.typeStr(new Uint8Array()); // "Bytes"
28
+ ```