drizzle-docs-generator 0.4.1 → 0.5.1

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 CHANGED
@@ -11,7 +11,7 @@ Drizzle ORM スキーマから DBML と Markdown ドキュメントを生成す
11
11
  - **JSDoc コメント**: 自動的に DBML の Note 句に変換
12
12
  - **リレーション対応**: `relations()` または `defineRelations()` から参照を生成
13
13
  - **Watch モード**: ファイル変更時に自動再生成
14
- - **複数の出力形式**: DBML (デフォルト) および ER 図付き Markdown
14
+ - **複数の出力形式**: Markdown (デフォルト) および ER 図付き DBML
15
15
 
16
16
  [English README](./README.md)
17
17
 
@@ -41,45 +41,67 @@ drizzle-docs generate ./src/db/schema.ts -d postgresql
41
41
 
42
42
  ## 使い方
43
43
 
44
- ### DBML 出力 (デフォルト)
44
+ ### 基本的な使用方法
45
45
 
46
46
  ```bash
47
- # 基本 - 単一ファイル
48
- drizzle-docs generate ./src/db/schema.ts -d postgresql
47
+ # Markdown 出力 (デフォルト)
48
+ drizzle-docs generate ./src/db/schema.ts -d postgresql -o ./docs
49
49
 
50
- # ディレクトリ - ディレクトリ内のすべてのスキーマファイルをインポート
51
- drizzle-docs generate ./src/db/schema/ -d postgresql
50
+ # DBML 出力
51
+ drizzle-docs generate ./src/db/schema.ts -d postgresql -f dbml -o schema.dbml
52
+ ```
53
+
54
+ ### 出力形式のオプション
55
+
56
+ #### Markdown 形式 (デフォルト)
57
+
58
+ デフォルトの出力形式は **Markdown** で、ER 図付きの複数ファイルを生成します。
59
+
60
+ **Markdown 形式固有のオプション:**
61
+
62
+ | オプション | 説明 |
63
+ | ----------------- | -------------------------------------- |
64
+ | `--single-file` | 複数ファイルではなく単一ファイルで出力 |
65
+ | `--no-er-diagram` | 出力から ER 図を除外 |
52
66
 
53
- # ファイル出力
54
- drizzle-docs generate ./src/db/schema.ts -d postgresql -o schema.dbml
67
+ **例:**
55
68
 
56
- # watch モード
57
- drizzle-docs generate ./src/db/schema.ts -d postgresql -w
69
+ ```bash
70
+ # ER 図付き複数ファイル (デフォルト)
71
+ drizzle-docs generate ./src/db/schema.ts -d postgresql -o ./docs
72
+
73
+ # 単一ファイル Markdown
74
+ drizzle-docs generate ./src/db/schema.ts -d postgresql --single-file -o schema.md
75
+
76
+ # ER 図なしの複数ファイル
77
+ drizzle-docs generate ./src/db/schema.ts -d postgresql --no-er-diagram -o ./docs
58
78
  ```
59
79
 
60
- ### Markdown 出力
80
+ #### DBML 形式
81
+
82
+ `-f dbml` または `--format dbml` オプションを使用して DBML 形式を生成します。
83
+
84
+ **例:**
61
85
 
62
86
  ```bash
63
- # Markdown 出力 (ER 図付き複数ファイル)
64
- drizzle-docs generate ./src/db/schema.ts -d postgresql -f markdown -o ./docs
87
+ # ファイルに出力
88
+ drizzle-docs generate ./src/db/schema.ts -d postgresql -f dbml -o schema.dbml
65
89
 
66
- # Markdown 出力 (単一ファイル)
67
- drizzle-docs generate ./src/db/schema.ts -d postgresql -f markdown --single-file -o schema.md
90
+ # ディレクトリ - ディレクトリ内のすべてのスキーマファイルをインポート
91
+ drizzle-docs generate ./src/db/schema/ -d postgresql -f dbml -o schema.dbml
68
92
 
69
- # ER 図なしの Markdown
70
- drizzle-docs generate ./src/db/schema.ts -d postgresql -f markdown --no-er-diagram -o ./docs
93
+ # Watch モード
94
+ drizzle-docs generate ./src/db/schema.ts -d postgresql -f dbml -w
71
95
  ```
72
96
 
73
- ### オプション
97
+ #### 共通オプション
74
98
 
75
99
  | オプション | 説明 |
76
100
  | ------------------------- | ----------------------------------------------------- |
77
101
  | `-o, --output <path>` | 出力ファイルまたはディレクトリパス |
78
102
  | `-d, --dialect <dialect>` | DB 種別: `postgresql` (デフォルト), `mysql`, `sqlite` |
79
- | `-f, --format <format>` | 出力形式: `dbml` (デフォルト), `markdown` |
103
+ | `-f, --format <format>` | 出力形式: `markdown` (デフォルト), `dbml` |
80
104
  | `-w, --watch` | ファイル変更時に自動再生成 |
81
- | `--single-file` | Markdown を単一ファイルで出力 (markdown のみ) |
82
- | `--no-er-diagram` | ER 図を Markdown 出力から除外 |
83
105
  | `--force` | 確認なしで既存ファイルを上書き |
84
106
 
85
107
  ### リレーション検出
package/README.md CHANGED
@@ -11,7 +11,7 @@ CLI tool to generate DBML and Markdown documentation from Drizzle ORM schemas. E
11
11
  - **JSDoc Comments**: Automatically extracts and converts to DBML Notes
12
12
  - **Relations Support**: Generate refs from `relations()` or `defineRelations()`
13
13
  - **Watch Mode**: Auto-regenerate on file changes
14
- - **Multiple Output Formats**: DBML (default) and Markdown with ER diagrams
14
+ - **Multiple Output Formats**: Markdown (default) and DBML with ER diagrams
15
15
 
16
16
  [日本語版READMEはこちら](./README.ja.md)
17
17
 
@@ -41,45 +41,67 @@ drizzle-docs generate ./src/db/schema.ts -d postgresql
41
41
 
42
42
  ## Usage
43
43
 
44
- ### DBML Output (Default)
44
+ ### Basic Usage
45
45
 
46
46
  ```bash
47
- # Basic - single file
48
- drizzle-docs generate ./src/db/schema.ts -d postgresql
47
+ # Markdown output (default)
48
+ drizzle-docs generate ./src/db/schema.ts -d postgresql -o ./docs
49
49
 
50
- # Directory - import all schema files from directory
51
- drizzle-docs generate ./src/db/schema/ -d postgresql
50
+ # DBML output
51
+ drizzle-docs generate ./src/db/schema.ts -d postgresql -f dbml -o schema.dbml
52
+ ```
52
53
 
53
- # Output to file
54
- drizzle-docs generate ./src/db/schema.ts -d postgresql -o schema.dbml
54
+ ### Output Format Options
55
55
 
56
- # Watch mode
57
- drizzle-docs generate ./src/db/schema.ts -d postgresql -w
56
+ #### Markdown Format (Default)
57
+
58
+ The default output format is **Markdown**, which generates multiple files with an ER diagram.
59
+
60
+ **Options specific to Markdown format:**
61
+
62
+ | Option | Description |
63
+ | ----------------- | ------------------------------------------- |
64
+ | `--single-file` | Output as a single file instead of multiple |
65
+ | `--no-er-diagram` | Exclude ER diagram from output |
66
+
67
+ **Examples:**
68
+
69
+ ```bash
70
+ # Multiple files with ER diagram (default)
71
+ drizzle-docs generate ./src/db/schema.ts -d postgresql -o ./docs
72
+
73
+ # Single file Markdown
74
+ drizzle-docs generate ./src/db/schema.ts -d postgresql --single-file -o schema.md
75
+
76
+ # Multiple files without ER diagram
77
+ drizzle-docs generate ./src/db/schema.ts -d postgresql --no-er-diagram -o ./docs
58
78
  ```
59
79
 
60
- ### Markdown Output
80
+ #### DBML Format
81
+
82
+ Use the `-f dbml` or `--format dbml` option to generate DBML format.
83
+
84
+ **Examples:**
61
85
 
62
86
  ```bash
63
- # Markdown output (multiple files with ER diagram)
64
- drizzle-docs generate ./src/db/schema.ts -d postgresql -f markdown -o ./docs
87
+ # Output to file
88
+ drizzle-docs generate ./src/db/schema.ts -d postgresql -f dbml -o schema.dbml
65
89
 
66
- # Markdown output (single file)
67
- drizzle-docs generate ./src/db/schema.ts -d postgresql -f markdown --single-file -o schema.md
90
+ # Directory - import all schema files from directory
91
+ drizzle-docs generate ./src/db/schema/ -d postgresql -f dbml -o schema.dbml
68
92
 
69
- # Markdown without ER diagram
70
- drizzle-docs generate ./src/db/schema.ts -d postgresql -f markdown --no-er-diagram -o ./docs
93
+ # Watch mode
94
+ drizzle-docs generate ./src/db/schema.ts -d postgresql -f dbml -w
71
95
  ```
72
96
 
73
- ### Options
97
+ #### Common Options
74
98
 
75
99
  | Option | Description |
76
100
  | ------------------------- | --------------------------------------------------- |
77
101
  | `-o, --output <path>` | Output file or directory path |
78
102
  | `-d, --dialect <dialect>` | Database: `postgresql` (default), `mysql`, `sqlite` |
79
- | `-f, --format <format>` | Output format: `dbml` (default), `markdown` |
103
+ | `-f, --format <format>` | Output format: `markdown` (default), `dbml` |
80
104
  | `-w, --watch` | Regenerate on file changes |
81
- | `--single-file` | Output Markdown as a single file (markdown only) |
82
- | `--no-er-diagram` | Exclude ER diagram from Markdown output |
83
105
  | `--force` | Overwrite existing files without confirmation |
84
106
 
85
107
  ### Relation Detection
package/dist/cli/index.js CHANGED
@@ -216,7 +216,7 @@ File changed, regenerating...`);
216
216
  }, 100));
217
217
  });
218
218
  }
219
- h.command("generate").description("Generate documentation from Drizzle schema files").argument("<schema>", "Path to Drizzle schema file or directory").option("-o, --output <path>", "Output file or directory path").option("-d, --dialect <dialect>", "Database dialect (postgresql, mysql, sqlite)", "postgresql").option("-f, --format <format>", "Output format (dbml, markdown)", "dbml").option("-w, --watch", "Watch for file changes and regenerate").option("--single-file", "Output Markdown as a single file (for markdown format)").option("--no-er-diagram", "Exclude ER diagram from Markdown output").option("--force", "Overwrite existing files without confirmation").action(async (r, e) => {
219
+ h.command("generate").description("Generate documentation from Drizzle schema files").argument("<schema>", "Path to Drizzle schema file or directory").option("-o, --output <path>", "Output file or directory path").option("-d, --dialect <dialect>", "Database dialect (postgresql, mysql, sqlite)", "postgresql").option("-f, --format <format>", "Output format (dbml, markdown)", "markdown").option("-w, --watch", "Watch for file changes and regenerate").option("--single-file", "Output Markdown as a single file (for markdown format)").option("--no-er-diagram", "Exclude ER diagram from Markdown output").option("--force", "Overwrite existing files without confirmation").action(async (r, e) => {
220
220
  const o = ["postgresql", "mysql", "sqlite"];
221
221
  o.includes(e.dialect) || (console.error(
222
222
  `Error: Invalid dialect "${e.dialect}". Valid options: ${o.join(", ")}`
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * CLI for drizzle-docs-generator\n *\n * Generates DBML files from Drizzle ORM schema definitions.\n */\n\nimport { Command } from \"commander\";\nimport {\n existsSync,\n lstatSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n watch,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { pgGenerate } from \"../generator/pg\";\nimport { mysqlGenerate } from \"../generator/mysql\";\nimport { sqliteGenerate } from \"../generator/sqlite\";\nimport { PgGenerator } from \"../generator/pg\";\nimport { MySqlGenerator } from \"../generator/mysql\";\nimport { SqliteGenerator } from \"../generator/sqlite\";\nimport { MarkdownFormatter } from \"../formatter/markdown\";\nimport { MermaidErDiagramFormatter } from \"../formatter/mermaid\";\nimport { register } from \"tsx/esm/api\";\nimport type { IntermediateSchema } from \"../types\";\n\n// Register tsx loader to support TypeScript and extensionless imports\nconst unregister = register();\n\nconst program = new Command();\n\n// Use import.meta.dirname (Node 20.11+) to resolve package.json\n// This works correctly even after bundling\nconst packageJsonPath = join(import.meta.dirname, \"../../package.json\");\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\")) as {\n version: string;\n description: string;\n};\n\nprogram.name(\"drizzle-docs\").description(packageJson.description).version(packageJson.version);\n\ntype Dialect = \"postgresql\" | \"mysql\" | \"sqlite\";\ntype OutputFormat = \"dbml\" | \"markdown\";\n\ninterface GenerateCommandOptions {\n output?: string;\n dialect: Dialect;\n watch?: boolean;\n format: OutputFormat;\n singleFile?: boolean;\n erDiagram: boolean; // commander uses --no-er-diagram which sets erDiagram to false\n force?: boolean; // skip overwrite confirmation for existing files\n}\n\n/**\n * Get the generate function based on dialect\n */\nfunction getGenerateFunction(dialect: Dialect) {\n switch (dialect) {\n case \"mysql\":\n return mysqlGenerate;\n case \"sqlite\":\n return sqliteGenerate;\n case \"postgresql\":\n default:\n return pgGenerate;\n }\n}\n\n/**\n * Get the generator class based on dialect\n */\nfunction getGeneratorClass(dialect: Dialect) {\n switch (dialect) {\n case \"mysql\":\n return MySqlGenerator;\n case \"sqlite\":\n return SqliteGenerator;\n case \"postgresql\":\n default:\n return PgGenerator;\n }\n}\n\n/**\n * Check if output directory has existing files\n */\nfunction hasExistingFiles(outputDir: string, tableNames: string[]): string[] {\n const existingFiles: string[] = [];\n\n if (!existsSync(outputDir)) {\n return existingFiles;\n }\n\n const readmePath = join(outputDir, \"README.md\");\n if (existsSync(readmePath)) {\n existingFiles.push(readmePath);\n }\n\n for (const tableName of tableNames) {\n const tablePath = join(outputDir, `${tableName}.md`);\n if (existsSync(tablePath)) {\n existingFiles.push(tablePath);\n }\n }\n\n return existingFiles;\n}\n\n/**\n * Generate output from a schema file (for watch mode)\n * Returns the generated output string for single-file formats,\n * or writes multiple files directly for multi-file markdown\n */\nasync function generateFromSchema(\n schemaPath: string,\n options: GenerateCommandOptions,\n): Promise<string | undefined> {\n // Use file URL for dynamic import (required for ESM)\n const schemaUrl = pathToFileURL(schemaPath).href;\n\n // Dynamic import with cache busting for watch mode\n const cacheBuster = options.watch ? `?t=${Date.now()}` : \"\";\n const schemaModule = (await import(schemaUrl + cacheBuster)) as Record<string, unknown>;\n\n if (options.format === \"markdown\") {\n const GeneratorClass = getGeneratorClass(options.dialect);\n const generator = new GeneratorClass({\n schema: schemaModule,\n source: schemaPath,\n });\n const intermediateSchema = generator.toIntermediateSchema();\n\n // Handle multi-file output in watch mode\n if (!options.singleFile && options.output) {\n writeMarkdownMultipleFiles(intermediateSchema, options.output, options);\n return undefined;\n }\n\n return generateMarkdownOutput(intermediateSchema, options);\n } else {\n const generate = getGenerateFunction(options.dialect);\n return generate({\n schema: schemaModule,\n source: schemaPath,\n });\n }\n}\n\n/**\n * Find all TypeScript schema files in a directory\n */\nfunction findSchemaFiles(dirPath: string): string[] {\n const files: string[] = [];\n\n try {\n const entries = readdirSync(dirPath, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(dirPath, entry.name);\n\n if (entry.isDirectory()) {\n // Recursively search subdirectories\n files.push(...findSchemaFiles(fullPath));\n } else if (entry.isFile() && /\\.(ts|js|mts|mjs|cts|cjs)$/.test(entry.name)) {\n files.push(fullPath);\n }\n }\n } catch (error) {\n if (error instanceof Error) {\n console.error(`Error reading directory ${dirPath}: ${error.message}`);\n }\n }\n\n return files;\n}\n\n/**\n * Resolve schema path (file or directory)\n */\nfunction resolveSchemaPath(schema: string): string[] {\n const schemaPath = resolve(process.cwd(), schema);\n\n // Check if path exists\n if (!existsSync(schemaPath)) {\n console.error(`Error: Schema path not found: ${schemaPath}`);\n process.exit(1);\n }\n\n // Check if it's a directory\n const stats = lstatSync(schemaPath);\n if (stats.isDirectory()) {\n const schemaFiles = findSchemaFiles(schemaPath);\n if (schemaFiles.length === 0) {\n console.error(`Error: No schema files found in directory: ${schemaPath}`);\n process.exit(1);\n }\n return schemaFiles;\n }\n\n // Single file\n return [schemaPath];\n}\n\n/**\n * Generate DBML format output\n */\nfunction generateDbmlOutput(\n mergedSchema: Record<string, unknown>,\n schemaPaths: string[],\n options: GenerateCommandOptions,\n): string {\n const generate = getGenerateFunction(options.dialect);\n return (\n generate({\n schema: mergedSchema,\n source: schemaPaths[0],\n }) || \"\"\n );\n}\n\n/**\n * Generate Markdown format output\n */\nfunction generateMarkdownOutput(\n intermediateSchema: IntermediateSchema,\n options: GenerateCommandOptions,\n): string {\n const markdownFormatter = new MarkdownFormatter();\n const markdown = markdownFormatter.format(intermediateSchema);\n\n // Include ER diagram unless --no-er-diagram is specified\n if (options.erDiagram) {\n const mermaidFormatter = new MermaidErDiagramFormatter();\n const erDiagram = mermaidFormatter.format(intermediateSchema);\n\n return `${markdown}\\n\\n---\\n\\n## ER Diagram\\n\\n\\`\\`\\`mermaid\\n${erDiagram}\\n\\`\\`\\``;\n }\n\n return markdown;\n}\n\n/**\n * Write Markdown to multiple files (one per table)\n */\nfunction writeMarkdownMultipleFiles(\n intermediateSchema: IntermediateSchema,\n outputDir: string,\n options: GenerateCommandOptions,\n): void {\n // Ensure output directory exists\n mkdirSync(outputDir, { recursive: true });\n\n const markdownFormatter = new MarkdownFormatter({ linkFormat: \"file\" });\n\n // Write README.md with index\n const index = markdownFormatter.generateIndex(intermediateSchema);\n let readme = `${index}\\n`;\n\n // Add ER diagram to README unless disabled\n if (options.erDiagram) {\n const mermaidFormatter = new MermaidErDiagramFormatter();\n const erDiagram = mermaidFormatter.format(intermediateSchema);\n readme += `\\n---\\n\\n## ER Diagram\\n\\n\\`\\`\\`mermaid\\n${erDiagram}\\n\\`\\`\\`\\n`;\n }\n\n writeFileSync(join(outputDir, \"README.md\"), readme, \"utf-8\");\n\n // Write individual table files\n for (const table of intermediateSchema.tables) {\n const tableDoc = markdownFormatter.generateTableDoc(table, intermediateSchema);\n const fileName = `${table.name}.md`;\n writeFileSync(join(outputDir, fileName), `# ${table.name}\\n\\n${tableDoc}\\n`, \"utf-8\");\n }\n}\n\n/**\n * Write single Markdown file\n */\nfunction writeSingleMarkdownFile(content: string, outputPath: string): void {\n const dir = dirname(outputPath);\n mkdirSync(dir, { recursive: true });\n writeFileSync(outputPath, content.endsWith(\"\\n\") ? content : content + \"\\n\", \"utf-8\");\n}\n\n/**\n * Run the generate command\n */\nasync function runGenerate(schema: string, options: GenerateCommandOptions): Promise<void> {\n const schemaPaths = resolveSchemaPath(schema);\n\n try {\n // Merge all schema modules\n const mergedSchema: Record<string, unknown> = {};\n\n for (const schemaPath of schemaPaths) {\n const schemaUrl = pathToFileURL(schemaPath).href;\n const cacheBuster = options.watch ? `?t=${Date.now()}` : \"\";\n\n try {\n const schemaModule = (await import(schemaUrl + cacheBuster)) as Record<string, unknown>;\n Object.assign(mergedSchema, schemaModule);\n } catch (error) {\n if (error instanceof Error) {\n console.error(`Error importing ${schemaPath}: ${error.message}`);\n console.error(\"\\nPossible causes:\");\n console.error(\"- Syntax error in the schema file\");\n console.error(\"- Missing dependencies (make sure drizzle-orm is installed)\");\n console.error(\"- Circular dependencies between schema files\");\n }\n throw error;\n }\n }\n\n if (options.format === \"markdown\") {\n // Generate Markdown format\n const GeneratorClass = getGeneratorClass(options.dialect);\n const generator = new GeneratorClass({\n schema: mergedSchema,\n source: schemaPaths[0],\n });\n const intermediateSchema = generator.toIntermediateSchema();\n\n if (options.singleFile) {\n // Single file Markdown output\n const content = generateMarkdownOutput(intermediateSchema, options);\n\n if (options.output) {\n // Check for existing file if --force is not specified\n if (!options.force && existsSync(options.output)) {\n console.error(\n `Error: Output file already exists: ${options.output}\\nUse --force to overwrite existing files.`,\n );\n process.exit(1);\n }\n writeSingleMarkdownFile(content, options.output);\n console.log(`Markdown generated: ${options.output}`);\n } else {\n console.log(content);\n }\n } else {\n // Multiple files Markdown output\n if (!options.output) {\n // If no output specified, default to stdout with single file format\n const content = generateMarkdownOutput(intermediateSchema, options);\n console.log(content);\n } else {\n // Check for existing files if --force is not specified\n if (!options.force) {\n const tableNames = intermediateSchema.tables.map((t) => t.name);\n const existingFiles = hasExistingFiles(options.output, tableNames);\n if (existingFiles.length > 0) {\n console.error(\n `Error: The following files already exist:\\n${existingFiles.map((f) => ` - ${f}`).join(\"\\n\")}\\nUse --force to overwrite existing files.`,\n );\n process.exit(1);\n }\n }\n writeMarkdownMultipleFiles(intermediateSchema, options.output, options);\n console.log(`Markdown generated: ${options.output}/`);\n }\n }\n } else {\n // Generate DBML format (default)\n const dbml = generateDbmlOutput(mergedSchema, schemaPaths, options);\n\n if (options.output) {\n // Check for existing file if --force is not specified\n if (!options.force && existsSync(options.output)) {\n console.error(\n `Error: Output file already exists: ${options.output}\\nUse --force to overwrite existing files.`,\n );\n process.exit(1);\n }\n const dir = dirname(options.output);\n mkdirSync(dir, { recursive: true });\n writeFileSync(options.output, dbml.endsWith(\"\\n\") ? dbml : dbml + \"\\n\", \"utf-8\");\n console.log(`DBML generated: ${options.output}`);\n } else {\n console.log(dbml);\n }\n }\n } catch (error) {\n if (error instanceof Error) {\n console.error(`Error generating output: ${error.message}`);\n } else {\n console.error(\"Error generating output:\", error);\n }\n process.exit(1);\n }\n}\n\n/**\n * Watch mode: regenerate on file changes\n */\nfunction watchSchema(schema: string, options: GenerateCommandOptions): void {\n const schemaPath = resolve(process.cwd(), schema);\n\n console.log(`Watching for changes: ${schemaPath}`);\n\n let debounceTimer: NodeJS.Timeout | null = null;\n\n watch(schemaPath, async (eventType) => {\n if (eventType === \"change\") {\n // Debounce to avoid multiple triggers\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n }\n\n debounceTimer = setTimeout(async () => {\n console.log(\"\\nFile changed, regenerating...\");\n try {\n const output = await generateFromSchema(schemaPath, options);\n const formatLabel = options.format === \"markdown\" ? \"Markdown\" : \"DBML\";\n const isMultiFile =\n options.format === \"markdown\" && !options.singleFile && options.output;\n\n if (!options.output && output) {\n console.log(output);\n } else if (options.output) {\n const outputLabel = isMultiFile ? `${options.output}/` : options.output;\n console.log(`${formatLabel} regenerated: ${outputLabel}`);\n }\n } catch (error) {\n if (error instanceof Error) {\n console.error(`Error: ${error.message}`);\n } else {\n console.error(\"Error:\", error);\n }\n }\n }, 100);\n }\n });\n}\n\nprogram\n .command(\"generate\")\n .description(\"Generate documentation from Drizzle schema files\")\n .argument(\"<schema>\", \"Path to Drizzle schema file or directory\")\n .option(\"-o, --output <path>\", \"Output file or directory path\")\n .option(\"-d, --dialect <dialect>\", \"Database dialect (postgresql, mysql, sqlite)\", \"postgresql\")\n .option(\"-f, --format <format>\", \"Output format (dbml, markdown)\", \"dbml\")\n .option(\"-w, --watch\", \"Watch for file changes and regenerate\")\n .option(\"--single-file\", \"Output Markdown as a single file (for markdown format)\")\n .option(\"--no-er-diagram\", \"Exclude ER diagram from Markdown output\")\n .option(\"--force\", \"Overwrite existing files without confirmation\")\n .action(async (schema: string, options: GenerateCommandOptions) => {\n // Validate dialect\n const validDialects: Dialect[] = [\"postgresql\", \"mysql\", \"sqlite\"];\n if (!validDialects.includes(options.dialect)) {\n console.error(\n `Error: Invalid dialect \"${options.dialect}\". Valid options: ${validDialects.join(\", \")}`,\n );\n process.exit(1);\n }\n\n // Validate format\n const validFormats: OutputFormat[] = [\"dbml\", \"markdown\"];\n if (!validFormats.includes(options.format)) {\n console.error(\n `Error: Invalid format \"${options.format}\". Valid options: ${validFormats.join(\", \")}`,\n );\n process.exit(1);\n }\n\n // Warn if --single-file or --no-er-diagram used with non-markdown format\n if (options.format !== \"markdown\") {\n if (options.singleFile) {\n console.warn(\"Warning: --single-file is only applicable with --format markdown\");\n }\n if (!options.erDiagram) {\n console.warn(\"Warning: --no-er-diagram is only applicable with --format markdown\");\n }\n }\n\n // Initial generation\n await runGenerate(schema, options);\n\n // Start watch mode if requested\n if (options.watch) {\n watchSchema(schema, options);\n }\n });\n\nprogram.parse();\n\n// Cleanup: Unregister tsx loader when process exits\nprocess.on(\"exit\", () => {\n unregister();\n});\n"],"names":["unregister","register","program","Command","packageJsonPath","join","packageJson","readFileSync","getGenerateFunction","dialect","mysqlGenerate","sqliteGenerate","pgGenerate","getGeneratorClass","MySqlGenerator","SqliteGenerator","PgGenerator","hasExistingFiles","outputDir","tableNames","existingFiles","existsSync","readmePath","tableName","tablePath","generateFromSchema","schemaPath","options","schemaUrl","pathToFileURL","cacheBuster","schemaModule","GeneratorClass","intermediateSchema","writeMarkdownMultipleFiles","generateMarkdownOutput","findSchemaFiles","dirPath","files","entries","readdirSync","entry","fullPath","error","resolveSchemaPath","schema","resolve","lstatSync","schemaFiles","generateDbmlOutput","mergedSchema","schemaPaths","markdown","MarkdownFormatter","erDiagram","MermaidErDiagramFormatter","mkdirSync","markdownFormatter","readme","writeFileSync","table","tableDoc","fileName","writeSingleMarkdownFile","content","outputPath","dir","dirname","runGenerate","t","dbml","watchSchema","debounceTimer","watch","eventType","output","formatLabel","isMultiFile","outputLabel","validDialects","validFormats"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * CLI for drizzle-docs-generator\n *\n * Generates DBML files from Drizzle ORM schema definitions.\n */\n\nimport { Command } from \"commander\";\nimport {\n existsSync,\n lstatSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n watch,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { pgGenerate } from \"../generator/pg\";\nimport { mysqlGenerate } from \"../generator/mysql\";\nimport { sqliteGenerate } from \"../generator/sqlite\";\nimport { PgGenerator } from \"../generator/pg\";\nimport { MySqlGenerator } from \"../generator/mysql\";\nimport { SqliteGenerator } from \"../generator/sqlite\";\nimport { MarkdownFormatter } from \"../formatter/markdown\";\nimport { MermaidErDiagramFormatter } from \"../formatter/mermaid\";\nimport { register } from \"tsx/esm/api\";\nimport type { IntermediateSchema } from \"../types\";\n\n// Register tsx loader to support TypeScript and extensionless imports\nconst unregister = register();\n\nconst program = new Command();\n\n// Use import.meta.dirname (Node 20.11+) to resolve package.json\n// This works correctly even after bundling\nconst packageJsonPath = join(import.meta.dirname, \"../../package.json\");\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\")) as {\n version: string;\n description: string;\n};\n\nprogram.name(\"drizzle-docs\").description(packageJson.description).version(packageJson.version);\n\ntype Dialect = \"postgresql\" | \"mysql\" | \"sqlite\";\ntype OutputFormat = \"dbml\" | \"markdown\";\n\ninterface GenerateCommandOptions {\n output?: string;\n dialect: Dialect;\n watch?: boolean;\n format: OutputFormat;\n singleFile?: boolean;\n erDiagram: boolean; // commander uses --no-er-diagram which sets erDiagram to false\n force?: boolean; // skip overwrite confirmation for existing files\n}\n\n/**\n * Get the generate function based on dialect\n */\nfunction getGenerateFunction(dialect: Dialect) {\n switch (dialect) {\n case \"mysql\":\n return mysqlGenerate;\n case \"sqlite\":\n return sqliteGenerate;\n case \"postgresql\":\n default:\n return pgGenerate;\n }\n}\n\n/**\n * Get the generator class based on dialect\n */\nfunction getGeneratorClass(dialect: Dialect) {\n switch (dialect) {\n case \"mysql\":\n return MySqlGenerator;\n case \"sqlite\":\n return SqliteGenerator;\n case \"postgresql\":\n default:\n return PgGenerator;\n }\n}\n\n/**\n * Check if output directory has existing files\n */\nfunction hasExistingFiles(outputDir: string, tableNames: string[]): string[] {\n const existingFiles: string[] = [];\n\n if (!existsSync(outputDir)) {\n return existingFiles;\n }\n\n const readmePath = join(outputDir, \"README.md\");\n if (existsSync(readmePath)) {\n existingFiles.push(readmePath);\n }\n\n for (const tableName of tableNames) {\n const tablePath = join(outputDir, `${tableName}.md`);\n if (existsSync(tablePath)) {\n existingFiles.push(tablePath);\n }\n }\n\n return existingFiles;\n}\n\n/**\n * Generate output from a schema file (for watch mode)\n * Returns the generated output string for single-file formats,\n * or writes multiple files directly for multi-file markdown\n */\nasync function generateFromSchema(\n schemaPath: string,\n options: GenerateCommandOptions,\n): Promise<string | undefined> {\n // Use file URL for dynamic import (required for ESM)\n const schemaUrl = pathToFileURL(schemaPath).href;\n\n // Dynamic import with cache busting for watch mode\n const cacheBuster = options.watch ? `?t=${Date.now()}` : \"\";\n const schemaModule = (await import(schemaUrl + cacheBuster)) as Record<string, unknown>;\n\n if (options.format === \"markdown\") {\n const GeneratorClass = getGeneratorClass(options.dialect);\n const generator = new GeneratorClass({\n schema: schemaModule,\n source: schemaPath,\n });\n const intermediateSchema = generator.toIntermediateSchema();\n\n // Handle multi-file output in watch mode\n if (!options.singleFile && options.output) {\n writeMarkdownMultipleFiles(intermediateSchema, options.output, options);\n return undefined;\n }\n\n return generateMarkdownOutput(intermediateSchema, options);\n } else {\n const generate = getGenerateFunction(options.dialect);\n return generate({\n schema: schemaModule,\n source: schemaPath,\n });\n }\n}\n\n/**\n * Find all TypeScript schema files in a directory\n */\nfunction findSchemaFiles(dirPath: string): string[] {\n const files: string[] = [];\n\n try {\n const entries = readdirSync(dirPath, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(dirPath, entry.name);\n\n if (entry.isDirectory()) {\n // Recursively search subdirectories\n files.push(...findSchemaFiles(fullPath));\n } else if (entry.isFile() && /\\.(ts|js|mts|mjs|cts|cjs)$/.test(entry.name)) {\n files.push(fullPath);\n }\n }\n } catch (error) {\n if (error instanceof Error) {\n console.error(`Error reading directory ${dirPath}: ${error.message}`);\n }\n }\n\n return files;\n}\n\n/**\n * Resolve schema path (file or directory)\n */\nfunction resolveSchemaPath(schema: string): string[] {\n const schemaPath = resolve(process.cwd(), schema);\n\n // Check if path exists\n if (!existsSync(schemaPath)) {\n console.error(`Error: Schema path not found: ${schemaPath}`);\n process.exit(1);\n }\n\n // Check if it's a directory\n const stats = lstatSync(schemaPath);\n if (stats.isDirectory()) {\n const schemaFiles = findSchemaFiles(schemaPath);\n if (schemaFiles.length === 0) {\n console.error(`Error: No schema files found in directory: ${schemaPath}`);\n process.exit(1);\n }\n return schemaFiles;\n }\n\n // Single file\n return [schemaPath];\n}\n\n/**\n * Generate DBML format output\n */\nfunction generateDbmlOutput(\n mergedSchema: Record<string, unknown>,\n schemaPaths: string[],\n options: GenerateCommandOptions,\n): string {\n const generate = getGenerateFunction(options.dialect);\n return (\n generate({\n schema: mergedSchema,\n source: schemaPaths[0],\n }) || \"\"\n );\n}\n\n/**\n * Generate Markdown format output\n */\nfunction generateMarkdownOutput(\n intermediateSchema: IntermediateSchema,\n options: GenerateCommandOptions,\n): string {\n const markdownFormatter = new MarkdownFormatter();\n const markdown = markdownFormatter.format(intermediateSchema);\n\n // Include ER diagram unless --no-er-diagram is specified\n if (options.erDiagram) {\n const mermaidFormatter = new MermaidErDiagramFormatter();\n const erDiagram = mermaidFormatter.format(intermediateSchema);\n\n return `${markdown}\\n\\n---\\n\\n## ER Diagram\\n\\n\\`\\`\\`mermaid\\n${erDiagram}\\n\\`\\`\\``;\n }\n\n return markdown;\n}\n\n/**\n * Write Markdown to multiple files (one per table)\n */\nfunction writeMarkdownMultipleFiles(\n intermediateSchema: IntermediateSchema,\n outputDir: string,\n options: GenerateCommandOptions,\n): void {\n // Ensure output directory exists\n mkdirSync(outputDir, { recursive: true });\n\n const markdownFormatter = new MarkdownFormatter({ linkFormat: \"file\" });\n\n // Write README.md with index\n const index = markdownFormatter.generateIndex(intermediateSchema);\n let readme = `${index}\\n`;\n\n // Add ER diagram to README unless disabled\n if (options.erDiagram) {\n const mermaidFormatter = new MermaidErDiagramFormatter();\n const erDiagram = mermaidFormatter.format(intermediateSchema);\n readme += `\\n---\\n\\n## ER Diagram\\n\\n\\`\\`\\`mermaid\\n${erDiagram}\\n\\`\\`\\`\\n`;\n }\n\n writeFileSync(join(outputDir, \"README.md\"), readme, \"utf-8\");\n\n // Write individual table files\n for (const table of intermediateSchema.tables) {\n const tableDoc = markdownFormatter.generateTableDoc(table, intermediateSchema);\n const fileName = `${table.name}.md`;\n writeFileSync(join(outputDir, fileName), `# ${table.name}\\n\\n${tableDoc}\\n`, \"utf-8\");\n }\n}\n\n/**\n * Write single Markdown file\n */\nfunction writeSingleMarkdownFile(content: string, outputPath: string): void {\n const dir = dirname(outputPath);\n mkdirSync(dir, { recursive: true });\n writeFileSync(outputPath, content.endsWith(\"\\n\") ? content : content + \"\\n\", \"utf-8\");\n}\n\n/**\n * Run the generate command\n */\nasync function runGenerate(schema: string, options: GenerateCommandOptions): Promise<void> {\n const schemaPaths = resolveSchemaPath(schema);\n\n try {\n // Merge all schema modules\n const mergedSchema: Record<string, unknown> = {};\n\n for (const schemaPath of schemaPaths) {\n const schemaUrl = pathToFileURL(schemaPath).href;\n const cacheBuster = options.watch ? `?t=${Date.now()}` : \"\";\n\n try {\n const schemaModule = (await import(schemaUrl + cacheBuster)) as Record<string, unknown>;\n Object.assign(mergedSchema, schemaModule);\n } catch (error) {\n if (error instanceof Error) {\n console.error(`Error importing ${schemaPath}: ${error.message}`);\n console.error(\"\\nPossible causes:\");\n console.error(\"- Syntax error in the schema file\");\n console.error(\"- Missing dependencies (make sure drizzle-orm is installed)\");\n console.error(\"- Circular dependencies between schema files\");\n }\n throw error;\n }\n }\n\n if (options.format === \"markdown\") {\n // Generate Markdown format\n const GeneratorClass = getGeneratorClass(options.dialect);\n const generator = new GeneratorClass({\n schema: mergedSchema,\n source: schemaPaths[0],\n });\n const intermediateSchema = generator.toIntermediateSchema();\n\n if (options.singleFile) {\n // Single file Markdown output\n const content = generateMarkdownOutput(intermediateSchema, options);\n\n if (options.output) {\n // Check for existing file if --force is not specified\n if (!options.force && existsSync(options.output)) {\n console.error(\n `Error: Output file already exists: ${options.output}\\nUse --force to overwrite existing files.`,\n );\n process.exit(1);\n }\n writeSingleMarkdownFile(content, options.output);\n console.log(`Markdown generated: ${options.output}`);\n } else {\n console.log(content);\n }\n } else {\n // Multiple files Markdown output\n if (!options.output) {\n // If no output specified, default to stdout with single file format\n const content = generateMarkdownOutput(intermediateSchema, options);\n console.log(content);\n } else {\n // Check for existing files if --force is not specified\n if (!options.force) {\n const tableNames = intermediateSchema.tables.map((t) => t.name);\n const existingFiles = hasExistingFiles(options.output, tableNames);\n if (existingFiles.length > 0) {\n console.error(\n `Error: The following files already exist:\\n${existingFiles.map((f) => ` - ${f}`).join(\"\\n\")}\\nUse --force to overwrite existing files.`,\n );\n process.exit(1);\n }\n }\n writeMarkdownMultipleFiles(intermediateSchema, options.output, options);\n console.log(`Markdown generated: ${options.output}/`);\n }\n }\n } else {\n // Generate DBML format\n const dbml = generateDbmlOutput(mergedSchema, schemaPaths, options);\n\n if (options.output) {\n // Check for existing file if --force is not specified\n if (!options.force && existsSync(options.output)) {\n console.error(\n `Error: Output file already exists: ${options.output}\\nUse --force to overwrite existing files.`,\n );\n process.exit(1);\n }\n const dir = dirname(options.output);\n mkdirSync(dir, { recursive: true });\n writeFileSync(options.output, dbml.endsWith(\"\\n\") ? dbml : dbml + \"\\n\", \"utf-8\");\n console.log(`DBML generated: ${options.output}`);\n } else {\n console.log(dbml);\n }\n }\n } catch (error) {\n if (error instanceof Error) {\n console.error(`Error generating output: ${error.message}`);\n } else {\n console.error(\"Error generating output:\", error);\n }\n process.exit(1);\n }\n}\n\n/**\n * Watch mode: regenerate on file changes\n */\nfunction watchSchema(schema: string, options: GenerateCommandOptions): void {\n const schemaPath = resolve(process.cwd(), schema);\n\n console.log(`Watching for changes: ${schemaPath}`);\n\n let debounceTimer: NodeJS.Timeout | null = null;\n\n watch(schemaPath, async (eventType) => {\n if (eventType === \"change\") {\n // Debounce to avoid multiple triggers\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n }\n\n debounceTimer = setTimeout(async () => {\n console.log(\"\\nFile changed, regenerating...\");\n try {\n const output = await generateFromSchema(schemaPath, options);\n const formatLabel = options.format === \"markdown\" ? \"Markdown\" : \"DBML\";\n const isMultiFile =\n options.format === \"markdown\" && !options.singleFile && options.output;\n\n if (!options.output && output) {\n console.log(output);\n } else if (options.output) {\n const outputLabel = isMultiFile ? `${options.output}/` : options.output;\n console.log(`${formatLabel} regenerated: ${outputLabel}`);\n }\n } catch (error) {\n if (error instanceof Error) {\n console.error(`Error: ${error.message}`);\n } else {\n console.error(\"Error:\", error);\n }\n }\n }, 100);\n }\n });\n}\n\nprogram\n .command(\"generate\")\n .description(\"Generate documentation from Drizzle schema files\")\n .argument(\"<schema>\", \"Path to Drizzle schema file or directory\")\n .option(\"-o, --output <path>\", \"Output file or directory path\")\n .option(\"-d, --dialect <dialect>\", \"Database dialect (postgresql, mysql, sqlite)\", \"postgresql\")\n .option(\"-f, --format <format>\", \"Output format (dbml, markdown)\", \"markdown\")\n .option(\"-w, --watch\", \"Watch for file changes and regenerate\")\n .option(\"--single-file\", \"Output Markdown as a single file (for markdown format)\")\n .option(\"--no-er-diagram\", \"Exclude ER diagram from Markdown output\")\n .option(\"--force\", \"Overwrite existing files without confirmation\")\n .action(async (schema: string, options: GenerateCommandOptions) => {\n // Validate dialect\n const validDialects: Dialect[] = [\"postgresql\", \"mysql\", \"sqlite\"];\n if (!validDialects.includes(options.dialect)) {\n console.error(\n `Error: Invalid dialect \"${options.dialect}\". Valid options: ${validDialects.join(\", \")}`,\n );\n process.exit(1);\n }\n\n // Validate format\n const validFormats: OutputFormat[] = [\"dbml\", \"markdown\"];\n if (!validFormats.includes(options.format)) {\n console.error(\n `Error: Invalid format \"${options.format}\". Valid options: ${validFormats.join(\", \")}`,\n );\n process.exit(1);\n }\n\n // Warn if --single-file or --no-er-diagram used with non-markdown format\n if (options.format !== \"markdown\") {\n if (options.singleFile) {\n console.warn(\"Warning: --single-file is only applicable with --format markdown\");\n }\n if (!options.erDiagram) {\n console.warn(\"Warning: --no-er-diagram is only applicable with --format markdown\");\n }\n }\n\n // Initial generation\n await runGenerate(schema, options);\n\n // Start watch mode if requested\n if (options.watch) {\n watchSchema(schema, options);\n }\n });\n\nprogram.parse();\n\n// Cleanup: Unregister tsx loader when process exits\nprocess.on(\"exit\", () => {\n unregister();\n});\n"],"names":["unregister","register","program","Command","packageJsonPath","join","packageJson","readFileSync","getGenerateFunction","dialect","mysqlGenerate","sqliteGenerate","pgGenerate","getGeneratorClass","MySqlGenerator","SqliteGenerator","PgGenerator","hasExistingFiles","outputDir","tableNames","existingFiles","existsSync","readmePath","tableName","tablePath","generateFromSchema","schemaPath","options","schemaUrl","pathToFileURL","cacheBuster","schemaModule","GeneratorClass","intermediateSchema","writeMarkdownMultipleFiles","generateMarkdownOutput","findSchemaFiles","dirPath","files","entries","readdirSync","entry","fullPath","error","resolveSchemaPath","schema","resolve","lstatSync","schemaFiles","generateDbmlOutput","mergedSchema","schemaPaths","markdown","MarkdownFormatter","erDiagram","MermaidErDiagramFormatter","mkdirSync","markdownFormatter","readme","writeFileSync","table","tableDoc","fileName","writeSingleMarkdownFile","content","outputPath","dir","dirname","runGenerate","t","dbml","watchSchema","debounceTimer","watch","eventType","output","formatLabel","isMultiFile","outputLabel","validDialects","validFormats"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"integration-test-utils.d.ts","sourceRoot":"","sources":["../../src/cli/integration-test-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAIrF,eAAO,MAAM,YAAY,QAA8C,CAAC;AACxE,eAAO,MAAM,YAAY,QAAqC,CAAC;AAC/D,eAAO,MAAM,YAAY,QAAwC,CAAC;AAClE,eAAO,MAAM,eAAe,QAAwC,CAAC;AACrE,eAAO,MAAM,eAAe,QAA2C,CAAC;AACxE,eAAO,MAAM,gBAAgB,QAAyC,CAAC;AACvE,eAAO,MAAM,gBAAgB,QAA4C,CAAC;AAG1E,eAAO,MAAM,eAAe,QAA2D,CAAC;AAGxF,eAAO,MAAM,eAAe,UAAsD,CAAC;AAEnF;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAa3C;AAGD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC;AACtE,OAAO,EAAE,IAAI,EAAE,CAAC"}
1
+ {"version":3,"file":"integration-test-utils.d.ts","sourceRoot":"","sources":["../../src/cli/integration-test-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAIrF,eAAO,MAAM,YAAY,QAA8C,CAAC;AACxE,eAAO,MAAM,YAAY,QAAwC,CAAC;AAClE,eAAO,MAAM,YAAY,QAAwC,CAAC;AAClE,eAAO,MAAM,eAAe,QAA2C,CAAC;AACxE,eAAO,MAAM,eAAe,QAA2C,CAAC;AACxE,eAAO,MAAM,gBAAgB,QAA4C,CAAC;AAC1E,eAAO,MAAM,gBAAgB,QAA4C,CAAC;AAG1E,eAAO,MAAM,eAAe,QAA2D,CAAC;AAGxF,eAAO,MAAM,eAAe,UAAsD,CAAC;AAEnF;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAa3C;AAGD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC;AACtE,OAAO,EAAE,IAAI,EAAE,CAAC"}
@@ -8,7 +8,6 @@ import { OutputFormatter, FormatterOptions } from './types';
8
8
  */
9
9
  export declare class DbmlFormatter implements OutputFormatter {
10
10
  private options;
11
- private databaseType;
12
11
  /**
13
12
  * Create a new DbmlFormatter
14
13
  *
@@ -46,6 +45,11 @@ export declare class DbmlFormatter implements OutputFormatter {
46
45
  * - Strings: already wrapped with single quotes (e.g., "'user'")
47
46
  * - Numbers/booleans: as-is (e.g., "true", "42")
48
47
  * - null: "null"
48
+ *
49
+ * DBML syntax requires:
50
+ * - SQL functions/expressions: wrapped in backticks (e.g., `now()`)
51
+ * - Strings: single quotes (e.g., 'user')
52
+ * - Numbers/booleans/null: as-is
49
53
  */
50
54
  private formatDefaultValue;
51
55
  /**
@@ -67,10 +71,9 @@ export declare class DbmlFormatter implements OutputFormatter {
67
71
  */
68
72
  private getRelationType;
69
73
  /**
70
- * Escape a name for DBML based on database type
74
+ * Escape a name for DBML
71
75
  *
72
- * - PostgreSQL/SQLite: Use double quotes ("name")
73
- * - MySQL: Use backticks (`name`)
76
+ * DBML uses double quotes for all database types
74
77
  */
75
78
  private escapeName;
76
79
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"dbml.d.ts","sourceRoot":"","sources":["../../src/formatter/dbml.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAQnB,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAYjE;;;;;GAKG;AACH,qBAAa,aAAc,YAAW,eAAe;IACnD,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,YAAY,CAA8B;IAElD;;;;OAIG;gBACS,OAAO,GAAE,gBAAqB;IAI1C;;;;;OAKG;IACH,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM;IA0B1C;;OAEG;IACH,OAAO,CAAC,UAAU;IAWlB;;OAEG;IACH,OAAO,CAAC,WAAW;IA8BnB;;OAEG;IACH,OAAO,CAAC,YAAY;IAapB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAyB3B;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IA2B1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAc1B;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IA6C1B;;OAEG;IACH,OAAO,CAAC,cAAc;IAsBtB;;OAEG;IACH,OAAO,CAAC,eAAe;IAavB;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAQlB;;OAEG;IACH,OAAO,CAAC,YAAY;CAGrB"}
1
+ {"version":3,"file":"dbml.d.ts","sourceRoot":"","sources":["../../src/formatter/dbml.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAOnB,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAYjE;;;;;GAKG;AACH,qBAAa,aAAc,YAAW,eAAe;IACnD,OAAO,CAAC,OAAO,CAA6B;IAE5C;;;;OAIG;gBACS,OAAO,GAAE,gBAAqB;IAI1C;;;;;OAKG;IACH,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM;IAuB1C;;OAEG;IACH,OAAO,CAAC,UAAU;IAWlB;;OAEG;IACH,OAAO,CAAC,WAAW;IA8BnB;;OAEG;IACH,OAAO,CAAC,YAAY;IAapB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAyB3B;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,kBAAkB;IA4B1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAc1B;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IA6C1B;;OAEG;IACH,OAAO,CAAC,cAAc;IAsBtB;;OAEG;IACH,OAAO,CAAC,eAAe;IAavB;;;;OAIG;IACH,OAAO,CAAC,UAAU;IAIlB;;OAEG;IACH,OAAO,CAAC,YAAY;CAGrB"}
@@ -1,19 +1,18 @@
1
1
  import { DbmlBuilder as u } from "./dbml-builder.js";
2
- const p = {
2
+ const m = {
3
3
  includeComments: !0,
4
4
  includeIndexes: !0,
5
5
  includeConstraints: !0
6
6
  };
7
7
  class l {
8
8
  options;
9
- databaseType = "postgresql";
10
9
  /**
11
10
  * Create a new DbmlFormatter
12
11
  *
13
12
  * @param options - Formatter options
14
13
  */
15
14
  constructor(e = {}) {
16
- this.options = { ...p, ...e };
15
+ this.options = { ...m, ...e };
17
16
  }
18
17
  /**
19
18
  * Format the intermediate schema into DBML
@@ -23,7 +22,6 @@ class l {
23
22
  */
24
23
  format(e) {
25
24
  const t = new u();
26
- this.databaseType = e.databaseType;
27
25
  for (const n of e.enums)
28
26
  this.formatEnum(t, n), t.line();
29
27
  for (const n of e.tables)
@@ -75,6 +73,11 @@ class l {
75
73
  * - Strings: already wrapped with single quotes (e.g., "'user'")
76
74
  * - Numbers/booleans: as-is (e.g., "true", "42")
77
75
  * - null: "null"
76
+ *
77
+ * DBML syntax requires:
78
+ * - SQL functions/expressions: wrapped in backticks (e.g., `now()`)
79
+ * - Strings: single quotes (e.g., 'user')
80
+ * - Numbers/booleans/null: as-is
78
81
  */
79
82
  formatDefaultValue(e) {
80
83
  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, "\\'")}'`;
@@ -142,13 +145,12 @@ class l {
142
145
  }
143
146
  }
144
147
  /**
145
- * Escape a name for DBML based on database type
148
+ * Escape a name for DBML
146
149
  *
147
- * - PostgreSQL/SQLite: Use double quotes ("name")
148
- * - MySQL: Use backticks (`name`)
150
+ * DBML uses double quotes for all database types
149
151
  */
150
152
  escapeName(e) {
151
- return this.databaseType === "mysql" ? `\`${e}\`` : `"${e}"`;
153
+ return `"${e}"`;
152
154
  }
153
155
  /**
154
156
  * Escape a string for use in DBML single-quoted strings
@@ -1 +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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"}
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} 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\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 // 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 * DBML syntax requires:\n * - SQL functions/expressions: wrapped in backticks (e.g., `now()`)\n * - Strings: single quotes (e.g., 'user')\n * - Numbers/booleans/null: as-is\n */\n private formatDefaultValue(value: string): string {\n // If it looks like a SQL expression (contains parentheses or is a known function)\n // Wrap in backticks for dbdiagram.io compatibility\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\n *\n * DBML uses double quotes for all database types\n */\n private escapeName(name: string): string {\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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drizzle-docs-generator",
3
- "version": "0.4.1",
3
+ "version": "0.5.1",
4
4
  "description": "A CLI tool that generates DBML files from Drizzle ORM schema definitions.",
5
5
  "keywords": [
6
6
  "cli",
@@ -61,11 +61,11 @@
61
61
  "dev": "vite build --watch",
62
62
  "test": "vitest",
63
63
  "test:run": "vitest run",
64
- "test:integration": "vitest run --config vitest.integration.config.ts",
64
+ "test:integration": "rm -rf src/cli/__integration_test_output__ && vitest run --config vitest.integration.config.ts",
65
65
  "lint": "oxlint",
66
66
  "format": "oxfmt --write",
67
67
  "format:check": "oxfmt --check",
68
68
  "typecheck": "tsc --noEmit",
69
- "generate:examples": "node dist/cli/index.js generate examples/pg/schema.ts -d postgresql -f dbml -o examples/pg/schema.dbml --force && node dist/cli/index.js generate examples/pg/schema.ts -d postgresql -f markdown -o examples/pg/markdown --force && node dist/cli/index.js generate examples/mysql/schema.ts -d mysql -f dbml -o examples/mysql/schema.dbml --force && node dist/cli/index.js generate examples/mysql/schema.ts -d mysql -f markdown -o examples/mysql/markdown --force && node dist/cli/index.js generate examples/sqlite/schema.ts -d sqlite -f dbml -o examples/sqlite/schema.dbml --force && node dist/cli/index.js generate examples/sqlite/schema.ts -d sqlite -f markdown -o examples/sqlite/markdown --force"
69
+ "generate:examples": "node dist/cli/index.js generate examples/pg/v0/schema.ts -d postgresql -f dbml -o examples/pg/v0/schema.dbml --force && node dist/cli/index.js generate examples/pg/v0/schema.ts -d postgresql -f markdown -o examples/pg/v0/markdown --force && node dist/cli/index.js generate examples/pg/v1/schema.ts -d postgresql -f dbml -o examples/pg/v1/schema.dbml --force && node dist/cli/index.js generate examples/pg/v1/schema.ts -d postgresql -f markdown -o examples/pg/v1/markdown --force && node dist/cli/index.js generate examples/mysql/v0/schema.ts -d mysql -f dbml -o examples/mysql/v0/schema.dbml --force && node dist/cli/index.js generate examples/mysql/v0/schema.ts -d mysql -f markdown -o examples/mysql/v0/markdown --force && node dist/cli/index.js generate examples/mysql/v1/schema.ts -d mysql -f dbml -o examples/mysql/v1/schema.dbml --force && node dist/cli/index.js generate examples/mysql/v1/schema.ts -d mysql -f markdown -o examples/mysql/v1/markdown --force && node dist/cli/index.js generate examples/sqlite/v0/schema.ts -d sqlite -f dbml -o examples/sqlite/v0/schema.dbml --force && node dist/cli/index.js generate examples/sqlite/v0/schema.ts -d sqlite -f markdown -o examples/sqlite/v0/markdown --force && node dist/cli/index.js generate examples/sqlite/v1/schema.ts -d sqlite -f dbml -o examples/sqlite/v1/schema.dbml --force && node dist/cli/index.js generate examples/sqlite/v1/schema.ts -d sqlite -f markdown -o examples/sqlite/v1/markdown --force"
70
70
  }
71
71
  }