@rdbms-erd/core 0.1.28 → 0.1.29

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/README.md CHANGED
@@ -35,6 +35,30 @@ doc.model.tables.push({
35
35
  console.log(generateDdl(doc));
36
36
  ```
37
37
 
38
+ ## Table and column IDs (required)
39
+
40
+ Every `TableModel.id` and `ColumnModel.id` must be **unique across the whole document**.
41
+ React Flow nodes use `table.id` as the node id; duplicate ids (for example two `table-1` rows from a DB import) collapse to one canvas node and break layout keys in `layout.nodePositions`.
42
+
43
+ When building a design from a database in your host app, do **not** reuse `table-1` per table. Use a fresh id per entity:
44
+
45
+ ```ts
46
+ import { createId } from "@rdbms-erd/core";
47
+
48
+ const table = {
49
+ id: createId("table"), // e.g. table-550e8400-e29b-41d4-a716-446655440000
50
+ physicalName: row.tableName,
51
+ logicalName: row.comment ?? "",
52
+ columns: row.columns.map((c) => ({
53
+ id: createId("col"),
54
+ physicalName: c.name,
55
+ // ...
56
+ })),
57
+ };
58
+ ```
59
+
60
+ `parseDesign` and `ensureUniqueDesignIds(doc)` reissue duplicate ids when loading legacy or host-generated JSON.
61
+
38
62
  ## Core Concepts
39
63
 
40
64
  - `DesignDocument`: ER JSON source of truth
package/dist/index.d.ts CHANGED
@@ -11,6 +11,14 @@ declare function alignNodePositions(selectedIds: string[], positions: Record<str
11
11
  y: number;
12
12
  }>;
13
13
 
14
+ /** 문서 전역에서 쓰는 안정적인 id (`table-{uuid}` 등). */
15
+ declare function createId(prefix: string): string;
16
+ /**
17
+ * 테이블·컬럼 id가 문서 전역에서 유일하도록 재발급한다.
18
+ * Host import 등으로 `table-1`이 중복된 경우 React Flow 노드 충돌을 방지한다.
19
+ */
20
+ declare function ensureUniqueDesignIds(doc: DesignDocument): DesignDocument;
21
+
14
22
  type BuiltinRdbmsDialect = "mssql" | "oracle" | "mysql" | "postgres" | "sqlite";
15
23
  type RdbmsDialect = BuiltinRdbmsDialect | (string & {});
16
24
 
@@ -249,4 +257,4 @@ declare function generateIndexDdl(doc: DesignDocument, options?: CoreDbMetaOptio
249
257
  /** 성능·부하 테스트용: 지정 개수의 빈 테이블과 격자 레이아웃을 생성한다. */
250
258
  declare function createLargeDesign(tableCount: number, dialect?: RdbmsDialect): DesignDocument;
251
259
 
252
- export { type AlignCommand, BUILTIN_DIALECTS, BUILTIN_DIALECT_METAS_JSON, type BuiltinRdbmsDialect, type ColumnModel, type CoreDbMetaOptions, type DbMetaAdapter, type DdlDiagnostic, type DdlDiagnosticSeverity, type DdlGenerateInput, type DdlGenerateOutput, type DdlGeneratorHook, type DdlGeneratorRules, type DdlScope, type DdlStyle, type DdlStyleBooleanLiteral, type DdlStyleQuote, type DesignDocument, type DesignModel, type DiagramLayout, type DialectCapability, type DialectMeta, type DialectMetaJson, type IndexModel, LOGICAL_DATA_TYPES, type LogicalDataType, type LogicalTypeMeta, PACKAGE_DEFAULT_PHYSICAL_TYPE_TEXT, type RdbmsDialect, type RelationshipModel, type TableModel, alignNodePositions, analyzeDdlDocument, applyLogicalTypeChange, convertDesignDialect, convertPhysicalTypeByLogicalType, createColumn, createDefaultDbMetaAdapter, createEmptyDesign, createLargeDesign, defaultDbMetaAdapter, defaultPhysicalType, dialectSupportsSchema, formatDdlDiagnostic, formatDdlDiagnostics, generateDdl, generateDdlForSelection, generateDdlWithDiagnostics, generateIndexDdl, generateIndexDdlWithDiagnostics, getRdbmsDialectCapability, inferLogicalTypeFromPhysical, isRelationshipLineRenderable, mergeDialectMetas, migrateLegacyFkLineVisibility, parseDesign, resolveDialectMetas, roundTripDesign, serializeDesign, validateDesignDocument };
260
+ export { type AlignCommand, BUILTIN_DIALECTS, BUILTIN_DIALECT_METAS_JSON, type BuiltinRdbmsDialect, type ColumnModel, type CoreDbMetaOptions, type DbMetaAdapter, type DdlDiagnostic, type DdlDiagnosticSeverity, type DdlGenerateInput, type DdlGenerateOutput, type DdlGeneratorHook, type DdlGeneratorRules, type DdlScope, type DdlStyle, type DdlStyleBooleanLiteral, type DdlStyleQuote, type DesignDocument, type DesignModel, type DiagramLayout, type DialectCapability, type DialectMeta, type DialectMetaJson, type IndexModel, LOGICAL_DATA_TYPES, type LogicalDataType, type LogicalTypeMeta, PACKAGE_DEFAULT_PHYSICAL_TYPE_TEXT, type RdbmsDialect, type RelationshipModel, type TableModel, alignNodePositions, analyzeDdlDocument, applyLogicalTypeChange, convertDesignDialect, convertPhysicalTypeByLogicalType, createColumn, createDefaultDbMetaAdapter, createEmptyDesign, createId, createLargeDesign, defaultDbMetaAdapter, defaultPhysicalType, dialectSupportsSchema, ensureUniqueDesignIds, formatDdlDiagnostic, formatDdlDiagnostics, generateDdl, generateDdlForSelection, generateDdlWithDiagnostics, generateIndexDdl, generateIndexDdlWithDiagnostics, getRdbmsDialectCapability, inferLogicalTypeFromPhysical, isRelationshipLineRenderable, mergeDialectMetas, migrateLegacyFkLineVisibility, parseDesign, resolveDialectMetas, roundTripDesign, serializeDesign, validateDesignDocument };
package/dist/index.js CHANGED
@@ -46,6 +46,108 @@ function alignNodePositions(selectedIds, positions, command, anchorId) {
46
46
  return out;
47
47
  }
48
48
 
49
+ // src/ensureUniqueDesignIds.ts
50
+ function fallbackId() {
51
+ return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
52
+ }
53
+ function createId(prefix) {
54
+ const suffix = typeof globalThis.crypto?.randomUUID === "function" ? globalThis.crypto.randomUUID() : fallbackId();
55
+ return `${prefix}-${suffix}`;
56
+ }
57
+ function remapColumnRefs(columnIdMap, columnId) {
58
+ if (!columnId) return columnId;
59
+ return columnIdMap.get(columnId) ?? columnId;
60
+ }
61
+ function normalizeTableColumns(table, usedColumnIds, columnIdMap) {
62
+ const columns = table.columns.map((col) => {
63
+ const oldId = col.id?.trim() || createId("col");
64
+ let id = oldId;
65
+ if (usedColumnIds.has(id)) {
66
+ id = createId("col");
67
+ columnIdMap.set(oldId, id);
68
+ }
69
+ usedColumnIds.add(id);
70
+ return { ...col, id };
71
+ });
72
+ return {
73
+ ...table,
74
+ columns: columns.map((col) => ({
75
+ ...col,
76
+ referencesPrimaryColumnId: remapColumnRefs(
77
+ columnIdMap,
78
+ col.referencesPrimaryColumnId
79
+ )
80
+ }))
81
+ };
82
+ }
83
+ function remapRelationships(relationships, tableIdMap, columnIdMap) {
84
+ return relationships.map((rel) => ({
85
+ ...rel,
86
+ sourceTableId: tableIdMap.get(rel.sourceTableId) ?? rel.sourceTableId,
87
+ targetTableId: tableIdMap.get(rel.targetTableId) ?? rel.targetTableId,
88
+ sourceColumnId: remapColumnRefs(columnIdMap, rel.sourceColumnId),
89
+ targetColumnId: remapColumnRefs(columnIdMap, rel.targetColumnId),
90
+ originPkColumnId: remapColumnRefs(columnIdMap, rel.originPkColumnId)
91
+ }));
92
+ }
93
+ function remapIndexes(indexes, tableIdMap) {
94
+ return indexes.map((idx) => ({
95
+ ...idx,
96
+ tableId: tableIdMap.get(idx.tableId) ?? idx.tableId
97
+ }));
98
+ }
99
+ function ensureUniqueDesignIds(doc) {
100
+ const usedColumnIds = /* @__PURE__ */ new Set();
101
+ const columnIdMap = /* @__PURE__ */ new Map();
102
+ const usedTableIds = /* @__PURE__ */ new Set();
103
+ const tableIdMap = /* @__PURE__ */ new Map();
104
+ const oldTableIds = [];
105
+ const nextTables = [];
106
+ for (const table of doc.model.tables) {
107
+ const oldId = table.id?.trim() || createId("table");
108
+ oldTableIds.push(oldId);
109
+ let id = oldId;
110
+ if (usedTableIds.has(id)) {
111
+ id = createId("table");
112
+ }
113
+ usedTableIds.add(id);
114
+ const duplicateOldCount = oldTableIds.filter((x) => x === oldId).length;
115
+ if (oldId !== id && duplicateOldCount === 1) {
116
+ tableIdMap.set(oldId, id);
117
+ }
118
+ nextTables.push(
119
+ normalizeTableColumns({ ...table, id }, usedColumnIds, columnIdMap)
120
+ );
121
+ }
122
+ const nodePositions = {};
123
+ for (let i = 0; i < nextTables.length; i++) {
124
+ const table = nextTables[i];
125
+ const oldId = oldTableIds[i];
126
+ nodePositions[table.id] = doc.layout.nodePositions[table.id] ?? doc.layout.nodePositions[oldId] ?? {
127
+ x: 60 + i % 5 * 48,
128
+ y: 60 + Math.floor(i / 5) * 48
129
+ };
130
+ }
131
+ const model = {
132
+ ...doc.model,
133
+ tables: nextTables,
134
+ relationships: remapRelationships(
135
+ doc.model.relationships,
136
+ tableIdMap,
137
+ columnIdMap
138
+ ),
139
+ indexes: remapIndexes(doc.model.indexes, tableIdMap)
140
+ };
141
+ return {
142
+ ...doc,
143
+ model,
144
+ layout: {
145
+ ...doc.layout,
146
+ nodePositions
147
+ }
148
+ };
149
+ }
150
+
49
151
  // src/index.ts
50
152
  var LOGICAL_DATA_TYPES = [
51
153
  "TEXT",
@@ -603,7 +705,7 @@ function validateDesignDocument(input, options) {
603
705
  const doc = input;
604
706
  migrateLegacyFkLineVisibility(doc.model);
605
707
  normalizeColumnDefaultValues(doc.model);
606
- return doc;
708
+ return ensureUniqueDesignIds(doc);
607
709
  }
608
710
  function roundTripDesign(doc) {
609
711
  return parseDesign(serializeDesign(doc));
@@ -912,6 +1014,6 @@ function createLargeDesign(tableCount, dialect = "postgres") {
912
1014
  return doc;
913
1015
  }
914
1016
 
915
- export { BUILTIN_DIALECTS, BUILTIN_DIALECT_METAS_JSON, LOGICAL_DATA_TYPES, PACKAGE_DEFAULT_PHYSICAL_TYPE_TEXT, alignNodePositions, analyzeDdlDocument, applyLogicalTypeChange, convertDesignDialect, convertPhysicalTypeByLogicalType, createColumn, createDefaultDbMetaAdapter, createEmptyDesign, createLargeDesign, defaultDbMetaAdapter, defaultPhysicalType, dialectSupportsSchema, formatDdlDiagnostic, formatDdlDiagnostics, generateDdl, generateDdlForSelection, generateDdlWithDiagnostics, generateIndexDdl, generateIndexDdlWithDiagnostics, getRdbmsDialectCapability, inferLogicalTypeFromPhysical, isRelationshipLineRenderable, mergeDialectMetas, migrateLegacyFkLineVisibility, parseDesign, resolveDialectMetas, roundTripDesign, serializeDesign, validateDesignDocument };
1017
+ export { BUILTIN_DIALECTS, BUILTIN_DIALECT_METAS_JSON, LOGICAL_DATA_TYPES, PACKAGE_DEFAULT_PHYSICAL_TYPE_TEXT, alignNodePositions, analyzeDdlDocument, applyLogicalTypeChange, convertDesignDialect, convertPhysicalTypeByLogicalType, createColumn, createDefaultDbMetaAdapter, createEmptyDesign, createId, createLargeDesign, defaultDbMetaAdapter, defaultPhysicalType, dialectSupportsSchema, ensureUniqueDesignIds, formatDdlDiagnostic, formatDdlDiagnostics, generateDdl, generateDdlForSelection, generateDdlWithDiagnostics, generateIndexDdl, generateIndexDdlWithDiagnostics, getRdbmsDialectCapability, inferLogicalTypeFromPhysical, isRelationshipLineRenderable, mergeDialectMetas, migrateLegacyFkLineVisibility, parseDesign, resolveDialectMetas, roundTripDesign, serializeDesign, validateDesignDocument };
916
1018
  //# sourceMappingURL=index.js.map
917
1019
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/alignment.ts","../src/index.ts"],"names":["quoteIdentifier","toDefaultExpression"],"mappings":"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","file":"index.js","sourcesContent":["export type AlignCommand =\r\n | \"left\"\r\n | \"h-center\"\r\n | \"right\"\r\n | \"top\"\r\n | \"v-center\"\r\n | \"bottom\"\r\n | \"h-gap\"\r\n | \"v-gap\";\r\n\r\n/**\r\n * 멀티 선택된 노드 위치를 bounding box 기준으로 정렬/분배한다.\r\n * positions는 id -> 좌표 맵이며, 반환값은 동일 키에 갱신된 좌표만 포함한다.\r\n */\r\nexport function alignNodePositions(\r\n selectedIds: string[],\r\n positions: Record<string, { x: number; y: number }>,\r\n command: AlignCommand,\r\n anchorId?: string\r\n): Record<string, { x: number; y: number }> {\r\n const entries = selectedIds\r\n .map((id) => {\r\n const pos = positions[id];\r\n return pos ? { id, pos: { ...pos } } : null;\r\n })\r\n .filter((e): e is { id: string; pos: { x: number; y: number } } => Boolean(e));\r\n\r\n if (entries.length < 2) {\r\n return {};\r\n }\r\n\r\n const xs = entries.map((e) => e.pos.x);\r\n const ys = entries.map((e) => e.pos.y);\r\n const minX = Math.min(...xs);\r\n const maxX = Math.max(...xs);\r\n const minY = Math.min(...ys);\r\n const maxY = Math.max(...ys);\r\n const centerX = (minX + maxX) / 2;\r\n const centerY = (minY + maxY) / 2;\r\n const anchorPos = anchorId\r\n ? entries.find((e) => e.id === anchorId)?.pos\r\n : undefined;\r\n const targetX = anchorPos?.x ?? centerX;\r\n const targetY = anchorPos?.y ?? centerY;\r\n\r\n const sortByX = [...entries].sort((a, b) => a.pos.x - b.pos.x);\r\n const sortByY = [...entries].sort((a, b) => a.pos.y - b.pos.y);\r\n\r\n const out: Record<string, { x: number; y: number }> = {};\r\n\r\n for (const e of entries) {\r\n const next = { ...e.pos };\r\n if (command === \"left\") next.x = anchorPos ? targetX : minX;\r\n if (command === \"h-center\") next.x = targetX;\r\n if (command === \"right\") next.x = anchorPos ? targetX : maxX;\r\n if (command === \"top\") next.y = anchorPos ? targetY : minY;\r\n if (command === \"v-center\") next.y = targetY;\r\n if (command === \"bottom\") next.y = anchorPos ? targetY : maxY;\r\n out[e.id] = next;\r\n }\r\n\r\n if (command === \"h-gap\") {\r\n const gap = entries.length > 1 ? (maxX - minX) / (entries.length - 1) : 0;\r\n sortByX.forEach((e, index) => {\r\n out[e.id] = { ...e.pos, x: minX + gap * index };\r\n });\r\n }\r\n\r\n if (command === \"v-gap\") {\r\n const gap = entries.length > 1 ? (maxY - minY) / (entries.length - 1) : 0;\r\n sortByY.forEach((e, index) => {\r\n out[e.id] = { ...e.pos, y: minY + gap * index };\r\n });\r\n }\r\n\r\n return out;\r\n}\r\n","export type BuiltinRdbmsDialect =\r\n | \"mssql\"\r\n | \"oracle\"\r\n | \"mysql\"\r\n | \"postgres\"\r\n | \"sqlite\";\r\nexport type RdbmsDialect = BuiltinRdbmsDialect | (string & {});\r\n\r\nexport { alignNodePositions, type AlignCommand } from \"./alignment\";\r\n\r\nexport const LOGICAL_DATA_TYPES = [\r\n \"TEXT\",\r\n \"DATE\",\r\n \"TIME\",\r\n \"DATETIME\",\r\n \"NUMBER\",\r\n \"DECIMAL\",\r\n \"FLOAT\",\r\n \"BOOLEAN\",\r\n \"JSON\",\r\n \"UUID\",\r\n \"BINARY\",\r\n] as const;\r\n\r\nexport type LogicalDataType = (typeof LOGICAL_DATA_TYPES)[number];\r\n\r\nexport interface ColumnModel {\r\n id: string;\r\n logicalName: string;\r\n physicalName: string;\r\n /** 컬럼 설명(업무/도메인 메모). */\r\n description?: string;\r\n logicalType: LogicalDataType;\r\n physicalType: string;\r\n defaultValue?: string;\r\n nullable: boolean;\r\n isPrimaryKey?: boolean;\r\n isForeignKey?: boolean;\r\n referencesPrimaryColumnId?: string;\r\n /** 테이블 노드에서 해당 컬럼 행 배경색 */\r\n color?: string;\r\n}\r\n\r\nexport interface TableModel {\r\n id: string;\r\n logicalName: string;\r\n physicalName: string;\r\n /** 테이블 설명(업무/도메인 메모). */\r\n description?: string;\r\n /** Dialect-dependent schema/catalog qualifier (e.g. `public`, `dbo`). */\r\n schemaName?: string;\r\n color?: string;\r\n columns: ColumnModel[];\r\n}\r\n\r\nexport interface RelationshipModel {\r\n id: string;\r\n /** 참조 원본(PK) 테이블 */\r\n sourceTableId: string;\r\n /** 참조 대상(FK) 테이블 */\r\n targetTableId: string;\r\n /**\r\n * 복합 PK→FK 연결에서 컬럼 쌍마다 관계 레코드는 여러 개 두되,\r\n * 동일 값을 가진 관계들은 캔버스에서 한 줄로 묶어 그린다.\r\n */\r\n relationshipGroupId?: string;\r\n /** source(PK) 컬럼 id */\r\n sourceColumnId?: string;\r\n /** target(FK) 컬럼 id */\r\n targetColumnId?: string;\r\n /** 연결 시 생성된 FK 컬럼인지 여부(삭제 시 컬럼 정리용) */\r\n autoCreatedTargetColumn?: boolean;\r\n /** FK가 최초로 연결된 PK 컬럼 id(컬럼명 변경과 무관) */\r\n originPkColumnId?: string;\r\n /** 타깃 cardinality. 기본 1:N */\r\n cardinality?: \"1:1\" | \"1:N\";\r\n /** 출발(소스) 엣지의 테이블 내부 절대 Y 좌표(px). */\r\n sourceLineY?: number;\r\n /** @deprecated legacy ratio(0~1). sourceLineY가 없을 때만 fallback으로 사용 */\r\n sourceLineRatio?: number;\r\n /** 관계선의 중간 꺾임 위치 비율(0~1). 두 테이블 앵커 사이의 비율로 저장한다. */\r\n linePivotRatio?: number;\r\n /** true이면 캔버스에서 해당 관계선을 기본적으로 숨긴다. 툴의「숨긴 관계선 보기」로만 표시 가능. */\r\n canvasLineHidden?: boolean;\r\n}\r\n\r\n/**\r\n * 캔버스에 관계선을 그릴지 여부.\r\n * - `revealHiddenLines === false`: `canvasLineHidden`인 관계는 제외.\r\n * - `revealHiddenLines === true`: 숨김 처리된 관계도 함께 그린다(표시만, 속성은 바꾸지 않음).\r\n */\r\nexport function isRelationshipLineRenderable(\r\n rel: RelationshipModel,\r\n revealHiddenLines: boolean,\r\n): boolean {\r\n if (rel.canvasLineHidden === true) return revealHiddenLines;\r\n return true;\r\n}\r\n\r\n/** 구버전 `ColumnModel.showFkRelationLine === false`를 관계의 `canvasLineHidden`으로 옮긴 뒤 컬럼 플래그를 제거한다. */\r\nexport function migrateLegacyFkLineVisibility(model: DesignModel): void {\r\n for (const table of model.tables) {\r\n for (const col of table.columns) {\r\n const legacy = (col as { showFkRelationLine?: boolean })\r\n .showFkRelationLine;\r\n if (legacy === false && col.isForeignKey) {\r\n for (const rel of model.relationships) {\r\n if (\r\n rel.targetTableId === table.id &&\r\n rel.targetColumnId === col.id\r\n ) {\r\n rel.canvasLineHidden = true;\r\n }\r\n }\r\n }\r\n if (\"showFkRelationLine\" in col) {\r\n delete (col as { showFkRelationLine?: boolean })\r\n .showFkRelationLine;\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * 구버전·수동 JSON 등에서 `defaultValue` 키가 없는 컬럼에 빈 문자열을 넣어 형태를 통일한다.\r\n * DDL·엑셀은 기존과 같이 빈 값은 기본값 없음으로 취급한다.\r\n */\r\nfunction normalizeColumnDefaultValues(model: DesignModel): void {\r\n for (const table of model.tables) {\r\n const cols = table.columns;\r\n if (!Array.isArray(cols)) continue;\r\n for (const col of cols) {\r\n if (col.defaultValue === undefined || col.defaultValue === null) {\r\n col.defaultValue = \"\";\r\n }\r\n }\r\n }\r\n}\r\n\r\nexport interface IndexModel {\r\n id: string;\r\n tableId: string;\r\n name: string;\r\n columns: string[];\r\n unique: boolean;\r\n}\r\n\r\nexport interface DiagramLayout {\r\n nodePositions: Record<string, { x: number; y: number }>;\r\n}\r\n\r\nexport interface DesignModel {\r\n dialect: RdbmsDialect;\r\n tables: TableModel[];\r\n relationships: RelationshipModel[];\r\n indexes: IndexModel[];\r\n}\r\n\r\nexport interface DesignDocument {\r\n schemaVersion: number;\r\n model: DesignModel;\r\n layout: DiagramLayout;\r\n settings?: Record<string, unknown>;\r\n}\r\n\r\nexport interface DialectCapability {\r\n supportsSchema: boolean;\r\n}\r\n\r\nexport type DdlStyleQuote = \"double\" | \"backtick\" | \"bracket\";\r\nexport type DdlStyleBooleanLiteral = \"trueFalse\" | \"oneZero\";\r\n\r\nexport interface DdlStyle {\r\n quote: DdlStyleQuote;\r\n boolLiteral?: DdlStyleBooleanLiteral;\r\n nowKeyword?: string;\r\n}\r\n\r\nexport interface LogicalTypeMeta {\r\n id: LogicalDataType;\r\n label?: string;\r\n defaultPhysicalType: string;\r\n}\r\n\r\nexport interface DialectMetaJson {\r\n id: RdbmsDialect;\r\n label: string;\r\n supportsSchema: boolean;\r\n logicalTypes: LogicalTypeMeta[];\r\n ddlStyle?: DdlStyle;\r\n}\r\n\r\nexport interface DialectMeta {\r\n id: RdbmsDialect;\r\n label: string;\r\n capabilities: DialectCapability;\r\n logicalTypes: readonly LogicalDataType[];\r\n defaultPhysicalTypeMap: Partial<Record<LogicalDataType, string>>;\r\n}\r\n\r\nexport type DdlScope =\r\n | { kind: \"all\" }\r\n | { kind: \"selected\"; tableIds: string[] };\r\n\r\nexport interface DdlGenerateInput {\r\n doc: DesignDocument;\r\n dialectId: RdbmsDialect;\r\n scope: DdlScope;\r\n}\r\n\r\nexport interface DdlGenerateOutput {\r\n sql: string;\r\n diagnostics?: DdlDiagnostic[];\r\n}\r\n\r\nexport type DdlGeneratorHook = (\r\n input: DdlGenerateInput,\r\n) => DdlGenerateOutput | Promise<DdlGenerateOutput>;\r\n\r\nexport interface DdlGeneratorRules {\r\n quoteIdentifier?: (dialect: RdbmsDialect, identifier: string) => string;\r\n toDefaultExpression?: (\r\n dialect: RdbmsDialect,\r\n col: ColumnModel,\r\n ) => string | null;\r\n}\r\n\r\nexport interface DbMetaAdapter {\r\n listDialects: () => DialectMeta[];\r\n getDialectMeta: (dialect: RdbmsDialect) => DialectMeta | undefined;\r\n getDefaultPhysicalType: (\r\n dialect: RdbmsDialect,\r\n logicalType: LogicalDataType,\r\n ) => string;\r\n getDdlRules: (dialect: RdbmsDialect) => DdlGeneratorRules;\r\n}\r\n\r\nexport interface CoreDbMetaOptions {\r\n dbMetaAdapter?: DbMetaAdapter;\r\n hostMetas?: DialectMetaJson[];\r\n hostDdlGenerators?: Record<string, DdlGeneratorHook>;\r\n fallbackOnHookError?: boolean;\r\n /** Host overrides: logical type → default physical DataType (designer / defaultPhysicalType). */\r\n defaultPhysicalTypes?: Partial<Record<LogicalDataType, string>>;\r\n}\r\n\r\n/** When TEXT is not in `defaultPhysicalTypes`, `defaultPhysicalType` uses this (not dialect NVARCHAR). */\r\nexport const PACKAGE_DEFAULT_PHYSICAL_TYPE_TEXT = \"VARCHAR(20)\";\r\n\r\nfunction isObject(value: unknown): value is Record<string, unknown> {\r\n return typeof value === \"object\" && value !== null;\r\n}\r\n\r\nexport const BUILTIN_DIALECTS: readonly BuiltinRdbmsDialect[] = [\r\n \"mssql\",\r\n \"oracle\",\r\n \"mysql\",\r\n \"postgres\",\r\n \"sqlite\",\r\n] as const;\r\n\r\nconst DIALECT_DEFAULT_TYPE_MAP: Record<\r\n BuiltinRdbmsDialect,\r\n Record<LogicalDataType, string>\r\n> = {\r\n mssql: {\r\n TEXT: \"NVARCHAR(255)\",\r\n DATE: \"DATE\",\r\n TIME: \"TIME\",\r\n DATETIME: \"DATETIME2\",\r\n NUMBER: \"INT\",\r\n DECIMAL: \"DECIMAL(10,2)\",\r\n FLOAT: \"FLOAT\",\r\n BOOLEAN: \"BIT\",\r\n JSON: \"NVARCHAR(MAX)\",\r\n UUID: \"UNIQUEIDENTIFIER\",\r\n BINARY: \"VARBINARY(255)\",\r\n },\r\n oracle: {\r\n TEXT: \"VARCHAR2(255)\",\r\n DATE: \"DATE\",\r\n TIME: \"TIMESTAMP\",\r\n DATETIME: \"TIMESTAMP\",\r\n NUMBER: \"NUMBER(10)\",\r\n DECIMAL: \"NUMBER(10,2)\",\r\n FLOAT: \"BINARY_FLOAT\",\r\n BOOLEAN: \"NUMBER(1)\",\r\n JSON: \"CLOB\",\r\n UUID: \"RAW(16)\",\r\n BINARY: \"RAW(255)\",\r\n },\r\n mysql: {\r\n TEXT: \"VARCHAR(255)\",\r\n DATE: \"DATE\",\r\n TIME: \"TIME\",\r\n DATETIME: \"DATETIME\",\r\n NUMBER: \"INT\",\r\n DECIMAL: \"DECIMAL(10,2)\",\r\n FLOAT: \"FLOAT\",\r\n BOOLEAN: \"BOOLEAN\",\r\n JSON: \"JSON\",\r\n UUID: \"CHAR(36)\",\r\n BINARY: \"VARBINARY(255)\",\r\n },\r\n postgres: {\r\n TEXT: \"VARCHAR(255)\",\r\n DATE: \"DATE\",\r\n TIME: \"TIME\",\r\n DATETIME: \"TIMESTAMP\",\r\n NUMBER: \"INTEGER\",\r\n DECIMAL: \"NUMERIC(10,2)\",\r\n FLOAT: \"REAL\",\r\n BOOLEAN: \"BOOLEAN\",\r\n JSON: \"JSONB\",\r\n UUID: \"UUID\",\r\n BINARY: \"BYTEA\",\r\n },\r\n sqlite: {\r\n TEXT: \"TEXT\",\r\n DATE: \"TEXT\",\r\n TIME: \"TEXT\",\r\n DATETIME: \"TEXT\",\r\n NUMBER: \"INTEGER\",\r\n DECIMAL: \"NUMERIC(10,2)\",\r\n FLOAT: \"REAL\",\r\n BOOLEAN: \"INTEGER\",\r\n JSON: \"TEXT\",\r\n UUID: \"TEXT\",\r\n BINARY: \"BLOB\",\r\n },\r\n};\r\n\r\nconst DIALECT_CAPABILITIES: Record<\r\n BuiltinRdbmsDialect,\r\n { supportsSchema: boolean }\r\n> = {\r\n mssql: { supportsSchema: true },\r\n oracle: { supportsSchema: true },\r\n mysql: { supportsSchema: true },\r\n postgres: { supportsSchema: true },\r\n sqlite: { supportsSchema: false },\r\n};\r\n\r\nconst DIALECT_LABELS: Record<BuiltinRdbmsDialect, string> = {\r\n mssql: \"MS SQL Server\",\r\n oracle: \"Oracle\",\r\n mysql: \"MySQL\",\r\n postgres: \"PostgreSQL\",\r\n sqlite: \"SQLite\",\r\n};\r\n\r\nconst DIALECT_DDL_STYLE: Record<BuiltinRdbmsDialect, DdlStyle> = {\r\n mssql: {\r\n quote: \"bracket\",\r\n boolLiteral: \"oneZero\",\r\n nowKeyword: \"GETDATE()\",\r\n },\r\n oracle: {\r\n quote: \"double\",\r\n boolLiteral: \"oneZero\",\r\n nowKeyword: \"CURRENT_TIMESTAMP\",\r\n },\r\n mysql: {\r\n quote: \"backtick\",\r\n boolLiteral: \"oneZero\",\r\n nowKeyword: \"CURRENT_TIMESTAMP\",\r\n },\r\n postgres: {\r\n quote: \"double\",\r\n boolLiteral: \"trueFalse\",\r\n nowKeyword: \"CURRENT_TIMESTAMP\",\r\n },\r\n sqlite: {\r\n quote: \"double\",\r\n boolLiteral: \"oneZero\",\r\n nowKeyword: \"CURRENT_TIMESTAMP\",\r\n },\r\n};\r\n\r\nfunction toLogicalTypeMetas(dialect: BuiltinRdbmsDialect): LogicalTypeMeta[] {\r\n return LOGICAL_DATA_TYPES.map((id) => ({\r\n id,\r\n defaultPhysicalType: DIALECT_DEFAULT_TYPE_MAP[dialect][id],\r\n }));\r\n}\r\n\r\nexport const BUILTIN_DIALECT_METAS_JSON: DialectMetaJson[] =\r\n BUILTIN_DIALECTS.map((dialect) => ({\r\n id: dialect,\r\n label: DIALECT_LABELS[dialect],\r\n supportsSchema: DIALECT_CAPABILITIES[dialect].supportsSchema,\r\n logicalTypes: toLogicalTypeMetas(dialect),\r\n ddlStyle: DIALECT_DDL_STYLE[dialect],\r\n }));\r\n\r\nfunction defaultDdlRules(): DdlGeneratorRules {\r\n return {\r\n quoteIdentifier: (dialect, identifier) => {\r\n if (dialect === \"mssql\") return `[${identifier}]`;\r\n if (dialect === \"mysql\") return `\\`${identifier}\\``;\r\n return `\"${identifier}\"`;\r\n },\r\n toDefaultExpression: (dialect, col) => {\r\n const raw = col.defaultValue?.trim();\r\n if (!raw) return null;\r\n const upper = raw.toUpperCase();\r\n const isFunctionLike =\r\n /[()]/.test(raw) ||\r\n upper === \"NULL\" ||\r\n upper === \"CURRENT_TIMESTAMP\" ||\r\n upper === \"CURRENT_DATE\";\r\n if (isFunctionLike) return raw;\r\n if (\r\n col.logicalType === \"NUMBER\" ||\r\n col.logicalType === \"DECIMAL\" ||\r\n col.logicalType === \"FLOAT\"\r\n )\r\n return raw;\r\n if (col.logicalType === \"BOOLEAN\") {\r\n if (upper === \"TRUE\" || upper === \"FALSE\") {\r\n if (\r\n dialect === \"mssql\" ||\r\n dialect === \"oracle\" ||\r\n dialect === \"sqlite\"\r\n )\r\n return upper === \"TRUE\" ? \"1\" : \"0\";\r\n return upper;\r\n }\r\n if (raw === \"1\" || raw === \"0\") return raw;\r\n return quoteSqlString(raw);\r\n }\r\n if (col.logicalType === \"DATE\" || col.logicalType === \"DATETIME\") {\r\n if (dialect === \"mssql\" && upper === \"NOW\") return \"GETDATE()\";\r\n if (upper === \"NOW\") return \"CURRENT_TIMESTAMP\";\r\n return quoteSqlString(raw);\r\n }\r\n if (\r\n (raw.startsWith(\"'\") && raw.endsWith(\"'\")) ||\r\n (raw.startsWith('\"') && raw.endsWith('\"'))\r\n )\r\n return raw;\r\n return quoteSqlString(raw);\r\n },\r\n };\r\n}\r\n\r\nfunction toAdapterDialectMeta(meta: DialectMetaJson): DialectMeta {\r\n const typeMap: Partial<Record<LogicalDataType, string>> = {};\r\n for (const lt of meta.logicalTypes) typeMap[lt.id] = lt.defaultPhysicalType;\r\n return {\r\n id: meta.id,\r\n label: meta.label,\r\n capabilities: { supportsSchema: meta.supportsSchema },\r\n logicalTypes: meta.logicalTypes.map((lt) => lt.id),\r\n defaultPhysicalTypeMap: typeMap,\r\n };\r\n}\r\n\r\nexport function mergeDialectMetas(\r\n base: DialectMetaJson[],\r\n host: DialectMetaJson[] = [],\r\n): DialectMetaJson[] {\r\n const byId = new Map<string, DialectMetaJson>(\r\n base.map((meta) => [meta.id, meta]),\r\n );\r\n for (const meta of host) byId.set(meta.id, meta);\r\n return Array.from(byId.values());\r\n}\r\n\r\nexport function resolveDialectMetas(\r\n options?: CoreDbMetaOptions,\r\n): DialectMetaJson[] {\r\n return mergeDialectMetas(\r\n BUILTIN_DIALECT_METAS_JSON,\r\n options?.hostMetas ?? [],\r\n );\r\n}\r\n\r\nfunction buildDbMetaAdapterFromMetas(metas: DialectMetaJson[]): DbMetaAdapter {\r\n const byId = new Map<RdbmsDialect, DialectMeta>(\r\n metas.map((meta) => [meta.id, toAdapterDialectMeta(meta)]),\r\n );\r\n const defaultRules = defaultDdlRules();\r\n return {\r\n listDialects: () => Array.from(byId.values()),\r\n getDialectMeta: (dialect) => byId.get(dialect),\r\n getDefaultPhysicalType: (dialect, logicalType) => {\r\n const mapped =\r\n byId.get(dialect)?.defaultPhysicalTypeMap[logicalType];\r\n return mapped ?? DIALECT_DEFAULT_TYPE_MAP.postgres[logicalType];\r\n },\r\n getDdlRules: (dialect) => {\r\n const json = metas.find((m) => m.id === dialect);\r\n const style = json?.ddlStyle;\r\n if (!style) return defaultRules;\r\n const quoteIdentifier: DdlGeneratorRules[\"quoteIdentifier\"] = (\r\n _d,\r\n identifier,\r\n ) => {\r\n if (style.quote === \"bracket\") return `[${identifier}]`;\r\n if (style.quote === \"backtick\") return `\\`${identifier}\\``;\r\n return `\"${identifier}\"`;\r\n };\r\n const toDefaultExpression: DdlGeneratorRules[\"toDefaultExpression\"] =\r\n (_d, col) => {\r\n const raw = col.defaultValue?.trim();\r\n if (!raw) return null;\r\n const upper = raw.toUpperCase();\r\n const isFunctionLike =\r\n /[()]/.test(raw) ||\r\n upper === \"NULL\" ||\r\n upper === \"CURRENT_TIMESTAMP\" ||\r\n upper === \"CURRENT_DATE\";\r\n if (isFunctionLike) return raw;\r\n if (\r\n col.logicalType === \"NUMBER\" ||\r\n col.logicalType === \"DECIMAL\" ||\r\n col.logicalType === \"FLOAT\"\r\n )\r\n return raw;\r\n if (col.logicalType === \"BOOLEAN\") {\r\n if (upper === \"TRUE\" || upper === \"FALSE\") {\r\n if ((style.boolLiteral ?? \"oneZero\") === \"oneZero\")\r\n return upper === \"TRUE\" ? \"1\" : \"0\";\r\n return upper;\r\n }\r\n if (raw === \"1\" || raw === \"0\") return raw;\r\n return quoteSqlString(raw);\r\n }\r\n if (\r\n col.logicalType === \"DATE\" ||\r\n col.logicalType === \"DATETIME\"\r\n ) {\r\n if (upper === \"NOW\")\r\n return style.nowKeyword ?? \"CURRENT_TIMESTAMP\";\r\n return quoteSqlString(raw);\r\n }\r\n if (\r\n (raw.startsWith(\"'\") && raw.endsWith(\"'\")) ||\r\n (raw.startsWith('\"') && raw.endsWith('\"'))\r\n )\r\n return raw;\r\n return quoteSqlString(raw);\r\n };\r\n return { quoteIdentifier, toDefaultExpression };\r\n },\r\n };\r\n}\r\n\r\nexport function createDefaultDbMetaAdapter(\r\n overrides?: Partial<DbMetaAdapter>,\r\n): DbMetaAdapter {\r\n const base = buildDbMetaAdapterFromMetas(BUILTIN_DIALECT_METAS_JSON);\r\n return { ...base, ...overrides };\r\n}\r\n\r\nexport const defaultDbMetaAdapter = createDefaultDbMetaAdapter();\r\n\r\nfunction resolveDbMetaAdapter(options?: CoreDbMetaOptions): DbMetaAdapter {\r\n if (options?.dbMetaAdapter) return options.dbMetaAdapter;\r\n if (options?.hostMetas && options.hostMetas.length > 0) {\r\n return buildDbMetaAdapterFromMetas(resolveDialectMetas(options));\r\n }\r\n return defaultDbMetaAdapter;\r\n}\r\n\r\nfunction hostMetaTextDefaultPhysical(\r\n dialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): string | undefined {\r\n const hostOnly = options?.hostMetas?.find((m) => m.id === dialect);\r\n const fromHost = hostOnly?.logicalTypes.find((lt) => lt.id === \"TEXT\")\r\n ?.defaultPhysicalType;\r\n const trimmed = fromHost?.trim();\r\n return trimmed && trimmed.length > 0 ? trimmed : undefined;\r\n}\r\n\r\nexport function defaultPhysicalType(\r\n dialect: RdbmsDialect,\r\n logicalType: LogicalDataType,\r\n options?: CoreDbMetaOptions,\r\n): string {\r\n const hostOverride = options?.defaultPhysicalTypes?.[logicalType]?.trim();\r\n if (hostOverride) return hostOverride;\r\n\r\n const fromAdapter = resolveDbMetaAdapter(options).getDefaultPhysicalType(\r\n dialect,\r\n logicalType,\r\n );\r\n\r\n if (logicalType === \"TEXT\") {\r\n const hostMetaText = hostMetaTextDefaultPhysical(dialect, options);\r\n if (hostMetaText) return hostMetaText;\r\n const builtinText = resolveDialectMetas()\r\n .find((m) => m.id === dialect)\r\n ?.logicalTypes.find((lt) => lt.id === \"TEXT\")\r\n ?.defaultPhysicalType?.trim();\r\n if (\r\n builtinText &&\r\n normalizePhysicalCompare(fromAdapter) ===\r\n normalizePhysicalCompare(builtinText)\r\n ) {\r\n return PACKAGE_DEFAULT_PHYSICAL_TYPE_TEXT;\r\n }\r\n return fromAdapter;\r\n }\r\n\r\n return fromAdapter;\r\n}\r\n\r\nfunction normalizePhysicalCompare(s: string): string {\r\n return s.trim().toUpperCase().replace(/\\s+/g, \" \");\r\n}\r\n\r\nfunction physicalTypeBaseName(s: string): string {\r\n const n = normalizePhysicalCompare(s);\r\n const p = n.indexOf(\"(\");\r\n return p >= 0 ? n.slice(0, p).trim() : n;\r\n}\r\n\r\n/**\r\n * 물리 데이터 유형 문자열에서 방언 메타의 기본 매핑(및 흔한 SQL 별칭)으로 논리 유형을 추정한다.\r\n */\r\nexport function inferLogicalTypeFromPhysical(\r\n dialect: RdbmsDialect,\r\n physicalType: string,\r\n options?: CoreDbMetaOptions,\r\n): LogicalDataType {\r\n const raw = physicalType?.trim();\r\n if (!raw) return \"TEXT\";\r\n\r\n const metas = resolveDialectMetas(options);\r\n const meta = metas.find((m) => m.id === dialect);\r\n const normFull = normalizePhysicalCompare(raw);\r\n const base = physicalTypeBaseName(raw);\r\n\r\n if (meta) {\r\n for (const lt of meta.logicalTypes) {\r\n if (\r\n normalizePhysicalCompare(lt.defaultPhysicalType) === normFull\r\n ) {\r\n return lt.id;\r\n }\r\n }\r\n for (const lt of meta.logicalTypes) {\r\n if (physicalTypeBaseName(lt.defaultPhysicalType) === base) {\r\n return lt.id;\r\n }\r\n }\r\n }\r\n\r\n const b = base;\r\n if (\r\n b === \"INT\" ||\r\n b === \"INTEGER\" ||\r\n b === \"BIGINT\" ||\r\n b === \"SMALLINT\" ||\r\n b === \"TINYINT\" ||\r\n b === \"NUMBER\" ||\r\n b === \"SERIAL\" ||\r\n b === \"SERIAL4\" ||\r\n b === \"SERIAL8\"\r\n ) {\r\n return \"NUMBER\";\r\n }\r\n if (\r\n b === \"DECIMAL\" ||\r\n b === \"NUMERIC\" ||\r\n b === \"MONEY\" ||\r\n b === \"SMALLMONEY\"\r\n ) {\r\n return \"DECIMAL\";\r\n }\r\n if (\r\n b === \"FLOAT\" ||\r\n b === \"REAL\" ||\r\n b === \"DOUBLE\" ||\r\n b === \"BINARY_FLOAT\" ||\r\n b === \"BINARY_DOUBLE\"\r\n ) {\r\n return \"FLOAT\";\r\n }\r\n if (b === \"BIT\" || b === \"BOOLEAN\" || b === \"BOOL\") {\r\n return \"BOOLEAN\";\r\n }\r\n if (\r\n b === \"DATETIME\" ||\r\n b === \"DATETIME2\" ||\r\n b === \"SMALLDATETIME\" ||\r\n b === \"TIMESTAMP\" ||\r\n b === \"TIMESTAMPTZ\"\r\n ) {\r\n return \"DATETIME\";\r\n }\r\n if (b === \"DATE\") return \"DATE\";\r\n if (b === \"TIME\" || b === \"TIMETZ\") return \"TIME\";\r\n if (\r\n b.includes(\"CHAR\") ||\r\n b === \"TEXT\" ||\r\n b === \"CLOB\" ||\r\n b === \"NCLOB\" ||\r\n b === \"NCHAR\" ||\r\n b === \"NVARCHAR\" ||\r\n b === \"VARCHAR\" ||\r\n b === \"VARCHAR2\"\r\n ) {\r\n return \"TEXT\";\r\n }\r\n if (b === \"JSON\" || b === \"JSONB\") return \"JSON\";\r\n if (b === \"UUID\" || b === \"UNIQUEIDENTIFIER\") return \"UUID\";\r\n if (\r\n b === \"BINARY\" ||\r\n b === \"VARBINARY\" ||\r\n b === \"RAW\" ||\r\n b === \"BYTEA\" ||\r\n b === \"BLOB\" ||\r\n b === \"IMAGE\"\r\n ) {\r\n return \"BINARY\";\r\n }\r\n\r\n return \"TEXT\";\r\n}\r\n\r\nexport function getRdbmsDialectCapability(\r\n dialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): DialectCapability {\r\n const meta = resolveDbMetaAdapter(options).getDialectMeta(dialect);\r\n return meta?.capabilities ?? { supportsSchema: false };\r\n}\r\n\r\nexport function dialectSupportsSchema(\r\n dialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): boolean {\r\n return getRdbmsDialectCapability(dialect, options).supportsSchema;\r\n}\r\n\r\nfunction parseTypeArguments(physicalType: string): number[] | null {\r\n const m = physicalType.match(/\\(([^)]+)\\)/);\r\n if (!m) return null;\r\n const values = m[1]\r\n .split(\",\")\r\n .map((v) => Number.parseInt(v.trim(), 10))\r\n .filter((v) => Number.isFinite(v));\r\n return values.length > 0 ? values : null;\r\n}\r\n\r\n/**\r\n * 컬럼의 논리 유형을 유지한 채 기존 물리 타입 문자열을 `nextDialect`에 맞게 변환한다.\r\n * `(` `)` 안의 정밀도·스케일·길이 등은 가능한 범위에서 보존하고, 나머지는 `defaultPhysicalType`으로 맞춘다.\r\n * `convertDesignDialect`에서 컬럼별 물리 타입을 갱신할 때 사용한다.\r\n */\r\nexport function convertPhysicalTypeByLogicalType(\r\n physicalType: string,\r\n logicalType: LogicalDataType,\r\n nextDialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): string {\r\n const args = parseTypeArguments(physicalType);\r\n const precision = args?.[0];\r\n const scale = args?.[1];\r\n const length = args?.[0];\r\n\r\n if (logicalType === \"NUMBER\") {\r\n if (nextDialect === \"oracle\") {\r\n if (precision && scale !== undefined)\r\n return `NUMBER(${precision},${scale})`;\r\n if (precision) return `NUMBER(${precision})`;\r\n return \"NUMBER(10)\";\r\n }\r\n if (nextDialect === \"mssql\") {\r\n if (precision && scale !== undefined)\r\n return `NUMERIC(${precision},${scale})`;\r\n if (precision) return `NUMERIC(${precision},0)`;\r\n return \"INT\";\r\n }\r\n if (nextDialect === \"mysql\") {\r\n if (precision && scale !== undefined)\r\n return `DECIMAL(${precision},${scale})`;\r\n if (precision) return `DECIMAL(${precision},0)`;\r\n return \"INT\";\r\n }\r\n if (nextDialect === \"postgres\") {\r\n if (precision && scale !== undefined)\r\n return `NUMERIC(${precision},${scale})`;\r\n if (precision) return `NUMERIC(${precision},0)`;\r\n return \"INTEGER\";\r\n }\r\n return \"INTEGER\";\r\n }\r\n\r\n if (logicalType === \"DECIMAL\") {\r\n if (precision && scale !== undefined) {\r\n if (nextDialect === \"oracle\")\r\n return `NUMBER(${precision},${scale})`;\r\n if (nextDialect === \"postgres\")\r\n return `NUMERIC(${precision},${scale})`;\r\n return `DECIMAL(${precision},${scale})`;\r\n }\r\n return defaultPhysicalType(nextDialect, logicalType, options);\r\n }\r\n\r\n if (logicalType === \"FLOAT\") {\r\n if (nextDialect === \"oracle\") return \"BINARY_FLOAT\";\r\n if (nextDialect === \"sqlite\") return \"REAL\";\r\n return \"FLOAT\";\r\n }\r\n\r\n if (logicalType === \"TEXT\") {\r\n if (nextDialect === \"oracle\")\r\n return length ? `VARCHAR2(${length})` : \"VARCHAR2(255)\";\r\n if (nextDialect === \"mssql\")\r\n return length ? `NVARCHAR(${length})` : \"NVARCHAR(255)\";\r\n if (nextDialect === \"mysql\")\r\n return length ? `VARCHAR(${length})` : \"VARCHAR(255)\";\r\n if (nextDialect === \"postgres\")\r\n return length ? `VARCHAR(${length})` : \"VARCHAR(255)\";\r\n return \"TEXT\";\r\n }\r\n\r\n if (logicalType === \"BINARY\") {\r\n if (nextDialect === \"mssql\")\r\n return length ? `VARBINARY(${length})` : \"VARBINARY(255)\";\r\n if (nextDialect === \"oracle\")\r\n return length ? `RAW(${length})` : \"RAW(255)\";\r\n if (nextDialect === \"mysql\")\r\n return length ? `VARBINARY(${length})` : \"VARBINARY(255)\";\r\n if (nextDialect === \"postgres\") return \"BYTEA\";\r\n return \"BLOB\";\r\n }\r\n\r\n return defaultPhysicalType(nextDialect, logicalType, options);\r\n}\r\n\r\nexport function convertDesignDialect(\r\n doc: DesignDocument,\r\n nextDialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): DesignDocument {\r\n if (doc.model.dialect === nextDialect) return doc;\r\n const supportsSchema = dialectSupportsSchema(nextDialect, options);\r\n return {\r\n ...doc,\r\n model: {\r\n ...doc.model,\r\n dialect: nextDialect,\r\n tables: doc.model.tables.map((table) => ({\r\n ...table,\r\n schemaName: supportsSchema ? table.schemaName : undefined,\r\n columns: table.columns.map((col) => ({\r\n ...col,\r\n physicalType: convertPhysicalTypeByLogicalType(\r\n col.physicalType,\r\n col.logicalType,\r\n nextDialect,\r\n options,\r\n ),\r\n })),\r\n })),\r\n },\r\n };\r\n}\r\n\r\nexport function applyLogicalTypeChange(\r\n column: ColumnModel,\r\n nextLogicalType: LogicalDataType,\r\n dialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): ColumnModel {\r\n return {\r\n ...column,\r\n logicalType: nextLogicalType,\r\n physicalType: defaultPhysicalType(dialect, nextLogicalType, options),\r\n };\r\n}\r\n\r\nexport function createColumn(\r\n dialect: RdbmsDialect,\r\n params: {\r\n id: string;\r\n logicalName: string;\r\n /** 생략 시 논리 이름과 동일한 물리 이름으로 생성된다. */\r\n physicalName?: string;\r\n description?: string;\r\n logicalType: LogicalDataType;\r\n defaultValue?: string;\r\n nullable?: boolean;\r\n isPrimaryKey?: boolean;\r\n isForeignKey?: boolean;\r\n referencesPrimaryColumnId?: string;\r\n color?: string;\r\n },\r\n options?: CoreDbMetaOptions,\r\n): ColumnModel {\r\n const physicalName = params.physicalName ?? params.logicalName;\r\n const isPrimaryKey = params.isPrimaryKey ?? false;\r\n const isForeignKey = params.isForeignKey ?? false;\r\n const col: ColumnModel = {\r\n id: params.id,\r\n logicalName: params.logicalName,\r\n physicalName,\r\n description: params.description,\r\n logicalType: params.logicalType,\r\n physicalType: defaultPhysicalType(dialect, params.logicalType, options),\r\n defaultValue: params.defaultValue,\r\n nullable: isPrimaryKey ? false : (params.nullable ?? true),\r\n isPrimaryKey,\r\n isForeignKey,\r\n referencesPrimaryColumnId: params.referencesPrimaryColumnId,\r\n };\r\n if (params.color !== undefined) col.color = params.color;\r\n return col;\r\n}\r\n\r\nexport function createEmptyDesign(\r\n dialect: RdbmsDialect = \"mssql\",\r\n): DesignDocument {\r\n return {\r\n schemaVersion: 1,\r\n model: {\r\n dialect,\r\n tables: [],\r\n relationships: [],\r\n indexes: [],\r\n },\r\n layout: {\r\n nodePositions: {},\r\n },\r\n };\r\n}\r\n\r\nexport function serializeDesign(doc: DesignDocument): string {\r\n return JSON.stringify(doc, null, 2);\r\n}\r\n\r\nexport function parseDesign(\r\n json: string,\r\n options?: CoreDbMetaOptions,\r\n): DesignDocument {\r\n const parsed = JSON.parse(json) as unknown;\r\n return validateDesignDocument(parsed, options);\r\n}\r\n\r\nexport function validateDesignDocument(\r\n input: unknown,\r\n options?: CoreDbMetaOptions,\r\n): DesignDocument {\r\n if (!isObject(input)) {\r\n throw new Error(\"Invalid design document: root must be object\");\r\n }\r\n\r\n if (input.schemaVersion !== 1) {\r\n throw new Error(\"Unsupported schemaVersion\");\r\n }\r\n\r\n if (\r\n !isObject(input.model) ||\r\n !Array.isArray(input.model.tables) ||\r\n !Array.isArray(input.model.relationships) ||\r\n !Array.isArray(input.model.indexes)\r\n ) {\r\n throw new Error(\"Invalid design document: model is malformed\");\r\n }\r\n\r\n const dialects = new Set(\r\n resolveDbMetaAdapter(options)\r\n .listDialects()\r\n .map((d) => d.id),\r\n );\r\n const modelDialect = (input.model as unknown as { dialect?: unknown })\r\n .dialect;\r\n if (\r\n typeof modelDialect !== \"string\" ||\r\n !dialects.has(modelDialect as RdbmsDialect)\r\n ) {\r\n throw new Error(\"Invalid design document: model.dialect is invalid\");\r\n }\r\n\r\n if (!isObject(input.layout) || !isObject(input.layout.nodePositions)) {\r\n throw new Error(\"Invalid design document: layout is malformed\");\r\n }\r\n\r\n const doc = input as unknown as DesignDocument;\r\n migrateLegacyFkLineVisibility(doc.model);\r\n normalizeColumnDefaultValues(doc.model);\r\n return doc;\r\n}\r\n\r\nexport function roundTripDesign(doc: DesignDocument): DesignDocument {\r\n return parseDesign(serializeDesign(doc));\r\n}\r\n\r\nfunction quoteIdentifier(\r\n dialect: RdbmsDialect,\r\n identifier: string,\r\n options?: CoreDbMetaOptions,\r\n): string {\r\n const quote =\r\n resolveDbMetaAdapter(options).getDdlRules(dialect).quoteIdentifier ??\r\n defaultDdlRules().quoteIdentifier!;\r\n return quote(dialect, identifier);\r\n}\r\n\r\nfunction qualifiedTableName(\r\n table: TableModel,\r\n dialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): string {\r\n const schema = table.schemaName?.trim();\r\n if (dialectSupportsSchema(dialect, options) && schema) {\r\n return `${quoteIdentifier(dialect, schema, options)}.${quoteIdentifier(dialect, table.physicalName, options)}`;\r\n }\r\n return quoteIdentifier(dialect, table.physicalName, options);\r\n}\r\n\r\nfunction quoteSqlString(value: string): string {\r\n return `'${value.replaceAll(\"'\", \"''\")}'`;\r\n}\r\n\r\nfunction toDefaultExpression(\r\n dialect: RdbmsDialect,\r\n col: ColumnModel,\r\n options?: CoreDbMetaOptions,\r\n): string | null {\r\n const handler =\r\n resolveDbMetaAdapter(options).getDdlRules(dialect)\r\n .toDefaultExpression ?? defaultDdlRules().toDefaultExpression!;\r\n return handler(dialect, col);\r\n}\r\n\r\nfunction joinColumnDefs(\r\n table: TableModel,\r\n dialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): string[] {\r\n const defs = table.columns.map((col) => {\r\n const nullable = col.nullable ? \"NULL\" : \"NOT NULL\";\r\n const defaultExpr = toDefaultExpression(dialect, col, options);\r\n const defaultSql = defaultExpr ? ` DEFAULT ${defaultExpr}` : \"\";\r\n return ` ${quoteIdentifier(dialect, col.physicalName, options)} ${col.physicalType}${defaultSql} ${nullable}`;\r\n });\r\n const pkColumns = table.columns\r\n .filter((col) => col.isPrimaryKey)\r\n .map((col) => quoteIdentifier(dialect, col.physicalName, options));\r\n if (pkColumns.length > 0) {\r\n defs.push(` PRIMARY KEY (${pkColumns.join(\", \")})`);\r\n }\r\n return defs;\r\n}\r\n\r\nfunction createTableSql(\r\n table: TableModel,\r\n dialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): string {\r\n const columns = joinColumnDefs(table, dialect, options);\r\n return `CREATE TABLE ${qualifiedTableName(table, dialect, options)} (\\n${columns.join(\",\\n\")}\\n);`;\r\n}\r\n\r\nfunction createRelationshipSql(\r\n rel: RelationshipModel,\r\n model: DesignModel,\r\n dialect: RdbmsDialect,\r\n index: number,\r\n options?: CoreDbMetaOptions,\r\n): string | null {\r\n const sourceTable = model.tables.find(\r\n (table) => table.id === rel.sourceTableId,\r\n );\r\n const targetTable = model.tables.find(\r\n (table) => table.id === rel.targetTableId,\r\n );\r\n if (\r\n !sourceTable ||\r\n !targetTable ||\r\n !rel.sourceColumnId ||\r\n !rel.targetColumnId\r\n ) {\r\n return null;\r\n }\r\n\r\n const sourceColumn = sourceTable.columns.find(\r\n (col) => col.id === rel.sourceColumnId,\r\n );\r\n const targetColumn = targetTable.columns.find(\r\n (col) => col.id === rel.targetColumnId,\r\n );\r\n if (!sourceColumn || !targetColumn) {\r\n return null;\r\n }\r\n\r\n const fkName = `FK_${targetTable.physicalName}_${sourceTable.physicalName}_${index + 1}`;\r\n return [\r\n `ALTER TABLE ${qualifiedTableName(targetTable, dialect, options)}`,\r\n ` ADD CONSTRAINT ${quoteIdentifier(dialect, fkName, options)}`,\r\n ` FOREIGN KEY (${quoteIdentifier(dialect, targetColumn.physicalName, options)})`,\r\n ` REFERENCES ${qualifiedTableName(sourceTable, dialect, options)} (${quoteIdentifier(dialect, sourceColumn.physicalName, options)});`,\r\n ].join(\"\\n\");\r\n}\r\n\r\nfunction createIndexSql(\r\n indexModel: IndexModel,\r\n model: DesignModel,\r\n dialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): string | null {\r\n const table = model.tables.find((item) => item.id === indexModel.tableId);\r\n if (!table || indexModel.columns.length === 0) {\r\n return null;\r\n }\r\n const unique = indexModel.unique ? \"UNIQUE \" : \"\";\r\n const columns = indexModel.columns\r\n .map((col) => quoteIdentifier(dialect, col, options))\r\n .join(\", \");\r\n return `CREATE ${unique}INDEX ${quoteIdentifier(dialect, indexModel.name, options)} ON ${qualifiedTableName(table, dialect, options)} (${columns});`;\r\n}\r\n\r\nfunction buildDdlSql(doc: DesignDocument, options?: CoreDbMetaOptions): string {\r\n const { model } = doc;\r\n const tableSql = model.tables.map((table) =>\r\n createTableSql(table, model.dialect, options),\r\n );\r\n const relSql = model.relationships\r\n .map((rel, index) =>\r\n createRelationshipSql(rel, model, model.dialect, index, options),\r\n )\r\n .filter((item): item is string => Boolean(item));\r\n return [...tableSql, ...relSql].join(\"\\n\\n\");\r\n}\r\n\r\nfunction buildIndexDdlSql(\r\n doc: DesignDocument,\r\n options?: CoreDbMetaOptions,\r\n): string {\r\n const { model } = doc;\r\n const statements = model.indexes\r\n .map((index) => createIndexSql(index, model, model.dialect, options))\r\n .filter((item): item is string => Boolean(item));\r\n return statements.join(\"\\n\\n\");\r\n}\r\n\r\nfunction sliceDocByScope(doc: DesignDocument, scope: DdlScope): DesignDocument {\r\n if (scope.kind === \"all\") return doc;\r\n const selected = new Set(scope.tableIds);\r\n return {\r\n ...doc,\r\n model: {\r\n ...doc.model,\r\n tables: doc.model.tables.filter((t) => selected.has(t.id)),\r\n relationships: doc.model.relationships.filter(\r\n (r) =>\r\n selected.has(r.sourceTableId) &&\r\n selected.has(r.targetTableId),\r\n ),\r\n indexes: doc.model.indexes.filter((i) => selected.has(i.tableId)),\r\n },\r\n };\r\n}\r\n\r\nfunction styleBasedDdlGenerator(\r\n input: DdlGenerateInput,\r\n options?: CoreDbMetaOptions,\r\n): DdlGenerateOutput {\r\n const scoped = sliceDocByScope(input.doc, input.scope);\r\n return {\r\n sql: buildDdlSql(scoped, options),\r\n diagnostics: analyzeDdlDocument(scoped, options),\r\n };\r\n}\r\n\r\nfunction hasBuiltinDialect(\r\n dialectId: RdbmsDialect,\r\n): dialectId is BuiltinRdbmsDialect {\r\n return (BUILTIN_DIALECTS as readonly string[]).includes(dialectId);\r\n}\r\n\r\nfunction getBuiltinDdlGenerator(\r\n dialectId: RdbmsDialect,\r\n _options?: CoreDbMetaOptions,\r\n): DdlGeneratorHook | undefined {\r\n if (!hasBuiltinDialect(dialectId)) return undefined;\r\n return (input) => styleBasedDdlGenerator(input, _options);\r\n}\r\n\r\nfunction invokeDdlGeneratorSync(\r\n generator: DdlGeneratorHook,\r\n input: DdlGenerateInput,\r\n): DdlGenerateOutput {\r\n const result = generator(input);\r\n if (\r\n result &&\r\n typeof (result as Promise<DdlGenerateOutput>).then === \"function\"\r\n ) {\r\n throw new Error(\"Async DDL generator is not supported in sync API\");\r\n }\r\n return result as DdlGenerateOutput;\r\n}\r\n\r\nfunction runDdlGenerator(\r\n doc: DesignDocument,\r\n scope: DdlScope,\r\n options?: CoreDbMetaOptions,\r\n): DdlGenerateOutput {\r\n const input: DdlGenerateInput = {\r\n doc,\r\n dialectId: doc.model.dialect,\r\n scope,\r\n };\r\n const hostGenerator = options?.hostDdlGenerators?.[doc.model.dialect];\r\n const builtinGenerator = getBuiltinDdlGenerator(doc.model.dialect, options);\r\n const fallback = () => styleBasedDdlGenerator(input, options);\r\n const fallbackOnError = options?.fallbackOnHookError ?? true;\r\n\r\n const selectedGenerator = hostGenerator ?? builtinGenerator;\r\n if (!selectedGenerator) return fallback();\r\n try {\r\n return invokeDdlGeneratorSync(selectedGenerator, input);\r\n } catch (error) {\r\n if (!fallbackOnError) throw error;\r\n return fallback();\r\n }\r\n}\r\n\r\n/** DDL/인덱스 분석 공통 심각도 */\r\nexport type DdlDiagnosticSeverity = \"error\" | \"warning\";\r\n\r\n/** 구조화된 DDL 관련 진단(에러·경고) */\r\nexport interface DdlDiagnostic {\r\n severity: DdlDiagnosticSeverity;\r\n code: string;\r\n message: string;\r\n /** 예: relationship:rel1, index:ix1, table:t1 */\r\n context?: string;\r\n}\r\n\r\n/**\r\n * 통일된 한 줄 텍스트 포맷.\r\n * 예: `[WARN][DDL_REL_MISSING_COLUMNS] ... | relationship:rel1`\r\n */\r\nexport function formatDdlDiagnostic(d: DdlDiagnostic): string {\r\n const level = d.severity === \"error\" ? \"ERROR\" : \"WARN\";\r\n const tail = d.context ? ` | ${d.context}` : \"\";\r\n return `[${level}][${d.code}] ${d.message}${tail}`;\r\n}\r\n\r\nexport function formatDdlDiagnostics(diagnostics: DdlDiagnostic[]): string {\r\n return diagnostics.map(formatDdlDiagnostic).join(\"\\n\");\r\n}\r\n\r\n/**\r\n * 모델 전체에 대한 DDL·인덱스 관련 진단(테이블/관계/인덱스).\r\n * 검증 예외(Invalid design document)와는 별도로, 생성 가능 여부와 경고를 나열한다.\r\n */\r\nexport function analyzeDdlDocument(\r\n doc: DesignDocument,\r\n options?: CoreDbMetaOptions,\r\n): DdlDiagnostic[] {\r\n const out: DdlDiagnostic[] = [];\r\n const { model } = doc;\r\n const tableById = new Map(model.tables.map((t) => [t.id, t]));\r\n const physicalTableNames = new Map<string, string[]>();\r\n\r\n for (const table of model.tables) {\r\n const qualifiedName =\r\n dialectSupportsSchema(model.dialect, options) &&\r\n table.schemaName?.trim()\r\n ? `${table.schemaName.trim()}.${table.physicalName}`\r\n : table.physicalName;\r\n const list = physicalTableNames.get(qualifiedName) ?? [];\r\n list.push(table.id);\r\n physicalTableNames.set(qualifiedName, list);\r\n if (table.columns.length === 0) {\r\n out.push({\r\n severity: \"warning\",\r\n code: \"DDL_EMPTY_TABLE\",\r\n message:\r\n \"컬럼이 없는 테이블은 CREATE TABLE 구문이 비어 있거나 무의미할 수 있다.\",\r\n context: `table:${table.id}`,\r\n });\r\n }\r\n }\r\n\r\n for (const [name, ids] of physicalTableNames) {\r\n if (ids.length > 1) {\r\n out.push({\r\n severity: \"warning\",\r\n code: \"DDL_DUPLICATE_TABLE_NAME\",\r\n message: `동일한 물리 테이블명 \"${name}\"이 ${ids.length}개 테이블에 사용되었다.`,\r\n context: `tables:${ids.join(\",\")}`,\r\n });\r\n }\r\n }\r\n\r\n for (const rel of model.relationships) {\r\n const ctx = `relationship:${rel.id}`;\r\n const sourceTable = tableById.get(rel.sourceTableId);\r\n const targetTable = tableById.get(rel.targetTableId);\r\n if (!sourceTable || !targetTable) {\r\n out.push({\r\n severity: \"error\",\r\n code: \"DDL_REL_UNKNOWN_TABLE\",\r\n message:\r\n \"관계의 소스 또는 타겟 테이블을 찾을 수 없어 FK DDL을 생성할 수 없다.\",\r\n context: ctx,\r\n });\r\n continue;\r\n }\r\n if (!rel.sourceColumnId || !rel.targetColumnId) {\r\n out.push({\r\n severity: \"warning\",\r\n code: \"DDL_REL_MISSING_COLUMNS\",\r\n message: \"소스/타겟 컬럼이 지정되지 않아 FK DDL을 생략한다.\",\r\n context: ctx,\r\n });\r\n continue;\r\n }\r\n const sourceColumn = sourceTable.columns.find(\r\n (c) => c.id === rel.sourceColumnId,\r\n );\r\n const targetColumn = targetTable.columns.find(\r\n (c) => c.id === rel.targetColumnId,\r\n );\r\n if (!sourceColumn || !targetColumn) {\r\n out.push({\r\n severity: \"warning\",\r\n code: \"DDL_REL_UNKNOWN_COLUMN\",\r\n message:\r\n \"관계에 지정된 컬럼 id를 테이블에서 찾을 수 없어 FK DDL을 생략한다.\",\r\n context: ctx,\r\n });\r\n }\r\n }\r\n\r\n for (const indexModel of model.indexes) {\r\n const ctx = `index:${indexModel.id}`;\r\n const table = tableById.get(indexModel.tableId);\r\n if (!table) {\r\n out.push({\r\n severity: \"warning\",\r\n code: \"IDX_UNKNOWN_TABLE\",\r\n message:\r\n \"인덱스가 가리키는 테이블을 찾을 수 없어 인덱스 DDL을 생략한다.\",\r\n context: ctx,\r\n });\r\n continue;\r\n }\r\n if (indexModel.columns.length === 0) {\r\n out.push({\r\n severity: \"warning\",\r\n code: \"IDX_EMPTY_COLUMNS\",\r\n message: \"인덱스 컬럼 목록이 비어 있어 인덱스 DDL을 생략한다.\",\r\n context: ctx,\r\n });\r\n continue;\r\n }\r\n for (const colPhys of indexModel.columns) {\r\n if (!table.columns.some((c) => c.physicalName === colPhys)) {\r\n out.push({\r\n severity: \"warning\",\r\n code: \"IDX_UNKNOWN_COLUMN\",\r\n message: `인덱스가 참조하는 물리 컬럼명 \"${colPhys}\"을(를) 테이블 \"${table.physicalName}\"에서 찾을 수 없다.`,\r\n context: ctx,\r\n });\r\n }\r\n }\r\n }\r\n\r\n return out;\r\n}\r\n\r\nexport function generateDdlWithDiagnostics(\r\n doc: DesignDocument,\r\n options?: CoreDbMetaOptions,\r\n): { sql: string; diagnostics: DdlDiagnostic[] } {\r\n const out = runDdlGenerator(doc, { kind: \"all\" }, options);\r\n return {\r\n sql: out.sql,\r\n diagnostics: out.diagnostics ?? analyzeDdlDocument(doc, options),\r\n };\r\n}\r\n\r\nexport function generateIndexDdlWithDiagnostics(\r\n doc: DesignDocument,\r\n options?: CoreDbMetaOptions,\r\n): { sql: string; diagnostics: DdlDiagnostic[] } {\r\n return {\r\n sql: buildIndexDdlSql(doc, options),\r\n diagnostics: analyzeDdlDocument(doc, options),\r\n };\r\n}\r\n\r\nexport function generateDdl(\r\n doc: DesignDocument,\r\n options?: CoreDbMetaOptions,\r\n): string {\r\n return runDdlGenerator(doc, { kind: \"all\" }, options).sql;\r\n}\r\n\r\nexport function generateDdlForSelection(\r\n doc: DesignDocument,\r\n tableIds: string[],\r\n options?: CoreDbMetaOptions,\r\n): { sql: string; diagnostics: DdlDiagnostic[] } {\r\n const out = runDdlGenerator(doc, { kind: \"selected\", tableIds }, options);\r\n const diagnostics =\r\n out.diagnostics ??\r\n analyzeDdlDocument(\r\n sliceDocByScope(doc, { kind: \"selected\", tableIds }),\r\n options,\r\n );\r\n return { sql: out.sql, diagnostics };\r\n}\r\n\r\nexport function generateIndexDdl(\r\n doc: DesignDocument,\r\n options?: CoreDbMetaOptions,\r\n): string {\r\n return buildIndexDdlSql(doc, options);\r\n}\r\n\r\n/** 성능·부하 테스트용: 지정 개수의 빈 테이블과 격자 레이아웃을 생성한다. */\r\nexport function createLargeDesign(\r\n tableCount: number,\r\n dialect: RdbmsDialect = \"postgres\",\r\n): DesignDocument {\r\n const doc = createEmptyDesign(dialect);\r\n const cols = 20;\r\n for (let i = 0; i < tableCount; i++) {\r\n const id = `t-${i}`;\r\n doc.model.tables.push({\r\n id,\r\n logicalName: `엔티티${i}`,\r\n physicalName: `TB_T${i}`,\r\n columns: [\r\n createColumn(dialect, {\r\n id: `${id}-pk`,\r\n logicalName: \"식별자\",\r\n logicalType: \"NUMBER\",\r\n nullable: false,\r\n }),\r\n ],\r\n });\r\n doc.layout.nodePositions[id] = {\r\n x: (i % cols) * 220,\r\n y: Math.floor(i / cols) * 120,\r\n };\r\n }\r\n return doc;\r\n}\r\n"]}
1
+ {"version":3,"sources":["../src/alignment.ts","../src/ensureUniqueDesignIds.ts","../src/index.ts"],"names":["quoteIdentifier","toDefaultExpression"],"mappings":"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","file":"index.js","sourcesContent":["export type AlignCommand =\r\n | \"left\"\r\n | \"h-center\"\r\n | \"right\"\r\n | \"top\"\r\n | \"v-center\"\r\n | \"bottom\"\r\n | \"h-gap\"\r\n | \"v-gap\";\r\n\r\n/**\r\n * 멀티 선택된 노드 위치를 bounding box 기준으로 정렬/분배한다.\r\n * positions는 id -> 좌표 맵이며, 반환값은 동일 키에 갱신된 좌표만 포함한다.\r\n */\r\nexport function alignNodePositions(\r\n selectedIds: string[],\r\n positions: Record<string, { x: number; y: number }>,\r\n command: AlignCommand,\r\n anchorId?: string\r\n): Record<string, { x: number; y: number }> {\r\n const entries = selectedIds\r\n .map((id) => {\r\n const pos = positions[id];\r\n return pos ? { id, pos: { ...pos } } : null;\r\n })\r\n .filter((e): e is { id: string; pos: { x: number; y: number } } => Boolean(e));\r\n\r\n if (entries.length < 2) {\r\n return {};\r\n }\r\n\r\n const xs = entries.map((e) => e.pos.x);\r\n const ys = entries.map((e) => e.pos.y);\r\n const minX = Math.min(...xs);\r\n const maxX = Math.max(...xs);\r\n const minY = Math.min(...ys);\r\n const maxY = Math.max(...ys);\r\n const centerX = (minX + maxX) / 2;\r\n const centerY = (minY + maxY) / 2;\r\n const anchorPos = anchorId\r\n ? entries.find((e) => e.id === anchorId)?.pos\r\n : undefined;\r\n const targetX = anchorPos?.x ?? centerX;\r\n const targetY = anchorPos?.y ?? centerY;\r\n\r\n const sortByX = [...entries].sort((a, b) => a.pos.x - b.pos.x);\r\n const sortByY = [...entries].sort((a, b) => a.pos.y - b.pos.y);\r\n\r\n const out: Record<string, { x: number; y: number }> = {};\r\n\r\n for (const e of entries) {\r\n const next = { ...e.pos };\r\n if (command === \"left\") next.x = anchorPos ? targetX : minX;\r\n if (command === \"h-center\") next.x = targetX;\r\n if (command === \"right\") next.x = anchorPos ? targetX : maxX;\r\n if (command === \"top\") next.y = anchorPos ? targetY : minY;\r\n if (command === \"v-center\") next.y = targetY;\r\n if (command === \"bottom\") next.y = anchorPos ? targetY : maxY;\r\n out[e.id] = next;\r\n }\r\n\r\n if (command === \"h-gap\") {\r\n const gap = entries.length > 1 ? (maxX - minX) / (entries.length - 1) : 0;\r\n sortByX.forEach((e, index) => {\r\n out[e.id] = { ...e.pos, x: minX + gap * index };\r\n });\r\n }\r\n\r\n if (command === \"v-gap\") {\r\n const gap = entries.length > 1 ? (maxY - minY) / (entries.length - 1) : 0;\r\n sortByY.forEach((e, index) => {\r\n out[e.id] = { ...e.pos, y: minY + gap * index };\r\n });\r\n }\r\n\r\n return out;\r\n}\r\n","import type {\r\n DesignDocument,\r\n DesignModel,\r\n IndexModel,\r\n RelationshipModel,\r\n TableModel,\r\n} from \"./index.js\";\r\n\r\nfunction fallbackId(): string {\r\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\r\n}\r\n\r\n/** 문서 전역에서 쓰는 안정적인 id (`table-{uuid}` 등). */\r\nexport function createId(prefix: string): string {\r\n const suffix =\r\n typeof globalThis.crypto?.randomUUID === \"function\"\r\n ? globalThis.crypto.randomUUID()\r\n : fallbackId();\r\n return `${prefix}-${suffix}`;\r\n}\r\n\r\nfunction remapColumnRefs(\r\n columnIdMap: Map<string, string>,\r\n columnId: string | undefined,\r\n): string | undefined {\r\n if (!columnId) return columnId;\r\n return columnIdMap.get(columnId) ?? columnId;\r\n}\r\n\r\nfunction normalizeTableColumns(\r\n table: TableModel,\r\n usedColumnIds: Set<string>,\r\n columnIdMap: Map<string, string>,\r\n): TableModel {\r\n const columns = table.columns.map((col) => {\r\n const oldId = col.id?.trim() || createId(\"col\");\r\n let id = oldId;\r\n if (usedColumnIds.has(id)) {\r\n id = createId(\"col\");\r\n columnIdMap.set(oldId, id);\r\n }\r\n usedColumnIds.add(id);\r\n return { ...col, id };\r\n });\r\n return {\r\n ...table,\r\n columns: columns.map((col) => ({\r\n ...col,\r\n referencesPrimaryColumnId: remapColumnRefs(\r\n columnIdMap,\r\n col.referencesPrimaryColumnId,\r\n ),\r\n })),\r\n };\r\n}\r\n\r\nfunction remapRelationships(\r\n relationships: RelationshipModel[],\r\n tableIdMap: Map<string, string>,\r\n columnIdMap: Map<string, string>,\r\n): RelationshipModel[] {\r\n return relationships.map((rel) => ({\r\n ...rel,\r\n sourceTableId: tableIdMap.get(rel.sourceTableId) ?? rel.sourceTableId,\r\n targetTableId: tableIdMap.get(rel.targetTableId) ?? rel.targetTableId,\r\n sourceColumnId: remapColumnRefs(columnIdMap, rel.sourceColumnId),\r\n targetColumnId: remapColumnRefs(columnIdMap, rel.targetColumnId),\r\n originPkColumnId: remapColumnRefs(columnIdMap, rel.originPkColumnId),\r\n }));\r\n}\r\n\r\nfunction remapIndexes(\r\n indexes: IndexModel[],\r\n tableIdMap: Map<string, string>,\r\n): IndexModel[] {\r\n return indexes.map((idx) => ({\r\n ...idx,\r\n tableId: tableIdMap.get(idx.tableId) ?? idx.tableId,\r\n }));\r\n}\r\n\r\n/**\r\n * 테이블·컬럼 id가 문서 전역에서 유일하도록 재발급한다.\r\n * Host import 등으로 `table-1`이 중복된 경우 React Flow 노드 충돌을 방지한다.\r\n */\r\nexport function ensureUniqueDesignIds(doc: DesignDocument): DesignDocument {\r\n const usedColumnIds = new Set<string>();\r\n const columnIdMap = new Map<string, string>();\r\n\r\n const usedTableIds = new Set<string>();\r\n const tableIdMap = new Map<string, string>();\r\n const oldTableIds: string[] = [];\r\n const nextTables: TableModel[] = [];\r\n\r\n for (const table of doc.model.tables) {\r\n const oldId = table.id?.trim() || createId(\"table\");\r\n oldTableIds.push(oldId);\r\n let id = oldId;\r\n if (usedTableIds.has(id)) {\r\n id = createId(\"table\");\r\n }\r\n usedTableIds.add(id);\r\n const duplicateOldCount = oldTableIds.filter((x) => x === oldId).length;\r\n if (oldId !== id && duplicateOldCount === 1) {\r\n tableIdMap.set(oldId, id);\r\n }\r\n nextTables.push(\r\n normalizeTableColumns({ ...table, id }, usedColumnIds, columnIdMap),\r\n );\r\n }\r\n\r\n const nodePositions: Record<string, { x: number; y: number }> = {};\r\n for (let i = 0; i < nextTables.length; i++) {\r\n const table = nextTables[i]!;\r\n const oldId = oldTableIds[i]!;\r\n nodePositions[table.id] =\r\n doc.layout.nodePositions[table.id] ??\r\n doc.layout.nodePositions[oldId] ?? {\r\n x: 60 + (i % 5) * 48,\r\n y: 60 + Math.floor(i / 5) * 48,\r\n };\r\n }\r\n\r\n const model: DesignModel = {\r\n ...doc.model,\r\n tables: nextTables,\r\n relationships: remapRelationships(\r\n doc.model.relationships,\r\n tableIdMap,\r\n columnIdMap,\r\n ),\r\n indexes: remapIndexes(doc.model.indexes, tableIdMap),\r\n };\r\n\r\n return {\r\n ...doc,\r\n model,\r\n layout: {\r\n ...doc.layout,\r\n nodePositions,\r\n },\r\n };\r\n}\r\n","export type BuiltinRdbmsDialect =\r\n | \"mssql\"\r\n | \"oracle\"\r\n | \"mysql\"\r\n | \"postgres\"\r\n | \"sqlite\";\r\nexport type RdbmsDialect = BuiltinRdbmsDialect | (string & {});\r\n\r\nexport { alignNodePositions, type AlignCommand } from \"./alignment\";\r\nimport { createId, ensureUniqueDesignIds } from \"./ensureUniqueDesignIds.js\";\r\nexport { createId, ensureUniqueDesignIds };\r\n\r\nexport const LOGICAL_DATA_TYPES = [\r\n \"TEXT\",\r\n \"DATE\",\r\n \"TIME\",\r\n \"DATETIME\",\r\n \"NUMBER\",\r\n \"DECIMAL\",\r\n \"FLOAT\",\r\n \"BOOLEAN\",\r\n \"JSON\",\r\n \"UUID\",\r\n \"BINARY\",\r\n] as const;\r\n\r\nexport type LogicalDataType = (typeof LOGICAL_DATA_TYPES)[number];\r\n\r\nexport interface ColumnModel {\r\n id: string;\r\n logicalName: string;\r\n physicalName: string;\r\n /** 컬럼 설명(업무/도메인 메모). */\r\n description?: string;\r\n logicalType: LogicalDataType;\r\n physicalType: string;\r\n defaultValue?: string;\r\n nullable: boolean;\r\n isPrimaryKey?: boolean;\r\n isForeignKey?: boolean;\r\n referencesPrimaryColumnId?: string;\r\n /** 테이블 노드에서 해당 컬럼 행 배경색 */\r\n color?: string;\r\n}\r\n\r\nexport interface TableModel {\r\n id: string;\r\n logicalName: string;\r\n physicalName: string;\r\n /** 테이블 설명(업무/도메인 메모). */\r\n description?: string;\r\n /** Dialect-dependent schema/catalog qualifier (e.g. `public`, `dbo`). */\r\n schemaName?: string;\r\n color?: string;\r\n columns: ColumnModel[];\r\n}\r\n\r\nexport interface RelationshipModel {\r\n id: string;\r\n /** 참조 원본(PK) 테이블 */\r\n sourceTableId: string;\r\n /** 참조 대상(FK) 테이블 */\r\n targetTableId: string;\r\n /**\r\n * 복합 PK→FK 연결에서 컬럼 쌍마다 관계 레코드는 여러 개 두되,\r\n * 동일 값을 가진 관계들은 캔버스에서 한 줄로 묶어 그린다.\r\n */\r\n relationshipGroupId?: string;\r\n /** source(PK) 컬럼 id */\r\n sourceColumnId?: string;\r\n /** target(FK) 컬럼 id */\r\n targetColumnId?: string;\r\n /** 연결 시 생성된 FK 컬럼인지 여부(삭제 시 컬럼 정리용) */\r\n autoCreatedTargetColumn?: boolean;\r\n /** FK가 최초로 연결된 PK 컬럼 id(컬럼명 변경과 무관) */\r\n originPkColumnId?: string;\r\n /** 타깃 cardinality. 기본 1:N */\r\n cardinality?: \"1:1\" | \"1:N\";\r\n /** 출발(소스) 엣지의 테이블 내부 절대 Y 좌표(px). */\r\n sourceLineY?: number;\r\n /** @deprecated legacy ratio(0~1). sourceLineY가 없을 때만 fallback으로 사용 */\r\n sourceLineRatio?: number;\r\n /** 관계선의 중간 꺾임 위치 비율(0~1). 두 테이블 앵커 사이의 비율로 저장한다. */\r\n linePivotRatio?: number;\r\n /** true이면 캔버스에서 해당 관계선을 기본적으로 숨긴다. 툴의「숨긴 관계선 보기」로만 표시 가능. */\r\n canvasLineHidden?: boolean;\r\n}\r\n\r\n/**\r\n * 캔버스에 관계선을 그릴지 여부.\r\n * - `revealHiddenLines === false`: `canvasLineHidden`인 관계는 제외.\r\n * - `revealHiddenLines === true`: 숨김 처리된 관계도 함께 그린다(표시만, 속성은 바꾸지 않음).\r\n */\r\nexport function isRelationshipLineRenderable(\r\n rel: RelationshipModel,\r\n revealHiddenLines: boolean,\r\n): boolean {\r\n if (rel.canvasLineHidden === true) return revealHiddenLines;\r\n return true;\r\n}\r\n\r\n/** 구버전 `ColumnModel.showFkRelationLine === false`를 관계의 `canvasLineHidden`으로 옮긴 뒤 컬럼 플래그를 제거한다. */\r\nexport function migrateLegacyFkLineVisibility(model: DesignModel): void {\r\n for (const table of model.tables) {\r\n for (const col of table.columns) {\r\n const legacy = (col as { showFkRelationLine?: boolean })\r\n .showFkRelationLine;\r\n if (legacy === false && col.isForeignKey) {\r\n for (const rel of model.relationships) {\r\n if (\r\n rel.targetTableId === table.id &&\r\n rel.targetColumnId === col.id\r\n ) {\r\n rel.canvasLineHidden = true;\r\n }\r\n }\r\n }\r\n if (\"showFkRelationLine\" in col) {\r\n delete (col as { showFkRelationLine?: boolean })\r\n .showFkRelationLine;\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * 구버전·수동 JSON 등에서 `defaultValue` 키가 없는 컬럼에 빈 문자열을 넣어 형태를 통일한다.\r\n * DDL·엑셀은 기존과 같이 빈 값은 기본값 없음으로 취급한다.\r\n */\r\nfunction normalizeColumnDefaultValues(model: DesignModel): void {\r\n for (const table of model.tables) {\r\n const cols = table.columns;\r\n if (!Array.isArray(cols)) continue;\r\n for (const col of cols) {\r\n if (col.defaultValue === undefined || col.defaultValue === null) {\r\n col.defaultValue = \"\";\r\n }\r\n }\r\n }\r\n}\r\n\r\nexport interface IndexModel {\r\n id: string;\r\n tableId: string;\r\n name: string;\r\n columns: string[];\r\n unique: boolean;\r\n}\r\n\r\nexport interface DiagramLayout {\r\n nodePositions: Record<string, { x: number; y: number }>;\r\n}\r\n\r\nexport interface DesignModel {\r\n dialect: RdbmsDialect;\r\n tables: TableModel[];\r\n relationships: RelationshipModel[];\r\n indexes: IndexModel[];\r\n}\r\n\r\nexport interface DesignDocument {\r\n schemaVersion: number;\r\n model: DesignModel;\r\n layout: DiagramLayout;\r\n settings?: Record<string, unknown>;\r\n}\r\n\r\nexport interface DialectCapability {\r\n supportsSchema: boolean;\r\n}\r\n\r\nexport type DdlStyleQuote = \"double\" | \"backtick\" | \"bracket\";\r\nexport type DdlStyleBooleanLiteral = \"trueFalse\" | \"oneZero\";\r\n\r\nexport interface DdlStyle {\r\n quote: DdlStyleQuote;\r\n boolLiteral?: DdlStyleBooleanLiteral;\r\n nowKeyword?: string;\r\n}\r\n\r\nexport interface LogicalTypeMeta {\r\n id: LogicalDataType;\r\n label?: string;\r\n defaultPhysicalType: string;\r\n}\r\n\r\nexport interface DialectMetaJson {\r\n id: RdbmsDialect;\r\n label: string;\r\n supportsSchema: boolean;\r\n logicalTypes: LogicalTypeMeta[];\r\n ddlStyle?: DdlStyle;\r\n}\r\n\r\nexport interface DialectMeta {\r\n id: RdbmsDialect;\r\n label: string;\r\n capabilities: DialectCapability;\r\n logicalTypes: readonly LogicalDataType[];\r\n defaultPhysicalTypeMap: Partial<Record<LogicalDataType, string>>;\r\n}\r\n\r\nexport type DdlScope =\r\n | { kind: \"all\" }\r\n | { kind: \"selected\"; tableIds: string[] };\r\n\r\nexport interface DdlGenerateInput {\r\n doc: DesignDocument;\r\n dialectId: RdbmsDialect;\r\n scope: DdlScope;\r\n}\r\n\r\nexport interface DdlGenerateOutput {\r\n sql: string;\r\n diagnostics?: DdlDiagnostic[];\r\n}\r\n\r\nexport type DdlGeneratorHook = (\r\n input: DdlGenerateInput,\r\n) => DdlGenerateOutput | Promise<DdlGenerateOutput>;\r\n\r\nexport interface DdlGeneratorRules {\r\n quoteIdentifier?: (dialect: RdbmsDialect, identifier: string) => string;\r\n toDefaultExpression?: (\r\n dialect: RdbmsDialect,\r\n col: ColumnModel,\r\n ) => string | null;\r\n}\r\n\r\nexport interface DbMetaAdapter {\r\n listDialects: () => DialectMeta[];\r\n getDialectMeta: (dialect: RdbmsDialect) => DialectMeta | undefined;\r\n getDefaultPhysicalType: (\r\n dialect: RdbmsDialect,\r\n logicalType: LogicalDataType,\r\n ) => string;\r\n getDdlRules: (dialect: RdbmsDialect) => DdlGeneratorRules;\r\n}\r\n\r\nexport interface CoreDbMetaOptions {\r\n dbMetaAdapter?: DbMetaAdapter;\r\n hostMetas?: DialectMetaJson[];\r\n hostDdlGenerators?: Record<string, DdlGeneratorHook>;\r\n fallbackOnHookError?: boolean;\r\n /** Host overrides: logical type → default physical DataType (designer / defaultPhysicalType). */\r\n defaultPhysicalTypes?: Partial<Record<LogicalDataType, string>>;\r\n}\r\n\r\n/** When TEXT is not in `defaultPhysicalTypes`, `defaultPhysicalType` uses this (not dialect NVARCHAR). */\r\nexport const PACKAGE_DEFAULT_PHYSICAL_TYPE_TEXT = \"VARCHAR(20)\";\r\n\r\nfunction isObject(value: unknown): value is Record<string, unknown> {\r\n return typeof value === \"object\" && value !== null;\r\n}\r\n\r\nexport const BUILTIN_DIALECTS: readonly BuiltinRdbmsDialect[] = [\r\n \"mssql\",\r\n \"oracle\",\r\n \"mysql\",\r\n \"postgres\",\r\n \"sqlite\",\r\n] as const;\r\n\r\nconst DIALECT_DEFAULT_TYPE_MAP: Record<\r\n BuiltinRdbmsDialect,\r\n Record<LogicalDataType, string>\r\n> = {\r\n mssql: {\r\n TEXT: \"NVARCHAR(255)\",\r\n DATE: \"DATE\",\r\n TIME: \"TIME\",\r\n DATETIME: \"DATETIME2\",\r\n NUMBER: \"INT\",\r\n DECIMAL: \"DECIMAL(10,2)\",\r\n FLOAT: \"FLOAT\",\r\n BOOLEAN: \"BIT\",\r\n JSON: \"NVARCHAR(MAX)\",\r\n UUID: \"UNIQUEIDENTIFIER\",\r\n BINARY: \"VARBINARY(255)\",\r\n },\r\n oracle: {\r\n TEXT: \"VARCHAR2(255)\",\r\n DATE: \"DATE\",\r\n TIME: \"TIMESTAMP\",\r\n DATETIME: \"TIMESTAMP\",\r\n NUMBER: \"NUMBER(10)\",\r\n DECIMAL: \"NUMBER(10,2)\",\r\n FLOAT: \"BINARY_FLOAT\",\r\n BOOLEAN: \"NUMBER(1)\",\r\n JSON: \"CLOB\",\r\n UUID: \"RAW(16)\",\r\n BINARY: \"RAW(255)\",\r\n },\r\n mysql: {\r\n TEXT: \"VARCHAR(255)\",\r\n DATE: \"DATE\",\r\n TIME: \"TIME\",\r\n DATETIME: \"DATETIME\",\r\n NUMBER: \"INT\",\r\n DECIMAL: \"DECIMAL(10,2)\",\r\n FLOAT: \"FLOAT\",\r\n BOOLEAN: \"BOOLEAN\",\r\n JSON: \"JSON\",\r\n UUID: \"CHAR(36)\",\r\n BINARY: \"VARBINARY(255)\",\r\n },\r\n postgres: {\r\n TEXT: \"VARCHAR(255)\",\r\n DATE: \"DATE\",\r\n TIME: \"TIME\",\r\n DATETIME: \"TIMESTAMP\",\r\n NUMBER: \"INTEGER\",\r\n DECIMAL: \"NUMERIC(10,2)\",\r\n FLOAT: \"REAL\",\r\n BOOLEAN: \"BOOLEAN\",\r\n JSON: \"JSONB\",\r\n UUID: \"UUID\",\r\n BINARY: \"BYTEA\",\r\n },\r\n sqlite: {\r\n TEXT: \"TEXT\",\r\n DATE: \"TEXT\",\r\n TIME: \"TEXT\",\r\n DATETIME: \"TEXT\",\r\n NUMBER: \"INTEGER\",\r\n DECIMAL: \"NUMERIC(10,2)\",\r\n FLOAT: \"REAL\",\r\n BOOLEAN: \"INTEGER\",\r\n JSON: \"TEXT\",\r\n UUID: \"TEXT\",\r\n BINARY: \"BLOB\",\r\n },\r\n};\r\n\r\nconst DIALECT_CAPABILITIES: Record<\r\n BuiltinRdbmsDialect,\r\n { supportsSchema: boolean }\r\n> = {\r\n mssql: { supportsSchema: true },\r\n oracle: { supportsSchema: true },\r\n mysql: { supportsSchema: true },\r\n postgres: { supportsSchema: true },\r\n sqlite: { supportsSchema: false },\r\n};\r\n\r\nconst DIALECT_LABELS: Record<BuiltinRdbmsDialect, string> = {\r\n mssql: \"MS SQL Server\",\r\n oracle: \"Oracle\",\r\n mysql: \"MySQL\",\r\n postgres: \"PostgreSQL\",\r\n sqlite: \"SQLite\",\r\n};\r\n\r\nconst DIALECT_DDL_STYLE: Record<BuiltinRdbmsDialect, DdlStyle> = {\r\n mssql: {\r\n quote: \"bracket\",\r\n boolLiteral: \"oneZero\",\r\n nowKeyword: \"GETDATE()\",\r\n },\r\n oracle: {\r\n quote: \"double\",\r\n boolLiteral: \"oneZero\",\r\n nowKeyword: \"CURRENT_TIMESTAMP\",\r\n },\r\n mysql: {\r\n quote: \"backtick\",\r\n boolLiteral: \"oneZero\",\r\n nowKeyword: \"CURRENT_TIMESTAMP\",\r\n },\r\n postgres: {\r\n quote: \"double\",\r\n boolLiteral: \"trueFalse\",\r\n nowKeyword: \"CURRENT_TIMESTAMP\",\r\n },\r\n sqlite: {\r\n quote: \"double\",\r\n boolLiteral: \"oneZero\",\r\n nowKeyword: \"CURRENT_TIMESTAMP\",\r\n },\r\n};\r\n\r\nfunction toLogicalTypeMetas(dialect: BuiltinRdbmsDialect): LogicalTypeMeta[] {\r\n return LOGICAL_DATA_TYPES.map((id) => ({\r\n id,\r\n defaultPhysicalType: DIALECT_DEFAULT_TYPE_MAP[dialect][id],\r\n }));\r\n}\r\n\r\nexport const BUILTIN_DIALECT_METAS_JSON: DialectMetaJson[] =\r\n BUILTIN_DIALECTS.map((dialect) => ({\r\n id: dialect,\r\n label: DIALECT_LABELS[dialect],\r\n supportsSchema: DIALECT_CAPABILITIES[dialect].supportsSchema,\r\n logicalTypes: toLogicalTypeMetas(dialect),\r\n ddlStyle: DIALECT_DDL_STYLE[dialect],\r\n }));\r\n\r\nfunction defaultDdlRules(): DdlGeneratorRules {\r\n return {\r\n quoteIdentifier: (dialect, identifier) => {\r\n if (dialect === \"mssql\") return `[${identifier}]`;\r\n if (dialect === \"mysql\") return `\\`${identifier}\\``;\r\n return `\"${identifier}\"`;\r\n },\r\n toDefaultExpression: (dialect, col) => {\r\n const raw = col.defaultValue?.trim();\r\n if (!raw) return null;\r\n const upper = raw.toUpperCase();\r\n const isFunctionLike =\r\n /[()]/.test(raw) ||\r\n upper === \"NULL\" ||\r\n upper === \"CURRENT_TIMESTAMP\" ||\r\n upper === \"CURRENT_DATE\";\r\n if (isFunctionLike) return raw;\r\n if (\r\n col.logicalType === \"NUMBER\" ||\r\n col.logicalType === \"DECIMAL\" ||\r\n col.logicalType === \"FLOAT\"\r\n )\r\n return raw;\r\n if (col.logicalType === \"BOOLEAN\") {\r\n if (upper === \"TRUE\" || upper === \"FALSE\") {\r\n if (\r\n dialect === \"mssql\" ||\r\n dialect === \"oracle\" ||\r\n dialect === \"sqlite\"\r\n )\r\n return upper === \"TRUE\" ? \"1\" : \"0\";\r\n return upper;\r\n }\r\n if (raw === \"1\" || raw === \"0\") return raw;\r\n return quoteSqlString(raw);\r\n }\r\n if (col.logicalType === \"DATE\" || col.logicalType === \"DATETIME\") {\r\n if (dialect === \"mssql\" && upper === \"NOW\") return \"GETDATE()\";\r\n if (upper === \"NOW\") return \"CURRENT_TIMESTAMP\";\r\n return quoteSqlString(raw);\r\n }\r\n if (\r\n (raw.startsWith(\"'\") && raw.endsWith(\"'\")) ||\r\n (raw.startsWith('\"') && raw.endsWith('\"'))\r\n )\r\n return raw;\r\n return quoteSqlString(raw);\r\n },\r\n };\r\n}\r\n\r\nfunction toAdapterDialectMeta(meta: DialectMetaJson): DialectMeta {\r\n const typeMap: Partial<Record<LogicalDataType, string>> = {};\r\n for (const lt of meta.logicalTypes) typeMap[lt.id] = lt.defaultPhysicalType;\r\n return {\r\n id: meta.id,\r\n label: meta.label,\r\n capabilities: { supportsSchema: meta.supportsSchema },\r\n logicalTypes: meta.logicalTypes.map((lt) => lt.id),\r\n defaultPhysicalTypeMap: typeMap,\r\n };\r\n}\r\n\r\nexport function mergeDialectMetas(\r\n base: DialectMetaJson[],\r\n host: DialectMetaJson[] = [],\r\n): DialectMetaJson[] {\r\n const byId = new Map<string, DialectMetaJson>(\r\n base.map((meta) => [meta.id, meta]),\r\n );\r\n for (const meta of host) byId.set(meta.id, meta);\r\n return Array.from(byId.values());\r\n}\r\n\r\nexport function resolveDialectMetas(\r\n options?: CoreDbMetaOptions,\r\n): DialectMetaJson[] {\r\n return mergeDialectMetas(\r\n BUILTIN_DIALECT_METAS_JSON,\r\n options?.hostMetas ?? [],\r\n );\r\n}\r\n\r\nfunction buildDbMetaAdapterFromMetas(metas: DialectMetaJson[]): DbMetaAdapter {\r\n const byId = new Map<RdbmsDialect, DialectMeta>(\r\n metas.map((meta) => [meta.id, toAdapterDialectMeta(meta)]),\r\n );\r\n const defaultRules = defaultDdlRules();\r\n return {\r\n listDialects: () => Array.from(byId.values()),\r\n getDialectMeta: (dialect) => byId.get(dialect),\r\n getDefaultPhysicalType: (dialect, logicalType) => {\r\n const mapped =\r\n byId.get(dialect)?.defaultPhysicalTypeMap[logicalType];\r\n return mapped ?? DIALECT_DEFAULT_TYPE_MAP.postgres[logicalType];\r\n },\r\n getDdlRules: (dialect) => {\r\n const json = metas.find((m) => m.id === dialect);\r\n const style = json?.ddlStyle;\r\n if (!style) return defaultRules;\r\n const quoteIdentifier: DdlGeneratorRules[\"quoteIdentifier\"] = (\r\n _d,\r\n identifier,\r\n ) => {\r\n if (style.quote === \"bracket\") return `[${identifier}]`;\r\n if (style.quote === \"backtick\") return `\\`${identifier}\\``;\r\n return `\"${identifier}\"`;\r\n };\r\n const toDefaultExpression: DdlGeneratorRules[\"toDefaultExpression\"] =\r\n (_d, col) => {\r\n const raw = col.defaultValue?.trim();\r\n if (!raw) return null;\r\n const upper = raw.toUpperCase();\r\n const isFunctionLike =\r\n /[()]/.test(raw) ||\r\n upper === \"NULL\" ||\r\n upper === \"CURRENT_TIMESTAMP\" ||\r\n upper === \"CURRENT_DATE\";\r\n if (isFunctionLike) return raw;\r\n if (\r\n col.logicalType === \"NUMBER\" ||\r\n col.logicalType === \"DECIMAL\" ||\r\n col.logicalType === \"FLOAT\"\r\n )\r\n return raw;\r\n if (col.logicalType === \"BOOLEAN\") {\r\n if (upper === \"TRUE\" || upper === \"FALSE\") {\r\n if ((style.boolLiteral ?? \"oneZero\") === \"oneZero\")\r\n return upper === \"TRUE\" ? \"1\" : \"0\";\r\n return upper;\r\n }\r\n if (raw === \"1\" || raw === \"0\") return raw;\r\n return quoteSqlString(raw);\r\n }\r\n if (\r\n col.logicalType === \"DATE\" ||\r\n col.logicalType === \"DATETIME\"\r\n ) {\r\n if (upper === \"NOW\")\r\n return style.nowKeyword ?? \"CURRENT_TIMESTAMP\";\r\n return quoteSqlString(raw);\r\n }\r\n if (\r\n (raw.startsWith(\"'\") && raw.endsWith(\"'\")) ||\r\n (raw.startsWith('\"') && raw.endsWith('\"'))\r\n )\r\n return raw;\r\n return quoteSqlString(raw);\r\n };\r\n return { quoteIdentifier, toDefaultExpression };\r\n },\r\n };\r\n}\r\n\r\nexport function createDefaultDbMetaAdapter(\r\n overrides?: Partial<DbMetaAdapter>,\r\n): DbMetaAdapter {\r\n const base = buildDbMetaAdapterFromMetas(BUILTIN_DIALECT_METAS_JSON);\r\n return { ...base, ...overrides };\r\n}\r\n\r\nexport const defaultDbMetaAdapter = createDefaultDbMetaAdapter();\r\n\r\nfunction resolveDbMetaAdapter(options?: CoreDbMetaOptions): DbMetaAdapter {\r\n if (options?.dbMetaAdapter) return options.dbMetaAdapter;\r\n if (options?.hostMetas && options.hostMetas.length > 0) {\r\n return buildDbMetaAdapterFromMetas(resolveDialectMetas(options));\r\n }\r\n return defaultDbMetaAdapter;\r\n}\r\n\r\nfunction hostMetaTextDefaultPhysical(\r\n dialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): string | undefined {\r\n const hostOnly = options?.hostMetas?.find((m) => m.id === dialect);\r\n const fromHost = hostOnly?.logicalTypes.find((lt) => lt.id === \"TEXT\")\r\n ?.defaultPhysicalType;\r\n const trimmed = fromHost?.trim();\r\n return trimmed && trimmed.length > 0 ? trimmed : undefined;\r\n}\r\n\r\nexport function defaultPhysicalType(\r\n dialect: RdbmsDialect,\r\n logicalType: LogicalDataType,\r\n options?: CoreDbMetaOptions,\r\n): string {\r\n const hostOverride = options?.defaultPhysicalTypes?.[logicalType]?.trim();\r\n if (hostOverride) return hostOverride;\r\n\r\n const fromAdapter = resolveDbMetaAdapter(options).getDefaultPhysicalType(\r\n dialect,\r\n logicalType,\r\n );\r\n\r\n if (logicalType === \"TEXT\") {\r\n const hostMetaText = hostMetaTextDefaultPhysical(dialect, options);\r\n if (hostMetaText) return hostMetaText;\r\n const builtinText = resolveDialectMetas()\r\n .find((m) => m.id === dialect)\r\n ?.logicalTypes.find((lt) => lt.id === \"TEXT\")\r\n ?.defaultPhysicalType?.trim();\r\n if (\r\n builtinText &&\r\n normalizePhysicalCompare(fromAdapter) ===\r\n normalizePhysicalCompare(builtinText)\r\n ) {\r\n return PACKAGE_DEFAULT_PHYSICAL_TYPE_TEXT;\r\n }\r\n return fromAdapter;\r\n }\r\n\r\n return fromAdapter;\r\n}\r\n\r\nfunction normalizePhysicalCompare(s: string): string {\r\n return s.trim().toUpperCase().replace(/\\s+/g, \" \");\r\n}\r\n\r\nfunction physicalTypeBaseName(s: string): string {\r\n const n = normalizePhysicalCompare(s);\r\n const p = n.indexOf(\"(\");\r\n return p >= 0 ? n.slice(0, p).trim() : n;\r\n}\r\n\r\n/**\r\n * 물리 데이터 유형 문자열에서 방언 메타의 기본 매핑(및 흔한 SQL 별칭)으로 논리 유형을 추정한다.\r\n */\r\nexport function inferLogicalTypeFromPhysical(\r\n dialect: RdbmsDialect,\r\n physicalType: string,\r\n options?: CoreDbMetaOptions,\r\n): LogicalDataType {\r\n const raw = physicalType?.trim();\r\n if (!raw) return \"TEXT\";\r\n\r\n const metas = resolveDialectMetas(options);\r\n const meta = metas.find((m) => m.id === dialect);\r\n const normFull = normalizePhysicalCompare(raw);\r\n const base = physicalTypeBaseName(raw);\r\n\r\n if (meta) {\r\n for (const lt of meta.logicalTypes) {\r\n if (\r\n normalizePhysicalCompare(lt.defaultPhysicalType) === normFull\r\n ) {\r\n return lt.id;\r\n }\r\n }\r\n for (const lt of meta.logicalTypes) {\r\n if (physicalTypeBaseName(lt.defaultPhysicalType) === base) {\r\n return lt.id;\r\n }\r\n }\r\n }\r\n\r\n const b = base;\r\n if (\r\n b === \"INT\" ||\r\n b === \"INTEGER\" ||\r\n b === \"BIGINT\" ||\r\n b === \"SMALLINT\" ||\r\n b === \"TINYINT\" ||\r\n b === \"NUMBER\" ||\r\n b === \"SERIAL\" ||\r\n b === \"SERIAL4\" ||\r\n b === \"SERIAL8\"\r\n ) {\r\n return \"NUMBER\";\r\n }\r\n if (\r\n b === \"DECIMAL\" ||\r\n b === \"NUMERIC\" ||\r\n b === \"MONEY\" ||\r\n b === \"SMALLMONEY\"\r\n ) {\r\n return \"DECIMAL\";\r\n }\r\n if (\r\n b === \"FLOAT\" ||\r\n b === \"REAL\" ||\r\n b === \"DOUBLE\" ||\r\n b === \"BINARY_FLOAT\" ||\r\n b === \"BINARY_DOUBLE\"\r\n ) {\r\n return \"FLOAT\";\r\n }\r\n if (b === \"BIT\" || b === \"BOOLEAN\" || b === \"BOOL\") {\r\n return \"BOOLEAN\";\r\n }\r\n if (\r\n b === \"DATETIME\" ||\r\n b === \"DATETIME2\" ||\r\n b === \"SMALLDATETIME\" ||\r\n b === \"TIMESTAMP\" ||\r\n b === \"TIMESTAMPTZ\"\r\n ) {\r\n return \"DATETIME\";\r\n }\r\n if (b === \"DATE\") return \"DATE\";\r\n if (b === \"TIME\" || b === \"TIMETZ\") return \"TIME\";\r\n if (\r\n b.includes(\"CHAR\") ||\r\n b === \"TEXT\" ||\r\n b === \"CLOB\" ||\r\n b === \"NCLOB\" ||\r\n b === \"NCHAR\" ||\r\n b === \"NVARCHAR\" ||\r\n b === \"VARCHAR\" ||\r\n b === \"VARCHAR2\"\r\n ) {\r\n return \"TEXT\";\r\n }\r\n if (b === \"JSON\" || b === \"JSONB\") return \"JSON\";\r\n if (b === \"UUID\" || b === \"UNIQUEIDENTIFIER\") return \"UUID\";\r\n if (\r\n b === \"BINARY\" ||\r\n b === \"VARBINARY\" ||\r\n b === \"RAW\" ||\r\n b === \"BYTEA\" ||\r\n b === \"BLOB\" ||\r\n b === \"IMAGE\"\r\n ) {\r\n return \"BINARY\";\r\n }\r\n\r\n return \"TEXT\";\r\n}\r\n\r\nexport function getRdbmsDialectCapability(\r\n dialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): DialectCapability {\r\n const meta = resolveDbMetaAdapter(options).getDialectMeta(dialect);\r\n return meta?.capabilities ?? { supportsSchema: false };\r\n}\r\n\r\nexport function dialectSupportsSchema(\r\n dialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): boolean {\r\n return getRdbmsDialectCapability(dialect, options).supportsSchema;\r\n}\r\n\r\nfunction parseTypeArguments(physicalType: string): number[] | null {\r\n const m = physicalType.match(/\\(([^)]+)\\)/);\r\n if (!m) return null;\r\n const values = m[1]\r\n .split(\",\")\r\n .map((v) => Number.parseInt(v.trim(), 10))\r\n .filter((v) => Number.isFinite(v));\r\n return values.length > 0 ? values : null;\r\n}\r\n\r\n/**\r\n * 컬럼의 논리 유형을 유지한 채 기존 물리 타입 문자열을 `nextDialect`에 맞게 변환한다.\r\n * `(` `)` 안의 정밀도·스케일·길이 등은 가능한 범위에서 보존하고, 나머지는 `defaultPhysicalType`으로 맞춘다.\r\n * `convertDesignDialect`에서 컬럼별 물리 타입을 갱신할 때 사용한다.\r\n */\r\nexport function convertPhysicalTypeByLogicalType(\r\n physicalType: string,\r\n logicalType: LogicalDataType,\r\n nextDialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): string {\r\n const args = parseTypeArguments(physicalType);\r\n const precision = args?.[0];\r\n const scale = args?.[1];\r\n const length = args?.[0];\r\n\r\n if (logicalType === \"NUMBER\") {\r\n if (nextDialect === \"oracle\") {\r\n if (precision && scale !== undefined)\r\n return `NUMBER(${precision},${scale})`;\r\n if (precision) return `NUMBER(${precision})`;\r\n return \"NUMBER(10)\";\r\n }\r\n if (nextDialect === \"mssql\") {\r\n if (precision && scale !== undefined)\r\n return `NUMERIC(${precision},${scale})`;\r\n if (precision) return `NUMERIC(${precision},0)`;\r\n return \"INT\";\r\n }\r\n if (nextDialect === \"mysql\") {\r\n if (precision && scale !== undefined)\r\n return `DECIMAL(${precision},${scale})`;\r\n if (precision) return `DECIMAL(${precision},0)`;\r\n return \"INT\";\r\n }\r\n if (nextDialect === \"postgres\") {\r\n if (precision && scale !== undefined)\r\n return `NUMERIC(${precision},${scale})`;\r\n if (precision) return `NUMERIC(${precision},0)`;\r\n return \"INTEGER\";\r\n }\r\n return \"INTEGER\";\r\n }\r\n\r\n if (logicalType === \"DECIMAL\") {\r\n if (precision && scale !== undefined) {\r\n if (nextDialect === \"oracle\")\r\n return `NUMBER(${precision},${scale})`;\r\n if (nextDialect === \"postgres\")\r\n return `NUMERIC(${precision},${scale})`;\r\n return `DECIMAL(${precision},${scale})`;\r\n }\r\n return defaultPhysicalType(nextDialect, logicalType, options);\r\n }\r\n\r\n if (logicalType === \"FLOAT\") {\r\n if (nextDialect === \"oracle\") return \"BINARY_FLOAT\";\r\n if (nextDialect === \"sqlite\") return \"REAL\";\r\n return \"FLOAT\";\r\n }\r\n\r\n if (logicalType === \"TEXT\") {\r\n if (nextDialect === \"oracle\")\r\n return length ? `VARCHAR2(${length})` : \"VARCHAR2(255)\";\r\n if (nextDialect === \"mssql\")\r\n return length ? `NVARCHAR(${length})` : \"NVARCHAR(255)\";\r\n if (nextDialect === \"mysql\")\r\n return length ? `VARCHAR(${length})` : \"VARCHAR(255)\";\r\n if (nextDialect === \"postgres\")\r\n return length ? `VARCHAR(${length})` : \"VARCHAR(255)\";\r\n return \"TEXT\";\r\n }\r\n\r\n if (logicalType === \"BINARY\") {\r\n if (nextDialect === \"mssql\")\r\n return length ? `VARBINARY(${length})` : \"VARBINARY(255)\";\r\n if (nextDialect === \"oracle\")\r\n return length ? `RAW(${length})` : \"RAW(255)\";\r\n if (nextDialect === \"mysql\")\r\n return length ? `VARBINARY(${length})` : \"VARBINARY(255)\";\r\n if (nextDialect === \"postgres\") return \"BYTEA\";\r\n return \"BLOB\";\r\n }\r\n\r\n return defaultPhysicalType(nextDialect, logicalType, options);\r\n}\r\n\r\nexport function convertDesignDialect(\r\n doc: DesignDocument,\r\n nextDialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): DesignDocument {\r\n if (doc.model.dialect === nextDialect) return doc;\r\n const supportsSchema = dialectSupportsSchema(nextDialect, options);\r\n return {\r\n ...doc,\r\n model: {\r\n ...doc.model,\r\n dialect: nextDialect,\r\n tables: doc.model.tables.map((table) => ({\r\n ...table,\r\n schemaName: supportsSchema ? table.schemaName : undefined,\r\n columns: table.columns.map((col) => ({\r\n ...col,\r\n physicalType: convertPhysicalTypeByLogicalType(\r\n col.physicalType,\r\n col.logicalType,\r\n nextDialect,\r\n options,\r\n ),\r\n })),\r\n })),\r\n },\r\n };\r\n}\r\n\r\nexport function applyLogicalTypeChange(\r\n column: ColumnModel,\r\n nextLogicalType: LogicalDataType,\r\n dialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): ColumnModel {\r\n return {\r\n ...column,\r\n logicalType: nextLogicalType,\r\n physicalType: defaultPhysicalType(dialect, nextLogicalType, options),\r\n };\r\n}\r\n\r\nexport function createColumn(\r\n dialect: RdbmsDialect,\r\n params: {\r\n id: string;\r\n logicalName: string;\r\n /** 생략 시 논리 이름과 동일한 물리 이름으로 생성된다. */\r\n physicalName?: string;\r\n description?: string;\r\n logicalType: LogicalDataType;\r\n defaultValue?: string;\r\n nullable?: boolean;\r\n isPrimaryKey?: boolean;\r\n isForeignKey?: boolean;\r\n referencesPrimaryColumnId?: string;\r\n color?: string;\r\n },\r\n options?: CoreDbMetaOptions,\r\n): ColumnModel {\r\n const physicalName = params.physicalName ?? params.logicalName;\r\n const isPrimaryKey = params.isPrimaryKey ?? false;\r\n const isForeignKey = params.isForeignKey ?? false;\r\n const col: ColumnModel = {\r\n id: params.id,\r\n logicalName: params.logicalName,\r\n physicalName,\r\n description: params.description,\r\n logicalType: params.logicalType,\r\n physicalType: defaultPhysicalType(dialect, params.logicalType, options),\r\n defaultValue: params.defaultValue,\r\n nullable: isPrimaryKey ? false : (params.nullable ?? true),\r\n isPrimaryKey,\r\n isForeignKey,\r\n referencesPrimaryColumnId: params.referencesPrimaryColumnId,\r\n };\r\n if (params.color !== undefined) col.color = params.color;\r\n return col;\r\n}\r\n\r\nexport function createEmptyDesign(\r\n dialect: RdbmsDialect = \"mssql\",\r\n): DesignDocument {\r\n return {\r\n schemaVersion: 1,\r\n model: {\r\n dialect,\r\n tables: [],\r\n relationships: [],\r\n indexes: [],\r\n },\r\n layout: {\r\n nodePositions: {},\r\n },\r\n };\r\n}\r\n\r\nexport function serializeDesign(doc: DesignDocument): string {\r\n return JSON.stringify(doc, null, 2);\r\n}\r\n\r\nexport function parseDesign(\r\n json: string,\r\n options?: CoreDbMetaOptions,\r\n): DesignDocument {\r\n const parsed = JSON.parse(json) as unknown;\r\n return validateDesignDocument(parsed, options);\r\n}\r\n\r\nexport function validateDesignDocument(\r\n input: unknown,\r\n options?: CoreDbMetaOptions,\r\n): DesignDocument {\r\n if (!isObject(input)) {\r\n throw new Error(\"Invalid design document: root must be object\");\r\n }\r\n\r\n if (input.schemaVersion !== 1) {\r\n throw new Error(\"Unsupported schemaVersion\");\r\n }\r\n\r\n if (\r\n !isObject(input.model) ||\r\n !Array.isArray(input.model.tables) ||\r\n !Array.isArray(input.model.relationships) ||\r\n !Array.isArray(input.model.indexes)\r\n ) {\r\n throw new Error(\"Invalid design document: model is malformed\");\r\n }\r\n\r\n const dialects = new Set(\r\n resolveDbMetaAdapter(options)\r\n .listDialects()\r\n .map((d) => d.id),\r\n );\r\n const modelDialect = (input.model as unknown as { dialect?: unknown })\r\n .dialect;\r\n if (\r\n typeof modelDialect !== \"string\" ||\r\n !dialects.has(modelDialect as RdbmsDialect)\r\n ) {\r\n throw new Error(\"Invalid design document: model.dialect is invalid\");\r\n }\r\n\r\n if (!isObject(input.layout) || !isObject(input.layout.nodePositions)) {\r\n throw new Error(\"Invalid design document: layout is malformed\");\r\n }\r\n\r\n const doc = input as unknown as DesignDocument;\r\n migrateLegacyFkLineVisibility(doc.model);\r\n normalizeColumnDefaultValues(doc.model);\r\n return ensureUniqueDesignIds(doc);\r\n}\r\n\r\nexport function roundTripDesign(doc: DesignDocument): DesignDocument {\r\n return parseDesign(serializeDesign(doc));\r\n}\r\n\r\nfunction quoteIdentifier(\r\n dialect: RdbmsDialect,\r\n identifier: string,\r\n options?: CoreDbMetaOptions,\r\n): string {\r\n const quote =\r\n resolveDbMetaAdapter(options).getDdlRules(dialect).quoteIdentifier ??\r\n defaultDdlRules().quoteIdentifier!;\r\n return quote(dialect, identifier);\r\n}\r\n\r\nfunction qualifiedTableName(\r\n table: TableModel,\r\n dialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): string {\r\n const schema = table.schemaName?.trim();\r\n if (dialectSupportsSchema(dialect, options) && schema) {\r\n return `${quoteIdentifier(dialect, schema, options)}.${quoteIdentifier(dialect, table.physicalName, options)}`;\r\n }\r\n return quoteIdentifier(dialect, table.physicalName, options);\r\n}\r\n\r\nfunction quoteSqlString(value: string): string {\r\n return `'${value.replaceAll(\"'\", \"''\")}'`;\r\n}\r\n\r\nfunction toDefaultExpression(\r\n dialect: RdbmsDialect,\r\n col: ColumnModel,\r\n options?: CoreDbMetaOptions,\r\n): string | null {\r\n const handler =\r\n resolveDbMetaAdapter(options).getDdlRules(dialect)\r\n .toDefaultExpression ?? defaultDdlRules().toDefaultExpression!;\r\n return handler(dialect, col);\r\n}\r\n\r\nfunction joinColumnDefs(\r\n table: TableModel,\r\n dialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): string[] {\r\n const defs = table.columns.map((col) => {\r\n const nullable = col.nullable ? \"NULL\" : \"NOT NULL\";\r\n const defaultExpr = toDefaultExpression(dialect, col, options);\r\n const defaultSql = defaultExpr ? ` DEFAULT ${defaultExpr}` : \"\";\r\n return ` ${quoteIdentifier(dialect, col.physicalName, options)} ${col.physicalType}${defaultSql} ${nullable}`;\r\n });\r\n const pkColumns = table.columns\r\n .filter((col) => col.isPrimaryKey)\r\n .map((col) => quoteIdentifier(dialect, col.physicalName, options));\r\n if (pkColumns.length > 0) {\r\n defs.push(` PRIMARY KEY (${pkColumns.join(\", \")})`);\r\n }\r\n return defs;\r\n}\r\n\r\nfunction createTableSql(\r\n table: TableModel,\r\n dialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): string {\r\n const columns = joinColumnDefs(table, dialect, options);\r\n return `CREATE TABLE ${qualifiedTableName(table, dialect, options)} (\\n${columns.join(\",\\n\")}\\n);`;\r\n}\r\n\r\nfunction createRelationshipSql(\r\n rel: RelationshipModel,\r\n model: DesignModel,\r\n dialect: RdbmsDialect,\r\n index: number,\r\n options?: CoreDbMetaOptions,\r\n): string | null {\r\n const sourceTable = model.tables.find(\r\n (table) => table.id === rel.sourceTableId,\r\n );\r\n const targetTable = model.tables.find(\r\n (table) => table.id === rel.targetTableId,\r\n );\r\n if (\r\n !sourceTable ||\r\n !targetTable ||\r\n !rel.sourceColumnId ||\r\n !rel.targetColumnId\r\n ) {\r\n return null;\r\n }\r\n\r\n const sourceColumn = sourceTable.columns.find(\r\n (col) => col.id === rel.sourceColumnId,\r\n );\r\n const targetColumn = targetTable.columns.find(\r\n (col) => col.id === rel.targetColumnId,\r\n );\r\n if (!sourceColumn || !targetColumn) {\r\n return null;\r\n }\r\n\r\n const fkName = `FK_${targetTable.physicalName}_${sourceTable.physicalName}_${index + 1}`;\r\n return [\r\n `ALTER TABLE ${qualifiedTableName(targetTable, dialect, options)}`,\r\n ` ADD CONSTRAINT ${quoteIdentifier(dialect, fkName, options)}`,\r\n ` FOREIGN KEY (${quoteIdentifier(dialect, targetColumn.physicalName, options)})`,\r\n ` REFERENCES ${qualifiedTableName(sourceTable, dialect, options)} (${quoteIdentifier(dialect, sourceColumn.physicalName, options)});`,\r\n ].join(\"\\n\");\r\n}\r\n\r\nfunction createIndexSql(\r\n indexModel: IndexModel,\r\n model: DesignModel,\r\n dialect: RdbmsDialect,\r\n options?: CoreDbMetaOptions,\r\n): string | null {\r\n const table = model.tables.find((item) => item.id === indexModel.tableId);\r\n if (!table || indexModel.columns.length === 0) {\r\n return null;\r\n }\r\n const unique = indexModel.unique ? \"UNIQUE \" : \"\";\r\n const columns = indexModel.columns\r\n .map((col) => quoteIdentifier(dialect, col, options))\r\n .join(\", \");\r\n return `CREATE ${unique}INDEX ${quoteIdentifier(dialect, indexModel.name, options)} ON ${qualifiedTableName(table, dialect, options)} (${columns});`;\r\n}\r\n\r\nfunction buildDdlSql(doc: DesignDocument, options?: CoreDbMetaOptions): string {\r\n const { model } = doc;\r\n const tableSql = model.tables.map((table) =>\r\n createTableSql(table, model.dialect, options),\r\n );\r\n const relSql = model.relationships\r\n .map((rel, index) =>\r\n createRelationshipSql(rel, model, model.dialect, index, options),\r\n )\r\n .filter((item): item is string => Boolean(item));\r\n return [...tableSql, ...relSql].join(\"\\n\\n\");\r\n}\r\n\r\nfunction buildIndexDdlSql(\r\n doc: DesignDocument,\r\n options?: CoreDbMetaOptions,\r\n): string {\r\n const { model } = doc;\r\n const statements = model.indexes\r\n .map((index) => createIndexSql(index, model, model.dialect, options))\r\n .filter((item): item is string => Boolean(item));\r\n return statements.join(\"\\n\\n\");\r\n}\r\n\r\nfunction sliceDocByScope(doc: DesignDocument, scope: DdlScope): DesignDocument {\r\n if (scope.kind === \"all\") return doc;\r\n const selected = new Set(scope.tableIds);\r\n return {\r\n ...doc,\r\n model: {\r\n ...doc.model,\r\n tables: doc.model.tables.filter((t) => selected.has(t.id)),\r\n relationships: doc.model.relationships.filter(\r\n (r) =>\r\n selected.has(r.sourceTableId) &&\r\n selected.has(r.targetTableId),\r\n ),\r\n indexes: doc.model.indexes.filter((i) => selected.has(i.tableId)),\r\n },\r\n };\r\n}\r\n\r\nfunction styleBasedDdlGenerator(\r\n input: DdlGenerateInput,\r\n options?: CoreDbMetaOptions,\r\n): DdlGenerateOutput {\r\n const scoped = sliceDocByScope(input.doc, input.scope);\r\n return {\r\n sql: buildDdlSql(scoped, options),\r\n diagnostics: analyzeDdlDocument(scoped, options),\r\n };\r\n}\r\n\r\nfunction hasBuiltinDialect(\r\n dialectId: RdbmsDialect,\r\n): dialectId is BuiltinRdbmsDialect {\r\n return (BUILTIN_DIALECTS as readonly string[]).includes(dialectId);\r\n}\r\n\r\nfunction getBuiltinDdlGenerator(\r\n dialectId: RdbmsDialect,\r\n _options?: CoreDbMetaOptions,\r\n): DdlGeneratorHook | undefined {\r\n if (!hasBuiltinDialect(dialectId)) return undefined;\r\n return (input) => styleBasedDdlGenerator(input, _options);\r\n}\r\n\r\nfunction invokeDdlGeneratorSync(\r\n generator: DdlGeneratorHook,\r\n input: DdlGenerateInput,\r\n): DdlGenerateOutput {\r\n const result = generator(input);\r\n if (\r\n result &&\r\n typeof (result as Promise<DdlGenerateOutput>).then === \"function\"\r\n ) {\r\n throw new Error(\"Async DDL generator is not supported in sync API\");\r\n }\r\n return result as DdlGenerateOutput;\r\n}\r\n\r\nfunction runDdlGenerator(\r\n doc: DesignDocument,\r\n scope: DdlScope,\r\n options?: CoreDbMetaOptions,\r\n): DdlGenerateOutput {\r\n const input: DdlGenerateInput = {\r\n doc,\r\n dialectId: doc.model.dialect,\r\n scope,\r\n };\r\n const hostGenerator = options?.hostDdlGenerators?.[doc.model.dialect];\r\n const builtinGenerator = getBuiltinDdlGenerator(doc.model.dialect, options);\r\n const fallback = () => styleBasedDdlGenerator(input, options);\r\n const fallbackOnError = options?.fallbackOnHookError ?? true;\r\n\r\n const selectedGenerator = hostGenerator ?? builtinGenerator;\r\n if (!selectedGenerator) return fallback();\r\n try {\r\n return invokeDdlGeneratorSync(selectedGenerator, input);\r\n } catch (error) {\r\n if (!fallbackOnError) throw error;\r\n return fallback();\r\n }\r\n}\r\n\r\n/** DDL/인덱스 분석 공통 심각도 */\r\nexport type DdlDiagnosticSeverity = \"error\" | \"warning\";\r\n\r\n/** 구조화된 DDL 관련 진단(에러·경고) */\r\nexport interface DdlDiagnostic {\r\n severity: DdlDiagnosticSeverity;\r\n code: string;\r\n message: string;\r\n /** 예: relationship:rel1, index:ix1, table:t1 */\r\n context?: string;\r\n}\r\n\r\n/**\r\n * 통일된 한 줄 텍스트 포맷.\r\n * 예: `[WARN][DDL_REL_MISSING_COLUMNS] ... | relationship:rel1`\r\n */\r\nexport function formatDdlDiagnostic(d: DdlDiagnostic): string {\r\n const level = d.severity === \"error\" ? \"ERROR\" : \"WARN\";\r\n const tail = d.context ? ` | ${d.context}` : \"\";\r\n return `[${level}][${d.code}] ${d.message}${tail}`;\r\n}\r\n\r\nexport function formatDdlDiagnostics(diagnostics: DdlDiagnostic[]): string {\r\n return diagnostics.map(formatDdlDiagnostic).join(\"\\n\");\r\n}\r\n\r\n/**\r\n * 모델 전체에 대한 DDL·인덱스 관련 진단(테이블/관계/인덱스).\r\n * 검증 예외(Invalid design document)와는 별도로, 생성 가능 여부와 경고를 나열한다.\r\n */\r\nexport function analyzeDdlDocument(\r\n doc: DesignDocument,\r\n options?: CoreDbMetaOptions,\r\n): DdlDiagnostic[] {\r\n const out: DdlDiagnostic[] = [];\r\n const { model } = doc;\r\n const tableById = new Map(model.tables.map((t) => [t.id, t]));\r\n const physicalTableNames = new Map<string, string[]>();\r\n\r\n for (const table of model.tables) {\r\n const qualifiedName =\r\n dialectSupportsSchema(model.dialect, options) &&\r\n table.schemaName?.trim()\r\n ? `${table.schemaName.trim()}.${table.physicalName}`\r\n : table.physicalName;\r\n const list = physicalTableNames.get(qualifiedName) ?? [];\r\n list.push(table.id);\r\n physicalTableNames.set(qualifiedName, list);\r\n if (table.columns.length === 0) {\r\n out.push({\r\n severity: \"warning\",\r\n code: \"DDL_EMPTY_TABLE\",\r\n message:\r\n \"컬럼이 없는 테이블은 CREATE TABLE 구문이 비어 있거나 무의미할 수 있다.\",\r\n context: `table:${table.id}`,\r\n });\r\n }\r\n }\r\n\r\n for (const [name, ids] of physicalTableNames) {\r\n if (ids.length > 1) {\r\n out.push({\r\n severity: \"warning\",\r\n code: \"DDL_DUPLICATE_TABLE_NAME\",\r\n message: `동일한 물리 테이블명 \"${name}\"이 ${ids.length}개 테이블에 사용되었다.`,\r\n context: `tables:${ids.join(\",\")}`,\r\n });\r\n }\r\n }\r\n\r\n for (const rel of model.relationships) {\r\n const ctx = `relationship:${rel.id}`;\r\n const sourceTable = tableById.get(rel.sourceTableId);\r\n const targetTable = tableById.get(rel.targetTableId);\r\n if (!sourceTable || !targetTable) {\r\n out.push({\r\n severity: \"error\",\r\n code: \"DDL_REL_UNKNOWN_TABLE\",\r\n message:\r\n \"관계의 소스 또는 타겟 테이블을 찾을 수 없어 FK DDL을 생성할 수 없다.\",\r\n context: ctx,\r\n });\r\n continue;\r\n }\r\n if (!rel.sourceColumnId || !rel.targetColumnId) {\r\n out.push({\r\n severity: \"warning\",\r\n code: \"DDL_REL_MISSING_COLUMNS\",\r\n message: \"소스/타겟 컬럼이 지정되지 않아 FK DDL을 생략한다.\",\r\n context: ctx,\r\n });\r\n continue;\r\n }\r\n const sourceColumn = sourceTable.columns.find(\r\n (c) => c.id === rel.sourceColumnId,\r\n );\r\n const targetColumn = targetTable.columns.find(\r\n (c) => c.id === rel.targetColumnId,\r\n );\r\n if (!sourceColumn || !targetColumn) {\r\n out.push({\r\n severity: \"warning\",\r\n code: \"DDL_REL_UNKNOWN_COLUMN\",\r\n message:\r\n \"관계에 지정된 컬럼 id를 테이블에서 찾을 수 없어 FK DDL을 생략한다.\",\r\n context: ctx,\r\n });\r\n }\r\n }\r\n\r\n for (const indexModel of model.indexes) {\r\n const ctx = `index:${indexModel.id}`;\r\n const table = tableById.get(indexModel.tableId);\r\n if (!table) {\r\n out.push({\r\n severity: \"warning\",\r\n code: \"IDX_UNKNOWN_TABLE\",\r\n message:\r\n \"인덱스가 가리키는 테이블을 찾을 수 없어 인덱스 DDL을 생략한다.\",\r\n context: ctx,\r\n });\r\n continue;\r\n }\r\n if (indexModel.columns.length === 0) {\r\n out.push({\r\n severity: \"warning\",\r\n code: \"IDX_EMPTY_COLUMNS\",\r\n message: \"인덱스 컬럼 목록이 비어 있어 인덱스 DDL을 생략한다.\",\r\n context: ctx,\r\n });\r\n continue;\r\n }\r\n for (const colPhys of indexModel.columns) {\r\n if (!table.columns.some((c) => c.physicalName === colPhys)) {\r\n out.push({\r\n severity: \"warning\",\r\n code: \"IDX_UNKNOWN_COLUMN\",\r\n message: `인덱스가 참조하는 물리 컬럼명 \"${colPhys}\"을(를) 테이블 \"${table.physicalName}\"에서 찾을 수 없다.`,\r\n context: ctx,\r\n });\r\n }\r\n }\r\n }\r\n\r\n return out;\r\n}\r\n\r\nexport function generateDdlWithDiagnostics(\r\n doc: DesignDocument,\r\n options?: CoreDbMetaOptions,\r\n): { sql: string; diagnostics: DdlDiagnostic[] } {\r\n const out = runDdlGenerator(doc, { kind: \"all\" }, options);\r\n return {\r\n sql: out.sql,\r\n diagnostics: out.diagnostics ?? analyzeDdlDocument(doc, options),\r\n };\r\n}\r\n\r\nexport function generateIndexDdlWithDiagnostics(\r\n doc: DesignDocument,\r\n options?: CoreDbMetaOptions,\r\n): { sql: string; diagnostics: DdlDiagnostic[] } {\r\n return {\r\n sql: buildIndexDdlSql(doc, options),\r\n diagnostics: analyzeDdlDocument(doc, options),\r\n };\r\n}\r\n\r\nexport function generateDdl(\r\n doc: DesignDocument,\r\n options?: CoreDbMetaOptions,\r\n): string {\r\n return runDdlGenerator(doc, { kind: \"all\" }, options).sql;\r\n}\r\n\r\nexport function generateDdlForSelection(\r\n doc: DesignDocument,\r\n tableIds: string[],\r\n options?: CoreDbMetaOptions,\r\n): { sql: string; diagnostics: DdlDiagnostic[] } {\r\n const out = runDdlGenerator(doc, { kind: \"selected\", tableIds }, options);\r\n const diagnostics =\r\n out.diagnostics ??\r\n analyzeDdlDocument(\r\n sliceDocByScope(doc, { kind: \"selected\", tableIds }),\r\n options,\r\n );\r\n return { sql: out.sql, diagnostics };\r\n}\r\n\r\nexport function generateIndexDdl(\r\n doc: DesignDocument,\r\n options?: CoreDbMetaOptions,\r\n): string {\r\n return buildIndexDdlSql(doc, options);\r\n}\r\n\r\n/** 성능·부하 테스트용: 지정 개수의 빈 테이블과 격자 레이아웃을 생성한다. */\r\nexport function createLargeDesign(\r\n tableCount: number,\r\n dialect: RdbmsDialect = \"postgres\",\r\n): DesignDocument {\r\n const doc = createEmptyDesign(dialect);\r\n const cols = 20;\r\n for (let i = 0; i < tableCount; i++) {\r\n const id = `t-${i}`;\r\n doc.model.tables.push({\r\n id,\r\n logicalName: `엔티티${i}`,\r\n physicalName: `TB_T${i}`,\r\n columns: [\r\n createColumn(dialect, {\r\n id: `${id}-pk`,\r\n logicalName: \"식별자\",\r\n logicalType: \"NUMBER\",\r\n nullable: false,\r\n }),\r\n ],\r\n });\r\n doc.layout.nodePositions[id] = {\r\n x: (i % cols) * 220,\r\n y: Math.floor(i / cols) * 120,\r\n };\r\n }\r\n return doc;\r\n}\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rdbms-erd/core",
3
- "version": "0.1.28",
3
+ "version": "0.1.29",
4
4
  "license": "MIT",
5
5
  "keywords": [
6
6
  "erd",