@simplysm/orm-common 14.0.51 → 14.0.53

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.
@@ -1,54 +0,0 @@
1
- # Executable
2
-
3
- Stored Procedure 실행 래퍼 클래스. `DbContext.executable()`로 등록된 프로퍼티를 호출하면 반환된다.
4
-
5
- ```typescript
6
- export class Executable<TParams extends ColumnBuilderRecord, TReturns extends ColumnBuilderRecord> {
7
- constructor(
8
- db: DbContextBase,
9
- builder: ProcedureBuilder<TParams, TReturns>,
10
- );
11
- }
12
- ```
13
-
14
- ## Members
15
-
16
- | Member | Kind | Type | Description |
17
- |--------|------|------|-------------|
18
- | `execute(params)` | method | `Promise<InferColumnExprs<TReturns>[][]>` | 프로시저 실행. 결과는 결과 셋 배열의 배열 |
19
- | `getExecProcQueryDef(params?)` | method | `ExecProcQueryDef` | 실행 없이 QueryDef만 반환 |
20
-
21
- ## Related Types
22
-
23
- ### `executable` (팩토리 함수)
24
-
25
- `DbContext.executable()`이 내부적으로 사용하는 팩토리 함수.
26
-
27
- ```typescript
28
- export function executable<
29
- TParams extends ColumnBuilderRecord,
30
- TReturns extends ColumnBuilderRecord,
31
- >(
32
- db: DbContextBase,
33
- builder: ProcedureBuilder<TParams, TReturns>,
34
- ): () => Executable<TParams, TReturns>;
35
- ```
36
-
37
- ## Usage
38
-
39
- ```typescript
40
- // 프로시저 정의
41
- const GetUserById = Procedure("GetUserById")
42
- .database("mydb")
43
- .params((c) => ({ userId: c.bigint() }))
44
- .returns((c) => ({ id: c.bigint(), name: c.varchar(100) }))
45
- .body("SELECT id, name FROM User WHERE id = userId");
46
-
47
- // DbContext에 등록
48
- class MyDb extends DbContext {
49
- getUserById = this.executable(GetUserById);
50
- }
51
-
52
- // 실행
53
- const [[user]] = await db.getUserById().execute({ userId: 1n });
54
- ```
@@ -1,75 +0,0 @@
1
- # parseSearchQuery
2
-
3
- 사용자 입력 검색 텍스트를 파싱하여 SQL LIKE 패턴으로 변환한다. `Queryable.search()`가 내부적으로 사용한다.
4
-
5
- ```typescript
6
- export function parseSearchQuery(searchText: string): ParsedSearchQuery;
7
- ```
8
-
9
- ## Parameters
10
-
11
- | Param | Type | Description |
12
- |-------|------|-------------|
13
- | `searchText` | `string` | 검색 쿼리 문자열 |
14
-
15
- ## Returns
16
-
17
- `ParsedSearchQuery` — 파싱된 검색 쿼리 객체
18
-
19
- ## Related Types
20
-
21
- ### `ParsedSearchQuery`
22
-
23
- ```typescript
24
- export interface ParsedSearchQuery {
25
- /** 일반 검색어 (OR 조건) - LIKE 패턴 */
26
- or: string[];
27
- /** 필수 검색어 (AND 조건, + 접두사 또는 따옴표) - LIKE 패턴 */
28
- must: string[];
29
- /** 제외 검색어 (NOT 조건, - 접두사) - LIKE 패턴 */
30
- not: string[];
31
- }
32
- ```
33
-
34
- ## 검색 구문
35
-
36
- | 구문 | 의미 | 예시 |
37
- |------|------|------|
38
- | `term1 term2` | OR (하나 이상 일치) | `apple banana` |
39
- | `+term` | 필수 포함 (AND) | `+apple +banana` |
40
- | `-term` | 제외 (NOT) | `apple -banana` |
41
- | `"exact phrase"` | 정확한 구문 일치 (필수) | `"맛있는 과일"` |
42
- | `*` | 와일드카드 | `app*` → `app%` |
43
-
44
- ## 이스케이프 시퀀스
45
-
46
- | 입력 | 의미 |
47
- |------|------|
48
- | `\\` | 리터럴 `\` |
49
- | `\*` | 리터럴 `*` |
50
- | `\%` | 리터럴 `%` |
51
- | `\"` | 리터럴 `"` |
52
- | `\+` | 리터럴 `+` |
53
- | `\-` | 리터럴 `-` |
54
-
55
- ## Usage
56
-
57
- ```typescript
58
- parseSearchQuery('apple "delicious fruit" -banana +strawberry')
59
- // {
60
- // or: ["%apple%"],
61
- // must: ["%delicious fruit%", "%strawberry%"],
62
- // not: ["%banana%"]
63
- // }
64
-
65
- parseSearchQuery('app* test')
66
- // {
67
- // or: ["app%", "%test%"],
68
- // must: [],
69
- // not: []
70
- // }
71
-
72
- // Queryable.search()와 함께 사용
73
- db.user()
74
- .search((u) => [u.name, u.email], "John +admin -deleted")
75
- ```
@@ -1,238 +0,0 @@
1
- # Queryable
2
-
3
- SELECT/INSERT/UPDATE/DELETE/UPSERT 체인 빌더. 메서드 체이닝으로 쿼리를 구성하고 `execute()` 계열 메서드로 실행한다. `DbContext.queryable()`로 등록된 프로퍼티를 호출하면 반환된다.
4
-
5
- ```typescript
6
- export class Queryable<
7
- TData extends DataRecord,
8
- TFrom extends TableBuilder<any, any> | never,
9
- > {
10
- constructor(readonly meta: QueryableMeta<TData>);
11
- }
12
- ```
13
-
14
- `TFrom`은 CUD(INSERT/UPDATE/DELETE) 연산에 필요한 TableBuilder 타입이다. VIEW 기반이거나 `select()`로 변환된 경우 `never`가 되어 CUD 메서드를 사용할 수 없다.
15
-
16
- ## Members
17
-
18
- ### SELECT 옵션
19
-
20
- | Member | Kind | Type | Description |
21
- |--------|------|------|-------------|
22
- | `select(fn)` | method | `Queryable<R, never>` | SELECT할 column 지정. fn이 반환한 구조로 결과 타입 변환 |
23
- | `distinct()` | method | `Queryable<TData, never>` | DISTINCT 중복 제거 |
24
- | `lock()` | method | `Queryable<TData, TFrom>` | FOR UPDATE 행 잠금 |
25
-
26
- ### 범위 제한
27
-
28
- | Member | Kind | Type | Description |
29
- |--------|------|------|-------------|
30
- | `top(count)` | method | `Queryable<TData, TFrom>` | 상위 N개 행만 선택 |
31
- | `limit(skip, take)` | method | `Queryable<TData, TFrom>` | LIMIT/OFFSET 페이지네이션. `orderBy()` 후에만 사용 가능 |
32
-
33
- ### 정렬
34
-
35
- | Member | Kind | Type | Description |
36
- |--------|------|------|-------------|
37
- | `orderBy(fn, direction?)` | method | `Queryable<TData, TFrom>` | 정렬 조건 추가. 여러 번 호출 시 순서대로 적용. 함수 또는 chain path 문자열 |
38
-
39
- ### WHERE 조건
40
-
41
- | Member | Kind | Type | Description |
42
- |--------|------|------|-------------|
43
- | `where(predicate)` | method | `Queryable<TData, TFrom>` | WHERE 조건 추가. 여러 번 호출 시 AND로 결합 |
44
- | `search(fn, searchText)` | method | `Queryable<TData, TFrom>` | 텍스트 검색. `parseSearchQuery` 구문 지원 |
45
-
46
- ### GROUP BY / HAVING
47
-
48
- | Member | Kind | Type | Description |
49
- |--------|------|------|-------------|
50
- | `groupBy(fn)` | method | `Queryable<TData, never>` | GROUP BY 절 추가 |
51
- | `having(predicate)` | method | `Queryable<TData, never>` | HAVING 조건 추가 |
52
-
53
- ### JOIN
54
-
55
- | Member | Kind | Type | Description |
56
- |--------|------|------|-------------|
57
- | `join(as, fn)` | method | `Queryable<TData & { [as]?: R[] }, TFrom>` | 1:N LEFT OUTER JOIN. 결과에 배열로 추가 |
58
- | `joinSingle(as, fn)` | method | `Queryable<...>` | N:1 또는 1:1 LEFT OUTER JOIN. 결과에 단일 객체로 추가 |
59
- | `include(fn)` | method | `Queryable<TData, TFrom>` | 테이블 관계 정의 기반 자동 JOIN. 중첩 경로 지원 (`p.user.company`) |
60
-
61
- ### 서브쿼리 / UNION
62
-
63
- | Member | Kind | Type | Description |
64
- |--------|------|------|-------------|
65
- | `wrap()` | method | `Queryable<TData, never>` | 현재 쿼리를 서브쿼리로 래핑. `distinct()`/`groupBy()` 후 `count()` 사용 시 필요 |
66
- | `static union(...queries)` | static | `Queryable<TData, never>` | 여러 Queryable을 UNION으로 결합 (중복 제거). 최소 2개 필요 |
67
-
68
- ### 재귀 CTE
69
-
70
- | Member | Kind | Type | Description |
71
- |--------|------|------|-------------|
72
- | `recursive(fn)` | method | `Queryable<TData, never>` | WITH RECURSIVE CTE 생성. 계층 구조 쿼리에 사용 |
73
-
74
- ### SELECT 실행
75
-
76
- | Member | Kind | Type | Description |
77
- |--------|------|------|-------------|
78
- | `execute()` | method | `Promise<TData[]>` | SELECT 실행, 결과 배열 반환 |
79
- | `single()` | method | `Promise<TData \| undefined>` | 단일 결과 반환. 2개 이상이면 에러 |
80
- | `first()` | method | `Promise<TData \| undefined>` | 첫 번째 결과만 반환 |
81
- | `count(fn?)` | method | `Promise<number>` | 행 수 반환. `distinct()`/`groupBy()` 후에는 `wrap()` 필요 |
82
- | `exists()` | method | `Promise<boolean>` | 조건에 일치하는 데이터 존재 여부 |
83
-
84
- ### INSERT
85
-
86
- | Member | Kind | Type | Description |
87
- |--------|------|------|-------------|
88
- | `insert(records)` | method | `Promise<void>` | INSERT 실행. MSSQL 1000행 제한으로 자동 청크 분할 |
89
- | `insert(records, outputColumns)` | method | `Promise<Pick<...>[]>` | INSERT 후 지정한 column 값 반환 |
90
- | `insertIfNotExists(record)` | method | `Promise<void>` | WHERE 조건에 일치하는 데이터가 없을 때만 INSERT |
91
- | `insertInto(targetTable)` | method | `Promise<void>` | INSERT INTO ... SELECT |
92
-
93
- ### UPDATE
94
-
95
- | Member | Kind | Type | Description |
96
- |--------|------|------|-------------|
97
- | `update(recordFn)` | method | `Promise<void>` | UPDATE 실행 |
98
- | `update(recordFn, outputColumns)` | method | `Promise<Pick<...>[]>` | UPDATE 후 지정한 column 값 반환 |
99
-
100
- ### DELETE
101
-
102
- | Member | Kind | Type | Description |
103
- |--------|------|------|-------------|
104
- | `delete()` | method | `Promise<void>` | DELETE 실행 |
105
- | `delete(outputColumns)` | method | `Promise<Pick<...>[]>` | DELETE 후 지정한 column 값 반환 |
106
-
107
- ### UPSERT
108
-
109
- | Member | Kind | Type | Description |
110
- |--------|------|------|-------------|
111
- | `upsert(updateFn)` | method | `Promise<void>` | WHERE 일치 시 UPDATE, 없으면 INSERT (updateFn이 두 작업에 동일 적용) |
112
- | `upsert(updateFn, insertFn)` | method | `Promise<void>` | UPDATE/INSERT 각각 다른 데이터로 UPSERT |
113
- | `upsert(updateFn, outputColumns)` | method | `Promise<Pick<...>[]>` | UPSERT 후 지정한 column 값 반환 |
114
-
115
- ### QueryDef 생성기
116
-
117
- 실행 없이 `QueryDef`만 반환. 테스트나 수동 실행에 사용.
118
-
119
- | Member | Kind | Type | Description |
120
- |--------|------|------|-------------|
121
- | `getSelectQueryDef()` | method | `SelectQueryDef` | SELECT QueryDef 생성 |
122
- | `getResultMeta(outputColumns?)` | method | `ResultMeta` | SELECT 결과 변환용 메타데이터 생성 |
123
- | `getInsertQueryDef(records, outputColumns?)` | method | `InsertQueryDef` | INSERT QueryDef 생성 |
124
- | `getInsertIfNotExistsQueryDef(record)` | method | `InsertIfNotExistsQueryDef` | INSERT IF NOT EXISTS QueryDef |
125
- | `getInsertIntoQueryDef(targetTable)` | method | `InsertIntoQueryDef` | INSERT INTO QueryDef |
126
- | `getUpdateQueryDef(recordFn, outputColumns?)` | method | `UpdateQueryDef` | UPDATE QueryDef |
127
- | `getDeleteQueryDef(outputColumns?)` | method | `DeleteQueryDef` | DELETE QueryDef |
128
- | `getUpsertQueryDef(updateFn, insertFn, outputColumns?)` | method | `UpsertQueryDef` | UPSERT QueryDef |
129
- | `switchFk(enabled)` | method | `Promise<void>` | FK 제약조건 활성화/비활성화 |
130
-
131
- ## Related Types
132
-
133
- ### `queryable` (팩토리 함수)
134
-
135
- `DbContext.queryable()`이 내부적으로 사용하는 팩토리 함수. 직접 호출할 일은 드물다.
136
-
137
- ```typescript
138
- export function queryable<TBuilder extends TableBuilder<any, any> | ViewBuilder<any, any, any>>(
139
- db: DbContextBase,
140
- tableOrView: TBuilder,
141
- as?: string,
142
- ): () => Queryable<TBuilder["$inferSelect"], ...>;
143
- ```
144
-
145
- ### `getMatchedPrimaryKeys`
146
-
147
- FK column 배열과 대상 테이블의 PK를 매칭하여 PK column 이름 배열을 반환한다.
148
-
149
- ```typescript
150
- export function getMatchedPrimaryKeys(
151
- fkCols: string[],
152
- targetTable: TableBuilder<any, any>,
153
- ): string[];
154
- ```
155
-
156
- ### `QueryableRecord<TData>`
157
-
158
- Queryable 콜백 내부에서 column을 참조할 때 사용하는 프록시 레코드 타입. 각 필드가 `ExprUnit`으로 래핑된다.
159
-
160
- ```typescript
161
- export type QueryableRecord<TData extends DataRecord> = {
162
- [K in keyof TData]: TData[K] extends ColumnPrimitive
163
- ? ExprUnit<TData[K]>
164
- : ...;
165
- };
166
- ```
167
-
168
- ### `QueryableWriteRecord<TData>`
169
-
170
- UPDATE/UPSERT에서 레코드를 작성할 때 사용하는 타입. 각 필드가 `ExprInput<T>`(ExprUnit 또는 리터럴 값)로 받는다.
171
-
172
- ```typescript
173
- export type QueryableWriteRecord<TData> = {
174
- [K in keyof TData]: TData[K] extends ColumnPrimitive ? ExprInput<TData[K]> : never;
175
- };
176
- ```
177
-
178
- ### `UnwrapQueryableRecord<R>`
179
-
180
- `select(fn)` 반환 타입에서 `ExprUnit<T>`를 `T`로 언래핑하여 실제 데이터 타입을 추론한다.
181
-
182
- ### `PathProxy<TObject>`
183
-
184
- `include(fn)` 에서 관계 경로를 타입 안전하게 지정하기 위한 프록시 타입. `ColumnPrimitive` 필드는 접근 불가.
185
-
186
- ```typescript
187
- export type PathProxy<TObject> = {
188
- [K in keyof TObject as TObject[K] extends ColumnPrimitive ? never : K]-?: PathProxy<...>;
189
- };
190
- ```
191
-
192
- ## Usage
193
-
194
- ```typescript
195
- // SELECT
196
- const users = await db.user()
197
- .where((u) => [expr.eq(u.isActive, true), expr.gt(u.age, 18)])
198
- .select((u) => ({ id: u.id, fullName: expr.concat(u.name, " (", u.email, ")") }))
199
- .include((i) => i.company)
200
- .orderBy((u) => u.name)
201
- .limit(0, 20)
202
- .execute();
203
-
204
- // INSERT
205
- await db.user().insert([{ name: "Alice", createdAt: DateTime.now() }]);
206
-
207
- // INSERT with output
208
- const [inserted] = await db.user().insert([{ name: "Bob" }], ["id"]);
209
-
210
- // UPDATE (column 참조)
211
- await db.product()
212
- .update((p) => ({
213
- price: expr.mul(p.price, expr.val("number", 1.1)),
214
- }));
215
-
216
- // UPSERT
217
- await db.user()
218
- .where((u) => [expr.eq(u.email, "test@test.com")])
219
- .upsert(
220
- () => ({ loginCount: expr.val("number", 1) }),
221
- (update) => ({ ...update, email: expr.val("string", "test@test.com") }),
222
- );
223
-
224
- // UNION
225
- const combined = Queryable.union(
226
- db.user().where((u) => [expr.eq(u.type, "admin")]),
227
- db.user().where((u) => [expr.eq(u.type, "manager")]),
228
- );
229
-
230
- // 재귀 CTE (계층 구조)
231
- const tree = await db.employee()
232
- .where((e) => [expr.null(e.managerId)])
233
- .recursive((cte) =>
234
- cte.from(Employee)
235
- .where((e) => [expr.eq(e.managerId, e.self[0].id)])
236
- )
237
- .execute();
238
- ```
@@ -1,63 +0,0 @@
1
- # ColumnBuilder
2
-
3
- Column 타입, nullable, autoIncrement, default, description을 정의하는 빌더. `TableBuilder.columns()` 및 `ProcedureBuilder.params()`/`returns()` 콜백에서 `createColumnFactory()`가 반환하는 팩토리 객체를 통해 생성된다.
4
-
5
- ```typescript
6
- export class ColumnBuilder<TValue extends ColumnPrimitive, TMeta extends ColumnMeta> {
7
- constructor(readonly meta: TMeta);
8
- }
9
- ```
10
-
11
- ## Members
12
-
13
- | Member | Kind | Type | Description |
14
- |--------|------|------|-------------|
15
- | `meta` | property | `TMeta` | Column 메타데이터 |
16
- | `autoIncrement()` | method | `ColumnBuilder<TValue, ...>` | AUTO_INCREMENT 설정. INSERT 타입에서 optional |
17
- | `nullable()` | method | `ColumnBuilder<TValue \| undefined, ...>` | NULL 허용. 값 타입에 `undefined` 추가 |
18
- | `default(value)` | method | `ColumnBuilder<TValue, ...>` | 기본값 설정. INSERT 타입에서 optional |
19
- | `description(desc)` | method | `ColumnBuilder<TValue, ...>` | Column 설명 (DDL Comment) |
20
-
21
- ## Related Types
22
-
23
- ### `createColumnFactory`
24
-
25
- `TableBuilder.columns()`, `ProcedureBuilder.params()`/`returns()` 콜백에서 자동으로 제공되는 팩토리.
26
-
27
- ```typescript
28
- export function createColumnFactory(): { ... };
29
- ```
30
-
31
- #### 지원 Column 타입
32
-
33
- | 메서드 | SQL 타입 | TypeScript 타입 | 비고 |
34
- |--------|----------|-----------------|------|
35
- | `int()` | INT | `number` | 4바이트 |
36
- | `bigint()` | BIGINT | `number` | 8바이트 |
37
- | `float()` | FLOAT | `number` | 4바이트 단정밀도 |
38
- | `double()` | DOUBLE | `number` | 8바이트 배정밀도 |
39
- | `decimal(precision, scale?)` | DECIMAL(p,s) | `number` | 고정 소수점 |
40
- | `varchar(length)` | VARCHAR(n) | `string` | 가변 길이 |
41
- | `char(length)` | CHAR(n) | `string` | 고정 길이 |
42
- | `text()` | TEXT/LONGTEXT | `string` | 대용량 |
43
- | `binary()` | LONGBLOB/VARBINARY(MAX)/BYTEA | `Bytes` | 바이너리 |
44
- | `boolean()` | TINYINT(1)/BIT/BOOLEAN | `boolean` | DBMS별 다름 |
45
- | `datetime()` | DATETIME | `DateTime` | |
46
- | `date()` | DATE | `DateOnly` | |
47
- | `time()` | TIME | `Time` | |
48
- | `uuid()` | BINARY(16)/UNIQUEIDENTIFIER/UUID | `Uuid` | |
49
-
50
- ## Usage
51
-
52
- ```typescript
53
- Table("User")
54
- .columns((c) => ({
55
- id: c.bigint().autoIncrement(), // bigint, AUTO_INCREMENT, INSERT optional
56
- name: c.varchar(100), // varchar(100), 필수
57
- email: c.varchar(200).nullable(), // varchar(200), NULL 허용
58
- status: c.varchar(20).default("active"), // varchar(20), 기본값 "active", INSERT optional
59
- createdAt: c.datetime().description("생성일시"),
60
- price: c.decimal(10, 2),
61
- data: c.binary(),
62
- }));
63
- ```
@@ -1,137 +0,0 @@
1
- # ForeignKeyBuilder
2
-
3
- FK/역참조/논리적 관계 빌더들. `TableBuilder.relations()` 및 `ViewBuilder.relations()` 콜백에서 `createRelationFactory()`가 반환하는 팩토리 객체를 통해 생성된다.
4
-
5
- **주의**: description/single 설정은 반드시 팩토리 함수의 `opts` 파라미터로 전달해야 한다. 메서드 체이닝(`.description()`, `.single()`)은 TypeScript 순환 참조(TS7022)를 유발하므로 제거되었다.
6
-
7
- ## 빌더 종류
8
-
9
- | 클래스 | 관계 방향 | DB FK 생성 | 사용 가능 위치 |
10
- |--------|-----------|------------|----------------|
11
- | `ForeignKeyBuilder` | N:1 | O | Table |
12
- | `ForeignKeyTargetBuilder` | 1:N 또는 1:1 | O (역참조) | Table |
13
- | `RelationKeyBuilder` | N:1 | X | Table, View |
14
- | `RelationKeyTargetBuilder` | 1:N 또는 1:1 | X (역참조) | Table, View |
15
-
16
- ## ForeignKeyBuilder
17
-
18
- ```typescript
19
- export class ForeignKeyBuilder<
20
- TOwner extends TableBuilder<any, any>,
21
- TTargetFn extends () => TableBuilder<any, any>,
22
- > {
23
- constructor(
24
- readonly meta: {
25
- ownerFn: () => TOwner;
26
- columns: string[];
27
- targetFn: TTargetFn;
28
- description?: string;
29
- },
30
- );
31
- }
32
- ```
33
-
34
- 팩토리 시그니처:
35
- ```typescript
36
- r.foreignKey(columns, targetFn, opts?: { description?: string }): ForeignKeyBuilder<...>
37
- ```
38
-
39
- ## ForeignKeyTargetBuilder
40
-
41
- ```typescript
42
- export class ForeignKeyTargetBuilder<
43
- TTargetTableFn extends () => TableBuilder<any, any>,
44
- TIsSingle extends boolean,
45
- > {
46
- constructor(
47
- readonly meta: {
48
- targetTableFn: TTargetTableFn;
49
- relationName: string;
50
- description?: string;
51
- isSingle?: TIsSingle;
52
- },
53
- );
54
- }
55
- ```
56
-
57
- 팩토리 시그니처 (오버로드):
58
- ```typescript
59
- // 배열 관계 (1:N)
60
- r.foreignKeyTarget(targetTableFn, relationName, opts?: { single?: false, description?: string }):
61
- ForeignKeyTargetBuilder<..., false>
62
-
63
- // 단일 관계 (1:1)
64
- r.foreignKeyTarget(targetTableFn, relationName, opts: { single: true, description?: string }):
65
- ForeignKeyTargetBuilder<..., true>
66
- ```
67
-
68
- ## RelationKeyBuilder
69
-
70
- `ForeignKeyBuilder`와 동일하지만 DB에 FK 제약조건을 생성하지 않는다. View에서도 사용 가능하다.
71
-
72
- 팩토리 시그니처:
73
- ```typescript
74
- r.relationKey(columns, targetFn, opts?: { description?: string }): RelationKeyBuilder<...>
75
- ```
76
-
77
- ## RelationKeyTargetBuilder
78
-
79
- `ForeignKeyTargetBuilder`와 동일하지만 DB에 FK를 생성하지 않는다.
80
-
81
- 팩토리 시그니처 (오버로드):
82
- ```typescript
83
- r.relationKeyTarget(targetTableFn, relationName, opts?: { single?: false, description?: string })
84
- r.relationKeyTarget(targetTableFn, relationName, opts: { single: true, description?: string })
85
- ```
86
-
87
- ## Related Types
88
-
89
- ### `createRelationFactory`
90
-
91
- ```typescript
92
- export function createRelationFactory<
93
- TOwner extends TableBuilder<any, any> | ViewBuilder<any, any, any>,
94
- TColumnKey extends string,
95
- >(ownerFn: () => TOwner): RelationFactory;
96
- ```
97
-
98
- TableBuilder → FK + RelationKey 모두 사용 가능.
99
- ViewBuilder → RelationKey만 사용 가능 (`foreignKey`/`foreignKeyTarget` 없음).
100
-
101
- ## Usage
102
-
103
- ```typescript
104
- const Post = Table("Post")
105
- .columns((c) => ({
106
- id: c.bigint().autoIncrement(),
107
- authorId: c.bigint(),
108
- title: c.varchar(200),
109
- }))
110
- .primaryKey("id")
111
- .relations((r) => ({
112
- // N:1: Post → User (DB FK 생성)
113
- author: r.foreignKey(["authorId"], () => User, { description: "작성자" }),
114
- }));
115
-
116
- const User = Table("User")
117
- .columns((c) => ({
118
- id: c.bigint().autoIncrement(),
119
- name: c.varchar(100),
120
- }))
121
- .primaryKey("id")
122
- .relations((r) => ({
123
- // 1:N 역참조 (배열)
124
- posts: r.foreignKeyTarget(() => Post, "author"),
125
- // 1:1 역참조 (단일 객체)
126
- profile: r.foreignKeyTarget(() => Profile, "user", { single: true }),
127
- // 설명 포함
128
- comments: r.foreignKeyTarget(() => Comment, "user", { description: "댓글목록" }),
129
- }));
130
-
131
- // View에서는 relationKey만 사용
132
- const UserSummary = View("UserSummary")
133
- .query((db: MyDb) => db.user().select(...))
134
- .relations((r) => ({
135
- company: r.relationKey(["companyId"], () => Company, { description: "소속회사" }),
136
- }));
137
- ```
@@ -1,54 +0,0 @@
1
- # IndexBuilder
2
-
3
- Index 정의 빌더. `TableBuilder.indexes()` 콜백에서 `createIndexFactory()`가 반환하는 팩토리 객체를 통해 생성된다.
4
-
5
- ```typescript
6
- export class IndexBuilder<TKeys extends string[]> {
7
- constructor(
8
- readonly meta: {
9
- columns: TKeys;
10
- name?: string;
11
- unique?: boolean;
12
- orderBy?: { [K in keyof TKeys]: "ASC" | "DESC" };
13
- description?: string;
14
- },
15
- );
16
- }
17
- ```
18
-
19
- ## Members
20
-
21
- | Member | Kind | Type | Description |
22
- |--------|------|------|-------------|
23
- | `meta` | property | `{ columns, name?, unique?, orderBy?, description? }` | Index 메타데이터 |
24
- | `name(name)` | method | `IndexBuilder<TKeys>` | Index 이름 설정 |
25
- | `unique()` | method | `IndexBuilder<TKeys>` | UNIQUE 인덱스 설정 |
26
- | `orderBy(...orderBy)` | method | `IndexBuilder<TKeys>` | 각 컬럼별 정렬 순서 설정 |
27
- | `description(desc)` | method | `IndexBuilder<TKeys>` | Index 설명 (DDL Comment) |
28
-
29
- ## Related Types
30
-
31
- ### `createIndexFactory`
32
-
33
- ```typescript
34
- export function createIndexFactory<TColumnKey extends string>(): {
35
- index<TKeys extends TColumnKey[]>(...columns: [...TKeys]): IndexBuilder<TKeys>;
36
- };
37
- ```
38
-
39
- ## Usage
40
-
41
- ```typescript
42
- Table("User")
43
- .columns((c) => ({
44
- id: c.bigint(),
45
- email: c.varchar(200),
46
- name: c.varchar(100),
47
- createdAt: c.datetime(),
48
- }))
49
- .indexes((i) => [
50
- i.index("email").unique(),
51
- i.index("name", "createdAt").orderBy("ASC", "DESC"),
52
- i.index("createdAt").name("IX_User_CreatedAt").orderBy("DESC"),
53
- ]);
54
- ```
@@ -1,67 +0,0 @@
1
- # Procedure
2
-
3
- Fluent API로 Stored Procedure 스키마를 정의하는 빌더 팩토리 함수.
4
-
5
- ```typescript
6
- export function Procedure(name: string): ProcedureBuilder<never, never>;
7
- ```
8
-
9
- ## Parameters
10
-
11
- | Param | Type | Description |
12
- |-------|------|-------------|
13
- | `name` | `string` | Procedure 이름 |
14
-
15
- ## Returns
16
-
17
- `ProcedureBuilder<never, never>` — 빈 ProcedureBuilder 인스턴스
18
-
19
- ## Related Types
20
-
21
- ### `ProcedureBuilder<TParams, TReturns>`
22
-
23
- ```typescript
24
- export class ProcedureBuilder<
25
- TParams extends ColumnBuilderRecord,
26
- TReturns extends ColumnBuilderRecord,
27
- > {
28
- readonly $params!: TParams;
29
- readonly $returns!: TReturns;
30
- }
31
- ```
32
-
33
- #### 빌더 메서드
34
-
35
- | 메서드 | 설명 |
36
- |--------|------|
37
- | `description(desc)` | Procedure 설명 설정 (DDL Comment) |
38
- | `database(db)` | Database 이름 설정 |
39
- | `schema(schema)` | Schema 이름 설정 |
40
- | `params(fn)` | 입력 파라미터 정의. `fn(c) => ({ userId: c.bigint(), ... })` |
41
- | `returns(fn)` | 반환 컬럼 정의. `fn(c) => ({ id: c.bigint(), ... })` |
42
- | `body(sql)` | Procedure 본문 SQL 설정 |
43
-
44
- ## Usage
45
-
46
- ```typescript
47
- const GetUserById = Procedure("GetUserById")
48
- .database("mydb")
49
- .params((c) => ({
50
- userId: c.bigint(),
51
- }))
52
- .returns((c) => ({
53
- id: c.bigint(),
54
- name: c.varchar(100),
55
- email: c.varchar(200).nullable(),
56
- }))
57
- .body("SELECT id, name, email FROM User WHERE id = userId");
58
- // MSSQL: .body("SELECT id, name, email FROM [User] WHERE id = @userId")
59
-
60
- // DbContext에 등록
61
- class MainDb extends DbContext {
62
- getUserById = this.executable(GetUserById);
63
- }
64
-
65
- // 실행
66
- const [[user]] = await db.getUserById().execute({ userId: 1n });
67
- ```