mikro-orm-markdown 0.1.0-alpha.4 → 0.1.0-alpha.5

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/CHANGELOG.md CHANGED
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.1.0-alpha.5] - 2026-06-29
9
+
10
+ ### Added
11
+
12
+ - `--mermaid-layout <layout>` and `--mermaid-theme <theme>` CLI options to inject Mermaid YAML frontmatter into each `erDiagram` fence
13
+ - `mermaid` option in the programmatic API (`generateMarkdown({ mermaid: { layout, theme } })`) with the same effect
14
+ - `MermaidLayout`, `MermaidTheme`, and `MermaidRenderOptions` types exported from the public API
15
+ - When neither option is set, output is identical to previous versions — no frontmatter is emitted
16
+
8
17
  ## [0.1.0-alpha.4] - 2026-06-29
9
18
 
10
19
  ### Fixed
package/README.ko.md CHANGED
@@ -79,6 +79,8 @@ npm run erd
79
79
  | `-d, --description <string>` | — | 제목 아래에 표시할 설명 문단 (선택) |
80
80
  | `--tsconfig <path>` | — | `.ts` config 로드 시 사용할 `tsconfig.json`; 기본값은 config 파일 근처의 가장 가까운 파일 |
81
81
  | `--src <paths...>` | — | 원본 TypeScript 엔티티 소스 경로/glob; MikroORM이 컴파일된 JavaScript에서 엔티티를 discovery할 때만 필요 |
82
+ | `--mermaid-layout <layout>` | — | Mermaid 레이아웃 엔진 (`dagre\|elk\|elk.stress`). 생략하면 뷰어 기본값 사용. |
83
+ | `--mermaid-theme <theme>` | — | Mermaid 테마 (`default\|neutral\|dark\|forest\|base`). 생략하면 뷰어 기본값 사용. |
82
84
 
83
85
  > 설명이 길거나 여러 줄이라면 CLI 대신 [프로그래밍 API](#프로그래밍-api)를 사용하세요 — 쉘 인용 부호 제약 없이 문자열을 그대로 전달할 수 있습니다.
84
86
 
@@ -392,6 +394,7 @@ await writeFile('./ERD.md', markdown, 'utf-8');
392
394
  | `description` | 제목 아래에 표시할 설명 문단입니다. CLI flag와 달리 쉘 quoting 제약 없이 문자열을 그대로 전달할 수 있습니다. |
393
395
  | `src` | 원본 TypeScript 엔티티 소스 경로/glob입니다. `orm.entities`가 컴파일된 JavaScript를 discovery할 때만 필요합니다. |
394
396
  | `onWarn` | 컴파일된 JavaScript에서 JSDoc을 읽지 못하는 상황 같은 non-fatal warning을 받을 callback입니다. |
397
+ | `mermaid` | Mermaid 렌더링 옵션입니다. 아래 [Mermaid 렌더링 옵션](#mermaid-렌더링-옵션)을 참고하세요. |
395
398
 
396
399
  MikroORM config를 비동기적으로 만들어야 한다면 직접 resolve한 뒤 결과 options object를 전달하세요:
397
400
 
@@ -400,6 +403,56 @@ const ormConfig = await createOrmConfig();
400
403
  const markdown = await generateMarkdown({ orm: ormConfig });
401
404
  ```
402
405
 
406
+ ### Mermaid 렌더링 옵션
407
+
408
+ 기본적으로 mikro-orm-markdown은 Mermaid frontmatter config를 출력하지 않습니다. 이렇게 해야 각 Markdown 뷰어의 기본 Mermaid 렌더링 동작이 유지됩니다.
409
+
410
+ CLI에서 Mermaid 렌더링 옵션을 사용하려면:
411
+
412
+ ```bash
413
+ mikro-orm-markdown --config ./mikro-orm.config.ts --mermaid-layout elk
414
+ mikro-orm-markdown --config ./mikro-orm.config.ts --mermaid-theme forest
415
+ mikro-orm-markdown --config ./mikro-orm.config.ts --mermaid-layout elk --mermaid-theme neutral
416
+ ```
417
+
418
+ 프로그래밍 API에서는:
419
+
420
+ ```typescript
421
+ const markdown = await generateMarkdown({
422
+ orm: ormConfig,
423
+ mermaid: {
424
+ layout: 'elk',
425
+ theme: 'forest',
426
+ },
427
+ });
428
+ ```
429
+
430
+ layout 또는 theme을 지정하면 각 `erDiagram` 펜스 앞에 YAML frontmatter 블록이 삽입됩니다:
431
+
432
+ ````markdown
433
+ ```mermaid
434
+ ---
435
+ config:
436
+ layout: elk
437
+ theme: forest
438
+ ---
439
+ erDiagram
440
+ ...
441
+ ```
442
+ ````
443
+
444
+ **사용 가능한 layout 값:**
445
+
446
+ | 값 | 설명 |
447
+ | -- | ---- |
448
+ | `dagre` | Mermaid 기본 레이아웃 엔진. |
449
+ | `elk` | 대체 레이아웃 엔진. 엔티티가 많거나 관계선이 복잡한 ERD에서 선 라우팅을 개선할 수 있습니다. |
450
+ | `elk.stress` | ELK stress 레이아웃 변형. Mermaid 버전과 뷰어에 따라 지원 여부가 다릅니다. |
451
+
452
+ **사용 가능한 theme 값:** `default`, `neutral`, `dark`, `forest`, `base`.
453
+
454
+ > `elk`와 theme 지원 여부는 뷰어마다 다릅니다. `--mermaid-layout`이나 `--mermaid-theme`을 지정하지 않으면 frontmatter는 출력되지 않습니다.
455
+
403
456
  ## 라이선스
404
457
 
405
458
  MIT
package/README.md CHANGED
@@ -79,6 +79,8 @@ npm run erd
79
79
  | `-d, --description <string>` | — | Optional description paragraph shown below the title |
80
80
  | `--tsconfig <path>` | — | `tsconfig.json` used when loading a `.ts` config; defaults to the nearest one beside the config file |
81
81
  | `--src <paths...>` | — | Original TypeScript entity source paths/globs; only needed when MikroORM discovers entities from compiled JavaScript |
82
+ | `--mermaid-layout <layout>` | — | Mermaid layout engine (`dagre\|elk\|elk.stress`). Omit to use the viewer's default. |
83
+ | `--mermaid-theme <theme>` | — | Mermaid theme (`default\|neutral\|dark\|forest\|base`). Omit to use the viewer's default. |
82
84
 
83
85
  > For a long or multiline description, use the [programmatic API](#programmatic-api) instead — it accepts any string directly, without shell quoting limits.
84
86
 
@@ -392,6 +394,7 @@ Programmatic options:
392
394
  | `description` | Optional paragraph below the title. Unlike the CLI flag, this can be any string without shell quoting concerns. |
393
395
  | `src` | Original TypeScript entity source paths/globs. Only needed when `orm.entities` discovers compiled JavaScript. |
394
396
  | `onWarn` | Callback for non-fatal warnings, such as compiled JavaScript JSDoc loss. |
397
+ | `mermaid` | Optional Mermaid rendering options. See [Mermaid rendering options](#mermaid-rendering-options) below. |
395
398
 
396
399
  If your MikroORM config is asynchronous, resolve it yourself and pass the resulting options object:
397
400
 
@@ -400,6 +403,56 @@ const ormConfig = await createOrmConfig();
400
403
  const markdown = await generateMarkdown({ orm: ormConfig });
401
404
  ```
402
405
 
406
+ ### Mermaid rendering options
407
+
408
+ By default, mikro-orm-markdown does not emit Mermaid frontmatter config. This preserves each Markdown viewer's default Mermaid rendering behavior.
409
+
410
+ You can opt into Mermaid rendering options via the CLI:
411
+
412
+ ```bash
413
+ mikro-orm-markdown --config ./mikro-orm.config.ts --mermaid-layout elk
414
+ mikro-orm-markdown --config ./mikro-orm.config.ts --mermaid-theme forest
415
+ mikro-orm-markdown --config ./mikro-orm.config.ts --mermaid-layout elk --mermaid-theme neutral
416
+ ```
417
+
418
+ Or via the programmatic API:
419
+
420
+ ```typescript
421
+ const markdown = await generateMarkdown({
422
+ orm: ormConfig,
423
+ mermaid: {
424
+ layout: 'elk',
425
+ theme: 'forest',
426
+ },
427
+ });
428
+ ```
429
+
430
+ When a layout or theme is set, a YAML frontmatter block is prepended to each `erDiagram` fence:
431
+
432
+ ````markdown
433
+ ```mermaid
434
+ ---
435
+ config:
436
+ layout: elk
437
+ theme: forest
438
+ ---
439
+ erDiagram
440
+ ...
441
+ ```
442
+ ````
443
+
444
+ **Available layout values:**
445
+
446
+ | Value | Description |
447
+ | ----- | ----------- |
448
+ | `dagre` | Mermaid's default layered layout. |
449
+ | `elk` | Alternative layout engine; can improve line routing on larger or denser ERDs. |
450
+ | `elk.stress` | ELK stress layout variant. Support varies by Mermaid version and viewer. |
451
+
452
+ **Available theme values:** `default`, `neutral`, `dark`, `forest`, `base`.
453
+
454
+ > Viewer support for `elk` and theme values varies. If no `--mermaid-layout` or `--mermaid-theme` is provided, no frontmatter is emitted.
455
+
403
456
  ## License
404
457
 
405
458
  MIT
package/dist/cli.cjs CHANGED
@@ -281,6 +281,8 @@ function toMarkdownAnchor(value) {
281
281
  }
282
282
 
283
283
  // src/render/mermaid.ts
284
+ var MERMAID_LAYOUTS = ["dagre", "elk", "elk.stress"];
285
+ var MERMAID_THEMES = ["default", "neutral", "dark", "forest", "base"];
284
286
  var FORMULA_DUMMY_TABLE = {
285
287
  alias: "e0",
286
288
  name: "",
@@ -567,8 +569,19 @@ function normalizeType(type) {
567
569
  }
568
570
  return type;
569
571
  }
570
- function renderErDiagram(model) {
571
- const lines = ["erDiagram"];
572
+ function renderErDiagram(model, mermaid) {
573
+ const lines = [];
574
+ if (mermaid?.layout !== void 0 || mermaid?.theme !== void 0) {
575
+ lines.push("---", "config:");
576
+ if (mermaid.layout !== void 0) {
577
+ lines.push(` layout: ${mermaid.layout}`);
578
+ }
579
+ if (mermaid.theme !== void 0) {
580
+ lines.push(` theme: ${mermaid.theme}`);
581
+ }
582
+ lines.push("---");
583
+ }
584
+ lines.push("erDiagram");
572
585
  for (const entity of model.entities) {
573
586
  lines.push(` ${toMermaidIdentifier(entity.className)} {`);
574
587
  for (const col of entity.columns) {
@@ -787,7 +800,7 @@ async function withTsMorphMetadataProvider(options, onWarn) {
787
800
  }
788
801
 
789
802
  // src/render/markdown.ts
790
- function renderMarkdown(docModel) {
803
+ function renderMarkdown(docModel, mermaid) {
791
804
  const sections = [`# ${escapeMarkdownInline(docModel.title)}`];
792
805
  if (docModel.description) {
793
806
  sections.push(escapeMarkdownParagraph(docModel.description));
@@ -796,7 +809,7 @@ function renderMarkdown(docModel) {
796
809
  sections.push(renderTableOfContents(docModel.groups));
797
810
  }
798
811
  for (const group of docModel.groups) {
799
- sections.push(renderGroupSection(group));
812
+ sections.push(renderGroupSection(group, mermaid));
800
813
  }
801
814
  return sections.join("\n\n");
802
815
  }
@@ -813,14 +826,14 @@ function renderTableOfContents(groups) {
813
826
  return `- [${label}](#${toMarkdownAnchor(group.name)})`;
814
827
  });
815
828
  }
816
- function renderGroupSection(group) {
829
+ function renderGroupSection(group, mermaid) {
817
830
  const parts = [`## ${escapeMarkdownInline(group.name)}`];
818
831
  if (group.erdEntities.length > 0) {
819
832
  const diagramModel = {
820
833
  entities: group.erdEntities.map((e) => e.model),
821
834
  relations: group.erdRelations
822
835
  };
823
- parts.push("```mermaid\n" + renderErDiagram(diagramModel) + "\n```");
836
+ parts.push("```mermaid\n" + renderErDiagram(diagramModel, mermaid) + "\n```");
824
837
  }
825
838
  for (const entity of group.textEntities) {
826
839
  parts.push(renderEntitySection(entity));
@@ -976,7 +989,7 @@ async function loadEntityMetadataWithTsMorphFallback(originalOrm, effectiveOrm)
976
989
  }
977
990
  }
978
991
  async function generateMarkdown(options) {
979
- const { orm, title = "Database Schema", description, src, onWarn } = options;
992
+ const { orm, title = "Database Schema", description, src, onWarn, mermaid } = options;
980
993
  const effectiveOrm = await withTsMorphMetadataProvider(orm, onWarn);
981
994
  const { metas, sourcePaths } = await loadEntityMetadataWithTsMorphFallback(orm, effectiveOrm);
982
995
  const jsDocResult = loadJsDoc(resolveJsDocSources(sourcePaths, src, onWarn));
@@ -984,7 +997,7 @@ async function generateMarkdown(options) {
984
997
  assertExplicitJsDocSourceCoverage(metas, jsDocResult, src, onWarn);
985
998
  }
986
999
  const docModel = buildDocumentModel(metas, jsDocResult, title, description, onWarn);
987
- return renderMarkdown(docModel);
1000
+ return renderMarkdown(docModel, mermaid);
988
1001
  }
989
1002
 
990
1003
  // src/cli.ts
@@ -1099,9 +1112,34 @@ async function writeMarkdownFile(outPath, markdown) {
1099
1112
  ${formatFileSystemError(cause)}`, { cause });
1100
1113
  }
1101
1114
  }
1115
+ function parseMermaidOptions(opts) {
1116
+ const { mermaidLayout, mermaidTheme } = opts;
1117
+ if (mermaidLayout !== void 0 && !MERMAID_LAYOUTS.includes(mermaidLayout)) {
1118
+ process.stderr.write(
1119
+ `Error: Invalid --mermaid-layout "${mermaidLayout}". Allowed values: ${MERMAID_LAYOUTS.join(", ")}
1120
+ `
1121
+ );
1122
+ process.exit(1);
1123
+ }
1124
+ if (mermaidTheme !== void 0 && !MERMAID_THEMES.includes(mermaidTheme)) {
1125
+ process.stderr.write(
1126
+ `Error: Invalid --mermaid-theme "${mermaidTheme}". Allowed values: ${MERMAID_THEMES.join(", ")}
1127
+ `
1128
+ );
1129
+ process.exit(1);
1130
+ }
1131
+ if (mermaidLayout === void 0 && mermaidTheme === void 0) {
1132
+ return void 0;
1133
+ }
1134
+ return {
1135
+ ...mermaidLayout !== void 0 && { layout: mermaidLayout },
1136
+ ...mermaidTheme !== void 0 && { theme: mermaidTheme }
1137
+ };
1138
+ }
1102
1139
  async function run(opts) {
1103
1140
  const configPath = path2.resolve(opts.config);
1104
1141
  const outPath = path2.resolve(opts.out);
1142
+ const mermaid = parseMermaidOptions(opts);
1105
1143
  let ormOptions;
1106
1144
  try {
1107
1145
  ormOptions = await loadOrmOptions(configPath, opts.tsconfig);
@@ -1120,6 +1158,7 @@ ${err instanceof Error ? err.message : String(err)}
1120
1158
  title: opts.title,
1121
1159
  ...opts.description !== void 0 && { description: opts.description },
1122
1160
  ...opts.src !== void 0 && { src: opts.src },
1161
+ ...mermaid !== void 0 && { mermaid },
1123
1162
  onWarn: (message) => void process.stderr.write(`Warning: ${message}
1124
1163
  `)
1125
1164
  });
@@ -1144,7 +1183,7 @@ var program = new import_commander.Command().name("mikro-orm-markdown").descript
1144
1183
  ).option(
1145
1184
  "--src <paths...>",
1146
1185
  "Source .ts file globs to read JSDoc from when entities run from compiled .js (comments are stripped at build time)"
1147
- ).action(run);
1186
+ ).option("--mermaid-layout <layout>", `Mermaid layout engine injected as frontmatter (${MERMAID_LAYOUTS.join("|")})`).option("--mermaid-theme <theme>", `Mermaid theme injected as frontmatter (${MERMAID_THEMES.join("|")})`).action(run);
1148
1187
  function isDirectCliExecution() {
1149
1188
  const entryPoint = process.argv[1];
1150
1189
  if (entryPoint === void 0) {