drizzle-docs-generator 0.1.1 → 0.3.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 +67 -8
- package/README.md +62 -3
- package/dist/adapter/index.d.ts +10 -0
- package/dist/adapter/index.d.ts.map +1 -0
- 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 +213 -40
- 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/index.d.ts +7 -0
- package/dist/formatter/index.d.ts.map +1 -0
- package/dist/formatter/markdown.d.ts +125 -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 +109 -211
- package/dist/generator/common.d.ts.map +1 -1
- package/dist/generator/common.js +252 -481
- package/dist/generator/common.js.map +1 -1
- package/dist/generator/index.d.ts +2 -1
- package/dist/generator/index.d.ts.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 +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -9
- package/dist/index.js.map +1 -1
- package/dist/test-utils/cli-runner.d.ts +4 -0
- package/dist/test-utils/cli-runner.d.ts.map +1 -1
- package/dist/test-utils/dbml-validator.d.ts +37 -0
- package/dist/test-utils/dbml-validator.d.ts.map +1 -1
- package/dist/types.d.ts +132 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { DbmlBuilder as u } from "./dbml-builder.js";
|
|
2
|
+
const p = {
|
|
3
|
+
includeComments: !0,
|
|
4
|
+
includeIndexes: !0,
|
|
5
|
+
includeConstraints: !0
|
|
6
|
+
};
|
|
7
|
+
class l {
|
|
8
|
+
options;
|
|
9
|
+
databaseType = "postgresql";
|
|
10
|
+
/**
|
|
11
|
+
* Create a new DbmlFormatter
|
|
12
|
+
*
|
|
13
|
+
* @param options - Formatter options
|
|
14
|
+
*/
|
|
15
|
+
constructor(e = {}) {
|
|
16
|
+
this.options = { ...p, ...e };
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Format the intermediate schema into DBML
|
|
20
|
+
*
|
|
21
|
+
* @param schema - The intermediate schema to format
|
|
22
|
+
* @returns DBML string
|
|
23
|
+
*/
|
|
24
|
+
format(e) {
|
|
25
|
+
const t = new u();
|
|
26
|
+
this.databaseType = e.databaseType;
|
|
27
|
+
for (const n of e.enums)
|
|
28
|
+
this.formatEnum(t, n), t.line();
|
|
29
|
+
for (const n of e.tables)
|
|
30
|
+
this.formatTable(t, n), t.line();
|
|
31
|
+
for (const n of e.relations)
|
|
32
|
+
this.formatRelation(t, n);
|
|
33
|
+
return t.build().trim();
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Format an enum definition to DBML
|
|
37
|
+
*/
|
|
38
|
+
formatEnum(e, t) {
|
|
39
|
+
const n = this.escapeName(t.name);
|
|
40
|
+
e.line(`Enum ${n} {`), e.indent();
|
|
41
|
+
for (const a of t.values)
|
|
42
|
+
e.line(a);
|
|
43
|
+
e.dedent(), e.line("}");
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Format a table definition to DBML
|
|
47
|
+
*/
|
|
48
|
+
formatTable(e, t) {
|
|
49
|
+
const n = this.escapeName(t.name);
|
|
50
|
+
e.line(`Table ${n} {`), e.indent();
|
|
51
|
+
for (const r of t.columns)
|
|
52
|
+
this.formatColumn(e, r);
|
|
53
|
+
const a = t.indexes.length > 0, s = t.constraints.filter((r) => r.type === "primary_key"), i = t.constraints.filter((r) => r.type === "unique"), o = s.length > 0 || i.length > 0;
|
|
54
|
+
this.options.includeIndexes && (a || o) && this.formatIndexesBlock(e, t.indexes, s, i), this.options.includeComments && t.comment && (e.line(), e.line(`Note: '${this.escapeString(t.comment)}'`)), e.dedent(), e.line("}");
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Format a column definition to DBML
|
|
58
|
+
*/
|
|
59
|
+
formatColumn(e, t) {
|
|
60
|
+
const n = this.escapeName(t.name), a = t.type, i = this.getColumnAttributes(t).join(", ");
|
|
61
|
+
i ? e.line(`${n} ${a} [${i}]`) : e.line(`${n} ${a}`);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get column attributes for DBML
|
|
65
|
+
*/
|
|
66
|
+
getColumnAttributes(e) {
|
|
67
|
+
const t = [];
|
|
68
|
+
return e.primaryKey && t.push("primary key"), e.nullable || t.push("not null"), e.unique && t.push("unique"), e.autoIncrement && t.push("increment"), e.defaultValue !== void 0 && t.push(`default: ${this.formatDefaultValue(e.defaultValue)}`), this.options.includeComments && e.comment && t.push(`note: '${this.escapeString(e.comment)}'`), t;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Format a default value for DBML
|
|
72
|
+
*
|
|
73
|
+
* The value comes from IntermediateSchema in "raw" format:
|
|
74
|
+
* - SQL expressions: no wrapping (e.g., "now()", "gen_random_uuid()")
|
|
75
|
+
* - Strings: already wrapped with single quotes (e.g., "'user'")
|
|
76
|
+
* - Numbers/booleans: as-is (e.g., "true", "42")
|
|
77
|
+
* - null: "null"
|
|
78
|
+
*/
|
|
79
|
+
formatDefaultValue(e) {
|
|
80
|
+
return e.includes("(") || e.includes("::") || this.isKnownSqlFunction(e) ? `\`${e}\`` : e === "null" || e === "NULL" ? "null" : e === "true" || e === "false" || /^-?\d+(\.\d+)?$/.test(e) ? e : e.startsWith("'") && e.endsWith("'") ? `'${e.slice(1, -1).replace(/''/g, "\\'")}'` : `'${e.replace(/'/g, "\\'")}'`;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Check if a value is a known SQL function/expression
|
|
84
|
+
*/
|
|
85
|
+
isKnownSqlFunction(e) {
|
|
86
|
+
return [
|
|
87
|
+
"now",
|
|
88
|
+
"current_timestamp",
|
|
89
|
+
"current_date",
|
|
90
|
+
"current_time",
|
|
91
|
+
"gen_random_uuid",
|
|
92
|
+
"uuid_generate_v4",
|
|
93
|
+
"autoincrement",
|
|
94
|
+
"auto_increment"
|
|
95
|
+
].some((n) => e.toLowerCase().includes(n));
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Format indexes block to DBML
|
|
99
|
+
*
|
|
100
|
+
* Includes primary key constraints, unique constraints, and regular indexes.
|
|
101
|
+
*/
|
|
102
|
+
formatIndexesBlock(e, t, n, a) {
|
|
103
|
+
e.line(), e.line("indexes {"), e.indent();
|
|
104
|
+
for (const s of n) {
|
|
105
|
+
const i = s.columns.map((o) => this.escapeName(o)).join(", ");
|
|
106
|
+
e.line(`(${i}) [pk]`);
|
|
107
|
+
}
|
|
108
|
+
for (const s of a) {
|
|
109
|
+
const i = s.columns.map((o) => this.escapeName(o)).join(", ");
|
|
110
|
+
e.line(`(${i}) [unique]`);
|
|
111
|
+
}
|
|
112
|
+
for (const s of t) {
|
|
113
|
+
const i = s.columns.map((c) => this.escapeName(c)).join(", "), o = [];
|
|
114
|
+
s.unique && o.push("unique"), s.name && o.push(`name: '${s.name}'`), s.type && o.push(`type: ${s.type}`);
|
|
115
|
+
const r = o.length > 0 ? ` [${o.join(", ")}]` : "";
|
|
116
|
+
e.line(`(${i})${r}`);
|
|
117
|
+
}
|
|
118
|
+
e.dedent(), e.line("}");
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Format a relation definition to DBML Ref
|
|
122
|
+
*/
|
|
123
|
+
formatRelation(e, t) {
|
|
124
|
+
const n = `${this.escapeName(t.fromTable)}.${t.fromColumns.map((r) => this.escapeName(r)).join(", ")}`, a = `${this.escapeName(t.toTable)}.${t.toColumns.map((r) => this.escapeName(r)).join(", ")}`, s = this.getRelationType(t.type);
|
|
125
|
+
let i = `Ref: ${n} ${s} ${a}`;
|
|
126
|
+
const o = [];
|
|
127
|
+
t.onDelete && t.onDelete.toLowerCase() !== "no action" && o.push(`delete: ${t.onDelete.toLowerCase()}`), t.onUpdate && t.onUpdate.toLowerCase() !== "no action" && o.push(`update: ${t.onUpdate.toLowerCase()}`), o.length > 0 && (i += ` [${o.join(", ")}]`), e.line(i);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Convert IntermediateRelationType to DBML relation symbol
|
|
131
|
+
*/
|
|
132
|
+
getRelationType(e) {
|
|
133
|
+
switch (e) {
|
|
134
|
+
case "one-to-one":
|
|
135
|
+
return "-";
|
|
136
|
+
case "one-to-many":
|
|
137
|
+
return "<";
|
|
138
|
+
case "many-to-one":
|
|
139
|
+
return ">";
|
|
140
|
+
case "many-to-many":
|
|
141
|
+
return "<>";
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Escape a name for DBML based on database type
|
|
146
|
+
*
|
|
147
|
+
* - PostgreSQL/SQLite: Use double quotes ("name")
|
|
148
|
+
* - MySQL: Use backticks (`name`)
|
|
149
|
+
*/
|
|
150
|
+
escapeName(e) {
|
|
151
|
+
return this.databaseType === "mysql" ? `\`${e}\`` : `"${e}"`;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Escape a string for use in DBML single-quoted strings
|
|
155
|
+
*/
|
|
156
|
+
escapeString(e) {
|
|
157
|
+
return e.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\n");
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
export {
|
|
161
|
+
l as DbmlFormatter
|
|
162
|
+
};
|
|
163
|
+
//# sourceMappingURL=dbml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dbml.js","sources":["../../src/formatter/dbml.ts"],"sourcesContent":["import type {\n IntermediateSchema,\n TableDefinition,\n ColumnDefinition,\n IndexDefinition,\n ConstraintDefinition,\n RelationDefinition,\n EnumDefinition,\n DatabaseType,\n} from \"../types\";\nimport type { OutputFormatter, FormatterOptions } from \"./types\";\nimport { DbmlBuilder } from \"./dbml-builder\";\n\n/**\n * Default formatter options\n */\nconst DEFAULT_OPTIONS: Required<FormatterOptions> = {\n includeComments: true,\n includeIndexes: true,\n includeConstraints: true,\n};\n\n/**\n * DbmlFormatter converts IntermediateSchema to DBML format\n *\n * This formatter wraps the existing DbmlBuilder to provide DBML output\n * from the database-agnostic IntermediateSchema representation.\n */\nexport class DbmlFormatter implements OutputFormatter {\n private options: Required<FormatterOptions>;\n private databaseType: DatabaseType = \"postgresql\";\n\n /**\n * Create a new DbmlFormatter\n *\n * @param options - Formatter options\n */\n constructor(options: FormatterOptions = {}) {\n this.options = { ...DEFAULT_OPTIONS, ...options };\n }\n\n /**\n * Format the intermediate schema into DBML\n *\n * @param schema - The intermediate schema to format\n * @returns DBML string\n */\n format(schema: IntermediateSchema): string {\n const dbml = new DbmlBuilder();\n\n // Store database type for name escaping\n this.databaseType = schema.databaseType;\n\n // Generate enums (PostgreSQL specific)\n for (const enumDef of schema.enums) {\n this.formatEnum(dbml, enumDef);\n dbml.line();\n }\n\n // Generate tables\n for (const table of schema.tables) {\n this.formatTable(dbml, table);\n dbml.line();\n }\n\n // Generate relations\n for (const relation of schema.relations) {\n this.formatRelation(dbml, relation);\n }\n\n return dbml.build().trim();\n }\n\n /**\n * Format an enum definition to DBML\n */\n private formatEnum(dbml: DbmlBuilder, enumDef: EnumDefinition): void {\n const name = this.escapeName(enumDef.name);\n dbml.line(`Enum ${name} {`);\n dbml.indent();\n for (const value of enumDef.values) {\n dbml.line(value);\n }\n dbml.dedent();\n dbml.line(\"}\");\n }\n\n /**\n * Format a table definition to DBML\n */\n private formatTable(dbml: DbmlBuilder, table: TableDefinition): void {\n const tableName = this.escapeName(table.name);\n dbml.line(`Table ${tableName} {`);\n dbml.indent();\n\n // Generate columns\n for (const column of table.columns) {\n this.formatColumn(dbml, column);\n }\n\n // Generate indexes block if enabled and there are indexes or constraints to show\n const hasIndexes = table.indexes.length > 0;\n const pkConstraints = table.constraints.filter((c) => c.type === \"primary_key\");\n const ucConstraints = table.constraints.filter((c) => c.type === \"unique\");\n const hasConstraints = pkConstraints.length > 0 || ucConstraints.length > 0;\n\n if (this.options.includeIndexes && (hasIndexes || hasConstraints)) {\n this.formatIndexesBlock(dbml, table.indexes, pkConstraints, ucConstraints);\n }\n\n // Add table-level Note if comment exists and comments are enabled\n if (this.options.includeComments && table.comment) {\n dbml.line();\n dbml.line(`Note: '${this.escapeString(table.comment)}'`);\n }\n\n dbml.dedent();\n dbml.line(\"}\");\n }\n\n /**\n * Format a column definition to DBML\n */\n private formatColumn(dbml: DbmlBuilder, column: ColumnDefinition): void {\n const name = this.escapeName(column.name);\n const type = column.type;\n const attrs = this.getColumnAttributes(column);\n const attrStr = attrs.join(\", \");\n\n if (attrStr) {\n dbml.line(`${name} ${type} [${attrStr}]`);\n } else {\n dbml.line(`${name} ${type}`);\n }\n }\n\n /**\n * Get column attributes for DBML\n */\n private getColumnAttributes(column: ColumnDefinition): string[] {\n const attrs: string[] = [];\n\n if (column.primaryKey) {\n attrs.push(\"primary key\");\n }\n if (!column.nullable) {\n attrs.push(\"not null\");\n }\n if (column.unique) {\n attrs.push(\"unique\");\n }\n if (column.autoIncrement) {\n attrs.push(\"increment\");\n }\n if (column.defaultValue !== undefined) {\n attrs.push(`default: ${this.formatDefaultValue(column.defaultValue)}`);\n }\n if (this.options.includeComments && column.comment) {\n attrs.push(`note: '${this.escapeString(column.comment)}'`);\n }\n\n return attrs;\n }\n\n /**\n * Format a default value for DBML\n *\n * The value comes from IntermediateSchema in \"raw\" format:\n * - SQL expressions: no wrapping (e.g., \"now()\", \"gen_random_uuid()\")\n * - Strings: already wrapped with single quotes (e.g., \"'user'\")\n * - Numbers/booleans: as-is (e.g., \"true\", \"42\")\n * - null: \"null\"\n */\n private formatDefaultValue(value: string): string {\n // If it looks like a SQL expression (contains parentheses or is a known function)\n if (value.includes(\"(\") || value.includes(\"::\") || this.isKnownSqlFunction(value)) {\n return `\\`${value}\\``;\n }\n // If it's null\n if (value === \"null\" || value === \"NULL\") {\n return \"null\";\n }\n // If it's a boolean\n if (value === \"true\" || value === \"false\") {\n return value;\n }\n // If it's a number\n if (/^-?\\d+(\\.\\d+)?$/.test(value)) {\n return value;\n }\n // If already wrapped in single quotes (from IntermediateSchema)\n if (value.startsWith(\"'\") && value.endsWith(\"'\")) {\n // Convert '' escape (SQL standard) to \\' escape (DBML)\n const inner = value.slice(1, -1).replace(/''/g, \"\\\\'\");\n return `'${inner}'`;\n }\n // Otherwise treat as string (shouldn't happen with proper IntermediateSchema)\n return `'${value.replace(/'/g, \"\\\\'\")}'`;\n }\n\n /**\n * Check if a value is a known SQL function/expression\n */\n private isKnownSqlFunction(value: string): boolean {\n const sqlKeywords = [\n \"now\",\n \"current_timestamp\",\n \"current_date\",\n \"current_time\",\n \"gen_random_uuid\",\n \"uuid_generate_v4\",\n \"autoincrement\",\n \"auto_increment\",\n ];\n return sqlKeywords.some((kw) => value.toLowerCase().includes(kw));\n }\n\n /**\n * Format indexes block to DBML\n *\n * Includes primary key constraints, unique constraints, and regular indexes.\n */\n private formatIndexesBlock(\n dbml: DbmlBuilder,\n indexes: IndexDefinition[],\n pkConstraints: ConstraintDefinition[],\n ucConstraints: ConstraintDefinition[],\n ): void {\n dbml.line();\n dbml.line(\"indexes {\");\n dbml.indent();\n\n // Primary key constraints\n for (const pk of pkConstraints) {\n const columns = pk.columns.map((c) => this.escapeName(c)).join(\", \");\n dbml.line(`(${columns}) [pk]`);\n }\n\n // Unique constraints\n for (const uc of ucConstraints) {\n const columns = uc.columns.map((c) => this.escapeName(c)).join(\", \");\n dbml.line(`(${columns}) [unique]`);\n }\n\n // Regular indexes\n for (const index of indexes) {\n const columns = index.columns.map((c) => this.escapeName(c)).join(\", \");\n const attrs: string[] = [];\n\n if (index.unique) {\n attrs.push(\"unique\");\n }\n if (index.name) {\n attrs.push(`name: '${index.name}'`);\n }\n if (index.type) {\n attrs.push(`type: ${index.type}`);\n }\n\n const attrStr = attrs.length > 0 ? ` [${attrs.join(\", \")}]` : \"\";\n dbml.line(`(${columns})${attrStr}`);\n }\n\n dbml.dedent();\n dbml.line(\"}\");\n }\n\n /**\n * Format a relation definition to DBML Ref\n */\n private formatRelation(dbml: DbmlBuilder, relation: RelationDefinition): void {\n const from = `${this.escapeName(relation.fromTable)}.${relation.fromColumns.map((c) => this.escapeName(c)).join(\", \")}`;\n const to = `${this.escapeName(relation.toTable)}.${relation.toColumns.map((c) => this.escapeName(c)).join(\", \")}`;\n const type = this.getRelationType(relation.type);\n\n let refLine = `Ref: ${from} ${type} ${to}`;\n\n const attrs: string[] = [];\n if (relation.onDelete && relation.onDelete.toLowerCase() !== \"no action\") {\n attrs.push(`delete: ${relation.onDelete.toLowerCase()}`);\n }\n if (relation.onUpdate && relation.onUpdate.toLowerCase() !== \"no action\") {\n attrs.push(`update: ${relation.onUpdate.toLowerCase()}`);\n }\n\n if (attrs.length > 0) {\n refLine += ` [${attrs.join(\", \")}]`;\n }\n\n dbml.line(refLine);\n }\n\n /**\n * Convert IntermediateRelationType to DBML relation symbol\n */\n private getRelationType(type: RelationDefinition[\"type\"]): \"<\" | \">\" | \"-\" | \"<>\" {\n switch (type) {\n case \"one-to-one\":\n return \"-\";\n case \"one-to-many\":\n return \"<\";\n case \"many-to-one\":\n return \">\";\n case \"many-to-many\":\n return \"<>\";\n }\n }\n\n /**\n * Escape a name for DBML based on database type\n *\n * - PostgreSQL/SQLite: Use double quotes (\"name\")\n * - MySQL: Use backticks (`name`)\n */\n private escapeName(name: string): string {\n if (this.databaseType === \"mysql\") {\n return `\\`${name}\\``;\n }\n // PostgreSQL and SQLite use double quotes\n return `\"${name}\"`;\n }\n\n /**\n * Escape a string for use in DBML single-quoted strings\n */\n private escapeString(str: string): string {\n return str.replace(/\\\\/g, \"\\\\\\\\\").replace(/'/g, \"\\\\'\").replace(/\\n/g, \"\\\\n\");\n }\n}\n"],"names":["DEFAULT_OPTIONS","DbmlFormatter","options","schema","dbml","DbmlBuilder","enumDef","table","relation","name","value","tableName","column","hasIndexes","pkConstraints","c","ucConstraints","hasConstraints","type","attrStr","attrs","kw","indexes","pk","columns","uc","index","from","to","refLine","str"],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type { OutputFormatter, FormatterOptions } from './types';
|
|
2
|
+
export type { MermaidFormatterOptions } from './mermaid';
|
|
3
|
+
export type { MarkdownFormatterOptions } from './markdown';
|
|
4
|
+
export { DbmlFormatter } from './dbml';
|
|
5
|
+
export { MarkdownFormatter } from './markdown';
|
|
6
|
+
export { MermaidErDiagramFormatter } from './mermaid';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/formatter/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACjE,YAAY,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACzD,YAAY,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAG3D,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { IntermediateSchema, TableDefinition } from '../types';
|
|
2
|
+
import { OutputFormatter, FormatterOptions } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Link format for table references
|
|
5
|
+
*/
|
|
6
|
+
export type LinkFormat = "anchor" | "file";
|
|
7
|
+
/**
|
|
8
|
+
* Options for MarkdownFormatter
|
|
9
|
+
*/
|
|
10
|
+
export interface MarkdownFormatterOptions extends FormatterOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Whether to use relative links for table references
|
|
13
|
+
* @default true
|
|
14
|
+
*/
|
|
15
|
+
useRelativeLinks?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Link format: "anchor" for #table-name, "file" for ./table-name.md
|
|
18
|
+
* @default "anchor"
|
|
19
|
+
*/
|
|
20
|
+
linkFormat?: LinkFormat;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* MarkdownFormatter converts IntermediateSchema to tbls-style Markdown format
|
|
24
|
+
*
|
|
25
|
+
* This formatter generates human-readable Markdown documentation from
|
|
26
|
+
* the database-agnostic IntermediateSchema representation.
|
|
27
|
+
*
|
|
28
|
+
* Output includes:
|
|
29
|
+
* - Table index (README.md style)
|
|
30
|
+
* - Individual table documentation with columns, constraints, indexes, and relations
|
|
31
|
+
*/
|
|
32
|
+
export declare class MarkdownFormatter implements OutputFormatter {
|
|
33
|
+
private options;
|
|
34
|
+
/**
|
|
35
|
+
* Create a new MarkdownFormatter
|
|
36
|
+
*
|
|
37
|
+
* @param options - Formatter options
|
|
38
|
+
*/
|
|
39
|
+
constructor(options?: MarkdownFormatterOptions);
|
|
40
|
+
/**
|
|
41
|
+
* Format the intermediate schema into a single Markdown document
|
|
42
|
+
*
|
|
43
|
+
* This generates a complete document containing the index and all table docs.
|
|
44
|
+
*
|
|
45
|
+
* @param schema - The intermediate schema to format
|
|
46
|
+
* @returns Markdown string
|
|
47
|
+
*/
|
|
48
|
+
format(schema: IntermediateSchema): string;
|
|
49
|
+
/**
|
|
50
|
+
* Generate the index section (README.md style)
|
|
51
|
+
*
|
|
52
|
+
* @param schema - The intermediate schema
|
|
53
|
+
* @returns Markdown string for the index
|
|
54
|
+
*/
|
|
55
|
+
generateIndex(schema: IntermediateSchema): string;
|
|
56
|
+
/**
|
|
57
|
+
* Generate documentation for a single table
|
|
58
|
+
*
|
|
59
|
+
* @param table - The table definition
|
|
60
|
+
* @param schema - The full schema (for relation lookups)
|
|
61
|
+
* @returns Markdown string for the table documentation
|
|
62
|
+
*/
|
|
63
|
+
generateTableDoc(table: TableDefinition, schema: IntermediateSchema): string;
|
|
64
|
+
/**
|
|
65
|
+
* Generate the columns table for a table
|
|
66
|
+
*/
|
|
67
|
+
private generateColumnsTable;
|
|
68
|
+
/**
|
|
69
|
+
* Generate the constraints table
|
|
70
|
+
*/
|
|
71
|
+
private generateConstraintsTable;
|
|
72
|
+
/**
|
|
73
|
+
* Generate the indexes table
|
|
74
|
+
*/
|
|
75
|
+
private generateIndexesTable;
|
|
76
|
+
/**
|
|
77
|
+
* Generate the relations table for a specific table
|
|
78
|
+
*/
|
|
79
|
+
private generateRelationsTable;
|
|
80
|
+
/**
|
|
81
|
+
* Generate documentation for enums
|
|
82
|
+
*/
|
|
83
|
+
private generateEnumsSection;
|
|
84
|
+
/**
|
|
85
|
+
* Get all relations involving a specific table
|
|
86
|
+
*/
|
|
87
|
+
private getTableRelations;
|
|
88
|
+
/**
|
|
89
|
+
* Get child relations for a specific column (where this column is referenced)
|
|
90
|
+
*/
|
|
91
|
+
private getChildRelations;
|
|
92
|
+
/**
|
|
93
|
+
* Get parent relations for a specific column (columns this column references)
|
|
94
|
+
*/
|
|
95
|
+
private getParentRelations;
|
|
96
|
+
/**
|
|
97
|
+
* Format relation links for display in columns table
|
|
98
|
+
*/
|
|
99
|
+
private formatRelationLinks;
|
|
100
|
+
/**
|
|
101
|
+
* Format constraint type for display
|
|
102
|
+
*/
|
|
103
|
+
private formatConstraintType;
|
|
104
|
+
/**
|
|
105
|
+
* Format constraint definition for display
|
|
106
|
+
*/
|
|
107
|
+
private formatConstraintDefinition;
|
|
108
|
+
/**
|
|
109
|
+
* Format relation type for display
|
|
110
|
+
*/
|
|
111
|
+
private formatRelationType;
|
|
112
|
+
/**
|
|
113
|
+
* Create a URL-safe slug from a string
|
|
114
|
+
*/
|
|
115
|
+
private slugify;
|
|
116
|
+
/**
|
|
117
|
+
* Create a table link based on the configured link format
|
|
118
|
+
*/
|
|
119
|
+
private createTableLink;
|
|
120
|
+
/**
|
|
121
|
+
* Escape special Markdown characters in a string
|
|
122
|
+
*/
|
|
123
|
+
private escapeMarkdown;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/formatter/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,eAAe,EAMhB,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEjE;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE3C;;GAEG;AACH,MAAM,WAAW,wBAAyB,SAAQ,gBAAgB;IAChE;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAaD;;;;;;;;;GASG;AACH,qBAAa,iBAAkB,YAAW,eAAe;IACvD,OAAO,CAAC,OAAO,CAAqC;IAEpD;;;;OAIG;gBACS,OAAO,GAAE,wBAA6B;IAIlD;;;;;;;OAOG;IACH,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM;IAyB1C;;;;;OAKG;IACH,aAAa,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM;IA4BjD;;;;;;OAMG;IACH,gBAAgB,CAAC,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,kBAAkB,GAAG,MAAM;IAsC5E;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA6C5B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAoBhC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAqB5B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAiC9B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAoB5B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAOzB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAazB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAa1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAS3B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAW5B;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAelC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;OAEG;IACH,OAAO,CAAC,OAAO;IAOf;;OAEG;IACH,OAAO,CAAC,eAAe;IAQvB;;OAEG;IACH,OAAO,CAAC,cAAc;CAGvB"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
const d = {
|
|
2
|
+
includeComments: !0,
|
|
3
|
+
includeIndexes: !0,
|
|
4
|
+
includeConstraints: !0,
|
|
5
|
+
useRelativeLinks: !0,
|
|
6
|
+
linkFormat: "anchor"
|
|
7
|
+
};
|
|
8
|
+
class T {
|
|
9
|
+
options;
|
|
10
|
+
/**
|
|
11
|
+
* Create a new MarkdownFormatter
|
|
12
|
+
*
|
|
13
|
+
* @param options - Formatter options
|
|
14
|
+
*/
|
|
15
|
+
constructor(e = {}) {
|
|
16
|
+
this.options = { ...d, ...e };
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Format the intermediate schema into a single Markdown document
|
|
20
|
+
*
|
|
21
|
+
* This generates a complete document containing the index and all table docs.
|
|
22
|
+
*
|
|
23
|
+
* @param schema - The intermediate schema to format
|
|
24
|
+
* @returns Markdown string
|
|
25
|
+
*/
|
|
26
|
+
format(e) {
|
|
27
|
+
const n = [];
|
|
28
|
+
n.push(this.generateIndex(e)), e.enums.length > 0 && (n.push(""), n.push("---"), n.push(""), n.push(this.generateEnumsSection(e.enums)));
|
|
29
|
+
for (const t of e.tables)
|
|
30
|
+
n.push(""), n.push("---"), n.push(""), n.push(this.generateTableDoc(t, e));
|
|
31
|
+
return n.join(`
|
|
32
|
+
`).trim();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Generate the index section (README.md style)
|
|
36
|
+
*
|
|
37
|
+
* @param schema - The intermediate schema
|
|
38
|
+
* @returns Markdown string for the index
|
|
39
|
+
*/
|
|
40
|
+
generateIndex(e) {
|
|
41
|
+
const n = [];
|
|
42
|
+
if (n.push("# Tables"), n.push(""), e.tables.length === 0)
|
|
43
|
+
return n.push("No tables defined."), n.join(`
|
|
44
|
+
`);
|
|
45
|
+
n.push("| Name | Columns | Comment |"), n.push("|------|---------|---------|");
|
|
46
|
+
for (const t of e.tables) {
|
|
47
|
+
const s = this.options.useRelativeLinks ? this.createTableLink(t.name) : t.name, i = t.columns.length, o = this.options.includeComments && t.comment ? this.escapeMarkdown(t.comment) : "";
|
|
48
|
+
n.push(`| ${s} | ${i} | ${o} |`);
|
|
49
|
+
}
|
|
50
|
+
return n.join(`
|
|
51
|
+
`);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Generate documentation for a single table
|
|
55
|
+
*
|
|
56
|
+
* @param table - The table definition
|
|
57
|
+
* @param schema - The full schema (for relation lookups)
|
|
58
|
+
* @returns Markdown string for the table documentation
|
|
59
|
+
*/
|
|
60
|
+
generateTableDoc(e, n) {
|
|
61
|
+
const t = [];
|
|
62
|
+
t.push(`## ${e.name}`), t.push(""), this.options.includeComments && e.comment && (t.push(this.escapeMarkdown(e.comment)), t.push("")), t.push(this.generateColumnsTable(e.columns, e.name, n)), this.options.includeConstraints && e.constraints.length > 0 && (t.push(""), t.push(this.generateConstraintsTable(e.constraints))), this.options.includeIndexes && e.indexes.length > 0 && (t.push(""), t.push(this.generateIndexesTable(e.indexes)));
|
|
63
|
+
const s = this.getTableRelations(e.name, n.relations);
|
|
64
|
+
return s.length > 0 && (t.push(""), t.push(this.generateRelationsTable(s, e.name))), t.join(`
|
|
65
|
+
`);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Generate the columns table for a table
|
|
69
|
+
*/
|
|
70
|
+
generateColumnsTable(e, n, t) {
|
|
71
|
+
const s = [];
|
|
72
|
+
if (s.push("### Columns"), s.push(""), e.length === 0)
|
|
73
|
+
return s.push("No columns defined."), s.join(`
|
|
74
|
+
`);
|
|
75
|
+
const i = e.map((o) => {
|
|
76
|
+
const a = this.getChildRelations(n, o.name, t.relations), r = this.getParentRelations(n, o.name, t.relations);
|
|
77
|
+
return { column: o, children: a, parents: r };
|
|
78
|
+
});
|
|
79
|
+
s.push("| Name | Type | Default | Nullable | Children | Parents | Comment |"), s.push("|------|------|---------|----------|----------|---------|---------|");
|
|
80
|
+
for (const { column: o, children: a, parents: r } of i) {
|
|
81
|
+
const u = o.primaryKey ? `**${o.name}**` : o.name, l = this.escapeMarkdown(o.type), p = o.defaultValue !== void 0 ? `\`${o.defaultValue}\`` : "-", c = o.nullable ? "YES" : "NO", h = a.length > 0 ? this.formatRelationLinks(a) : "-", m = r.length > 0 ? this.formatRelationLinks(r) : "-", f = this.options.includeComments && o.comment ? this.escapeMarkdown(o.comment) : "-";
|
|
82
|
+
s.push(
|
|
83
|
+
`| ${u} | ${l} | ${p} | ${c} | ${h} | ${m} | ${f} |`
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
return s.join(`
|
|
87
|
+
`);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Generate the constraints table
|
|
91
|
+
*/
|
|
92
|
+
generateConstraintsTable(e) {
|
|
93
|
+
const n = [];
|
|
94
|
+
n.push("### Constraints"), n.push(""), n.push("| Name | Type | Definition |"), n.push("|------|------|------------|");
|
|
95
|
+
for (const t of e) {
|
|
96
|
+
const s = t.name || "-", i = this.formatConstraintType(t.type), o = this.formatConstraintDefinition(t);
|
|
97
|
+
n.push(`| ${s} | ${i} | ${o} |`);
|
|
98
|
+
}
|
|
99
|
+
return n.join(`
|
|
100
|
+
`);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Generate the indexes table
|
|
104
|
+
*/
|
|
105
|
+
generateIndexesTable(e) {
|
|
106
|
+
const n = [];
|
|
107
|
+
n.push("### Indexes"), n.push(""), n.push("| Name | Columns | Unique | Type |"), n.push("|------|---------|--------|------|");
|
|
108
|
+
for (const t of e) {
|
|
109
|
+
const s = t.name || "-", i = t.columns.join(", "), o = t.unique ? "YES" : "NO", a = t.type || "-";
|
|
110
|
+
n.push(`| ${s} | ${i} | ${o} | ${a} |`);
|
|
111
|
+
}
|
|
112
|
+
return n.join(`
|
|
113
|
+
`);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Generate the relations table for a specific table
|
|
117
|
+
*/
|
|
118
|
+
generateRelationsTable(e, n) {
|
|
119
|
+
const t = [];
|
|
120
|
+
t.push("### Relations"), t.push(""), t.push("| Parent | Child | Type |"), t.push("|--------|-------|------|");
|
|
121
|
+
for (const s of e) {
|
|
122
|
+
const i = s.toTable === n, o = `${s.toTable}.${s.toColumns.join(", ")}`, a = `${s.fromTable}.${s.fromColumns.join(", ")}`, r = this.formatRelationType(s.type), u = this.options.useRelativeLinks ? this.createTableLink(s.toTable, o) : o, l = this.options.useRelativeLinks ? this.createTableLink(s.fromTable, a) : a, p = i ? `**${u}**` : u, c = i ? l : `**${l}**`;
|
|
123
|
+
t.push(`| ${p} | ${c} | ${r} |`);
|
|
124
|
+
}
|
|
125
|
+
return t.join(`
|
|
126
|
+
`);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Generate documentation for enums
|
|
130
|
+
*/
|
|
131
|
+
generateEnumsSection(e) {
|
|
132
|
+
const n = [];
|
|
133
|
+
n.push("# Enums"), n.push("");
|
|
134
|
+
for (const t of e) {
|
|
135
|
+
n.push(`## ${t.name}`), n.push(""), n.push("| Value |"), n.push("|-------|");
|
|
136
|
+
for (const s of t.values)
|
|
137
|
+
n.push(`| ${s} |`);
|
|
138
|
+
n.push("");
|
|
139
|
+
}
|
|
140
|
+
return n.join(`
|
|
141
|
+
`).trim();
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Get all relations involving a specific table
|
|
145
|
+
*/
|
|
146
|
+
getTableRelations(e, n) {
|
|
147
|
+
return n.filter((t) => t.fromTable === e || t.toTable === e);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Get child relations for a specific column (where this column is referenced)
|
|
151
|
+
*/
|
|
152
|
+
getChildRelations(e, n, t) {
|
|
153
|
+
return t.filter((s) => s.toTable === e && s.toColumns.includes(n)).map((s) => ({
|
|
154
|
+
table: s.fromTable,
|
|
155
|
+
column: s.fromColumns.join(", ")
|
|
156
|
+
}));
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get parent relations for a specific column (columns this column references)
|
|
160
|
+
*/
|
|
161
|
+
getParentRelations(e, n, t) {
|
|
162
|
+
return t.filter((s) => s.fromTable === e && s.fromColumns.includes(n)).map((s) => ({
|
|
163
|
+
table: s.toTable,
|
|
164
|
+
column: s.toColumns.join(", ")
|
|
165
|
+
}));
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Format relation links for display in columns table
|
|
169
|
+
*/
|
|
170
|
+
formatRelationLinks(e) {
|
|
171
|
+
return e.map((n) => {
|
|
172
|
+
const t = `${n.table}.${n.column}`;
|
|
173
|
+
return this.options.useRelativeLinks ? this.createTableLink(n.table, t) : t;
|
|
174
|
+
}).join(", ");
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Format constraint type for display
|
|
178
|
+
*/
|
|
179
|
+
formatConstraintType(e) {
|
|
180
|
+
return {
|
|
181
|
+
primary_key: "PRIMARY KEY",
|
|
182
|
+
foreign_key: "FOREIGN KEY",
|
|
183
|
+
unique: "UNIQUE",
|
|
184
|
+
check: "CHECK",
|
|
185
|
+
not_null: "NOT NULL"
|
|
186
|
+
}[e] || e;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Format constraint definition for display
|
|
190
|
+
*/
|
|
191
|
+
formatConstraintDefinition(e) {
|
|
192
|
+
if (e.definition)
|
|
193
|
+
return `\`${e.definition}\``;
|
|
194
|
+
const n = e.columns.join(", ");
|
|
195
|
+
if (e.type === "foreign_key" && e.referencedTable) {
|
|
196
|
+
const t = e.referencedColumns?.join(", ") || "";
|
|
197
|
+
return `(${n}) → ${e.referencedTable}(${t})`;
|
|
198
|
+
}
|
|
199
|
+
return `(${n})`;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Format relation type for display
|
|
203
|
+
*/
|
|
204
|
+
formatRelationType(e) {
|
|
205
|
+
return {
|
|
206
|
+
"one-to-one": "One to One",
|
|
207
|
+
"one-to-many": "One to Many",
|
|
208
|
+
"many-to-one": "Many to One",
|
|
209
|
+
"many-to-many": "Many to Many"
|
|
210
|
+
}[e] || e;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Create a URL-safe slug from a string
|
|
214
|
+
*/
|
|
215
|
+
slugify(e) {
|
|
216
|
+
return e.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Create a table link based on the configured link format
|
|
220
|
+
*/
|
|
221
|
+
createTableLink(e, n) {
|
|
222
|
+
const t = n || e;
|
|
223
|
+
return this.options.linkFormat === "file" ? `[${t}](./${e}.md)` : `[${t}](#${this.slugify(e)})`;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Escape special Markdown characters in a string
|
|
227
|
+
*/
|
|
228
|
+
escapeMarkdown(e) {
|
|
229
|
+
return e.replace(/\|/g, "\\|").replace(/\n/g, " ");
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
export {
|
|
233
|
+
T as MarkdownFormatter
|
|
234
|
+
};
|
|
235
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sources":["../../src/formatter/markdown.ts"],"sourcesContent":["import type {\n IntermediateSchema,\n TableDefinition,\n ColumnDefinition,\n IndexDefinition,\n ConstraintDefinition,\n RelationDefinition,\n EnumDefinition,\n} from \"../types\";\nimport type { OutputFormatter, FormatterOptions } from \"./types\";\n\n/**\n * Link format for table references\n */\nexport type LinkFormat = \"anchor\" | \"file\";\n\n/**\n * Options for MarkdownFormatter\n */\nexport interface MarkdownFormatterOptions extends FormatterOptions {\n /**\n * Whether to use relative links for table references\n * @default true\n */\n useRelativeLinks?: boolean;\n /**\n * Link format: \"anchor\" for #table-name, \"file\" for ./table-name.md\n * @default \"anchor\"\n */\n linkFormat?: LinkFormat;\n}\n\n/**\n * Default formatter options\n */\nconst DEFAULT_OPTIONS: Required<MarkdownFormatterOptions> = {\n includeComments: true,\n includeIndexes: true,\n includeConstraints: true,\n useRelativeLinks: true,\n linkFormat: \"anchor\",\n};\n\n/**\n * MarkdownFormatter converts IntermediateSchema to tbls-style Markdown format\n *\n * This formatter generates human-readable Markdown documentation from\n * the database-agnostic IntermediateSchema representation.\n *\n * Output includes:\n * - Table index (README.md style)\n * - Individual table documentation with columns, constraints, indexes, and relations\n */\nexport class MarkdownFormatter implements OutputFormatter {\n private options: Required<MarkdownFormatterOptions>;\n\n /**\n * Create a new MarkdownFormatter\n *\n * @param options - Formatter options\n */\n constructor(options: MarkdownFormatterOptions = {}) {\n this.options = { ...DEFAULT_OPTIONS, ...options };\n }\n\n /**\n * Format the intermediate schema into a single Markdown document\n *\n * This generates a complete document containing the index and all table docs.\n *\n * @param schema - The intermediate schema to format\n * @returns Markdown string\n */\n format(schema: IntermediateSchema): string {\n const lines: string[] = [];\n\n // Generate index section\n lines.push(this.generateIndex(schema));\n\n // Generate enum documentation if any\n if (schema.enums.length > 0) {\n lines.push(\"\");\n lines.push(\"---\");\n lines.push(\"\");\n lines.push(this.generateEnumsSection(schema.enums));\n }\n\n // Generate table documentation\n for (const table of schema.tables) {\n lines.push(\"\");\n lines.push(\"---\");\n lines.push(\"\");\n lines.push(this.generateTableDoc(table, schema));\n }\n\n return lines.join(\"\\n\").trim();\n }\n\n /**\n * Generate the index section (README.md style)\n *\n * @param schema - The intermediate schema\n * @returns Markdown string for the index\n */\n generateIndex(schema: IntermediateSchema): string {\n const lines: string[] = [];\n\n lines.push(\"# Tables\");\n lines.push(\"\");\n\n if (schema.tables.length === 0) {\n lines.push(\"No tables defined.\");\n return lines.join(\"\\n\");\n }\n\n // Table header\n lines.push(\"| Name | Columns | Comment |\");\n lines.push(\"|------|---------|---------|\");\n\n // Table rows\n for (const table of schema.tables) {\n const name = this.options.useRelativeLinks ? this.createTableLink(table.name) : table.name;\n const columnCount = table.columns.length;\n const comment =\n this.options.includeComments && table.comment ? this.escapeMarkdown(table.comment) : \"\";\n\n lines.push(`| ${name} | ${columnCount} | ${comment} |`);\n }\n\n return lines.join(\"\\n\");\n }\n\n /**\n * Generate documentation for a single table\n *\n * @param table - The table definition\n * @param schema - The full schema (for relation lookups)\n * @returns Markdown string for the table documentation\n */\n generateTableDoc(table: TableDefinition, schema: IntermediateSchema): string {\n const lines: string[] = [];\n\n // Table heading with anchor\n lines.push(`## ${table.name}`);\n lines.push(\"\");\n\n // Table comment\n if (this.options.includeComments && table.comment) {\n lines.push(this.escapeMarkdown(table.comment));\n lines.push(\"\");\n }\n\n // Columns section\n lines.push(this.generateColumnsTable(table.columns, table.name, schema));\n\n // Constraints section\n if (this.options.includeConstraints && table.constraints.length > 0) {\n lines.push(\"\");\n lines.push(this.generateConstraintsTable(table.constraints));\n }\n\n // Indexes section\n if (this.options.includeIndexes && table.indexes.length > 0) {\n lines.push(\"\");\n lines.push(this.generateIndexesTable(table.indexes));\n }\n\n // Relations section\n const tableRelations = this.getTableRelations(table.name, schema.relations);\n if (tableRelations.length > 0) {\n lines.push(\"\");\n lines.push(this.generateRelationsTable(tableRelations, table.name));\n }\n\n return lines.join(\"\\n\");\n }\n\n /**\n * Generate the columns table for a table\n */\n private generateColumnsTable(\n columns: ColumnDefinition[],\n tableName: string,\n schema: IntermediateSchema,\n ): string {\n const lines: string[] = [];\n\n lines.push(\"### Columns\");\n lines.push(\"\");\n\n if (columns.length === 0) {\n lines.push(\"No columns defined.\");\n return lines.join(\"\\n\");\n }\n\n // Build column info with relations\n const columnInfo = columns.map((col) => {\n const children = this.getChildRelations(tableName, col.name, schema.relations);\n const parents = this.getParentRelations(tableName, col.name, schema.relations);\n return { column: col, children, parents };\n });\n\n // Table header\n lines.push(\"| Name | Type | Default | Nullable | Children | Parents | Comment |\");\n lines.push(\"|------|------|---------|----------|----------|---------|---------|\");\n\n // Table rows\n for (const { column, children, parents } of columnInfo) {\n const name = column.primaryKey ? `**${column.name}**` : column.name;\n const type = this.escapeMarkdown(column.type);\n const defaultVal = column.defaultValue !== undefined ? `\\`${column.defaultValue}\\`` : \"-\";\n const nullable = column.nullable ? \"YES\" : \"NO\";\n const childrenStr = children.length > 0 ? this.formatRelationLinks(children) : \"-\";\n const parentsStr = parents.length > 0 ? this.formatRelationLinks(parents) : \"-\";\n const comment =\n this.options.includeComments && column.comment ? this.escapeMarkdown(column.comment) : \"-\";\n\n lines.push(\n `| ${name} | ${type} | ${defaultVal} | ${nullable} | ${childrenStr} | ${parentsStr} | ${comment} |`,\n );\n }\n\n return lines.join(\"\\n\");\n }\n\n /**\n * Generate the constraints table\n */\n private generateConstraintsTable(constraints: ConstraintDefinition[]): string {\n const lines: string[] = [];\n\n lines.push(\"### Constraints\");\n lines.push(\"\");\n\n lines.push(\"| Name | Type | Definition |\");\n lines.push(\"|------|------|------------|\");\n\n for (const constraint of constraints) {\n const name = constraint.name || \"-\";\n const type = this.formatConstraintType(constraint.type);\n const definition = this.formatConstraintDefinition(constraint);\n\n lines.push(`| ${name} | ${type} | ${definition} |`);\n }\n\n return lines.join(\"\\n\");\n }\n\n /**\n * Generate the indexes table\n */\n private generateIndexesTable(indexes: IndexDefinition[]): string {\n const lines: string[] = [];\n\n lines.push(\"### Indexes\");\n lines.push(\"\");\n\n lines.push(\"| Name | Columns | Unique | Type |\");\n lines.push(\"|------|---------|--------|------|\");\n\n for (const index of indexes) {\n const name = index.name || \"-\";\n const columns = index.columns.join(\", \");\n const unique = index.unique ? \"YES\" : \"NO\";\n const type = index.type || \"-\";\n\n lines.push(`| ${name} | ${columns} | ${unique} | ${type} |`);\n }\n\n return lines.join(\"\\n\");\n }\n\n /**\n * Generate the relations table for a specific table\n */\n private generateRelationsTable(relations: RelationDefinition[], tableName: string): string {\n const lines: string[] = [];\n\n lines.push(\"### Relations\");\n lines.push(\"\");\n\n lines.push(\"| Parent | Child | Type |\");\n lines.push(\"|--------|-------|------|\");\n\n for (const relation of relations) {\n const isParent = relation.toTable === tableName;\n const parent = `${relation.toTable}.${relation.toColumns.join(\", \")}`;\n const child = `${relation.fromTable}.${relation.fromColumns.join(\", \")}`;\n const type = this.formatRelationType(relation.type);\n\n // Add links if enabled\n const parentLink = this.options.useRelativeLinks\n ? this.createTableLink(relation.toTable, parent)\n : parent;\n const childLink = this.options.useRelativeLinks\n ? this.createTableLink(relation.fromTable, child)\n : child;\n\n // Highlight the current table\n const parentDisplay = isParent ? `**${parentLink}**` : parentLink;\n const childDisplay = !isParent ? `**${childLink}**` : childLink;\n\n lines.push(`| ${parentDisplay} | ${childDisplay} | ${type} |`);\n }\n\n return lines.join(\"\\n\");\n }\n\n /**\n * Generate documentation for enums\n */\n private generateEnumsSection(enums: EnumDefinition[]): string {\n const lines: string[] = [];\n\n lines.push(\"# Enums\");\n lines.push(\"\");\n\n for (const enumDef of enums) {\n lines.push(`## ${enumDef.name}`);\n lines.push(\"\");\n lines.push(\"| Value |\");\n lines.push(\"|-------|\");\n for (const value of enumDef.values) {\n lines.push(`| ${value} |`);\n }\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\").trim();\n }\n\n /**\n * Get all relations involving a specific table\n */\n private getTableRelations(\n tableName: string,\n relations: RelationDefinition[],\n ): RelationDefinition[] {\n return relations.filter((r) => r.fromTable === tableName || r.toTable === tableName);\n }\n\n /**\n * Get child relations for a specific column (where this column is referenced)\n */\n private getChildRelations(\n tableName: string,\n columnName: string,\n relations: RelationDefinition[],\n ): Array<{ table: string; column: string }> {\n return relations\n .filter((r) => r.toTable === tableName && r.toColumns.includes(columnName))\n .map((r) => ({\n table: r.fromTable,\n column: r.fromColumns.join(\", \"),\n }));\n }\n\n /**\n * Get parent relations for a specific column (columns this column references)\n */\n private getParentRelations(\n tableName: string,\n columnName: string,\n relations: RelationDefinition[],\n ): Array<{ table: string; column: string }> {\n return relations\n .filter((r) => r.fromTable === tableName && r.fromColumns.includes(columnName))\n .map((r) => ({\n table: r.toTable,\n column: r.toColumns.join(\", \"),\n }));\n }\n\n /**\n * Format relation links for display in columns table\n */\n private formatRelationLinks(relations: Array<{ table: string; column: string }>): string {\n return relations\n .map((r) => {\n const text = `${r.table}.${r.column}`;\n return this.options.useRelativeLinks ? this.createTableLink(r.table, text) : text;\n })\n .join(\", \");\n }\n\n /**\n * Format constraint type for display\n */\n private formatConstraintType(type: ConstraintDefinition[\"type\"]): string {\n const typeMap: Record<ConstraintDefinition[\"type\"], string> = {\n primary_key: \"PRIMARY KEY\",\n foreign_key: \"FOREIGN KEY\",\n unique: \"UNIQUE\",\n check: \"CHECK\",\n not_null: \"NOT NULL\",\n };\n return typeMap[type] || type;\n }\n\n /**\n * Format constraint definition for display\n */\n private formatConstraintDefinition(constraint: ConstraintDefinition): string {\n if (constraint.definition) {\n return `\\`${constraint.definition}\\``;\n }\n\n const columns = constraint.columns.join(\", \");\n\n if (constraint.type === \"foreign_key\" && constraint.referencedTable) {\n const refColumns = constraint.referencedColumns?.join(\", \") || \"\";\n return `(${columns}) → ${constraint.referencedTable}(${refColumns})`;\n }\n\n return `(${columns})`;\n }\n\n /**\n * Format relation type for display\n */\n private formatRelationType(type: RelationDefinition[\"type\"]): string {\n const typeMap: Record<RelationDefinition[\"type\"], string> = {\n \"one-to-one\": \"One to One\",\n \"one-to-many\": \"One to Many\",\n \"many-to-one\": \"Many to One\",\n \"many-to-many\": \"Many to Many\",\n };\n return typeMap[type] || type;\n }\n\n /**\n * Create a URL-safe slug from a string\n */\n private slugify(str: string): string {\n return str\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n }\n\n /**\n * Create a table link based on the configured link format\n */\n private createTableLink(tableName: string, displayText?: string): string {\n const text = displayText || tableName;\n if (this.options.linkFormat === \"file\") {\n return `[${text}](./${tableName}.md)`;\n }\n return `[${text}](#${this.slugify(tableName)})`;\n }\n\n /**\n * Escape special Markdown characters in a string\n */\n private escapeMarkdown(str: string): string {\n return str.replace(/\\|/g, \"\\\\|\").replace(/\\n/g, \" \");\n }\n}\n"],"names":["DEFAULT_OPTIONS","MarkdownFormatter","options","schema","lines","table","name","columnCount","comment","tableRelations","columns","tableName","columnInfo","col","children","parents","column","type","defaultVal","nullable","childrenStr","parentsStr","constraints","constraint","definition","indexes","index","unique","relations","relation","isParent","parent","child","parentLink","childLink","parentDisplay","childDisplay","enums","enumDef","value","r","columnName","text","refColumns","str","displayText"],"mappings":"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"}
|