@simplysm/sd-claude 14.0.91 → 14.0.92

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.
Files changed (93) hide show
  1. package/claude/references/sd-simplysm14/README.md +7 -6
  2. package/claude/references/sd-simplysm14/apis/angular/README.md +59 -39
  3. package/claude/references/sd-simplysm14/apis/angular/controls.md +119 -186
  4. package/claude/references/sd-simplysm14/apis/angular/crud.md +70 -31
  5. package/claude/references/sd-simplysm14/apis/angular/directives.md +55 -57
  6. package/claude/references/sd-simplysm14/apis/angular/features.md +86 -105
  7. package/claude/references/sd-simplysm14/apis/angular/infra.md +48 -57
  8. package/claude/references/sd-simplysm14/apis/angular/layout.md +37 -47
  9. package/claude/references/sd-simplysm14/apis/angular/overlay.md +82 -74
  10. package/claude/references/sd-simplysm14/apis/angular/routing-appstructure.md +61 -50
  11. package/claude/references/sd-simplysm14/apis/angular/shared-data.md +74 -57
  12. package/claude/references/sd-simplysm14/apis/angular/sheet.md +63 -72
  13. package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +23 -18
  14. package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +21 -19
  15. package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +23 -18
  16. package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +72 -32
  17. package/claude/references/sd-simplysm14/apis/core-browser/README.md +18 -18
  18. package/claude/references/sd-simplysm14/apis/core-browser/dom-element.md +29 -29
  19. package/claude/references/sd-simplysm14/apis/core-browser/indexed-db.md +41 -41
  20. package/claude/references/sd-simplysm14/apis/core-common/README.md +97 -90
  21. package/claude/references/sd-simplysm14/apis/core-common/async-runtime.md +75 -51
  22. package/claude/references/sd-simplysm14/apis/core-common/collection-ext.md +81 -0
  23. package/claude/references/sd-simplysm14/apis/core-common/errors.md +27 -29
  24. package/claude/references/sd-simplysm14/apis/core-common/obj.md +44 -45
  25. package/claude/references/sd-simplysm14/apis/core-common/serialization.md +34 -33
  26. package/claude/references/sd-simplysm14/apis/core-common/value-types.md +86 -0
  27. package/claude/references/sd-simplysm14/apis/core-node/README.md +6 -6
  28. package/claude/references/sd-simplysm14/apis/core-node/consola.md +3 -0
  29. package/claude/references/sd-simplysm14/apis/core-node/cpx.md +2 -2
  30. package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +1 -1
  31. package/claude/references/sd-simplysm14/apis/core-node/fsx.md +2 -2
  32. package/claude/references/sd-simplysm14/apis/core-node/worker.md +6 -3
  33. package/claude/references/sd-simplysm14/apis/excel/README.md +10 -10
  34. package/claude/references/sd-simplysm14/apis/excel/conditional-format.md +4 -2
  35. package/claude/references/sd-simplysm14/apis/excel/utils.md +1 -1
  36. package/claude/references/sd-simplysm14/apis/excel/workbook-worksheet.md +6 -6
  37. package/claude/references/sd-simplysm14/apis/lint/README.md +6 -32
  38. package/claude/references/sd-simplysm14/apis/lint/recommended.md +60 -0
  39. package/claude/references/sd-simplysm14/apis/lint/rules.md +17 -17
  40. package/claude/references/sd-simplysm14/apis/orm-common/README.md +15 -6
  41. package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +68 -102
  42. package/claude/references/sd-simplysm14/apis/orm-common/expr.md +75 -89
  43. package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +87 -99
  44. package/claude/references/sd-simplysm14/apis/orm-common/schema.md +110 -147
  45. package/claude/references/sd-simplysm14/apis/orm-common/types.md +48 -51
  46. package/claude/references/sd-simplysm14/apis/orm-node/README.md +8 -13
  47. package/claude/references/sd-simplysm14/apis/orm-node/db-conn.md +5 -5
  48. package/claude/references/sd-simplysm14/apis/sd-cli/README.md +9 -6
  49. package/claude/references/sd-simplysm14/apis/sd-cli/SdTsCompiler.md +9 -8
  50. package/claude/references/sd-simplysm14/apis/sd-cli/sd-config-types.md +23 -19
  51. package/claude/references/sd-simplysm14/apis/service-client/README.md +20 -12
  52. package/claude/references/sd-simplysm14/apis/service-client/orm.md +6 -6
  53. package/claude/references/sd-simplysm14/apis/service-client/transport.md +1 -1
  54. package/claude/references/sd-simplysm14/apis/service-common/README.md +35 -32
  55. package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +23 -22
  56. package/claude/references/sd-simplysm14/apis/service-common/protocol.md +23 -23
  57. package/claude/references/sd-simplysm14/apis/service-server/README.md +51 -43
  58. package/claude/references/sd-simplysm14/apis/service-server/service-authoring.md +6 -6
  59. package/claude/references/sd-simplysm14/apis/service-server/transport-internals.md +31 -21
  60. package/claude/references/sd-simplysm14/apis/service-server/v1-legacy.md +8 -8
  61. package/claude/references/sd-simplysm14/apis/storage/README.md +55 -49
  62. package/claude/references/sd-simplysm14/manuals/client-component.md +843 -740
  63. package/claude/references/sd-simplysm14/manuals/client-crud.md +8 -0
  64. package/claude/references/sd-simplysm14/manuals/client-demo.md +6 -16
  65. package/claude/references/sd-simplysm14/manuals/client-shared-data.md +26 -0
  66. package/claude/references/sd-simplysm14/manuals/logging.md +1 -1
  67. package/claude/references/sd-simplysm14/manuals/orm.md +15 -1
  68. package/claude/rules/sd-design-rules.md +7 -0
  69. package/claude/sd-system-prompt.md +5 -8
  70. package/claude/skills/sd-debug/SKILL.md +43 -0
  71. package/claude/skills/sd-debug/workflow.js +390 -0
  72. package/claude/skills/sd-demo/SKILL.md +18 -20
  73. package/claude/skills/sd-dev/SKILL.md +127 -24
  74. package/claude/skills/sd-docs/SKILL.md +5 -3
  75. package/claude/skills/sd-docs/references/subagent-prompt.md +2 -3
  76. package/claude/skills/sd-impl/SKILL.md +18 -18
  77. package/claude/skills/sd-manual/SKILL.md +1 -0
  78. package/claude/skills/sd-review/SKILL.md +24 -18
  79. package/claude/skills/sd-review/workflow.js +324 -0
  80. package/claude/skills/sd-spec/SKILL.md +96 -679
  81. package/claude/skills/sd-spec/references/example-spec.md +28 -50
  82. package/claude/skills/sd-spec/references/format-analyze.md +232 -0
  83. package/claude/skills/sd-spec/references/format-design.md +248 -0
  84. package/claude/skills/sd-spec/workflow-analyze.js +615 -0
  85. package/claude/skills/sd-spec/workflow-design.js +667 -0
  86. package/claude/skills/sd-unpack/scripts/handlers/office_com.py +5 -1
  87. package/package.json +1 -1
  88. package/scripts/postinstall.mjs +157 -18
  89. package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +0 -68
  90. package/claude/references/sd-simplysm14/apis/core-common/array-ext.md +0 -77
  91. package/claude/references/sd-simplysm14/apis/core-common/datetime.md +0 -86
  92. package/claude/skills/sd-skill/SKILL.md +0 -245
  93. package/claude/skills/sd-skill/scripts/run_eval.py +0 -380
@@ -1,67 +1,64 @@
1
- # @simplysm/orm-common — 하위 타입 / QueryDef AST / QueryBuilder / 결과 파싱
1
+ # @simplysm/orm-common — 하위 타입 / QueryDef·Expr AST / QueryBuilder / 결과 파싱
2
2
 
3
- executor·QueryBuilder 를 직접 구현하거나, `QueryDef`/`Expr` AST·column 타입을 다루거나, 원시 결과를 TS 객체로 환원할 때 참조하는 묶음. 일반 쿼리 작성에서는 expr/Queryable 가 이 타입들을 가려주므로 직접 쓸 일이 적다.
3
+ executor·QueryBuilder 를 직접 구현하거나, `QueryDef`/`Expr` AST·column 타입을 다루거나, 원시 DB 결과를 TS 객체로 환원할 때 참조하는 묶음. 일반 쿼리 작성에서는 expr/Queryable 가 이 타입들을 가려주므로 직접 쓸 일이 적다.
4
4
 
5
- ## column 타입
5
+ ## Database / Executor 타입
6
6
 
7
- - `DataType` — SQL 데이터 타입 union: `{type:"int"}`, `{type:"bigint"}`, `{type:"float"}`, `{type:"double"}`, `{type:"decimal", precision, scale?}`, `{type:"varchar", length}`, `{type:"char", length}`, `{type:"text"}`, `{type:"binary"}`, `{type:"boolean"}`, `{type:"datetime"}`, `{type:"date"}`, `{type:"time"}`, `{type:"uuid"}`. `expr.cast` 의 targetType·DDL column 정의에 사용.
8
- - `ColumnPrimitiveMap` — TS 타입 이름 실제 타입 매핑: `string→string`, `number→number`, `boolean→boolean`, `DateTime→DateTime`, `DateOnly→DateOnly`, `Time→Time`, `Uuid→Uuid`, `Bytes→Bytes`.
9
- - `ColumnPrimitiveStr` — `keyof ColumnPrimitiveMap`(타입 이름 문자열). `ExprUnit.dataType`·`val` 의 dataType.
10
- - `ColumnPrimitive` — 저장 가능한 모든 원시 union + `undefined`(=NULL).
11
- - `dataTypeStrToColumnPrimitiveStr` (const) — SQL DataType 이름 TS 타입 이름 매핑 객체(`int→"number"`, `varchar→"string"`, `datetime→"DateTime"` 등). `cast` 가 결과 타입 결정에 사용.
12
- - `InferColumnPrimitiveFromDataType<T>` — `DataType` 에서 TS 타입 추론.
13
- - `inferColumnPrimitiveStr(value)`런타임 값에서 `ColumnPrimitiveStr` 추론. NULL 이면 추론 불가 throw.
14
- - `ColumnMeta` — column 메타: `{ type: ColumnPrimitiveStr; dataType: DataType; autoIncrement?; nullable?; default?; description? }`. `ColumnBuilder.meta` 타입.
7
+ - `Dialect` (type) `"mysql" | "mssql" | "postgresql"`. 지원 DBMS.
8
+ - `dialects` (const) `Dialect[]` 전체 목록. dialect 검증 테스트 루프에 사용.
9
+ - `IsolationLevel` (type) — `"READ_UNCOMMITTED" | "READ_COMMITTED" | "REPEATABLE_READ" | "SERIALIZABLE"`. 트랜잭션 격리 수준(`connect`/`transaction` 인자).
10
+ - `DbContextExecutor` (interface) 실제 DB 연결·실행 어댑터 계약. `connect()`/`close()`/`beginTransaction(isolationLevel?)`/`commitTransaction()`/`rollbackTransaction()`/`executeDefs(defs, resultMetas?)` 구현 필요. 서버(node)·클라이언트(service-client)가 각각 구현해 `DbContext` 생성자에 주입.
11
+ - `DataRecord` (type) — `{ [key: string]: ColumnPrimitive | DataRecord | DataRecord[] }`. 재귀적 결과 레코드(중첩 include 표현).
12
+ - `ResultMeta` (interface) 결과 변환 메타. `columns`=컬럼명→`ColumnPrimitiveStr` 매핑(타입 파싱용), `joins`=조인 alias→`{ isSingle }`(단일/배열 중첩 구분). `Queryable.getResultMeta()` 가 생성, `parseQueryResult` 가 소비.
13
+ - `QueryBuildResult` (interface) — `QueryBuilder.build()` 반환. `sql`=빌드된 SQL, `resultSetIndex`=결과를 가져올 인덱스(기본 0; MySQL INSERT+OUTPUT 은 1), `resultSetStride`=다중 결과에서 N번째마다 추출(MySQL 배치 INSERT 의 SELECT 만 모을 때).
14
+ - `Migration` (interface) db-context.md 참조(여기서도 재노출).
15
15
 
16
- ## db 타입
16
+ ## Column 원시 타입
17
17
 
18
- - `Dialect` — `"mysql" | "mssql" | "postgresql"`. 지원 DBMS(MySQL 8.0.14+, MSSQL 2012+, PostgreSQL 9.0+).
19
- - `dialects` (const) — `Dialect[]`(전체 목록). dialect별 테스트 매트릭스에 사용.
20
- - `DataRecord` — 재귀 결과 레코드 타입: `{ [key: string]: ColumnPrimitive | DataRecord | DataRecord[] }`. include 중첩(단일 객체/배열)을 표현.
21
- - `QueryBuildResult` — `build()` 반환: `{ sql: string; resultSetIndex?: number; resultSetStride?: number }`. `resultSetIndex`=결과를 가져올 셋 index(기본 0, 예 MySQL INSERT+OUTPUT 는 1). `resultSetStride`=다중 결과에서 N번째마다 추출(MySQL 배치 INSERT 의 `INSERT;SELECT;...` 에서 SELECT 만 모을 때).
22
- - `IsolationLevel` — 트랜잭션 격리 수준(자세히는 [db-context.md](./db-context.md)).
23
- - `DbContextExecutor` / `ResultMeta` / `Migration` executor·결과 메타·마이그레이션 정의. [db-context.md](./db-context.md) 참조.
18
+ - `DataType` (type) SQL 데이터 타입 union(`{ type: "int" }`, `{ type: "decimal"; precision; scale? }`, `{ type: "varchar"; length }`, `char`/`text`/`binary`/`boolean`/`datetime`/`date`/`time`/`uuid`, `bigint`/`float`/`double`). `cast`/DDL 컬럼 정의에 사용.
19
+ - `ColumnPrimitiveMap` (type) — 타입명→실제 TS 타입 매핑(`string`/`number`/`boolean`/`DateTime`/`DateOnly`/`Time`/`Uuid`/`Bytes`).
20
+ - `ColumnPrimitiveStr` (type) `keyof ColumnPrimitiveMap`(타입명 문자열). `ExprUnit.dataType` 타입.
21
+ - `ColumnPrimitive` (type) 저장 가능한 모든 원시 `| undefined`(undefined=NULL).
22
+ - `ColumnMeta` (interface) 컬럼 메타(`type`/`dataType`/`autoIncrement?`/`nullable?`/`default?`/`description?`). `ColumnBuilder.meta`.
23
+ - `dataTypeStrToColumnPrimitiveStr` (const) SQL 타입명→TS 타입명 매핑 테이블(`int`→`"number"`, `datetime`→`"DateTime"` 등).
24
+ - `InferColumnPrimitiveFromDataType<T>` (type) — `DataType` 에서 TS 타입 추론.
25
+ - `inferColumnPrimitiveStr(value)` (function) — 런타임 값에서 `ColumnPrimitiveStr` 추론. NULL 이면 추론 불가로 throw. 리터럴을 ExprUnit 으로 자동 래핑할 때 사용.
24
26
 
25
- ## QueryDef AST (query-def.ts)
27
+ ## Expr AST 타입
26
28
 
27
- `executeDefs`/`build` 다루는 쿼리 정의 AST. `Queryable.getXQueryDef()`·`DbContext.getXQueryDef()` 가 생성.
29
+ `Expr` 모든 표현식 노드의 union, `WhereExpr` 는 WHERE 절용(비교+논리) union. `expr.*` 빌더가 이 AST 를 만들고, `ExprRendererBase` SQL 로 렌더링한다. 각 노드는 `type` 판별 필드를 가진 interface:
28
30
 
29
- - `QueryDefObjectName` `{ database?; schema?; name }`. DB 객체 네임스페이스(MySQL `database.name`, MSSQL `database.schema.name`, PostgreSQL `schema.name`).
30
- - DML: `SelectQueryDef`(from/as/select/distinct/top/lock/where/joins/orderBy/limit/groupBy/having/with), `SelectQueryDefJoin`(SelectQueryDef + `isSingle?`), `InsertQueryDef`(records/overrideIdentity?/output?), `InsertIfNotExistsQueryDef`, `InsertIntoQueryDef`, `UpdateQueryDef`, `DeleteQueryDef`, `UpsertQueryDef`.
31
- - `CudOutputDef` — CUD OUTPUT 절: `{ columns: string[]; pkColNames: string[]; aiColName? }`. 삽입/갱신/삭제 행 회수 정의.
32
- - DDL: `ClearSchemaQueryDef`, `CreateTableQueryDef`/`DropTableQueryDef`/`RenameTableQueryDef`/`TruncateQueryDef`, `AddColumnQueryDef`/`DropColumnQueryDef`/`ModifyColumnQueryDef`/`RenameColumnQueryDef`, `AddPrimaryKeyQueryDef`/`DropPrimaryKeyQueryDef`/`AddForeignKeyQueryDef`/`DropForeignKeyQueryDef`/`AddIndexQueryDef`/`DropIndexQueryDef`, `CreateViewQueryDef`/`DropViewQueryDef`/`CreateProcQueryDef`/`DropProcQueryDef`/`ExecProcQueryDef`.
33
- - Utils/Meta: `SwitchFkQueryDef`(`{ table; enabled }`, DDL 아님 — 트랜잭션 가능), `SchemaExistsQueryDef`.
34
- - `DDL_TYPES` (const) — DDL QueryDef type 문자열 배열. 트랜잭션 중 DDL 차단 판정(`switchFk` 는 제외)에 사용.
35
- - `DdlType` `(typeof DDL_TYPES)[number]`.
36
- - `QueryDef` — 전체 union(DML + DDL + SwitchFk + SchemaExists). `executeDefs(defs: QueryDef[])` 의 원소 타입.
31
+ - 값: `ExprColumn`(컬럼 참조 `path`), `ExprValue`(리터럴 `value`), `ExprRaw`(`sql`+`params`).
32
+ - 비교: `ExprEq`/`ExprGt`/`ExprLt`/`ExprGte`/`ExprLte`/`ExprBetween`/`ExprIsNull`/`ExprLike`/`ExprRegexp`/`ExprIn`/`ExprInQuery`/`ExprExists`.
33
+ - 논리: `ExprNot`/`ExprAnd`/`ExprOr`.
34
+ - 문자열: `ExprConcat`/`ExprLeft`/`ExprRight`/`ExprTrim`/`ExprPadStart`/`ExprReplace`/`ExprUpper`/`ExprLower`/`ExprLength`/`ExprByteLength`/`ExprSubstring`/`ExprIndexOf`.
35
+ - 숫자: `ExprAbs`/`ExprRound`/`ExprCeil`/`ExprFloor`.
36
+ - 날짜: `ExprYear`/`ExprMonth`/`ExprDay`/`ExprHour`/`ExprMinute`/`ExprSecond`/`ExprIsoWeek`/`ExprIsoWeekStartDate`/`ExprIsoYearMonth`/`ExprDateDiff`/`ExprDateAdd`/`ExprFormatDate`.
37
+ - 조건: `ExprCoalesce`/`ExprNullIf`/`ExprIs`/`ExprSwitch`/`ExprIf`.
38
+ - 집계: `ExprCount`/`ExprSum`/`ExprAvg`/`ExprMax`/`ExprMin`.
39
+ - 기타: `ExprGreatest`/`ExprLeast`/`ExprRowNum`/`ExprRandom`/`ExprCast`/`ExprSubquery`.
40
+ - 윈도우: `ExprWindow`(`fn`=`WinFn`, `spec`=`WinSpec`). `WinFn` union = `WinFnRowNumber`/`WinFnRank`/`WinFnDenseRank`/`WinFnNtile`/`WinFnLag`/`WinFnLead`/`WinFnFirstValue`/`WinFnLastValue`/`WinFnSum`/`WinFnAvg`/`WinFnCount`/`WinFnMin`/`WinFnMax`. `WinSpec`=`{ partitionBy?: Expr[]; orderBy?: [Expr, dir?][] }`.
41
+ - `DateUnit` (type) — `"year"|"month"|"day"|"hour"|"minute"|"second"`. dateDiff/dateAdd 단위.
37
42
 
38
- ## Expr AST (expr.ts)
43
+ ## QueryDef AST 타입
39
44
 
40
- `ExprUnit.expr`/`WhereExprUnit.expr` 담는 JSON AST. QueryBuilder ExprRendererSQL 변환.
45
+ `QueryDef` 모든 쿼리 정의 union. `Queryable`/`DbContext` 생성하고 `executeDefs`·QueryBuilder 소비. 각자 `type` 판별 필드:
41
46
 
42
- - `Expr` — 전체 표현식 union(값 `ExprColumn`/`ExprValue`/`ExprRaw`, 문자열/숫자/날짜/조건/집계/기타/window `ExprWindow`/시스템 `ExprSubquery`). select/orderBy 등.
43
- - `WhereExpr` WHERE 전용 union(비교 `ExprEq`/`ExprGt`/.../`ExprIn`/`ExprInQuery`/`ExprExists` + 논리 `ExprNot`/`ExprAnd`/`ExprOr`). where/having.
44
- - 개별 인터페이스(`ExprEq`, `ExprConcat`, `ExprCount`, `ExprCast`, `ExprWindow` 등) — 각 `expr.*` 함수가 만드는 노드. `type` discriminant + 피연산자 필드.
45
- - `DateUnit` — `"year"|"month"|"day"|"hour"|"minute"|"second"`. dateDiff/dateAdd.
46
- - `WinFn` — window 함수 노드 union(`WinFnRowNumber`/`WinFnRank`/`WinFnLag`/`WinFnSum`/...). `WinSpec` `{ partitionBy?: Expr[]; orderBy?: [Expr,("ASC"|"DESC")?][] }`(OVER ).
47
+ - 공통: `QueryDefObjectName`(`database?`/`schema?`/`name`dialect 네임스페이스), `CudOutputDef`(`columns`/`pkColNames`/`aiColName?` CUD OUTPUT 절).
48
+ - DML: `SelectQueryDef`(from/as/select/distinct/top/lock/where/joins/orderBy/limit/groupBy/having/with), `SelectQueryDefJoin`(SelectQueryDef + `isSingle?`), `InsertQueryDef`(`records`/`overrideIdentity?`/`aiColName?`/`output?` — overrideIdentity 는 AI 컬럼에 명시값 삽입 시, aiColName 은 PostgreSQL 시퀀스 보정용), `InsertIfNotExistsQueryDef`, `InsertIntoQueryDef`, `UpdateQueryDef`, `DeleteQueryDef`, `UpsertQueryDef`.
49
+ - DDL: `CreateTableQueryDef`/`DropTableQueryDef`/`RenameTableQueryDef`/`TruncateQueryDef`, `AddColumnQueryDef`/`DropColumnQueryDef`/`ModifyColumnQueryDef`/`RenameColumnQueryDef`, `AddPrimaryKeyQueryDef`/`DropPrimaryKeyQueryDef`, `AddForeignKeyQueryDef`/`DropForeignKeyQueryDef`, `AddIndexQueryDef`/`DropIndexQueryDef`, `CreateViewQueryDef`/`DropViewQueryDef`, `CreateProcQueryDef`/`DropProcQueryDef`/`ExecProcQueryDef`, `ClearSchemaQueryDef`.
50
+ - Utils/Meta: `SwitchFkQueryDef`(`enabled`DDL 아님, 트랜잭션 내 사용 가능), `SchemaExistsQueryDef`.
51
+ - `DDL_TYPES` (const) DDL 타입 문자열 배열(`["createTable", ...]`). 트랜잭션 DDL 차단·검증에 사용(`switchFk` 제외). `DdlType` (type) = `(typeof DDL_TYPES)[number]`.
47
52
 
48
- ## QueryBuilder (QueryDef SQL)
53
+ ## QueryBuilder (dialect SQL 렌더링)
49
54
 
50
- 직접 SQL 문자열이 필요하거나 dialect 동작을 검증할 때.
51
-
52
- - `createQueryBuilder(dialect: Dialect): QueryBuilderBase` dialect 맞는 QueryBuilder 생성(`mysql`→Mysql, `mssql`→Mssql, `postgresql`→Postgresql).
53
- - `QueryBuilderBase` (abstract) `build(def: QueryDef): QueryBuildResult` 공개 진입점. `def.type` 으로 동적 dispatch. 나머지는 protected/abstract(dialect 구현).
54
- - `MysqlQueryBuilder` / `MssqlQueryBuilder` / `PostgresqlQueryBuilder` — dialect별 구현. 보통 `createQueryBuilder` 로 얻음.
55
- - `ExprRendererBase` (abstract) — Expr→SQL 렌더러. `render(expr): string`, `renderWhere(exprs): string` 공개. `wrap(name)`/`escapeString`/`escapeValue` 는 dialect abstract.
56
- - `MysqlExprRenderer` / `MssqlExprRenderer` / `PostgresqlExprRenderer` — dialect별 렌더러.
57
-
58
- ```typescript
59
- const sql = createQueryBuilder("mysql").build(queryable.getSelectQueryDef()).sql;
60
- ```
55
+ - `createQueryBuilder(dialect)` (function) `Dialect` 맞는 `QueryBuilderBase` 인스턴스 반환(mysql→`MysqlQueryBuilder` 등). QueryDef 를 SQL 로 변환할 때의 진입점.
56
+ - `QueryBuilderBase` (abstract class) — QueryDef→SQL 추상 기본. `build(def)` 가 `def.type` 으로 동적 dispatch 해 `QueryBuildResult` 반환. dialect 공통 로직(WHERE/ORDER BY/GROUP BY/JOIN 렌더 골격) 구현, 차이나는 부분은 abstract(`tableName`/`renderJoin`/`renderLimit` 등). 새 dialect 추가 시 상속.
57
+ - `ExprRendererBase` (abstract class) — Expr→SQL 추상 기본. `render(expr)` `expr.type` 으로 dispatch. `wrap(name)`(식별자 감싸기: MySQL `` `name` ``, MSSQL `[name]`, PostgreSQL `"name"`)·`escapeString(value)`·`escapeValue(value)` 는 abstract.
58
+ - dialect 구현체: `MysqlQueryBuilder`/`MysqlExprRenderer`, `MssqlQueryBuilder`/`MssqlExprRenderer`, `PostgresqlQueryBuilder`/`PostgresqlExprRenderer`. 보통 `createQueryBuilder` 얻고 직접 `new` 하지 않음.
61
59
 
62
60
  ## 결과 파싱
63
61
 
64
- executor 원시 행을 받은 `ResultMeta` TS 객체로 환원할 때.
65
-
66
- - `parseQueryResult<T>(rawResults, meta): Promise<T[] | undefined>` 원시 결과 배열 + `ResultMeta` 타입 변환·JOIN 중첩. JOIN 없으면 단순 파싱, 있으면 그룹키 기준 재귀 그룹핑(O(n) Map). 입력 비었거나 파싱 전부 객체면 `undefined`. 100건마다 이벤트 루프 양보(async 전용). isSingle 관계에 서로 다른 결과가 섞이면 throw.
67
- - `pickResultSets<T>(rawResults, buildResult): T[]` — 다중 결과셋에서 `QueryBuildResult` 의 `resultSetIndex`/`resultSetStride` 에 따라 필요한 셋만 추출. index 없으면 첫 셋, stride 없으면 index 셋 단일, stride 있으면 index 부터 stride 간격으로 concat(MySQL 배치 INSERT 의 SELECT 만 모을 때).
62
+ - `parseQueryResult(rawResults, meta)` (function) — 원시 DB 결과 배열을 `ResultMeta` 기준으로 타입 변환·JOIN 중첩한 객체 배열로 환원. async 전용(대량 처리 중 이벤트 루프 양보). 입력이 비었거나 파싱 후 전부 빈 객체면 `undefined` 반환. 타입 파싱 실패 시 throw. `meta` 없이 부를 이유 없음(입력=출력).
63
+ - 평탄 키 `"posts.id"` → 중첩 `{ posts: { id } }` 로 변환. `joins[key].isSingle` 에 따라 배열/단일 객체로 그룹핑. `isSingle: true` 인데 서로 다른 결과가 여럿이면 throw.
64
+ - `pickResultSets(rawResults, buildResult)` (function)다중 결과셋에서 `QueryBuildResult` 메타(`resultSetIndex`/`resultSetStride`)에 따라 필요한 셋만 추출. `resultSetIndex` 없으면 셋, `stride` 없으면 해당 인덱스 단일 셋, `stride` 있으면 인덱스부터 stride 간격 셋을 concat(MySQL 배치 INSERT SELECT 결과만 모을 때).
@@ -1,16 +1,15 @@
1
1
  # @simplysm/orm-node
2
2
 
3
- Node.js 환경에서 `@simplysm/orm-common` 의 `DbContext` 를 실제 DB(MySQL/MSSQL/PostgreSQL)에 연결·실행하는 ORM 런타임. 고수준 진입점(`createOrm`)과 저수준 연결(`createDbConn`/`DbConn`)을 함께 노출.
3
+ Node.js 환경에서 `@simplysm/orm-common` 의 `DbContext` 를 MySQL/MSSQL/PostgreSQL 에 연결·실행하는 ORM 런타임. 고수준 진입점 `createOrm`(트랜잭션 경계 관리)과 저수준 연결 `createDbConn`/`DbConn`(raw SQL·파라미터 쿼리·bulk insert·수동 트랜잭션)을 함께 노출. query DSL 자체는 `@simplysm/orm-common` 의 `DbContext` 가 제공하고, 이 패키지는 그 컨텍스트를 실제 DB 연결에 묶는 역할.
4
4
 
5
5
  ## 사용 트리거 인덱스
6
6
 
7
7
  - **createOrm / Orm / OrmOptions** — `DbContext` 서브클래스로 ORM 인스턴스를 만들고 `connect`/`connectWithoutTransaction` 으로 트랜잭션 경계를 잡아 query 를 돌릴 때. (아래 "ORM 진입" 군)
8
- - **NodeDbContextExecutor** `DbContext` 직접 주입할 executor 손수 만들 때(`createOrm` 내부에서 자동 생성하므로 직접 일은 드묾). (아래 "ORM 진입" db-conn.md)
9
- - **createDbConn / DbConn / DbConnConfig 계열 / getDialectFromConfig / DB_CONN_\* 상수** — ORM 없이 raw SQL·파라미터 쿼리·bulk insert·수동 트랜잭션을 직접 다루거나 dialect별 접속 설정을 작성할 때. 자세히: [db-conn.md](./db-conn.md)
8
+ - **createDbConn / DbConn / DbConnConfig 계열 / getDialectFromConfig / NodeDbContextExecutor / DB_CONN_\* 상수** — `createOrm` 추상화를 거치지 않고 raw SQL·파라미터 쿼리·bulk insert·수동 트랜잭션을 직접 다루거나, dialect별 접속 설정 타입을 작성하거나, `DbContext` executor 를 손수 조립할 때. 자세히: [db-conn.md](./db-conn.md)
10
9
 
11
10
  ## ORM 진입
12
11
 
13
- `DbContext` 서브클래스와 접속 설정을 받아 연결·트랜잭션 경계를 관리하는 고수준 진입. query DSL 자체는 `@simplysm/orm-common` `DbContext` 제공하고, 군은 컨텍스트를 실제 DB 연결에 묶는 역할.
12
+ `DbContext` 서브클래스와 접속 설정을 받아 연결·트랜잭션 경계를 관리하는 고수준 진입. 대부분의 작업은 군으로 충분하며, raw SQL·executor 커스터마이징이 필요할 때만 [db-conn.md](./db-conn.md) 계층으로 내려감.
14
13
 
15
14
  ### createOrm
16
15
 
@@ -24,7 +23,7 @@ function createOrm<T extends DbContext>(
24
23
 
25
24
  `DbContext` 서브클래스를 받아 `Orm<T>` 를 반환. DB 인스턴스는 `connect`/`connectWithoutTransaction` 호출마다 새로 생성되므로 반환된 `Orm` 객체 자체는 재사용 가능.
26
25
 
27
- - DbClass — `DbContext` 를 상속한 생성자. `(executor, { database, schema? })` 시그니처 고정. query 진입점(`this.queryable(Entity)`)을 정의한 사용자 DB 클래스를 넘김. 어떤 엔티티 집합을 다룰지 결정하는 자리.
26
+ - DbClass — `DbContext` 를 상속한 생성자. `(executor, { database, schema? })` 시그니처 고정. `this.queryable(Entity)` 로 query 진입점을 정의한 사용자 DB 클래스를 넘김 어떤 엔티티 집합을 다룰지 결정하는 자리.
28
27
  - config — `DbConnConfig`(dialect별 분기 유니온, [db-conn.md](./db-conn.md) 참조). 접속 대상·인증 정보. DBMS 종류·호스트·계정이 여기서 정해짐.
29
28
  - options? — `OrmOptions`. config 의 `database`/`schema` 를 덮어쓰는 우선 옵션. 같은 접속 정보로 DB·스키마만 바꿔 쓸 때(다중 테넌트 등) 지정.
30
29
 
@@ -38,7 +37,7 @@ const orm = createOrm(TestDb, mysqlConfig, { database: "TestDb" });
38
37
  await orm.connect(async (db) => {
39
38
  await db.user().insert([{ id: 100, name: "orm-test" }]);
40
39
  return db.user().execute();
41
- }); // 트랜잭션 안에서 실행 후 자동 커밋
40
+ }); // 트랜잭션 안에서 실행 후 콜백 정상 종료 시 자동 커밋
42
41
  ```
43
42
 
44
43
  ### Orm
@@ -56,9 +55,9 @@ interface Orm<T extends DbContext> {
56
55
  `createOrm` 반환 타입. 각 메서드 호출마다 DB 인스턴스를 새로 만들어 연결→콜백→정리.
57
56
 
58
57
  - DbClass / config / options — `createOrm` 에 넘긴 값을 그대로 읽기 전용으로 보관. 같은 설정으로 재연결·진단할 때 참조.
59
- - connect — 콜백을 **트랜잭션 안에서** 실행. 콜백이 정상 종료하면 커밋, throw 하면 롤백 후 그 오류를 다시 throw. 여러 쓰기를 원자적으로 묶어야 할 때.
60
- - isolationLevel? — `"READ_UNCOMMITTED" | "READ_COMMITTED" | "REPEATABLE_READ" | "SERIALIZABLE"`(`@simplysm/orm-common`). 트랜잭션 격리 수준. 미지정 시 연결의 `defaultIsolationLevel`, 그것도 없으면 `READ_UNCOMMITTED`. 더티 리드를 막아야 하면 `READ_COMMITTED` 이상으로 올림.
61
- - connectWithoutTransaction — 콜백을 **트랜잭션 없이** 실행. 읽기 전용이거나, 콜백 내부에서 `db.transaction(...)` 으로 부분 트랜잭션을 직접 열어 일부 구간만 원자화할 때.
58
+ - connect — 콜백을 **트랜잭션 안에서** 실행. 콜백이 정상 종료하면 커밋, throw 하면 롤백 후 그 오류를 다시 throw. 여러 쓰기를 원자적으로 묶어야 할 때 기본으로 사용.
59
+ - isolationLevel? — `IsolationLevel`(`@simplysm/orm-common`). 트랜잭션 격리 수준. 테스트로 확인된 값: `"READ_UNCOMMITTED" | "READ_COMMITTED" | "REPEATABLE_READ" | "SERIALIZABLE"`. 미지정 시 연결의 `defaultIsolationLevel`, 그것도 없으면 `READ_UNCOMMITTED`. 더티 리드를 막아야 하면 `READ_COMMITTED` 이상으로 올림.
60
+ - connectWithoutTransaction — 콜백을 **트랜잭션 없이** 실행. 읽기 전용이거나, initialize 등 트랜잭션 안에서 동작하지 않는 작업, 또는 콜백 내부에서 `db.transaction(...)` 으로 부분 트랜잭션을 직접 열어 일부 구간만 원자화할 때.
62
61
  - callback — 연결된 DbContext 인스턴스(`T`)를 받아 query 를 수행하고 임의 값 `R` 을 반환. 그 반환값이 `connect`/`connectWithoutTransaction` 의 결과가 됨.
63
62
 
64
63
  ```typescript
@@ -84,7 +83,3 @@ interface OrmOptions {
84
83
 
85
84
  - database? — 사용할 DB 이름. config 의 `database` 대신 쓸 때. 접속 정보는 같고 DB 만 다른 다중 테넌트 상황에서 인스턴스별로 지정.
86
85
  - schema? — 스키마 이름(예: MSSQL `dbo`, PostgreSQL `public`). MySQL 은 스키마 개념이 없어 보통 미지정.
87
-
88
- ### NodeDbContextExecutor
89
-
90
- `@simplysm/orm-common` 의 `DbContextExecutor` 를 Node 환경에서 구현한 클래스. `createOrm` 이 내부에서 생성·주입하므로 직접 다룰 일은 드묾. `DbContext` 를 `createOrm` 없이 손수 조립할 때만 사용. 생성자·메서드 전체 시그니처와 동작은 [db-conn.md](./db-conn.md) 의 동명 섹션 참조.
@@ -1,6 +1,6 @@
1
1
  # @simplysm/orm-node — 저수준 DB 연결
2
2
 
3
- `createOrm` 추상화를 거치지 않고 raw SQL·파라미터 쿼리·bulk insert·수동 트랜잭션을 직접 다루거나, dialect별 접속 설정 타입을 작성하거나, `DbContext` 의 executor 를 손수 구성할 때 함께 읽히는 묶음. 연결 인스턴스 생성·연결 인터페이스·접속 설정·executor·dialect 헬퍼·상수로 구성.
3
+ `createOrm` 추상화를 거치지 않고 raw SQL·파라미터 쿼리·bulk insert·수동 트랜잭션을 직접 다루거나, dialect별 접속 설정 타입을 작성하거나, `DbContext` 의 executor 를 손수 조립할 때 함께 읽히는 묶음. 연결 인스턴스 생성·연결 인터페이스·접속 설정·executor·dialect 헬퍼·상수로 구성.
4
4
 
5
5
  ## createDbConn
6
6
 
@@ -20,7 +20,7 @@ await conn.connect();
20
20
  저수준 연결 인터페이스. `EventEmitter<{ close: void }>` 를 상속하며 연결 종료 시 `close` 이벤트를 발생시킨다. 구현체 `MssqlDbConn`/`MysqlDbConn`/`PostgresqlDbConn` 은 직접 export 되지 않고 `createDbConn` 으로만 획득(타입 `DbConn` 만 import 가능).
21
21
 
22
22
  - config: DbConnConfig — 이 연결의 접속 설정(읽기 전용). 어떤 dialect·DB 로 연결됐는지 확인용.
23
- - isConnected: boolean — 현재 연결 여부. `connect` 성공 시 `true`, `close`/종료(`end`) 이벤트 시 `false`. 재연결 판단·정리 분기에 사용.
23
+ - isConnected: boolean — 현재 연결 여부. `connect` 성공 시 `true`, `close`/드라이버 `end` 이벤트 시 `false`. 재연결 판단·정리 분기에 사용.
24
24
  - isInTransaction: boolean — 트랜잭션 진행 여부. `beginTransaction` 후 `true`, 커밋·롤백 후 `false`. 중첩 방지·상태 확인에 사용.
25
25
  - connect(): Promise\<void\> — 연결 수립. 이미 연결돼 있으면 `DB_CONN_ERRORS.ALREADY_CONNECTED` throw.
26
26
  - close(): Promise\<void\> — 연결 종료. 미연결 상태면 아무 동작 없이 반환(throw 안 함). 재호출 안전.
@@ -87,8 +87,8 @@ new NodeDbContextExecutor(config: DbConnConfig)
87
87
  - connect(): Promise\<void\> — `createDbConn(config)` 로 연결 생성 후 수립.
88
88
  - close(): Promise\<void\> — 연결 종료 후 내부 참조 해제.
89
89
  - beginTransaction(isolationLevel?: IsolationLevel) / commitTransaction() / rollbackTransaction() — 내부 `DbConn` 에 트랜잭션 제어 위임. `isolationLevel?` 의미는 위 `DbConn.beginTransaction` 과 동일.
90
- - executeParametrized(query: string, params?: unknown[]): Promise\<Record\<string, unknown\>[][]\> — 파라미터 쿼리 위임.
91
- - bulkInsert(tableName: string, columnMetas: Record\<string, ColumnMeta\>, records: DataRecord[]): Promise\<void\> — bulk insert 위임.
90
+ - executeParametrized(query: string, params?: unknown[]): Promise\<Record\<string, unknown\>[][]\> — 파라미터 쿼리를 내부 `DbConn` 에 위임.
91
+ - bulkInsert(tableName: string, columnMetas: Record\<string, ColumnMeta\>, records: DataRecord[]): Promise\<void\> — bulk insert 를 내부 `DbConn` 에 위임.
92
92
  - executeDefs\<T\>(defs: QueryDef[], resultMetas?: (ResultMeta | undefined)[]): Promise\<T[][]\> — `QueryDef` 배열을 dialect 쿼리 빌더로 SQL 변환해 실행. `resultMetas` 가 전부 `null`/미지정이면(결과 불필요) 모든 def 를 하나의 SQL 로 합쳐 단일 요청으로 보내고 def 수만큼 빈 배열 반환(쓰기 전용 최적화, 인터페이스 계약 유지). 그 외엔 def 마다 개별 실행 후, 해당 위치에 `resultMeta` 가 있으면 `parseQueryResult` 로 타입 변환해 반환, 없으면 raw 결과셋 그대로 반환.
93
93
  - 모든 실행 메서드는 미연결 상태에서 호출 시 `SdError(DB_CONN_ERRORS.NOT_CONNECTED)` throw.
94
94
 
@@ -102,4 +102,4 @@ new NodeDbContextExecutor(config: DbConnConfig)
102
102
 
103
103
  - `createDbConn` 반환 객체는 미연결 상태 — 반드시 `connect()` 호출 후 사용.
104
104
  - bulk insert 는 dialect별 네이티브 경로가 달라(MySQL 임시파일 + `LOCAL INFILE`, PostgreSQL `COPY`, MSSQL `BulkLoad`) 서버 측 권한·설정에 의존할 수 있음.
105
- - 대부분의 작업은 `createOrm`(README)으로 충분. 이 계층은 raw SQL·executor 커스터마이징이 필요한 경우에만.
105
+ - 대부분의 작업은 `createOrm`([README](./README.md))으로 충분. 이 계층은 raw SQL·executor 커스터마이징이 필요한 경우에만.
@@ -1,23 +1,26 @@
1
1
  # @simplysm/sd-cli
2
2
 
3
- simplysm 모노레포의 빌드/배포 오케스트레이터 CLI. entry(`src/index.ts`)가 외부로 노출하는 것은 CLI 실행 코드가 아니라 세 가지뿐: ① `sd.config.ts` 작성용 설정 타입군, ② 패키지 단위 TypeScript/Angular AOT 증분 컴파일러(`SdTsCompiler`)와 그 옵션·결과 타입, ③ Vitest 전용 Angular Vite 플러그인(`sdAngularPlugin`).
3
+ simplysm 모노레포의 빌드/배포 오케스트레이터 CLI. entry(`src/index.ts`)가 외부로 노출하는 CLI 실행 코드가 아니라 세 묶음뿐 ① `sd.config.ts` 작성용 설정 타입군, ② 패키지 단위 TypeScript/Angular AOT 증분 컴파일러 `SdTsCompiler` 와 그 옵션·결과 타입, ③ Vitest 전용 Angular Vite 플러그인 `sdAngularPlugin`.
4
4
 
5
5
  ## 사용 트리거 인덱스
6
6
 
7
- - **sd.config.ts 설정 타입** — 프로젝트 루트 `sd.config.ts` 를 작성·수정하며 어떤 패키지를 어떤 타겟(`node`/`browser`/`neutral`/`client`/`server`/`scripts`)으로 빌드할지, 배포(npm/로컬/FTP)·Capacitor/Electron/PWA·서버 옵션을 지정할 때. `SdConfigFn` 으로 default export 함수 타입을 잡고 각 패키지를 타겟별 인터페이스로 채움. 자세히: [sd-config-types.md](./sd-config-types.md)
8
- - **SdTsCompiler / ISdTsCompilerOptions / ISdTsCompilerResult / ISdTsCompilerEmitOptions** — sd-cli 외부에서 패키지 단위 TS(또는 Angular AOT) 증분 컴파일을 직접 구동하거나 그 결과(emit·진단·lint·SCSS)를 다룰 때. 자세히: [SdTsCompiler.md](./SdTsCompiler.md)
7
+ - **sd.config.ts 설정 타입** — 프로젝트 루트 `sd.config.ts` 를 작성·수정하며 패키지별 빌드 타겟(`node`/`browser`/`neutral`/`client`/`server`/`scripts`), 배포(npm/로컬/FTP)·Capacitor/Electron/PWA·서버 옵션·의존성 교체를 지정할 때. 자세히: [sd-config-types.md](./sd-config-types.md)
8
+ - **SdTsCompiler / ISdTsCompilerOptions / ISdTsCompilerResult / ISdTsCompilerEmitOptions** — sd-cli 외부에서 패키지 1개의 TS(또는 Angular AOT) 증분 컴파일을 직접 구동하거나 그 결과(emit·진단·lint·SCSS)를 다룰 때. 자세히: [SdTsCompiler.md](./SdTsCompiler.md)
9
9
  - **sdAngularPlugin / SdAngularPluginOptions** — Vitest 에서 Angular 패키지의 `.ts` 를 AOT 컴파일해 주입하는 Vite 플러그인을 설정할 때. 아래 인라인 섹션 참조.
10
10
 
11
11
  ## sdAngularPlugin
12
12
 
13
13
  ```typescript
14
14
  function sdAngularPlugin(options: SdAngularPluginOptions): Plugin; // vite Plugin 반환
15
- interface SdAngularPluginOptions { pkg: string; }
15
+
16
+ interface SdAngularPluginOptions {
17
+ pkg: string;
18
+ }
16
19
  ```
17
20
 
18
- Angular AOT 컴파일을 수행하는 **Vitest 전용** Vite 플러그인(`vitest.config.ts` 의 `angular` project plugins 에 등록). 내부에서 `SdTsCompiler` 로 대상 패키지의 `.ts`(tests 포함, `includeTests: true`, `output: { js: true, dts: false }`)를 AOT 컴파일하고, Vite `transform` 훅에서 컴파일된 JS 를 반환한다. `enforce: "pre"` 로 다른 transform 보다 먼저 동작하며, 컴파일러가 만든 인라인 base64 소스맵을 분리해 Vite 호환 형태(`{ code, map }`)로 넘긴다. `compilerOptionsTransformer` 로 `noEmit:false`·`declaration:false`·`inlineSourceMap:true`·`rootDir = cwd` 를 강제하고, `buildEnd` 마다 내부 컴파일러를 폐기해 다음 watch 재빌드 재생성하며, watch 변경 파일을 모아 `buildStart` 의 캐시 무효화에 쓴다.
21
+ Angular AOT 컴파일을 수행하는 **Vitest 전용** Vite 플러그인. 내부에서 `SdTsCompiler` 로 대상 패키지의 `.ts`(tests 포함 `includeTests: true`, `output: { js: true, dts: false }`)를 AOT 컴파일하고, Vite `transform` 훅에서 컴파일된 JS 를 반환한다. `enforce: "pre"` 로 다른 transform 보다 먼저 동작하며, 컴파일러가 emit 인라인 base64 소스맵을 분리해 Vite 호환 형태(`{ code, map }`)로 넘긴다. `compilerOptionsTransformer` 로 `noEmit:false`·`declaration:false`·`inlineSourceMap:true`·`rootDir = cwd` 를 강제하고, `buildEnd` 마다 내부 컴파일러를 폐기해 다음 watch 재빌드 재생성하며, `watchChange` 로 모은 변경 파일을 `buildStart` 의 증분 캐시 무효화에 쓴다.
19
22
 
20
- - pkg: string — 컴파일 대상 패키지 디렉토리명. `sd.config.ts` 의 `packages` 키와 동일(`@simplysm/` 접두사 제외한 짧은 이름, 예: `"angular"`). 플러그인은 `process.cwd()/packages/<pkg>` 를 컴파일 루트로 잡으므로, 테스트하려는 Angular 패키지명을 그대로 넣는다.
23
+ - **pkg**: string — 컴파일 대상 패키지 디렉토리명. `sd.config.ts` 의 `packages` (`@simplysm/` 접두사 제외한 짧은 이름, 예: `"angular"`) 동일. 플러그인은 `process.cwd()/packages/<pkg>` 를 컴파일 루트로 잡으므로, 테스트하려는 Angular 패키지명을 그대로 넣는다.
21
24
 
22
25
  ```typescript
23
26
  // vitest.config.ts
@@ -1,6 +1,6 @@
1
1
  # @simplysm/sd-cli — SdTsCompiler
2
2
 
3
- 패키지 디렉토리의 `.ts` 를 TypeScript 또는 Angular AOT 로 **증분** 컴파일하는 클래스. 한 번의 `compileAsync` 호출로 직렬화된 진단 + emit 결과 + lint + SCSS 결과를 한 묶음(`ISdTsCompilerResult`)으로 반환한다. tsconfig 의 `angularCompilerOptions` 존재 여부로 Angular/일반 모드를 자동 판별. 빌드 엔진과 `sdAngularPlugin` 내부에서 사용. 진단은 worker 경계를 통과하도록 `SerializedDiagnostic` 으로 직렬화되며, 내부 크래시는 단계별로 잡아 진단으로 보고(부분 복구)한다.
3
+ 패키지 디렉토리 1개의 `.ts` 를 TypeScript 또는 Angular AOT 로 **증분** 컴파일하는 클래스. 한 번의 `compileAsync` 호출로 직렬화된 진단 + emit 결과 + lint + SCSS 결과를 한 묶음(`ISdTsCompilerResult`)으로 반환한다. tsconfig 의 `angularCompilerOptions` 존재 여부로 Angular/일반 모드를 자동 판별. 빌드 엔진과 `sdAngularPlugin` 내부에서 사용. 진단은 worker 경계를 통과하도록 `SerializedDiagnostic` 으로 직렬화되며, 내부 크래시는 단계별로 잡아 진단으로 보고(부분 복구)한다.
4
4
 
5
5
  ## ISdTsCompilerOptions (생성자 인자)
6
6
 
@@ -31,9 +31,9 @@ interface ISdTsCompilerOptions {
31
31
  - sourceFileCache?: AngularSourceFileCache — Angular 증분용 SourceFile 캐시. 미제공 시 내부 생성. 여러 `compileAsync` 라운드 간 캐시를 공유하려면 외부에서 주입.
32
32
  - transformStylesheet?: (data, containingFile, stylesheetFile?) => Promise<string|null> — 컴포넌트 스타일 변환 콜백(Angular only). `null` 반환 시 변환 안 함. 미제공이고 Angular 면 라이브러리용 SCSS 변환 콜백을 자동 생성. 클라이언트 빌드처럼 커스텀 스타일 파이프라인이 필요할 때 직접 제공.
33
33
  - externalStylesheets?: Map<string, string> — 외부 스타일시트 맵(클라이언트 빌드용). 지정 시 비-템플릿 스타일 리소스를 해시 기반 `.css` 외부 파일명으로 매핑(`resourceNameToFileName`). 스타일을 별도 청크로 뽑을 때.
34
- - compilerOptionsTransformer?: (options) => ts.CompilerOptions — 최종 compilerOptions 후처리 훅. 클라이언트의 `target`/`module`/`rootDir` 강제 등에 쓴다.
35
- - lint?: boolean — true 면 `compileAsync` 가 program 기반 lint 를 함께 돌려 결과를 `result.lint` 에 담는다(affected 파일만 대상). 컴파일과 동시에 lint 하고 싶을 때.
36
- - globalScss?: boolean — true 면 `scss/styles.scss` → `dist/styles.css` 글로벌 SCSS 를 컴파일하고 에러를 `result.scssErrors` 에 더한다.
34
+ - compilerOptionsTransformer?: (options) => ts.CompilerOptions — 최종 compilerOptions 후처리 훅. 클라이언트의 `target`/`module`/`rootDir` 강제, Vitest 의 `inlineSourceMap` 강제 등에 쓴다.
35
+ - lint?: boolean — true 면 `compileAsync` 가 program 기반 lint 를 함께 돌려 결과를 `result.lint` 에 담는다(affected 파일만 대상, globalScss 와 병렬 실행). 컴파일과 동시에 lint 하고 싶을 때.
36
+ - globalScss?: boolean — true 면 `scss/styles.scss` → `styles.css`(패키지 루트) 글로벌 SCSS 를 컴파일하고 에러를 `result.scssErrors` 에 더한다.
37
37
 
38
38
  ## ISdTsCompilerEmitOptions (compileAsync 2번째 인자)
39
39
 
@@ -48,7 +48,7 @@ interface ISdTsCompilerEmitOptions {
48
48
  ```
49
49
 
50
50
  - sourceFilter?: (fileName) => boolean — emit 결과 필터(Angular only). true 인 소스만 `emitResults` 에 남긴다. 특정 파일의 emit 만 필요할 때(예: HMR 단일 파일).
51
- - additionalTransformers?.before / .after — Angular 기본 transformers 앞/뒤에 끼울 추가 TS transformer 배열(Angular only). 커스텀 코드 변환을 주입할 때.
51
+ - additionalTransformers?.before / .after — Angular 기본 transformers 앞/뒤에 끼울 추가 TS transformer 배열(Angular only). before = 변환 전, after = 변환 후 단계에 주입. 커스텀 코드 변환을 끼울 때.
52
52
 
53
53
  ## SdTsCompiler — 메서드
54
54
 
@@ -104,14 +104,15 @@ interface ISdTsCompilerResult {
104
104
  ```
105
105
 
106
106
  - program: ts.Program — TS Program 참조. lint·외부 도구에 넘길 때.
107
- - builderProgram — 증분 BuilderProgram 참조.
107
+ - builderProgram: ts.EmitAndSemanticDiagnosticsBuilderProgram — 증분 BuilderProgram 참조.
108
108
  - isForAngular: boolean — Angular 모드로 컴파일됐는지(tsconfig 의 `angularCompilerOptions` 유무로 결정). 후속 처리 분기에 쓴다.
109
109
  - affectedFiles: ReadonlySet<string> | undefined — 이번 빌드에서 영향받은 파일(posix 경로). `undefined` = 전역 변경(전체 리빌드). 부분 재처리 범위 판단에 쓴다.
110
110
  - diagnostics: SerializedDiagnostic[] — 직렬화된 진단 전체(worker 경계 통과용). 내부 크래시 진단도 합산됨.
111
- - errorCount / warningCount: number — Error / Warning 카테고리 진단 수. 크래시는 errorCount 가산.
111
+ - errorCount: number — Error 카테고리 진단 수. 크래시는 여기에 가산.
112
+ - warningCount: number — Warning 카테고리 진단 수.
112
113
  - errors?: string[] — Error 진단을 `"파일:줄:열: TS코드: 메시지"` 형식으로 포맷한 배열(없으면 undefined). 로그 출력에 바로 쓴다.
113
114
  - ngtscProgram?: NgtscProgram — NgtscProgram 참조(Angular only, HMR 용). non-Angular 이면 undefined.
114
115
  - emitResults?: EmitResult[] — Angular emit 결과 배열. 각 항목 `{ filename; contents; sourceFileName }`(sourceFileName = 원본 소스 경로). non-Angular 은 writeFile 훅으로 디스크에 직접 쓰므로 undefined. 메모리상 컴파일 결과가 필요한 플러그인이 소비.
115
- - lint?: LintWithProgramResult — lint 결과(`lint: true` 일 때만).
116
+ - lint?: LintWithProgramResult — lint 결과(`lint: true` 일 때만). `{ success; errorCount; warningCount; formattedOutput }` 형상.
116
117
  - scssErrors: string[] — SCSS 컴파일 에러 목록.
117
118
  - scssDependencies: ReadonlyMap<string, ReadonlySet<string>> — SCSS 의존성 맵(소유자 파일 → 의존 SCSS 경로 집합). watch 역방향 탐색용.
@@ -1,6 +1,6 @@
1
1
  # @simplysm/sd-cli — sd.config.ts 설정 타입
2
2
 
3
- 프로젝트 루트 `sd.config.ts` 작성·수정 시 함께 읽히는 타입 묶음. `sd.config.ts` 는 `SdConfigFn` default export 해야 한다. 권위 소스는 `packages/sd-cli/src/sd-config.types.ts`. 모든 타입은 `import type { ... } from "@simplysm/sd-cli"` 로 가져온다.
3
+ 프로젝트 루트 `sd.config.ts` 작성·수정 시 함께 읽히는 타입 묶음. `sd.config.ts` 는 `SdConfigFn` 형태의 함수를 default export 해야 하며, 반환값 `SdConfig` 의 `packages` 맵에 각 패키지를 타겟별 설정으로 채운다. 모든 타입은 `import type { ... } from "@simplysm/sd-cli"` 로 가져온다.
4
4
 
5
5
  ## SdConfigFn / SdConfigParams / SdConfig
6
6
 
@@ -22,15 +22,15 @@ interface SdConfig {
22
22
 
23
23
  `SdConfigParams` (sd-cli 가 설정 함수에 주입):
24
24
 
25
- - cwd: string — 현재 작업 디렉토리(워크스페이스 루트). 설정에서 경로를 절대화할 때 쓴다.
26
- - dev: boolean — 개발 모드 플래그. true 면 dev 실행(watch/dev). env·publish 모드별로 분기할 때 쓴다.
27
- - opt: string[] — CLI 의 `-o` 플래그로 넘어온 추가 옵션 배열. 임의 빌드 변형(예: 특정 환경 타겟)을 분기할 쓴다.
25
+ - cwd: string — 현재 작업 디렉토리(워크스페이스 루트). 설정에서 경로를 절대화할 때 기준.
26
+ - dev: boolean — 개발 모드 플래그. true 면 dev 실행(watch/dev) 중. env·빌드 타겟을 dev/prod 분기할 때.
27
+ - opt: string[] — CLI 의 `-o` 플래그로 넘어온 추가 옵션 배열. 특정 옵션이 들어왔을 때만 패키지를 켜는 식의 임의 빌드 변형에.
28
28
 
29
29
  `SdConfig`:
30
30
 
31
- - packages: Record<string, SdPackageConfig | undefined> — 키는 `packages/` 하위 디렉토리명(예: `"core-common"`), 값은 해당 패키지 빌드 설정. `undefined` 면 그 패키지를 빌드 대상에서 제외. 워크스페이스의 어떤 패키지를 어떤 타겟으로 빌드할지 한 곳에 모은다.
32
- - replaceDeps?: Record<string, string> — 의존성 교체(심링크). 키는 node_modules 에서 찾을 패키지 glob(예: `"@simplysm/*"`), 값은 로컬 소스 디렉토리 경로로 키의 `*` 캡처가 값의 `*` 에 치환됨(예: `"../simplysm/packages/*"`). 배포된 패키지 대신 로컬 소스를 곧바로 쓰고 싶을 때.
33
- - postPublish?: SdPostPublishScriptConfig[] — 배포 완료 후 순차 실행할 스크립트 목록. 배포 후 알림·태깅후처리에 쓴다.
31
+ - packages: Record<string, SdPackageConfig | undefined> — 키는 `packages/` 하위 디렉토리명(예: `"core-common"`), 값은 빌드 설정. `undefined` 면 그 패키지를 빌드 대상에서 제외. 어떤 패키지를 어떤 타겟으로 빌드할지 한 곳에 모은다.
32
+ - replaceDeps?: Record<string, string> — 의존성 교체(심링크). 키는 node_modules 에서 찾을 패키지 glob(예: `"@simplysm/*"`), 값은 로컬 소스 디렉토리 경로로 키의 `*` 캡처가 값의 `*` 에 치환됨(예: `"../simplysm/packages/*"`). 배포된 패키지 대신 로컬 소스를 곧바로 물려 디버깅할 때.
33
+ - postPublish?: SdPostPublishScriptConfig[] — 배포 완료 후 순차 실행할 스크립트 목록. 배포 후 태깅·알림후처리에.
34
34
 
35
35
  사용 예:
36
36
 
@@ -59,7 +59,7 @@ type SdPackageConfig =
59
59
 
60
60
  판별자는 `target`. enum literal 별 의미:
61
61
 
62
- - "node" / "browser" / "neutral" (→ `SdBuildPackageConfig`) — esbuild 라이브러리 패키지. "node" = Node.js 전용, "browser" = 브라우저 전용, "neutral" = 공용. npm 배포 라이브러리에 쓴다.
62
+ - "node" / "browser" / "neutral" (→ `SdBuildPackageConfig`) — esbuild 라이브러리 패키지. "node" = Node.js 전용, "browser" = 브라우저 전용, "neutral" = 양쪽 공용. npm 배포 라이브러리에 쓴다.
63
63
  - "client" (→ `SdClientPackageConfig`) — Frontend 앱(Angular + Capacitor/Electron/PWA 옵션). esbuild + define 으로 env 주입.
64
64
  - "server" (→ `SdServerPackageConfig`) — Fastify 서버 앱. esbuild banner 로 env 주입, PM2 옵션.
65
65
  - "scripts" (→ `SdScriptsPackageConfig`) — 유틸 패키지. watch 훅이 없으면 watch/typecheck 대상에서 제외됨.
@@ -97,13 +97,13 @@ interface SdClientPackageConfig {
97
97
  }
98
98
  ```
99
99
 
100
- - server: string | number — 연결할 dev 서버. string = 서버 패키지명(예: `"demo-server"`), number = 포트 직접 지정(하위 호환). 보통 같은 워크스페이스의 서버 패키지명을 준다.
100
+ - server: string | number — 연결할 서버. string = 서버 패키지명(예: `"demo-server"`), number = 포트 직접 지정(하위 호환). 보통 같은 워크스페이스의 서버 패키지명을 준다.
101
101
  - env?: Record<string, string> — 빌드 시 `process.env` 를 객체로 치환할 환경 변수. 프론트 코드에 빌드 타임 상수를 주입할 때.
102
- - publish?: SdPublishConfig — 산출물 배포 설정.
102
+ - publish?: SdPublishConfig — 산출물 배포 설정. 미지정 시 배포 안 함.
103
103
  - capacitor?: SdCapacitorConfig — Capacitor 모바일 앱 패키징 설정. 지정 시 Android 등으로 패키징.
104
104
  - electron?: SdElectronConfig — Electron 데스크톱 앱 패키징 설정.
105
- - configs?: Record<string, unknown> — 런타임 설정. 빌드 시 `dist/.config.json` 으로 기록되어 앱이 런타임에 읽음. 배포 환경별 가변 값.
106
- - exclude?: string[] — Capacitor/Electron `package.json` 에 추가(번들 제외)할 패키지 목록.
105
+ - configs?: Record<string, unknown> — 런타임 설정. 빌드 시 `dist/.config.json` 으로 기록되어 앱이 런타임에 읽음. 배포 환경별 가변 값에.
106
+ - exclude?: string[] — Capacitor/Electron `package.json` 에 추가(번들에서 빼 외부 패키지로 둘)할 패키지 목록.
107
107
  - browserSupport?: SdBrowserSupportConfig — 브라우저 호환(browserslist/PostCSS/legacyModule) 설정.
108
108
  - pwa?: false | SdPwaConfig — PWA 설정. `false` 면 비활성화, 미지정 시 기본값으로 활성화, 객체면 manifest 커스텀. PWA 가 필요 없으면 `false`.
109
109
 
@@ -122,9 +122,10 @@ interface SdServerPackageConfig {
122
122
  ```
123
123
 
124
124
  - env?: Record<string, string> — 빌드 시 `process.env.KEY` 를 상수로 치환(esbuild banner). 서버 빌드 타임 상수 주입.
125
+ - publish?: SdPublishConfig — 산출물 배포 설정.
125
126
  - configs?: Record<string, unknown> — 런타임 설정. `dist/.config.json` 으로 기록.
126
127
  - externals?: string[] — esbuild 번들에 포함하지 않을 외부 모듈. 자동 `binding.gyp` 감지 항목에 더해짐. 네이티브 모듈을 번들에서 뺄 때.
127
- - pm2?.name?: string — PM2 프로세스 이름. 미지정 시 `package.json` name 에서 생성. 지정 시 `dist/pm2.config.cjs` 생성.
128
+ - pm2?.name?: string — PM2 프로세스 이름. 미지정 시 `package.json` name 에서 생성. `pm2` 지정 시 `dist/pm2.config.cjs` 생성.
128
129
  - pm2?.ignoreWatchPaths?: string[] — PM2 watch 에서 제외할 경로.
129
130
  - packageManager?: "volta" | "mise" — 산출물에 생성할 패키지 매니저 설정 종류. "volta" = volta 설정, "mise" = `mise.toml` 생성. 배포 서버의 매니저에 맞춘다.
130
131
 
@@ -138,6 +139,7 @@ interface SdScriptsPackageConfig {
138
139
  }
139
140
  ```
140
141
 
142
+ - publish?: SdPublishConfig — 산출물 배포 설정.
141
143
  - watch?: SdWatchHookConfig — watch 훅. 지정해야만 이 패키지가 watch 모드에 포함됨(미지정 시 watch/typecheck 제외). 파일 변경 시 임의 명령 실행에 쓴다.
142
144
 
143
145
  ## SdWatchHookConfig
@@ -174,6 +176,7 @@ interface SdPostPublishScriptConfig {
174
176
  }
175
177
  ```
176
178
 
179
+ - type: "script" — 후처리 스크립트임을 나타내는 판별자(고정).
177
180
  - cmd: string — 배포 후 실행할 명령어.
178
181
  - args: string[] — 인수. `%VER%`(버전), `%PROJECT%`(프로젝트명) 치환됨.
179
182
 
@@ -221,7 +224,7 @@ interface SdCapacitorPermission { name: string; maxSdkVersion?: number; ignore?:
221
224
  interface SdCapacitorIntentFilter { action?: string; category?: string; }
222
225
  ```
223
226
 
224
- - SdCapacitorSignConfig.keystore — keystore 파일 경로(패키지 기준 상대). storePassword/alias/password = 서명 자격. keystoreType?: string — keystore 타입(기본값 `"jks"`).
227
+ - SdCapacitorSignConfig.keystore — keystore 파일 경로(패키지 기준 상대). storePassword/alias/password = 서명 자격증명. keystoreType?: string — keystore 타입(기본값 `"jks"`).
225
228
  - SdCapacitorPermission.name — 권한 이름(예: `"CAMERA"`). maxSdkVersion?: number — 권한 적용 최대 SDK. ignore?: string — `tools:ignore` 속성 값.
226
229
  - SdCapacitorIntentFilter.action — intent 액션(예: `"android.intent.action.VIEW"`). category — intent 카테고리(예: `"android.intent.category.DEFAULT"`).
227
230
 
@@ -263,8 +266,9 @@ interface SdPwaManifestConfig {
263
266
 
264
267
  - manifest?: SdPwaManifestConfig — PWA manifest 커스터마이징. 미지정 시 기본 manifest.
265
268
  - display?: "standalone"|"fullscreen"|"minimal-ui"|"browser" — 앱 표시 모드. "standalone" = 브라우저 UI 없는 앱 창, "fullscreen" = 전체 화면, "minimal-ui" = 최소 브라우저 UI, "browser" = 일반 탭. 네이티브 느낌이면 "standalone".
266
- - name/short_name/theme_color/background_color — manifest 표준 필드(이름·축약명·테마색·배경색).
267
- - icons?: Array<{ src; sizes; type? }> manifest 아이콘 목록(경로·크기·MIME).
269
+ - name/short_name — manifest 앱 이름 / 짧은 이름.
270
+ - theme_color/background_color manifest 테마 / 배경 색.
271
+ - icons?: Array<{ src; sizes; type? }> — manifest 아이콘 목록. src = 경로, sizes = 크기(예: `"512x512"`), type = MIME 타입.
268
272
 
269
273
  ## SdBrowserSupportConfig (client 의 browserSupport)
270
274
 
@@ -284,8 +288,8 @@ interface SdBrowserSupportConfig {
284
288
 
285
289
  ```typescript
286
290
  type BuildTarget = "node" | "browser" | "neutral";
287
- interface NpmConfig { name; version; description?; dependencies?; devDependencies?; peerDependencies?; volta?; }
291
+ interface NpmConfig { name: string; version: string; description?: string; dependencies?: Record<string,string>; devDependencies?: Record<string,string>; peerDependencies?: Record<string,string>; volta?: unknown; }
288
292
  ```
289
293
 
290
- - BuildTarget — esbuild 라이브러리 빌드 런타임 타겟 enum(위 `SdPackageConfig` 풀이 참조).
291
- - NpmConfig — `package.json` 구조 타입. name/version 필수, 나머지 선택. package.json 을 타입 안전하게 다룰 때.
294
+ - BuildTarget — esbuild 라이브러리 빌드 런타임 타겟 enum. "node" = Node 전용, "browser" = 브라우저 전용, "neutral" = 공용(위 `SdPackageConfig` 풀이와 동일).
295
+ - NpmConfig — `package.json` 구조 타입. name/version 필수, description/dependencies/devDependencies/peerDependencies/volta 선택. package.json 을 타입 안전하게 다룰 때.
@@ -1,6 +1,6 @@
1
1
  # @simplysm/service-client
2
2
 
3
- WebSocket 으로 서비스 서버(`@simplysm/service-server`)에 접속해 서비스 메서드 RPC 호출·서버 푸시 이벤트 구독/발행·파일 업/다운로드·서버측 ORM 원격 실행을 수행하는 클라이언트. 브라우저(DOM Worker)와 Node.js(글로벌 `WebSocket` 없으면 `ws` 로 polyfill, `worker_threads`) 양쪽에서 동작.
3
+ WebSocket 으로 서비스 서버에 접속해 서비스 RPC 호출·서버 푸시 이벤트 구독/발행·파일 업/다운로드·서버측 ORM 원격 실행을 수행하는 클라이언트. 브라우저와 Node.js 양쪽에서 동작(Node 에서 글로벌 `WebSocket` 없으면 모듈 로드 시 `ws` 로 polyfill).
4
4
 
5
5
  ## 사용 트리거 인덱스
6
6
 
@@ -32,7 +32,7 @@ WebSocket 으로 서비스 서버(`@simplysm/service-server`)에 접속해 서
32
32
  - connect(): Promise\<void\> — 서버에 WebSocket 연결. 초기 연결 실패 시 throw. 통신(서비스 호출·이벤트 등록) 전에 반드시 1회 호출.
33
33
  - close(): Promise\<void\> — 연결 수동 종료(이후 자동 재연결 안 함) 및 프로토콜 워커 자원 해제. 종료한 인스턴스는 재사용하지 말 것.
34
34
  - send(serviceName, methodName, params, progress?): Promise\<unknown\> — 저수준 서비스 호출. `serviceName.methodName` 메시지를 보내고 응답 반환. 보통 `getService` 프록시로 간접 호출. progress 인자를 주지 않아도 client 의 `request/response/server-progress` 이벤트는 항상 발생.
35
- - auth(token): Promise\<void\> — 인증 토큰 전송 후 내부 보관. 보관 토큰은 재연결 시 자동 재인증·파일 업로드 Bearer 인증에 재사용.
35
+ - auth(token): Promise\<void\> — 인증 토큰 전송 후 내부 보관. 보관 토큰은 재연결 시 자동 재인증·파일 업로드 Bearer 인증에 재사용. 파일 업로드 전에는 반드시 선행.
36
36
  - getService / getEvent / addListener / removeListener / emitEvent / uploadFile / downloadFileBuffer — 아래 각 섹션 참조.
37
37
 
38
38
  ```ts
@@ -69,7 +69,7 @@ client.on("state", (s) => { if (s === "reconnecting") showOfflineBanner(); });
69
69
 
70
70
  - TService — 서버 서비스 메서드 인터페이스 타입. 컴파일 타임 시그니처 검증용(런타임 검증 아님). 앱에선 server 패키지가 export 한 `ServiceMethods<typeof XxxService>` 사용.
71
71
  - serviceName: string — 서버의 `defineService("XxxName", ...)` 이름과 일치해야 함.
72
- - ServiceProxy\<TService\> — TService 의 각 함수 멤버를 `(...args) => Promise<Awaited<R>>` 로 매핑. 함수 아닌 속성은 `never` 로 제외.
72
+ - ServiceProxy\<TService\> — TService 의 각 함수 멤버를 `(...args) => Promise<Awaited<R>>` 로 매핑하는 타입 변환기. 원본이 동기 반환이어도 Promise 로 래핑됨. 함수 아닌 속성은 `never` 로 제외.
73
73
 
74
74
  ```ts
75
75
  const svc = client.getService<TestServiceMethods>("TestService");
@@ -80,22 +80,26 @@ const result = await svc.echo("hi"); // 서버 TestService.echo("hi") 호출, Pr
80
80
 
81
81
  서버 푸시 이벤트는 `@simplysm/service-common` 의 `defineEvent` 산출물(`ServiceEventDef`. `$info` = 구독 필터 정보 타입, `$data` = 페이로드 타입) 단위로 다룬다. 등록한 리스너는 재연결 시 자동 복구됨.
82
82
 
83
- `addListener<TEventDef>(eventDef, info, cb): Promise<string>` — 리스너 등록. 미연결(`connected === false`)이면 throw. 반환 key 로 나중에 제거.
83
+ `addListener<TEventDef>(eventDef, info, cb): Promise<string>` — 리스너 등록. 미연결(`connected === false`)이면 throw("서버에 연결되지 않았습니다."). 반환 key 로 나중에 제거.
84
84
 
85
85
  - eventDef: TEventDef — 이벤트 정의(`defineEvent` 결과). `$info`/`$data` 타입의 출처.
86
- - info: TEventDef["$info"] — 이 구독을 식별·필터링할 정보. 서버가 emit 대상 선별에 사용.
86
+ - info: TEventDef["$info"] — 이 구독을 식별·필터링할 정보. 발행측 selector 값을 보고 전달 여부 결정.
87
87
  - cb: (data: $data) => PromiseLike\<void\> — 이벤트 수신 콜백. 콜백 내 예외는 로깅만 되고 호출부로 전파되지 않음.
88
88
 
89
89
  `removeListener(key): Promise<void>` — 등록 key 로 리스너 제거. 서버 전송 실패(연결 끊김 등)는 무시(서버가 끊김 시 리스너를 자동 정리하므로 안전).
90
90
 
91
- `emitEvent<TEventDef>(eventDef, infoSelector, data): Promise<void>` — 이벤트 발행. 서버에서 동일 이벤트 구독자 목록을 조회한 뒤 `infoSelector(info)` 가 true 인 대상에게만 data 전송.
91
+ `emitEvent<TEventDef>(eventDef, infoSelector, data): Promise<void>` — 이벤트 발행. 서버에서 동일 이벤트 구독자 목록을 조회한 뒤 `infoSelector(info)` 가 true 인 대상에게만 data 전송. 매칭 대상이 0개면 전송 자체를 생략.
92
92
 
93
- - infoSelector: (item: $info) => boolean — 발행 대상 구독자를 info 기준으로 필터. true 반환 구독자에게만 전달.
93
+ - infoSelector: (item: $info) => boolean — 발행 대상 구독자를 info 기준으로 필터. true 반환 구독자에게만 전달. 전체 전송이면 `() => true`.
94
94
  - data: TEventDef["$data"] — 전송 페이로드.
95
95
 
96
96
  `getEvent<TEventDef>(eventDef): ClientEventProxy<TEventDef>` — 특정 eventDef 에 바인딩된 프록시 반환. eventDef 를 매번 넘기지 않고 짧게 쓰려 할 때(앱의 `AppServiceProvider.xxxEvent` getter 패턴).
97
97
 
98
- `ClientEventProxy<TEventDef>` 멤버: `addListener(info, cb)`, `removeListener(key)`, `emit(infoSelector, data)` — 위 client 메서드의 eventDef 고정판.
98
+ `ClientEventProxy<TEventDef>` 멤버(위 client 메서드의 eventDef 고정판):
99
+
100
+ - addListener(info, cb): Promise\<string\> — 리스너 등록.
101
+ - removeListener(key): Promise\<void\> — 리스너 제거.
102
+ - emit(infoSelector, data): Promise\<void\> — 이벤트 발행.
99
103
 
100
104
  ```ts
101
105
  const chatEvent = defineEvent<{ channel: string }, string>("Chat");
@@ -104,7 +108,7 @@ await client.emitEvent(chatEvent, (info) => info.channel === "room1", "hello");
104
108
  await client.removeListener(key);
105
109
  ```
106
110
 
107
- `EventClient` / `createEventClient(transport)` 는 `ServiceClient` 가 내부 조립에 쓰는 저수준 구현. 위 메서드에 더해 `resubscribeAll(): Promise<void>`(보관된 모든 리스너를 서버에 재등록, 재연결 복구용)를 가짐. 일반 사용에선 직접 만들지 않음.
111
+ `EventClient` / `createEventClient(transport)` 는 `ServiceClient` 가 내부 조립에 쓰는 저수준 구현. 위 메서드(getEvent/addListener/removeListener/emit)에 더해 `resubscribeAll(): Promise<void>`(보관된 모든 리스너를 서버에 재등록, 재연결 복구용)를 가짐. 일반 사용에선 직접 만들지 않음.
108
112
 
109
113
  ## 파일 업/다운로드 (uploadFile / downloadFileBuffer)
110
114
 
@@ -142,6 +146,10 @@ const bytes = await client.downloadFileBuffer("/files/a.txt");
142
146
 
143
147
  전역 추적이면 콜백 대신 ServiceClient 의 `request/response/server-progress` 이벤트(`client.on("response-progress", ...)`)를 써도 됨 — `send` 는 progress 인자 유무와 무관하게 이 이벤트들을 항상 발생시킴.
144
148
 
149
+ ```ts
150
+ client.on("response-progress", (s) => updateBar(s.completedSize / s.totalSize));
151
+ ```
152
+
145
153
  ## 환경 호환 타입·헬퍼 (browser-compat)
146
154
 
147
155
  Node/browser 공용 코드에서 DOM 전용 타입을 피하고 Worker 지원 여부를 분기하기 위한 타입·함수. 프로토콜 인코딩/파싱 Worker 오프로딩 판단 시 내부에서 사용.
@@ -149,6 +157,6 @@ Node/browser 공용 코드에서 DOM 전용 타입을 피하고 Worker 지원
149
157
  - BlobInput = `Blob | Uint8Array<ArrayBuffer> | ArrayBuffer | string` — `Blob` 생성자가 받는 데이터 타입(DOM `BlobPart` 대체). `uploadFile` 의 커스텀 객체 data 타입.
150
158
  - FileCollection (interface) — DOM `FileList` 대체. `length`, `item(index): File | null`, 인덱스 접근, `[Symbol.iterator]` 보유. 브라우저 `FileList` 와 구조적 호환.
151
159
  - BrowserWorker (interface) — DOM `Worker` 최소 인터페이스(`onmessage`/`onerror` 핸들러, `postMessage(message, transfer?)`, `terminate()`). DOM lib 없이 타입체크 통과용.
152
- - isBrowserWorkerSupported(): boolean — `globalThis` 에 `Worker` 존재 여부. 브라우저 DOM Worker 가용 판단.
153
- - isNodeWorkerSupported(): boolean — `process.versions.node` 존재 여부. Node `worker_threads` 가용 판단.
154
- - isWorkerSupported(): boolean — 위 둘 중 하나라도 true. 프로토콜 인코딩/파싱 오프로딩 가능 여부 판단(미지원 시 메인 스레드 폴백).
160
+ - isBrowserWorkerSupported(): boolean — `globalThis` 에 `Worker` 존재 여부 반환. 브라우저 DOM Worker 가용 판단.
161
+ - isNodeWorkerSupported(): boolean — `process.versions.node` 존재 여부 반환. Node `worker_threads` 가용 판단.
162
+ - isWorkerSupported(): boolean — 위 둘 중 하나라도 true 면 true. 프로토콜 인코딩/파싱 오프로딩 가능 여부 판단(미지원 시 메인 스레드 폴백).
@@ -10,8 +10,8 @@
10
10
 
11
11
  `OrmClientConnector` 메서드:
12
12
 
13
- - connect<T, R>(config, callback): Promise\<R\> — 트랜잭션 안에서 callback 실행. DbContext 생성 → `db.connect(...)`(connect + beginTransaction + callback + commit/rollback) 수행. callback 정상 반환 시 커밋(반환값이 그대로 반환됨), throw 시 롤백되어 콜백 내 다건 작업이 원자 처리됨. callback 에서 발생한 에러 중 외래키 제약 위반 메시지(`a parent row: a foreign key constraint` / `conflicted with the REFERENCE`)는 "경고! 연관된 작업으로 인해 작업이 거부되었습니다. 후속 작업을 확인해 주세요." 로 감싸 throw(원본은 `cause` 에 보존), 그 외 에러는 그대로 throw.
14
- - connectWithoutTransaction<T, R>(config, callback): Promise\<R\> — 트랜잭션 없이 callback 실행(`db.connectWithoutTransaction`). 트랜잭션 안에서 동작하지 않는 작업(예: DB initialize)·조회 전용 작업에 사용. callback 반환값이 그대로 반환됨.
13
+ - connect<T, R>(config, callback): Promise\<R\> — 트랜잭션 안에서 callback 실행. DbContext 생성 → `db.connect(...)`(connect + beginTransaction + callback + commit/rollback) 수행. callback 정상 반환 시 커밋(반환값이 그대로 반환됨), throw 시 롤백되어 콜백 내 다건 작업이 원자 처리됨. callback 에서 발생한 에러 중 외래키 제약 위반 메시지(MySQL `a parent row: a foreign key constraint` / MSSQL `conflicted with the REFERENCE` / PostgreSQL `violates foreign key constraint`)는 "경고! 연관된 작업으로 인해 작업이 거부되었습니다. 후속 작업을 확인해 주세요." 로 감싸 `SdError` 로 throw(원본은 cause 에 보존), 그 외 에러는 그대로 throw.
14
+ - connectWithoutTransaction<T, R>(config, callback): Promise\<R\> — 트랜잭션 없이 callback 실행(`db.connectWithoutTransaction`). 트랜잭션 안에서 동작하지 않는 작업(예: DB initialize)·조회 전용 작업에 사용. callback 반환값이 그대로 반환됨. 외래키 메시지 래핑 없음.
15
15
 
16
16
  공통 인자:
17
17
 
@@ -34,20 +34,20 @@ const rows = await connector.connect(
34
34
  - connOpt: `DbConnOptions & { configName: string }` — 서버측 ORM 연결 설정. `configName` 은 서버에 등록된 ORM 설정 이름(서버가 이 이름으로 실제 DB 접속 정보를 찾음). 나머지 필드는 `@simplysm/service-common` 의 `DbConnOptions`.
35
35
  - dbContextOpt?: `{ database: string; schema?: string }` — DbContext 에 적용할 DB명·스키마. 생략 시 서버 `getInfo()` 가 돌려준 `database`/`schema` 를 사용. database 가 옵션·서버 양쪽 모두 비어 있으면 throw("database는 필수입니다." — 결측을 임의 보정하지 않음).
36
36
  - database: string — 대상 데이터베이스명.
37
- - schema?: string — 대상 스키마명(미지정 시 서버 기본값).
37
+ - schema?: string — 대상 스키마명. 미지정 시 서버 `getInfo()` 의 schema 를 사용.
38
38
 
39
39
  ## OrmClientDbContextExecutor
40
40
 
41
41
  `DbContextExecutor`(`@simplysm/orm-common`) 구현체. 모든 메서드를 `client.getService<OrmService>("Orm")` RPC 로 위임. 커넥터가 내부에서 DbContext 에 주입하므로 직접 생성·호출은 보통 불필요.
42
42
 
43
- `new OrmClientDbContextExecutor(client, opt)` — 생성. opt = `DbConnOptions & { configName: string }`. 생성 시 `Orm` 서비스 프록시 확보.
43
+ `new OrmClientDbContextExecutor(client, opt)` — 생성. opt = `DbConnOptions & { configName: string }`. 생성 시 `Orm` 서비스 프록시 확보. 아래 connect 이외의 실행 메서드는 connId 가 없으면(미연결) throw("데이터베이스에 연결되지 않았습니다.").
44
44
 
45
45
  - getInfo(): `Promise<{ dialect; database?; schema? }>` — 서버 ORM 설정 정보(방언·기본 DB명·스키마) 조회. 커넥터가 dbContextOpt 미지정 시 fallback 으로 사용.
46
- - connect(): Promise\<void\> — 서버에 커넥션 생성, 반환된 connId 를 내부 보관. 이후 트랜잭션·쿼리 호출의 핸들. 이후 모든 실행 메서드는 connId 없으면(미연결) throw.
46
+ - connect(): Promise\<void\> — 서버에 커넥션 생성, 반환된 connId 를 내부 보관. 이후 트랜잭션·쿼리 호출의 핸들.
47
47
  - beginTransaction(isolationLevel?): Promise\<void\> — 트랜잭션 시작. isolationLevel(orm-common `IsolationLevel`) 미지정 시 서버 기본값.
48
48
  - commitTransaction(): Promise\<void\> — 트랜잭션 커밋.
49
49
  - rollbackTransaction(): Promise\<void\> — 트랜잭션 롤백.
50
50
  - close(): Promise\<void\> — 커넥션 종료 후 보관 connId 해제.
51
51
  - executeDefs\<T\>(defs, options?): Promise\<T[][]\> — 쿼리 정의 배열(`QueryDef[]`)을 서버에서 실행. options 는 정의별 결과 매핑 메타(`(ResultMeta | undefined)[]`, 항목별 nullable)로 행 역직렬화 방식 지정. 정의 1개당 결과 배열 1개를 가진 2차원 배열 반환.
52
52
  - executeParametrized(query, params?): Promise\<unknown[][]\> — 파라미터 바인딩 raw SQL 실행. query = SQL 문자열, params = 바인딩 값 배열.
53
- - bulkInsert(tableName, columnDefs, records): Promise\<void\> — 대량 삽입. columnDefs(`Record<string, ColumnMeta>`)로 컬럼별 메타를, records 로 삽입할 행 객체 배열을 전달.
53
+ - bulkInsert(tableName, columnDefs, records): Promise\<void\> — 대량 삽입. tableName = 대상 테이블명, columnDefs(`Record<string, ColumnMeta>`)로 컬럼별 메타를, records(`Record<string, unknown>[]`)로 삽입할 행 객체 배열을 전달.