@g1cloud/entity-modeler-next 5.2.19 → 5.2.21
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/dist/adapter/persisted.d.ts +5 -0
- package/dist/agent/resolver.d.ts +48 -0
- package/dist/agent/symbolicOp.d.ts +7 -0
- package/dist/core/columnResolve.d.ts +20 -0
- package/dist/core/indexCleanup.d.ts +13 -6
- package/dist/core/javaTypes.d.ts +64 -2
- package/dist/core/types.d.ts +20 -0
- package/dist/editor/attribute.d.ts +7 -2
- package/dist/editor/commandPlans.d.ts +2 -2
- package/dist/editor/controller.d.ts +8 -5
- package/dist/entity-modeler-next.css +1 -1
- package/dist/entity-modeler.js +11845 -11722
- package/dist/entity-modeler.umd.cjs +25 -25
- package/dist/i18n/ko.d.ts +1 -1
- package/dist/view/useAttributeEditing.d.ts +5 -0
- package/package.json +1 -1
|
@@ -24,6 +24,11 @@ export interface PDbAttr {
|
|
|
24
24
|
updatable?: boolean;
|
|
25
25
|
/** JPA @Column(insertable=…). undefined=기본 따름. v1 레거시엔 없는 신규 옵션. */
|
|
26
26
|
insertable?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* JPA @Column(nullable=false) — **이 컬럼 하나의** NOT NULL. undefined=속성 축(`notNull`)을 따름.
|
|
29
|
+
* 논리 모델 `DbColumn.notNull` 직렬화(그 주석이 축의 정본). v1 레거시엔 없는 신규 옵션.
|
|
30
|
+
*/
|
|
31
|
+
notNull?: boolean;
|
|
27
32
|
/**
|
|
28
33
|
* 공유 통화 컬럼(SHARED_REF) — 같은 엔터티 내 다른 컬럼 modelId 참조(read-only 투영, 물리 컬럼 0).
|
|
29
34
|
* 논리 모델 DbColumn.sharedColumnRef 직렬화. FK 전파용 targetModelId와는 별개 개념. v1 레거시 없음.
|
package/dist/agent/resolver.d.ts
CHANGED
|
@@ -153,6 +153,24 @@ export type ResolveError = {
|
|
|
153
153
|
entity: Handle;
|
|
154
154
|
handle: Handle;
|
|
155
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* `groupCode` 는 있는데 `type` 이 `GroupCodeEnum` 이 아니다 — 위 `groupcode-required` 의 **반대 방향**.
|
|
158
|
+
*
|
|
159
|
+
* ★커플링은 XOR 이 아니라 **동치**다(`core/javaTypes.isGroupCodeCouplingBroken`). 종전엔 한 방향만
|
|
160
|
+
* 막았고, 그래서 «`groupCode` 는 남긴 채 `type` 만 `String` 으로» 가 add·update 전부 통과했다 —
|
|
161
|
+
* 코드 enum 에 묶인 속성이 평범한 문자열을 방출하는 **깨진 파생**이다. GUI 는 `setAttributeGroupCode`
|
|
162
|
+
* 가 둘을 항상 함께 바꿔 이 상태를 만들 수 없으므로, 막지 않으면 AI 경로에만 생기는 형상이 된다.
|
|
163
|
+
* ⇒ 고칠 자리는 둘 중 하나다: `type` 을 `GroupCodeEnum` 으로 두거나, `groupCode` 를 함께 비우거나
|
|
164
|
+
* (같은 patch 에 둘을 함께 주면 통과한다 — 판정이 **결과 상태** 기준이다).
|
|
165
|
+
*/
|
|
166
|
+
| {
|
|
167
|
+
code: 'groupcode-type-mismatch';
|
|
168
|
+
opIndex: number;
|
|
169
|
+
entity: Handle;
|
|
170
|
+
handle: Handle;
|
|
171
|
+
type: string;
|
|
172
|
+
groupCode: string;
|
|
173
|
+
}
|
|
156
174
|
/** 물리 컬럼을 만들면서 dataType 미지정 — 빈 타입 컬럼은 DDL에서 드롭된다(발명 대신 요구). */
|
|
157
175
|
| {
|
|
158
176
|
code: 'datatype-required';
|
|
@@ -416,6 +434,36 @@ export type ResolveError = {
|
|
|
416
434
|
current: string;
|
|
417
435
|
requested: string;
|
|
418
436
|
}
|
|
437
|
+
/**
|
|
438
|
+
* attribute.update patch의 `type` — **동반 구조가 함께 가야 성립**하는 전환이라 거부.
|
|
439
|
+
*
|
|
440
|
+
* ★위 `attrType` 게이트의 **짝**이다(2026-09-02 신설). 그쪽은 `attrType` 을 직접 준 경우를 막는데,
|
|
441
|
+
* `type` 만 주는 경로가 열려 있었다: `{type:'Money'}` 를 NORMAL 속성에 주면 `type` 만 갈리고
|
|
442
|
+
* `attrType`·`dbAttrs` 는 그대로라 **컬럼 1개짜리 EMBED 아닌 Money** 라는 모순이 남는다(반대로
|
|
443
|
+
* EMBED_PREDEF 에 `{type:'String'}` 를 주면 컬럼 2개짜리 String 이 된다). 통과시키면 그 자리는
|
|
444
|
+
* 코드젠·DDL·검증이 각자 다르게 읽는 **조용한 반쪽 적용**이고, `attrType` 게이트가 막으려던 *「아무도
|
|
445
|
+
* 관리하지 않는데 사용자도 고칠 수 없는」* 상태의 같은 부류다. ⚠️GUI 는 같은 조작을 **지원**하므로
|
|
446
|
+
* (`editor/attribute.convertAttributeType` — 삭제+추가 합성) 막지 않으면 *「GUI 로는 되는데 AI 로는
|
|
447
|
+
* 조용히 깨진다」* 가 된다. 판정선은 `core/javaTypes.isStructuralTypeChange` 로 **공유**한다.
|
|
448
|
+
* ⇒ 대안이 실재하므로 표현력 부족이 아니다 — `reason` 이 그 경로를 지목한다.
|
|
449
|
+
*/
|
|
450
|
+
| {
|
|
451
|
+
code: 'attribute-type-conversion-unsupported';
|
|
452
|
+
opIndex: number;
|
|
453
|
+
entity: Handle;
|
|
454
|
+
handle: Handle;
|
|
455
|
+
/**
|
|
456
|
+
* `core/javaTypes.typeOwner` 의 부류를 그대로 전달한다 — **사용자가 갈 곳이 갈린다**:
|
|
457
|
+
* - `column-count` — 컬럼 개수 축이 갈린다(`EMBED_PREDEF` 출발 또는 ② 임베더블 목적지)
|
|
458
|
+
* ⇒ **`attribute.remove` + `attribute.add`**(+ 자리 복원이 필요하면 `attribute.reorder`).
|
|
459
|
+
* - `association-owned` — `EMBED_OWN`/`EMBED_REF` 라 컬럼이 association source 소유 ⇒ 관계 op 소관.
|
|
460
|
+
* - `derived` — `RELATION_*` 이라 `type` 이 파생값이다(부모 PK 의 Java 타입 / 상대 엔티티)
|
|
461
|
+
* ⇒ 고칠 자리는 **부모 쪽 또는 관계**이지 이 속성이 아니다(GUI 도 같은 이유로 잠근다).
|
|
462
|
+
*/
|
|
463
|
+
reason: 'column-count' | 'association-owned' | 'derived';
|
|
464
|
+
current: string;
|
|
465
|
+
requested: string;
|
|
466
|
+
}
|
|
419
467
|
/** association.update patch 미지 키(스키마는 하드 폐색 — REST 직접 호출 대비 심층 방어). */
|
|
420
468
|
| {
|
|
421
469
|
code: 'association-patch-unknown-key';
|
|
@@ -154,6 +154,13 @@ export interface EmbeddableColumnOverride {
|
|
|
154
154
|
insertable?: boolean;
|
|
155
155
|
/** JPA @Column(updatable=). OWN 컬럼에만 저장(SHARED_REF는 타깃 파생). */
|
|
156
156
|
updatable?: boolean;
|
|
157
|
+
/**
|
|
158
|
+
* JPA @Column(nullable=false) — **이 서브컬럼 하나의** NOT NULL. 미설정이면 속성 축(`notNull`)을 따른다.
|
|
159
|
+
* ★임베더블은 컬럼마다 제약이 갈릴 수 있고(실측: `ChangedBy` 의 type 컬럼만 `NOT NULL`) 속성 축 하나로는
|
|
160
|
+
* 그 비대칭을 담을 수 없다 — 그래서 서브컬럼 축이 있다(SoT=`core/types.ts` `DbColumn.notNull`).
|
|
161
|
+
* OWN 컬럼에만 저장(SHARED_REF는 타깃 파생).
|
|
162
|
+
*/
|
|
163
|
+
notNull?: boolean;
|
|
157
164
|
/**
|
|
158
165
|
* SHARED_REF — 이 서브컬럼이 자체 물리 컬럼을 갖지 않고 같은 엔터티의 다른 컬럼(**물리명**)을 공유해
|
|
159
166
|
* read-only 투영됨(대표: Money의 currency가 별도 스칼라 통화 컬럼 공유). 설정 시 resolver가 그 물리명을
|
|
@@ -89,6 +89,26 @@ export declare function resolveEffectiveColumn(attr: Attribute, col: DbColumn, i
|
|
|
89
89
|
*
|
|
90
90
|
* ⚠️판정은 **내용 유무**다(`??` 아님) — 빈 객체 `{}` 가 폴백을 조용히 막는 것을 피한다.
|
|
91
91
|
*/
|
|
92
|
+
/**
|
|
93
|
+
* **실효 NOT NULL** — 컬럼 축(`DbColumn.notNull`)이 설정돼 있으면 그것, 아니면 속성 축(`Attribute.notNull`).
|
|
94
|
+
*
|
|
95
|
+
* ★`effectiveLogicalName` 과 **같은 형상**이다 — 두 저장 자리를 한 값으로 접는 단일 출처이고 **컬럼이
|
|
96
|
+
* 이긴다**(더 구체적인 자리). 다른 점은 폴백 방향의 «원천»뿐이다: 논리명·타입·길이는 *선언원*(카탈로그·
|
|
97
|
+
* 임베더블·부모 PK)에서 상속하지만(`resolveEffectiveColumn`), NOT NULL 은 **자기 속성**에서 내려온다
|
|
98
|
+
* — 카탈로그 필드에 그 축이 없고(실물 `@Embeddable` 이 `nullable` 을 대개 지정하지 않는다) 제약의
|
|
99
|
+
* 소유자는 «사용처»이기 때문이다(같은 임베더블이 어떤 테이블에선 NOT NULL, 다른 곳에선 nullable).
|
|
100
|
+
*
|
|
101
|
+
* ⚠️판정은 `?? `(nullish)다 — 저장 라운드트립이 미설정을 `null` 로 바꾸므로 `!== undefined` 로 읽으면
|
|
102
|
+
* `null` 을 «false 설정»으로 오독한다(이 리포의 wire clear 규약: *「저장값 null 을 엄격 비교로 읽지 말 것」*).
|
|
103
|
+
*
|
|
104
|
+
* ★`identifier` 는 여기서 보지 않는다 — PK 는 소비처마다 다르게 다룬다(DDL 은 `NOT NULL` 을 생략하고
|
|
105
|
+
* PK 제약으로 표현, 코드젠은 `@Id` 를 낸다) ⇒ 그 판단을 이 함수로 끌어오면 두 소비처가 어긋난다.
|
|
106
|
+
*/
|
|
107
|
+
export declare function effectiveNotNull(attr: {
|
|
108
|
+
notNull?: boolean;
|
|
109
|
+
}, col: {
|
|
110
|
+
notNull?: boolean;
|
|
111
|
+
} | undefined): boolean;
|
|
92
112
|
export declare function effectiveEntityLogicalName(entity: {
|
|
93
113
|
classLogicalName?: MultiLangText;
|
|
94
114
|
table?: {
|
|
@@ -13,10 +13,17 @@ export type IndexColumnCleanup = {
|
|
|
13
13
|
* ⚠️한 조작에서 여러 속성이 사라지면 **한 번에** 넘길 것 — 속성마다 따로 호출하면 각 산출이 원본 기준이라
|
|
14
14
|
* 나중 패치가 앞의 정리를 되돌린다.
|
|
15
15
|
*
|
|
16
|
-
* ★`
|
|
17
|
-
* 자리 보존 전환이 그렇다: 삭제+추가 합성이라 속성 id 는 갈리는데 승계된 dbAttr 은 modelId 째 다음
|
|
18
|
-
* 속성으로 넘어간다).
|
|
19
|
-
*
|
|
20
|
-
*
|
|
16
|
+
* ★`survivingRefs` — **속성은 사라지지만 그것이 가리키던 자리는 살아남는** 조작용(`convertAttributeType`
|
|
17
|
+
* 의 자리 보존 전환이 그렇다: 삭제+추가 합성이라 속성 id 는 갈리는데 승계된 dbAttr 은 modelId 째 다음
|
|
18
|
+
* 속성으로 넘어간다). 그런 ref 는 «이번 조작이 깨뜨린 ref» 가 아니므로 위 규율대로 정리 대상이 아니다 —
|
|
19
|
+
* 빼면 살아있는 컬럼을 가리키던 인덱스가 조용히 비고, 그것이 이 모듈이 막으려던 **무신호 소실** 그
|
|
20
|
+
* 자체가 된다. 미지정이면 종전과 같다(전부 고아).
|
|
21
|
+
*
|
|
22
|
+
* ★★**집합이 아니라 «맵»인 이유**(2026-09-02 정정): 종전엔 `survivingColumnIds`(Set)였고 그것이 **컬럼
|
|
23
|
+
* 표기만 지켰다**. 그런데 `columnRef` 는 두 표기가 공존하고(`indexColumnRef.ts`) **편집 뷰가 만드는
|
|
24
|
+
* 인덱스는 속성 modelId 를 쓴다**(`EntityIndexSection.candidateItems`·`EntityIndexesWide.availItems`).
|
|
25
|
+
* 전환은 속성 id 를 새로 부여하므로, 컬럼이 승계돼도 **GUI 로 만든 인덱스는 그대로 비워졌다** —
|
|
26
|
+
* 막으려던 실패 모드가 같은 조작의 다른 표기로 재발한 형태다. 옛 ref → 새 ref 를 받아 **갈아끼운다**.
|
|
27
|
+
* 1컬럼 승계는 정규형(dbAttr 표기)으로 접어 넘기는 것이 자연스럽다(`indexRefResolver.canon` 동형).
|
|
21
28
|
*/
|
|
22
|
-
export declare function planIndexColumnCleanup(entity: Entity, removedAttributeIds: readonly ModelId[],
|
|
29
|
+
export declare function planIndexColumnCleanup(entity: Entity, removedAttributeIds: readonly ModelId[], survivingRefs?: ReadonlyMap<ModelId, ModelId>): IndexColumnCleanup[];
|
package/dist/core/javaTypes.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Entity, Association, Attribute, DisplayMode, EmbeddableCatalog, PredefinedCustomTypeCatalog } from './types';
|
|
1
|
+
import { Entity, Association, Attribute, DbColumn, DisplayMode, EmbeddableCatalog, PredefinedCustomTypeCatalog, PredefinedCustomTypeEntry } from './types';
|
|
2
2
|
export interface JavaTypeDef {
|
|
3
3
|
/** 저장값 = 레거시 enum 상수명. Attribute.type에 그대로 들어간다. */
|
|
4
4
|
value: string;
|
|
@@ -90,10 +90,15 @@ export declare const SELECTABLE_JAVA_TYPES: readonly JavaTypeDef[];
|
|
|
90
90
|
* 목록에 없으면 EMBED_PREDEF 속성의 현재값이 아래 폴백으로만 보이고 **다른 타입으로 바꾸는 순간
|
|
91
91
|
* 되돌아갈 수 없다**. 그것이 직렬화 타입에서 실사용 보고로 드러났던 바로 그 함정이고(`serializedTypes`
|
|
92
92
|
* 주석), ②는 그 **두 번째 사본**이었다. 선택 시 부수효과(자리 보존 전환 = 삭제+추가 합성)는
|
|
93
|
-
* `editor/attribute.
|
|
93
|
+
* `editor/attribute.convertAttributeType`가 소유한다 — 이 함수는 «고를 수 있게» 할 뿐이다.
|
|
94
94
|
* ⇒ 부수효과로 레거시 ③`CustomMoneyType`(1컬럼, 라벨 `Money`) 속성을 GUI에서 ②`Money`(2컬럼)로
|
|
95
95
|
* 승격할 수 있게 된다 — 종전엔 v1→v2 마이그레이션(`migrateLegacyMoney`)만이 그 경로였다. 두 항목은
|
|
96
96
|
* `Money` ↔ `Money (금액)` 로 갈려 보이고, 그것이 **레거시 값을 잃지 않으면서 옮겨 갈 수 있는** 상태다.
|
|
97
|
+
* ⚠️★**이 근거는 도입 당시 자기소멸해 있었다**(2026-09-02 사용자 보고 · 같은 날 정정): 같은 커밋이
|
|
98
|
+
* 와이드 뷰에 EMBED 가드를 더해 EMBED 속성의 셀렉트가 **양쪽 다 `disabled`** 가 됐고, 그러면
|
|
99
|
+
* *「바꾸는 순간」* 자체가 없어 병합이 실효를 갖지 못했다. 진입만 열리고 출구가 없는 **단방향 트랩**이
|
|
100
|
+
* 된 것이고(*「한번 가면 못 돌아오는 형태」*), 그 함정의 **세 번째 사본**을 그 트랙이 새로 만든 셈이다.
|
|
101
|
+
* ⇒ 가드를 `EMBED_OWN`·`EMBED_REF`(association 이 정체성인 둘)로 좁혀 위 문장이 **이제 참이다**.
|
|
97
102
|
*
|
|
98
103
|
* open-bluesea BSSelect는 model-value가 items에 없으면 placeholder로 떨어뜨려 값이 빈칸으로 보인다(표시
|
|
99
104
|
* 손상). 현재값이 후보(① + 주입 ③) 밖(②임베더블 타입명·미주입 ③ customtype명·⑤ GroupCodeEnum·미지
|
|
@@ -110,6 +115,63 @@ export declare const SELECTABLE_JAVA_TYPES: readonly JavaTypeDef[];
|
|
|
110
115
|
* «선택 가능한 타입»의 출처가 아니다 — 그 둘을 섞으면 편집이 한 방향으로만 흐른다.
|
|
111
116
|
*/
|
|
112
117
|
export declare function typeSelectItems(currentType: string, predefinedCustomTypes?: PredefinedCustomTypeCatalog, serializedTypes?: readonly string[], embeddables?: EmbeddableCatalog): JavaTypeDef[];
|
|
118
|
+
/**
|
|
119
|
+
* `type` 을 **누가 소유하는가** — 이 값이 「이 속성 혼자의 값」인지 가르는 단일 출처.
|
|
120
|
+
*
|
|
121
|
+
* 이 리포에서 편집 어포던스와 AI 거부가 **반복해서 같은 선을 각자 그려** 왔고 그때마다 갈렸다
|
|
122
|
+
* (와이드 ↔ 인스펙터 EMBED 가드 · GUI ↔ resolver `type` 축). 판별 유니온으로 못박아 소비처가
|
|
123
|
+
* 「어느 부류인가」를 묻게 한다 — 부울 셋을 나열하면 새 `attrType` 이 생겼을 때 조용히 `own` 이 된다.
|
|
124
|
+
*
|
|
125
|
+
* - `structural` — **동반 구조(`dbAttrs` 개수)가 함께 가야** 성립. `EMBED_PREDEF`.
|
|
126
|
+
* - `association` — **association 이 정체성**(어느 임베더블인지 관계가 정한다). `EMBED_OWN`·`EMBED_REF`.
|
|
127
|
+
* - `derived` — **다른 곳에서 파생**. `RELATION_OWN`(부모 PK 의 Java 타입) · `RELATION_REF`(상대 엔티티).
|
|
128
|
+
* - `own` — 사용자가 정하는 값. `NORMAL`.
|
|
129
|
+
*
|
|
130
|
+
* ⚠️`DIVIDER` 는 의도적으로 `own` 이다 — 계약상 `type=''` 이지만 **검증·코드젠·DDL 이 그 행을 통째로
|
|
131
|
+
* 건너뛰므로**(`core/types.AttributeType` 주석) 값이 실려도 어디서도 읽히지 않는다. 읽히지 않는 값을
|
|
132
|
+
* 막는 것은 게이트를 과하게 만든다.
|
|
133
|
+
* ⚠️`groupCode` 결합(⑤ `GroupCodeEnum`)은 **여기 없다** — `attrType` 이 아니라 «형제 필드»와의 커플링이라
|
|
134
|
+
* 판정 입력이 다르다(`isGroupCodeCouplingBroken`). 섞으면 「결과 상태로 재야 하는 축」과 「출발만 보면
|
|
135
|
+
* 되는 축」이 한 함수에 들어간다.
|
|
136
|
+
*/
|
|
137
|
+
export type TypeOwner = 'own' | 'structural' | 'association' | 'derived';
|
|
138
|
+
export declare function typeOwner(attr: Pick<Attribute, 'attrType'>): TypeOwner;
|
|
139
|
+
/**
|
|
140
|
+
* 이 타입 변경이 **`type` 하나로 표현할 수 없는** 자리인가 — 동반 구조가 함께 가야 하거나 그 값의
|
|
141
|
+
* 소유자가 따로 있는 변경이다. GUI 와 AI 가 **같은 선**을 보게 하려고 여기 둔다.
|
|
142
|
+
*
|
|
143
|
+
* 참인 경우가 둘이다: **출발이 `own` 이 아니거나**(위 `typeOwner`), **목적지가 ② 임베더블**이거나
|
|
144
|
+
* (1컬럼이 N컬럼이 된다 — 목적지 의존이라 `typeOwner` 로는 못 잡는 유일한 축).
|
|
145
|
+
*
|
|
146
|
+
* ★소비처가 둘이고 **하는 일이 다르다**: GUI 는 `structural` 을 «자리 보존 전환»(`convertAttributeType`
|
|
147
|
+
* — 삭제+추가 합성)으로 **처리**하고 나머지는 셀렉트를 잠그며, AI(`agent/resolver`)는 patch 로 표현할
|
|
148
|
+
* 수 없으므로 **전부 거부**한다(op 배치는 `attribute.remove`+`attribute.add`(+`reorder`)로 같은 일을
|
|
149
|
+
* 낼 수 있어 표현력 부족이 아니다). 판정선만 공유하고 처방은 각자다 — 선이 갈리면 *「GUI 로는 되는데
|
|
150
|
+
* AI 로는 조용히 반쪽 적용」* 이 된다.
|
|
151
|
+
* ★같은 값 재전송(라운드트립 에코)은 변경이 아니므로 거짓이다(`attrType` 게이트의 에코 통과와 동형).
|
|
152
|
+
*/
|
|
153
|
+
export declare function isStructuralTypeChange(attr: Pick<Attribute, 'attrType' | 'type'>, targetType: string, embeddables: EmbeddableCatalog): boolean;
|
|
154
|
+
/**
|
|
155
|
+
* ⑤ 파생 타입 커플링이 깨졌는가 — **`GroupCodeEnum` 과 `groupCode` 결합은 «항상 함께»**다(XOR 이면 깨짐).
|
|
156
|
+
*
|
|
157
|
+
* ★종전엔 **한 방향만** 강제했다(`type=GroupCodeEnum` 인데 `groupCode` 없음 = `groupcode-required`, 세 자리).
|
|
158
|
+
* 반대 방향 — `groupCode` 는 남긴 채 `type` 만 다른 값으로 — 은 **add·update 전부 열려 있었고**, 그러면
|
|
159
|
+
* 코드 enum 에 묶인 속성이 `String` 을 방출하는 **깨진 파생**이 조용히 생긴다(GUI 는 `setAttributeGroupCode`
|
|
160
|
+
* 가 둘을 항상 함께 바꿔서 이 상태를 만들 수 없다 = 또 하나의 GUI↔AI 비대칭이었다).
|
|
161
|
+
* ⇒ 불변식을 XOR 한 줄로 못박아 **세 자리가 같은 술어**를 본다. 판정은 **결과 상태**로 하는 것이 전제다
|
|
162
|
+
* (patch 만 보면 「type 은 두고 groupCode 만 제거」를, 기존 값만 보면 그 반대를 놓친다 — CC-3·CC-5 규율).
|
|
163
|
+
*/
|
|
164
|
+
export declare function isGroupCodeCouplingBroken(type: string | undefined, groupCode: string | undefined): boolean;
|
|
165
|
+
/**
|
|
166
|
+
* ③ predefined customtype 을 고를 때 그 **단일 컬럼**에 실릴 물리 메타 — 카탈로그가 소유한다.
|
|
167
|
+
*
|
|
168
|
+
* ★함수로 뽑아 둔 이유: 이 시드를 하는 자리가 **둘**이다 — 컬럼 개수가 안 바뀌는 평범한 타입 변경
|
|
169
|
+
* (`view/useAttributeEditing.setAttrType`)과, EMBED_PREDEF 에서 ③ 으로 되돌아오는 **자리 보존 전환**
|
|
170
|
+
* (`editor/attribute.convertAttributeType`). 두 자리가 규칙을 각자 적으면 이 리포가 반복해 싸운
|
|
171
|
+
* 미러 드리프트가 그대로 열린다(VE-4). `length`·`scale` 은 카탈로그 미지정이면 **환원**한다 —
|
|
172
|
+
* 남겨 두면 이전 타입의 값이 새 타입 컬럼에 붙어 stale 원천이 된다(`setDb` 의 scale 환원과 동형).
|
|
173
|
+
*/
|
|
174
|
+
export declare function seedPredefinedCustomTypeColumn(base: DbColumn, entry: PredefinedCustomTypeEntry): DbColumn;
|
|
113
175
|
/**
|
|
114
176
|
* EMBED 표시 속성의 컬렉션 모드(`@ElementCollection`)를 판정한다 — 컬렉션이면 `collectionType`(기본
|
|
115
177
|
* LIST), 단일(`@Embedded`)이거나 EMBED가 아니면 undefined. 판정 권위는 임베더블을 가리키는 end의
|
package/dist/core/types.d.ts
CHANGED
|
@@ -175,6 +175,26 @@ export interface DbColumn {
|
|
|
175
175
|
updatable?: boolean;
|
|
176
176
|
/** JPA @Column(insertable=…). undefined=기본 따름. v1 레거시엔 없는 신규 옵션. */
|
|
177
177
|
insertable?: boolean;
|
|
178
|
+
/**
|
|
179
|
+
* JPA `@Column(nullable=false)` — **이 컬럼 하나의** NOT NULL. `undefined`(=미설정)면 속성 축
|
|
180
|
+
* (`Attribute.notNull`)을 따른다(`updatable`·`insertable` 과 같은 **inherit 3-상태**).
|
|
181
|
+
*
|
|
182
|
+
* ★**왜 컬럼 축이 필요한가**: `Attribute.notNull` 은 속성당 하나뿐인데 **한 속성이 N컬럼**인 자리
|
|
183
|
+
* (`EMBED_PREDEF`·`EMBED_OWN`)에서는 컬럼마다 제약이 갈릴 수 있다. 실측 계기 = `ChangedBy` 값 타입
|
|
184
|
+
* 병합 6엔티티(`ItemInventoryHistory`·`OfflineOrderHistory`·`Claim`·`ClaimHistory`·`OrderHistory`·
|
|
185
|
+
* `RefundChangeHist`) — **DDL 이 `changed_by_type_code` 를 `NOT NULL`, `changed_by_id` 를 nullable 로
|
|
186
|
+
* 확증**하는데 두 스칼라 속성을 하나로 병합하면 그 비대칭을 담을 데가 없어 **DB 로 확증된 제약이 사라졌다**.
|
|
187
|
+
*
|
|
188
|
+
* ★해소는 **`columnResolve.effectiveNotNull` 단일 출처**로만 읽는다 — 소비처가 넷이다(DDL `NOT NULL` ·
|
|
189
|
+
* 코드젠 `@Column(nullable=false)` · `CHK-TYPE-8`[nullable × 원시 타입] · 표시 배지). 이 모듈이 생긴
|
|
190
|
+
* 이유가 정확히 *「상속 해소가 소비처마다 제각각이어서 DDL 만 raw 를 읽었다」* 이므로 재기술 금지.
|
|
191
|
+
*
|
|
192
|
+
* ⚠️**op patch 에서 «평탄» 키로 오면 안 된다** — `notNull` 은 `DBATTR_FLAT_KEYS` 에 **넣지 않는다**.
|
|
193
|
+
* 그 집합은 평탄 키를 컬럼으로 내려보내는데(`resolver.ts`), `notNull` 은 이미 **속성 레벨 평탄 키**라
|
|
194
|
+
* 넣으면 기존 `attribute.update {notNull}` 이 조용히 컬럼으로 납치된다(두 축이 같은 이름을 쓰는 유일한
|
|
195
|
+
* 자리다). 컬럼 축은 **dotted `dbAttrs.<i>.notNull`** 또는 `embeddableOverrides[].notNull` 로만 쓴다.
|
|
196
|
+
*/
|
|
197
|
+
notNull?: boolean;
|
|
178
198
|
/**
|
|
179
199
|
* 공유 통화 컬럼(SHARED_REF) — 이 컬럼이 자체 물리 컬럼을 갖지 않고 같은 엔터티의 다른 컬럼을
|
|
180
200
|
* **modelId로 참조**해 그 물리 컬럼에 read-only 투영됨을 뜻한다(예: Money embeddable의 currency
|
|
@@ -2,7 +2,7 @@ import { Ref } from 'vue';
|
|
|
2
2
|
import { Command, EditorState } from '../command/types';
|
|
3
3
|
import { Translator } from '../i18n';
|
|
4
4
|
import { EditorController, Selection } from './controller';
|
|
5
|
-
import { EmbeddableCatalog, ModelId } from '../core/types';
|
|
5
|
+
import { EmbeddableCatalog, ModelId, PredefinedCustomTypeCatalog } from '../core/types';
|
|
6
6
|
/** 이 축이 팩토리 클로저에서 쓰는 것 전부. 늘어나면 여기 선언이 먼저 늘어난다(= 의존 인벤토리). */
|
|
7
7
|
export interface AttributeContext {
|
|
8
8
|
/** 편집 대상 reactive 상태(속성만 교체되므로 참조 안정). */
|
|
@@ -15,6 +15,11 @@ export interface AttributeContext {
|
|
|
15
15
|
gateEntityLocked: (entityId: ModelId) => boolean;
|
|
16
16
|
/** 호스트 주입 임베더블 카탈로그(`addPredefinedEmbed`의 슬롯 골격 소스). */
|
|
17
17
|
embeddableCatalog: Ref<EmbeddableCatalog>;
|
|
18
|
+
/**
|
|
19
|
+
* 호스트 주입 ③ predefined customtype 카탈로그 — `convertAttributeType` 이 **되돌림 목적지**로
|
|
20
|
+
* ③ 을 받을 때 그 단일 컬럼 메타를 시드하는 출처(②와 같은 성격의 주입이라 나란히 둔다).
|
|
21
|
+
*/
|
|
22
|
+
predefinedCustomTypeCatalog: Ref<PredefinedCustomTypeCatalog>;
|
|
18
23
|
/** UI 크롬 번역기 — FK 직접 삭제 차단 안내 문구용. */
|
|
19
24
|
t: Translator;
|
|
20
25
|
/** 차단 안내(텍스트별 단기 dedup) — 무음 차단을 막는 백스톱. */
|
|
@@ -22,4 +27,4 @@ export interface AttributeContext {
|
|
|
22
27
|
/** 삭제된 행을 선택이 가리키지 않도록 해제하는 쓰기(`removeAttributes`). */
|
|
23
28
|
selection: Ref<Selection>;
|
|
24
29
|
}
|
|
25
|
-
export declare function createAttributeApi(ctx: AttributeContext): Pick<EditorController, 'addPredefinedEmbed' | '
|
|
30
|
+
export declare function createAttributeApi(ctx: AttributeContext): Pick<EditorController, 'addPredefinedEmbed' | 'convertAttributeType' | 'addSerializedTypeAttribute' | 'addAttribute' | 'addDivider' | 'updateAttribute' | 'setAttributeGroupCode' | 'setEmbedColumns' | 'removeAttribute' | 'removeAttributes' | 'setAttributeSwatch' | 'setAttributeSwatches' | 'reorderAttributes'>;
|
|
@@ -23,9 +23,9 @@ export declare function removeAttributeCommands(entityId: ModelId, attributeIds:
|
|
|
23
23
|
/**
|
|
24
24
|
* 누산된 제거가 남길 인덱스 dangling 정리 명령 — 조작의 서브명령 **맨 끝**에 한 번 붙인다.
|
|
25
25
|
* `logical`은 제거 **전** 상태여야 한다(사라지는 속성의 dbAttr modelId를 알아야 하므로).
|
|
26
|
-
* `
|
|
26
|
+
* `survivingRefs`는 그대로 통과시킨다 — 의미·근거는 `core/indexCleanup.planIndexColumnCleanup` 소유.
|
|
27
27
|
*/
|
|
28
|
-
export declare function indexCleanupCommands(logical: LogicalModel, removed: RemovedAttributes,
|
|
28
|
+
export declare function indexCleanupCommands(logical: LogicalModel, removed: RemovedAttributes, survivingRefs?: ReadonlyMap<ModelId, ModelId>): Command[];
|
|
29
29
|
/**
|
|
30
30
|
* 식별자 전파 reconcile 계획을 자식 엔터티 대상 서브명령 배열로 변환.
|
|
31
31
|
* 1차 변경(관계 생성/삭제 등)과 함께 composite로 묶으면 전파 FK 동기화가 하나의 undo/redo
|
|
@@ -380,11 +380,14 @@ export interface EditorController {
|
|
|
380
380
|
*/
|
|
381
381
|
addPredefinedEmbed(entityId: ModelId, embeddableType: string): ModelId | null;
|
|
382
382
|
/**
|
|
383
|
-
* 기존
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
|
|
387
|
-
|
|
383
|
+
* 기존 속성의 타입을 **자리 보존 전환** — 타입 셀렉트가 «컬럼 개수 축이 갈리는» 값을 낼 때의 착지점.
|
|
384
|
+
* `addPredefinedEmbed`가 꼬리에 **새 행**을 만드는 것과 달리 이쪽은 그 자리에서 형상을 바꾼다(사용처
|
|
385
|
+
* 순서를 어긋내지 않는다). `targetType`이 ② 임베더블 카탈로그에 있으면 `EMBED_PREDEF`로, 없으면
|
|
386
|
+
* `NORMAL`로 착지한다 — 즉 **되돌림도 이 경로다**(단방향이 아니다).
|
|
387
|
+
* 대상이 없거나 전환 불가(FK 파생 · 임베더블 착지인데 식별자 · `EMBED_OWN`/`EMBED_REF`/`RELATION_*`/
|
|
388
|
+
* `DIVIDER` 출발 · `groupCode` 결합 · 같은 타입 재선택)면 no-op(null).
|
|
389
|
+
*/
|
|
390
|
+
convertAttributeType(entityId: ModelId, attributeId: ModelId, targetType: string): ModelId | null;
|
|
388
391
|
addAttribute(entityId: ModelId, partial?: Partial<Attribute>): ModelId | null;
|
|
389
392
|
/**
|
|
390
393
|
* 시각 구획 행(DIVIDER) 추가 — 거대 엔티티에서 속성 묶음을 끊는 구분선. DB 컬럼·타입·식별자 없이
|