@simplysm/orm-node 13.0.96 → 13.0.97
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/package.json +4 -4
- package/README.md +0 -289
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/orm-node",
|
|
3
|
-
"version": "13.0.
|
|
3
|
+
"version": "13.0.97",
|
|
4
4
|
"description": "Simplysm package - ORM module (node)",
|
|
5
5
|
"author": "simplysm",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -20,13 +20,13 @@
|
|
|
20
20
|
"sideEffects": false,
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"consola": "^3.4.2",
|
|
23
|
-
"@simplysm/core-common": "13.0.
|
|
24
|
-
"@simplysm/orm-common": "13.0.
|
|
23
|
+
"@simplysm/core-common": "13.0.97",
|
|
24
|
+
"@simplysm/orm-common": "13.0.97"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/pg": "^8.18.0",
|
|
28
28
|
"@types/pg-copy-streams": "^1.2.5",
|
|
29
|
-
"mysql2": "^3.
|
|
29
|
+
"mysql2": "^3.20.0",
|
|
30
30
|
"pg": "^8.20.0",
|
|
31
31
|
"pg-copy-streams": "^7.0.0",
|
|
32
32
|
"tedious": "^19.2.1"
|
package/README.md
DELETED
|
@@ -1,289 +0,0 @@
|
|
|
1
|
-
# @simplysm/orm-node
|
|
2
|
-
|
|
3
|
-
Node.js용 ORM 모듈. MySQL, PostgreSQL, MSSQL(Azure 포함) 데이터베이스를 지원한다.
|
|
4
|
-
|
|
5
|
-
## 설치
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install @simplysm/orm-node
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
사용하는 DB에 따라 드라이버를 추가로 설치한다 (모두 optional peerDependency):
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
npm install mysql2 # MySQL
|
|
15
|
-
npm install pg pg-copy-streams # PostgreSQL
|
|
16
|
-
npm install tedious # MSSQL / Azure SQL
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
**의존성:** `@simplysm/core-common`, `@simplysm/orm-common`, `consola`
|
|
20
|
-
|
|
21
|
-
## 아키텍처 개요
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
createOrm() -- 최상위 팩토리 (ORM 인스턴스)
|
|
25
|
-
└─ NodeDbContextExecutor -- DbContextExecutor 구현체
|
|
26
|
-
└─ createDbConn() -- DB 연결 생성
|
|
27
|
-
└─ MysqlDbConn / PostgresqlDbConn / MssqlDbConn -- 실제 연결
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
- `createOrm` -- `@simplysm/orm-common`의 `DbContext`와 DB 연결을 결합하는 고수준 API
|
|
31
|
-
- `NodeDbContextExecutor` -- `QueryDef` -> SQL 변환 및 실행을 담당하는 어댑터
|
|
32
|
-
- `createDbConn` -- DB 연결 인스턴스를 생성하는 팩토리
|
|
33
|
-
- `MysqlDbConn` / `PostgresqlDbConn` / `MssqlDbConn` -- 각 DBMS별 실제 연결 구현
|
|
34
|
-
|
|
35
|
-
## 주요 사용법
|
|
36
|
-
|
|
37
|
-
### ORM 인스턴스 생성 및 트랜잭션
|
|
38
|
-
|
|
39
|
-
```typescript
|
|
40
|
-
import { createOrm } from "@simplysm/orm-node";
|
|
41
|
-
import { defineDbContext, Table } from "@simplysm/orm-common";
|
|
42
|
-
|
|
43
|
-
// 1. 테이블 및 DbContext 정의 (orm-common)
|
|
44
|
-
const User = Table("user")
|
|
45
|
-
.columns((c) => ({ id: c.int().autoIncrement(), name: c.varchar(100) }))
|
|
46
|
-
.primaryKey("id");
|
|
47
|
-
|
|
48
|
-
const Order = Table("order")
|
|
49
|
-
.columns((c) => ({ id: c.int().autoIncrement(), userId: c.int(), amount: c.decimal(10, 2) }))
|
|
50
|
-
.primaryKey("id");
|
|
51
|
-
|
|
52
|
-
const MyDb = defineDbContext({
|
|
53
|
-
tables: { user: User, order: Order },
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
// 2. ORM 인스턴스 생성
|
|
57
|
-
// database는 필수 -- config 또는 options 중 하나에 반드시 지정해야 한다.
|
|
58
|
-
const orm = createOrm(MyDb, {
|
|
59
|
-
dialect: "mysql",
|
|
60
|
-
host: "localhost",
|
|
61
|
-
port: 3306,
|
|
62
|
-
username: "root",
|
|
63
|
-
password: "password",
|
|
64
|
-
database: "mydb",
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
// 3-a. 자동 트랜잭션 (commit/rollback 자동 처리)
|
|
68
|
-
const result = await orm.connect(async (db) => {
|
|
69
|
-
const users = await db.user().execute();
|
|
70
|
-
await db.user().insert([{ name: "Alice" }]);
|
|
71
|
-
return users;
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
// 3-b. 트랜잭션 없이 실행
|
|
75
|
-
const users = await orm.connectWithoutTransaction(async (db) => {
|
|
76
|
-
return await db.user().execute();
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
// 3-c. 격리 수준 지정
|
|
80
|
-
await orm.connect(async (db) => {
|
|
81
|
-
/* ... */
|
|
82
|
-
}, "SERIALIZABLE");
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### OrmOptions로 database/schema 오버라이드
|
|
86
|
-
|
|
87
|
-
```typescript
|
|
88
|
-
const orm = createOrm(MyDb, config, {
|
|
89
|
-
database: "other_db", // config.database 대신 사용
|
|
90
|
-
schema: "custom_schema", // config.schema 대신 사용
|
|
91
|
-
});
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### 저수준 DB 연결
|
|
95
|
-
|
|
96
|
-
```typescript
|
|
97
|
-
import { createDbConn } from "@simplysm/orm-node";
|
|
98
|
-
|
|
99
|
-
// createDbConn은 연결 객체만 생성한다. connect()를 호출해야 실제 연결이 수립된다.
|
|
100
|
-
const conn = await createDbConn(config);
|
|
101
|
-
await conn.connect();
|
|
102
|
-
|
|
103
|
-
await conn.beginTransaction();
|
|
104
|
-
try {
|
|
105
|
-
const rows = await conn.execute(["SELECT * FROM users"]);
|
|
106
|
-
await conn.executeParametrized("INSERT INTO users (name) VALUES (?)", ["Alice"]);
|
|
107
|
-
await conn.commitTransaction();
|
|
108
|
-
} catch {
|
|
109
|
-
await conn.rollbackTransaction();
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
await conn.close();
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
### 벌크 인서트
|
|
116
|
-
|
|
117
|
-
각 DBMS의 네이티브 벌크 API를 사용하여 최적 성능을 제공한다.
|
|
118
|
-
|
|
119
|
-
```typescript
|
|
120
|
-
await conn.bulkInsert("users", columnMetas, records);
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
| DBMS | 방식 |
|
|
124
|
-
|------|------|
|
|
125
|
-
| MySQL | `LOAD DATA LOCAL INFILE` (임시 CSV 파일) |
|
|
126
|
-
| PostgreSQL | `COPY FROM STDIN` (스트림 기반 CSV) |
|
|
127
|
-
| MSSQL | tedious `BulkLoad` API (네이티브) |
|
|
128
|
-
|
|
129
|
-
## API 레퍼런스
|
|
130
|
-
|
|
131
|
-
### `createOrm(dbContextDef, config, options?): Orm`
|
|
132
|
-
|
|
133
|
-
ORM 인스턴스 팩토리. `defineDbContext`로 정의한 DbContext 정의와 연결 설정을 결합한다.
|
|
134
|
-
|
|
135
|
-
```typescript
|
|
136
|
-
function createOrm<TDef extends DbContextDef<any, any, any>>(
|
|
137
|
-
dbContextDef: TDef,
|
|
138
|
-
config: DbConnConfig,
|
|
139
|
-
options?: OrmOptions,
|
|
140
|
-
): Orm<TDef>;
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
`database`는 `options.database` -> `config.database` 순서로 결정되며, 둘 다 없으면 에러가 발생한다. `schema`도 같은 우선순위로 결정된다.
|
|
144
|
-
|
|
145
|
-
**`Orm<TDef>` 인터페이스:**
|
|
146
|
-
|
|
147
|
-
| 속성/메서드 | 타입 | 설명 |
|
|
148
|
-
|---|---|---|
|
|
149
|
-
| `dbContextDef` | `TDef` (readonly) | DbContext 정의 |
|
|
150
|
-
| `config` | `DbConnConfig` (readonly) | 연결 설정 |
|
|
151
|
-
| `options` | `OrmOptions` (readonly, optional) | 옵션 |
|
|
152
|
-
| `connect(callback, isolationLevel?)` | `Promise<R>` | 트랜잭션 내에서 콜백 실행 |
|
|
153
|
-
| `connectWithoutTransaction(callback)` | `Promise<R>` | 트랜잭션 없이 콜백 실행 |
|
|
154
|
-
|
|
155
|
-
**`OrmOptions` 인터페이스:**
|
|
156
|
-
|
|
157
|
-
| 필드 | 타입 | 설명 |
|
|
158
|
-
|---|---|---|
|
|
159
|
-
| `database?` | `string` | config.database 대신 사용할 DB 이름 |
|
|
160
|
-
| `schema?` | `string` | config.schema 대신 사용할 스키마 이름 |
|
|
161
|
-
|
|
162
|
-
### `createDbConn(config): Promise<DbConn>`
|
|
163
|
-
|
|
164
|
-
DB 연결 인스턴스를 생성하여 반환한다. 반환된 객체에 `connect()`를 호출해야 실제 연결이 수립된다. 드라이버 모듈은 호출 시 lazy import된다.
|
|
165
|
-
|
|
166
|
-
```typescript
|
|
167
|
-
function createDbConn(config: DbConnConfig): Promise<DbConn>;
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
### `DbConn` 인터페이스
|
|
171
|
-
|
|
172
|
-
모든 DB 연결 구현체의 공통 인터페이스. `EventEmitter<{ close: void }>`를 상속한다.
|
|
173
|
-
|
|
174
|
-
```typescript
|
|
175
|
-
interface DbConn extends EventEmitter<{ close: void }> {
|
|
176
|
-
config: DbConnConfig;
|
|
177
|
-
isConnected: boolean;
|
|
178
|
-
isInTransaction: boolean;
|
|
179
|
-
|
|
180
|
-
connect(): Promise<void>;
|
|
181
|
-
close(): Promise<void>;
|
|
182
|
-
beginTransaction(isolationLevel?: IsolationLevel): Promise<void>;
|
|
183
|
-
commitTransaction(): Promise<void>;
|
|
184
|
-
rollbackTransaction(): Promise<void>;
|
|
185
|
-
execute(queries: string[]): Promise<Record<string, unknown>[][]>;
|
|
186
|
-
executeParametrized(query: string, params?: unknown[]): Promise<Record<string, unknown>[][]>;
|
|
187
|
-
bulkInsert(
|
|
188
|
-
tableName: string,
|
|
189
|
-
columnMetas: Record<string, ColumnMeta>,
|
|
190
|
-
records: Record<string, unknown>[],
|
|
191
|
-
): Promise<void>;
|
|
192
|
-
}
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
### `DbConnConfig` 타입
|
|
196
|
-
|
|
197
|
-
`dialect` 필드로 분기되는 유니온 타입이다.
|
|
198
|
-
|
|
199
|
-
```typescript
|
|
200
|
-
type DbConnConfig = MysqlDbConnConfig | MssqlDbConnConfig | PostgresqlDbConnConfig;
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
**공통 필드:**
|
|
204
|
-
|
|
205
|
-
| 필드 | 타입 | 설명 |
|
|
206
|
-
|---|---|---|
|
|
207
|
-
| `dialect` | `"mysql"` \| `"mssql"` \| `"mssql-azure"` \| `"postgresql"` | DBMS 종류 |
|
|
208
|
-
| `host` | `string` | 호스트 |
|
|
209
|
-
| `port?` | `number` | 포트 |
|
|
210
|
-
| `username` | `string` | 사용자명 |
|
|
211
|
-
| `password` | `string` | 비밀번호 |
|
|
212
|
-
| `database?` | `string` | 데이터베이스명 |
|
|
213
|
-
| `defaultIsolationLevel?` | `IsolationLevel` | 기본 격리 수준 |
|
|
214
|
-
|
|
215
|
-
**MSSQL/PostgreSQL 전용:**
|
|
216
|
-
|
|
217
|
-
| 필드 | 타입 | 설명 |
|
|
218
|
-
|---|---|---|
|
|
219
|
-
| `schema?` | `string` | 스키마 (MSSQL 기본: `dbo`, PostgreSQL 기본: `public`) |
|
|
220
|
-
|
|
221
|
-
**MSSQL 특수 dialect:**
|
|
222
|
-
- `"mssql-azure"`: Azure SQL용. `encrypt: true`가 자동 적용됨.
|
|
223
|
-
|
|
224
|
-
### `NodeDbContextExecutor`
|
|
225
|
-
|
|
226
|
-
`@simplysm/orm-common`의 `DbContextExecutor` 인터페이스 구현체. `DbContext`가 내부적으로 사용한다.
|
|
227
|
-
|
|
228
|
-
```typescript
|
|
229
|
-
class NodeDbContextExecutor implements DbContextExecutor {
|
|
230
|
-
constructor(config: DbConnConfig);
|
|
231
|
-
|
|
232
|
-
connect(): Promise<void>;
|
|
233
|
-
close(): Promise<void>;
|
|
234
|
-
beginTransaction(isolationLevel?: IsolationLevel): Promise<void>;
|
|
235
|
-
commitTransaction(): Promise<void>;
|
|
236
|
-
rollbackTransaction(): Promise<void>;
|
|
237
|
-
executeParametrized(query: string, params?: unknown[]): Promise<Record<string, unknown>[][]>;
|
|
238
|
-
bulkInsert(tableName: string, columnMetas: Record<string, ColumnMeta>, records: DataRecord[]): Promise<void>;
|
|
239
|
-
executeDefs<T = DataRecord>(defs: QueryDef[], resultMetas?: (ResultMeta | undefined)[]): Promise<T[][]>;
|
|
240
|
-
}
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
**`executeDefs` 동작:**
|
|
244
|
-
- `QueryDef`를 dialect에 맞는 SQL로 변환 (`createQueryBuilder`)
|
|
245
|
-
- `resultMetas`가 모두 `undefined`이면 -> 결과 없는 쿼리로 판단하여 단일 배치 실행
|
|
246
|
-
- `ResultMeta`가 있으면 -> `parseQueryResult`로 타입 변환 적용
|
|
247
|
-
|
|
248
|
-
### DB 연결 구현 클래스
|
|
249
|
-
|
|
250
|
-
| 클래스 | 드라이버 | dialect |
|
|
251
|
-
|---|---|---|
|
|
252
|
-
| `MysqlDbConn` | `mysql2/promise` | `"mysql"` |
|
|
253
|
-
| `PostgresqlDbConn` | `pg` + `pg-copy-streams` | `"postgresql"` |
|
|
254
|
-
| `MssqlDbConn` | `tedious` | `"mssql"`, `"mssql-azure"` |
|
|
255
|
-
|
|
256
|
-
모두 `EventEmitter<{ close: void }>`를 상속하고 `DbConn`을 구현한다. 드라이버 모듈은 `createDbConn` 호출 시 lazy import된다.
|
|
257
|
-
|
|
258
|
-
**DBMS별 참고 사항:**
|
|
259
|
-
- MySQL: `username`이 `"root"`인 경우 특정 database에 바인딩하지 않고 연결한다 (관리 작업용).
|
|
260
|
-
- MySQL: `charset`은 `utf8mb4`로 고정, `multipleStatements`가 활성화되어 있다.
|
|
261
|
-
- PostgreSQL: 기본 포트 `5432`가 자동 적용된다.
|
|
262
|
-
- MSSQL: `trustServerCertificate: true`로 설정된다.
|
|
263
|
-
|
|
264
|
-
### `getDialectFromConfig(config): Dialect`
|
|
265
|
-
|
|
266
|
-
config에서 `Dialect`를 추출한다. `"mssql-azure"` -> `"mssql"`로 변환된다.
|
|
267
|
-
|
|
268
|
-
```typescript
|
|
269
|
-
function getDialectFromConfig(config: DbConnConfig): Dialect;
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
### 상수
|
|
273
|
-
|
|
274
|
-
| 상수 | 값 | 설명 |
|
|
275
|
-
|---|---|---|
|
|
276
|
-
| `DB_CONN_CONNECT_TIMEOUT` | 10초 (10,000ms) | 연결 타임아웃 |
|
|
277
|
-
| `DB_CONN_DEFAULT_TIMEOUT` | 10분 (600,000ms) | 쿼리 기본 타임아웃 |
|
|
278
|
-
| `DB_CONN_ERRORS.NOT_CONNECTED` | `"'Connection' is not connected."` | 미연결 에러 메시지 |
|
|
279
|
-
| `DB_CONN_ERRORS.ALREADY_CONNECTED` | `"'Connection' is already connected."` | 중복 연결 에러 메시지 |
|
|
280
|
-
|
|
281
|
-
연결 유휴 시 자동 종료: 마지막 쿼리 실행 후 `DB_CONN_DEFAULT_TIMEOUT * 2` (20분) 동안 활동이 없으면 연결이 자동으로 닫힌다.
|
|
282
|
-
|
|
283
|
-
### IsolationLevel 타입
|
|
284
|
-
|
|
285
|
-
`@simplysm/orm-common`에서 제공하는 트랜잭션 격리 수준이다. `isolationLevel`을 지정하지 않으면 `config.defaultIsolationLevel`이 사용되고, 이것도 없으면 `READ_UNCOMMITTED`가 기본값이다.
|
|
286
|
-
|
|
287
|
-
```typescript
|
|
288
|
-
type IsolationLevel = "READ_UNCOMMITTED" | "READ_COMMITTED" | "REPEATABLE_READ" | "SERIALIZABLE";
|
|
289
|
-
```
|