@simplysm/orm-common 13.0.68 → 13.0.70

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 +104 -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,423 +1,423 @@
1
- import type { Bytes, DateOnly, DateTime, Time, Uuid } from "@simplysm/core-common";
2
- import type { ColumnMeta, ColumnPrimitive } from "../../types/column";
3
- import type { ExprInput } from "../../expr/expr-unit";
4
- import type { DataRecord } from "../../types/db";
5
-
6
- // ============================================
7
- // ColumnBuilder
8
- // ============================================
9
-
10
- /**
11
- * 컬럼 정의 빌더
12
- *
13
- * Fluent API를 통해 컬럼의 타입, nullable, autoIncrement, default, 설명을 정의
14
- * TableBuilder.columns()에서 사용
15
- *
16
- * @template TValue - 컬럼 타입
17
- * @template TMeta - 컬럼 메타데이터 타입
18
- *
19
- * @example
20
- * ```typescript
21
- * Table("User")
22
- * .columns((c) => ({
23
- * id: c.bigint().autoIncrement(), // bigint, auto increment
24
- * name: c.varchar(100), // varchar(100), required
25
- * email: c.varchar(200).nullable(), // varchar(200), nullable
26
- * status: c.varchar(20).default("active"), // varchar(20), default
27
- * createdAt: c.datetime().description("생성일시"),
28
- * }));
29
- * ```
30
- *
31
- * @see {@link createColumnFactory} 컬럼 팩토리
32
- * @see {@link TableBuilder} 테이블 빌더
33
- */
34
- export class ColumnBuilder<TValue extends ColumnPrimitive, TMeta extends ColumnMeta> {
35
- /**
36
- * @param meta - 컬럼 메타데이터
37
- */
38
- constructor(readonly meta: TMeta) {}
39
-
40
- /**
41
- * Auto Increment 설정
42
- *
43
- * INSERT 시 자동 증가. INSERT용 타입 추론에서 optional로 처리
44
- *
45
- * @returns ColumnBuilder 인스턴스
46
- *
47
- * @example
48
- * ```typescript
49
- * id: c.bigint().autoIncrement()
50
- * ```
51
- */
52
- autoIncrement(): ColumnBuilder<TValue, Omit<TMeta, "autoIncrement"> & { autoIncrement: true }> {
53
- return new ColumnBuilder({ ...this.meta, autoIncrement: true });
54
- }
55
-
56
- /**
57
- * Nullable 설정
58
- *
59
- * NULL 허용. 타입에 undefined 추가
60
- *
61
- * @returns ColumnBuilder 인스턴스
62
- *
63
- * @example
64
- * ```typescript
65
- * email: c.varchar(200).nullable() // string | undefined
66
- * ```
67
- */
68
- nullable(): ColumnBuilder<TValue | undefined, Omit<TMeta, "nullable"> & { nullable: true }> {
69
- return new ColumnBuilder({ ...this.meta, nullable: true });
70
- }
71
-
72
- /**
73
- * 기본값 설정
74
- *
75
- * INSERT 시 미지정 시 사용. INSERT용 타입 추론에서 optional로 처리
76
- *
77
- * @param value - 기본값
78
- * @returns ColumnBuilder 인스턴스
79
- *
80
- * @example
81
- * ```typescript
82
- * status: c.varchar(20).default("active")
83
- * createdAt: c.datetime().default("CURRENT_TIMESTAMP")
84
- * ```
85
- */
86
- default(
87
- value: TValue,
88
- ): ColumnBuilder<TValue, Omit<TMeta, "default"> & { default: typeof value }> {
89
- return new ColumnBuilder({ ...this.meta, default: value });
90
- }
91
-
92
- /**
93
- * 컬럼 설명 설정
94
- *
95
- * @param desc - 컬럼 설명 (DDL 주석으로 사용)
96
- * @returns ColumnBuilder 인스턴스
97
- *
98
- * @example
99
- * ```typescript
100
- * createdAt: c.datetime().description("레코드 생성 일시")
101
- * ```
102
- */
103
- description(desc: string): ColumnBuilder<TValue, TMeta & { description: string }> {
104
- return new ColumnBuilder({ ...this.meta, description: desc });
105
- }
106
- }
107
-
108
- // ============================================
109
- // 컬럼 팩토리
110
- // ============================================
111
-
112
- /**
113
- * 컬럼 빌더 팩토리 생성
114
- *
115
- * TableBuilder.columns()에서 사용하는 컬럼 타입 팩토리
116
- * 모든 기본 데이터 타입에 대한 빌더 생성 메서드 제공
117
- *
118
- * @returns 컬럼 타입별 빌더 생성 메서드를 포함한 객체
119
- *
120
- * @example
121
- * ```typescript
122
- * Table("User")
123
- * .columns((c) => ({
124
- * // 숫자 타입
125
- * id: c.bigint().autoIncrement(),
126
- * count: c.int(),
127
- * price: c.decimal(10, 2),
128
- *
129
- * // 문자열 타입
130
- * name: c.varchar(100),
131
- * code: c.char(10),
132
- * content: c.text(),
133
- *
134
- * // 날짜/시간 타입
135
- * createdAt: c.datetime(),
136
- * birthDate: c.date(),
137
- * startTime: c.time(),
138
- *
139
- * // 기타 타입
140
- * isActive: c.boolean(),
141
- * data: c.binary(),
142
- * uuid: c.uuid(),
143
- * }));
144
- * ```
145
- *
146
- * @see {@link ColumnBuilder} 컬럼 빌더 클래스
147
- */
148
- export function createColumnFactory() {
149
- return {
150
- /**
151
- * INT 컬럼 (4 bytes, -2^31 ~ 2^31-1)
152
- *
153
- * @returns ColumnBuilder 인스턴스
154
- */
155
- int(): ColumnBuilder<number, { type: "number"; dataType: { type: "int" } }> {
156
- return new ColumnBuilder({ type: "number", dataType: { type: "int" } });
157
- },
158
-
159
- /**
160
- * BIGINT 컬럼 (8 bytes, -2^63 ~ 2^63-1)
161
- *
162
- * @returns ColumnBuilder 인스턴스
163
- */
164
- bigint(): ColumnBuilder<number, { type: "number"; dataType: { type: "bigint" } }> {
165
- return new ColumnBuilder({ type: "number", dataType: { type: "bigint" } });
166
- },
167
-
168
- /**
169
- * FLOAT 컬럼 (4 bytes, 단정밀도 부동소수점)
170
- *
171
- * @returns ColumnBuilder 인스턴스
172
- */
173
- float(): ColumnBuilder<number, { type: "number"; dataType: { type: "float" } }> {
174
- return new ColumnBuilder({ type: "number", dataType: { type: "float" } });
175
- },
176
-
177
- /**
178
- * DOUBLE 컬럼 (8 bytes, 배정밀도 부동소수점)
179
- *
180
- * @returns ColumnBuilder 인스턴스
181
- */
182
- double(): ColumnBuilder<number, { type: "number"; dataType: { type: "double" } }> {
183
- return new ColumnBuilder({ type: "number", dataType: { type: "double" } });
184
- },
185
-
186
- /**
187
- * DECIMAL 컬럼 (고정 소수점)
188
- *
189
- * @param precision - 전체 자릿수
190
- * @param scale - 소수점 이하 자릿수 (선택)
191
- * @returns ColumnBuilder 인스턴스
192
- *
193
- * @example
194
- * ```typescript
195
- * price: c.decimal(10, 2) // DECIMAL(10, 2)
196
- * ```
197
- */
198
- decimal(
199
- precision: number,
200
- scale?: number,
201
- ): ColumnBuilder<
202
- number,
203
- { type: "number"; dataType: { type: "decimal"; precision: number; scale?: number } }
204
- > {
205
- return new ColumnBuilder({ type: "number", dataType: { type: "decimal", precision, scale } });
206
- },
207
-
208
- /**
209
- * VARCHAR 컬럼 (가변 길이 문자열)
210
- *
211
- * @param length - 최대 길이
212
- * @returns ColumnBuilder 인스턴스
213
- *
214
- * @example
215
- * ```typescript
216
- * name: c.varchar(100) // VARCHAR(100)
217
- * ```
218
- */
219
- varchar(
220
- length: number,
221
- ): ColumnBuilder<string, { type: "string"; dataType: { type: "varchar"; length: number } }> {
222
- return new ColumnBuilder({ type: "string", dataType: { type: "varchar", length } });
223
- },
224
-
225
- /**
226
- * CHAR 컬럼 (고정 길이 문자열)
227
- *
228
- * @param length - 고정 길이
229
- * @returns ColumnBuilder 인스턴스
230
- *
231
- * @example
232
- * ```typescript
233
- * countryCode: c.char(2) // CHAR(2)
234
- * ```
235
- */
236
- char(
237
- length: number,
238
- ): ColumnBuilder<string, { type: "string"; dataType: { type: "char"; length: number } }> {
239
- return new ColumnBuilder({ type: "string", dataType: { type: "char" as const, length } });
240
- },
241
-
242
- /**
243
- * TEXT 컬럼 (대용량 문자열)
244
- *
245
- * @returns ColumnBuilder 인스턴스
246
- */
247
- text(): ColumnBuilder<string, { type: "string"; dataType: { type: "text" } }> {
248
- return new ColumnBuilder({ type: "string", dataType: { type: "text" } });
249
- },
250
-
251
- /**
252
- * BINARY 컬럼 (바이너리 데이터)
253
- *
254
- * DBMS별: MySQL=LONGBLOB, MSSQL=VARBINARY(MAX), PostgreSQL=BYTEA
255
- *
256
- * @returns ColumnBuilder 인스턴스
257
- */
258
- binary(): ColumnBuilder<Bytes, { type: "Bytes"; dataType: { type: "binary" } }> {
259
- return new ColumnBuilder({ type: "Bytes", dataType: { type: "binary" } });
260
- },
261
-
262
- /**
263
- * BOOLEAN 컬럼
264
- *
265
- * DBMS별: MySQL=TINYINT(1), MSSQL=BIT, PostgreSQL=BOOLEAN
266
- *
267
- * @returns ColumnBuilder 인스턴스
268
- */
269
- boolean(): ColumnBuilder<boolean, { type: "boolean"; dataType: { type: "boolean" } }> {
270
- return new ColumnBuilder({ type: "boolean", dataType: { type: "boolean" } });
271
- },
272
-
273
- /**
274
- * DATETIME 컬럼 (날짜 + 시간)
275
- *
276
- * @returns ColumnBuilder 인스턴스
277
- */
278
- datetime(): ColumnBuilder<DateTime, { type: "DateTime"; dataType: { type: "datetime" } }> {
279
- return new ColumnBuilder({ type: "DateTime", dataType: { type: "datetime" } });
280
- },
281
-
282
- /**
283
- * DATE 컬럼 (날짜만)
284
- *
285
- * @returns ColumnBuilder 인스턴스
286
- */
287
- date(): ColumnBuilder<DateOnly, { type: "DateOnly"; dataType: { type: "date" } }> {
288
- return new ColumnBuilder({ type: "DateOnly", dataType: { type: "date" } });
289
- },
290
-
291
- /**
292
- * TIME 컬럼 (시간만)
293
- *
294
- * @returns ColumnBuilder 인스턴스
295
- */
296
- time(): ColumnBuilder<Time, { type: "Time"; dataType: { type: "time" } }> {
297
- return new ColumnBuilder({ type: "Time", dataType: { type: "time" } });
298
- },
299
-
300
- /**
301
- * UUID 컬럼
302
- *
303
- * DBMS별: MySQL=BINARY(16), MSSQL=UNIQUEIDENTIFIER, PostgreSQL=UUID
304
- *
305
- * @returns ColumnBuilder 인스턴스
306
- */
307
- uuid(): ColumnBuilder<Uuid, { type: "Uuid"; dataType: { type: "uuid" } }> {
308
- return new ColumnBuilder({ type: "Uuid", dataType: { type: "uuid" } });
309
- },
310
- };
311
- }
312
-
313
- // ============================================
314
- // ColumnDefRecord - 컬럼 빌더 레코드
315
- // ============================================
316
-
317
- /**
318
- * 컬럼 빌더 레코드 타입
319
- *
320
- * TableBuilder.columns()의 반환 타입으로 사용
321
- */
322
- export type ColumnBuilderRecord = Record<string, ColumnBuilder<ColumnPrimitive, ColumnMeta>>;
323
-
324
- // ============================================
325
- // Infer - 타입 추론 유틸리티
326
- // ============================================
327
-
328
- /**
329
- * 컬럼 빌더 레코드에서 실제 타입 추론
330
- *
331
- * @template T - 컬럼 빌더 레코드 타입
332
- *
333
- * @example
334
- * ```typescript
335
- * type UserColumns = InferColumns<typeof User.$columns>;
336
- * // { id: number; name: string; email: string | undefined; }
337
- * ```
338
- */
339
- export type InferColumns<TBuilders extends ColumnBuilderRecord> = {
340
- [K in keyof TBuilders]: TBuilders[K] extends ColumnBuilder<infer V, any> ? V : never;
341
- };
342
-
343
- /**
344
- * 컬럼 빌더 레코드에서 표현식 입력 타입 추론
345
- *
346
- * @template T - 컬럼 빌더 레코드 타입
347
- */
348
- export type InferColumnExprs<TBuilders extends ColumnBuilderRecord> = {
349
- [K in keyof TBuilders]: TBuilders[K] extends ColumnBuilder<infer V, any> ? ExprInput<V> : never;
350
- };
351
-
352
- /**
353
- * INSERT 시 필수 컬럼 추출
354
- *
355
- * autoIncrement, nullable, default가 없는 컬럼만 필수
356
- *
357
- * @template T - 컬럼 빌더 레코드 타입
358
- */
359
- export type RequiredInsertKeys<TBuilders extends ColumnBuilderRecord> = {
360
- [K in keyof TBuilders]: TBuilders[K]["meta"] extends infer M extends ColumnMeta
361
- ? M["autoIncrement"] extends true
362
- ? never
363
- : M["nullable"] extends true
364
- ? never
365
- : M["default"] extends undefined
366
- ? K
367
- : never
368
- : never;
369
- }[keyof TBuilders];
370
-
371
- /**
372
- * INSERT 시 선택적 컬럼 추출
373
- *
374
- * autoIncrement, nullable, default가 있는 컬럼은 optional
375
- *
376
- * @template T - 컬럼 빌더 레코드 타입
377
- */
378
- export type OptionalInsertKeys<TBuilders extends ColumnBuilderRecord> = Exclude<
379
- keyof TBuilders,
380
- RequiredInsertKeys<TBuilders>
381
- >;
382
-
383
- /**
384
- * INSERT용 타입 추론
385
- *
386
- * 필수 컬럼은 required, optional 컬럼은 Partial
387
- *
388
- * @template T - 컬럼 빌더 레코드 타입
389
- *
390
- * @example
391
- * ```typescript
392
- * type UserInsert = InferInsertColumns<typeof User.$columns>;
393
- * // { name: string; } & { id?: number; email?: string; status?: string; }
394
- * ```
395
- */
396
- export type InferInsertColumns<TBuilders extends ColumnBuilderRecord> = Pick<
397
- InferColumns<TBuilders>,
398
- RequiredInsertKeys<TBuilders>
399
- > &
400
- Partial<Pick<InferColumns<TBuilders>, OptionalInsertKeys<TBuilders>>>;
401
-
402
- /**
403
- * UPDATE용 타입 추론
404
- *
405
- * 모든 컬럼이 optional
406
- *
407
- * @template T - 컬럼 빌더 레코드 타입
408
- */
409
- export type InferUpdateColumns<TBuilders extends ColumnBuilderRecord> = Partial<
410
- InferColumns<TBuilders>
411
- >;
412
-
413
- /**
414
- * 데이터 레코드에서 컬럼 빌더 레코드로 변환
415
- *
416
- * @template TData - 데이터 레코드 타입
417
- */
418
- export type DataToColumnBuilderRecord<TData extends DataRecord> = {
419
- [K in keyof TData as TData[K] extends ColumnPrimitive ? K : never]: ColumnBuilder<
420
- TData[K] extends ColumnPrimitive ? TData[K] : never,
421
- any
422
- >;
423
- };
1
+ import type { Bytes, DateOnly, DateTime, Time, Uuid } from "@simplysm/core-common";
2
+ import type { ColumnMeta, ColumnPrimitive } from "../../types/column";
3
+ import type { ExprInput } from "../../expr/expr-unit";
4
+ import type { DataRecord } from "../../types/db";
5
+
6
+ // ============================================
7
+ // ColumnBuilder
8
+ // ============================================
9
+
10
+ /**
11
+ * Column definition builder
12
+ *
13
+ * Fluent API를 통해 column의 type, nullable, autoIncrement, default, description을 definition
14
+ * TableBuilder.columns()used in
15
+ *
16
+ * @template TValue - Column value type
17
+ * @template TMeta - Column Metadata type
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * Table("User")
22
+ * .columns((c) => ({
23
+ * id: c.bigint().autoIncrement(), // bigint, auto increment
24
+ * name: c.varchar(100), // varchar(100), required
25
+ * email: c.varchar(200).nullable(), // varchar(200), nullable
26
+ * status: c.varchar(20).default("active"), // varchar(20), default value
27
+ * createdAt: c.datetime().description("생성일시"),
28
+ * }));
29
+ * ```
30
+ *
31
+ * @see {@link createColumnFactory} column factory
32
+ * @see {@link TableBuilder} Table builder
33
+ */
34
+ export class ColumnBuilder<TValue extends ColumnPrimitive, TMeta extends ColumnMeta> {
35
+ /**
36
+ * @param meta - Column Metadata
37
+ */
38
+ constructor(readonly meta: TMeta) {}
39
+
40
+ /**
41
+ * Auto Increment 설정
42
+ *
43
+ * INSERT 시 Auto increment. INSERT용 Type inference에서 optional로 processing
44
+ *
45
+ * @returns new ColumnBuilder instance
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * id: c.bigint().autoIncrement()
50
+ * ```
51
+ */
52
+ autoIncrement(): ColumnBuilder<TValue, Omit<TMeta, "autoIncrement"> & { autoIncrement: true }> {
53
+ return new ColumnBuilder({ ...this.meta, autoIncrement: true });
54
+ }
55
+
56
+ /**
57
+ * Nullable 설정
58
+ *
59
+ * Allow NULL. value 타입에 undefined Add
60
+ *
61
+ * @returns new ColumnBuilder instance
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * email: c.varchar(200).nullable() // string | undefined
66
+ * ```
67
+ */
68
+ nullable(): ColumnBuilder<TValue | undefined, Omit<TMeta, "nullable"> & { nullable: true }> {
69
+ return new ColumnBuilder({ ...this.meta, nullable: true });
70
+ }
71
+
72
+ /**
73
+ * Default value 설정
74
+ *
75
+ * INSERT 시 value 미지정 시 사용. INSERT용 Type inference에서 optional로 processing
76
+ *
77
+ * @param value - Default value
78
+ * @returns new ColumnBuilder instance
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * status: c.varchar(20).default("active")
83
+ * createdAt: c.datetime().default("CURRENT_TIMESTAMP")
84
+ * ```
85
+ */
86
+ default(
87
+ value: TValue,
88
+ ): ColumnBuilder<TValue, Omit<TMeta, "default"> & { default: typeof value }> {
89
+ return new ColumnBuilder({ ...this.meta, default: value });
90
+ }
91
+
92
+ /**
93
+ * column set description
94
+ *
95
+ * @param desc - Column description (DDL Comment으로 사용)
96
+ * @returns new ColumnBuilder instance
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * createdAt: c.datetime().description("레코드 Generate 일시")
101
+ * ```
102
+ */
103
+ description(desc: string): ColumnBuilder<TValue, TMeta & { description: string }> {
104
+ return new ColumnBuilder({ ...this.meta, description: desc });
105
+ }
106
+ }
107
+
108
+ // ============================================
109
+ // column factory
110
+ // ============================================
111
+
112
+ /**
113
+ * Column builder factory Generate
114
+ *
115
+ * TableBuilder.columns()used in하는 Column type factory
116
+ * 모든 Basic data type에 대한 builder Generate method 제공
117
+ *
118
+ * @returns Column type별 builder Generate 메서드를 포함한 object
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * Table("User")
123
+ * .columns((c) => ({
124
+ * // Number type
125
+ * id: c.bigint().autoIncrement(),
126
+ * count: c.int(),
127
+ * price: c.decimal(10, 2),
128
+ *
129
+ * // 문자열 type
130
+ * name: c.varchar(100),
131
+ * code: c.char(10),
132
+ * content: c.text(),
133
+ *
134
+ * // Date/시간 type
135
+ * createdAt: c.datetime(),
136
+ * birthDate: c.date(),
137
+ * startTime: c.time(),
138
+ *
139
+ * // Other type
140
+ * isActive: c.boolean(),
141
+ * data: c.binary(),
142
+ * uuid: c.uuid(),
143
+ * }));
144
+ * ```
145
+ *
146
+ * @see {@link ColumnBuilder} Column builder class
147
+ */
148
+ export function createColumnFactory() {
149
+ return {
150
+ /**
151
+ * INT column (4 bytes, -2^31 ~ 2^31-1)
152
+ *
153
+ * @returns ColumnBuilder instance
154
+ */
155
+ int(): ColumnBuilder<number, { type: "number"; dataType: { type: "int" } }> {
156
+ return new ColumnBuilder({ type: "number", dataType: { type: "int" } });
157
+ },
158
+
159
+ /**
160
+ * BIGINT column (8 bytes, -2^63 ~ 2^63-1)
161
+ *
162
+ * @returns ColumnBuilder instance
163
+ */
164
+ bigint(): ColumnBuilder<number, { type: "number"; dataType: { type: "bigint" } }> {
165
+ return new ColumnBuilder({ type: "number", dataType: { type: "bigint" } });
166
+ },
167
+
168
+ /**
169
+ * FLOAT column (4 bytes, 단정밀도 부동소수점)
170
+ *
171
+ * @returns ColumnBuilder instance
172
+ */
173
+ float(): ColumnBuilder<number, { type: "number"; dataType: { type: "float" } }> {
174
+ return new ColumnBuilder({ type: "number", dataType: { type: "float" } });
175
+ },
176
+
177
+ /**
178
+ * DOUBLE column (8 bytes, 배정밀도 부동소수점)
179
+ *
180
+ * @returns ColumnBuilder instance
181
+ */
182
+ double(): ColumnBuilder<number, { type: "number"; dataType: { type: "double" } }> {
183
+ return new ColumnBuilder({ type: "number", dataType: { type: "double" } });
184
+ },
185
+
186
+ /**
187
+ * DECIMAL column (고정 소수점)
188
+ *
189
+ * @param precision - 전체 자릿수
190
+ * @param scale - 소수점 이하 자릿수 (Select)
191
+ * @returns ColumnBuilder instance
192
+ *
193
+ * @example
194
+ * ```typescript
195
+ * price: c.decimal(10, 2) // DECIMAL(10, 2)
196
+ * ```
197
+ */
198
+ decimal(
199
+ precision: number,
200
+ scale?: number,
201
+ ): ColumnBuilder<
202
+ number,
203
+ { type: "number"; dataType: { type: "decimal"; precision: number; scale?: number } }
204
+ > {
205
+ return new ColumnBuilder({ type: "number", dataType: { type: "decimal", precision, scale } });
206
+ },
207
+
208
+ /**
209
+ * VARCHAR column (가변 길이 문자열)
210
+ *
211
+ * @param length - 최대 길이
212
+ * @returns ColumnBuilder instance
213
+ *
214
+ * @example
215
+ * ```typescript
216
+ * name: c.varchar(100) // VARCHAR(100)
217
+ * ```
218
+ */
219
+ varchar(
220
+ length: number,
221
+ ): ColumnBuilder<string, { type: "string"; dataType: { type: "varchar"; length: number } }> {
222
+ return new ColumnBuilder({ type: "string", dataType: { type: "varchar", length } });
223
+ },
224
+
225
+ /**
226
+ * CHAR column (고정 길이 문자열)
227
+ *
228
+ * @param length - 고정 길이
229
+ * @returns ColumnBuilder instance
230
+ *
231
+ * @example
232
+ * ```typescript
233
+ * countryCode: c.char(2) // CHAR(2)
234
+ * ```
235
+ */
236
+ char(
237
+ length: number,
238
+ ): ColumnBuilder<string, { type: "string"; dataType: { type: "char"; length: number } }> {
239
+ return new ColumnBuilder({ type: "string", dataType: { type: "char" as const, length } });
240
+ },
241
+
242
+ /**
243
+ * TEXT column (대용량 문자열)
244
+ *
245
+ * @returns ColumnBuilder instance
246
+ */
247
+ text(): ColumnBuilder<string, { type: "string"; dataType: { type: "text" } }> {
248
+ return new ColumnBuilder({ type: "string", dataType: { type: "text" } });
249
+ },
250
+
251
+ /**
252
+ * BINARY column (바이너리 data)
253
+ *
254
+ * DBMS별: MySQL=LONGBLOB, MSSQL=VARBINARY(MAX), PostgreSQL=BYTEA
255
+ *
256
+ * @returns ColumnBuilder instance
257
+ */
258
+ binary(): ColumnBuilder<Bytes, { type: "Bytes"; dataType: { type: "binary" } }> {
259
+ return new ColumnBuilder({ type: "Bytes", dataType: { type: "binary" } });
260
+ },
261
+
262
+ /**
263
+ * BOOLEAN column
264
+ *
265
+ * DBMS별: MySQL=TINYINT(1), MSSQL=BIT, PostgreSQL=BOOLEAN
266
+ *
267
+ * @returns ColumnBuilder instance
268
+ */
269
+ boolean(): ColumnBuilder<boolean, { type: "boolean"; dataType: { type: "boolean" } }> {
270
+ return new ColumnBuilder({ type: "boolean", dataType: { type: "boolean" } });
271
+ },
272
+
273
+ /**
274
+ * DATETIME column (Date + 시간)
275
+ *
276
+ * @returns ColumnBuilder instance
277
+ */
278
+ datetime(): ColumnBuilder<DateTime, { type: "DateTime"; dataType: { type: "datetime" } }> {
279
+ return new ColumnBuilder({ type: "DateTime", dataType: { type: "datetime" } });
280
+ },
281
+
282
+ /**
283
+ * DATE column (Date만)
284
+ *
285
+ * @returns ColumnBuilder instance
286
+ */
287
+ date(): ColumnBuilder<DateOnly, { type: "DateOnly"; dataType: { type: "date" } }> {
288
+ return new ColumnBuilder({ type: "DateOnly", dataType: { type: "date" } });
289
+ },
290
+
291
+ /**
292
+ * TIME column (시간만)
293
+ *
294
+ * @returns ColumnBuilder instance
295
+ */
296
+ time(): ColumnBuilder<Time, { type: "Time"; dataType: { type: "time" } }> {
297
+ return new ColumnBuilder({ type: "Time", dataType: { type: "time" } });
298
+ },
299
+
300
+ /**
301
+ * UUID column
302
+ *
303
+ * DBMS별: MySQL=BINARY(16), MSSQL=UNIQUEIDENTIFIER, PostgreSQL=UUID
304
+ *
305
+ * @returns ColumnBuilder instance
306
+ */
307
+ uuid(): ColumnBuilder<Uuid, { type: "Uuid"; dataType: { type: "uuid" } }> {
308
+ return new ColumnBuilder({ type: "Uuid", dataType: { type: "uuid" } });
309
+ },
310
+ };
311
+ }
312
+
313
+ // ============================================
314
+ // ColumnDefRecord - Column builder 레코드
315
+ // ============================================
316
+
317
+ /**
318
+ * Column builder record type
319
+ *
320
+ * TableBuilder.columns()의 return 타입으로 사용
321
+ */
322
+ export type ColumnBuilderRecord = Record<string, ColumnBuilder<ColumnPrimitive, ColumnMeta>>;
323
+
324
+ // ============================================
325
+ // Infer - Type inference 유틸리티
326
+ // ============================================
327
+
328
+ /**
329
+ * Column builder 레코드에서 실제 value Type inference
330
+ *
331
+ * @template T - Column builder record type
332
+ *
333
+ * @example
334
+ * ```typescript
335
+ * type UserColumns = InferColumns<typeof User.$columns>;
336
+ * // { id: number; name: string; email: string | undefined; }
337
+ * ```
338
+ */
339
+ export type InferColumns<TBuilders extends ColumnBuilderRecord> = {
340
+ [K in keyof TBuilders]: TBuilders[K] extends ColumnBuilder<infer V, any> ? V : never;
341
+ };
342
+
343
+ /**
344
+ * Column builder 레코드에서 expression 입력 Type inference
345
+ *
346
+ * @template T - Column builder record type
347
+ */
348
+ export type InferColumnExprs<TBuilders extends ColumnBuilderRecord> = {
349
+ [K in keyof TBuilders]: TBuilders[K] extends ColumnBuilder<infer V, any> ? ExprInput<V> : never;
350
+ };
351
+
352
+ /**
353
+ * INSERT 시 required column key 추출
354
+ *
355
+ * autoIncrement, nullable, default가 없는 column만 required
356
+ *
357
+ * @template T - Column builder record type
358
+ */
359
+ export type RequiredInsertKeys<TBuilders extends ColumnBuilderRecord> = {
360
+ [K in keyof TBuilders]: TBuilders[K]["meta"] extends infer M extends ColumnMeta
361
+ ? M["autoIncrement"] extends true
362
+ ? never
363
+ : M["nullable"] extends true
364
+ ? never
365
+ : M["default"] extends undefined
366
+ ? K
367
+ : never
368
+ : never;
369
+ }[keyof TBuilders];
370
+
371
+ /**
372
+ * INSERT 시 optional column key 추출
373
+ *
374
+ * autoIncrement, nullable, default가 있는 column은 optional
375
+ *
376
+ * @template T - Column builder record type
377
+ */
378
+ export type OptionalInsertKeys<TBuilders extends ColumnBuilderRecord> = Exclude<
379
+ keyof TBuilders,
380
+ RequiredInsertKeys<TBuilders>
381
+ >;
382
+
383
+ /**
384
+ * INSERT용 Type inference
385
+ *
386
+ * required column은 required, optional column은 Partial
387
+ *
388
+ * @template T - Column builder record type
389
+ *
390
+ * @example
391
+ * ```typescript
392
+ * type UserInsert = InferInsertColumns<typeof User.$columns>;
393
+ * // { name: string; } & { id?: number; email?: string; status?: string; }
394
+ * ```
395
+ */
396
+ export type InferInsertColumns<TBuilders extends ColumnBuilderRecord> = Pick<
397
+ InferColumns<TBuilders>,
398
+ RequiredInsertKeys<TBuilders>
399
+ > &
400
+ Partial<Pick<InferColumns<TBuilders>, OptionalInsertKeys<TBuilders>>>;
401
+
402
+ /**
403
+ * UPDATE용 Type inference
404
+ *
405
+ * 모든 column이 optional
406
+ *
407
+ * @template T - Column builder record type
408
+ */
409
+ export type InferUpdateColumns<TBuilders extends ColumnBuilderRecord> = Partial<
410
+ InferColumns<TBuilders>
411
+ >;
412
+
413
+ /**
414
+ * data 레코드에서 Column builder 레코드로 Transform
415
+ *
416
+ * @template TData - data record type
417
+ */
418
+ export type DataToColumnBuilderRecord<TData extends DataRecord> = {
419
+ [K in keyof TData as TData[K] extends ColumnPrimitive ? K : never]: ColumnBuilder<
420
+ TData[K] extends ColumnPrimitive ? TData[K] : never,
421
+ any
422
+ >;
423
+ };