@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
@@ -1,20 +1,20 @@
1
1
  import consola from "consola";
2
2
 
3
3
  /**
4
- * Map with automatic expiration feature
5
- * Updates access time in LRU manner, auto-deletes if not accessed for specified time
4
+ * 자동 만료 기능이 있는 Map
5
+ * LRU 방식으로 접근 시간을 갱신하고, 지정된 시간 동안 접근하지 않으면 자동 삭제
6
6
  *
7
- * @note Must call dispose() or use 'using' statement after use.
8
- * Otherwise GC timer continues running and causes memory leak.
7
+ * @note 사용 반드시 dispose() 호출하거나 'using' 문을 사용해야 함.
8
+ * 그렇지 않으면 GC 타이머가 계속 실행되어 메모리 누수 발생.
9
9
  *
10
10
  * @example
11
- * // using statement (recommended)
11
+ * // using (권장)
12
12
  * using map = new LazyGcMap({ gcInterval: 10000, expireTime: 60000 });
13
13
  *
14
- * // Or explicit dispose() call
14
+ * // 또는 명시적 dispose() 호출
15
15
  * const map = new LazyGcMap({ gcInterval: 10000, expireTime: 60000 });
16
16
  * try {
17
- * // ... usage
17
+ * // ... 사용
18
18
  * } finally {
19
19
  * map.dispose();
20
20
  * }
@@ -22,21 +22,21 @@ import consola from "consola";
22
22
  export class LazyGcMap<TKey, TValue> {
23
23
  private static readonly _logger = consola.withTag("LazyGcMap");
24
24
 
25
- // Store actual data and last access time together
25
+ // 실제 데이터와 마지막 접근 시간을 함께 저장
26
26
  private readonly _map = new Map<TKey, { value: TValue; lastAccess: number }>();
27
27
 
28
- // GC timer
28
+ // GC 타이머
29
29
  private _gcTimer?: ReturnType<typeof setInterval>;
30
- // Flag to prevent duplicate GC runs
30
+ // 중복 GC 실행 방지 플래그
31
31
  private _isGcRunning = false;
32
- // Whether dispose() has been called
32
+ // dispose() 호출되었는지 여부
33
33
  private _isDestroyed = false;
34
34
 
35
35
  /**
36
- * @param _options Configuration options
37
- * @param _options.gcInterval GC interval in milliseconds. Default: 1/10 of expireTime (minimum 1000ms)
38
- * @param _options.expireTime Expiration time in milliseconds. Deleted after this time since last access. Example: 60000 (60 seconds)
39
- * @param _options.onExpire Callback called on expiration. Can be async function, errors are logged and continue execution
36
+ * @param _options 설정 옵션
37
+ * @param _options.gcInterval GC 간격 (밀리초). 기본값: expireTime의 1/10 (최소 1000ms)
38
+ * @param _options.expireTime 만료 시간 (밀리초). 마지막 접근 이후 시간이 지나면 삭제됨. 예: 60000 (60)
39
+ * @param _options.onExpire 만료 호출되는 콜백. 비동기 함수 가능, 에러 발생 로그 출력 계속 실행
40
40
  */
41
41
  constructor(
42
42
  private readonly _options: {
@@ -46,48 +46,48 @@ export class LazyGcMap<TKey, TValue> {
46
46
  },
47
47
  ) {}
48
48
 
49
- /** Number of stored items */
49
+ /** 저장된 항목 */
50
50
  get size(): number {
51
51
  return this._map.size;
52
52
  }
53
53
 
54
- /** Check if key exists (does not update access time) */
54
+ /** key 존재 여부 확인 (접근 시간 갱신하지 않음) */
55
55
  has(key: TKey): boolean {
56
56
  if (this._isDestroyed) return false;
57
57
  return this._map.has(key);
58
58
  }
59
59
 
60
- /** Get value (updates access time) */
60
+ /** 조회 (접근 시간 갱신) */
61
61
  get(key: TKey): TValue | undefined {
62
62
  if (this._isDestroyed) return undefined;
63
63
  const item = this._map.get(key);
64
64
  if (item == null) return undefined;
65
65
 
66
- // Update access time on retrieval (LRU)
66
+ // 조회 접근 시간 갱신 (LRU)
67
67
  item.lastAccess = Date.now();
68
68
  return item.value;
69
69
  }
70
70
 
71
- /** Store value (sets access time and starts GC timer) */
71
+ /** 저장 (접근 시간 설정 GC 타이머 시작) */
72
72
  set(key: TKey, value: TValue): void {
73
73
  if (this._isDestroyed) return;
74
74
  this._map.set(key, { value, lastAccess: Date.now() });
75
- // Start GC timer when data is added
75
+ // 데이터 추가 GC 타이머 시작
76
76
  this._startGc();
77
77
  }
78
78
 
79
- /** Delete item (stops GC timer if empty) */
79
+ /** 항목 삭제 (비어있으면 GC 타이머 중지) */
80
80
  delete(key: TKey): boolean {
81
81
  if (this._isDestroyed) return false;
82
82
  const result = this._map.delete(key);
83
- // Stop timer if empty
83
+ // 비어있으면 타이머 중지
84
84
  if (this._map.size === 0) {
85
85
  this._stopGc();
86
86
  }
87
87
  return result;
88
88
  }
89
89
 
90
- /** Clean up instance (stop GC timer and delete data) */
90
+ /** 인스턴스 정리 (GC 타이머 중지 데이터 삭제) */
91
91
  dispose(): void {
92
92
  if (this._isDestroyed) return;
93
93
  this._isDestroyed = true;
@@ -95,13 +95,13 @@ export class LazyGcMap<TKey, TValue> {
95
95
  this._stopGc();
96
96
  }
97
97
 
98
- /** Support for 'using' statement */
98
+ /** 'using' 지원 */
99
99
  [Symbol.dispose](): void {
100
100
  this.dispose();
101
101
  }
102
102
 
103
103
  /**
104
- * Delete all items (instance can still be used)
104
+ * 모든 항목 삭제 (인스턴스는 계속 사용 가능)
105
105
  */
106
106
  clear(): void {
107
107
  if (this._isDestroyed) return;
@@ -110,14 +110,14 @@ export class LazyGcMap<TKey, TValue> {
110
110
  }
111
111
 
112
112
  /**
113
- * Return value for key, or create and store via factory if not found
114
- * @param key Key to look up
115
- * @param factory Function to create value if key not found
116
- * @returns Existing or newly created value
113
+ * key 대한 값을 반환하거나, 없으면 팩토리로 생성하여 저장 반환
114
+ * @param key 조회할 key
115
+ * @param factory key가 없을 값을 생성하는 함수
116
+ * @returns 기존 또는 새로 생성된 값
117
117
  */
118
118
  getOrCreate(key: TKey, factory: () => TValue): TValue {
119
119
  if (this._isDestroyed) {
120
- throw new Error("LazyGcMap has already been disposed.");
120
+ throw new Error("LazyGcMap 이미 dispose되었습니다.");
121
121
  }
122
122
  const item = this._map.get(key);
123
123
  if (item == null) {
@@ -130,7 +130,7 @@ export class LazyGcMap<TKey, TValue> {
130
130
  return item.value;
131
131
  }
132
132
 
133
- /** Iterate over values only (Iterator) */
133
+ /** 값만 순회 (Iterator) */
134
134
  *values(): IterableIterator<TValue> {
135
135
  if (this._isDestroyed) return;
136
136
  for (const item of this._map.values()) {
@@ -138,13 +138,13 @@ export class LazyGcMap<TKey, TValue> {
138
138
  }
139
139
  }
140
140
 
141
- /** Iterate over keys only (Iterator) */
141
+ /** key만 순회 (Iterator) */
142
142
  *keys(): IterableIterator<TKey> {
143
143
  if (this._isDestroyed) return;
144
144
  yield* this._map.keys();
145
145
  }
146
146
 
147
- /** Iterate over entries (Iterator) */
147
+ /** 엔트리 순회 (Iterator) */
148
148
  *entries(): IterableIterator<[TKey, TValue]> {
149
149
  if (this._isDestroyed) return;
150
150
  for (const [key, item] of this._map.entries()) {
@@ -165,14 +165,14 @@ export class LazyGcMap<TKey, TValue> {
165
165
  }
166
166
 
167
167
  private async _runGc(): Promise<void> {
168
- // Skip if already running (prevent duplicate runs when onExpire callback takes time)
168
+ // 이미 실행 중이면 건너뜀 (onExpire 콜백이 오래 걸릴 중복 실행 방지)
169
169
  if (this._isGcRunning) return;
170
170
  this._isGcRunning = true;
171
171
 
172
172
  try {
173
173
  const now = Date.now();
174
174
 
175
- // 1. Collect expired items (before deletion)
175
+ // 1. 만료된 항목 수집 (삭제 )
176
176
  const expiredEntries: { key: TKey; item: { value: TValue; lastAccess: number } }[] = [];
177
177
  for (const [key, item] of this._map) {
178
178
  if (now - item.lastAccess > this._options.expireTime) {
@@ -180,33 +180,33 @@ export class LazyGcMap<TKey, TValue> {
180
180
  }
181
181
  }
182
182
 
183
- // 2. Run callback then delete each item
183
+ // 2. 항목에 대해 콜백 실행 후 삭제
184
184
  for (const { key, item } of expiredEntries) {
185
- // Check current state before callback (skip if already replaced or deleted)
185
+ // 콜백 현재 상태 확인 (이미 교체되었거나 삭제된 경우 건너뜀)
186
186
  const currentItem = this._map.get(key);
187
187
  if (currentItem !== item) {
188
188
  continue;
189
189
  }
190
190
 
191
- // Run expiration callback
191
+ // 만료 콜백 실행
192
192
  if (this._options.onExpire != null) {
193
193
  try {
194
194
  await this._options.onExpire(key, item.value);
195
195
  } catch (err) {
196
- LazyGcMap._logger.error("onExpire callback error", err);
196
+ LazyGcMap._logger.error("onExpire 콜백 오류", err);
197
197
  }
198
198
  }
199
199
 
200
- // Check if item was re-registered after callback
201
- // Scenario: onExpire callback calls set() with same key,
202
- // we should not delete newly registered item. If item reference is same, not re-registered, so delete.
200
+ // 콜백 항목이 다시 등록되었는지 확인
201
+ // 시나리오: onExpire 콜백이 같은 key로 set() 호출하면,
202
+ // 새로 등록된 항목을 삭제하면 됨. 항목 참조가 같으면 재등록되지 않은 것이므로 삭제.
203
203
  const afterItem = this._map.get(key);
204
204
  if (afterItem === item) {
205
205
  this._map.delete(key);
206
206
  }
207
207
  }
208
208
 
209
- // Stop GC if empty after cleanup
209
+ // 정리 비어있으면 GC 중지
210
210
  if (this._map.size === 0) {
211
211
  this._stopGc();
212
212
  }
package/src/types/time.ts CHANGED
@@ -2,10 +2,10 @@ import { ArgumentError } from "../errors/argument-error";
2
2
  import { convert12To24, format } from "../utils/date-format";
3
3
 
4
4
  /**
5
- * Time class (without date: HH:mm:ss.fff, immutable)
5
+ * 시간 클래스 (날짜 제외: HH:mm:ss.fff, 불변)
6
6
  *
7
- * An immutable class that stores only time without date information.
8
- * Values exceeding 24 hours or negative values are automatically normalized.
7
+ * 날짜 정보 없이 시간만 저장하는 불변 클래스.
8
+ * 24시간을 초과하거나 음수인 값은 자동으로 정규화됨.
9
9
  *
10
10
  * @example
11
11
  * const now = new Time();
@@ -17,13 +17,13 @@ export class Time {
17
17
 
18
18
  private readonly _tick: number;
19
19
 
20
- /** Create with current time */
20
+ /** 현재 시간으로 생성 */
21
21
  constructor();
22
- /** Create with hour, minute, second, millisecond */
22
+ /** 시, 분, 초, 밀리초로 생성 */
23
23
  constructor(hour: number, minute: number, second?: number, millisecond?: number);
24
- /** Create from tick (millisecond) */
24
+ /** tick (밀리초)으로 생성 */
25
25
  constructor(tick: number);
26
- /** Create by extracting time part only from Date object */
26
+ /** Date 객체에서 시간 부분만 추출하여 생성 */
27
27
  constructor(date: Date);
28
28
  constructor(arg1?: number | Date, arg2?: number, arg3?: number, arg4?: number) {
29
29
  if (arg1 === undefined) {
@@ -55,11 +55,11 @@ export class Time {
55
55
  }
56
56
 
57
57
  /**
58
- * Parse a string to create Time instance
58
+ * 문자열을 파싱하여 Time 인스턴스 생성
59
59
  *
60
- * @param str Time string
61
- * @returns Parsed Time instance
62
- * @throws ArgumentError If unsupported format
60
+ * @param str 시간 문자열
61
+ * @returns 파싱된 Time 인스턴스
62
+ * @throws ArgumentError 지원하지 않는 형식인 경우
63
63
  *
64
64
  * @example
65
65
  * Time.parse("10:30:00") // HH:mm:ss
@@ -91,8 +91,8 @@ export class Time {
91
91
  );
92
92
  }
93
93
 
94
- // ISO 8601 format (e.g., 2025-01-15T10:30:00.123Z, 2025-01-15T10:30:00+09:00)
95
- // Use Date object to handle timezone conversion
94
+ // ISO 8601 형식 (예: 2025-01-15T10:30:00.123Z, 2025-01-15T10:30:00+09:00)
95
+ // 타임존 변환 처리를 위해 Date 객체 사용
96
96
  const isoMatch = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.exec(str);
97
97
  if (isoMatch != null) {
98
98
  const date = new Date(str);
@@ -107,12 +107,12 @@ export class Time {
107
107
  }
108
108
 
109
109
  throw new ArgumentError(
110
- `Failed to parse time format. Supported formats: 'HH:mm:ss', 'HH:mm:ss.fff', 'AM/PM HH:mm:ss', ISO 8601`,
110
+ `시간 형식 파싱 실패. 지원 형식: 'HH:mm:ss', 'HH:mm:ss.fff', 'AM/PM HH:mm:ss', ISO 8601`,
111
111
  { input: str },
112
112
  );
113
113
  }
114
114
 
115
- //#region Getters (read-only)
115
+ //#region Getters (읽기 전용)
116
116
 
117
117
  get hour(): number {
118
118
  return Math.floor(this._tick / (60 * 60 * 1000));
@@ -134,61 +134,61 @@ export class Time {
134
134
  return this._tick;
135
135
  }
136
136
 
137
- /** Whether time is set correctly */
137
+ /** 시간이 올바르게 설정되었는지 여부 */
138
138
  get isValid(): boolean {
139
139
  return !Number.isNaN(this._tick);
140
140
  }
141
141
 
142
142
  //#endregion
143
143
 
144
- //#region Immutable transformation methods (returns new instance)
144
+ //#region 불변 변환 메서드 ( 인스턴스 반환)
145
145
 
146
- /** Return new instance with specified hour */
146
+ /** 지정된 시로 인스턴스 반환 */
147
147
  setHour(hour: number): Time {
148
148
  return new Time(hour, this.minute, this.second, this.millisecond);
149
149
  }
150
150
 
151
- /** Return new instance with specified minute */
151
+ /** 지정된 분으로 인스턴스 반환 */
152
152
  setMinute(minute: number): Time {
153
153
  return new Time(this.hour, minute, this.second, this.millisecond);
154
154
  }
155
155
 
156
- /** Return new instance with specified second */
156
+ /** 지정된 초로 인스턴스 반환 */
157
157
  setSecond(second: number): Time {
158
158
  return new Time(this.hour, this.minute, second, this.millisecond);
159
159
  }
160
160
 
161
- /** Return new instance with specified millisecond */
161
+ /** 지정된 밀리초로 인스턴스 반환 */
162
162
  setMillisecond(millisecond: number): Time {
163
163
  return new Time(this.hour, this.minute, this.second, millisecond);
164
164
  }
165
165
 
166
166
  //#endregion
167
167
 
168
- //#region Arithmetic methods (returns new instance)
168
+ //#region 산술 메서드 ( 인스턴스 반환)
169
169
 
170
- /** Return new instance with specified hours added (24-hour wraparound) */
170
+ /** 지정된 시간을 더한 인스턴스 반환 (24시간 순환) */
171
171
  addHours(hours: number): Time {
172
172
  let newTick = (this._tick + hours * 60 * 60 * 1000) % Time.MS_PER_DAY;
173
173
  if (newTick < 0) newTick += Time.MS_PER_DAY;
174
174
  return new Time(newTick);
175
175
  }
176
176
 
177
- /** Return new instance with specified minutes added (24-hour wraparound) */
177
+ /** 지정된 분을 더한 인스턴스 반환 (24시간 순환) */
178
178
  addMinutes(minutes: number): Time {
179
179
  let newTick = (this._tick + minutes * 60 * 1000) % Time.MS_PER_DAY;
180
180
  if (newTick < 0) newTick += Time.MS_PER_DAY;
181
181
  return new Time(newTick);
182
182
  }
183
183
 
184
- /** Return new instance with specified seconds added (24-hour wraparound) */
184
+ /** 지정된 초를 더한 인스턴스 반환 (24시간 순환) */
185
185
  addSeconds(seconds: number): Time {
186
186
  let newTick = (this._tick + seconds * 1000) % Time.MS_PER_DAY;
187
187
  if (newTick < 0) newTick += Time.MS_PER_DAY;
188
188
  return new Time(newTick);
189
189
  }
190
190
 
191
- /** Return new instance with specified milliseconds added (24-hour wraparound) */
191
+ /** 지정된 밀리초를 더한 인스턴스 반환 (24시간 순환) */
192
192
  addMilliseconds(milliseconds: number): Time {
193
193
  let newTick = (this._tick + milliseconds) % Time.MS_PER_DAY;
194
194
  if (newTick < 0) newTick += Time.MS_PER_DAY;
@@ -200,9 +200,9 @@ export class Time {
200
200
  //#region Formatting
201
201
 
202
202
  /**
203
- * Convert to string with specified format
204
- * @param format Format string
205
- * @see dtFormat for supported format strings
203
+ * 지정된 형식으로 문자열 변환
204
+ * @param format 형식 문자열
205
+ * @see dtFormat 지원되는 형식 문자열 참조
206
206
  */
207
207
  toFormatString(formatStr: string): string {
208
208
  return format(formatStr, {
package/src/types/uuid.ts CHANGED
@@ -2,16 +2,16 @@ import type { Bytes } from "../common.types";
2
2
  import { ArgumentError } from "../errors/argument-error";
3
3
 
4
4
  /**
5
- * UUID v4 class
5
+ * UUID v4 클래스
6
6
  *
7
- * Generates cryptographically secure UUIDs based on crypto.getRandomValues. (Chrome 79+, Node.js compatible)
7
+ * crypto.getRandomValues 기반으로 암호학적으로 안전한 UUID를 생성. (Chrome 79+, Node.js 호환)
8
8
  *
9
9
  * @example
10
10
  * const id = Uuid.generate();
11
11
  * const fromStr = new Uuid("550e8400-e29b-41d4-a716-446655440000");
12
12
  */
13
13
  export class Uuid {
14
- // Pre-calculate hex strings for 0x00 ~ 0xFF (256 entries)
14
+ // 0x00 ~ 0xFF에 대한 hex 문자열 사전 계산 (256 항목)
15
15
  private static readonly _hexTable: string[] = Array.from({ length: 256 }, (_, i) =>
16
16
  i.toString(16).padStart(2, "0"),
17
17
  );
@@ -19,7 +19,7 @@ export class Uuid {
19
19
  private static readonly _uuidRegex =
20
20
  /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
21
21
 
22
- /** Convert 16-byte array to UUID string */
22
+ /** 16바이트 배열을 UUID 문자열로 변환 */
23
23
  private static _bytesToUuidStr(bytes: Uint8Array): string {
24
24
  const h = Uuid._hexTable;
25
25
  return (
@@ -46,12 +46,12 @@ export class Uuid {
46
46
  );
47
47
  }
48
48
 
49
- /** Create new UUID v4 instance */
49
+ /** UUID v4 인스턴스 생성 */
50
50
  static generate(): Uuid {
51
51
  const bytes = new Uint8Array(16);
52
52
  crypto.getRandomValues(bytes);
53
53
 
54
- // Set UUID v4 bits
54
+ // UUID v4 비트 설정
55
55
  bytes[6] = (bytes[6] & 0x0f) | 0x40;
56
56
  bytes[8] = (bytes[8] & 0x3f) | 0x80;
57
57
 
@@ -59,13 +59,13 @@ export class Uuid {
59
59
  }
60
60
 
61
61
  /**
62
- * Create UUID from 16-byte Uint8Array
63
- * @param bytes 16-byte array
64
- * @throws {ArgumentError} If byte size is not 16
62
+ * 16바이트 Uint8Array로 UUID 생성
63
+ * @param bytes 16바이트 배열
64
+ * @throws {ArgumentError} 바이트 크기가 16이 아닌 경우
65
65
  */
66
66
  static fromBytes(bytes: Bytes): Uuid {
67
67
  if (bytes.length !== 16) {
68
- throw new ArgumentError("UUID byte size must be 16.", { length: bytes.length });
68
+ throw new ArgumentError("UUID 바이트 크기는 16이어야 합니다.", { length: bytes.length });
69
69
  }
70
70
 
71
71
  return new Uuid(Uuid._bytesToUuidStr(bytes));
@@ -74,22 +74,22 @@ export class Uuid {
74
74
  private readonly _uuid: string;
75
75
 
76
76
  /**
77
- * @param uuid UUID string (format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
78
- * @throws {ArgumentError} If format is invalid
77
+ * @param uuid UUID 문자열 (형식: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
78
+ * @throws {ArgumentError} 형식이 유효하지 않은 경우
79
79
  */
80
80
  constructor(uuid: string) {
81
81
  if (!Uuid._uuidRegex.test(uuid)) {
82
- throw new ArgumentError("Invalid UUID format.", { uuid });
82
+ throw new ArgumentError("유효하지 않은 UUID 형식입니다.", { uuid });
83
83
  }
84
84
  this._uuid = uuid;
85
85
  }
86
86
 
87
- /** Convert UUID to string */
87
+ /** UUID 문자열로 변환 */
88
88
  toString(): string {
89
89
  return this._uuid;
90
90
  }
91
91
 
92
- /** Convert UUID to 16-byte Uint8Array */
92
+ /** UUID 16바이트 Uint8Array 변환 */
93
93
  toBytes(): Bytes {
94
94
  const u = this._uuid;
95
95
  // UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (8-4-4-4-12)
@@ -2,32 +2,32 @@ import type { Bytes } from "../common.types";
2
2
  import { ArgumentError } from "../errors/argument-error";
3
3
 
4
4
  /**
5
- * Uint8Array utility functions (complex operations only)
5
+ * Uint8Array 유틸리티 함수 (복잡한 연산만)
6
6
  *
7
- * Features:
8
- * - concat: Concatenate multiple Uint8Arrays
9
- * - toHex: Convert Uint8Array to hex string
10
- * - fromHex: Convert hex string to Uint8Array
11
- * - toBase64: Convert Uint8Array to base64 string
12
- * - fromBase64: Convert base64 string to Uint8Array
7
+ * 기능:
8
+ * - concat: 여러 Uint8Array 결합
9
+ * - toHex: Uint8Array hex 문자열로 변환
10
+ * - fromHex: hex 문자열을 Uint8Array로 변환
11
+ * - toBase64: Uint8Array base64 문자열로 변환
12
+ * - fromBase64: base64 문자열을 Uint8Array로 변환
13
13
  */
14
14
 
15
- /** Lookup table for hex conversion (performance optimization) */
15
+ /** hex 변환용 조회 테이블 (성능 최적화) */
16
16
  const hexTable: string[] = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
17
17
 
18
- /** Base64 encoding table */
18
+ /** Base64 인코딩 테이블 */
19
19
  const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
20
20
 
21
- /** Base64 decoding lookup table (O(1) lookup, covers all byte values) */
21
+ /** Base64 디코딩 조회 테이블 (O(1) 조회, 모든 바이트 포함) */
22
22
  const BASE64_LOOKUP: number[] = Array.from({ length: 256 }, (_, i) => {
23
23
  const idx = BASE64_CHARS.indexOf(String.fromCharCode(i));
24
24
  return idx === -1 ? 0 : idx;
25
25
  });
26
26
 
27
27
  /**
28
- * Concatenate multiple Uint8Arrays
29
- * @param arrays Uint8Array array to concatenate
30
- * @returns New concatenated Uint8Array
28
+ * 여러 Uint8Array 결합
29
+ * @param arrays 결합할 Uint8Array 배열
30
+ * @returns 결합된 Uint8Array
31
31
  * @example
32
32
  * const a = new Uint8Array([1, 2]);
33
33
  * const b = new Uint8Array([3, 4]);
@@ -46,9 +46,9 @@ export function concat(arrays: Bytes[]): Bytes {
46
46
  }
47
47
 
48
48
  /**
49
- * Convert to hex string
50
- * @param bytes Uint8Array to convert
51
- * @returns Lowercase hex string
49
+ * hex 문자열로 변환
50
+ * @param bytes 변환할 Uint8Array
51
+ * @returns 소문자 hex 문자열
52
52
  * @example
53
53
  * toHex(new Uint8Array([255, 0, 127]));
54
54
  * // "ff007f"
@@ -63,20 +63,20 @@ export function toHex(bytes: Bytes): string {
63
63
  }
64
64
 
65
65
  /**
66
- * Convert from hex string to Uint8Array
67
- * @param hex Hex string to convert (lowercase and uppercase allowed)
68
- * @returns Converted Uint8Array
69
- * @throws {ArgumentError} If odd length or invalid hex characters are present
66
+ * hex 문자열을 Uint8Array로 변환
67
+ * @param hex 변환할 hex 문자열 (대소문자 허용)
68
+ * @returns 변환된 Uint8Array
69
+ * @throws {ArgumentError} 홀수 길이이거나 유효하지 않은 hex 문자가 포함된 경우
70
70
  * @example
71
71
  * fromHex("ff007f");
72
72
  * // Uint8Array([255, 0, 127])
73
73
  */
74
74
  export function fromHex(hex: string): Bytes {
75
75
  if (hex.length % 2 !== 0) {
76
- throw new ArgumentError("Hex string must have even length", { hex });
76
+ throw new ArgumentError("hex 문자열은 짝수 길이여야 합니다", { hex });
77
77
  }
78
78
  if (hex.length > 0 && !/^[0-9a-fA-F]+$/.test(hex)) {
79
- throw new ArgumentError("Invalid hex character included", { hex });
79
+ throw new ArgumentError("유효하지 않은 hex 문자가 포함되어 있습니다", { hex });
80
80
  }
81
81
  const bytes = new Uint8Array(hex.length / 2);
82
82
  for (let i = 0; i < bytes.length; i++) {
@@ -86,9 +86,9 @@ export function fromHex(hex: string): Bytes {
86
86
  }
87
87
 
88
88
  /**
89
- * Convert Bytes to base64 string
90
- * @param bytes Uint8Array to convert
91
- * @returns Base64 encoded string
89
+ * Bytes base64 문자열로 변환
90
+ * @param bytes 변환할 Uint8Array
91
+ * @returns Base64 인코딩된 문자열
92
92
  * @example
93
93
  * toBase64(new Uint8Array([72, 101, 108, 108, 111]));
94
94
  * // "SGVsbG8="
@@ -113,33 +113,33 @@ export function toBase64(bytes: Bytes): string {
113
113
  }
114
114
 
115
115
  /**
116
- * Convert base64 string to Bytes
117
- * @param base64 Base64 string to convert
118
- * @returns Decoded Uint8Array
119
- * @throws {ArgumentError} If invalid base64 character is present
116
+ * base64 문자열을 Bytes로 변환
117
+ * @param base64 변환할 base64 문자열
118
+ * @returns 디코딩된 Uint8Array
119
+ * @throws {ArgumentError} 유효하지 않은 base64 문자가 포함된 경우
120
120
  * @example
121
121
  * fromBase64("SGVsbG8=");
122
122
  * // Uint8Array([72, 101, 108, 108, 111])
123
123
  */
124
124
  export function fromBase64(base64: string): Bytes {
125
- // Remove whitespace and normalize padding
125
+ // 공백 제거 패딩 정규화
126
126
  const cleanBase64 = base64.replace(/\s/g, "").replace(/=+$/, "");
127
127
 
128
- // Handle empty string
128
+ // 문자열 처리
129
129
  if (cleanBase64.length === 0) {
130
130
  return new Uint8Array(0);
131
131
  }
132
132
 
133
- // Validation: characters
133
+ // 유효성 검사: 문자
134
134
  if (!/^[A-Za-z0-9+/]+$/.test(cleanBase64)) {
135
- throw new ArgumentError("Invalid base64 character included", {
135
+ throw new ArgumentError("유효하지 않은 base64 문자가 포함되어 있습니다", {
136
136
  base64: base64.substring(0, 20),
137
137
  });
138
138
  }
139
139
 
140
- // Validation: length (remainder of 1 after padding removal is invalid)
140
+ // 유효성 검사: 길이 (패딩 제거 나머지가 1이면 유효하지 않음)
141
141
  if (cleanBase64.length % 4 === 1) {
142
- throw new ArgumentError("Invalid base64 length", { length: cleanBase64.length });
142
+ throw new ArgumentError("유효하지 않은 base64 길이입니다", { length: cleanBase64.length });
143
143
  }
144
144
 
145
145
  const len = cleanBase64.length;