diff --git a/packages/models/project.json b/packages/models/project.json index 0045b607e..b09523d29 100644 --- a/packages/models/project.json +++ b/packages/models/project.json @@ -21,7 +21,7 @@ "dependsOn": [ "^build", "generate-docs", - { "projects": "models-transformers", "target": "build" } + { "projects": "zod2md-jsdocs", "target": "build" } ] }, "lint": {}, diff --git a/packages/models/tsconfig.lib.json b/packages/models/tsconfig.lib.json index 2c92983e0..366c01702 100644 --- a/packages/models/tsconfig.lib.json +++ b/packages/models/tsconfig.lib.json @@ -6,8 +6,9 @@ "types": ["node"], "plugins": [ { - "transform": "./packages/models/transformers/dist", - "afterDeclarations": true + "transform": "./tools/zod2md-jsdocs/dist", + "afterDeclarations": true, + "baseUrl": "https://github.com/code-pushup/cli/blob/main/packages/models/docs/models-reference.md" } ] }, diff --git a/tools/zod2md-jsdocs/README.md b/tools/zod2md-jsdocs/README.md new file mode 100644 index 000000000..c56a57a0b --- /dev/null +++ b/tools/zod2md-jsdocs/README.md @@ -0,0 +1,71 @@ +# @code-pushup/zod2md-jsdocs + +TypeScript transformer plugin that automatically enhances type definitions with JSDoc comments and schema metadata. + +## Purpose + +This package provides a TypeScript compiler transformer that automatically adds JSDoc documentation to type aliases and interfaces during compilation. It's designed to improve developer experience by injecting helpful metadata and documentation links directly into generated type definitions. + +## How It Works + +The [TS transformer](https://github.com/itsdouges/typescript-transformer-handbook) hooks into the TypeScript compilation process using `ts-patch` and automatically adds JSDoc comments above type definitions. Each comment includes: + +- The type name +- A description explaining the type is derived from a Zod schema +- A link to the type reference documentation + +## Example + +Given a type definition like: + +```typescript +export type Report = { + // ... type properties +}; +``` + +The transformer automatically generates: + +```typescript +/** + * Type Definition: `Report` + * + * This type is derived from a Zod schema and represents + * the validated structure of `Report` used within the application. + * + * @see {@link https://github.com/code-pushup/cli/blob/main/packages/models/docs/models-reference.md#report} + */ +export type Report = { + // ... type properties +}; +``` + +## Usage + +1. `ts-patch install` + +2. Add the transformer to your `tsconfig.json`: + +```json +{ + "compilerOptions": { + "plugins": [ + { + "transform": "./path/to/transformer/dist", + "afterDeclarations": true, + "baseUrl": "https://example.com/docs/api-reference.md" + } + ] + } +} +``` + +3. Build your TypeScript project. The transformer will run automatically and add JSDoc comments to your type definitions. + +### Options + +| Option | Type | Required | Description | +| ------------------- | --------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `transform` | `string` | Yes | Path to the transformer module | +| `afterDeclarations` | `boolean` | No | Set to `true` to run the transformer after TypeScript generates declaration files (`.d.ts`). This ensures JSDoc comments are added to the emitted type definitions. | +| `baseUrl` | `string` | Yes | Base URL for documentation links (e.g., `https://example.com/docs/api-reference.md`) | diff --git a/packages/models/transformers/eslint.config.cjs b/tools/zod2md-jsdocs/eslint.config.cjs similarity index 67% rename from packages/models/transformers/eslint.config.cjs rename to tools/zod2md-jsdocs/eslint.config.cjs index 4eaecdb17..467b6c94b 100644 --- a/packages/models/transformers/eslint.config.cjs +++ b/tools/zod2md-jsdocs/eslint.config.cjs @@ -1,4 +1,4 @@ -const baseConfig = require('../../../eslint.config.js').default; +const baseConfig = require('../../eslint.config.js').default; module.exports = [ ...baseConfig, diff --git a/packages/models/transformers/package.json b/tools/zod2md-jsdocs/package.json similarity index 85% rename from packages/models/transformers/package.json rename to tools/zod2md-jsdocs/package.json index e5d33d01b..e29c5d9db 100644 --- a/packages/models/transformers/package.json +++ b/tools/zod2md-jsdocs/package.json @@ -1,5 +1,5 @@ { - "name": "@code-pushup/models-transformers", + "name": "@code-pushup/zod2md-jsdocs", "version": "0.0.0", "description": "TypeScript transformers enhancing models with JSDoc and schema metadata", "type": "commonjs", diff --git a/packages/models/transformers/project.json b/tools/zod2md-jsdocs/project.json similarity index 51% rename from packages/models/transformers/project.json rename to tools/zod2md-jsdocs/project.json index 9b3ed9b10..18501546f 100644 --- a/packages/models/transformers/project.json +++ b/tools/zod2md-jsdocs/project.json @@ -1,7 +1,7 @@ { - "name": "models-transformers", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "sourceRoot": "packages/models/transformers/src", + "name": "zod2md-jsdocs", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "tools/zod2md-jsdocs/src", "projectType": "library", "targets": { "build": { @@ -9,9 +9,9 @@ "outputs": ["{options.outputPath}"], "dependsOn": ["pre-build"], "options": { - "outputPath": "packages/models/transformers/dist", - "main": "packages/models/transformers/src/index.ts", - "tsConfig": "packages/models/transformers/tsconfig.lib.json" + "outputPath": "tools/zod2md-jsdocs/dist", + "main": "tools/zod2md-jsdocs/src/index.ts", + "tsConfig": "tools/zod2md-jsdocs/tsconfig.lib.json" } }, "pre-build": { diff --git a/packages/models/transformers/src/index.ts b/tools/zod2md-jsdocs/src/index.ts similarity index 100% rename from packages/models/transformers/src/index.ts rename to tools/zod2md-jsdocs/src/index.ts diff --git a/packages/models/transformers/src/lib/transformers.ts b/tools/zod2md-jsdocs/src/lib/transformers.ts similarity index 71% rename from packages/models/transformers/src/lib/transformers.ts rename to tools/zod2md-jsdocs/src/lib/transformers.ts index b61f19455..33fb2e6ba 100644 --- a/packages/models/transformers/src/lib/transformers.ts +++ b/tools/zod2md-jsdocs/src/lib/transformers.ts @@ -3,26 +3,31 @@ import type * as ts from 'typescript'; const tsInstance: typeof ts = require('typescript'); -const BASE_URL = - 'https://github.com/code-pushup/cli/blob/main/packages/models/docs/models-reference.md'; - -function generateJSDocComment(typeName: string): string { - const markdownLink = `${BASE_URL}#${typeName.toLowerCase()}`; +function generateJSDocComment(typeName: string, baseUrl: string): string { + const markdownLink = `${baseUrl}#${typeName.toLowerCase()}`; return `* * Type Definition: \`${typeName}\` - * - * This type is derived from a Zod schema and represents + * + * This type is derived from a Zod schema and represents * the validated structure of \`${typeName}\` used within the application. - * + * * @see {@link ${markdownLink}} `; } function annotateTypeDefinitions( _program: ts.Program, - _pluginConfig: PluginConfig, + pluginConfig: PluginConfig, extras?: TransformerExtras, ): ts.TransformerFactory { + const baseUrl = pluginConfig.baseUrl as string | undefined; + + if (!baseUrl) { + throw new Error( + 'zod2md-jsdocs: "baseUrl" option is required. ' + + 'Please configure it in your tsconfig.json plugins section.', + ); + } const tsLib = extras?.ts ?? tsInstance; return (context: ts.TransformationContext) => { const visitor = (node: ts.Node): ts.Node => { @@ -30,7 +35,7 @@ function annotateTypeDefinitions( tsLib.isTypeAliasDeclaration(node) || tsLib.isInterfaceDeclaration(node) ) { - const jsDocComment = generateJSDocComment(node.name.text); + const jsDocComment = generateJSDocComment(node.name.text, baseUrl); tsLib.addSyntheticLeadingComment( node, tsLib.SyntaxKind.MultiLineCommentTrivia, diff --git a/packages/models/transformers/tsconfig.json b/tools/zod2md-jsdocs/tsconfig.json similarity index 81% rename from packages/models/transformers/tsconfig.json rename to tools/zod2md-jsdocs/tsconfig.json index fe17bec70..0c1036efe 100644 --- a/packages/models/transformers/tsconfig.json +++ b/tools/zod2md-jsdocs/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../../tsconfig.base.json", + "extends": "../../tsconfig.base.json", "compilerOptions": { "module": "commonjs", "verbatimModuleSyntax": false diff --git a/packages/models/transformers/tsconfig.lib.json b/tools/zod2md-jsdocs/tsconfig.lib.json similarity index 76% rename from packages/models/transformers/tsconfig.lib.json rename to tools/zod2md-jsdocs/tsconfig.lib.json index 48174f134..bebaef047 100644 --- a/packages/models/transformers/tsconfig.lib.json +++ b/tools/zod2md-jsdocs/tsconfig.lib.json @@ -4,7 +4,8 @@ "outDir": "./dist", "rootDir": "./", "module": "commonjs", - "types": ["node"] + "types": ["node"], + "esModuleInterop": true }, "include": ["src/**/*.ts"] } diff --git a/tools/zod2md-jsdocs/tsconfig.spec.json b/tools/zod2md-jsdocs/tsconfig.spec.json new file mode 100644 index 000000000..827403667 --- /dev/null +++ b/tools/zod2md-jsdocs/tsconfig.spec.json @@ -0,0 +1,29 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": [ + "vitest/globals", + "vitest/importMeta", + "vite/client", + "node", + "vitest" + ] + }, + "include": [ + "vite.config.ts", + "vite.config.mts", + "vitest.config.ts", + "vitest.config.mts", + "vitest.unit.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.test.tsx", + "src/**/*.spec.tsx", + "src/**/*.test.js", + "src/**/*.spec.js", + "src/**/*.test.jsx", + "src/**/*.spec.jsx", + "src/**/*.d.ts" + ] +} diff --git a/tools/zod2md-jsdocs/vitest.unit.config.ts b/tools/zod2md-jsdocs/vitest.unit.config.ts new file mode 100644 index 000000000..f32d2557d --- /dev/null +++ b/tools/zod2md-jsdocs/vitest.unit.config.ts @@ -0,0 +1,3 @@ +import { createUnitTestConfig } from '../../testing/test-setup-config/src/index.js'; + +export default createUnitTestConfig('zod2md-jsdocs');