mikro-orm-markdown
mikro-orm-markdown 是一个microorm ERD生成器,创建 美人鱼ER图 和 Markdown数据库模式文档 从你的 MikroORM 实体。
使用CLI或TypeScript API来记录实体列、关系、索引、约束和JSDoc描述,而无需连接到实时数据库。
看到 microorm ERD示例输出。
座席用户(Claude Code和其他座席技能兼容工具)可以选择使用座席技能at skills/mikro-orm-markdown/ 要设置和排除此工具的故障-它不是NPM包的一部分。
深受启发 prisma-markdown 通过 @samchon. 谢谢你的好主意。
特性
- 美人鱼ERD图 从microorm实体元数据生成的
- Markdown模式文档 每个实体列表、实际的DB列名、键、可空性、描述、索引和约束
- jsdoc驱动的分组和可见性 通过
@namespace,@erd,@describe,@hidden - 不需要实时数据库连接 -从您的配置中使用microorm元数据发现
- 可跨通用SQL驱动程序工作 -覆盖了SQLite, PostgreSQL, MySQL和MariaDB的冒烟测试
MikroORM-specific概念
除了基于prism的工具所能表达的, mikro-orm-markdown 也可视化概念独特的microorm:
- 可嵌入 -存储在拥有实体的表中的值对象,可以是扁平的列(例如:
address_street,address_city)或作为JSON列,具体取决于@Embedded选项。没有创建单独的表。 - 单表继承(STI) -子类如
Dog和Cat共享一个animals表格。鉴别列(例如:type)区分每行属于哪个子类。 - @ formula -一个没有物理DB列的虚拟列。它的值在SELECT时由SQL表达式计算(例如:
LENGTH(name)).
需求
- Node.js >= 18
- 6号或7号 - - - - - -
@mikro-orm/core对等依赖是否与范围相关>=6.0.0 <8. microorm 7本身需要Node.js >= 22.17,因此在Node 18或20上只能安装v6。 - microorm配置文件 - CLI期望默认导出一个普通的microorm选项对象。
- 配套的microorm驱动包 -例如
@mikro-orm/postgresql,@mikro-orm/mysql,@mikro-orm/mariadb,或@mikro-orm/sqlite. 不需要实时数据库连接,但是kroorm仍然需要驱动程序来发现元数据。 - 装饰器或模式定义的实体 - - - - - -
@Entity()类从类中读取JSDoc。定义的实体EntitySchema(或microorm 7)defineEntity()(它建立在它的基础上)以相同的方式呈现并从导出的模式声明中读取JSDoc -参见 方案定义实体。 - 在microorm7中,从
@mikro-orm/decorators- v7把他们赶了出去@mikro-orm/core成@mikro-orm/decorators/legacy(打印稿experimentalDecorators),@mikro-orm/decorators/es(ES-standard修饰符)。两者都使用这个工具;在v6上,他们呆在里面@mikro-orm/core。 - 可解析的属性类型 -每个实体属性的类型必须在microorm发现期间被知道。使用显式的装饰器选项,例如
type:/entity:,或安装@mikro-orm/reflection以便CLI可以自动使用TsMorphMetadataProvider用于TypeScript源文件。 tsx用于TypeScript配置文件 -仅在加载a时需要.ts通过命令行配置microorm。.js配置文件不需要它。
如果你安装了
@mikro-orm/reflection请把它放在 完全相同的版本 作为@mikro-orm/core. MikroORM期待官方@mikro-orm/*包共享一个版本,不匹配会导致无法发现。
安装
npm install -D mikro-orm-markdown
# or
pnpm add -D mikro-orm-markdown
快速启动
添加一个脚本到您的 package.json,指出 --config 在你的microorm配置文件中:
{
"scripts": {
"erd": "mikro-orm-markdown --config ./mikro-orm.config.ts --out ./ERD.md --title 'My Database'"
}
}
.ts配置 -安装tsx作为开发依赖项(npm install -D tsx); 命令行将自动加载它,并且默认的MikroORM发现为entitiesTs除非你明确地设置preferTs。.js配置 -不需要额外的包装。可以是手写的,也可以是你自己的构建输出(例如。./dist/mikro-orm.config.js).
然后运行:
npm run erd
CLI选项
| 选项 | 默认的 | 描述 |
|---|---|---|
-c, --config <path> | (必需) | MikroORM配置文件路径 |
-o, --out <path> | ./ERD.md | 输出Markdown文件路径 |
-t, --title <string> | Database Schema | 生成文档的H1标题 |
-d, --description <string> | - - - - - - | 标题下方显示的可选描述段落 |
--tsconfig <path> | - - - - - - | tsconfig.json 加载时使用 .ts 配置;默认为配置文件旁边最近的一个 |
--src <paths...> | - - - - - - | 原始的TypeScript实体源路径/globs;只有当microorm从编译后的JavaScript中发现实体时才需要 |
--mermaid-layout <layout> | - - - - - - | 美人鱼布局引擎(dagre|elk|elk.stress). 省略以使用查看器的默认值。 |
--mermaid-theme <theme> | - - - - - - | 美人鱼主题(default|neutral|dark|forest|base). 省略以使用查看器的默认值。 |
对于长或多行描述,请使用 编程API 相反,它直接接受任何字符串,没有shell引用限制。
JSDoc标签
注释实体类或导出的模式声明,请参见 下面 -控制生成文档中的部分和可见性。JSDoc注释是从TypeScript实体源文件中读取的。
建议设置: 使用一个
.tsmicroorm配置entitiesTs指向源实体。在这个设置中,JSDoc是从原始TypeScript文件中读取的--src不需要。
/**
* Blog post authored by a registered user.
* @namespace Blog
*/
@Entity()
export class Post {
/** Post title */
@Property()
title!: string;
}
普通的JSDoc文本(没有标记)变成了描述 类 描述实体,以及a上面的文本 财产 描述其列。当一个属性没有JSDoc时,它的 @Property({ comment }) value (DDL列注释)被用作列描述。同样地,当一个类没有JSDoc描述时,它的 @Entity({ comment }) 值(DDL表注释)或 comment 在一个 EntitySchema)作为实体描述。
| 标签 | 描述 |
|---|---|
@namespace <Name> | 在节中包含实体 Name (ERD +文本表) |
@erd <Name> | 包括在节中 Name的ERD图 |
@describe <Name> | 包括在节中 Name仅限文本表 |
@hidden | 从整个文档中排除实体 |
对象中放置没有标记的实体 default 部分。
一个实体可以携带多个标签以出现在多个部分中。
方案定义实体
定义的实体 EntitySchema -或microorm 7的 defineEntity()——从导出的模式声明中读取JSDoc。上面的描述和每个标签的工作方式相同:
/**
* Blog post declared without a decorator class.
* @namespace Blog
*/
export const PostSchema = new EntitySchema({
name: 'Post',
properties: {
id: { primary: true, type: 'integer' },
/** Post title */
title: { type: 'string' },
},
});
- 名义模式 (没有
class:链接,如上面的例子)也从properties对象文字- microorm 7'sproperties: (p) => ({...})包括生成器回调。在列表中,它胜过comment属性选项,该选项将保留回退。 - 阶级维系模式 (
class:)从类中读取属性JSDoc。实体级的JSDoc逐个字段地合并类获胜的冲突,并且@hidden当任何位置都有它时应用。 - 如果模式定义的实体的声明不能被读取——在扫描的源代码中找不到,有歧义,或者只能在删除注释的编译JavaScript中找到——那么就会出现警告
@hidden那里写的字从来不会无声地掉落。
编译后的JavaScript构建
如果您的microorm配置从编译的 .js 文件,例如 entities: ['./dist/**/*.js'],仍然可以发现实体结构,但是JSDoc注释可能已经被剥离。
这意味着描述和标签,如 @namespace 和 @hidden 不能从中读出 .js 文件。
使用 --src 只有在这种情况下:
mikro-orm-markdown \
--config ./dist/mikro-orm.config.js \
--src "src/**/*.entity.ts"
如果 --src 不匹配文件或省略已发现的实体声明,生成失败而不是静默地生成不完整的文档。
基数的关系: @atLeastOne
@atLeastOne 是一个JSDoc标签,而不是TypeScript装饰器。
集合关系(1:N 或 M:N)呈现为 零个或多个 默认情况下。将集合属性标记为 @atLeastOne 将该集合端呈现为 一个或多个 而不是:
@Entity()
export class Author {
/** @atLeastOne */
@OneToMany(() => Post, (post) => post.author)
posts = new Collection<Post>(this);
}
这改变了ERD的边缘 Post }o--|| Author 成 Post }|--|| Author. 这只是一个文档提示—microorm没有模式级别的最小值,并且不强制计数。(Mermaid只区分零或多和一或多,所以不能表示更大的最小值。)
关系边具有 两端,独立设置:
- 单(1)面 (
@ManyToOne,或所有权@OneToOne) -自动从你的模式中读取,不需要标签: 一个 (||); 0或1 (o|)当nullable: true. 一个拥有的一对一的反方总是 0或1 -唯一的FK将引用限制在1,但不需要1。 - 收集(N)侧 (
@OneToMany/@ManyToMany) - - - 零个或多个 默认情况下;@atLeastOne将这一面提高到 一个或多个 (}o→}|,或o{→|{(取决于渲染集合的边的哪一边)。
四种组合(Post ↔ Author):
Post }o--|| Author → author 0+ posts, post exactly 1 author (default)
Post }o--o| Author → author 0+ posts, post 0-or-1 author (nullable: true)
Post }|--|| Author → author 1+ posts, post exactly 1 author (@atLeastOne)
Post }|--o| Author → author 1+ posts, post 0-or-1 author (both)
NestJS大摇大摆这五个标签是定制的
mikro-orm-markdown- Swagger忽略它们,所以即使实体类兼作dto也不会有功能冲突。(启用了Swagger注释内省功能后,普通的未标记的JSDoc描述可能仍然会出现在您的Swagger文档中。)
输出示例
鉴于这些实体:
/**
* Blog post authored by a registered user.
* @namespace Blog
*/
@Entity()
export class Post {
@PrimaryKey({ type: 'integer' })
id!: number;
/** Post title */
@Property({ type: 'string' })
title!: string;
@Property({ type: 'text', nullable: true })
body?: string;
@ManyToOne({ entity: () => Author })
author!: Author;
}
/** @namespace Blog */
@Entity()
export class Author {
@PrimaryKey({ type: 'integer' })
id!: number;
@Property({ type: 'string' })
name!: string;
@Property({ type: 'string', unique: true })
email!: string;
/** @atLeastOne */
@OneToMany({ entity: () => Post, mappedBy: 'author' })
posts = new Collection<Post>(this);
}
省略了导入。显式的
type:选项使示例在没有@mikro-orm/reflection。
两个实体共享 @namespace Blog 标签,所以他们降落在一个 ## Blog 部分。使用MikroORM的默认命名策略,生成的 ERD.md 包含如下的ERD:
erDiagram
Post {
integer id PK
string title
string body
integer author_id FK
}
Author {
integer id PK
string name
string email UK
}
Post }|--|| Author : "author"
代码如何映射到输出:
@namespace Blog→两个实体都分组在## Blog部分@ManyToOne({ entity: () => Author })→的Post来Author关系线和author_id FK列@atLeastOne在Author.posts→收集端呈现为一个或多个:Post }|--|| Authorunique: true在email→email被标记UK(唯一键)@Property({ nullable: true })在body→的Nullable细胞被标记Y/** Post title */→填满 描述 细胞的title
每个实体还获得一个列表。例如,生成的 Post 部分看起来像这样:
### Post
*Table: `post`*
> Blog post authored by a registered user.
| Column | Type | Key | Nullable | Description |
| --------- | ------- | ----------- | -------- | ----------- |
| id | integer | PK | | |
| title | string | | | Post title |
| body | text | | Y | |
| author_id | integer | FK (author) | | |
生成的输出中特定于microorm的注释:
| 注释 | 意义 |
|---|---|
formula: <expr> | 美人鱼的评论 @Formula 计算列 |
[EmbeddableType] | 从一个内联的扁平柱 @Embedded 值对象 |
discriminator | STI鉴别列 |
笔记
单表继承(STI)
STI是一种模式,其中多个实体类共享单个数据库表,使用鉴别符列区分行。
@Entity({ discriminatorColumn: 'type', abstract: true })
export class Animal {
@PrimaryKey({ type: 'integer' })
id!: number;
@Property({ type: 'string' })
name!: string;
}
@Entity({ discriminatorValue: 'dog' })
export class Dog extends Animal {
@Property({ type: 'string', nullable: true })
breed?: string;
}
当一个实体使用 discriminatorColumn, mikro-orm-markdown 自动检测。尽管子类共享一个物理表,但每个类都被绘制为它的 自己的盒子 所以这个图显示了每个子类的有效形状:
erDiagram
Animal {
integer id PK
string name
string type "discriminator"
}
Dog {
integer id PK
string name
string type
string breed
}
根(Animal)只列出共享列并标记鉴别符(type); 每个子类(Dog)重复继承的列并添加自己的列。
生成的Markdown表还包括STI注释,例如 STI root — discriminator column: type 在根和 Extends Animal (Single Table Inheritance, discriminator value: dog) 在每个子类上。
故障排除
“没有发现任何实体”
您的microorm配置没有找到任何实体。这通常意味着实体路径与CLI加载配置的方式不匹配:
- 如果你用的是
.ts命令行加载tsx自动且默认为preferTs: true),确保entitiesTs指向你的TypeScript源文件。 - 如果您使用的是编译过的
.js配置,确保entities指向 建立输出 (如。./dist/**/*.entity.js),并且您已经先运行了构建。 - MikroORM使用
entitiesTs在TypeScript模式下运行时entities否则-如果使用基于文件夹/文件的发现,请同时指定两者。
“请提供‘type’或‘entity’属性”
在元数据发现期间,microorm无法解析属性类型。CLI加载 .ts 款通过 tsx,所以使能 emitDecoratorMetadata 单凭一己之力无法修复这条道路。
用以下方法之一修复它:
- 添加显式的装饰器选项,例如
@Property({ type: 'string' })或@ManyToOne({ entity: () => User })。 - 安装
@mikro-orm/reflection在相同的版本@mikro-orm/core以便CLI可以自动使用TsMorphMetadataProvider。
“找不到模块”@/…’”(路径别名)
如果您的配置或实体使用 tsconfig 路径别名(例如 @/entities/user), tsx 当它找不到合适的时候可能无法解决它们 tsconfig.json。将配置文件保存在项目根目录下(在 tsconfig.json)避免了这种情况。如果你的配置在其他地方,显式传递正确的文件:
mikro-orm-markdown --config ./packages/api/mikro-orm.config.ts --tsconfig ./packages/api/tsconfig.json
缺少JSDoc标记,或者 @hidden 实体出现
您的实体可能是从编译的JavaScript中发现的。构建工具可能会从 .js 文件,描述, @namespace, @hidden 不能在那里读。
更喜欢 .ts 配置与 entitiesTs 指向源文件。如果必须从已编译的 .js,传递TypeScript的原始源代码:
mikro-orm-markdown --config ./dist/mikro-orm.config.js --src "src/**/*.entity.ts"
配置文件要求
配置文件必须有 默认的出口 普通配置对象的:
export default defineConfig({ ... }); // ✅
export const config = defineConfig({ ... }); // ❌ named export not supported
export default async () => defineConfig({ ... }); // ❌ functions/Promises not supported
如果您需要异步解析配置,请使用编程API(见下文)。
高级用法
编程API
如果您需要将ERD生成集成到自定义构建脚本或以编程方式处理输出:
import { writeFile } from 'node:fs/promises';
import { generateMarkdown } from 'mikro-orm-markdown';
import ormConfig from './mikro-orm.config.js';
const markdown = await generateMarkdown({
orm: ormConfig,
title: 'My Database',
description: 'Schema documentation generated from MikroORM metadata.',
});
await writeFile('./ERD.md', markdown, 'utf-8');
编程选项:
| 选项 | 描述 |
|---|---|
orm | microorm选项对象。必需的。 |
title | H1标题。默认为 Database Schema。 |
description | 标题下面的可选段落。与CLI标志不同的是,这可以是任何不涉及shell引用的字符串。 |
src | 原始的TypeScript实体源路径/globs。只在需要的时候 orm.entities 发现编译后的JavaScript。 |
onWarn | 回调非致命警告,如编译后的JavaScript JSDoc丢失。总是接收一个普通消息字符串。声明第二个参数的处理程序也会接收一个结构化的 { title, detail, impact, fix } 对象为长制导警告;直接传递的可变记录器(例如: console.warn)只接收字符串。 |
mermaid | 可选的美人鱼渲染选项。看到 美人鱼渲染选项 在下面。 |
如果你的microorm配置是异步的,自己解析它并传递结果的options对象:
const ormConfig = await createOrmConfig();
const markdown = await generateMarkdown({ orm: ormConfig });
美人鱼渲染选项
默认情况下,micro - form -markdown不会发出美人鱼标题配置。这保留了每个Markdown查看器的默认美人鱼渲染行为。
你可以通过CLI选择美人鱼的渲染选项:
mikro-orm-markdown --config ./mikro-orm.config.ts --mermaid-layout elk --mermaid-theme neutral
或者通过编程API:
const markdown = await generateMarkdown({
orm: ormConfig,
mermaid: {
layout: 'elk',
theme: 'forest',
},
});
当设置布局或主题时,将在每个布局或主题前添加一个YAML前文块 erDiagram 围墙:
```mermaid
---
config:
layout: elk
theme: forest
---
erDiagram
...
```
可用的布局值:
| 价值 | 描述 |
|---|---|
dagre | 美人鱼的默认分层布局。 |
elk | 备选布局引擎;可以改善更大或更密集的erd上的线路路由。 |
elk.stress | ELK强调布局变体。支持因美人鱼版本和查看器而异。 |
可用的主题值: default, neutral, dark, forest, base。
查看器支持
elk主题价值也各不相同。如果没有--mermaid-layout或--mermaid-theme,则不释放任何前置物质。
计划的特点
计划在未来的版本中提供以下特性。
--check 模式
一个 --check 当输出文件与当前实体元数据不同步时(不写入任何文件)以非零代码退出的标志。
用于CI管道来强制执行 ERD.md 总是与实体更改一起提交。
mikro-orm-markdown --config ./mikro-orm.config.ts --check
--watch 模式
一个 --watch 监视实体源文件并在每次更改时自动重新生成输出文档的标志。
在主动开发期间,当您希望ERD保持最新状态而无需手动运行CLI时,非常有用。
mikro-orm-markdown --config ./mikro-orm.config.ts --watch
许可证
麻省理工学院