@simplysm/core-common 13.0.96 → 13.0.98

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/types.md CHANGED
@@ -1,341 +1,287 @@
1
- # 타입
1
+ # Types
2
2
 
3
- ## DateTime
3
+ Data types and common type definitions.
4
4
 
5
- 불변(immutable) 날짜/시간 타입. 모든 변경 메서드는 새 인스턴스를 반환한다.
5
+ Source: `src/types/*.ts`, `src/common.types.ts`, `src/env.ts`
6
6
 
7
- ### 생성
7
+ ---
8
8
 
9
- ```typescript
10
- import { DateTime } from "@simplysm/core-common";
11
-
12
- new DateTime(); // 현재 시각
13
- new DateTime(2024, 1, 15); // 2024-01-15 00:00:00
14
- new DateTime(2024, 1, 15, 14, 30, 0); // 2024-01-15 14:30:00
15
- new DateTime(2024, 1, 15, 14, 30, 0, 500); // 밀리초 포함
16
- new DateTime(tick); // tick(밀리초)으로 생성
17
- new DateTime(new Date()); // Date 객체에서 생성
18
- ```
9
+ ## `Uuid`
19
10
 
20
- ### 파싱
11
+ UUID v4 class. Generates cryptographically secure UUIDs based on `crypto.getRandomValues` (Chrome 79+, Node.js compatible).
21
12
 
22
13
  ```typescript
23
- DateTime.parse("2024-01-15T14:30:00.000Z"); // ISO 8601
24
- DateTime.parse("2024-01-15 14:30:00"); // yyyy-MM-dd HH:mm:ss
25
- DateTime.parse("2024-01-15 14:30:00.123"); // yyyy-MM-dd HH:mm:ss.fff
26
- DateTime.parse("20240115143000"); // yyyyMMddHHmmss
27
- DateTime.parse("2024-01-15 AM 10:30:00"); // yyyy-MM-dd AM/PM HH:mm:ss
28
- DateTime.parse("2024-01-15 오전 10:30:00"); // yyyy-MM-dd 오전/오후 HH:mm:ss
14
+ export class Uuid {
15
+ /** Create new UUID v4 instance */
16
+ static generate(): Uuid;
17
+
18
+ /**
19
+ * Create UUID from 16-byte Uint8Array
20
+ * @throws {ArgumentError} If byte size is not 16
21
+ */
22
+ static fromBytes(bytes: Bytes): Uuid;
23
+
24
+ /**
25
+ * @param uuid UUID string (format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
26
+ * @throws {ArgumentError} If format is invalid
27
+ */
28
+ constructor(uuid: string);
29
+
30
+ /** Convert UUID to string */
31
+ toString(): string;
32
+
33
+ /** Convert UUID to 16-byte Uint8Array */
34
+ toBytes(): Bytes;
35
+ }
29
36
  ```
30
37
 
31
- ### 속성
32
-
33
- | 속성 | 타입 | 설명 |
34
- |------|------|------|
35
- | `year` | `number` | 연도 |
36
- | `month` | `number` | 월 (1~12) |
37
- | `day` | `number` | 일 |
38
- | `hour` | `number` | 시 (0~23) |
39
- | `minute` | `number` | 분 |
40
- | `second` | `number` | 초 |
41
- | `millisecond` | `number` | 밀리초 |
42
- | `tick` | `number` | epoch 밀리초 |
43
- | `dayOfWeek` | `number` | 요일 (0=일요일) |
44
- | `timezoneOffsetMinutes` | `number` | 타임존 오프셋(분) |
45
- | `isValid` | `boolean` | 유효성 |
46
- | `date` | `Date` | 내부 Date 객체 (readonly) |
47
-
48
- ### 변경 (새 인스턴스 반환)
38
+ ---
49
39
 
50
- ```typescript
51
- const dt = new DateTime(2024, 1, 15, 14, 30, 0);
52
-
53
- dt.setYear(2025); // 2025-01-15 14:30:00
54
- dt.setMonth(6); // 2024-06-15 14:30:00
55
- dt.setDay(20); // 2024-01-20 14:30:00
56
- dt.setHour(10); // 2024-01-15 10:30:00
57
- dt.setMinute(45); // 2024-01-15 14:45:00
58
- dt.setSecond(30); // 2024-01-15 14:30:30
59
- dt.setMillisecond(500); // 2024-01-15 14:30:00.500
60
-
61
- dt.addYears(1); // 2025-01-15 14:30:00
62
- dt.addMonths(3); // 2024-04-15 14:30:00
63
- dt.addDays(10); // 2024-01-25 14:30:00
64
- dt.addHours(-2); // 2024-01-15 12:30:00
65
- dt.addMinutes(15); // 2024-01-15 14:45:00
66
- dt.addSeconds(30); // 2024-01-15 14:30:30
67
- dt.addMilliseconds(500); // 2024-01-15 14:30:00.500
68
- ```
40
+ ## `DateTime`
69
41
 
70
- ### 포맷
42
+ Immutable date+time class wrapping JavaScript `Date`. Supports millisecond precision and operates based on local timezone.
71
43
 
72
44
  ```typescript
73
- dt.toFormatString("yyyy-MM-dd HH:mm:ss"); // "2024-01-15 14:30:00"
74
- dt.toFormatString("yy/M/d tt h:mm"); // "24/1/15 PM 2:30"
75
- dt.toString(); // ISO 8601 형식 "2024-01-15T14:30:00.000+09:00"
45
+ export class DateTime {
46
+ readonly date: Date;
47
+
48
+ /** Create with current time */
49
+ constructor();
50
+ /** Create with year, month, day, hour, minute, second, millisecond */
51
+ constructor(year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millisecond?: number);
52
+ /** Create from tick (millisecond) */
53
+ constructor(tick: number);
54
+ /** Create from Date object */
55
+ constructor(date: Date);
56
+
57
+ /**
58
+ * Parse a string to create DateTime instance
59
+ * Supported formats: 'yyyy-MM-dd HH:mm:ss', 'yyyy-MM-dd HH:mm:ss.fff', 'yyyyMMddHHmmss',
60
+ * 'yyyy-MM-dd AM/PM HH:mm:ss', ISO 8601
61
+ * @throws ArgumentError If unsupported format
62
+ */
63
+ static parse(str: string): DateTime;
64
+ }
76
65
  ```
77
66
 
78
- 포맷 패턴:
79
-
80
- | 패턴 | 설명 | 예시 |
81
- |------|------|------|
82
- | `yyyy` | 4자리 연도 | 2024 |
83
- | `yy` | 2자리 연도 | 24 |
84
- | `MM` | 0패딩 월 | 01~12 |
85
- | `M` | 월 | 1~12 |
86
- | `ddd` | 요일 | 일, 월, 화, 수, 목, 금, 토 |
87
- | `dd` | 0패딩 일 | 01~31 |
88
- | `d` | 일 | 1~31 |
89
- | `tt` | 오전/오후 | AM, PM |
90
- | `hh` | 0패딩 12시간 | 01~12 |
91
- | `h` | 12시간 | 1~12 |
92
- | `HH` | 0패딩 24시간 | 00~23 |
93
- | `H` | 24시간 | 0~23 |
94
- | `mm` | 0패딩 분 | 00~59 |
95
- | `m` | 분 | 0~59 |
96
- | `ss` | 0패딩 초 | 00~59 |
97
- | `s` | 초 | 0~59 |
98
- | `fff` | 밀리초(3자리) | 000~999 |
99
- | `ff` | 밀리초(2자리) | 00~99 |
100
- | `f` | 밀리초(1자리) | 0~9 |
101
- | `zzz` | 타임존(+-HH:mm) | +09:00 |
102
- | `zz` | 타임존(+-HH) | +09 |
103
- | `z` | 타임존(+-H) | +9 |
67
+ **Getters** (read-only): `year`, `month`, `day`, `hour`, `minute`, `second`, `millisecond`, `tick`, `dayOfWeek` (0=Sunday), `timezoneOffsetMinutes`, `isValid`
68
+
69
+ **Immutable setters** (return new instance): `setYear(year)`, `setMonth(month)`, `setDay(day)`, `setHour(hour)`, `setMinute(minute)`, `setSecond(second)`, `setMillisecond(millisecond)`
70
+
71
+ **Arithmetic** (return new instance): `addYears(n)`, `addMonths(n)`, `addDays(n)`, `addHours(n)`, `addMinutes(n)`, `addSeconds(n)`, `addMilliseconds(n)`
72
+
73
+ **Formatting**: `toFormatString(formatStr)`, `toString()` (default: `"yyyy-MM-ddTHH:mm:ss.fffzzz"`)
104
74
 
105
75
  ---
106
76
 
107
- ## DateOnly
77
+ ## `DateOnly`
78
+
79
+ Immutable date class (without time: `yyyy-MM-dd`). Operates based on local timezone.
80
+
81
+ ```typescript
82
+ export class DateOnly {
83
+ readonly date: Date;
84
+
85
+ /** Current date */
86
+ constructor();
87
+ /** Initialize with year, month, day */
88
+ constructor(year: number, month: number, day: number);
89
+ /** Create from tick (millisecond) */
90
+ constructor(tick: number);
91
+ /** Create from Date type */
92
+ constructor(date: Date);
93
+
94
+ /**
95
+ * Parse a string into DateOnly
96
+ * Supported formats: 'yyyy-MM-dd', 'yyyyMMdd', ISO 8601
97
+ */
98
+ static parse(str: string): DateOnly;
99
+
100
+ /**
101
+ * Get the start date of a week based on week information
102
+ */
103
+ static getDateByYearWeekSeq(
104
+ arg: { year: number; month?: number; weekSeq: number },
105
+ weekStartDay?: number,
106
+ minDaysInFirstWeek?: number,
107
+ ): DateOnly;
108
+ }
109
+ ```
110
+
111
+ **Getters** (read-only): `year`, `month`, `day`, `tick`, `dayOfWeek`, `isValid`
108
112
 
109
- 불변 날짜 전용 타입 (시간 정보 없음).
113
+ **Immutable setters**: `setYear(year)`, `setMonth(month)`, `setDay(day)`
110
114
 
111
- ### 생성/파싱
115
+ **Arithmetic**: `addYears(n)`, `addMonths(n)`, `addDays(n)`
116
+
117
+ **Week calculation methods**:
112
118
 
113
119
  ```typescript
114
- import { DateOnly } from "@simplysm/core-common";
115
-
116
- new DateOnly(); // 오늘
117
- new DateOnly(2024, 1, 15); // 2024-01-15
118
- new DateOnly(tick); // tick(밀리초)으로 생성
119
- new DateOnly(new Date()); // Date 객체에서 생성
120
- DateOnly.parse("2024-01-15"); // yyyy-MM-dd
121
- DateOnly.parse("20240115"); // yyyyMMdd
122
- DateOnly.parse("2024-01-15T00:00:00Z"); // ISO 8601 (UTC -> 로컬 변환)
120
+ getBaseYearMonthSeqForWeekSeq(weekStartDay?: number, minDaysInFirstWeek?: number): { year: number; monthSeq: number };
121
+ getWeekSeqStartDate(weekStartDay?: number, minDaysInFirstWeek?: number): DateOnly;
122
+ getWeekSeqOfYear(weekStartDay?: number, minDaysInFirstWeek?: number): { year: number; weekSeq: number };
123
+ getWeekSeqOfMonth(weekStartDay?: number, minDaysInFirstWeek?: number): { year: number; monthSeq: number; weekSeq: number };
123
124
  ```
124
125
 
125
- ### 속성
126
+ Defaults: `weekStartDay = 1` (Monday), `minDaysInFirstWeek = 4` (ISO 8601 standard).
127
+
128
+ **Formatting**: `toFormatString(formatStr)`, `toString()` (default: `"yyyy-MM-dd"`)
126
129
 
127
- | 속성 | 타입 | 설명 |
128
- |------|------|------|
129
- | `year` | `number` | 연도 |
130
- | `month` | `number` | 월 (1~12) |
131
- | `day` | `number` | 일 |
132
- | `tick` | `number` | epoch 밀리초 |
133
- | `dayOfWeek` | `number` | 요일 (0=일요일) |
134
- | `isValid` | `boolean` | 유효성 |
135
- | `date` | `Date` | 내부 Date 객체 (readonly) |
130
+ ---
136
131
 
137
- ### 주차 계산
132
+ ## `Time`
138
133
 
139
- 모든 주차 메서드는 `weekStartDay`(주 시작 요일, 기본값 1=월요일)와 `minDaysInFirstWeek`(첫 최소 일수, 기본값 4=ISO 8601) 옵션을 지원한다.
134
+ Immutable time class (without date: `HH:mm:ss.fff`). Values exceeding 24 hours or negative values are automatically normalized (24-hour wraparound).
140
135
 
141
136
  ```typescript
142
- const date = new DateOnly(2024, 1, 15);
137
+ export class Time {
138
+ /** Create with current time */
139
+ constructor();
140
+ /** Create with hour, minute, second, millisecond */
141
+ constructor(hour: number, minute: number, second?: number, millisecond?: number);
142
+ /** Create from tick (millisecond) */
143
+ constructor(tick: number);
144
+ /** Create by extracting time part only from Date object */
145
+ constructor(date: Date);
146
+
147
+ /**
148
+ * Parse a string to create Time instance
149
+ * Supported formats: 'HH:mm:ss', 'HH:mm:ss.fff', 'AM/PM HH:mm:ss', ISO 8601 (extract time part)
150
+ * @throws ArgumentError If unsupported format
151
+ */
152
+ static parse(str: string): Time;
153
+ }
154
+ ```
143
155
 
144
- // 연간 주차
145
- date.getWeekSeqOfYear();
146
- // { year: 2024, weekSeq: 3 }
156
+ **Getters**: `hour`, `minute`, `second`, `millisecond`, `tick`, `isValid`
147
157
 
148
- // 월간 주차
149
- date.getWeekSeqOfMonth();
150
- // { year: 2024, monthSeq: 1, weekSeq: 3 }
158
+ **Immutable setters**: `setHour(hour)`, `setMinute(minute)`, `setSecond(second)`, `setMillisecond(millisecond)`
151
159
 
152
- // 해당 주의 시작일
153
- date.getWeekSeqStartDate();
160
+ **Arithmetic** (24-hour wraparound): `addHours(n)`, `addMinutes(n)`, `addSeconds(n)`, `addMilliseconds(n)`
154
161
 
155
- // 주차 기준 기본 연/월
156
- date.getBaseYearMonthSeqForWeekSeq();
157
- // { year: 2024, monthSeq: 1 }
162
+ **Formatting**: `toFormatString(formatStr)`, `toString()` (default: `"HH:mm:ss.fff"`)
158
163
 
159
- // 연/주차로 날짜 계산
160
- DateOnly.getDateByYearWeekSeq({ year: 2024, weekSeq: 3 });
161
- // 2024년 3주차 시작일 (월요일)
164
+ ---
165
+
166
+ ## `LazyGcMap`
162
167
 
163
- // 월/주차로 날짜 계산
164
- DateOnly.getDateByYearWeekSeq({ year: 2025, month: 1, weekSeq: 3 });
165
- // 2025년 1월 3주차 시작일
168
+ Map with automatic expiration feature. Updates access time in LRU manner; auto-deletes if not accessed for specified time. Supports the `using` statement (`Symbol.dispose`).
166
169
 
167
- // US 스타일 (일요일 시작, 첫 주 최소 1일)
168
- date.getWeekSeqOfYear(0, 1);
170
+ ```typescript
171
+ export class LazyGcMap<TKey, TValue> {
172
+ /**
173
+ * @param options.gcInterval GC interval in ms. Default: 1/10 of expireTime (minimum 1000ms)
174
+ * @param options.expireTime Expiration time in ms since last access
175
+ * @param options.onExpire Callback called on expiration (can be async)
176
+ */
177
+ constructor(options: {
178
+ gcInterval?: number;
179
+ expireTime: number;
180
+ onExpire?: (key: TKey, value: TValue) => void | Promise<void>;
181
+ });
182
+
183
+ get size(): number;
184
+ has(key: TKey): boolean;
185
+ get(key: TKey): TValue | undefined;
186
+ set(key: TKey, value: TValue): void;
187
+ delete(key: TKey): boolean;
188
+ clear(): void;
189
+ getOrCreate(key: TKey, factory: () => TValue): TValue;
190
+ values(): IterableIterator<TValue>;
191
+ keys(): IterableIterator<TKey>;
192
+ entries(): IterableIterator<[TKey, TValue]>;
193
+ dispose(): void;
194
+ [Symbol.dispose](): void;
195
+ }
169
196
  ```
170
197
 
171
- ### 변경/포맷
198
+ **Example:**
172
199
 
173
200
  ```typescript
174
- // 변경 메서드 ( 인스턴스 반환)
175
- date.setYear(2025); date.setMonth(6); date.setDay(20);
176
- date.addYears(1); date.addMonths(3); date.addDays(10);
177
-
178
- // 포맷
179
- date.toFormatString("yyyy-MM-dd"); // "2024-01-15"
180
- date.toString(); // "2024-01-15"
201
+ using map = new LazyGcMap({ gcInterval: 10000, expireTime: 60000 });
202
+ map.set("session", data);
203
+ const val = map.getOrCreate("key", () => computeExpensive());
181
204
  ```
182
205
 
183
206
  ---
184
207
 
185
- ## Time
186
-
187
- 불변 시간 전용 타입 (24시간 래핑).
208
+ ## `Bytes`
188
209
 
189
- ### 생성/파싱
210
+ Binary type alias used instead of `Buffer`.
190
211
 
191
212
  ```typescript
192
- import { Time } from "@simplysm/core-common";
193
-
194
- new Time(); // 현재 시각
195
- new Time(14, 30); // 14:30:00
196
- new Time(14, 30, 15, 500); // 14:30:15.500
197
- new Time(tick); // tick(밀리초)으로 생성
198
- new Time(new Date()); // Date 객체에서 시간 부분만 추출
199
- Time.parse("14:30:00"); // HH:mm:ss
200
- Time.parse("14:30:00.123"); // HH:mm:ss.fff
201
- Time.parse("AM 10:30:00"); // AM/PM HH:mm:ss
202
- Time.parse("2025-01-15T10:30:00Z"); // ISO 8601 (시간 부분만 추출)
213
+ export type Bytes = Uint8Array;
203
214
  ```
204
215
 
205
- ### 속성
216
+ ---
206
217
 
207
- | 속성 | 타입 | 설명 |
208
- |------|------|------|
209
- | `hour` | `number` | 시 (0~23) |
210
- | `minute` | `number` | 분 |
211
- | `second` | `number` | 초 |
212
- | `millisecond` | `number` | 밀리초 |
213
- | `tick` | `number` | 하루 기준 밀리초 |
214
- | `isValid` | `boolean` | 유효성 |
218
+ ## `PrimitiveTypeMap`
215
219
 
216
- ### 24시간 래핑
220
+ Primitive type mapping shared with orm-common.
217
221
 
218
222
  ```typescript
219
- const time = new Time(23, 0);
220
- time.addHours(3); // 02:00:00 (다음날로 넘어감)
221
-
222
- const time2 = new Time(1, 0);
223
- time2.addHours(-3); // 22:00:00 (이전날로 넘어감)
223
+ export type PrimitiveTypeMap = {
224
+ string: string;
225
+ number: number;
226
+ boolean: boolean;
227
+ DateTime: DateTime;
228
+ DateOnly: DateOnly;
229
+ Time: Time;
230
+ Uuid: Uuid;
231
+ Bytes: Bytes;
232
+ };
224
233
  ```
225
234
 
226
- ### 변경/포맷
235
+ ---
236
+
237
+ ## `PrimitiveTypeStr`
227
238
 
228
239
  ```typescript
229
- // 변경 메서드 (새 인스턴스 반환, 24시간 래핑)
230
- time.setHour(10); time.setMinute(45);
231
- time.setSecond(30); time.setMillisecond(500);
232
- time.addHours(2); time.addMinutes(30);
233
- time.addSeconds(30); time.addMilliseconds(500);
234
-
235
- // 포맷
236
- time.toFormatString("HH:mm:ss"); // "14:30:00"
237
- time.toString(); // "14:30:00.000"
240
+ export type PrimitiveTypeStr = keyof PrimitiveTypeMap;
238
241
  ```
239
242
 
240
243
  ---
241
244
 
242
- ## Uuid
243
-
244
- UUID v4 생성/변환. `crypto.getRandomValues` 기반.
245
+ ## `PrimitiveType`
245
246
 
246
247
  ```typescript
247
- import { Uuid } from "@simplysm/core-common";
248
-
249
- const id = Uuid.generate(); // 새 UUID 생성
250
- const fromStr = new Uuid("550e8400-e29b-41d4-a716-446655440000");
251
- const fromBytes = Uuid.fromBytes(bytes); // 16바이트 배열에서 생성 (길이가 16이 아니면 ArgumentError)
252
- id.toString(); // "xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx"
253
- id.toBytes(); // Uint8Array (16 bytes)
248
+ export type PrimitiveType = PrimitiveTypeMap[PrimitiveTypeStr] | undefined;
254
249
  ```
255
250
 
256
251
  ---
257
252
 
258
- ## LazyGcMap
253
+ ## `DeepPartial<T>`
259
254
 
260
- 자동 만료 기능이 있는 LRU 캐시. GC 타이머를 사용하므로 반드시 `dispose()` 또는 `using` 문으로 정리해야 한다.
255
+ Recursively makes all properties of an object optional. Primitive types are kept as-is.
261
256
 
262
257
  ```typescript
263
- import { LazyGcMap } from "@simplysm/core-common";
264
-
265
- const cache = new LazyGcMap<string, object>({
266
- expireTime: 60_000, // 60초 만료 (필수)
267
- gcInterval: 10_000, // 10초마다 GC (기본값: expireTime/10, 최소 1000ms)
268
- onExpire: (key, value) => { /* 정리 로직, async 가능 */ },
269
- });
270
-
271
- cache.set("key", value); // 값 저장 (GC 타이머 시작)
272
- cache.get("key"); // 값 조회 (접근 시 만료 시간 갱신)
273
- cache.getOrCreate("key", () => createValue()); // 없으면 생성
274
- cache.has("key"); // 존재 여부 (접근 시간 갱신 안 함)
275
- cache.delete("key"); // 삭제
276
- cache.clear(); // 전체 삭제 (인스턴스는 재사용 가능)
277
- cache.size; // 저장된 항목 수
278
-
279
- // 이터레이터
280
- for (const value of cache.values()) { /* ... */ }
281
- for (const key of cache.keys()) { /* ... */ }
282
- for (const [key, value] of cache.entries()) { /* ... */ }
283
-
284
- // 정리 (Disposable 지원)
285
- cache.dispose();
286
- // 또는
287
- using cache2 = new LazyGcMap({ expireTime: 30_000 });
258
+ export type DeepPartial<TObject> = Partial<{
259
+ [K in keyof TObject]: TObject[K] extends PrimitiveType ? TObject[K] : DeepPartial<TObject[K]>;
260
+ }>;
288
261
  ```
289
262
 
290
- | 메서드 | 시그니처 | 설명 |
291
- |--------|---------|------|
292
- | `get` | `get(key: TKey): TValue \| undefined` | 값 조회 (만료 갱신) |
293
- | `set` | `set(key: TKey, value: TValue): void` | 값 설정 |
294
- | `getOrCreate` | `getOrCreate(key: TKey, factory: () => TValue): TValue` | 없으면 생성 |
295
- | `has` | `has(key: TKey): boolean` | 존재 여부 (만료 갱신 안 함) |
296
- | `delete` | `delete(key: TKey): boolean` | 삭제 |
297
- | `clear` | `clear(): void` | 전체 삭제 |
298
- | `size` | `number` (getter) | 저장된 항목 수 |
299
- | `values` | `values(): IterableIterator<TValue>` | 값 이터레이터 |
300
- | `keys` | `keys(): IterableIterator<TKey>` | 키 이터레이터 |
301
- | `entries` | `entries(): IterableIterator<[TKey, TValue]>` | 엔트리 이터레이터 |
302
- | `dispose` | `dispose(): void` | GC 타이머 정리 및 데이터 삭제 |
303
-
304
263
  ---
305
264
 
306
- ## Bytes
265
+ ## `Type<T>`
307
266
 
308
- `Uint8Array`의 타입 별칭. `Buffer` 대신 사용한다.
267
+ Constructor type used for dependency injection, factory patterns, and `instanceof` checks.
309
268
 
310
269
  ```typescript
311
- import type { Bytes } from "@simplysm/core-common";
270
+ export interface Type<TInstance> extends Function {
271
+ new (...args: unknown[]): TInstance;
272
+ }
312
273
  ```
313
274
 
314
275
  ---
315
276
 
316
- ## 공통 타입
277
+ ## `env`
278
+
279
+ Unified environment variable accessor. Merges `import.meta.env` and `process.env`. `DEV` is parsed as boolean, `VER` as optional string.
317
280
 
318
281
  ```typescript
319
- // 프리미티브 타입
320
- type PrimitiveTypeMap = {
321
- string: string;
322
- number: number;
323
- boolean: boolean;
324
- DateTime: DateTime;
325
- DateOnly: DateOnly;
326
- Time: Time;
327
- Uuid: Uuid;
328
- Bytes: Bytes;
282
+ export const env: {
283
+ DEV: boolean;
284
+ VER?: string;
285
+ [key: string]: unknown;
329
286
  };
330
-
331
- type PrimitiveTypeStr = keyof PrimitiveTypeMap;
332
- type PrimitiveType = PrimitiveTypeMap[PrimitiveTypeStr] | undefined;
333
-
334
- // 재귀 Partial
335
- type DeepPartial<T> = Partial<{
336
- [K in keyof T]: T[K] extends PrimitiveType ? T[K] : DeepPartial<T[K]>;
337
- }>;
338
-
339
- // 생성자 타입 (DI용)
340
- interface Type<T> extends Function { new (...args: unknown[]): T; }
341
287
  ```