Skip to content

feat(metadata): documentation, fixes and improvements #2006

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/dry-flies-raise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"openapi-metadata": patch
---

Add comments for better documentation and add new exports
5 changes: 5 additions & 0 deletions .changeset/honest-coats-relax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"openapi-metadata": patch
---

Merge properly operations together
14 changes: 14 additions & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import en from "./en";
import zh from "./zh";
import ja from "./ja";
import shared from "./shared";
import { transformerTwoslash } from "@shikijs/vitepress-twoslash";
import { ModuleKind, ModuleResolutionKind } from "typescript";

// https://vitepress.dev/reference/site-config
export default defineConfig({
Expand All @@ -12,4 +14,16 @@ export default defineConfig({
zh: { label: "简体中文", ...zh },
ja: { label: "日本語", ...ja },
},
markdown: {
codeTransformers: [
transformerTwoslash({
twoslashOptions: {
compilerOptions: {
experimentalDecorators: true,
moduleResolution: ModuleResolutionKind.Bundler,
},
},
}),
],
},
});
24 changes: 16 additions & 8 deletions docs/.vitepress/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,23 @@ export default defineConfig({
},
{
text: "openapi-metadata",
base: "/openapi-metadata",
items: [
{ text: "Getting Started", link: "/" },
{ text: "Decorators", link: "/decorators" },
{ text: "Metadata", link: "/metadata" },
{ text: "Type loader", link: "/type-loader" },
{ text: "UI Integrations", link: "/ui" },
{ text: "Examples", link: "/examples" },
{ text: "About", link: "/about" },
{ text: "Getting Started", link: "/openapi-metadata" },
{ text: "Decorators", link: "/openapi-metadata/decorators" },
{ text: "Metadata", link: "/openapi-metadata/metadata" },
{ text: "Type loader", link: "/openapi-metadata/type-loader" },
{ text: "UI Integrations", link: "/openapi-metadata/ui" },
{
text: "Integrations",
items: [
{
text: "AdonisJS",
link: "https://friendsofadonis.com/docs/openapi",
},
],
},
{ text: "Examples", link: "/openapi-metadata/examples" },
{ text: "About", link: "/openapi-metadata/about" },
],
},
],
Expand Down
3 changes: 3 additions & 0 deletions docs/.vitepress/theme/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ import type { Theme } from "vitepress";
import DefaultTheme from "vitepress/theme";
import CustomLayout from "./CustomLayout.vue";
import SponsorList from "./SponsorList.vue";
import TwoslashFloatingVue from "@shikijs/vitepress-twoslash/client";
import "./style.css";
import "@shikijs/vitepress-twoslash/style.css";

export default {
extends: DefaultTheme,
Layout: CustomLayout,
enhanceApp({ app, router, siteData }) {
app.component("SponsorList", SponsorList);
app.use(TwoslashFloatingVue);
},
} satisfies Theme;
2 changes: 1 addition & 1 deletion docs/data/contributors.json

Large diffs are not rendered by default.

60 changes: 45 additions & 15 deletions docs/openapi-metadata/decorators.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,48 @@ Decorators are used to enrich your OpenAPI specifications. They can be applied o

> For more information about the decorators, you can directly refer to the [source code](https://github.com/openapi-ts/openapi-typescript/packages/openapi-metadata/src/decorators).

| Decorator | Usage | Description |
| ----------------------- | ------------------- | ------------------------------------------------------------------------ |
| `@ApiBody` | Method | Sets the requestBody of the operation. |
| `@ApiCookie` | Controller / Method | Adds a cookie parameter to the operation(s). |
| `@ApiExcludeController` | Method | Excludes the operations of this controller from the document generation. |
| `@ApiExcludeOperation` | Method | Excludes this operation from the document generation. |
| `@ApiExtraModels` | Controller | Adds extra models to be loaded in the schema. |
| `@ApiHeader` | Controller / Method | Adds a header parameter to the operation(s). |
| `@ApiOperation` | Method | Configures an operation. |
| `@ApiParam` | Controller / Method | Adds a path parameter to the operation(s). |
| `@ApiProperty` | Model | Configures a schema property property. |
| `@ApiQuery` | Controller / Method | Adds a query parameter to the operation(s). |
| `@ApiResponse` | Controller / Method | Adds a response to the operation(s). |
| `@ApiSecurity` | Controller / Method | Sets the security scheme to the operation(s). |
| `@ApiTags` | Controller / Method | Adds tags to the operation(s). |
_You can hover the following code snippet to get information about each decorator._

```ts twoslash
// @noErrors
// ---cut---
import {
ApiBody,
ApiCookie,
ApiExcludeController,
ApiExcludeOperation,
ApiExtraModels,
ApiHeader,
ApiOperation,
ApiParam,
ApiProperty,
ApiPropertyOptional,
ApiQuery,
ApiResponse,
ApiSecurity,
ApiBasicAuth,
ApiOauth2,
ApiBearerAuth,
ApiCookieAuth,
ApiTags
} from 'openapi-metadata/decorators'
// ---cut---
@ApiBody()
@ApiCookie()
@ApiExcludeController()
@ApiExcludeOperation()
@ApiExtraModels()
@ApiHeader()
@ApiOperation()
@ApiParam()
@ApiProperty()
@ApiPropertyOptional()
@ApiQuery()
@ApiResponse()
@ApiSecurity()
@ApiBasicAuth()
@ApiOAuth2()
@ApiBearerAuth()
@ApiCookieAuth()
@ApiTags()
```
6 changes: 4 additions & 2 deletions docs/openapi-metadata/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ This library is made to be used through an integration with your favorite framew

## Express

```ts
```ts twoslash
// @noErrors
import express from "express";
import { generateDocument } from "openapi-metadata";
import { generateScalarUI } from "openapi-metadata/ui";
Expand All @@ -29,7 +30,8 @@ app.get("/api/docs", (req, res) => {

## Fastify

```ts
```ts twoslash
// @noErrors
import fastify from "fastify";
import { generateDocument } from "openapi-metadata";
import { generateScalarUI } from "openapi-metadata/ui";
Expand Down
44 changes: 23 additions & 21 deletions docs/openapi-metadata/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ title: "Getting started"

::: code-group

```ts [users_controller.ts]
```ts [users_controller.ts] twoslash
// @noErrors
import { ApiOperation, ApiResponse } from "openapi-metadata/decorators";
import User from "./user";

class UsersController {
@ApiOperation({
method: "get",
pattern: "/users",
methods: ["get"],
path: "/users",
summary: "List users"
})
@ApiResponse({ type: [User] })
Expand All @@ -25,7 +26,7 @@ class UsersController {
}
```

```ts [user.ts]
```ts [user.ts] twoslash
import { ApiProperty } from "openapi-metadata/decorators";

class User {
Expand All @@ -40,7 +41,8 @@ class User {
}
```

```ts [index.ts]
```ts [index.ts] twoslash
// @noErrors
import "reflect-metadata";
import { generateDocument } from "openapi-metadata";
import UsersController from "./users_controller";
Expand All @@ -49,7 +51,7 @@ const document = await generateDocument({
controllers: [UsersController],
document: {
info: {
name: "My Api",
title: "My Api",
version: "1.0.0",
},
},
Expand Down Expand Up @@ -109,21 +111,21 @@ To get started, you can use the `generateDocument` function to create an (almost

::: code-group

```ts [index.ts]
```ts [index.ts] twoslash
import "reflect-metadata";
import { generateDocument } from "openapi-metadata";

const builder = await generateDocument({
const document = await generateDocument({
controllers: [],
document: {
info: {
name: "My API",
title: "My API",
version: "1.0.0",
},
},
});

console.log(document.build()); // <- Your generated OpenAPI specifications
console.log(document); // <- Your generated OpenAPI specifications
```

:::
Expand All @@ -135,14 +137,15 @@ In the following example we have a `UsersController` which declares an operation

::: code-group

```ts [controllers/users_controller.ts]
```ts [controllers/users_controller.ts] twoslash
// @noErrors
import { ApiOperation, ApiResponse } from "openapi-metadata/decorators";
import User from "../schemas/user";

export default class UsersController {
@ApiOperation({
method: "get",
pattern: "/users",
methods: ["get"],
path: "/users",
summary: "List users",
})
@ApiResponse({ type: [User] })
Expand All @@ -164,7 +167,7 @@ By using the `@ApiProperty` decorator on class we can define the properties of o

::: code-group

```ts [schemas/user.ts]
```ts [schemas/user.ts] twoslash
import { ApiProperty } from "openapi-metadata/decorators";

export default class User {
Expand All @@ -184,18 +187,19 @@ export default class User {

:::

### Add the controller to the generated document
### Register your controller

Now that we have our controller ready, we can use it to generate our document.
Now that we have our controller ready, we can include it when generating our document.

::: code-group

```ts [index.ts]
```ts [index.ts] twoslash
// @noErrors
import "reflect-metadata";
import { generateDocument } from "openapi-metadata";
import UsersController from "./controllers/users_controller.ts";

const builder = await generateDocument({
const document = await generateDocument({
controllers: [UsersController],
document: {
info: {
Expand All @@ -205,9 +209,7 @@ const builder = await generateDocument({
},
});

console.log(document.build()); // <- Your generated OpenAPI specifications
console.log(document); // <- Your generated OpenAPI specifications
```

:::

### Going further
6 changes: 3 additions & 3 deletions docs/openapi-metadata/ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,23 @@ title: UI integrations

## [Scalar](https://scalar.com)

```ts
```ts twoslash
import { generateScalarUI } from "openapi-metadata/ui";

generateScalarUI("http://localhost:3000/api");
```

## [Swagger UI](https://swagger.io/tools/swagger-ui/)

```ts
```ts twoslash
import { generateSwaggerUI } from "openapi-metadata/ui";

generateSwaggerUI("http://localhost:3000/api");
```

## [Rapidoc](https://rapidocweb.com/)

```ts
```ts twoslash
import { generateRapidocUI } from "openapi-metadata/ui";

generateRapidocUI("http://localhost:3000/api");
Expand Down
4 changes: 3 additions & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
"update-contributors": "node scripts/update-contributors.js"
},
"devDependencies": {
"vitepress": "1.5.0"
"vitepress": "1.5.0",
"@shikijs/vitepress-twoslash": "^1.22.2",
"openapi-metadata": "workspace:*"
}
}
6 changes: 6 additions & 0 deletions packages/openapi-metadata/src/decorators/api-body.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ import { type OperationBodyMetadata, OperationBodyMetadataStorage } from "../met

export type ApiBodyOptions = SetOptional<OperationBodyMetadata, "mediaType">;

/**
* Configures the request body.
* Can be applied to Controllers and Operations.
*
* @see https://swagger.io/specification/#request-body-object
*/
export function ApiBody(options: ApiBodyOptions): MethodDecorator {
return (target, propertyKey) => {
OperationBodyMetadataStorage.defineMetadata(
Expand Down
6 changes: 6 additions & 0 deletions packages/openapi-metadata/src/decorators/api-cookie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ import { type OperationParameterMetadata, OperationParameterMetadataStorage } fr

export type ApiCookieOptions = Omit<OperationParameterMetadata, "in">;

/**
* Configures a cookie parameter.
* Can be applied to Operations and Controllers.
*
* @see https://swagger.io/specification/#parameter-object
*/
export function ApiCookie(options: ApiCookieOptions) {
return (target: Object, propertyKey?: string | symbol) => {
OperationParameterMetadataStorage.mergeMetadata(target, [{ in: "cookie", ...options }], propertyKey);
Expand Down
8 changes: 8 additions & 0 deletions packages/openapi-metadata/src/decorators/api-exclude.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import { ExcludeMetadataStorage } from "../metadata/exclude.js";

/**
* Exclude this Controller from the generated schema.
* Useful when working with framework integrations that autoload controllers.
*/
export function ApiExcludeController(): ClassDecorator {
return (target) => {
ExcludeMetadataStorage.defineMetadata(target, true);
};
}

/**
* Exclude this Operation from the generated schema.
* Useful when working with framework integrations that autoload controllers.
*/
export function ApiExcludeOperation(): MethodDecorator {
return (target, propertyKey) => {
ExcludeMetadataStorage.defineMetadata(target, true, propertyKey);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { ExtraModelsMetadataStorage } from "../metadata/extra-models.js";
import type { Thunk, TypeValue } from "../types.js";

/**
* Adds extra models to the generated schema that are not used anywhere else.
* Useful when you want to share models that are not used by your operations.
*/
export function ApiExtraModels(...models: (TypeValue | Thunk<TypeValue>)[]) {
return (target: Object) => {
ExtraModelsMetadataStorage.mergeMetadata(target, models);
Expand Down
Loading
Loading