dsh-codepect
dsh-codepect is a DSH plugin generating OpenAPI 3.0 from TS/JS. Features: visual docs, versioning, change detection, mock & auto-rescan. Zero-dep, offline, ensures code-doc sync for backend API delivery. dsh-codepect是DSH插件,扫描TS/JS生成OpenAPI3.0文档。支持可视化、多版本、变更检测、Mock及自动重扫。零依赖离线可用,确保代码文档一致,助后端交付API契约。
- Stars
- 0
- Language
- JavaScript
- Created
- Aug 29, 2026
- Updated
- Aug 29, 2026
Introduction
dsh-codepect
dsh-codepect is an automatic API documentation generator built on the DSH dynamic Cordis
plugin mechanism. It scans TypeScript/JavaScript sources in the workspace, parses JSDoc
comments and NestJS/Express-style route definitions, and generates OpenAPI 3.0 specs
(openapi.json / openapi.yaml). Zero external dependencies, works offline.
The name combines "code" and "spec": your source code is turned into an OpenAPI contract.
Quick start
git clone https://github.com/hunbs-1/dsh-codepect.git
cd dsh-codepect
node devtest/host-smoke.cjs # zero-dependency offline smoke test (no npm install, no network)
The scanner is fully self-contained: cloning and running the smoke test needs no dependencies. To use it as a documentation generator you need a running DSH instance (the plugin is a DSH dynamic Cordis plugin). Load it once per DSH process as described in the usage section.
Detailed usage
Prerequisites: a running DSH instance (the plugin runs inside DSH, not as a standalone program) and your own TypeScript/JavaScript API source that uses JSDoc comments, NestJS decorators or Express routes.
1. Get the plugin
git clone https://github.com/hunbs-1/dsh-codepect.git
Only two files are actually needed by the plugin itself: src/host.js (Host half: scanning,
schema inference, OpenAPI generation, mock server, git integration, HTTP routes) and
src/client.js (Client half: the embedded "Settings -> API Docs" page and the run-card panel).
2. Add a config file
Place .dsh-api-docs.config.json (the dotless spelling is also accepted) in the folder where
you use the plugin, and point include at your source directory. The scan root is the folder
containing this config file; nothing outside that folder is ever scanned.
{
"title": "My API",
"version": "1.0.0",
"description": "API docs for my service",
"language": "zh",
"include": ["src/**/*.ts"],
"exclude": ["**/node_modules/**", "**/dist/**"]
}
See the configuration reference below for every field.
3. Load the plugin in a DSH session
Either:
- ask your DSH assistant to read
dsh-codepect/src/host.jsanddsh-codepect/src/client.jsand register them as a dynamic Cordis plugin (code.host / code.client), or - use the cordis_define mechanism manually with
src/host.jsascode.hostandsrc/client.jsascode.client, then run the package and approve if asked.
Note: dynamic plugins live in the DSH process memory only, so after restarting DSH you load the plugin again (the two files are the single source of truth, so this is quick and lossless).
4. Generate the docs
- Call the model tool
api_docs_generate(optionally with{ "rescan": true }), or - let the plugin's startup scan run automatically when it loads, or
- change a source file while
watch.enabledis on to trigger an auto-rescan.
The scan writes openapi.json and openapi.yaml at the configured output paths and updates
the version archive and changelog.
5. View the docs
- Standalone page:
http://localhost:3080/api-docs(search, endpoint expansion, schemas, changelog, copyable examples, mock links, version switch, language and theme toggles) - Embedded page: DSH Web UI, Settings -> API Docs
- Run card: the plugin's status panel (endpoint/schema counts, breaking changes, git revision, output paths)
- Contract files:
http://localhost:3080/api-docs.json(JSON) and/api-docs.yaml(YAML), ready to hand to frontend teams or tooling.
6. Versioning and breaking-change detection
- Keep
versionin the config (e.g."1.0.0"). - Each scan archives the full spec under that version (
api-docs/versions.json). - Change your source (add/remove an endpoint, make a parameter required, change a schema), then rescan.
- Open the changelog (
/api-docs/changelog.jsonor the changelog toggle in the UI): new entries mark breaking changes (endpoint removed, required parameter added/removed, type changes, request/response structure changes) and non-breaking changes separately, with the git revision captured at scan time. - Browse any archived version at
/api-docs/version/{v}(HTML),.../{v}.jsonor.../{v}.yaml; the version dropdown in the docs pages switches between them.
7. Mock server
Enable mockEnabled (default true). Mock data is generated from each endpoint's 200 response
schema and served at mockPrefix + endpoint path, method-aware:
GET http://localhost:3080/api-mock/api/users/123
POST http://localhost:3080/api-mock/api/users
8. Request examples
Each endpoint gets a cURL and a JavaScript Fetch example (path/query parameters filled with
example values, example request body when present), stored in the x-examples extension and
shown in the docs UI (the standalone page has a copy button).
9. Language switching
The UI language defaults to config.language ("zh" or "en"). Both the standalone page and
the embedded page have an in-page language button; the standalone page remembers the choice in
localStorage. Plugin-generated texts (response descriptions, changelog entries, validation
and scan messages) follow the configured language at scan time.
10. Watch mode
Set watch.enabled to auto-rescan when a scanned source file changes:
"watch": { "enabled": true, "intervalSeconds": 5 }
11. The model tool
api_docs_generate supports two flags:
rescan: true— force a full rescan nowdiagnoseBase: true— return the workspace root resolution diagnostics (which directory was chosen as scan root and why)
12. Move the plugin to another project
Copy src/host.js, src/client.js and a .dsh-api-docs.config.json whose include points at
that project's sources. Because the scan root is the config file's folder, the plugin scans
exactly that project and nothing else.
Configuration reference
Place .dsh-api-docs.config.json (dotless spelling also accepted) in the folder you use the
plugin in:
{
"title": "Demo User Service API",
"version": "1.0.0",
"description": "Sample API documentation generated by the dsh-codepect plugin",
"language": "en",
"include": ["demo-api/**/*.ts"],
"exclude": ["**/node_modules/**", "**/.git/**", "**/dist/**"],
"outputPath": "demo-api/openapi.json",
"yamlOutputPath": "demo-api/openapi.yaml",
"versionArchivePath": "api-docs/versions.json",
"changelogPath": "api-docs/changelog.json",
"mockEnabled": true,
"mockPrefix": "/api-mock",
"examplesEnabled": true,
"watch": { "enabled": true, "intervalSeconds": 5 }
}
| Field | Default | Description |
|---|---|---|
title | API Documentation | Spec title, shown in the docs page header |
version | 1.0.0 | Current spec version; archived per scan under versionArchivePath |
description | empty | Spec info description, shown under the title |
language | zh | UI language: zh or en (in-page toggle still available) |
include | ["**/*.ts", "**/*.js"] | Glob patterns of source files, relative to the config folder |
exclude | node_modules/.git/dist/build/coverage | Glob patterns to skip |
outputPath | api-docs/openapi.json | JSON spec output path (relative to the config folder) |
yamlOutputPath | api-docs/openapi.yaml | YAML spec output path |
versionArchivePath | api-docs/versions.json | Version archive file |
changelogPath | api-docs/changelog.json | Changelog file |
mockEnabled | true | Enable the /api-mock/* mock server |
mockPrefix | /api-mock | Mock server URL prefix |
examplesEnabled | true | Generate cURL/Fetch examples into x-examples |
watch | { "enabled": false, "intervalSeconds": 60 } | Auto-rescan on source change |
Scan scope
The scan root is the directory that contains the plugin config file; that directory is probed
first and takes priority over any session or sticky directory, so the plugin only ever scans
the folder where it is used. include / exclude patterns are resolved relative to that
directory, and escaping patterns (absolute paths or ../) are rejected with a warning —
nothing outside the config directory is ever scanned.
HTTP routes
| Route | Description |
|---|---|
GET /api-docs | Standalone docs page (version switch, changelog, copyable examples, mock links, language/theme toggles) |
GET /api-docs.json / /api-docs.yaml | Current OpenAPI spec (JSON / YAML) |
GET /api-docs/versions.json | Version index |
GET /api-docs/version/{v} / .../{v}.json / .../{v}.yaml | Historical version docs (page / JSON / YAML) |
GET /api-docs/changelog.json | Changelog |
| `GET | POST |
Source annotation guide
The plugin reads documentation from your source comments — no separate doc files to maintain:
/** User management endpoints */
@Controller('api/users')
export class UserController {
/**
* Get user details
* Returns the full user record for a user id
*/
@Get(':id')
async getUser(
/** The user id */
@Param('id') id: string
): Promise<User> { ... }
}
- Summary: the first line of a JSDoc block before a controller/method/route.
- Description: following lines of the same JSDoc block.
- Parameters:
@param {type} name - description(Express),@Param/@Query/@Headersdecorators with inline JSDoc (NestJS). - Request body:
@Body()parameter type (NestJS),@param body(Express). - Return type: the method's TypeScript return type /
@returns {type}. - Schemas:
interface/type/enumdeclarations with inline field comments. - Deprecation:
@deprecated.
demo-api/ is a complete demo project showing all of the above.
Features
Core (MVP)
| Module | Description |
|---|---|
| Source scanning | Recursively discovers include-matched TS/JS files and parses JSDoc blocks (summary / description / @param / @returns / @deprecated / @tag) |
| Route discovery | NestJS: @Controller('base') + @Get/@Post/@Put/@Patch/@Delete/@All('path'); Express: app.get/post/...('path') |
| Parameter extraction | NestJS: @Param('id') -> path, @Query('page') -> query, @Headers('x-t') -> header, @Body() -> requestBody; Express: :id path tokens + JSDoc @param |
| Schema inference | Primitives, arrays, union enums, nested objects, $ref, optional fields, Promise/Partial/Readonly/Record unwrapping, Date -> date-time, cycle guard |
| Spec generation | Standard OpenAPI 3.0: paths + parameters + requestBody + responses + components.schemas |
| Output files | openapi.json (pretty JSON) + openapi.yaml (hand-rolled YAML serializer, round-trip validated) |
| Doc pages | 1. DSH Web UI "Settings -> API Docs" embedded page 2. Standalone page /api-docs 3. Run-card status panel |
| Model tool | api_docs_generate tool: { "rescan": true } forces a rescan |
Extensions (V2)
| Feature | Description |
|---|---|
| Multi-version docs | Each generation archives a version (api-docs/versions.json); routes /api-docs/version/{v} (HTML) / .json / .yaml; version dropdown in UI |
| Breaking-change detection | Diffs against the previous version and flags Breaking Changes (removed endpoint, required param added/removed, type changes, request/response structure changes) plus non-breaking changes (new endpoint, new optional param); changelog at api-docs/changelog.json, viewable in the UI |
| Mock server | Generates mock data from the OpenAPI schema (enum/example values, nested objects, arrays, $ref resolution); prefix /api-mock + endpoint path, e.g. /api-mock/api/users/123, method-aware |
| Git integration | Records the current commit per scan (git rev-parse --short HEAD, persisted with the changelog); built-in spec validation ($ref integrity, duplicate params, missing responses); optional watch mode auto-rescans on source changes |
| Request examples | Generates cURL and JavaScript Fetch examples per endpoint (path/query filling, example request body), shown in x-examples and in the docs UI (copy button on the standalone page) |
| i18n | UI language switchable between Chinese and English (default from config.language, in-page toggle button) |
Project structure
dsh-codepect/
├── src/
│ ├── host.js # Plugin Host source (scanner / schema inference / OpenAPI gen / mock / git)
│ └── client.js # Plugin Client source (DSH Web UI embedded docs page + run card)
├── demo-api/src/ # Demo project (NestJS controller + DTOs + enum + Express routes)
├── devtest/ # Test scripts (offline smoke, HTTP E2E, browser interaction)
├── .dsh-api-docs.config.json # Plugin config example
├── README.md # This file
└── LICENSE # MIT
demo-api/openapi.json,demo-api/openapi.yamlandapi-docs/are generated artifacts and are gitignored; run one scan after cloning to regenerate them.
Testing
node devtest/e2e-check.cjs # 22 HTTP feature checks, expected 22/22
node devtest/host-smoke.cjs # offline pipeline smoke test (scan + YAML round-trip)
Suggested manual flow for breaking-change detection:
- Note the current endpoint count (8 for the demo)
- Remove a
@Getmethod or make a query param required indemo-api/src/user.controller.ts - Wait ~5 seconds (watch mode auto-rescans), open the changelog
- Expect a new entry with a red "breaking changes" marker, endpoint count updated
Implementation notes
- Path anchoring: the plugin config file's directory is the scan root and is probed first;
only if no config file is found does it fall back to the initiating session/workspace
cascade. Writes carry an explicit
{ mode: 'workspace-write', workspaceRoot: <workspace> }sandbox policy. - Lifecycle: all routes/tools/RPC/timers are disposed with the plugin fiber; a
scanninglock prevents re-entrant scans. - Error isolation: a single-file parse failure is recorded in
status.errorsand does not abort the whole scan. - i18n: the standalone page and the embedded React page both translate via a zh->en string
map (
tr()), toggled by the in-page language button (standalone page remembers the choice inlocalStorage); the default comes fromconfig.language.
Known limitations
- Generic instantiations (e.g.
Paginated<User>) and complex function types degrade to{} - Interface properties written as object literals with semicolons parse incompletely
- With multiple
@Controllerclasses in one file, the last base path wins - Change detection is structural (JSON Schema equality), not semantic compatibility analysis
- Mock data is deterministic sample values; no randomization or custom scripts
License
MIT