@g1cloud/entity-modeler-next 5.1.3 → 5.1.5
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/core/embedSlots.d.ts +66 -0
- package/dist/core/scaffoldJava.d.ts +35 -1
- package/dist/core/types.d.ts +14 -0
- package/dist/editor/commandPlans.d.ts +11 -0
- package/dist/entity-modeler-next.css +1 -1
- package/dist/entity-modeler.js +11847 -11693
- package/dist/entity-modeler.umd.cjs +29 -29
- package/dist/i18n/ko.d.ts +1 -0
- package/dist/view/useAttributeEditing.d.ts +4 -0
- package/package.json +1 -1
|
@@ -57,6 +57,72 @@ export interface EmbedSlotReorder {
|
|
|
57
57
|
* @param nextAttributeOrder 재정렬 후 임베더블 속성 순서(전체 — `reorderedSequence` 산출).
|
|
58
58
|
*/
|
|
59
59
|
export declare function planEmbedSlotReorder(model: LogicalModel, embeddableRef: ModelId, nextAttributeOrder: readonly ModelId[]): EmbedSlotReorder[];
|
|
60
|
+
/** 한 사용처의 **슬롯 제거** 계획 — 임베더블 속성이 삭제되면 그 자리 슬롯을 걷어낸다. */
|
|
61
|
+
export interface EmbedSlotRemoval {
|
|
62
|
+
/** 표시 속성을 보유한 소유자 엔티티. */
|
|
63
|
+
entityId: ModelId;
|
|
64
|
+
/** `EMBED_OWN` 표시 속성. */
|
|
65
|
+
attributeId: ModelId;
|
|
66
|
+
/** 제거 후 전체 슬롯 목록(남는 슬롯의 **순서·정체성 보존** — 신규 슬롯 없음). */
|
|
67
|
+
dbAttrs: DbColumn[];
|
|
68
|
+
/** 걷어낸 슬롯 — **호출자가 무엇이 사라지는지 볼 수 있게** 실어 보낸다(S5 `dropped` 동형). */
|
|
69
|
+
dropped: DbColumn[];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* 임베드 슬롯 **삭제 전파** — 임베더블 속성이 삭제되면 사용처(owner)의 그 자리 슬롯을 함께 걷어낸다.
|
|
73
|
+
* `planEmbedSlotFill`(꼬리 보충)의 **역방향 짝**이고, 게이트는 `planEmbedSlotReorder`(순열)와
|
|
74
|
+
* `planEmbedSlotShapeNormalization`(형상)에서 각각 하나씩 물려받는다.
|
|
75
|
+
*
|
|
76
|
+
* ## 왜 필요한가 — 삭제는 «남은 슬롯의 뜻»을 바꾼다
|
|
77
|
+
* 슬롯↔소스 대응은 **위치(인덱스)뿐**이라, 선언 속성 하나가 사라지면 그 뒤 슬롯이 **한 칸씩 밀려**
|
|
78
|
+
* 각자 남의 컬럼을 상속한다. 보충 부재가 *"컬럼이 모자란다"*(양의 문제)라면 이쪽은
|
|
79
|
+
* *"남은 컬럼이 다른 것을 가리킨다"*(뜻의 문제)라 조용하고 더 나쁘다.
|
|
80
|
+
* ★실측(프로덕션 `OrderItemOriginalAmt` · 사용처 62슬롯): 선언 속성 **하나만** 지우면
|
|
81
|
+
* `CHK-NAME-2` 가 **+30**(사용처 2 → 34) 된다.
|
|
82
|
+
*
|
|
83
|
+
* ## 왜 가능한가 — reorder 와 같은 근거
|
|
84
|
+
* *사후 복원은 불가지만 조작 시점엔 근거가 있다.* 삭제를 실행하는 시점에는 어느 선언 컬럼
|
|
85
|
+
* (`DbColumn.modelId`)이 사라지는지 알 수 있으므로, **남는 컬럼이 이전 평탄 목록의 어느 위치였는지**로
|
|
86
|
+
* 남길 슬롯이 유일하게 결정된다. `planEmbedSlotReorder` 는 **재사용할 수 없다** — 그쪽 게이트 1이
|
|
87
|
+
* *"순열일 때만"* 이라 집합이 줄면 즉시 빈 계획이 된다.
|
|
88
|
+
*
|
|
89
|
+
* ## 게이트 셋 — 확실할 때만 걷어낸다
|
|
90
|
+
* 1. **삭제만**: 지울 것이 실제로 있고(집합이 줄고) 그 속성이 컬럼을 가질 때. 추가가 섞였으면 위치
|
|
91
|
+
* 대응이 이번 조작 안에서 흔들려 근거가 없다(호출자가 가른다 — reorder 게이트 1과 같은 규율).
|
|
92
|
+
* 2. **대응이 성립하던 사용처만**: 슬롯 수가 삭제 전 선언 컬럼 수와 같아야 한다. 이미 뒤처진/앞선
|
|
93
|
+
* 사용처는 인덱스 대응 자체가 깨져 있어 걷어내면 **더 나빠진다**(reorder 게이트 2 동형).
|
|
94
|
+
* 3. ★**사라지는 자리가 진짜 override 를 쥐지 않았을 때만**: 슬롯이 **선언과 다른** 물리명·공유참조를
|
|
95
|
+
* 들고 있으면 그건 사람이 넣은 `@AttributeOverride` 라 도구가 버릴 수 없다(S5 게이트 2 동형).
|
|
96
|
+
* ⚠️★**「빈 슬롯인가」로 재면 안 된다 — 「선언과 다른가」로 재야 한다.** 연결 시점
|
|
97
|
+
* `flattenEmbeddableColumns` 가 소스 값을 **verbatim 복사**하므로 방금 연결한 사용처의 슬롯은 전부
|
|
98
|
+
* 물리명을 «명시 보유»한 형태고, 저장·재로드하면 `embedColTo` 가 source diff 로 환원해 빈 순수
|
|
99
|
+
* 참조가 된다 — **같은 논리 상태가 세션에 따라 다른 표현**을 갖는다. «빈 슬롯»으로 재면 그 표현
|
|
100
|
+
* 차이에 걸려 전파가 죽는다(프로덕션 실측: 전파 **75 → 2** · 보류 17 → **90**). 선언과 대조하면
|
|
101
|
+
* **버릴 것이 실제로 있는지**만 본다.
|
|
102
|
+
* ⚠️**「선언과 같으니 버려도 무해」가 아니다** — 삭제 축에서는 선언 자체가 사라지므로 그 값을 다시
|
|
103
|
+
* 구할 데가 없다. 버릴 수 있는 근거는 *복원 가능성*이 아니라 **그 슬롯이 독자적으로 아는 정보가
|
|
104
|
+
* 없다**는 것이다: 컬럼이 사라지는 것은 선언을 지운 **정당한 결과**이고, 남기면 오히려 그 슬롯이
|
|
105
|
+
* 밀려 남의 컬럼을 상속한다. 반대로 선언과 다른 값은 슬롯만 아는 정보라 사라지면 복구 불가다.
|
|
106
|
+
*
|
|
107
|
+
* ## 왜 충돌 게이트가 없는가 (S5 와 다른 점)
|
|
108
|
+
* S5(형상 정규화)는 **빈 슬롯을 삽입**하므로 새 이름이 생겨 충돌을 만들 수 있고, 그래서 정규화 후
|
|
109
|
+
* 이름 다중집합을 실제로 계산하는 게이트를 뒀다. 삭제는 반대로 **이름이 늘 수 없다**:
|
|
110
|
+
* - 남는 슬롯의 **상속원이 바뀌지 않는다** — 새 선언 목록은 옛 목록의 **부분수열**이고 남길 슬롯을
|
|
111
|
+
* 그 부분수열로 골랐으므로, 남는 슬롯 j 의 짝은 삭제 전 그 슬롯의 짝과 **같은 컬럼**이다.
|
|
112
|
+
* - 사라지는 슬롯은 게이트 3에 의해 **빈 슬롯이거나 선언과 같은 값**뿐이라, 그 이름은 사라지는 선언
|
|
113
|
+
* 컬럼의 이름과 같고 함께 사라진다.
|
|
114
|
+
* ⇒ 실효 이름 다중집합은 **엄격히 줄거나 같다**(`CHK-NAME-2` 는 감소 방향) — reorder 가 *"순열은 슬롯
|
|
115
|
+
* 집합을 보존한다"* 로 게이트를 뺀 것과 같은 자리다.
|
|
116
|
+
* ⚠️애초 설계에는 S5 대칭으로 게이트 4(산출물 대조)를 두려 했으나 **구현 중 기각**했다 — 위 논증으로
|
|
117
|
+
* 발동이 불가능한 데다, 판정에 쓸 `duplicateNameCount` 가 **삭제 전 model** 을 보므로 남는 슬롯이
|
|
118
|
+
* *옛* 선언 j 를 상속한 것으로 계산해 **틀린 상태로 판정**한다(정확히 재려면 삭제 반영 future 가 필요한데
|
|
119
|
+
* 그 비용을 발동 0 인 게이트에 치를 이유가 없다). 대신 그 불변식을 테스트가 단언한다.
|
|
120
|
+
*
|
|
121
|
+
* @param model 삭제 **이전** 상태(현재 모델) — 사라지는 슬롯의 정체를 알아야 한다.
|
|
122
|
+
* @param embeddableRef 속성이 삭제된 임베더블(사용처가 `embedded.embeddableRef`로 가리키는 그 엔티티).
|
|
123
|
+
* @param removedAttributeIds 삭제되는 임베더블 속성 id 집합.
|
|
124
|
+
*/
|
|
125
|
+
export declare function planEmbedSlotRemoval(model: LogicalModel, embeddableRef: ModelId, removedAttributeIds: readonly ModelId[]): EmbedSlotRemoval[];
|
|
60
126
|
/** 한 사용처의 **형상 정규화** 계획 — legacy(1 속성 = 1 슬롯) → fresh(1 컬럼 = 1 슬롯). */
|
|
61
127
|
export interface EmbedSlotShapeNormalization {
|
|
62
128
|
/** 표시 속성을 보유한 소유자 엔티티. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Entity, LogicalModel, ModelId, SuperClassCatalog, EmbeddableCatalog } from './types';
|
|
1
|
+
import { Association, Attribute, Entity, LogicalModel, ModelId, SuperClassCatalog, EmbeddableCatalog } from './types';
|
|
2
2
|
import { JavaTypeDef } from './javaTypes';
|
|
3
3
|
/**
|
|
4
4
|
* `AttributeConverter` FQN 기본값 — **레거시 생성기 상수 미러**(`bluework-im` `EntityJavaFile.java:77~78`
|
|
@@ -128,4 +128,38 @@ export interface ScaffoldedEntity {
|
|
|
128
128
|
*/
|
|
129
129
|
export declare function isGeneratable(entity: Entity): boolean;
|
|
130
130
|
export declare function scaffoldEntityJava(logical: LogicalModel, targetIds: readonly ModelId[], opts?: ScaffoldOptions): ScaffoldedEntity[];
|
|
131
|
+
/**
|
|
132
|
+
* 식별 FK가 `@MapsId`(관용구4)인지 판정 — **단일 컬럼 @OneToOne 식별 FK**는 대상 PK를 공유하는 파생
|
|
133
|
+
* 식별이다(실물 OrderShipping: `@Id String orderNo` + `@MapsId @OneToOne order`가 order_no 컬럼 공유).
|
|
134
|
+
* 이 경우 FK는 스칼라 @Id에 매핑될 뿐 별도 PK 멤버가 아니므로 PK 카디널리티 카운트에서 제외한다.
|
|
135
|
+
* 걸러지는 쪽 = 직접 @Id 멤버(관용구3 @Id@ManyToOne[단수 아님]·관용구5 대상 복합키[컬럼 2+]).
|
|
136
|
+
*
|
|
137
|
+
* ★★**종전엔 조건이 하나 더 있었다** — *"스칼라 @Id와 같은 물리 컬럼을 공유"*. 그 조건은 모델에 스칼라
|
|
138
|
+
* PK가 **실재할 것**을 요구했는데 FK 전파는 FK 속성만 만들고 스칼라를 만들지 않으므로(`propagation.ts`)
|
|
139
|
+
* **프로덕션 발동이 0**이었고, 실물이 `@MapsId` 21/21인데 모델은 22건 전부 관용구5로 방출되는 **전면
|
|
140
|
+
* 드리프트**가 났다. 스칼라 필드는 이제 **방출 시점에 합성**하므로(`derivedIdFieldName` ?? 부모 PK
|
|
141
|
+
* 물리명 camelCase — 실물 관행 19/19) 그 조건이 불요해졌고, 모델은 **속성 하나**를 유지한다
|
|
142
|
+
* (⇒ 물리명 중복이 생기지 않아 `CHK-NAME-2`·DDL 이 무변경). 근거=`.claude/docs/MapsIdIdiom-entry_2026-08-26.md` §3.A.
|
|
143
|
+
* ★관용구5(`@Id`를 연관 필드에 직접)는 JPA 정식이지만 **이 코드베이스 실물에 0건**이라 선택지를 두지
|
|
144
|
+
* 않았다(§3.A (가) 확정 — 요구가 관측되면 관용구 선택 축을 신설).
|
|
145
|
+
*/
|
|
146
|
+
export declare function isMapsIdFk(fk: Attribute, assoc: Association | undefined): boolean;
|
|
147
|
+
/**
|
|
148
|
+
* `@MapsId` FK가 매핑되는 **스칼라 @Id의 필드명**. 모델 지정(`derivedIdFieldName`)이 우선이고, 없으면
|
|
149
|
+
* **부모 PK 물리명의 camelCase**로 파생한다(실물 21건 대조 19/19 — 모델 속성명 폴백은 18/19로 이름 결손
|
|
150
|
+
* 1건에서 어긋나므로 물리명 쪽을 택했다). 부모 컬럼도 미해소면 FK 자신의 물리명, 그마저 없으면 빈 문자열
|
|
151
|
+
* (호출부가 fillIn으로 표면화).
|
|
152
|
+
*/
|
|
153
|
+
export declare function mapsIdScalarName(fk: Attribute, assoc: Association, byId: Map<ModelId, Entity>): string;
|
|
154
|
+
/**
|
|
155
|
+
* `@MapsId` 스칼라 @Id의 **Java 타입** — 이름과 **같은 경로**(`derivedFrom.sourceAttributeRef`)로 조달한다.
|
|
156
|
+
*
|
|
157
|
+
* ★`pkMemberFieldType(fk, …)`을 직접 쓰면 안 된다 — 그 함수는 부모를 **`member.type`(엔티티명)으로 조회**
|
|
158
|
+
* 하는데 **실 데이터의 FK 속성은 `type`이 빈 문자열**이다(전파가 채우지 않는다 — 실측 `PaymentMethodPolicy`
|
|
159
|
+
* `{name:'paymentMethod', type:''}`). 그러면 부모 미해소로 `Object`가 나간다(실물은 `String`). 반면
|
|
160
|
+
* `derivedFrom`은 부모 PK 속성을 **modelId로 직접** 가리키므로 해소율이 19/19다.
|
|
161
|
+
* ⚠️이것은 이 변경이 만든 결함이 아니라 **선재 결함의 노출**이다 — 같은 경로를 `{Entity}PK` 필드 타입과
|
|
162
|
+
* 단일키 Repository 타입도 쓰고 있어 그쪽도 `Object`가 나가고 있었다.
|
|
163
|
+
*/
|
|
164
|
+
export declare function mapsIdScalarType(fk: Attribute, assoc: Association, byId: Map<ModelId, Entity>, logical: LogicalModel, opts: ScaffoldOptions): string;
|
|
131
165
|
export {};
|
package/dist/core/types.d.ts
CHANGED
|
@@ -224,6 +224,20 @@ export interface Attribute {
|
|
|
224
224
|
/** 부모의 어느 식별자 속성을 미러하는가 */
|
|
225
225
|
sourceAttributeRef: ModelId;
|
|
226
226
|
};
|
|
227
|
+
/**
|
|
228
|
+
* 파생 식별 관용구(`@MapsId`)에서 방출되는 **스칼라 식별자 필드명**.
|
|
229
|
+
*
|
|
230
|
+
* 이 속성의 `name`은 **연관 필드명**(`@MapsId @OneToOne` 필드 · `mappedBy` 소스)이고, 같은 관계가
|
|
231
|
+
* 만드는 **두 번째 Java 필드**가 스칼라 `@Id`다 — 종전엔 `name` 하나가 두 역할을 겸해 이 이름을 담을
|
|
232
|
+
* 자리가 없었다(엔티티 행과 엣지 인스펙터가 **같은 `name`을 편집**한다: `PropertyPanel.navFieldName`
|
|
233
|
+
* ↔ `EntityAttributesWide`). 컬럼은 공유하므로 **속성은 여전히 하나**이고, 물리명·타입은 파생이다
|
|
234
|
+
* (`dbAttrs[0].physicalName` 또는 부모 컬럼명 / 부모 PK의 Java 타입).
|
|
235
|
+
*
|
|
236
|
+
* 미지정 시 **부모 PK 물리명의 camelCase**로 폴백한다 — 실물 관행 19/19이므로 발명이 아니다
|
|
237
|
+
* (모델 속성명 폴백은 18/19: 이름 결손 1건에서 어긋난다). `isMapsIdFk` 미발동 형상(관용구3
|
|
238
|
+
* `@Id@ManyToOne`·관용구5 대상 복합키·비식별 FK)에서는 무시된다.
|
|
239
|
+
*/
|
|
240
|
+
derivedIdFieldName?: string;
|
|
227
241
|
/**
|
|
228
242
|
* 임베더블 인라인 EMBED hydration의 출처(load-only, 화면 표시 전용).
|
|
229
243
|
* 레거시는 임베더블 타입의 플래튼 컬럼 묶음을 소유자 association end에 인라인(EMBED_OWN)으로만
|
|
@@ -78,6 +78,17 @@ export declare function cascadeCommands(futureLogical: LogicalModel, parentId: M
|
|
|
78
78
|
* 어긋날 수 없다(여기서 splice를 다시 쓰면 그 지점이 드리프트 후보가 된다).
|
|
79
79
|
*/
|
|
80
80
|
export declare function embedSlotReorderCommands(logical: LogicalModel, entityId: ModelId, attrIds: ModelId[], toIndex: number): Command[];
|
|
81
|
+
/**
|
|
82
|
+
* 임베더블 속성 **삭제**가 사용처 슬롯으로 번지는 서브명령(`core/embedSlots.planEmbedSlotRemoval`).
|
|
83
|
+
* 위 재정렬 짝과 같은 형태다 — 삭제 명령과 **같은 composite**에 실어 undo 를 원자적으로 만든다.
|
|
84
|
+
*
|
|
85
|
+
* ★`cascadeCommands`(보충 축이 사는 자리)에 얹지 않고 **전용 seam**으로 둔 이유: 그쪽은 조작이 **반영된
|
|
86
|
+
* 미래 모델**을 받아 «무엇이 사라졌는가»를 알 수 없다. 삭제 전파는 사라지는 슬롯의 정체가 입력이라
|
|
87
|
+
* **삭제 전 `logical` + 지울 id 목록**이 필요하고, 그 시그니처가 정확히 재정렬 짝과 같다.
|
|
88
|
+
*
|
|
89
|
+
* `logical`은 삭제 **전** 상태여야 한다(인덱스 정리 `indexCleanupCommands`와 같은 계약).
|
|
90
|
+
*/
|
|
91
|
+
export declare function embedSlotRemovalCommands(logical: LogicalModel, entityId: ModelId, removedAttributeIds: readonly ModelId[]): Command[];
|
|
81
92
|
/**
|
|
82
93
|
* "자식의 FK 집합이 직접 바뀌는" 트리거(관계 삭제·identifying 토글)용 연쇄 서브명령.
|
|
83
94
|
* 1) seed 자식을 직접 reconcile(FK 증감/플립), 2) 그 변화를 적용한 상태로 후손 cascade.
|