import { Association, DiagramLayout, Entity, LogicalGroup, ModelId, MultiLangText, Point } from '../core/types'; export interface PGeo { location: { x: number; y: number; }; size: { width: number; height: number; }; } export interface PStyle { properties: Record; } export interface PDbAttr { modelId: string; physicalName: string; logicalName?: MultiLangText; dataType: string; length?: number; scale?: number; unique?: boolean; autoIncrement?: boolean; updatable?: boolean; /** JPA @Column(insertable=…). undefined=기본 따름. v1 레거시엔 없는 신규 옵션. */ insertable?: boolean; /** * JPA @Column(nullable=false) — **이 컬럼 하나의** NOT NULL. undefined=속성 축(`notNull`)을 따름. * 논리 모델 `DbColumn.notNull` 직렬화(그 주석이 축의 정본). v1 레거시엔 없는 신규 옵션. */ notNull?: boolean; /** * 공유 통화 컬럼(SHARED_REF) — 같은 엔터티 내 다른 컬럼 modelId 참조(read-only 투영, 물리 컬럼 0). * 논리 모델 DbColumn.sharedColumnRef 직렬화. FK 전파용 targetModelId와는 별개 개념. v1 레거시 없음. */ sharedColumnRef?: string; /** 레거시 AttributeDatabaseAttribute.multiValue. 라운드트립 보존 전용. */ multiValue?: boolean; /** 레거시 AttributeDatabaseAttribute.multiValueSeparator(기본 "|"). 라운드트립 보존 전용. */ multiValueSeparator?: string; /** 레거시 AttributeDatabaseAttribute.sequenceName → 논리 `DbColumn.sequenceName`(오버라이드·애플리케이션 채번 두 용법 · 그쪽 주석). */ sequenceName?: string; /** FK 컬럼이 참조하는 부모 PK 컬럼 modelId. 식별자 전파(derivedFrom) 재구성의 명시 링크. */ targetModelId?: string; } export interface PAttribute { modelId: string; name: string; type: string; customType?: string; attrType: string; identifier: boolean; notNull: boolean; transient_?: boolean; /** Hibernate @NaturalId(자연키/비즈니스 키). 속성 레벨. v1 레거시엔 없는 신규 옵션. */ naturalId?: boolean; /** @NaturalId(mutable=true). undefined/false=불변(Hibernate 기본). */ naturalIdMutable?: boolean; description?: MultiLangText; attributeGroup?: string; groupCode?: string; /** 레거시 AttributeModel.defaultValue. 코드성 속성은 groupCode의 code 문자열, 그 외 자유 입력. */ defaultValue?: string; /** 레거시 AttributeModel.personalInfoAttributeType(enum 이름). 라운드트립 보존 전용. */ personalInfoAttributeType?: string; order?: number; dbAttrs: PDbAttr[]; style?: PStyle; } /** * association end에 인라인 저장되는 속성. 레거시 실데이터는 전체 PAttribute를 인라인으로 기록하나 * (FK 본체·nav 참조), next-native가 기록한 문서는 `{modelId}` 참조만 가질 수 있어 둘 다 수용한다. */ export type PInlineAttribute = { modelId: string; } & Partial>; export interface PAssocEnd { endModel: { refId: string; }; multiplicity: string; navigable: boolean; composition: boolean; jpaAttribute?: { fetchType?: string; cascadeTypes?: string[]; orphanRemoval?: boolean; orderBy?: string; collectionType?: string; collectionTable?: string; orderColumn?: string; }; attribute?: PInlineAttribute; } export interface PAssociation { modelId: string; description?: string; locations?: Point[]; end1: PAssocEnd; end2: PAssocEnd; style?: PStyle; } /** * 레거시 OperationModel 직렬화 형태. ⚠️ description은 평문 string(PEntity/PAttribute의 MultiLangText와 비대칭). * parent(back-ref)·properties 등 미매핑 키는 index signature로 수용 → 어댑터가 legacyRaw로 verbatim 보존. */ export interface POperation { modelId: string; name: string; visibility?: string; sourceCode?: string; description?: string; order?: number; personalInfoAttributeType?: string; style?: PStyle; [key: string]: unknown; } export interface PEntity { modelId: string; name: string; stereotype: string; packageName?: string; superClass?: string; schema?: string; description?: MultiLangText; abstractClass?: boolean; hasPersonalInfo?: boolean; declarationOfInterfaces?: string[]; attributes: PAttribute[]; operations?: POperation[]; ownedAssociations?: PAssociation[]; indexes?: PIndex[]; jpaAttrs?: PJpaAttrs; dbAttrs?: { physicalName: string; logicalName?: MultiLangText; }; geo?: PGeo; style?: PStyle; collapsed?: boolean; locked?: boolean; } export interface PIndex { modelId: string; name: string; unique: boolean; description?: string; parameters?: string; indexColumns: { targetColumn: { refId: string; }; descending: boolean; }[]; } export interface PJpaAttrs { useVersion?: boolean; useCacheable?: boolean; useDynamicInsert?: boolean; useDynamicUpdate?: boolean; useDiscriminator?: boolean; /** 레거시 EntityJPAAttribute discriminator 상세. 어댑터가 jpaAttrs 객체 통째 패스스루라 자동 round-trip. */ discriminatorColumnName?: string; discriminatorType?: string; discriminatorLength?: number; } export interface PGroup { modelId: string; name?: MultiLangText; description?: string; packageName?: string; excludeDDLGeneration?: boolean; entities?: PEntity[]; /** 레거시는 노트를 엔티티처럼 그룹 멤버로 중첩 저장(그룹 상대좌표). 그룹 밖 자유 노트는 PDiagram.notes. */ notes?: PNote[]; geo?: PGeo; style?: PStyle; locked?: boolean; } /** * 레거시 NoteModel 직렬화 형태. 연결선은 `ownedConnections`(end1/end2/locations 구조)로 저장되고 * next-native가 쓰는 `connections`(targetRef/waypoints)와 비대칭 — 둘 다 수용한다. `parent`(back-ref)· * `properties` 등 미매핑 키는 index signature로 받아 어댑터가 legacyRaw로 verbatim 보존. */ export interface PNote { modelId: string; memo: string; geo: PGeo; style?: PStyle; connections?: { targetRef: string; waypoints: Point[]; }[]; [key: string]: unknown; } export interface PDiagram { /** Mongo _id (문자열화) */ id?: string; /** * 데이터 형태 세대(트랙 B 마커). 부재/1 = 레거시 flat(이 PDiagram 형태), 2 = logical/layout(PDiagramV2). * `fromPersisted` 분기 신호. 레거시 doc은 이 필드가 없다. */ schemaVersion?: number; /** op 쓰기 롤아웃 게이트(불변식: true ⟹ schemaVersion>=2). v1 doc엔 무의미. */ opWriteEnabled?: boolean; diagramVersion?: string; version?: number; size?: { width: number; height: number; }; packageName?: string; entities?: PEntity[]; groups?: PGroup[]; notes?: PNote[]; } /** v2 logical 컨테이너 — core 모델 + 컨테이너 rev(영속 전용 CAS 메타, 파서가 RevCache로 분리). */ export type PV2Entity = Entity & { rev?: number; }; export type PV2Association = Association & { rev?: number; }; export type PV2Group = LogicalGroup & { rev?: number; }; export interface PV2Logical { /** logicalVersion — 거친 stale 마커(reconcile 힌트, CAS 게이트 아님). M2 §4.2. */ version?: number; modelId: ModelId; packageName?: string; entities: PV2Entity[]; associations: PV2Association[]; groups: PV2Group[]; } export interface PV2Layout extends DiagramLayout { /** layout.version — layout op LWW CAS 게이트. M2 §4.2. */ version?: number; } export interface PDiagramV2 { /** Mongo _id (문자열화) */ id?: string; schemaVersion: 2; /** op 쓰기 롤아웃 게이트. false = read-only 프리즈(B-0-1, 쓰기 kill-switch). */ opWriteEnabled?: boolean; /** * 문서 단위 「참고 전용」 — 이 문서 전체가 산출·검증 대상이 아니다(이해용 스크래치 자료·테스트 문서). * * ★엔티티 단위는 `Entity.referenceOnly`(논리 모델)이고 이쪽은 **doc 루트 마커**다. 자리가 갈리는 이유: * op 어휘에 모델·문서 레벨 op 이 **하나도 없다**(`opSubject.ts` 인벤토리 실측) ⇒ 논리 모델에 두면 op * 신설 + 호스트 인터프리터 선행 배포가 딸려 온다. 반면 문서 레벨 정책 마커는 이미 이 자리에 산다 * (`schemaVersion`·`opWriteEnabled`) ⇒ 호스트 라우트가 토글하고 lib 은 `DiagramMeta` 로 읽는다. * * ⚠️대가 둘(선례 `opWriteEnabled` 와 동일): 변경이 op 이력에 남지 않고, JSON 백업 왕복에 실리지 않는다. */ referenceOnly?: boolean; /** doc-level optlock(기존 version 계승). */ version?: number; diagramVersion?: string; packageName?: string; size?: { width: number; height: number; }; logical: PV2Logical; layout: PV2Layout; }