@nonsoo/prisma-mermaid 0.1.1 → 0.1.3

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.md CHANGED
@@ -64,6 +64,35 @@ await generateMermaidERD({
64
64
  });
65
65
  ```
66
66
 
67
+ ## Styling Diagrams
68
+
69
+ This library ships with sensible default styles for Mermaid ERD and Class diagrams. However, if you need more control, both `generateMermaidClass` and `generateMermaidERD` accept a configuration object that lets you customize the final diagram output.
70
+
71
+ The configuration `type` is exported as `MermaidDiagramConfig`. You can import it directly and pass the config object to the generator functions.
72
+
73
+ ```ts
74
+ import {
75
+ type MermaidDiagramConfig,
76
+ generateMermaidERD,
77
+ } from "@nonsoo/prisma-mermaid";
78
+
79
+ const config = {
80
+ type: "mermaid-erd",
81
+ config: {
82
+ type: "mermaid-erd",
83
+ config: {
84
+ layout: "elk",
85
+ },
86
+ },
87
+ } satisfies MermaidDiagramConfig;
88
+
89
+ await generateMermaidERD({
90
+ schemaPath: "./prisma/schema.prisma",
91
+ output: "./diagrams/erdDiagram.mmd",
92
+ config,
93
+ });
94
+ ```
95
+
67
96
  ## Purpose
68
97
 
69
98
  Documentation should evolve alongside the code it describes. Diagrams-as-code tools such as Mermaid make it easier for teams to maintain clear, accurate diagrams as their systems grow and change. However, creating these diagrams manually — especially for database schemas — still introduces friction and the risk of diagrams falling out of sync with the system.
package/build/index.cjs CHANGED
@@ -41,8 +41,12 @@ var import_node_fs = require("fs");
41
41
  var import_node_path = __toESM(require("path"), 1);
42
42
 
43
43
  // src/constants/mermaid.ts
44
+ var DEFAULT_BASE_NODE_SPACING = 100;
45
+ var DEFAULT_BASE_EDGE_SPACING = 150;
44
46
  var mermaidERDiagramConfig = {
45
47
  theme: "neutral",
48
+ layout: "dagre",
49
+ look: "classic",
46
50
  themeVariables: {
47
51
  fontSize: "20px",
48
52
  fontFamily: "Arial",
@@ -57,6 +61,8 @@ var mermaidERDiagramConfig = {
57
61
  };
58
62
  var mermaidClassDiagramConfig = {
59
63
  theme: "neutral",
64
+ layout: "dagre",
65
+ look: "classic",
60
66
  themeVariables: {
61
67
  fontFamily: "Arial",
62
68
  lineHeight: "1.4"
@@ -70,8 +76,6 @@ var mermaidClassDiagramConfig = {
70
76
  hideEmptyMembersBox: true
71
77
  }
72
78
  };
73
- var DEFAULT_BASE_NODE_SPACING = 100;
74
- var DEFAULT_BASE_EDGE_SPACING = 150;
75
79
 
76
80
  // src/utils/mermaid.ts
77
81
  var generateDiagramSpacing = ({
@@ -169,7 +173,8 @@ var { getDMMF } = import_internals.default;
169
173
  var generateDiagram = async ({
170
174
  outputPath,
171
175
  schemaPath,
172
- generatorPrismaDocument
176
+ generatorPrismaDocument,
177
+ config
173
178
  }) => {
174
179
  const outputDir = outputPath ? import_node_path.default.resolve(outputPath) : import_node_path.default.join(`${process.cwd()}/src/generated/diagrams`);
175
180
  try {
@@ -178,11 +183,16 @@ var generateDiagram = async ({
178
183
  });
179
184
  const models = prismaDocument.datamodel.models;
180
185
  const enums = prismaDocument.datamodel.enums;
186
+ const userGeneratedConfig = config?.type === "mermaid-class" ? config?.config : {};
187
+ const diagramConfig = {
188
+ ...mermaidClassDiagramConfig,
189
+ ...userGeneratedConfig
190
+ };
181
191
  const mermaidLines = [
182
192
  "%% --------------------------------------------",
183
193
  "%% Auto-generated Mermaid Class Diagram. Do Not Edit Directly.",
184
194
  "%% --------------------------------------------\n",
185
- generateMermaidConfig(mermaidClassDiagramConfig, models),
195
+ generateMermaidConfig(diagramConfig, models),
186
196
  "classDiagram"
187
197
  ];
188
198
  const relationships = {};
@@ -302,13 +312,32 @@ var generateRelationships2 = ({
302
312
  }
303
313
  return relationLines;
304
314
  };
315
+ var validateForeignKeys = ({
316
+ foreignKeys,
317
+ foreignKeyLocation,
318
+ mermaidLines
319
+ }) => {
320
+ if (foreignKeys.size > 0) {
321
+ for (const key of foreignKeys) {
322
+ const keyIndexMermaidLines = foreignKeyLocation.get(key);
323
+ if (!keyIndexMermaidLines) continue;
324
+ const currentLine = mermaidLines[keyIndexMermaidLines];
325
+ if (!currentLine) continue;
326
+ const lineArray = currentLine.split(" ");
327
+ lineArray[2] = "FK";
328
+ const finalLine = lineArray.join(" ");
329
+ mermaidLines[keyIndexMermaidLines] = finalLine;
330
+ }
331
+ }
332
+ };
305
333
 
306
334
  // src/lib/MermaidERD/prismaMermaidErd.ts
307
335
  var { getDMMF: getDMMF2 } = import_internals2.default;
308
336
  var generateDiagram2 = async ({
309
337
  outputPath,
310
338
  schemaPath,
311
- generatorPrismaDocument
339
+ generatorPrismaDocument,
340
+ config
312
341
  }) => {
313
342
  const outputDir = outputPath ? import_node_path2.default.resolve(outputPath) : import_node_path2.default.join(`${process.cwd()}/src/generated/diagrams`);
314
343
  try {
@@ -317,17 +346,22 @@ var generateDiagram2 = async ({
317
346
  });
318
347
  const schemaModels = prismaDocument.datamodel.models;
319
348
  const schemaEnums = prismaDocument.datamodel.enums;
320
- console.dir(schemaEnums, { depth: null });
349
+ const userGeneratedConfig = config?.type === "mermaid-erd" ? config?.config : {};
350
+ const diagramConfig = {
351
+ ...mermaidERDiagramConfig,
352
+ ...userGeneratedConfig
353
+ };
321
354
  const mermaidLines = [
322
355
  "%% --------------------------------------------",
323
356
  "%% Auto-generated Mermaid ER Diagram. Do Not Edit Directly.",
324
357
  "%% --------------------------------------------\n",
325
- generateMermaidConfig(mermaidERDiagramConfig, schemaModels),
358
+ generateMermaidConfig(diagramConfig, schemaModels),
326
359
  "erDiagram"
327
360
  ];
328
361
  const relationships = {};
329
362
  schemaModels.forEach((model) => {
330
363
  mermaidLines.push(` ${model.name} {`);
364
+ const foreignKeyLocation = /* @__PURE__ */ new Map();
331
365
  const foreignKeys = /* @__PURE__ */ new Set();
332
366
  model.fields.forEach((field) => {
333
367
  if (field.relationFromFields && field.relationFromFields.length > 0) {
@@ -343,6 +377,7 @@ var generateDiagram2 = async ({
343
377
  field.nativeType
344
378
  )} ${getOptionalitySymbol(field.isRequired)}`
345
379
  );
380
+ foreignKeyLocation.set(field.name, mermaidLines.length - 1);
346
381
  if (field.relationName) {
347
382
  if (!relationships[field.relationName]) {
348
383
  relationships[field.relationName] = [];
@@ -355,6 +390,11 @@ var generateDiagram2 = async ({
355
390
  });
356
391
  }
357
392
  });
393
+ validateForeignKeys({
394
+ foreignKeyLocation,
395
+ foreignKeys,
396
+ mermaidLines
397
+ });
358
398
  mermaidLines.push(` }`);
359
399
  });
360
400
  schemaEnums.forEach((enumDef) => {
package/build/index.d.cts CHANGED
@@ -1,7 +1,48 @@
1
1
  import { DMMF } from '@prisma/generator-helper';
2
2
 
3
+ type ConfigTheme = "default" | "redux-dark" | "forest" | "neutral" | "mc" | "base" | "redux" | "redux-dark";
4
+ type ConfigLook = "classic" | "handDrawn" | "neo";
5
+ type ConfigLayout = "dagre" | "elk";
6
+ type ConfigThemeVariables = {
7
+ fontSize: `${number}px`;
8
+ fontFamily: string;
9
+ padding: `${number}px`;
10
+ lineHeight: string;
11
+ nodeSpacing: number;
12
+ edgeSpacing: number;
13
+ };
14
+ type ConfigFlowchart = {
15
+ nodeSpacing: number;
16
+ rankSpacing: number;
17
+ htmlLabels: boolean;
18
+ };
19
+ type MermaidERDiagramConfig = {
20
+ type: Exclude<PrismaGeneratorsKeys, "mermaid-class">;
21
+ config: Partial<{
22
+ theme: ConfigTheme;
23
+ layout: ConfigLayout;
24
+ look: ConfigLook;
25
+ themeVariables: Partial<ConfigThemeVariables>;
26
+ flowchart: Partial<ConfigFlowchart>;
27
+ }>;
28
+ };
29
+ type MermaidClassDiagramConfig = {
30
+ type: Exclude<PrismaGeneratorsKeys, "mermaid-erd">;
31
+ config: Partial<{
32
+ theme: ConfigTheme;
33
+ layout: ConfigLayout;
34
+ look: ConfigLook;
35
+ themeVariables: Partial<ConfigThemeVariables>;
36
+ flowchart: Partial<ConfigFlowchart>;
37
+ class: Partial<{
38
+ hideEmptyMembersBox: boolean;
39
+ }>;
40
+ }>;
41
+ };
42
+ type MermaidDiagramConfig = MermaidERDiagramConfig | MermaidClassDiagramConfig;
3
43
  type GenerateDiagramOptions = {
4
44
  generatorPrismaDocument?: DMMF.Document;
45
+ config?: MermaidDiagramConfig;
5
46
  schemaPath: string;
6
47
  outputPath: string | undefined;
7
48
  };
@@ -44,7 +85,7 @@ type PrismaGeneratorsKeys = "mermaid-erd" | "mermaid-class";
44
85
  * or, if `outputPath` is omitted:
45
86
  * `<projectRoot>/src/generated/diagrams/mermaidClassDiagram.mmd`
46
87
  */
47
- declare const generateDiagram$1: ({ outputPath, schemaPath, generatorPrismaDocument, }: GenerateDiagramOptions) => Promise<string>;
88
+ declare const generateDiagram$1: ({ outputPath, schemaPath, generatorPrismaDocument, config, }: GenerateDiagramOptions) => Promise<string>;
48
89
 
49
90
  /**
50
91
  * Generates a Mermaid ERD (Entity-Relationship Diagram) from a Prisma schema.
@@ -58,6 +99,6 @@ declare const generateDiagram$1: ({ outputPath, schemaPath, generatorPrismaDocum
58
99
  * or, if no output path is provided:
59
100
  * `<projectRoot>/src/generated/diagrams/mermaidErdDiagram.mmd`
60
101
  */
61
- declare const generateDiagram: ({ outputPath, schemaPath, generatorPrismaDocument, }: GenerateDiagramOptions) => Promise<string>;
102
+ declare const generateDiagram: ({ outputPath, schemaPath, generatorPrismaDocument, config, }: GenerateDiagramOptions) => Promise<string>;
62
103
 
63
- export { type ClassCardinality, type ERDCardinality, type GenerateCardinality, type GenerateCardinalityOptions, type GenerateDiagram, type GenerateDiagramOptions, type GenerateDiagramSpacingOptions, type GenerateRelationshipOptions, type GenerateRelationships, type PrismaGeneratorsKeys, type Relationships, generateDiagram$1 as generateMermaidClass, generateDiagram as generateMermaidERD };
104
+ export { type ClassCardinality, type ERDCardinality, type GenerateCardinality, type GenerateCardinalityOptions, type GenerateDiagram, type GenerateDiagramOptions, type GenerateDiagramSpacingOptions, type GenerateRelationshipOptions, type GenerateRelationships, type MermaidClassDiagramConfig, type MermaidDiagramConfig, type MermaidERDiagramConfig, type PrismaGeneratorsKeys, type Relationships, generateDiagram$1 as generateMermaidClass, generateDiagram as generateMermaidERD };
package/build/index.d.ts CHANGED
@@ -1,7 +1,48 @@
1
1
  import { DMMF } from '@prisma/generator-helper';
2
2
 
3
+ type ConfigTheme = "default" | "redux-dark" | "forest" | "neutral" | "mc" | "base" | "redux" | "redux-dark";
4
+ type ConfigLook = "classic" | "handDrawn" | "neo";
5
+ type ConfigLayout = "dagre" | "elk";
6
+ type ConfigThemeVariables = {
7
+ fontSize: `${number}px`;
8
+ fontFamily: string;
9
+ padding: `${number}px`;
10
+ lineHeight: string;
11
+ nodeSpacing: number;
12
+ edgeSpacing: number;
13
+ };
14
+ type ConfigFlowchart = {
15
+ nodeSpacing: number;
16
+ rankSpacing: number;
17
+ htmlLabels: boolean;
18
+ };
19
+ type MermaidERDiagramConfig = {
20
+ type: Exclude<PrismaGeneratorsKeys, "mermaid-class">;
21
+ config: Partial<{
22
+ theme: ConfigTheme;
23
+ layout: ConfigLayout;
24
+ look: ConfigLook;
25
+ themeVariables: Partial<ConfigThemeVariables>;
26
+ flowchart: Partial<ConfigFlowchart>;
27
+ }>;
28
+ };
29
+ type MermaidClassDiagramConfig = {
30
+ type: Exclude<PrismaGeneratorsKeys, "mermaid-erd">;
31
+ config: Partial<{
32
+ theme: ConfigTheme;
33
+ layout: ConfigLayout;
34
+ look: ConfigLook;
35
+ themeVariables: Partial<ConfigThemeVariables>;
36
+ flowchart: Partial<ConfigFlowchart>;
37
+ class: Partial<{
38
+ hideEmptyMembersBox: boolean;
39
+ }>;
40
+ }>;
41
+ };
42
+ type MermaidDiagramConfig = MermaidERDiagramConfig | MermaidClassDiagramConfig;
3
43
  type GenerateDiagramOptions = {
4
44
  generatorPrismaDocument?: DMMF.Document;
45
+ config?: MermaidDiagramConfig;
5
46
  schemaPath: string;
6
47
  outputPath: string | undefined;
7
48
  };
@@ -44,7 +85,7 @@ type PrismaGeneratorsKeys = "mermaid-erd" | "mermaid-class";
44
85
  * or, if `outputPath` is omitted:
45
86
  * `<projectRoot>/src/generated/diagrams/mermaidClassDiagram.mmd`
46
87
  */
47
- declare const generateDiagram$1: ({ outputPath, schemaPath, generatorPrismaDocument, }: GenerateDiagramOptions) => Promise<string>;
88
+ declare const generateDiagram$1: ({ outputPath, schemaPath, generatorPrismaDocument, config, }: GenerateDiagramOptions) => Promise<string>;
48
89
 
49
90
  /**
50
91
  * Generates a Mermaid ERD (Entity-Relationship Diagram) from a Prisma schema.
@@ -58,6 +99,6 @@ declare const generateDiagram$1: ({ outputPath, schemaPath, generatorPrismaDocum
58
99
  * or, if no output path is provided:
59
100
  * `<projectRoot>/src/generated/diagrams/mermaidErdDiagram.mmd`
60
101
  */
61
- declare const generateDiagram: ({ outputPath, schemaPath, generatorPrismaDocument, }: GenerateDiagramOptions) => Promise<string>;
102
+ declare const generateDiagram: ({ outputPath, schemaPath, generatorPrismaDocument, config, }: GenerateDiagramOptions) => Promise<string>;
62
103
 
63
- export { type ClassCardinality, type ERDCardinality, type GenerateCardinality, type GenerateCardinalityOptions, type GenerateDiagram, type GenerateDiagramOptions, type GenerateDiagramSpacingOptions, type GenerateRelationshipOptions, type GenerateRelationships, type PrismaGeneratorsKeys, type Relationships, generateDiagram$1 as generateMermaidClass, generateDiagram as generateMermaidERD };
104
+ export { type ClassCardinality, type ERDCardinality, type GenerateCardinality, type GenerateCardinalityOptions, type GenerateDiagram, type GenerateDiagramOptions, type GenerateDiagramSpacingOptions, type GenerateRelationshipOptions, type GenerateRelationships, type MermaidClassDiagramConfig, type MermaidDiagramConfig, type MermaidERDiagramConfig, type PrismaGeneratorsKeys, type Relationships, generateDiagram$1 as generateMermaidClass, generateDiagram as generateMermaidERD };
package/build/index.js CHANGED
@@ -4,8 +4,12 @@ import { readFileSync, writeFileSync, mkdirSync } from "fs";
4
4
  import path from "path";
5
5
 
6
6
  // src/constants/mermaid.ts
7
+ var DEFAULT_BASE_NODE_SPACING = 100;
8
+ var DEFAULT_BASE_EDGE_SPACING = 150;
7
9
  var mermaidERDiagramConfig = {
8
10
  theme: "neutral",
11
+ layout: "dagre",
12
+ look: "classic",
9
13
  themeVariables: {
10
14
  fontSize: "20px",
11
15
  fontFamily: "Arial",
@@ -20,6 +24,8 @@ var mermaidERDiagramConfig = {
20
24
  };
21
25
  var mermaidClassDiagramConfig = {
22
26
  theme: "neutral",
27
+ layout: "dagre",
28
+ look: "classic",
23
29
  themeVariables: {
24
30
  fontFamily: "Arial",
25
31
  lineHeight: "1.4"
@@ -33,8 +39,6 @@ var mermaidClassDiagramConfig = {
33
39
  hideEmptyMembersBox: true
34
40
  }
35
41
  };
36
- var DEFAULT_BASE_NODE_SPACING = 100;
37
- var DEFAULT_BASE_EDGE_SPACING = 150;
38
42
 
39
43
  // src/utils/mermaid.ts
40
44
  var generateDiagramSpacing = ({
@@ -132,7 +136,8 @@ var { getDMMF } = pkg;
132
136
  var generateDiagram = async ({
133
137
  outputPath,
134
138
  schemaPath,
135
- generatorPrismaDocument
139
+ generatorPrismaDocument,
140
+ config
136
141
  }) => {
137
142
  const outputDir = outputPath ? path.resolve(outputPath) : path.join(`${process.cwd()}/src/generated/diagrams`);
138
143
  try {
@@ -141,11 +146,16 @@ var generateDiagram = async ({
141
146
  });
142
147
  const models = prismaDocument.datamodel.models;
143
148
  const enums = prismaDocument.datamodel.enums;
149
+ const userGeneratedConfig = config?.type === "mermaid-class" ? config?.config : {};
150
+ const diagramConfig = {
151
+ ...mermaidClassDiagramConfig,
152
+ ...userGeneratedConfig
153
+ };
144
154
  const mermaidLines = [
145
155
  "%% --------------------------------------------",
146
156
  "%% Auto-generated Mermaid Class Diagram. Do Not Edit Directly.",
147
157
  "%% --------------------------------------------\n",
148
- generateMermaidConfig(mermaidClassDiagramConfig, models),
158
+ generateMermaidConfig(diagramConfig, models),
149
159
  "classDiagram"
150
160
  ];
151
161
  const relationships = {};
@@ -265,13 +275,32 @@ var generateRelationships2 = ({
265
275
  }
266
276
  return relationLines;
267
277
  };
278
+ var validateForeignKeys = ({
279
+ foreignKeys,
280
+ foreignKeyLocation,
281
+ mermaidLines
282
+ }) => {
283
+ if (foreignKeys.size > 0) {
284
+ for (const key of foreignKeys) {
285
+ const keyIndexMermaidLines = foreignKeyLocation.get(key);
286
+ if (!keyIndexMermaidLines) continue;
287
+ const currentLine = mermaidLines[keyIndexMermaidLines];
288
+ if (!currentLine) continue;
289
+ const lineArray = currentLine.split(" ");
290
+ lineArray[2] = "FK";
291
+ const finalLine = lineArray.join(" ");
292
+ mermaidLines[keyIndexMermaidLines] = finalLine;
293
+ }
294
+ }
295
+ };
268
296
 
269
297
  // src/lib/MermaidERD/prismaMermaidErd.ts
270
298
  var { getDMMF: getDMMF2 } = pkg2;
271
299
  var generateDiagram2 = async ({
272
300
  outputPath,
273
301
  schemaPath,
274
- generatorPrismaDocument
302
+ generatorPrismaDocument,
303
+ config
275
304
  }) => {
276
305
  const outputDir = outputPath ? path2.resolve(outputPath) : path2.join(`${process.cwd()}/src/generated/diagrams`);
277
306
  try {
@@ -280,17 +309,22 @@ var generateDiagram2 = async ({
280
309
  });
281
310
  const schemaModels = prismaDocument.datamodel.models;
282
311
  const schemaEnums = prismaDocument.datamodel.enums;
283
- console.dir(schemaEnums, { depth: null });
312
+ const userGeneratedConfig = config?.type === "mermaid-erd" ? config?.config : {};
313
+ const diagramConfig = {
314
+ ...mermaidERDiagramConfig,
315
+ ...userGeneratedConfig
316
+ };
284
317
  const mermaidLines = [
285
318
  "%% --------------------------------------------",
286
319
  "%% Auto-generated Mermaid ER Diagram. Do Not Edit Directly.",
287
320
  "%% --------------------------------------------\n",
288
- generateMermaidConfig(mermaidERDiagramConfig, schemaModels),
321
+ generateMermaidConfig(diagramConfig, schemaModels),
289
322
  "erDiagram"
290
323
  ];
291
324
  const relationships = {};
292
325
  schemaModels.forEach((model) => {
293
326
  mermaidLines.push(` ${model.name} {`);
327
+ const foreignKeyLocation = /* @__PURE__ */ new Map();
294
328
  const foreignKeys = /* @__PURE__ */ new Set();
295
329
  model.fields.forEach((field) => {
296
330
  if (field.relationFromFields && field.relationFromFields.length > 0) {
@@ -306,6 +340,7 @@ var generateDiagram2 = async ({
306
340
  field.nativeType
307
341
  )} ${getOptionalitySymbol(field.isRequired)}`
308
342
  );
343
+ foreignKeyLocation.set(field.name, mermaidLines.length - 1);
309
344
  if (field.relationName) {
310
345
  if (!relationships[field.relationName]) {
311
346
  relationships[field.relationName] = [];
@@ -318,6 +353,11 @@ var generateDiagram2 = async ({
318
353
  });
319
354
  }
320
355
  });
356
+ validateForeignKeys({
357
+ foreignKeyLocation,
358
+ foreignKeys,
359
+ mermaidLines
360
+ });
321
361
  mermaidLines.push(` }`);
322
362
  });
323
363
  schemaEnums.forEach((enumDef) => {
@@ -1382,8 +1382,12 @@ var import_node_fs = require("fs");
1382
1382
  var import_node_path = __toESM(require("path"), 1);
1383
1383
 
1384
1384
  // src/constants/mermaid.ts
1385
+ var DEFAULT_BASE_NODE_SPACING = 100;
1386
+ var DEFAULT_BASE_EDGE_SPACING = 150;
1385
1387
  var mermaidERDiagramConfig = {
1386
1388
  theme: "neutral",
1389
+ layout: "dagre",
1390
+ look: "classic",
1387
1391
  themeVariables: {
1388
1392
  fontSize: "20px",
1389
1393
  fontFamily: "Arial",
@@ -1398,6 +1402,8 @@ var mermaidERDiagramConfig = {
1398
1402
  };
1399
1403
  var mermaidClassDiagramConfig = {
1400
1404
  theme: "neutral",
1405
+ layout: "dagre",
1406
+ look: "classic",
1401
1407
  themeVariables: {
1402
1408
  fontFamily: "Arial",
1403
1409
  lineHeight: "1.4"
@@ -1411,8 +1417,6 @@ var mermaidClassDiagramConfig = {
1411
1417
  hideEmptyMembersBox: true
1412
1418
  }
1413
1419
  };
1414
- var DEFAULT_BASE_NODE_SPACING = 100;
1415
- var DEFAULT_BASE_EDGE_SPACING = 150;
1416
1420
 
1417
1421
  // src/utils/mermaid.ts
1418
1422
  var generateDiagramSpacing = ({
@@ -1510,7 +1514,8 @@ var { getDMMF } = import_internals.default;
1510
1514
  var generateDiagram = async ({
1511
1515
  outputPath,
1512
1516
  schemaPath,
1513
- generatorPrismaDocument
1517
+ generatorPrismaDocument,
1518
+ config
1514
1519
  }) => {
1515
1520
  const outputDir = outputPath ? import_node_path.default.resolve(outputPath) : import_node_path.default.join(`${process.cwd()}/src/generated/diagrams`);
1516
1521
  try {
@@ -1519,11 +1524,16 @@ var generateDiagram = async ({
1519
1524
  });
1520
1525
  const models = prismaDocument.datamodel.models;
1521
1526
  const enums = prismaDocument.datamodel.enums;
1527
+ const userGeneratedConfig = config?.type === "mermaid-class" ? config?.config : {};
1528
+ const diagramConfig = {
1529
+ ...mermaidClassDiagramConfig,
1530
+ ...userGeneratedConfig
1531
+ };
1522
1532
  const mermaidLines = [
1523
1533
  "%% --------------------------------------------",
1524
1534
  "%% Auto-generated Mermaid Class Diagram. Do Not Edit Directly.",
1525
1535
  "%% --------------------------------------------\n",
1526
- generateMermaidConfig(mermaidClassDiagramConfig, models),
1536
+ generateMermaidConfig(diagramConfig, models),
1527
1537
  "classDiagram"
1528
1538
  ];
1529
1539
  const relationships = {};
@@ -1643,13 +1653,32 @@ var generateRelationships2 = ({
1643
1653
  }
1644
1654
  return relationLines;
1645
1655
  };
1656
+ var validateForeignKeys = ({
1657
+ foreignKeys,
1658
+ foreignKeyLocation,
1659
+ mermaidLines
1660
+ }) => {
1661
+ if (foreignKeys.size > 0) {
1662
+ for (const key of foreignKeys) {
1663
+ const keyIndexMermaidLines = foreignKeyLocation.get(key);
1664
+ if (!keyIndexMermaidLines) continue;
1665
+ const currentLine = mermaidLines[keyIndexMermaidLines];
1666
+ if (!currentLine) continue;
1667
+ const lineArray = currentLine.split(" ");
1668
+ lineArray[2] = "FK";
1669
+ const finalLine = lineArray.join(" ");
1670
+ mermaidLines[keyIndexMermaidLines] = finalLine;
1671
+ }
1672
+ }
1673
+ };
1646
1674
 
1647
1675
  // src/lib/MermaidERD/prismaMermaidErd.ts
1648
1676
  var { getDMMF: getDMMF2 } = import_internals2.default;
1649
1677
  var generateDiagram2 = async ({
1650
1678
  outputPath,
1651
1679
  schemaPath,
1652
- generatorPrismaDocument
1680
+ generatorPrismaDocument,
1681
+ config
1653
1682
  }) => {
1654
1683
  const outputDir = outputPath ? import_node_path2.default.resolve(outputPath) : import_node_path2.default.join(`${process.cwd()}/src/generated/diagrams`);
1655
1684
  try {
@@ -1658,17 +1687,22 @@ var generateDiagram2 = async ({
1658
1687
  });
1659
1688
  const schemaModels = prismaDocument.datamodel.models;
1660
1689
  const schemaEnums = prismaDocument.datamodel.enums;
1661
- console.dir(schemaEnums, { depth: null });
1690
+ const userGeneratedConfig = config?.type === "mermaid-erd" ? config?.config : {};
1691
+ const diagramConfig = {
1692
+ ...mermaidERDiagramConfig,
1693
+ ...userGeneratedConfig
1694
+ };
1662
1695
  const mermaidLines = [
1663
1696
  "%% --------------------------------------------",
1664
1697
  "%% Auto-generated Mermaid ER Diagram. Do Not Edit Directly.",
1665
1698
  "%% --------------------------------------------\n",
1666
- generateMermaidConfig(mermaidERDiagramConfig, schemaModels),
1699
+ generateMermaidConfig(diagramConfig, schemaModels),
1667
1700
  "erDiagram"
1668
1701
  ];
1669
1702
  const relationships = {};
1670
1703
  schemaModels.forEach((model) => {
1671
1704
  mermaidLines.push(` ${model.name} {`);
1705
+ const foreignKeyLocation = /* @__PURE__ */ new Map();
1672
1706
  const foreignKeys = /* @__PURE__ */ new Set();
1673
1707
  model.fields.forEach((field) => {
1674
1708
  if (field.relationFromFields && field.relationFromFields.length > 0) {
@@ -1684,6 +1718,7 @@ var generateDiagram2 = async ({
1684
1718
  field.nativeType
1685
1719
  )} ${getOptionalitySymbol(field.isRequired)}`
1686
1720
  );
1721
+ foreignKeyLocation.set(field.name, mermaidLines.length - 1);
1687
1722
  if (field.relationName) {
1688
1723
  if (!relationships[field.relationName]) {
1689
1724
  relationships[field.relationName] = [];
@@ -1696,6 +1731,11 @@ var generateDiagram2 = async ({
1696
1731
  });
1697
1732
  }
1698
1733
  });
1734
+ validateForeignKeys({
1735
+ foreignKeyLocation,
1736
+ foreignKeys,
1737
+ mermaidLines
1738
+ });
1699
1739
  mermaidLines.push(` }`);
1700
1740
  });
1701
1741
  schemaEnums.forEach((enumDef) => {
@@ -1727,7 +1767,7 @@ var prismaGenerators = /* @__PURE__ */ new Map([
1727
1767
  // package.json
1728
1768
  var package_default = {
1729
1769
  name: "@nonsoo/prisma-mermaid",
1730
- version: "0.1.1",
1770
+ version: "0.1.3",
1731
1771
  description: "A Prisma generator that generates Mermaid Class or ER diagrams from your Prisma schema.",
1732
1772
  main: "build/index.js",
1733
1773
  bin: {
@@ -1777,7 +1817,6 @@ var package_default = {
1777
1817
  devDependencies: {
1778
1818
  "@changesets/cli": "^2.29.7",
1779
1819
  "@eslint/js": "^9.39.1",
1780
- "@prisma/internals": "^7.0.1",
1781
1820
  "@types/node": "^24.10.1",
1782
1821
  eslint: "^9.39.1",
1783
1822
  "eslint-config-prettier": "^10.1.8",
@@ -1790,13 +1829,10 @@ var package_default = {
1790
1829
  vitest: "^4.0.10"
1791
1830
  },
1792
1831
  peerDependencies: {
1793
- "@prisma/client": "^6.0.0 || ^7.0.0",
1794
- "@prisma/internals": "^6.0.0 || ^7.0.0"
1832
+ "@prisma/client": "^6.0.0 || ^7.0.0"
1795
1833
  },
1796
- peerDependenciesMeta: {
1797
- "@prisma/internals": {
1798
- optional: true
1799
- }
1834
+ dependencies: {
1835
+ "@prisma/internals": "^7.0.0"
1800
1836
  }
1801
1837
  };
1802
1838
 
@@ -1387,8 +1387,12 @@ import { readFileSync, writeFileSync, mkdirSync } from "fs";
1387
1387
  import path from "path";
1388
1388
 
1389
1389
  // src/constants/mermaid.ts
1390
+ var DEFAULT_BASE_NODE_SPACING = 100;
1391
+ var DEFAULT_BASE_EDGE_SPACING = 150;
1390
1392
  var mermaidERDiagramConfig = {
1391
1393
  theme: "neutral",
1394
+ layout: "dagre",
1395
+ look: "classic",
1392
1396
  themeVariables: {
1393
1397
  fontSize: "20px",
1394
1398
  fontFamily: "Arial",
@@ -1403,6 +1407,8 @@ var mermaidERDiagramConfig = {
1403
1407
  };
1404
1408
  var mermaidClassDiagramConfig = {
1405
1409
  theme: "neutral",
1410
+ layout: "dagre",
1411
+ look: "classic",
1406
1412
  themeVariables: {
1407
1413
  fontFamily: "Arial",
1408
1414
  lineHeight: "1.4"
@@ -1416,8 +1422,6 @@ var mermaidClassDiagramConfig = {
1416
1422
  hideEmptyMembersBox: true
1417
1423
  }
1418
1424
  };
1419
- var DEFAULT_BASE_NODE_SPACING = 100;
1420
- var DEFAULT_BASE_EDGE_SPACING = 150;
1421
1425
 
1422
1426
  // src/utils/mermaid.ts
1423
1427
  var generateDiagramSpacing = ({
@@ -1515,7 +1519,8 @@ var { getDMMF } = pkg;
1515
1519
  var generateDiagram = async ({
1516
1520
  outputPath,
1517
1521
  schemaPath,
1518
- generatorPrismaDocument
1522
+ generatorPrismaDocument,
1523
+ config
1519
1524
  }) => {
1520
1525
  const outputDir = outputPath ? path.resolve(outputPath) : path.join(`${process.cwd()}/src/generated/diagrams`);
1521
1526
  try {
@@ -1524,11 +1529,16 @@ var generateDiagram = async ({
1524
1529
  });
1525
1530
  const models = prismaDocument.datamodel.models;
1526
1531
  const enums = prismaDocument.datamodel.enums;
1532
+ const userGeneratedConfig = config?.type === "mermaid-class" ? config?.config : {};
1533
+ const diagramConfig = {
1534
+ ...mermaidClassDiagramConfig,
1535
+ ...userGeneratedConfig
1536
+ };
1527
1537
  const mermaidLines = [
1528
1538
  "%% --------------------------------------------",
1529
1539
  "%% Auto-generated Mermaid Class Diagram. Do Not Edit Directly.",
1530
1540
  "%% --------------------------------------------\n",
1531
- generateMermaidConfig(mermaidClassDiagramConfig, models),
1541
+ generateMermaidConfig(diagramConfig, models),
1532
1542
  "classDiagram"
1533
1543
  ];
1534
1544
  const relationships = {};
@@ -1648,13 +1658,32 @@ var generateRelationships2 = ({
1648
1658
  }
1649
1659
  return relationLines;
1650
1660
  };
1661
+ var validateForeignKeys = ({
1662
+ foreignKeys,
1663
+ foreignKeyLocation,
1664
+ mermaidLines
1665
+ }) => {
1666
+ if (foreignKeys.size > 0) {
1667
+ for (const key of foreignKeys) {
1668
+ const keyIndexMermaidLines = foreignKeyLocation.get(key);
1669
+ if (!keyIndexMermaidLines) continue;
1670
+ const currentLine = mermaidLines[keyIndexMermaidLines];
1671
+ if (!currentLine) continue;
1672
+ const lineArray = currentLine.split(" ");
1673
+ lineArray[2] = "FK";
1674
+ const finalLine = lineArray.join(" ");
1675
+ mermaidLines[keyIndexMermaidLines] = finalLine;
1676
+ }
1677
+ }
1678
+ };
1651
1679
 
1652
1680
  // src/lib/MermaidERD/prismaMermaidErd.ts
1653
1681
  var { getDMMF: getDMMF2 } = pkg2;
1654
1682
  var generateDiagram2 = async ({
1655
1683
  outputPath,
1656
1684
  schemaPath,
1657
- generatorPrismaDocument
1685
+ generatorPrismaDocument,
1686
+ config
1658
1687
  }) => {
1659
1688
  const outputDir = outputPath ? path2.resolve(outputPath) : path2.join(`${process.cwd()}/src/generated/diagrams`);
1660
1689
  try {
@@ -1663,17 +1692,22 @@ var generateDiagram2 = async ({
1663
1692
  });
1664
1693
  const schemaModels = prismaDocument.datamodel.models;
1665
1694
  const schemaEnums = prismaDocument.datamodel.enums;
1666
- console.dir(schemaEnums, { depth: null });
1695
+ const userGeneratedConfig = config?.type === "mermaid-erd" ? config?.config : {};
1696
+ const diagramConfig = {
1697
+ ...mermaidERDiagramConfig,
1698
+ ...userGeneratedConfig
1699
+ };
1667
1700
  const mermaidLines = [
1668
1701
  "%% --------------------------------------------",
1669
1702
  "%% Auto-generated Mermaid ER Diagram. Do Not Edit Directly.",
1670
1703
  "%% --------------------------------------------\n",
1671
- generateMermaidConfig(mermaidERDiagramConfig, schemaModels),
1704
+ generateMermaidConfig(diagramConfig, schemaModels),
1672
1705
  "erDiagram"
1673
1706
  ];
1674
1707
  const relationships = {};
1675
1708
  schemaModels.forEach((model) => {
1676
1709
  mermaidLines.push(` ${model.name} {`);
1710
+ const foreignKeyLocation = /* @__PURE__ */ new Map();
1677
1711
  const foreignKeys = /* @__PURE__ */ new Set();
1678
1712
  model.fields.forEach((field) => {
1679
1713
  if (field.relationFromFields && field.relationFromFields.length > 0) {
@@ -1689,6 +1723,7 @@ var generateDiagram2 = async ({
1689
1723
  field.nativeType
1690
1724
  )} ${getOptionalitySymbol(field.isRequired)}`
1691
1725
  );
1726
+ foreignKeyLocation.set(field.name, mermaidLines.length - 1);
1692
1727
  if (field.relationName) {
1693
1728
  if (!relationships[field.relationName]) {
1694
1729
  relationships[field.relationName] = [];
@@ -1701,6 +1736,11 @@ var generateDiagram2 = async ({
1701
1736
  });
1702
1737
  }
1703
1738
  });
1739
+ validateForeignKeys({
1740
+ foreignKeyLocation,
1741
+ foreignKeys,
1742
+ mermaidLines
1743
+ });
1704
1744
  mermaidLines.push(` }`);
1705
1745
  });
1706
1746
  schemaEnums.forEach((enumDef) => {
@@ -1732,7 +1772,7 @@ var prismaGenerators = /* @__PURE__ */ new Map([
1732
1772
  // package.json
1733
1773
  var package_default = {
1734
1774
  name: "@nonsoo/prisma-mermaid",
1735
- version: "0.1.1",
1775
+ version: "0.1.3",
1736
1776
  description: "A Prisma generator that generates Mermaid Class or ER diagrams from your Prisma schema.",
1737
1777
  main: "build/index.js",
1738
1778
  bin: {
@@ -1782,7 +1822,6 @@ var package_default = {
1782
1822
  devDependencies: {
1783
1823
  "@changesets/cli": "^2.29.7",
1784
1824
  "@eslint/js": "^9.39.1",
1785
- "@prisma/internals": "^7.0.1",
1786
1825
  "@types/node": "^24.10.1",
1787
1826
  eslint: "^9.39.1",
1788
1827
  "eslint-config-prettier": "^10.1.8",
@@ -1795,13 +1834,10 @@ var package_default = {
1795
1834
  vitest: "^4.0.10"
1796
1835
  },
1797
1836
  peerDependencies: {
1798
- "@prisma/client": "^6.0.0 || ^7.0.0",
1799
- "@prisma/internals": "^6.0.0 || ^7.0.0"
1837
+ "@prisma/client": "^6.0.0 || ^7.0.0"
1800
1838
  },
1801
- peerDependenciesMeta: {
1802
- "@prisma/internals": {
1803
- optional: true
1804
- }
1839
+ dependencies: {
1840
+ "@prisma/internals": "^7.0.0"
1805
1841
  }
1806
1842
  };
1807
1843
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nonsoo/prisma-mermaid",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "A Prisma generator that generates Mermaid Class or ER diagrams from your Prisma schema.",
5
5
  "main": "build/index.js",
6
6
  "bin": {
@@ -50,7 +50,6 @@
50
50
  "devDependencies": {
51
51
  "@changesets/cli": "^2.29.7",
52
52
  "@eslint/js": "^9.39.1",
53
- "@prisma/internals": "^7.0.1",
54
53
  "@types/node": "^24.10.1",
55
54
  "eslint": "^9.39.1",
56
55
  "eslint-config-prettier": "^10.1.8",
@@ -63,12 +62,9 @@
63
62
  "vitest": "^4.0.10"
64
63
  },
65
64
  "peerDependencies": {
66
- "@prisma/client": "^6.0.0 || ^7.0.0",
67
- "@prisma/internals": "^6.0.0 || ^7.0.0"
65
+ "@prisma/client": "^6.0.0 || ^7.0.0"
68
66
  },
69
- "peerDependenciesMeta": {
70
- "@prisma/internals": {
71
- "optional": true
72
- }
67
+ "dependencies": {
68
+ "@prisma/internals": "^7.0.0"
73
69
  }
74
70
  }