docs: added typedoc plugin to parse DML json files (#8300)

* docs-util: add docblock generator for models built with DML

* add missing turbo task

* docs-util: added typedoc plugin to parse dml json files
This commit is contained in:
Shahed Nasser
2024-07-29 14:19:04 +02:00
committed by GitHub
parent df734a3ce9
commit 7ad4e7b1c9
11 changed files with 124 additions and 29 deletions
@@ -34,6 +34,7 @@
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20.9.4", "@types/node": "^20.9.4",
"@types/pluralize": "^0.0.33" "@types/pluralize": "^0.0.33",
"types": "*"
} }
} }
@@ -5,7 +5,7 @@ import { GeneratorEvent } from "../helpers/generator-event-manager.js"
import { minimatch } from "minimatch" import { minimatch } from "minimatch"
import getBasePath from "../../utils/get-base-path.js" import getBasePath from "../../utils/get-base-path.js"
import toJsonFormatted from "../../utils/to-json-formatted.js" import toJsonFormatted from "../../utils/to-json-formatted.js"
import { DmlFile } from "../../types/index.js" import { DmlFile } from "types"
/** /**
* A class used to generate DML JSON files with descriptions of properties. * A class used to generate DML JSON files with descriptions of properties.
@@ -5,7 +5,7 @@ import { getDmlOutputBasePath } from "../../utils/get-output-base-paths.js"
import path from "path" import path from "path"
import { camelToWords, RELATION_NAMES, snakeToPascal } from "utils" import { camelToWords, RELATION_NAMES, snakeToPascal } from "utils"
import toJsonFormatted from "../../utils/to-json-formatted.js" import toJsonFormatted from "../../utils/to-json-formatted.js"
import { DmlFile, DmlObject } from "../../types/index.js" import { DmlFile, DmlObject } from "types"
/** /**
* DML generator for data models created with DML. * DML generator for data models created with DML.
@@ -2,7 +2,7 @@ import { readdirSync, existsSync, readFileSync, writeFileSync } from "fs"
import { getDmlOutputBasePath } from "../utils/get-output-base-paths.js" import { getDmlOutputBasePath } from "../utils/get-output-base-paths.js"
import path from "path" import path from "path"
import getMonorepoRoot from "../utils/get-monorepo-root.js" import getMonorepoRoot from "../utils/get-monorepo-root.js"
import { DmlFile } from "../types/index.js" import { DmlFile } from "types"
import toJsonFormatted from "../utils/to-json-formatted.js" import toJsonFormatted from "../utils/to-json-formatted.js"
export default async function () { export default async function () {
@@ -2,7 +2,7 @@
"name": "typedoc-generate-references", "name": "typedoc-generate-references",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"dev": "cross-env ts-node src/index.ts", "dev": "node --loader ts-node/esm src/index.ts",
"start": "node dist/index.js", "start": "node dist/index.js",
"build": "tsc", "build": "tsc",
"watch": "tsc --watch", "watch": "tsc --watch",
@@ -24,6 +24,7 @@
"devDependencies": { "devDependencies": {
"@types/eslint": "^8.56.6", "@types/eslint": "^8.56.6",
"@types/node": "^16.11.10", "@types/node": "^16.11.10",
"types": "*",
"typescript": "5.5" "typescript": "5.5"
}, },
"keywords": [ "keywords": [
@@ -0,0 +1,104 @@
import { existsSync, readFileSync } from "fs"
import path from "path"
import {
Application,
Comment,
Context,
Converter,
DeclarationReflection,
ReferenceType,
} from "typedoc"
import { getDmlProperties, isDmlEntity } from "utils"
import { DmlFile } from "types"
const FILE_NAME_REGEX = /packages\/modules\/(?<module>[a-z-]+)/
export function load(app: Application) {
app.converter.on(
Converter.EVENT_CREATE_DECLARATION,
getDescriptionsFromJson,
2
)
}
function getDescriptionsFromJson(
context: Context,
reflection: DeclarationReflection
) {
if (!isDmlEntity(reflection)) {
return
}
const dmlPropertyReflections = getDmlProperties(
reflection.type as ReferenceType
)
if (!dmlPropertyReflections) {
return
}
const fileName = context.project
.getSymbolFromReflection(reflection)
?.valueDeclaration?.parent.getSourceFile().fileName
if (!fileName) {
return
}
const moduleName = FILE_NAME_REGEX.exec(fileName)
if (!moduleName?.groups?.module) {
return
}
const jsonFilePath = path.resolve(
__dirname,
path.join(
"..",
"..",
"..",
"generated",
"dml-output",
`${moduleName.groups.module}.json`
)
)
if (!existsSync(jsonFilePath)) {
return
}
const jsonFileContent = JSON.parse(
readFileSync(jsonFilePath, "utf-8")
) as DmlFile
if (!jsonFileContent[reflection.name]) {
return
}
Object.entries(jsonFileContent[reflection.name].properties).forEach(
([propertyName, description]) => {
const propertyReflection = dmlPropertyReflections.find(
(propertyRef) => propertyRef.name === propertyName
)
if (!propertyReflection) {
return
}
const comment = propertyReflection.comment || new Comment()
const isExpandable = description.includes("@expandable")
comment.summary.push({
kind: "text",
text: description.replace("@expandable", "").trim(),
})
if (isExpandable) {
comment.modifierTags.add("@expandable")
}
propertyReflection.comment = comment
}
)
}
@@ -41,12 +41,6 @@ export class DmlRelationsResolver {
this.resolveRelationReferences.bind(this), this.resolveRelationReferences.bind(this),
1 1
) )
// this.app.converter.on(
// Converter.EVENT_RESOLVE_BEGIN,
// this.resolveRelationTargets.bind(this),
// -1
// )
} }
addReflection(_context: Context, reflection: DeclarationReflection) { addReflection(_context: Context, reflection: DeclarationReflection) {
@@ -110,24 +104,6 @@ export class DmlRelationsResolver {
}) })
} }
resolveRelationTargets(context: Context) {
if (!this.app.options.getValue("resolveDmlRelations")) {
return
}
this.relationProperties.forEach(({ property, target }) => {
const targetSymbol = context.project.getSymbolFromReflection(target)
if (property.type?.type !== "reference" || !targetSymbol) {
return
}
// change reference to the target itself.
property.type = ReferenceType.createResolvedReference(
`DmlEntity`,
target,
context.project
)
})
}
findReflectionMatchingProperties( findReflectionMatchingProperties(
properties: DeclarationReflection[] properties: DeclarationReflection[]
): DeclarationReflection | undefined { ): DeclarationReflection | undefined {
@@ -11,6 +11,7 @@ import { GenerateNamespacePlugin } from "./generate-namespace"
import { DmlRelationsResolver } from "./dml-relations-resolver" import { DmlRelationsResolver } from "./dml-relations-resolver"
import { load as dmlTypesNormalizer } from "./dml-types-normalizer" import { load as dmlTypesNormalizer } from "./dml-types-normalizer"
import { MermaidDiagramDMLGenerator } from "./mermaid-diagram-dml-generator" import { MermaidDiagramDMLGenerator } from "./mermaid-diagram-dml-generator"
import { load as dmlJsonParser } from "./dml-json-parser"
export function load(app: Application) { export function load(app: Application) {
resolveReferencesPluginLoad(app) resolveReferencesPluginLoad(app)
@@ -21,6 +22,7 @@ export function load(app: Application) {
signatureModifierPlugin(app) signatureModifierPlugin(app)
parentIgnorePlugin(app) parentIgnorePlugin(app)
dmlTypesNormalizer(app) dmlTypesNormalizer(app)
dmlJsonParser(app)
new GenerateNamespacePlugin(app) new GenerateNamespacePlugin(app)
new MermaidDiagramGenerator(app) new MermaidDiagramGenerator(app)
+9
View File
@@ -259,3 +259,12 @@ export declare module "typedoc" {
normalizeDmlTypes: boolean normalizeDmlTypes: boolean
} }
} }
export declare type DmlObject = Record<string, string>
export declare type DmlFile = {
[k: string]: {
filePath: string
properties: DmlObject
}
}
+2
View File
@@ -2360,6 +2360,7 @@ __metadata:
pluralize: ^8.0.0 pluralize: ^8.0.0
prettier: ^3.2.4 prettier: ^3.2.4
ts-node: ^10.9.1 ts-node: ^10.9.1
types: "*"
typescript: 5.5 typescript: 5.5
utils: "*" utils: "*"
yaml: ^2.3.4 yaml: ^2.3.4
@@ -5346,6 +5347,7 @@ __metadata:
"@types/node": ^16.11.10 "@types/node": ^16.11.10
eslint: ^8.53.0 eslint: ^8.53.0
glob: ^10.3.10 glob: ^10.3.10
types: "*"
typescript: 5.5 typescript: 5.5
utils: "*" utils: "*"
yaml: ^2.3.3 yaml: ^2.3.3