@simplysm/sd-claude 14.0.88 → 14.0.89
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 +17 -17
- package/claude/references/sd-simplysm14/apis/angular/README.md +27 -53
- package/claude/references/sd-simplysm14/apis/angular/controls.md +37 -105
- package/claude/references/sd-simplysm14/apis/angular/crud.md +46 -43
- package/claude/references/sd-simplysm14/apis/angular/directives.md +22 -32
- package/claude/references/sd-simplysm14/apis/angular/features.md +40 -55
- package/claude/references/sd-simplysm14/apis/angular/infra.md +40 -40
- package/claude/references/sd-simplysm14/apis/angular/layout.md +25 -53
- package/claude/references/sd-simplysm14/apis/angular/overlay.md +70 -82
- package/claude/references/sd-simplysm14/apis/angular/routing-appstructure.md +44 -39
- package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +21 -36
- package/claude/references/sd-simplysm14/apis/angular/shared-data.md +52 -65
- package/claude/references/sd-simplysm14/apis/angular/sheet.md +65 -70
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +33 -35
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +7 -7
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +29 -29
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +45 -50
- package/claude/references/sd-simplysm14/apis/core-browser/README.md +42 -55
- package/claude/references/sd-simplysm14/apis/core-browser/dom-element.md +62 -0
- package/claude/references/sd-simplysm14/apis/core-browser/indexed-db.md +13 -12
- package/claude/references/sd-simplysm14/apis/core-common/README.md +222 -98
- package/claude/references/sd-simplysm14/apis/core-common/array-ext.md +102 -53
- package/claude/references/sd-simplysm14/apis/core-common/async-runtime.md +128 -0
- package/claude/references/sd-simplysm14/apis/core-common/datetime.md +98 -64
- package/claude/references/sd-simplysm14/apis/core-common/errors.md +91 -0
- package/claude/references/sd-simplysm14/apis/core-common/json-transfer.md +34 -28
- package/claude/references/sd-simplysm14/apis/core-common/obj.md +104 -40
- package/claude/references/sd-simplysm14/apis/core-node/README.md +11 -8
- package/claude/references/sd-simplysm14/apis/core-node/consola.md +23 -31
- package/claude/references/sd-simplysm14/apis/core-node/cpx.md +33 -22
- package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +28 -25
- package/claude/references/sd-simplysm14/apis/core-node/fsx.md +39 -53
- package/claude/references/sd-simplysm14/apis/core-node/pathx.md +26 -29
- package/claude/references/sd-simplysm14/apis/core-node/worker.md +27 -29
- package/claude/references/sd-simplysm14/apis/excel/README.md +14 -14
- package/claude/references/sd-simplysm14/apis/lint/README.md +27 -21
- package/claude/references/sd-simplysm14/apis/lint/rules.md +89 -49
- package/claude/references/sd-simplysm14/apis/orm-common/README.md +5 -59
- package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +98 -67
- package/claude/references/sd-simplysm14/apis/orm-common/expr.md +107 -92
- package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +99 -65
- package/claude/references/sd-simplysm14/apis/orm-common/schema.md +83 -98
- package/claude/references/sd-simplysm14/apis/orm-common/types.md +62 -52
- package/claude/references/sd-simplysm14/apis/orm-node/README.md +62 -25
- package/claude/references/sd-simplysm14/apis/orm-node/db-conn.md +27 -27
- package/claude/references/sd-simplysm14/apis/sd-cli/README.md +12 -15
- package/claude/references/sd-simplysm14/apis/sd-cli/SdTsCompiler.md +92 -45
- package/claude/references/sd-simplysm14/apis/sd-cli/sd-config-types.md +226 -108
- package/claude/references/sd-simplysm14/apis/service-client/README.md +84 -86
- package/claude/references/sd-simplysm14/apis/service-client/orm.md +14 -11
- package/claude/references/sd-simplysm14/apis/service-client/transport.md +33 -10
- package/claude/references/sd-simplysm14/apis/service-common/README.md +37 -23
- package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +9 -9
- package/claude/references/sd-simplysm14/apis/service-common/protocol.md +13 -13
- package/claude/references/sd-simplysm14/apis/service-server/README.md +81 -65
- package/claude/references/sd-simplysm14/apis/service-server/service-authoring.md +32 -35
- package/claude/references/sd-simplysm14/apis/service-server/transport-internals.md +44 -33
- package/claude/references/sd-simplysm14/apis/service-server/v1-legacy.md +34 -45
- package/claude/references/sd-simplysm14/apis/storage/README.md +24 -18
- package/claude/skills/sd-demo/SKILL.md +6 -0
- package/claude/skills/sd-impl/SKILL.md +4 -7
- package/claude/skills/sd-spec/SKILL.md +31 -858
- package/claude/skills/sd-spec/references/spec-authoring.md +519 -0
- package/claude/workflows/sd-docs.js +84 -0
- package/package.json +1 -1
- package/claude/references/sd-simplysm14/apis/orm-common/query-builder.md +0 -29
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/.specs/inventory/spec.md +0 -99
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/package.json +0 -12
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/index.ts +0 -3
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/inbound/inbound.list.ts +0 -150
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/inventory/inventory-master.list.ts +0 -143
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/outbound/outbound.list.ts +0 -150
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/pnpm-workspace.yaml +0 -2
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/sd.config.ts +0 -12
- package/claude/skills/sd-demo/evals/golden.jsonl +0 -1
- package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/package.json +0 -8
- package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/src/.gitkeep +0 -0
- package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/tests/.gitkeep +0 -0
- package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/tsconfig.json +0 -10
- package/claude/skills/sd-dev/evals/golden.jsonl +0 -1
- package/claude/skills/sd-docs/SKILL.md +0 -46
- package/claude/skills/sd-docs/evals/fixtures/new-write/.claude/references/sd-simplysm14/README.md +0 -7
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/bar/package.json +0 -5
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/bar/src/index.ts +0 -3
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/baz/package.json +0 -6
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/baz/src/index.ts +0 -1
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/foo/package.json +0 -5
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/foo/src/index.ts +0 -8
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/.claude/references/sd-simplysm14/README.md +0 -7
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/.claude/references/sd-simplysm14/apis/foo/README.md +0 -3
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/bar/package.json +0 -5
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/bar/src/index.ts +0 -3
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/baz/package.json +0 -6
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/baz/src/index.ts +0 -1
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/foo/package.json +0 -5
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/foo/src/index.ts +0 -8
- package/claude/skills/sd-docs/evals/golden.jsonl +0 -2
- package/claude/skills/sd-impl/evals/fixtures/case-a-new-screen/.specs/260513120000_warehouse/spec.md +0 -101
- package/claude/skills/sd-impl/evals/fixtures/case-b-update-with-demo/.specs/260513120000_warehouse/spec.md +0 -101
- package/claude/skills/sd-impl/evals/fixtures/case-b-update-with-demo/packages/app/src/screens/box-register/box-register.view.ts +0 -46
- package/claude/skills/sd-impl/evals/fixtures/case-c-new-cross/.specs/260513120000_warehouse/spec.md +0 -89
- package/claude/skills/sd-impl/evals/fixtures/case-d-spec-modify/.specs/260513120000_warehouse/spec.md +0 -101
- package/claude/skills/sd-impl/evals/golden.jsonl +0 -4
- package/claude/skills/sd-manual/evals/fixtures/new-manual/src/notification.ts +0 -25
- package/claude/skills/sd-manual/evals/fixtures/update-manual/.claude/references/sd-simplysm14/manuals/notification.md +0 -14
- package/claude/skills/sd-manual/evals/fixtures/update-manual/src/notification.ts +0 -37
- package/claude/skills/sd-manual/evals/golden.jsonl +0 -2
- package/claude/skills/sd-review/evals/fixtures/code-review/src/foo.ts +0 -7
- package/claude/skills/sd-review/evals/fixtures/doc-review/docs/foo.md +0 -4
- package/claude/skills/sd-review/evals/golden.jsonl +0 -2
- package/claude/skills/sd-skill/evals/fixtures/existing-skill/.claude/skills/todo-format/SKILL.md +0 -14
- package/claude/skills/sd-skill/evals/fixtures/new-skill/.gitkeep +0 -0
- package/claude/skills/sd-skill/evals/golden.jsonl +0 -2
- package/claude/skills/sd-spec/evals/fixtures/case-a-split//355/232/214/354/235/230/353/241/235.md +0 -20
- package/claude/skills/sd-spec/evals/fixtures/case-b-detail/.specs/260513120000_warehouse/spec.md +0 -95
- package/claude/skills/sd-spec/evals/golden.jsonl +0 -2
- package/claude/skills/sd-unpack/evals/fixtures/eml-with-text-attachment/meeting.eml +0 -21
- package/claude/skills/sd-unpack/evals/fixtures/simple-eml/meeting.eml +0 -10
- package/claude/skills/sd-unpack/evals/golden.jsonl +0 -2
- package/claude/skills/sd-use/evals/fixtures/empty/.gitkeep +0 -0
- package/claude/skills/sd-use/evals/golden.jsonl +0 -6
- /package/claude/{skills/sd-docs/references/doc-rules.md → workflows/sd-docs.rules.md} +0 -0
|
@@ -1,67 +1,64 @@
|
|
|
1
1
|
# @simplysm/orm-common — 스키마 정의
|
|
2
2
|
|
|
3
|
-
DB 객체(Table/View/Procedure)와 그 구성요소(Column/Index/관계)를 fluent 빌더로 선언하는 묶음. 모든 빌더는 immutable — 각 메서드가 새 인스턴스를 반환한다. 정의한 빌더는 `DbContext`
|
|
3
|
+
DB 객체(Table/View/Procedure)와 그 구성요소(Column/Index/관계)를 fluent 빌더로 선언하는 묶음. 모든 빌더는 immutable — 각 메서드가 새 인스턴스를 반환한다. 정의한 빌더는 `DbContext` 안에서 `this.queryable()`/`this.executable()` 로 등록한다.
|
|
4
4
|
|
|
5
5
|
## Table / TableBuilder
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
`Table(name)` → `TableBuilder` 시작점. 체이닝으로 database·schema·columns·primaryKey·indexes·relations 를 붙인다.
|
|
8
8
|
|
|
9
|
-
- `Table<TName>(name: TName): TableBuilder` — 빈
|
|
10
|
-
- `
|
|
11
|
-
- `
|
|
12
|
-
- `
|
|
13
|
-
- `
|
|
14
|
-
- `
|
|
15
|
-
- `
|
|
16
|
-
- `
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
- `Table<TName>(name: TName): TableBuilder` — 이름만 가진 빈 빌더 생성. 이후 체이닝으로 정의를 쌓음.
|
|
10
|
+
- `description(desc: string)` — 테이블 설명. DDL 코멘트로 쓰임. 스키마 문서화·DB 코멘트가 필요할 때.
|
|
11
|
+
- `database(db: string)` — 소속 database 이름. dialect별 네임스페이스의 첫 분절. 멀티 DB 환경에서 필수.
|
|
12
|
+
- `schema(schema: string)` — schema 이름. MSSQL(dbo)·PostgreSQL(public) 에서만 의미. MySQL 은 무시.
|
|
13
|
+
- `columns(fn: (c) => Record<string, ColumnBuilder>)` — 컬럼 정의. `c` 는 `createColumnFactory()` 결과(int/varchar/... 타입 메서드). 타입 추론(`$inferSelect` 등)의 기준이 됨.
|
|
14
|
+
- `primaryKey(...columns)` — PK 컬럼 키. 여러 개 넘기면 복합 PK. CUD 의 output(pkColNames)·include 의 FK↔PK 매칭에 사용.
|
|
15
|
+
- `indexes(fn: (i) => IndexBuilder[])` — 인덱스 배열. `i` 는 `createIndexFactory()` 결과(`i.index(...cols)`). DDL `addIndex` 생성에 사용.
|
|
16
|
+
- `relations(fn: (r) => Record<string, 관계빌더>)` — FK/역참조 관계. `r` 는 Table 일 때 foreignKey/foreignKeyTarget/relationKey/relationKeyTarget 모두 제공. include() 자동 조인의 근거.
|
|
17
|
+
|
|
18
|
+
추론 전용 가상 프로퍼티(런타임 값 없음, 타입만): `$inferSelect`(컬럼+관계, 관계는 optional), `$inferColumns`(컬럼만), `$inferInsert`(autoIncrement/nullable/default 제외 시 필수), `$inferUpdate`(전부 optional).
|
|
19
19
|
|
|
20
20
|
```typescript
|
|
21
|
-
const
|
|
21
|
+
const Post = Table("Post")
|
|
22
22
|
.database("mydb")
|
|
23
23
|
.columns((c) => ({
|
|
24
24
|
id: c.bigint().autoIncrement(),
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
authorId: c.bigint(),
|
|
26
|
+
title: c.varchar(200),
|
|
27
|
+
content: c.text().nullable(),
|
|
27
28
|
}))
|
|
28
29
|
.primaryKey("id")
|
|
29
|
-
.indexes((i) => [i.index("
|
|
30
|
-
.relations((r) => ({
|
|
30
|
+
.indexes((i) => [i.index("authorId")])
|
|
31
|
+
.relations((r) => ({ author: r.foreignKey(["authorId"], () => User) }));
|
|
31
32
|
```
|
|
32
33
|
|
|
33
34
|
## View / ViewBuilder
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
`View(name)` → `ViewBuilder`. `query()` 로 SELECT Queryable 을 데이터 소스로 지정. View 는 컬럼 추론을 query 결과 타입(`TData`)에서 얻고, FK 는 등록하지 않으므로 관계는 relationKey 계열만 쓴다.
|
|
36
37
|
|
|
37
|
-
- `View(name: string): ViewBuilder` — 빈
|
|
38
|
-
- `
|
|
39
|
-
- `
|
|
40
|
-
- `
|
|
41
|
-
- `ViewBuilder.query(viewFn: (db) => Queryable)` — 뷰 본문 SELECT 정의. `db` 는 DbContext, 반환은 Queryable.
|
|
42
|
-
- `ViewBuilder.relations(fn: (r) => ...)` — 관계 정의(`relationKey`/`relationKeyTarget` 만).
|
|
43
|
-
- `ViewBuilder.meta` — `name`/`description`/`database`/`schema`/`viewFn`/`relations`.
|
|
44
|
-
- `$inferSelect` — 뷰 데이터 타입(타입 추론용).
|
|
38
|
+
- `View(name: string): ViewBuilder` — 빈 View 빌더.
|
|
39
|
+
- `description(desc)` / `database(db)` / `schema(schema)` — Table 과 동일 의미.
|
|
40
|
+
- `query<TViewData, TDb>(viewFn: (db: TDb) => Queryable<TViewData, any>)` — View 본문 SELECT. `db` 는 DbContext, 반환 Queryable 의 컬럼 구조가 View 컬럼이 됨. `queryable()` 등록 시 이 viewFn 을 실행해 컬럼 alias 를 재배치함.
|
|
41
|
+
- `relations(fn: (r) => ...)` — 관계 정의. View 의 `r` 은 relationKey/relationKeyTarget 만 제공(DB FK 미생성). 반환 타입에 관계가 합쳐짐(`TData & InferDeepRelations`).
|
|
45
42
|
|
|
46
43
|
```typescript
|
|
47
44
|
const ActiveUsers = View("ActiveUsers")
|
|
48
45
|
.database("mydb")
|
|
49
|
-
.query((db: MyDb) =>
|
|
46
|
+
.query((db: MyDb) =>
|
|
47
|
+
db.user()
|
|
48
|
+
.where((u) => [expr.eq(u.isActive, true)])
|
|
49
|
+
.select((u) => ({ id: u.id, name: u.name })),
|
|
50
|
+
);
|
|
50
51
|
```
|
|
51
52
|
|
|
52
53
|
## Procedure / ProcedureBuilder
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
`Procedure(name)` → `ProcedureBuilder`. 파라미터·반환 컬럼·본문 SQL 을 정의. `DbContext.executable()` 로 등록해 `Executable` 로 실행한다.
|
|
55
56
|
|
|
56
|
-
- `Procedure(name: string): ProcedureBuilder
|
|
57
|
-
- `
|
|
58
|
-
- `
|
|
59
|
-
- `
|
|
60
|
-
- `
|
|
61
|
-
- `ProcedureBuilder.returns(fn: (c) => Record<string, ColumnBuilder>)` — 반환 결과 column 정의.
|
|
62
|
-
- `ProcedureBuilder.body(sql: string)` — 본문 SQL. DBMS별 구문 차이 주의(MySQL: `param`, MSSQL: `@param`, PostgreSQL: `RETURN QUERY` 필요).
|
|
63
|
-
- `ProcedureBuilder.meta` — `name`/`description`/`database`/`schema`/`params`/`returns`/`query`.
|
|
64
|
-
- `$params` / `$returns` — 타입 추론용.
|
|
57
|
+
- `Procedure(name: string): ProcedureBuilder<never, never>` — 빈 프로시저 빌더.
|
|
58
|
+
- `description(desc)` / `database(db)` / `schema(schema)` — Table 과 동일 의미.
|
|
59
|
+
- `params(fn: (c) => Record<string, ColumnBuilder>)` — 입력 파라미터. `c` 는 컬럼 factory. dialect별 호출 구문 차이(MSSQL `@param`, MySQL/PG `param`) 주의.
|
|
60
|
+
- `returns(fn: (c) => ...)` — 반환 결과 컬럼. 결과 행 타입 추론에 사용.
|
|
61
|
+
- `body(sql: string)` — 본문 SQL(메타 키는 `query`). dialect별 구문 차이(MSSQL `@param`·`[User]`, PG `RETURN QUERY`) 주의.
|
|
65
62
|
|
|
66
63
|
```typescript
|
|
67
64
|
const GetUserById = Procedure("GetUserById")
|
|
@@ -73,49 +70,51 @@ const GetUserById = Procedure("GetUserById")
|
|
|
73
70
|
|
|
74
71
|
## ColumnBuilder / createColumnFactory
|
|
75
72
|
|
|
76
|
-
`
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
- `
|
|
81
|
-
- `
|
|
82
|
-
- `
|
|
83
|
-
- `
|
|
84
|
-
- `
|
|
85
|
-
- `
|
|
86
|
-
- `
|
|
87
|
-
- `
|
|
88
|
-
- `
|
|
89
|
-
- `
|
|
90
|
-
- `
|
|
91
|
-
- `
|
|
92
|
-
- `
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
-
|
|
98
|
-
-
|
|
99
|
-
- `
|
|
73
|
+
`createColumnFactory()` 가 타입별 컬럼 생성 메서드를 반환하고, 각 메서드의 결과 `ColumnBuilder` 에 수식자를 체이닝한다.
|
|
74
|
+
|
|
75
|
+
타입 메서드(전부 인자 없음, decimal/varchar/char 제외):
|
|
76
|
+
|
|
77
|
+
- `int()` — INT(4B, ±2^31). 일반 정수.
|
|
78
|
+
- `bigint()` — BIGINT(8B, ±2^63). ID·대용량 정수.
|
|
79
|
+
- `float()` — FLOAT(4B 단정밀도). 근사 실수.
|
|
80
|
+
- `double()` — DOUBLE(8B 배정밀도). 근사 실수 고정밀.
|
|
81
|
+
- `decimal(precision, scale?)` — DECIMAL 고정소수점. `precision`=전체 자릿수, `scale`=소수 자릿수. 금액 등 정확값.
|
|
82
|
+
- `varchar(length)` — 가변 길이 문자열. `length`=최대 길이.
|
|
83
|
+
- `char(length)` — 고정 길이 문자열. `length`=고정 길이. 코드값 등.
|
|
84
|
+
- `text()` — 대용량 텍스트(TEXT/LONGTEXT).
|
|
85
|
+
- `binary()` — 바이너리(MySQL LONGBLOB / MSSQL VARBINARY(MAX) / PG BYTEA). 값 타입 `Bytes`.
|
|
86
|
+
- `boolean()` — 불리언(MySQL TINYINT(1) / MSSQL BIT / PG BOOLEAN).
|
|
87
|
+
- `datetime()` — 날짜+시간(`DateTime`).
|
|
88
|
+
- `date()` — 날짜만(`DateOnly`).
|
|
89
|
+
- `time()` — 시간만(`Time`).
|
|
90
|
+
- `uuid()` — UUID(MySQL BINARY(16) / MSSQL UNIQUEIDENTIFIER / PG UUID). 값 타입 `Uuid`.
|
|
91
|
+
|
|
92
|
+
수식자(`ColumnBuilder` 메서드):
|
|
93
|
+
|
|
94
|
+
- `autoIncrement()` — 자동 증가. INSERT 추론에서 optional 처리, CUD output 의 aiColName 으로 식별. PK 자동키에.
|
|
95
|
+
- `nullable()` — NULL 허용. 값 타입에 `undefined` 추가, INSERT 추론에서 optional. "값 없음" 가능 컬럼에.
|
|
96
|
+
- `default(value)` — DDL 기본값. INSERT 추론에서 optional 처리. `"CURRENT_TIMESTAMP"` 같은 식 문자열도 허용.
|
|
97
|
+
- `description(desc)` — 컬럼 코멘트.
|
|
100
98
|
|
|
101
99
|
```typescript
|
|
102
100
|
.columns((c) => ({
|
|
103
101
|
id: c.bigint().autoIncrement(),
|
|
104
|
-
status: c.varchar(20).default("active"),
|
|
105
102
|
email: c.varchar(200).nullable(),
|
|
103
|
+
status: c.varchar(20).default("active"),
|
|
106
104
|
}))
|
|
107
105
|
```
|
|
108
106
|
|
|
107
|
+
추론 유틸 타입: `ColumnBuilderRecord`(컬럼 레코드), `InferColumns`(값 타입), `InferColumnExprs`(ExprInput 타입), `InferInsertColumns`/`InferUpdateColumns`/`RequiredInsertKeys`/`OptionalInsertKeys`(INSERT/UPDATE 추론), `DataToColumnBuilderRecord`(데이터→컬럼 변환, `insertInto` 대상 검증용).
|
|
108
|
+
|
|
109
109
|
## IndexBuilder / createIndexFactory
|
|
110
110
|
|
|
111
|
-
`
|
|
111
|
+
`createIndexFactory<TColumnKey>()` → `{ index(...columns) }`. 반환 `IndexBuilder` 에 수식자 체이닝.
|
|
112
112
|
|
|
113
|
-
- `
|
|
114
|
-
- `
|
|
115
|
-
- `
|
|
116
|
-
- `
|
|
117
|
-
- `
|
|
118
|
-
- `IndexBuilder.meta` — `columns`/`name?`/`unique?`/`orderBy?`/`description?`.
|
|
113
|
+
- `index(...columns): IndexBuilder` — 인덱스 컬럼 지정(복합 가능).
|
|
114
|
+
- `name(name)` — 인덱스 이름. 미지정 시 DDL 생성기가 자동 작명.
|
|
115
|
+
- `unique()` — 유니크 인덱스. 중복 방지 제약.
|
|
116
|
+
- `orderBy(...orderBy)` — 컬럼별 정렬 방향. 각 값 `"ASC"|"DESC"`, 컬럼 수와 개수 일치 필요. 정렬 최적화 인덱스에.
|
|
117
|
+
- `description(description)` — 인덱스 코멘트.
|
|
119
118
|
|
|
120
119
|
```typescript
|
|
121
120
|
.indexes((i) => [
|
|
@@ -124,39 +123,25 @@ modifier(생성된 ColumnBuilder 에 체이닝):
|
|
|
124
123
|
])
|
|
125
124
|
```
|
|
126
125
|
|
|
127
|
-
## 관계 빌더 (
|
|
128
|
-
|
|
129
|
-
Table 의 `relations()` 는 FK+RelationKey 둘 다, View 의 `relations()` 는 RelationKey 만 사용 가능.
|
|
126
|
+
## 관계 빌더 (foreignKey / foreignKeyTarget / relationKey / relationKeyTarget)
|
|
130
127
|
|
|
131
|
-
|
|
132
|
-
- `r.foreignKeyTarget(targetTableFn: () => Table, relationName: string, opts?: { single?: boolean; description? })` — 1:N 역참조(DB FK 생성 측의 반대편). `relationName` 은 대상 테이블에 정의된 FK 관계 이름. `single:true` 면 단일 객체(1:1), 기본은 배열. → `ForeignKeyTargetBuilder`.
|
|
133
|
-
- `r.relationKey(columns, targetFn, opts?)` — N:1 논리 관계(DB FK **미생성**). View 에서도 사용. → `RelationKeyBuilder`.
|
|
134
|
-
- `r.relationKeyTarget(targetTableFn, relationName, opts?: { single?; description? })` — 1:N 논리 역참조(DB FK 미생성). `single:true` → 단일. → `RelationKeyTargetBuilder`.
|
|
128
|
+
`createRelationFactory(ownerFn)` 가 owner 종류에 따라 다른 factory 를 반환: Table 이면 FK 4종 전부, View 이면 relationKey 계열 2종만. `relations()` 콜백의 `r` 가 이 factory. 대상 테이블은 순환 참조 방지를 위해 `() => Table` 지연 함수로 전달.
|
|
135
129
|
|
|
136
|
-
|
|
137
|
-
- `
|
|
138
|
-
- `
|
|
139
|
-
|
|
140
|
-
> 주의: `description`/`single` 은 메서드 체이닝(`.description()`)이 아니라 factory 의 `opts` 인자로 전달한다(순환 참조 TS7022 회피).
|
|
130
|
+
- `r.foreignKey(columns, () => Target, opts?)` — N:1 FK 관계(DB FK 제약 생성). `columns`=현재 테이블의 FK 컬럼들. `opts.description`=관계 설명. include 시 단일 객체로 로드. → `ForeignKeyBuilder`.
|
|
131
|
+
- `r.foreignKeyTarget(() => Target, relationName, opts?)` — 1:N 역참조(DB FK 미생성, 상대 FK 를 역으로 봄). `relationName`=상대 테이블의 FK 관계 이름. `opts.single:true`=1:1 단일 객체로 로드(미지정/false 면 배열). `opts.description`=설명. → `ForeignKeyTargetBuilder`.
|
|
132
|
+
- `r.relationKey(columns, () => Target, opts?)` — N:1 논리 관계(DB FK 미생성). foreignKey 와 동일하나 제약 없음. View 에서도 사용 가능. → `RelationKeyBuilder`.
|
|
133
|
+
- `r.relationKeyTarget(() => Target, relationName, opts?)` — 1:N 논리 역참조(DB FK 미생성). foreignKeyTarget 과 동일. `opts.single`/`opts.description` 동일. View 에서도 사용 가능. → `RelationKeyTargetBuilder`.
|
|
141
134
|
|
|
142
135
|
```typescript
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
136
|
+
// 자식 테이블: N:1
|
|
137
|
+
.relations((r) => ({ author: r.foreignKey(["authorId"], () => User, { description: "작성자" }) }))
|
|
138
|
+
// 부모 테이블: 1:N 역참조 + 1:1 단일
|
|
139
|
+
.relations((r) => ({
|
|
140
|
+
posts: r.foreignKeyTarget(() => Post, "author"),
|
|
141
|
+
profile: r.foreignKeyTarget(() => Profile, "user", { single: true }),
|
|
142
|
+
}))
|
|
147
143
|
```
|
|
148
144
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
빌더에서 export 되는 추론 헬퍼·레코드 타입(직접 타입 작성 시):
|
|
145
|
+
빌더 클래스(메타만 보관, 메서드 없음): `ForeignKeyBuilder`/`ForeignKeyTargetBuilder`/`RelationKeyBuilder`/`RelationKeyTargetBuilder`. 추론 타입: `RelationBuilderRecord`, `InferDeepRelations`(관계를 optional 로, 같은 테이블 재방문 시 순환 절단), `ExtractRelationTarget`/`ExtractRelationTargetResult`.
|
|
152
146
|
|
|
153
|
-
|
|
154
|
-
- `InferColumns<TBuilders>` — column 레코드 → 값 타입 객체.
|
|
155
|
-
- `InferColumnExprs<TBuilders>` — column 레코드 → `ExprInput` 입력 타입 객체(프로시저 params).
|
|
156
|
-
- `InferInsertColumns<TBuilders>` — INSERT 타입(필수/optional 분리).
|
|
157
|
-
- `InferUpdateColumns<TBuilders>` — UPDATE 타입(전부 Partial).
|
|
158
|
-
- `RequiredInsertKeys` / `OptionalInsertKeys` — INSERT 필수/선택 key 추출.
|
|
159
|
-
- `DataToColumnBuilderRecord<TData>` — 데이터 레코드 → column 빌더 레코드(insertInto 타입 매칭용).
|
|
160
|
-
- `RelationBuilderRecord` — 4개 관계 빌더 union 의 레코드.
|
|
161
|
-
- `InferDeepRelations<TRelations, TVisited?>` — 관계 정의 → 심층 관계 타입(전부 optional, 동일 테이블 재방문 시 순환 차단).
|
|
162
|
-
- `ExtractRelationTarget` / `ExtractRelationTargetResult` — 단일(N:1)/배열·단일(1:N) 대상 타입 추출.
|
|
147
|
+
> 주의: description/single 은 반드시 factory `opts` 인자로 전달한다. `.description()`·`.single()` 메서드 체이닝은 TS 순환 참조(TS7022) 때문에 제거되어 존재하지 않는다.
|
|
@@ -1,52 +1,62 @@
|
|
|
1
|
-
# @simplysm/orm-common —
|
|
2
|
-
|
|
3
|
-
executor
|
|
4
|
-
|
|
5
|
-
## Column
|
|
6
|
-
|
|
7
|
-
- `type DataType` — SQL
|
|
8
|
-
- `type ColumnPrimitiveMap` — TS 타입
|
|
9
|
-
- `type ColumnPrimitiveStr` — 위 키(`"string"
|
|
10
|
-
- `type ColumnPrimitive` —
|
|
11
|
-
- `const dataTypeStrToColumnPrimitiveStr` — SQL
|
|
12
|
-
- `type InferColumnPrimitiveFromDataType<T>` —
|
|
13
|
-
- `inferColumnPrimitiveStr(value): ColumnPrimitiveStr` — 런타임 값에서 타입명 추론. NULL 이면 throw(추론 불가).
|
|
14
|
-
- `interface ColumnMeta` —
|
|
15
|
-
|
|
16
|
-
## Database
|
|
17
|
-
|
|
18
|
-
- `type Dialect = "mysql" | "mssql" | "postgresql"` — 지원
|
|
19
|
-
- `const dialects: Dialect[]` —
|
|
20
|
-
- `type IsolationLevel` —
|
|
21
|
-
- `type DataRecord` — 재귀 결과
|
|
22
|
-
- `interface
|
|
23
|
-
- `interface ResultMeta` — 결과 변환 메타: `columns
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
- `type
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
`
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
- `
|
|
1
|
+
# @simplysm/orm-common — 타입·실행 엔진 내부
|
|
2
|
+
|
|
3
|
+
executor·어댑터를 구현하거나 QueryDef/Expr AST·결과 메타를 직접 다루고, QueryDef 를 dialect SQL 로 렌더링하거나 raw 결과를 TS 객체로 환원할 때 참조하는 묶음. 일반 쿼리 작성에서는 expr/Queryable 가 이 타입들을 가려주므로 직접 쓸 일이 적다.
|
|
4
|
+
|
|
5
|
+
## Column 타입
|
|
6
|
+
|
|
7
|
+
- `type 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"}`. cast/DDL 에서 사용.
|
|
8
|
+
- `type ColumnPrimitiveMap` — TS 타입 이름→실제 타입(`string`/`number`/`boolean`/`DateTime`/`DateOnly`/`Time`/`Uuid`/`Bytes`).
|
|
9
|
+
- `type ColumnPrimitiveStr` — 위 맵의 키(`"string"` 등). ExprUnit.dataType 의 타입.
|
|
10
|
+
- `type ColumnPrimitive` — 저장 가능한 모든 원시값 `| undefined`(undefined=NULL).
|
|
11
|
+
- `const dataTypeStrToColumnPrimitiveStr` — SQL 타입명→TS 타입명 매핑 객체(`int→"number"`, `datetime→"DateTime"` 등).
|
|
12
|
+
- `type InferColumnPrimitiveFromDataType<T>` — DataType 에서 TS 타입 추론(cast 결과 타입).
|
|
13
|
+
- `function inferColumnPrimitiveStr(value): ColumnPrimitiveStr` — 런타임 값에서 타입명 추론. NULL 이면 throw(추론 불가).
|
|
14
|
+
- `interface ColumnMeta` — 컬럼 메타: `type`(ColumnPrimitiveStr), `dataType`, `autoIncrement?`, `nullable?`, `default?`, `description?`.
|
|
15
|
+
|
|
16
|
+
## Database 타입
|
|
17
|
+
|
|
18
|
+
- `type Dialect = "mysql" | "mssql" | "postgresql"` — 지원 DBMS.
|
|
19
|
+
- `const dialects: Dialect[]` — 전 dialect 목록(테스트 `it.each` 등에).
|
|
20
|
+
- `type IsolationLevel` — `"READ_UNCOMMITTED"|"READ_COMMITTED"|"REPEATABLE_READ"|"SERIALIZABLE"`. 트랜잭션 격리(엄격도 순).
|
|
21
|
+
- `type DataRecord` — 재귀 결과 행 타입(`{ [k]: ColumnPrimitive | DataRecord | DataRecord[] }`). include 중첩 표현.
|
|
22
|
+
- `interface QueryBuildResult` — QueryBuilder.build() 반환: `sql`(렌더된 SQL), `resultSetIndex?`(가져올 결과셋 인덱스, 기본 0), `resultSetStride?`(N번째마다 추출, MySQL 배치 INSERT 의 SELECT 만 모을 때).
|
|
23
|
+
- `interface ResultMeta` — 결과 변환 메타: `columns`(컬럼키→ColumnPrimitiveStr), `joins`(조인키→`{isSingle}`). `parseQueryResult` 입력.
|
|
24
|
+
|
|
25
|
+
## Executor / Migration 인터페이스
|
|
26
|
+
|
|
27
|
+
- `interface DbContextExecutor` — DB 연결·실행 계약(orm-node 등이 구현). `connect()`/`close()`/`beginTransaction(isolationLevel?)`/`commitTransaction()`/`rollbackTransaction()`/`executeDefs<T>(defs, resultMetas?): Promise<T[][]>`. 새 DB 어댑터 작성 시 이 면을 채움.
|
|
28
|
+
- `interface Migration` — `{ name; up(db) }` ([db-context.md](./db-context.md) 참조).
|
|
29
|
+
|
|
30
|
+
## QueryDef AST
|
|
31
|
+
|
|
32
|
+
`type QueryDef` 는 DML+DDL+Utils+Meta 의 union. executor 의 `executeDefs` 가 받고 QueryBuilder 가 SQL 로 변환.
|
|
33
|
+
|
|
34
|
+
- 공통: `interface QueryDefObjectName` — `{ database?; schema?; name }`(dialect별 네임스페이스: MySQL `db.name`, MSSQL `db.schema.name`, PG `schema.name`). `interface CudOutputDef` — `{ columns; pkColNames; aiColName? }`(CUD OUTPUT).
|
|
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.
|
|
39
|
+
|
|
40
|
+
## Expr AST
|
|
41
|
+
|
|
42
|
+
- `type Expr` — 값/문자열/숫자/날짜/조건/집계/window 표현식의 전체 union.
|
|
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` 디스크리미네이터 + 피연산자 필드를 가진 평범한 데이터 객체.
|
|
47
|
+
|
|
48
|
+
## dialect QueryBuilder (SQL 렌더러)
|
|
49
|
+
|
|
50
|
+
QueryDef → SQL 문자열 변환. executor 구현체가 사용.
|
|
51
|
+
|
|
52
|
+
- `createQueryBuilder(dialect: Dialect): QueryBuilderBase` — dialect 에 맞는 빌더 인스턴스 생성(mysql→Mysql, mssql→Mssql, postgresql→Postgresql).
|
|
53
|
+
- `abstract class QueryBuilderBase` — 렌더링 기반. `build(def): QueryBuildResult` 가 `def.type` 이름의 메서드로 동적 dispatch(미지원 타입이면 throw). 공통 절 렌더링(WHERE/ORDER BY/GROUP BY/HAVING/JOIN/FROM)은 구현, dialect 차이는 abstract(select/insert/... DML, 각 DDL, tableName/renderJoin). LATERAL/CROSS APPLY 필요 감지(`needsLateral`), 재귀 self 조인 감지(`isRecursiveSelfJoin`) 보조.
|
|
54
|
+
- `class MysqlQueryBuilder` / `class MssqlQueryBuilder` / `class PostgresqlQueryBuilder` — `QueryBuilderBase` 의 dialect 구현체.
|
|
55
|
+
- `abstract class ExprRendererBase` — `Expr`/`WhereExpr` 노드를 SQL 조각으로 렌더링하는 추상 기반. `class MysqlExprRenderer`/`class MssqlExprRenderer`/`class PostgresqlExprRenderer` 가 dialect 구현. QueryBuilder 내부에서 식별자 wrap·표현식 변환에 사용.
|
|
56
|
+
|
|
57
|
+
## 결과 파싱 유틸
|
|
58
|
+
|
|
59
|
+
executor 가 DB raw 결과를 TS 객체로 환원할 때 사용. 일반 사용자는 직접 호출하지 않음.
|
|
60
|
+
|
|
61
|
+
- `parseQueryResult<T>(rawResults, meta: ResultMeta): Promise<T[] | undefined>` — flat raw 행 배열을 `meta.columns`(키→타입)로 타입 변환하고 `meta.joins`(키→`{isSingle}`)로 중첩 그룹핑. 입력이 비었거나 파싱 후 전부 빈 객체면 undefined. async 전용(100행마다 이벤트 루프 양보). `isSingle:true` 관계에 서로 다른 다건이 매칭되면 throw.
|
|
62
|
+
- `pickResultSets<T>(rawResults: T[][], buildResult): T[]` — 다중 결과셋 추출. `resultSetIndex` 없으면 첫 셋, `resultSetStride` 없으면 해당 인덱스 셋, 있으면 인덱스부터 stride 간격으로 concat(MySQL 배치 INSERT 의 SELECT 결과만 모을 때).
|
|
@@ -1,53 +1,90 @@
|
|
|
1
1
|
# @simplysm/orm-node
|
|
2
2
|
|
|
3
|
-
Node.js 환경에서 `@simplysm/orm-common` 의 `DbContext` 를
|
|
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`
|
|
8
|
-
-
|
|
7
|
+
- **createOrm / Orm / OrmOptions** — `DbContext` 서브클래스로 ORM 인스턴스를 만들고 트랜잭션 단위로 query 를 돌릴 때. (이 README 아래 "ORM 진입" 군)
|
|
8
|
+
- **NodeDbContextExecutor** — `DbContext` 에 직접 주입할 executor 를 손수 만들 때(보통 `createOrm` 이 내부에서 처리하므로 직접 쓸 일은 드묾). (이 README 아래 "ORM 진입" 군)
|
|
9
|
+
- **createDbConn / DbConn / 설정 타입 / DB_CONN_\* / getDialectFromConfig** — ORM 없이 raw SQL·bulk insert·트랜잭션을 직접 다루거나 dialect 별 연결을 손수 제어할 때. 자세히: [db-conn.md](./db-conn.md)
|
|
9
10
|
|
|
10
|
-
## ORM
|
|
11
|
+
## ORM 진입
|
|
11
12
|
|
|
12
|
-
`DbContext` 서브클래스와
|
|
13
|
+
`DbContext` 서브클래스와 연결 설정을 받아 트랜잭션 경계를 관리하는 고수준 진입. query DSL 자체는 `@simplysm/orm-common` 의 `DbContext` 가 제공하고, 이 군은 그 컨텍스트를 실제 연결에 묶는 역할.
|
|
13
14
|
|
|
14
15
|
### createOrm
|
|
15
16
|
|
|
16
17
|
```typescript
|
|
17
|
-
createOrm<T extends DbContext>(
|
|
18
|
+
function createOrm<T extends DbContext>(
|
|
18
19
|
DbClass: new (executor: DbContextExecutor, opt: { database: string; schema?: string }) => T,
|
|
19
20
|
config: DbConnConfig,
|
|
20
21
|
options?: OrmOptions,
|
|
21
22
|
): Orm<T>
|
|
22
23
|
```
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
- `config: DbConnConfig` — DB 접속 정보. `dialect` 로 DBMS 분기. 상세 필드는 db-conn.md.
|
|
26
|
-
- `options?: OrmOptions` — `config` 의 `database`/`schema` 보다 **우선** 적용(값이 있을 때만 덮어씀). 같은 `config` 로 DB/스키마만 바꿔 붙일 때 사용.
|
|
27
|
-
- 반환 `Orm<T>` — 아래 필드·메서드를 가진 객체.
|
|
25
|
+
`DbContext` 서브클래스를 받아 `Orm<T>` 를 반환. 인스턴스는 메서드 호출마다 새로 만들어지므로 `Orm` 객체는 재사용 가능.
|
|
28
26
|
|
|
29
|
-
`
|
|
27
|
+
- DbClass: `DbContext` 를 상속한 생성자. `executor`(연결 실행자)와 `{ database, schema? }` 를 받는 시그니처 고정. query 진입점(`this.queryable(Entity)`)을 정의한 사용자 DB 클래스를 넘김.
|
|
28
|
+
- config: `DbConnConfig`(dialect 별 분기 유니온, [db-conn.md](./db-conn.md) 참조). 접속 대상·인증 정보.
|
|
29
|
+
- options?: `OrmOptions`. config 의 `database`/`schema` 를 덮어쓰는 우선 옵션. 같은 접속 정보로 DB·스키마만 바꿔 쓸 때.
|
|
30
|
+
|
|
31
|
+
database 해석: `options.database` → `config.database` 순으로 찾고, 둘 다 없거나 빈 문자열이면 `"database는 필수입니다"` throw. schema 도 `options.schema` → `config.schema` 순.
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
class MyDb extends DbContext {
|
|
35
|
+
user = this.queryable(User);
|
|
36
|
+
}
|
|
37
|
+
const orm = createOrm(MyDb, { dialect: "mysql", host: "localhost", port: 3306, username: "root", password: "pw", database: "mydb" });
|
|
38
|
+
await orm.connect(async (db) => db.user().execute()); // 트랜잭션 안
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Orm
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
interface Orm<T extends DbContext> {
|
|
45
|
+
readonly DbClass; readonly config: DbConnConfig; readonly options?: OrmOptions;
|
|
46
|
+
connect<R>(callback: (conn: T) => Promise<R>, isolationLevel?: IsolationLevel): Promise<R>;
|
|
47
|
+
connectWithoutTransaction<R>(callback: (conn: T) => Promise<R>): Promise<R>;
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`createOrm` 반환 타입. 매 호출마다 DB 인스턴스를 새로 만들어 연결→콜백→정리.
|
|
52
|
+
|
|
53
|
+
- connect: 콜백을 **트랜잭션 안에서** 실행. 콜백 정상 종료 시 커밋, throw 시 롤백.
|
|
54
|
+
- isolationLevel?: `"READ_UNCOMMITTED" | "READ_COMMITTED" | "REPEATABLE_READ" | "SERIALIZABLE"`(`@simplysm/orm-common`). 트랜잭션 격리 수준. 미지정 시 연결의 `defaultIsolationLevel`, 그것도 없으면 `READ_UNCOMMITTED`. 더티 리드를 막아야 하면 `READ_COMMITTED` 이상.
|
|
55
|
+
- connectWithoutTransaction: 콜백을 **트랜잭션 없이** 실행. 콜백 내부에서 `db.transaction(...)` 으로 부분 트랜잭션을 직접 열 때 사용(examples 테스트 패턴).
|
|
56
|
+
- callback: 연결된 DbContext 인스턴스(`T`)를 받아 query 를 수행하고 임의 값 `R` 을 반환. 그 반환값이 `connect`/`connectWithoutTransaction` 의 결과가 됨.
|
|
30
57
|
|
|
31
58
|
### OrmOptions
|
|
32
59
|
|
|
33
|
-
|
|
34
|
-
|
|
60
|
+
```typescript
|
|
61
|
+
interface OrmOptions { database?: string; schema?: string; }
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`createOrm` 3번째 인자. config 보다 우선 적용.
|
|
35
65
|
|
|
36
|
-
|
|
66
|
+
- database?: 사용할 DB 이름. config 의 `database` 대신 쓸 때. 다중 테넌트처럼 접속 정보는 같고 DB 만 다를 때.
|
|
67
|
+
- schema?: 스키마 이름(예: MSSQL `dbo`, PostgreSQL `public`). MySQL 은 스키마 개념이 없어 보통 미지정.
|
|
37
68
|
|
|
38
|
-
|
|
39
|
-
- `config` (readonly) — 생성에 쓰인 `DbConnConfig` 그대로 노출.
|
|
40
|
-
- `options?` (readonly) — 생성에 쓰인 `OrmOptions` 그대로 노출.
|
|
41
|
-
- `connect<R>(callback: (conn: T) => Promise<R>, isolationLevel?: IsolationLevel): Promise<R>` — 새 `DbContext` 를 만들어 **트랜잭션 안에서** 콜백 실행하고 콜백 반환값을 그대로 반환. `isolationLevel` 로 격리수준 지정(미지정 시 연결설정의 기본 격리수준). 커밋·롤백·연결 종료는 `DbContext.connect` 가 관리.
|
|
42
|
-
- `connectWithoutTransaction<R>(callback: (conn: T) => Promise<R>): Promise<R>` — **트랜잭션 없이** 연결만 열고 콜백 실행. DDL 처럼 트랜잭션 밖에서 돌려야 하거나 콜백 내부에서 `db.transaction(...)` 을 직접 제어할 때 사용.
|
|
69
|
+
### NodeDbContextExecutor
|
|
43
70
|
|
|
44
|
-
|
|
71
|
+
`DbContextExecutor`(`@simplysm/orm-common`) 의 Node 구현체. `createOrm` 이 내부에서 생성·주입하므로 직접 다룰 일은 드묾. `DbContext` 를 `createOrm` 없이 손수 조립할 때만 사용.
|
|
45
72
|
|
|
46
73
|
```typescript
|
|
47
|
-
class
|
|
48
|
-
|
|
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[][]>;
|
|
49
82
|
}
|
|
50
|
-
const orm = createOrm(MyDb, { dialect: "mysql", host: "localhost", username: "root", password: "pw", database: "mydb" });
|
|
51
|
-
const users = await orm.connect(async (db) => db.user().execute(), "READ_COMMITTED");
|
|
52
|
-
await orm.connectWithoutTransaction(async (db) => db.transaction(async () => { /* ... */ }));
|
|
53
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 별 개별 실행.
|