@simplysm/orm-common 13.0.69 → 13.0.71

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 (204) hide show
  1. package/README.md +54 -1447
  2. package/dist/create-db-context.d.ts +10 -10
  3. package/dist/create-db-context.js +9 -9
  4. package/dist/create-db-context.js.map +1 -1
  5. package/dist/ddl/column-ddl.d.ts +4 -4
  6. package/dist/ddl/initialize.d.ts +17 -17
  7. package/dist/ddl/initialize.js +2 -2
  8. package/dist/ddl/initialize.js.map +1 -1
  9. package/dist/ddl/relation-ddl.d.ts +6 -6
  10. package/dist/ddl/schema-ddl.d.ts +4 -4
  11. package/dist/ddl/table-ddl.d.ts +24 -24
  12. package/dist/ddl/table-ddl.js +4 -4
  13. package/dist/ddl/table-ddl.js.map +1 -1
  14. package/dist/errors/db-transaction-error.d.ts +15 -15
  15. package/dist/errors/db-transaction-error.d.ts.map +1 -1
  16. package/dist/exec/executable.d.ts +23 -23
  17. package/dist/exec/executable.js +3 -3
  18. package/dist/exec/executable.js.map +1 -1
  19. package/dist/exec/queryable.d.ts +160 -160
  20. package/dist/exec/queryable.js +119 -119
  21. package/dist/exec/queryable.js.map +1 -1
  22. package/dist/exec/search-parser.d.ts +37 -37
  23. package/dist/exec/search-parser.d.ts.map +1 -1
  24. package/dist/expr/expr-unit.d.ts +4 -4
  25. package/dist/expr/expr.d.ts +257 -257
  26. package/dist/expr/expr.js +265 -265
  27. package/dist/expr/expr.js.map +1 -1
  28. package/dist/query-builder/base/expr-renderer-base.d.ts +9 -9
  29. package/dist/query-builder/base/expr-renderer-base.js +2 -2
  30. package/dist/query-builder/base/expr-renderer-base.js.map +1 -1
  31. package/dist/query-builder/base/query-builder-base.d.ts +26 -26
  32. package/dist/query-builder/base/query-builder-base.d.ts.map +1 -1
  33. package/dist/query-builder/base/query-builder-base.js +22 -22
  34. package/dist/query-builder/base/query-builder-base.js.map +1 -1
  35. package/dist/query-builder/mssql/mssql-expr-renderer.d.ts +4 -4
  36. package/dist/query-builder/mssql/mssql-expr-renderer.d.ts.map +1 -1
  37. package/dist/query-builder/mssql/mssql-expr-renderer.js +18 -18
  38. package/dist/query-builder/mssql/mssql-expr-renderer.js.map +1 -1
  39. package/dist/query-builder/mssql/mssql-query-builder.d.ts +2 -2
  40. package/dist/query-builder/mssql/mssql-query-builder.d.ts.map +1 -1
  41. package/dist/query-builder/mssql/mssql-query-builder.js +11 -11
  42. package/dist/query-builder/mssql/mssql-query-builder.js.map +1 -1
  43. package/dist/query-builder/mysql/mysql-expr-renderer.d.ts +4 -4
  44. package/dist/query-builder/mysql/mysql-expr-renderer.d.ts.map +1 -1
  45. package/dist/query-builder/mysql/mysql-expr-renderer.js +17 -17
  46. package/dist/query-builder/mysql/mysql-expr-renderer.js.map +1 -1
  47. package/dist/query-builder/mysql/mysql-query-builder.d.ts +8 -8
  48. package/dist/query-builder/mysql/mysql-query-builder.d.ts.map +1 -1
  49. package/dist/query-builder/mysql/mysql-query-builder.js +5 -5
  50. package/dist/query-builder/mysql/mysql-query-builder.js.map +1 -1
  51. package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts +4 -4
  52. package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts.map +1 -1
  53. package/dist/query-builder/postgresql/postgresql-expr-renderer.js +17 -17
  54. package/dist/query-builder/postgresql/postgresql-expr-renderer.js.map +1 -1
  55. package/dist/query-builder/postgresql/postgresql-query-builder.d.ts +5 -5
  56. package/dist/query-builder/postgresql/postgresql-query-builder.d.ts.map +1 -1
  57. package/dist/query-builder/postgresql/postgresql-query-builder.js +8 -8
  58. package/dist/query-builder/postgresql/postgresql-query-builder.js.map +1 -1
  59. package/dist/query-builder/query-builder.d.ts +1 -1
  60. package/dist/schema/factory/column-builder.d.ts +79 -79
  61. package/dist/schema/factory/column-builder.js +42 -42
  62. package/dist/schema/factory/index-builder.d.ts +39 -39
  63. package/dist/schema/factory/index-builder.js +26 -26
  64. package/dist/schema/factory/relation-builder.d.ts +99 -99
  65. package/dist/schema/factory/relation-builder.d.ts.map +1 -1
  66. package/dist/schema/factory/relation-builder.js +38 -38
  67. package/dist/schema/procedure-builder.d.ts +49 -49
  68. package/dist/schema/procedure-builder.d.ts.map +1 -1
  69. package/dist/schema/procedure-builder.js +33 -33
  70. package/dist/schema/table-builder.d.ts +59 -59
  71. package/dist/schema/table-builder.d.ts.map +1 -1
  72. package/dist/schema/table-builder.js +43 -43
  73. package/dist/schema/view-builder.d.ts +49 -49
  74. package/dist/schema/view-builder.d.ts.map +1 -1
  75. package/dist/schema/view-builder.js +32 -32
  76. package/dist/types/column.d.ts +22 -22
  77. package/dist/types/column.js +1 -1
  78. package/dist/types/column.js.map +1 -1
  79. package/dist/types/db.d.ts +40 -40
  80. package/dist/types/expr.d.ts +59 -59
  81. package/dist/types/expr.d.ts.map +1 -1
  82. package/dist/types/query-def.d.ts +44 -44
  83. package/dist/types/query-def.d.ts.map +1 -1
  84. package/dist/utils/result-parser.d.ts +11 -11
  85. package/dist/utils/result-parser.js +3 -3
  86. package/dist/utils/result-parser.js.map +1 -1
  87. package/package.json +5 -5
  88. package/src/create-db-context.ts +20 -20
  89. package/src/ddl/column-ddl.ts +4 -4
  90. package/src/ddl/initialize.ts +259 -259
  91. package/src/ddl/relation-ddl.ts +89 -89
  92. package/src/ddl/schema-ddl.ts +4 -4
  93. package/src/ddl/table-ddl.ts +189 -189
  94. package/src/errors/db-transaction-error.ts +13 -13
  95. package/src/exec/executable.ts +25 -25
  96. package/src/exec/queryable.ts +2033 -2033
  97. package/src/exec/search-parser.ts +57 -57
  98. package/src/expr/expr-unit.ts +4 -4
  99. package/src/expr/expr.ts +2140 -2140
  100. package/src/query-builder/base/expr-renderer-base.ts +237 -237
  101. package/src/query-builder/base/query-builder-base.ts +213 -213
  102. package/src/query-builder/mssql/mssql-expr-renderer.ts +607 -607
  103. package/src/query-builder/mssql/mssql-query-builder.ts +650 -650
  104. package/src/query-builder/mysql/mysql-expr-renderer.ts +613 -613
  105. package/src/query-builder/mysql/mysql-query-builder.ts +759 -759
  106. package/src/query-builder/postgresql/postgresql-expr-renderer.ts +611 -611
  107. package/src/query-builder/postgresql/postgresql-query-builder.ts +686 -686
  108. package/src/query-builder/query-builder.ts +19 -19
  109. package/src/schema/factory/column-builder.ts +423 -423
  110. package/src/schema/factory/index-builder.ts +164 -164
  111. package/src/schema/factory/relation-builder.ts +453 -453
  112. package/src/schema/procedure-builder.ts +232 -232
  113. package/src/schema/table-builder.ts +319 -319
  114. package/src/schema/view-builder.ts +221 -221
  115. package/src/types/column.ts +188 -188
  116. package/src/types/db.ts +208 -208
  117. package/src/types/expr.ts +697 -697
  118. package/src/types/query-def.ts +513 -513
  119. package/src/utils/result-parser.ts +458 -458
  120. package/tests/db-context/create-db-context.spec.ts +224 -0
  121. package/tests/db-context/define-db-context.spec.ts +68 -0
  122. package/tests/ddl/basic.expected.ts +341 -0
  123. package/tests/ddl/basic.spec.ts +714 -0
  124. package/tests/ddl/column-builder.expected.ts +310 -0
  125. package/tests/ddl/column-builder.spec.ts +637 -0
  126. package/tests/ddl/index-builder.expected.ts +38 -0
  127. package/tests/ddl/index-builder.spec.ts +202 -0
  128. package/tests/ddl/procedure-builder.expected.ts +52 -0
  129. package/tests/ddl/procedure-builder.spec.ts +234 -0
  130. package/tests/ddl/relation-builder.expected.ts +36 -0
  131. package/tests/ddl/relation-builder.spec.ts +372 -0
  132. package/tests/ddl/table-builder.expected.ts +113 -0
  133. package/tests/ddl/table-builder.spec.ts +433 -0
  134. package/tests/ddl/view-builder.expected.ts +38 -0
  135. package/tests/ddl/view-builder.spec.ts +176 -0
  136. package/tests/dml/delete.expected.ts +96 -0
  137. package/tests/dml/delete.spec.ts +160 -0
  138. package/tests/dml/insert.expected.ts +192 -0
  139. package/tests/dml/insert.spec.ts +288 -0
  140. package/tests/dml/update.expected.ts +176 -0
  141. package/tests/dml/update.spec.ts +318 -0
  142. package/tests/dml/upsert.expected.ts +215 -0
  143. package/tests/dml/upsert.spec.ts +242 -0
  144. package/tests/errors/queryable-errors.spec.ts +177 -0
  145. package/tests/escape.spec.ts +100 -0
  146. package/tests/examples/pivot.expected.ts +211 -0
  147. package/tests/examples/pivot.spec.ts +533 -0
  148. package/tests/examples/sampling.expected.ts +69 -0
  149. package/tests/examples/sampling.spec.ts +105 -0
  150. package/tests/examples/unpivot.expected.ts +120 -0
  151. package/tests/examples/unpivot.spec.ts +226 -0
  152. package/tests/exec/search-parser.spec.ts +283 -0
  153. package/tests/executable/basic.expected.ts +18 -0
  154. package/tests/executable/basic.spec.ts +54 -0
  155. package/tests/expr/comparison.expected.ts +282 -0
  156. package/tests/expr/comparison.spec.ts +400 -0
  157. package/tests/expr/conditional.expected.ts +134 -0
  158. package/tests/expr/conditional.spec.ts +276 -0
  159. package/tests/expr/date.expected.ts +332 -0
  160. package/tests/expr/date.spec.ts +526 -0
  161. package/tests/expr/math.expected.ts +62 -0
  162. package/tests/expr/math.spec.ts +106 -0
  163. package/tests/expr/string.expected.ts +218 -0
  164. package/tests/expr/string.spec.ts +356 -0
  165. package/tests/expr/utility.expected.ts +147 -0
  166. package/tests/expr/utility.spec.ts +182 -0
  167. package/tests/select/basic.expected.ts +322 -0
  168. package/tests/select/basic.spec.ts +502 -0
  169. package/tests/select/filter.expected.ts +357 -0
  170. package/tests/select/filter.spec.ts +1068 -0
  171. package/tests/select/group.expected.ts +169 -0
  172. package/tests/select/group.spec.ts +244 -0
  173. package/tests/select/join.expected.ts +582 -0
  174. package/tests/select/join.spec.ts +805 -0
  175. package/tests/select/order.expected.ts +150 -0
  176. package/tests/select/order.spec.ts +189 -0
  177. package/tests/select/recursive-cte.expected.ts +244 -0
  178. package/tests/select/recursive-cte.spec.ts +514 -0
  179. package/tests/select/result-meta.spec.ts +270 -0
  180. package/tests/select/subquery.expected.ts +363 -0
  181. package/tests/select/subquery.spec.ts +537 -0
  182. package/tests/select/view.expected.ts +155 -0
  183. package/tests/select/view.spec.ts +235 -0
  184. package/tests/select/window.expected.ts +345 -0
  185. package/tests/select/window.spec.ts +618 -0
  186. package/tests/setup/MockExecutor.ts +18 -0
  187. package/tests/setup/TestDbContext.ts +59 -0
  188. package/tests/setup/models/Company.ts +13 -0
  189. package/tests/setup/models/Employee.ts +10 -0
  190. package/tests/setup/models/MonthlySales.ts +11 -0
  191. package/tests/setup/models/Post.ts +16 -0
  192. package/tests/setup/models/Sales.ts +10 -0
  193. package/tests/setup/models/User.ts +19 -0
  194. package/tests/setup/procedure/GetAllUsers.ts +9 -0
  195. package/tests/setup/procedure/GetUserById.ts +12 -0
  196. package/tests/setup/test-utils.ts +72 -0
  197. package/tests/setup/views/ActiveUsers.ts +8 -0
  198. package/tests/setup/views/UserSummary.ts +11 -0
  199. package/tests/types/nullable-queryable-record.spec.ts +145 -0
  200. package/tests/utils/result-parser-perf.spec.ts +210 -0
  201. package/tests/utils/result-parser.spec.ts +701 -0
  202. package/docs/expressions.md +0 -172
  203. package/docs/queries.md +0 -444
  204. package/docs/schema.md +0 -245
@@ -1,319 +1,319 @@
1
- import {
2
- type ColumnBuilderRecord,
3
- createColumnFactory,
4
- type InferColumns,
5
- type InferInsertColumns,
6
- type InferUpdateColumns,
7
- } from "./factory/column-builder";
8
- import { createIndexFactory, type IndexBuilder } from "./factory/index-builder";
9
- import {
10
- createRelationFactory,
11
- type InferDeepRelations,
12
- type RelationBuilderRecord,
13
- } from "./factory/relation-builder";
14
-
15
- // ============================================
16
- // TableBuilder
17
- // ============================================
18
-
19
- /**
20
- * 데이터베이스 테이블 정의 빌더
21
- *
22
- * Fluent API를 통해 테이블의 컬럼, PK, 인덱스, 관계를 정의
23
- * DbContext에서 queryable()과 함께 사용하여 타입 안전한 쿼리 작성
24
- *
25
- * @template TColumns - 컬럼 정의 레코드 타입
26
- * @template TRelations - 관계 정의 레코드 타입
27
- *
28
- * @example
29
- * ```typescript
30
- * // 테이블 정의
31
- * const User = Table("User")
32
- * .database("mydb")
33
- * .columns((c) => ({
34
- * id: c.bigint().autoIncrement(),
35
- * name: c.varchar(100),
36
- * email: c.varchar(200).nullable(),
37
- * status: c.varchar(20).default("active"),
38
- * }))
39
- * .primaryKey("id")
40
- * .indexes((i) => [i.index("email").unique()]);
41
- *
42
- * // DbContext에서 사용
43
- * class MyDb extends DbContext {
44
- * readonly user = queryable(this, User);
45
- * }
46
- * ```
47
- *
48
- * @see {@link Table} 팩토리 함수
49
- * @see {@link queryable} Queryable 생성
50
- */
51
- export class TableBuilder<
52
- TColumns extends ColumnBuilderRecord,
53
- TRelations extends RelationBuilderRecord,
54
- > {
55
- /** 컬럼 정의 (타입 추론용) */
56
- readonly $columns!: TColumns;
57
- /** 관계 정의 (타입 추론용) */
58
- readonly $relations!: TRelations;
59
-
60
- /** 전체 타입 추론 (컬럼 + 관계) */
61
- readonly $infer!: InferColumns<TColumns> & InferDeepRelations<TRelations>;
62
- /** 컬럼만 타입 추론 */
63
- readonly $inferColumns!: InferColumns<TColumns>;
64
- /** INSERT용 타입 추론 (autoIncrement 제외, nullable/default는 optional) */
65
- readonly $inferInsert!: InferInsertColumns<TColumns>;
66
- /** UPDATE용 타입 추론 (모든 필드 optional) */
67
- readonly $inferUpdate!: InferUpdateColumns<TColumns>;
68
-
69
- /**
70
- * @param meta - 테이블 메타데이터
71
- * @param meta.name - 테이블 이름
72
- * @param meta.description - 테이블 설명 (주석)
73
- * @param meta.database - 데이터베이스 이름
74
- * @param meta.schema - 스키마 이름 (MSSQL/PostgreSQL)
75
- * @param meta.columns - 컬럼 정의
76
- * @param meta.primaryKey - PK 컬럼 배열
77
- * @param meta.relations - 관계 정의
78
- * @param meta.indexes - 인덱스 정의
79
- */
80
- constructor(
81
- readonly meta: {
82
- name: string;
83
- description?: string;
84
- database?: string;
85
- schema?: string;
86
-
87
- columns?: TColumns;
88
- primaryKey?: (keyof TColumns & string)[];
89
- relations?: TRelations;
90
- indexes?: IndexBuilder<(keyof TColumns & string)[]>[];
91
- },
92
- ) {}
93
-
94
- /**
95
- * 테이블 설명 설정
96
- *
97
- * @param desc - 테이블 설명 (DDL 주석으로 사용)
98
- * @returns TableBuilder 인스턴스
99
- */
100
- description(desc: string) {
101
- return new TableBuilder({ ...this.meta, description: desc });
102
- }
103
-
104
- /**
105
- * 데이터베이스 이름 설정
106
- *
107
- * @param db - 데이터베이스 이름
108
- * @returns TableBuilder 인스턴스
109
- *
110
- * @example
111
- * ```typescript
112
- * const User = Table("User").database("mydb");
113
- * ```
114
- */
115
- database(db: string) {
116
- return new TableBuilder({ ...this.meta, database: db });
117
- }
118
-
119
- /**
120
- * 스키마 이름 설정
121
- *
122
- * MSSQL, PostgreSQL에서 사용
123
- *
124
- * @param schema - 스키마 이름 (MSSQL: dbo, PostgreSQL: public)
125
- * @returns TableBuilder 인스턴스
126
- *
127
- * @example
128
- * ```typescript
129
- * const User = Table("User")
130
- * .database("mydb")
131
- * .schema("custom_schema");
132
- * ```
133
- */
134
- schema(schema: string) {
135
- return new TableBuilder({ ...this.meta, schema });
136
- }
137
-
138
- /**
139
- * 컬럼 정의
140
- *
141
- * 컬럼 팩토리를 통해 타입 안전한 컬럼 정의
142
- *
143
- * @template TNewColumnDefs - 새 컬럼 정의 타입
144
- * @param fn - 컬럼 팩토리를 받아 컬럼 정의를 반환하는 함수
145
- * @returns TableBuilder 인스턴스
146
- *
147
- * @example
148
- * ```typescript
149
- * const User = Table("User")
150
- * .columns((c) => ({
151
- * id: c.bigint().autoIncrement(),
152
- * name: c.varchar(100),
153
- * email: c.varchar(200).nullable(),
154
- * createdAt: c.datetime().default("CURRENT_TIMESTAMP"),
155
- * }));
156
- * ```
157
- */
158
- columns<TNewColumnDefs extends ColumnBuilderRecord>(
159
- fn: (c: ReturnType<typeof createColumnFactory>) => TNewColumnDefs,
160
- ) {
161
- return new TableBuilder<TNewColumnDefs, TRelations>({
162
- ...this.meta,
163
- columns: fn(createColumnFactory()),
164
- });
165
- }
166
-
167
- /**
168
- * Primary Key 설정
169
- *
170
- * @param columns - PK를 구성할 컬럼 이름들 (복합 PK 가능)
171
- * @returns TableBuilder 인스턴스
172
- *
173
- * @example
174
- * ```typescript
175
- * // 단일 PK
176
- * const User = Table("User")
177
- * .columns((c) => ({ id: c.bigint() }))
178
- * .primaryKey("id");
179
- *
180
- * // 복합 PK
181
- * const UserRole = Table("UserRole")
182
- * .columns((c) => ({
183
- * userId: c.bigint(),
184
- * roleId: c.bigint(),
185
- * }))
186
- * .primaryKey("userId", "roleId");
187
- * ```
188
- */
189
- primaryKey(...columns: (keyof TColumns & string)[]) {
190
- return new TableBuilder({
191
- ...this.meta,
192
- primaryKey: columns,
193
- });
194
- }
195
-
196
- /**
197
- * 인덱스 정의
198
- *
199
- * @param fn - 인덱스 팩토리를 받아 인덱스 배열을 반환하는 함수
200
- * @returns TableBuilder 인스턴스
201
- *
202
- * @example
203
- * ```typescript
204
- * const User = Table("User")
205
- * .columns((c) => ({
206
- * id: c.bigint(),
207
- * email: c.varchar(200),
208
- * name: c.varchar(100),
209
- * }))
210
- * .indexes((i) => [
211
- * i.index("email").unique(),
212
- * i.index("name").orderBy("ASC"),
213
- * ]);
214
- * ```
215
- */
216
- indexes(
217
- fn: (
218
- i: ReturnType<typeof createIndexFactory<keyof TColumns & string>>,
219
- ) => IndexBuilder<string[]>[],
220
- ) {
221
- return new TableBuilder({
222
- ...this.meta,
223
- indexes: fn(createIndexFactory<keyof TColumns & string>()),
224
- });
225
- }
226
-
227
- /**
228
- * 관계 정의
229
- *
230
- * FK, 역참조 등 테이블관계 설정
231
- *
232
- * @template T - 관계 정의 타입
233
- * @param fn - 관계 팩토리를 받아 관계 정의를 반환하는 함수
234
- * @returns TableBuilder 인스턴스
235
- *
236
- * @example
237
- * ```typescript
238
- * const Post = Table("Post")
239
- * .columns((c) => ({
240
- * id: c.bigint().autoIncrement(),
241
- * authorId: c.bigint(),
242
- * title: c.varchar(200),
243
- * }))
244
- * .primaryKey("id")
245
- * .relations((r) => ({
246
- * // FK 관계 (N:1)
247
- * author: r.foreignKey(["authorId"], () => User),
248
- * }));
249
- *
250
- * const User = Table("User")
251
- * .columns((c) => ({
252
- * id: c.bigint().autoIncrement(),
253
- * name: c.varchar(100),
254
- * }))
255
- * .primaryKey("id")
256
- * .relations((r) => ({
257
- * // 역참조 (1:N)
258
- * posts: r.foreignKeyTarget(() => Post, "author"),
259
- * }));
260
- * ```
261
- *
262
- * @see {@link ForeignKeyBuilder} FK 빌더
263
- * @see {@link ForeignKeyTargetBuilder} FK 역참조 빌더
264
- */
265
- relations<T extends RelationBuilderRecord>(
266
- fn: (r: ReturnType<typeof createRelationFactory<this, keyof TColumns & string>>) => T,
267
- ): TableBuilder<TColumns, T> {
268
- return new TableBuilder({
269
- ...this.meta,
270
- relations: fn(createRelationFactory<this, keyof TColumns & string>(() => this)),
271
- });
272
- }
273
- }
274
-
275
- // ============================================
276
- // Table 함수
277
- // ============================================
278
-
279
- /**
280
- * 테이블 빌더 생성 팩토리 함수
281
- *
282
- * TableBuilder를 생성하여 Fluent API로 테이블 스키마 정의
283
- *
284
- * @param name - 테이블 이름
285
- * @returns TableBuilder 인스턴스
286
- *
287
- * @example
288
- * ```typescript
289
- * // 기본 사용
290
- * const User = Table("User")
291
- * .database("mydb")
292
- * .columns((c) => ({
293
- * id: c.bigint().autoIncrement(),
294
- * name: c.varchar(100),
295
- * email: c.varchar(200).nullable(),
296
- * }))
297
- * .primaryKey("id")
298
- * .indexes((i) => [i.index("email").unique()]);
299
- *
300
- * // 관계 포함
301
- * const Post = Table("Post")
302
- * .database("mydb")
303
- * .columns((c) => ({
304
- * id: c.bigint().autoIncrement(),
305
- * authorId: c.bigint(),
306
- * title: c.varchar(200),
307
- * content: c.text(),
308
- * }))
309
- * .primaryKey("id")
310
- * .relations((r) => ({
311
- * author: r.foreignKey(["authorId"], () => User),
312
- * }));
313
- * ```
314
- *
315
- * @see {@link TableBuilder} 빌더 클래스
316
- */
317
- export function Table(name: string) {
318
- return new TableBuilder({ name });
319
- }
1
+ import {
2
+ type ColumnBuilderRecord,
3
+ createColumnFactory,
4
+ type InferColumns,
5
+ type InferInsertColumns,
6
+ type InferUpdateColumns,
7
+ } from "./factory/column-builder";
8
+ import { createIndexFactory, type IndexBuilder } from "./factory/index-builder";
9
+ import {
10
+ createRelationFactory,
11
+ type InferDeepRelations,
12
+ type RelationBuilderRecord,
13
+ } from "./factory/relation-builder";
14
+
15
+ // ============================================
16
+ // TableBuilder
17
+ // ============================================
18
+
19
+ /**
20
+ * Database Table definition builder
21
+ *
22
+ * Fluent API를 통해 Table의 column, PK, Index, 관계를 definition
23
+ * DbContext에서 queryable()과 함께 사용하여 type 안전한 query 작성
24
+ *
25
+ * @template TColumns - Column definition record type
26
+ * @template TRelations - relationship definition record type
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * // Table definition
31
+ * const User = Table("User")
32
+ * .database("mydb")
33
+ * .columns((c) => ({
34
+ * id: c.bigint().autoIncrement(),
35
+ * name: c.varchar(100),
36
+ * email: c.varchar(200).nullable(),
37
+ * status: c.varchar(20).default("active"),
38
+ * }))
39
+ * .primaryKey("id")
40
+ * .indexes((i) => [i.index("email").unique()]);
41
+ *
42
+ * // DbContextused in
43
+ * class MyDb extends DbContext {
44
+ * readonly user = queryable(this, User);
45
+ * }
46
+ * ```
47
+ *
48
+ * @see {@link Table} factory function
49
+ * @see {@link queryable} Queryable Generate
50
+ */
51
+ export class TableBuilder<
52
+ TColumns extends ColumnBuilderRecord,
53
+ TRelations extends RelationBuilderRecord,
54
+ > {
55
+ /** Column definition (type for inference) */
56
+ readonly $columns!: TColumns;
57
+ /** relationship definition (type for inference) */
58
+ readonly $relations!: TRelations;
59
+
60
+ /** 전체 Type inference (column + relationship) */
61
+ readonly $infer!: InferColumns<TColumns> & InferDeepRelations<TRelations>;
62
+ /** column만 Type inference */
63
+ readonly $inferColumns!: InferColumns<TColumns>;
64
+ /** INSERT용 Type inference (autoIncrement exclude, nullable/default는 optional) */
65
+ readonly $inferInsert!: InferInsertColumns<TColumns>;
66
+ /** UPDATE용 Type inference (모든 field optional) */
67
+ readonly $inferUpdate!: InferUpdateColumns<TColumns>;
68
+
69
+ /**
70
+ * @param meta - Table Metadata
71
+ * @param meta.name - Table 이름
72
+ * @param meta.description - Table description (주석)
73
+ * @param meta.database - Database 이름
74
+ * @param meta.schema - Schema 이름 (MSSQL/PostgreSQL)
75
+ * @param meta.columns - Column definition
76
+ * @param meta.primaryKey - PK column array
77
+ * @param meta.relations - relationship definition
78
+ * @param meta.indexes - Index definition
79
+ */
80
+ constructor(
81
+ readonly meta: {
82
+ name: string;
83
+ description?: string;
84
+ database?: string;
85
+ schema?: string;
86
+
87
+ columns?: TColumns;
88
+ primaryKey?: (keyof TColumns & string)[];
89
+ relations?: TRelations;
90
+ indexes?: IndexBuilder<(keyof TColumns & string)[]>[];
91
+ },
92
+ ) {}
93
+
94
+ /**
95
+ * Table set description
96
+ *
97
+ * @param desc - Table description (DDL Comment으로 사용)
98
+ * @returns new TableBuilder instance
99
+ */
100
+ description(desc: string) {
101
+ return new TableBuilder({ ...this.meta, description: desc });
102
+ }
103
+
104
+ /**
105
+ * Database set name
106
+ *
107
+ * @param db - Database 이름
108
+ * @returns new TableBuilder instance
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * const User = Table("User").database("mydb");
113
+ * ```
114
+ */
115
+ database(db: string) {
116
+ return new TableBuilder({ ...this.meta, database: db });
117
+ }
118
+
119
+ /**
120
+ * schema set name
121
+ *
122
+ * MSSQL, PostgreSQLused in
123
+ *
124
+ * @param schema - Schema 이름 (MSSQL: dbo, PostgreSQL: public)
125
+ * @returns new TableBuilder instance
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * const User = Table("User")
130
+ * .database("mydb")
131
+ * .schema("custom_schema");
132
+ * ```
133
+ */
134
+ schema(schema: string) {
135
+ return new TableBuilder({ ...this.meta, schema });
136
+ }
137
+
138
+ /**
139
+ * Column definition
140
+ *
141
+ * column factory를 통해 type 안전한 Column definition
142
+ *
143
+ * @template TNewColumnDefs - 새 Column definition type
144
+ * @param fn - Column factory를 받아 Column definition를 반환하는 function
145
+ * @returns new TableBuilder instance
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * const User = Table("User")
150
+ * .columns((c) => ({
151
+ * id: c.bigint().autoIncrement(),
152
+ * name: c.varchar(100),
153
+ * email: c.varchar(200).nullable(),
154
+ * createdAt: c.datetime().default("CURRENT_TIMESTAMP"),
155
+ * }));
156
+ * ```
157
+ */
158
+ columns<TNewColumnDefs extends ColumnBuilderRecord>(
159
+ fn: (c: ReturnType<typeof createColumnFactory>) => TNewColumnDefs,
160
+ ) {
161
+ return new TableBuilder<TNewColumnDefs, TRelations>({
162
+ ...this.meta,
163
+ columns: fn(createColumnFactory()),
164
+ });
165
+ }
166
+
167
+ /**
168
+ * Primary Key 설정
169
+ *
170
+ * @param columns - PK를 구성할 column name들 (복합 PK 가능)
171
+ * @returns new TableBuilder instance
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * // 단일 PK
176
+ * const User = Table("User")
177
+ * .columns((c) => ({ id: c.bigint() }))
178
+ * .primaryKey("id");
179
+ *
180
+ * // 복합 PK
181
+ * const UserRole = Table("UserRole")
182
+ * .columns((c) => ({
183
+ * userId: c.bigint(),
184
+ * roleId: c.bigint(),
185
+ * }))
186
+ * .primaryKey("userId", "roleId");
187
+ * ```
188
+ */
189
+ primaryKey(...columns: (keyof TColumns & string)[]) {
190
+ return new TableBuilder({
191
+ ...this.meta,
192
+ primaryKey: columns,
193
+ });
194
+ }
195
+
196
+ /**
197
+ * Index definition
198
+ *
199
+ * @param fn - Index factory를 받아 Index 배열을 반환하는 function
200
+ * @returns new TableBuilder instance
201
+ *
202
+ * @example
203
+ * ```typescript
204
+ * const User = Table("User")
205
+ * .columns((c) => ({
206
+ * id: c.bigint(),
207
+ * email: c.varchar(200),
208
+ * name: c.varchar(100),
209
+ * }))
210
+ * .indexes((i) => [
211
+ * i.index("email").unique(),
212
+ * i.index("name").orderBy("ASC"),
213
+ * ]);
214
+ * ```
215
+ */
216
+ indexes(
217
+ fn: (
218
+ i: ReturnType<typeof createIndexFactory<keyof TColumns & string>>,
219
+ ) => IndexBuilder<string[]>[],
220
+ ) {
221
+ return new TableBuilder({
222
+ ...this.meta,
223
+ indexes: fn(createIndexFactory<keyof TColumns & string>()),
224
+ });
225
+ }
226
+
227
+ /**
228
+ * relationship definition
229
+ *
230
+ * FK, 역참조 등 Tablerelationship 설정
231
+ *
232
+ * @template T - relationship definition type
233
+ * @param fn - relationship factory를 받아 relationship 정의를 반환하는 function
234
+ * @returns new TableBuilder instance
235
+ *
236
+ * @example
237
+ * ```typescript
238
+ * const Post = Table("Post")
239
+ * .columns((c) => ({
240
+ * id: c.bigint().autoIncrement(),
241
+ * authorId: c.bigint(),
242
+ * title: c.varchar(200),
243
+ * }))
244
+ * .primaryKey("id")
245
+ * .relations((r) => ({
246
+ * // FK relationship (N:1)
247
+ * author: r.foreignKey(["authorId"], () => User),
248
+ * }));
249
+ *
250
+ * const User = Table("User")
251
+ * .columns((c) => ({
252
+ * id: c.bigint().autoIncrement(),
253
+ * name: c.varchar(100),
254
+ * }))
255
+ * .primaryKey("id")
256
+ * .relations((r) => ({
257
+ * // 역참조 (1:N)
258
+ * posts: r.foreignKeyTarget(() => Post, "author"),
259
+ * }));
260
+ * ```
261
+ *
262
+ * @see {@link ForeignKeyBuilder} FK builder
263
+ * @see {@link ForeignKeyTargetBuilder} FK 역참조 builder
264
+ */
265
+ relations<T extends RelationBuilderRecord>(
266
+ fn: (r: ReturnType<typeof createRelationFactory<this, keyof TColumns & string>>) => T,
267
+ ): TableBuilder<TColumns, T> {
268
+ return new TableBuilder({
269
+ ...this.meta,
270
+ relations: fn(createRelationFactory<this, keyof TColumns & string>(() => this)),
271
+ });
272
+ }
273
+ }
274
+
275
+ // ============================================
276
+ // Table function
277
+ // ============================================
278
+
279
+ /**
280
+ * Table builder Generate factory function
281
+ *
282
+ * TableBuilder를 생성하여 Fluent API로 Table schema definition
283
+ *
284
+ * @param name - Table 이름
285
+ * @returns TableBuilder instance
286
+ *
287
+ * @example
288
+ * ```typescript
289
+ * // Basic 사용
290
+ * const User = Table("User")
291
+ * .database("mydb")
292
+ * .columns((c) => ({
293
+ * id: c.bigint().autoIncrement(),
294
+ * name: c.varchar(100),
295
+ * email: c.varchar(200).nullable(),
296
+ * }))
297
+ * .primaryKey("id")
298
+ * .indexes((i) => [i.index("email").unique()]);
299
+ *
300
+ * // relationship include
301
+ * const Post = Table("Post")
302
+ * .database("mydb")
303
+ * .columns((c) => ({
304
+ * id: c.bigint().autoIncrement(),
305
+ * authorId: c.bigint(),
306
+ * title: c.varchar(200),
307
+ * content: c.text(),
308
+ * }))
309
+ * .primaryKey("id")
310
+ * .relations((r) => ({
311
+ * author: r.foreignKey(["authorId"], () => User),
312
+ * }));
313
+ * ```
314
+ *
315
+ * @see {@link TableBuilder} builder class
316
+ */
317
+ export function Table(name: string) {
318
+ return new TableBuilder({ name });
319
+ }