@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.
- package/README.md +54 -1447
- package/dist/create-db-context.d.ts +10 -10
- package/dist/create-db-context.js +9 -9
- package/dist/create-db-context.js.map +1 -1
- package/dist/ddl/column-ddl.d.ts +4 -4
- package/dist/ddl/initialize.d.ts +17 -17
- package/dist/ddl/initialize.js +2 -2
- package/dist/ddl/initialize.js.map +1 -1
- package/dist/ddl/relation-ddl.d.ts +6 -6
- package/dist/ddl/schema-ddl.d.ts +4 -4
- package/dist/ddl/table-ddl.d.ts +24 -24
- package/dist/ddl/table-ddl.js +4 -4
- package/dist/ddl/table-ddl.js.map +1 -1
- package/dist/errors/db-transaction-error.d.ts +15 -15
- package/dist/errors/db-transaction-error.d.ts.map +1 -1
- package/dist/exec/executable.d.ts +23 -23
- package/dist/exec/executable.js +3 -3
- package/dist/exec/executable.js.map +1 -1
- package/dist/exec/queryable.d.ts +160 -160
- package/dist/exec/queryable.js +119 -119
- package/dist/exec/queryable.js.map +1 -1
- package/dist/exec/search-parser.d.ts +37 -37
- package/dist/exec/search-parser.d.ts.map +1 -1
- package/dist/expr/expr-unit.d.ts +4 -4
- package/dist/expr/expr.d.ts +257 -257
- package/dist/expr/expr.js +265 -265
- package/dist/expr/expr.js.map +1 -1
- package/dist/query-builder/base/expr-renderer-base.d.ts +9 -9
- package/dist/query-builder/base/expr-renderer-base.js +2 -2
- package/dist/query-builder/base/expr-renderer-base.js.map +1 -1
- package/dist/query-builder/base/query-builder-base.d.ts +26 -26
- package/dist/query-builder/base/query-builder-base.d.ts.map +1 -1
- package/dist/query-builder/base/query-builder-base.js +22 -22
- package/dist/query-builder/base/query-builder-base.js.map +1 -1
- package/dist/query-builder/mssql/mssql-expr-renderer.d.ts +4 -4
- package/dist/query-builder/mssql/mssql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/mssql/mssql-expr-renderer.js +18 -18
- package/dist/query-builder/mssql/mssql-expr-renderer.js.map +1 -1
- package/dist/query-builder/mssql/mssql-query-builder.d.ts +2 -2
- package/dist/query-builder/mssql/mssql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/mssql/mssql-query-builder.js +11 -11
- package/dist/query-builder/mssql/mssql-query-builder.js.map +1 -1
- package/dist/query-builder/mysql/mysql-expr-renderer.d.ts +4 -4
- package/dist/query-builder/mysql/mysql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/mysql/mysql-expr-renderer.js +17 -17
- package/dist/query-builder/mysql/mysql-expr-renderer.js.map +1 -1
- package/dist/query-builder/mysql/mysql-query-builder.d.ts +8 -8
- package/dist/query-builder/mysql/mysql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/mysql/mysql-query-builder.js +5 -5
- package/dist/query-builder/mysql/mysql-query-builder.js.map +1 -1
- package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts +4 -4
- package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/postgresql/postgresql-expr-renderer.js +17 -17
- package/dist/query-builder/postgresql/postgresql-expr-renderer.js.map +1 -1
- package/dist/query-builder/postgresql/postgresql-query-builder.d.ts +5 -5
- package/dist/query-builder/postgresql/postgresql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/postgresql/postgresql-query-builder.js +8 -8
- package/dist/query-builder/postgresql/postgresql-query-builder.js.map +1 -1
- package/dist/query-builder/query-builder.d.ts +1 -1
- package/dist/schema/factory/column-builder.d.ts +79 -79
- package/dist/schema/factory/column-builder.js +42 -42
- package/dist/schema/factory/index-builder.d.ts +39 -39
- package/dist/schema/factory/index-builder.js +26 -26
- package/dist/schema/factory/relation-builder.d.ts +99 -99
- package/dist/schema/factory/relation-builder.d.ts.map +1 -1
- package/dist/schema/factory/relation-builder.js +38 -38
- package/dist/schema/procedure-builder.d.ts +49 -49
- package/dist/schema/procedure-builder.d.ts.map +1 -1
- package/dist/schema/procedure-builder.js +33 -33
- package/dist/schema/table-builder.d.ts +59 -59
- package/dist/schema/table-builder.d.ts.map +1 -1
- package/dist/schema/table-builder.js +43 -43
- package/dist/schema/view-builder.d.ts +49 -49
- package/dist/schema/view-builder.d.ts.map +1 -1
- package/dist/schema/view-builder.js +32 -32
- package/dist/types/column.d.ts +22 -22
- package/dist/types/column.js +1 -1
- package/dist/types/column.js.map +1 -1
- package/dist/types/db.d.ts +40 -40
- package/dist/types/expr.d.ts +59 -59
- package/dist/types/expr.d.ts.map +1 -1
- package/dist/types/query-def.d.ts +44 -44
- package/dist/types/query-def.d.ts.map +1 -1
- package/dist/utils/result-parser.d.ts +11 -11
- package/dist/utils/result-parser.js +3 -3
- package/dist/utils/result-parser.js.map +1 -1
- package/package.json +5 -5
- package/src/create-db-context.ts +20 -20
- package/src/ddl/column-ddl.ts +4 -4
- package/src/ddl/initialize.ts +259 -259
- package/src/ddl/relation-ddl.ts +89 -89
- package/src/ddl/schema-ddl.ts +4 -4
- package/src/ddl/table-ddl.ts +189 -189
- package/src/errors/db-transaction-error.ts +13 -13
- package/src/exec/executable.ts +25 -25
- package/src/exec/queryable.ts +2033 -2033
- package/src/exec/search-parser.ts +57 -57
- package/src/expr/expr-unit.ts +4 -4
- package/src/expr/expr.ts +2140 -2140
- package/src/query-builder/base/expr-renderer-base.ts +237 -237
- package/src/query-builder/base/query-builder-base.ts +213 -213
- package/src/query-builder/mssql/mssql-expr-renderer.ts +607 -607
- package/src/query-builder/mssql/mssql-query-builder.ts +650 -650
- package/src/query-builder/mysql/mysql-expr-renderer.ts +613 -613
- package/src/query-builder/mysql/mysql-query-builder.ts +759 -759
- package/src/query-builder/postgresql/postgresql-expr-renderer.ts +611 -611
- package/src/query-builder/postgresql/postgresql-query-builder.ts +686 -686
- package/src/query-builder/query-builder.ts +19 -19
- package/src/schema/factory/column-builder.ts +423 -423
- package/src/schema/factory/index-builder.ts +164 -164
- package/src/schema/factory/relation-builder.ts +453 -453
- package/src/schema/procedure-builder.ts +232 -232
- package/src/schema/table-builder.ts +319 -319
- package/src/schema/view-builder.ts +221 -221
- package/src/types/column.ts +188 -188
- package/src/types/db.ts +208 -208
- package/src/types/expr.ts +697 -697
- package/src/types/query-def.ts +513 -513
- package/src/utils/result-parser.ts +458 -458
- package/tests/db-context/create-db-context.spec.ts +224 -0
- package/tests/db-context/define-db-context.spec.ts +68 -0
- package/tests/ddl/basic.expected.ts +341 -0
- package/tests/ddl/basic.spec.ts +714 -0
- package/tests/ddl/column-builder.expected.ts +310 -0
- package/tests/ddl/column-builder.spec.ts +637 -0
- package/tests/ddl/index-builder.expected.ts +38 -0
- package/tests/ddl/index-builder.spec.ts +202 -0
- package/tests/ddl/procedure-builder.expected.ts +52 -0
- package/tests/ddl/procedure-builder.spec.ts +234 -0
- package/tests/ddl/relation-builder.expected.ts +36 -0
- package/tests/ddl/relation-builder.spec.ts +372 -0
- package/tests/ddl/table-builder.expected.ts +113 -0
- package/tests/ddl/table-builder.spec.ts +433 -0
- package/tests/ddl/view-builder.expected.ts +38 -0
- package/tests/ddl/view-builder.spec.ts +176 -0
- package/tests/dml/delete.expected.ts +96 -0
- package/tests/dml/delete.spec.ts +160 -0
- package/tests/dml/insert.expected.ts +192 -0
- package/tests/dml/insert.spec.ts +288 -0
- package/tests/dml/update.expected.ts +176 -0
- package/tests/dml/update.spec.ts +318 -0
- package/tests/dml/upsert.expected.ts +215 -0
- package/tests/dml/upsert.spec.ts +242 -0
- package/tests/errors/queryable-errors.spec.ts +177 -0
- package/tests/escape.spec.ts +100 -0
- package/tests/examples/pivot.expected.ts +211 -0
- package/tests/examples/pivot.spec.ts +533 -0
- package/tests/examples/sampling.expected.ts +69 -0
- package/tests/examples/sampling.spec.ts +104 -0
- package/tests/examples/unpivot.expected.ts +120 -0
- package/tests/examples/unpivot.spec.ts +226 -0
- package/tests/exec/search-parser.spec.ts +283 -0
- package/tests/executable/basic.expected.ts +18 -0
- package/tests/executable/basic.spec.ts +54 -0
- package/tests/expr/comparison.expected.ts +282 -0
- package/tests/expr/comparison.spec.ts +400 -0
- package/tests/expr/conditional.expected.ts +134 -0
- package/tests/expr/conditional.spec.ts +276 -0
- package/tests/expr/date.expected.ts +332 -0
- package/tests/expr/date.spec.ts +526 -0
- package/tests/expr/math.expected.ts +62 -0
- package/tests/expr/math.spec.ts +106 -0
- package/tests/expr/string.expected.ts +218 -0
- package/tests/expr/string.spec.ts +356 -0
- package/tests/expr/utility.expected.ts +147 -0
- package/tests/expr/utility.spec.ts +182 -0
- package/tests/select/basic.expected.ts +322 -0
- package/tests/select/basic.spec.ts +502 -0
- package/tests/select/filter.expected.ts +357 -0
- package/tests/select/filter.spec.ts +1068 -0
- package/tests/select/group.expected.ts +169 -0
- package/tests/select/group.spec.ts +244 -0
- package/tests/select/join.expected.ts +582 -0
- package/tests/select/join.spec.ts +805 -0
- package/tests/select/order.expected.ts +150 -0
- package/tests/select/order.spec.ts +189 -0
- package/tests/select/recursive-cte.expected.ts +244 -0
- package/tests/select/recursive-cte.spec.ts +514 -0
- package/tests/select/result-meta.spec.ts +270 -0
- package/tests/select/subquery.expected.ts +363 -0
- package/tests/select/subquery.spec.ts +537 -0
- package/tests/select/view.expected.ts +155 -0
- package/tests/select/view.spec.ts +235 -0
- package/tests/select/window.expected.ts +345 -0
- package/tests/select/window.spec.ts +618 -0
- package/tests/setup/MockExecutor.ts +18 -0
- package/tests/setup/TestDbContext.ts +59 -0
- package/tests/setup/models/Company.ts +13 -0
- package/tests/setup/models/Employee.ts +10 -0
- package/tests/setup/models/MonthlySales.ts +11 -0
- package/tests/setup/models/Post.ts +16 -0
- package/tests/setup/models/Sales.ts +10 -0
- package/tests/setup/models/User.ts +19 -0
- package/tests/setup/procedure/GetAllUsers.ts +9 -0
- package/tests/setup/procedure/GetUserById.ts +12 -0
- package/tests/setup/test-utils.ts +72 -0
- package/tests/setup/views/ActiveUsers.ts +8 -0
- package/tests/setup/views/UserSummary.ts +11 -0
- package/tests/types/nullable-queryable-record.spec.ts +145 -0
- package/tests/utils/result-parser-perf.spec.ts +210 -0
- package/tests/utils/result-parser.spec.ts +701 -0
- package/docs/expressions.md +0 -172
- package/docs/queries.md +0 -444
- 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를 통해
|
|
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
|
-
* //
|
|
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용
|
|
65
|
-
readonly $inferInsert!: InferInsertColumns<TColumns>;
|
|
66
|
-
/** UPDATE용
|
|
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 -
|
|
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 -
|
|
98
|
-
* @returns
|
|
99
|
-
*/
|
|
100
|
-
description(desc: string) {
|
|
101
|
-
return new TableBuilder({ ...this.meta, description: desc });
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* @param db -
|
|
108
|
-
* @returns
|
|
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,
|
|
123
|
-
*
|
|
124
|
-
* @param schema -
|
|
125
|
-
* @returns
|
|
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
|
|
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를 구성할
|
|
171
|
-
* @returns
|
|
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
|
|
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
|
|
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
|
|
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, 역참조 등 Table 간 relationship 설정
|
|
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
|
+
}
|