mikro-orm-markdown 0.1.0-alpha.2 → 0.1.0-alpha.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/CHANGELOG.md +53 -0
- package/CODE_OF_CONDUCT.md +25 -0
- package/LICENSE +1 -1
- package/README.ko.md +248 -41
- package/README.md +248 -41
- package/SECURITY.md +28 -0
- package/dist/cli.cjs +670 -134
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.d.cts +51 -0
- package/dist/cli.d.ts +51 -0
- package/dist/cli.js +650 -136
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +500 -119
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -17
- package/dist/index.d.ts +21 -17
- package/dist/index.js +489 -119
- package/dist/index.js.map +1 -1
- package/package.json +30 -6
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,23 +17,33 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
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
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
21
31
|
var src_exports = {};
|
|
22
32
|
__export(src_exports, {
|
|
23
33
|
MetadataLoadError: () => MetadataLoadError,
|
|
24
|
-
generateMarkdown: () => generateMarkdown
|
|
34
|
+
generateMarkdown: () => generateMarkdown,
|
|
35
|
+
resolveJsDocSources: () => resolveJsDocSources
|
|
25
36
|
});
|
|
26
37
|
module.exports = __toCommonJS(src_exports);
|
|
27
38
|
|
|
28
39
|
// src/docs/jsdoc.ts
|
|
29
40
|
var import_ts_morph = require("ts-morph");
|
|
30
|
-
function loadJsDoc(
|
|
41
|
+
function loadJsDoc(filePaths) {
|
|
31
42
|
const entities = /* @__PURE__ */ new Map();
|
|
32
43
|
const props = /* @__PURE__ */ new Map();
|
|
33
|
-
|
|
34
|
-
|
|
44
|
+
const classNames = /* @__PURE__ */ new Set();
|
|
45
|
+
if (filePaths.length === 0) {
|
|
46
|
+
return { entities, props, sourceFileCount: 0, classNames };
|
|
35
47
|
}
|
|
36
48
|
const project = new import_ts_morph.Project({
|
|
37
49
|
skipAddingFilesFromTsConfig: true,
|
|
@@ -41,34 +53,44 @@ function loadJsDoc(srcGlobs) {
|
|
|
41
53
|
skipLibCheck: true
|
|
42
54
|
}
|
|
43
55
|
});
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
for (const prop of cls.getProperties()) {
|
|
57
|
-
const propDocs = prop.getJsDocs();
|
|
58
|
-
if (propDocs.length === 0) {
|
|
56
|
+
for (const filePath of filePaths) {
|
|
57
|
+
try {
|
|
58
|
+
project.addSourceFilesAtPaths(filePath);
|
|
59
|
+
} catch {
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const sourceFiles = project.getSourceFiles();
|
|
63
|
+
for (const sourceFile of sourceFiles) {
|
|
64
|
+
try {
|
|
65
|
+
for (const cls of sourceFile.getClasses()) {
|
|
66
|
+
const className = cls.getName();
|
|
67
|
+
if (!className) {
|
|
59
68
|
continue;
|
|
60
69
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
70
|
+
classNames.add(className);
|
|
71
|
+
const classDocs = cls.getJsDocs();
|
|
72
|
+
if (classDocs.length > 0) {
|
|
73
|
+
entities.set(className, parseEntityJsDoc(classDocs));
|
|
74
|
+
}
|
|
75
|
+
const propMap = /* @__PURE__ */ new Map();
|
|
76
|
+
for (const prop of cls.getProperties()) {
|
|
77
|
+
const propDocs = prop.getJsDocs();
|
|
78
|
+
if (propDocs.length === 0) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const info = parsePropJsDoc(propDocs);
|
|
82
|
+
if (info.description !== void 0 || info.atLeastOne) {
|
|
83
|
+
propMap.set(prop.getName(), info);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (propMap.size > 0) {
|
|
87
|
+
props.set(className, propMap);
|
|
64
88
|
}
|
|
65
89
|
}
|
|
66
|
-
|
|
67
|
-
props.set(className, propMap);
|
|
68
|
-
}
|
|
90
|
+
} catch {
|
|
69
91
|
}
|
|
70
92
|
}
|
|
71
|
-
return { entities, props };
|
|
93
|
+
return { entities, props, sourceFileCount: sourceFiles.length, classNames };
|
|
72
94
|
}
|
|
73
95
|
function parseEntityJsDoc(jsDocs) {
|
|
74
96
|
const namespaces = [];
|
|
@@ -103,17 +125,25 @@ function parseEntityJsDoc(jsDocs) {
|
|
|
103
125
|
hidden
|
|
104
126
|
};
|
|
105
127
|
}
|
|
106
|
-
function
|
|
128
|
+
function parsePropJsDoc(jsDocs) {
|
|
129
|
+
let description;
|
|
130
|
+
let atLeastOne = false;
|
|
107
131
|
for (const doc of jsDocs) {
|
|
108
132
|
const desc = doc.getDescription().trim();
|
|
109
|
-
if (desc) {
|
|
110
|
-
|
|
133
|
+
if (desc && description === void 0) {
|
|
134
|
+
description = desc;
|
|
135
|
+
}
|
|
136
|
+
for (const tag of doc.getTags()) {
|
|
137
|
+
if (tag.getTagName() === "atLeastOne") {
|
|
138
|
+
atLeastOne = true;
|
|
139
|
+
}
|
|
111
140
|
}
|
|
112
141
|
}
|
|
113
|
-
return void 0;
|
|
142
|
+
return { ...description !== void 0 && { description }, atLeastOne };
|
|
114
143
|
}
|
|
115
144
|
|
|
116
145
|
// src/metadata/load.ts
|
|
146
|
+
var path = __toESM(require("path"), 1);
|
|
117
147
|
var import_core = require("@mikro-orm/core");
|
|
118
148
|
var MetadataLoadError = class extends Error {
|
|
119
149
|
constructor(message, cause) {
|
|
@@ -122,13 +152,46 @@ var MetadataLoadError = class extends Error {
|
|
|
122
152
|
this.name = "MetadataLoadError";
|
|
123
153
|
}
|
|
124
154
|
};
|
|
155
|
+
async function closeDiscoveryResources(orm) {
|
|
156
|
+
await orm.config.getMetadataCacheAdapter()?.close?.();
|
|
157
|
+
await orm.config.getResultCacheAdapter()?.close?.();
|
|
158
|
+
}
|
|
159
|
+
function collectEntitySchemaNames(options) {
|
|
160
|
+
const configuredEntities = [...options.entities ?? [], ...options.entitiesTs ?? []];
|
|
161
|
+
const names = [];
|
|
162
|
+
for (const entity of configuredEntities) {
|
|
163
|
+
if (entity instanceof import_core.EntitySchema) {
|
|
164
|
+
names.push(entity.meta.className);
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (entity !== null && typeof entity === "object" && "schema" in entity && entity.schema instanceof import_core.EntitySchema) {
|
|
168
|
+
names.push(entity.schema.meta.className);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return names;
|
|
172
|
+
}
|
|
173
|
+
function assertNoEntitySchemaEntities(options) {
|
|
174
|
+
const schemaNames = collectEntitySchemaNames(options);
|
|
175
|
+
if (schemaNames.length === 0) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
throw new MetadataLoadError(
|
|
179
|
+
`EntitySchema-defined entities are not currently supported: ${schemaNames.join(", ")}.
|
|
180
|
+
Use decorator-based @Entity() classes instead.`
|
|
181
|
+
);
|
|
182
|
+
}
|
|
125
183
|
async function loadEntityMetadata(options) {
|
|
184
|
+
assertNoEntitySchemaEntities(options);
|
|
126
185
|
let orm;
|
|
127
186
|
try {
|
|
128
187
|
orm = await import_core.MikroORM.init({
|
|
129
188
|
...options,
|
|
130
189
|
debug: false,
|
|
131
|
-
connect: false
|
|
190
|
+
connect: false,
|
|
191
|
+
// Always disable the metadata cache for one-shot doc runs so the project
|
|
192
|
+
// is never littered with a temp/ folder, regardless of how metadataProvider
|
|
193
|
+
// was configured.
|
|
194
|
+
metadataCache: { ...options.metadataCache, enabled: false }
|
|
132
195
|
});
|
|
133
196
|
} catch (cause) {
|
|
134
197
|
throw new MetadataLoadError(
|
|
@@ -136,23 +199,80 @@ async function loadEntityMetadata(options) {
|
|
|
136
199
|
cause
|
|
137
200
|
);
|
|
138
201
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
202
|
+
try {
|
|
203
|
+
const all = Object.values(orm.getMetadata().getAll());
|
|
204
|
+
if (all.length === 0) {
|
|
205
|
+
throw new MetadataLoadError(
|
|
206
|
+
"No entities were discovered. Check that your config specifies at least one entity path or class."
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
const baseDir = orm.config.get("baseDir");
|
|
210
|
+
const sourcePaths = [...new Set(all.filter((m) => m.path).map((m) => path.resolve(baseDir, m.path)))];
|
|
211
|
+
return { metas: all, sourcePaths };
|
|
212
|
+
} finally {
|
|
213
|
+
await closeDiscoveryResources(orm);
|
|
144
214
|
}
|
|
145
|
-
return all;
|
|
146
215
|
}
|
|
147
216
|
|
|
217
|
+
// src/model/build.ts
|
|
218
|
+
var import_core3 = require("@mikro-orm/core");
|
|
219
|
+
|
|
148
220
|
// src/render/mermaid.ts
|
|
149
221
|
var import_core2 = require("@mikro-orm/core");
|
|
222
|
+
|
|
223
|
+
// src/render/escape.ts
|
|
224
|
+
var MARKDOWN_INLINE_SPECIAL_CHARS = /[\\`|*#]/g;
|
|
225
|
+
var MERMAID_IDENTIFIER_INVALID_CHARS = /[^a-zA-Z0-9_]/g;
|
|
226
|
+
function normalizeInlineText(value) {
|
|
227
|
+
return value.replace(/\r\n?/g, "\n").replace(/[\n\t]+/g, " ").replace(/\s{2,}/g, " ").trim();
|
|
228
|
+
}
|
|
229
|
+
function splitNormalizedLines(value) {
|
|
230
|
+
return value.replace(/\r\n?/g, "\n").split("\n");
|
|
231
|
+
}
|
|
232
|
+
function escapeHtmlText(value) {
|
|
233
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
234
|
+
}
|
|
235
|
+
function escapeMarkdownInline(value) {
|
|
236
|
+
return escapeHtmlText(normalizeInlineText(value)).replace(MARKDOWN_INLINE_SPECIAL_CHARS, "\\$&");
|
|
237
|
+
}
|
|
238
|
+
function escapeMarkdownTableCell(value) {
|
|
239
|
+
return splitNormalizedLines(value).map((line) => escapeMarkdownInline(line)).join("<br>");
|
|
240
|
+
}
|
|
241
|
+
function escapeMarkdownParagraph(value) {
|
|
242
|
+
return splitNormalizedLines(value).map((line) => escapeMarkdownInline(line)).join(" \n");
|
|
243
|
+
}
|
|
244
|
+
function renderMarkdownBlockQuote(value) {
|
|
245
|
+
return splitNormalizedLines(value).map((line) => `> ${escapeMarkdownInline(line)}`).join("\n");
|
|
246
|
+
}
|
|
247
|
+
function renderMarkdownInlineCode(value) {
|
|
248
|
+
const normalized = normalizeInlineText(value);
|
|
249
|
+
const backtickRuns = normalized.match(/`+/g) ?? [];
|
|
250
|
+
const longestRun = Math.max(0, ...backtickRuns.map((run) => run.length));
|
|
251
|
+
const fence = "`".repeat(longestRun + 1);
|
|
252
|
+
const needsPadding = normalized.startsWith("`") || normalized.endsWith("`");
|
|
253
|
+
const content = needsPadding ? ` ${normalized} ` : normalized;
|
|
254
|
+
return `${fence}${content}${fence}`;
|
|
255
|
+
}
|
|
256
|
+
function toMermaidIdentifier(value) {
|
|
257
|
+
const normalized = normalizeInlineText(value).replace(MERMAID_IDENTIFIER_INVALID_CHARS, "_").replace(/_+/g, "_");
|
|
258
|
+
const identifier = normalized === "" ? "_" : normalized;
|
|
259
|
+
return /^[a-zA-Z_]/.test(identifier) ? identifier : `_${identifier}`;
|
|
260
|
+
}
|
|
261
|
+
function escapeMermaidQuotedText(value) {
|
|
262
|
+
return normalizeInlineText(value).replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
263
|
+
}
|
|
264
|
+
function toMarkdownAnchor(value) {
|
|
265
|
+
return normalizeInlineText(value).toLowerCase().replace(/[^\p{L}\p{N}\s_-]/gu, "").replace(/\s+/g, "-");
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// src/render/mermaid.ts
|
|
150
269
|
var FORMULA_DUMMY_TABLE = {
|
|
151
270
|
alias: "e0",
|
|
152
271
|
name: "",
|
|
153
272
|
qualifiedName: "",
|
|
154
273
|
toString: () => "e0"
|
|
155
274
|
};
|
|
275
|
+
var UNRESOLVED_FORMULA = "<unresolved>";
|
|
156
276
|
function buildDiagramModel(metas) {
|
|
157
277
|
const metaByClass = new Map(metas.map((m) => [m.className, m]));
|
|
158
278
|
const entities = metas.filter((meta) => !meta.pivotTable && !meta.embeddable).map((meta) => buildEntityModel(meta, metaByClass));
|
|
@@ -160,17 +280,14 @@ function buildDiagramModel(metas) {
|
|
|
160
280
|
return { entities, relations };
|
|
161
281
|
}
|
|
162
282
|
function buildEntityModel(meta, metaByClass) {
|
|
163
|
-
const isStiRoot = meta.discriminatorColumn !== void 0 && !meta.
|
|
283
|
+
const isStiRoot = meta.discriminatorColumn !== void 0 && !meta.extends;
|
|
164
284
|
const isStiChild = Boolean(meta.extends) && meta.discriminatorValue !== void 0;
|
|
165
285
|
const columns = [];
|
|
166
286
|
for (const prop of Object.values(meta.properties)) {
|
|
167
287
|
if (isStiRoot && prop.inherited === true) {
|
|
168
288
|
continue;
|
|
169
289
|
}
|
|
170
|
-
|
|
171
|
-
if (col !== null) {
|
|
172
|
-
columns.push(col);
|
|
173
|
-
}
|
|
290
|
+
columns.push(...buildColumns(prop, metaByClass, meta));
|
|
174
291
|
}
|
|
175
292
|
return {
|
|
176
293
|
className: meta.className,
|
|
@@ -180,47 +297,73 @@ function buildEntityModel(meta, metaByClass) {
|
|
|
180
297
|
isEmbeddable: meta.embeddable === true,
|
|
181
298
|
...isStiRoot && { discriminatorColumn: meta.discriminatorColumn },
|
|
182
299
|
...isStiChild && { extendsEntity: meta.extends },
|
|
300
|
+
...isStiChild && meta.discriminatorValue !== void 0 && { discriminatorValue: String(meta.discriminatorValue) },
|
|
183
301
|
constraints: buildConstraints(meta)
|
|
184
302
|
};
|
|
185
303
|
}
|
|
186
|
-
function
|
|
304
|
+
function buildColumns(prop, metaByClass, owningMeta) {
|
|
187
305
|
if (prop.kind === import_core2.ReferenceKind.EMBEDDED) {
|
|
188
|
-
|
|
306
|
+
if (prop.object === true || prop.array === true) {
|
|
307
|
+
return [
|
|
308
|
+
{
|
|
309
|
+
propName: prop.name,
|
|
310
|
+
fieldName: prop.fieldNames?.[0] ?? prop.name,
|
|
311
|
+
type: "json",
|
|
312
|
+
isPrimary: false,
|
|
313
|
+
isForeignKey: false,
|
|
314
|
+
isUnique: prop.unique === true,
|
|
315
|
+
isNullable: prop.nullable === true,
|
|
316
|
+
...prop.comment !== void 0 && { comment: prop.comment },
|
|
317
|
+
embeddedIn: prop.array === true ? `${prop.type}[]` : prop.type
|
|
318
|
+
}
|
|
319
|
+
];
|
|
320
|
+
}
|
|
321
|
+
return [];
|
|
189
322
|
}
|
|
190
323
|
if (prop.kind === import_core2.ReferenceKind.SCALAR) {
|
|
324
|
+
if (prop.object === true && prop.embedded !== void 0) {
|
|
325
|
+
return [];
|
|
326
|
+
}
|
|
191
327
|
const formulaExpr = prop.formula !== void 0 ? resolveFormulaExpr(prop.formula) : void 0;
|
|
192
328
|
let embeddedIn;
|
|
329
|
+
let embeddedPropName;
|
|
193
330
|
if (prop.embedded !== void 0) {
|
|
194
331
|
const parentPropName = prop.embedded[0];
|
|
195
332
|
embeddedIn = owningMeta.properties[parentPropName]?.type;
|
|
333
|
+
embeddedPropName = prop.embedded[1];
|
|
196
334
|
}
|
|
197
335
|
const isDiscriminator = owningMeta.discriminatorColumn !== void 0 && prop.name === owningMeta.discriminatorColumn;
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
336
|
+
const enumItems = prop.enum === true && Array.isArray(prop.items) && prop.items.length > 0 ? prop.items.map((item) => String(item)) : void 0;
|
|
337
|
+
return [
|
|
338
|
+
{
|
|
339
|
+
propName: prop.name,
|
|
340
|
+
fieldName: prop.fieldNames?.[0] ?? prop.name,
|
|
341
|
+
// Store the original type (e.g. `varchar(255)`); the Mermaid renderer
|
|
342
|
+
// sanitizes it for diagram identifiers, while the markdown table shows
|
|
343
|
+
// it verbatim. Guard against a missing type so downstream string
|
|
344
|
+
// handling never sees undefined (matches the FK path's defaulting).
|
|
345
|
+
type: prop.type ?? "unknown",
|
|
346
|
+
isPrimary: prop.primary === true,
|
|
347
|
+
isForeignKey: false,
|
|
348
|
+
isUnique: prop.unique === true,
|
|
349
|
+
isNullable: prop.nullable === true,
|
|
350
|
+
...prop.comment !== void 0 && { comment: prop.comment },
|
|
351
|
+
...formulaExpr !== void 0 && { formula: formulaExpr },
|
|
352
|
+
...embeddedIn !== void 0 && { embeddedIn },
|
|
353
|
+
...embeddedPropName !== void 0 && { embeddedPropName },
|
|
354
|
+
...isDiscriminator && { isDiscriminator: true },
|
|
355
|
+
...enumItems !== void 0 && { enumItems }
|
|
356
|
+
}
|
|
357
|
+
];
|
|
210
358
|
}
|
|
211
359
|
if (prop.kind === import_core2.ReferenceKind.MANY_TO_ONE || prop.kind === import_core2.ReferenceKind.ONE_TO_ONE && prop.owner === true) {
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
isPrimary: false,
|
|
218
|
-
isForeignKey: true,
|
|
219
|
-
isUnique: prop.unique === true,
|
|
220
|
-
isNullable: prop.nullable === true
|
|
221
|
-
};
|
|
360
|
+
const cols = buildForeignKeyColumns(prop, metaByClass);
|
|
361
|
+
if (prop.type === owningMeta.className) {
|
|
362
|
+
return cols.map((col) => ({ ...col, isSelfReference: true }));
|
|
363
|
+
}
|
|
364
|
+
return cols;
|
|
222
365
|
}
|
|
223
|
-
return
|
|
366
|
+
return [];
|
|
224
367
|
}
|
|
225
368
|
function resolveFormulaExpr(cb) {
|
|
226
369
|
try {
|
|
@@ -230,18 +373,47 @@ function resolveFormulaExpr(cb) {
|
|
|
230
373
|
get: (_target, key) => typeof key === "string" ? key : ""
|
|
231
374
|
}
|
|
232
375
|
);
|
|
233
|
-
|
|
376
|
+
const result = cb(FORMULA_DUMMY_TABLE, cols);
|
|
377
|
+
return typeof result === "string" ? result : String(result);
|
|
234
378
|
} catch {
|
|
235
|
-
return
|
|
379
|
+
return UNRESOLVED_FORMULA;
|
|
236
380
|
}
|
|
237
381
|
}
|
|
238
|
-
function
|
|
239
|
-
const
|
|
382
|
+
function buildForeignKeyColumns(prop, metaByClass) {
|
|
383
|
+
const fieldNames = prop.fieldNames && prop.fieldNames.length > 0 ? prop.fieldNames : [`${prop.name}_id`];
|
|
384
|
+
const fkTypes = resolveFkTypes(prop, metaByClass, fieldNames.length);
|
|
385
|
+
return fieldNames.map((fieldName, index) => ({
|
|
386
|
+
propName: prop.name,
|
|
387
|
+
fieldName,
|
|
388
|
+
type: fkTypes[index] ?? fkTypes[0] ?? "integer",
|
|
389
|
+
isPrimary: prop.primary === true,
|
|
390
|
+
isForeignKey: true,
|
|
391
|
+
isUnique: prop.unique === true,
|
|
392
|
+
isNullable: prop.nullable === true,
|
|
393
|
+
...prop.comment !== void 0 && { comment: prop.comment },
|
|
394
|
+
referencedEntity: prop.type
|
|
395
|
+
}));
|
|
396
|
+
}
|
|
397
|
+
function resolveFkTypes(prop, metaByClass, fieldNameCount) {
|
|
398
|
+
const refMeta = metaByClass.get(prop.type);
|
|
240
399
|
if (!refMeta) {
|
|
241
|
-
return "integer";
|
|
400
|
+
return Array.from({ length: fieldNameCount }, () => "integer");
|
|
401
|
+
}
|
|
402
|
+
const primaryProps = getPrimaryProps(refMeta);
|
|
403
|
+
const referencedColumnNames = prop.referencedColumnNames ?? [];
|
|
404
|
+
return Array.from({ length: fieldNameCount }, (_value, index) => {
|
|
405
|
+
const referencedColumnName = referencedColumnNames[index];
|
|
406
|
+
const pkProp = referencedColumnName !== void 0 ? primaryProps.find((candidate) => candidate.fieldNames.includes(referencedColumnName)) : void 0;
|
|
407
|
+
return (pkProp ?? primaryProps[index] ?? primaryProps[0])?.type ?? "integer";
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
function getPrimaryProps(meta) {
|
|
411
|
+
const primaryKeys = meta.primaryKeys ?? [];
|
|
412
|
+
const orderedPrimaryProps = primaryKeys.map((key) => meta.properties[String(key)]).filter((prop) => prop !== void 0);
|
|
413
|
+
if (orderedPrimaryProps.length > 0) {
|
|
414
|
+
return orderedPrimaryProps;
|
|
242
415
|
}
|
|
243
|
-
|
|
244
|
-
return pkProp ? normalizeType(pkProp.type) : "integer";
|
|
416
|
+
return Object.values(meta.properties).filter((prop) => prop.primary === true);
|
|
245
417
|
}
|
|
246
418
|
function buildConstraints(meta) {
|
|
247
419
|
const result = [];
|
|
@@ -249,7 +421,7 @@ function buildConstraints(meta) {
|
|
|
249
421
|
const props = idx.properties;
|
|
250
422
|
result.push({
|
|
251
423
|
type: "index",
|
|
252
|
-
properties:
|
|
424
|
+
properties: resolveConstraintProperties(meta, props),
|
|
253
425
|
...idx.name !== void 0 && { name: idx.name }
|
|
254
426
|
});
|
|
255
427
|
}
|
|
@@ -257,7 +429,7 @@ function buildConstraints(meta) {
|
|
|
257
429
|
const props = uniq.properties;
|
|
258
430
|
result.push({
|
|
259
431
|
type: "unique",
|
|
260
|
-
properties:
|
|
432
|
+
properties: resolveConstraintProperties(meta, props),
|
|
261
433
|
...uniq.name !== void 0 && { name: uniq.name }
|
|
262
434
|
});
|
|
263
435
|
}
|
|
@@ -274,6 +446,19 @@ function buildConstraints(meta) {
|
|
|
274
446
|
}
|
|
275
447
|
return result;
|
|
276
448
|
}
|
|
449
|
+
function resolveConstraintProperties(meta, props) {
|
|
450
|
+
const propNames = Array.isArray(props) ? props : props !== void 0 ? [props] : [];
|
|
451
|
+
return propNames.flatMap((propName) => {
|
|
452
|
+
const prop = meta.properties[String(propName)];
|
|
453
|
+
if (prop === void 0) {
|
|
454
|
+
return [String(propName)];
|
|
455
|
+
}
|
|
456
|
+
if (prop.fieldNames !== void 0 && prop.fieldNames.length > 0) {
|
|
457
|
+
return prop.fieldNames;
|
|
458
|
+
}
|
|
459
|
+
return [prop.name];
|
|
460
|
+
});
|
|
461
|
+
}
|
|
277
462
|
function buildRelationEdges(metas) {
|
|
278
463
|
const edges = [];
|
|
279
464
|
for (const meta of metas) {
|
|
@@ -292,6 +477,9 @@ function buildRelationEdges(metas) {
|
|
|
292
477
|
function buildEdge(fromEntity, prop) {
|
|
293
478
|
const isNullable = prop.nullable === true;
|
|
294
479
|
if (prop.kind === import_core2.ReferenceKind.MANY_TO_ONE) {
|
|
480
|
+
if (prop.type === fromEntity) {
|
|
481
|
+
return null;
|
|
482
|
+
}
|
|
295
483
|
return {
|
|
296
484
|
fromEntity,
|
|
297
485
|
toEntity: prop.type,
|
|
@@ -323,14 +511,16 @@ function buildEdge(fromEntity, prop) {
|
|
|
323
511
|
function renderErDiagram(model) {
|
|
324
512
|
const lines = ["erDiagram"];
|
|
325
513
|
for (const entity of model.entities) {
|
|
326
|
-
lines.push(` ${entity.className} {`);
|
|
514
|
+
lines.push(` ${toMermaidIdentifier(entity.className)} {`);
|
|
327
515
|
for (const col of entity.columns) {
|
|
328
516
|
lines.push(` ${renderColumnLine(col)}`);
|
|
329
517
|
}
|
|
330
518
|
lines.push(" }");
|
|
331
519
|
}
|
|
332
520
|
for (const rel of model.relations) {
|
|
333
|
-
lines.push(
|
|
521
|
+
lines.push(
|
|
522
|
+
` ${toMermaidIdentifier(rel.fromEntity)} ${rel.fromCardinality}--${rel.toCardinality} ${toMermaidIdentifier(rel.toEntity)} : "${escapeMermaidQuotedText(rel.label)}"`
|
|
523
|
+
);
|
|
334
524
|
}
|
|
335
525
|
return lines.join("\n");
|
|
336
526
|
}
|
|
@@ -338,8 +528,6 @@ function renderColumnLine(col) {
|
|
|
338
528
|
let qualifier = "";
|
|
339
529
|
if (col.isPrimary) {
|
|
340
530
|
qualifier = " PK";
|
|
341
|
-
} else if (col.isForeignKey) {
|
|
342
|
-
qualifier = " FK";
|
|
343
531
|
} else if (col.isUnique) {
|
|
344
532
|
qualifier = " UK";
|
|
345
533
|
}
|
|
@@ -350,27 +538,38 @@ function renderColumnLine(col) {
|
|
|
350
538
|
comment = "discriminator";
|
|
351
539
|
} else if (col.embeddedIn !== void 0) {
|
|
352
540
|
comment = `[${col.embeddedIn}]`;
|
|
353
|
-
} else if (col.
|
|
354
|
-
comment =
|
|
541
|
+
} else if (col.isSelfReference) {
|
|
542
|
+
comment = "self-ref";
|
|
355
543
|
}
|
|
356
|
-
const commentStr = comment !== void 0 ? ` "${comment}"` : "";
|
|
357
|
-
return `${col.type} ${col.fieldName}${qualifier}${commentStr}`;
|
|
358
|
-
}
|
|
359
|
-
function normalizeType(type) {
|
|
360
|
-
return type.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
544
|
+
const commentStr = comment !== void 0 ? ` "${escapeMermaidQuotedText(comment)}"` : "";
|
|
545
|
+
return `${toMermaidIdentifier(col.type)} ${toMermaidIdentifier(col.fieldName)}${qualifier}${commentStr}`;
|
|
361
546
|
}
|
|
362
547
|
|
|
363
548
|
// src/model/build.ts
|
|
364
|
-
|
|
365
|
-
|
|
549
|
+
var FROM_ONE_OR_MORE = "}|";
|
|
550
|
+
var TO_ONE_OR_MORE = "|{";
|
|
551
|
+
function buildDocumentModel(metas, jsDocResult, title, description, onWarn) {
|
|
552
|
+
const { entities: diagramEntities, relations } = buildDiagramModel(metas);
|
|
553
|
+
const allRelations = applyAtLeastOne(relations, metas, jsDocResult.props, onWarn);
|
|
554
|
+
const hiddenClasses = /* @__PURE__ */ new Set();
|
|
555
|
+
for (const model of diagramEntities) {
|
|
556
|
+
if (jsDocResult.entities.get(model.className)?.hidden) {
|
|
557
|
+
hiddenClasses.add(model.className);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
366
560
|
const enrichedByClass = /* @__PURE__ */ new Map();
|
|
367
561
|
for (const model of diagramEntities) {
|
|
368
562
|
const jsDoc = jsDocResult.entities.get(model.className);
|
|
369
563
|
if (jsDoc?.hidden) {
|
|
370
564
|
continue;
|
|
371
565
|
}
|
|
372
|
-
const
|
|
373
|
-
|
|
566
|
+
const columns = model.columns.filter(
|
|
567
|
+
(col) => !(col.isForeignKey && col.referencedEntity !== void 0 && hiddenClasses.has(col.referencedEntity))
|
|
568
|
+
);
|
|
569
|
+
const visibleModel = columns.length === model.columns.length ? model : { ...model, columns };
|
|
570
|
+
const ownPropDocs = jsDocResult.props.get(model.className) ?? /* @__PURE__ */ new Map();
|
|
571
|
+
const propDocs = withEmbeddedPropDocs(ownPropDocs, visibleModel.columns, jsDocResult.props);
|
|
572
|
+
enrichedByClass.set(model.className, { model: visibleModel, jsDoc, propDocs });
|
|
374
573
|
}
|
|
375
574
|
const groupNames = /* @__PURE__ */ new Set();
|
|
376
575
|
let anyUntagged = false;
|
|
@@ -411,6 +610,65 @@ function buildDocumentModel(metas, jsDocResult, title, description) {
|
|
|
411
610
|
});
|
|
412
611
|
return { title, groups, ...description !== void 0 && { description } };
|
|
413
612
|
}
|
|
613
|
+
function withEmbeddedPropDocs(ownPropDocs, columns, allPropDocs) {
|
|
614
|
+
const merged = new Map(ownPropDocs);
|
|
615
|
+
for (const col of columns) {
|
|
616
|
+
if (merged.has(col.propName) || col.embeddedIn === void 0 || col.embeddedPropName === void 0) {
|
|
617
|
+
continue;
|
|
618
|
+
}
|
|
619
|
+
const info = allPropDocs.get(col.embeddedIn)?.get(col.embeddedPropName);
|
|
620
|
+
if (info) {
|
|
621
|
+
merged.set(col.propName, info);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
return merged;
|
|
625
|
+
}
|
|
626
|
+
function applyAtLeastOne(relations, metas, props, onWarn) {
|
|
627
|
+
const adjusted = relations.map((edge) => ({ ...edge }));
|
|
628
|
+
const metaByClass = new Map(metas.map((m) => [m.className, m]));
|
|
629
|
+
for (const [className, propMap] of props) {
|
|
630
|
+
const meta = metaByClass.get(className);
|
|
631
|
+
if (!meta) {
|
|
632
|
+
continue;
|
|
633
|
+
}
|
|
634
|
+
for (const [propName, info] of propMap) {
|
|
635
|
+
if (!info.atLeastOne) {
|
|
636
|
+
continue;
|
|
637
|
+
}
|
|
638
|
+
const prop = meta.properties[propName];
|
|
639
|
+
if (!prop) {
|
|
640
|
+
continue;
|
|
641
|
+
}
|
|
642
|
+
let edge;
|
|
643
|
+
if (prop.kind === import_core3.ReferenceKind.ONE_TO_MANY && prop.mappedBy) {
|
|
644
|
+
edge = adjusted.find(
|
|
645
|
+
(e) => e.fromEntity === prop.type && e.toEntity === className && e.label === prop.mappedBy
|
|
646
|
+
);
|
|
647
|
+
if (edge) {
|
|
648
|
+
edge.fromCardinality = FROM_ONE_OR_MORE;
|
|
649
|
+
}
|
|
650
|
+
} else if (prop.kind === import_core3.ReferenceKind.MANY_TO_MANY && prop.owner === true) {
|
|
651
|
+
edge = adjusted.find((e) => e.fromEntity === className && e.toEntity === prop.type && e.label === propName);
|
|
652
|
+
if (edge) {
|
|
653
|
+
edge.toCardinality = TO_ONE_OR_MORE;
|
|
654
|
+
}
|
|
655
|
+
} else if (prop.kind === import_core3.ReferenceKind.MANY_TO_MANY && prop.mappedBy) {
|
|
656
|
+
edge = adjusted.find(
|
|
657
|
+
(e) => e.fromEntity === prop.type && e.toEntity === className && e.label === prop.mappedBy
|
|
658
|
+
);
|
|
659
|
+
if (edge) {
|
|
660
|
+
edge.fromCardinality = FROM_ONE_OR_MORE;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
if (!edge) {
|
|
664
|
+
onWarn?.(
|
|
665
|
+
`@atLeastOne on ${className}.${propName} had no effect: no matching relation edge was found. It applies only to collection relations that can be matched to a rendered edge: @OneToMany with mappedBy, or @ManyToMany on either the owning side or an inverse mappedBy side.`
|
|
666
|
+
);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
return adjusted;
|
|
671
|
+
}
|
|
414
672
|
function hasNoNamespaceTags(jsDoc) {
|
|
415
673
|
if (!jsDoc) {
|
|
416
674
|
return true;
|
|
@@ -436,19 +694,55 @@ function belongsToGroupForText(jsDoc, groupName, isDefault) {
|
|
|
436
694
|
return jsDoc.namespaces.includes(groupName) || jsDoc.describeNamespaces.includes(groupName);
|
|
437
695
|
}
|
|
438
696
|
|
|
697
|
+
// src/provider.ts
|
|
698
|
+
async function withTsMorphMetadataProvider(options, onWarn) {
|
|
699
|
+
if (options.metadataProvider !== void 0) {
|
|
700
|
+
return options;
|
|
701
|
+
}
|
|
702
|
+
try {
|
|
703
|
+
const { TsMorphMetadataProvider } = await import("@mikro-orm/reflection");
|
|
704
|
+
return { ...options, metadataProvider: TsMorphMetadataProvider };
|
|
705
|
+
} catch (err) {
|
|
706
|
+
const code = err !== null && typeof err === "object" && "code" in err ? err.code : void 0;
|
|
707
|
+
const isNotInstalled = code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND";
|
|
708
|
+
if (!isNotInstalled && onWarn) {
|
|
709
|
+
onWarn(
|
|
710
|
+
`@mikro-orm/reflection is installed but failed to load: ${err instanceof Error ? err.message : String(err)}. Ensure all @mikro-orm/* packages are installed at the same version.`
|
|
711
|
+
);
|
|
712
|
+
}
|
|
713
|
+
return options;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
|
|
439
717
|
// src/render/markdown.ts
|
|
440
718
|
function renderMarkdown(docModel) {
|
|
441
|
-
const sections = [`# ${docModel.title}`];
|
|
719
|
+
const sections = [`# ${escapeMarkdownInline(docModel.title)}`];
|
|
442
720
|
if (docModel.description) {
|
|
443
|
-
sections.push(docModel.description);
|
|
721
|
+
sections.push(escapeMarkdownParagraph(docModel.description));
|
|
722
|
+
}
|
|
723
|
+
if (docModel.groups.length > 1) {
|
|
724
|
+
sections.push(renderTableOfContents(docModel.groups));
|
|
444
725
|
}
|
|
445
726
|
for (const group of docModel.groups) {
|
|
446
727
|
sections.push(renderGroupSection(group));
|
|
447
728
|
}
|
|
448
729
|
return sections.join("\n\n");
|
|
449
730
|
}
|
|
731
|
+
function renderBulletSection(header, items, renderItem) {
|
|
732
|
+
const lines = [header, ""];
|
|
733
|
+
for (const item of items) {
|
|
734
|
+
lines.push(renderItem(item));
|
|
735
|
+
}
|
|
736
|
+
return lines.join("\n");
|
|
737
|
+
}
|
|
738
|
+
function renderTableOfContents(groups) {
|
|
739
|
+
return renderBulletSection("## Contents", groups, (group) => {
|
|
740
|
+
const label = escapeMarkdownInline(group.name).replace(/[[\]]/g, "\\$&");
|
|
741
|
+
return `- [${label}](#${toMarkdownAnchor(group.name)})`;
|
|
742
|
+
});
|
|
743
|
+
}
|
|
450
744
|
function renderGroupSection(group) {
|
|
451
|
-
const parts = [`## ${group.name}`];
|
|
745
|
+
const parts = [`## ${escapeMarkdownInline(group.name)}`];
|
|
452
746
|
if (group.erdEntities.length > 0) {
|
|
453
747
|
const diagramModel = {
|
|
454
748
|
entities: group.erdEntities.map((e) => e.model),
|
|
@@ -462,14 +756,18 @@ function renderGroupSection(group) {
|
|
|
462
756
|
return parts.join("\n\n");
|
|
463
757
|
}
|
|
464
758
|
function renderEntitySection(entity) {
|
|
465
|
-
const parts = [`### ${entity.model.className}`];
|
|
759
|
+
const parts = [`### ${escapeMarkdownInline(entity.model.className)}`];
|
|
760
|
+
parts.push(`*Table: ${renderMarkdownInlineCode(entity.model.tableName)}*`);
|
|
466
761
|
if (entity.jsDoc?.description) {
|
|
467
|
-
parts.push(
|
|
762
|
+
parts.push(renderMarkdownBlockQuote(entity.jsDoc.description));
|
|
468
763
|
}
|
|
469
764
|
if (entity.model.discriminatorColumn) {
|
|
470
|
-
parts.push(`*STI root \u2014 discriminator column:
|
|
765
|
+
parts.push(`*STI root \u2014 discriminator column: ${renderMarkdownInlineCode(entity.model.discriminatorColumn)}*`);
|
|
471
766
|
} else if (entity.model.extendsEntity) {
|
|
472
|
-
|
|
767
|
+
const discValue = entity.model.discriminatorValue !== void 0 ? `, discriminator value: ${renderMarkdownInlineCode(entity.model.discriminatorValue)}` : "";
|
|
768
|
+
parts.push(
|
|
769
|
+
`*Extends ${renderMarkdownInlineCode(entity.model.extendsEntity)} (Single Table Inheritance${discValue})*`
|
|
770
|
+
);
|
|
473
771
|
}
|
|
474
772
|
if (entity.model.columns.length > 0) {
|
|
475
773
|
parts.push(renderColumnTable(entity));
|
|
@@ -477,6 +775,10 @@ function renderEntitySection(entity) {
|
|
|
477
775
|
if (entity.model.constraints.length > 0) {
|
|
478
776
|
parts.push(renderConstraints(entity.model.constraints));
|
|
479
777
|
}
|
|
778
|
+
const computedColumns = entity.model.columns.filter((col) => col.formula !== void 0);
|
|
779
|
+
if (computedColumns.length > 0) {
|
|
780
|
+
parts.push(renderComputedColumns(computedColumns));
|
|
781
|
+
}
|
|
480
782
|
return parts.join("\n\n");
|
|
481
783
|
}
|
|
482
784
|
function renderColumnTable(entity) {
|
|
@@ -485,24 +787,27 @@ function renderColumnTable(entity) {
|
|
|
485
787
|
const rows = entity.model.columns.map((col) => {
|
|
486
788
|
const key = resolveColumnKey(col);
|
|
487
789
|
const nullable = col.isNullable && !col.isPrimary ? "Y" : "";
|
|
488
|
-
const
|
|
489
|
-
|
|
790
|
+
const docDesc = entity.propDocs.get(col.propName)?.description ?? col.comment ?? "";
|
|
791
|
+
const enumDesc = col.enumItems !== void 0 ? `One of: ${col.enumItems.join(", ")}` : "";
|
|
792
|
+
const desc = [docDesc, enumDesc].filter((part) => part !== "").join("\n");
|
|
793
|
+
return `| ${escapeMarkdownTableCell(col.fieldName)} | ${escapeMarkdownTableCell(col.type)} | ${escapeMarkdownTableCell(key)} | ${nullable} | ${escapeMarkdownTableCell(desc)} |`;
|
|
490
794
|
});
|
|
491
795
|
return [header, sep, ...rows].join("\n");
|
|
492
796
|
}
|
|
493
797
|
function resolveColumnKey(col) {
|
|
798
|
+
const fkKey = col.fieldName !== col.propName ? `FK (${col.propName})` : "FK";
|
|
799
|
+
if (col.isPrimary && col.isForeignKey) {
|
|
800
|
+
return `PK, ${fkKey}`;
|
|
801
|
+
}
|
|
494
802
|
if (col.isPrimary) {
|
|
495
803
|
return "PK";
|
|
496
804
|
}
|
|
497
805
|
if (col.isForeignKey) {
|
|
498
|
-
return
|
|
806
|
+
return fkKey;
|
|
499
807
|
}
|
|
500
808
|
if (col.isUnique) {
|
|
501
809
|
return "UK";
|
|
502
810
|
}
|
|
503
|
-
if (col.formula !== void 0) {
|
|
504
|
-
return `formula: ${col.formula}`;
|
|
505
|
-
}
|
|
506
811
|
if (col.isDiscriminator) {
|
|
507
812
|
return "discriminator";
|
|
508
813
|
}
|
|
@@ -511,32 +816,108 @@ function resolveColumnKey(col) {
|
|
|
511
816
|
}
|
|
512
817
|
return "";
|
|
513
818
|
}
|
|
819
|
+
function renderComputedColumns(columns) {
|
|
820
|
+
return renderBulletSection("**Computed columns:**", columns, (col) => {
|
|
821
|
+
const expr = col.formula ? `: ${renderMarkdownInlineCode(col.formula)}` : "";
|
|
822
|
+
return `- ${renderMarkdownInlineCode(col.fieldName)}${expr}`;
|
|
823
|
+
});
|
|
824
|
+
}
|
|
514
825
|
function renderConstraints(constraints) {
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
const
|
|
826
|
+
return renderBulletSection("**Constraints:**", constraints, (c) => {
|
|
827
|
+
const name = c.name ? ` ${renderMarkdownInlineCode(c.name)}` : "";
|
|
828
|
+
const properties = c.properties.map(escapeMarkdownInline).join(", ");
|
|
518
829
|
if (c.type === "index") {
|
|
519
|
-
|
|
520
|
-
} else if (c.type === "unique") {
|
|
521
|
-
lines.push(`- Unique${name}: (${c.properties.join(", ")})`);
|
|
522
|
-
} else if (c.type === "check") {
|
|
523
|
-
lines.push(`- Check${name}: \`${c.expression ?? ""}\``);
|
|
830
|
+
return `- Index${name}: (${properties})`;
|
|
524
831
|
}
|
|
525
|
-
|
|
526
|
-
|
|
832
|
+
if (c.type === "unique") {
|
|
833
|
+
return `- Unique${name}: (${properties})`;
|
|
834
|
+
}
|
|
835
|
+
return `- Check${name}: ${renderMarkdownInlineCode(c.expression ?? "")}`;
|
|
836
|
+
});
|
|
527
837
|
}
|
|
528
838
|
|
|
529
839
|
// src/index.ts
|
|
840
|
+
var COMPILED_JS = /\.(c|m)?js$/i;
|
|
841
|
+
function resolveJsDocSources(sourcePaths, src, onWarn) {
|
|
842
|
+
if (src !== void 0 && src.length > 0) {
|
|
843
|
+
return src;
|
|
844
|
+
}
|
|
845
|
+
if (sourcePaths.some((p) => COMPILED_JS.test(p)) && onWarn) {
|
|
846
|
+
onWarn(
|
|
847
|
+
'Entities were discovered from compiled JavaScript, so JSDoc descriptions and @namespace/@hidden tags cannot be read (build tools strip comments). Hidden entities may be exposed. Pass --src "<glob to your .ts sources>" (or the `src` option) to read JSDoc from the original TypeScript files.'
|
|
848
|
+
);
|
|
849
|
+
}
|
|
850
|
+
return sourcePaths;
|
|
851
|
+
}
|
|
852
|
+
function assertExplicitJsDocSourceCoverage(metas, jsDocResult, src, onWarn) {
|
|
853
|
+
if (jsDocResult.sourceFileCount === 0) {
|
|
854
|
+
throw new Error(
|
|
855
|
+
`No source files matched the explicit src paths: ${src.join(", ")}
|
|
856
|
+
Check the --src glob/path (or the \`src\` option). Without matching TypeScript sources, JSDoc tags such as @namespace and @hidden cannot be read.`
|
|
857
|
+
);
|
|
858
|
+
}
|
|
859
|
+
const isRenderable = (meta) => !meta.pivotTable && !meta.embeddable;
|
|
860
|
+
const missingConcrete = metas.filter((meta) => isRenderable(meta) && !meta.abstract).map((meta) => meta.className).filter((className) => !jsDocResult.classNames.has(className));
|
|
861
|
+
if (missingConcrete.length > 0) {
|
|
862
|
+
throw new Error(
|
|
863
|
+
`Explicit src paths did not include source declarations for discovered entities: ${missingConcrete.join(", ")}
|
|
864
|
+
Check that --src (or the \`src\` option) points at all TypeScript entity files. JSDoc tags such as @namespace and @hidden for missing entities cannot be read.`
|
|
865
|
+
);
|
|
866
|
+
}
|
|
867
|
+
if (onWarn) {
|
|
868
|
+
const missingAbstract = metas.filter((meta) => isRenderable(meta) && meta.abstract).map((meta) => meta.className).filter((className) => !jsDocResult.classNames.has(className));
|
|
869
|
+
if (missingAbstract.length > 0) {
|
|
870
|
+
onWarn(
|
|
871
|
+
`Abstract STI parent entities were not found in the explicit src paths: ${missingAbstract.join(", ")}
|
|
872
|
+
@hidden and @namespace tags for these entities will not be applied. Include their source files in --src to enable JSDoc tags for them.`
|
|
873
|
+
);
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
function errorMessages(err) {
|
|
878
|
+
const messages = [];
|
|
879
|
+
const seen = /* @__PURE__ */ new Set();
|
|
880
|
+
let current = err;
|
|
881
|
+
while (current instanceof Error && !seen.has(current)) {
|
|
882
|
+
seen.add(current);
|
|
883
|
+
messages.push(current.message);
|
|
884
|
+
current = current.cause;
|
|
885
|
+
}
|
|
886
|
+
return messages;
|
|
887
|
+
}
|
|
888
|
+
function isMissingTsMorphSourceFile(err) {
|
|
889
|
+
return errorMessages(err).some((message) => message.includes("Source file") && message.includes("not found"));
|
|
890
|
+
}
|
|
891
|
+
async function loadEntityMetadataWithTsMorphFallback(originalOrm, effectiveOrm) {
|
|
892
|
+
try {
|
|
893
|
+
return await loadEntityMetadata(effectiveOrm);
|
|
894
|
+
} catch (err) {
|
|
895
|
+
const wasAutoInjected = originalOrm.metadataProvider === void 0 && effectiveOrm.metadataProvider !== void 0;
|
|
896
|
+
if (!wasAutoInjected || !isMissingTsMorphSourceFile(err)) {
|
|
897
|
+
throw err;
|
|
898
|
+
}
|
|
899
|
+
try {
|
|
900
|
+
return await loadEntityMetadata(originalOrm);
|
|
901
|
+
} catch {
|
|
902
|
+
throw err;
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
}
|
|
530
906
|
async function generateMarkdown(options) {
|
|
531
|
-
const { orm, title = "Database Schema", description, src
|
|
532
|
-
const
|
|
533
|
-
const
|
|
534
|
-
const
|
|
907
|
+
const { orm, title = "Database Schema", description, src, onWarn } = options;
|
|
908
|
+
const effectiveOrm = await withTsMorphMetadataProvider(orm, onWarn);
|
|
909
|
+
const { metas, sourcePaths } = await loadEntityMetadataWithTsMorphFallback(orm, effectiveOrm);
|
|
910
|
+
const jsDocResult = loadJsDoc(resolveJsDocSources(sourcePaths, src, onWarn));
|
|
911
|
+
if (src !== void 0 && src.length > 0) {
|
|
912
|
+
assertExplicitJsDocSourceCoverage(metas, jsDocResult, src, onWarn);
|
|
913
|
+
}
|
|
914
|
+
const docModel = buildDocumentModel(metas, jsDocResult, title, description, onWarn);
|
|
535
915
|
return renderMarkdown(docModel);
|
|
536
916
|
}
|
|
537
917
|
// Annotate the CommonJS export names for ESM import in node:
|
|
538
918
|
0 && (module.exports = {
|
|
539
919
|
MetadataLoadError,
|
|
540
|
-
generateMarkdown
|
|
920
|
+
generateMarkdown,
|
|
921
|
+
resolveJsDocSources
|
|
541
922
|
});
|
|
542
923
|
//# sourceMappingURL=index.cjs.map
|