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.
Files changed (136) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/LICENSE +21 -0
  3. package/README.md +952 -0
  4. package/dist/configs/env.d.ts +14 -0
  5. package/dist/configs/env.d.ts.map +1 -0
  6. package/dist/configs/env.js +46 -0
  7. package/dist/configs/index.d.ts +2 -0
  8. package/dist/configs/index.d.ts.map +1 -0
  9. package/dist/configs/index.js +17 -0
  10. package/dist/features/connection/index.d.ts +3 -0
  11. package/dist/features/connection/index.d.ts.map +1 -0
  12. package/dist/features/connection/index.js +18 -0
  13. package/dist/features/connection/pool.d.ts +42 -0
  14. package/dist/features/connection/pool.d.ts.map +1 -0
  15. package/dist/features/connection/pool.js +131 -0
  16. package/dist/features/connection/tx.d.ts +10 -0
  17. package/dist/features/connection/tx.d.ts.map +1 -0
  18. package/dist/features/connection/tx.js +37 -0
  19. package/dist/features/query/builder.d.ts +253 -0
  20. package/dist/features/query/builder.d.ts.map +1 -0
  21. package/dist/features/query/builder.js +613 -0
  22. package/dist/features/query/bulkInsert.d.ts +10 -0
  23. package/dist/features/query/bulkInsert.d.ts.map +1 -0
  24. package/dist/features/query/bulkInsert.js +30 -0
  25. package/dist/features/query/delete.d.ts +8 -0
  26. package/dist/features/query/delete.d.ts.map +1 -0
  27. package/dist/features/query/delete.js +15 -0
  28. package/dist/features/query/index.d.ts +10 -0
  29. package/dist/features/query/index.d.ts.map +1 -0
  30. package/dist/features/query/index.js +25 -0
  31. package/dist/features/query/insert.d.ts +7 -0
  32. package/dist/features/query/insert.d.ts.map +1 -0
  33. package/dist/features/query/insert.js +18 -0
  34. package/dist/features/query/interfaces/Advanced.d.ts +177 -0
  35. package/dist/features/query/interfaces/Advanced.d.ts.map +1 -0
  36. package/dist/features/query/interfaces/Advanced.js +2 -0
  37. package/dist/features/query/interfaces/Order.d.ts +6 -0
  38. package/dist/features/query/interfaces/Order.d.ts.map +1 -0
  39. package/dist/features/query/interfaces/Order.js +2 -0
  40. package/dist/features/query/interfaces/Query.d.ts +6 -0
  41. package/dist/features/query/interfaces/Query.d.ts.map +1 -0
  42. package/dist/features/query/interfaces/Query.js +2 -0
  43. package/dist/features/query/interfaces/Where.d.ts +3 -0
  44. package/dist/features/query/interfaces/Where.d.ts.map +1 -0
  45. package/dist/features/query/interfaces/Where.js +2 -0
  46. package/dist/features/query/interfaces/index.d.ts +5 -0
  47. package/dist/features/query/interfaces/index.d.ts.map +1 -0
  48. package/dist/features/query/interfaces/index.js +20 -0
  49. package/dist/features/query/select.d.ts +15 -0
  50. package/dist/features/query/select.d.ts.map +1 -0
  51. package/dist/features/query/select.js +33 -0
  52. package/dist/features/query/update.d.ts +8 -0
  53. package/dist/features/query/update.d.ts.map +1 -0
  54. package/dist/features/query/update.js +28 -0
  55. package/dist/features/query/upsert.d.ts +11 -0
  56. package/dist/features/query/upsert.d.ts.map +1 -0
  57. package/dist/features/query/upsert.js +31 -0
  58. package/dist/features/query/where.d.ts +11 -0
  59. package/dist/features/query/where.d.ts.map +1 -0
  60. package/dist/features/query/where.js +30 -0
  61. package/dist/features/repository/base.d.ts +107 -0
  62. package/dist/features/repository/base.d.ts.map +1 -0
  63. package/dist/features/repository/base.js +243 -0
  64. package/dist/features/repository/create.d.ts +13 -0
  65. package/dist/features/repository/create.d.ts.map +1 -0
  66. package/dist/features/repository/create.js +16 -0
  67. package/dist/features/repository/index.d.ts +4 -0
  68. package/dist/features/repository/index.d.ts.map +1 -0
  69. package/dist/features/repository/index.js +19 -0
  70. package/dist/features/repository/interfaces/Find.d.ts +9 -0
  71. package/dist/features/repository/interfaces/Find.d.ts.map +1 -0
  72. package/dist/features/repository/interfaces/Find.js +2 -0
  73. package/dist/features/repository/interfaces/Repo.d.ts +29 -0
  74. package/dist/features/repository/interfaces/Repo.d.ts.map +1 -0
  75. package/dist/features/repository/interfaces/Repo.js +2 -0
  76. package/dist/features/repository/interfaces/index.d.ts +3 -0
  77. package/dist/features/repository/interfaces/index.d.ts.map +1 -0
  78. package/dist/features/repository/interfaces/index.js +18 -0
  79. package/dist/features/schema/column.d.ts +62 -0
  80. package/dist/features/schema/column.d.ts.map +1 -0
  81. package/dist/features/schema/column.js +74 -0
  82. package/dist/features/schema/index.d.ts +4 -0
  83. package/dist/features/schema/index.d.ts.map +1 -0
  84. package/dist/features/schema/index.js +19 -0
  85. package/dist/features/schema/interfaces/Column.d.ts +19 -0
  86. package/dist/features/schema/interfaces/Column.d.ts.map +1 -0
  87. package/dist/features/schema/interfaces/Column.js +2 -0
  88. package/dist/features/schema/interfaces/Infer.d.ts +20 -0
  89. package/dist/features/schema/interfaces/Infer.d.ts.map +1 -0
  90. package/dist/features/schema/interfaces/Infer.js +2 -0
  91. package/dist/features/schema/interfaces/Table.d.ts +7 -0
  92. package/dist/features/schema/interfaces/Table.d.ts.map +1 -0
  93. package/dist/features/schema/interfaces/Table.js +2 -0
  94. package/dist/features/schema/interfaces/index.d.ts +4 -0
  95. package/dist/features/schema/interfaces/index.d.ts.map +1 -0
  96. package/dist/features/schema/interfaces/index.js +19 -0
  97. package/dist/features/schema/table.d.ts +14 -0
  98. package/dist/features/schema/table.d.ts.map +1 -0
  99. package/dist/features/schema/table.js +17 -0
  100. package/dist/features/transform/case.d.ts +19 -0
  101. package/dist/features/transform/case.d.ts.map +1 -0
  102. package/dist/features/transform/case.js +32 -0
  103. package/dist/features/transform/index.d.ts +3 -0
  104. package/dist/features/transform/index.d.ts.map +1 -0
  105. package/dist/features/transform/index.js +18 -0
  106. package/dist/features/transform/mapper.d.ts +9 -0
  107. package/dist/features/transform/mapper.d.ts.map +1 -0
  108. package/dist/features/transform/mapper.js +17 -0
  109. package/dist/index.d.ts +35 -0
  110. package/dist/index.d.ts.map +1 -0
  111. package/dist/index.js +63 -0
  112. package/dist/interfaces/DatabaseConfig.d.ts +25 -0
  113. package/dist/interfaces/DatabaseConfig.d.ts.map +1 -0
  114. package/dist/interfaces/DatabaseConfig.js +2 -0
  115. package/dist/interfaces/EnvSource.d.ts +4 -0
  116. package/dist/interfaces/EnvSource.d.ts.map +1 -0
  117. package/dist/interfaces/EnvSource.js +2 -0
  118. package/dist/interfaces/PostgresDriverOptions.d.ts +20 -0
  119. package/dist/interfaces/PostgresDriverOptions.d.ts.map +1 -0
  120. package/dist/interfaces/PostgresDriverOptions.js +2 -0
  121. package/dist/interfaces/index.d.ts +3 -0
  122. package/dist/interfaces/index.d.ts.map +1 -0
  123. package/dist/interfaces/index.js +18 -0
  124. package/dist/utils/dbError.d.ts +61 -0
  125. package/dist/utils/dbError.d.ts.map +1 -0
  126. package/dist/utils/dbError.js +122 -0
  127. package/dist/utils/index.d.ts +4 -0
  128. package/dist/utils/index.d.ts.map +1 -0
  129. package/dist/utils/index.js +19 -0
  130. package/dist/utils/logger.d.ts +63 -0
  131. package/dist/utils/logger.d.ts.map +1 -0
  132. package/dist/utils/logger.js +138 -0
  133. package/dist/utils/reader.d.ts +49 -0
  134. package/dist/utils/reader.d.ts.map +1 -0
  135. package/dist/utils/reader.js +159 -0
  136. package/package.json +73 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/query/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC"}
@@ -0,0 +1,25 @@
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("./select"), exports);
18
+ __exportStar(require("./insert"), exports);
19
+ __exportStar(require("./update"), exports);
20
+ __exportStar(require("./delete"), exports);
21
+ __exportStar(require("./upsert"), exports);
22
+ __exportStar(require("./bulkInsert"), exports);
23
+ __exportStar(require("./where"), exports);
24
+ __exportStar(require("./interfaces"), exports);
25
+ __exportStar(require("./builder"), exports);
@@ -0,0 +1,7 @@
1
+ import { BuiltQuery } from './interfaces/Query';
2
+ /**
3
+ * INSERT 쿼리를 생성합니다. RETURNING * 으로 삽입된 row를 반환합니다.
4
+ * camelCase key → snake_case 컬럼명으로 자동 변환됩니다.
5
+ */
6
+ export declare function buildInsert(table: string, data: Record<string, unknown>): BuiltQuery;
7
+ //# sourceMappingURL=insert.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insert.d.ts","sourceRoot":"","sources":["../../../src/features/query/insert.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD;;;GAGG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,UAAU,CAWZ"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildInsert = buildInsert;
4
+ const case_1 = require("../transform/case");
5
+ /**
6
+ * INSERT 쿼리를 생성합니다. RETURNING * 으로 삽입된 row를 반환합니다.
7
+ * camelCase key → snake_case 컬럼명으로 자동 변환됩니다.
8
+ */
9
+ function buildInsert(table, data) {
10
+ const entries = Object.entries(data).filter(([, v]) => v !== undefined);
11
+ const cols = entries.map(([k]) => (0, case_1.toSnake)(k)).join(', ');
12
+ const placeholders = entries.map((_, i) => `$${i + 1}`).join(', ');
13
+ const params = entries.map(([, v]) => v);
14
+ return {
15
+ sql: `INSERT INTO ${table} (${cols}) VALUES (${placeholders}) RETURNING *`,
16
+ params,
17
+ };
18
+ }
@@ -0,0 +1,177 @@
1
+ /** WHERE 조건 연산자 */
2
+ export type WhereOp = '=' | '!=' | '>' | '<' | '>=' | '<=' | 'LIKE' | 'ILIKE' | 'IN' | 'NOT IN' | 'IS NULL' | 'IS NOT NULL';
3
+ /**
4
+ * 고급 WHERE 조건값.
5
+ * `{ operator: 'LIKE', value: '%search%' }` 형태로 사용합니다.
6
+ */
7
+ export interface WhereVal<T> {
8
+ operator: WhereOp;
9
+ /** IS NULL / IS NOT NULL 일 때는 생략 가능 */
10
+ value?: T | T[];
11
+ }
12
+ /**
13
+ * 고급 WHERE 조건 입력 타입.
14
+ * 단순 값(등호 조건) 또는 `WhereVal`(연산자 지정) 모두 허용합니다.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * // 등호
19
+ * { isActive: true }
20
+ * // LIKE
21
+ * { email: { operator: 'LIKE', value: '%@gmail.com' } }
22
+ * // IN
23
+ * { id: { operator: 'IN', value: [1, 2, 3] } }
24
+ * // NULL 체크
25
+ * { deletedAt: { operator: 'IS NULL' } }
26
+ * ```
27
+ */
28
+ export type AdvancedWhere<T> = {
29
+ [K in keyof T]?: T[K] | WhereVal<T[K]>;
30
+ };
31
+ /** JOIN 종류 */
32
+ export type JoinType = 'INNER' | 'LEFT' | 'RIGHT' | 'FULL';
33
+ /**
34
+ * JOIN 절 정의.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * repo.select()
39
+ * .join({ table: 'orders', on: 'users.id = orders.user_id', type: 'LEFT' })
40
+ * ```
41
+ */
42
+ export interface JoinClause {
43
+ table: string;
44
+ /** ON 절 (snake_case 컬럼명으로 직접 작성) */
45
+ on: string;
46
+ type?: JoinType;
47
+ }
48
+ /** 집계 함수 종류 */
49
+ export type AggregateFn = 'COUNT' | 'SUM' | 'AVG' | 'MIN' | 'MAX';
50
+ /**
51
+ * 집계 함수 정의.
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * .calculate([
56
+ * { fn: 'COUNT', alias: 'count' },
57
+ * { fn: 'AVG', column: 'price', alias: 'avgPrice' },
58
+ * ])
59
+ * ```
60
+ */
61
+ export interface AggregateCalc {
62
+ fn: AggregateFn;
63
+ /** 대상 컬럼 (생략 시 *) */
64
+ column?: string;
65
+ alias: string;
66
+ }
67
+ /** 페이지네이션 입력 옵션 */
68
+ export interface PaginateOpts {
69
+ page: number;
70
+ pageSize: number;
71
+ }
72
+ /**
73
+ * 페이지네이션 결과.
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * {
78
+ * data: [...],
79
+ * count: 150,
80
+ * page: 2,
81
+ * pageSize: 20,
82
+ * nextAction: true,
83
+ * previousAction: true
84
+ * }
85
+ * ```
86
+ */
87
+ export interface PageResult<T> {
88
+ data: T[];
89
+ /** 필터 조건에 해당하는 전체 row 수 */
90
+ count: number;
91
+ page: number;
92
+ pageSize: number;
93
+ /** 다음 페이지가 존재하는지 여부 */
94
+ nextAction: boolean;
95
+ /** 이전 페이지가 존재하는지 여부 */
96
+ previousAction: boolean;
97
+ }
98
+ /** ORDER BY 절 */
99
+ export interface OrderByClause<T = Record<string, unknown>> {
100
+ column: keyof T | string;
101
+ direction?: 'ASC' | 'DESC';
102
+ }
103
+ /** 내부 조건 저장 포맷 (실행 시 SQL 생성) */
104
+ export interface RawCond {
105
+ col: string;
106
+ op: WhereOp;
107
+ val?: unknown;
108
+ }
109
+ /**
110
+ * 커서 기반(Keyset) 페이지네이션 옵션.
111
+ *
112
+ * OFFSET 방식 대비 대용량 테이블에서 일정한 성능을 보장합니다.
113
+ * 인덱스가 걸린 컬럼(id, createdAt 등)을 cursorColumn으로 지정하세요.
114
+ *
115
+ * @example
116
+ * ```ts
117
+ * // 첫 번째 페이지
118
+ * const p1 = await repo.select().cursorPaginate({ pageSize: 20, cursorColumn: 'id' });
119
+ * // 다음 페이지
120
+ * const p2 = await repo.select().cursorPaginate({ pageSize: 20, cursorColumn: 'id', cursor: p1.nextCursor });
121
+ * ```
122
+ */
123
+ export interface KeysetPaginateOpts {
124
+ pageSize: number;
125
+ /** 이전 페이지 결과의 nextCursor 값 (최초 요청 시 생략) */
126
+ cursor?: string;
127
+ /** 커서로 사용할 컬럼 (camelCase, 인덱스가 존재해야 합니다) */
128
+ cursorColumn: string;
129
+ direction?: 'asc' | 'desc';
130
+ }
131
+ /** 커서 기반 페이지네이션 결과 */
132
+ export interface KeysetPageResult<T> {
133
+ data: T[];
134
+ /** 다음 페이지 요청 시 cursor 파라미터로 전달하세요. null이면 마지막 페이지입니다. */
135
+ nextCursor: string | null;
136
+ pageSize: number;
137
+ hasNext: boolean;
138
+ }
139
+ /**
140
+ * 배치 스트리밍 옵션.
141
+ * 대용량 데이터를 메모리에 전부 로드하지 않고 청크 단위로 처리합니다.
142
+ */
143
+ export interface StreamOpts {
144
+ /** 한 번에 DB에서 읽어올 row 수 (기본값: 500) */
145
+ batchSize?: number;
146
+ }
147
+ /**
148
+ * 쿼리 실행 라이프사이클 훅.
149
+ *
150
+ * @example
151
+ * ```ts
152
+ * repo.select()
153
+ * .hooks({
154
+ * beforeExec: ({ sql }) => logger.debug('실행 예정 SQL:', sql),
155
+ * afterExec: ({ rows, elapsed }) => metrics.record('query', elapsed),
156
+ * onError: ({ err }) => alerting.send(err),
157
+ * })
158
+ * .paginate({ page: 1, pageSize: 20 });
159
+ * ```
160
+ */
161
+ export interface ExecHooks<T extends Record<string, unknown> = Record<string, unknown>> {
162
+ beforeExec?: (ctx: {
163
+ sql: string;
164
+ params: unknown[];
165
+ }) => void | Promise<void>;
166
+ afterExec?: (ctx: {
167
+ rows: T[];
168
+ elapsed: number;
169
+ sql: string;
170
+ }) => void | Promise<void>;
171
+ onError?: (ctx: {
172
+ err: Error;
173
+ sql: string;
174
+ params: unknown[];
175
+ }) => void | Promise<void>;
176
+ }
177
+ //# sourceMappingURL=Advanced.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Advanced.d.ts","sourceRoot":"","sources":["../../../../src/features/query/interfaces/Advanced.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,6 @@
1
+ export type OrderDir = 'ASC' | 'DESC';
2
+ export interface OrderByInput<T> {
3
+ col: keyof T;
4
+ dir?: OrderDir;
5
+ }
6
+ //# sourceMappingURL=Order.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Order.d.ts","sourceRoot":"","sources":["../../../../src/features/query/interfaces/Order.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;AAEtC,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAC,CAAC;IACb,GAAG,CAAC,EAAE,QAAQ,CAAC;CAChB"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,6 @@
1
+ /** SQL 문자열과 parameterized 값 묶음 */
2
+ export interface BuiltQuery {
3
+ readonly sql: string;
4
+ readonly params: unknown[];
5
+ }
6
+ //# sourceMappingURL=Query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Query.d.ts","sourceRoot":"","sources":["../../../../src/features/query/interfaces/Query.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;CAC5B"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ /** WHERE 조건 입력 타입 (camelCase key) */
2
+ export type WhereInput<T> = Partial<T>;
3
+ //# sourceMappingURL=Where.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Where.d.ts","sourceRoot":"","sources":["../../../../src/features/query/interfaces/Where.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,5 @@
1
+ export * from './Query';
2
+ export * from './Where';
3
+ export * from './Order';
4
+ export * from './Advanced';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/features/query/interfaces/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC"}
@@ -0,0 +1,20 @@
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("./Query"), exports);
18
+ __exportStar(require("./Where"), exports);
19
+ __exportStar(require("./Order"), exports);
20
+ __exportStar(require("./Advanced"), exports);
@@ -0,0 +1,15 @@
1
+ import { BuiltQuery } from './interfaces/Query';
2
+ import { WhereInput } from './interfaces/Where';
3
+ import { OrderByInput } from './interfaces/Order';
4
+ export interface SelectOpts<T extends Record<string, unknown>> {
5
+ where?: WhereInput<T>;
6
+ orderBy?: OrderByInput<T>[];
7
+ limit?: number;
8
+ offset?: number;
9
+ }
10
+ /**
11
+ * SELECT 쿼리를 생성합니다.
12
+ * 모든 WHERE 조건은 camelCase → snake_case 자동 변환됩니다.
13
+ */
14
+ export declare function buildSelect<T extends Record<string, unknown>>(table: string, opts?: SelectOpts<T>): BuiltQuery;
15
+ //# sourceMappingURL=select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../../src/features/query/select.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC3D,KAAK,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IACtB,OAAO,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,UAAU,CAAC,CAAC,CAAM,GACvB,UAAU,CA8BZ"}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildSelect = buildSelect;
4
+ const case_1 = require("../transform/case");
5
+ const where_1 = require("./where");
6
+ /**
7
+ * SELECT 쿼리를 생성합니다.
8
+ * 모든 WHERE 조건은 camelCase → snake_case 자동 변환됩니다.
9
+ */
10
+ function buildSelect(table, opts = {}) {
11
+ const parts = [`SELECT * FROM ${table}`];
12
+ const params = [];
13
+ if (opts.where && Object.keys(opts.where).length > 0) {
14
+ const { sql: w, params: wp } = (0, where_1.buildWhere)(opts.where, params.length + 1);
15
+ if (w) {
16
+ parts.push(w);
17
+ params.push(...wp);
18
+ }
19
+ }
20
+ if (opts.orderBy && opts.orderBy.length > 0) {
21
+ const clauses = opts.orderBy.map(({ col, dir }) => `${(0, case_1.toSnake)(String(col))} ${dir ?? 'ASC'}`);
22
+ parts.push(`ORDER BY ${clauses.join(', ')}`);
23
+ }
24
+ if (opts.limit !== undefined) {
25
+ params.push(opts.limit);
26
+ parts.push(`LIMIT $${params.length}`);
27
+ }
28
+ if (opts.offset !== undefined) {
29
+ params.push(opts.offset);
30
+ parts.push(`OFFSET $${params.length}`);
31
+ }
32
+ return { sql: parts.join(' '), params };
33
+ }
@@ -0,0 +1,8 @@
1
+ import { BuiltQuery } from './interfaces/Query';
2
+ import { WhereInput } from './interfaces/Where';
3
+ /**
4
+ * UPDATE 쿼리를 생성합니다. RETURNING * 으로 수정된 row를 반환합니다.
5
+ * camelCase key → snake_case 컬럼명으로 자동 변환됩니다.
6
+ */
7
+ export declare function buildUpdate<T extends Record<string, unknown>>(table: string, data: Partial<T>, where: WhereInput<T>): BuiltQuery;
8
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/features/query/update.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAChB,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,GACnB,UAAU,CAsBZ"}
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildUpdate = buildUpdate;
4
+ const case_1 = require("../transform/case");
5
+ const where_1 = require("./where");
6
+ /**
7
+ * UPDATE 쿼리를 생성합니다. RETURNING * 으로 수정된 row를 반환합니다.
8
+ * camelCase key → snake_case 컬럼명으로 자동 변환됩니다.
9
+ */
10
+ function buildUpdate(table, data, where) {
11
+ const entries = Object.entries(data).filter(([, v]) => v !== undefined);
12
+ const params = [];
13
+ const setClauses = entries.map(([k, v]) => {
14
+ params.push(v);
15
+ return `${(0, case_1.toSnake)(k)} = $${params.length}`;
16
+ });
17
+ const { sql: whereSql, params: whereParams } = (0, where_1.buildWhere)(where, params.length + 1);
18
+ params.push(...whereParams);
19
+ const sql = [
20
+ `UPDATE ${table}`,
21
+ `SET ${setClauses.join(', ')}`,
22
+ whereSql,
23
+ 'RETURNING *',
24
+ ]
25
+ .filter(Boolean)
26
+ .join(' ');
27
+ return { sql, params };
28
+ }
@@ -0,0 +1,11 @@
1
+ import { BuiltQuery } from './interfaces/Query';
2
+ /**
3
+ * INSERT ... ON CONFLICT DO UPDATE 쿼리를 생성합니다.
4
+ * 충돌 컬럼을 제외한 나머지 컬럼을 EXCLUDED 값으로 업데이트합니다.
5
+ *
6
+ * @param table - 테이블명 (snake_case)
7
+ * @param data - 삽입할 데이터 (camelCase key)
8
+ * @param conflictCol - 충돌 기준 컬럼명 (snake_case)
9
+ */
10
+ export declare function buildUpsert(table: string, data: Record<string, unknown>, conflictCol: string): BuiltQuery;
11
+ //# sourceMappingURL=upsert.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upsert.d.ts","sourceRoot":"","sources":["../../../src/features/query/upsert.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,WAAW,EAAE,MAAM,GAClB,UAAU,CAqBZ"}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildUpsert = buildUpsert;
4
+ const case_1 = require("../transform/case");
5
+ /**
6
+ * INSERT ... ON CONFLICT DO UPDATE 쿼리를 생성합니다.
7
+ * 충돌 컬럼을 제외한 나머지 컬럼을 EXCLUDED 값으로 업데이트합니다.
8
+ *
9
+ * @param table - 테이블명 (snake_case)
10
+ * @param data - 삽입할 데이터 (camelCase key)
11
+ * @param conflictCol - 충돌 기준 컬럼명 (snake_case)
12
+ */
13
+ function buildUpsert(table, data, conflictCol) {
14
+ const entries = Object.entries(data).filter(([, v]) => v !== undefined);
15
+ const cols = entries.map(([k]) => (0, case_1.toSnake)(k)).join(', ');
16
+ const placeholders = entries.map((_, i) => `$${i + 1}`).join(', ');
17
+ const params = entries.map(([, v]) => v);
18
+ const updateSet = entries
19
+ .map(([k]) => (0, case_1.toSnake)(k))
20
+ .filter((col) => col !== conflictCol)
21
+ .map((col) => `${col} = EXCLUDED.${col}`)
22
+ .join(', ');
23
+ return {
24
+ sql: [
25
+ `INSERT INTO ${table} (${cols}) VALUES (${placeholders})`,
26
+ `ON CONFLICT (${conflictCol}) DO UPDATE SET ${updateSet}`,
27
+ 'RETURNING *',
28
+ ].join(' '),
29
+ params,
30
+ };
31
+ }
@@ -0,0 +1,11 @@
1
+ import { BuiltQuery } from './interfaces/Query';
2
+ import { WhereInput } from './interfaces/Where';
3
+ /**
4
+ * WhereInput 객체로부터 WHERE 절 SQL과 params를 생성합니다.
5
+ * camelCase key → snake_case 컬럼명으로 자동 변환됩니다.
6
+ *
7
+ * @param where - camelCase key 기반 조건 객체
8
+ * @param startIdx - param placeholder 시작 번호 ($1, $2 ...)
9
+ */
10
+ export declare function buildWhere<T extends Record<string, unknown>>(where: WhereInput<T>, startIdx?: number): BuiltQuery;
11
+ //# sourceMappingURL=where.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"where.d.ts","sourceRoot":"","sources":["../../../src/features/query/where.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC1D,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EACpB,QAAQ,GAAE,MAAU,GACnB,UAAU,CAqBZ"}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildWhere = buildWhere;
4
+ const case_1 = require("../transform/case");
5
+ /**
6
+ * WhereInput 객체로부터 WHERE 절 SQL과 params를 생성합니다.
7
+ * camelCase key → snake_case 컬럼명으로 자동 변환됩니다.
8
+ *
9
+ * @param where - camelCase key 기반 조건 객체
10
+ * @param startIdx - param placeholder 시작 번호 ($1, $2 ...)
11
+ */
12
+ function buildWhere(where, startIdx = 1) {
13
+ const entries = Object.entries(where).filter(([, v]) => v !== undefined);
14
+ if (entries.length === 0) {
15
+ return { sql: '', params: [] };
16
+ }
17
+ const params = [];
18
+ const conditions = [];
19
+ for (const [key, val] of entries) {
20
+ const col = (0, case_1.toSnake)(key);
21
+ if (val === null) {
22
+ conditions.push(`${col} IS NULL`);
23
+ }
24
+ else {
25
+ conditions.push(`${col} = $${startIdx + params.length}`);
26
+ params.push(val);
27
+ }
28
+ }
29
+ return { sql: `WHERE ${conditions.join(' AND ')}`, params };
30
+ }
@@ -0,0 +1,107 @@
1
+ import { PoolClient } from 'pg';
2
+ import { TableDef, Cols } from '../schema/interfaces/Table';
3
+ import { InferRow, InferInsert, InferUpdate } from '../schema/interfaces/Infer';
4
+ import { BuiltQuery } from '../query/interfaces/Query';
5
+ import { QueryBuilder } from '../query/builder';
6
+ import { AdvancedWhere, ExecHooks } from '../query/interfaces/Advanced';
7
+ import { IRepo } from './interfaces/Repo';
8
+ import { FindOpts } from './interfaces/Find';
9
+ /**
10
+ * 기본 CRUD 레포지토리.
11
+ *
12
+ * - 모든 DB 에러는 `DbError`로 변환됩니다.
13
+ * - 사용자에게 노출할 메시지는 `DbError.toUserPayload()`를 사용하세요.
14
+ * - 트랜잭션 내에서 사용하려면 `exec(built, client)` 형태로 client를 전달하세요.
15
+ */
16
+ export declare class BaseRepo<TDef extends TableDef<string, Cols>> implements IRepo<InferRow<TDef>, InferInsert<TDef>, InferUpdate<TDef>> {
17
+ protected readonly def: TDef;
18
+ protected readonly tableName: string;
19
+ protected readonly pkKey: string;
20
+ protected readonly pkCol: string;
21
+ private _globalHooks?;
22
+ constructor(def: TDef);
23
+ /**
24
+ * 이 레포지토리의 모든 `select()` 빌더에 적용될 글로벌 훅을 등록합니다.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * userRepo.useHooks({
29
+ * beforeExec: ({ sql }) => logger.debug('SQL:', sql),
30
+ * afterExec: ({ elapsed }) => metrics.record('db.query', elapsed),
31
+ * });
32
+ * ```
33
+ */
34
+ useHooks(h: ExecHooks<InferRow<TDef>>): this;
35
+ /**
36
+ * SQL을 실행하고 camelCase 변환된 rows를 반환합니다.
37
+ *
38
+ * - 에러 발생 시 `DbError`로 변환 후 로깅하고 re-throw합니다.
39
+ * - `client`를 넘기면 해당 client를 재사용합니다 (트랜잭션 지원).
40
+ */
41
+ protected exec<T extends Record<string, unknown>>(built: BuiltQuery, client?: PoolClient): Promise<T[]>;
42
+ findAll(opts?: FindOpts<InferRow<TDef>>): Promise<InferRow<TDef>[]>;
43
+ findById(id: number | string): Promise<InferRow<TDef> | null>;
44
+ findOne(where: Partial<InferRow<TDef>>): Promise<InferRow<TDef> | null>;
45
+ create(data: InferInsert<TDef>): Promise<InferRow<TDef>>;
46
+ update(id: number | string, data: InferUpdate<TDef>): Promise<InferRow<TDef> | null>;
47
+ delete(id: number | string): Promise<boolean>;
48
+ /**
49
+ * 데이터를 삽입하거나, 충돌 시 UPDATE합니다.
50
+ * @param conflictCol - 충돌 기준 컬럼 (snake_case, 기본값: primary key)
51
+ */
52
+ upsert(data: InferInsert<TDef>, conflictCol?: string): Promise<InferRow<TDef>>;
53
+ /**
54
+ * 여러 row를 단일 INSERT 쿼리로 삽입합니다.
55
+ */
56
+ bulkCreate(rows: InferInsert<TDef>[]): Promise<InferRow<TDef>[]>;
57
+ /**
58
+ * 유연한 플루언트 쿼리 빌더를 반환합니다.
59
+ *
60
+ * WHERE, OR, ORDER BY, GROUP BY, JOIN, LIMIT, OFFSET, paginate, calculate 등을
61
+ * 메서드 체인으로 조합할 수 있습니다.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * // 기본 조회 (await 직접 사용 가능)
66
+ * const users = await repo.select({ isActive: true })
67
+ * .orderBy([{ column: 'createdAt', direction: 'DESC' }])
68
+ * .limit(20);
69
+ *
70
+ * // OR 조건
71
+ * const results = await repo.select()
72
+ * .or({ email: { operator: 'LIKE', value: '%@gmail.com' } });
73
+ *
74
+ * // 페이지네이션
75
+ * const page = await repo.select()
76
+ * .paginate({ page: 1, pageSize: 20 });
77
+ *
78
+ * // 집계
79
+ * const agg = await repo.select({ isActive: true })
80
+ * .calculate([{ fn: 'COUNT', alias: 'count' }]);
81
+ * ```
82
+ */
83
+ select(where?: AdvancedWhere<InferRow<TDef>>): QueryBuilder<InferRow<TDef>>;
84
+ /**
85
+ * 단건 조회 (없으면 null). `select(where).one()` 의 단축형입니다.
86
+ *
87
+ * @example
88
+ * ```ts
89
+ * const user = await repo.selectOne({ id: 1 });
90
+ * ```
91
+ */
92
+ selectOne(where: AdvancedWhere<InferRow<TDef>>): Promise<InferRow<TDef> | null>;
93
+ /**
94
+ * Raw SQL을 직접 실행합니다.
95
+ * DB 컬럼명(snake_case) → TypeScript(camelCase) 자동 변환이 적용됩니다.
96
+ *
97
+ * @example
98
+ * ```ts
99
+ * const rows = await repo.raw<UserRow>(
100
+ * 'SELECT * FROM users WHERE first_name ILIKE $1',
101
+ * ['%john%'],
102
+ * );
103
+ * ```
104
+ */
105
+ raw<R extends Record<string, unknown> = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<R[]>;
106
+ }
107
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/features/repository/base.ts"],"names":[],"mappings":"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"}