drizzle-docs-generator 0.2.0 → 0.4.0
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.ja.md +59 -15
- package/README.md +55 -11
- package/dist/adapter/types.d.ts +40 -0
- package/dist/adapter/types.d.ts.map +1 -0
- package/dist/adapter/v0-adapter.d.ts +73 -0
- package/dist/adapter/v0-adapter.d.ts.map +1 -0
- package/dist/adapter/v0-adapter.js +136 -0
- package/dist/adapter/v0-adapter.js.map +1 -0
- package/dist/adapter/v1-adapter.d.ts +40 -0
- package/dist/adapter/v1-adapter.d.ts.map +1 -0
- package/dist/adapter/v1-adapter.js +83 -0
- package/dist/adapter/v1-adapter.js.map +1 -0
- package/dist/cli/index.js +194 -71
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/integration-test-utils.d.ts +19 -0
- package/dist/cli/integration-test-utils.d.ts.map +1 -0
- package/dist/formatter/dbml-builder.d.ts +29 -0
- package/dist/formatter/dbml-builder.d.ts.map +1 -0
- package/dist/formatter/dbml-builder.js +39 -0
- package/dist/formatter/dbml-builder.js.map +1 -0
- package/dist/formatter/dbml.d.ts +81 -0
- package/dist/formatter/dbml.d.ts.map +1 -0
- package/dist/formatter/dbml.js +163 -0
- package/dist/formatter/dbml.js.map +1 -0
- package/dist/formatter/markdown.d.ts +126 -0
- package/dist/formatter/markdown.d.ts.map +1 -0
- package/dist/formatter/markdown.js +235 -0
- package/dist/formatter/markdown.js.map +1 -0
- package/dist/formatter/mermaid.d.ts +102 -0
- package/dist/formatter/mermaid.d.ts.map +1 -0
- package/dist/formatter/mermaid.js +177 -0
- package/dist/formatter/mermaid.js.map +1 -0
- package/dist/formatter/types.d.ts +37 -0
- package/dist/formatter/types.d.ts.map +1 -0
- package/dist/generator/common.d.ts +115 -208
- package/dist/generator/common.d.ts.map +1 -1
- package/dist/generator/common.js +260 -479
- package/dist/generator/common.js.map +1 -1
- package/dist/generator/mysql.js +3 -3
- package/dist/generator/pg.d.ts +8 -7
- package/dist/generator/pg.d.ts.map +1 -1
- package/dist/generator/pg.js +29 -31
- package/dist/generator/pg.js.map +1 -1
- package/dist/generator/sqlite.js +3 -3
- package/dist/index.d.ts +15 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -18
- package/dist/index.js.map +1 -1
- package/dist/test-utils/cli-runner.d.ts +4 -1
- package/dist/test-utils/cli-runner.d.ts.map +1 -1
- package/dist/test-utils/dbml-validator.d.ts +29 -0
- package/dist/test-utils/dbml-validator.d.ts.map +1 -1
- package/dist/types.d.ts +128 -16
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -2
- package/dist/generator/index.d.ts +0 -15
- package/dist/generator/index.d.ts.map +0 -1
- package/dist/parser/index.d.ts +0 -5
- package/dist/parser/index.d.ts.map +0 -1
- package/dist/test-utils/index.d.ts +0 -7
- package/dist/test-utils/index.d.ts.map +0 -1
package/dist/generator/common.js
CHANGED
|
@@ -1,59 +1,26 @@
|
|
|
1
|
-
import { is as
|
|
2
|
-
import { PgTable as
|
|
3
|
-
import { MySqlTable as
|
|
4
|
-
import { SQLiteTable as
|
|
5
|
-
import { mkdirSync as
|
|
6
|
-
import { resolve as
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
* Increase the indentation level by one
|
|
14
|
-
* @returns This instance for method chaining
|
|
15
|
-
*/
|
|
16
|
-
indent() {
|
|
17
|
-
return this.indentLevel++, this;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Decrease the indentation level by one (minimum 0)
|
|
21
|
-
* @returns This instance for method chaining
|
|
22
|
-
*/
|
|
23
|
-
dedent() {
|
|
24
|
-
return this.indentLevel = Math.max(0, this.indentLevel - 1), this;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Add a line with the current indentation level
|
|
28
|
-
* @param content - The content to add (empty string adds a blank line)
|
|
29
|
-
* @returns This instance for method chaining
|
|
30
|
-
*/
|
|
31
|
-
line(e = "") {
|
|
32
|
-
const t = " ".repeat(this.indentLevel);
|
|
33
|
-
return this.lines.push(e ? `${t}${e}` : ""), this;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Build the final DBML string from all added lines
|
|
37
|
-
* @returns The complete DBML content as a string
|
|
38
|
-
*/
|
|
39
|
-
build() {
|
|
40
|
-
return this.lines.join(`
|
|
41
|
-
`);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
class B {
|
|
1
|
+
import { is as r, Relation as h, getTableName as m, getTableColumns as y } from "drizzle-orm";
|
|
2
|
+
import { PgTable as c, getTableConfig as b } from "drizzle-orm/pg-core";
|
|
3
|
+
import { MySqlTable as f, getTableConfig as d } from "drizzle-orm/mysql-core";
|
|
4
|
+
import { SQLiteTable as u, getTableConfig as T } from "drizzle-orm/sqlite-core";
|
|
5
|
+
import { mkdirSync as C, writeFileSync as D } from "node:fs";
|
|
6
|
+
import { resolve as R, dirname as q } from "node:path";
|
|
7
|
+
import { DbmlFormatter as j } from "../formatter/dbml.js";
|
|
8
|
+
import { extractComments as v } from "../parser/comments.js";
|
|
9
|
+
import { extractRelations as V } from "../parser/relations.js";
|
|
10
|
+
import { V0RelationAdapter as x } from "../adapter/v0-adapter.js";
|
|
11
|
+
import { V1RelationAdapter as K } from "../adapter/v1-adapter.js";
|
|
12
|
+
class N {
|
|
45
13
|
schema;
|
|
46
|
-
relational;
|
|
47
14
|
generatedRefs = [];
|
|
48
15
|
comments;
|
|
49
16
|
parsedRelations;
|
|
50
17
|
source;
|
|
51
18
|
/**
|
|
52
19
|
* Create a new generator instance
|
|
53
|
-
* @param options - Configuration options including schema,
|
|
20
|
+
* @param options - Configuration options including schema, source code, and comments
|
|
54
21
|
*/
|
|
55
22
|
constructor(e) {
|
|
56
|
-
this.schema = e.schema, this.
|
|
23
|
+
this.schema = e.schema, this.source = e.source, e.comments ? this.comments = e.comments : this.source && (this.comments = v(this.source)), this.source && (this.parsedRelations = V(this.source));
|
|
57
24
|
}
|
|
58
25
|
/**
|
|
59
26
|
* Generate complete DBML output from the schema
|
|
@@ -66,13 +33,8 @@ class B {
|
|
|
66
33
|
* @returns The complete DBML string
|
|
67
34
|
*/
|
|
68
35
|
generate() {
|
|
69
|
-
const e =
|
|
70
|
-
|
|
71
|
-
this.generateTable(e, o), e.line();
|
|
72
|
-
this.relational && (s.length > 0 ? this.generateRelationalRefsFromV1(s) : (n.length > 0 || this.parsedRelations) && this.generateRelationalRefsFromV0());
|
|
73
|
-
for (const o of this.generatedRefs)
|
|
74
|
-
this.generateRef(e, o);
|
|
75
|
-
return e.build().trim();
|
|
36
|
+
const e = this.toIntermediateSchema();
|
|
37
|
+
return new j().format(e);
|
|
76
38
|
}
|
|
77
39
|
/**
|
|
78
40
|
* Get all tables from schema
|
|
@@ -98,32 +60,7 @@ class B {
|
|
|
98
60
|
* @returns True if value is a Drizzle table
|
|
99
61
|
*/
|
|
100
62
|
isTable(e) {
|
|
101
|
-
return
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Get all v0 relations from schema (legacy relations() API)
|
|
105
|
-
*
|
|
106
|
-
* Extracts legacy relations defined using the old relations() API.
|
|
107
|
-
* These are identified by having 'table' and 'config' properties.
|
|
108
|
-
*
|
|
109
|
-
* @returns Array of legacy relation objects
|
|
110
|
-
*/
|
|
111
|
-
getV0Relations() {
|
|
112
|
-
const e = [];
|
|
113
|
-
for (const t of Object.values(this.schema))
|
|
114
|
-
this.isV0Relations(t) && e.push(t);
|
|
115
|
-
return e;
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Check if a value is a Drizzle v0 relations object (from relations())
|
|
119
|
-
*
|
|
120
|
-
* Validates the legacy relations() format by checking for 'table' and 'config' properties.
|
|
121
|
-
*
|
|
122
|
-
* @param value - The value to check
|
|
123
|
-
* @returns True if value is a legacy relations object
|
|
124
|
-
*/
|
|
125
|
-
isV0Relations(e) {
|
|
126
|
-
return typeof e != "object" || e === null ? !1 : "table" in e && "config" in e && typeof e.config == "object";
|
|
63
|
+
return r(e, c) || r(e, f) || r(e, u);
|
|
127
64
|
}
|
|
128
65
|
/**
|
|
129
66
|
* Check if a value is a v1 relation entry (from defineRelations())
|
|
@@ -140,8 +77,8 @@ class B {
|
|
|
140
77
|
const t = e;
|
|
141
78
|
if (!("table" in t) || !("name" in t) || typeof t.name != "string" || !("relations" in t) || typeof t.relations != "object" || t.relations === null)
|
|
142
79
|
return !1;
|
|
143
|
-
const n = t.relations,
|
|
144
|
-
return
|
|
80
|
+
const n = t.relations, o = Object.values(n);
|
|
81
|
+
return o.length > 0 ? o.some((s) => r(s, h)) : this.isTable(t.table);
|
|
145
82
|
}
|
|
146
83
|
/**
|
|
147
84
|
* Get all v1 relation entries from schema (defineRelations() API)
|
|
@@ -174,26 +111,7 @@ class B {
|
|
|
174
111
|
if (typeof e != "object" || e === null || Array.isArray(e))
|
|
175
112
|
return !1;
|
|
176
113
|
const n = Object.values(e);
|
|
177
|
-
return n.length > 0 && n.every((
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Generate a table definition in DBML format
|
|
181
|
-
*
|
|
182
|
-
* Creates the complete table definition including columns, indexes, constraints,
|
|
183
|
-
* and table-level comments. Also collects foreign keys if not in relational mode.
|
|
184
|
-
*
|
|
185
|
-
* @param dbml - The DBML builder to add the table to
|
|
186
|
-
* @param table - The Drizzle table to generate
|
|
187
|
-
*/
|
|
188
|
-
generateTable(e, t) {
|
|
189
|
-
const n = g(t), s = d(t), o = this.dialectConfig.escapeName(n);
|
|
190
|
-
e.line(`Table ${o} {`), e.indent();
|
|
191
|
-
for (const a of Object.values(s))
|
|
192
|
-
this.generateColumn(e, a, n);
|
|
193
|
-
const i = this.getTableConfig(t);
|
|
194
|
-
i && this.generateIndexesBlock(e, i);
|
|
195
|
-
const r = this.comments?.tables[n]?.comment;
|
|
196
|
-
r && (e.line(), e.line(`Note: '${$(r)}'`)), e.dedent(), e.line("}"), !this.relational && i && i.foreignKeys.length > 0 && this.collectForeignKeysFromConfig(n, i.foreignKeys);
|
|
114
|
+
return n.length > 0 && n.every((o) => this.isV1RelationEntry(o));
|
|
197
115
|
}
|
|
198
116
|
/**
|
|
199
117
|
* Get table configuration from a Drizzle table
|
|
@@ -205,85 +123,51 @@ class B {
|
|
|
205
123
|
* @returns Table configuration or undefined if dialect is not supported
|
|
206
124
|
*/
|
|
207
125
|
getTableConfig(e) {
|
|
208
|
-
if (
|
|
209
|
-
const t =
|
|
210
|
-
return
|
|
211
|
-
indexes: t.indexes || [],
|
|
212
|
-
primaryKeys: t.primaryKeys || [],
|
|
213
|
-
uniqueConstraints: t.uniqueConstraints || [],
|
|
214
|
-
foreignKeys: t.foreignKeys || []
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
if (m(e, T)) {
|
|
218
|
-
const t = N(e);
|
|
219
|
-
return {
|
|
220
|
-
indexes: t.indexes || [],
|
|
221
|
-
primaryKeys: t.primaryKeys || [],
|
|
222
|
-
uniqueConstraints: t.uniqueConstraints || [],
|
|
223
|
-
foreignKeys: t.foreignKeys || []
|
|
224
|
-
};
|
|
126
|
+
if (r(e, c)) {
|
|
127
|
+
const t = b(e);
|
|
128
|
+
return this.mapTableConfig(t);
|
|
225
129
|
}
|
|
226
|
-
if (
|
|
227
|
-
const t =
|
|
228
|
-
return
|
|
229
|
-
indexes: t.indexes || [],
|
|
230
|
-
primaryKeys: t.primaryKeys || [],
|
|
231
|
-
uniqueConstraints: t.uniqueConstraints || [],
|
|
232
|
-
foreignKeys: t.foreignKeys || []
|
|
233
|
-
};
|
|
130
|
+
if (r(e, f)) {
|
|
131
|
+
const t = d(e);
|
|
132
|
+
return this.mapTableConfig(t);
|
|
234
133
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
*
|
|
239
|
-
* Creates a column line with type and attributes (primary key, not null, unique, etc.)
|
|
240
|
-
* and includes column-level comments if available.
|
|
241
|
-
*
|
|
242
|
-
* @param dbml - The DBML builder to add the column to
|
|
243
|
-
* @param column - The Drizzle column to generate
|
|
244
|
-
* @param tableName - Optional table name for looking up comments
|
|
245
|
-
*/
|
|
246
|
-
generateColumn(e, t, n) {
|
|
247
|
-
const s = this.dialectConfig.escapeName(t.name), o = this.getColumnType(t), i = this.getColumnAttributes(t, n), r = this.formatAttributes(i);
|
|
248
|
-
r ? e.line(`${s} ${o} [${r}]`) : e.line(`${s} ${o}`);
|
|
249
|
-
}
|
|
250
|
-
/**
|
|
251
|
-
* Get the SQL type for a column
|
|
252
|
-
*
|
|
253
|
-
* @param column - The column to get the SQL type from
|
|
254
|
-
* @returns The SQL type string (e.g., "varchar", "integer")
|
|
255
|
-
*/
|
|
256
|
-
getColumnType(e) {
|
|
257
|
-
return e.getSQLType();
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* Get column attributes for DBML
|
|
261
|
-
*
|
|
262
|
-
* Extracts attributes like primary key, not null, unique, increment, default value,
|
|
263
|
-
* and note from the column. Uses column metadata and comments if available.
|
|
264
|
-
*
|
|
265
|
-
* @param column - The column to get attributes from
|
|
266
|
-
* @param tableName - Optional table name for looking up comments
|
|
267
|
-
* @returns Array of attribute strings for DBML format
|
|
268
|
-
*/
|
|
269
|
-
getColumnAttributes(e, t) {
|
|
270
|
-
const n = [];
|
|
271
|
-
e.primary && n.push("primary key"), e.notNull && n.push("not null"), e.isUnique && n.push("unique"), this.dialectConfig.isIncrement(e) && n.push("increment");
|
|
272
|
-
const s = this.getDefaultValue(e);
|
|
273
|
-
if (s !== void 0 && n.push(`default: ${s}`), t) {
|
|
274
|
-
const o = this.comments?.tables[t]?.columns[e.name]?.comment;
|
|
275
|
-
o && n.push(`note: '${$(o)}'`);
|
|
134
|
+
if (r(e, u)) {
|
|
135
|
+
const t = T(e);
|
|
136
|
+
return this.mapTableConfig(t);
|
|
276
137
|
}
|
|
277
|
-
return n;
|
|
278
138
|
}
|
|
279
139
|
/**
|
|
280
|
-
*
|
|
140
|
+
* Map Drizzle's internal table config to our typed TableConfig
|
|
281
141
|
*
|
|
282
|
-
*
|
|
283
|
-
*
|
|
142
|
+
* Note: Drizzle ORM's columns type is `SQL<unknown> | IndexedColumn` union,
|
|
143
|
+
* so we use `{ name?: string }` and cast to access the name property.
|
|
144
|
+
* This is unavoidable due to Drizzle's internal type structure.
|
|
284
145
|
*/
|
|
285
|
-
|
|
286
|
-
return
|
|
146
|
+
mapTableConfig(e) {
|
|
147
|
+
return {
|
|
148
|
+
indexes: (e.indexes || []).map((t) => ({
|
|
149
|
+
config: {
|
|
150
|
+
columns: t.config.columns.filter((n) => typeof n.name == "string").map((n) => ({ name: n.name })),
|
|
151
|
+
name: t.config.name,
|
|
152
|
+
unique: t.config.unique ?? !1,
|
|
153
|
+
using: t.config.using
|
|
154
|
+
}
|
|
155
|
+
})),
|
|
156
|
+
primaryKeys: (e.primaryKeys || []).map((t) => ({
|
|
157
|
+
columns: t.columns.filter((n) => typeof n.name == "string").map((n) => ({ name: n.name })),
|
|
158
|
+
name: t.name
|
|
159
|
+
})),
|
|
160
|
+
uniqueConstraints: (e.uniqueConstraints || []).map((t) => ({
|
|
161
|
+
columns: t.columns.filter((n) => typeof n.name == "string").map((n) => ({ name: n.name })),
|
|
162
|
+
name: t.name
|
|
163
|
+
})),
|
|
164
|
+
foreignKeys: (e.foreignKeys || []).map((t) => ({
|
|
165
|
+
reference: t.reference,
|
|
166
|
+
name: t.name,
|
|
167
|
+
onDelete: t.onDelete,
|
|
168
|
+
onUpdate: t.onUpdate
|
|
169
|
+
}))
|
|
170
|
+
};
|
|
287
171
|
}
|
|
288
172
|
/**
|
|
289
173
|
* Get the default value for a column
|
|
@@ -303,58 +187,19 @@ class B {
|
|
|
303
187
|
if (t !== void 0) {
|
|
304
188
|
if (typeof t == "object" && t !== null) {
|
|
305
189
|
if ("queryChunks" in t) {
|
|
306
|
-
const n = t.queryChunks,
|
|
307
|
-
for (const
|
|
308
|
-
typeof
|
|
309
|
-
return
|
|
190
|
+
const n = t.queryChunks, o = [];
|
|
191
|
+
for (const s of n)
|
|
192
|
+
typeof s == "string" ? o.push(s) : typeof s == "object" && s !== null && "value" in s && o.push(String(s.value));
|
|
193
|
+
return o.join("");
|
|
310
194
|
}
|
|
311
|
-
return "sql" in t ?
|
|
195
|
+
return "sql" in t ? t.sql : JSON.stringify(t);
|
|
312
196
|
}
|
|
313
197
|
if (typeof t == "string")
|
|
314
|
-
return `'${t.replace(/'/g, "
|
|
198
|
+
return `'${t.replace(/'/g, "''")}'`;
|
|
315
199
|
if (typeof t == "number" || typeof t == "boolean")
|
|
316
200
|
return String(t);
|
|
317
201
|
}
|
|
318
202
|
}
|
|
319
|
-
/**
|
|
320
|
-
* Generate indexes block from table configuration
|
|
321
|
-
*
|
|
322
|
-
* Creates the indexes block containing primary keys, unique constraints,
|
|
323
|
-
* and regular indexes with their respective attributes.
|
|
324
|
-
*
|
|
325
|
-
* @param dbml - The DBML builder to add the indexes block to
|
|
326
|
-
* @param tableConfig - The table configuration containing index information
|
|
327
|
-
*/
|
|
328
|
-
generateIndexesBlock(e, t) {
|
|
329
|
-
const { indexes: n, primaryKeys: s, uniqueConstraints: o } = t;
|
|
330
|
-
if (!(n.length === 0 && s.length === 0 && o.length === 0)) {
|
|
331
|
-
e.line(), e.line("indexes {"), e.indent();
|
|
332
|
-
for (const i of s) {
|
|
333
|
-
const r = this.getPrimaryKeyColumns(i);
|
|
334
|
-
if (r.length > 0) {
|
|
335
|
-
const a = r.map((l) => this.dialectConfig.escapeName(l)).join(", ");
|
|
336
|
-
e.line(`(${a}) [pk]`);
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
for (const i of o) {
|
|
340
|
-
const r = this.getUniqueConstraintColumns(i);
|
|
341
|
-
if (r.length > 0) {
|
|
342
|
-
const a = r.map((l) => this.dialectConfig.escapeName(l)).join(", ");
|
|
343
|
-
e.line(`(${a}) [unique]`);
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
for (const i of n) {
|
|
347
|
-
const r = this.getIndexColumns(i);
|
|
348
|
-
if (r.length > 0) {
|
|
349
|
-
const a = r.map((h) => this.dialectConfig.escapeName(h)).join(", "), l = [];
|
|
350
|
-
this.isUniqueIndex(i) && l.push("unique");
|
|
351
|
-
const c = l.length > 0 ? ` [${l.join(", ")}]` : "";
|
|
352
|
-
e.line(`(${a})${c}`);
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
e.dedent(), e.line("}");
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
203
|
/**
|
|
359
204
|
* Collect foreign keys from table configuration
|
|
360
205
|
*
|
|
@@ -366,8 +211,8 @@ class B {
|
|
|
366
211
|
*/
|
|
367
212
|
collectForeignKeysFromConfig(e, t) {
|
|
368
213
|
for (const n of t) {
|
|
369
|
-
const
|
|
370
|
-
|
|
214
|
+
const o = this.parseForeignKey(e, n);
|
|
215
|
+
this.generatedRefs.push(o);
|
|
371
216
|
}
|
|
372
217
|
}
|
|
373
218
|
/**
|
|
@@ -378,322 +223,258 @@ class B {
|
|
|
378
223
|
*
|
|
379
224
|
* @param tableName - The name of the source table
|
|
380
225
|
* @param fk - The foreign key definition to parse
|
|
381
|
-
* @returns GeneratedRef object
|
|
226
|
+
* @returns GeneratedRef object
|
|
382
227
|
*/
|
|
383
228
|
parseForeignKey(e, t) {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
};
|
|
395
|
-
} catch {
|
|
396
|
-
return;
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
/**
|
|
400
|
-
* Get a mapping from variable names to table names in the schema
|
|
401
|
-
*
|
|
402
|
-
* Creates a map from TypeScript variable names (e.g., "usersTable") to
|
|
403
|
-
* actual database table names (e.g., "users").
|
|
404
|
-
*
|
|
405
|
-
* @returns Map of variable names to table names
|
|
406
|
-
*/
|
|
407
|
-
getTableNameMapping() {
|
|
408
|
-
const e = /* @__PURE__ */ new Map();
|
|
409
|
-
for (const [t, n] of Object.entries(this.schema))
|
|
410
|
-
if (this.isTable(n)) {
|
|
411
|
-
const s = g(n);
|
|
412
|
-
e.set(t, s);
|
|
413
|
-
}
|
|
414
|
-
return e;
|
|
229
|
+
const n = t.reference(), o = n.columns.map((a) => a.name), s = n.foreignColumns.map((a) => a.name), i = m(n.foreignTable);
|
|
230
|
+
return {
|
|
231
|
+
fromTable: e,
|
|
232
|
+
fromColumns: o,
|
|
233
|
+
toTable: i,
|
|
234
|
+
toColumns: s,
|
|
235
|
+
type: ">",
|
|
236
|
+
onDelete: t.onDelete,
|
|
237
|
+
onUpdate: t.onUpdate
|
|
238
|
+
};
|
|
415
239
|
}
|
|
416
240
|
/**
|
|
417
|
-
*
|
|
241
|
+
* Detect if relation definitions are present in the schema
|
|
418
242
|
*
|
|
419
|
-
*
|
|
420
|
-
*
|
|
243
|
+
* Checks for both v1 (defineRelations()) and v0 (relations()) API usage.
|
|
244
|
+
* Returns true if any relation definitions are found.
|
|
421
245
|
*
|
|
422
|
-
* @
|
|
423
|
-
* @returns Map of property names to column names
|
|
246
|
+
* @returns True if relations are defined, false otherwise
|
|
424
247
|
*/
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
if (n && this.isTable(n)) {
|
|
428
|
-
const s = d(n);
|
|
429
|
-
for (const [o, i] of Object.entries(s))
|
|
430
|
-
t.set(o, i.name);
|
|
431
|
-
}
|
|
432
|
-
return t;
|
|
248
|
+
hasRelationDefinitions() {
|
|
249
|
+
return !!(this.getV1RelationEntries().length > 0 || this.parsedRelations && this.parsedRelations.relations.length > 0);
|
|
433
250
|
}
|
|
434
251
|
/**
|
|
435
|
-
*
|
|
252
|
+
* Create the appropriate relation adapter based on schema contents
|
|
436
253
|
*
|
|
437
|
-
*
|
|
438
|
-
*
|
|
254
|
+
* Detects whether v1 or v0 relations are present and returns the
|
|
255
|
+
* corresponding adapter implementation.
|
|
439
256
|
*
|
|
440
|
-
* @
|
|
441
|
-
* @param targetTable - The target table variable name
|
|
442
|
-
* @param sourceFields - The source table's field names
|
|
443
|
-
* @param targetReferences - The target table's reference column names
|
|
444
|
-
* @returns True if a reverse one() relation exists
|
|
257
|
+
* @returns RelationAdapter instance (V1RelationAdapter or V0RelationAdapter)
|
|
445
258
|
*/
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
if (o.type === "one" && o.sourceTable === t && o.targetTable === e && o.fields.length > 0 && o.references.length > 0) {
|
|
450
|
-
const i = o.fields, r = o.references;
|
|
451
|
-
if (this.arraysEqual(i, s) && this.arraysEqual(r, n))
|
|
452
|
-
return !0;
|
|
453
|
-
}
|
|
454
|
-
return !1;
|
|
259
|
+
createRelationAdapter() {
|
|
260
|
+
const e = this.getV1RelationEntries();
|
|
261
|
+
return e.length > 0 ? new K(e) : new x(this.schema, this.parsedRelations);
|
|
455
262
|
}
|
|
456
263
|
/**
|
|
457
|
-
*
|
|
264
|
+
* Convert a UnifiedRelation to a RelationDefinition
|
|
458
265
|
*
|
|
459
|
-
*
|
|
460
|
-
*
|
|
461
|
-
* @returns True if arrays have same length and same elements in order
|
|
462
|
-
*/
|
|
463
|
-
arraysEqual(e, t) {
|
|
464
|
-
return e.length !== t.length ? !1 : e.every((n, s) => n === t[s]);
|
|
465
|
-
}
|
|
466
|
-
/**
|
|
467
|
-
* Generate references from v0 relations() API
|
|
266
|
+
* Maps the unified relation format from adapters to the intermediate
|
|
267
|
+
* schema's RelationDefinition format.
|
|
468
268
|
*
|
|
469
|
-
*
|
|
470
|
-
*
|
|
471
|
-
*
|
|
472
|
-
* Detects one-to-one relationships when bidirectional one() relations exist.
|
|
269
|
+
* @param unified - The unified relation from adapter
|
|
270
|
+
* @returns RelationDefinition for intermediate schema
|
|
473
271
|
*/
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
const i = this.getColumnNameMapping(n.sourceTable), r = this.getColumnNameMapping(n.targetTable), a = n.fields.map(
|
|
485
|
-
(u) => i.get(u) || u
|
|
486
|
-
), l = n.references.map((u) => r.get(u) || u), c = `${s}.${a.join(",")}-${o}.${l.join(",")}`, h = `${o}.${l.join(",")}-${s}.${a.join(",")}`;
|
|
487
|
-
if (t.has(c) || t.has(h))
|
|
488
|
-
continue;
|
|
489
|
-
t.add(c);
|
|
490
|
-
const f = this.hasReverseOneRelation(
|
|
491
|
-
n.sourceTable,
|
|
492
|
-
n.targetTable,
|
|
493
|
-
n.fields,
|
|
494
|
-
n.references
|
|
495
|
-
), p = {
|
|
496
|
-
fromTable: s,
|
|
497
|
-
fromColumns: a,
|
|
498
|
-
toTable: o,
|
|
499
|
-
toColumns: l,
|
|
500
|
-
type: f ? "-" : ">"
|
|
501
|
-
};
|
|
502
|
-
this.generatedRefs.push(p);
|
|
503
|
-
}
|
|
272
|
+
unifiedRelationToDefinition(e) {
|
|
273
|
+
return {
|
|
274
|
+
fromTable: e.sourceTable,
|
|
275
|
+
fromColumns: e.sourceColumns,
|
|
276
|
+
toTable: e.targetTable,
|
|
277
|
+
toColumns: e.targetColumns,
|
|
278
|
+
type: e.relationType,
|
|
279
|
+
onDelete: e.onDelete,
|
|
280
|
+
onUpdate: e.onUpdate
|
|
281
|
+
};
|
|
504
282
|
}
|
|
505
283
|
/**
|
|
506
|
-
*
|
|
284
|
+
* Convert the Drizzle schema to an intermediate schema representation
|
|
507
285
|
*
|
|
508
|
-
*
|
|
509
|
-
*
|
|
510
|
-
* DBML Ref lines. Detects one-to-one relationships with bidirectional checks.
|
|
286
|
+
* Creates a database-agnostic intermediate representation that can be
|
|
287
|
+
* used to generate various output formats (DBML, Markdown, JSON, etc.)
|
|
511
288
|
*
|
|
512
|
-
* @
|
|
289
|
+
* @returns The intermediate schema representation
|
|
513
290
|
*/
|
|
514
|
-
|
|
515
|
-
const t =
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
const
|
|
525
|
-
|
|
526
|
-
continue;
|
|
527
|
-
t.add(c);
|
|
528
|
-
const f = this.hasV1ReverseOneRelation(
|
|
529
|
-
e,
|
|
530
|
-
l,
|
|
531
|
-
s,
|
|
532
|
-
a,
|
|
533
|
-
r
|
|
534
|
-
), p = {
|
|
535
|
-
fromTable: s,
|
|
536
|
-
fromColumns: r,
|
|
537
|
-
toTable: l,
|
|
538
|
-
toColumns: a,
|
|
539
|
-
type: f ? "-" : ">"
|
|
540
|
-
};
|
|
541
|
-
this.generatedRefs.push(p);
|
|
291
|
+
toIntermediateSchema() {
|
|
292
|
+
const e = this.getTables(), t = this.getDatabaseType(e[0]), n = e.map(
|
|
293
|
+
(i) => this.tableToDefinition(i)
|
|
294
|
+
);
|
|
295
|
+
let o = [];
|
|
296
|
+
if (this.hasRelationDefinitions())
|
|
297
|
+
o = this.createRelationAdapter().extract().map((l) => this.unifiedRelationToDefinition(l));
|
|
298
|
+
else {
|
|
299
|
+
this.generatedRefs = [];
|
|
300
|
+
for (const i of e) {
|
|
301
|
+
const a = m(i), l = this.getTableConfig(i);
|
|
302
|
+
l && l.foreignKeys.length > 0 && this.collectForeignKeysFromConfig(a, l.foreignKeys);
|
|
542
303
|
}
|
|
304
|
+
o = this.generatedRefs.map((i) => this.refToRelationDefinition(i));
|
|
543
305
|
}
|
|
306
|
+
const s = this.collectEnumDefinitions();
|
|
307
|
+
return {
|
|
308
|
+
databaseType: t,
|
|
309
|
+
tables: n,
|
|
310
|
+
relations: o,
|
|
311
|
+
enums: s
|
|
312
|
+
};
|
|
544
313
|
}
|
|
545
314
|
/**
|
|
546
|
-
*
|
|
315
|
+
* Determine the database type from a Drizzle table
|
|
547
316
|
*
|
|
548
|
-
*
|
|
549
|
-
*
|
|
550
|
-
*
|
|
551
|
-
* @param entries - All v1 relation entries
|
|
552
|
-
* @param fromTableName - The table to search for reverse relation
|
|
553
|
-
* @param toTableName - The expected target table of the reverse relation
|
|
554
|
-
* @param fromColumns - The expected source columns of the reverse relation
|
|
555
|
-
* @param toColumns - The expected target columns of the reverse relation
|
|
556
|
-
* @returns True if a matching reverse One relation exists
|
|
317
|
+
* @param table - The table to check (can be undefined for empty schemas)
|
|
318
|
+
* @returns The database type
|
|
557
319
|
*/
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
if (!i)
|
|
561
|
-
return !1;
|
|
562
|
-
for (const r of Object.values(i.relations)) {
|
|
563
|
-
if (!m(r, b))
|
|
564
|
-
continue;
|
|
565
|
-
const a = r;
|
|
566
|
-
if (g(a.targetTable) !== n)
|
|
567
|
-
continue;
|
|
568
|
-
const c = a.sourceColumns.map((f) => f.name), h = a.targetColumns.map((f) => f.name);
|
|
569
|
-
if (c.length === s.length && h.length === o.length && c.every((f, p) => f === s[p]) && h.every((f, p) => f === o[p]))
|
|
570
|
-
return !0;
|
|
571
|
-
}
|
|
572
|
-
return !1;
|
|
320
|
+
getDatabaseType(e) {
|
|
321
|
+
return !e || r(e, c) ? "postgresql" : r(e, f) ? "mysql" : r(e, u) ? "sqlite" : "postgresql";
|
|
573
322
|
}
|
|
574
323
|
/**
|
|
575
|
-
*
|
|
576
|
-
*
|
|
577
|
-
* Creates a consistent key by sorting table names alphabetically.
|
|
324
|
+
* Convert a Drizzle table to a TableDefinition
|
|
578
325
|
*
|
|
579
|
-
* @param
|
|
580
|
-
* @
|
|
581
|
-
* @returns A unique key string for the relation
|
|
326
|
+
* @param table - The Drizzle table to convert
|
|
327
|
+
* @returns The table definition
|
|
582
328
|
*/
|
|
583
|
-
|
|
584
|
-
const
|
|
585
|
-
|
|
329
|
+
tableToDefinition(e) {
|
|
330
|
+
const t = m(e), n = y(e), o = this.getTableConfig(e), s = Object.values(n).map(
|
|
331
|
+
(g) => this.columnToDefinition(g, t)
|
|
332
|
+
), i = this.extractIndexDefinitions(o), a = this.extractConstraintDefinitions(o), l = this.comments?.tables[t]?.comment;
|
|
333
|
+
return {
|
|
334
|
+
name: t,
|
|
335
|
+
comment: l,
|
|
336
|
+
columns: s,
|
|
337
|
+
indexes: i,
|
|
338
|
+
constraints: a
|
|
339
|
+
};
|
|
586
340
|
}
|
|
587
341
|
/**
|
|
588
|
-
*
|
|
342
|
+
* Convert a Drizzle column to a ColumnDefinition
|
|
589
343
|
*
|
|
590
|
-
*
|
|
591
|
-
*
|
|
592
|
-
*
|
|
593
|
-
* @param tableName - The source table name
|
|
594
|
-
* @param relation - The relation object to parse
|
|
595
|
-
* @returns GeneratedRef object or undefined if parsing fails
|
|
344
|
+
* @param column - The Drizzle column to convert
|
|
345
|
+
* @param tableName - The name of the table containing the column
|
|
346
|
+
* @returns The column definition
|
|
596
347
|
*/
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
fromColumns: r,
|
|
610
|
-
toTable: s,
|
|
611
|
-
toColumns: a,
|
|
612
|
-
type: l
|
|
613
|
-
};
|
|
614
|
-
} catch {
|
|
615
|
-
return;
|
|
616
|
-
}
|
|
348
|
+
columnToDefinition(e, t) {
|
|
349
|
+
const n = this.comments?.tables[t]?.columns[e.name]?.comment, o = this.getDefaultValue(e);
|
|
350
|
+
return {
|
|
351
|
+
name: e.name,
|
|
352
|
+
type: e.getSQLType(),
|
|
353
|
+
nullable: !e.notNull,
|
|
354
|
+
defaultValue: o,
|
|
355
|
+
primaryKey: e.primary,
|
|
356
|
+
unique: e.isUnique,
|
|
357
|
+
autoIncrement: this.dialectConfig.isIncrement(e) || void 0,
|
|
358
|
+
comment: n
|
|
359
|
+
};
|
|
617
360
|
}
|
|
618
361
|
/**
|
|
619
|
-
*
|
|
362
|
+
* Extract index definitions from table config
|
|
620
363
|
*
|
|
621
|
-
*
|
|
622
|
-
*
|
|
623
|
-
*
|
|
624
|
-
* @param dbml - The DBML builder to add the reference to
|
|
625
|
-
* @param ref - The reference definition to generate
|
|
626
|
-
*/
|
|
627
|
-
generateRef(e, t) {
|
|
628
|
-
const n = `${this.dialectConfig.escapeName(t.fromTable)}.${t.fromColumns.map((r) => this.dialectConfig.escapeName(r)).join(", ")}`, s = `${this.dialectConfig.escapeName(t.toTable)}.${t.toColumns.map((r) => this.dialectConfig.escapeName(r)).join(", ")}`;
|
|
629
|
-
let o = `Ref: ${n} ${t.type} ${s}`;
|
|
630
|
-
const i = [];
|
|
631
|
-
t.onDelete && t.onDelete !== "no action" && i.push(`delete: ${t.onDelete}`), t.onUpdate && t.onUpdate !== "no action" && i.push(`update: ${t.onUpdate}`), i.length > 0 && (o += ` [${i.join(", ")}]`), e.line(o);
|
|
632
|
-
}
|
|
633
|
-
// Helper methods for extracting column information from constraints
|
|
634
|
-
/**
|
|
635
|
-
* Get column names from an index definition
|
|
636
|
-
*
|
|
637
|
-
* @param idx - The index definition to extract columns from
|
|
638
|
-
* @returns Array of column names in the index
|
|
364
|
+
* @param tableConfig - The table configuration
|
|
365
|
+
* @returns Array of index definitions
|
|
639
366
|
*/
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
return e.config.columns.map((n) => typeof n == "object" && n !== null && "name" in n ? n.name : "").filter(Boolean);
|
|
643
|
-
} catch {
|
|
367
|
+
extractIndexDefinitions(e) {
|
|
368
|
+
if (!e)
|
|
644
369
|
return [];
|
|
370
|
+
const t = [];
|
|
371
|
+
for (const n of e.indexes) {
|
|
372
|
+
const o = n.config.columns.map((s) => s.name);
|
|
373
|
+
o.length > 0 && t.push({
|
|
374
|
+
name: n.config.name || `idx_${o.join("_")}`,
|
|
375
|
+
columns: o,
|
|
376
|
+
unique: n.config.unique,
|
|
377
|
+
type: n.config.using
|
|
378
|
+
});
|
|
645
379
|
}
|
|
380
|
+
return t;
|
|
646
381
|
}
|
|
647
382
|
/**
|
|
648
|
-
*
|
|
383
|
+
* Extract constraint definitions from table config
|
|
649
384
|
*
|
|
650
|
-
* @param
|
|
651
|
-
* @returns
|
|
385
|
+
* @param tableConfig - The table configuration
|
|
386
|
+
* @returns Array of constraint definitions
|
|
652
387
|
*/
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
return
|
|
656
|
-
|
|
657
|
-
|
|
388
|
+
extractConstraintDefinitions(e) {
|
|
389
|
+
if (!e)
|
|
390
|
+
return [];
|
|
391
|
+
const t = [];
|
|
392
|
+
for (const n of e.primaryKeys) {
|
|
393
|
+
const o = n.columns.map((s) => s.name);
|
|
394
|
+
o.length > 0 && t.push({
|
|
395
|
+
name: n.name || `pk_${o.join("_")}`,
|
|
396
|
+
type: "primary_key",
|
|
397
|
+
columns: o
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
for (const n of e.uniqueConstraints) {
|
|
401
|
+
const o = n.columns.map((s) => s.name);
|
|
402
|
+
o.length > 0 && t.push({
|
|
403
|
+
name: n.name || `uq_${o.join("_")}`,
|
|
404
|
+
type: "unique",
|
|
405
|
+
columns: o
|
|
406
|
+
});
|
|
658
407
|
}
|
|
408
|
+
for (const n of e.foreignKeys) {
|
|
409
|
+
const o = this.parseForeignKeyForConstraint(n);
|
|
410
|
+
o && t.push(o);
|
|
411
|
+
}
|
|
412
|
+
return t;
|
|
659
413
|
}
|
|
660
414
|
/**
|
|
661
|
-
*
|
|
662
|
-
*
|
|
663
|
-
* @param
|
|
664
|
-
* @returns
|
|
665
|
-
*/
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
415
|
+
* Parse a foreign key into a ConstraintDefinition
|
|
416
|
+
*
|
|
417
|
+
* @param fk - The foreign key definition
|
|
418
|
+
* @returns ConstraintDefinition
|
|
419
|
+
*/
|
|
420
|
+
parseForeignKeyForConstraint(e) {
|
|
421
|
+
const t = e.reference(), n = t.columns.map((i) => i.name), o = t.foreignColumns.map((i) => i.name), s = m(t.foreignTable);
|
|
422
|
+
return {
|
|
423
|
+
name: e.name || `fk_${n.join("_")}_${s}`,
|
|
424
|
+
type: "foreign_key",
|
|
425
|
+
columns: n,
|
|
426
|
+
referencedTable: s,
|
|
427
|
+
referencedColumns: o
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Convert a GeneratedRef to a RelationDefinition
|
|
432
|
+
*
|
|
433
|
+
* @param ref - The generated reference
|
|
434
|
+
* @returns The relation definition
|
|
435
|
+
*/
|
|
436
|
+
refToRelationDefinition(e) {
|
|
437
|
+
let t;
|
|
438
|
+
switch (e.type) {
|
|
439
|
+
case "-":
|
|
440
|
+
t = "one-to-one";
|
|
441
|
+
break;
|
|
442
|
+
case ">":
|
|
443
|
+
t = "many-to-one";
|
|
444
|
+
break;
|
|
445
|
+
case "<":
|
|
446
|
+
t = "one-to-many";
|
|
447
|
+
break;
|
|
448
|
+
default:
|
|
449
|
+
t = "many-to-one";
|
|
671
450
|
}
|
|
451
|
+
return {
|
|
452
|
+
fromTable: e.fromTable,
|
|
453
|
+
fromColumns: e.fromColumns,
|
|
454
|
+
toTable: e.toTable,
|
|
455
|
+
toColumns: e.toColumns,
|
|
456
|
+
type: t,
|
|
457
|
+
onDelete: e.onDelete,
|
|
458
|
+
onUpdate: e.onUpdate
|
|
459
|
+
};
|
|
672
460
|
}
|
|
673
461
|
/**
|
|
674
|
-
*
|
|
462
|
+
* Collect enum definitions from the schema
|
|
463
|
+
*
|
|
464
|
+
* Override in subclasses for dialect-specific enum handling (e.g., PostgreSQL)
|
|
675
465
|
*
|
|
676
|
-
* @
|
|
677
|
-
* @returns Array of column names in the unique constraint
|
|
466
|
+
* @returns Array of enum definitions (empty by default)
|
|
678
467
|
*/
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
return e.columns.map((n) => n.name);
|
|
682
|
-
} catch {
|
|
683
|
-
return [];
|
|
684
|
-
}
|
|
468
|
+
collectEnumDefinitions() {
|
|
469
|
+
return [];
|
|
685
470
|
}
|
|
686
471
|
}
|
|
687
|
-
function P(
|
|
688
|
-
const t =
|
|
689
|
-
|
|
690
|
-
}
|
|
691
|
-
function $(y) {
|
|
692
|
-
return y.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\n");
|
|
472
|
+
function P(p, e) {
|
|
473
|
+
const t = R(p), n = q(t);
|
|
474
|
+
C(n, { recursive: !0 }), D(t, e, "utf-8");
|
|
693
475
|
}
|
|
694
476
|
export {
|
|
695
|
-
|
|
696
|
-
D as DbmlBuilder,
|
|
477
|
+
N as BaseGenerator,
|
|
697
478
|
P as writeDbmlFile
|
|
698
479
|
};
|
|
699
480
|
//# sourceMappingURL=common.js.map
|