@simplysm/core-common 13.0.28 → 13.0.29

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 (67) hide show
  1. package/dist/errors/sd-error.d.ts.map +1 -1
  2. package/dist/errors/sd-error.js +4 -1
  3. package/dist/errors/sd-error.js.map +1 -1
  4. package/dist/errors/timeout-error.d.ts.map +1 -1
  5. package/dist/errors/timeout-error.js.map +1 -1
  6. package/dist/extensions/arr-ext.d.ts +1 -1
  7. package/dist/extensions/arr-ext.d.ts.map +1 -1
  8. package/dist/extensions/arr-ext.helpers.d.ts.map +1 -1
  9. package/dist/extensions/arr-ext.helpers.js +4 -1
  10. package/dist/extensions/arr-ext.helpers.js.map +1 -1
  11. package/dist/extensions/arr-ext.js +15 -5
  12. package/dist/extensions/arr-ext.js.map +1 -1
  13. package/dist/extensions/arr-ext.types.d.ts.map +1 -1
  14. package/dist/features/event-emitter.d.ts.map +1 -1
  15. package/dist/features/event-emitter.js.map +1 -1
  16. package/dist/types/date-only.d.ts.map +1 -1
  17. package/dist/types/date-only.js +15 -5
  18. package/dist/types/date-only.js.map +1 -1
  19. package/dist/types/date-time.d.ts.map +1 -1
  20. package/dist/types/date-time.js +69 -9
  21. package/dist/types/date-time.js.map +1 -1
  22. package/dist/types/time.d.ts.map +1 -1
  23. package/dist/types/time.js +12 -2
  24. package/dist/types/time.js.map +1 -1
  25. package/dist/types/uuid.d.ts.map +1 -1
  26. package/dist/types/uuid.js +4 -1
  27. package/dist/types/uuid.js.map +1 -1
  28. package/dist/utils/bytes.d.ts.map +1 -1
  29. package/dist/utils/bytes.js +3 -1
  30. package/dist/utils/bytes.js.map +1 -1
  31. package/dist/utils/date-format.d.ts.map +1 -1
  32. package/dist/utils/date-format.js.map +1 -1
  33. package/dist/utils/json.d.ts.map +1 -1
  34. package/dist/utils/json.js +3 -1
  35. package/dist/utils/json.js.map +1 -1
  36. package/dist/utils/num.d.ts.map +1 -1
  37. package/dist/utils/num.js.map +1 -1
  38. package/dist/utils/obj.d.ts.map +1 -1
  39. package/dist/utils/obj.js +19 -5
  40. package/dist/utils/obj.js.map +1 -1
  41. package/dist/utils/str.d.ts.map +1 -1
  42. package/dist/utils/str.js.map +1 -1
  43. package/dist/utils/transferable.d.ts.map +1 -1
  44. package/dist/utils/transferable.js +18 -4
  45. package/dist/utils/transferable.js.map +1 -1
  46. package/dist/zip/sd-zip.d.ts.map +1 -1
  47. package/dist/zip/sd-zip.js +7 -1
  48. package/dist/zip/sd-zip.js.map +1 -1
  49. package/package.json +2 -2
  50. package/src/errors/sd-error.ts +11 -2
  51. package/src/errors/timeout-error.ts +3 -1
  52. package/src/extensions/arr-ext.helpers.ts +4 -1
  53. package/src/extensions/arr-ext.ts +48 -15
  54. package/src/extensions/arr-ext.types.ts +26 -8
  55. package/src/features/event-emitter.ts +7 -2
  56. package/src/types/date-only.ts +19 -6
  57. package/src/types/date-time.ts +70 -9
  58. package/src/types/time.ts +14 -3
  59. package/src/types/uuid.ts +5 -2
  60. package/src/utils/bytes.ts +3 -1
  61. package/src/utils/date-format.ts +4 -2
  62. package/src/utils/json.ts +7 -2
  63. package/src/utils/num.ts +8 -2
  64. package/src/utils/obj.ts +44 -11
  65. package/src/utils/str.ts +13 -4
  66. package/src/utils/transferable.ts +20 -5
  67. package/src/zip/sd-zip.ts +13 -3
@@ -246,7 +246,10 @@ const arrayReadonlyExtensions: ReadonlyArrayExt<any> & ThisType<any[]> = {
246
246
  return result;
247
247
  },
248
248
 
249
- toMapValues<T, K, V>(keySelector: (item: T, index: number) => K, valueSelector: (items: T[]) => V): Map<K, V | T> {
249
+ toMapValues<T, K, V>(
250
+ keySelector: (item: T, index: number) => K,
251
+ valueSelector: (items: T[]) => V,
252
+ ): Map<K, V | T> {
250
253
  const itemsMap = new Map<K, T[]>();
251
254
 
252
255
  for (let i = 0; i < this.length; i++) {
@@ -304,7 +307,9 @@ const arrayReadonlyExtensions: ReadonlyArrayExt<any> & ThisType<any[]> = {
304
307
  return fn(rootItems);
305
308
  },
306
309
 
307
- distinct<T>(options?: boolean | { matchAddress?: boolean; keyFn?: (item: T) => string | number }): T[] {
310
+ distinct<T>(
311
+ options?: boolean | { matchAddress?: boolean; keyFn?: (item: T) => string | number },
312
+ ): T[] {
308
313
  // 옵션 정규화
309
314
  const opts = typeof options === "boolean" ? { matchAddress: options } : (options ?? {});
310
315
 
@@ -367,7 +372,9 @@ const arrayReadonlyExtensions: ReadonlyArrayExt<any> & ThisType<any[]> = {
367
372
  return result;
368
373
  },
369
374
 
370
- orderBy<T>(selector?: (item: T) => string | number | DateTime | DateOnly | Time | undefined): T[] {
375
+ orderBy<T>(
376
+ selector?: (item: T) => string | number | DateTime | DateOnly | Time | undefined,
377
+ ): T[] {
371
378
  return [...this].sort((p, n) => {
372
379
  const pp = selector == null ? p : selector(p);
373
380
  const pn = selector == null ? n : selector(n);
@@ -375,7 +382,9 @@ const arrayReadonlyExtensions: ReadonlyArrayExt<any> & ThisType<any[]> = {
375
382
  });
376
383
  },
377
384
 
378
- orderByDesc<T>(selector?: (item: T) => string | number | DateTime | DateOnly | Time | undefined): T[] {
385
+ orderByDesc<T>(
386
+ selector?: (item: T) => string | number | DateTime | DateOnly | Time | undefined,
387
+ ): T[] {
379
388
  return [...this].sort((p, n) => {
380
389
  const pp = selector == null ? p : selector(p);
381
390
  const pn = selector == null ? n : selector(n);
@@ -403,7 +412,9 @@ const arrayReadonlyExtensions: ReadonlyArrayExt<any> & ThisType<any[]> = {
403
412
 
404
413
  if (keyIndexedTarget) {
405
414
  for (const targetItem of uncheckedTarget) {
406
- const keyStr = JSON.stringify(options!.keys!.map((k) => (targetItem as Record<string, unknown>)[k]));
415
+ const keyStr = JSON.stringify(
416
+ options!.keys!.map((k) => (targetItem as Record<string, unknown>)[k]),
417
+ );
407
418
  const arr = keyIndexedTarget.get(keyStr);
408
419
  if (arr) {
409
420
  arr.push(targetItem);
@@ -429,7 +440,9 @@ const arrayReadonlyExtensions: ReadonlyArrayExt<any> & ThisType<any[]> = {
429
440
 
430
441
  // 전체 일치가 없고 keys 옵션이 있으면 Map에서 O(1) 조회
431
442
  if (sameTarget === undefined && keyIndexedTarget) {
432
- const sourceKeyStr = JSON.stringify(options!.keys!.map((k) => (sourceItem as Record<string, unknown>)[k]));
443
+ const sourceKeyStr = JSON.stringify(
444
+ options!.keys!.map((k) => (sourceItem as Record<string, unknown>)[k]),
445
+ );
433
446
  const candidates = keyIndexedTarget.get(sourceKeyStr);
434
447
  if (candidates && candidates.length > 0) {
435
448
  // uncheckedTargetSet에서 O(1) 조회로 아직 남아있는 첫 번째 항목 선택
@@ -467,13 +480,16 @@ const arrayReadonlyExtensions: ReadonlyArrayExt<any> & ThisType<any[]> = {
467
480
  orgItems instanceof Map
468
481
  ? orgItems
469
482
  : orgItems.toMap((orgItem) =>
470
- typeof keyPropNameOrFn === "function" ? keyPropNameOrFn(orgItem) : orgItem[keyPropNameOrFn],
483
+ typeof keyPropNameOrFn === "function"
484
+ ? keyPropNameOrFn(orgItem)
485
+ : orgItem[keyPropNameOrFn],
471
486
  );
472
487
  const includeSame = options?.includeSame ?? false;
473
488
 
474
489
  const diffs: ArrayDiffs2Result<T>[] = [];
475
490
  for (const item of this) {
476
- const keyValue = typeof keyPropNameOrFn === "function" ? keyPropNameOrFn(item) : item[keyPropNameOrFn];
491
+ const keyValue =
492
+ typeof keyPropNameOrFn === "function" ? keyPropNameOrFn(item) : item[keyPropNameOrFn];
477
493
  if (keyValue == null) {
478
494
  diffs.push({ type: "create", item, orgItem: undefined });
479
495
  continue;
@@ -542,7 +558,9 @@ const arrayReadonlyExtensions: ReadonlyArrayExt<any> & ThisType<any[]> = {
542
558
  for (let i = 0; i < this.length; i++) {
543
559
  const item = selector !== undefined ? selector(this[i], i) : this[i];
544
560
  if (typeof item !== "number") {
545
- throw new ArgumentError("sum 은 number 에 대해서만 사용할 수 있습니다.", { type: typeof item });
561
+ throw new ArgumentError("sum 은 number 에 대해서만 사용할 수 있습니다.", {
562
+ type: typeof item,
563
+ });
546
564
  }
547
565
  result += item;
548
566
  }
@@ -555,7 +573,9 @@ const arrayReadonlyExtensions: ReadonlyArrayExt<any> & ThisType<any[]> = {
555
573
  for (let i = 0; i < this.length; i++) {
556
574
  const item = selector !== undefined ? selector(this[i], i) : this[i];
557
575
  if (typeof item !== "number" && typeof item !== "string") {
558
- throw new ArgumentError("min 은 number/string 에 대해서만 사용할 수 있습니다.", { type: typeof item });
576
+ throw new ArgumentError("min 은 number/string 에 대해서만 사용할 수 있습니다.", {
577
+ type: typeof item,
578
+ });
559
579
  }
560
580
  if (result === undefined || result > item) {
561
581
  result = item;
@@ -570,7 +590,9 @@ const arrayReadonlyExtensions: ReadonlyArrayExt<any> & ThisType<any[]> = {
570
590
  for (let i = 0; i < this.length; i++) {
571
591
  const item = selector !== undefined ? selector(this[i], i) : this[i];
572
592
  if (typeof item !== "number" && typeof item !== "string") {
573
- throw new ArgumentError("max 은 number/string 에 대해서만 사용할 수 있습니다.", { type: typeof item });
593
+ throw new ArgumentError("max 은 number/string 에 대해서만 사용할 수 있습니다.", {
594
+ type: typeof item,
595
+ });
574
596
  }
575
597
  if (result === undefined || result < item) {
576
598
  result = item;
@@ -595,7 +617,9 @@ const arrayReadonlyExtensions: ReadonlyArrayExt<any> & ThisType<any[]> = {
595
617
  };
596
618
 
597
619
  const arrayMutableExtensions: MutableArrayExt<any> & ThisType<any[]> = {
598
- distinctThis<T>(options?: boolean | { matchAddress?: boolean; keyFn?: (item: T) => string | number }): T[] {
620
+ distinctThis<T>(
621
+ options?: boolean | { matchAddress?: boolean; keyFn?: (item: T) => string | number },
622
+ ): T[] {
599
623
  // 옵션 정규화
600
624
  const opts = typeof options === "boolean" ? { matchAddress: options } : (options ?? {});
601
625
 
@@ -700,7 +724,9 @@ const arrayMutableExtensions: MutableArrayExt<any> & ThisType<any[]> = {
700
724
  return this;
701
725
  },
702
726
 
703
- orderByThis<T>(selector?: (item: T) => string | number | DateTime | DateOnly | Time | undefined): T[] {
727
+ orderByThis<T>(
728
+ selector?: (item: T) => string | number | DateTime | DateOnly | Time | undefined,
729
+ ): T[] {
704
730
  return this.sort((p, n) => {
705
731
  const pp = selector?.(p) ?? p;
706
732
  const pn = selector?.(n) ?? n;
@@ -708,7 +734,9 @@ const arrayMutableExtensions: MutableArrayExt<any> & ThisType<any[]> = {
708
734
  });
709
735
  },
710
736
 
711
- orderByDescThis<T>(selector?: (item: T) => string | number | DateTime | DateOnly | Time | undefined): T[] {
737
+ orderByDescThis<T>(
738
+ selector?: (item: T) => string | number | DateTime | DateOnly | Time | undefined,
739
+ ): T[] {
712
740
  return this.sort((p, n) => {
713
741
  const pp = selector?.(p) ?? p;
714
742
  const pn = selector?.(n) ?? n;
@@ -774,4 +802,9 @@ declare global {
774
802
 
775
803
  //#endregion
776
804
 
777
- export type { ArrayDiffsResult, ArrayDiffs2Result, TreeArray, ComparableType } from "./arr-ext.types";
805
+ export type {
806
+ ArrayDiffsResult,
807
+ ArrayDiffs2Result,
808
+ TreeArray,
809
+ ComparableType,
810
+ } from "./arr-ext.types";
@@ -108,7 +108,10 @@ export interface ReadonlyArrayExt<TItem> {
108
108
  valueSelector: (item: TItem, index: number) => V,
109
109
  ): Map<K, Set<V>>;
110
110
 
111
- toMapValues<K, V>(keySelector: (item: TItem, index: number) => K, valueSelector: (items: TItem[]) => V): Map<K, V>;
111
+ toMapValues<K, V>(
112
+ keySelector: (item: TItem, index: number) => K,
113
+ valueSelector: (items: TItem[]) => V,
114
+ ): Map<K, V>;
112
115
 
113
116
  toObject(keySelector: (item: TItem, index: number) => string): Record<string, TItem>;
114
117
 
@@ -153,18 +156,27 @@ export interface ReadonlyArrayExt<TItem> {
153
156
  * // ]}]
154
157
  * ```
155
158
  */
156
- toTree<K extends keyof TItem, P extends keyof TItem>(keyProp: K, parentKey: P): TreeArray<TItem>[];
159
+ toTree<K extends keyof TItem, P extends keyof TItem>(
160
+ keyProp: K,
161
+ parentKey: P,
162
+ ): TreeArray<TItem>[];
157
163
 
158
164
  /**
159
165
  * 중복 제거
160
166
  * @param options matchAddress: 주소 비교 (true면 Set 사용), keyFn: 커스텀 키 함수 (O(n) 성능)
161
167
  * @note 객체 배열에서 keyFn 없이 사용 시 O(n²) 복잡도. 대량 데이터는 keyFn 사용 권장
162
168
  */
163
- distinct(options?: boolean | { matchAddress?: boolean; keyFn?: (item: TItem) => string | number }): TItem[];
169
+ distinct(
170
+ options?: boolean | { matchAddress?: boolean; keyFn?: (item: TItem) => string | number },
171
+ ): TItem[];
164
172
 
165
- orderBy(selector?: (item: TItem) => string | number | DateOnly | DateTime | Time | undefined): TItem[];
173
+ orderBy(
174
+ selector?: (item: TItem) => string | number | DateOnly | DateTime | Time | undefined,
175
+ ): TItem[];
166
176
 
167
- orderByDesc(selector?: (item: TItem) => string | number | DateOnly | DateTime | Time | undefined): TItem[];
177
+ orderByDesc(
178
+ selector?: (item: TItem) => string | number | DateOnly | DateTime | Time | undefined,
179
+ ): TItem[];
168
180
 
169
181
  /**
170
182
  * 두 배열 비교 (INSERT/DELETE/UPDATE)
@@ -221,13 +233,19 @@ export interface MutableArrayExt<TItem> {
221
233
  * @note 객체 배열에서 keyFn 없이 사용 시 O(n²) 복잡도. 대량 데이터는 keyFn 사용 권장
222
234
  * @mutates
223
235
  */
224
- distinctThis(options?: boolean | { matchAddress?: boolean; keyFn?: (item: TItem) => string | number }): TItem[];
236
+ distinctThis(
237
+ options?: boolean | { matchAddress?: boolean; keyFn?: (item: TItem) => string | number },
238
+ ): TItem[];
225
239
 
226
240
  /** 원본 배열 오름차순 정렬 @mutates */
227
- orderByThis(selector?: (item: TItem) => string | number | DateOnly | DateTime | Time | undefined): TItem[];
241
+ orderByThis(
242
+ selector?: (item: TItem) => string | number | DateOnly | DateTime | Time | undefined,
243
+ ): TItem[];
228
244
 
229
245
  /** 원본 배열 내림차순 정렬 @mutates */
230
- orderByDescThis(selector?: (item: TItem) => string | number | DateOnly | DateTime | Time | undefined): TItem[];
246
+ orderByDescThis(
247
+ selector?: (item: TItem) => string | number | DateOnly | DateTime | Time | undefined,
248
+ ): TItem[];
231
249
 
232
250
  /** 원본 배열에 항목 삽입 @mutates */
233
251
  insert(index: number, ...items: TItem[]): this;
@@ -20,7 +20,9 @@
20
20
  * emitter.emit("data", "hello");
21
21
  * emitter.emit("done"); // void 타입은 인자 없이 호출
22
22
  */
23
- export class EventEmitter<TEvents extends { [K in keyof TEvents]: unknown } = Record<string, unknown>> {
23
+ export class EventEmitter<
24
+ TEvents extends { [K in keyof TEvents]: unknown } = Record<string, unknown>,
25
+ > {
24
26
  private readonly _target = new EventTarget();
25
27
  // 이벤트 타입별로 리스너 맵 관리 (같은 리스너를 다른 이벤트에 등록 가능)
26
28
  // 다형적 리스너 관리를 위해 Function 타입 사용
@@ -77,7 +79,10 @@ export class EventEmitter<TEvents extends { [K in keyof TEvents]: unknown } = Re
77
79
  * @param type 이벤트 타입
78
80
  * @param args 이벤트 데이터 (void 타입이면 생략)
79
81
  */
80
- emit<K extends keyof TEvents & string>(type: K, ...args: TEvents[K] extends void ? [] : [data: TEvents[K]]): void {
82
+ emit<K extends keyof TEvents & string>(
83
+ type: K,
84
+ ...args: TEvents[K] extends void ? [] : [data: TEvents[K]]
85
+ ): void {
81
86
  this._target.dispatchEvent(new CustomEvent(type, { detail: args[0] }));
82
87
  }
83
88
 
@@ -64,7 +64,11 @@ export class DateOnly {
64
64
  // yyyyMMdd 형식 (타임존 영향 없음)
65
65
  const matchCompact = /^(\d{4})(\d{2})(\d{2})$/.exec(str);
66
66
  if (matchCompact != null) {
67
- return new DateOnly(Number(matchCompact[1]), Number(matchCompact[2]), Number(matchCompact[3]));
67
+ return new DateOnly(
68
+ Number(matchCompact[1]),
69
+ Number(matchCompact[2]),
70
+ Number(matchCompact[3]),
71
+ );
68
72
  }
69
73
 
70
74
  // ISO 8601 등 기타 형식 (Date.parse 사용, 타임존 변환 적용)
@@ -80,9 +84,12 @@ export class DateOnly {
80
84
  return new DateOnly(localTick);
81
85
  }
82
86
 
83
- throw new ArgumentError(`날짜 형식을 파싱할 수 없습니다. 지원 형식: 'yyyy-MM-dd', 'yyyyMMdd', ISO 8601 날짜`, {
84
- input: str,
85
- });
87
+ throw new ArgumentError(
88
+ `날짜 형식을 파싱할 수 없습니다. 지원 형식: 'yyyy-MM-dd', 'yyyyMMdd', ISO 8601 날짜`,
89
+ {
90
+ input: str,
91
+ },
92
+ );
86
93
  }
87
94
 
88
95
  //#region 주차 계산
@@ -156,10 +163,16 @@ export class DateOnly {
156
163
  * // 미국식 (일요일 시작, 첫 주 1일 이상)
157
164
  * new DateOnly(2025, 1, 1).getWeekSeqOfYear(0, 1); // { year: 2025, weekSeq: 1 }
158
165
  */
159
- getWeekSeqOfYear(weekStartDay: number = 1, minDaysInFirstWeek: number = 4): { year: number; weekSeq: number } {
166
+ getWeekSeqOfYear(
167
+ weekStartDay: number = 1,
168
+ minDaysInFirstWeek: number = 4,
169
+ ): { year: number; weekSeq: number } {
160
170
  const base = this.getBaseYearMonthSeqForWeekSeq(weekStartDay, minDaysInFirstWeek);
161
171
 
162
- const firstWeekStart = new DateOnly(base.year, 1, 1).getWeekSeqStartDate(weekStartDay, minDaysInFirstWeek);
172
+ const firstWeekStart = new DateOnly(base.year, 1, 1).getWeekSeqStartDate(
173
+ weekStartDay,
174
+ minDaysInFirstWeek,
175
+ );
163
176
 
164
177
  const diffDays = (this.tick - firstWeekStart.tick) / DateOnly.MS_PER_DAY;
165
178
  return {
@@ -43,7 +43,15 @@ export class DateTime {
43
43
  if (arg1 === undefined) {
44
44
  this.date = new Date();
45
45
  } else if (arg2 !== undefined && arg3 !== undefined) {
46
- this.date = new Date(arg1 as number, arg2 - 1, arg3, arg4 ?? 0, arg5 ?? 0, arg6 ?? 0, arg7 ?? 0);
46
+ this.date = new Date(
47
+ arg1 as number,
48
+ arg2 - 1,
49
+ arg3,
50
+ arg4 ?? 0,
51
+ arg5 ?? 0,
52
+ arg6 ?? 0,
53
+ arg7 ?? 0,
54
+ );
47
55
  } else if (arg1 instanceof Date) {
48
56
  this.date = new Date(arg1.getTime());
49
57
  } else {
@@ -72,7 +80,9 @@ export class DateTime {
72
80
  }
73
81
 
74
82
  const match1 =
75
- /^([0-9]{4})-([0-9]{2})-([0-9]{2}) (오전|오후) ([0-9]{1,2}):([0-9]{2}):([0-9]{2})(\.([0-9]{1,3}))?$/.exec(str);
83
+ /^([0-9]{4})-([0-9]{2})-([0-9]{2}) (오전|오후) ([0-9]{1,2}):([0-9]{2}):([0-9]{2})(\.([0-9]{1,3}))?$/.exec(
84
+ str,
85
+ );
76
86
  if (match1 != null) {
77
87
  const rawHour = Number(match1[5]);
78
88
  const isPM = match1[4] === "오후";
@@ -100,7 +110,10 @@ export class DateTime {
100
110
  );
101
111
  }
102
112
 
103
- const match3 = /^([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})(\.([0-9]{1,3}))?$/.exec(str);
113
+ const match3 =
114
+ /^([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})(\.([0-9]{1,3}))?$/.exec(
115
+ str,
116
+ );
104
117
  if (match3 != null) {
105
118
  return new DateTime(
106
119
  Number(match3[1]),
@@ -173,7 +186,15 @@ export class DateTime {
173
186
 
174
187
  /** 지정된 연도로 새 인스턴스 반환 */
175
188
  setYear(year: number): DateTime {
176
- return new DateTime(year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond);
189
+ return new DateTime(
190
+ year,
191
+ this.month,
192
+ this.day,
193
+ this.hour,
194
+ this.minute,
195
+ this.second,
196
+ this.millisecond,
197
+ );
177
198
  }
178
199
 
179
200
  /**
@@ -202,27 +223,67 @@ export class DateTime {
202
223
  * 자동으로 다음/이전 달로 조정됨 (예: 1월에 day=32 → 2월 1일)
203
224
  */
204
225
  setDay(day: number): DateTime {
205
- return new DateTime(this.year, this.month, day, this.hour, this.minute, this.second, this.millisecond);
226
+ return new DateTime(
227
+ this.year,
228
+ this.month,
229
+ day,
230
+ this.hour,
231
+ this.minute,
232
+ this.second,
233
+ this.millisecond,
234
+ );
206
235
  }
207
236
 
208
237
  /** 지정된 시로 새 인스턴스 반환 */
209
238
  setHour(hour: number): DateTime {
210
- return new DateTime(this.year, this.month, this.day, hour, this.minute, this.second, this.millisecond);
239
+ return new DateTime(
240
+ this.year,
241
+ this.month,
242
+ this.day,
243
+ hour,
244
+ this.minute,
245
+ this.second,
246
+ this.millisecond,
247
+ );
211
248
  }
212
249
 
213
250
  /** 지정된 분으로 새 인스턴스 반환 */
214
251
  setMinute(minute: number): DateTime {
215
- return new DateTime(this.year, this.month, this.day, this.hour, minute, this.second, this.millisecond);
252
+ return new DateTime(
253
+ this.year,
254
+ this.month,
255
+ this.day,
256
+ this.hour,
257
+ minute,
258
+ this.second,
259
+ this.millisecond,
260
+ );
216
261
  }
217
262
 
218
263
  /** 지정된 초로 새 인스턴스 반환 */
219
264
  setSecond(second: number): DateTime {
220
- return new DateTime(this.year, this.month, this.day, this.hour, this.minute, second, this.millisecond);
265
+ return new DateTime(
266
+ this.year,
267
+ this.month,
268
+ this.day,
269
+ this.hour,
270
+ this.minute,
271
+ second,
272
+ this.millisecond,
273
+ );
221
274
  }
222
275
 
223
276
  /** 지정된 밀리초로 새 인스턴스 반환 */
224
277
  setMillisecond(millisecond: number): DateTime {
225
- return new DateTime(this.year, this.month, this.day, this.hour, this.minute, this.second, millisecond);
278
+ return new DateTime(
279
+ this.year,
280
+ this.month,
281
+ this.day,
282
+ this.hour,
283
+ this.minute,
284
+ this.second,
285
+ millisecond,
286
+ );
226
287
  }
227
288
 
228
289
  //#endregion
package/src/types/time.ts CHANGED
@@ -36,7 +36,8 @@ export class Time {
36
36
  Time.MS_PER_DAY;
37
37
  } else if (arg2 !== undefined) {
38
38
  let tick =
39
- ((arg4 ?? 0) + (arg3 ?? 0) * 1000 + arg2 * 60 * 1000 + (arg1 as number) * 60 * 60 * 1000) % Time.MS_PER_DAY;
39
+ ((arg4 ?? 0) + (arg3 ?? 0) * 1000 + arg2 * 60 * 1000 + (arg1 as number) * 60 * 60 * 1000) %
40
+ Time.MS_PER_DAY;
40
41
  if (tick < 0) tick += Time.MS_PER_DAY;
41
42
  this._tick = tick;
42
43
  } else if (arg1 instanceof Date) {
@@ -72,7 +73,12 @@ export class Time {
72
73
  const rawHour = Number(match1[2]);
73
74
  const isPM = match1[1] === "오후";
74
75
  const hour = convert12To24(rawHour, isPM);
75
- return new Time(hour, Number(match1[3]), Number(match1[4]), Number(match1[6] ? match1[6].padEnd(3, "0") : "0"));
76
+ return new Time(
77
+ hour,
78
+ Number(match1[3]),
79
+ Number(match1[4]),
80
+ Number(match1[6] ? match1[6].padEnd(3, "0") : "0"),
81
+ );
76
82
  }
77
83
 
78
84
  const match2 = /([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})(\.([0-9]{1,3}))?$/.exec(str);
@@ -91,7 +97,12 @@ export class Time {
91
97
  if (isoMatch != null) {
92
98
  const date = new Date(str);
93
99
  if (!Number.isNaN(date.getTime())) {
94
- return new Time(date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds());
100
+ return new Time(
101
+ date.getHours(),
102
+ date.getMinutes(),
103
+ date.getSeconds(),
104
+ date.getMilliseconds(),
105
+ );
95
106
  }
96
107
  }
97
108
 
package/src/types/uuid.ts CHANGED
@@ -12,9 +12,12 @@ import { ArgumentError } from "../errors/argument-error";
12
12
  */
13
13
  export class Uuid {
14
14
  // 0x00 ~ 0xFF에 대한 hex 문자열 미리 계산 (256개)
15
- private static readonly _hexTable: string[] = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
15
+ private static readonly _hexTable: string[] = Array.from({ length: 256 }, (_, i) =>
16
+ i.toString(16).padStart(2, "0"),
17
+ );
16
18
 
17
- private static readonly _uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
19
+ private static readonly _uuidRegex =
20
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
18
21
 
19
22
  /** 16바이트 배열을 UUID 문자열로 변환 */
20
23
  private static _bytesToUuidStr(bytes: Uint8Array): string {
@@ -132,7 +132,9 @@ export function bytesFromBase64(base64: string): Bytes {
132
132
 
133
133
  // 유효성 검사: 문자
134
134
  if (!/^[A-Za-z0-9+/]+$/.test(cleanBase64)) {
135
- throw new ArgumentError("유효하지 않은 base64 문자가 포함되어 있습니다", { base64: base64.substring(0, 20) });
135
+ throw new ArgumentError("유효하지 않은 base64 문자가 포함되어 있습니다", {
136
+ base64: base64.substring(0, 20),
137
+ });
136
138
  }
137
139
 
138
140
  // 유효성 검사: 길이 (패딩 제거 후 나머지가 1이면 유효하지 않음)
@@ -151,10 +151,12 @@ export function formatDate(
151
151
  ): string {
152
152
  const { year, month, day, hour, minute, second, millisecond, timezoneOffsetMinutes } = args;
153
153
 
154
- const absOffsetMinutes = timezoneOffsetMinutes !== undefined ? Math.abs(timezoneOffsetMinutes) : undefined;
154
+ const absOffsetMinutes =
155
+ timezoneOffsetMinutes !== undefined ? Math.abs(timezoneOffsetMinutes) : undefined;
155
156
  const offsetHour = absOffsetMinutes !== undefined ? Math.floor(absOffsetMinutes / 60) : undefined;
156
157
  const offsetMinute = absOffsetMinutes !== undefined ? absOffsetMinutes % 60 : undefined;
157
- const offsetSign = timezoneOffsetMinutes !== undefined ? (timezoneOffsetMinutes >= 0 ? "+" : "-") : undefined;
158
+ const offsetSign =
159
+ timezoneOffsetMinutes !== undefined ? (timezoneOffsetMinutes >= 0 ? "+" : "-") : undefined;
158
160
 
159
161
  const week =
160
162
  year !== undefined && month !== undefined && day !== undefined
package/src/utils/json.ts CHANGED
@@ -129,7 +129,10 @@ export function jsonStringify(
129
129
  seen.add(currValue);
130
130
 
131
131
  // toJSON 메서드가 있으면 호출 (Date, DateTime 등 커스텀 타입은 이미 위에서 처리됨)
132
- if ("toJSON" in currValue && typeof (currValue as { toJSON: unknown }).toJSON === "function") {
132
+ if (
133
+ "toJSON" in currValue &&
134
+ typeof (currValue as { toJSON: unknown }).toJSON === "function"
135
+ ) {
133
136
  const toJsonResult = (currValue as { toJSON: (key?: string) => unknown }).toJSON(key);
134
137
  seen.delete(currValue);
135
138
  return convertSpecialTypes(key, toJsonResult);
@@ -209,7 +212,9 @@ export function jsonParse<TResult = unknown>(json: string): TResult {
209
212
  }
210
213
  if (typed.__type__ === "Uint8Array" && typeof typed.data === "string") {
211
214
  if (typed.data === "__hidden__") {
212
- throw new SdError("redactBytes 옵션으로 직렬화된 Uint8Array는 parse로 복원할 수 없습니다");
215
+ throw new SdError(
216
+ "redactBytes 옵션으로 직렬화된 Uint8Array는 parse로 복원할 수 없습니다",
217
+ );
213
218
  }
214
219
  return bytesFromHex(typed.data);
215
220
  }
package/src/utils/num.ts CHANGED
@@ -86,8 +86,14 @@ export function numIsNullOrEmpty(val: number | undefined): val is 0 | undefined
86
86
  * numFormat(1234, { min: 2 }) // "1,234.00"
87
87
  */
88
88
  export function numFormat(val: number, digit?: { max?: number; min?: number }): string;
89
- export function numFormat(val: number | undefined, digit?: { max?: number; min?: number }): string | undefined;
90
- export function numFormat(val: number | undefined, digit?: { max?: number; min?: number }): string | undefined {
89
+ export function numFormat(
90
+ val: number | undefined,
91
+ digit?: { max?: number; min?: number },
92
+ ): string | undefined;
93
+ export function numFormat(
94
+ val: number | undefined,
95
+ digit?: { max?: number; min?: number },
96
+ ): string | undefined {
91
97
  return val?.toLocaleString(undefined, {
92
98
  maximumFractionDigits: digit?.max,
93
99
  minimumFractionDigits: digit?.min,
package/src/utils/obj.ts CHANGED
@@ -204,7 +204,11 @@ export function objEqual(source: unknown, target: unknown, options?: EqualOption
204
204
  }
205
205
 
206
206
  if (typeof source === "object" && typeof target === "object") {
207
- return objEqualObject(source as Record<string, unknown>, target as Record<string, unknown>, options);
207
+ return objEqualObject(
208
+ source as Record<string, unknown>,
209
+ target as Record<string, unknown>,
210
+ options,
211
+ );
208
212
  }
209
213
 
210
214
  return false;
@@ -229,9 +233,14 @@ function objEqualArray(source: unknown[], target: unknown[], options?: EqualOpti
229
233
  });
230
234
  } else {
231
235
  // 재귀 호출 시 topLevelIncludes/topLevelExcludes 옵션은 최상위 레벨에만 적용되므로 제외
232
- const recursiveOptions = { ignoreArrayIndex: options.ignoreArrayIndex, onlyOneDepth: options.onlyOneDepth };
236
+ const recursiveOptions = {
237
+ ignoreArrayIndex: options.ignoreArrayIndex,
238
+ onlyOneDepth: options.onlyOneDepth,
239
+ };
233
240
  return source.every((sourceItem) => {
234
- const idx = target.findIndex((t, i) => !matchedIndices.has(i) && objEqual(t, sourceItem, recursiveOptions));
241
+ const idx = target.findIndex(
242
+ (t, i) => !matchedIndices.has(i) && objEqual(t, sourceItem, recursiveOptions),
243
+ );
235
244
  if (idx !== -1) {
236
245
  matchedIndices.add(idx);
237
246
  return true;
@@ -269,7 +278,11 @@ function objEqualArray(source: unknown[], target: unknown[], options?: EqualOpti
269
278
  * @note 비문자열 키(객체, 배열 등) 처리 시 O(n²) 복잡도 발생
270
279
  * @note 대량 데이터의 경우 onlyOneDepth: true 옵션 사용 권장 (참조 비교로 O(n)으로 개선)
271
280
  */
272
- function objEqualMap(source: Map<unknown, unknown>, target: Map<unknown, unknown>, options?: EqualOptions): boolean {
281
+ function objEqualMap(
282
+ source: Map<unknown, unknown>,
283
+ target: Map<unknown, unknown>,
284
+ options?: EqualOptions,
285
+ ): boolean {
273
286
  // Map 비교 시 topLevelIncludes/topLevelExcludes 옵션은 무시됨 (object 속성 키에만 적용)
274
287
  const sourceKeys = Array.from(source.keys()).filter((key) => source.get(key) != null);
275
288
  const targetKeys = Array.from(target.keys()).filter((key) => target.get(key) != null);
@@ -392,7 +405,9 @@ function objEqualSet(source: Set<unknown>, target: Set<unknown>, options?: Equal
392
405
  const targetArr = [...target];
393
406
  const matchedIndices = new Set<number>();
394
407
  for (const sourceItem of source) {
395
- const idx = targetArr.findIndex((t, i) => !matchedIndices.has(i) && objEqual(sourceItem, t, options));
408
+ const idx = targetArr.findIndex(
409
+ (t, i) => !matchedIndices.has(i) && objEqual(sourceItem, t, options),
410
+ );
396
411
  if (idx === -1) {
397
412
  return false;
398
413
  }
@@ -447,7 +462,9 @@ export function objMerge<TSource, TMergeTarget>(
447
462
  }
448
463
 
449
464
  if (target === null) {
450
- return opt?.useDelTargetNull ? (undefined as TSource & TMergeTarget) : (objClone(source) as TSource & TMergeTarget);
465
+ return opt?.useDelTargetNull
466
+ ? (undefined as TSource & TMergeTarget)
467
+ : (objClone(source) as TSource & TMergeTarget);
451
468
  }
452
469
 
453
470
  if (typeof target !== "object") {
@@ -588,7 +605,10 @@ export function objMerge3<
588
605
  * objOmit(user, ["email"]);
589
606
  * // { name: "Alice", age: 30 }
590
607
  */
591
- export function objOmit<T extends Record<string, unknown>, K extends keyof T>(item: T, omitKeys: K[]): Omit<T, K> {
608
+ export function objOmit<T extends Record<string, unknown>, K extends keyof T>(
609
+ item: T,
610
+ omitKeys: K[],
611
+ ): Omit<T, K> {
592
612
  const result: Record<string, unknown> = {};
593
613
  for (const key of Object.keys(item)) {
594
614
  if (!omitKeys.includes(key as K)) {
@@ -609,7 +629,10 @@ export function objOmit<T extends Record<string, unknown>, K extends keyof T>(it
609
629
  * objOmitByFilter(data, (key) => key.startsWith("_"));
610
630
  * // { name: "Alice", age: 30 }
611
631
  */
612
- export function objOmitByFilter<T extends Record<string, unknown>>(item: T, omitKeyFn: (key: keyof T) => boolean): T {
632
+ export function objOmitByFilter<T extends Record<string, unknown>>(
633
+ item: T,
634
+ omitKeyFn: (key: keyof T) => boolean,
635
+ ): T {
613
636
  const result: Record<string, unknown> = {};
614
637
  for (const key of Object.keys(item)) {
615
638
  if (!omitKeyFn(key)) {
@@ -629,7 +652,10 @@ export function objOmitByFilter<T extends Record<string, unknown>>(item: T, omit
629
652
  * objPick(user, ["name", "age"]);
630
653
  * // { name: "Alice", age: 30 }
631
654
  */
632
- export function objPick<T extends Record<string, unknown>, K extends keyof T>(item: T, keys: K[]): Pick<T, K> {
655
+ export function objPick<T extends Record<string, unknown>, K extends keyof T>(
656
+ item: T,
657
+ keys: K[],
658
+ ): Pick<T, K> {
633
659
  const result: Record<string, unknown> = {};
634
660
  for (const key of keys) {
635
661
  result[key as string] = item[key];
@@ -669,7 +695,11 @@ function getChainSplits(chain: string): (string | number)[] {
669
695
  */
670
696
  export function objGetChainValue(obj: unknown, chain: string, optional: true): unknown | undefined;
671
697
  export function objGetChainValue(obj: unknown, chain: string): unknown;
672
- export function objGetChainValue(obj: unknown, chain: string, optional?: true): unknown | undefined {
698
+ export function objGetChainValue(
699
+ obj: unknown,
700
+ chain: string,
701
+ optional?: true,
702
+ ): unknown | undefined {
673
703
  const splits = getChainSplits(chain);
674
704
  let result: unknown = obj;
675
705
  for (const splitItem of splits) {
@@ -957,7 +987,10 @@ function objMapImpl<TSource extends object, TNewKey extends string, TNewValue>(
957
987
  ): Record<string, TNewValue> {
958
988
  const result: Record<string, TNewValue> = {};
959
989
  for (const key of Object.keys(obj)) {
960
- const [newKey, newValue] = fn(key as keyof TSource, (obj as Record<string, TSource[keyof TSource]>)[key]);
990
+ const [newKey, newValue] = fn(
991
+ key as keyof TSource,
992
+ (obj as Record<string, TSource[keyof TSource]>)[key],
993
+ );
961
994
  result[newKey ?? key] = newValue;
962
995
  }
963
996
  return result;