@g1cloud/entity-modeler-next 5.2.27 → 5.2.29

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.
@@ -1,4 +1,4 @@
1
- import { Entity, Association, Attribute, DbColumn, DisplayMode, EmbeddableCatalog, PredefinedCustomTypeCatalog, PredefinedCustomTypeEntry } from './types';
1
+ import { Entity, Association, Attribute, DbColumn, DisplayMode, EmbeddableCatalog, EmbeddableCatalogEntry, PredefinedCustomTypeCatalog, PredefinedCustomTypeEntry } from './types';
2
2
  export interface JavaTypeDef {
3
3
  /** 저장값 = 레거시 enum 상수명. Attribute.type에 그대로 들어간다. */
4
4
  value: string;
@@ -42,10 +42,22 @@ export declare function javaTypeFromDataType(dataType: string | undefined): stri
42
42
  * 자바 타입 ↔ 물리 DB 타입 호환 판정. `CHK-TYPE-7`의 판정 산식(단일 출처).
43
43
  *
44
44
  * 반환값 3-상태: `true` 호환 · `false` 부정합 · **`undefined` 판정 불가**(호출자는 skip한다). undefined는
45
- * ①어느 한쪽이 빈값 ②자바 타입이 `DATA_TYPES_BY_JAVA_TYPE` 밖(임베더블·주입 customtype·CustomType)
45
+ * ①어느 한쪽이 빈값 ②자바 타입이 `DATA_TYPES_BY_JAVA_TYPE` 밖이고 주입 카탈로그에도 없음
46
46
  * ③물리 타입이 `ALL_DATA_TYPES` 밖(미지 값 — 그 축은 `CHK-TYPE-1`이 타깃 다이얼렉트 기준으로 지목한다.
47
47
  * 여기서 함께 신고하면 한 컬럼에 두 경고가 겹치고 사용자가 할 일이 갈린다).
48
48
  *
49
+ * ★★**③ predefined customtype 축은 «주입될 때만» 판정한다**(2026-09-04 신설 · `predefinedCustomTypes`).
50
+ * 계기 = 사용자 질문 *「MultiLangString 지정하고 JSONB 설정 안 한 경우 경고가 있어?」* → 없었고, 이유가
51
+ * **규칙 부재가 아니라 이 함수의 구조적 skip** 이었다(그 타입들은 lib 정적 표에 «없는 것이 정상»이다 —
52
+ * 호스트 주입이므로). 전수 실측 861컬럼: `MultiLangString` **JSONB 287/289** · `StoredFile` 1/1 ·
53
+ * `GroupCodeEnum` VARCHAR 515/518 · ★`CustomType` **지배 형상 없음**(JSONB 27·CLOB 17·VARCHAR 8종).
54
+ * ⇒ ★**lib 에 표를 박지 않는 이유가 바로 그 마지막 줄이다** — 규약의 소유자는 호스트 카탈로그이고
55
+ * 코어가 `MultiLangString → JSONB` 를 안다고 적으면 그건 모델러 밖 지식의 하드코딩이다.
56
+ * ⚠️**엔트리의 `dataType` 을 「시드 기본값」이자 「허용 기준」으로 겸용**한다(축 신설 0). 실측이 단일
57
+ * 형상(99%)이라 지금은 같은 값이지만, **한 타입에 복수 물리 타입이 정당해지면 그때 엔트리에 허용 집합을
58
+ * 신설**한다(그 전까지 집합 축을 미리 만들면 쓰이지 않는 표현이 하나 는다). 미주입이면 **inert** —
59
+ * `reservedWords`·`selectableDataTypes` 와 같은 ctx 게이트다.
60
+ *
49
61
  * ★★**정수형 × `NUMERIC`/`DECIMAL`은 정밀도 무관 호환**이다(2026-08-24 운영 DB 실측으로 확정).
50
62
  * 이 자리에 한때 *"무정밀도면 부정합"* 조건이 있었고 **실측이 그것을 무너뜨렸다** — 근거 이력을 남긴다:
51
63
  * · 1차 근거는 실물 **Java 필드 타입**이었다(`private int`이므로 컬럼도 정수여야 한다).
@@ -60,7 +72,7 @@ export declare function javaTypeFromDataType(dataType: string | undefined): stri
60
72
  * Hibernate 가 아니라 마이그레이션이 만들고(`dbTypes.ts` 주석), Hibernate 는 정수 필드의 `precision`을
61
73
  * 무시하므로 어노테이션은 *의도*일 뿐이다.
62
74
  */
63
- export declare function isJavaDataTypeCompatible(javaType: string | undefined, dataType: string | undefined): boolean | undefined;
75
+ export declare function isJavaDataTypeCompatible(javaType: string | undefined, dataType: string | undefined, predefinedCustomTypes?: PredefinedCustomTypeCatalog): boolean | undefined;
64
76
  /** 저장값 → 박싱 타입명(`PrimitiveInt`→`Integer`). 원시가 아니면 undefined. */
65
77
  export declare function boxedJavaTypeOf(value: string | undefined): string | undefined;
66
78
  /**
@@ -145,12 +157,48 @@ export declare function typeOwner(attr: Pick<Attribute, 'attrType'>): TypeOwner;
145
157
  *
146
158
  * ★소비처가 둘이고 **하는 일이 다르다**: GUI 는 `structural` 을 «자리 보존 전환»(`convertAttributeType`
147
159
  * — 삭제+추가 합성)으로 **처리**하고 나머지는 셀렉트를 잠그며, AI(`agent/resolver`)는 patch 로 표현할
148
- * 수 없으므로 **전부 거부**한다(op 배치는 `attribute.remove`+`attribute.add`(+`reorder`)로 같은 일을
149
- * 낼 수 있어 표현력 부족이 아니다). 판정선만 공유하고 처방은 각자다 — 선이 갈리면 *「GUI 로는 되는데
150
- * AI 로는 조용히 반쪽 적용」* 이 된다.
160
+ * 수 없으므로 거부한다. 판정선만 공유하고 처방은 각자다 — 선이 갈리면 *「GUI 로는 되는데 AI 로는
161
+ * 조용히 반쪽 적용」* 이 된다.
162
+ * ⚠️★**AI 쪽 「전부 거부」는 2026-09-04 에 좁혀졌다** — 컬럼 개수가 «안 바뀌는» 자리는
163
+ * `columnPreservingValueTypeEntry`(아래)가 갈라 내고 그쪽은 in-place patch 로 열려 있다. 이 함수는
164
+ * **여전히 GUI 의 전환 판정 단일 출처**이므로 «건드리지 않았다» — 좁히면 GUI 가 그 형상을 전환이 아닌
165
+ * 단순 update 로 흘려 `attrType` 이 안 따라가는 회귀가 된다(두 물음이 «같은 선»이 아니다).
151
166
  * ★같은 값 재전송(라운드트립 에코)은 변경이 아니므로 거짓이다(`attrType` 게이트의 에코 통과와 동형).
152
167
  */
153
168
  export declare function isStructuralTypeChange(attr: Pick<Attribute, 'attrType' | 'type'>, targetType: string, embeddables: EmbeddableCatalog): boolean;
169
+ /**
170
+ * 이 타입 변경이 **컬럼 개수를 바꾸지 않는** ② 값 타입 재지정인가 — 맞으면 목적지 카탈로그 엔트리를,
171
+ * 아니면 `undefined` 를 돌려준다. AI(op) 경로가 이 자리를 **in-place `{type, attrType}` patch** 로
172
+ * 처리해도 되는지의 단일 출처다.
173
+ *
174
+ * ★**왜 필요했나**(2026-09-04 · 무인화 갭 ④): `isStructuralTypeChange` 는 *「목적지가 ② 임베더블」* 이기만
175
+ * 하면 참이라 **1필드 카탈로그 × 1컬럼 속성**까지 `attribute-type-conversion-unsupported`(reason
176
+ * **`column-count`**)로 막았다 — 이름이 사유를 자칭하는데 **그 사유가 성립하지 않는 자리**다. 실측
177
+ * 근거: 값 타입 배치 **28자리 전량**이 그 형상이라 symbolic-ops 를 못 쓰고 raw `/ops` 로 우회했다.
178
+ *
179
+ * ★★**계약을 «id 보존»(in-place)으로 정한 근거 — 취향이 아니라 손실 논거다**: 같은 착지점을 GUI 는
180
+ * 삭제+추가로 내는데(새 속성 id), AI 의 어휘로 그걸 흉내 내면 **데이터가 사라진다** — `AttrSpec` 에
181
+ * `order` 가 없어 자리가 맨 뒤로 밀리고, `EmbeddableColumnOverride` 에 `logicalName`·`dataType` 이 없어
182
+ * **컬럼 논리명이 조용히 소실**되며(그 배치 실측 27/28 자리 보유), agent 경로엔 `survivingRefs` 가 없어
183
+ * **인덱스 ref 가 끊긴다**. 컬럼 개수가 같으면 `dbAttrs` 를 **modelId 째 그대로** 두면 되므로 그 손실이
184
+ * **전부 발생하지 않는다** ⇒ in-place 가 우월하고, 이 술어가 그 「같을 때」를 정의한다.
185
+ * ★**GUI 는 그대로 «전환»(새 id)이다** — 두 경로의 최종 «모델 상태»는 속성 modelId 를 빼면 같다.
186
+ * 같은 배치에 같은 id 가 `$pull`·`$push` 양쪽에 등장하면 병합 순서에 의존하므로(`convertAttributeType`
187
+ * 헤더) GUI 쪽이 id 를 새로 다는 것도 근거가 있고, 둘 다 각자 자리에서 옳다.
188
+ *
189
+ * 성립 조건 넷 — 하나라도 어긋나면 `undefined`(= 종전 거부 유지):
190
+ * ① 실제 변경일 것(에코 제외) ② 출발이 **컬럼을 가진 값 속성**(`NORMAL`·`EMBED_PREDEF` — `convertAttributeType`
191
+ * 의 진입 규칙과 같다. `EMBED_OWN`·`EMBED_REF` 는 association 이 정체성, `RELATION_*` 은 컬럼이 관계 파생)
192
+ * ③ 목적지가 **② 카탈로그**에 있을 것 ④ 그 필드 수가 **현재 `dbAttrs` 길이와 같을 것**.
193
+ *
194
+ * ⚠️**되돌림(② → `NORMAL`)은 여기서 열지 않는다** — 그 방향은 ③ predefined customtype 목적지에서
195
+ * `seedPredefinedCustomTypeColumn` 이 컬럼 메타를 시드하는데(`convertAttributeType`), resolver 에는 그
196
+ * 카탈로그가 주입되지 않아 **AI 만 시드를 빠뜨린 채 착지**한다(= 조용한 비대칭). 열려면 그 카탈로그
197
+ * 주입이 선행이고, 그때까지는 거부가 정직하다.
198
+ * ⚠️**PK 카디널리티 게이트가 불필요해지는 것도 이 조건 덕분**이다 — `convertAttributeType` 이 막는 것은
199
+ * *컬럼 개수가 바뀌는* PK(1→2 면 자식 FK 미러가 무너진다)이고, 여기는 정의상 개수가 같다.
200
+ */
201
+ export declare function columnPreservingValueTypeEntry(attr: Pick<Attribute, 'attrType' | 'type' | 'dbAttrs'>, targetType: string, embeddables: EmbeddableCatalog): EmbeddableCatalogEntry | undefined;
154
202
  /**
155
203
  * ⑤ 파생 타입 커플링이 깨졌는가 — **`GroupCodeEnum` 과 `groupCode` 결합은 «항상 함께»**다(XOR 이면 깨짐).
156
204
  *
@@ -1,4 +1,4 @@
1
- import { EmbeddableCatalog, LogicalModel, ModelId, SuperClassCatalog } from './types';
1
+ import { EmbeddableCatalog, LogicalModel, ModelId, PredefinedCustomTypeCatalog, SuperClassCatalog } from './types';
2
2
  export declare const PHYSICAL_NAME_MAX_LENGTH = 63;
3
3
  /**
4
4
  * 물리명이 이식성 권장 한도를 초과하면 **초과 길이(문자 수)**, 아니면 null(비차단 — 호출부는 저장을
@@ -62,6 +62,18 @@ export interface ValidationContext {
62
62
  * dangling으로 오탐될 수 있다 — 카탈로그가 주입돼야 정확 판정(로컬 컬럼만 참조하는 모델은 무영향).
63
63
  */
64
64
  superClassCatalog?: SuperClassCatalog;
65
+ /**
66
+ * ③ predefined customtype 카탈로그(`MultiLangString`·`StoredFile` 등 호스트 주입 단일 컬럼 커스텀 타입)
67
+ * — `CHK-TYPE-7` 이 그 타입들의 `dataType` 규약을 판정하는 출처. 미주입이면 종전대로 **판정 불가로 skip**
68
+ * (reservedWords·embeddableCatalog 와 동형 ctx 게이트 = **inert-by-default**).
69
+ *
70
+ * ★**왜 lib 이 표를 안 갖는가**: 이 타입들은 프레임워크 공통분 + 프로젝트별 추가분이라 규약의 소유자가
71
+ * 호스트다(`types.ts` `PredefinedCustomTypeEntry` 주석과 같은 근거). 실측이 그 판단을 뒷받침한다 —
72
+ * `CustomType`(④ 자유 축)은 지배 형상이 아예 없어(JSONB 27·CLOB 17·VARCHAR 8종) 어떤 정적 표도 틀린다.
73
+ * ⚠️주입은 **`ScaffoldOptions.customTypeCatalog`(④ 컨버터 FQN 맵)와 다른 축**이다 — 이름이 비슷해
74
+ * 헷갈리기 쉽다(2026-09-04 착수 실측: 호스트가 주입 중인 것은 ④ 쪽이고 ③ 은 주입 0이었다).
75
+ */
76
+ predefinedCustomTypes?: PredefinedCustomTypeCatalog;
65
77
  }
66
78
  /**
67
79
  * 설계 품질 검증 — 논리 모델(+선택 컨텍스트)을 받아 이슈 목록을 돌려준다.