@g1cloud/entity-modeler-next 5.0.0-alpha.1
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/LICENSE +6 -0
- package/README.md +42 -0
- package/dist/adapter/diagramAdapter.d.ts +44 -0
- package/dist/adapter/persisted.d.ts +245 -0
- package/dist/agent/buildAgentBatch.d.ts +16 -0
- package/dist/agent/resolver.d.ts +54 -0
- package/dist/agent/schema.d.ts +9 -0
- package/dist/agent/symbolicOp.d.ts +109 -0
- package/dist/command/commands.d.ts +108 -0
- package/dist/command/op.d.ts +80 -0
- package/dist/command/opSync.d.ts +89 -0
- package/dist/command/stack.d.ts +48 -0
- package/dist/command/types.d.ts +29 -0
- package/dist/core/autolayout.d.ts +12 -0
- package/dist/core/dbTypes.d.ts +45 -0
- package/dist/core/id.d.ts +2 -0
- package/dist/core/javaTypes.d.ts +52 -0
- package/dist/core/propagation.d.ts +49 -0
- package/dist/core/relationMarker.d.ts +44 -0
- package/dist/core/resolve.d.ts +63 -0
- package/dist/core/routing.d.ts +58 -0
- package/dist/core/sharedColumn.d.ts +19 -0
- package/dist/core/sqlReservedWords.d.ts +25 -0
- package/dist/core/svg.d.ts +98 -0
- package/dist/core/text.d.ts +8 -0
- package/dist/core/types.d.ts +400 -0
- package/dist/core/validation.d.ts +53 -0
- package/dist/editor/controller.d.ts +371 -0
- package/dist/entity-modeler-next.css +1 -0
- package/dist/entity-modeler.js +19943 -0
- package/dist/entity-modeler.umd.cjs +41 -0
- package/dist/index.d.ts +32 -0
- package/dist/view/AssociationEdge.vue.d.ts +16 -0
- package/dist/view/DiagramCanvas.vue.d.ts +9 -0
- package/dist/view/DiagramExplorer.vue.d.ts +11 -0
- package/dist/view/EditModeToggle.vue.d.ts +10 -0
- package/dist/view/EditorToolbar.vue.d.ts +10 -0
- package/dist/view/EmContextMenu.vue.d.ts +26 -0
- package/dist/view/EmIcon.vue.d.ts +12 -0
- package/dist/view/EntityAttributesWide.vue.d.ts +7 -0
- package/dist/view/EntityBasicsSection.vue.d.ts +7 -0
- package/dist/view/EntityColumnsSection.vue.d.ts +7 -0
- package/dist/view/EntityDetailModal.vue.d.ts +7 -0
- package/dist/view/EntityIndexSection.vue.d.ts +7 -0
- package/dist/view/EntityIndexesWide.vue.d.ts +7 -0
- package/dist/view/EntityModeler.vue.d.ts +6 -0
- package/dist/view/EntityNode.vue.d.ts +20 -0
- package/dist/view/EntityOperationsSection.vue.d.ts +7 -0
- package/dist/view/EntityOperationsWide.vue.d.ts +7 -0
- package/dist/view/EntityTextPreview.vue.d.ts +5 -0
- package/dist/view/GroupCodeCombobox.vue.d.ts +11 -0
- package/dist/view/GroupNode.vue.d.ts +11 -0
- package/dist/view/InlineIssueBadge.vue.d.ts +8 -0
- package/dist/view/MultiLangTextField.vue.d.ts +24 -0
- package/dist/view/NoteConnectionEdge.vue.d.ts +12 -0
- package/dist/view/NoteNode.vue.d.ts +11 -0
- package/dist/view/OperationSourceEditor.vue.d.ts +7 -0
- package/dist/view/PropertyPanel.vue.d.ts +6 -0
- package/dist/view/ValidationPanel.vue.d.ts +6 -0
- package/dist/view/diagramGeometry.d.ts +9 -0
- package/dist/view/exportSvg.d.ts +7 -0
- package/dist/view/groupCodeFilter.d.ts +8 -0
- package/dist/view/groupHover.d.ts +10 -0
- package/dist/view/openEntityDetail.d.ts +5 -0
- package/dist/view/relationHighlight.d.ts +38 -0
- package/dist/view/swatches.d.ts +37 -0
- package/dist/view/useFloatingRoute.d.ts +28 -0
- package/dist/view/validationDisplay.d.ts +10 -0
- package/dist/view/waypointController.d.ts +14 -0
- package/package.json +61 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 다이어그램 기하 스냅샷 → 벡터 SVG 문자열 (순수 함수, DOM 무의존).
|
|
3
|
+
*
|
|
4
|
+
* `core/text.ts`(모델→Markdown)와 같은 "산출물 합성" 계열이되, 입력이 논리 모델이 아니라
|
|
5
|
+
* 화면에서 측정한 기하 스냅샷(`DiagramGeometry`)이다. CSS 레이아웃 규칙을 일절 재현하지 않고
|
|
6
|
+
* 측정된 좌표·텍스트·색을 SVG primitive(<rect>/<text>/<line>/<path>)로 직렬화만 한다
|
|
7
|
+
* → CSS↔SVG 드리프트 0, DOM 무의존이라 단위 테스트 가능. 측정(DOM 의존)은 view 레이어 담당.
|
|
8
|
+
*
|
|
9
|
+
* 모든 좌표는 flow 좌표계(절대)다 — 측정 레이어가 그렇게 환산해 넘긴다.
|
|
10
|
+
*/
|
|
11
|
+
/** 텍스트 한 조각 — 측정된 위치에 같은 폰트로 그린다(위치가 실측이라 폰트 메트릭 재계산 불요). */
|
|
12
|
+
export interface SvgTextFrag {
|
|
13
|
+
x: number;
|
|
14
|
+
/** 수직 중앙 y. dominant-baseline=central로 그려 baseline 추정을 피한다. */
|
|
15
|
+
y: number;
|
|
16
|
+
text: string;
|
|
17
|
+
fill: string;
|
|
18
|
+
fontSize: number;
|
|
19
|
+
fontFamily?: string;
|
|
20
|
+
fontWeight?: number | string;
|
|
21
|
+
/** 'italic' 등. 미지정이면 normal. */
|
|
22
|
+
fontStyle?: string;
|
|
23
|
+
/** 가로 정렬 기준점. 기본 start(좌측). */
|
|
24
|
+
anchor?: 'start' | 'middle' | 'end';
|
|
25
|
+
}
|
|
26
|
+
/** 박스 내부 가로 구분선 (행/구획 경계). 좌표는 절대 flow 좌표. */
|
|
27
|
+
export interface SvgHLine {
|
|
28
|
+
x1: number;
|
|
29
|
+
x2: number;
|
|
30
|
+
y: number;
|
|
31
|
+
stroke: string;
|
|
32
|
+
strokeWidth?: number;
|
|
33
|
+
}
|
|
34
|
+
/** 모서리별 둥글기 — 헤더(상단만)·그룹 라벨(비대칭) 같은 4코너 비대칭 radius 표현용. */
|
|
35
|
+
export interface Corners {
|
|
36
|
+
tl: number;
|
|
37
|
+
tr: number;
|
|
38
|
+
br: number;
|
|
39
|
+
bl: number;
|
|
40
|
+
}
|
|
41
|
+
/** 박스형 노드(엔티티·그룹·노트) 기하. */
|
|
42
|
+
export interface SvgBox {
|
|
43
|
+
x: number;
|
|
44
|
+
y: number;
|
|
45
|
+
w: number;
|
|
46
|
+
h: number;
|
|
47
|
+
fill: string;
|
|
48
|
+
stroke: string;
|
|
49
|
+
strokeWidth?: number;
|
|
50
|
+
/** 점선 그룹 등. SVG stroke-dasharray 값(예: '6 4'). */
|
|
51
|
+
strokeDasharray?: string;
|
|
52
|
+
/** 단일 값(4코너 동일) 또는 코너별. 비대칭이면 rect가 아닌 rounded path로 그린다. */
|
|
53
|
+
radius?: number | Corners;
|
|
54
|
+
/** 반투명 그룹 배경 등. */
|
|
55
|
+
opacity?: number;
|
|
56
|
+
texts: SvgTextFrag[];
|
|
57
|
+
lines?: SvgHLine[];
|
|
58
|
+
/**
|
|
59
|
+
* 라인 아이콘(키 마커·임베드 글리프 등) — 측정 레이어가 좌표·색·viewBox를 박은 완결 <svg>
|
|
60
|
+
* 마크업 문자열. 신뢰된 내부 데이터(EmIcon)라 이스케이프 없이 그대로 삽입한다.
|
|
61
|
+
*/
|
|
62
|
+
icons?: string[];
|
|
63
|
+
}
|
|
64
|
+
/** 엣지(연관선·노트연결선) 기하. d는 이미 렌더된 path를 그대로 차용. */
|
|
65
|
+
export interface SvgEdge {
|
|
66
|
+
d: string;
|
|
67
|
+
stroke: string;
|
|
68
|
+
strokeWidth: number;
|
|
69
|
+
/** 점선 노트연결선 등. */
|
|
70
|
+
strokeDasharray?: string;
|
|
71
|
+
labels: SvgTextFrag[];
|
|
72
|
+
/**
|
|
73
|
+
* 끝점 표기 마커(까마귀발·선택성 원·컴포지션 마름모·네비 화살표) — 측정 레이어가 좌표·색을 박은
|
|
74
|
+
* 완결 <line>/<circle>/<path> 마크업 문자열. 신뢰된 내부 데이터(AssociationEdge)라 그대로 삽입.
|
|
75
|
+
*/
|
|
76
|
+
markers?: string[];
|
|
77
|
+
}
|
|
78
|
+
/** 화면 측정으로 만든 다이어그램 전체 기하 스냅샷 (export 전용 뷰모델). */
|
|
79
|
+
export interface DiagramGeometry {
|
|
80
|
+
viewBox: {
|
|
81
|
+
x: number;
|
|
82
|
+
y: number;
|
|
83
|
+
w: number;
|
|
84
|
+
h: number;
|
|
85
|
+
};
|
|
86
|
+
/** 캔버스 배경색(테마 반영). 미지정이면 배경 rect를 그리지 않음(투명). */
|
|
87
|
+
background?: string;
|
|
88
|
+
/** Z-order 하위부터: 그룹 → 엣지 → 엔티티/노트 순으로 합성한다. */
|
|
89
|
+
groups: SvgBox[];
|
|
90
|
+
edges: SvgEdge[];
|
|
91
|
+
entities: SvgBox[];
|
|
92
|
+
notes: SvgBox[];
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* 기하 스냅샷을 완결된 SVG 문서 문자열로 합성한다.
|
|
96
|
+
* Z-order(캔버스와 동일): 배경 → 그룹 → 엣지 → 엔티티 → 노트.
|
|
97
|
+
*/
|
|
98
|
+
export declare function renderDiagramSvg(geo: DiagramGeometry): string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { DisplayMode, LogicalModel } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* 표시 모드별 라벨(평문) — Diagram Explorer 트리/캡션 공용.
|
|
4
|
+
* EntityNode의 labelSegs와 동일 의미 규칙: '논리'는 업무 논리명이며 없으면 '(논리명)'
|
|
5
|
+
* 플레이스홀더(코드명으로 폴백하지 않음), '물리'는 physicalName, CLASS만 코드명.
|
|
6
|
+
*/
|
|
7
|
+
export declare function displayLabel(mode: DisplayMode, code: string, logical: string | undefined, physical: string | undefined): string;
|
|
8
|
+
export declare function entityModelToText(logical: LogicalModel): string;
|
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 논리 모델 ↔ 레이아웃 모델 분리의 타입 계약.
|
|
3
|
+
*
|
|
4
|
+
* 핵심 원칙: 레이아웃이 논리 모델을 `modelId`로 참조한다(단방향).
|
|
5
|
+
* 논리 모델에는 좌표/크기/waypoint/style 같은 렌더링 정보가 없다 →
|
|
6
|
+
* 코드생성·DDL·API 수정의 깨끗한 입력이 된다.
|
|
7
|
+
*
|
|
8
|
+
* 레거시 대응:
|
|
9
|
+
* - EntityModel/AttributeModel/AssociationModel/GroupModel (geo·style 제거)
|
|
10
|
+
* - Geo/Point/Size → 레이아웃 모델로 이동
|
|
11
|
+
*/
|
|
12
|
+
export type ModelId = string;
|
|
13
|
+
/** 다국어 텍스트 (레거시 Map<String,String>, bluework4-tool MultiLangText 동형) */
|
|
14
|
+
export type MultiLangText = Partial<Record<'ko' | 'en' | 'ja' | 'zh', string>>;
|
|
15
|
+
/** MultiLangText가 지원하는 언어 코드. 입력 가능 언어셋·유저 언어 주입의 단위. */
|
|
16
|
+
export type LangCode = keyof MultiLangText;
|
|
17
|
+
export type ClassStereotype = 'UNDEFINED' | 'JPA_ENTITY' | 'JPA_EMBEDDABLE' | 'JPA_MULTI_LANGUAGE_ENTITY';
|
|
18
|
+
export type Multiplicity = 'NO_INSTANCE_OR_ONE_INSTANCE' | 'EXACTLY_ONE_INSTANCE' | 'ZERO_OR_MORE_INSTANCES' | 'ONE_OR_MORE_INSTANCES';
|
|
19
|
+
export type JpaCascadeType = 'ALL' | 'PERSIST' | 'MERGE' | 'REMOVE' | 'REFRESH' | 'DETACH';
|
|
20
|
+
export type JpaFetchType = 'LAZY' | 'EAGER';
|
|
21
|
+
export type AttributeType = 'NORMAL' | 'RELATION_OWN' | 'RELATION_REF' | 'EMBED_OWN' | 'EMBED_REF' | 'EMBED_PREDEF'
|
|
22
|
+
/**
|
|
23
|
+
* 시각 구획 행 — 속성이 아니라 거대 엔티티에서 속성 묶음을 끊어 읽는 구분선. DB 컬럼·식별자·타입을
|
|
24
|
+
* 갖지 않으며(dbAttrs=[], type=''), `name`은 선택적 섹션 라벨(빈 문자열이면 민무늬 선). 검증·코드
|
|
25
|
+
* 생성·식별자 전파 등 논리 속성 순회에서는 제외 대상이다(과거엔 name이 대시인 NORMAL 가짜 속성으로
|
|
26
|
+
* 표현 → 속성명 중복/속성 과다 검증 false-positive 유발. adapter가 로드 시 DIVIDER로 승격).
|
|
27
|
+
*/
|
|
28
|
+
| 'DIVIDER';
|
|
29
|
+
/**
|
|
30
|
+
* Predefined 임베더블 카탈로그 — 신규 EMBED_PREDEF 삽입 시 dbAttr 골격을 시드하고, 빈 슬롯을 표시
|
|
31
|
+
* 폴백할 메타모델 정의. 레거시 `AttributeMeta.getPredefinedEmbeddableMetaModel`(Name/Address/Tel/
|
|
32
|
+
* UploadedFile) 대응. **호스트가 주입**하며(완전 통합 시 embeddableCatalog API) 코어는 소비만 한다
|
|
33
|
+
* — 코어에 4종을 박으면 곧 하드코딩이므로 정의를 외부(호스트/dev 프리셋)에 둔다.
|
|
34
|
+
*/
|
|
35
|
+
export interface EmbeddableCatalogField {
|
|
36
|
+
/** 논리 필드명(레거시 AttributeMeta name, 예: countryCode) — 현재 dbAttr엔 미저장, 폴백 인덱스 매칭·식별용. */
|
|
37
|
+
name: string;
|
|
38
|
+
physicalName: string;
|
|
39
|
+
logicalName?: MultiLangText;
|
|
40
|
+
dataType: string;
|
|
41
|
+
length?: number;
|
|
42
|
+
scale?: number;
|
|
43
|
+
/**
|
|
44
|
+
* 이 컬럼이 공유 통화 컬럼(SHARED_REF) 모드를 지원하는지 — true면 삽입/편집 UI가 OWN/SHARED_REF
|
|
45
|
+
* picker를 노출한다(예: Money의 currency 필드). per-usage로 같은 엔터티의 다른 컬럼을 참조하는
|
|
46
|
+
* 모델 표현은 인스턴스 `DbColumn.sharedColumnRef`가 담당하며, 이 플래그는 어떤 카탈로그 필드에
|
|
47
|
+
* 그 어포던스를 열어줄지 결정하는 **UI 힌트**일 뿐 모델에 모드를 저장하지 않는다.
|
|
48
|
+
*/
|
|
49
|
+
shareable?: boolean;
|
|
50
|
+
}
|
|
51
|
+
export interface EmbeddableCatalogEntry {
|
|
52
|
+
/** Attribute.type에 들어가는 임베더블 타입명(예: EmbeddableAddress). 카탈로그 내 유일. */
|
|
53
|
+
type: string;
|
|
54
|
+
/** 삽입 시 기본 속성명(예: address). 사후 rename 허용. */
|
|
55
|
+
defaultName: string;
|
|
56
|
+
/** 메뉴 표시 라벨(미지정 시 type). */
|
|
57
|
+
label?: MultiLangText;
|
|
58
|
+
/** 펼쳐질 컬럼 메타모델(선언 순서 = dbAttr 인덱스). */
|
|
59
|
+
fields: EmbeddableCatalogField[];
|
|
60
|
+
}
|
|
61
|
+
export type EmbeddableCatalog = EmbeddableCatalogEntry[];
|
|
62
|
+
/**
|
|
63
|
+
* Predefined customtype 카탈로그 — 등록된 **단일 컬럼** 커스텀 자바 타입(레거시 JavaType 중 StoredFile·
|
|
64
|
+
* MultiLangString 등 ③ 분류)의 타입 셀렉트 진입 정의. ②embeddable과 달리 단일 컬럼이라 컬럼 구조가
|
|
65
|
+
* ①스칼라와 동일 — 별도 진입이 아니라 ① 타입 셀렉트에 병합 노출하고(④ CustomType과 동질), 선택 시
|
|
66
|
+
* 단일 dbAttr의 dataType만 카탈로그 메타로 시드한다(attrType은 NORMAL 유지 — EMBED_PREDEF 아님).
|
|
67
|
+
* EmbeddableCatalog와 동형으로 **호스트가 주입**하며(MultiLangString·StoredFile은 프레임워크 공통분 +
|
|
68
|
+
* 프로젝트별 추가분) 코어는 소비만 한다 — lib에 정적 baseline을 두지 않는다. 빈 배열이면 셀렉트에
|
|
69
|
+
* 추가 옵션이 노출되지 않는다(inert — 기존 customtype-typed 속성은 폴백 합성으로 원형 표시).
|
|
70
|
+
*/
|
|
71
|
+
export interface PredefinedCustomTypeEntry {
|
|
72
|
+
/** Attribute.type에 들어가는 커스텀 타입명(예: StoredFile). 카탈로그 내 유일. */
|
|
73
|
+
type: string;
|
|
74
|
+
/** 셀렉트 표시 라벨(미지정 시 type). */
|
|
75
|
+
label?: MultiLangText;
|
|
76
|
+
/** 선택 시 단일 dbAttr에 시드할 물리 DB 타입. */
|
|
77
|
+
dataType: string;
|
|
78
|
+
length?: number;
|
|
79
|
+
scale?: number;
|
|
80
|
+
}
|
|
81
|
+
export type PredefinedCustomTypeCatalog = PredefinedCustomTypeEntry[];
|
|
82
|
+
/**
|
|
83
|
+
* 공통 코드 그룹 카탈로그 — 속성의 `groupCode`(코드성 속성이 참조하는 공통 코드 그룹) 선택 UI에 쓰일
|
|
84
|
+
* 그룹·코드 정의. 레거시 `EMGroupCodeSelectionLayer` + `EMGroupCodeProvider`(호스트 콜백) 대응.
|
|
85
|
+
* EmbeddableCatalog와 동형으로 **호스트가 주입**하며(완전 통합 시 systemCode API) 코어는 소비만 한다
|
|
86
|
+
* — 코어에 코드 데이터를 박으면 곧 하드코딩이므로 정의를 외부(호스트/dev 프리셋)에 둔다.
|
|
87
|
+
* 빈 배열이면 groupCode 드롭다운은 비노출(inert).
|
|
88
|
+
*/
|
|
89
|
+
export interface GroupCodeValue {
|
|
90
|
+
/** 코드 값(예: "GOLD"). 속성 선택 시 그대로 defaultValue로 채워진다. */
|
|
91
|
+
code: string;
|
|
92
|
+
/** 메뉴 표시 라벨(미지정 시 code). */
|
|
93
|
+
label?: MultiLangText;
|
|
94
|
+
/** 코드 색상(레거시 codeList color, 선택). */
|
|
95
|
+
color?: string;
|
|
96
|
+
}
|
|
97
|
+
export interface GroupCodeCatalogEntry {
|
|
98
|
+
/** Attribute.groupCode에 들어가는 그룹 코드명(예: "CUSTOMER_GRADE"). 카탈로그 내 유일. */
|
|
99
|
+
groupCode: string;
|
|
100
|
+
/** 메뉴 표시 라벨(미지정 시 groupCode). */
|
|
101
|
+
label?: MultiLangText;
|
|
102
|
+
/** 그룹에 속한 코드 값 목록(선언 순서 = 드롭다운 표시 순서). */
|
|
103
|
+
codes: GroupCodeValue[];
|
|
104
|
+
}
|
|
105
|
+
export type GroupCodeCatalog = GroupCodeCatalogEntry[];
|
|
106
|
+
export interface DbColumn {
|
|
107
|
+
modelId: ModelId;
|
|
108
|
+
physicalName: string;
|
|
109
|
+
logicalName?: MultiLangText;
|
|
110
|
+
dataType: string;
|
|
111
|
+
length?: number;
|
|
112
|
+
scale?: number;
|
|
113
|
+
unique?: boolean;
|
|
114
|
+
autoIncrement?: boolean;
|
|
115
|
+
updatable?: boolean;
|
|
116
|
+
/** JPA @Column(insertable=…). undefined=기본 따름. v1 레거시엔 없는 신규 옵션. */
|
|
117
|
+
insertable?: boolean;
|
|
118
|
+
/**
|
|
119
|
+
* 공유 통화 컬럼(SHARED_REF) — 이 컬럼이 자체 물리 컬럼을 갖지 않고 같은 엔터티의 다른 컬럼을
|
|
120
|
+
* **modelId로 참조**해 그 물리 컬럼에 read-only 투영됨을 뜻한다(예: Money embeddable의 currency
|
|
121
|
+
* 서브컬럼이 별도 스칼라 통화 속성의 컬럼을 공유). 존재 시 physicalName·insertable·updatable는
|
|
122
|
+
* 저장하지 않고 타깃 컬럼에서 파생(자동 insertable=false·updatable=false). 부재 시 OWN(전용 컬럼).
|
|
123
|
+
* FK 전파의 부모 PK 링크(persisted PDbAttr.targetModelId)와는 의미가 다른 별개 개념. v1 레거시엔
|
|
124
|
+
* 없는 신규 옵션. 근거=OrderItem 실측 67개 중 48개가 단일 통화 컬럼 공유(memory money-shared-currency-column-decision).
|
|
125
|
+
*/
|
|
126
|
+
sharedColumnRef?: ModelId;
|
|
127
|
+
/** 다중값 컬럼 여부(레거시 AttributeDatabaseAttribute.multiValue). 라운드트립 보존 전용. */
|
|
128
|
+
multiValue?: boolean;
|
|
129
|
+
/** 다중값 직렬화 구분자(레거시 기본 "|"). multiValue=false여도 원형 보존 위해 verbatim 유지. */
|
|
130
|
+
multiValueSeparator?: string;
|
|
131
|
+
/** 시퀀스명(레거시 AttributeDatabaseAttribute.sequenceName). 라운드트립 보존 전용. */
|
|
132
|
+
sequenceName?: string;
|
|
133
|
+
}
|
|
134
|
+
export interface Attribute {
|
|
135
|
+
modelId: ModelId;
|
|
136
|
+
name: string;
|
|
137
|
+
type: string;
|
|
138
|
+
/** 빌트인 JavaType이 아닌 사용자 정의/커스텀 타입명(예: StoredFile). type이 커스텀 마커일 때 실제 타입. */
|
|
139
|
+
customType?: string;
|
|
140
|
+
attrType: AttributeType;
|
|
141
|
+
identifier: boolean;
|
|
142
|
+
notNull: boolean;
|
|
143
|
+
transient?: boolean;
|
|
144
|
+
description?: MultiLangText;
|
|
145
|
+
attributeGroup?: string;
|
|
146
|
+
groupCode?: string;
|
|
147
|
+
/**
|
|
148
|
+
* 속성 기본값(레거시 AttributeModel.defaultValue). 코드성 속성은 groupCode 선택 시 그 code 문자열을
|
|
149
|
+
* 채우고, 그 외엔 자유 입력("Y"/"N"/"999" 등). 항상 문자열 패스스루(타입 무관 verbatim 보존).
|
|
150
|
+
*/
|
|
151
|
+
defaultValue?: string;
|
|
152
|
+
/**
|
|
153
|
+
* 개인정보 속성 유형(레거시 AttributeModel.personalInfoAttributeType, PersonalInfoAttributeType enum 이름).
|
|
154
|
+
* 라운드트립 보존 전용 — Operation.personalInfoAttributeType와 동형으로 문자열 패스스루.
|
|
155
|
+
*/
|
|
156
|
+
personalInfoAttributeType?: string;
|
|
157
|
+
order: number;
|
|
158
|
+
/** 보통 1개, 임베더블 플래튼 시 다수 */
|
|
159
|
+
dbAttrs: DbColumn[];
|
|
160
|
+
/**
|
|
161
|
+
* 식별자 전파로 생성된 FK 속성의 출처. 수동 작성 속성은 undefined.
|
|
162
|
+
* 재전파/정리 시 컬럼 단위 매칭 키로 쓴다(associationRef + sourceAttributeRef).
|
|
163
|
+
*/
|
|
164
|
+
derivedFrom?: {
|
|
165
|
+
/** 이 FK를 만든 관계 */
|
|
166
|
+
associationRef: ModelId;
|
|
167
|
+
/** 부모의 어느 식별자 속성을 미러하는가 */
|
|
168
|
+
sourceAttributeRef: ModelId;
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* 임베더블 인라인 EMBED hydration의 출처(load-only, 화면 표시 전용).
|
|
172
|
+
* 레거시는 임베더블 타입의 플래튼 컬럼 묶음을 소유자 association end에 인라인(EMBED_OWN)으로만
|
|
173
|
+
* 저장한다 → 로드 시 소유자 엔티티로 펼쳐 표시한다(컬럼은 source 물리정의 ⊕ owner 오버라이드 머지).
|
|
174
|
+
* 저장 시 이 속성은 entity.attributes에서 제외되고 association 인라인 원형(legacyEmbedRaw)으로 환원된다.
|
|
175
|
+
*/
|
|
176
|
+
embedded?: {
|
|
177
|
+
/** 이 임베드를 만든 association */
|
|
178
|
+
associationRef: ModelId;
|
|
179
|
+
/** 임베더블 타입 엔티티(컬럼 정의 source) */
|
|
180
|
+
embeddableRef: ModelId;
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
export interface IndexColumn {
|
|
184
|
+
/** 참조 컬럼 modelId */
|
|
185
|
+
columnRef: ModelId;
|
|
186
|
+
descending: boolean;
|
|
187
|
+
}
|
|
188
|
+
export interface EntityIndex {
|
|
189
|
+
modelId: ModelId;
|
|
190
|
+
name: string;
|
|
191
|
+
unique: boolean;
|
|
192
|
+
description?: string;
|
|
193
|
+
parameters?: string;
|
|
194
|
+
columns: IndexColumn[];
|
|
195
|
+
}
|
|
196
|
+
export interface EntityJpaAttrs {
|
|
197
|
+
useVersion?: boolean;
|
|
198
|
+
useCacheable?: boolean;
|
|
199
|
+
useDynamicInsert?: boolean;
|
|
200
|
+
useDynamicUpdate?: boolean;
|
|
201
|
+
useDiscriminator?: boolean;
|
|
202
|
+
/**
|
|
203
|
+
* @DiscriminatorColumn 상세 — useDiscriminator=true일 때만 의미.
|
|
204
|
+
* 레거시 EntityJPAAttribute.discriminatorColumnName/discriminatorType/discriminatorLength.
|
|
205
|
+
* discriminatorType은 레거시 DiscriminatorType enum(STRING/CHAR/INTEGER)이나 persisted 계층 관례대로 문자열로 보존.
|
|
206
|
+
*/
|
|
207
|
+
discriminatorColumnName?: string;
|
|
208
|
+
discriminatorType?: string;
|
|
209
|
+
discriminatorLength?: number;
|
|
210
|
+
}
|
|
211
|
+
export type OperationVisibility = 'PUBLIC' | 'PRIVATE' | 'PROTECTED' | 'PACKAGE';
|
|
212
|
+
/**
|
|
213
|
+
* 엔티티 메서드 (레거시 OperationModel). 현재는 round-trip 보존 전용 — 렌더/편집은 PR2.
|
|
214
|
+
*/
|
|
215
|
+
export interface Operation {
|
|
216
|
+
modelId: ModelId;
|
|
217
|
+
name: string;
|
|
218
|
+
visibility?: OperationVisibility;
|
|
219
|
+
/** Java 메서드 본문 (멀티라인) */
|
|
220
|
+
sourceCode?: string;
|
|
221
|
+
/**
|
|
222
|
+
* ⚠️ 레거시 직렬화는 평문 string(Entity.description의 MultiLangText와 비대칭).
|
|
223
|
+
* 어댑터가 평문↔{ko} 변환해 모델 형태를 통일한다. PR2에서 ko 외 언어 편집 시 평문 역환원 비대칭 잔존.
|
|
224
|
+
*/
|
|
225
|
+
description?: MultiLangText;
|
|
226
|
+
order: number;
|
|
227
|
+
personalInfoAttributeType?: string;
|
|
228
|
+
/**
|
|
229
|
+
* 라운드트립 전용 — 레거시 직렬화의 미매핑 키(parent back-ref·properties 등) 원형.
|
|
230
|
+
* 로드 시 어댑터가 보관, 저장 시 verbatim 환원한다. UI·전파는 무시한다.
|
|
231
|
+
* style은 뷰 관심사라 EntityLayout.operationStyles로 분리(여기 포함 안 함). [[embed-hydration-option-na]] 보존 패턴 동형.
|
|
232
|
+
*/
|
|
233
|
+
legacyRaw?: Record<string, unknown>;
|
|
234
|
+
}
|
|
235
|
+
export interface Entity {
|
|
236
|
+
modelId: ModelId;
|
|
237
|
+
name: string;
|
|
238
|
+
stereotype: ClassStereotype;
|
|
239
|
+
packageName?: string;
|
|
240
|
+
superClass?: string;
|
|
241
|
+
schema?: string;
|
|
242
|
+
description?: MultiLangText;
|
|
243
|
+
abstractClass?: boolean;
|
|
244
|
+
hasPersonalInfo?: boolean;
|
|
245
|
+
declarationOfInterfaces?: string[];
|
|
246
|
+
attributes: Attribute[];
|
|
247
|
+
operations?: Operation[];
|
|
248
|
+
indexes?: EntityIndex[];
|
|
249
|
+
jpaAttrs?: EntityJpaAttrs;
|
|
250
|
+
table?: {
|
|
251
|
+
physicalName: string;
|
|
252
|
+
logicalName?: MultiLangText;
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
export interface AssociationEnd {
|
|
256
|
+
/** 이 끝이 가리키는 엔티티 */
|
|
257
|
+
entityRef: ModelId;
|
|
258
|
+
multiplicity: Multiplicity;
|
|
259
|
+
navigable: boolean;
|
|
260
|
+
composition: boolean;
|
|
261
|
+
/** FK/조인을 표현하는 속성 (RELATION_OWN/REF) */
|
|
262
|
+
attributeRef?: ModelId;
|
|
263
|
+
/**
|
|
264
|
+
* 라운드트립 전용 — 레거시 crossed 직렬화의 nav 참조 속성 원형(신규 모델에 표현 슬롯 없음).
|
|
265
|
+
* 로드 시 어댑터가 보관, 저장 시 그대로 환원한다. UI·전파는 무시한다.
|
|
266
|
+
*/
|
|
267
|
+
legacyNavRaw?: Record<string, unknown>;
|
|
268
|
+
/**
|
|
269
|
+
* 라운드트립 전용 — 레거시 EMBED 직렬화의 인라인 속성 원형(EMBED_REF/EMBED_OWN).
|
|
270
|
+
* EMBED hydration은 load-only라 저장 시 소유자로 펼친 표시 속성을 버리고 이 원형을 verbatim 환원한다
|
|
271
|
+
* (의미 재구성 없이 무손실 보존). UI·전파는 무시한다. [[embed-hydration-option-na]]
|
|
272
|
+
*/
|
|
273
|
+
legacyEmbedRaw?: Record<string, unknown>;
|
|
274
|
+
jpa?: {
|
|
275
|
+
fetchType?: JpaFetchType;
|
|
276
|
+
cascadeTypes?: JpaCascadeType[];
|
|
277
|
+
orphanRemoval?: boolean;
|
|
278
|
+
orderBy?: string;
|
|
279
|
+
/**
|
|
280
|
+
* 컬렉션 EMBED(`@ElementCollection`) 전용 — 이 end가 *_MORE multiplicity(N행)일 때만 의미.
|
|
281
|
+
* 단일 EMBED(EXACTLY_ONE)엔 무의미(검증 CHK로 차단·UI 비노출). 컬렉션 판정 권위는 multiplicity이며
|
|
282
|
+
* 아래 필드는 부속 메타다(결정 3: 별도 boolean 플래그 없음 — collection 여부는 multiplicity가 SoT).
|
|
283
|
+
*/
|
|
284
|
+
collectionType?: 'LIST' | 'SET';
|
|
285
|
+
/** `@CollectionTable` 이름(미지정 시 코드젠 규약 폴백). */
|
|
286
|
+
collectionTable?: string;
|
|
287
|
+
/** List일 때 `@OrderColumn` 명(미지정 시 폴백 or 순서 비보존). */
|
|
288
|
+
orderColumn?: string;
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
export interface Association {
|
|
292
|
+
modelId: ModelId;
|
|
293
|
+
description?: string;
|
|
294
|
+
/**
|
|
295
|
+
* 식별 관계 여부. true면 부모 PK가 자식 PK의 일부로 전파(식별 관계),
|
|
296
|
+
* false/undefined면 일반 FK로만 전파(비식별 관계).
|
|
297
|
+
* self-association(end1.entityRef===end2.entityRef)은 식별 불가(INV-3).
|
|
298
|
+
*/
|
|
299
|
+
identifying?: boolean;
|
|
300
|
+
/** 부모(PK 원천, "1" 측) */
|
|
301
|
+
end1: AssociationEnd;
|
|
302
|
+
/** 자식(FK 보유, "N" 측) */
|
|
303
|
+
end2: AssociationEnd;
|
|
304
|
+
}
|
|
305
|
+
export interface LogicalGroup {
|
|
306
|
+
modelId: ModelId;
|
|
307
|
+
name?: MultiLangText;
|
|
308
|
+
/** 그룹 설명(자유 텍스트) — 모듈/도메인 경계 의도 메모 */
|
|
309
|
+
description?: string;
|
|
310
|
+
packageName?: string;
|
|
311
|
+
excludeDDLGeneration: boolean;
|
|
312
|
+
/** 멤버십을 값 포함이 아닌 id 참조로 */
|
|
313
|
+
memberEntityRefs: ModelId[];
|
|
314
|
+
}
|
|
315
|
+
/** 논리 모델 전체 (한 비즈니스 모듈의 의미 정보) */
|
|
316
|
+
export interface LogicalModel {
|
|
317
|
+
modelId: ModelId;
|
|
318
|
+
packageName?: string;
|
|
319
|
+
entities: Entity[];
|
|
320
|
+
associations: Association[];
|
|
321
|
+
groups: LogicalGroup[];
|
|
322
|
+
}
|
|
323
|
+
export interface Point {
|
|
324
|
+
x: number;
|
|
325
|
+
y: number;
|
|
326
|
+
}
|
|
327
|
+
export interface Size {
|
|
328
|
+
width: number;
|
|
329
|
+
height: number;
|
|
330
|
+
}
|
|
331
|
+
export interface Geo {
|
|
332
|
+
location: Point;
|
|
333
|
+
size: Size;
|
|
334
|
+
}
|
|
335
|
+
export type DisplayMode = 'LOGICAL' | 'PHYSICAL' | 'LOGICAL_PHYSICAL' | 'CLASS';
|
|
336
|
+
export interface Style {
|
|
337
|
+
properties: Record<string, unknown>;
|
|
338
|
+
}
|
|
339
|
+
export interface EntityLayout {
|
|
340
|
+
entityRef: ModelId;
|
|
341
|
+
geo: Geo;
|
|
342
|
+
collapsed?: boolean;
|
|
343
|
+
displayMode?: DisplayMode;
|
|
344
|
+
/** 엔티티 헤더 바 색상 등 (style.properties.swatch = 토큰명) */
|
|
345
|
+
style?: Style;
|
|
346
|
+
/** 속성별 강조 색상 — attribute modelId 참조. 색은 뷰 관심사라 논리 Attribute가 아닌 레이아웃에 둔다. */
|
|
347
|
+
attributeStyles?: Record<ModelId, Style>;
|
|
348
|
+
/** 메서드별 강조 색상 — operation modelId 참조. attributeStyles와 동형(색은 뷰 관심사). */
|
|
349
|
+
operationStyles?: Record<ModelId, Style>;
|
|
350
|
+
}
|
|
351
|
+
export interface AssociationLayout {
|
|
352
|
+
associationRef: ModelId;
|
|
353
|
+
/** 직각 라우팅 제어점 (편집 가능 waypoint) */
|
|
354
|
+
waypoints: Point[];
|
|
355
|
+
/** 양 끝이 붙는 컬럼 앵커 (속성 행 단위 연결) */
|
|
356
|
+
sourceColumnRef?: ModelId;
|
|
357
|
+
targetColumnRef?: ModelId;
|
|
358
|
+
labelOffset?: Point;
|
|
359
|
+
style?: Style;
|
|
360
|
+
}
|
|
361
|
+
export interface GroupLayout {
|
|
362
|
+
groupRef: ModelId;
|
|
363
|
+
geo: Geo;
|
|
364
|
+
style?: Style;
|
|
365
|
+
/**
|
|
366
|
+
* 그룹 박스에 시각적으로 포함된 노트 멤버십(레거시 `groups[].notes`). 노트는 순수 레이아웃
|
|
367
|
+
* 객체(논리 의미 없음)라 멤버십도 레이아웃에 둔다 — 엔티티 멤버십(LogicalGroup.memberEntityRefs)과 비대칭.
|
|
368
|
+
*/
|
|
369
|
+
memberNoteRefs?: ModelId[];
|
|
370
|
+
}
|
|
371
|
+
export interface NoteConnection {
|
|
372
|
+
/** 노트가 연결하는 대상 (엔티티/노트 등) */
|
|
373
|
+
targetRef: ModelId;
|
|
374
|
+
waypoints: Point[];
|
|
375
|
+
}
|
|
376
|
+
export interface Note {
|
|
377
|
+
modelId: ModelId;
|
|
378
|
+
memo: string;
|
|
379
|
+
geo: Geo;
|
|
380
|
+
style?: Style;
|
|
381
|
+
connections?: NoteConnection[];
|
|
382
|
+
/**
|
|
383
|
+
* 레거시 직렬화 중 next 모델로 매핑하지 않은 키(`ownedConnections`·`parent`·`properties`)의
|
|
384
|
+
* verbatim 보존(operation legacyRaw와 동형). 연결선 의미 재구성은 추후 UI에서.
|
|
385
|
+
*/
|
|
386
|
+
legacyRaw?: Record<string, unknown>;
|
|
387
|
+
}
|
|
388
|
+
/** 한 다이어그램(뷰)의 레이아웃 — 1 논리모델 : N 다이어그램 가능 */
|
|
389
|
+
export interface DiagramLayout {
|
|
390
|
+
diagramId: ModelId;
|
|
391
|
+
/** 어떤 논리 모델을 비추는가 */
|
|
392
|
+
logicalModelRef: ModelId;
|
|
393
|
+
name?: string;
|
|
394
|
+
canvasSize?: Size;
|
|
395
|
+
zoom?: number;
|
|
396
|
+
entityLayouts: EntityLayout[];
|
|
397
|
+
associationLayouts: AssociationLayout[];
|
|
398
|
+
groupLayouts: GroupLayout[];
|
|
399
|
+
notes: Note[];
|
|
400
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { EmbeddableCatalog, LogicalModel, ModelId } from './types';
|
|
2
|
+
export declare const PHYSICAL_NAME_MAX_LENGTH = 63;
|
|
3
|
+
/**
|
|
4
|
+
* 물리명이 이식성 권장 한도를 초과하면 경고 메시지, 아니면 null(비차단 — 호출부는 저장을 막지 않는다).
|
|
5
|
+
* 빈값/미설정은 경고 없음(레거시 isNotEmpty 게이트 동형).
|
|
6
|
+
*/
|
|
7
|
+
export declare function physicalNameWarning(name: string | null | undefined): string | null;
|
|
8
|
+
export type IssueSeverity = 'error' | 'warning' | 'info';
|
|
9
|
+
export type IssueTargetKind = 'entity' | 'attribute' | 'column' | 'association' | 'index' | 'group' | 'model';
|
|
10
|
+
export interface ValidationIssue {
|
|
11
|
+
/** 규칙 식별자(예: 'CHK-NAME-1'). 엔진 불변식 INV-*와 다른 네임스페이스(위반 가능·수정 대상). */
|
|
12
|
+
ruleId: string;
|
|
13
|
+
severity: IssueSeverity;
|
|
14
|
+
targetKind: IssueTargetKind;
|
|
15
|
+
/** 문제 요소의 modelId(model 레벨이면 생략). 뷰가 클릭→포커스에 사용. */
|
|
16
|
+
targetRef?: ModelId;
|
|
17
|
+
/** 보조 ref(예: 컬럼/속성 이슈의 소속 엔티티) — 뷰 그룹핑/내비용. */
|
|
18
|
+
contextRef?: ModelId;
|
|
19
|
+
message: string;
|
|
20
|
+
}
|
|
21
|
+
/** 카탈로그 의존 규칙을 켜는 선택 주입 — 미주입 시 해당 규칙 skip(범위 밖 아님, 컨텍스트 부재). */
|
|
22
|
+
export interface ValidationContext {
|
|
23
|
+
/** SQL 예약어 집합(대문자). 호스트 주입. 미주입 시 CHK-NAME-6 skip. */
|
|
24
|
+
reservedWords?: ReadonlySet<string>;
|
|
25
|
+
/**
|
|
26
|
+
* 타겟 DB가 허용하는 dataType 집합(다이얼렉트별). 호스트 주입. 미주입 시 CHK-TYPE-1 skip.
|
|
27
|
+
* reservedWords와 동형으로 ctx 게이트 — 코어 SELECTABLE_DATA_TYPES를 기본값으로 박지 않는 이유:
|
|
28
|
+
* 레거시 보존 타입(NCHAR 등 import verbatim)을 호스트가 다이얼렉트 셋을 줄 때까지 일괄 경고하지 않기 위함.
|
|
29
|
+
* 자연 주입값 = `new Set(SELECTABLE_DATA_TYPES)`(PG 타겟) — 호스트 통합 시 다이얼렉트로 대체.
|
|
30
|
+
*/
|
|
31
|
+
selectableDataTypes?: ReadonlySet<string>;
|
|
32
|
+
/** 비대 엔티티(god-object) 판정 임계치 — 논리 속성 수가 이 값 초과면 CHK-DSN-4. 미주입 시 skip. */
|
|
33
|
+
largeEntityThreshold?: number;
|
|
34
|
+
/**
|
|
35
|
+
* CHK-DSN-3(모델링된 관계 없는 엔티티) 켜기 — **기본 off**(미주입/false 시 skip).
|
|
36
|
+
* 옵트인인 이유: 비형식 FK(연관 엣지 없이 raw id 컬럼만 둔 경우)는 코어가 탐지 불가라 잔존 오탐이
|
|
37
|
+
* 원리적으로 제거되지 않는다. "참여"는 연관·상속(superClass)·임베딩(embedded)까지 넓혀 오탐을 최소화하되,
|
|
38
|
+
* 의도적 연관 생략 모델에선 노이즈이므로 호스트/사용자가 명시적으로 켤 때만 평가한다.
|
|
39
|
+
*/
|
|
40
|
+
flagEntitiesWithoutRelations?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Predefined 임베더블 카탈로그 — CHK-TYPE-3(공유 통화 컬럼 SHARED_REF 타깃 타입 불일치)의 기대
|
|
43
|
+
* 타입 출처. 호스트/dev 주입(reservedWords와 동형 ctx 게이트). 미주입/빈 배열이면 CHK-TYPE-3 skip.
|
|
44
|
+
*/
|
|
45
|
+
embeddableCatalog?: EmbeddableCatalog;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 설계 품질 검증 — 논리 모델(+선택 컨텍스트)을 받아 이슈 목록을 돌려준다.
|
|
49
|
+
* 순수 함수. 호출부가 심각도/차단정책/표시시점을 해석한다(예: 빈 이름 info는 저장 시점에만 표시).
|
|
50
|
+
*
|
|
51
|
+
* 범위: 명명·중복(CHK-NAME, P1) + JPA 정합성·물리타입·식별 사이클(CHK-JPA·CHK-TYPE, P2) + 설계 안티패턴(CHK-DSN, P3).
|
|
52
|
+
*/
|
|
53
|
+
export declare function validateModel(model: LogicalModel, ctx?: ValidationContext): ValidationIssue[];
|