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,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./Column"), exports);
|
|
18
|
+
__exportStar(require("./Table"), exports);
|
|
19
|
+
__exportStar(require("./Infer"), exports);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TableDef, Cols } from './interfaces/Table';
|
|
2
|
+
/**
|
|
3
|
+
* 테이블 정의를 생성합니다.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* const usersTable = defineTable('users', {
|
|
8
|
+
* id: col.serial().primaryKey(),
|
|
9
|
+
* name: col.varchar(255).notNull(),
|
|
10
|
+
* });
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare function defineTable<TName extends string, TCols extends Cols>(name: TName, cols: TCols): TableDef<TName, TCols>;
|
|
14
|
+
//# sourceMappingURL=table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../src/features/schema/table.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAEpD;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,KAAK,SAAS,MAAM,EAAE,KAAK,SAAS,IAAI,EAClE,IAAI,EAAE,KAAK,EACX,IAAI,EAAE,KAAK,GACV,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAExB"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defineTable = defineTable;
|
|
4
|
+
/**
|
|
5
|
+
* 테이블 정의를 생성합니다.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* const usersTable = defineTable('users', {
|
|
10
|
+
* id: col.serial().primaryKey(),
|
|
11
|
+
* name: col.varchar(255).notNull(),
|
|
12
|
+
* });
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
function defineTable(name, cols) {
|
|
16
|
+
return { name, cols };
|
|
17
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* snake_case 문자열을 camelCase로 변환합니다.
|
|
3
|
+
* 예: "first_name" → "firstName"
|
|
4
|
+
*/
|
|
5
|
+
export declare function toCamel(str: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* camelCase 문자열을 snake_case로 변환합니다.
|
|
8
|
+
* 예: "firstName" → "first_name"
|
|
9
|
+
*/
|
|
10
|
+
export declare function toSnake(str: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* 객체의 모든 key를 camelCase로 변환합니다.
|
|
13
|
+
*/
|
|
14
|
+
export declare function keysToCamel(obj: Record<string, unknown>): Record<string, unknown>;
|
|
15
|
+
/**
|
|
16
|
+
* 객체의 모든 key를 snake_case로 변환합니다.
|
|
17
|
+
*/
|
|
18
|
+
export declare function keysToSnake(obj: Record<string, unknown>): Record<string, unknown>;
|
|
19
|
+
//# sourceMappingURL=case.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"case.d.ts","sourceRoot":"","sources":["../../../src/features/transform/case.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAIjF;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAIjF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toCamel = toCamel;
|
|
4
|
+
exports.toSnake = toSnake;
|
|
5
|
+
exports.keysToCamel = keysToCamel;
|
|
6
|
+
exports.keysToSnake = keysToSnake;
|
|
7
|
+
/**
|
|
8
|
+
* snake_case 문자열을 camelCase로 변환합니다.
|
|
9
|
+
* 예: "first_name" → "firstName"
|
|
10
|
+
*/
|
|
11
|
+
function toCamel(str) {
|
|
12
|
+
return str.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* camelCase 문자열을 snake_case로 변환합니다.
|
|
16
|
+
* 예: "firstName" → "first_name"
|
|
17
|
+
*/
|
|
18
|
+
function toSnake(str) {
|
|
19
|
+
return str.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 객체의 모든 key를 camelCase로 변환합니다.
|
|
23
|
+
*/
|
|
24
|
+
function keysToCamel(obj) {
|
|
25
|
+
return Object.fromEntries(Object.entries(obj).map(([k, v]) => [toCamel(k), v]));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 객체의 모든 key를 snake_case로 변환합니다.
|
|
29
|
+
*/
|
|
30
|
+
function keysToSnake(obj) {
|
|
31
|
+
return Object.fromEntries(Object.entries(obj).map(([k, v]) => [toSnake(k), v]));
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/transform/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./case"), exports);
|
|
18
|
+
__exportStar(require("./mapper"), exports);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DB raw row를 camelCase TypeScript 객체로 변환합니다.
|
|
3
|
+
*/
|
|
4
|
+
export declare function mapRow<T>(raw: Record<string, unknown>): T;
|
|
5
|
+
/**
|
|
6
|
+
* DB raw rows 배열을 camelCase TypeScript 객체 배열로 변환합니다.
|
|
7
|
+
*/
|
|
8
|
+
export declare function mapRows<T>(raws: Record<string, unknown>[]): T[];
|
|
9
|
+
//# sourceMappingURL=mapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mapper.d.ts","sourceRoot":"","sources":["../../../src/features/transform/mapper.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAEzD;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,EAAE,CAE/D"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mapRow = mapRow;
|
|
4
|
+
exports.mapRows = mapRows;
|
|
5
|
+
const case_1 = require("./case");
|
|
6
|
+
/**
|
|
7
|
+
* DB raw row를 camelCase TypeScript 객체로 변환합니다.
|
|
8
|
+
*/
|
|
9
|
+
function mapRow(raw) {
|
|
10
|
+
return (0, case_1.keysToCamel)(raw);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* DB raw rows 배열을 camelCase TypeScript 객체 배열로 변환합니다.
|
|
14
|
+
*/
|
|
15
|
+
function mapRows(raws) {
|
|
16
|
+
return raws.map((r) => mapRow(r));
|
|
17
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export { col, Col } from './features/schema/column';
|
|
2
|
+
export { defineTable } from './features/schema/table';
|
|
3
|
+
export type { ColShape } from './features/schema/interfaces/Column';
|
|
4
|
+
export type { TableDef, Cols } from './features/schema/interfaces/Table';
|
|
5
|
+
export type { InferRow, InferInsert, InferUpdate } from './features/schema/interfaces/Infer';
|
|
6
|
+
export { createRepo } from './features/repository/create';
|
|
7
|
+
export { BaseRepo } from './features/repository/base';
|
|
8
|
+
export type { IRepo } from './features/repository/interfaces/Repo';
|
|
9
|
+
export type { FindOpts } from './features/repository/interfaces/Find';
|
|
10
|
+
export { getPool, withClient, closePool, getPoolStatus, checkPoolHealth } from './features/connection/pool';
|
|
11
|
+
export type { PoolStatus } from './features/connection/pool';
|
|
12
|
+
export { runInTx } from './features/connection/tx';
|
|
13
|
+
export { buildSelect } from './features/query/select';
|
|
14
|
+
export { buildInsert } from './features/query/insert';
|
|
15
|
+
export { buildUpdate } from './features/query/update';
|
|
16
|
+
export { buildDelete } from './features/query/delete';
|
|
17
|
+
export { buildUpsert } from './features/query/upsert';
|
|
18
|
+
export { buildBulkInsert } from './features/query/bulkInsert';
|
|
19
|
+
export { buildWhere } from './features/query/where';
|
|
20
|
+
export type { BuiltQuery } from './features/query/interfaces/Query';
|
|
21
|
+
export type { WhereInput } from './features/query/interfaces/Where';
|
|
22
|
+
export type { OrderByInput, OrderDir } from './features/query/interfaces/Order';
|
|
23
|
+
export type { SelectOpts } from './features/query/select';
|
|
24
|
+
export { QueryBuilder } from './features/query/builder';
|
|
25
|
+
export type { AdvancedWhere, WhereOp, WhereVal, JoinClause, JoinType, AggregateFn, AggregateCalc, PaginateOpts, PageResult, OrderByClause, KeysetPaginateOpts, KeysetPageResult, StreamOpts, ExecHooks, } from './features/query/interfaces/Advanced';
|
|
26
|
+
export { toCamel, toSnake, keysToCamel, keysToSnake } from './features/transform/case';
|
|
27
|
+
export { mapRow, mapRows } from './features/transform/mapper';
|
|
28
|
+
export { DbError } from './utils/dbError';
|
|
29
|
+
export type { DbErrorKind, DbErrorPayload } from './utils/dbError';
|
|
30
|
+
export { getDatabaseConfig } from './configs/env';
|
|
31
|
+
export type { DatabaseConfig } from './interfaces/DatabaseConfig';
|
|
32
|
+
export { PostgresConfig, NodeEnvSource, readEnv } from './utils/reader';
|
|
33
|
+
export { Logger } from './utils/logger';
|
|
34
|
+
export type { LogLevel, LogFormat, LoggerConfig } from './utils/logger';
|
|
35
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAe,0BAA0B,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAY,yBAAyB,CAAC;AAC5D,YAAY,EAAE,QAAQ,EAAE,MAAU,qCAAqC,CAAC;AACxE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AACzE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAG7F,OAAO,EAAE,UAAU,EAAE,MAAa,8BAA8B,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAe,4BAA4B,CAAC;AAC/D,YAAY,EAAE,KAAK,EAAE,MAAa,uCAAuC,CAAC;AAC1E,YAAY,EAAE,QAAQ,EAAE,MAAU,uCAAuC,CAAC;AAG1E,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC5G,YAAY,EAAE,UAAU,EAAE,MAAQ,4BAA4B,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAgB,0BAA0B,CAAC;AAG7D,OAAO,EAAE,WAAW,EAAE,MAAY,yBAAyB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAY,yBAAyB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAY,yBAAyB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAY,yBAAyB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAY,yBAAyB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAQ,6BAA6B,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAa,wBAAwB,CAAC;AAC3D,YAAY,EAAE,UAAU,EAAE,MAAQ,mCAAmC,CAAC;AACtE,YAAY,EAAE,UAAU,EAAE,MAAQ,mCAAmC,CAAC;AACtE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAChF,YAAY,EAAE,UAAU,EAAE,MAAQ,yBAAyB,CAAC;AAG5D,OAAO,EAAE,YAAY,EAAE,MAAW,0BAA0B,CAAC;AAC7D,YAAY,EACV,aAAa,EACb,OAAO,EACP,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,WAAW,EACX,aAAa,EACb,YAAY,EACZ,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,UAAU,EACV,SAAS,GACV,MAAM,sCAAsC,CAAC;AAG9C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACvF,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAQ,6BAA6B,CAAC;AAGhE,OAAO,EAAE,OAAO,EAAE,MAAgB,iBAAiB,CAAC;AACpD,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAGxE,OAAO,EAAE,MAAM,EAAE,MAAiB,gBAAgB,CAAC;AACnD,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Logger = exports.readEnv = exports.NodeEnvSource = exports.PostgresConfig = exports.getDatabaseConfig = exports.DbError = exports.mapRows = exports.mapRow = exports.keysToSnake = exports.keysToCamel = exports.toSnake = exports.toCamel = exports.QueryBuilder = exports.buildWhere = exports.buildBulkInsert = exports.buildUpsert = exports.buildDelete = exports.buildUpdate = exports.buildInsert = exports.buildSelect = exports.runInTx = exports.checkPoolHealth = exports.getPoolStatus = exports.closePool = exports.withClient = exports.getPool = exports.BaseRepo = exports.createRepo = exports.defineTable = exports.Col = exports.col = void 0;
|
|
4
|
+
// ── Schema ──────────────────────────────────────────────────────────────────
|
|
5
|
+
var column_1 = require("./features/schema/column");
|
|
6
|
+
Object.defineProperty(exports, "col", { enumerable: true, get: function () { return column_1.col; } });
|
|
7
|
+
Object.defineProperty(exports, "Col", { enumerable: true, get: function () { return column_1.Col; } });
|
|
8
|
+
var table_1 = require("./features/schema/table");
|
|
9
|
+
Object.defineProperty(exports, "defineTable", { enumerable: true, get: function () { return table_1.defineTable; } });
|
|
10
|
+
// ── Repository ───────────────────────────────────────────────────────────────
|
|
11
|
+
var create_1 = require("./features/repository/create");
|
|
12
|
+
Object.defineProperty(exports, "createRepo", { enumerable: true, get: function () { return create_1.createRepo; } });
|
|
13
|
+
var base_1 = require("./features/repository/base");
|
|
14
|
+
Object.defineProperty(exports, "BaseRepo", { enumerable: true, get: function () { return base_1.BaseRepo; } });
|
|
15
|
+
// ── Connection ───────────────────────────────────────────────────────────────
|
|
16
|
+
var pool_1 = require("./features/connection/pool");
|
|
17
|
+
Object.defineProperty(exports, "getPool", { enumerable: true, get: function () { return pool_1.getPool; } });
|
|
18
|
+
Object.defineProperty(exports, "withClient", { enumerable: true, get: function () { return pool_1.withClient; } });
|
|
19
|
+
Object.defineProperty(exports, "closePool", { enumerable: true, get: function () { return pool_1.closePool; } });
|
|
20
|
+
Object.defineProperty(exports, "getPoolStatus", { enumerable: true, get: function () { return pool_1.getPoolStatus; } });
|
|
21
|
+
Object.defineProperty(exports, "checkPoolHealth", { enumerable: true, get: function () { return pool_1.checkPoolHealth; } });
|
|
22
|
+
var tx_1 = require("./features/connection/tx");
|
|
23
|
+
Object.defineProperty(exports, "runInTx", { enumerable: true, get: function () { return tx_1.runInTx; } });
|
|
24
|
+
// ── Query builders ───────────────────────────────────────────────────────────
|
|
25
|
+
var select_1 = require("./features/query/select");
|
|
26
|
+
Object.defineProperty(exports, "buildSelect", { enumerable: true, get: function () { return select_1.buildSelect; } });
|
|
27
|
+
var insert_1 = require("./features/query/insert");
|
|
28
|
+
Object.defineProperty(exports, "buildInsert", { enumerable: true, get: function () { return insert_1.buildInsert; } });
|
|
29
|
+
var update_1 = require("./features/query/update");
|
|
30
|
+
Object.defineProperty(exports, "buildUpdate", { enumerable: true, get: function () { return update_1.buildUpdate; } });
|
|
31
|
+
var delete_1 = require("./features/query/delete");
|
|
32
|
+
Object.defineProperty(exports, "buildDelete", { enumerable: true, get: function () { return delete_1.buildDelete; } });
|
|
33
|
+
var upsert_1 = require("./features/query/upsert");
|
|
34
|
+
Object.defineProperty(exports, "buildUpsert", { enumerable: true, get: function () { return upsert_1.buildUpsert; } });
|
|
35
|
+
var bulkInsert_1 = require("./features/query/bulkInsert");
|
|
36
|
+
Object.defineProperty(exports, "buildBulkInsert", { enumerable: true, get: function () { return bulkInsert_1.buildBulkInsert; } });
|
|
37
|
+
var where_1 = require("./features/query/where");
|
|
38
|
+
Object.defineProperty(exports, "buildWhere", { enumerable: true, get: function () { return where_1.buildWhere; } });
|
|
39
|
+
// ── Fluent QueryBuilder ───────────────────────────────────────────────────────
|
|
40
|
+
var builder_1 = require("./features/query/builder");
|
|
41
|
+
Object.defineProperty(exports, "QueryBuilder", { enumerable: true, get: function () { return builder_1.QueryBuilder; } });
|
|
42
|
+
// ── Transform ────────────────────────────────────────────────────────────────
|
|
43
|
+
var case_1 = require("./features/transform/case");
|
|
44
|
+
Object.defineProperty(exports, "toCamel", { enumerable: true, get: function () { return case_1.toCamel; } });
|
|
45
|
+
Object.defineProperty(exports, "toSnake", { enumerable: true, get: function () { return case_1.toSnake; } });
|
|
46
|
+
Object.defineProperty(exports, "keysToCamel", { enumerable: true, get: function () { return case_1.keysToCamel; } });
|
|
47
|
+
Object.defineProperty(exports, "keysToSnake", { enumerable: true, get: function () { return case_1.keysToSnake; } });
|
|
48
|
+
var mapper_1 = require("./features/transform/mapper");
|
|
49
|
+
Object.defineProperty(exports, "mapRow", { enumerable: true, get: function () { return mapper_1.mapRow; } });
|
|
50
|
+
Object.defineProperty(exports, "mapRows", { enumerable: true, get: function () { return mapper_1.mapRows; } });
|
|
51
|
+
// ── Error handling ───────────────────────────────────────────────────────────
|
|
52
|
+
var dbError_1 = require("./utils/dbError");
|
|
53
|
+
Object.defineProperty(exports, "DbError", { enumerable: true, get: function () { return dbError_1.DbError; } });
|
|
54
|
+
// ── Config ───────────────────────────────────────────────────────────────────
|
|
55
|
+
var env_1 = require("./configs/env");
|
|
56
|
+
Object.defineProperty(exports, "getDatabaseConfig", { enumerable: true, get: function () { return env_1.getDatabaseConfig; } });
|
|
57
|
+
var reader_1 = require("./utils/reader");
|
|
58
|
+
Object.defineProperty(exports, "PostgresConfig", { enumerable: true, get: function () { return reader_1.PostgresConfig; } });
|
|
59
|
+
Object.defineProperty(exports, "NodeEnvSource", { enumerable: true, get: function () { return reader_1.NodeEnvSource; } });
|
|
60
|
+
Object.defineProperty(exports, "readEnv", { enumerable: true, get: function () { return reader_1.readEnv; } });
|
|
61
|
+
// ── Logger ───────────────────────────────────────────────────────────────────
|
|
62
|
+
var logger_1 = require("./utils/logger");
|
|
63
|
+
Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return logger_1.Logger; } });
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostgreSQL 연결 설정 인터페이스
|
|
3
|
+
* pg 라이브러리의 PoolConfig와 ClientConfig의 모든 옵션을 포함합니다
|
|
4
|
+
*/
|
|
5
|
+
export interface DatabaseConfig {
|
|
6
|
+
host: string;
|
|
7
|
+
port: number;
|
|
8
|
+
user: string;
|
|
9
|
+
password: string;
|
|
10
|
+
database: string | undefined;
|
|
11
|
+
connectionString?: string;
|
|
12
|
+
ssl?: boolean | object;
|
|
13
|
+
max?: number;
|
|
14
|
+
idleTimeoutMillis?: number;
|
|
15
|
+
connectionTimeoutMillis?: number;
|
|
16
|
+
allowExitOnIdle?: boolean;
|
|
17
|
+
statement_timeout?: number;
|
|
18
|
+
query_timeout?: number;
|
|
19
|
+
application_name?: string;
|
|
20
|
+
parseInputDatesAsUTC?: boolean;
|
|
21
|
+
keepAlive?: boolean;
|
|
22
|
+
keepAliveInitialDelayMillis?: number;
|
|
23
|
+
types?: Record<string, unknown>;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=DatabaseConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DatabaseConfig.d.ts","sourceRoot":"","sources":["../../src/interfaces/DatabaseConfig.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,cAAc;IAE3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAG1B,GAAG,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAGvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,eAAe,CAAC,EAAE,OAAO,CAAC;IAG1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IAGvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAG1B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAG/B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,2BAA2B,CAAC,EAAE,MAAM,CAAC;IAGvC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EnvSource.d.ts","sourceRoot":"","sources":["../../src/interfaces/EnvSource.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACtB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACxC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface PostgresDriverOptions {
|
|
2
|
+
host?: string;
|
|
3
|
+
port?: number;
|
|
4
|
+
database?: string;
|
|
5
|
+
user?: string;
|
|
6
|
+
password?: string;
|
|
7
|
+
connectionString?: string;
|
|
8
|
+
ssl?: boolean;
|
|
9
|
+
max?: number;
|
|
10
|
+
idleTimeoutMillis?: number;
|
|
11
|
+
connectionTimeoutMillis?: number;
|
|
12
|
+
allowExitOnIdle?: boolean;
|
|
13
|
+
statement_timeout?: number;
|
|
14
|
+
query_timeout?: number;
|
|
15
|
+
application_name?: string;
|
|
16
|
+
parseInputDatesAsUTC?: boolean;
|
|
17
|
+
keepAlive?: boolean;
|
|
18
|
+
keepAliveInitialDelayMillis?: number;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=PostgresDriverOptions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PostgresDriverOptions.d.ts","sourceRoot":"","sources":["../../src/interfaces/PostgresDriverOptions.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,2BAA2B,CAAC,EAAE,MAAM,CAAC;CACxC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/interfaces/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./PostgresDriverOptions"), exports);
|
|
18
|
+
__exportStar(require("./EnvSource"), exports);
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostgreSQL 에러 분류 타입.
|
|
3
|
+
* pg 라이브러리의 error.code (SQLSTATE) 기준으로 분류됩니다.
|
|
4
|
+
*/
|
|
5
|
+
export type DbErrorKind = 'uniqueViolation' | 'foreignKeyViolation' | 'notNullViolation' | 'checkViolation' | 'deadlock' | 'serializationFailure' | 'connectionFailed' | 'tooManyConnections' | 'queryTimeout' | 'undefinedTable' | 'undefinedColumn' | 'syntaxError' | 'invalidInput' | 'unknown';
|
|
6
|
+
/** 사용자 노출용 에러 페이로드 */
|
|
7
|
+
export interface DbErrorPayload {
|
|
8
|
+
error: string;
|
|
9
|
+
kind: DbErrorKind;
|
|
10
|
+
isRetryable: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* PostgreSQL 에러를 분류하고, 내부 에러와 사용자 노출 메시지를 분리합니다.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* try {
|
|
18
|
+
* await userRepo.create(data);
|
|
19
|
+
* } catch (err) {
|
|
20
|
+
* if (err instanceof DbError) {
|
|
21
|
+
* res.status(400).json(err.toUserPayload());
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare class DbError extends Error {
|
|
27
|
+
readonly kind: DbErrorKind;
|
|
28
|
+
/** PostgreSQL SQLSTATE 코드 */
|
|
29
|
+
readonly pgCode: string;
|
|
30
|
+
/** 사용자에게 안전하게 노출 가능한 메시지 */
|
|
31
|
+
readonly userMessage: string;
|
|
32
|
+
/** 재시도 가능 여부 */
|
|
33
|
+
readonly isRetryable: boolean;
|
|
34
|
+
/** 관련 테이블명 */
|
|
35
|
+
readonly table?: string;
|
|
36
|
+
/** 관련 컬럼명 */
|
|
37
|
+
readonly column?: string;
|
|
38
|
+
/** 위반된 제약조건명 */
|
|
39
|
+
readonly constraint?: string;
|
|
40
|
+
/** pg가 제공하는 상세 설명 (내부 로그용) */
|
|
41
|
+
readonly detail?: string;
|
|
42
|
+
/** pg가 제공하는 힌트 (내부 로그용) */
|
|
43
|
+
readonly hint?: string;
|
|
44
|
+
private constructor();
|
|
45
|
+
/**
|
|
46
|
+
* 알 수 없는 에러를 DbError로 변환합니다.
|
|
47
|
+
* 이미 DbError이면 그대로 반환합니다.
|
|
48
|
+
*/
|
|
49
|
+
static from(err: unknown): DbError;
|
|
50
|
+
/**
|
|
51
|
+
* 사용자에게 안전하게 노출할 수 있는 정보만 담은 객체를 반환합니다.
|
|
52
|
+
* Express response 등에서 직접 사용하세요.
|
|
53
|
+
*/
|
|
54
|
+
toUserPayload(): DbErrorPayload;
|
|
55
|
+
/**
|
|
56
|
+
* 내부 로깅용 컨텍스트를 반환합니다.
|
|
57
|
+
* 절대 사용자에게 직접 노출하지 마세요.
|
|
58
|
+
*/
|
|
59
|
+
toLogContext(): Record<string, unknown>;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=dbError.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dbError.d.ts","sourceRoot":"","sources":["../../src/utils/dbError.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,WAAW,GACnB,iBAAiB,GACjB,qBAAqB,GACrB,kBAAkB,GAClB,gBAAgB,GAChB,UAAU,GACV,sBAAsB,GACtB,kBAAkB,GAClB,oBAAoB,GACpB,cAAc,GACd,gBAAgB,GAChB,iBAAiB,GACjB,aAAa,GACb,cAAc,GACd,SAAS,CAAC;AA0Dd,sBAAsB;AACtB,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,WAAW,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,OAAQ,SAAQ,KAAK;IAChC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,6BAA6B;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,4BAA4B;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,gBAAgB;IAChB,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,cAAc;IACd,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa;IACb,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB;IAChB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,8BAA8B;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,2BAA2B;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEvB,OAAO;IAmBP;;;OAGG;IACH,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;IAmBlC;;;OAGG;IACH,aAAa,IAAI,cAAc;IAQ/B;;;OAGG;IACH,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAYxC"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DbError = void 0;
|
|
4
|
+
/** pg SQLSTATE 코드 → DbErrorKind 매핑 */
|
|
5
|
+
const PG_CODE_TO_KIND = {
|
|
6
|
+
'23505': 'uniqueViolation',
|
|
7
|
+
'23503': 'foreignKeyViolation',
|
|
8
|
+
'23502': 'notNullViolation',
|
|
9
|
+
'23514': 'checkViolation',
|
|
10
|
+
'40P01': 'deadlock',
|
|
11
|
+
'40001': 'serializationFailure',
|
|
12
|
+
'08000': 'connectionFailed',
|
|
13
|
+
'08003': 'connectionFailed',
|
|
14
|
+
'08006': 'connectionFailed',
|
|
15
|
+
'08001': 'connectionFailed',
|
|
16
|
+
'08004': 'connectionFailed',
|
|
17
|
+
'53300': 'tooManyConnections',
|
|
18
|
+
'57014': 'queryTimeout',
|
|
19
|
+
'42P01': 'undefinedTable',
|
|
20
|
+
'42703': 'undefinedColumn',
|
|
21
|
+
'42601': 'syntaxError',
|
|
22
|
+
};
|
|
23
|
+
/** 사용자에게 노출할 메시지 (내부 상세 정보 미포함) */
|
|
24
|
+
const USER_MESSAGES = {
|
|
25
|
+
uniqueViolation: '이미 존재하는 값입니다.',
|
|
26
|
+
foreignKeyViolation: '참조 데이터가 존재하지 않거나, 참조 중인 데이터를 삭제할 수 없습니다.',
|
|
27
|
+
notNullViolation: '필수 값이 누락되었습니다.',
|
|
28
|
+
checkViolation: '유효하지 않은 값입니다.',
|
|
29
|
+
deadlock: '처리 중 충돌이 발생했습니다. 잠시 후 다시 시도해 주세요.',
|
|
30
|
+
serializationFailure: '처리 중 충돌이 발생했습니다. 잠시 후 다시 시도해 주세요.',
|
|
31
|
+
connectionFailed: '데이터베이스에 연결할 수 없습니다.',
|
|
32
|
+
tooManyConnections: '서버가 일시적으로 혼잡합니다. 잠시 후 다시 시도해 주세요.',
|
|
33
|
+
queryTimeout: '요청 처리 시간이 초과되었습니다.',
|
|
34
|
+
undefinedTable: '서버 내부 오류가 발생했습니다.',
|
|
35
|
+
undefinedColumn: '서버 내부 오류가 발생했습니다.',
|
|
36
|
+
syntaxError: '서버 내부 오류가 발생했습니다.',
|
|
37
|
+
invalidInput: '입력 형식이 올바르지 않습니다.',
|
|
38
|
+
unknown: '알 수 없는 오류가 발생했습니다.',
|
|
39
|
+
};
|
|
40
|
+
/** 재시도가 의미 있는 에러 종류 */
|
|
41
|
+
const RETRYABLE_KINDS = new Set([
|
|
42
|
+
'deadlock',
|
|
43
|
+
'serializationFailure',
|
|
44
|
+
'tooManyConnections',
|
|
45
|
+
'connectionFailed',
|
|
46
|
+
]);
|
|
47
|
+
/**
|
|
48
|
+
* PostgreSQL 에러를 분류하고, 내부 에러와 사용자 노출 메시지를 분리합니다.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* try {
|
|
53
|
+
* await userRepo.create(data);
|
|
54
|
+
* } catch (err) {
|
|
55
|
+
* if (err instanceof DbError) {
|
|
56
|
+
* res.status(400).json(err.toUserPayload());
|
|
57
|
+
* }
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
class DbError extends Error {
|
|
62
|
+
constructor(kind, pgCode, internalMessage, opts = {}) {
|
|
63
|
+
super(internalMessage);
|
|
64
|
+
this.name = 'DbError';
|
|
65
|
+
this.kind = kind;
|
|
66
|
+
this.pgCode = pgCode;
|
|
67
|
+
this.userMessage = USER_MESSAGES[kind];
|
|
68
|
+
this.isRetryable = RETRYABLE_KINDS.has(kind);
|
|
69
|
+
this.table = opts.table;
|
|
70
|
+
this.column = opts.column;
|
|
71
|
+
this.constraint = opts.constraint;
|
|
72
|
+
this.detail = opts.detail;
|
|
73
|
+
this.hint = opts.hint;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* 알 수 없는 에러를 DbError로 변환합니다.
|
|
77
|
+
* 이미 DbError이면 그대로 반환합니다.
|
|
78
|
+
*/
|
|
79
|
+
static from(err) {
|
|
80
|
+
if (err instanceof DbError)
|
|
81
|
+
return err;
|
|
82
|
+
const pg = err;
|
|
83
|
+
const code = pg.code ?? 'UNKNOWN';
|
|
84
|
+
const kind = PG_CODE_TO_KIND[code] ??
|
|
85
|
+
(code.startsWith('22') ? 'invalidInput' : 'unknown');
|
|
86
|
+
return new DbError(kind, code, pg.message ?? 'Unknown database error', {
|
|
87
|
+
table: pg.table,
|
|
88
|
+
column: pg.column,
|
|
89
|
+
constraint: pg.constraint,
|
|
90
|
+
detail: pg.detail,
|
|
91
|
+
hint: pg.hint,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* 사용자에게 안전하게 노출할 수 있는 정보만 담은 객체를 반환합니다.
|
|
96
|
+
* Express response 등에서 직접 사용하세요.
|
|
97
|
+
*/
|
|
98
|
+
toUserPayload() {
|
|
99
|
+
return {
|
|
100
|
+
error: this.userMessage,
|
|
101
|
+
kind: this.kind,
|
|
102
|
+
isRetryable: this.isRetryable,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* 내부 로깅용 컨텍스트를 반환합니다.
|
|
107
|
+
* 절대 사용자에게 직접 노출하지 마세요.
|
|
108
|
+
*/
|
|
109
|
+
toLogContext() {
|
|
110
|
+
return {
|
|
111
|
+
pgCode: this.pgCode,
|
|
112
|
+
kind: this.kind,
|
|
113
|
+
table: this.table,
|
|
114
|
+
column: this.column,
|
|
115
|
+
constraint: this.constraint,
|
|
116
|
+
detail: this.detail,
|
|
117
|
+
hint: this.hint,
|
|
118
|
+
message: this.message,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
exports.DbError = DbError;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./logger"), exports);
|
|
18
|
+
__exportStar(require("./reader"), exports);
|
|
19
|
+
__exportStar(require("./dbError"), exports);
|