reltype 0.1.1
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/CHANGELOG.md +67 -0
- package/LICENSE +21 -0
- package/README.md +952 -0
- package/dist/configs/env.d.ts +14 -0
- package/dist/configs/env.d.ts.map +1 -0
- package/dist/configs/env.js +46 -0
- package/dist/configs/index.d.ts +2 -0
- package/dist/configs/index.d.ts.map +1 -0
- package/dist/configs/index.js +17 -0
- package/dist/features/connection/index.d.ts +3 -0
- package/dist/features/connection/index.d.ts.map +1 -0
- package/dist/features/connection/index.js +18 -0
- package/dist/features/connection/pool.d.ts +42 -0
- package/dist/features/connection/pool.d.ts.map +1 -0
- package/dist/features/connection/pool.js +131 -0
- package/dist/features/connection/tx.d.ts +10 -0
- package/dist/features/connection/tx.d.ts.map +1 -0
- package/dist/features/connection/tx.js +37 -0
- package/dist/features/query/builder.d.ts +253 -0
- package/dist/features/query/builder.d.ts.map +1 -0
- package/dist/features/query/builder.js +613 -0
- package/dist/features/query/bulkInsert.d.ts +10 -0
- package/dist/features/query/bulkInsert.d.ts.map +1 -0
- package/dist/features/query/bulkInsert.js +30 -0
- package/dist/features/query/delete.d.ts +8 -0
- package/dist/features/query/delete.d.ts.map +1 -0
- package/dist/features/query/delete.js +15 -0
- package/dist/features/query/index.d.ts +10 -0
- package/dist/features/query/index.d.ts.map +1 -0
- package/dist/features/query/index.js +25 -0
- package/dist/features/query/insert.d.ts +7 -0
- package/dist/features/query/insert.d.ts.map +1 -0
- package/dist/features/query/insert.js +18 -0
- package/dist/features/query/interfaces/Advanced.d.ts +177 -0
- package/dist/features/query/interfaces/Advanced.d.ts.map +1 -0
- package/dist/features/query/interfaces/Advanced.js +2 -0
- package/dist/features/query/interfaces/Order.d.ts +6 -0
- package/dist/features/query/interfaces/Order.d.ts.map +1 -0
- package/dist/features/query/interfaces/Order.js +2 -0
- package/dist/features/query/interfaces/Query.d.ts +6 -0
- package/dist/features/query/interfaces/Query.d.ts.map +1 -0
- package/dist/features/query/interfaces/Query.js +2 -0
- package/dist/features/query/interfaces/Where.d.ts +3 -0
- package/dist/features/query/interfaces/Where.d.ts.map +1 -0
- package/dist/features/query/interfaces/Where.js +2 -0
- package/dist/features/query/interfaces/index.d.ts +5 -0
- package/dist/features/query/interfaces/index.d.ts.map +1 -0
- package/dist/features/query/interfaces/index.js +20 -0
- package/dist/features/query/select.d.ts +15 -0
- package/dist/features/query/select.d.ts.map +1 -0
- package/dist/features/query/select.js +33 -0
- package/dist/features/query/update.d.ts +8 -0
- package/dist/features/query/update.d.ts.map +1 -0
- package/dist/features/query/update.js +28 -0
- package/dist/features/query/upsert.d.ts +11 -0
- package/dist/features/query/upsert.d.ts.map +1 -0
- package/dist/features/query/upsert.js +31 -0
- package/dist/features/query/where.d.ts +11 -0
- package/dist/features/query/where.d.ts.map +1 -0
- package/dist/features/query/where.js +30 -0
- package/dist/features/repository/base.d.ts +107 -0
- package/dist/features/repository/base.d.ts.map +1 -0
- package/dist/features/repository/base.js +243 -0
- package/dist/features/repository/create.d.ts +13 -0
- package/dist/features/repository/create.d.ts.map +1 -0
- package/dist/features/repository/create.js +16 -0
- package/dist/features/repository/index.d.ts +4 -0
- package/dist/features/repository/index.d.ts.map +1 -0
- package/dist/features/repository/index.js +19 -0
- package/dist/features/repository/interfaces/Find.d.ts +9 -0
- package/dist/features/repository/interfaces/Find.d.ts.map +1 -0
- package/dist/features/repository/interfaces/Find.js +2 -0
- package/dist/features/repository/interfaces/Repo.d.ts +29 -0
- package/dist/features/repository/interfaces/Repo.d.ts.map +1 -0
- package/dist/features/repository/interfaces/Repo.js +2 -0
- package/dist/features/repository/interfaces/index.d.ts +3 -0
- package/dist/features/repository/interfaces/index.d.ts.map +1 -0
- package/dist/features/repository/interfaces/index.js +18 -0
- package/dist/features/schema/column.d.ts +62 -0
- package/dist/features/schema/column.d.ts.map +1 -0
- package/dist/features/schema/column.js +74 -0
- package/dist/features/schema/index.d.ts +4 -0
- package/dist/features/schema/index.d.ts.map +1 -0
- package/dist/features/schema/index.js +19 -0
- package/dist/features/schema/interfaces/Column.d.ts +19 -0
- package/dist/features/schema/interfaces/Column.d.ts.map +1 -0
- package/dist/features/schema/interfaces/Column.js +2 -0
- package/dist/features/schema/interfaces/Infer.d.ts +20 -0
- package/dist/features/schema/interfaces/Infer.d.ts.map +1 -0
- package/dist/features/schema/interfaces/Infer.js +2 -0
- package/dist/features/schema/interfaces/Table.d.ts +7 -0
- package/dist/features/schema/interfaces/Table.d.ts.map +1 -0
- package/dist/features/schema/interfaces/Table.js +2 -0
- package/dist/features/schema/interfaces/index.d.ts +4 -0
- package/dist/features/schema/interfaces/index.d.ts.map +1 -0
- package/dist/features/schema/interfaces/index.js +19 -0
- package/dist/features/schema/table.d.ts +14 -0
- package/dist/features/schema/table.d.ts.map +1 -0
- package/dist/features/schema/table.js +17 -0
- package/dist/features/transform/case.d.ts +19 -0
- package/dist/features/transform/case.d.ts.map +1 -0
- package/dist/features/transform/case.js +32 -0
- package/dist/features/transform/index.d.ts +3 -0
- package/dist/features/transform/index.d.ts.map +1 -0
- package/dist/features/transform/index.js +18 -0
- package/dist/features/transform/mapper.d.ts +9 -0
- package/dist/features/transform/mapper.d.ts.map +1 -0
- package/dist/features/transform/mapper.js +17 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +63 -0
- package/dist/interfaces/DatabaseConfig.d.ts +25 -0
- package/dist/interfaces/DatabaseConfig.d.ts.map +1 -0
- package/dist/interfaces/DatabaseConfig.js +2 -0
- package/dist/interfaces/EnvSource.d.ts +4 -0
- package/dist/interfaces/EnvSource.d.ts.map +1 -0
- package/dist/interfaces/EnvSource.js +2 -0
- package/dist/interfaces/PostgresDriverOptions.d.ts +20 -0
- package/dist/interfaces/PostgresDriverOptions.d.ts.map +1 -0
- package/dist/interfaces/PostgresDriverOptions.js +2 -0
- package/dist/interfaces/index.d.ts +3 -0
- package/dist/interfaces/index.d.ts.map +1 -0
- package/dist/interfaces/index.js +18 -0
- package/dist/utils/dbError.d.ts +61 -0
- package/dist/utils/dbError.d.ts.map +1 -0
- package/dist/utils/dbError.js +122 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +19 -0
- package/dist/utils/logger.d.ts +63 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +138 -0
- package/dist/utils/reader.d.ts +49 -0
- package/dist/utils/reader.d.ts.map +1 -0
- package/dist/utils/reader.js +159 -0
- package/package.json +73 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export type LogLevel = 'debug' | 'info' | 'log' | 'warn' | 'error';
|
|
2
|
+
/** 로그 출력 포맷 */
|
|
3
|
+
export type LogFormat = 'text' | 'json';
|
|
4
|
+
export interface LoggerConfig {
|
|
5
|
+
/** 로거 활성화 여부 (기본값: true) */
|
|
6
|
+
enabled?: boolean;
|
|
7
|
+
/** 최소 출력 로그 레벨 (기본값: "info") */
|
|
8
|
+
level?: LogLevel;
|
|
9
|
+
/** 출력 포맷 — text: 컬러 텍스트, json: 구조화된 JSON (기본값: "text") */
|
|
10
|
+
format?: LogFormat;
|
|
11
|
+
/** ANSI 색상 사용 여부 (format=text 일 때만 적용, 기본값: TTY 지원 여부) */
|
|
12
|
+
enableColors?: boolean;
|
|
13
|
+
/** 타임스탬프 출력 여부 (기본값: true) */
|
|
14
|
+
enableTimestamp?: boolean;
|
|
15
|
+
/** 로그 prefix (예: "[Pool]", "[Repo]") */
|
|
16
|
+
prefix?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 범용 Logger 클래스.
|
|
20
|
+
*
|
|
21
|
+
* - format='text' : ANSI 컬러 텍스트 (개발 환경)
|
|
22
|
+
* - format='json' : 구조화된 JSON 한 줄 출력 (프로덕션 / 로그 수집기 연동)
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* // 텍스트 포맷 (개발)
|
|
27
|
+
* const logger = new Logger({ prefix: '[DB]', level: 'debug' });
|
|
28
|
+
*
|
|
29
|
+
* // JSON 포맷 (프로덕션)
|
|
30
|
+
* const logger = new Logger({ prefix: '[DB]', format: 'json' });
|
|
31
|
+
*
|
|
32
|
+
* // env 기반 자동 설정
|
|
33
|
+
* const logger = Logger.fromEnv(process.env, { prefix: '[DB]' });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare class Logger {
|
|
37
|
+
private readonly enabled;
|
|
38
|
+
private readonly level;
|
|
39
|
+
private readonly format;
|
|
40
|
+
private readonly enableColors;
|
|
41
|
+
private readonly enableTimestamp;
|
|
42
|
+
private readonly prefix?;
|
|
43
|
+
constructor(config?: LoggerConfig);
|
|
44
|
+
/**
|
|
45
|
+
* 환경 변수에서 Logger 인스턴스를 생성합니다.
|
|
46
|
+
*
|
|
47
|
+
* 지원 환경 변수:
|
|
48
|
+
* - LOGGER / LOG_ENABLED: "true" | "1" | "yes" | "on"
|
|
49
|
+
* - LOG_LEVEL: "debug" | "info" | "log" | "warn" | "error"
|
|
50
|
+
* - LOG_FORMAT: "text" | "json"
|
|
51
|
+
*/
|
|
52
|
+
static fromEnv(env: Record<string, string | undefined>, baseConfig?: LoggerConfig): Logger;
|
|
53
|
+
debug(...args: unknown[]): void;
|
|
54
|
+
info(...args: unknown[]): void;
|
|
55
|
+
log(...args: unknown[]): void;
|
|
56
|
+
warn(...args: unknown[]): void;
|
|
57
|
+
error(...args: unknown[]): void;
|
|
58
|
+
private shouldEmit;
|
|
59
|
+
private emit;
|
|
60
|
+
private emitJson;
|
|
61
|
+
private emitText;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;AAEnE,eAAe;AACf,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAExC,MAAM,WAAW,YAAY;IAC3B,4BAA4B;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gCAAgC;IAChC,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,8BAA8B;IAC9B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAsCD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAW;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;IACvC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAU;IAC1C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;gBAErB,MAAM,GAAE,YAAiB;IAarC;;;;;;;OAOG;IACH,MAAM,CAAC,OAAO,CACZ,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EACvC,UAAU,GAAE,YAAiB,GAC5B,MAAM;IAqBT,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAC/B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAC9B,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAC7B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAC9B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAE/B,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,IAAI;IAUZ,OAAO,CAAC,QAAQ;IAwBhB,OAAO,CAAC,QAAQ;CAmBjB"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Logger = void 0;
|
|
4
|
+
const ANSI = {
|
|
5
|
+
reset: '\x1b[0m',
|
|
6
|
+
gray: '\x1b[90m',
|
|
7
|
+
cyan: '\x1b[36m',
|
|
8
|
+
white: '\x1b[37m',
|
|
9
|
+
yellow: '\x1b[33m',
|
|
10
|
+
red: '\x1b[31m',
|
|
11
|
+
};
|
|
12
|
+
const LEVEL_COLOR = {
|
|
13
|
+
debug: ANSI.gray,
|
|
14
|
+
info: ANSI.cyan,
|
|
15
|
+
log: ANSI.white,
|
|
16
|
+
warn: ANSI.yellow,
|
|
17
|
+
error: ANSI.red,
|
|
18
|
+
};
|
|
19
|
+
const LEVEL_PRIORITY = {
|
|
20
|
+
debug: 0,
|
|
21
|
+
info: 1,
|
|
22
|
+
log: 2,
|
|
23
|
+
warn: 3,
|
|
24
|
+
error: 4,
|
|
25
|
+
};
|
|
26
|
+
const VALID_LEVELS = ['debug', 'info', 'log', 'warn', 'error'];
|
|
27
|
+
/**
|
|
28
|
+
* 범용 Logger 클래스.
|
|
29
|
+
*
|
|
30
|
+
* - format='text' : ANSI 컬러 텍스트 (개발 환경)
|
|
31
|
+
* - format='json' : 구조화된 JSON 한 줄 출력 (프로덕션 / 로그 수집기 연동)
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* // 텍스트 포맷 (개발)
|
|
36
|
+
* const logger = new Logger({ prefix: '[DB]', level: 'debug' });
|
|
37
|
+
*
|
|
38
|
+
* // JSON 포맷 (프로덕션)
|
|
39
|
+
* const logger = new Logger({ prefix: '[DB]', format: 'json' });
|
|
40
|
+
*
|
|
41
|
+
* // env 기반 자동 설정
|
|
42
|
+
* const logger = Logger.fromEnv(process.env, { prefix: '[DB]' });
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
class Logger {
|
|
46
|
+
constructor(config = {}) {
|
|
47
|
+
const nodeProcess = globalThis.process;
|
|
48
|
+
const ttySupportsColor = !!nodeProcess?.stdout?.isTTY;
|
|
49
|
+
this.enabled = config.enabled ?? true;
|
|
50
|
+
this.level = config.level ?? 'info';
|
|
51
|
+
this.format = config.format ?? 'text';
|
|
52
|
+
this.enableColors = config.enableColors ?? ttySupportsColor;
|
|
53
|
+
this.enableTimestamp = config.enableTimestamp ?? true;
|
|
54
|
+
this.prefix = config.prefix;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* 환경 변수에서 Logger 인스턴스를 생성합니다.
|
|
58
|
+
*
|
|
59
|
+
* 지원 환경 변수:
|
|
60
|
+
* - LOGGER / LOG_ENABLED: "true" | "1" | "yes" | "on"
|
|
61
|
+
* - LOG_LEVEL: "debug" | "info" | "log" | "warn" | "error"
|
|
62
|
+
* - LOG_FORMAT: "text" | "json"
|
|
63
|
+
*/
|
|
64
|
+
static fromEnv(env, baseConfig = {}) {
|
|
65
|
+
const rawEnabled = env.LOGGER ?? env.LOG_ENABLED;
|
|
66
|
+
const rawLevel = env.LOG_LEVEL?.toLowerCase();
|
|
67
|
+
const rawFormat = env.LOG_FORMAT?.toLowerCase();
|
|
68
|
+
const enabled = rawEnabled !== undefined
|
|
69
|
+
? ['true', '1', 'yes', 'on'].includes(rawEnabled.toLowerCase())
|
|
70
|
+
: baseConfig.enabled ?? false;
|
|
71
|
+
const level = rawLevel && VALID_LEVELS.includes(rawLevel)
|
|
72
|
+
? rawLevel
|
|
73
|
+
: baseConfig.level ?? 'info';
|
|
74
|
+
const format = rawFormat === 'json' ? 'json' : baseConfig.format ?? 'text';
|
|
75
|
+
return new Logger({ ...baseConfig, enabled, level, format });
|
|
76
|
+
}
|
|
77
|
+
debug(...args) { this.emit('debug', args); }
|
|
78
|
+
info(...args) { this.emit('info', args); }
|
|
79
|
+
log(...args) { this.emit('log', args); }
|
|
80
|
+
warn(...args) { this.emit('warn', args); }
|
|
81
|
+
error(...args) { this.emit('error', args); }
|
|
82
|
+
shouldEmit(level) {
|
|
83
|
+
return this.enabled && LEVEL_PRIORITY[level] >= LEVEL_PRIORITY[this.level];
|
|
84
|
+
}
|
|
85
|
+
emit(level, args) {
|
|
86
|
+
if (!this.shouldEmit(level))
|
|
87
|
+
return;
|
|
88
|
+
if (this.format === 'json') {
|
|
89
|
+
this.emitJson(level, args);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
this.emitText(level, args);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
emitJson(level, args) {
|
|
96
|
+
const [first, ...rest] = args;
|
|
97
|
+
const msg = typeof first === 'string' ? first : JSON.stringify(first);
|
|
98
|
+
const meta = rest.length > 0 ? rest : undefined;
|
|
99
|
+
const entry = {
|
|
100
|
+
ts: new Date().toISOString(),
|
|
101
|
+
level: level.toUpperCase(),
|
|
102
|
+
msg,
|
|
103
|
+
...(this.prefix && { prefix: this.prefix }),
|
|
104
|
+
...(meta && { meta }),
|
|
105
|
+
};
|
|
106
|
+
const output = JSON.stringify(entry);
|
|
107
|
+
if (level === 'error') {
|
|
108
|
+
console.error(output);
|
|
109
|
+
}
|
|
110
|
+
else if (level === 'warn') {
|
|
111
|
+
console.warn(output);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
console.log(output);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
emitText(level, args) {
|
|
118
|
+
const color = this.enableColors ? LEVEL_COLOR[level] : '';
|
|
119
|
+
const reset = this.enableColors ? ANSI.reset : '';
|
|
120
|
+
const parts = [];
|
|
121
|
+
if (this.enableTimestamp)
|
|
122
|
+
parts.push(new Date().toISOString());
|
|
123
|
+
if (this.prefix)
|
|
124
|
+
parts.push(this.prefix);
|
|
125
|
+
parts.push(level.toUpperCase());
|
|
126
|
+
const prefixStr = color ? `${color}${parts.join(' ')}${reset}` : parts.join(' ');
|
|
127
|
+
if (level === 'error') {
|
|
128
|
+
console.error(prefixStr, ...args);
|
|
129
|
+
}
|
|
130
|
+
else if (level === 'warn') {
|
|
131
|
+
console.warn(prefixStr, ...args);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
console.log(prefixStr, ...args);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
exports.Logger = Logger;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { EnvSource, PostgresDriverOptions } from "../interfaces";
|
|
2
|
+
/**
|
|
3
|
+
* 기본 `Record<string, string | undefined>` 형태의 객체에서
|
|
4
|
+
* 환경 변수를 읽어오는 구현체입니다.
|
|
5
|
+
*/
|
|
6
|
+
export declare class NodeEnvSource implements EnvSource {
|
|
7
|
+
private readonly env;
|
|
8
|
+
constructor(env: Record<string, string | undefined>);
|
|
9
|
+
get(key: string): string | undefined;
|
|
10
|
+
}
|
|
11
|
+
export declare function parseString(key: string, value: string): string;
|
|
12
|
+
export declare function parseNumber(key: string, value: string): number;
|
|
13
|
+
export declare function parseBoolean(key: string, value: string): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* `process.env` 와 같은 환경 객체에서 타입까지 안전하게 읽어오는 유틸 함수입니다.
|
|
16
|
+
*
|
|
17
|
+
* 기본값의 타입을 기준으로 파서를 자동 선택합니다.
|
|
18
|
+
* - string → `parseString`
|
|
19
|
+
* - number → `parseNumber`
|
|
20
|
+
* - boolean → `parseBoolean`
|
|
21
|
+
*/
|
|
22
|
+
export declare function readEnv<T extends string | number | boolean>(env: Record<string, string | undefined>, key: string, defaultValue: T): T;
|
|
23
|
+
export declare class PostgresConfig {
|
|
24
|
+
readonly host?: string;
|
|
25
|
+
readonly port?: number;
|
|
26
|
+
readonly database?: string;
|
|
27
|
+
readonly user?: string;
|
|
28
|
+
readonly password?: string;
|
|
29
|
+
readonly connectionString?: string;
|
|
30
|
+
readonly ssl?: boolean;
|
|
31
|
+
readonly max?: number;
|
|
32
|
+
readonly idleTimeoutMillis?: number;
|
|
33
|
+
readonly connectionTimeoutMillis?: number;
|
|
34
|
+
readonly allowExitOnIdle?: boolean;
|
|
35
|
+
readonly statement_timeout?: number;
|
|
36
|
+
readonly query_timeout?: number;
|
|
37
|
+
readonly application_name?: string;
|
|
38
|
+
readonly parseInputDatesAsUTC?: boolean;
|
|
39
|
+
readonly keepAlive?: boolean;
|
|
40
|
+
readonly keepAliveInitialDelayMillis?: number;
|
|
41
|
+
private constructor();
|
|
42
|
+
static fromEnv(source: EnvSource): PostgresConfig;
|
|
43
|
+
private validate;
|
|
44
|
+
toDriverOptions(): PostgresDriverOptions;
|
|
45
|
+
toSafeJSON(): this & {
|
|
46
|
+
password: string | undefined;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=reader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../src/utils/reader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAEjE;;;GAGG;AACH,qBAAa,aAAc,YAAW,SAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAEpE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;CAGrC;AAID,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAK9D;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAW9D;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAOhE;AAED;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,OAAO,EACzD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EACvC,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,CAAC,GACd,CAAC,CAgBH;AA0BD,qBAAa,cAAc;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAEnC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IAC1C,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IAE9C,OAAO;IAKP,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,GAAG,cAAc;IAiEjD,OAAO,CAAC,QAAQ;IAYhB,eAAe,IAAI,qBAAqB;IAIxC,UAAU;;;CAMX"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PostgresConfig = exports.NodeEnvSource = void 0;
|
|
4
|
+
exports.parseString = parseString;
|
|
5
|
+
exports.parseNumber = parseNumber;
|
|
6
|
+
exports.parseBoolean = parseBoolean;
|
|
7
|
+
exports.readEnv = readEnv;
|
|
8
|
+
/**
|
|
9
|
+
* 기본 `Record<string, string | undefined>` 형태의 객체에서
|
|
10
|
+
* 환경 변수를 읽어오는 구현체입니다.
|
|
11
|
+
*/
|
|
12
|
+
class NodeEnvSource {
|
|
13
|
+
constructor(env) {
|
|
14
|
+
this.env = env;
|
|
15
|
+
}
|
|
16
|
+
get(key) {
|
|
17
|
+
return this.env[key];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.NodeEnvSource = NodeEnvSource;
|
|
21
|
+
const isEmpty = (v) => v.trim() === "";
|
|
22
|
+
function parseString(key, value) {
|
|
23
|
+
if (isEmpty(value)) {
|
|
24
|
+
throw new Error(`Empty value provided for ${key}`);
|
|
25
|
+
}
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
function parseNumber(key, value) {
|
|
29
|
+
if (isEmpty(value)) {
|
|
30
|
+
throw new Error(`Empty value provided for ${key}`);
|
|
31
|
+
}
|
|
32
|
+
const num = Number(value);
|
|
33
|
+
if (!Number.isFinite(num)) {
|
|
34
|
+
throw new Error(`Invalid number value for ${key}: ${value}`);
|
|
35
|
+
}
|
|
36
|
+
return num;
|
|
37
|
+
}
|
|
38
|
+
function parseBoolean(key, value) {
|
|
39
|
+
const normalized = value.trim().toLowerCase();
|
|
40
|
+
if (["true", "1"].includes(normalized))
|
|
41
|
+
return true;
|
|
42
|
+
if (["false", "0"].includes(normalized))
|
|
43
|
+
return false;
|
|
44
|
+
throw new Error(`Invalid boolean value for ${key}: ${value}`);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* `process.env` 와 같은 환경 객체에서 타입까지 안전하게 읽어오는 유틸 함수입니다.
|
|
48
|
+
*
|
|
49
|
+
* 기본값의 타입을 기준으로 파서를 자동 선택합니다.
|
|
50
|
+
* - string → `parseString`
|
|
51
|
+
* - number → `parseNumber`
|
|
52
|
+
* - boolean → `parseBoolean`
|
|
53
|
+
*/
|
|
54
|
+
function readEnv(env, key, defaultValue) {
|
|
55
|
+
const raw = env[key];
|
|
56
|
+
if (raw === undefined) {
|
|
57
|
+
return defaultValue;
|
|
58
|
+
}
|
|
59
|
+
if (typeof defaultValue === "number") {
|
|
60
|
+
return parseNumber(key, raw);
|
|
61
|
+
}
|
|
62
|
+
if (typeof defaultValue === "boolean") {
|
|
63
|
+
return parseBoolean(key, raw);
|
|
64
|
+
}
|
|
65
|
+
return parseString(key, raw);
|
|
66
|
+
}
|
|
67
|
+
// ===== Postgres config builder =====
|
|
68
|
+
const DB_ENV_KEYS = {
|
|
69
|
+
CONNECTION_STRING: "DB_CONNECTION_STRING",
|
|
70
|
+
HOST: "DB_HOST",
|
|
71
|
+
PORT: "DB_PORT",
|
|
72
|
+
NAME: "DB_NAME",
|
|
73
|
+
USER: "DB_USER",
|
|
74
|
+
PASSWORD: "DB_PASSWORD",
|
|
75
|
+
SSL: "DB_SSL",
|
|
76
|
+
MAX: "DB_MAX",
|
|
77
|
+
IDLE_TIMEOUT: "DB_IDLE_TIMEOUT",
|
|
78
|
+
CONNECTION_TIMEOUT: "DB_CONNECTION_TIMEOUT",
|
|
79
|
+
ALLOW_EXIT_ON_IDLE: "DB_ALLOW_EXIT_ON_IDLE",
|
|
80
|
+
STATEMENT_TIMEOUT: "DB_STATEMENT_TIMEOUT",
|
|
81
|
+
QUERY_TIMEOUT: "DB_QUERY_TIMEOUT",
|
|
82
|
+
APPLICATION_NAME: "DB_APPLICATION_NAME",
|
|
83
|
+
PARSE_INPUT_DATES_AS_UTC: "DB_PARSE_INPUT_DATES_AS_UTC",
|
|
84
|
+
KEEP_ALIVE: "DB_KEEP_ALIVE",
|
|
85
|
+
KEEP_ALIVE_INITIAL_DELAY: "DB_KEEP_ALIVE_INITIAL_DELAY",
|
|
86
|
+
};
|
|
87
|
+
class PostgresConfig {
|
|
88
|
+
constructor(options) {
|
|
89
|
+
Object.assign(this, options);
|
|
90
|
+
this.validate();
|
|
91
|
+
}
|
|
92
|
+
static fromEnv(source) {
|
|
93
|
+
const get = (key) => source.get(key);
|
|
94
|
+
const getOptionalNumber = (key) => {
|
|
95
|
+
const raw = get(key);
|
|
96
|
+
return raw !== undefined ? parseNumber(key, raw) : undefined;
|
|
97
|
+
};
|
|
98
|
+
const getOptionalBoolean = (key) => {
|
|
99
|
+
const raw = get(key);
|
|
100
|
+
return raw !== undefined ? parseBoolean(key, raw) : undefined;
|
|
101
|
+
};
|
|
102
|
+
const connectionString = get(DB_ENV_KEYS.CONNECTION_STRING);
|
|
103
|
+
// connectionString 우선 정책
|
|
104
|
+
if (connectionString) {
|
|
105
|
+
return new PostgresConfig({
|
|
106
|
+
connectionString: parseString(DB_ENV_KEYS.CONNECTION_STRING, connectionString),
|
|
107
|
+
ssl: getOptionalBoolean(DB_ENV_KEYS.SSL),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
const database = get(DB_ENV_KEYS.NAME);
|
|
111
|
+
if (!database) {
|
|
112
|
+
throw new Error("DB_NAME is required when DB_CONNECTION_STRING is not set");
|
|
113
|
+
}
|
|
114
|
+
const portRaw = get(DB_ENV_KEYS.PORT);
|
|
115
|
+
if (!portRaw) {
|
|
116
|
+
throw new Error("DB_PORT is required when DB_CONNECTION_STRING is not set");
|
|
117
|
+
}
|
|
118
|
+
return new PostgresConfig({
|
|
119
|
+
host: get(DB_ENV_KEYS.HOST) ?? "127.0.0.1",
|
|
120
|
+
port: get(DB_ENV_KEYS.PORT)
|
|
121
|
+
? parseNumber(DB_ENV_KEYS.PORT, portRaw)
|
|
122
|
+
: 5432,
|
|
123
|
+
database: parseString(DB_ENV_KEYS.NAME, database),
|
|
124
|
+
user: get(DB_ENV_KEYS.USER) ?? "postgres",
|
|
125
|
+
password: get(DB_ENV_KEYS.PASSWORD) ?? "postgres",
|
|
126
|
+
ssl: getOptionalBoolean(DB_ENV_KEYS.SSL),
|
|
127
|
+
max: getOptionalNumber(DB_ENV_KEYS.MAX),
|
|
128
|
+
idleTimeoutMillis: getOptionalNumber(DB_ENV_KEYS.IDLE_TIMEOUT),
|
|
129
|
+
connectionTimeoutMillis: getOptionalNumber(DB_ENV_KEYS.CONNECTION_TIMEOUT),
|
|
130
|
+
allowExitOnIdle: getOptionalBoolean(DB_ENV_KEYS.ALLOW_EXIT_ON_IDLE),
|
|
131
|
+
statement_timeout: getOptionalNumber(DB_ENV_KEYS.STATEMENT_TIMEOUT),
|
|
132
|
+
query_timeout: getOptionalNumber(DB_ENV_KEYS.QUERY_TIMEOUT),
|
|
133
|
+
application_name: get(DB_ENV_KEYS.APPLICATION_NAME),
|
|
134
|
+
parseInputDatesAsUTC: getOptionalBoolean(DB_ENV_KEYS.PARSE_INPUT_DATES_AS_UTC),
|
|
135
|
+
keepAlive: getOptionalBoolean(DB_ENV_KEYS.KEEP_ALIVE),
|
|
136
|
+
keepAliveInitialDelayMillis: getOptionalNumber(DB_ENV_KEYS.KEEP_ALIVE_INITIAL_DELAY),
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
validate() {
|
|
140
|
+
if (this.port !== undefined) {
|
|
141
|
+
if (this.port <= 0 || this.port > 65535) {
|
|
142
|
+
throw new Error(`Invalid port range: ${this.port}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (this.max !== undefined && this.max <= 0) {
|
|
146
|
+
throw new Error(`DB_MAX must be greater than 0`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
toDriverOptions() {
|
|
150
|
+
return { ...this };
|
|
151
|
+
}
|
|
152
|
+
toSafeJSON() {
|
|
153
|
+
return {
|
|
154
|
+
...this,
|
|
155
|
+
password: this.password ? "***" : undefined,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
exports.PostgresConfig = PostgresConfig;
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "reltype",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Type-first relational modeling for PostgreSQL in TypeScript. Fluent query builder with automatic camelCase ↔ snake_case conversion, CRUD, streaming, cursor pagination, and hooks.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"require": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE",
|
|
17
|
+
"CHANGELOG.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc -p tsconfig.build.json --noEmit false",
|
|
21
|
+
"typecheck": "tsc --noEmit",
|
|
22
|
+
"prepublishOnly": "npm run typecheck && npm run build",
|
|
23
|
+
"dev": "nodemon --exec ts-node src/_test/index.ts"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"postgresql",
|
|
27
|
+
"postgres",
|
|
28
|
+
"pg",
|
|
29
|
+
"orm",
|
|
30
|
+
"query-builder",
|
|
31
|
+
"typescript",
|
|
32
|
+
"type-safe",
|
|
33
|
+
"camelcase",
|
|
34
|
+
"snake-case",
|
|
35
|
+
"repository-pattern",
|
|
36
|
+
"crud",
|
|
37
|
+
"pagination",
|
|
38
|
+
"cursor-pagination",
|
|
39
|
+
"streaming",
|
|
40
|
+
"fluent",
|
|
41
|
+
"relational",
|
|
42
|
+
"database"
|
|
43
|
+
],
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "https://github.com/psh-suhyun/reltype.git"
|
|
47
|
+
},
|
|
48
|
+
"bugs": {
|
|
49
|
+
"url": "https://github.com/psh-suhyun/reltype/issues"
|
|
50
|
+
},
|
|
51
|
+
"homepage": "https://github.com/psh-suhyun/reltype#readme",
|
|
52
|
+
"author": "psh-suhyun",
|
|
53
|
+
"license": "MIT",
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=16.0.0",
|
|
56
|
+
"npm": ">=7.0.0"
|
|
57
|
+
},
|
|
58
|
+
"peerDependencies": {
|
|
59
|
+
"pg": ">=8.0.0"
|
|
60
|
+
},
|
|
61
|
+
"dependencies": {
|
|
62
|
+
"dotenv": "^17.3.1"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@types/express": "^4.17.25",
|
|
66
|
+
"@types/pg": "^8.16.0",
|
|
67
|
+
"express": "^5.2.1",
|
|
68
|
+
"nodemon": "^3.1.11",
|
|
69
|
+
"pg": "^8.18.0",
|
|
70
|
+
"tspec": "^0.2.11",
|
|
71
|
+
"typescript": "^5.9.3"
|
|
72
|
+
}
|
|
73
|
+
}
|