@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
package/LICENSE
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
(c) Copyright 2023 UZEN, all rights reserved.
|
|
2
|
+
|
|
3
|
+
This software is the confidential and proprietary information of
|
|
4
|
+
UZEN Co.,Ltd., Inc. You shall not disclose such Confidential
|
|
5
|
+
Information and shall use it only in accordance with the terms of the
|
|
6
|
+
license agreement you entered into with UZEN.
|
package/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# entity-modeler-next
|
|
2
|
+
|
|
3
|
+
Vue 3 기반 비주얼 엔티티 모델링 / 클래스 다이어그램 에디터.
|
|
4
|
+
레거시 GWT/Vaadin 7 모듈(`bluework-entitymodeler`)의 후속이며, `bluework4-tool`(Nuxt/Vue/Mongo)에 임베드된다.
|
|
5
|
+
|
|
6
|
+
## 스택
|
|
7
|
+
|
|
8
|
+
TypeScript · Vue 3 · **Vue Flow** · Pinia(비강제) · Vite(library mode) · Vitest · view는 `@g1cloud/open-bluesea-core`(BS) 컴포넌트 기반
|
|
9
|
+
|
|
10
|
+
## 구조
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
src/
|
|
14
|
+
core/ 논리/레이아웃 타입(분리)·resolve(정합성)·routing·autolayout·propagation·validation·타입 카탈로그. 프레임워크 무관
|
|
15
|
+
command/ Command(do/undo)·CommandStack·op/opSync(시맨틱 op emit + CAS 동시성)
|
|
16
|
+
editor/ reactive controller (CommandStack 래핑 컴포저블, EDITOR inject 키)
|
|
17
|
+
view/ Vue Flow 컴포넌트 (DiagramCanvas·EntityNode·GroupNode·AssociationEdge·PropertyPanel·ValidationPanel 등)
|
|
18
|
+
adapter/ 레거시 PDiagram 매핑 (persisted v1/v2·fromPersisted/toPersisted/toPersistedV2 라운드트립)
|
|
19
|
+
agent/ 자연어→op 트랙 (symbolicOp·resolver·schema·buildAgentBatch)
|
|
20
|
+
dev/ 데모 하니스 (라이브러리 빌드에서 제외)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
핵심 설계: **레이아웃이 논리 모델을 `modelId`로 참조(단방향)**. 논리 모델엔 geo/waypoint/style이 없다.
|
|
24
|
+
**현재 구조·상태·문서 인덱스의 정본은 루트 `CLAUDE.md`** (저장 스키마 영향은 `docs/M0-schema-impact.md`).
|
|
25
|
+
|
|
26
|
+
## 스크립트
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pnpm dev # 스파이크/데모 dev 서버
|
|
30
|
+
pnpm test # Vitest (core 단위 테스트)
|
|
31
|
+
pnpm typecheck # vue-tsc
|
|
32
|
+
pnpm build # 라이브러리 빌드 (dist/)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## M0 스파이크 검증 포인트 (브라우저)
|
|
36
|
+
|
|
37
|
+
`pnpm dev` 후 다음을 확인:
|
|
38
|
+
- 엔티티 노드가 속성 행·PK 마커와 함께 렌더되는가
|
|
39
|
+
- 관계선이 **직각 라우팅**으로 그려지는가
|
|
40
|
+
- 파란 **waypoint**를 드래그하면 경로가 갱신되는가
|
|
41
|
+
- 세그먼트 중점(회색 원)을 **더블클릭**하면 waypoint가 추가되는가
|
|
42
|
+
- 관계선 끝이 특정 **컬럼 행(앵커)**에 붙는가 (Order.id ↔ OrderLine.orderId)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { EditorState } from '../command/types';
|
|
2
|
+
import { ModelId } from '../core/types';
|
|
3
|
+
import { PDiagram, PDiagramV2 } from './persisted';
|
|
4
|
+
export interface DiagramMeta {
|
|
5
|
+
id?: string;
|
|
6
|
+
version?: number;
|
|
7
|
+
diagramVersion?: string;
|
|
8
|
+
size?: {
|
|
9
|
+
width: number;
|
|
10
|
+
height: number;
|
|
11
|
+
};
|
|
12
|
+
packageName?: string;
|
|
13
|
+
/** 데이터 형태 세대 — 1=legacy flat, 2=logical/layout(op API 대상). 부재 시 1. */
|
|
14
|
+
schemaVersion?: number;
|
|
15
|
+
/** op 쓰기 롤아웃 게이트(불변식: true ⟹ schemaVersion>=2). v2 && false = read-only 프리즈(B-0-1). */
|
|
16
|
+
opWriteEnabled?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* v2 doc일 때 RevCache 시드(컨테이너 rev + layout/logical version). v1은 undefined.
|
|
19
|
+
* controller가 OpSyncAdapter.seed로 주입(base rev 라이브 캐시 초기화).
|
|
20
|
+
*/
|
|
21
|
+
revSeed?: {
|
|
22
|
+
revs: Record<ModelId, number>;
|
|
23
|
+
layoutVersion: number;
|
|
24
|
+
logicalVersion: number;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 마커 분기 파서 — `schemaVersion`을 보고 v1(legacy flat) vs v2(logical/layout) 경로 선택(B-0).
|
|
29
|
+
* reload(프리즈 후 재적재)도 이 진입점을 경유해 동일 분기를 탄다.
|
|
30
|
+
*/
|
|
31
|
+
export declare function fromPersisted(doc: PDiagram | PDiagramV2): {
|
|
32
|
+
state: EditorState;
|
|
33
|
+
meta: DiagramMeta;
|
|
34
|
+
};
|
|
35
|
+
export declare function toPersisted(state: EditorState, meta?: DiagramMeta): PDiagram;
|
|
36
|
+
/**
|
|
37
|
+
* v2 직렬화기 — `fromPersistedV2`의 역(near-identity). element는 core 모델 그대로 기록하고
|
|
38
|
+
* 컨테이너 rev·logical/layout version만 `meta.revSeed`에서 되붙인다(부재 시 0 시드).
|
|
39
|
+
*
|
|
40
|
+
* 마이그레이션(v1→v2 fork)은 revSeed 없는 meta로 호출 → 전 컨테이너 rev 0, version 0 시드.
|
|
41
|
+
* `id`·`opWriteEnabled`는 호출자가 meta로 제어(마이그레이션은 _id 미주입 + opWriteEnabled=true).
|
|
42
|
+
* 서버는 클라 전송 doc을 신뢰 없이 재검증(schemaVersion·sourceDiagramId·_id) — M4 §3 단위 1.
|
|
43
|
+
*/
|
|
44
|
+
export declare function toPersistedV2(state: EditorState, meta?: DiagramMeta): PDiagramV2;
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { Association, DiagramLayout, Entity, LogicalGroup, ModelId, MultiLangText, Point } from '../core/types';
|
|
2
|
+
export interface PGeo {
|
|
3
|
+
location: {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
};
|
|
7
|
+
size: {
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export interface PStyle {
|
|
13
|
+
properties: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
export interface PDbAttr {
|
|
16
|
+
modelId: string;
|
|
17
|
+
physicalName: string;
|
|
18
|
+
logicalName?: MultiLangText;
|
|
19
|
+
dataType: string;
|
|
20
|
+
length?: number;
|
|
21
|
+
scale?: number;
|
|
22
|
+
unique?: boolean;
|
|
23
|
+
autoIncrement?: boolean;
|
|
24
|
+
updatable?: boolean;
|
|
25
|
+
/** JPA @Column(insertable=…). undefined=기본 따름. v1 레거시엔 없는 신규 옵션. */
|
|
26
|
+
insertable?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* 공유 통화 컬럼(SHARED_REF) — 같은 엔터티 내 다른 컬럼 modelId 참조(read-only 투영, 물리 컬럼 0).
|
|
29
|
+
* 논리 모델 DbColumn.sharedColumnRef 직렬화. FK 전파용 targetModelId와는 별개 개념. v1 레거시 없음.
|
|
30
|
+
*/
|
|
31
|
+
sharedColumnRef?: string;
|
|
32
|
+
/** 레거시 AttributeDatabaseAttribute.multiValue. 라운드트립 보존 전용. */
|
|
33
|
+
multiValue?: boolean;
|
|
34
|
+
/** 레거시 AttributeDatabaseAttribute.multiValueSeparator(기본 "|"). 라운드트립 보존 전용. */
|
|
35
|
+
multiValueSeparator?: string;
|
|
36
|
+
/** 레거시 AttributeDatabaseAttribute.sequenceName. 라운드트립 보존 전용. */
|
|
37
|
+
sequenceName?: string;
|
|
38
|
+
/** FK 컬럼이 참조하는 부모 PK 컬럼 modelId. 식별자 전파(derivedFrom) 재구성의 명시 링크. */
|
|
39
|
+
targetModelId?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface PAttribute {
|
|
42
|
+
modelId: string;
|
|
43
|
+
name: string;
|
|
44
|
+
type: string;
|
|
45
|
+
customType?: string;
|
|
46
|
+
attrType: string;
|
|
47
|
+
identifier: boolean;
|
|
48
|
+
notNull: boolean;
|
|
49
|
+
transient_?: boolean;
|
|
50
|
+
description?: MultiLangText;
|
|
51
|
+
attributeGroup?: string;
|
|
52
|
+
groupCode?: string;
|
|
53
|
+
/** 레거시 AttributeModel.defaultValue. 코드성 속성은 groupCode의 code 문자열, 그 외 자유 입력. */
|
|
54
|
+
defaultValue?: string;
|
|
55
|
+
/** 레거시 AttributeModel.personalInfoAttributeType(enum 이름). 라운드트립 보존 전용. */
|
|
56
|
+
personalInfoAttributeType?: string;
|
|
57
|
+
order?: number;
|
|
58
|
+
dbAttrs: PDbAttr[];
|
|
59
|
+
style?: PStyle;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* association end에 인라인 저장되는 속성. 레거시 실데이터는 전체 PAttribute를 인라인으로 기록하나
|
|
63
|
+
* (FK 본체·nav 참조), next-native가 기록한 문서는 `{modelId}` 참조만 가질 수 있어 둘 다 수용한다.
|
|
64
|
+
*/
|
|
65
|
+
export type PInlineAttribute = {
|
|
66
|
+
modelId: string;
|
|
67
|
+
} & Partial<Omit<PAttribute, 'modelId'>>;
|
|
68
|
+
export interface PAssocEnd {
|
|
69
|
+
endModel: {
|
|
70
|
+
refId: string;
|
|
71
|
+
};
|
|
72
|
+
multiplicity: string;
|
|
73
|
+
navigable: boolean;
|
|
74
|
+
composition: boolean;
|
|
75
|
+
jpaAttribute?: {
|
|
76
|
+
fetchType?: string;
|
|
77
|
+
cascadeTypes?: string[];
|
|
78
|
+
orphanRemoval?: boolean;
|
|
79
|
+
orderBy?: string;
|
|
80
|
+
collectionType?: string;
|
|
81
|
+
collectionTable?: string;
|
|
82
|
+
orderColumn?: string;
|
|
83
|
+
};
|
|
84
|
+
attribute?: PInlineAttribute;
|
|
85
|
+
}
|
|
86
|
+
export interface PAssociation {
|
|
87
|
+
modelId: string;
|
|
88
|
+
description?: string;
|
|
89
|
+
locations?: Point[];
|
|
90
|
+
end1: PAssocEnd;
|
|
91
|
+
end2: PAssocEnd;
|
|
92
|
+
style?: PStyle;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* 레거시 OperationModel 직렬화 형태. ⚠️ description은 평문 string(PEntity/PAttribute의 MultiLangText와 비대칭).
|
|
96
|
+
* parent(back-ref)·properties 등 미매핑 키는 index signature로 수용 → 어댑터가 legacyRaw로 verbatim 보존.
|
|
97
|
+
*/
|
|
98
|
+
export interface POperation {
|
|
99
|
+
modelId: string;
|
|
100
|
+
name: string;
|
|
101
|
+
visibility?: string;
|
|
102
|
+
sourceCode?: string;
|
|
103
|
+
description?: string;
|
|
104
|
+
order?: number;
|
|
105
|
+
personalInfoAttributeType?: string;
|
|
106
|
+
style?: PStyle;
|
|
107
|
+
[key: string]: unknown;
|
|
108
|
+
}
|
|
109
|
+
export interface PEntity {
|
|
110
|
+
modelId: string;
|
|
111
|
+
name: string;
|
|
112
|
+
stereotype: string;
|
|
113
|
+
packageName?: string;
|
|
114
|
+
superClass?: string;
|
|
115
|
+
schema?: string;
|
|
116
|
+
description?: MultiLangText;
|
|
117
|
+
abstractClass?: boolean;
|
|
118
|
+
hasPersonalInfo?: boolean;
|
|
119
|
+
declarationOfInterfaces?: string[];
|
|
120
|
+
attributes: PAttribute[];
|
|
121
|
+
operations?: POperation[];
|
|
122
|
+
ownedAssociations?: PAssociation[];
|
|
123
|
+
indexes?: PIndex[];
|
|
124
|
+
jpaAttrs?: PJpaAttrs;
|
|
125
|
+
dbAttrs?: {
|
|
126
|
+
physicalName: string;
|
|
127
|
+
logicalName?: MultiLangText;
|
|
128
|
+
};
|
|
129
|
+
geo?: PGeo;
|
|
130
|
+
style?: PStyle;
|
|
131
|
+
collapsed?: boolean;
|
|
132
|
+
}
|
|
133
|
+
export interface PIndex {
|
|
134
|
+
modelId: string;
|
|
135
|
+
name: string;
|
|
136
|
+
unique: boolean;
|
|
137
|
+
description?: string;
|
|
138
|
+
parameters?: string;
|
|
139
|
+
indexColumns: {
|
|
140
|
+
targetColumn: {
|
|
141
|
+
refId: string;
|
|
142
|
+
};
|
|
143
|
+
descending: boolean;
|
|
144
|
+
}[];
|
|
145
|
+
}
|
|
146
|
+
export interface PJpaAttrs {
|
|
147
|
+
useVersion?: boolean;
|
|
148
|
+
useCacheable?: boolean;
|
|
149
|
+
useDynamicInsert?: boolean;
|
|
150
|
+
useDynamicUpdate?: boolean;
|
|
151
|
+
useDiscriminator?: boolean;
|
|
152
|
+
/** 레거시 EntityJPAAttribute discriminator 상세. 어댑터가 jpaAttrs 객체 통째 패스스루라 자동 round-trip. */
|
|
153
|
+
discriminatorColumnName?: string;
|
|
154
|
+
discriminatorType?: string;
|
|
155
|
+
discriminatorLength?: number;
|
|
156
|
+
}
|
|
157
|
+
export interface PGroup {
|
|
158
|
+
modelId: string;
|
|
159
|
+
name?: MultiLangText;
|
|
160
|
+
description?: string;
|
|
161
|
+
packageName?: string;
|
|
162
|
+
excludeDDLGeneration?: boolean;
|
|
163
|
+
entities?: PEntity[];
|
|
164
|
+
/** 레거시는 노트를 엔티티처럼 그룹 멤버로 중첩 저장(그룹 상대좌표). 그룹 밖 자유 노트는 PDiagram.notes. */
|
|
165
|
+
notes?: PNote[];
|
|
166
|
+
geo?: PGeo;
|
|
167
|
+
style?: PStyle;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* 레거시 NoteModel 직렬화 형태. 연결선은 `ownedConnections`(end1/end2/locations 구조)로 저장되고
|
|
171
|
+
* next-native가 쓰는 `connections`(targetRef/waypoints)와 비대칭 — 둘 다 수용한다. `parent`(back-ref)·
|
|
172
|
+
* `properties` 등 미매핑 키는 index signature로 받아 어댑터가 legacyRaw로 verbatim 보존.
|
|
173
|
+
*/
|
|
174
|
+
export interface PNote {
|
|
175
|
+
modelId: string;
|
|
176
|
+
memo: string;
|
|
177
|
+
geo: PGeo;
|
|
178
|
+
style?: PStyle;
|
|
179
|
+
connections?: {
|
|
180
|
+
targetRef: string;
|
|
181
|
+
waypoints: Point[];
|
|
182
|
+
}[];
|
|
183
|
+
[key: string]: unknown;
|
|
184
|
+
}
|
|
185
|
+
export interface PDiagram {
|
|
186
|
+
/** Mongo _id (문자열화) */
|
|
187
|
+
id?: string;
|
|
188
|
+
/**
|
|
189
|
+
* 데이터 형태 세대(트랙 B 마커). 부재/1 = 레거시 flat(이 PDiagram 형태), 2 = logical/layout(PDiagramV2).
|
|
190
|
+
* `fromPersisted` 분기 신호. 레거시 doc은 이 필드가 없다.
|
|
191
|
+
*/
|
|
192
|
+
schemaVersion?: number;
|
|
193
|
+
/** op 쓰기 롤아웃 게이트(불변식: true ⟹ schemaVersion>=2). v1 doc엔 무의미. */
|
|
194
|
+
opWriteEnabled?: boolean;
|
|
195
|
+
diagramVersion?: string;
|
|
196
|
+
version?: number;
|
|
197
|
+
size?: {
|
|
198
|
+
width: number;
|
|
199
|
+
height: number;
|
|
200
|
+
};
|
|
201
|
+
packageName?: string;
|
|
202
|
+
entities?: PEntity[];
|
|
203
|
+
groups?: PGroup[];
|
|
204
|
+
notes?: PNote[];
|
|
205
|
+
}
|
|
206
|
+
/** v2 logical 컨테이너 — core 모델 + 컨테이너 rev(영속 전용 CAS 메타, 파서가 RevCache로 분리). */
|
|
207
|
+
export type PV2Entity = Entity & {
|
|
208
|
+
rev?: number;
|
|
209
|
+
};
|
|
210
|
+
export type PV2Association = Association & {
|
|
211
|
+
rev?: number;
|
|
212
|
+
};
|
|
213
|
+
export type PV2Group = LogicalGroup & {
|
|
214
|
+
rev?: number;
|
|
215
|
+
};
|
|
216
|
+
export interface PV2Logical {
|
|
217
|
+
/** logicalVersion — 거친 stale 마커(reconcile 힌트, CAS 게이트 아님). M2 §4.2. */
|
|
218
|
+
version?: number;
|
|
219
|
+
modelId: ModelId;
|
|
220
|
+
packageName?: string;
|
|
221
|
+
entities: PV2Entity[];
|
|
222
|
+
associations: PV2Association[];
|
|
223
|
+
groups: PV2Group[];
|
|
224
|
+
}
|
|
225
|
+
export interface PV2Layout extends DiagramLayout {
|
|
226
|
+
/** layout.version — layout op LWW CAS 게이트. M2 §4.2. */
|
|
227
|
+
version?: number;
|
|
228
|
+
}
|
|
229
|
+
export interface PDiagramV2 {
|
|
230
|
+
/** Mongo _id (문자열화) */
|
|
231
|
+
id?: string;
|
|
232
|
+
schemaVersion: 2;
|
|
233
|
+
/** op 쓰기 롤아웃 게이트. false = read-only 프리즈(B-0-1, 쓰기 kill-switch). */
|
|
234
|
+
opWriteEnabled?: boolean;
|
|
235
|
+
/** doc-level optlock(기존 version 계승). */
|
|
236
|
+
version?: number;
|
|
237
|
+
diagramVersion?: string;
|
|
238
|
+
packageName?: string;
|
|
239
|
+
size?: {
|
|
240
|
+
width: number;
|
|
241
|
+
height: number;
|
|
242
|
+
};
|
|
243
|
+
logical: PV2Logical;
|
|
244
|
+
layout: PV2Layout;
|
|
245
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ModelId } from '../core/types';
|
|
2
|
+
import { OpOrigin, OpShape, PersistedOpBatch } from '../command/op';
|
|
3
|
+
export interface BuildAgentBatchOptions {
|
|
4
|
+
/** clientOpId(멱등 키) 발급기 — 주입 시 테스트 결정성. 기본 newId(crypto.randomUUID). */
|
|
5
|
+
mkClientOpId?: () => string;
|
|
6
|
+
/** op 출처 — 기본 'agent'(감사·aggregation 트리거 분기). REST 브리지면 'rest'. */
|
|
7
|
+
origin?: OpOrigin;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* 에이전트/REST 경로의 stateless 배치 조립.
|
|
11
|
+
*
|
|
12
|
+
* @param diagramId 대상 diagram id(호스트 라우트가 bizModule→DBRef로 해소하므로 doc id).
|
|
13
|
+
* @param revs base rev 스냅샷(`fromPersisted(doc).meta.revSeed.revs`). 컨테이너 modelId→rev.
|
|
14
|
+
* @param ops resolver 산출 OpShape 배치(한 원자 단위).
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildAgentBatch(diagramId: string, revs: Record<ModelId, number>, ops: OpShape[], options?: BuildAgentBatchOptions): PersistedOpBatch;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { LogicalModel, ModelId } from '../core/types';
|
|
2
|
+
import { OpShape } from '../command/op';
|
|
3
|
+
import { AssocHandle, Handle, SymbolicOp } from './symbolicOp';
|
|
4
|
+
/** 해소 실패 — 어느 심볼릭 op(`opIndex`)의 어떤 핸들이 0개/복수 매칭인지. */
|
|
5
|
+
export type ResolveError = {
|
|
6
|
+
code: 'entity-not-found';
|
|
7
|
+
opIndex: number;
|
|
8
|
+
handle: Handle;
|
|
9
|
+
} | {
|
|
10
|
+
code: 'entity-ambiguous';
|
|
11
|
+
opIndex: number;
|
|
12
|
+
handle: Handle;
|
|
13
|
+
matches: ModelId[];
|
|
14
|
+
} | {
|
|
15
|
+
code: 'attribute-not-found';
|
|
16
|
+
opIndex: number;
|
|
17
|
+
entity: Handle;
|
|
18
|
+
handle: Handle;
|
|
19
|
+
} | {
|
|
20
|
+
code: 'attribute-ambiguous';
|
|
21
|
+
opIndex: number;
|
|
22
|
+
entity: Handle;
|
|
23
|
+
handle: Handle;
|
|
24
|
+
matches: ModelId[];
|
|
25
|
+
} | {
|
|
26
|
+
code: 'association-not-found';
|
|
27
|
+
opIndex: number;
|
|
28
|
+
handle: AssocHandle;
|
|
29
|
+
} | {
|
|
30
|
+
code: 'association-ambiguous';
|
|
31
|
+
opIndex: number;
|
|
32
|
+
handle: AssocHandle;
|
|
33
|
+
matches: ModelId[];
|
|
34
|
+
} | {
|
|
35
|
+
code: 'self-identifying';
|
|
36
|
+
opIndex: number;
|
|
37
|
+
handle: AssocHandle;
|
|
38
|
+
};
|
|
39
|
+
export type ResolveResult = {
|
|
40
|
+
ok: true;
|
|
41
|
+
ops: OpShape[];
|
|
42
|
+
} | {
|
|
43
|
+
ok: false;
|
|
44
|
+
errors: ResolveError[];
|
|
45
|
+
};
|
|
46
|
+
export interface ResolverOptions {
|
|
47
|
+
/** modelId 발급기(주입 시 테스트 결정성). 기본 newId. */
|
|
48
|
+
mkId?: () => ModelId;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 심볼릭 op 배치를 OpShape 배치로 해소한다.
|
|
52
|
+
* 전부 해소되면 `{ok:true, ops}`, 하나라도 실패하면 `{ok:false, errors}`(모든 실패 누적 — 에이전트가 한 번에 재질의).
|
|
53
|
+
*/
|
|
54
|
+
export declare function resolveSymbolicOps(model: LogicalModel, ops: SymbolicOp[], options?: ResolverOptions): ResolveResult;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type JsonSchema = Record<string, unknown>;
|
|
2
|
+
/** 단일 SymbolicOp의 JSON Schema(kind로 판별되는 anyOf). $defs는 최상위에서 정의. */
|
|
3
|
+
export declare const SYMBOLIC_OP_SCHEMA: JsonSchema;
|
|
4
|
+
/**
|
|
5
|
+
* MCP `apply_model_ops` 도구의 input_schema. 한 배치 = 한 원자 단위(resolver가 전부 해소 or 전부 실패).
|
|
6
|
+
* description은 "언제 호출하는지"를 명시 — 최신 모델은 도구를 보수적으로 집으므로 트리거 조건이 호출률을 좌우.
|
|
7
|
+
*/
|
|
8
|
+
export declare const APPLY_MODEL_OPS_INPUT_SCHEMA: JsonSchema;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { ClassStereotype, Multiplicity } from '../core/types';
|
|
2
|
+
/**
|
|
3
|
+
* 요소 지정 핸들 — modelId 대신 이름/물리명.
|
|
4
|
+
* 엔티티: 물리명(`table.physicalName`) 우선, 논리명(`name`) 보조 — 논리명은 모델 내 중복 허용(CHK-NAME-3)이라 모호 가능.
|
|
5
|
+
* 속성: 소속 엔티티 내 속성명(`name`) 또는 컬럼 물리명(`dbAttrs[].physicalName`) — 둘 다 엔티티 내 유일(CHK-NAME-1/2).
|
|
6
|
+
*/
|
|
7
|
+
export interface Handle {
|
|
8
|
+
/** 매칭할 이름/물리명. */
|
|
9
|
+
ref: string;
|
|
10
|
+
/** 매칭 키 고정. 미지정 시 대상별 기본 순서로 시도(엔티티=물리명→논리명, 속성=논리명→물리명). */
|
|
11
|
+
by?: 'physicalName' | 'name';
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 관계 지정 — 관계는 무명이라 양 끝 엔티티로 주소한다.
|
|
15
|
+
* `from`=부모(end1, PK 원천 "1"측), `to`=자식(end2, FK 보유 "N"측).
|
|
16
|
+
* 같은 (from,to) 쌍에 복수 관계가 있으면 모호 → resolver가 escalation.
|
|
17
|
+
*/
|
|
18
|
+
export interface AssocHandle {
|
|
19
|
+
from: Handle;
|
|
20
|
+
to: Handle;
|
|
21
|
+
}
|
|
22
|
+
/** entity.add 페이로드 — resolver가 modelId 발급 + 빈 골격 조립. */
|
|
23
|
+
export interface EntitySpec {
|
|
24
|
+
name: string;
|
|
25
|
+
/** 기본 'JPA_ENTITY'. */
|
|
26
|
+
stereotype?: ClassStereotype;
|
|
27
|
+
/** 설정 시 `table.physicalName`. */
|
|
28
|
+
physicalName?: string;
|
|
29
|
+
}
|
|
30
|
+
/** attribute.add 페이로드 — resolver가 modelId 발급 + dbAttr 골격 조립. */
|
|
31
|
+
export interface AttrSpec {
|
|
32
|
+
name: string;
|
|
33
|
+
/** Java 타입(예: 'Long', 'String'). */
|
|
34
|
+
type: string;
|
|
35
|
+
identifier?: boolean;
|
|
36
|
+
notNull?: boolean;
|
|
37
|
+
/** 설정 시 단일 dbAttr 컬럼 생성(미설정이면 name을 물리명으로). */
|
|
38
|
+
physicalName?: string;
|
|
39
|
+
/** dbAttr 물리 타입(예: 'BIGINT'). physicalName/dataType/length/scale 중 하나라도 있으면 dbAttr 생성. */
|
|
40
|
+
dataType?: string;
|
|
41
|
+
/** dbAttr 컬럼 길이(VARCHAR(n)·DECIMAL precision). 0/미설정은 미지정. */
|
|
42
|
+
length?: number;
|
|
43
|
+
/** dbAttr 소수 자릿수(DECIMAL/NUMERIC scale). length 동반이 일반적. 0/미설정은 미지정. */
|
|
44
|
+
scale?: number;
|
|
45
|
+
}
|
|
46
|
+
/** association.add 페이로드 — from/to 엔티티는 resolver가 해소, modelId 발급 + end 조립. */
|
|
47
|
+
export interface AssocSpec {
|
|
48
|
+
/** 부모(end1, PK 원천). */
|
|
49
|
+
from: Handle;
|
|
50
|
+
/** 자식(end2, FK 보유). */
|
|
51
|
+
to: Handle;
|
|
52
|
+
/** end1 다중성(기본 EXACTLY_ONE_INSTANCE). */
|
|
53
|
+
fromMultiplicity?: Multiplicity;
|
|
54
|
+
/** end2 다중성(기본 ZERO_OR_MORE_INSTANCES). */
|
|
55
|
+
toMultiplicity?: Multiplicity;
|
|
56
|
+
/** 식별 관계 여부(부모 PK가 자식 PK로 전파). self-association은 식별 불가(INV-3) — resolver가 거부. */
|
|
57
|
+
identifying?: boolean;
|
|
58
|
+
/** end2 composition(부모가 자식 생명주기 소유). */
|
|
59
|
+
composition?: boolean;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* LLM이 산출하는 단일 심볼릭 op. `kind`는 op.ts 어휘와 1:1(로케이터만 심볼릭).
|
|
63
|
+
* `patch`는 OpShape.patch와 동형(부분 patch, 그대로 전달 — 값 품질은 검증 엔진이 사후 경고).
|
|
64
|
+
*/
|
|
65
|
+
export type SymbolicOp = {
|
|
66
|
+
kind: 'entity.add';
|
|
67
|
+
spec: EntitySpec;
|
|
68
|
+
} | {
|
|
69
|
+
kind: 'entity.update';
|
|
70
|
+
entity: Handle;
|
|
71
|
+
patch: Record<string, unknown>;
|
|
72
|
+
} | {
|
|
73
|
+
kind: 'entity.remove';
|
|
74
|
+
entity: Handle;
|
|
75
|
+
} | {
|
|
76
|
+
kind: 'attribute.add';
|
|
77
|
+
entity: Handle;
|
|
78
|
+
spec: AttrSpec;
|
|
79
|
+
} | {
|
|
80
|
+
kind: 'attribute.update';
|
|
81
|
+
entity: Handle;
|
|
82
|
+
attribute: Handle;
|
|
83
|
+
patch: Record<string, unknown>;
|
|
84
|
+
} | {
|
|
85
|
+
kind: 'attribute.remove';
|
|
86
|
+
entity: Handle;
|
|
87
|
+
attribute: Handle;
|
|
88
|
+
} | {
|
|
89
|
+
kind: 'association.add';
|
|
90
|
+
spec: AssocSpec;
|
|
91
|
+
} | {
|
|
92
|
+
kind: 'association.remove';
|
|
93
|
+
association: AssocHandle;
|
|
94
|
+
} | {
|
|
95
|
+
kind: 'association.update';
|
|
96
|
+
association: AssocHandle;
|
|
97
|
+
patch: Record<string, unknown>;
|
|
98
|
+
} | {
|
|
99
|
+
kind: 'associationEnd.update';
|
|
100
|
+
association: AssocHandle;
|
|
101
|
+
end: 'from' | 'to';
|
|
102
|
+
patch: Record<string, unknown>;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* v1이 다루는 심볼릭 op 종류의 닫힌 집합(단일 출처). resolver·JSON Schema(`schema.ts`)가 공유한다.
|
|
106
|
+
* 아래 컴파일타임 단언이 이 튜플과 `SymbolicOp['kind']`의 일치를 강제 — 한쪽만 늘리면 타입 에러.
|
|
107
|
+
*/
|
|
108
|
+
export declare const SYMBOLIC_OP_KINDS: readonly ["entity.add", "entity.update", "entity.remove", "attribute.add", "attribute.update", "attribute.remove", "association.add", "association.remove", "association.update", "associationEnd.update"];
|
|
109
|
+
export type SymbolicOpKind = (typeof SYMBOLIC_OP_KINDS)[number];
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { Association, AssociationEnd, AssociationLayout, Attribute, Entity, EntityIndex, Geo, LogicalGroup, ModelId, Note, Operation, Point } from '../core/types';
|
|
2
|
+
import { Command } from './types';
|
|
3
|
+
export declare function addEntity(entity: Entity, geo: Geo): Command;
|
|
4
|
+
/** 엔티티 삭제 — 참조 관계·레이아웃·그룹 멤버십까지 cascade. memento로 위치 보존 복원. */
|
|
5
|
+
export declare function removeEntity(entityId: ModelId): Command;
|
|
6
|
+
/** 엔티티 필드 부분 수정 (name·stereotype·package·table·jpaAttrs·description 등). 얕은 patch. */
|
|
7
|
+
export declare function updateEntity(entityId: ModelId, patch: Partial<Entity>): Command;
|
|
8
|
+
export declare function renameEntity(entityId: ModelId, newName: string): Command;
|
|
9
|
+
/** 엔티티 위치 이동 — 레이아웃만 변경 */
|
|
10
|
+
export declare function moveEntity(entityId: ModelId, location: Point): Command;
|
|
11
|
+
/**
|
|
12
|
+
* 엔티티 크기 변경 — 레이아웃만 변경 (그룹/노트 동형).
|
|
13
|
+
* 저장값은 수동 지정 크기 그대로. 콘텐츠 실측 최소 이하로의 클램프는 렌더(CSS min-content)가
|
|
14
|
+
* 담당하므로(레거시 evaluateWidth/Height = max(geo, contentMin) 동형) 여기선 raw size를 보관한다.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resizeEntity(entityId: ModelId, size: {
|
|
17
|
+
width: number;
|
|
18
|
+
height: number;
|
|
19
|
+
}): Command;
|
|
20
|
+
/** 엔티티 헤더 바 색상 변경 (레이아웃만 변경) */
|
|
21
|
+
export declare function setEntitySwatch(entityId: ModelId, token: string | null): Command;
|
|
22
|
+
/** 엔티티 접기/펼치기 (레이아웃만 변경 — 속성/메서드 칸 렌더 게이트) */
|
|
23
|
+
export declare function setEntityCollapsed(entityId: ModelId, collapsed: boolean): Command;
|
|
24
|
+
/**
|
|
25
|
+
* 활성 다이어그램 전체 엔티티 접기/펼치기 (D2) — 사전 per-entity collapsed를 캡처한 단일 커맨드.
|
|
26
|
+
* N개 개별 커맨드가 아니라 한 번의 undo로 각 엔티티의 직전 상태를 그대로 복원한다(혼재 상태 보존).
|
|
27
|
+
*/
|
|
28
|
+
export declare function setAllEntitiesCollapsed(collapsed: boolean): Command;
|
|
29
|
+
/** 속성 강조 색상 변경 (레이아웃 attributeStyles[attrId]) */
|
|
30
|
+
export declare function setAttributeSwatch(entityId: ModelId, attributeId: ModelId, token: string | null): Command;
|
|
31
|
+
export declare function addGroup(group: LogicalGroup, geo: Geo): Command;
|
|
32
|
+
/** 그룹 필드 부분 수정 (name·description·packageName·excludeDDLGeneration). 얕은 patch. */
|
|
33
|
+
export declare function updateGroup(groupId: ModelId, patch: Partial<LogicalGroup>): Command;
|
|
34
|
+
/** 그룹 해제(삭제) — 멤버 엔티티는 남고 그룹/박스만 제거 */
|
|
35
|
+
export declare function removeGroup(groupId: ModelId): Command;
|
|
36
|
+
export declare function addEntityToGroup(groupId: ModelId, entityId: ModelId): Command;
|
|
37
|
+
export declare function removeEntityFromGroup(groupId: ModelId, entityId: ModelId): Command;
|
|
38
|
+
export declare function moveGroup(groupId: ModelId, location: Point): Command;
|
|
39
|
+
export declare function resizeGroup(groupId: ModelId, size: {
|
|
40
|
+
width: number;
|
|
41
|
+
height: number;
|
|
42
|
+
}): Command;
|
|
43
|
+
export declare function addAttribute(entityId: ModelId, attribute: Attribute): Command;
|
|
44
|
+
/** 속성 필드 부분 수정 (name·type·dataType·dbAttrs·identifier·notNull 등). 얕은 patch. */
|
|
45
|
+
export declare function updateAttribute(entityId: ModelId, attributeId: ModelId, patch: Partial<Attribute>): Command;
|
|
46
|
+
export declare function removeAttribute(entityId: ModelId, attributeId: ModelId): Command;
|
|
47
|
+
/**
|
|
48
|
+
* 속성 재정렬 — 대상(attrIds)을 현재 표시 순서를 유지한 채 toIndex로 이동.
|
|
49
|
+
* 표시 순서 = attributes 배열 순서가 SoT이므로 배열을 splice 이동하고, 저장·range선택이
|
|
50
|
+
* 의존하는 order 필드를 0..n-1로 전체 재인덱싱한다(중간 삭제로 생긴 기존 갭도 함께 치유).
|
|
51
|
+
* toIndex = 대상을 모두 제거한 뒤의 배열(rest) 기준 삽입 위치.
|
|
52
|
+
* invert는 변경 전 배열 스냅샷(order 포함 얕은 복사)으로 통째 복원 → 재인덱싱 손실 없이 원자 원복.
|
|
53
|
+
*/
|
|
54
|
+
export declare function reorderAttributes(entityId: ModelId, attrIds: ModelId[], toIndex: number): Command;
|
|
55
|
+
export declare function addOperation(entityId: ModelId, operation: Operation): Command;
|
|
56
|
+
/** 메서드 필드 부분 수정 (name·visibility·sourceCode·description 등). 얕은 patch. */
|
|
57
|
+
export declare function updateOperation(entityId: ModelId, operationId: ModelId, patch: Partial<Operation>): Command;
|
|
58
|
+
export declare function removeOperation(entityId: ModelId, operationId: ModelId): Command;
|
|
59
|
+
/**
|
|
60
|
+
* 메서드 재정렬 — reorderAttributes 동형. order 필드를 0..n-1 로 재인덱싱, invert는 스냅샷 통째 복원.
|
|
61
|
+
*/
|
|
62
|
+
export declare function reorderOperations(entityId: ModelId, operationIds: ModelId[], toIndex: number): Command;
|
|
63
|
+
/**
|
|
64
|
+
* 메서드 강조 색상 변경 (레이아웃 operationStyles[operationId]) — setAttributeSwatch 동형.
|
|
65
|
+
* 고아 operationStyles 항목은 operationTo가 현존 operation에 한해서만 emit하므로 round-trip 무해(별도 정리 불요).
|
|
66
|
+
*/
|
|
67
|
+
export declare function setOperationSwatch(entityId: ModelId, operationId: ModelId, token: string | null): Command;
|
|
68
|
+
export declare function addAssociation(association: Association, layout: AssociationLayout): Command;
|
|
69
|
+
export declare function removeAssociation(assocId: ModelId): Command;
|
|
70
|
+
/** 관계(end 제외) 필드 부분 수정 — identifying·description 등. 얕은 patch. */
|
|
71
|
+
export declare function updateAssociation(assocId: ModelId, patch: Partial<Association>): Command;
|
|
72
|
+
/** 관계 한쪽 끝 부분 수정 (multiplicity·navigable·composition·jpa). 얕은 patch. */
|
|
73
|
+
export declare function updateAssociationEnd(assocId: ModelId, which: 'end1' | 'end2', patch: Partial<AssociationEnd>): Command;
|
|
74
|
+
export declare function addIndex(entityId: ModelId, index: EntityIndex): Command;
|
|
75
|
+
export declare function updateIndex(entityId: ModelId, indexId: ModelId, patch: Partial<EntityIndex>): Command;
|
|
76
|
+
export declare function removeIndex(entityId: ModelId, indexId: ModelId): Command;
|
|
77
|
+
export declare function moveWaypoint(assocId: ModelId, index: number, point: Point): Command;
|
|
78
|
+
export declare function removeWaypoint(assocId: ModelId, index: number): Command;
|
|
79
|
+
/** 관계선의 모든 waypoint를 (dx,dy)만큼 평행이동 (그룹 이동 시 내부 관계 꺾은점 동반) */
|
|
80
|
+
export declare function translateWaypoints(assocId: ModelId, dx: number, dy: number): Command;
|
|
81
|
+
/** 관계선의 모든 꺾은점(waypoint) 제거 → 직선화 */
|
|
82
|
+
export declare function clearWaypoints(assocId: ModelId): Command;
|
|
83
|
+
export declare function addWaypoint(assocId: ModelId, index: number, point: Point): Command;
|
|
84
|
+
export declare function addNote(note: Note): Command;
|
|
85
|
+
export declare function removeNote(noteId: ModelId): Command;
|
|
86
|
+
export declare function moveNote(noteId: ModelId, location: Point): Command;
|
|
87
|
+
export declare function resizeNote(noteId: ModelId, size: {
|
|
88
|
+
width: number;
|
|
89
|
+
height: number;
|
|
90
|
+
}): Command;
|
|
91
|
+
export declare function setNoteMemo(noteId: ModelId, memo: string): Command;
|
|
92
|
+
/**
|
|
93
|
+
* 노트를 그룹 박스 멤버로 편입(레이아웃 GroupLayout.memberNoteRefs). 이미 멤버면 no-op.
|
|
94
|
+
* addEntityToGroup과 거울이나 대상이 논리(memberEntityRefs)가 아닌 레이아웃이다 — 노트가 순수
|
|
95
|
+
* 레이아웃 객체라 멤버십도 레이아웃에 둔다. 빈 슬롯을 새로 만들었으면 invert가 undefined로 환원
|
|
96
|
+
* (addNoteConnection의 createdArray 패턴 동형).
|
|
97
|
+
*/
|
|
98
|
+
export declare function addNoteToGroup(groupId: ModelId, noteId: ModelId): Command;
|
|
99
|
+
/** 노트를 그룹 멤버에서 제외(레이아웃). removeEntityFromGroup과 거울. */
|
|
100
|
+
export declare function removeNoteFromGroup(groupId: ModelId, noteId: ModelId): Command;
|
|
101
|
+
/** 노트 → 대상(엔티티 등) 연결 추가. 같은 targetRef가 이미 있으면 no-op. */
|
|
102
|
+
export declare function addNoteConnection(noteId: ModelId, targetRef: ModelId): Command;
|
|
103
|
+
export declare function removeNoteConnection(noteId: ModelId, targetRef: ModelId): Command;
|
|
104
|
+
export declare function moveNoteConnectionWaypoint(noteId: ModelId, targetRef: ModelId, index: number, point: Point): Command;
|
|
105
|
+
export declare function addNoteConnectionWaypoint(noteId: ModelId, targetRef: ModelId, index: number, point: Point): Command;
|
|
106
|
+
export declare function removeNoteConnectionWaypoint(noteId: ModelId, targetRef: ModelId, index: number): Command;
|
|
107
|
+
export declare function clearNoteConnectionWaypoints(noteId: ModelId, targetRef: ModelId): Command;
|
|
108
|
+
export declare function composite(label: string, commands: Command[], coalesceKey?: string): Command;
|