@simplysm/orm-common 14.1.2 → 14.1.6
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/dist/db-context.d.ts +11 -10
- package/dist/db-context.d.ts.map +1 -1
- package/dist/db-context.js +14 -11
- package/dist/db-context.js.map +1 -1
- package/dist/ddl/initialize.js.map +1 -1
- package/dist/ddl/relation-ddl.d.ts +1 -1
- package/dist/ddl/relation-ddl.d.ts.map +1 -1
- package/dist/ddl/relation-ddl.js.map +1 -1
- package/dist/ddl/table-ddl.d.ts +3 -3
- package/dist/ddl/table-ddl.d.ts.map +1 -1
- package/dist/ddl/table-ddl.js.map +1 -1
- package/dist/errors/db-transaction-error.d.ts +4 -5
- package/dist/errors/db-transaction-error.d.ts.map +1 -1
- package/dist/errors/db-transaction-error.js +5 -6
- package/dist/errors/db-transaction-error.js.map +1 -1
- package/dist/exec/executable.d.ts +4 -13
- package/dist/exec/executable.d.ts.map +1 -1
- package/dist/exec/executable.js.map +1 -1
- package/dist/exec/queryable.d.ts +11 -9
- package/dist/exec/queryable.d.ts.map +1 -1
- package/dist/exec/queryable.js +9 -5
- package/dist/exec/queryable.js.map +1 -1
- package/dist/expr/expr.d.ts +7 -4
- package/dist/expr/expr.d.ts.map +1 -1
- package/dist/expr/expr.js +5 -2
- package/dist/expr/expr.js.map +1 -1
- package/dist/models/system-migration.d.ts +1 -1
- package/dist/models/system-migration.d.ts.map +1 -1
- package/dist/query-builder/base/expr-renderer-base.d.ts +2 -1
- package/dist/query-builder/base/expr-renderer-base.d.ts.map +1 -1
- package/dist/query-builder/base/expr-renderer-base.js.map +1 -1
- package/dist/query-builder/mssql/mssql-expr-renderer.d.ts +2 -2
- package/dist/query-builder/mssql/mssql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/mssql/mssql-expr-renderer.js.map +1 -1
- package/dist/query-builder/mysql/mysql-expr-renderer.d.ts +2 -2
- package/dist/query-builder/mysql/mysql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/mysql/mysql-expr-renderer.js.map +1 -1
- package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts +2 -2
- package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/postgresql/postgresql-expr-renderer.js.map +1 -1
- package/dist/query-builder/postgresql/postgresql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/postgresql/postgresql-query-builder.js.map +1 -1
- package/dist/schema/factory/column-builder.d.ts +1 -1
- package/dist/schema/factory/column-builder.d.ts.map +1 -1
- package/dist/schema/factory/relation-builder.d.ts +55 -49
- package/dist/schema/factory/relation-builder.d.ts.map +1 -1
- package/dist/schema/factory/relation-builder.js +12 -15
- package/dist/schema/factory/relation-builder.js.map +1 -1
- package/dist/schema/table-builder.d.ts +35 -18
- package/dist/schema/table-builder.d.ts.map +1 -1
- package/dist/schema/table-builder.js +32 -15
- package/dist/schema/table-builder.js.map +1 -1
- package/dist/schema/view-builder.d.ts +28 -24
- package/dist/schema/view-builder.d.ts.map +1 -1
- package/dist/schema/view-builder.js +18 -14
- package/dist/schema/view-builder.js.map +1 -1
- package/dist/types/column.d.ts +6 -17
- package/dist/types/column.d.ts.map +1 -1
- package/dist/types/column.js +3 -19
- package/dist/types/column.js.map +1 -1
- package/dist/types/db-context-def.d.ts +7 -7
- package/dist/types/db-context-def.d.ts.map +1 -1
- package/dist/types/query-def.d.ts +1 -1
- package/dist/types/query-def.d.ts.map +1 -1
- package/dist/utils/result-parser.d.ts.map +1 -1
- package/dist/utils/result-parser.js +3 -7
- package/dist/utils/result-parser.js.map +1 -1
- package/package.json +3 -3
- package/src/db-context.ts +23 -20
- package/src/ddl/initialize.ts +4 -4
- package/src/ddl/relation-ddl.ts +1 -1
- package/src/ddl/table-ddl.ts +3 -3
- package/src/errors/db-transaction-error.ts +6 -4
- package/src/exec/executable.ts +5 -4
- package/src/exec/queryable.ts +31 -24
- package/src/expr/expr.ts +10 -4
- package/src/query-builder/base/expr-renderer-base.ts +2 -1
- package/src/query-builder/mssql/mssql-expr-renderer.ts +5 -5
- package/src/query-builder/mysql/mysql-expr-renderer.ts +2 -2
- package/src/query-builder/postgresql/postgresql-expr-renderer.ts +5 -5
- package/src/query-builder/postgresql/postgresql-query-builder.ts +4 -3
- package/src/schema/factory/column-builder.ts +3 -3
- package/src/schema/factory/relation-builder.ts +350 -346
- package/src/schema/table-builder.ts +209 -193
- package/src/schema/view-builder.ts +148 -143
- package/src/types/column.ts +7 -26
- package/src/types/db-context-def.ts +7 -7
- package/src/types/query-def.ts +1 -1
- package/src/utils/result-parser.ts +11 -19
|
@@ -1,346 +1,350 @@
|
|
|
1
|
-
import { type InferColumns } from "./column-builder";
|
|
2
|
-
import type { TableBuilder } from "../table-builder";
|
|
3
|
-
import type { ViewBuilder } from "../view-builder";
|
|
4
|
-
|
|
5
|
-
// ============================================
|
|
6
|
-
// ForeignKeyBuilder
|
|
7
|
-
// ============================================
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Foreign Key 관계 builder (N:1)
|
|
11
|
-
*
|
|
12
|
-
* 현재 Table에서 대상 Table로의 FK 관계를 정의
|
|
13
|
-
* DB에 실제 FK 제약조건을 생성
|
|
14
|
-
*
|
|
15
|
-
* description 설정은 factory 함수의 opts 파라미터로 전달한다.
|
|
16
|
-
* 메서드 체이닝(.description())은 TypeScript 순환 참조 시 TS7022를 유발하므로 제거됨.
|
|
17
|
-
*
|
|
18
|
-
* @template
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
* @param meta
|
|
31
|
-
* @param meta.columns - FK column 이름 배열
|
|
32
|
-
* @param meta.targetFn - 대상 Table factory
|
|
33
|
-
* @param meta.description - 관계 설명
|
|
34
|
-
*/
|
|
35
|
-
constructor(
|
|
36
|
-
readonly meta: {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* description, single
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* @template
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
* @param meta -
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* View
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
*
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
*/
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
opts?: { description?: string },
|
|
193
|
-
):
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
// ============================================
|
|
269
|
-
//
|
|
270
|
-
// ============================================
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
? InferColumns<TCols>
|
|
324
|
-
: InferColumns<TCols>[]
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
*
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
1
|
+
import { type InferColumns } from "./column-builder";
|
|
2
|
+
import type { TableBuilder } from "../table-builder";
|
|
3
|
+
import type { ViewBuilder } from "../view-builder";
|
|
4
|
+
|
|
5
|
+
// ============================================
|
|
6
|
+
// ForeignKeyBuilder
|
|
7
|
+
// ============================================
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Foreign Key 관계 builder (N:1)
|
|
11
|
+
*
|
|
12
|
+
* 현재 Table에서 대상 Table로의 FK 관계를 정의
|
|
13
|
+
* DB에 실제 FK 제약조건을 생성
|
|
14
|
+
*
|
|
15
|
+
* description 설정은 factory 함수의 opts 파라미터로 전달한다.
|
|
16
|
+
* 메서드 체이닝(.description())은 TypeScript 순환 참조 시 TS7022를 유발하므로 제거됨.
|
|
17
|
+
*
|
|
18
|
+
* @template TTargetFn - 대상 Table builder factory 타입 (무제약)
|
|
19
|
+
*
|
|
20
|
+
* 대상 타겟을 잡는 제네릭은 **무제약**(`extends () => TableBuilder<...>` 제약 없음)이다.
|
|
21
|
+
* 제약이 있으면 모델 const 형성 중 `() => typeof X` 타겟 화살표를 eager 평가하여
|
|
22
|
+
* TS6 에서 순환 const(TS7022/7024)를 유발하기 때문이다. 대상 해소는 `$inferSelect`
|
|
23
|
+
* 접근 시점에 lazy 하게(`ExtractRelationTarget`) 이루어진다.
|
|
24
|
+
*
|
|
25
|
+
* @see {@link ForeignKeyTargetBuilder} 역참조 builder
|
|
26
|
+
* @see {@link RelationKeyBuilder} DB FK 없는 관계
|
|
27
|
+
*/
|
|
28
|
+
export class ForeignKeyBuilder<TTargetFn> {
|
|
29
|
+
/**
|
|
30
|
+
* @param meta - FK 메타데이터
|
|
31
|
+
* @param meta.columns - FK column 이름 배열
|
|
32
|
+
* @param meta.targetFn - 대상 Table factory
|
|
33
|
+
* @param meta.description - 관계 설명
|
|
34
|
+
*/
|
|
35
|
+
constructor(
|
|
36
|
+
readonly meta: {
|
|
37
|
+
columns: string[];
|
|
38
|
+
targetFn: TTargetFn;
|
|
39
|
+
description?: string;
|
|
40
|
+
},
|
|
41
|
+
) {}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Foreign Key 역참조 builder (1:N)
|
|
46
|
+
*
|
|
47
|
+
* 다른 Table이 현재 Table을 참조하는 FK의 역참조를 정의
|
|
48
|
+
* include() 시 배열로 로드됨 (opts.single: true 시 단일 객체)
|
|
49
|
+
*
|
|
50
|
+
* description, single 설정은 factory 함수의 opts 파라미터로 전달한다.
|
|
51
|
+
* 메서드 체이닝(.description(), .single())은 TypeScript 순환 참조 시 TS7022를 유발하므로 제거됨.
|
|
52
|
+
*
|
|
53
|
+
* @template TTargetTableFn - 참조하는 Table builder factory 타입 (무제약)
|
|
54
|
+
* @template TIsSingle - 단일 객체 여부
|
|
55
|
+
*
|
|
56
|
+
* @see {@link ForeignKeyBuilder} FK builder
|
|
57
|
+
*/
|
|
58
|
+
export class ForeignKeyTargetBuilder<TTargetTableFn, TIsSingle> {
|
|
59
|
+
/**
|
|
60
|
+
* @param meta - FK 역참조 메타데이터
|
|
61
|
+
* @param meta.targetTableFn - 참조하는 Table factory
|
|
62
|
+
* @param meta.relationName - 참조하는 Table의 FK 관계 이름
|
|
63
|
+
* @param meta.description - 관계 설명
|
|
64
|
+
* @param meta.isSingle - 단일 객체 여부
|
|
65
|
+
*/
|
|
66
|
+
constructor(
|
|
67
|
+
readonly meta: {
|
|
68
|
+
targetTableFn: TTargetTableFn;
|
|
69
|
+
relationName: string;
|
|
70
|
+
description?: string;
|
|
71
|
+
isSingle?: TIsSingle;
|
|
72
|
+
},
|
|
73
|
+
) {}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ============================================
|
|
77
|
+
// RelationKeyBuilder (FK와 동일하지만 DB에 FK를 등록하지 않음)
|
|
78
|
+
// ============================================
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 논리적 관계 builder (N:1) - DB FK 미생성
|
|
82
|
+
*
|
|
83
|
+
* ForeignKeyBuilder와 동일하지만 DB에 FK 제약조건을 생성하지 않음
|
|
84
|
+
* View에서도 사용 가능
|
|
85
|
+
*
|
|
86
|
+
* description 설정은 factory 함수의 opts 파라미터로 전달한다.
|
|
87
|
+
*
|
|
88
|
+
* @template TTargetFn - 대상 Table/View builder factory 타입 (무제약)
|
|
89
|
+
*
|
|
90
|
+
* @see {@link ForeignKeyBuilder} DB FK 생성 버전
|
|
91
|
+
*/
|
|
92
|
+
export class RelationKeyBuilder<TTargetFn> {
|
|
93
|
+
/**
|
|
94
|
+
* @param meta - 관계 메타데이터
|
|
95
|
+
* @param meta.columns - 관계 column 이름 배열
|
|
96
|
+
* @param meta.targetFn - 대상 Table/View factory
|
|
97
|
+
* @param meta.description - 관계 설명
|
|
98
|
+
*/
|
|
99
|
+
constructor(
|
|
100
|
+
readonly meta: {
|
|
101
|
+
columns: string[];
|
|
102
|
+
targetFn: TTargetFn;
|
|
103
|
+
description?: string;
|
|
104
|
+
},
|
|
105
|
+
) {}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* 논리적 관계 역참조 builder (1:N) - DB FK 미생성
|
|
110
|
+
*
|
|
111
|
+
* ForeignKeyTargetBuilder와 동일하지만 DB에 FK 제약조건을 생성하지 않음
|
|
112
|
+
* View에서도 사용 가능
|
|
113
|
+
*
|
|
114
|
+
* description, single 설정은 factory 함수의 opts 파라미터로 전달한다.
|
|
115
|
+
*
|
|
116
|
+
* @template TTargetTableFn - 참조하는 Table/View builder factory 타입 (무제약)
|
|
117
|
+
* @template TIsSingle - 단일 객체 여부
|
|
118
|
+
*
|
|
119
|
+
* @see {@link ForeignKeyTargetBuilder} DB FK 생성 버전
|
|
120
|
+
*/
|
|
121
|
+
export class RelationKeyTargetBuilder<TTargetTableFn, TIsSingle> {
|
|
122
|
+
/**
|
|
123
|
+
* @param meta - 관계 역참조 메타데이터
|
|
124
|
+
* @param meta.targetTableFn - 참조하는 Table/View factory
|
|
125
|
+
* @param meta.relationName - 참조하는 Table/View의 관계 이름
|
|
126
|
+
* @param meta.description - 관계 설명
|
|
127
|
+
* @param meta.isSingle - 단일 객체 여부
|
|
128
|
+
*/
|
|
129
|
+
constructor(
|
|
130
|
+
readonly meta: {
|
|
131
|
+
targetTableFn: TTargetTableFn;
|
|
132
|
+
relationName: string;
|
|
133
|
+
description?: string;
|
|
134
|
+
isSingle?: TIsSingle;
|
|
135
|
+
},
|
|
136
|
+
) {}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ============================================
|
|
140
|
+
// 관계 factory
|
|
141
|
+
// ============================================
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* FK 관계 factory 타입 (table 전용)
|
|
145
|
+
*
|
|
146
|
+
* 컬럼 키 제약(`TColumnKey extends string`)은 self-contained 하므로 **유지**한다.
|
|
147
|
+
* 대상 타겟을 잡는 제네릭(`TTargetFn`/`TTargetTableFn`)은 **무제약**이다.
|
|
148
|
+
*
|
|
149
|
+
* @template TColumnKey - Column key 타입
|
|
150
|
+
*/
|
|
151
|
+
export type RelationFkFactory<TColumnKey extends string> = {
|
|
152
|
+
/** N:1 FK 관계 정의 (DB FK 생성) */
|
|
153
|
+
foreignKey<TTargetFn>(
|
|
154
|
+
columns: TColumnKey[],
|
|
155
|
+
targetFn: TTargetFn,
|
|
156
|
+
opts?: { description?: string },
|
|
157
|
+
): ForeignKeyBuilder<TTargetFn>;
|
|
158
|
+
/** 1:N FK 역참조 정의 (single: true → 단일 객체) */
|
|
159
|
+
foreignKeyTarget<TTargetTableFn>(
|
|
160
|
+
targetTableFn: TTargetTableFn,
|
|
161
|
+
relationName: string,
|
|
162
|
+
opts: { single: true; description?: string },
|
|
163
|
+
): ForeignKeyTargetBuilder<TTargetTableFn, true>;
|
|
164
|
+
foreignKeyTarget<TTargetTableFn>(
|
|
165
|
+
targetTableFn: TTargetTableFn,
|
|
166
|
+
relationName: string,
|
|
167
|
+
opts?: { single?: false; description?: string },
|
|
168
|
+
): ForeignKeyTargetBuilder<TTargetTableFn, false>;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* 논리적 관계 factory 타입 (table/View 공용)
|
|
173
|
+
*
|
|
174
|
+
* @template TColumnKey - Column key 타입
|
|
175
|
+
*/
|
|
176
|
+
export type RelationRkFactory<TColumnKey extends string> = {
|
|
177
|
+
/** N:1 논리적 관계 정의 (DB FK 미생성) */
|
|
178
|
+
relationKey<TTargetFn>(
|
|
179
|
+
columns: TColumnKey[],
|
|
180
|
+
targetFn: TTargetFn,
|
|
181
|
+
opts?: { description?: string },
|
|
182
|
+
): RelationKeyBuilder<TTargetFn>;
|
|
183
|
+
/** 1:N 논리적 역참조 정의 (single: true → 단일 객체) */
|
|
184
|
+
relationKeyTarget<TTargetTableFn>(
|
|
185
|
+
targetTableFn: TTargetTableFn,
|
|
186
|
+
relationName: string,
|
|
187
|
+
opts: { single: true; description?: string },
|
|
188
|
+
): RelationKeyTargetBuilder<TTargetTableFn, true>;
|
|
189
|
+
relationKeyTarget<TTargetTableFn>(
|
|
190
|
+
targetTableFn: TTargetTableFn,
|
|
191
|
+
relationName: string,
|
|
192
|
+
opts?: { single?: false; description?: string },
|
|
193
|
+
): RelationKeyTargetBuilder<TTargetTableFn, false>;
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Table용 관계 factory (FK + RelationKey 모두 사용 가능)
|
|
198
|
+
*/
|
|
199
|
+
export type TableRelationFactory<TColumnKey extends string> = RelationFkFactory<TColumnKey> &
|
|
200
|
+
RelationRkFactory<TColumnKey>;
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* View용 관계 factory (RelationKey만 사용 가능)
|
|
204
|
+
*/
|
|
205
|
+
export type ViewRelationFactory<TColumnKey extends string> = RelationRkFactory<TColumnKey>;
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* 관계 builder factory 생성
|
|
209
|
+
*
|
|
210
|
+
* `TableBuilder.relations(fn)` / `ViewBuilder.relations(fn)` 의 콜백 인자로 전달된다.
|
|
211
|
+
* Table은 FK + RelationKey 모두 사용 가능, View는 RelationKey만 사용 가능.
|
|
212
|
+
*
|
|
213
|
+
* @template TColumnKey - Column key 타입
|
|
214
|
+
* @returns 관계 builder factory
|
|
215
|
+
*/
|
|
216
|
+
export function createRelationFactory<TColumnKey extends string = string>(): TableRelationFactory<TColumnKey> {
|
|
217
|
+
return {
|
|
218
|
+
foreignKey(columns, targetFn, opts?) {
|
|
219
|
+
return new ForeignKeyBuilder({
|
|
220
|
+
columns,
|
|
221
|
+
targetFn,
|
|
222
|
+
description: opts?.description,
|
|
223
|
+
});
|
|
224
|
+
},
|
|
225
|
+
foreignKeyTarget(targetTableFn, relationName, opts?) {
|
|
226
|
+
return new ForeignKeyTargetBuilder({
|
|
227
|
+
targetTableFn,
|
|
228
|
+
relationName,
|
|
229
|
+
description: opts?.description,
|
|
230
|
+
isSingle: opts?.single,
|
|
231
|
+
});
|
|
232
|
+
},
|
|
233
|
+
relationKey(columns, targetFn, opts?) {
|
|
234
|
+
return new RelationKeyBuilder({
|
|
235
|
+
columns,
|
|
236
|
+
targetFn,
|
|
237
|
+
description: opts?.description,
|
|
238
|
+
});
|
|
239
|
+
},
|
|
240
|
+
relationKeyTarget(targetTableFn, relationName, opts?) {
|
|
241
|
+
return new RelationKeyTargetBuilder({
|
|
242
|
+
targetTableFn,
|
|
243
|
+
relationName,
|
|
244
|
+
description: opts?.description,
|
|
245
|
+
isSingle: opts?.single,
|
|
246
|
+
});
|
|
247
|
+
},
|
|
248
|
+
} as TableRelationFactory<TColumnKey>;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// ============================================
|
|
252
|
+
// builder 레코드
|
|
253
|
+
// ============================================
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* 관계 builder 레코드 타입
|
|
257
|
+
*
|
|
258
|
+
* `TableBuilder.relations(fn)` / `ViewBuilder.relations(fn)` 콜백의 반환 타입.
|
|
259
|
+
*/
|
|
260
|
+
export type RelationBuilderRecord = Record<
|
|
261
|
+
string,
|
|
262
|
+
| ForeignKeyBuilder<any>
|
|
263
|
+
| ForeignKeyTargetBuilder<any, any>
|
|
264
|
+
| RelationKeyBuilder<any>
|
|
265
|
+
| RelationKeyTargetBuilder<any, any>
|
|
266
|
+
>;
|
|
267
|
+
|
|
268
|
+
// ============================================
|
|
269
|
+
// Infer - 관계 타입 추론 (lazy 구조적 walk + 순환 방지 visited)
|
|
270
|
+
// ============================================
|
|
271
|
+
//
|
|
272
|
+
// 핵심: 관계 대상을 `ReturnType<TFn>` 으로 즉시 풀지 않고
|
|
273
|
+
// `TFn extends () => infer TTarget` 형태로 **lazy** 하게 푼다.
|
|
274
|
+
// 이로써 `$inferSelect` phantom 필드에 접근하기 전까지 `() => typeof X` 타겟이
|
|
275
|
+
// 평가되지 않아, 모델 const 형성 중 순환이 발생하지 않는다.
|
|
276
|
+
// 같은 테이블/뷰 이름 재방문(`TVisited`) 시 컬럼만 반환하여 무한 재귀를 끊는다.
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* FK/RelationKey에서 대상 타입 추출 (단일 객체, N:1)
|
|
280
|
+
*
|
|
281
|
+
* 대상이 Table이면 컬럼 + 심층 관계, View면 데이터 + 심층 관계를 반환한다.
|
|
282
|
+
*
|
|
283
|
+
* @template TRelation - FK 또는 RelationKey builder 타입
|
|
284
|
+
* @template TVisited - 순환 방지를 위한 방문 테이블/뷰명 집합
|
|
285
|
+
*/
|
|
286
|
+
export type ExtractRelationTarget<TRelation, TVisited extends string = never> = TRelation extends
|
|
287
|
+
| ForeignKeyBuilder<infer TTargetFn>
|
|
288
|
+
| RelationKeyBuilder<infer TTargetFn>
|
|
289
|
+
? TTargetFn extends () => infer TTarget
|
|
290
|
+
? TTarget extends TableBuilder<infer TName, infer TCols, infer TRels>
|
|
291
|
+
? TName extends TVisited
|
|
292
|
+
? InferColumns<TCols>
|
|
293
|
+
: InferColumns<TCols> & InferDeepRelations<TRels, TVisited | TName>
|
|
294
|
+
: TTarget extends ViewBuilder<any, infer TVName, infer TData, infer TVRels>
|
|
295
|
+
? TVName extends TVisited
|
|
296
|
+
? TData
|
|
297
|
+
: TData & InferDeepRelations<TVRels, TVisited | TVName>
|
|
298
|
+
: never
|
|
299
|
+
: never
|
|
300
|
+
: never;
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* FKTarget/RelationKeyTarget에서 대상 타입 추출 (배열 또는 단일 객체, 1:N)
|
|
304
|
+
*
|
|
305
|
+
* opts.single: true 시 단일 객체, 아니면 배열.
|
|
306
|
+
*
|
|
307
|
+
* @template TRelation - FKTarget 또는 RelationKeyTarget builder 타입
|
|
308
|
+
* @template TVisited - 순환 방지를 위한 방문 테이블/뷰명 집합
|
|
309
|
+
*/
|
|
310
|
+
export type ExtractRelationTargetResult<
|
|
311
|
+
TRelation,
|
|
312
|
+
TVisited extends string = never,
|
|
313
|
+
> = TRelation extends
|
|
314
|
+
| ForeignKeyTargetBuilder<infer TTargetTableFn, infer TIsSingle>
|
|
315
|
+
| RelationKeyTargetBuilder<infer TTargetTableFn, infer TIsSingle>
|
|
316
|
+
? TTargetTableFn extends () => infer TTarget
|
|
317
|
+
? TTarget extends TableBuilder<infer TName, infer TCols, infer TRels>
|
|
318
|
+
? TName extends TVisited
|
|
319
|
+
? TIsSingle extends true
|
|
320
|
+
? InferColumns<TCols>
|
|
321
|
+
: InferColumns<TCols>[]
|
|
322
|
+
: TIsSingle extends true
|
|
323
|
+
? InferColumns<TCols> & InferDeepRelations<TRels, TVisited | TName>
|
|
324
|
+
: (InferColumns<TCols> & InferDeepRelations<TRels, TVisited | TName>)[]
|
|
325
|
+
: TTarget extends ViewBuilder<any, infer TVName, infer TData, infer TVRels>
|
|
326
|
+
? TVName extends TVisited
|
|
327
|
+
? TIsSingle extends true
|
|
328
|
+
? TData
|
|
329
|
+
: TData[]
|
|
330
|
+
: TIsSingle extends true
|
|
331
|
+
? TData & InferDeepRelations<TVRels, TVisited | TVName>
|
|
332
|
+
: (TData & InferDeepRelations<TVRels, TVisited | TVName>)[]
|
|
333
|
+
: never
|
|
334
|
+
: never
|
|
335
|
+
: never;
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* 관계 레코드에서 심층 관계 타입 추론
|
|
339
|
+
*
|
|
340
|
+
* include() 없이 접근 시 undefined가 되도록 모든 관계를 optional로 설정.
|
|
341
|
+
* 입력 제약 없음(무제약) — 관계가 없는(`{}`) 테이블도 안전하게 빈 객체로 해소된다.
|
|
342
|
+
*
|
|
343
|
+
* @template TRelations - 관계 builder 레코드 타입 (무제약)
|
|
344
|
+
* @template TVisited - 순환 방지를 위한 방문 테이블/뷰명 집합
|
|
345
|
+
*/
|
|
346
|
+
export type InferDeepRelations<TRelations, TVisited extends string = never> = {
|
|
347
|
+
[K in keyof TRelations]?:
|
|
348
|
+
| ExtractRelationTarget<TRelations[K], TVisited>
|
|
349
|
+
| ExtractRelationTargetResult<TRelations[K], TVisited>;
|
|
350
|
+
};
|