Skip to main content

tsed-openapi

Document a Ts.ED v8 API with OpenAPI. Configures @tsed/swagger (Swagger UI) and @tsed/scalar, annotates operations and models with @tsed/schema decorators, splits controllers across several documents, and exports the spec to a file. Use when adding or fixing the `swagger` or `scalar` configuration, writing @Returns, @Summary, @Description, @Tags, @Security, @OperationId, @Hidden, @Docs, @Consumes, @Produces or @Example, generating swagger.json/openapi.json in CI, or when a route, model, property or response schema is missing or wrong in the generated spec.

来源信息

仓库
tsedio/tsed
最近来源活动
2026年10月3日 16:50
检测到的 SKILL.md 语言
英语
星标
3,086
分支
292

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

文件资源管理器
4 个文件

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
tsed-openapi
description
Document a Ts.ED v8 API with OpenAPI. Configures @tsed/swagger (Swagger UI) and @tsed/scalar, annotates operations and models with @tsed/schema decorators, splits controllers across several documents, and exports the spec to a file. Use when adding or fixing the `swagger` or `scalar` configuration, writing @Returns, @Summary, @Description, @Tags, @Security, @OperationId, @Hidden, @Docs, @Consumes, @Produces or @Example, generating swagger.json/openapi.json in CI, or when a route, model, property or response schema is missing or wrong in the generated spec.
# Ts.ED OpenAPI Ts.ED generates the OpenAPI document from the same `@tsed/schema` metadata that drives validation and serialization. Fix the metadata, never hand-edit the generated JSON. Read [the configuration reference](references/configuration.md) for every `swagger` / `scalar` option and [the decorator reference](references/decorators.md) for operation and response patterns. Model decorators belong to the sibling skill `tsed-models`; routes and parameters to `tsed-controllers`. ## 1. Install and register a UI 1. Install one or both UIs: `npm install @tsed/swagger` and/or `npm install @tsed/scalar`. 2. Import the package once in `Server.ts` for its side effect. Without the import the module is not registered and neither the UI nor the JSON route exists. 3. Declare `swagger` and/or `scalar` as an **array** of documents. ```typescript import "@tsed/platform-express"; import "@tsed/swagger"; import "@tsed/scalar"; import {Configuration} from "@tsed/di"; import * as rest from "./controllers/rest/index.js"; @Configuration({ mount: {"/rest": [...Object.values(rest)]}, swagger: [{path: "/doc", specVersion: "3.0.3"}], scalar: [{path: "/scalar", specVersion: "3.1.0"}] }) export class Server {} ``` - `mount` takes controller classes only (imported one by one or through a barrel as above). Do not pass glob strings: they are silently dropped, so the server and the spec expose no route. - The UI is served on `path`; the JSON on `<path>/<fileName>` (`swagger.json` for Swagger, `openapi.json` for Scalar). - `specVersion` accepts `"2.0"`, `"3.0.1"`, `"3.0.2"`, `"3.0.3"`, `"3.1.0"`. Always set it: when omitted (and `spec.openapi` is absent) Ts.ED emits Swagger `2.0`. - Do not give two documents the same `path`: the generated spec is cached by `path`. ## 2. Describe the document Put static metadata in `spec` and let controllers contribute paths and schemas. ```typescript swagger: [ { path: "/doc", specVersion: "3.0.3", spec: { info: {title: "Orders API", version: "1.2.0"}, components: { securitySchemes: {bearer: {type: "http", scheme: "bearer", bearerFormat: "JWT"}} } }, operationIdPattern: "%c_%m", sortPaths: true } ]; ``` - `info.version` falls back to the root `version` configuration key. - Use `operationIdPattern` (`%c` class name, `%m` method name) or `operationIdFormatter: (name, propertyKey, path) => string`. The default is camelCase of `%c.%m`; duplicates get a suffix. - Use `specPath` to merge a base JSON file, and the `$alterOpenSpec(spec, conf)` hook on `Server` for last-mile edits. ## 3. Document operations Import every decorator below from `@tsed/schema`. ```typescript import {Controller} from "@tsed/di"; import {NotFound} from "@tsed/exceptions"; import {PathParams} from "@tsed/platform-params"; import {Description, Get, Returns, Security, Summary, Tags} from "@tsed/schema"; import {Order} from "../models/Order.js"; @Controller("/orders") @Tags("Orders") export class OrdersController { @Get("/:id") @Summary("Get an order") @Description("Returns one order by its identifier") @Security("bearer") @(Returns(200, Order).Description("The order").Groups("read")) @(Returns(404, NotFound).Description("Order not found")) get(@PathParams("id") id: string) {} } ``` 1. Declare one `@Returns(status, Model)` per status code. Wrap chained calls in parentheses: `@(Returns(...).X())`. 2. Describe collections with `@(Returns(200, Array).Of(Order))`; a TypeScript `Promise<Order[]>` return type is not read. 3. Describe generics with `@Generics("T")` on the model and `.Of(Model)` / `.Nested(Model)` on the response. 4. Add `@Deprecated()`, `@OperationId("name")`, `@Consumes(...)`, `@Produces(...)` or `.ContentType(...)` only when the default is wrong. 5. Add examples on models with `@Example(value)`; on responses with `.Examples({...})`. 6. Every `@Security(name)` must match a key of `spec.components.securitySchemes` (OS3) or `spec.securityDefinitions` (OS2). ## 4. Split controllers across documents - By decorator: set `doc: "admin"` on a document and `@Docs("admin")` on controllers. Import `Docs` from `@tsed/swagger` or `@tsed/scalar`. - By route: set `pathPatterns: ["/rest/admin/**"]` (micromatch, negation with `!`). Patterns are tested against the controller's mounted route, not individual method paths. - A document with neither `doc` nor `pathPatterns` includes every non-hidden controller. A document with either one includes only matching controllers. - Use `@Hidden()` on a controller or a method to remove it from every document. ## 5. Export the spec without serving it Pick one; details and a full script in [the configuration reference](references/configuration.md#export-the-spec). 1. `outFile: "./spec/openapi.json"` on a document: written at `$onReady` on every start. 2. A script that calls `PlatformExpress.bootstrap(Server)` (no `listen()`), resolves `SwaggerService` from `@tsed/swagger` and calls `getOpenAPISpec(conf)`. 3. The Ts.ED CLI plugin `@tsed/cli-generate-swagger` (`tsed run generate-swagger --output <dir>`); see the sibling skill `tsed-cli`. 4. `getSpec(Controller)` or `generateSpec({tokens, ...})` from `@tsed/schema` for a DI-free unit test. ## 6. Diagnose a missing route or model Check in this order: 1. The UI package is imported in `Server.ts` and the configuration key is an array. 2. The controller is reachable from `mount` (or `imports`); the spec is built from mounted controllers only. 3. No `@Hidden()` on the class or method. 4. The document's `doc` / `pathPatterns` filter matches the controller (step 4). 5. The response has `@Returns(status, Model)`; without it the operation has no response schema. 6. Each model property carries a schema decorator (`@Property()`, `@Required()`, ...); undecorated properties are absent. 7. `.Groups(...)` on `@Returns` or `@Groups` on properties is not filtering the field out. 8. `disableSpec: true` removes the JSON route; `viewPath: false` removes the UI. ## Do not - Do not import decorators from `@tsed/common`; use `@tsed/schema`, `@tsed/di`, `@tsed/platform-params`. - Do not write `swagger: {...}` as an object; it must be an array. - Do not add `@Docs()` to some controllers and expect the others to stay in a document that sets `doc`. - Do not hand-write `paths` in `spec` for routes Ts.ED already serves; decorate the controller. - Do not expose the UI publicly by accident: gate the configuration by environment when the API is private. ## Pitfalls - A blank Swagger UI or Scalar page behind `helmet` is a CSP problem, not a spec problem. See https://tsed.dev/tutorials/swagger.md. - `hidden: true` on a Swagger document only hides it from the UI dropdown; the route stays served. - `outFile` is written after the server is ready, not at build time; a CI job needs option 2 or 3 of step 5. - `@Returns(Model)` without a status documents `200`. The second argument must be a class: write `@(Returns(404).Description("Not found"))`, not `@Returns(404, {description: "Not found"})`. - Scalar UI options go under `options`; `cdn` overrides the default jsDelivr bundle URL. - `SwaggerService` is an alias of `OpenAPIService` from `@tsed/openapi-utils`; `@tsed/scalar` does not re-export it. ## Checklist - The UI package is imported and `swagger` / `scalar` is an array with unique `path` values. - `spec.info` and security schemes are declared; every `@Security` name resolves. - Every operation has `@Summary`, and one `@Returns` per status code with a model. - Arrays and generics use `.Of()`; no response relies on the TypeScript return type. - Multi-document filters (`doc` + `@Docs`, or `pathPatterns`) were checked against the served JSON. - The exported spec was regenerated and diffed after the change. Further reading: https://tsed.dev/tutorials/swagger.md, https://tsed.dev/tutorials/scalar.md, https://tsed.dev/docs/controllers.md, https://tsed.dev/docs/model.md.
在 GitHub 查看