@simplysm/sd-claude 14.0.88 → 14.0.90
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/claude/references/sd-simplysm14/README.md +16 -17
- package/claude/references/sd-simplysm14/apis/angular/README.md +39 -43
- package/claude/references/sd-simplysm14/apis/angular/controls.md +174 -80
- package/claude/references/sd-simplysm14/apis/angular/crud.md +41 -50
- package/claude/references/sd-simplysm14/apis/angular/directives.md +60 -26
- package/claude/references/sd-simplysm14/apis/angular/features.md +109 -37
- package/claude/references/sd-simplysm14/apis/angular/infra.md +61 -44
- package/claude/references/sd-simplysm14/apis/angular/layout.md +39 -31
- package/claude/references/sd-simplysm14/apis/angular/overlay.md +73 -85
- package/claude/references/sd-simplysm14/apis/angular/routing-appstructure.md +54 -39
- package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +55 -30
- package/claude/references/sd-simplysm14/apis/angular/shared-data.md +71 -67
- package/claude/references/sd-simplysm14/apis/angular/sheet.md +82 -72
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +35 -36
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +71 -43
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +38 -30
- 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 +39 -38
- package/claude/references/sd-simplysm14/apis/core-common/README.md +95 -103
- package/claude/references/sd-simplysm14/apis/core-common/array-ext.md +59 -54
- package/claude/references/sd-simplysm14/apis/core-common/async-runtime.md +86 -0
- package/claude/references/sd-simplysm14/apis/core-common/datetime.md +57 -66
- package/claude/references/sd-simplysm14/apis/core-common/errors.md +86 -0
- package/claude/references/sd-simplysm14/apis/core-common/obj.md +60 -42
- package/claude/references/sd-simplysm14/apis/core-common/serialization.md +55 -0
- package/claude/references/sd-simplysm14/apis/core-node/README.md +10 -8
- package/claude/references/sd-simplysm14/apis/core-node/consola.md +29 -32
- package/claude/references/sd-simplysm14/apis/core-node/cpx.md +34 -22
- package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +29 -25
- package/claude/references/sd-simplysm14/apis/core-node/fsx.md +40 -53
- package/claude/references/sd-simplysm14/apis/core-node/pathx.md +22 -29
- package/claude/references/sd-simplysm14/apis/core-node/worker.md +31 -31
- package/claude/references/sd-simplysm14/apis/excel/README.md +26 -26
- package/claude/references/sd-simplysm14/apis/excel/cell.md +37 -29
- package/claude/references/sd-simplysm14/apis/excel/conditional-format.md +29 -15
- package/claude/references/sd-simplysm14/apis/excel/style.md +33 -27
- package/claude/references/sd-simplysm14/apis/excel/utils.md +29 -19
- package/claude/references/sd-simplysm14/apis/excel/workbook-worksheet.md +78 -55
- package/claude/references/sd-simplysm14/apis/excel/wrapper.md +42 -45
- package/claude/references/sd-simplysm14/apis/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 +6 -62
- package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +149 -67
- package/claude/references/sd-simplysm14/apis/orm-common/expr.md +111 -99
- package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +115 -72
- package/claude/references/sd-simplysm14/apis/orm-common/schema.md +134 -92
- package/claude/references/sd-simplysm14/apis/orm-common/types.md +67 -52
- package/claude/references/sd-simplysm14/apis/orm-node/README.md +63 -26
- package/claude/references/sd-simplysm14/apis/orm-node/db-conn.md +51 -40
- package/claude/references/sd-simplysm14/apis/sd-cli/README.md +10 -12
- 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 +90 -88
- package/claude/references/sd-simplysm14/apis/service-client/orm.md +37 -29
- package/claude/references/sd-simplysm14/apis/service-client/transport.md +45 -20
- package/claude/references/sd-simplysm14/apis/service-common/README.md +89 -40
- package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +126 -34
- package/claude/references/sd-simplysm14/apis/service-common/protocol.md +109 -54
- package/claude/references/sd-simplysm14/apis/service-server/README.md +70 -66
- package/claude/references/sd-simplysm14/apis/service-server/service-authoring.md +47 -47
- package/claude/references/sd-simplysm14/apis/service-server/transport-internals.md +71 -34
- package/claude/references/sd-simplysm14/apis/service-server/v1-legacy.md +31 -32
- package/claude/references/sd-simplysm14/apis/storage/README.md +34 -28
- package/claude/references/sd-simplysm14/manuals/client-app-structure.md +142 -140
- package/claude/references/sd-simplysm14/manuals/client-orm.md +1 -1
- package/claude/references/sd-simplysm14/manuals/client-service.md +19 -7
- package/claude/references/sd-simplysm14/manuals/client-shared-data.md +2 -2
- package/claude/references/sd-simplysm14/manuals/client-system-log.md +11 -3
- package/claude/references/sd-simplysm14/manuals/data-log.md +0 -1
- package/claude/references/sd-simplysm14/manuals/orm.md +16 -0
- package/claude/rules/sd-design-rules.md +10 -0
- package/claude/skills/sd-docs/SKILL.md +58 -46
- package/claude/skills/sd-docs/references/{doc-rules.md → subagent-prompt.md} +103 -103
- package/claude/skills/sd-impl/SKILL.md +1 -1
- package/claude/skills/sd-spec/SKILL.md +858 -858
- package/claude/skills/sd-spec/references/example-spec.md +26 -36
- package/package.json +1 -1
- package/claude/references/sd-simplysm14/apis/core-common/json-transfer.md +0 -47
- 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/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
|
@@ -1,80 +1,162 @@
|
|
|
1
|
-
# @simplysm/orm-common — DbContext /
|
|
1
|
+
# @simplysm/orm-common — DbContext / 연결·트랜잭션·DDL·마이그레이션
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`DbContext` 추상 클래스를 상속해 테이블·뷰·프로시저를 클래스 프로퍼티로 등록하고, 연결·트랜잭션·DDL·마이그레이션을 실행하는 묶음. `DbContextExecutor` 구현체와 `{ database, schema? }` 옵션을 생성자로 주입한다. 각 프로퍼티가 독립 직렬화되어 40+ 테이블에서도 TS7056 이 발생하지 않는다. 트랜잭션 롤백 에러는 `DbTransactionError` 로 표준화된다.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
> 앱(Angular) 환경에서는 화면이 `DbContext` 를 직접 생성하지 않고 `AppOrmProvider.connectAsync(cb)` 로 감싼다(client-orm.md). `db` 인자가 곧 아래 `DbContext` 인스턴스이므로, 콜백 안의 쿼리 작성법은 동일하다.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
## DbContext (abstract class)
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
abstract class DbContext implements DbContextBase {
|
|
11
|
+
constructor(executor: DbContextExecutor, opt: { database: string; schema?: string });
|
|
12
|
+
|
|
13
|
+
status: DbContextStatus; // "ready" | "connect" | "transact"
|
|
14
|
+
get database(): string | undefined;
|
|
15
|
+
get schema(): string | undefined;
|
|
16
|
+
migrations: Migration[]; // 서브클래스에서 오버라이드
|
|
17
|
+
|
|
18
|
+
// 등록 (protected — 서브클래스 프로퍼티 초기화에서 사용)
|
|
19
|
+
protected queryable<T>(builder: T): () => Queryable<...>;
|
|
20
|
+
protected executable<T>(builder: T): () => Executable<...>;
|
|
21
|
+
|
|
22
|
+
// 연결
|
|
23
|
+
connect<R>(fn: () => Promise<R>, isolationLevel?: IsolationLevel): Promise<R>;
|
|
24
|
+
connectWithoutTransaction<R>(callback: () => Promise<R>): Promise<R>;
|
|
25
|
+
transaction<R>(fn: () => Promise<R>, isolationLevel?: IsolationLevel): Promise<R>;
|
|
26
|
+
|
|
27
|
+
// DDL 실행 / DDL QueryDef 생성기 / initialize ...
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
식별자 풀이:
|
|
32
|
+
|
|
33
|
+
- constructor `executor: DbContextExecutor` — 실제 DB 연결·쿼리 실행을 위임할 어댑터(서버 측 node executor, 클라이언트 측 service-client executor). 이 패키지는 SQL/QueryDef 까지만 만들고 실행은 전부 executor 가 한다.
|
|
34
|
+
- constructor `opt.database: string` — 기본 데이터베이스명. 빌더가 database 를 지정하지 않으면 이 값이 객체 네임스페이스에 쓰인다.
|
|
35
|
+
- constructor `opt.schema?: string` — 기본 스키마명(MSSQL `dbo`, PostgreSQL `public`). MySQL 은 무시.
|
|
36
|
+
- `status: "ready"|"connect"|"transact"` — 현재 상태. "ready"=미연결, "connect"=연결됨(트랜잭션 없음), "transact"=트랜잭션 중. `connect()` 중복 호출 방지·트랜잭션 중 DDL 차단 판정에 쓰인다.
|
|
37
|
+
- `database` / `schema` (getter) — 주입한 opt 값을 그대로 노출. 빌더의 `getQueryDefObjectName` 기본값으로 쓰임.
|
|
38
|
+
- `migrations: Migration[]` — 마이그레이션 정의 배열. 기본 `[]`, 서브클래스에서 오버라이드해 채운다. `initialize()` 가 미실행 항목만 순서대로 실행.
|
|
39
|
+
- `queryable(builder)` (protected) — `TableBuilder`/`ViewBuilder` 를 받아 호출할 때마다 새 alias 가 붙는 `() => Queryable` 팩토리를 반환. 서브클래스에서 `user = this.queryable(User)` 형태로 멤버를 만든다.
|
|
40
|
+
- `executable(builder)` (protected) — `ProcedureBuilder` 를 받아 `() => Executable` 팩토리를 반환. 서브클래스에서 `getUserById = this.executable(GetUserById)` 형태로 만든다.
|
|
41
|
+
- `connect(fn, isolationLevel?)` — 연결 + 트랜잭션으로 `fn` 을 감싼다. 정상 종료 시 commit, throw 시 rollback 후 재throw, 무조건 close. 첫 호출 시 관계 정합성을 1회 검증(`validateRelations`). 기본 진입점.
|
|
42
|
+
- `connectWithoutTransaction(callback)` — 연결만 하고 트랜잭션은 열지 않음. 트랜잭션 안에서 동작하지 않는 작업(`initialize`/일부 DDL) 전용. 끝나면 close.
|
|
43
|
+
- `transaction(fn, isolationLevel?)` — 이미 `connect` 상태일 때 그 안에서 트랜잭션 블록을 추가로 연다. "transact" 상태에서 재호출하면 throw.
|
|
44
|
+
- `isolationLevel?` — 트랜잭션 격리 수준. 미지정 시 executor/DB 기본값. 값별 의미는 아래 `IsolationLevel` 참조.
|
|
45
|
+
|
|
46
|
+
사용 예 (직접 API):
|
|
14
47
|
|
|
15
48
|
```typescript
|
|
16
49
|
class MainDb extends DbContext {
|
|
17
50
|
user = this.queryable(User);
|
|
18
51
|
post = this.queryable(Post);
|
|
19
52
|
getUserById = this.executable(GetUserById);
|
|
20
|
-
migrations = [{ name: "001", up: async (db) => { await db.createTable(User); } }];
|
|
53
|
+
override migrations = [{ name: "001", up: async (db) => { await db.createTable(User); } }];
|
|
21
54
|
}
|
|
55
|
+
|
|
22
56
|
const db = new MainDb(executor, { database: "mydb" });
|
|
23
|
-
await db.connect(async () => {
|
|
57
|
+
const users = await db.connect(async () => {
|
|
58
|
+
return db.user().where((u) => [expr.eq(u.isActive, true)]).execute();
|
|
59
|
+
});
|
|
24
60
|
```
|
|
25
61
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
- `
|
|
36
|
-
- `
|
|
37
|
-
- `
|
|
38
|
-
- `
|
|
39
|
-
- `
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
- `
|
|
45
|
-
- `
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
- `
|
|
56
|
-
- `
|
|
57
|
-
- `
|
|
58
|
-
|
|
59
|
-
##
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
- `
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
62
|
+
주의:
|
|
63
|
+
|
|
64
|
+
- 트랜잭션("transact") 상태에서 DDL(`createTable` 등)을 `executeDefs` 로 보내면 "TRANSACTION 상태에서는 DDL을 실행할 수 없습니다" throw. DDL 은 `connectWithoutTransaction` 안에서 실행.
|
|
65
|
+
- 롤백 자체가 실패해도 원래 에러를 우선 throw 하고, 롤백 실패 원인은 `err.cause` 로 부착(단, `NO_ACTIVE_TRANSACTION` 은 무시).
|
|
66
|
+
|
|
67
|
+
## DDL 실행 메서드
|
|
68
|
+
|
|
69
|
+
`connectWithoutTransaction` 안에서 호출하며, 즉시 executor 로 실행한다. 모두 `Promise<void>`(예외: `schemaExists` → `Promise<boolean>`).
|
|
70
|
+
|
|
71
|
+
- `createTable(table: TableBuilder)` / `dropTable(table)` / `renameTable(table, newName)` — 테이블 생성/삭제/이름변경. drop·rename 의 `table` 인자는 `QueryDefObjectName`(`{ database?, schema?, name }`).
|
|
72
|
+
- `createView(view: ViewBuilder)` / `dropView(view)` — 뷰 생성/삭제.
|
|
73
|
+
- `createProc(procedure: ProcedureBuilder)` / `dropProc(procedure)` — 프로시저 생성/삭제.
|
|
74
|
+
- `addColumn(table, columnName, column: ColumnBuilder)` / `dropColumn(table, column)` / `modifyColumn(table, columnName, column)` / `renameColumn(table, column, newName)` — column 추가/삭제/타입·속성변경/이름변경.
|
|
75
|
+
- `addPrimaryKey(table, columns: string[])` / `dropPrimaryKey(table)` — PK 추가/삭제. 복합 PK 는 `columns` 에 여러 이름.
|
|
76
|
+
- `addForeignKey(table, relationName, relationDef: ForeignKeyBuilder)` / `dropForeignKey(table, relationName)` — FK 제약 추가/삭제.
|
|
77
|
+
- `addIndex(table, indexBuilder: IndexBuilder<string[]>)` / `dropIndex(table, columns: string[])` — index 추가/삭제. drop 은 column 이름 배열로 식별.
|
|
78
|
+
- `clearSchema(params: { database; schema? })` — 스키마의 모든 객체 삭제(초기화).
|
|
79
|
+
- `schemaExists(database, schema?): Promise<boolean>` — 스키마 존재 여부.
|
|
80
|
+
- `truncate(table)` — 테이블 데이터 전체 비우기(구조 유지).
|
|
81
|
+
- `switchFk(table, enabled: boolean)` — FK 제약 일시 활성/비활성. `enabled` false=비활성(대량 적재 전), true=재활성. DDL 이 아니라 트랜잭션 안에서도 호출 가능.
|
|
82
|
+
|
|
83
|
+
각 `createX`/`dropX`/... 에는 동일 시그니처의 `getXQueryDef(...): QueryDef` 생성기 버전이 쌍으로 존재(실행하지 않고 QueryDef AST 만 반환). 추가로 `getCreateObjectQueryDef(builder)` 는 Table/View/Procedure 중 무엇이든 받아 알맞은 create QueryDef 를 반환한다. 마이그레이션에서 여러 DDL 을 모아 한 번에 보내거나 DDL 을 검사·로깅할 때 사용.
|
|
84
|
+
|
|
85
|
+
## initialize
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
initialize(options?: { dbs?: string[]; force?: boolean }): Promise<boolean>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
- `dbs?: string[]` — 초기화 대상 데이터베이스명 목록. 미지정 시 컨텍스트의 기본 database.
|
|
92
|
+
- `force?: boolean` — true 면 기존 스키마를 비우고(`clearSchema`) 전체 재생성. false/미지정이면 미적용 마이그레이션만 증분 실행하고, 변경이 있었는지를 boolean 으로 반환.
|
|
93
|
+
- 반환값 — 실제로 스키마를 만들거나 마이그레이션을 적용했으면 true. 트랜잭션 안에서 돌지 않으므로 `connectWithoutTransaction` 으로 호출.
|
|
94
|
+
|
|
95
|
+
## DbContextBase / DbContextStatus / DbContextDdlMethods
|
|
96
|
+
|
|
97
|
+
- `DbContextBase` (interface) — `Queryable`/`Executable`/`ViewBuilder` 가 의존하는 컨텍스트 최소 면(`status`, `database`, `schema`, `getNextAlias()`, `resetAliasCounter()`, `executeDefs()`, `getQueryDefObjectName()`, `switchFk()`). 직접 구현할 일은 드물고, 커스텀 컨텍스트 타입의 상한으로 쓰인다.
|
|
98
|
+
- `DbContextStatus` — `"ready" | "connect" | "transact"`. 위 `status` 와 동일 의미.
|
|
99
|
+
- `DbContextDdlMethods` (interface) — 위 DDL 실행 메서드 + QueryDef 생성기 전체를 모은 인터페이스. `Migration.up(db)` 의 `db` 타입이 `DbContextBase & DbContextDdlMethods` 라 마이그레이션 콜백에서 DDL 을 호출할 수 있다.
|
|
100
|
+
|
|
101
|
+
## DbContextExecutor / ResultMeta
|
|
102
|
+
|
|
103
|
+
`DbContextExecutor` (interface) — DbContext 가 연결·실행을 위임할 어댑터. 직접 구현은 서버/클라이언트 어댑터 패키지에서만.
|
|
104
|
+
|
|
105
|
+
- `connect(): Promise<void>` / `close(): Promise<void>` — 물리 연결 수립/종료.
|
|
106
|
+
- `beginTransaction(isolationLevel?)` / `commitTransaction()` / `rollbackTransaction()` — 트랜잭션 제어. rollback 은 활성 트랜잭션이 없으면 `DbTransactionError(NO_ACTIVE_TRANSACTION)` 를 던질 수 있음.
|
|
107
|
+
- `executeDefs<T>(defs: QueryDef[], resultMetas?: (ResultMeta|undefined)[]): Promise<T[][]>` — QueryDef 배열을 실행하고 def별 결과 배열을 반환. `resultMetas` 가 있으면 해당 def 결과를 그 메타로 타입 환원.
|
|
108
|
+
- `ResultMeta` (interface) — `{ columns: Record<string, ColumnPrimitiveStr>; joins: Record<string, { isSingle: boolean }> }`. SELECT 결과를 TS 객체로 환원할 때의 column 타입·JOIN 중첩 구조 메타. `Queryable.getResultMeta()` 가 생성. (자세히는 [types.md](./types.md))
|
|
109
|
+
|
|
110
|
+
## Migration
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
interface Migration {
|
|
114
|
+
name: string;
|
|
115
|
+
up: (db: DbContextBase & DbContextDdlMethods) => Promise<void>;
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
- `name: string` — 마이그레이션 고유 이름(타임스탬프 권장, 예 `20260105_001_create_user`). 적용 여부 추적 키이므로 한 번 배포 후 변경 금지.
|
|
120
|
+
- `up(db)` — 적용 시 실행할 함수. `db` 로 DDL 메서드를 호출. 미적용 항목만 `name` 순서대로 1회씩 실행된다.
|
|
121
|
+
|
|
122
|
+
## IsolationLevel
|
|
123
|
+
|
|
124
|
+
`connect`/`transaction`/`beginTransaction` 의 격리 수준.
|
|
125
|
+
|
|
126
|
+
- `"READ_UNCOMMITTED"` — 커밋 전 데이터까지 읽음(Dirty Read 허용). 가장 느슨, 정합성 낮음.
|
|
127
|
+
- `"READ_COMMITTED"` — 커밋된 데이터만 읽음. 일반적 기본값.
|
|
128
|
+
- `"REPEATABLE_READ"` — 트랜잭션 내 동일 쿼리가 동일 결과 보장.
|
|
129
|
+
- `"SERIALIZABLE"` — 완전 직렬화. 가장 엄격, 경합 시 잠금/충돌 비용 큼.
|
|
130
|
+
|
|
131
|
+
## DbTransactionError / DbErrorCode
|
|
132
|
+
|
|
133
|
+
DBMS별 네이티브 트랜잭션 에러를 표준 코드로 래핑한다. 롤백·재시도 분기에서 `instanceof DbTransactionError` + `err.code` 로 판별.
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
class DbTransactionError extends Error {
|
|
137
|
+
readonly name = "DbTransactionError";
|
|
138
|
+
constructor(code: DbErrorCode, message: string, originalError?: unknown);
|
|
139
|
+
readonly code: DbErrorCode;
|
|
140
|
+
readonly originalError?: unknown;
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
- `code: DbErrorCode` — 표준화된 에러 코드(아래). 분기 기준.
|
|
145
|
+
- `message: string` — 사람용 메시지.
|
|
146
|
+
- `originalError?: unknown` — 원본 DBMS 에러(디버깅용 원형 보존).
|
|
147
|
+
|
|
148
|
+
`DbErrorCode` (enum, 값은 동명 문자열):
|
|
149
|
+
|
|
150
|
+
- `NO_ACTIVE_TRANSACTION` — 롤백 대상 활성 트랜잭션 없음. 이미 롤백/커밋된 경우. `connect` 내부에서 이 코드는 무시된다.
|
|
151
|
+
- `TRANSACTION_ALREADY_STARTED` — 트랜잭션이 이미 시작됨(중복 begin).
|
|
152
|
+
- `DEADLOCK` — 데드락 발생. 재시도 정책 트리거로 사용.
|
|
153
|
+
- `LOCK_TIMEOUT` — 잠금 대기 타임아웃.
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
try {
|
|
157
|
+
await executor.rollbackTransaction();
|
|
158
|
+
} catch (err) {
|
|
159
|
+
if (err instanceof DbTransactionError && err.code === DbErrorCode.NO_ACTIVE_TRANSACTION) return;
|
|
160
|
+
throw err;
|
|
161
|
+
}
|
|
162
|
+
```
|
|
@@ -1,113 +1,125 @@
|
|
|
1
1
|
# @simplysm/orm-common — expr (SQL 표현식 빌더)
|
|
2
2
|
|
|
3
|
-
dialect 독립 SQL 표현식을 JSON AST(`Expr`)로
|
|
3
|
+
`expr` 객체로 dialect 독립 SQL 표현식을 JSON AST(`Expr`)로 조립한다. dialect별 QueryBuilder 가 MySQL/MSSQL/PostgreSQL 로 변환. where/having 콜백은 `WhereExprUnit[]`, select/orderBy/groupBy 콜백은 `ExprUnit<T>`, update/upsert/where 비교값은 `ExprInput<T>`(= `ExprUnit<T> | T`)를 다룬다.
|
|
4
|
+
|
|
5
|
+
**리터럴 래핑 규칙(orm.md)**: where 비교·update/upsert/insert 값은 `ExprInput` 자리라 **리터럴을 그대로** 넘긴다 — `expr.val` 로 감싸지 말 것. `expr.val` 은 `select` 콜백에서 상수 column 을 만들 때처럼 `ExprUnit` 이 요구되는 자리에서만.
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// 좋음 // 나쁨 (불필요한 래핑)
|
|
9
|
+
.where((u) => [expr.eq(u.status, "active")]) // expr.eq(u.status, expr.val("string","active"))
|
|
10
|
+
.update((u) => ({ name: "새이름" })) // ({ name: expr.val("string","새이름") })
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
연산 함수 인자는 대부분 `ExprInput<T>` — column 프록시(`ExprUnit`)·중첩 식·리터럴을 섞어 넘길 수 있다. `undefined` 컬럼 타입은 `.n` getter 로 non-null 단언 가능.
|
|
14
|
+
|
|
15
|
+
## ExprUnit / WhereExprUnit / ExprInput
|
|
16
|
+
|
|
17
|
+
- `ExprUnit<TPrimitive>` — 타입 안전 값 표현식 래퍼. `.dataType`(ColumnPrimitiveStr), `.expr`(AST), `.$infer`(타입 추론 마커). `.n` getter — 동일 식을 `NonNullable<T>` 로 좁힌 새 ExprUnit(`p.state!.sumQty` 처럼 nullable join 컬럼을 non-null 로 다룰 때 `.n` 대신 `!` 도 가능).
|
|
18
|
+
- `WhereExprUnit` — WHERE/HAVING 절 boolean 표현식 래퍼(`.expr: WhereExpr`). 비교·논리 함수가 반환.
|
|
19
|
+
- `ExprInput<T>` — `ExprUnit<T> | T`. 연산 인자·쓰기 값이 받는 타입(리터럴 직접 허용).
|
|
4
20
|
|
|
5
21
|
## 값 생성
|
|
6
22
|
|
|
7
|
-
- `
|
|
8
|
-
- `
|
|
9
|
-
- `
|
|
10
|
-
- `
|
|
11
|
-
|
|
12
|
-
## WHERE — 비교 (WhereExprUnit
|
|
13
|
-
|
|
14
|
-
- `
|
|
15
|
-
- `
|
|
16
|
-
- `
|
|
17
|
-
- `
|
|
18
|
-
- `
|
|
19
|
-
- `
|
|
20
|
-
- `
|
|
21
|
-
- `
|
|
22
|
-
- `
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
- `
|
|
36
|
-
- `
|
|
37
|
-
- `
|
|
38
|
-
- `
|
|
39
|
-
- `
|
|
40
|
-
- `
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
- `
|
|
45
|
-
|
|
46
|
-
## SELECT —
|
|
47
|
-
|
|
48
|
-
- `
|
|
49
|
-
- `
|
|
50
|
-
- `
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
- `
|
|
58
|
-
- `
|
|
59
|
-
- `
|
|
60
|
-
- `
|
|
61
|
-
- `
|
|
62
|
-
|
|
63
|
-
## SELECT —
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
- `
|
|
68
|
-
- `
|
|
69
|
-
- `
|
|
70
|
-
|
|
71
|
-
## SELECT —
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
- `
|
|
75
|
-
- `
|
|
76
|
-
- `
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
- `
|
|
83
|
-
- `
|
|
84
|
-
- `
|
|
85
|
-
- `
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
`spec: WinSpecInput` = `{ partitionBy?: ExprInput[]; orderBy?: [ExprInput, ("ASC"|"DESC")?][] }`.
|
|
90
|
-
- `expr.rowNumber(spec)` — ROW_NUMBER()(파티션 내 1-base 순번).
|
|
91
|
-
- `expr.rank(spec)` — RANK()(동순위 후 건너뜀: 1,1,3).
|
|
92
|
-
- `expr.denseRank(spec)` — DENSE_RANK()(동순위 후 연속: 1,1,2).
|
|
93
|
-
- `expr.ntile(n: number, spec)` — NTILE(n)(파티션을 n 그룹으로, 1~n).
|
|
94
|
-
- `expr.lag(column, spec, options?)` / `expr.lead(column, spec, options?)` — 이전/다음 행 값. `options` = `{ offset?: number; default?: ExprInput }`(offset 기본 1, default 는 경계값).
|
|
95
|
-
- `expr.firstValue(column, spec)` / `expr.lastValue(column, spec)` — 프레임 첫/마지막 값.
|
|
96
|
-
- `expr.sumOver/avgOver(column, spec)` — window 합/평균(누적합·이동평균).
|
|
97
|
-
- `expr.countOver(spec, column?)` — window 카운트(column 생략 시 전체).
|
|
98
|
-
- `expr.minOver/maxOver(column, spec)` — window 최소/최대.
|
|
23
|
+
- `val(dataType, value)` — 리터럴을 ExprUnit 으로 래핑. `dataType`="string"|"number"|"boolean"|"DateTime"|"DateOnly"|"Time"|"Uuid"|"Bytes". `value` undefined 허용(결과 타입에 undefined 포함). `select` 상수 컬럼 등 ExprUnit 강제 자리에서만.
|
|
24
|
+
- `col(dataType, ...path)` — column 참조 생성(내부용). 보통 콜백 프록시로 충분.
|
|
25
|
+
- `raw(dataType)\`SQL\`` — 이스케이프 해치. 태그드 템플릿, 보간값은 자동 파라미터화. ORM 미지원 DB 함수 직접 사용 시. 보간값은 `ExprInput`. union 의 NULL 자리채움(`` expr.raw("number")`NULL` ``)에도 사용(orm-union.md).
|
|
26
|
+
- `toExpr(value)` — `ExprInput` → `Expr` AST 변환(내부 헬퍼).
|
|
27
|
+
|
|
28
|
+
## WHERE — 비교 (반환 `WhereExprUnit`)
|
|
29
|
+
|
|
30
|
+
- `eq(source, target)` — 동등(NULL 안전: MySQL `<=>`, 그 외 `IS NULL OR =`).
|
|
31
|
+
- `gt(source, target)` / `lt(source, target)` / `gte(source, target)` / `lte(source, target)` — `>` / `<` / `>=` / `<=`.
|
|
32
|
+
- `between(source, from?, to?)` — 범위. `from`/`to` 중 하나가 undefined 면 그 방향 제한 없음(한쪽만 주면 `>=`/`<=` 로 동작).
|
|
33
|
+
- `null(source)` — IS NULL.
|
|
34
|
+
- `like(source, pattern)` — LIKE. `%`=0+ 문자, `_`=1 문자, 특수문자 `\` 이스케이프.
|
|
35
|
+
- `regexp(source, pattern)` — 정규식 매칭(구문은 DBMS 의존).
|
|
36
|
+
- `in(source, values)` — IN(값 목록).
|
|
37
|
+
- `inQuery(source, query)` — IN (SELECT ...). `query` 는 단일 column SELECT Queryable — 아니면 throw.
|
|
38
|
+
- `exists(query)` — EXISTS (서브쿼리 행 존재). SELECT 절은 제거되어 패킷 절약. (orm.md: SELECT 절 내부 `exists` 는 행당 N회 실행되므로 금지 — `joinSingle` 로 부착)
|
|
39
|
+
|
|
40
|
+
## WHERE — 논리 (반환 `WhereExprUnit`)
|
|
41
|
+
|
|
42
|
+
- `not(arg)` — NOT.
|
|
43
|
+
- `and(conditions)` — AND 결합. 빈 배열이면 throw. `where` 에 배열 넘기면 자동 AND 라 보통 불필요.
|
|
44
|
+
- `or(conditions)` — OR 결합. 빈 배열이면 throw.
|
|
45
|
+
|
|
46
|
+
## SELECT — 문자열 (반환 `ExprUnit`)
|
|
47
|
+
|
|
48
|
+
- `concat(...args)` — CONCAT(NULL→빈문자열).
|
|
49
|
+
- `left(source, length)` / `right(source, length)` — 왼쪽/오른쪽 N자.
|
|
50
|
+
- `trim(source)` — 양쪽 공백 제거.
|
|
51
|
+
- `padStart(source, length, fillString)` — LPAD(목표 길이까지 왼쪽 채움).
|
|
52
|
+
- `replace(source, from, to)` — 문자열 치환.
|
|
53
|
+
- `upper(source)` / `lower(source)` — 대/소문자 변환.
|
|
54
|
+
- `length(source)` — 문자 수. `byteLength(source)` — 바이트 수(UTF-8 CJK 3바이트).
|
|
55
|
+
- `substring(source, start, length?)` — 부분 문자열(1-기반 인덱스, length 생략 시 끝까지).
|
|
56
|
+
- `indexOf(source, search)` — 위치(1-기반, 없으면 0).
|
|
57
|
+
|
|
58
|
+
## SELECT — 숫자 (반환 `ExprUnit`)
|
|
59
|
+
|
|
60
|
+
- `abs(source)` — 절대값. `round(source, digits)` — 반올림(소수 자릿수). `ceil(source)` — 올림. `floor(source)` — 내림.
|
|
61
|
+
|
|
62
|
+
## SELECT — 날짜 (반환 `ExprUnit`)
|
|
63
|
+
|
|
64
|
+
- `year(source)` / `month(source)` / `day(source)` — 연/월/일(source: DateTime|DateOnly).
|
|
65
|
+
- `hour(source)` / `minute(source)` / `second(source)` — 시/분/초(source: DateTime|Time).
|
|
66
|
+
- `isoWeek(source)` — ISO 주 번호(1~53). `isoWeekStartDate(source)` — 그 주 월요일. `isoYearMonth(source)` — 해당 월 1일.
|
|
67
|
+
- `dateDiff(unit, from, to)` — 날짜 차(to - from). `unit`="year"|"month"|"day"|"hour"|"minute"|"second".
|
|
68
|
+
- `dateAdd(unit, source, value)` — 날짜 가감(value 음수 허용). 결과 타입은 source 와 동일.
|
|
69
|
+
- `formatDate(source, format)` — 포맷 문자열로 변환(`"%Y-%m-%d"` 등, 규칙 DBMS 의존).
|
|
70
|
+
|
|
71
|
+
## SELECT — 조건 (반환 `ExprUnit`)
|
|
72
|
+
|
|
73
|
+
- `coalesce(...args)` — 첫 non-null. 마지막 인수가 non-nullable 이면 결과도 non-nullable. join 도출 컬럼 기본값(`coalesce(p.state!.sum, 0)`)에 자주.
|
|
74
|
+
- `nullIf(source, value)` — source===value 이면 NULL(빈 문자열→NULL 변환 등).
|
|
75
|
+
- `is(condition)` — `WhereExprUnit` → boolean column 으로 변환(SELECT 절에서 조건 결과를 컬럼화).
|
|
76
|
+
- `switch<T>()` — CASE WHEN 빌더. `.case(condition, then).case(...).default(value)` 체이닝으로 `ExprUnit<T>` 마무리.
|
|
77
|
+
- `if(condition, then, else_)` — 삼항(IF/IIF). then/else 중 최소 하나 non-null 아니면 throw(타입 추론용).
|
|
78
|
+
|
|
79
|
+
## SELECT — 집계 (반환 `ExprUnit`)
|
|
80
|
+
|
|
81
|
+
NULL 값 행은 무시, 전부 NULL/무행이면 NULL.
|
|
82
|
+
|
|
83
|
+
- `count(arg?, distinct?)` — 행 수. `arg` 미지정=전체, `distinct: true`=중복 제거.
|
|
84
|
+
- `sum(arg)` / `avg(arg)` — 합/평균(number, 결과 nullable).
|
|
85
|
+
- `max(arg)` / `min(arg)` — 최대/최소(결과 nullable).
|
|
86
|
+
|
|
87
|
+
## SELECT — 기타 (반환 `ExprUnit`)
|
|
88
|
+
|
|
89
|
+
- `greatest(...args)` / `least(...args)` — 여러 값 중 최대/최소(행 내 비교). 인자 중 ExprUnit 하나는 있어야 타입 추론(없으면 throw).
|
|
90
|
+
- `rowNum()` — 전체 행 순번(1-기반, 단순 버전). `random()` — 0~1 난수(무작위 정렬에).
|
|
91
|
+
- `cast(source, targetType)` — 타입 변환. `targetType`=`DataType`(`{ type:"varchar", length:20 }` 등).
|
|
92
|
+
- `subquery(dataType, queryable)` — 스칼라 서브쿼리(1행 1열). `queryable`=`getSelectQueryDef()` 보유 객체. (orm.md: SELECT 절 내부 subquery 는 행당 N회 실행 → `joinSingle` 권장)
|
|
93
|
+
|
|
94
|
+
## SELECT — Window 함수 (반환 `ExprUnit`)
|
|
95
|
+
|
|
96
|
+
모두 `spec: { partitionBy?: ExprInput[]; orderBy?: [ExprInput, ("ASC"|"DESC")?][] }`(OVER 절) 인자를 받음.
|
|
97
|
+
|
|
98
|
+
- `rowNumber(spec)` — 파티션 내 순번(1-기반).
|
|
99
|
+
- `rank(spec)` — 순위(동순위 후 건너뜀: 1,1,3). `denseRank(spec)` — 순위(동순위 후 연속: 1,1,2).
|
|
100
|
+
- `ntile(n, spec)` — 파티션을 n 그룹으로 분할(그룹 번호 1~n).
|
|
101
|
+
- `lag(column, spec, options?)` / `lead(column, spec, options?)` — 이전/다음 행 값. `options.offset?`(기본 1), `options.default?`(없을 때 기본값).
|
|
102
|
+
- `firstValue(column, spec)` / `lastValue(column, spec)` — 프레임 내 첫/마지막 값.
|
|
103
|
+
- `sumOver(column, spec)` / `avgOver(column, spec)` / `minOver(column, spec)` / `maxOver(column, spec)` — window 합/평균/최소/최대(누적합·이동평균 등).
|
|
104
|
+
- `countOver(spec, column?)` — window 행 수. `column` 미지정=전체.
|
|
99
105
|
|
|
100
106
|
```typescript
|
|
101
107
|
db.order().select((o) => ({
|
|
102
108
|
...o,
|
|
103
|
-
rowNum: expr.rowNumber({ partitionBy: [o.userId], orderBy: [[o.createdAt, "DESC"]] }),
|
|
104
109
|
runningTotal: expr.sumOver(o.amount, { partitionBy: [o.userId], orderBy: [[o.createdAt, "ASC"]] }),
|
|
105
110
|
}));
|
|
106
111
|
```
|
|
107
112
|
|
|
108
|
-
##
|
|
113
|
+
## SwitchExprBuilder
|
|
114
|
+
|
|
115
|
+
`expr.switch<T>()` 반환 객체.
|
|
109
116
|
|
|
110
|
-
- `
|
|
111
|
-
- `
|
|
112
|
-
|
|
113
|
-
|
|
117
|
+
- `case(condition: WhereExprUnit, then: ExprInput<T>)` — 분기 추가(체이닝).
|
|
118
|
+
- `default(value: ExprInput<T>)` — ELSE 값 + 마무리, `ExprUnit<T>` 반환. case/default 중 최소 하나 non-null 아니면 throw.
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
grade: expr.switch<string>()
|
|
122
|
+
.case(expr.gte(u.score, 90), "A")
|
|
123
|
+
.case(expr.gte(u.score, 80), "B")
|
|
124
|
+
.default("F"),
|
|
125
|
+
```
|