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.
Files changed (61) hide show
  1. package/README.ja.md +59 -15
  2. package/README.md +55 -11
  3. package/dist/adapter/types.d.ts +40 -0
  4. package/dist/adapter/types.d.ts.map +1 -0
  5. package/dist/adapter/v0-adapter.d.ts +73 -0
  6. package/dist/adapter/v0-adapter.d.ts.map +1 -0
  7. package/dist/adapter/v0-adapter.js +136 -0
  8. package/dist/adapter/v0-adapter.js.map +1 -0
  9. package/dist/adapter/v1-adapter.d.ts +40 -0
  10. package/dist/adapter/v1-adapter.d.ts.map +1 -0
  11. package/dist/adapter/v1-adapter.js +83 -0
  12. package/dist/adapter/v1-adapter.js.map +1 -0
  13. package/dist/cli/index.js +194 -71
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/cli/integration-test-utils.d.ts +19 -0
  16. package/dist/cli/integration-test-utils.d.ts.map +1 -0
  17. package/dist/formatter/dbml-builder.d.ts +29 -0
  18. package/dist/formatter/dbml-builder.d.ts.map +1 -0
  19. package/dist/formatter/dbml-builder.js +39 -0
  20. package/dist/formatter/dbml-builder.js.map +1 -0
  21. package/dist/formatter/dbml.d.ts +81 -0
  22. package/dist/formatter/dbml.d.ts.map +1 -0
  23. package/dist/formatter/dbml.js +163 -0
  24. package/dist/formatter/dbml.js.map +1 -0
  25. package/dist/formatter/markdown.d.ts +126 -0
  26. package/dist/formatter/markdown.d.ts.map +1 -0
  27. package/dist/formatter/markdown.js +235 -0
  28. package/dist/formatter/markdown.js.map +1 -0
  29. package/dist/formatter/mermaid.d.ts +102 -0
  30. package/dist/formatter/mermaid.d.ts.map +1 -0
  31. package/dist/formatter/mermaid.js +177 -0
  32. package/dist/formatter/mermaid.js.map +1 -0
  33. package/dist/formatter/types.d.ts +37 -0
  34. package/dist/formatter/types.d.ts.map +1 -0
  35. package/dist/generator/common.d.ts +115 -208
  36. package/dist/generator/common.d.ts.map +1 -1
  37. package/dist/generator/common.js +260 -479
  38. package/dist/generator/common.js.map +1 -1
  39. package/dist/generator/mysql.js +3 -3
  40. package/dist/generator/pg.d.ts +8 -7
  41. package/dist/generator/pg.d.ts.map +1 -1
  42. package/dist/generator/pg.js +29 -31
  43. package/dist/generator/pg.js.map +1 -1
  44. package/dist/generator/sqlite.js +3 -3
  45. package/dist/index.d.ts +15 -4
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +22 -18
  48. package/dist/index.js.map +1 -1
  49. package/dist/test-utils/cli-runner.d.ts +4 -1
  50. package/dist/test-utils/cli-runner.d.ts.map +1 -1
  51. package/dist/test-utils/dbml-validator.d.ts +29 -0
  52. package/dist/test-utils/dbml-validator.d.ts.map +1 -1
  53. package/dist/types.d.ts +128 -16
  54. package/dist/types.d.ts.map +1 -1
  55. package/package.json +3 -2
  56. package/dist/generator/index.d.ts +0 -15
  57. package/dist/generator/index.d.ts.map +0 -1
  58. package/dist/parser/index.d.ts +0 -5
  59. package/dist/parser/index.d.ts.map +0 -1
  60. package/dist/test-utils/index.d.ts +0 -7
  61. package/dist/test-utils/index.d.ts.map +0 -1
@@ -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,126 @@
1
+ import { IntermediateSchema, TableDefinition } from '../types';
2
+ import { OutputFormatter, FormatterOptions } from './types';
3
+ /**
4
+ * Link format for table references
5
+ */
6
+ 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
+ export {};
126
+ //# 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,KAAK,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEpC;;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 */\ntype 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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"}