-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Expand file tree
/
Copy pathdbml.js
More file actions
136 lines (105 loc) · 3.99 KB
/
Copy pathdbml.js
File metadata and controls
136 lines (105 loc) · 3.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import { Parser } from "@dbml/core";
import { arrangeTables } from "../arrangeTables";
import { Cardinality, Constraint } from "../../data/constants";
import { nanoid } from "nanoid";
const parser = new Parser();
export function fromDBML(src) {
const ast = parser.parse(src, "dbmlv2");
const tables = [];
const enums = [];
const relationships = [];
for (const schema of ast.schemas) {
for (const table of schema.tables) {
let parsedTable = {};
parsedTable.id = nanoid();
parsedTable.name = table.name;
parsedTable.comment = table.note ?? "";
parsedTable.color = table.headerColor ?? "#175e7a";
parsedTable.fields = [];
parsedTable.indices = [];
for (const column of table.fields) {
const field = {};
field.id = nanoid();
field.name = column.name;
field.type = extractTypeName(column.type.type_name).toUpperCase();
field.size = column.type.args ?? "";
field.default = column.dbdefault?.value ?? "";
field.check = "";
field.primary = !!column.pk;
field.unique = !!column.pk;
field.notNull = !!column.not_null;
field.increment = !!column.increment;
field.comment = column.note ?? "";
parsedTable.fields.push(field);
}
for (const idx of table.indexes) {
const parsedIndex = {};
parsedIndex.id = idx.id - 1;
parsedIndex.fields = idx.columns.map((x) => x.value);
parsedIndex.name =
idx.name ?? `${parsedTable.name}_index_${parsedIndex.id}`;
parsedIndex.unique = !!idx.unique;
parsedTable.indices.push(parsedIndex);
}
tables.push(parsedTable);
}
for (const ref of schema.refs) {
const startTableName = ref.endpoints[0].tableName;
const endTableName = ref.endpoints[1].tableName;
const startFieldName = ref.endpoints[0].fieldNames[0];
const endFieldName = ref.endpoints[1].fieldNames[0];
const startTable = tables.find((t) => t.name === startTableName);
if (!startTable) continue;
const endTable = tables.find((t) => t.name === endTableName);
if (!endTable) continue;
const endField = endTable.fields.find((f) => f.name === endFieldName);
if (!endField) continue;
const startField = startTable.fields.find(
(f) => f.name === startFieldName,
);
if (!startField) continue;
const relationship = {};
relationship.name =
"fk_" + startTableName + "_" + startFieldName + "_" + endTableName;
relationship.startTableId = startTable.id;
relationship.endTableId = endTable.id;
relationship.endFieldId = endField.id;
relationship.startFieldId = startField.id;
relationship.id = nanoid();
relationship.updateConstraint = ref.onDelete
? ref.onDelete[0].toUpperCase() + ref.onDelete.substring(1)
: Constraint.NONE;
relationship.deleteConstraint = ref.onUpdate
? ref.onUpdate[0].toUpperCase() + ref.onUpdate.substring(1)
: Constraint.NONE;
const startRelation = ref.endpoints[0].relation;
const endRelation = ref.endpoints[1].relation;
if (startRelation === "*" && endRelation === "1") {
relationship.cardinality = Cardinality.MANY_TO_ONE;
}
if (startRelation === "1" && endRelation === "*") {
relationship.cardinality = Cardinality.ONE_TO_MANY;
}
if (startRelation === "1" && endRelation === "1") {
relationship.cardinality = Cardinality.ONE_TO_ONE;
}
relationships.push(relationship);
}
for (const schemaEnum of schema.enums) {
const parsedEnum = {};
parsedEnum.name = schemaEnum.name;
parsedEnum.values = schemaEnum.values.map((x) => x.name);
enums.push(parsedEnum);
}
}
const diagram = { tables, enums, relationships };
arrangeTables(diagram);
return diagram;
}
function extractTypeName(type) {
const match = type.match(/^(\w+)(?:\([^)]*\))?/);
if (match && match[1]) {
return match[1];
}
return type;
}