import { EmbeddableCatalog, LogicalModel, ModelId, PredefinedCustomTypeCatalog, SuperClassCatalog } from './types'; export declare const PHYSICAL_NAME_MAX_LENGTH = 63; /** * 물리명이 이식성 권장 한도를 초과하면 **초과 길이(문자 수)**, 아니면 null(비차단 — 호출부는 저장을 * 막지 않는다). 빈값/미설정은 경고 없음(레거시 isNotEmpty 게이트 동형). * * 이전엔 완성된 경고 문자열을 반환했으나, i18n(P3)로 core가 표시 문자열을 만들지 않게 되어 길이만 * 돌려준다 — 컬럼·테이블·인덱스 3곳이 이 값을 `CHK-NAME-5` params `{max,len}`로 재사용(단일 출처). */ export declare function physicalNameLengthOverflow(name: string | null | undefined): number | null; export type IssueSeverity = 'error' | 'warning' | 'info'; export type IssueTargetKind = 'entity' | 'attribute' | 'column' | 'association' | 'index' | 'group' | 'model'; export interface ValidationIssue { /** * 규칙 식별자(예: 'CHK-NAME-1'). 엔진 불변식 INV-*와 다른 네임스페이스(위반 가능·수정 대상). * **메시지 code**를 겸한다 — 뷰가 `ruleId`(+targetKind/params 변형)로 i18n 키를 해석해 로컬라이즈 * (`view/validationDisplay.issueMessageKey`). core는 문자열을 만들지 않는다(D3, 논리↔표시 분리). */ ruleId: string; severity: IssueSeverity; targetKind: IssueTargetKind; /** 문제 요소의 modelId(model 레벨이면 생략). 뷰가 클릭→포커스에 사용. */ targetRef?: ModelId; /** 보조 ref(예: 컬럼/속성 이슈의 소속 엔티티) — 뷰 그룹핑/내비용. */ contextRef?: ModelId; /** * 메시지 보간 파라미터 — 뷰가 `c.t(key, params)`로 치환. 값은 식별자/카운트/JPA 리터럴 등 * **번역 대상이 아닌 데이터**(name·dataType·which='end1'/'end2'·cascade='ALL'/'REMOVE' 등). * 정적 메시지 규칙은 생략. i18n 카탈로그(`em.i18n`)에 의존하지 않도록 구조만 노출(순수성 유지). */ params?: Record; } /** 카탈로그 의존 규칙을 켜는 선택 주입 — 미주입 시 해당 규칙 skip(범위 밖 아님, 컨텍스트 부재). */ export interface ValidationContext { /** SQL 예약어 집합(대문자). 호스트 주입. 미주입 시 CHK-NAME-6 skip. */ reservedWords?: ReadonlySet; /** * 타겟 DB가 허용하는 dataType 집합(다이얼렉트별). 호스트 주입. 미주입 시 CHK-TYPE-1 skip. * reservedWords와 동형으로 ctx 게이트 — 코어 SELECTABLE_DATA_TYPES를 기본값으로 박지 않는 이유: * 레거시 보존 타입(NCHAR 등 import verbatim)을 호스트가 다이얼렉트 셋을 줄 때까지 일괄 경고하지 않기 위함. * 자연 주입값 = `new Set(SELECTABLE_DATA_TYPES)`(PG 타겟) — 호스트 통합 시 다이얼렉트로 대체. */ selectableDataTypes?: ReadonlySet; /** 비대 엔티티(god-object) 판정 임계치 — 논리 속성 수가 이 값 초과면 CHK-DSN-4. 미주입 시 skip. */ largeEntityThreshold?: number; /** * CHK-DSN-3(모델링된 관계 없는 엔티티) 켜기 — **기본 off**(미주입/false 시 skip). * 옵트인인 이유: 비형식 FK(연관 엣지 없이 raw id 컬럼만 둔 경우)는 코어가 탐지 불가라 잔존 오탐이 * 원리적으로 제거되지 않는다. "참여"는 연관·상속(superClass)·임베딩(embedded)까지 넓혀 오탐을 최소화하되, * 의도적 연관 생략 모델에선 노이즈이므로 호스트/사용자가 명시적으로 켤 때만 평가한다. */ flagEntitiesWithoutRelations?: boolean; /** * Predefined 임베더블 카탈로그 — CHK-TYPE-3(공유 통화 컬럼 SHARED_REF 타깃 타입 불일치)의 기대 * 타입 출처. 호스트/dev 주입(reservedWords와 동형 ctx 게이트). 미주입/빈 배열이면 CHK-TYPE-3 skip. */ embeddableCatalog?: EmbeddableCatalog; /** * 슈퍼클래스 카탈로그 — CHK-DSN-5(dangling 인덱스 대상)가 인덱스 columnRef의 상속 컬럼(`inherited:` * 합성 ref)을 유효한 대상으로 인지하는 화이트리스트 출처. 호스트/dev 주입(embeddableCatalog 동형 ctx * 게이트). 미주입/빈 배열이면 상속 컬럼을 인지하지 못하므로, superClass 상속 컬럼을 참조하는 인덱스가 * dangling으로 오탐될 수 있다 — 카탈로그가 주입돼야 정확 판정(로컬 컬럼만 참조하는 모델은 무영향). */ superClassCatalog?: SuperClassCatalog; /** * ③ predefined customtype 카탈로그(`MultiLangString`·`StoredFile` 등 호스트 주입 단일 컬럼 커스텀 타입) * — `CHK-TYPE-7` 이 그 타입들의 `dataType` 규약을 판정하는 출처. 미주입이면 종전대로 **판정 불가로 skip** * (reservedWords·embeddableCatalog 와 동형 ctx 게이트 = **inert-by-default**). * * ★**왜 lib 이 표를 안 갖는가**: 이 타입들은 프레임워크 공통분 + 프로젝트별 추가분이라 규약의 소유자가 * 호스트다(`types.ts` `PredefinedCustomTypeEntry` 주석과 같은 근거). 실측이 그 판단을 뒷받침한다 — * `CustomType`(④ 자유 축)은 지배 형상이 아예 없어(JSONB 27·CLOB 17·VARCHAR 8종) 어떤 정적 표도 틀린다. * ⚠️주입은 **`ScaffoldOptions.customTypeCatalog`(④ 컨버터 FQN 맵)와 다른 축**이다 — 이름이 비슷해 * 헷갈리기 쉽다(2026-09-04 착수 실측: 호스트가 주입 중인 것은 ④ 쪽이고 ③ 은 주입 0이었다). */ predefinedCustomTypes?: PredefinedCustomTypeCatalog; } /** * 설계 품질 검증 — 논리 모델(+선택 컨텍스트)을 받아 이슈 목록을 돌려준다. * 순수 함수. 호출부가 심각도/차단정책/표시시점을 해석한다(예: 빈 이름 info는 저장 시점에만 표시). * * 범위: 명명·중복(CHK-NAME, P1) + JPA 정합성·물리타입·식별 사이클(CHK-JPA·CHK-TYPE, P2) + 설계 안티패턴(CHK-DSN, P3). */ export declare function validateModel(model: LogicalModel, ctx?: ValidationContext): ValidationIssue[];