@nonsoo/prisma-mermaid 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +65 -0
- package/build/index.cjs +383 -0
- package/build/index.d.cts +63 -0
- package/build/index.d.ts +63 -0
- package/build/index.js +345 -0
- package/build/lib/PrismaMermaidGenerators/bin.cjs +1844 -0
- package/build/lib/PrismaMermaidGenerators/bin.d.cts +1 -0
- package/build/lib/PrismaMermaidGenerators/bin.d.ts +1 -0
- package/build/lib/PrismaMermaidGenerators/bin.js +1849 -0
- package/package.json +74 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Prisma-Mermaid
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Prisma to Mermaid Generator
|
|
2
|
+
|
|
3
|
+
Generate Mermaid class diagrams and Mermaid ERD diagrams directly from your Prisma schema. This package exposes a Prisma generator that runs during `prisma generate` as well as two programmatic helpers -- generateMermaidClass and generateMermaidERD.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm i --save-dev @nonsoo/prisma-mermaid @mermaid-js/mermaid-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage (Prisma Generator)
|
|
12
|
+
|
|
13
|
+
Add the following generator to your prisma schema
|
|
14
|
+
|
|
15
|
+
```prisma
|
|
16
|
+
generator diagram {
|
|
17
|
+
provider = "prisma-mermaid"
|
|
18
|
+
output = "../src/generated/diagrams"
|
|
19
|
+
format = "mermaid-erd"
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`format` Options
|
|
24
|
+
|
|
25
|
+
| Value | Description |
|
|
26
|
+
| ------------- | --------------------------------- |
|
|
27
|
+
| mermaid-erd | Generates a Mermaid ERD diagram |
|
|
28
|
+
| mermaid-class | Generates a Mermaid class diagram |
|
|
29
|
+
|
|
30
|
+
### Disabling the Diagram Generator (Useful for CI)
|
|
31
|
+
|
|
32
|
+
Set the following environment variable in your .env:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
PRISMA_DIAGRAM_GENERATOR_DISABLE=true
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Usage (Internal Functions)
|
|
39
|
+
|
|
40
|
+
You can also call the underlying functions directly if you want to generate diagrams outside of the Prisma CLI.
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
import {
|
|
44
|
+
generateMermaidClass,
|
|
45
|
+
generateMermaidERD,
|
|
46
|
+
} from "@nonsoo/prisma-mermaid";
|
|
47
|
+
|
|
48
|
+
await generateMermaidClass({
|
|
49
|
+
schemaPath: "./prisma/schema.prisma",
|
|
50
|
+
output: "./diagrams/classDiagram.mmd",
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
await generateMermaidERD({
|
|
54
|
+
schemaPath: "./prisma/schema.prisma",
|
|
55
|
+
output: "./diagrams/erdDiagram.mmd",
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Philosophy
|
|
60
|
+
|
|
61
|
+
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.
|
|
62
|
+
|
|
63
|
+
Prisma already provides a single source of truth for your data model through the Prisma schema. Therefore, by generating diagrams directly from this schema, we can ensure documentation stays automatically aligned with the current state of the database models.
|
|
64
|
+
|
|
65
|
+
This library bridges that gap. It transforms your Prisma schema into Mermaid-powered ERD or class diagrams, combining code generation with diagrams-as-code. Once generated, these diagrams can be used to create Markdown files, SVGs, PDFs, or any other Mermaid-supported output — always consistent, always up to date.
|
package/build/index.cjs
ADDED
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
generateMermaidClass: () => generateDiagram,
|
|
34
|
+
generateMermaidERD: () => generateDiagram2
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(index_exports);
|
|
37
|
+
|
|
38
|
+
// src/lib/MermaidClass/prismaMermaidClass.ts
|
|
39
|
+
var import_internals = __toESM(require("@prisma/internals"), 1);
|
|
40
|
+
var import_node_fs = require("fs");
|
|
41
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
42
|
+
|
|
43
|
+
// src/constants/mermaid.ts
|
|
44
|
+
var mermaidERDiagramConfig = {
|
|
45
|
+
theme: "neutral",
|
|
46
|
+
themeVariables: {
|
|
47
|
+
fontSize: "20px",
|
|
48
|
+
fontFamily: "Arial",
|
|
49
|
+
padding: "12px",
|
|
50
|
+
lineHeight: "1.4"
|
|
51
|
+
},
|
|
52
|
+
flowchart: {
|
|
53
|
+
nodeSpacing: 80,
|
|
54
|
+
rankSpacing: 120,
|
|
55
|
+
htmlLabels: true
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
var mermaidClassDiagramConfig = {
|
|
59
|
+
theme: "neutral",
|
|
60
|
+
themeVariables: {
|
|
61
|
+
fontFamily: "Arial",
|
|
62
|
+
lineHeight: "1.4"
|
|
63
|
+
},
|
|
64
|
+
flowchart: {
|
|
65
|
+
nodeSpacing: 300,
|
|
66
|
+
rankSpacing: 120,
|
|
67
|
+
htmlLabels: true
|
|
68
|
+
},
|
|
69
|
+
class: {
|
|
70
|
+
hideEmptyMembersBox: true
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
var DEFAULT_BASE_NODE_SPACING = 100;
|
|
74
|
+
var DEFAULT_BASE_EDGE_SPACING = 150;
|
|
75
|
+
|
|
76
|
+
// src/utils/mermaid.ts
|
|
77
|
+
var generateDiagramSpacing = ({
|
|
78
|
+
baseEdge,
|
|
79
|
+
baseNode,
|
|
80
|
+
models
|
|
81
|
+
}) => {
|
|
82
|
+
const totalFields = models.reduce((sum, m) => sum + m.fields.length, 0);
|
|
83
|
+
const totalRelations = models.reduce(
|
|
84
|
+
(sum, m) => sum + m.fields.filter((f) => f.relationName && f.relationFromFields?.length).length,
|
|
85
|
+
0
|
|
86
|
+
);
|
|
87
|
+
return {
|
|
88
|
+
nodeSpacing: baseNode + models.length * 6 + totalFields * 2,
|
|
89
|
+
edgeSpacing: baseEdge + models.length * 4 + totalRelations * 4
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
var generateMermaidConfig = (config, models) => {
|
|
93
|
+
if (config["themeVariables"]) {
|
|
94
|
+
const { edgeSpacing, nodeSpacing } = generateDiagramSpacing({
|
|
95
|
+
baseEdge: DEFAULT_BASE_EDGE_SPACING,
|
|
96
|
+
baseNode: DEFAULT_BASE_NODE_SPACING,
|
|
97
|
+
models
|
|
98
|
+
});
|
|
99
|
+
config["themeVariables"] = {
|
|
100
|
+
...config["themeVariables"],
|
|
101
|
+
edgeSpacing,
|
|
102
|
+
nodeSpacing
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const json = JSON.stringify(config, null, 2);
|
|
106
|
+
return `%%{init: ${json}}%%
|
|
107
|
+
`;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// src/lib/MermaidClass/utils.ts
|
|
111
|
+
var generateCardinality = ({
|
|
112
|
+
isList,
|
|
113
|
+
isRequired
|
|
114
|
+
}) => {
|
|
115
|
+
if (isList) return '"*"';
|
|
116
|
+
return isRequired ? '"1"' : '"0..1"';
|
|
117
|
+
};
|
|
118
|
+
var generateRelationships = ({
|
|
119
|
+
relationships
|
|
120
|
+
}) => {
|
|
121
|
+
const lines = [];
|
|
122
|
+
for (const relName in relationships) {
|
|
123
|
+
const sides = relationships[relName];
|
|
124
|
+
if (!sides) continue;
|
|
125
|
+
if (sides.length === 1) {
|
|
126
|
+
const a = sides[0];
|
|
127
|
+
if (!a) continue;
|
|
128
|
+
lines.push(
|
|
129
|
+
`${a.model} ${generateCardinality({
|
|
130
|
+
isList: a.isList,
|
|
131
|
+
isRequired: a.isRequired
|
|
132
|
+
})} --> "1" ${a.fieldType} : ${relName}`
|
|
133
|
+
);
|
|
134
|
+
} else if (sides.length === 2) {
|
|
135
|
+
const a = sides[0];
|
|
136
|
+
const b = sides[1];
|
|
137
|
+
if (!a || !b) continue;
|
|
138
|
+
lines.push(
|
|
139
|
+
`${a.model} ${generateCardinality({
|
|
140
|
+
isList: a.isList,
|
|
141
|
+
isRequired: a.isRequired
|
|
142
|
+
})} --> ${generateCardinality({
|
|
143
|
+
isList: b.isList,
|
|
144
|
+
isRequired: b.isRequired
|
|
145
|
+
})} ${b.model} : ${relName}`
|
|
146
|
+
);
|
|
147
|
+
} else {
|
|
148
|
+
for (let i = 1; i < sides.length; i++) {
|
|
149
|
+
const a = sides[0];
|
|
150
|
+
const b = sides[i];
|
|
151
|
+
if (!a || !b) continue;
|
|
152
|
+
lines.push(
|
|
153
|
+
`${a.model} ${generateCardinality({
|
|
154
|
+
isList: a.isList,
|
|
155
|
+
isRequired: a.isRequired
|
|
156
|
+
})} --> ${generateCardinality({
|
|
157
|
+
isList: b.isList,
|
|
158
|
+
isRequired: b.isRequired
|
|
159
|
+
})} ${b.model} : ${relName}`
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return lines;
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
// src/lib/MermaidClass/prismaMermaidClass.ts
|
|
168
|
+
var { getDMMF } = import_internals.default;
|
|
169
|
+
var generateDiagram = async ({
|
|
170
|
+
outputPath,
|
|
171
|
+
schemaPath,
|
|
172
|
+
generatorPrismaDocument
|
|
173
|
+
}) => {
|
|
174
|
+
const outputDir = outputPath ? import_node_path.default.resolve(outputPath) : import_node_path.default.join(`${process.cwd()}/src/generated/diagrams`);
|
|
175
|
+
try {
|
|
176
|
+
const prismaDocument = generatorPrismaDocument ?? await getDMMF({
|
|
177
|
+
datamodel: (0, import_node_fs.readFileSync)(schemaPath, "utf-8")
|
|
178
|
+
});
|
|
179
|
+
const models = prismaDocument.datamodel.models;
|
|
180
|
+
const enums = prismaDocument.datamodel.enums;
|
|
181
|
+
const mermaidLines = [
|
|
182
|
+
"%% --------------------------------------------",
|
|
183
|
+
"%% Auto-generated Mermaid Class Diagram. Do Not Edit Directly.",
|
|
184
|
+
"%% --------------------------------------------\n",
|
|
185
|
+
generateMermaidConfig(mermaidClassDiagramConfig, models),
|
|
186
|
+
"classDiagram"
|
|
187
|
+
];
|
|
188
|
+
const relationships = {};
|
|
189
|
+
models.forEach((model) => {
|
|
190
|
+
mermaidLines.push(`class ${model.name} {`);
|
|
191
|
+
model.fields.forEach((field) => {
|
|
192
|
+
mermaidLines.push(` ${field.type} ${field.name}`);
|
|
193
|
+
if (field.relationName) {
|
|
194
|
+
if (!relationships[field.relationName]) {
|
|
195
|
+
relationships[field.relationName] = [];
|
|
196
|
+
}
|
|
197
|
+
relationships[field.relationName].push({
|
|
198
|
+
model: model.name,
|
|
199
|
+
fieldType: field.type,
|
|
200
|
+
isList: field.isList ?? false,
|
|
201
|
+
isRequired: field.isRequired ?? false
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
mermaidLines.push("}");
|
|
206
|
+
});
|
|
207
|
+
enums.forEach((enumDef) => {
|
|
208
|
+
mermaidLines.push(`class ${enumDef.name} {`);
|
|
209
|
+
enumDef.values.forEach((val) => {
|
|
210
|
+
mermaidLines.push(` <<enumeration>> ${val.name}`);
|
|
211
|
+
});
|
|
212
|
+
mermaidLines.push("}");
|
|
213
|
+
});
|
|
214
|
+
const relationLines = generateRelationships({ relationships });
|
|
215
|
+
const output = mermaidLines.concat(relationLines).join("\n");
|
|
216
|
+
(0, import_node_fs.mkdirSync)(outputDir, { recursive: true });
|
|
217
|
+
const outFile = import_node_path.default.join(outputDir, "mermaidClassDiagram.mmd");
|
|
218
|
+
(0, import_node_fs.writeFileSync)(outFile, output, "utf-8");
|
|
219
|
+
console.log(`Mermaid Class Diagram written to: ${outFile}`);
|
|
220
|
+
return outFile;
|
|
221
|
+
} catch (e) {
|
|
222
|
+
console.error("Failed to generate Mermaid Class Diagram.", e);
|
|
223
|
+
return "";
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
// src/lib/MermaidERD/prismaMermaidErd.ts
|
|
228
|
+
var import_internals2 = __toESM(require("@prisma/internals"), 1);
|
|
229
|
+
var import_fs = require("fs");
|
|
230
|
+
var import_node_fs2 = require("fs");
|
|
231
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
232
|
+
|
|
233
|
+
// src/lib/MermaidERD/utils.ts
|
|
234
|
+
var generateCardinality2 = ({
|
|
235
|
+
isList,
|
|
236
|
+
isRequired
|
|
237
|
+
}) => {
|
|
238
|
+
if (isList) {
|
|
239
|
+
return "}|";
|
|
240
|
+
}
|
|
241
|
+
return isRequired ? "||" : "o|";
|
|
242
|
+
};
|
|
243
|
+
var getKeyConstraints = (isId, fieldName, foreignKeys, nativeTypes) => {
|
|
244
|
+
if (isId) return "PK";
|
|
245
|
+
if (nativeTypes) {
|
|
246
|
+
const allNativeTypes = nativeTypes.flatMap((nativeType) => nativeType);
|
|
247
|
+
if (!isId && allNativeTypes.includes("UniqueIdentifier")) {
|
|
248
|
+
return "FK";
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (!isId && foreignKeys.has(fieldName)) return "FK";
|
|
252
|
+
return "";
|
|
253
|
+
};
|
|
254
|
+
var getOptionalitySymbol = (isRequired) => {
|
|
255
|
+
return isRequired ? "" : `"?"`;
|
|
256
|
+
};
|
|
257
|
+
var generateRelationships2 = ({
|
|
258
|
+
relationships
|
|
259
|
+
}) => {
|
|
260
|
+
const relationLines = [];
|
|
261
|
+
for (const relName in relationships) {
|
|
262
|
+
const sides = relationships[relName];
|
|
263
|
+
if (!sides) continue;
|
|
264
|
+
if (sides.length === 1) {
|
|
265
|
+
const a = sides[0];
|
|
266
|
+
if (!a) continue;
|
|
267
|
+
relationLines.push(
|
|
268
|
+
` ${a.model} ${generateCardinality2({
|
|
269
|
+
isList: a.isList,
|
|
270
|
+
isRequired: a.isRequired
|
|
271
|
+
})}--${generateCardinality2({ isList: false, isRequired: true })} ${a.fieldType} : ${relName}`
|
|
272
|
+
);
|
|
273
|
+
} else if (sides.length === 2) {
|
|
274
|
+
const a = sides[0];
|
|
275
|
+
const b = sides[1];
|
|
276
|
+
if (!a || !b) continue;
|
|
277
|
+
relationLines.push(
|
|
278
|
+
` ${a.model} ${generateCardinality2({
|
|
279
|
+
isList: a.isList,
|
|
280
|
+
isRequired: a.isRequired
|
|
281
|
+
})}--${generateCardinality2({
|
|
282
|
+
isList: b.isList,
|
|
283
|
+
isRequired: b.isRequired
|
|
284
|
+
})} ${b.model} : ${relName}`
|
|
285
|
+
);
|
|
286
|
+
} else {
|
|
287
|
+
for (let i = 1; i < sides.length; i++) {
|
|
288
|
+
const a = sides[0];
|
|
289
|
+
const b = sides[i];
|
|
290
|
+
if (!a || !b) continue;
|
|
291
|
+
relationLines.push(
|
|
292
|
+
` ${a.model} ${generateCardinality2({
|
|
293
|
+
isList: a.isList,
|
|
294
|
+
isRequired: a.isRequired
|
|
295
|
+
})}--${generateCardinality2({
|
|
296
|
+
isList: b.isList,
|
|
297
|
+
isRequired: b.isRequired
|
|
298
|
+
})} ${b.model} : ${relName}`
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return relationLines;
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
// src/lib/MermaidERD/prismaMermaidErd.ts
|
|
307
|
+
var { getDMMF: getDMMF2 } = import_internals2.default;
|
|
308
|
+
var generateDiagram2 = async ({
|
|
309
|
+
outputPath,
|
|
310
|
+
schemaPath,
|
|
311
|
+
generatorPrismaDocument
|
|
312
|
+
}) => {
|
|
313
|
+
const outputDir = outputPath ? import_node_path2.default.resolve(outputPath) : import_node_path2.default.join(`${process.cwd()}/src/generated/diagrams`);
|
|
314
|
+
try {
|
|
315
|
+
const prismaDocument = generatorPrismaDocument ?? await getDMMF2({
|
|
316
|
+
datamodel: (0, import_fs.readFileSync)(schemaPath, "utf-8")
|
|
317
|
+
});
|
|
318
|
+
const schemaModels = prismaDocument.datamodel.models;
|
|
319
|
+
const schemaEnums = prismaDocument.datamodel.enums;
|
|
320
|
+
console.dir(schemaEnums, { depth: null });
|
|
321
|
+
const mermaidLines = [
|
|
322
|
+
"%% --------------------------------------------",
|
|
323
|
+
"%% Auto-generated Mermaid ER Diagram. Do Not Edit Directly.",
|
|
324
|
+
"%% --------------------------------------------\n",
|
|
325
|
+
generateMermaidConfig(mermaidERDiagramConfig, schemaModels),
|
|
326
|
+
"erDiagram"
|
|
327
|
+
];
|
|
328
|
+
const relationships = {};
|
|
329
|
+
schemaModels.forEach((model) => {
|
|
330
|
+
mermaidLines.push(` ${model.name} {`);
|
|
331
|
+
const foreignKeys = /* @__PURE__ */ new Set();
|
|
332
|
+
model.fields.forEach((field) => {
|
|
333
|
+
if (field.relationFromFields && field.relationFromFields.length > 0) {
|
|
334
|
+
field.relationFromFields.forEach((fk) => {
|
|
335
|
+
foreignKeys.add(fk);
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
mermaidLines.push(
|
|
339
|
+
` ${field.type} ${field.name} ${getKeyConstraints(
|
|
340
|
+
field.isId,
|
|
341
|
+
field.name,
|
|
342
|
+
foreignKeys,
|
|
343
|
+
field.nativeType
|
|
344
|
+
)} ${getOptionalitySymbol(field.isRequired)}`
|
|
345
|
+
);
|
|
346
|
+
if (field.relationName) {
|
|
347
|
+
if (!relationships[field.relationName]) {
|
|
348
|
+
relationships[field.relationName] = [];
|
|
349
|
+
}
|
|
350
|
+
relationships[field.relationName].push({
|
|
351
|
+
model: model.name,
|
|
352
|
+
fieldType: field.type,
|
|
353
|
+
isList: field.isList ?? false,
|
|
354
|
+
isRequired: field.isRequired ?? false
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
mermaidLines.push(` }`);
|
|
359
|
+
});
|
|
360
|
+
schemaEnums.forEach((enumDef) => {
|
|
361
|
+
mermaidLines.push(` ${enumDef.name} {`);
|
|
362
|
+
enumDef.values.forEach((enumValue) => {
|
|
363
|
+
mermaidLines.push(` ${enumValue.name}`);
|
|
364
|
+
});
|
|
365
|
+
mermaidLines.push(` }`);
|
|
366
|
+
});
|
|
367
|
+
const relationLines = generateRelationships2({ relationships });
|
|
368
|
+
const output = mermaidLines.concat(relationLines);
|
|
369
|
+
(0, import_node_fs2.mkdirSync)(outputDir, { recursive: true });
|
|
370
|
+
const outFile = import_node_path2.default.join(outputDir, "mermaidErdDiagram.mmd");
|
|
371
|
+
(0, import_fs.writeFileSync)(outFile, output.join("\n"));
|
|
372
|
+
console.log(`Mermaid ERD generated at: ${outFile}`);
|
|
373
|
+
return outFile;
|
|
374
|
+
} catch {
|
|
375
|
+
console.error("Failed to generate Mermaid ER Diagram.");
|
|
376
|
+
return "";
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
380
|
+
0 && (module.exports = {
|
|
381
|
+
generateMermaidClass,
|
|
382
|
+
generateMermaidERD
|
|
383
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { DMMF } from '@prisma/generator-helper';
|
|
2
|
+
|
|
3
|
+
type GenerateDiagramOptions = {
|
|
4
|
+
generatorPrismaDocument?: DMMF.Document;
|
|
5
|
+
schemaPath: string;
|
|
6
|
+
outputPath: string | undefined;
|
|
7
|
+
};
|
|
8
|
+
type Relationships = {
|
|
9
|
+
[key: string]: Array<{
|
|
10
|
+
model: string;
|
|
11
|
+
fieldType: string;
|
|
12
|
+
isList: boolean;
|
|
13
|
+
isRequired: boolean;
|
|
14
|
+
}>;
|
|
15
|
+
};
|
|
16
|
+
type GenerateRelationshipOptions = {
|
|
17
|
+
relationships: Relationships;
|
|
18
|
+
};
|
|
19
|
+
type GenerateCardinalityOptions = {
|
|
20
|
+
isList: boolean;
|
|
21
|
+
isRequired: boolean;
|
|
22
|
+
};
|
|
23
|
+
type ClassCardinality = '"*"' | '"1"' | '"0..1"';
|
|
24
|
+
type ERDCardinality = "||" | "}|" | "o|";
|
|
25
|
+
type GenerateDiagram = (options: GenerateDiagramOptions) => Promise<string>;
|
|
26
|
+
type GenerateRelationships = (options: GenerateRelationshipOptions) => string[];
|
|
27
|
+
type GenerateCardinality = (options: GenerateCardinalityOptions) => ClassCardinality | ERDCardinality;
|
|
28
|
+
type GenerateDiagramSpacingOptions = {
|
|
29
|
+
models: DMMF.Datamodel["models"];
|
|
30
|
+
baseNode: number;
|
|
31
|
+
baseEdge: number;
|
|
32
|
+
};
|
|
33
|
+
type PrismaGeneratorsKeys = "mermaid-erd" | "mermaid-class";
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Generates a Mermaid **Class Diagram** from a Prisma schema.
|
|
37
|
+
*
|
|
38
|
+
* This function reads the Prisma schema (via a provided DMMF document or by
|
|
39
|
+
* reading and parsing the schema file), extracts all models, enums, and
|
|
40
|
+
* relationships, and constructs a Mermaid `classDiagram` definition.
|
|
41
|
+
*
|
|
42
|
+
* The output file is written to:
|
|
43
|
+
* `<outputPath>/mermaidClassDiagram.mmd`
|
|
44
|
+
* or, if `outputPath` is omitted:
|
|
45
|
+
* `<projectRoot>/src/generated/diagrams/mermaidClassDiagram.mmd`
|
|
46
|
+
*/
|
|
47
|
+
declare const generateDiagram$1: ({ outputPath, schemaPath, generatorPrismaDocument, }: GenerateDiagramOptions) => Promise<string>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Generates a Mermaid ERD (Entity-Relationship Diagram) from a Prisma schema.
|
|
51
|
+
*
|
|
52
|
+
* This function reads the Prisma schema (either from the provided DMMF document
|
|
53
|
+
* or by loading and parsing the schema file), extracts all models, enums, and
|
|
54
|
+
* relationships, and then produces a `.mmd` Mermaid ER diagram file.
|
|
55
|
+
*
|
|
56
|
+
* The output file is written to:
|
|
57
|
+
* `<outputPath>/mermaidErdDiagram.mmd`
|
|
58
|
+
* or, if no output path is provided:
|
|
59
|
+
* `<projectRoot>/src/generated/diagrams/mermaidErdDiagram.mmd`
|
|
60
|
+
*/
|
|
61
|
+
declare const generateDiagram: ({ outputPath, schemaPath, generatorPrismaDocument, }: GenerateDiagramOptions) => Promise<string>;
|
|
62
|
+
|
|
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 };
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { DMMF } from '@prisma/generator-helper';
|
|
2
|
+
|
|
3
|
+
type GenerateDiagramOptions = {
|
|
4
|
+
generatorPrismaDocument?: DMMF.Document;
|
|
5
|
+
schemaPath: string;
|
|
6
|
+
outputPath: string | undefined;
|
|
7
|
+
};
|
|
8
|
+
type Relationships = {
|
|
9
|
+
[key: string]: Array<{
|
|
10
|
+
model: string;
|
|
11
|
+
fieldType: string;
|
|
12
|
+
isList: boolean;
|
|
13
|
+
isRequired: boolean;
|
|
14
|
+
}>;
|
|
15
|
+
};
|
|
16
|
+
type GenerateRelationshipOptions = {
|
|
17
|
+
relationships: Relationships;
|
|
18
|
+
};
|
|
19
|
+
type GenerateCardinalityOptions = {
|
|
20
|
+
isList: boolean;
|
|
21
|
+
isRequired: boolean;
|
|
22
|
+
};
|
|
23
|
+
type ClassCardinality = '"*"' | '"1"' | '"0..1"';
|
|
24
|
+
type ERDCardinality = "||" | "}|" | "o|";
|
|
25
|
+
type GenerateDiagram = (options: GenerateDiagramOptions) => Promise<string>;
|
|
26
|
+
type GenerateRelationships = (options: GenerateRelationshipOptions) => string[];
|
|
27
|
+
type GenerateCardinality = (options: GenerateCardinalityOptions) => ClassCardinality | ERDCardinality;
|
|
28
|
+
type GenerateDiagramSpacingOptions = {
|
|
29
|
+
models: DMMF.Datamodel["models"];
|
|
30
|
+
baseNode: number;
|
|
31
|
+
baseEdge: number;
|
|
32
|
+
};
|
|
33
|
+
type PrismaGeneratorsKeys = "mermaid-erd" | "mermaid-class";
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Generates a Mermaid **Class Diagram** from a Prisma schema.
|
|
37
|
+
*
|
|
38
|
+
* This function reads the Prisma schema (via a provided DMMF document or by
|
|
39
|
+
* reading and parsing the schema file), extracts all models, enums, and
|
|
40
|
+
* relationships, and constructs a Mermaid `classDiagram` definition.
|
|
41
|
+
*
|
|
42
|
+
* The output file is written to:
|
|
43
|
+
* `<outputPath>/mermaidClassDiagram.mmd`
|
|
44
|
+
* or, if `outputPath` is omitted:
|
|
45
|
+
* `<projectRoot>/src/generated/diagrams/mermaidClassDiagram.mmd`
|
|
46
|
+
*/
|
|
47
|
+
declare const generateDiagram$1: ({ outputPath, schemaPath, generatorPrismaDocument, }: GenerateDiagramOptions) => Promise<string>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Generates a Mermaid ERD (Entity-Relationship Diagram) from a Prisma schema.
|
|
51
|
+
*
|
|
52
|
+
* This function reads the Prisma schema (either from the provided DMMF document
|
|
53
|
+
* or by loading and parsing the schema file), extracts all models, enums, and
|
|
54
|
+
* relationships, and then produces a `.mmd` Mermaid ER diagram file.
|
|
55
|
+
*
|
|
56
|
+
* The output file is written to:
|
|
57
|
+
* `<outputPath>/mermaidErdDiagram.mmd`
|
|
58
|
+
* or, if no output path is provided:
|
|
59
|
+
* `<projectRoot>/src/generated/diagrams/mermaidErdDiagram.mmd`
|
|
60
|
+
*/
|
|
61
|
+
declare const generateDiagram: ({ outputPath, schemaPath, generatorPrismaDocument, }: GenerateDiagramOptions) => Promise<string>;
|
|
62
|
+
|
|
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 };
|