@simplysm/sd-claude 14.0.89 → 14.0.90
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/claude/references/sd-simplysm14/README.md +16 -17
- package/claude/references/sd-simplysm14/apis/angular/README.md +52 -30
- package/claude/references/sd-simplysm14/apis/angular/controls.md +200 -38
- package/claude/references/sd-simplysm14/apis/angular/crud.md +41 -53
- package/claude/references/sd-simplysm14/apis/angular/directives.md +66 -22
- package/claude/references/sd-simplysm14/apis/angular/features.md +127 -40
- package/claude/references/sd-simplysm14/apis/angular/infra.md +60 -43
- package/claude/references/sd-simplysm14/apis/angular/layout.md +56 -20
- package/claude/references/sd-simplysm14/apis/angular/overlay.md +74 -74
- package/claude/references/sd-simplysm14/apis/angular/routing-appstructure.md +50 -40
- package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +55 -15
- package/claude/references/sd-simplysm14/apis/angular/shared-data.md +59 -42
- package/claude/references/sd-simplysm14/apis/angular/sheet.md +77 -62
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +8 -7
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +71 -43
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +22 -14
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +19 -19
- package/claude/references/sd-simplysm14/apis/core-browser/README.md +17 -17
- package/claude/references/sd-simplysm14/apis/core-browser/dom-element.md +28 -28
- package/claude/references/sd-simplysm14/apis/core-browser/indexed-db.md +37 -37
- package/claude/references/sd-simplysm14/apis/core-common/README.md +87 -219
- package/claude/references/sd-simplysm14/apis/core-common/array-ext.md +54 -98
- package/claude/references/sd-simplysm14/apis/core-common/async-runtime.md +57 -99
- package/claude/references/sd-simplysm14/apis/core-common/datetime.md +60 -103
- package/claude/references/sd-simplysm14/apis/core-common/errors.md +42 -47
- package/claude/references/sd-simplysm14/apis/core-common/obj.md +42 -88
- package/claude/references/sd-simplysm14/apis/core-common/serialization.md +55 -0
- package/claude/references/sd-simplysm14/apis/core-node/README.md +6 -7
- package/claude/references/sd-simplysm14/apis/core-node/consola.md +17 -12
- package/claude/references/sd-simplysm14/apis/core-node/cpx.md +14 -13
- package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +9 -8
- package/claude/references/sd-simplysm14/apis/core-node/fsx.md +14 -13
- package/claude/references/sd-simplysm14/apis/core-node/pathx.md +4 -8
- package/claude/references/sd-simplysm14/apis/core-node/worker.md +14 -12
- package/claude/references/sd-simplysm14/apis/excel/README.md +22 -22
- package/claude/references/sd-simplysm14/apis/excel/cell.md +37 -29
- package/claude/references/sd-simplysm14/apis/excel/conditional-format.md +29 -15
- package/claude/references/sd-simplysm14/apis/excel/style.md +33 -27
- package/claude/references/sd-simplysm14/apis/excel/utils.md +29 -19
- package/claude/references/sd-simplysm14/apis/excel/workbook-worksheet.md +78 -55
- package/claude/references/sd-simplysm14/apis/excel/wrapper.md +42 -45
- package/claude/references/sd-simplysm14/apis/orm-common/README.md +6 -8
- package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +118 -67
- package/claude/references/sd-simplysm14/apis/orm-common/expr.md +83 -86
- package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +102 -93
- package/claude/references/sd-simplysm14/apis/orm-common/schema.md +138 -81
- package/claude/references/sd-simplysm14/apis/orm-common/types.md +49 -44
- package/claude/references/sd-simplysm14/apis/orm-node/README.md +42 -42
- package/claude/references/sd-simplysm14/apis/orm-node/db-conn.md +44 -33
- package/claude/references/sd-simplysm14/apis/sd-cli/README.md +11 -10
- package/claude/references/sd-simplysm14/apis/service-client/README.md +56 -52
- package/claude/references/sd-simplysm14/apis/service-client/orm.md +33 -28
- package/claude/references/sd-simplysm14/apis/service-client/transport.md +23 -21
- package/claude/references/sd-simplysm14/apis/service-common/README.md +83 -48
- package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +126 -34
- package/claude/references/sd-simplysm14/apis/service-common/protocol.md +109 -54
- package/claude/references/sd-simplysm14/apis/service-server/README.md +69 -81
- package/claude/references/sd-simplysm14/apis/service-server/service-authoring.md +46 -43
- package/claude/references/sd-simplysm14/apis/service-server/transport-internals.md +63 -37
- package/claude/references/sd-simplysm14/apis/service-server/v1-legacy.md +40 -30
- package/claude/references/sd-simplysm14/apis/storage/README.md +17 -17
- package/claude/references/sd-simplysm14/manuals/client-app-structure.md +142 -140
- package/claude/references/sd-simplysm14/manuals/client-orm.md +1 -1
- package/claude/references/sd-simplysm14/manuals/client-service.md +19 -7
- package/claude/references/sd-simplysm14/manuals/client-shared-data.md +2 -2
- package/claude/references/sd-simplysm14/manuals/client-system-log.md +11 -3
- package/claude/references/sd-simplysm14/manuals/data-log.md +0 -1
- package/claude/references/sd-simplysm14/manuals/orm.md +16 -0
- package/claude/rules/sd-design-rules.md +10 -0
- package/claude/skills/sd-demo/SKILL.md +0 -6
- package/claude/skills/sd-docs/SKILL.md +58 -0
- package/claude/{workflows/sd-docs.rules.md → skills/sd-docs/references/subagent-prompt.md} +103 -103
- package/claude/skills/sd-impl/SKILL.md +7 -4
- package/claude/skills/sd-spec/SKILL.md +842 -15
- package/claude/skills/sd-spec/references/example-spec.md +26 -36
- package/package.json +1 -1
- package/claude/references/sd-simplysm14/apis/core-common/json-transfer.md +0 -53
- package/claude/skills/sd-spec/references/spec-authoring.md +0 -519
- package/claude/workflows/sd-docs.js +0 -84
|
@@ -1,64 +1,105 @@
|
|
|
1
|
-
# @simplysm/orm-common — 스키마 정의
|
|
1
|
+
# @simplysm/orm-common — 스키마 정의 (Table / View / Procedure / column / index / relation)
|
|
2
2
|
|
|
3
|
-
DB 객체(Table/View/Procedure)와 그 구성요소(
|
|
3
|
+
DB 객체(Table/View/Procedure)와 그 구성요소(column/index/관계)를 fluent 빌더로 선언하는 묶음. 모든 빌더는 immutable — 각 메서드가 새 인스턴스를 반환한다. 정의한 빌더는 `DbContext` 안에서 `this.queryable()`/`this.executable()` 로 등록한다. column 은 기본 `NOT NULL`; `.nullable()`/`.default(...)` 는 도메인 근거가 있을 때만 붙인다(orm.md).
|
|
4
4
|
|
|
5
5
|
## Table / TableBuilder
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
7
|
+
```typescript
|
|
8
|
+
function Table<TName extends string>(name: TName): TableBuilder<TName, {}, {}>;
|
|
9
|
+
|
|
10
|
+
class TableBuilder<TName, TColumns, TRelations> {
|
|
11
|
+
readonly meta: { name; description?; database?; schema?; columns?; primaryKey?; relations?; indexes? };
|
|
12
|
+
readonly $inferSelect; // columns + 관계(optional)
|
|
13
|
+
readonly $inferColumns; // column 값 타입만
|
|
14
|
+
readonly $inferInsert; // INSERT 타입 (autoIncrement/nullable/default 는 optional)
|
|
15
|
+
readonly $inferUpdate; // UPDATE 타입 (전부 optional)
|
|
16
|
+
|
|
17
|
+
description(desc: string): TableBuilder;
|
|
18
|
+
database(db: string): TableBuilder;
|
|
19
|
+
schema(schema: string): TableBuilder;
|
|
20
|
+
columns(fn: (c) => TNewColumns): TableBuilder;
|
|
21
|
+
primaryKey(...columns: (keyof TColumns)[]): TableBuilder;
|
|
22
|
+
indexes(fn: (i) => IndexBuilder[]): TableBuilder;
|
|
23
|
+
relations(fn: (r) => TRelations): TableBuilder;
|
|
24
|
+
}
|
|
25
|
+
```
|
|
17
26
|
|
|
18
|
-
|
|
27
|
+
- `Table(name)` — 빈 `TableBuilder` 생성. 이후 fluent 메서드로 채운다.
|
|
28
|
+
- `description(desc)` — 테이블 설명. CREATE TABLE 시 DDL comment 로 들어감.
|
|
29
|
+
- `database(db)` — 데이터베이스명 고정. 미지정 시 `DbContext` 의 기본 database.
|
|
30
|
+
- `schema(schema)` — 스키마명(MSSQL/PostgreSQL). MySQL 무시.
|
|
31
|
+
- `columns(fn)` — column factory `c` 를 받아 `{ name: c.타입() }` 레코드를 반환. 아래 column factory 참조. 호출 후 `$inferColumns` 등 타입이 갱신.
|
|
32
|
+
- `primaryKey(...columns)` — PK column 이름(들). 여러 개 넘기면 복합 PK.
|
|
33
|
+
- `indexes(fn)` — index factory `i` 를 받아 `IndexBuilder[]` 반환.
|
|
34
|
+
- `relations(fn)` — relation factory `r` 를 받아 FK/역참조 관계 레코드 반환. Table 은 `foreignKey`/`foreignKeyTarget`/`relationKey`/`relationKeyTarget` 모두 사용 가능.
|
|
35
|
+
- `$inferSelect` — SELECT 결과 타입(컬럼 + include 가능한 관계는 optional). `queryable` 콜백 인자의 원천.
|
|
36
|
+
- `$inferInsert` / `$inferUpdate` — `insert`/`update` 입력 타입. INSERT 는 autoIncrement·nullable·default column 이 optional, UPDATE 는 전부 optional.
|
|
19
37
|
|
|
20
38
|
```typescript
|
|
21
|
-
const
|
|
39
|
+
const User = Table("User")
|
|
22
40
|
.database("mydb")
|
|
23
41
|
.columns((c) => ({
|
|
24
42
|
id: c.bigint().autoIncrement(),
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
content: c.text().nullable(),
|
|
43
|
+
name: c.varchar(100),
|
|
44
|
+
email: c.varchar(200).nullable(),
|
|
28
45
|
}))
|
|
29
46
|
.primaryKey("id")
|
|
30
|
-
.indexes((i) => [i.index("
|
|
31
|
-
.relations((r) => ({ author: r.foreignKey(["authorId"], () => User) }));
|
|
47
|
+
.indexes((i) => [i.index("email").unique()]);
|
|
32
48
|
```
|
|
33
49
|
|
|
34
50
|
## View / ViewBuilder
|
|
35
51
|
|
|
36
|
-
|
|
52
|
+
```typescript
|
|
53
|
+
function View(name: string): ViewBuilder;
|
|
54
|
+
|
|
55
|
+
class ViewBuilder<TDbContext, TData, TRelations> {
|
|
56
|
+
readonly meta: { name; description?; database?; schema?; viewFn?; relations? };
|
|
57
|
+
readonly $inferSelect; // TData
|
|
58
|
+
|
|
59
|
+
description(desc): ViewBuilder;
|
|
60
|
+
database(db): ViewBuilder;
|
|
61
|
+
schema(schema): ViewBuilder;
|
|
62
|
+
query(viewFn: (db) => Queryable<TViewData, any>): ViewBuilder;
|
|
63
|
+
relations(fn: (r) => T): ViewBuilder;
|
|
64
|
+
}
|
|
65
|
+
```
|
|
37
66
|
|
|
38
|
-
- `View(name
|
|
39
|
-
- `
|
|
40
|
-
- `
|
|
41
|
-
- `
|
|
67
|
+
- `View(name)` — 빈 `ViewBuilder` 생성.
|
|
68
|
+
- `query(viewFn)` — 뷰 본문 SELECT 를 `db` 를 받는 함수로 정의. 반환 `Queryable` 의 select 결과가 뷰 데이터 타입이 됨. `queryable(this, View)` 등록 시 이 함수가 평가되어 column 이 구성된다.
|
|
69
|
+
- `relations(fn)` — 뷰는 `relationKey`/`relationKeyTarget` 만 사용 가능(DB FK 미생성). `foreignKey` 는 타입상 불가.
|
|
70
|
+
- `description`/`database`/`schema` — Table 과 동일 의미.
|
|
42
71
|
|
|
43
72
|
```typescript
|
|
44
73
|
const ActiveUsers = View("ActiveUsers")
|
|
45
74
|
.database("mydb")
|
|
46
|
-
.query((db:
|
|
47
|
-
db.user()
|
|
48
|
-
.where((u) => [expr.eq(u.isActive, true)])
|
|
49
|
-
.select((u) => ({ id: u.id, name: u.name })),
|
|
75
|
+
.query((db: MainDb) =>
|
|
76
|
+
db.user().where((u) => [expr.eq(u.status, "active")]).select((u) => ({ id: u.id, name: u.name })),
|
|
50
77
|
);
|
|
51
78
|
```
|
|
52
79
|
|
|
53
80
|
## Procedure / ProcedureBuilder
|
|
54
81
|
|
|
55
|
-
|
|
82
|
+
```typescript
|
|
83
|
+
function Procedure(name: string): ProcedureBuilder<never, never>;
|
|
84
|
+
|
|
85
|
+
class ProcedureBuilder<TParams, TReturns> {
|
|
86
|
+
readonly meta: { name; description?; database?; schema?; params?; returns?; query? };
|
|
87
|
+
readonly $params; readonly $returns;
|
|
88
|
+
|
|
89
|
+
description(desc): ProcedureBuilder;
|
|
90
|
+
database(db): ProcedureBuilder;
|
|
91
|
+
schema(schema): ProcedureBuilder;
|
|
92
|
+
params(fn: (c) => T): ProcedureBuilder;
|
|
93
|
+
returns(fn: (c) => T): ProcedureBuilder;
|
|
94
|
+
body(sql: string): ProcedureBuilder;
|
|
95
|
+
}
|
|
96
|
+
```
|
|
56
97
|
|
|
57
|
-
- `Procedure(name
|
|
58
|
-
- `
|
|
59
|
-
- `
|
|
60
|
-
- `
|
|
61
|
-
- `
|
|
98
|
+
- `Procedure(name)` — 빈 빌더 생성.
|
|
99
|
+
- `params(fn)` — 입력 파라미터를 column factory 로 정의. `Executable.execute(params)` 의 입력 타입이 됨.
|
|
100
|
+
- `returns(fn)` — 결과 column 정의. `execute` 결과 행 타입이 됨.
|
|
101
|
+
- `body(sql)` — 프로시저 본문 SQL. DBMS별 구문 차이 주의(MySQL: `userId`, MSSQL: `@userId`, PostgreSQL: `RETURN QUERY` 필요).
|
|
102
|
+
- `description`/`database`/`schema` — Table 과 동일.
|
|
62
103
|
|
|
63
104
|
```typescript
|
|
64
105
|
const GetUserById = Procedure("GetUserById")
|
|
@@ -68,53 +109,52 @@ const GetUserById = Procedure("GetUserById")
|
|
|
68
109
|
.body("SELECT id, name FROM User WHERE id = userId");
|
|
69
110
|
```
|
|
70
111
|
|
|
71
|
-
##
|
|
112
|
+
## column factory / ColumnBuilder
|
|
72
113
|
|
|
73
|
-
`
|
|
114
|
+
`columns`/`params`/`returns` 콜백 인자 `c` 가 column factory. 각 메서드는 `ColumnBuilder` 를 반환하고 `.autoIncrement()`/`.nullable()`/`.default()`/`.description()` 로 속성을 더한다(모두 immutable).
|
|
74
115
|
|
|
75
|
-
타입
|
|
116
|
+
타입 메서드:
|
|
76
117
|
|
|
77
|
-
- `int()` — INT(
|
|
78
|
-
- `bigint()` — BIGINT(
|
|
79
|
-
- `float()` — FLOAT(
|
|
80
|
-
- `double()` — DOUBLE(
|
|
81
|
-
- `decimal(precision, scale?)` —
|
|
118
|
+
- `int()` — INT(4바이트 정수).
|
|
119
|
+
- `bigint()` — BIGINT(8바이트 정수). autoIncrement PK 에 주로 사용.
|
|
120
|
+
- `float()` — FLOAT(단정밀도 실수).
|
|
121
|
+
- `double()` — DOUBLE(배정밀도 실수).
|
|
122
|
+
- `decimal(precision, scale?)` — 고정 소수점. `precision`=전체 자릿수, `scale`=소수 자릿수(선택). 금액 등 정밀도 필요 시.
|
|
82
123
|
- `varchar(length)` — 가변 길이 문자열. `length`=최대 길이.
|
|
83
|
-
- `char(length)` — 고정 길이 문자열.
|
|
84
|
-
- `text()` — 대용량
|
|
85
|
-
- `binary()` — 바이너리(MySQL LONGBLOB / MSSQL VARBINARY(MAX) /
|
|
86
|
-
- `boolean()` — 불리언(MySQL TINYINT(1) / MSSQL BIT /
|
|
87
|
-
- `datetime()` —
|
|
88
|
-
- `date()` —
|
|
89
|
-
- `time()` —
|
|
90
|
-
- `uuid()` — UUID(MySQL BINARY(16) / MSSQL UNIQUEIDENTIFIER /
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
- `autoIncrement()` — 자동 증가. INSERT
|
|
95
|
-
- `nullable()` — NULL 허용. 값 타입에 `undefined` 추가, INSERT
|
|
96
|
-
- `default(value)` —
|
|
97
|
-
- `description(desc)` —
|
|
124
|
+
- `char(length)` — 고정 길이 문자열.
|
|
125
|
+
- `text()` — 대용량 텍스트.
|
|
126
|
+
- `binary()` — 바이너리(MySQL LONGBLOB / MSSQL VARBINARY(MAX) / PostgreSQL BYTEA). 값 타입 `Bytes`.
|
|
127
|
+
- `boolean()` — 불리언(MySQL TINYINT(1) / MSSQL BIT / PostgreSQL BOOLEAN).
|
|
128
|
+
- `datetime()` — 날짜+시간. 값 타입 `DateTime`.
|
|
129
|
+
- `date()` — 날짜만. 값 타입 `DateOnly`.
|
|
130
|
+
- `time()` — 시간만. 값 타입 `Time`.
|
|
131
|
+
- `uuid()` — UUID(MySQL BINARY(16) / MSSQL UNIQUEIDENTIFIER / PostgreSQL UUID). 값 타입 `Uuid`.
|
|
132
|
+
|
|
133
|
+
`ColumnBuilder` 속성 메서드:
|
|
134
|
+
|
|
135
|
+
- `autoIncrement()` — INSERT 시 자동 증가. INSERT 타입에서 optional 처리. PK 자동 증가 column 에.
|
|
136
|
+
- `nullable()` — NULL 허용. 값 타입에 `undefined` 추가, INSERT optional. 도메인상 값이 없을 수 있을 때만.
|
|
137
|
+
- `default(value)` — INSERT 시 미지정이면 사용할 기본값. INSERT optional 처리. 사용자가 명시 지시한 경우에만.
|
|
138
|
+
- `description(desc)` — column 설명(DDL comment).
|
|
98
139
|
|
|
99
140
|
```typescript
|
|
100
141
|
.columns((c) => ({
|
|
101
142
|
id: c.bigint().autoIncrement(),
|
|
143
|
+
price: c.decimal(10, 2),
|
|
102
144
|
email: c.varchar(200).nullable(),
|
|
103
145
|
status: c.varchar(20).default("active"),
|
|
104
146
|
}))
|
|
105
147
|
```
|
|
106
148
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
## IndexBuilder / createIndexFactory
|
|
149
|
+
## index factory / IndexBuilder
|
|
110
150
|
|
|
111
|
-
`
|
|
151
|
+
`indexes` 콜백 인자 `i` 의 `index(...columns)` 로 시작해 fluent 로 옵션을 더한다.
|
|
112
152
|
|
|
113
|
-
- `index(...columns)
|
|
114
|
-
-
|
|
115
|
-
-
|
|
116
|
-
-
|
|
117
|
-
-
|
|
153
|
+
- `i.index(...columns)` — index 대상 column 이름(들). 여러 개면 복합 index.
|
|
154
|
+
- `.name(name)` — index 이름 지정. 미지정 시 자동 생성.
|
|
155
|
+
- `.unique()` — 유니크 index.
|
|
156
|
+
- `.orderBy(...orderBy)` — column별 정렬 방향 배열("ASC"|"DESC"). column 수와 길이 일치해야 함.
|
|
157
|
+
- `.description(description)` — index 설명(DDL comment).
|
|
118
158
|
|
|
119
159
|
```typescript
|
|
120
160
|
.indexes((i) => [
|
|
@@ -123,25 +163,42 @@ const GetUserById = Procedure("GetUserById")
|
|
|
123
163
|
])
|
|
124
164
|
```
|
|
125
165
|
|
|
126
|
-
##
|
|
166
|
+
## relation factory
|
|
127
167
|
|
|
128
|
-
`
|
|
168
|
+
`relations` 콜백 인자 `r`. Table 은 4종 모두, View 는 `relationKey`/`relationKeyTarget` 만. 대상 빌더는 순환 참조 방지를 위해 모두 `() => Target` 지연 함수로 넘긴다. `description`/`single` 은 메서드 체이닝이 아니라 마지막 `opts` 인자로 전달(체이닝은 TS7022 유발로 제거됨).
|
|
129
169
|
|
|
130
|
-
- `r.foreignKey(columns, () => Target, opts?)` — N:1 FK 관계(DB FK 제약
|
|
131
|
-
- `r.foreignKeyTarget(() => Target, relationName, opts?)` — 1:N
|
|
132
|
-
- `r.relationKey(columns, () => Target, opts?)` — N:1 논리 관계(DB FK
|
|
133
|
-
- `r.relationKeyTarget(() => Target, relationName, opts?)` — 1:N 논리 역참조(DB FK 미생성).
|
|
170
|
+
- `r.foreignKey(columns, () => Target, opts?)` — N:1 FK 관계(DB FK 제약 **생성**). `columns`=현재 테이블 FK column 배열, 대상은 그 테이블의 PK 와 매칭. `opts.description?`. → `ForeignKeyBuilder`.
|
|
171
|
+
- `r.foreignKeyTarget(() => Target, relationName, opts?)` — FK 역참조(1:N, DB FK 생성 측의 역방향). `relationName`=대상 테이블에서 이쪽을 가리키는 FK 관계 이름. `opts.single: true` 면 1:1 단일 객체, 아니면 배열. `opts.description?`. → `ForeignKeyTargetBuilder`.
|
|
172
|
+
- `r.relationKey(columns, () => Target, opts?)` — N:1 논리 관계(DB FK **미생성**). FK 와 동일하나 제약 없음. View 에서도 사용. → `RelationKeyBuilder`.
|
|
173
|
+
- `r.relationKeyTarget(() => Target, relationName, opts?)` — 1:N/1:1 논리 역참조(DB FK 미생성). `opts.single`/`opts.description` 동일. → `RelationKeyTargetBuilder`.
|
|
174
|
+
|
|
175
|
+
각 `opts`:
|
|
176
|
+
|
|
177
|
+
- `description?: string` — 관계 설명.
|
|
178
|
+
- `single?: boolean` (target 계열만) — true=결과를 단일 객체(1:1), false/미지정=배열(1:N). `include()`/`$inferSelect` 의 해당 키 타입이 단일/배열로 갈린다.
|
|
134
179
|
|
|
135
180
|
```typescript
|
|
136
|
-
|
|
137
|
-
.
|
|
138
|
-
|
|
139
|
-
.relations((r) => ({
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
}))
|
|
181
|
+
const Post = Table("Post")
|
|
182
|
+
.columns((c) => ({ id: c.bigint().autoIncrement(), authorId: c.bigint() }))
|
|
183
|
+
.primaryKey("id")
|
|
184
|
+
.relations((r) => ({ author: r.foreignKey(["authorId"], () => User, { description: "작성자" }) }));
|
|
185
|
+
|
|
186
|
+
const User = Table("User")
|
|
187
|
+
.columns((c) => ({ id: c.bigint().autoIncrement(), name: c.varchar(100) }))
|
|
188
|
+
.primaryKey("id")
|
|
189
|
+
.relations((r) => ({
|
|
190
|
+
posts: r.foreignKeyTarget(() => Post, "author"),
|
|
191
|
+
profile: r.foreignKeyTarget(() => Profile, "user", { single: true }),
|
|
192
|
+
}));
|
|
143
193
|
```
|
|
144
194
|
|
|
145
|
-
|
|
195
|
+
주의: FK column 개수와 대상 테이블 PK 개수가 다르면 `include()`/join 시 "FK/PK column count mismatch" throw. PK 가 복합이면 FK column 도 같은 순서·개수로.
|
|
196
|
+
|
|
197
|
+
## 빌더/추론 타입 (직접 참조 드묾)
|
|
146
198
|
|
|
147
|
-
|
|
199
|
+
- `ColumnBuilderRecord` — `Record<string, ColumnBuilder<...>>`. `columns`/`params`/`returns` 반환 타입.
|
|
200
|
+
- `RelationBuilderRecord` — 4종 relation 빌더의 union 레코드. `relations` 반환 타입.
|
|
201
|
+
- `InferColumns<T>` / `InferInsertColumns<T>` / `InferUpdateColumns<T>` / `InferColumnExprs<T>` — column 레코드에서 각각 값 타입 / INSERT 입력 / UPDATE 입력 / `ExprInput` 입력 타입을 추론. `$inferColumns` 등 내부 사용.
|
|
202
|
+
- `RequiredInsertKeys<T>` / `OptionalInsertKeys<T>` — INSERT 시 필수/선택 column key 분리(autoIncrement·nullable·default 가 선택).
|
|
203
|
+
- `DataToColumnBuilderRecord<TData>` — 데이터 레코드 → column 빌더 레코드 역변환. `insertInto` 의 대상 테이블 제약에 사용.
|
|
204
|
+
- `InferDeepRelations<T>` / `ExtractRelationTarget<T>` / `ExtractRelationTargetResult<T>` — 관계 정의에서 심층 결과 타입을 optional 로 추론(같은 테이블 재방문 시 순환 차단). `$inferSelect` 의 관계 부분.
|
|
@@ -1,62 +1,67 @@
|
|
|
1
|
-
# @simplysm/orm-common —
|
|
1
|
+
# @simplysm/orm-common — 하위 타입 / QueryDef AST / QueryBuilder / 결과 파싱
|
|
2
2
|
|
|
3
|
-
executor
|
|
3
|
+
executor·QueryBuilder 를 직접 구현하거나, `QueryDef`/`Expr` AST·column 타입을 다루거나, 원시 결과를 TS 객체로 환원할 때 참조하는 묶음. 일반 쿼리 작성에서는 expr/Queryable 가 이 타입들을 가려주므로 직접 쓸 일이 적다.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## column 타입
|
|
6
6
|
|
|
7
|
-
- `
|
|
8
|
-
- `
|
|
9
|
-
- `
|
|
10
|
-
- `
|
|
11
|
-
- `
|
|
12
|
-
- `
|
|
13
|
-
- `
|
|
14
|
-
- `
|
|
7
|
+
- `DataType` — SQL 데이터 타입 union: `{type:"int"}`, `{type:"bigint"}`, `{type:"float"}`, `{type:"double"}`, `{type:"decimal", precision, scale?}`, `{type:"varchar", length}`, `{type:"char", length}`, `{type:"text"}`, `{type:"binary"}`, `{type:"boolean"}`, `{type:"datetime"}`, `{type:"date"}`, `{type:"time"}`, `{type:"uuid"}`. `expr.cast` 의 targetType·DDL column 정의에 사용.
|
|
8
|
+
- `ColumnPrimitiveMap` — TS 타입 이름 → 실제 타입 매핑: `string→string`, `number→number`, `boolean→boolean`, `DateTime→DateTime`, `DateOnly→DateOnly`, `Time→Time`, `Uuid→Uuid`, `Bytes→Bytes`.
|
|
9
|
+
- `ColumnPrimitiveStr` — `keyof ColumnPrimitiveMap`(타입 이름 문자열). `ExprUnit.dataType`·`val` 의 dataType.
|
|
10
|
+
- `ColumnPrimitive` — 저장 가능한 모든 원시 값 union + `undefined`(=NULL).
|
|
11
|
+
- `dataTypeStrToColumnPrimitiveStr` (const) — SQL DataType 이름 → TS 타입 이름 매핑 객체(`int→"number"`, `varchar→"string"`, `datetime→"DateTime"` 등). `cast` 가 결과 타입 결정에 사용.
|
|
12
|
+
- `InferColumnPrimitiveFromDataType<T>` — `DataType` 에서 TS 값 타입 추론.
|
|
13
|
+
- `inferColumnPrimitiveStr(value)` — 런타임 값에서 `ColumnPrimitiveStr` 추론. NULL 이면 추론 불가 throw.
|
|
14
|
+
- `ColumnMeta` — column 메타: `{ type: ColumnPrimitiveStr; dataType: DataType; autoIncrement?; nullable?; default?; description? }`. `ColumnBuilder.meta` 타입.
|
|
15
15
|
|
|
16
|
-
##
|
|
16
|
+
## db 타입
|
|
17
17
|
|
|
18
|
-
- `
|
|
19
|
-
- `const
|
|
20
|
-
- `
|
|
21
|
-
- `
|
|
22
|
-
- `
|
|
23
|
-
- `
|
|
18
|
+
- `Dialect` — `"mysql" | "mssql" | "postgresql"`. 지원 DBMS(MySQL 8.0.14+, MSSQL 2012+, PostgreSQL 9.0+).
|
|
19
|
+
- `dialects` (const) — `Dialect[]`(전체 목록). dialect별 테스트 매트릭스에 사용.
|
|
20
|
+
- `DataRecord` — 재귀 결과 레코드 타입: `{ [key: string]: ColumnPrimitive | DataRecord | DataRecord[] }`. include 중첩(단일 객체/배열)을 표현.
|
|
21
|
+
- `QueryBuildResult` — `build()` 반환: `{ sql: string; resultSetIndex?: number; resultSetStride?: number }`. `resultSetIndex`=결과를 가져올 셋 index(기본 0, 예 MySQL INSERT+OUTPUT 는 1). `resultSetStride`=다중 결과에서 N번째마다 추출(MySQL 배치 INSERT 의 `INSERT;SELECT;...` 에서 SELECT 만 모을 때).
|
|
22
|
+
- `IsolationLevel` — 트랜잭션 격리 수준(자세히는 [db-context.md](./db-context.md)).
|
|
23
|
+
- `DbContextExecutor` / `ResultMeta` / `Migration` — executor·결과 메타·마이그레이션 정의. [db-context.md](./db-context.md) 참조.
|
|
24
24
|
|
|
25
|
-
##
|
|
25
|
+
## QueryDef AST (query-def.ts)
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
- `interface Migration` — `{ name; up(db) }` ([db-context.md](./db-context.md) 참조).
|
|
27
|
+
`executeDefs`/`build` 가 다루는 쿼리 정의 AST. `Queryable.getXQueryDef()`·`DbContext.getXQueryDef()` 가 생성.
|
|
29
28
|
|
|
30
|
-
|
|
29
|
+
- `QueryDefObjectName` — `{ database?; schema?; name }`. DB 객체 네임스페이스(MySQL `database.name`, MSSQL `database.schema.name`, PostgreSQL `schema.name`).
|
|
30
|
+
- DML: `SelectQueryDef`(from/as/select/distinct/top/lock/where/joins/orderBy/limit/groupBy/having/with), `SelectQueryDefJoin`(SelectQueryDef + `isSingle?`), `InsertQueryDef`(records/overrideIdentity?/output?), `InsertIfNotExistsQueryDef`, `InsertIntoQueryDef`, `UpdateQueryDef`, `DeleteQueryDef`, `UpsertQueryDef`.
|
|
31
|
+
- `CudOutputDef` — CUD OUTPUT 절: `{ columns: string[]; pkColNames: string[]; aiColName? }`. 삽입/갱신/삭제 행 회수 정의.
|
|
32
|
+
- DDL: `ClearSchemaQueryDef`, `CreateTableQueryDef`/`DropTableQueryDef`/`RenameTableQueryDef`/`TruncateQueryDef`, `AddColumnQueryDef`/`DropColumnQueryDef`/`ModifyColumnQueryDef`/`RenameColumnQueryDef`, `AddPrimaryKeyQueryDef`/`DropPrimaryKeyQueryDef`/`AddForeignKeyQueryDef`/`DropForeignKeyQueryDef`/`AddIndexQueryDef`/`DropIndexQueryDef`, `CreateViewQueryDef`/`DropViewQueryDef`/`CreateProcQueryDef`/`DropProcQueryDef`/`ExecProcQueryDef`.
|
|
33
|
+
- Utils/Meta: `SwitchFkQueryDef`(`{ table; enabled }`, DDL 아님 — 트랜잭션 가능), `SchemaExistsQueryDef`.
|
|
34
|
+
- `DDL_TYPES` (const) — DDL QueryDef type 문자열 배열. 트랜잭션 중 DDL 차단 판정(`switchFk` 는 제외)에 사용.
|
|
35
|
+
- `DdlType` — `(typeof DDL_TYPES)[number]`.
|
|
36
|
+
- `QueryDef` — 전체 union(DML + DDL + SwitchFk + SchemaExists). `executeDefs(defs: QueryDef[])` 의 원소 타입.
|
|
31
37
|
|
|
32
|
-
|
|
38
|
+
## Expr AST (expr.ts)
|
|
33
39
|
|
|
34
|
-
|
|
35
|
-
- DML: `SelectQueryDef`(from/select/where/joins/orderBy/limit/groupBy/having/with/distinct/top/lock), `SelectQueryDefJoin`(+`isSingle?`), `InsertQueryDef`(records/overrideIdentity?/output?), `InsertIfNotExistsQueryDef`(record/existsSelectQuery), `InsertIntoQueryDef`(recordsSelectQuery), `UpdateQueryDef`(record/where/joins), `DeleteQueryDef`, `UpsertQueryDef`(existsSelectQuery/insertRecord/updateRecord).
|
|
36
|
-
- DDL: `ClearSchemaQueryDef`, `CreateTableQueryDef`/`DropTableQueryDef`/`RenameTableQueryDef`/`TruncateQueryDef`, `AddColumnQueryDef`/`DropColumnQueryDef`/`ModifyColumnQueryDef`/`RenameColumnQueryDef`, `AddPrimaryKeyQueryDef`/`DropPrimaryKeyQueryDef`/`AddForeignKeyQueryDef`/`DropForeignKeyQueryDef`/`AddIndexQueryDef`/`DropIndexQueryDef`, `CreateViewQueryDef`/`DropViewQueryDef`/`CreateProcQueryDef`/`DropProcQueryDef`/`ExecProcQueryDef`.
|
|
37
|
-
- Utils/Meta: `SwitchFkQueryDef`(`table`/`enabled`), `SchemaExistsQueryDef`.
|
|
38
|
-
- `const DDL_TYPES` — DDL QueryDef 의 `type` 문자열 배열(`switchFk` 제외 — 트랜잭션 내 허용). `transact` 중 DDL 차단 검사·검증에. `type DdlType` — 그 union.
|
|
40
|
+
`ExprUnit.expr`/`WhereExprUnit.expr` 가 담는 JSON AST. QueryBuilder 의 ExprRenderer 가 SQL 로 변환.
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
- `Expr` — 전체 표현식 union(값 `ExprColumn`/`ExprValue`/`ExprRaw`, 문자열/숫자/날짜/조건/집계/기타/window `ExprWindow`/시스템 `ExprSubquery`). select/orderBy 등.
|
|
43
|
+
- `WhereExpr` — WHERE 전용 union(비교 `ExprEq`/`ExprGt`/.../`ExprIn`/`ExprInQuery`/`ExprExists` + 논리 `ExprNot`/`ExprAnd`/`ExprOr`). where/having.
|
|
44
|
+
- 개별 인터페이스(`ExprEq`, `ExprConcat`, `ExprCount`, `ExprCast`, `ExprWindow` 등) — 각 `expr.*` 함수가 만드는 노드. `type` discriminant + 피연산자 필드.
|
|
45
|
+
- `DateUnit` — `"year"|"month"|"day"|"hour"|"minute"|"second"`. dateDiff/dateAdd.
|
|
46
|
+
- `WinFn` — window 함수 노드 union(`WinFnRowNumber`/`WinFnRank`/`WinFnLag`/`WinFnSum`/...). `WinSpec` — `{ partitionBy?: Expr[]; orderBy?: [Expr,("ASC"|"DESC")?][] }`(OVER 절).
|
|
41
47
|
|
|
42
|
-
|
|
43
|
-
- `type WhereExpr` — 비교·논리·NULL·LIKE·IN·EXISTS 등 WHERE 전용 union.
|
|
44
|
-
- `type DateUnit = "year"|"month"|"day"|"hour"|"minute"|"second"` — dateDiff/dateAdd 단위.
|
|
45
|
-
- `interface WinSpec` — `{ partitionBy?: Expr[]; orderBy?: [Expr, ("ASC"|"DESC")?][] }`(window OVER 절 AST).
|
|
46
|
-
- 노드별 인터페이스: `ExprColumn`(`path`), `ExprValue`(`value`), `ExprRaw`(`sql`/`params`), 비교 `ExprEq`/`ExprGt`/`ExprLt`/`ExprGte`/`ExprLte`/`ExprBetween`/`ExprIsNull`/`ExprLike`/`ExprRegexp`/`ExprIn`/`ExprInQuery`/`ExprExists`, 논리 `ExprNot`/`ExprAnd`/`ExprOr`, 문자열·숫자·날짜·조건·집계·기타(`ExprConcat`...`ExprSubquery`), window `ExprWindow` 등. 각 노드는 `type` 디스크리미네이터 + 피연산자 필드를 가진 평범한 데이터 객체.
|
|
48
|
+
## QueryBuilder (QueryDef → SQL)
|
|
47
49
|
|
|
48
|
-
|
|
50
|
+
직접 SQL 문자열이 필요하거나 dialect 동작을 검증할 때.
|
|
49
51
|
|
|
50
|
-
|
|
52
|
+
- `createQueryBuilder(dialect: Dialect): QueryBuilderBase` — dialect 에 맞는 QueryBuilder 생성(`mysql`→Mysql, `mssql`→Mssql, `postgresql`→Postgresql).
|
|
53
|
+
- `QueryBuilderBase` (abstract) — `build(def: QueryDef): QueryBuildResult` 가 공개 진입점. `def.type` 으로 동적 dispatch. 나머지는 protected/abstract(dialect 구현).
|
|
54
|
+
- `MysqlQueryBuilder` / `MssqlQueryBuilder` / `PostgresqlQueryBuilder` — dialect별 구현. 보통 `createQueryBuilder` 로 얻음.
|
|
55
|
+
- `ExprRendererBase` (abstract) — Expr→SQL 렌더러. `render(expr): string`, `renderWhere(exprs): string` 공개. `wrap(name)`/`escapeString`/`escapeValue` 는 dialect abstract.
|
|
56
|
+
- `MysqlExprRenderer` / `MssqlExprRenderer` / `PostgresqlExprRenderer` — dialect별 렌더러.
|
|
51
57
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
- `abstract class ExprRendererBase` — `Expr`/`WhereExpr` 노드를 SQL 조각으로 렌더링하는 추상 기반. `class MysqlExprRenderer`/`class MssqlExprRenderer`/`class PostgresqlExprRenderer` 가 dialect 구현. QueryBuilder 내부에서 식별자 wrap·표현식 변환에 사용.
|
|
58
|
+
```typescript
|
|
59
|
+
const sql = createQueryBuilder("mysql").build(queryable.getSelectQueryDef()).sql;
|
|
60
|
+
```
|
|
56
61
|
|
|
57
|
-
## 결과 파싱
|
|
62
|
+
## 결과 파싱
|
|
58
63
|
|
|
59
|
-
executor 가
|
|
64
|
+
executor 가 원시 행을 받은 뒤 `ResultMeta` 로 TS 객체로 환원할 때.
|
|
60
65
|
|
|
61
|
-
- `parseQueryResult<T>(rawResults, meta
|
|
62
|
-
- `pickResultSets<T>(rawResults
|
|
66
|
+
- `parseQueryResult<T>(rawResults, meta): Promise<T[] | undefined>` — 원시 결과 배열 + `ResultMeta` 로 타입 변환·JOIN 중첩. JOIN 없으면 단순 파싱, 있으면 그룹키 기준 재귀 그룹핑(O(n) Map). 입력 비었거나 파싱 후 전부 빈 객체면 `undefined`. 100건마다 이벤트 루프 양보(async 전용). isSingle 관계에 서로 다른 결과가 섞이면 throw.
|
|
67
|
+
- `pickResultSets<T>(rawResults, buildResult): T[]` — 다중 결과셋에서 `QueryBuildResult` 의 `resultSetIndex`/`resultSetStride` 에 따라 필요한 셋만 추출. index 없으면 첫 셋, stride 없으면 index 셋 단일, stride 있으면 index 부터 stride 간격으로 concat(MySQL 배치 INSERT 의 SELECT 만 모을 때).
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# @simplysm/orm-node
|
|
2
2
|
|
|
3
|
-
Node.js 환경에서 `@simplysm/orm-common` 의 `DbContext` 를 실제 DB(MySQL/MSSQL/PostgreSQL)에 연결·실행하는 ORM 런타임. 고수준 진입점(`createOrm`)과 저수준 연결(`createDbConn`/`DbConn`)을 함께
|
|
3
|
+
Node.js 환경에서 `@simplysm/orm-common` 의 `DbContext` 를 실제 DB(MySQL/MSSQL/PostgreSQL)에 연결·실행하는 ORM 런타임. 고수준 진입점(`createOrm`)과 저수준 연결(`createDbConn`/`DbConn`)을 함께 노출.
|
|
4
4
|
|
|
5
5
|
## 사용 트리거 인덱스
|
|
6
6
|
|
|
7
|
-
- **createOrm / Orm / OrmOptions** — `DbContext` 서브클래스로 ORM 인스턴스를 만들고 트랜잭션
|
|
8
|
-
- **NodeDbContextExecutor** — `DbContext` 에 직접 주입할 executor 를 손수 만들 때(
|
|
9
|
-
- **createDbConn / DbConn /
|
|
7
|
+
- **createOrm / Orm / OrmOptions** — `DbContext` 서브클래스로 ORM 인스턴스를 만들고 `connect`/`connectWithoutTransaction` 으로 트랜잭션 경계를 잡아 query 를 돌릴 때. (아래 "ORM 진입" 군)
|
|
8
|
+
- **NodeDbContextExecutor** — `DbContext` 에 직접 주입할 executor 를 손수 만들 때(`createOrm` 이 내부에서 자동 생성하므로 직접 쓸 일은 드묾). (아래 "ORM 진입" 군 및 db-conn.md)
|
|
9
|
+
- **createDbConn / DbConn / DbConnConfig 계열 / getDialectFromConfig / DB_CONN_\* 상수** — ORM 없이 raw SQL·파라미터 쿼리·bulk insert·수동 트랜잭션을 직접 다루거나 dialect별 접속 설정을 작성할 때. 자세히: [db-conn.md](./db-conn.md)
|
|
10
10
|
|
|
11
11
|
## ORM 진입
|
|
12
12
|
|
|
13
|
-
`DbContext` 서브클래스와
|
|
13
|
+
`DbContext` 서브클래스와 접속 설정을 받아 연결·트랜잭션 경계를 관리하는 고수준 진입. query DSL 자체는 `@simplysm/orm-common` 의 `DbContext` 가 제공하고, 이 군은 그 컨텍스트를 실제 DB 연결에 묶는 역할.
|
|
14
14
|
|
|
15
15
|
### createOrm
|
|
16
16
|
|
|
@@ -22,69 +22,69 @@ function createOrm<T extends DbContext>(
|
|
|
22
22
|
): Orm<T>
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
`DbContext` 서브클래스를 받아 `Orm<T>` 를 반환. 인스턴스는
|
|
25
|
+
`DbContext` 서브클래스를 받아 `Orm<T>` 를 반환. DB 인스턴스는 `connect`/`connectWithoutTransaction` 호출마다 새로 생성되므로 반환된 `Orm` 객체 자체는 재사용 가능.
|
|
26
26
|
|
|
27
|
-
- DbClass
|
|
28
|
-
- config
|
|
29
|
-
- options
|
|
27
|
+
- DbClass — `DbContext` 를 상속한 생성자. `(executor, { database, schema? })` 시그니처 고정. query 진입점(`this.queryable(Entity)`)을 정의한 사용자 DB 클래스를 넘김. 어떤 엔티티 집합을 다룰지 결정하는 자리.
|
|
28
|
+
- config — `DbConnConfig`(dialect별 분기 유니온, [db-conn.md](./db-conn.md) 참조). 접속 대상·인증 정보. DBMS 종류·호스트·계정이 여기서 정해짐.
|
|
29
|
+
- options? — `OrmOptions`. config 의 `database`/`schema` 를 덮어쓰는 우선 옵션. 같은 접속 정보로 DB·스키마만 바꿔 쓸 때(다중 테넌트 등) 지정.
|
|
30
30
|
|
|
31
|
-
database 해석: `options.database` → `config.database` 순으로 찾고, 둘 다 없거나 빈 문자열이면 `"database는 필수입니다"` throw. schema
|
|
31
|
+
database 해석: `options.database` → `config.database` 순으로 찾고, 둘 다 없거나 빈 문자열이면 `"database는 필수입니다"` throw. schema 해석도 `options.schema` → `config.schema` 순(없으면 `undefined` 유지).
|
|
32
32
|
|
|
33
33
|
```typescript
|
|
34
|
-
class
|
|
34
|
+
class TestDb extends DbContext {
|
|
35
35
|
user = this.queryable(User);
|
|
36
36
|
}
|
|
37
|
-
const orm = createOrm(
|
|
38
|
-
await orm.connect(async (db) =>
|
|
37
|
+
const orm = createOrm(TestDb, mysqlConfig, { database: "TestDb" });
|
|
38
|
+
await orm.connect(async (db) => {
|
|
39
|
+
await db.user().insert([{ id: 100, name: "orm-test" }]);
|
|
40
|
+
return db.user().execute();
|
|
41
|
+
}); // 트랜잭션 안에서 실행 후 자동 커밋
|
|
39
42
|
```
|
|
40
43
|
|
|
41
44
|
### Orm
|
|
42
45
|
|
|
43
46
|
```typescript
|
|
44
47
|
interface Orm<T extends DbContext> {
|
|
45
|
-
readonly DbClass
|
|
48
|
+
readonly DbClass: new (executor: DbContextExecutor, opt: { database: string; schema?: string }) => T;
|
|
49
|
+
readonly config: DbConnConfig;
|
|
50
|
+
readonly options?: OrmOptions;
|
|
46
51
|
connect<R>(callback: (conn: T) => Promise<R>, isolationLevel?: IsolationLevel): Promise<R>;
|
|
47
52
|
connectWithoutTransaction<R>(callback: (conn: T) => Promise<R>): Promise<R>;
|
|
48
53
|
}
|
|
49
54
|
```
|
|
50
55
|
|
|
51
|
-
`createOrm` 반환 타입.
|
|
56
|
+
`createOrm` 반환 타입. 각 메서드 호출마다 DB 인스턴스를 새로 만들어 연결→콜백→정리.
|
|
52
57
|
|
|
53
|
-
-
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
58
|
+
- DbClass / config / options — `createOrm` 에 넘긴 값을 그대로 읽기 전용으로 보관. 같은 설정으로 재연결·진단할 때 참조.
|
|
59
|
+
- connect — 콜백을 **트랜잭션 안에서** 실행. 콜백이 정상 종료하면 커밋, throw 하면 롤백 후 그 오류를 다시 throw. 여러 쓰기를 원자적으로 묶어야 할 때.
|
|
60
|
+
- isolationLevel? — `"READ_UNCOMMITTED" | "READ_COMMITTED" | "REPEATABLE_READ" | "SERIALIZABLE"`(`@simplysm/orm-common`). 트랜잭션 격리 수준. 미지정 시 연결의 `defaultIsolationLevel`, 그것도 없으면 `READ_UNCOMMITTED`. 더티 리드를 막아야 하면 `READ_COMMITTED` 이상으로 올림.
|
|
61
|
+
- connectWithoutTransaction — 콜백을 **트랜잭션 없이** 실행. 읽기 전용이거나, 콜백 내부에서 `db.transaction(...)` 으로 부분 트랜잭션을 직접 열어 일부 구간만 원자화할 때.
|
|
62
|
+
- callback — 연결된 DbContext 인스턴스(`T`)를 받아 query 를 수행하고 임의 값 `R` 을 반환. 그 반환값이 `connect`/`connectWithoutTransaction` 의 결과가 됨.
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
// 읽기는 트랜잭션 없이, 그 안에서 일부 쓰기만 부분 트랜잭션으로
|
|
66
|
+
await orm.connectWithoutTransaction(async (db) => {
|
|
67
|
+
await db.transaction(async () => {
|
|
68
|
+
await db.user().insert([{ id: 300, name: "partial-tx" }]);
|
|
69
|
+
});
|
|
70
|
+
return db.user().execute();
|
|
71
|
+
});
|
|
72
|
+
```
|
|
57
73
|
|
|
58
74
|
### OrmOptions
|
|
59
75
|
|
|
60
76
|
```typescript
|
|
61
|
-
interface OrmOptions {
|
|
77
|
+
interface OrmOptions {
|
|
78
|
+
database?: string;
|
|
79
|
+
schema?: string;
|
|
80
|
+
}
|
|
62
81
|
```
|
|
63
82
|
|
|
64
83
|
`createOrm` 3번째 인자. config 보다 우선 적용.
|
|
65
84
|
|
|
66
|
-
- database
|
|
67
|
-
- schema
|
|
85
|
+
- database? — 사용할 DB 이름. config 의 `database` 대신 쓸 때. 접속 정보는 같고 DB 만 다른 다중 테넌트 상황에서 인스턴스별로 지정.
|
|
86
|
+
- schema? — 스키마 이름(예: MSSQL `dbo`, PostgreSQL `public`). MySQL 은 스키마 개념이 없어 보통 미지정.
|
|
68
87
|
|
|
69
88
|
### NodeDbContextExecutor
|
|
70
89
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
```typescript
|
|
74
|
-
class NodeDbContextExecutor implements DbContextExecutor {
|
|
75
|
-
constructor(config: DbConnConfig);
|
|
76
|
-
connect(): Promise<void>; close(): Promise<void>;
|
|
77
|
-
beginTransaction(isolationLevel?: IsolationLevel): Promise<void>;
|
|
78
|
-
commitTransaction(): Promise<void>; rollbackTransaction(): Promise<void>;
|
|
79
|
-
executeParametrized(query: string, params?: unknown[]): Promise<Record<string, unknown>[][]>;
|
|
80
|
-
bulkInsert(tableName: string, columnMetas: Record<string, ColumnMeta>, records: DataRecord[]): Promise<void>;
|
|
81
|
-
executeDefs<T>(defs: QueryDef[], resultMetas?: (ResultMeta | undefined)[]): Promise<T[][]>;
|
|
82
|
-
}
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
- constructor(config): `DbConnConfig` 로 dialect 를 결정(`getDialectFromConfig`). `connect()` 호출 전까지 실제 연결은 열지 않음.
|
|
86
|
-
- connect/close: 내부적으로 `createDbConn` 으로 연결 생성 후 open/close. `connect` 미호출 상태에서 다른 메서드 호출 시 `DB_CONN_ERRORS.NOT_CONNECTED` 로 throw.
|
|
87
|
-
- begin/commit/rollbackTransaction: 연결의 트랜잭션 제어를 그대로 위임. `isolationLevel?` 은 위 `Orm.connect` 와 동일 의미.
|
|
88
|
-
- executeParametrized: 파라미터 바인딩 query 1건 실행. dialect 별 placeholder 차이는 [db-conn.md](./db-conn.md) 참조.
|
|
89
|
-
- bulkInsert: 네이티브 bulk API 로 대량 삽입. tableName, 컬럼명→`ColumnMeta` 매핑, 레코드 배열을 넘김.
|
|
90
|
-
- executeDefs: `QueryDef[]` 를 dialect 별 query builder 로 SQL 변환 후 실행하고 `resultMetas` 로 결과 파싱. `resultMetas` 가 전부 null 이면 결과가 불필요한 것으로 보고 모든 def 를 하나의 SQL 로 합쳐 1회 실행, `defs.length` 만큼 빈 배열을 반환(인터페이스 계약 유지). 그 외엔 def 별 개별 실행.
|
|
90
|
+
`@simplysm/orm-common` 의 `DbContextExecutor` 를 Node 환경에서 구현한 클래스. `createOrm` 이 내부에서 생성·주입하므로 직접 다룰 일은 드묾. `DbContext` 를 `createOrm` 없이 손수 조립할 때만 사용. 생성자·메서드 전체 시그니처와 동작은 [db-conn.md](./db-conn.md) 의 동명 섹션 참조.
|