@simplysm/sd-claude 14.0.87 → 14.0.88
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 -18
- package/claude/references/sd-simplysm14/apis/angular/README.md +61 -0
- package/claude/references/sd-simplysm14/apis/angular/controls.md +119 -0
- package/claude/references/sd-simplysm14/apis/angular/crud.md +50 -0
- package/claude/references/sd-simplysm14/apis/angular/directives.md +44 -0
- package/claude/references/sd-simplysm14/apis/angular/features.md +55 -0
- package/claude/references/sd-simplysm14/apis/angular/infra.md +74 -0
- package/claude/references/sd-simplysm14/apis/angular/layout.md +55 -0
- package/claude/references/sd-simplysm14/apis/angular/overlay.md +115 -0
- package/claude/references/sd-simplysm14/apis/angular/routing-appstructure.md +64 -0
- package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +43 -0
- package/claude/references/sd-simplysm14/apis/angular/shared-data.md +70 -0
- package/claude/references/sd-simplysm14/apis/angular/sheet.md +78 -0
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +80 -0
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +66 -0
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +71 -0
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +67 -0
- package/claude/references/sd-simplysm14/apis/core-browser/README.md +83 -0
- package/claude/references/sd-simplysm14/apis/core-browser/indexed-db.md +79 -0
- package/claude/references/sd-simplysm14/apis/core-common/README.md +138 -0
- package/claude/references/sd-simplysm14/apis/core-common/array-ext.md +72 -0
- package/claude/references/sd-simplysm14/apis/core-common/datetime.md +95 -0
- package/claude/references/sd-simplysm14/apis/core-common/json-transfer.md +47 -0
- package/claude/references/sd-simplysm14/apis/core-common/obj.md +53 -0
- package/claude/references/sd-simplysm14/apis/core-node/README.md +14 -0
- package/claude/references/sd-simplysm14/apis/core-node/consola.md +51 -0
- package/claude/references/sd-simplysm14/apis/core-node/cpx.md +39 -0
- package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +38 -0
- package/claude/references/sd-simplysm14/apis/core-node/fsx.md +86 -0
- package/claude/references/sd-simplysm14/apis/core-node/pathx.md +42 -0
- package/claude/references/sd-simplysm14/apis/core-node/worker.md +54 -0
- package/claude/references/sd-simplysm14/apis/excel/README.md +43 -0
- package/claude/references/sd-simplysm14/apis/excel/cell.md +54 -0
- package/claude/references/sd-simplysm14/apis/excel/conditional-format.md +51 -0
- package/claude/references/sd-simplysm14/apis/excel/style.md +67 -0
- package/claude/references/sd-simplysm14/apis/excel/utils.md +35 -0
- package/claude/references/sd-simplysm14/apis/excel/workbook-worksheet.md +97 -0
- package/claude/references/sd-simplysm14/apis/excel/wrapper.md +83 -0
- package/claude/references/sd-simplysm14/apis/lint/README.md +43 -0
- package/claude/references/sd-simplysm14/apis/lint/rules.md +90 -0
- package/claude/references/sd-simplysm14/apis/orm-common/README.md +67 -0
- package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +80 -0
- package/claude/references/sd-simplysm14/apis/orm-common/expr.md +113 -0
- package/claude/references/sd-simplysm14/apis/orm-common/query-builder.md +29 -0
- package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +111 -0
- package/claude/references/sd-simplysm14/apis/orm-common/schema.md +162 -0
- package/claude/references/sd-simplysm14/apis/orm-common/types.md +52 -0
- package/claude/references/sd-simplysm14/apis/orm-node/README.md +53 -0
- package/claude/references/sd-simplysm14/apis/orm-node/db-conn.md +94 -0
- package/claude/references/sd-simplysm14/apis/sd-cli/README.md +29 -0
- package/claude/references/sd-simplysm14/apis/sd-cli/SdTsCompiler.md +70 -0
- package/claude/references/sd-simplysm14/apis/sd-cli/sd-config-types.md +173 -0
- package/claude/references/sd-simplysm14/apis/service-client/README.md +152 -0
- package/claude/references/sd-simplysm14/apis/service-client/orm.md +45 -0
- package/claude/references/sd-simplysm14/apis/service-client/transport.md +36 -0
- package/claude/references/sd-simplysm14/apis/service-common/README.md +70 -0
- package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +48 -0
- package/claude/references/sd-simplysm14/apis/service-common/protocol.md +72 -0
- package/claude/references/sd-simplysm14/apis/service-server/README.md +102 -0
- package/claude/references/sd-simplysm14/apis/service-server/service-authoring.md +74 -0
- package/claude/references/sd-simplysm14/apis/service-server/transport-internals.md +51 -0
- package/claude/references/sd-simplysm14/apis/service-server/v1-legacy.md +50 -0
- package/claude/references/sd-simplysm14/apis/storage/README.md +114 -0
- package/claude/skills/sd-docs/SKILL.md +17 -29
- package/claude/skills/sd-docs/references/{subagent-prompt.md → doc-rules.md} +25 -40
- package/package.json +1 -1
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# @simplysm/orm-common — QueryBuilder (dialect SQL 렌더러)
|
|
2
|
+
|
|
3
|
+
`QueryDef` AST 를 각 DBMS SQL 문자열로 변환하는 클래스군. executor 구현체(`@simplysm/orm-node` 등)가 사용하며, 일반 쿼리 작성에선 직접 다루지 않는다.
|
|
4
|
+
|
|
5
|
+
## 팩토리
|
|
6
|
+
|
|
7
|
+
- `createQueryBuilder(dialect: Dialect): QueryBuilderBase` — dialect 에 맞는 QueryBuilder 인스턴스 생성. `dialect` 가 `"mysql"|"mssql"|"postgresql"` 중 하나에 따라 아래 구현체 반환.
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
const builder = createQueryBuilder("mysql");
|
|
11
|
+
const { sql } = builder.build(queryDef);
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## QueryBuilder 클래스
|
|
15
|
+
|
|
16
|
+
- `abstract class QueryBuilderBase` — QueryDef → SQL 추상 기반.
|
|
17
|
+
- `build(def: QueryDef): QueryBuildResult` — `def.type` 과 동일 이름 메서드로 동적 dispatch 하여 SQL 렌더. 알 수 없는 타입이면 throw. dialect 공통 로직만 구현하고 차이나는 부분은 abstract(하위 클래스 구현).
|
|
18
|
+
- `class MysqlQueryBuilder extends QueryBuilderBase` — MySQL 렌더러.
|
|
19
|
+
- `class MssqlQueryBuilder extends QueryBuilderBase` — MSSQL 렌더러(TOP, IDENTITY_INSERT, OUTPUT 등).
|
|
20
|
+
- `class PostgresqlQueryBuilder extends QueryBuilderBase` — PostgreSQL 렌더러.
|
|
21
|
+
|
|
22
|
+
## ExprRenderer 클래스
|
|
23
|
+
|
|
24
|
+
`QueryBuilder` 내부에서 `Expr`/`WhereExpr` AST 를 SQL 식 문자열로 렌더.
|
|
25
|
+
|
|
26
|
+
- `abstract class ExprRendererBase` — 표현식 렌더 추상 기반. `render(expr)`/`renderWhere(wheres)` 를 dispatch, dialect 차이(함수명·NULL 안전 비교·날짜 함수 등)는 abstract.
|
|
27
|
+
- `class MysqlExprRenderer extends ExprRendererBase` — MySQL 표현식 렌더러(`<=>` 등).
|
|
28
|
+
- `class MssqlExprRenderer extends ExprRendererBase` — MSSQL 표현식 렌더러.
|
|
29
|
+
- `class PostgresqlExprRenderer extends ExprRendererBase` — PostgreSQL 표현식 렌더러.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# @simplysm/orm-common — Queryable (쿼리 작성)
|
|
2
|
+
|
|
3
|
+
`db.user()` 등 등록된 팩토리 호출로 받는 체이닝 쿼리 빌더. 옵션·필터·조인을 immutable 체이닝으로 쌓은 뒤 종결 메서드로 실행한다. 콜백 인자 `columns`/`u` 등은 `QueryableRecord`(column → `ExprUnit` 프록시)이며, 표현식은 [expr.md](./expr.md) 로 만든다.
|
|
4
|
+
|
|
5
|
+
`Queryable<TData, TFrom>` — `TData` 결과 데이터 타입, `TFrom` 소스 TableBuilder(CUD 연산은 TableBuilder 기반에서만 가능, View/서브쿼리는 `never`).
|
|
6
|
+
|
|
7
|
+
## 옵션 (SELECT 컬럼 / DISTINCT / LOCK)
|
|
8
|
+
|
|
9
|
+
- `select(fn: (cols) => R): Queryable<...>` — SELECT column 재지정. `fn` 은 원본 column 프록시를 받아 `{별칭: ExprUnit | 리터럴 | 중첩객체}` 반환. CUD 소스성 상실(`TFrom=never`).
|
|
10
|
+
- `distinct(): Queryable` — DISTINCT 적용. 이후 `count()` 직접 호출 불가(`wrap()` 필요).
|
|
11
|
+
- `lock(): Queryable` — FOR UPDATE 행 잠금. 트랜잭션 내 배타 잠금이 필요할 때.
|
|
12
|
+
|
|
13
|
+
## 행 제한 (TOP / LIMIT)
|
|
14
|
+
|
|
15
|
+
- `top(count: number): Queryable` — 상위 N행. ORDER BY 없이도 사용 가능.
|
|
16
|
+
- `limit(skip: number, take: number): Queryable` — 페이지네이션(OFFSET `skip`, LIMIT `take`). **ORDER BY 선행 필수**(없으면 throw).
|
|
17
|
+
|
|
18
|
+
## 정렬 (ORDER BY)
|
|
19
|
+
|
|
20
|
+
- `orderBy(fnOrKey, orderBy?: "ASC"|"DESC"): Queryable` — 정렬 조건 추가(여러 번 호출 시 순서대로 누적).
|
|
21
|
+
- `fnOrKey` — 정렬 column 을 반환하는 함수 `(cols) => ExprUnit`, 또는 체인 경로 문자열(`"id"`, `"user.name"` — `obj.getChainValue` 로 해석. 동적 정렬 루프용).
|
|
22
|
+
- `orderBy` — 방향. 기본 ASC.
|
|
23
|
+
|
|
24
|
+
## 검색 (WHERE / search)
|
|
25
|
+
|
|
26
|
+
- `where(predicate: (cols) => WhereExprUnit[]): Queryable` — WHERE 조건 추가. 배열 내부는 AND, 여러 번 호출도 AND 누적. 조건은 `expr.eq` 등으로 생성.
|
|
27
|
+
- `search(fn: (cols) => ExprUnit<string|undefined>[], searchText: string): Queryable` — 다중 column 텍스트 검색. `fn` 은 검색 대상 column 들, `searchText` 는 검색 문법 문자열(공백=OR, `+`=필수, `-`=제외, `"..."`=구문, `*`=와일드카드). 빈 문자열이면 변화 없이 self 반환. 내부적으로 `lower(col) LIKE pattern` 조합을 AND/OR 로 조립. (문법 상세: README 검색 파서)
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
db.user().where((u) => [expr.eq(u.isActive, true)]).search((u) => [u.name, u.email], "John -withdrawn");
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 그룹 (GROUP BY / HAVING)
|
|
34
|
+
|
|
35
|
+
- `groupBy(fn: (cols) => ExprUnit[]): Queryable` — GROUP BY. 이후 `count()` 직접 호출 불가(`wrap()` 필요).
|
|
36
|
+
- `having(predicate: (cols) => WhereExprUnit[]): Queryable` — 그룹 필터(GROUP BY 이후). AND 누적.
|
|
37
|
+
|
|
38
|
+
## 조인 (JOIN / JOIN SINGLE / INCLUDE)
|
|
39
|
+
|
|
40
|
+
- `join<A, R>(as: A, fn: (qr, cols) => Queryable<R>): Queryable<TData & { [as]?: R[] }>` — 1:N LEFT JOIN, 결과에 **배열**로 추가. `qr` 는 `JoinQueryable`(`.from(table)`/`.select(cols)`/`.union(...)`), `cols` 는 바깥 column. 조인 조건은 반환 Queryable 의 `where` 로.
|
|
41
|
+
- `joinSingle<A, R>(as, fn): Queryable<... & { [as]?: R }>` — N:1/1:1 LEFT JOIN, 결과에 **단일 객체**로 추가.
|
|
42
|
+
- `include(fn: (item) => PathProxy): Queryable` — TableBuilder 의 FK/FKT 관계를 자동 조인. `fn` 은 타입 안전 경로 프록시(`item.user.company` 처럼 관계 필드만 접근 가능, ColumnPrimitive 필드는 접근 불가). 다단계·중복 include 지원. 관계 미정의 시 throw, View 기반 queryable 에선 사용 불가.
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
db.post().include((p) => p.user.company);
|
|
46
|
+
db.user().join("posts", (qr, u) => qr.from(Post).where((p) => [expr.eq(p.userId, u.id)]));
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 서브쿼리 / UNION / 재귀
|
|
50
|
+
|
|
51
|
+
- `wrap(): Queryable<TData, never>` — 현재 쿼리를 서브쿼리로 래핑. `distinct()`/`groupBy()` 후 `count()` 하려면 필수.
|
|
52
|
+
- `static Queryable.union<TData>(...queries): Queryable<TData, never>` — 여러 Queryable UNION(중복 제거). 최소 2개, 미만 시 throw. (`JoinQueryable.union` 도 동일 의미)
|
|
53
|
+
- `recursive(fn: (qr: RecursiveQueryable) => Queryable): Queryable<TData, never>` — 재귀 CTE(WITH RECURSIVE). 계층 데이터 조회. `qr.from(table)`/`qr.select(cols)`/`qr.union(...)` 로 재귀 본문 정의, 재귀 측은 `self` 프로퍼티로 base 를 자기 참조.
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
const count = await db.user().select((u) => ({ name: u.name })).distinct().wrap().count();
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 종결 — SELECT 실행
|
|
60
|
+
|
|
61
|
+
- `execute(): Promise<TData[]>` — SELECT 실행, 결과 배열.
|
|
62
|
+
- `single(): Promise<TData | undefined>` — 단일 결과. 2건 이상이면 throw.
|
|
63
|
+
- `first(): Promise<TData | undefined>` — 첫 결과(내부적으로 `top(1)`).
|
|
64
|
+
- `count(fn?: (cols) => ExprUnit): Promise<number>` — 행 수. `fn` 지정 시 해당 column 카운트. `distinct()`/`groupBy()` 직후 호출 시 throw(`wrap()` 먼저).
|
|
65
|
+
- `exists(): Promise<boolean>` — 조건 충족 행 존재 여부(`top(1)` 후 길이 검사).
|
|
66
|
+
- `getSelectQueryDef(): SelectQueryDef` / `getResultMeta(outputColumns?): ResultMeta` — 실행용 def·결과 메타 생성(executor·서브쿼리 합성에서 사용).
|
|
67
|
+
|
|
68
|
+
## 종결 — INSERT
|
|
69
|
+
|
|
70
|
+
각 INSERT 는 `outputColumns` 미전달 시 `void`, 전달 시 해당 column 만 뽑은 레코드를 반환(반환 자동증가 PK 수신 등).
|
|
71
|
+
- `insert(records: TFrom["$inferInsert"][], outputColumns?): Promise<void | Pick<...>[]>` — 다건 INSERT. MSSQL 1000행 제한 때문에 1000건씩 청크 분할. AI column 에 명시값 있으면 자동 overrideIdentity.
|
|
72
|
+
- `insertIfNotExists(record, outputColumns?): Promise<void | Pick<...>>` — 현재 WHERE 조건 매칭이 없을 때만 INSERT.
|
|
73
|
+
- `insertInto(targetTable, outputColumns?): Promise<void | Pick<...>[]>` — 현재 SELECT 결과를 다른 테이블에 INSERT INTO ... SELECT. `targetTable` column 구조가 현재 데이터와 호환되어야 함(타입 매칭).
|
|
74
|
+
- `getInsertQueryDef` / `getInsertIfNotExistsQueryDef` / `getInsertIntoQueryDef` — 각 def 생성기.
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
const [inserted] = await db.user().insert([{ name: "Hong" }], ["id"]);
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## 종결 — UPDATE / DELETE
|
|
81
|
+
|
|
82
|
+
- `update(recordFwd: (cols) => QueryableWriteRecord, outputColumns?): Promise<void | Pick<...>[]>` — UPDATE. `recordFwd` 는 column → 갱신값(`ExprInput`) 매핑 반환. 기존 값 참조 가능(`expr.mul(p.price, ...)`). WHERE 는 미리 체이닝.
|
|
83
|
+
- `delete(outputColumns?): Promise<void | Pick<...>[]>` — DELETE. WHERE 미리 체이닝.
|
|
84
|
+
- `getUpdateQueryDef` / `getDeleteQueryDef` — def 생성기.
|
|
85
|
+
|
|
86
|
+
## 종결 — UPSERT
|
|
87
|
+
|
|
88
|
+
- `upsert(updateFn, insertFn?, outputColumns?): Promise<void | Pick<...>[]>` — WHERE 매칭 있으면 UPDATE, 없으면 INSERT.
|
|
89
|
+
- `updateFn: (cols) => QueryableWriteRecord` — 갱신/삽입 공통값(insertFn 생략 시 INSERT 도 이 값 사용).
|
|
90
|
+
- `insertFn?: (updateRecord) => QueryableWriteRecord` — INSERT 전용값(update 결과를 받아 변형). UPDATE/INSERT 데이터가 다를 때.
|
|
91
|
+
- `outputColumns?` — 반환 column.
|
|
92
|
+
- `getUpsertQueryDef(...)` — def 생성기.
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
await db.user()
|
|
96
|
+
.where((u) => [expr.eq(u.email, "t@t.com")])
|
|
97
|
+
.upsert(() => ({ name: expr.val("string", "x"), email: expr.val("string", "t@t.com") }));
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## DDL Helper / 기타
|
|
101
|
+
|
|
102
|
+
- `switchFk(enabled: boolean): Promise<void>` — 이 테이블 FK 제약 활성/비활성(트랜잭션 내 가능). TableBuilder/ViewBuilder 기반에서만.
|
|
103
|
+
- `queryable(db, tableOrView, as?): () => Queryable` — Table/View 용 Queryable 팩토리 함수(보통 `DbContext.queryable()` 가 호출). `as` 미지정 시 자동 alias.
|
|
104
|
+
- `getMatchedPrimaryKeys(fkCols, targetTable): string[]` — FK column 배열과 대상 PK 매칭(개수 불일치 시 throw). include 내부 헬퍼.
|
|
105
|
+
|
|
106
|
+
## 관련 타입
|
|
107
|
+
|
|
108
|
+
- `QueryableRecord<TData>` — column → `ExprUnit` 프록시 레코드(콜백 인자 타입).
|
|
109
|
+
- `QueryableWriteRecord<TData>` — column → `ExprInput`(쓰기 콜백 반환 타입).
|
|
110
|
+
- `UnwrapQueryableRecord<R>` — `select` 결과 `ExprUnit` 언래핑 → 데이터 타입.
|
|
111
|
+
- `PathProxy<TObject>` — `include` 경로 수집용 타입 안전 프록시(관계 필드만 노출).
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# @simplysm/orm-common — 스키마 정의
|
|
2
|
+
|
|
3
|
+
DB 객체(Table/View/Procedure)와 그 구성요소(Column/Index/관계)를 fluent 빌더로 선언하는 묶음. 모든 빌더는 immutable — 각 메서드가 새 인스턴스를 반환한다. 정의한 빌더는 `DbContext` 의 `queryable()`/`executable()` 로 등록한다.
|
|
4
|
+
|
|
5
|
+
## Table / TableBuilder
|
|
6
|
+
|
|
7
|
+
테이블 정의 빌더. `Table(name)` 으로 시작해 메서드 체이닝.
|
|
8
|
+
|
|
9
|
+
- `Table<TName>(name: TName): TableBuilder` — 빈 테이블 빌더 생성.
|
|
10
|
+
- `TableBuilder.description(desc: string)` — 테이블 설명. DDL Comment 로 사용.
|
|
11
|
+
- `TableBuilder.database(db: string)` — 소속 database 이름.
|
|
12
|
+
- `TableBuilder.schema(schema: string)` — schema 이름(MSSQL=dbo, PostgreSQL=public). MySQL 은 무시.
|
|
13
|
+
- `TableBuilder.columns(fn: (c) => Record<string, ColumnBuilder>)` — column 정의. `c` 는 column factory(아래 ColumnBuilder factory). 타입 추론의 핵심.
|
|
14
|
+
- `TableBuilder.primaryKey(...columns: string[])` — PK column 지정. 여러 개 전달 시 복합 PK.
|
|
15
|
+
- `TableBuilder.indexes(fn: (i) => IndexBuilder[])` — index 정의. `i` 는 index factory.
|
|
16
|
+
- `TableBuilder.relations(fn: (r) => Record<string, RelationBuilder>)` — FK/역참조 관계 정의. `r` 은 relation factory(FK + RelationKey 모두 사용 가능).
|
|
17
|
+
- `TableBuilder.meta` — 위 설정이 담긴 메타(`name`/`description`/`database`/`schema`/`columns`/`primaryKey`/`relations`/`indexes`). 런타임에서 읽음.
|
|
18
|
+
- 타입 추론 프로퍼티(값은 없고 타입만): `$inferSelect`(column+관계 전체), `$inferColumns`(column 만), `$inferInsert`(autoIncrement/nullable/default 는 optional), `$inferUpdate`(전부 optional).
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
const User = Table("User")
|
|
22
|
+
.database("mydb")
|
|
23
|
+
.columns((c) => ({
|
|
24
|
+
id: c.bigint().autoIncrement(),
|
|
25
|
+
name: c.varchar(100),
|
|
26
|
+
email: c.varchar(200).nullable(),
|
|
27
|
+
}))
|
|
28
|
+
.primaryKey("id")
|
|
29
|
+
.indexes((i) => [i.index("email").unique()])
|
|
30
|
+
.relations((r) => ({ posts: r.foreignKeyTarget(() => Post, "author") }));
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## View / ViewBuilder
|
|
34
|
+
|
|
35
|
+
뷰 정의 빌더. SELECT Queryable 로 데이터 소스를 정의. 관계는 RelationKey 만 가능(DB FK 미생성).
|
|
36
|
+
|
|
37
|
+
- `View(name: string): ViewBuilder` — 빈 뷰 빌더 생성.
|
|
38
|
+
- `ViewBuilder.description(desc: string)` — 뷰 설명(DDL Comment).
|
|
39
|
+
- `ViewBuilder.database(db: string)` — 소속 database 이름.
|
|
40
|
+
- `ViewBuilder.schema(schema: string)` — schema 이름(MSSQL/PostgreSQL).
|
|
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` — 뷰 데이터 타입(타입 추론용).
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
const ActiveUsers = View("ActiveUsers")
|
|
48
|
+
.database("mydb")
|
|
49
|
+
.query((db: MyDb) => db.user().where((u) => [expr.eq(u.status, "active")]));
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Procedure / ProcedureBuilder
|
|
53
|
+
|
|
54
|
+
저장 프로시저 정의 빌더. `DbContext.executable()` 로 등록해 `Executable` 로 실행.
|
|
55
|
+
|
|
56
|
+
- `Procedure(name: string): ProcedureBuilder` — 빈 프로시저 빌더 생성.
|
|
57
|
+
- `ProcedureBuilder.description(desc: string)` — 설명(DDL Comment).
|
|
58
|
+
- `ProcedureBuilder.database(db: string)` — 소속 database.
|
|
59
|
+
- `ProcedureBuilder.schema(schema: string)` — schema 이름.
|
|
60
|
+
- `ProcedureBuilder.params(fn: (c) => Record<string, ColumnBuilder>)` — 입력 파라미터 정의(column factory 사용).
|
|
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` — 타입 추론용.
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
const GetUserById = Procedure("GetUserById")
|
|
68
|
+
.database("mydb")
|
|
69
|
+
.params((c) => ({ userId: c.bigint() }))
|
|
70
|
+
.returns((c) => ({ id: c.bigint(), name: c.varchar(100) }))
|
|
71
|
+
.body("SELECT id, name FROM User WHERE id = userId");
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## ColumnBuilder / createColumnFactory
|
|
75
|
+
|
|
76
|
+
`columns()`/`params()`/`returns()` 콜백의 `c` 로 받는 factory. 타입별 메서드로 column 을 만든 뒤 modifier 체이닝.
|
|
77
|
+
|
|
78
|
+
factory 타입 메서드:
|
|
79
|
+
- `c.int()` — INT(4바이트). 값 타입 `number`.
|
|
80
|
+
- `c.bigint()` — BIGINT(8바이트). 값 타입 `number`(bigint 아님).
|
|
81
|
+
- `c.float()` — FLOAT(4바이트 단정밀도). `number`.
|
|
82
|
+
- `c.double()` — DOUBLE(8바이트 배정밀도). `number`.
|
|
83
|
+
- `c.decimal(precision, scale?)` — DECIMAL 고정소수점. `precision` 전체 자릿수, `scale` 소수 자릿수(선택). `number`.
|
|
84
|
+
- `c.varchar(length)` — VARCHAR(가변). `length` 최대 길이. `string`.
|
|
85
|
+
- `c.char(length)` — CHAR(고정). `string`.
|
|
86
|
+
- `c.text()` — TEXT 대용량. `string`.
|
|
87
|
+
- `c.binary()` — 바이너리(MySQL=LONGBLOB, MSSQL=VARBINARY(MAX), PostgreSQL=BYTEA). `Bytes`.
|
|
88
|
+
- `c.boolean()` — BOOLEAN(MySQL=TINYINT(1), MSSQL=BIT, PostgreSQL=BOOLEAN). `boolean`.
|
|
89
|
+
- `c.datetime()` — DATETIME(날짜+시간). `DateTime`.
|
|
90
|
+
- `c.date()` — DATE(날짜만). `DateOnly`.
|
|
91
|
+
- `c.time()` — TIME(시간만). `Time`.
|
|
92
|
+
- `c.uuid()` — UUID(MySQL=BINARY(16), MSSQL=UNIQUEIDENTIFIER, PostgreSQL=UUID). `Uuid`.
|
|
93
|
+
|
|
94
|
+
modifier(생성된 ColumnBuilder 에 체이닝):
|
|
95
|
+
- `.autoIncrement()` — 자동 증가. INSERT 타입에서 optional 처리. (PK 식별 시 OUTPUT 의 aiColName 으로도 사용)
|
|
96
|
+
- `.nullable()` — NULL 허용. 값 타입에 `undefined` 추가, INSERT 타입에서 optional.
|
|
97
|
+
- `.default(value)` — INSERT 시 미지정 기본값. INSERT 타입에서 optional. (예: `"CURRENT_TIMESTAMP"`)
|
|
98
|
+
- `.description(desc)` — column 설명(DDL Comment).
|
|
99
|
+
- `ColumnBuilder.meta` — `ColumnMeta`(`type`/`dataType`/`autoIncrement?`/`nullable?`/`default?`/`description?`).
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
.columns((c) => ({
|
|
103
|
+
id: c.bigint().autoIncrement(),
|
|
104
|
+
status: c.varchar(20).default("active"),
|
|
105
|
+
email: c.varchar(200).nullable(),
|
|
106
|
+
}))
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## IndexBuilder / createIndexFactory
|
|
110
|
+
|
|
111
|
+
`indexes()` 콜백의 `i` factory.
|
|
112
|
+
|
|
113
|
+
- `i.index(...columns: string[]): IndexBuilder` — index 생성. 여러 column 전달 시 복합 index.
|
|
114
|
+
- `IndexBuilder.name(name)` — index 이름 지정(미지정 시 자동).
|
|
115
|
+
- `IndexBuilder.unique()` — 유니크 index.
|
|
116
|
+
- `IndexBuilder.orderBy(...orderBy: ("ASC"|"DESC")[])` — column 별 정렬 방향. column 수와 인자 수 일치 필요.
|
|
117
|
+
- `IndexBuilder.description(description)` — index 설명(DDL Comment).
|
|
118
|
+
- `IndexBuilder.meta` — `columns`/`name?`/`unique?`/`orderBy?`/`description?`.
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
.indexes((i) => [
|
|
122
|
+
i.index("email").unique(),
|
|
123
|
+
i.index("status", "createdAt").orderBy("ASC", "DESC"),
|
|
124
|
+
])
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## 관계 빌더 (relations 콜백의 r factory)
|
|
128
|
+
|
|
129
|
+
Table 의 `relations()` 는 FK+RelationKey 둘 다, View 의 `relations()` 는 RelationKey 만 사용 가능.
|
|
130
|
+
|
|
131
|
+
- `r.foreignKey(columns: string[], targetFn: () => Table, opts?: { description? })` — N:1 FK(DB FK 제약 생성). `columns` 는 owner 의 FK column, `targetFn` 은 지연 평가 대상 테이블. → `ForeignKeyBuilder`.
|
|
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`.
|
|
135
|
+
|
|
136
|
+
각 관계 빌더의 `meta`:
|
|
137
|
+
- `ForeignKeyBuilder.meta` / `RelationKeyBuilder.meta` — `ownerFn`/`columns`/`targetFn`/`description?`.
|
|
138
|
+
- `ForeignKeyTargetBuilder.meta` / `RelationKeyTargetBuilder.meta` — `targetTableFn`/`relationName`/`description?`/`isSingle?`.
|
|
139
|
+
|
|
140
|
+
> 주의: `description`/`single` 은 메서드 체이닝(`.description()`)이 아니라 factory 의 `opts` 인자로 전달한다(순환 참조 TS7022 회피).
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
const Post = Table("Post")
|
|
144
|
+
.columns((c) => ({ id: c.bigint().autoIncrement(), authorId: c.bigint() }))
|
|
145
|
+
.primaryKey("id")
|
|
146
|
+
.relations((r) => ({ author: r.foreignKey(["authorId"], () => User, { description: "작성자" }) }));
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## 타입 추론 유틸 / 레코드 타입
|
|
150
|
+
|
|
151
|
+
빌더에서 export 되는 추론 헬퍼·레코드 타입(직접 타입 작성 시):
|
|
152
|
+
|
|
153
|
+
- `ColumnBuilderRecord` — `Record<string, ColumnBuilder>`. `columns()` 반환 타입.
|
|
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) 대상 타입 추출.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# @simplysm/orm-common — QueryDef / Expr / Column 타입
|
|
2
|
+
|
|
3
|
+
executor·QueryBuilder 를 직접 구현하거나 AST·결과 메타를 다룰 때 참조하는 저수준 타입군. 일반 쿼리 작성에선 직접 쓸 일이 적다.
|
|
4
|
+
|
|
5
|
+
## Column / DataType 타입
|
|
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"}`.
|
|
8
|
+
- `type ColumnPrimitiveMap` — TS 타입 이름 → 실제 타입: `string`/`number`/`boolean`/`DateTime`/`DateOnly`/`Time`/`Uuid`/`Bytes`.
|
|
9
|
+
- `type ColumnPrimitiveStr` — 위 키(`"string"|"number"|...`).
|
|
10
|
+
- `type ColumnPrimitive` — 모든 원시 값 union + `undefined`(NULL 표현).
|
|
11
|
+
- `const dataTypeStrToColumnPrimitiveStr` — SQL 타입명 → TS 타입명 매핑 객체(`int`→`"number"`, `datetime`→`"DateTime"` 등).
|
|
12
|
+
- `type InferColumnPrimitiveFromDataType<T>` — `DataType` → TS 타입 추론(`cast` 결과 타입).
|
|
13
|
+
- `inferColumnPrimitiveStr(value): ColumnPrimitiveStr` — 런타임 값에서 타입명 추론. NULL 이면 throw(추론 불가).
|
|
14
|
+
- `interface ColumnMeta` — column 메타: `type: ColumnPrimitiveStr`/`dataType: DataType`/`autoIncrement?`/`nullable?`/`default?`/`description?`.
|
|
15
|
+
|
|
16
|
+
## Database / Executor / 결과 타입
|
|
17
|
+
|
|
18
|
+
- `type Dialect = "mysql" | "mssql" | "postgresql"` — 지원 dialect.
|
|
19
|
+
- `const dialects: Dialect[]` — 전체 dialect 목록(dialect별 테스트 루프용).
|
|
20
|
+
- `type IsolationLevel` — 격리 수준: `"READ_UNCOMMITTED"`(dirty read 허용)/`"READ_COMMITTED"`(기본, 커밋된 것만)/`"REPEATABLE_READ"`(반복 읽기 일관)/`"SERIALIZABLE"`(완전 직렬화·가장 엄격).
|
|
21
|
+
- `type DataRecord` — 재귀 결과 레코드(`ColumnPrimitive | DataRecord | DataRecord[]`). include 중첩 표현.
|
|
22
|
+
- `interface DbContextExecutor` — DB I/O 주입 인터페이스: `connect()`/`close()`/`beginTransaction(isolationLevel?)`/`commitTransaction()`/`rollbackTransaction()`/`executeDefs(defs, resultMetas?)`.
|
|
23
|
+
- `interface ResultMeta` — 결과 변환 메타: `columns: Record<string, ColumnPrimitiveStr>`(키→타입)/`joins: Record<string, {isSingle}>`(조인 alias→단일/배열). `parseQueryResult` 입력.
|
|
24
|
+
- `interface QueryBuildResult` — `QueryBuilder.build()` 반환: `sql: string`/`resultSetIndex?`(가져올 결과셋, 기본 0)/`resultSetStride?`(N번째마다 추출, MySQL 배치 INSERT 용).
|
|
25
|
+
- `interface Migration` — `name: string`/`up: (db) => Promise<void>`.
|
|
26
|
+
|
|
27
|
+
## Expr AST 타입
|
|
28
|
+
|
|
29
|
+
`type Expr` — 전체 표현식 union. `type WhereExpr` — WHERE 전용 union(비교+논리). 각 멤버는 `type` 판별자 + 인자 필드를 가진 인터페이스. 모두 `type` 리터럴로 구분되며, 사용자는 `expr.*` 빌더로 생성하므로 직접 만들 일은 거의 없음.
|
|
30
|
+
|
|
31
|
+
- 값: `ExprColumn`(`path: string[]`) / `ExprValue`(`value`) / `ExprRaw`(`sql`/`params`).
|
|
32
|
+
- 비교(WhereExpr): `ExprEq`/`ExprGt`/`ExprLt`/`ExprGte`/`ExprLte`(각 `source`/`target`), `ExprBetween`(`source`/`from?`/`to?`), `ExprIsNull`(`arg`), `ExprLike`/`ExprRegexp`(`source`/`pattern`), `ExprIn`(`source`/`values`), `ExprInQuery`(`source`/`query`), `ExprExists`(`query`).
|
|
33
|
+
- 논리(WhereExpr): `ExprNot`(`arg`), `ExprAnd`/`ExprOr`(`conditions`).
|
|
34
|
+
- 문자열: `ExprConcat`/`ExprLeft`/`ExprRight`/`ExprTrim`/`ExprPadStart`/`ExprReplace`/`ExprUpper`/`ExprLower`/`ExprLength`/`ExprByteLength`/`ExprSubstring`/`ExprIndexOf`.
|
|
35
|
+
- 숫자: `ExprAbs`/`ExprRound`(`digits`)/`ExprCeil`/`ExprFloor`.
|
|
36
|
+
- 날짜: `ExprYear`/`ExprMonth`/`ExprDay`/`ExprHour`/`ExprMinute`/`ExprSecond`/`ExprIsoWeek`/`ExprIsoWeekStartDate`/`ExprIsoYearMonth`/`ExprDateDiff`(`unit`/`from`/`to`)/`ExprDateAdd`(`unit`/`source`/`value`)/`ExprFormatDate`(`format`).
|
|
37
|
+
- 조건: `ExprCoalesce`/`ExprNullIf`/`ExprIs`/`ExprSwitch`(`cases`/`else`)/`ExprIf`(`condition`/`then`/`else?`).
|
|
38
|
+
- 집계: `ExprCount`(`arg?`/`distinct?`)/`ExprSum`/`ExprAvg`/`ExprMax`/`ExprMin`.
|
|
39
|
+
- 기타: `ExprGreatest`/`ExprLeast`/`ExprRowNum`/`ExprRandom`/`ExprCast`(`source`/`targetType`).
|
|
40
|
+
- Window: `ExprWindow`(`fn: WinFn`/`spec: WinSpec`). `WinFn` union = `WinFnRowNumber`/`WinFnRank`/`WinFnDenseRank`/`WinFnNtile`(`n`)/`WinFnLag`/`WinFnLead`(`column`/`offset?`/`default?`)/`WinFnFirstValue`/`WinFnLastValue`/`WinFnSum`/`WinFnAvg`/`WinFnCount`/`WinFnMin`/`WinFnMax`. `WinSpec` = `{ partitionBy?: Expr[]; orderBy?: [Expr, ("ASC"|"DESC")?][] }`.
|
|
41
|
+
- 시스템: `ExprSubquery`(`queryDef`).
|
|
42
|
+
- `type DateUnit = "year"|"month"|"day"|"hour"|"minute"|"second"`.
|
|
43
|
+
|
|
44
|
+
## QueryDef AST 타입
|
|
45
|
+
|
|
46
|
+
`type QueryDef` — 전체 쿼리 정의 union(DML+DDL+Utils+Meta). `executeDefs`/`build` 입력.
|
|
47
|
+
|
|
48
|
+
- DML: `SelectQueryDef`(`from`/`as`/`select?`/`distinct?`/`top?`/`lock?`/`where?`/`joins?`/`orderBy?`/`limit?`/`groupBy?`/`having?`/`with?`), `SelectQueryDefJoin`(+`isSingle?`), `InsertQueryDef`(`records`/`overrideIdentity?`/`output?`), `InsertIfNotExistsQueryDef`(`record`/`existsSelectQuery`), `InsertIntoQueryDef`(`recordsSelectQuery`), `UpdateQueryDef`(`record`/`where?`/`joins?`...), `DeleteQueryDef`, `UpsertQueryDef`(`existsSelectQuery`/`insertRecord`/`updateRecord`).
|
|
49
|
+
- DDL: `ClearSchemaQueryDef`, `CreateTableQueryDef`(`columns`/`primaryKey?`)/`DropTableQueryDef`/`RenameTableQueryDef`/`TruncateQueryDef`, `AddColumnQueryDef`/`DropColumnQueryDef`/`ModifyColumnQueryDef`/`RenameColumnQueryDef`, `AddPrimaryKeyQueryDef`/`DropPrimaryKeyQueryDef`, `AddForeignKeyQueryDef`(`foreignKey: {name/fkColumns/targetTable/targetPkColumns}`)/`DropForeignKeyQueryDef`, `AddIndexQueryDef`(`index: {name/columns/unique?}`)/`DropIndexQueryDef`, `CreateViewQueryDef`/`DropViewQueryDef`, `CreateProcQueryDef`(`params?`/`returns?`/`query`)/`DropProcQueryDef`/`ExecProcQueryDef`(`params`).
|
|
50
|
+
- Utils/Meta: `SwitchFkQueryDef`(`enabled`), `SchemaExistsQueryDef`.
|
|
51
|
+
- 공통: `QueryDefObjectName`(`database?`/`schema?`/`name`) — DB 객체 이름(MySQL=`db.name`, MSSQL=`db.schema.name`, PG=`schema.name`). `CudOutputDef`(`columns`/`pkColNames`/`aiColName?`) — CUD OUTPUT 절.
|
|
52
|
+
- `const DDL_TYPES` — DDL 타입명 배열(트랜잭션 내 DDL 차단 검사용. `switchFk` 는 제외 — 트랜잭션 내 허용). `type DdlType` — 그 union.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# @simplysm/orm-node
|
|
2
|
+
|
|
3
|
+
Node.js 환경에서 `@simplysm/orm-common` 의 `DbContext` 를 실 DB(MSSQL/MySQL/PostgreSQL)에 연결해 구동하는 ORM 실행 계층. 고수준 `createOrm` 팩토리와 저수준 연결(`DbConn`) 계층을 함께 제공.
|
|
4
|
+
|
|
5
|
+
## 사용 트리거 인덱스
|
|
6
|
+
|
|
7
|
+
- **createOrm / Orm / OrmOptions** — `DbContext` 서브클래스 + 연결설정으로 ORM 인스턴스를 만들고 `connect`/`connectWithoutTransaction` 콜백 안에서 쿼리 실행할 때. 앱에서 ORM 을 쓰는 일반 진입점. (아래 인라인 군)
|
|
8
|
+
- **저수준 DB 연결 계층** (`createDbConn`, `DbConn`, `DbConnConfig`+dialect별 Config, `NodeDbContextExecutor`, `getDialectFromConfig`, `DB_CONN_*` 상수) — ORM 추상화 없이 직접 SQL·파라미터 쿼리·bulk insert·수동 트랜잭션을 다루거나 `DbContext` 의 executor 를 직접 구성할 때. 자세히: [db-conn.md](./db-conn.md)
|
|
9
|
+
|
|
10
|
+
## ORM 팩토리 (createOrm)
|
|
11
|
+
|
|
12
|
+
`DbContext` 서브클래스와 연결설정을 받아, 호출마다 새 `DbContext` 인스턴스를 만들고 트랜잭션 단위 실행을 관리하는 가장 일반적인 진입점.
|
|
13
|
+
|
|
14
|
+
### createOrm
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
createOrm<T extends DbContext>(
|
|
18
|
+
DbClass: new (executor: DbContextExecutor, opt: { database: string; schema?: string }) => T,
|
|
19
|
+
config: DbConnConfig,
|
|
20
|
+
options?: OrmOptions,
|
|
21
|
+
): Orm<T>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- `DbClass` — `@simplysm/orm-common` 의 `DbContext` 를 상속한 사용자 클래스 생성자. 내부에서 `NodeDbContextExecutor(config)` 와 `{ database, schema }` 를 주입해 인스턴스화함.
|
|
25
|
+
- `config: DbConnConfig` — DB 접속 정보. `dialect` 로 DBMS 분기. 상세 필드는 db-conn.md.
|
|
26
|
+
- `options?: OrmOptions` — `config` 의 `database`/`schema` 보다 **우선** 적용(값이 있을 때만 덮어씀). 같은 `config` 로 DB/스키마만 바꿔 붙일 때 사용.
|
|
27
|
+
- 반환 `Orm<T>` — 아래 필드·메서드를 가진 객체.
|
|
28
|
+
|
|
29
|
+
`database` 가 `options` 와 `config` 양쪽 모두에서 없거나 빈 문자열이면 연결 시 `"database는 필수입니다"` throw.
|
|
30
|
+
|
|
31
|
+
### OrmOptions
|
|
32
|
+
|
|
33
|
+
- `database?: string` — DB 이름. 지정 시 `config.database` 대신 사용(우선).
|
|
34
|
+
- `schema?: string` — 스키마 이름(MSSQL `dbo`, PostgreSQL `public` 등). 지정 시 `config.schema` 대신 사용(우선). MySQL 은 스키마 개념이 없어 보통 생략.
|
|
35
|
+
|
|
36
|
+
### Orm<T>
|
|
37
|
+
|
|
38
|
+
- `DbClass` (readonly) — 생성에 쓰인 `DbContext` 생성자 그대로 노출.
|
|
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(...)` 을 직접 제어할 때 사용.
|
|
43
|
+
|
|
44
|
+
사용 예:
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
class MyDb extends DbContext {
|
|
48
|
+
user = this.queryable(User);
|
|
49
|
+
}
|
|
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
|
+
```
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# @simplysm/orm-node — 저수준 DB 연결
|
|
2
|
+
|
|
3
|
+
`createOrm` 추상화 없이 직접 SQL/파라미터 쿼리/bulk insert/수동 트랜잭션을 다루거나, `DbContext` 의 executor 를 직접 구성할 때 사용하는 계층. 연결 인스턴스 생성·연결 인터페이스·접속설정·executor·dialect 헬퍼·상수로 구성.
|
|
4
|
+
|
|
5
|
+
## createDbConn
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
createDbConn(config: DbConnConfig): Promise<DbConn>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`config.dialect` 에 맞는 드라이버를 **지연 import** 해 연결 인스턴스를 만든다(mysql → `mysql2/promise`, postgresql → `pg` + `pg-copy-streams`, mssql/mssql-azure → `tedious`). 한 번 로드한 드라이버는 모듈 캐시에 보관. 반환된 객체는 아직 **미연결** 상태이므로 `connect()` 를 별도 호출해야 함.
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
const conn = await createDbConn({ dialect: "postgresql", host: "localhost", username: "u", password: "p", database: "db" });
|
|
15
|
+
await conn.connect();
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## DbConn
|
|
19
|
+
|
|
20
|
+
저수준 연결 인터페이스. `EventEmitter<{ close: void }>` 를 상속하며 연결 종료 시 `close` 이벤트를 발생시킨다. 구현체 `MysqlDbConn`/`MssqlDbConn`/`PostgresqlDbConn` 는 직접 export 되지 않고 `createDbConn` 으로만 획득.
|
|
21
|
+
|
|
22
|
+
- `config: DbConnConfig` — 이 연결의 접속설정(읽기전용).
|
|
23
|
+
- `isConnected: boolean` — 현재 연결 여부. `connect` 성공 시 `true`, `close`/종료 이벤트 시 `false`.
|
|
24
|
+
- `isInTransaction: boolean` — 트랜잭션 진행 여부. `beginTransaction` 후 `true`, 커밋/롤백 후 `false`.
|
|
25
|
+
- `connect(): Promise<void>` — 연결 수립. 이미 연결돼 있으면 `DB_CONN_ERRORS.ALREADY_CONNECTED` throw.
|
|
26
|
+
- `close(): Promise<void>` — 연결 종료. 미연결 상태면 아무 동작 없이 반환.
|
|
27
|
+
- `beginTransaction(isolationLevel?: IsolationLevel): Promise<void>` — 트랜잭션 시작. `isolationLevel` 미지정 시 `config.defaultIsolationLevel`, 그것도 없으면 `READ_UNCOMMITTED`.
|
|
28
|
+
- `commitTransaction(): Promise<void>` — 커밋.
|
|
29
|
+
- `rollbackTransaction(): Promise<void>` — 롤백.
|
|
30
|
+
- `execute(queries: string[]): Promise<Record<string, unknown>[][]>` — 원시 SQL 문자열 배열을 순차 실행. 빈 문자열은 건너뛰며, 각 쿼리의 결과셋을 평탄화해 묶은 배열 반환.
|
|
31
|
+
- `executeParametrized(query: string, params?: unknown[]): Promise<Record<string, unknown>[][]>` — 파라미터 바인딩 쿼리 실행. SQL 인젝션 회피·값 재바인딩 시. 반환은 결과셋 배열(MySQL 멀티스테이트먼트는 statement별로 분리, INSERT/UPDATE/DELETE 자리는 빈 배열).
|
|
32
|
+
- `bulkInsert(tableName: string, columnMetas: Record<string, ColumnMeta>, records: Record<string, unknown>[]): Promise<void>` — 네이티브 bulk API 로 대량 삽입. `tableName` 은 `database.table` 또는 `database.schema.table`. `columnMetas` 는 컬럼명 → `ColumnMeta`(타입·nullable) 매핑이며 키 순서가 컬럼 순서를 결정. `records` 가 빈 배열이면 아무 동작 없이 반환. dialect별 경로: MSSQL tedious BulkLoad, MySQL `LOAD DATA LOCAL INFILE`(임시 CSV 파일 생성·삭제, UUID/binary 는 `UNHEX`), PostgreSQL `COPY FROM STDIN`(CSV 스트림).
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
await conn.beginTransaction();
|
|
36
|
+
const [rows] = await conn.executeParametrized('SELECT * FROM "User" WHERE id = $1', [1]);
|
|
37
|
+
await conn.commitTransaction();
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## DbConnConfig (dialect별 분기)
|
|
41
|
+
|
|
42
|
+
`MysqlDbConnConfig | MssqlDbConnConfig | PostgresqlDbConnConfig` 유니온. `dialect` 리터럴로 분기.
|
|
43
|
+
|
|
44
|
+
공통 필드:
|
|
45
|
+
|
|
46
|
+
- `dialect` — `"mysql"` | `"mssql"` | `"mssql-azure"` | `"postgresql"`. DBMS 선택. `"mssql-azure"` 는 Azure SQL 용으로 드라이버는 mssql 과 동일하되 연결 시 `encrypt` 활성화. 쿼리 빌더용으로는 `getDialectFromConfig` 가 `"mssql"` 로 정규화.
|
|
47
|
+
- `host: string` — 접속 호스트.
|
|
48
|
+
- `port?: number` — 포트. 미지정 시 드라이버 기본값(PostgreSQL 은 5432 로 보정).
|
|
49
|
+
- `username: string` — 인증 사용자.
|
|
50
|
+
- `password: string` — 인증 비밀번호.
|
|
51
|
+
- `database?: string` — 기본 DB 이름.
|
|
52
|
+
- `defaultIsolationLevel?: IsolationLevel` — `beginTransaction` 의 `isolationLevel` 미지정 시 적용할 기본 격리수준.
|
|
53
|
+
|
|
54
|
+
dialect별 추가 필드:
|
|
55
|
+
|
|
56
|
+
- `MysqlDbConnConfig` — `dialect: "mysql"`. 공통 필드만(스키마 개념 없음).
|
|
57
|
+
- `MssqlDbConnConfig` — `dialect: "mssql" | "mssql-azure"`. `schema?: string`(예 `dbo`) 추가.
|
|
58
|
+
- `PostgresqlDbConnConfig` — `dialect: "postgresql"`. `schema?: string`(예 `public`) 추가.
|
|
59
|
+
|
|
60
|
+
## getDialectFromConfig
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
getDialectFromConfig(config: DbConnConfig): Dialect
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`config.dialect` 를 `@simplysm/orm-common` 의 `Dialect` 로 변환. `"mssql-azure"` → `"mssql"` 로 정규화하고 나머지는 그대로 반환. 쿼리 빌더의 dialect 결정에 사용.
|
|
67
|
+
|
|
68
|
+
## NodeDbContextExecutor
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
new NodeDbContextExecutor(config: DbConnConfig)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`@simplysm/orm-common` 의 `DbContextExecutor` 를 Node 환경에서 구현한 클래스. `createOrm` 이 내부에서 자동 주입하므로 보통 직접 쓸 일은 없고, `DbContext` 를 `createOrm` 없이 수동 인스턴스화할 때만 사용. 생성자에는 `DbConnConfig` 만 받고, 실제 연결은 `connect()` 시점에 `createDbConn` 으로 지연 생성한다.
|
|
75
|
+
|
|
76
|
+
- `connect(): Promise<void>` — `createDbConn(config)` 로 연결 생성 후 수립.
|
|
77
|
+
- `close(): Promise<void>` — 연결 종료 후 내부 참조 해제.
|
|
78
|
+
- `beginTransaction(isolationLevel?: IsolationLevel)` / `commitTransaction()` / `rollbackTransaction()` — 트랜잭션 위임.
|
|
79
|
+
- `executeParametrized(query: string, params?: unknown[]): Promise<Record<string, unknown>[][]>` — 파라미터 쿼리 위임.
|
|
80
|
+
- `bulkInsert(tableName: string, columnMetas: Record<string, ColumnMeta>, records: DataRecord[]): Promise<void>` — bulk insert 위임.
|
|
81
|
+
- `executeDefs<T>(defs: QueryDef[], resultMetas?: (ResultMeta | undefined)[]): Promise<T[][]>` — `QueryDef` 배열을 dialect 쿼리 빌더로 SQL 변환해 실행. `resultMetas` 가 전부 `null`/미지정이면(결과 불필요) 모든 def 를 하나의 SQL 로 합쳐 단일 요청으로 보내고 def 수만큼 빈 배열 반환(쓰기 전용 최적화). 그 외엔 def 마다 개별 실행 후, 해당 위치에 `resultMeta` 가 있으면 `parseQueryResult` 로 타입 변환해 반환.
|
|
82
|
+
- 모든 실행 메서드는 미연결 상태에서 호출 시 `SdError(DB_CONN_ERRORS.NOT_CONNECTED)` throw.
|
|
83
|
+
|
|
84
|
+
## 상수
|
|
85
|
+
|
|
86
|
+
- `DB_CONN_CONNECT_TIMEOUT` — 연결 수립 타임아웃. `10 * 1000`(10초).
|
|
87
|
+
- `DB_CONN_DEFAULT_TIMEOUT` — 쿼리 기본 타임아웃. `10 * 60 * 1000`(10분). 마지막 활동 후 이 값의 2배가 지나면 연결을 자동 종료(idle 타임아웃).
|
|
88
|
+
- `DB_CONN_ERRORS` — 오류 메시지 상수 객체. `NOT_CONNECTED`(미연결 상태 실행 시), `ALREADY_CONNECTED`(이미 연결된 상태에서 재연결 시). `expect(...).rejects.toThrow(DB_CONN_ERRORS.NOT_CONNECTED)` 처럼 throw 비교·메시지 매칭에 사용.
|
|
89
|
+
|
|
90
|
+
## 주의사항
|
|
91
|
+
|
|
92
|
+
- `createDbConn` 반환 객체는 미연결 상태 — 반드시 `connect()` 호출 후 사용.
|
|
93
|
+
- bulk insert 는 dialect별 네이티브 경로가 달라(MySQL 은 임시파일 + `LOCAL INFILE`, PostgreSQL 은 `COPY`) 서버 측 권한·설정에 의존할 수 있음.
|
|
94
|
+
- 대부분의 작업은 `createOrm`(README)으로 충분. 이 계층은 원시 SQL·executor 커스터마이징이 필요한 경우에만.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# @simplysm/sd-cli
|
|
2
|
+
|
|
3
|
+
simplysm 모노레포의 빌드/배포 오케스트레이터 CLI. entry(`src/index.ts`)가 라이브러리로 재노출하는 것은 `sd.config.ts` 작성용 설정 타입 묶음, Vitest용 Angular AOT Vite 플러그인, 프로그래밍 방식 TS/Angular AOT 컴파일러 클래스 3종. (CLI 서브커맨드 구현 자체는 entry export 대상 아님.)
|
|
4
|
+
|
|
5
|
+
## 사용 트리거 인덱스
|
|
6
|
+
|
|
7
|
+
- **sd.config.ts 설정 타입** (`SdConfig`, `SdConfigFn`, `SdConfigParams`, `SdPackageConfig` 계열, `SdPublishConfig` 계열, Capacitor/Electron/PWA 설정 등) — 프로젝트 루트 `sd.config.ts` 를 작성·수정해 패키지 빌드 타겟·배포·앱 패키징을 설정할 때. 자세히: [sd-config-types.md](./sd-config-types.md)
|
|
8
|
+
- **SdTsCompiler** (`SdTsCompiler`, `ISdTsCompilerOptions`, `ISdTsCompilerResult`) — 패키지의 `.ts` 를 TS/Angular AOT 로 증분 컴파일하고 진단·emit·lint·SCSS 결과를 한 번에 얻을 때 (빌드 엔진·플러그인 내부에서 사용). 자세히: [SdTsCompiler.md](./SdTsCompiler.md)
|
|
9
|
+
- **sdAngularPlugin** — Vitest 에서 Angular 패키지를 AOT 컴파일해 TestBed 로 돌리기 위한 Vite 플러그인을 `vitest.config.ts` 에 끼울 때. 아래 인라인 섹션 참조.
|
|
10
|
+
|
|
11
|
+
## sdAngularPlugin
|
|
12
|
+
|
|
13
|
+
Vitest 전용 Vite 플러그인. `SdTsCompiler` 로 대상 패키지의 `.ts` 를 AOT 컴파일하고, `transform` 훅에서 컴파일된 JS 를 반환한다.
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
function sdAngularPlugin(options: SdAngularPluginOptions): Plugin
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`SdAngularPluginOptions`:
|
|
20
|
+
|
|
21
|
+
- pkg: string — `sd.config.ts` 의 `packages` 키(패키지 디렉토리명, `@simplysm/` 접두사 제외). `config()` 훅에서 `packages/<pkg>` 를 컴파일 루트로 해석한다. 어느 Angular 패키지를 테스트 빌드할지 지정.
|
|
22
|
+
|
|
23
|
+
동작: `enforce: "pre"` 플러그인. `buildStart` 에서 내부 `SdTsCompiler`(`output: { js: true, dts: false }`, `includeTests: true`, `rootDir` = cwd)로 패키지 전체를 AOT 컴파일해 소스경로→JS 맵을 만들고, `transform` 훅이 매칭되는 `.ts` 요청에 컴파일된 JS(인라인 소스맵 분리)를 돌려준다. `watchChange` 로 모은 변경 파일을 다음 `buildStart` 의 증분 무효화에 넘기고, `buildEnd` 에서 컴파일러를 폐기해 다음 라운드에 재생성한다. 진단은 logger 로 보고, emit 디스크 출력은 하지 않음.
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { sdAngularPlugin } from "@simplysm/sd-cli";
|
|
27
|
+
// vitest.config.ts project.plugins 에 추가
|
|
28
|
+
plugins: [sdAngularPlugin({ pkg: "angular" })];
|
|
29
|
+
```
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# @simplysm/sd-cli — SdTsCompiler
|
|
2
|
+
|
|
3
|
+
패키지 디렉토리의 `.ts` 를 TS 또는 Angular AOT 로 **증분** 컴파일하는 클래스. 한 번의 `compileAsync` 호출로 직렬화된 진단 + emit 결과 + lint + SCSS 결과를 묶어 반환. tsconfig 의 `angularCompilerOptions` 존재 여부로 Angular/일반 모드를 자동 판별. 빌드 엔진·`sdAngularPlugin` 내부에서 사용. 진단은 worker 경계를 통과하도록 `SerializedDiagnostic` 으로 직렬화됨.
|
|
4
|
+
|
|
5
|
+
## SdTsCompiler
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
class SdTsCompiler {
|
|
9
|
+
constructor(options: ISdTsCompilerOptions);
|
|
10
|
+
compileAsync(modifiedFiles?: ReadonlySet<string>, emitOptions?: ISdTsCompilerEmitOptions): Promise<ISdTsCompilerResult>;
|
|
11
|
+
compileSideEffectScss(): void;
|
|
12
|
+
findAffectedByScss(scssPath: string): string[];
|
|
13
|
+
get sideEffectScssRegistry(): Map<string, SideEffectScssEntry>;
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
- compileAsync(modifiedFiles?, emitOptions?) — 1회 증분 컴파일. `modifiedFiles` = 직전 변경 파일 절대경로 집합(전달 시 sourceFileCache·packageJsonCache 무효화, 미전달 시 전체). `emitOptions` = emit 세부 제어. 위험 구간을 단계별 try/catch 로 감싸 부분 복구하며, 잡힌 크래시는 결과의 `diagnostics`/`errors` 에 합산됨(silent skip 아님).
|
|
18
|
+
- compileSideEffectScss() — `sideEffectScssRegistry` 에 등록된 side-effect SCSS 항목을 모두 CSS 로 컴파일. emit 코드가 항목을 레지스트리에 채운 뒤 호출.
|
|
19
|
+
- findAffectedByScss(scssPath) — 주어진 SCSS 경로에 의존하는 소스 파일 목록 반환(역방향 탐색). watch 에서 SCSS 변경 시 재컴파일 대상을 찾을 때.
|
|
20
|
+
- sideEffectScssRegistry — side-effect SCSS 항목 맵(소스경로 → 엔트리). emit 코드가 항목을 등록하는 통로.
|
|
21
|
+
|
|
22
|
+
`compileAsync` 동작 요약: tsconfig 파싱 → `includeTests` 에 따라 rootNames 결정 → `output` 플래그로 compilerOptions 구성(`compilerOptionsTransformer` 마지막 적용) → Angular 면 `NgtscProgram.analyzeAsync`, 아니면 `EmitAndSemanticDiagnosticsBuilderProgram` → affected 파일 추적 → emit → 진단 수집·직렬화·필터(workspace 내부만) → `globalScss`/`lint` 병렬 실행. 비-Angular emit 은 writeFile 훅으로 디스크에 직접 쓰고(`emitResults` undefined), Angular emit 은 `emitResults` 로 메모리 반환.
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { SdTsCompiler } from "@simplysm/sd-cli";
|
|
26
|
+
const compiler = new SdTsCompiler({ pkgDir, cwd, output: { js: true, dts: true }, lint: true });
|
|
27
|
+
const result = await compiler.compileAsync();
|
|
28
|
+
if (result.errorCount > 0) console.error(result.errors);
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## ISdTsCompilerOptions
|
|
32
|
+
|
|
33
|
+
생성자 옵션.
|
|
34
|
+
|
|
35
|
+
- pkgDir: string — 컴파일 대상 패키지 디렉토리 절대경로. rootNames·outDir·SCSS loadPath 기준.
|
|
36
|
+
- cwd: string — workspace 루트. diagnostics 필터링(워크스페이스 내부 진단만 남김)·상대경로 로깅 기준.
|
|
37
|
+
- output: { js: boolean; dts: boolean } — 출력 제어. `js` = `.js` emit 여부, `dts` = `.d.ts` emit 여부. 둘 다 false 면 noEmit(타입체크만). 조합에 따라 declaration/sourceMap/tsBuildInfoFile 이름이 달라짐.
|
|
38
|
+
- includeTests?: boolean — `tests/` 파일을 rootNames 에 포함할지. 기본 false. 테스트 AOT 컴파일(Vitest)에서 true.
|
|
39
|
+
- env?: "node" | "browser" — 타입체크 환경. 설정 시 환경별 compilerOptions 조정(`getCompilerOptionsForEnv`) 적용. 동일 패키지를 환경별로 분리 검증할 때.
|
|
40
|
+
- sourceFileCache?: AngularSourceFileCache — Angular 증분 빌드용 SourceFile 캐시. 미제공 시 내부 생성. 인스턴스 간 캐시 공유로 증분 속도 확보.
|
|
41
|
+
- transformStylesheet?: (data, containingFile, stylesheetFile?) => Promise<string | null> — 스타일시트 변환 콜백(Angular 전용). 인라인/외부 스타일을 가공해 반환, `null` 이면 미변환. 미제공 + Angular 면 라이브러리용 SCSS 변환 콜백이 자동 생성됨.
|
|
42
|
+
- externalStylesheets?: Map<string, string> — 외부 스타일시트 맵(클라이언트 빌드용). `resourceNameToFileName` 에서 비-템플릿 리소스를 해시 기반 `.css` 외부 ID 로 치환할 때 채워짐.
|
|
43
|
+
- compilerOptionsTransformer?: (options) => ts.CompilerOptions — compilerOptions 최종 후처리. 내부 구성 이후 마지막에 적용되어 target/module/rootDir 등을 강제 가능. 클라이언트·Vitest 빌드에서 사용.
|
|
44
|
+
- lint?: boolean — true 면 `compileAsync` 가 lint 를 함께 실행하고 결과를 `result.lint` 에 포함. lint runner 는 lazy init 후 인스턴스 재사용.
|
|
45
|
+
- globalScss?: boolean — true 면 `scss/styles.scss` → `dist/styles.css` 글로벌 SCSS 컴파일 수행. 글로벌 스타일 산출이 필요한 패키지에서.
|
|
46
|
+
|
|
47
|
+
## ISdTsCompilerEmitOptions
|
|
48
|
+
|
|
49
|
+
`compileAsync` 의 두 번째 인자(emit 세부 제어, Angular 전용).
|
|
50
|
+
|
|
51
|
+
- sourceFilter?: (fileName: string) => boolean — emit 대상 소스 필터. 지정 시 통과한 소스의 EmitResult 만 결과에 포함. 일부 파일만 재emit 할 때.
|
|
52
|
+
- additionalTransformers?: { before?; after? } — Angular transformers 외 추가 TS transformer factory. `before`/`after` 각각 `ts.TransformerFactory<ts.SourceFile>[]`. 컴파일 파이프라인에 사용자 변환을 끼울 때.
|
|
53
|
+
|
|
54
|
+
## ISdTsCompilerResult
|
|
55
|
+
|
|
56
|
+
`compileAsync` 반환값.
|
|
57
|
+
|
|
58
|
+
- program: ts.Program — TypeScript Program 참조. lint·외부 도구용.
|
|
59
|
+
- builderProgram: ts.EmitAndSemanticDiagnosticsBuilderProgram — Builder Program 참조. 다음 증분 호출에 재사용됨.
|
|
60
|
+
- isForAngular: boolean — Angular 패키지 여부(tsconfig `angularCompilerOptions` 존재로 판별).
|
|
61
|
+
- affectedFiles: ReadonlySet<string> | undefined — 이번 빌드에서 영향받은 파일(posix 경로). `undefined` = 전역 변경(전체 리빌드).
|
|
62
|
+
- diagnostics: SerializedDiagnostic[] — 직렬화된 진단 정보(worker 경계 통과용). 워크스페이스 내부 진단만 남기고 필터됨.
|
|
63
|
+
- errorCount: number — Error 카테고리 진단 수(단계별 크래시 진단 합산).
|
|
64
|
+
- warningCount: number — Warning 카테고리 진단 수.
|
|
65
|
+
- errors?: string[] — Error 진단을 "파일:줄:열: TS코드: 메시지" 형식으로 포맷한 배열. 없으면 undefined.
|
|
66
|
+
- ngtscProgram?: NgtscProgram — NgtscProgram 참조(Angular 전용, HMR 용). 비-Angular 이면 undefined.
|
|
67
|
+
- emitResults?: EmitResult[] — Angular emit 결과 배열(`{ filename, contents, sourceFileName }`). 비-Angular 면 undefined(writeFile 훅이 디스크에 직접 씀).
|
|
68
|
+
- lint?: LintWithProgramResult — lint 결과. `lint` 옵션 활성 시에만 존재.
|
|
69
|
+
- scssErrors: string[] — SCSS 컴파일 에러 목록.
|
|
70
|
+
- scssDependencies: ReadonlyMap<string, ReadonlySet<string>> — SCSS 의존성 맵(소유자 파일 → 의존 SCSS 경로 집합). watch 역방향 탐색용.
|