@g1cloud/entity-modeler-next 5.0.0-beta.52 → 5.0.0-beta.53
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/agent/resolver.d.ts +66 -3
- package/dist/agent/symbolicOp.d.ts +44 -4
- package/dist/core/entityPackage.d.ts +24 -0
- package/dist/entity-modeler.js +5446 -5271
- package/dist/entity-modeler.umd.cjs +23 -23
- package/dist/i18n/ko.d.ts +2 -1
- package/package.json +1 -1
package/dist/agent/resolver.d.ts
CHANGED
|
@@ -1,7 +1,47 @@
|
|
|
1
|
-
import { EmbeddableCatalog, LogicalModel, ModelId } from '../core/types';
|
|
1
|
+
import { ClassStereotype, MultiLangText, EmbeddableCatalog, LogicalModel, ModelId } from '../core/types';
|
|
2
2
|
import { OpShape } from '../command/op';
|
|
3
|
-
import { AssocHandle, Handle, SymbolicOp } from './symbolicOp';
|
|
3
|
+
import { AssocHandle, GroupHandle, Handle, SymbolicOp } from './symbolicOp';
|
|
4
4
|
/** 해소 실패 — 어느 심볼릭 op(`opIndex`)의 어떤 핸들이 0개/복수 매칭인지. */
|
|
5
|
+
/**
|
|
6
|
+
* 모호 엔티티 후보 — **판별 맥락을 함께 싣는다**.
|
|
7
|
+
*
|
|
8
|
+
* modelId 만 돌려주면 사람이 고를 근거가 없다(UUID 둘 사이에 우열이 없다). 실제로 stale/live 를 가르는 데
|
|
9
|
+
* 쓰인 축을 그대로 싣는다 — 패키지 소속·테이블·속성 수·참조 수, 그리고 스테레오타입(한 이름 아래
|
|
10
|
+
* `@Entity` 와 `@Embeddable` 이 섞인 형상이 실 데이터에 있다). 거부에 사람이 행동할 맥락을 동봉하는 것은
|
|
11
|
+
* 이 리포의 기존 패턴이다(`attribute-fk-managed` 가 소유 관계의 양 끝 이름을 싣는다).
|
|
12
|
+
*
|
|
13
|
+
* 고른 뒤 지목하는 수단은 `Handle.by:'modelId'`다 — 이 둘이 짝이라야 고리가 닫힌다.
|
|
14
|
+
*/
|
|
15
|
+
export interface EntityCandidate {
|
|
16
|
+
modelId: ModelId;
|
|
17
|
+
stereotype: ClassStereotype;
|
|
18
|
+
/** 실효 패키지(명시 packageName 또는 소속 그룹의 packageName). 없으면 null — 코드젠과 같은 판별 단계. */
|
|
19
|
+
packageName: string | null;
|
|
20
|
+
/** 테이블 물리명 **원문**. 미설정이면 null — 폴백하지 않는다(미설정 자체가 미완성 신호라서). */
|
|
21
|
+
table: string | null;
|
|
22
|
+
attributes: number;
|
|
23
|
+
/** 이 엔티티를 양 끝 중 하나로 갖는 관계 수 — 0이면 고립(버려진 쪽일 가능성). */
|
|
24
|
+
references: number;
|
|
25
|
+
/**
|
|
26
|
+
* 참조하는 상대 엔티티 식별자(이름 → 테이블 → modelId 순 폴백, 중복 제거).
|
|
27
|
+
*
|
|
28
|
+
* ★수치만으로는 갈리지 않는 실 형상이 있다 — 프로덕션 `module-catalog` 의 `Gift` 두 벌은 패키지·테이블·
|
|
29
|
+
* 참조 수가 **전부 같고** 속성 수(6 vs 8)만 다르다. *누가 쓰는가*가 실제 판별 축이라 함께 싣는다
|
|
30
|
+
* (이름이 빈 엔티티가 실재해 테이블·modelId 로 폴백한다 — 없는 이름을 지어내지 않는다).
|
|
31
|
+
*/
|
|
32
|
+
referencedBy: string[];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 모호 그룹 후보 — 엔티티 축과 같은 이유로 판별 맥락을 싣는다(→ `EntityCandidate`).
|
|
36
|
+
* 그룹은 테이블·속성이 없으므로 축이 다르다: 이름(다국어 원문)·패키지·멤버 수.
|
|
37
|
+
*/
|
|
38
|
+
export interface GroupCandidate {
|
|
39
|
+
modelId: ModelId;
|
|
40
|
+
/** 다국어 원문 그대로 — 표시 로케일은 소비처가 정한다(resolver는 로케일을 모른다). */
|
|
41
|
+
name: MultiLangText | null;
|
|
42
|
+
packageName: string | null;
|
|
43
|
+
members: number;
|
|
44
|
+
}
|
|
5
45
|
export type ResolveError = {
|
|
6
46
|
code: 'entity-not-found';
|
|
7
47
|
opIndex: number;
|
|
@@ -10,7 +50,7 @@ export type ResolveError = {
|
|
|
10
50
|
code: 'entity-ambiguous';
|
|
11
51
|
opIndex: number;
|
|
12
52
|
handle: Handle;
|
|
13
|
-
matches:
|
|
53
|
+
matches: EntityCandidate[];
|
|
14
54
|
} | {
|
|
15
55
|
code: 'attribute-not-found';
|
|
16
56
|
opIndex: number;
|
|
@@ -296,6 +336,29 @@ export type ResolveError = {
|
|
|
296
336
|
* 관계를 association.remove로 삭제하도록 유도.
|
|
297
337
|
*/
|
|
298
338
|
| {
|
|
339
|
+
code: 'group-not-found';
|
|
340
|
+
opIndex: number;
|
|
341
|
+
handle: GroupHandle;
|
|
342
|
+
} | {
|
|
343
|
+
code: 'group-ambiguous';
|
|
344
|
+
opIndex: number;
|
|
345
|
+
handle: GroupHandle;
|
|
346
|
+
matches: GroupCandidate[];
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* group.update patch에 `LogicalGroup` 논리 노드에 실재하지 않는 미지 키 — 형제 op의 화이트리스트와 같은 근거
|
|
350
|
+
* (호스트가 patch 를 논리 노드에 통째 `$set` 하므로 통과하면 스키마 밖 orphan 키가 그대로 영속된다).
|
|
351
|
+
*
|
|
352
|
+
* ★`memberEntityRefs` 는 **일부러 화이트리스트 밖**이다. patch 로 통과시키면 배열을 **통째 교체**하게 되어
|
|
353
|
+
* 동시 편집이 서로를 덮는다 — 호스트는 멤버십을 `$push`/`$pull` 원소 단위로 처리하는 전용 verb 를
|
|
354
|
+
* 갖고 있으므로(`group.addMember`/`removeMember`) 그쪽이 정상 경로다.
|
|
355
|
+
*/
|
|
356
|
+
| {
|
|
357
|
+
code: 'group-patch-unknown-key';
|
|
358
|
+
opIndex: number;
|
|
359
|
+
handle: GroupHandle;
|
|
360
|
+
keys: string[];
|
|
361
|
+
} | {
|
|
299
362
|
code: 'attribute-fk-managed';
|
|
300
363
|
opIndex: number;
|
|
301
364
|
entity: Handle;
|
|
@@ -5,10 +5,17 @@ import { ClassStereotype, MultiLangText, Multiplicity, OperationVisibility } fro
|
|
|
5
5
|
* 속성: 소속 엔티티 내 속성명(`name`) 또는 컬럼 물리명(`dbAttrs[].physicalName`) — 둘 다 엔티티 내 유일(CHK-NAME-1/2).
|
|
6
6
|
*/
|
|
7
7
|
export interface Handle {
|
|
8
|
-
/** 매칭할 이름/물리명. */
|
|
8
|
+
/** 매칭할 이름/물리명. `by:'modelId'`면 modelId 원문. */
|
|
9
9
|
ref: string;
|
|
10
|
-
/**
|
|
11
|
-
|
|
10
|
+
/**
|
|
11
|
+
* 매칭 키 고정. 미지정 시 대상별 기본 순서로 시도(엔티티=물리명→논리명, 속성=논리명→물리명).
|
|
12
|
+
*
|
|
13
|
+
* ★`'modelId'`는 **모호 해소 탈출구**다 — 이름·물리명이 둘 다 겹쳐 주소지정이 불가능한 대상이 실재한다
|
|
14
|
+
* (임베더블은 `table`이 없어 물리명 차원 자체가 없고, 같은 테이블에 매핑된 동명 엔티티도 실 데이터에
|
|
15
|
+
* 있다). resolver가 모호를 보고할 때 후보를 판별 맥락과 함께 돌려주므로, 사람이 그중 하나를 골라
|
|
16
|
+
* 이 키로 확정한다. 평시엔 쓰지 않는다(핸들 설계 취지는 "LLM은 사람 용어로만 말한다").
|
|
17
|
+
*/
|
|
18
|
+
by?: 'physicalName' | 'name' | 'modelId';
|
|
12
19
|
}
|
|
13
20
|
/**
|
|
14
21
|
* 관계 지정 — 관계는 무명이라 양 끝 엔티티로 주소한다.
|
|
@@ -143,6 +150,24 @@ export interface AssocSpec {
|
|
|
143
150
|
/** end2 composition(부모가 자식 생명주기 소유). */
|
|
144
151
|
composition?: boolean;
|
|
145
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* 그룹 지정 핸들 — 그룹엔 테이블(물리명) 차원이 없어 `Handle` 과 `by` 축이 다르다.
|
|
155
|
+
*
|
|
156
|
+
* 실측(프로덕션 v2 29문서·그룹 220): **`name` 은 220/220 전량 보유**하고 `packageName` 은 177(80%)만
|
|
157
|
+
* 있다. 그래서 기본은 엔티티와 같은 관용(물리 정체성 우선 → 논리 보조)으로 `packageName` → `name`
|
|
158
|
+
* 순서를 시도하되, packageName 이 없는 43개는 자연히 name 으로 잡힌다.
|
|
159
|
+
*
|
|
160
|
+
* ★`name` 은 `MultiLangText` 라 **어느 로케일 값이든 일치하면 매칭**한다(사람이 부르는 이름이 로케일마다
|
|
161
|
+
* 다를 수 있고, 어느 하나를 정본으로 고르면 나머지 로케일로 부른 요청이 조용히 not-found 가 된다).
|
|
162
|
+
* ★문서 내 중복이 실재한다(실측 packageName 4종·ko 이름 3종) ⇒ 모호는 **후보를 동봉해 보고**하고
|
|
163
|
+
* `by:'modelId'` 로 확정한다(엔티티 축과 같은 형태).
|
|
164
|
+
*/
|
|
165
|
+
export interface GroupHandle {
|
|
166
|
+
/** 매칭할 패키지명/이름. `by:'modelId'`면 modelId 원문. */
|
|
167
|
+
ref: string;
|
|
168
|
+
/** 매칭 키 고정. 미지정 시 packageName → name 순서. */
|
|
169
|
+
by?: 'packageName' | 'name' | 'modelId';
|
|
170
|
+
}
|
|
146
171
|
/**
|
|
147
172
|
* group.add 페이로드 — 엔티티 멤버를 묶는 논리 그룹(레거시 LogicalGroup). resolver가 modelId 발급 +
|
|
148
173
|
* 멤버 핸들을 entity modelId(`memberEntityRefs`)로 해소. 그룹 멤버십은 값 포함이 아닌 **id 참조**(엔티티는
|
|
@@ -283,12 +308,27 @@ export type SymbolicOp = {
|
|
|
283
308
|
} | {
|
|
284
309
|
kind: 'group.add';
|
|
285
310
|
spec: GroupSpec;
|
|
311
|
+
} | {
|
|
312
|
+
kind: 'group.update';
|
|
313
|
+
group: GroupHandle;
|
|
314
|
+
patch: Record<string, unknown>;
|
|
315
|
+
} | {
|
|
316
|
+
kind: 'group.remove';
|
|
317
|
+
group: GroupHandle;
|
|
318
|
+
} | {
|
|
319
|
+
kind: 'group.addMember';
|
|
320
|
+
group: GroupHandle;
|
|
321
|
+
entity: Handle;
|
|
322
|
+
} | {
|
|
323
|
+
kind: 'group.removeMember';
|
|
324
|
+
group: GroupHandle;
|
|
325
|
+
entity: Handle;
|
|
286
326
|
};
|
|
287
327
|
/**
|
|
288
328
|
* v1이 다루는 심볼릭 op 종류의 닫힌 집합(단일 출처). resolver·JSON Schema(`schema.ts`)가 공유한다.
|
|
289
329
|
* 아래 컴파일타임 단언이 이 튜플과 `SymbolicOp['kind']`의 일치를 강제 — 한쪽만 늘리면 타입 에러.
|
|
290
330
|
*/
|
|
291
|
-
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", "index.add", "index.update", "index.remove", "operation.add", "operation.update", "operation.remove", "attribute.reorder", "operation.reorder", "group.add"];
|
|
331
|
+
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", "index.add", "index.update", "index.remove", "operation.add", "operation.update", "operation.remove", "attribute.reorder", "operation.reorder", "group.add", "group.update", "group.remove", "group.addMember", "group.removeMember"];
|
|
292
332
|
export type SymbolicOpKind = (typeof SYMBOLIC_OP_KINDS)[number];
|
|
293
333
|
/**
|
|
294
334
|
* `AttributeType`(core) 런타임 목록 — JSON Schema enum과 resolver 값 검증이 공유한다.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Entity, LogicalModel } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* 패키지 동일성 키. `kind` 를 함께 들고 다니는 이유는 **비교 가능성**이다 — 명시 패키지는 FQN 전체이고
|
|
4
|
+
* 그룹 세그먼트는 조각이라, 서로 다른 종류끼리는 같은지 다른지 판정할 수 없다(조각만으로는 base·layer 를
|
|
5
|
+
* 모른다). 그 경우를 조용히 "다르다"로 처리하면 실제 충돌을 놓치므로 호출부가 구분할 수 있게 남긴다.
|
|
6
|
+
*/
|
|
7
|
+
export type EntityPackageKey = {
|
|
8
|
+
kind: 'explicit';
|
|
9
|
+
value: string;
|
|
10
|
+
}
|
|
11
|
+
/** 그룹 세그먼트. `''` = 세그먼트 생략(그룹 미소속 또는 그룹에 packageName 없음). */
|
|
12
|
+
| {
|
|
13
|
+
kind: 'group';
|
|
14
|
+
value: string;
|
|
15
|
+
};
|
|
16
|
+
export declare function entityPackageKey(entity: Entity, logical: LogicalModel): EntityPackageKey;
|
|
17
|
+
/**
|
|
18
|
+
* 두 엔티티가 **서로 다른 패키지에 놓인다는 것이 증명되는가**.
|
|
19
|
+
*
|
|
20
|
+
* 이름은 일부러 `samePackage` 의 부정이 아니라 *증명 가능성*으로 잡았다 — 판정 불가(키 종류가 다름)를
|
|
21
|
+
* "다르다"로 흘리면 면제가 조용히 넓어져 **실제 충돌이 무신호**가 된다. 면제는 적극적으로 증명될 때만
|
|
22
|
+
* 준다(그 외에는 종전대로 신고 = 현행 동작 보존).
|
|
23
|
+
*/
|
|
24
|
+
export declare function provablyDifferentPackage(a: Entity, b: Entity, logical: LogicalModel): boolean;
|