@simplysm/core-common 13.0.69 → 13.0.71

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 (151) hide show
  1. package/README.md +66 -267
  2. package/dist/common.types.d.ts +14 -14
  3. package/dist/errors/argument-error.d.ts +10 -10
  4. package/dist/errors/argument-error.d.ts.map +1 -1
  5. package/dist/errors/argument-error.js +2 -2
  6. package/dist/errors/argument-error.js.map +1 -1
  7. package/dist/errors/not-implemented-error.d.ts +8 -8
  8. package/dist/errors/not-implemented-error.js +2 -2
  9. package/dist/errors/not-implemented-error.js.map +1 -1
  10. package/dist/errors/sd-error.d.ts +10 -10
  11. package/dist/errors/sd-error.d.ts.map +1 -1
  12. package/dist/errors/timeout-error.d.ts +10 -10
  13. package/dist/errors/timeout-error.js +3 -3
  14. package/dist/errors/timeout-error.js.map +1 -1
  15. package/dist/extensions/arr-ext.d.ts +2 -2
  16. package/dist/extensions/arr-ext.helpers.d.ts +8 -8
  17. package/dist/extensions/arr-ext.helpers.js +1 -1
  18. package/dist/extensions/arr-ext.helpers.js.map +1 -1
  19. package/dist/extensions/arr-ext.js +13 -13
  20. package/dist/extensions/arr-ext.js.map +1 -1
  21. package/dist/extensions/arr-ext.types.d.ts +57 -57
  22. package/dist/extensions/arr-ext.types.d.ts.map +1 -1
  23. package/dist/extensions/map-ext.d.ts +16 -16
  24. package/dist/extensions/set-ext.d.ts +11 -11
  25. package/dist/features/debounce-queue.d.ts +17 -15
  26. package/dist/features/debounce-queue.d.ts.map +1 -1
  27. package/dist/features/debounce-queue.js +6 -6
  28. package/dist/features/debounce-queue.js.map +1 -1
  29. package/dist/features/event-emitter.d.ts +20 -20
  30. package/dist/features/event-emitter.js +17 -17
  31. package/dist/features/serial-queue.d.ts +11 -11
  32. package/dist/features/serial-queue.js +5 -5
  33. package/dist/features/serial-queue.js.map +1 -1
  34. package/dist/globals.d.ts +4 -4
  35. package/dist/types/date-only.d.ts +64 -64
  36. package/dist/types/date-only.d.ts.map +1 -1
  37. package/dist/types/date-only.js +63 -63
  38. package/dist/types/date-time.d.ts +37 -37
  39. package/dist/types/date-time.d.ts.map +1 -1
  40. package/dist/types/date-time.js +54 -37
  41. package/dist/types/date-time.js.map +1 -1
  42. package/dist/types/lazy-gc-map.d.ts +26 -26
  43. package/dist/types/lazy-gc-map.d.ts.map +1 -1
  44. package/dist/types/lazy-gc-map.js +26 -26
  45. package/dist/types/lazy-gc-map.js.map +1 -1
  46. package/dist/types/time.d.ts +25 -25
  47. package/dist/types/time.d.ts.map +1 -1
  48. package/dist/types/time.js +25 -25
  49. package/dist/types/time.js.map +1 -1
  50. package/dist/types/uuid.d.ts +11 -11
  51. package/dist/types/uuid.d.ts.map +1 -1
  52. package/dist/types/uuid.js +12 -12
  53. package/dist/types/uuid.js.map +1 -1
  54. package/dist/utils/bytes.d.ts +17 -17
  55. package/dist/utils/bytes.js +4 -4
  56. package/dist/utils/bytes.js.map +1 -1
  57. package/dist/utils/date-format.d.ts +45 -45
  58. package/dist/utils/date-format.js +1 -1
  59. package/dist/utils/date-format.js.map +1 -1
  60. package/dist/utils/error.d.ts +4 -4
  61. package/dist/utils/json.d.ts +17 -17
  62. package/dist/utils/json.js +3 -3
  63. package/dist/utils/json.js.map +1 -1
  64. package/dist/utils/num.d.ts +23 -23
  65. package/dist/utils/obj.d.ts +111 -111
  66. package/dist/utils/obj.d.ts.map +1 -1
  67. package/dist/utils/obj.js +3 -3
  68. package/dist/utils/obj.js.map +1 -1
  69. package/dist/utils/path.d.ts +10 -10
  70. package/dist/utils/primitive.d.ts +5 -5
  71. package/dist/utils/primitive.js +1 -1
  72. package/dist/utils/primitive.js.map +1 -1
  73. package/dist/utils/str.d.ts +46 -46
  74. package/dist/utils/str.d.ts.map +1 -1
  75. package/dist/utils/str.js +5 -5
  76. package/dist/utils/str.js.map +1 -1
  77. package/dist/utils/template-strings.d.ts +26 -26
  78. package/dist/utils/transferable.d.ts +18 -18
  79. package/dist/utils/transferable.js +1 -1
  80. package/dist/utils/transferable.js.map +1 -1
  81. package/dist/utils/wait.d.ts +9 -9
  82. package/dist/utils/xml.d.ts +13 -13
  83. package/dist/utils/xml.d.ts.map +1 -1
  84. package/dist/utils/xml.js +1 -0
  85. package/dist/utils/xml.js.map +1 -1
  86. package/dist/zip/sd-zip.d.ts +22 -22
  87. package/dist/zip/sd-zip.js +16 -16
  88. package/package.json +4 -4
  89. package/src/common.types.ts +17 -17
  90. package/src/errors/argument-error.ts +15 -15
  91. package/src/errors/not-implemented-error.ts +9 -9
  92. package/src/errors/sd-error.ts +12 -12
  93. package/src/errors/timeout-error.ts +12 -12
  94. package/src/extensions/arr-ext.helpers.ts +10 -10
  95. package/src/extensions/arr-ext.ts +57 -57
  96. package/src/extensions/arr-ext.types.ts +59 -59
  97. package/src/extensions/map-ext.ts +16 -16
  98. package/src/extensions/set-ext.ts +11 -11
  99. package/src/features/debounce-queue.ts +21 -19
  100. package/src/features/event-emitter.ts +25 -25
  101. package/src/features/serial-queue.ts +13 -13
  102. package/src/globals.ts +4 -4
  103. package/src/index.ts +1 -1
  104. package/src/types/date-only.ts +83 -83
  105. package/src/types/date-time.ts +64 -44
  106. package/src/types/lazy-gc-map.ts +45 -45
  107. package/src/types/time.ts +34 -34
  108. package/src/types/uuid.ts +17 -17
  109. package/src/utils/bytes.ts +35 -35
  110. package/src/utils/date-format.ts +65 -65
  111. package/src/utils/error.ts +4 -4
  112. package/src/utils/json.ts +39 -39
  113. package/src/utils/num.ts +23 -23
  114. package/src/utils/obj.ts +138 -138
  115. package/src/utils/path.ts +10 -10
  116. package/src/utils/primitive.ts +6 -6
  117. package/src/utils/str.ts +260 -261
  118. package/src/utils/template-strings.ts +29 -29
  119. package/src/utils/transferable.ts +284 -284
  120. package/src/utils/wait.ts +10 -10
  121. package/src/utils/xml.ts +20 -19
  122. package/src/zip/sd-zip.ts +25 -25
  123. package/tests/errors/errors.spec.ts +80 -0
  124. package/tests/extensions/array-extension.spec.ts +796 -0
  125. package/tests/extensions/map-extension.spec.ts +147 -0
  126. package/tests/extensions/set-extension.spec.ts +74 -0
  127. package/tests/types/date-only.spec.ts +638 -0
  128. package/tests/types/date-time.spec.ts +391 -0
  129. package/tests/types/lazy-gc-map.spec.ts +692 -0
  130. package/tests/types/time.spec.ts +559 -0
  131. package/tests/types/uuid.spec.ts +74 -0
  132. package/tests/utils/bytes-utils.spec.ts +230 -0
  133. package/tests/utils/date-format.spec.ts +373 -0
  134. package/tests/utils/debounce-queue.spec.ts +272 -0
  135. package/tests/utils/json.spec.ts +486 -0
  136. package/tests/utils/number.spec.ts +157 -0
  137. package/tests/utils/object.spec.ts +829 -0
  138. package/tests/utils/path.spec.ts +78 -0
  139. package/tests/utils/primitive.spec.ts +43 -0
  140. package/tests/utils/sd-event-emitter.spec.ts +216 -0
  141. package/tests/utils/serial-queue.spec.ts +365 -0
  142. package/tests/utils/string.spec.ts +281 -0
  143. package/tests/utils/template-strings.spec.ts +57 -0
  144. package/tests/utils/transferable.spec.ts +703 -0
  145. package/tests/utils/wait.spec.ts +145 -0
  146. package/tests/utils/xml.spec.ts +146 -0
  147. package/tests/zip/sd-zip.spec.ts +238 -0
  148. package/docs/extensions.md +0 -503
  149. package/docs/features.md +0 -109
  150. package/docs/types.md +0 -486
  151. package/docs/utils.md +0 -780
@@ -2,32 +2,32 @@ import type { Bytes } from "../common.types";
2
2
  import { ArgumentError } from "../errors/argument-error";
3
3
 
4
4
  /**
5
- * Uint8Array 유틸리티 함수 (복잡한 연산만)
5
+ * Uint8Array utility functions (complex operations only)
6
6
  *
7
- * 기능:
8
- * - bytesConcat: 여러 Uint8Array 연결
9
- * - bytesToHex: Uint8Array hex 문자열로 변환
10
- * - bytesFromHex: hex 문자열을 Uint8Array로 변환
11
- * - bytesToBase64: Uint8Array base64 문자열로 변환
12
- * - bytesFromBase64: base64 문자열을 Uint8Array로 변환
7
+ * Features:
8
+ * - bytesConcat: Concatenate multiple Uint8Arrays
9
+ * - bytesToHex: Convert Uint8Array to hex string
10
+ * - bytesFromHex: Convert hex string to Uint8Array
11
+ * - bytesToBase64: Convert Uint8Array to base64 string
12
+ * - bytesFromBase64: Convert base64 string to Uint8Array
13
13
  */
14
14
 
15
- /** hex 변환용 룩업 테이블 (성능 최적화) */
15
+ /** Lookup table for hex conversion (performance optimization) */
16
16
  const hexTable: string[] = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
17
17
 
18
- /** base64 인코딩 테이블 */
18
+ /** Base64 encoding table */
19
19
  const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
20
20
 
21
- /** base64 디코딩 룩업 테이블 (O(1) 조회, 모든 바이트 커버) */
21
+ /** Base64 decoding lookup table (O(1) lookup, covers all byte values) */
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
- * 여러 Uint8Array 연결
29
- * @param arrays 연결할 Uint8Array 배열
30
- * @returns 연결된 Uint8Array
28
+ * Concatenate multiple Uint8Arrays
29
+ * @param arrays Uint8Array array to concatenate
30
+ * @returns New concatenated 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 bytesConcat(arrays: Bytes[]): Bytes {
46
46
  }
47
47
 
48
48
  /**
49
- * hex 문자열로 변환
50
- * @param bytes 변환할 Uint8Array
51
- * @returns 소문자 hex 문자열
49
+ * Convert to hex string
50
+ * @param bytes Uint8Array to convert
51
+ * @returns Lowercase hex string
52
52
  * @example
53
53
  * bytesToHex(new Uint8Array([255, 0, 127]));
54
54
  * // "ff007f"
@@ -63,20 +63,20 @@ export function bytesToHex(bytes: Bytes): string {
63
63
  }
64
64
 
65
65
  /**
66
- * hex 문자열에서 Uint8Array로 변환
67
- * @param hex 변환할 hex 문자열 (소문자/대문자 모두 허용)
68
- * @returns 변환된 Uint8Array
69
- * @throws {ArgumentError} 홀수 길이 또는 유효하지 않은 hex 문자가 포함된 경우
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
70
70
  * @example
71
71
  * bytesFromHex("ff007f");
72
72
  * // Uint8Array([255, 0, 127])
73
73
  */
74
74
  export function bytesFromHex(hex: string): Bytes {
75
75
  if (hex.length % 2 !== 0) {
76
- throw new ArgumentError("hex 문자열은 짝수 길이여야 합니다", { hex });
76
+ throw new ArgumentError("Hex string must have even length", { hex });
77
77
  }
78
78
  if (hex.length > 0 && !/^[0-9a-fA-F]+$/.test(hex)) {
79
- throw new ArgumentError("유효하지 않은 hex 문자가 포함되어 있습니다", { hex });
79
+ throw new ArgumentError("Invalid hex character included", { 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 bytesFromHex(hex: string): Bytes {
86
86
  }
87
87
 
88
88
  /**
89
- * Bytes base64 문자열로 변환
90
- * @param bytes 변환할 Uint8Array
91
- * @returns base64 인코딩된 문자열
89
+ * Convert Bytes to base64 string
90
+ * @param bytes Uint8Array to convert
91
+ * @returns Base64 encoded string
92
92
  * @example
93
93
  * bytesToBase64(new Uint8Array([72, 101, 108, 108, 111]));
94
94
  * // "SGVsbG8="
@@ -113,33 +113,33 @@ export function bytesToBase64(bytes: Bytes): string {
113
113
  }
114
114
 
115
115
  /**
116
- * base64 문자열을 Bytes로 변환
117
- * @param base64 변환할 base64 문자열
118
- * @returns 디코딩된 Uint8Array
119
- * @throws {ArgumentError} 유효하지 않은 base64 문자가 포함된 경우
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
120
120
  * @example
121
121
  * bytesFromBase64("SGVsbG8=");
122
122
  * // Uint8Array([72, 101, 108, 108, 111])
123
123
  */
124
124
  export function bytesFromBase64(base64: string): Bytes {
125
- // 공백 제거 패딩 정규화
125
+ // Remove whitespace and normalize padding
126
126
  const cleanBase64 = base64.replace(/\s/g, "").replace(/=+$/, "");
127
127
 
128
- // 문자열 처리
128
+ // Handle empty string
129
129
  if (cleanBase64.length === 0) {
130
130
  return new Uint8Array(0);
131
131
  }
132
132
 
133
- // 유효성 검사: 문자
133
+ // Validation: characters
134
134
  if (!/^[A-Za-z0-9+/]+$/.test(cleanBase64)) {
135
- throw new ArgumentError("유효하지 않은 base64 문자가 포함되어 있습니다", {
135
+ throw new ArgumentError("Invalid base64 character included", {
136
136
  base64: base64.substring(0, 20),
137
137
  });
138
138
  }
139
139
 
140
- // 유효성 검사: 길이 (패딩 제거 나머지가 1이면 유효하지 않음)
140
+ // Validation: length (remainder of 1 after padding removal is invalid)
141
141
  if (cleanBase64.length % 4 === 1) {
142
- throw new ArgumentError("유효하지 않은 base64 길이입니다", { length: cleanBase64.length });
142
+ throw new ArgumentError("Invalid base64 length", { length: cleanBase64.length });
143
143
  }
144
144
 
145
145
  const len = cleanBase64.length;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * 설정 연도/월/일 정규화 결과
2
+ * Result of year/month/day normalization when setting month
3
3
  */
4
4
  export interface DtNormalizedMonth {
5
5
  year: number;
@@ -8,27 +8,27 @@ export interface DtNormalizedMonth {
8
8
  }
9
9
 
10
10
  /**
11
- * 설정 연도/월/일을 정규화
12
- * - 월이 1-12 범위를 벗어나면 연도를 조정
13
- * - 대상 월의 일수보다 현재 일자가 크면 해당 월의 마지막 날로 조정
11
+ * Normalize year/month/day when setting month
12
+ * - Adjust year if month is outside 1-12 range
13
+ * - Adjust to last day of target month if current day is greater than the number of days in the target month
14
14
  *
15
- * @param year 기준 연도
16
- * @param month 설정할 (1-12 범위 외의 값도 허용)
17
- * @param day 기준 일자
18
- * @returns 정규화된 연도, 월,
15
+ * @param year Base year
16
+ * @param month Month to set (values outside 1-12 range allowed)
17
+ * @param day Base day
18
+ * @returns Normalized year, month, day
19
19
  *
20
20
  * @example
21
21
  * normalizeMonth(2025, 13, 15) // { year: 2026, month: 1, day: 15 }
22
22
  * normalizeMonth(2025, 2, 31) // { year: 2025, month: 2, day: 28 }
23
23
  */
24
24
  export function normalizeMonth(year: number, month: number, day: number): DtNormalizedMonth {
25
- // 오버플로우/언더플로우 정규화
26
- // month 1-12 범위를 벗어나면 연도를 조정
25
+ // Normalize month overflow/underflow
26
+ // Adjust year if month is outside 1-12 range
27
27
  const normalizedYear = year + Math.floor((month - 1) / 12);
28
- // JavaScript % 연산자는 음수에서 음수를 반환하므로 (% 12 + 12) % 12 패턴으로 0-11 범위를 보장 1-12로 변환
28
+ // JavaScript % operator returns negative for negative, so use (% 12 + 12) % 12 pattern to ensure 0-11 range, then convert to 1-12
29
29
  const normalizedMonth = ((((month - 1) % 12) + 12) % 12) + 1;
30
30
 
31
- // 대상 월의 마지막 구하기
31
+ // Get last day of target month
32
32
  const lastDay = new Date(normalizedYear, normalizedMonth, 0).getDate();
33
33
  const normalizedDay = Math.min(day, lastDay);
34
34
 
@@ -36,13 +36,13 @@ export function normalizeMonth(year: number, month: number, day: number): DtNorm
36
36
  }
37
37
 
38
38
  /**
39
- * 12시간제를 24시간제로 변환
40
- * - 오전 12 = 0시, 오후 12 = 12
41
- * - 오전 1-11 = 1-11시, 오후 1-11 = 13-23
39
+ * Convert 12-hour format to 24-hour format
40
+ * - 12:00 AM = 0:00, 12:00 PM = 12:00
41
+ * - 1-11 AM = 1-11, 1-11 PM = 13-23
42
42
  *
43
- * @param rawHour 12시간제 (1-12)
44
- * @param isPM 오후 여부
45
- * @returns 24시간제 (0-23)
43
+ * @param rawHour 12-hour format hour (1-12)
44
+ * @param isPM Whether PM
45
+ * @returns 24-hour format hour (0-23)
46
46
  */
47
47
  export function convert12To24(rawHour: number, isPM: boolean): number {
48
48
  if (rawHour === 12) {
@@ -51,15 +51,15 @@ export function convert12To24(rawHour: number, isPM: boolean): number {
51
51
  return isPM ? rawHour + 12 : rawHour;
52
52
  }
53
53
 
54
- //#region 정규식 캐싱 (모듈 로드 1회만 생성)
54
+ //#region Regex caching (created once at module load)
55
55
 
56
56
  /**
57
- * 포맷 패턴 정규식
57
+ * Format pattern regex
58
58
  *
59
- * 순서 중요:
60
- * dtFormat() 함수에서 패턴(yyyy, MM, dd ) 먼저 처리해야
61
- * 짧은 패턴(y, M, d ) 부분 매칭되는 것을 방지합니다.
62
- * 예: "yyyy" 먼저 처리하지 않으면 "yy" 매칭될 수 있음
59
+ * Order is important:
60
+ * In the dtFormat() function, longer patterns (yyyy, MM, dd, etc.) must be processed first
61
+ * to prevent shorter patterns (y, M, d, etc.) from being partially matched.
62
+ * Example: If "yyyy" is not processed first, "yy" may be matched twice
63
63
  */
64
64
  const patterns = {
65
65
  yyyy: /yyyy/g,
@@ -91,49 +91,49 @@ const weekStrings = ["일", "월", "화", "수", "목", "금", "토"];
91
91
  //#endregion
92
92
 
93
93
  /**
94
- * 포맷 문자열에 따라 날짜/시간을 문자열로 변환한다
94
+ * Convert date/time to string according to format string
95
95
  *
96
- * @param formatString 포맷 문자열
97
- * @param args 날짜/시간 구성 요소
96
+ * @param formatString Format string
97
+ * @param args Date/time components
98
98
  *
99
99
  * @remarks
100
- * C#과 동일한 포맷 문자열을 지원한다:
100
+ * Supports the same format strings as C#:
101
101
  *
102
- * | 포맷 | 설명 | 예시 |
103
- * |------|------|------|
104
- * | yyyy | 4자리 연도 | 2024 |
105
- * | yy | 2자리 연도 | 24 |
106
- * | MM | 0으로 패딩된 | 01~12 |
107
- * | M | | 1~12 |
108
- * | ddd | 요일 (한글) | 일, 월, 화, 수, 목, 금, |
109
- * | dd | 0으로 패딩된 | 01~31 |
110
- * | d | | 1~31 |
111
- * | tt | 오전/오후 | 오전, 오후 |
112
- * | hh | 0으로 패딩된 12시간 | 01~12 |
113
- * | h | 12시간 | 1~12 |
114
- * | HH | 0으로 패딩된 24시간 | 00~23 |
115
- * | H | 24시간 | 0~23 |
116
- * | mm | 0으로 패딩된 | 00~59 |
117
- * | m | | 0~59 |
118
- * | ss | 0으로 패딩된 | 00~59 |
119
- * | s | | 0~59 |
120
- * | fff | 밀리초 (3자리) | 000~999 |
121
- * | ff | 밀리초 (2자리) | 00~99 |
122
- * | f | 밀리초 (1자리) | 0~9 |
123
- * | zzz | 타임존 오프셋 (±HH:mm) | +09:00 |
124
- * | zz | 타임존 오프셋 (±HH) | +09 |
125
- * | z | 타임존 오프셋 (±H) | +9 |
102
+ * | Format | Description | Example |
103
+ * |--------|-------------|---------|
104
+ * | yyyy | 4-digit year | 2024 |
105
+ * | yy | 2-digit year | 24 |
106
+ * | MM | Zero-padded month | 01~12 |
107
+ * | M | Month | 1~12 |
108
+ * | ddd | Day of week | Sun, Mon, Tue, Wed, Thu, Fri, Sat |
109
+ * | dd | Zero-padded day | 01~31 |
110
+ * | d | Day | 1~31 |
111
+ * | tt | AM/PM | AM, PM |
112
+ * | hh | Zero-padded 12-hour | 01~12 |
113
+ * | h | 12-hour | 1~12 |
114
+ * | HH | Zero-padded 24-hour | 00~23 |
115
+ * | H | 24-hour | 0~23 |
116
+ * | mm | Zero-padded minute | 00~59 |
117
+ * | m | Minute | 0~59 |
118
+ * | ss | Zero-padded second | 00~59 |
119
+ * | s | Second | 0~59 |
120
+ * | fff | Milliseconds (3 digits) | 000~999 |
121
+ * | ff | Milliseconds (2 digits) | 00~99 |
122
+ * | f | Milliseconds (1 digit) | 0~9 |
123
+ * | zzz | Timezone offset (±HH:mm) | +09:00 |
124
+ * | zz | Timezone offset (±HH) | +09 |
125
+ * | z | Timezone offset (±H) | +9 |
126
126
  *
127
127
  * @example
128
128
  * ```typescript
129
129
  * formatDate("yyyy-MM-dd", { year: 2024, month: 3, day: 15 });
130
130
  * // "2024-03-15"
131
131
  *
132
- * formatDate("yyyyMd (ddd)", { year: 2024, month: 3, day: 15 });
133
- * // "2024315 ()"
132
+ * formatDate("yyyy-M-d (ddd)", { year: 2024, month: 3, day: 15 });
133
+ * // "2024-3-15 (Fri)"
134
134
  *
135
135
  * formatDate("tt h:mm:ss", { hour: 14, minute: 30, second: 45 });
136
- * // "오후 2:30:45"
136
+ * // "PM 2:30:45"
137
137
  * ```
138
138
  */
139
139
  export function formatDate(
@@ -165,35 +165,35 @@ export function formatDate(
165
165
 
166
166
  let result = formatString;
167
167
 
168
- // 연도
168
+ // Year
169
169
  if (year !== undefined) {
170
170
  const yearStr = year.toString();
171
171
  result = result.replace(patterns.yyyy, yearStr);
172
172
  result = result.replace(patterns.yy, yearStr.substring(2, 4));
173
173
  }
174
174
 
175
- //
175
+ // Month
176
176
  if (month !== undefined) {
177
177
  const monthStr = month.toString();
178
178
  result = result.replace(patterns.MM, monthStr.padStart(2, "0"));
179
179
  result = result.replace(patterns.M, monthStr);
180
180
  }
181
181
 
182
- // 요일
182
+ // Day of week
183
183
  if (week !== undefined) {
184
184
  result = result.replace(patterns.ddd, weekStrings[week]);
185
185
  }
186
186
 
187
- //
187
+ // Day
188
188
  if (day !== undefined) {
189
189
  const dayStr = day.toString();
190
190
  result = result.replace(patterns.dd, dayStr.padStart(2, "0"));
191
191
  result = result.replace(patterns.d, dayStr);
192
192
  }
193
193
 
194
- // 시간
194
+ // Hour
195
195
  if (hour !== undefined) {
196
- result = result.replace(patterns.tt, hour < 12 ? "오전" : "오후");
196
+ result = result.replace(patterns.tt, hour < 12 ? "AM" : "PM");
197
197
 
198
198
  const hour12 = hour % 12 || 12;
199
199
  const hour12Str = hour12.toString();
@@ -205,21 +205,21 @@ export function formatDate(
205
205
  result = result.replace(patterns.H, hourStr);
206
206
  }
207
207
 
208
- //
208
+ // Minute
209
209
  if (minute !== undefined) {
210
210
  const minuteStr = minute.toString();
211
211
  result = result.replace(patterns.mm, minuteStr.padStart(2, "0"));
212
212
  result = result.replace(patterns.m, minuteStr);
213
213
  }
214
214
 
215
- //
215
+ // Second
216
216
  if (second !== undefined) {
217
217
  const secondStr = second.toString();
218
218
  result = result.replace(patterns.ss, secondStr.padStart(2, "0"));
219
219
  result = result.replace(patterns.s, secondStr);
220
220
  }
221
221
 
222
- // 밀리초
222
+ // Millisecond
223
223
  if (millisecond !== undefined) {
224
224
  const msStr = millisecond.toString().padStart(3, "0");
225
225
  result = result.replace(patterns.fff, msStr);
@@ -227,7 +227,7 @@ export function formatDate(
227
227
  result = result.replace(patterns.f, msStr.substring(0, 1));
228
228
  }
229
229
 
230
- // 타임존
230
+ // Timezone
231
231
  if (offsetSign !== undefined && offsetHour !== undefined && offsetMinute !== undefined) {
232
232
  result = result.replace(
233
233
  patterns.zzz,
@@ -1,10 +1,10 @@
1
1
  /**
2
- * unknown 타입의 에러에서 메시지를 추출하는 유틸리티.
2
+ * Utility to extract message from unknown type error.
3
3
  *
4
- * Error 인스턴스이면 message 속성을, 아니면 String 변환을 반환한다.
4
+ * Returns the message property if it's an Error instance, otherwise returns String conversion.
5
5
  *
6
- * @param err - catch 블록의 unknown 에러
7
- * @returns 에러 메시지 문자열
6
+ * @param err - Unknown error from catch block
7
+ * @returns Error message string
8
8
  */
9
9
  export function errorMessage(err: unknown): string {
10
10
  return err instanceof Error ? err.message : String(err);
package/src/utils/json.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
- * JSON 변환 유틸리티
3
- * 커스텀 타입(DateTime, DateOnly, Time, Uuid )을 지원하는 JSON 직렬화/역직렬화
2
+ * JSON conversion utility
3
+ * JSON serialization/deserialization supporting custom types (DateTime, DateOnly, Time, Uuid, etc.)
4
4
  */
5
5
  import { DateTime } from "../types/date-time";
6
6
  import { DateOnly } from "../types/date-only";
@@ -19,19 +19,19 @@ interface TypedObject {
19
19
  //#region stringify
20
20
 
21
21
  /**
22
- * 객체를 JSON 문자열로 직렬화
23
- * DateTime, DateOnly, Time, Uuid, Set, Map, Error, Uint8Array 등 커스텀 타입 지원
22
+ * Serialize object to JSON string
23
+ * Supports custom types like DateTime, DateOnly, Time, Uuid, Set, Map, Error, Uint8Array, etc.
24
24
  *
25
- * @param obj 직렬화할 객체
26
- * @param options 직렬화 옵션
27
- * @param options.space JSON 들여쓰기 (숫자: 공백 수, 문자열: 들여쓰기 문자열)
28
- * @param options.replacer 커스텀 replacer 함수. 기본 타입 변환 전에 호출됨
29
- * @param options.redactBytes true Uint8Array 내용을 "__hidden__"으로 대체 (로깅용). 옵션으로 직렬화한 결과는 jsonParse()로 원본 Uint8Array 복원할 수 없음
25
+ * @param obj Object to serialize
26
+ * @param options Serialization options
27
+ * @param options.space JSON indentation (number: number of spaces, string: indentation string)
28
+ * @param options.replacer Custom replacer function. Called before default type conversion
29
+ * @param options.redactBytes If true, replace Uint8Array contents with "__hidden__" (for logging). Results serialized with this option cannot restore original Uint8Array via jsonParse()
30
30
  *
31
31
  * @remarks
32
- * - 순환 참조가 있는 객체는 TypeError를 던짐
33
- * - 객체의 toJSON 메서드가 있으면 호출하여 결과를 사용함 (Date, DateTime 커스텀 타입 제외)
34
- * - 전역 프로토타입을 수정하지 않아 Worker 환경에서도 안전함
32
+ * - Objects with circular references throw TypeError
33
+ * - If object has toJSON method, it is called and the result is used (except for custom types like Date, DateTime)
34
+ * - Safe in Worker environments as global prototypes are not modified
35
35
  */
36
36
  export function jsonStringify(
37
37
  obj: unknown,
@@ -41,21 +41,21 @@ export function jsonStringify(
41
41
  redactBytes?: boolean;
42
42
  },
43
43
  ): string {
44
- // 순환 참조 감지를 위한 WeakSet
44
+ // WeakSet for circular reference detection
45
45
  const seen = new WeakSet<object>();
46
46
 
47
47
  /**
48
- * 재귀적으로 객체를 순회하며 특수 타입을 __type__ 형식으로 변환
48
+ * Recursively traverse object and convert special types to __type__ format
49
49
  *
50
- * JSON.stringify replacer toJSON 호출 후의 값을 받으므로,
51
- * Date 등의 타입을 올바르게 처리하려면 미리 변환해야 함.
52
- * 방식은 전역 프로토타입을 수정하지 않아 Worker 환경에서도 안전함.
50
+ * JSON.stringify's replacer receives values after toJSON call,
51
+ * so types like Date must be converted beforehand for proper handling.
52
+ * This approach is safe in Worker environments as global prototypes are not modified.
53
53
  *
54
- * @param key 현재 값의 (루트는 undefined)
55
- * @param value 변환할
54
+ * @param key Key of current value (root is undefined)
55
+ * @param value Value to convert
56
56
  */
57
57
  const convertSpecialTypes = (key: string | undefined, value: unknown): unknown => {
58
- // 커스텀 replacer 적용
58
+ // Apply custom replacer
59
59
  const currValue = options?.replacer !== undefined ? options.replacer(key, value) : value;
60
60
 
61
61
  if (currValue instanceof Date) {
@@ -108,9 +108,9 @@ export function jsonStringify(
108
108
  return { __type__: "Uint8Array", data: bytesToHex(currValue) };
109
109
  }
110
110
 
111
- // 배열 처리
111
+ // Array processing
112
112
  if (Array.isArray(currValue)) {
113
- // 순환 참조 감지
113
+ // Detect circular reference
114
114
  if (seen.has(currValue)) {
115
115
  throw new TypeError("Converting circular structure to JSON");
116
116
  }
@@ -120,15 +120,15 @@ export function jsonStringify(
120
120
  return result;
121
121
  }
122
122
 
123
- // 일반 객체 처리
123
+ // Generic object processing
124
124
  if (currValue !== null && typeof currValue === "object") {
125
- // 순환 참조 감지
125
+ // Detect circular reference
126
126
  if (seen.has(currValue)) {
127
127
  throw new TypeError("Converting circular structure to JSON");
128
128
  }
129
129
  seen.add(currValue);
130
130
 
131
- // toJSON 메서드가 있으면 호출 (Date, DateTime 커스텀 타입은 이미 위에서 처리됨)
131
+ // Call toJSON method if present (custom types like Date, DateTime already handled above)
132
132
  if (
133
133
  "toJSON" in currValue &&
134
134
  typeof (currValue as { toJSON: unknown }).toJSON === "function"
@@ -141,7 +141,7 @@ export function jsonStringify(
141
141
  const result: Record<string, unknown> = {};
142
142
  for (const [k, v] of Object.entries(currValue)) {
143
143
  const converted = convertSpecialTypes(k, v);
144
- // undefined JSON에서 제외됨
144
+ // undefined is excluded from JSON
145
145
  if (converted !== undefined) {
146
146
  result[k] = converted;
147
147
  }
@@ -153,8 +153,8 @@ export function jsonStringify(
153
153
  return currValue;
154
154
  };
155
155
 
156
- // 전체 객체를 미리 변환 JSON.stringify 호출
157
- // 방식은 Date.prototype.toJSON 수정하지 않아 동시성 환경에서 안전함
156
+ // Convert entire object first, then call JSON.stringify
157
+ // This approach is safe in concurrent environments as Date.prototype.toJSON is not modified
158
158
  const converted = convertSpecialTypes(undefined, obj);
159
159
  return JSON.stringify(converted, null, options?.space);
160
160
  }
@@ -164,23 +164,23 @@ export function jsonStringify(
164
164
  //#region parse
165
165
 
166
166
  /**
167
- * JSON 문자열을 객체로 역직렬화
168
- * DateTime, DateOnly, Time, Uuid, Set, Map, Error, Uint8Array 등 커스텀 타입 복원
167
+ * Deserialize JSON string to object
168
+ * Restore custom types like DateTime, DateOnly, Time, Uuid, Set, Map, Error, Uint8Array, etc.
169
169
  *
170
170
  * @remarks
171
- * `__type__`과 `data` 키를 가진 객체는 타입 복원에 사용된다.
172
- * 사용자 데이터에 `{ __type__: "Date" | "DateTime" | "DateOnly" | "Time" | "Uuid" | "Set" | "Map" | "Error" | "Uint8Array", data: ... }`
173
- * 형태가 있으면 의도치 않게 타입 변환될 있으므로 주의한다.
171
+ * Objects with `__type__` and `data` keys are used for type restoration.
172
+ * Be careful if user data contains objects with `{ __type__: "Date" | "DateTime" | "DateOnly" | "Time" | "Uuid" | "Set" | "Map" | "Error" | "Uint8Array", data: ... }`
173
+ * format as they may be unintentionally converted to types.
174
174
  *
175
- * @security 개발 모드(`__DEV__`)에서만 에러 메시지에 JSON 문자열 전체가 포함된다.
176
- * 프로덕션 모드에서는 JSON 길이만 포함된다.
175
+ * @security In development mode (`__DEV__`), the error message includes the entire JSON string.
176
+ * In production mode, only JSON length is included.
177
177
  */
178
178
  export function jsonParse<TResult = unknown>(json: string): TResult {
179
179
  try {
180
180
  return objNullToUndefined(
181
181
  JSON.parse(json, (_key, value: unknown) => {
182
182
  if (value != null && typeof value === "object") {
183
- // __type__ 기반 타입 복원
183
+ // Restore types based on __type__ marker
184
184
  if ("__type__" in value && "data" in value) {
185
185
  const typed = value as TypedObject;
186
186
  if (typed.__type__ === "Date" && typeof typed.data === "string") {
@@ -213,7 +213,7 @@ export function jsonParse<TResult = unknown>(json: string): TResult {
213
213
  if (typed.__type__ === "Uint8Array" && typeof typed.data === "string") {
214
214
  if (typed.data === "__hidden__") {
215
215
  throw new SdError(
216
- "redactBytes 옵션으로 직렬화된 Uint8Array는 parse로 복원할 수 없습니다",
216
+ "Uint8Array serialized with redactBytes option cannot be restored via parse",
217
217
  );
218
218
  }
219
219
  return bytesFromHex(typed.data);
@@ -226,9 +226,9 @@ export function jsonParse<TResult = unknown>(json: string): TResult {
226
226
  ) as TResult;
227
227
  } catch (err) {
228
228
  if (env.DEV) {
229
- throw new SdError(err, "JSON 파싱 에러: \n" + json);
229
+ throw new SdError(err, "JSON parsing error: \n" + json);
230
230
  }
231
- throw new SdError(err, `JSON 파싱 에러 (length: ${json.length})`);
231
+ throw new SdError(err, `JSON parsing error (length: ${json.length})`);
232
232
  }
233
233
  }
234
234