From 2040256d3a331a1dc333e3476e1ae2012e1f08fd Mon Sep 17 00:00:00 2001 From: Jeongho Nam Date: Sun, 26 Nov 2023 03:11:07 +0900 Subject: [PATCH] Close #693 - `@ignore` comment tag. If you want to exclude a controller method from SDK library, write `@ignore` comment on the target controller method, then SDK generator will ignore it. --- packages/core/package.json | 6 +- packages/fetcher/package.json | 2 +- packages/sdk/package.json | 6 +- .../sdk/src/analyses/ControllerAnalyzer.ts | 7 +- test/features/ignore/nestia.config.ts | 15 + test/features/ignore/src/Backend.ts | 25 + test/features/ignore/src/api/HttpError.ts | 1 + test/features/ignore/src/api/IConnection.ts | 1 + test/features/ignore/src/api/Primitive.ts | 1 + .../src/api/functional/bbs/articles/index.ts | 114 +++ .../ignore/src/api/functional/bbs/index.ts | 7 + .../ignore/src/api/functional/health/index.ts | 42 ++ .../ignore/src/api/functional/index.ts | 9 + .../src/api/functional/performance/index.ts | 45 ++ test/features/ignore/src/api/index.ts | 4 + test/features/ignore/src/api/module.ts | 5 + .../ignore/src/api/structures/IBbsArticle.ts | 43 ++ .../ignore/src/api/structures/IPerformance.ts | 10 + .../ignore/src/api/structures/ISystem.ts | 81 +++ .../src/controllers/BbsArticlesController.ts | 48 ++ .../src/controllers/HealthController.ts | 9 + .../src/controllers/PerformanceController.ts | 17 + .../api/test_api_bbs_article_erase.ts | 8 + .../api/test_api_bbs_article_store.ts | 14 + .../api/test_api_bbs_article_update.ts | 20 + .../features/api/test_api_health_check.ts | 5 + .../test/features/api/test_api_performance.ts | 13 + test/features/ignore/src/test/index.ts | 40 ++ test/features/ignore/swagger.json | 649 ++++++++++++++++++ test/features/ignore/tsconfig.json | 98 +++ test/package.json | 8 +- website/pages/docs/sdk/sdk.mdx | 179 ++++- website/pages/docs/sdk/swagger.mdx | 3 +- 33 files changed, 1520 insertions(+), 15 deletions(-) create mode 100644 test/features/ignore/nestia.config.ts create mode 100644 test/features/ignore/src/Backend.ts create mode 100644 test/features/ignore/src/api/HttpError.ts create mode 100644 test/features/ignore/src/api/IConnection.ts create mode 100644 test/features/ignore/src/api/Primitive.ts create mode 100644 test/features/ignore/src/api/functional/bbs/articles/index.ts create mode 100644 test/features/ignore/src/api/functional/bbs/index.ts create mode 100644 test/features/ignore/src/api/functional/health/index.ts create mode 100644 test/features/ignore/src/api/functional/index.ts create mode 100644 test/features/ignore/src/api/functional/performance/index.ts create mode 100644 test/features/ignore/src/api/index.ts create mode 100644 test/features/ignore/src/api/module.ts create mode 100644 test/features/ignore/src/api/structures/IBbsArticle.ts create mode 100644 test/features/ignore/src/api/structures/IPerformance.ts create mode 100644 test/features/ignore/src/api/structures/ISystem.ts create mode 100644 test/features/ignore/src/controllers/BbsArticlesController.ts create mode 100644 test/features/ignore/src/controllers/HealthController.ts create mode 100644 test/features/ignore/src/controllers/PerformanceController.ts create mode 100644 test/features/ignore/src/test/features/api/test_api_bbs_article_erase.ts create mode 100644 test/features/ignore/src/test/features/api/test_api_bbs_article_store.ts create mode 100644 test/features/ignore/src/test/features/api/test_api_bbs_article_update.ts create mode 100644 test/features/ignore/src/test/features/api/test_api_health_check.ts create mode 100644 test/features/ignore/src/test/features/api/test_api_performance.ts create mode 100644 test/features/ignore/src/test/index.ts create mode 100644 test/features/ignore/swagger.json create mode 100644 test/features/ignore/tsconfig.json diff --git a/packages/core/package.json b/packages/core/package.json index ec8b883f0..9a59b1891 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@nestia/core", - "version": "2.3.11", + "version": "2.3.12", "description": "Super-fast validation decorators of NestJS", "main": "lib/index.js", "typings": "lib/index.d.ts", @@ -34,7 +34,7 @@ }, "homepage": "https://nestia.io", "dependencies": { - "@nestia/fetcher": "^2.3.11", + "@nestia/fetcher": "^2.3.12", "@nestjs/common": ">=7.0.1", "@nestjs/core": ">=7.0.1", "@nestjs/platform-express": ">=7.0.1", @@ -47,7 +47,7 @@ "typia": "^5.2.6" }, "peerDependencies": { - "@nestia/fetcher": ">=2.3.11", + "@nestia/fetcher": ">=2.3.12", "@nestjs/common": ">=7.0.1", "@nestjs/core": ">=7.0.1", "@nestjs/platform-express": ">=7.0.1", diff --git a/packages/fetcher/package.json b/packages/fetcher/package.json index af2714a50..42710934c 100644 --- a/packages/fetcher/package.json +++ b/packages/fetcher/package.json @@ -1,6 +1,6 @@ { "name": "@nestia/fetcher", - "version": "2.3.11", + "version": "2.3.12", "description": "Fetcher library of Nestia SDK", "main": "lib/index.js", "typings": "lib/index.d.ts", diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 98ffb63ec..79f783470 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@nestia/sdk", - "version": "2.3.11", + "version": "2.3.12", "description": "Nestia SDK and Swagger generator", "main": "lib/index.js", "typings": "lib/index.d.ts", @@ -35,7 +35,7 @@ }, "homepage": "https://nestia.io", "dependencies": { - "@nestia/fetcher": "^2.3.11", + "@nestia/fetcher": "^2.3.12", "cli": "^1.0.1", "get-function-location": "^2.0.0", "glob": "^7.2.0", @@ -47,7 +47,7 @@ "typia": "^5.2.6" }, "peerDependencies": { - "@nestia/fetcher": ">=2.3.11", + "@nestia/fetcher": ">=2.3.12", "@nestjs/common": ">=7.0.1", "@nestjs/core": ">=7.0.1", "reflect-metadata": ">=0.1.12", diff --git a/packages/sdk/src/analyses/ControllerAnalyzer.ts b/packages/sdk/src/analyses/ControllerAnalyzer.ts index 55c39acd6..f2c40af27 100644 --- a/packages/sdk/src/analyses/ControllerAnalyzer.ts +++ b/packages/sdk/src/analyses/ControllerAnalyzer.ts @@ -115,6 +115,10 @@ export namespace ControllerAnalyzer { return []; } + // SKIP @IGNORE TAG + const jsDocTags = signature.getJsDocTags(); + if (jsDocTags.some((tag) => tag.name === "ignore")) return []; + // EXPLORE CHILDREN TYPES const importDict: ImportAnalyzer.Dictionary = new HashMap(); const parameters: Array = @@ -168,8 +172,7 @@ export namespace ControllerAnalyzer { .toJSON() .map((pair) => [pair.first, pair.second.toJSON()]); - // PARSE COMMENT TAGS - const jsDocTags = signature.getJsDocTags(); + // CONSIDER SECURITY TAGS const security: Record[] = SecurityAnalyzer.merge( ...controller.security, ...func.security, diff --git a/test/features/ignore/nestia.config.ts b/test/features/ignore/nestia.config.ts new file mode 100644 index 000000000..2594a40d0 --- /dev/null +++ b/test/features/ignore/nestia.config.ts @@ -0,0 +1,15 @@ +import { INestiaConfig } from "@nestia/sdk"; + +export const NESTIA_CONFIG: INestiaConfig = { + input: ["src/controllers"], + output: "src/api", + swagger: { + output: "swagger.json", + security: { + bearer: { + type: "apiKey", + }, + }, + }, +}; +export default NESTIA_CONFIG; diff --git a/test/features/ignore/src/Backend.ts b/test/features/ignore/src/Backend.ts new file mode 100644 index 000000000..f8c78c113 --- /dev/null +++ b/test/features/ignore/src/Backend.ts @@ -0,0 +1,25 @@ +import core from "@nestia/core"; +import { INestApplication } from "@nestjs/common"; +import { NestFactory } from "@nestjs/core"; +import { Singleton } from "tstl"; + +export class Backend { + public readonly application: Singleton> = + new Singleton(async () => + NestFactory.create( + await core.EncryptedModule.dynamic(__dirname + "/controllers", { + key: "A".repeat(32), + iv: "B".repeat(16), + }), + { logger: false }, + ), + ); + + public async open(): Promise { + return (await this.application.get()).listen(37_000); + } + + public async close(): Promise { + return (await this.application.get()).close(); + } +} diff --git a/test/features/ignore/src/api/HttpError.ts b/test/features/ignore/src/api/HttpError.ts new file mode 100644 index 000000000..5df328ae4 --- /dev/null +++ b/test/features/ignore/src/api/HttpError.ts @@ -0,0 +1 @@ +export { HttpError } from "@nestia/fetcher"; diff --git a/test/features/ignore/src/api/IConnection.ts b/test/features/ignore/src/api/IConnection.ts new file mode 100644 index 000000000..107bdb8f8 --- /dev/null +++ b/test/features/ignore/src/api/IConnection.ts @@ -0,0 +1 @@ +export type { IConnection } from "@nestia/fetcher"; diff --git a/test/features/ignore/src/api/Primitive.ts b/test/features/ignore/src/api/Primitive.ts new file mode 100644 index 000000000..60d394424 --- /dev/null +++ b/test/features/ignore/src/api/Primitive.ts @@ -0,0 +1 @@ +export type { Primitive } from "@nestia/fetcher"; diff --git a/test/features/ignore/src/api/functional/bbs/articles/index.ts b/test/features/ignore/src/api/functional/bbs/articles/index.ts new file mode 100644 index 000000000..f998c774e --- /dev/null +++ b/test/features/ignore/src/api/functional/bbs/articles/index.ts @@ -0,0 +1,114 @@ +/** + * @packageDocumentation + * @module api.functional.bbs.articles + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import type { IConnection, Primitive } from "@nestia/fetcher"; +import { PlainFetcher } from "@nestia/fetcher/lib/PlainFetcher"; +import type { Format } from "typia/lib/tags/Format"; + +import type { IBbsArticle } from "../../../structures/IBbsArticle"; + +/** + * Store an article. + * + * @param input Content to store + * @returns Newly archived article + * @deprecated + * + * @controller BbsArticlesController.store + * @path POST /bbs/articles + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export async function store( + connection: IConnection, + input: store.Input, +): Promise { + return PlainFetcher.fetch( + { + ...connection, + headers: { + ...(connection.headers ?? {}), + "Content-Type": "application/json", + }, + }, + { + ...store.METADATA, + path: store.path(), + } as const, + input, + ); +} +export namespace store { + export type Input = Primitive; + export type Output = Primitive; + + export const METADATA = { + method: "POST", + path: "/bbs/articles", + request: { + type: "application/json", + encrypted: false + }, + response: { + type: "application/json", + encrypted: false, + }, + status: null, + } as const; + + export const path = (): string => { + return `/bbs/articles`; + } +} + +/** + * + * @internal + * + * @controller BbsArticlesController.update + * @path PUT /bbs/articles/:id + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export async function update( + connection: IConnection, + id: string & Format<"uuid">, + input: update.Input, +): Promise { + return PlainFetcher.fetch( + { + ...connection, + headers: { + ...(connection.headers ?? {}), + "Content-Type": "application/json", + }, + }, + { + ...update.METADATA, + path: update.path(id), + } as const, + input, + ); +} +export namespace update { + export type Input = Primitive>; + + export const METADATA = { + method: "PUT", + path: "/bbs/articles/:id", + request: { + type: "application/json", + encrypted: false + }, + response: { + type: "application/json", + encrypted: false, + }, + status: null, + } as const; + + export const path = (id: string & Format<"uuid">): string => { + return `/bbs/articles/${encodeURIComponent(id ?? "null")}`; + } +} \ No newline at end of file diff --git a/test/features/ignore/src/api/functional/bbs/index.ts b/test/features/ignore/src/api/functional/bbs/index.ts new file mode 100644 index 000000000..efe5ba769 --- /dev/null +++ b/test/features/ignore/src/api/functional/bbs/index.ts @@ -0,0 +1,7 @@ +/** + * @packageDocumentation + * @module api.functional.bbs + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +export * as articles from "./articles"; \ No newline at end of file diff --git a/test/features/ignore/src/api/functional/health/index.ts b/test/features/ignore/src/api/functional/health/index.ts new file mode 100644 index 000000000..22f66eceb --- /dev/null +++ b/test/features/ignore/src/api/functional/health/index.ts @@ -0,0 +1,42 @@ +/** + * @packageDocumentation + * @module api.functional.health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import type { IConnection } from "@nestia/fetcher"; +import { PlainFetcher } from "@nestia/fetcher/lib/PlainFetcher"; + +/** + * @controller HealthController.get + * @path GET /health + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export async function get( + connection: IConnection, +): Promise { + return PlainFetcher.fetch( + connection, + { + ...get.METADATA, + path: get.path(), + } as const, + ); +} +export namespace get { + + export const METADATA = { + method: "GET", + path: "/health", + request: null, + response: { + type: "application/json", + encrypted: false, + }, + status: null, + } as const; + + export const path = (): string => { + return `/health`; + } +} \ No newline at end of file diff --git a/test/features/ignore/src/api/functional/index.ts b/test/features/ignore/src/api/functional/index.ts new file mode 100644 index 000000000..0d710aad5 --- /dev/null +++ b/test/features/ignore/src/api/functional/index.ts @@ -0,0 +1,9 @@ +/** + * @packageDocumentation + * @module api.functional + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +export * as bbs from "./bbs"; +export * as health from "./health"; +export * as performance from "./performance"; \ No newline at end of file diff --git a/test/features/ignore/src/api/functional/performance/index.ts b/test/features/ignore/src/api/functional/performance/index.ts new file mode 100644 index 000000000..31e056e76 --- /dev/null +++ b/test/features/ignore/src/api/functional/performance/index.ts @@ -0,0 +1,45 @@ +/** + * @packageDocumentation + * @module api.functional.performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import type { IConnection, Primitive } from "@nestia/fetcher"; +import { PlainFetcher } from "@nestia/fetcher/lib/PlainFetcher"; + +import type { IPerformance } from "../../structures/IPerformance"; + +/** + * @controller PerformanceController.get + * @path GET /performance + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export async function get( + connection: IConnection, +): Promise { + return PlainFetcher.fetch( + connection, + { + ...get.METADATA, + path: get.path(), + } as const, + ); +} +export namespace get { + export type Output = Primitive; + + export const METADATA = { + method: "GET", + path: "/performance", + request: null, + response: { + type: "application/json", + encrypted: false, + }, + status: null, + } as const; + + export const path = (): string => { + return `/performance`; + } +} \ No newline at end of file diff --git a/test/features/ignore/src/api/index.ts b/test/features/ignore/src/api/index.ts new file mode 100644 index 000000000..1705f43c8 --- /dev/null +++ b/test/features/ignore/src/api/index.ts @@ -0,0 +1,4 @@ +import * as api from "./module"; + +export * from "./module"; +export default api; diff --git a/test/features/ignore/src/api/module.ts b/test/features/ignore/src/api/module.ts new file mode 100644 index 000000000..dbb6e9a51 --- /dev/null +++ b/test/features/ignore/src/api/module.ts @@ -0,0 +1,5 @@ +export type * from "./IConnection"; +export type * from "./Primitive"; +export * from "./HttpError"; + +export * as functional from "./functional"; diff --git a/test/features/ignore/src/api/structures/IBbsArticle.ts b/test/features/ignore/src/api/structures/IBbsArticle.ts new file mode 100644 index 000000000..c919f3bdd --- /dev/null +++ b/test/features/ignore/src/api/structures/IBbsArticle.ts @@ -0,0 +1,43 @@ +export interface IBbsArticle extends IBbsArticle.IStore { + /** + * @format uuid + */ + id: string; + + /** + * @format date-time + */ + created_at: string; +} +export namespace IBbsArticle { + export interface IStore { + /** + * @minLength 3 + * @maxLength 50 + */ + title: string; + body: string; + files: IAttachmentFile[]; + } + + export type IUpdate = Partial; +} + +export interface IAttachmentFile { + /** + * @minLengt 1 + * @maxLength 255 + */ + name: string | null; + + /** + * @minLength 1 + * @maxLength 8 + */ + extension: string | null; + + /** + * @format url + */ + url: string; +} diff --git a/test/features/ignore/src/api/structures/IPerformance.ts b/test/features/ignore/src/api/structures/IPerformance.ts new file mode 100644 index 000000000..a9e9336e1 --- /dev/null +++ b/test/features/ignore/src/api/structures/IPerformance.ts @@ -0,0 +1,10 @@ +/** + * Performance info. + * + * @author Samchon + */ +export interface IPerformance { + cpu: NodeJS.CpuUsage; + memory: NodeJS.MemoryUsage; + resource: NodeJS.ResourceUsage; +} diff --git a/test/features/ignore/src/api/structures/ISystem.ts b/test/features/ignore/src/api/structures/ISystem.ts new file mode 100644 index 000000000..68f05ca92 --- /dev/null +++ b/test/features/ignore/src/api/structures/ISystem.ts @@ -0,0 +1,81 @@ +/** + * System Information. + * + * @author Jeongho Nam + */ +export interface ISystem { + /** + * Random Unique ID. + */ + uid: number; + + /** + * `process.argv` + */ + arguments: string[]; + + /** + * Git commit info. + */ + commit: ISystem.ICommit; + + /** + * `package.json` + */ + package: ISystem.IPackage; + + /** + * Creation time of this server. + */ + created_at: string; +} + +export namespace ISystem { + /** + * Git commit info. + */ + export interface ICommit { + shortHash: string; + branch: string; + hash: string; + subject: string; + sanitizedSubject: string; + body: string; + author: ICommit.IUser; + committer: ICommit.IUser; + authored_at: string; + commited_at: string; + notes?: string; + tags: string[]; + } + export namespace ICommit { + /** + * Git user account info. + */ + export interface IUser { + name: string; + email: string; + } + } + + /** + * NPM package info. + */ + export interface IPackage { + name: string; + version: string; + description: string; + main?: string; + typings?: string; + scripts: Record; + repository: { type: "git"; url: string }; + author: string; + license: string; + bugs: { url: string }; + homepage: string; + devDependencies?: Record; + dependencies: Record; + publishConfig?: { registry: string }; + files?: string[]; + } +} diff --git a/test/features/ignore/src/controllers/BbsArticlesController.ts b/test/features/ignore/src/controllers/BbsArticlesController.ts new file mode 100644 index 000000000..15b126275 --- /dev/null +++ b/test/features/ignore/src/controllers/BbsArticlesController.ts @@ -0,0 +1,48 @@ +import core, { TypedBody, TypedParam, TypedRoute } from "@nestia/core"; +import { Controller } from "@nestjs/common"; +import typia, { tags } from "typia"; + +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +@Controller("bbs/articles") +export class BbsArticlesController { + /** + * Store an article. + * + * @param input Content to store + * @returns Newly archived article + * @deprecated + */ + @TypedRoute.Post() + public async store( + @TypedBody() input: IBbsArticle.IStore, + ): Promise { + const output: IBbsArticle = { + ...typia.random(), + ...input, + }; + return output; + } + + /** + * @internal + */ + @TypedRoute.Put(":id") + public async update( + @TypedParam("id") id: string & tags.Format<"uuid">, + @TypedBody() input: IBbsArticle.IUpdate, + ): Promise { + id; + input; + } + + /** + * @ignore + */ + @TypedRoute.Put(":id") + public async erase( + @TypedParam("id") id: string & tags.Format<"uuid">, + ): Promise { + id; + } +} diff --git a/test/features/ignore/src/controllers/HealthController.ts b/test/features/ignore/src/controllers/HealthController.ts new file mode 100644 index 000000000..a9ce3563b --- /dev/null +++ b/test/features/ignore/src/controllers/HealthController.ts @@ -0,0 +1,9 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +@Controller("health") +export class HealthController { + @core.TypedRoute.Get() + public get(): void {} +} diff --git a/test/features/ignore/src/controllers/PerformanceController.ts b/test/features/ignore/src/controllers/PerformanceController.ts new file mode 100644 index 000000000..798d64fae --- /dev/null +++ b/test/features/ignore/src/controllers/PerformanceController.ts @@ -0,0 +1,17 @@ +import { Controller } from "@nestjs/common"; + +import core from "@nestia/core"; + +import { IPerformance } from "@api/lib/structures/IPerformance"; + +@Controller("performance") +export class PerformanceController { + @core.TypedRoute.Get() + public async get(): Promise { + return { + cpu: process.cpuUsage(), + memory: process.memoryUsage(), + resource: process.resourceUsage(), + }; + } +} diff --git a/test/features/ignore/src/test/features/api/test_api_bbs_article_erase.ts b/test/features/ignore/src/test/features/api/test_api_bbs_article_erase.ts new file mode 100644 index 000000000..e4ba5c56b --- /dev/null +++ b/test/features/ignore/src/test/features/api/test_api_bbs_article_erase.ts @@ -0,0 +1,8 @@ +import { TestValidator } from "@nestia/e2e"; + +import api from "@api"; + +export const test_api_bbs_article_erase = (): void => { + const erase = (api.functional.bbs.articles as any).erase; + TestValidator.equals("ignore")(erase)(undefined); +}; diff --git a/test/features/ignore/src/test/features/api/test_api_bbs_article_store.ts b/test/features/ignore/src/test/features/api/test_api_bbs_article_store.ts new file mode 100644 index 000000000..e1cae5f84 --- /dev/null +++ b/test/features/ignore/src/test/features/api/test_api_bbs_article_store.ts @@ -0,0 +1,14 @@ +import typia from "typia"; + +import api from "@api"; +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +export const test_api_bbs_article_store = async ( + connection: api.IConnection, +): Promise => { + const article: IBbsArticle = await api.functional.bbs.articles.store( + connection, + typia.random(), + ); + typia.assertEquals(article); +}; diff --git a/test/features/ignore/src/test/features/api/test_api_bbs_article_update.ts b/test/features/ignore/src/test/features/api/test_api_bbs_article_update.ts new file mode 100644 index 000000000..ec81a2e61 --- /dev/null +++ b/test/features/ignore/src/test/features/api/test_api_bbs_article_update.ts @@ -0,0 +1,20 @@ +import typia from "typia"; + +import api from "@api"; +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +export const test_api_bbs_article_update = async ( + connection: api.IConnection, +): Promise => { + const article: IBbsArticle = await api.functional.bbs.articles.store( + connection, + typia.random(), + ); + typia.assertEquals(article); + + await api.functional.bbs.articles.update( + connection, + article.id, + typia.random(), + ); +}; diff --git a/test/features/ignore/src/test/features/api/test_api_health_check.ts b/test/features/ignore/src/test/features/api/test_api_health_check.ts new file mode 100644 index 000000000..c34703c71 --- /dev/null +++ b/test/features/ignore/src/test/features/api/test_api_health_check.ts @@ -0,0 +1,5 @@ +import api from "@api"; + +export const test_api_monitor_health_check = ( + connection: api.IConnection, +): Promise => api.functional.health.get(connection); diff --git a/test/features/ignore/src/test/features/api/test_api_performance.ts b/test/features/ignore/src/test/features/api/test_api_performance.ts new file mode 100644 index 000000000..55b6d2ca7 --- /dev/null +++ b/test/features/ignore/src/test/features/api/test_api_performance.ts @@ -0,0 +1,13 @@ +import typia from "typia"; + +import api from "@api"; +import { IPerformance } from "@api/lib/structures/IPerformance"; + +export const test_api_monitor_performance = async ( + connection: api.IConnection, +): Promise => { + const performance: IPerformance = await api.functional.performance.get( + connection, + ); + typia.assert(performance); +}; diff --git a/test/features/ignore/src/test/index.ts b/test/features/ignore/src/test/index.ts new file mode 100644 index 000000000..339bdd6a4 --- /dev/null +++ b/test/features/ignore/src/test/index.ts @@ -0,0 +1,40 @@ +import { DynamicExecutor } from "@nestia/e2e"; + +import { Backend } from "../Backend"; + +async function main(): Promise { + const server: Backend = new Backend(); + await server.open(); + + const report: DynamicExecutor.IReport = await DynamicExecutor.validate({ + extension: __filename.substring(__filename.length - 2), + prefix: "test", + parameters: () => [ + { + host: "http://127.0.0.1:37000", + encryption: { + key: "A".repeat(32), + iv: "B".repeat(16), + }, + }, + ], + })(`${__dirname}/features`); + await server.close(); + + const exceptions: Error[] = report.executions + .filter((exec) => exec.error !== null) + .map((exec) => exec.error!); + if (exceptions.length === 0) { + console.log("Success"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + } else { + for (const exp of exceptions) console.log(exp); + console.log("Failed"); + console.log("Elapsed time", report.time.toLocaleString(), `ms`); + process.exit(-1); + } +} +main().catch((exp) => { + console.log(exp); + process.exit(-1); +}); diff --git a/test/features/ignore/swagger.json b/test/features/ignore/swagger.json new file mode 100644 index 000000000..8d5c3711e --- /dev/null +++ b/test/features/ignore/swagger.json @@ -0,0 +1,649 @@ +{ + "openapi": "3.0.1", + "servers": [ + { + "url": "https://github.com/samchon/nestia", + "description": "insert your server url" + } + ], + "info": { + "version": "2.3.12", + "title": "@nestia/test", + "description": "Test program of Nestia", + "license": { + "name": "MIT" + } + }, + "paths": { + "/bbs/articles": { + "post": { + "deprecated": true, + "tags": [], + "parameters": [], + "requestBody": { + "description": "Content to store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IBbsArticle.IStore" + } + } + }, + "required": true, + "x-nestia-encrypted": false + }, + "responses": { + "201": { + "description": "Newly archived article", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IBbsArticle" + } + } + }, + "x-nestia-encrypted": false + } + }, + "summary": "Store an article", + "description": "Store an article.", + "x-nestia-namespace": "bbs.articles.store", + "x-nestia-jsDocTags": [ + { + "name": "param", + "text": [ + { + "text": "input", + "kind": "parameterName" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "Content to store", + "kind": "text" + } + ] + }, + { + "name": "returns", + "text": [ + { + "text": "Newly archived article", + "kind": "text" + } + ] + }, + { + "name": "deprecated" + } + ], + "x-nestia-method": "POST" + } + }, + "/health": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "x-nestia-encrypted": false + } + }, + "x-nestia-namespace": "health.get", + "x-nestia-jsDocTags": [], + "x-nestia-method": "GET" + } + }, + "/performance": { + "get": { + "tags": [], + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IPerformance" + } + } + }, + "x-nestia-encrypted": false + } + }, + "x-nestia-namespace": "performance.get", + "x-nestia-jsDocTags": [], + "x-nestia-method": "GET" + } + } + }, + "components": { + "schemas": { + "IBbsArticle.IStore": { + "type": "object", + "properties": { + "title": { + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "3", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "50", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "type": "string", + "maxLength": 50, + "minLength": 3, + "x-typia-typeTags": [ + { + "name": "MinLength<3>", + "target": "string", + "kind": "minLength", + "value": 3, + "validate": "3 <= $input.length", + "exclusive": true + }, + { + "name": "MaxLength<50>", + "target": "string", + "kind": "maxLength", + "value": 50, + "validate": "$input.length <= 50", + "exclusive": true + } + ] + }, + "body": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "string" + }, + "files": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "array", + "items": { + "$ref": "#/components/schemas/IAttachmentFile" + } + } + }, + "nullable": false, + "required": [ + "title", + "body", + "files" + ], + "x-typia-jsDocTags": [] + }, + "IAttachmentFile": { + "type": "object", + "properties": { + "name": { + "x-typia-jsDocTags": [ + { + "name": "minLengt", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "255", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "type": "string", + "maxLength": 255, + "x-typia-typeTags": [ + { + "name": "MaxLength<255>", + "target": "string", + "kind": "maxLength", + "value": 255, + "validate": "$input.length <= 255", + "exclusive": true + } + ], + "nullable": true + }, + "extension": { + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "1", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "8", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "type": "string", + "maxLength": 8, + "minLength": 1, + "x-typia-typeTags": [ + { + "name": "MinLength<1>", + "target": "string", + "kind": "minLength", + "value": 1, + "validate": "1 <= $input.length", + "exclusive": true + }, + { + "name": "MaxLength<8>", + "target": "string", + "kind": "maxLength", + "value": 8, + "validate": "$input.length <= 8", + "exclusive": true + } + ], + "nullable": true + }, + "url": { + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "url", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "type": "string", + "format": "url", + "x-typia-typeTags": [ + { + "name": "Format<\"url\">", + "target": "string", + "kind": "format", + "value": "url", + "validate": "/^[a-zA-Z0-9]+:\\/\\/(?:www.)?[-a-zA-Z0-9@:%._+~#=]{1,256}.[a-zA-Z0-9()]{1,6}\\b(?:[-a-zA-Z0-9()@:%_+.~#?&/=]*)$/.test($input)", + "exclusive": true + } + ] + } + }, + "nullable": false, + "required": [ + "name", + "extension", + "url" + ], + "x-typia-jsDocTags": [] + }, + "IBbsArticle": { + "type": "object", + "properties": { + "id": { + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "uuid", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "type": "string", + "format": "uuid", + "x-typia-typeTags": [ + { + "name": "Format<\"uuid\">", + "target": "string", + "kind": "format", + "value": "uuid", + "validate": "/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i.test($input)", + "exclusive": true + } + ] + }, + "created_at": { + "x-typia-jsDocTags": [ + { + "name": "format", + "text": [ + { + "text": "date-time", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "type": "string", + "format": "date-time", + "x-typia-typeTags": [ + { + "name": "Format<\"date-time\">", + "target": "string", + "kind": "format", + "value": "date-time", + "validate": "!isNaN(new Date($input).getTime())", + "exclusive": true + } + ] + }, + "title": { + "x-typia-jsDocTags": [ + { + "name": "minLength", + "text": [ + { + "text": "3", + "kind": "text" + } + ] + }, + { + "name": "maxLength", + "text": [ + { + "text": "50", + "kind": "text" + } + ] + } + ], + "x-typia-required": true, + "x-typia-optional": false, + "type": "string", + "maxLength": 50, + "minLength": 3, + "x-typia-typeTags": [ + { + "name": "MinLength<3>", + "target": "string", + "kind": "minLength", + "value": 3, + "validate": "3 <= $input.length", + "exclusive": true + }, + { + "name": "MaxLength<50>", + "target": "string", + "kind": "maxLength", + "value": 50, + "validate": "$input.length <= 50", + "exclusive": true + } + ] + }, + "body": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "string" + }, + "files": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "array", + "items": { + "$ref": "#/components/schemas/IAttachmentFile" + } + } + }, + "nullable": false, + "required": [ + "id", + "created_at", + "title", + "body", + "files" + ], + "x-typia-jsDocTags": [] + }, + "IPerformance": { + "type": "object", + "properties": { + "cpu": { + "$ref": "#/components/schemas/process.global.NodeJS.CpuUsage" + }, + "memory": { + "$ref": "#/components/schemas/process.global.NodeJS.MemoryUsage" + }, + "resource": { + "$ref": "#/components/schemas/process.global.NodeJS.ResourceUsage" + } + }, + "nullable": false, + "required": [ + "cpu", + "memory", + "resource" + ], + "description": "Performance info.", + "x-typia-jsDocTags": [ + { + "name": "author", + "text": [ + { + "text": "Samchon", + "kind": "text" + } + ] + } + ] + }, + "process.global.NodeJS.CpuUsage": { + "type": "object", + "properties": { + "user": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "system": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + } + }, + "nullable": false, + "required": [ + "user", + "system" + ], + "x-typia-jsDocTags": [] + }, + "process.global.NodeJS.MemoryUsage": { + "type": "object", + "properties": { + "rss": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "heapTotal": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "heapUsed": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "external": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "arrayBuffers": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + } + }, + "nullable": false, + "required": [ + "rss", + "heapTotal", + "heapUsed", + "external", + "arrayBuffers" + ], + "x-typia-jsDocTags": [] + }, + "process.global.NodeJS.ResourceUsage": { + "type": "object", + "properties": { + "fsRead": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "fsWrite": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "involuntaryContextSwitches": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "ipcReceived": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "ipcSent": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "majorPageFault": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "maxRSS": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "minorPageFault": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "sharedMemorySize": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "signalsCount": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "swappedOut": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "systemCPUTime": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "unsharedDataSize": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "unsharedStackSize": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "userCPUTime": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + }, + "voluntaryContextSwitches": { + "x-typia-required": true, + "x-typia-optional": false, + "type": "number" + } + }, + "nullable": false, + "required": [ + "fsRead", + "fsWrite", + "involuntaryContextSwitches", + "ipcReceived", + "ipcSent", + "majorPageFault", + "maxRSS", + "minorPageFault", + "sharedMemorySize", + "signalsCount", + "swappedOut", + "systemCPUTime", + "unsharedDataSize", + "unsharedStackSize", + "userCPUTime", + "voluntaryContextSwitches" + ], + "x-typia-jsDocTags": [] + } + }, + "securitySchemes": { + "bearer": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + } + } + } +} \ No newline at end of file diff --git a/test/features/ignore/tsconfig.json b/test/features/ignore/tsconfig.json new file mode 100644 index 000000000..c33dfa28f --- /dev/null +++ b/test/features/ignore/tsconfig.json @@ -0,0 +1,98 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */// "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + "paths": { + "@api": ["./src/api"], + "@api/lib/*": ["./src/api/*"], + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. *//* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true, /* Skip type checking all .d.ts files. */ + "plugins": [ + { "transform": "typescript-transform-paths" }, + { "transform": "typia/lib/transform" }, + { "transform": "@nestia/core/lib/transform" }, + ], + } + } \ No newline at end of file diff --git a/test/package.json b/test/package.json index 4964a7e3f..84d81c40a 100644 --- a/test/package.json +++ b/test/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@nestia/test", - "version": "2.3.11", + "version": "2.3.12", "description": "Test program of Nestia", "main": "index.js", "scripts": { @@ -37,9 +37,9 @@ "typia": "^5.2.6", "uuid": "^9.0.0", "nestia": "^4.5.0", - "@nestia/core": "^2.3.11", + "@nestia/core": "^2.3.12", "@nestia/e2e": "^0.3.6", - "@nestia/fetcher": "^2.3.11", - "@nestia/sdk": "^2.3.11" + "@nestia/fetcher": "^2.3.12", + "@nestia/sdk": "^2.3.12" } } \ No newline at end of file diff --git a/website/pages/docs/sdk/sdk.mdx b/website/pages/docs/sdk/sdk.mdx index 5191cf77b..7ddca9469 100644 --- a/website/pages/docs/sdk/sdk.mdx +++ b/website/pages/docs/sdk/sdk.mdx @@ -450,7 +450,184 @@ export default NESTIA_CONFIG; ## Comment Tags -SDK library of `@nestia/sdk` supports special comment tags configuring client headers. +### Hiding +If you want to hide some API endpoints from the SDK library, write a comment tag to the controller method. + + - `@deprepcated`: warning from IDE + - `@internal`: hide from `d.ts` files + - `@ignore`: actually ignore, so that not even generated + +At first, `@deprecated` does not hide target API from the SDK library, but just mark as deprecated. In that case, IDE will warn to the SDK users. In such reason, `@deprecated` comment tag is useful for legacy API endpoints that would be removed in the future. + +The second `@internal` tag also does not hide from the SDK library, but it would be disappeared from `d.ts` files, so that client developers can't identify the API. Therefore, `@internal` tag is useful for some API endpoints that would be used only in the backend server for testing or debugging purpose. + +The last `@ignore` tag is the most powerful one. If you write `@ignore` tag to the controller method, the SDK library would never generate the API endpoint at all. In that case, client developers can't use the API endpoint even if they know the API endpoint path and method. It is useful for some endpoints that are not supported in the SDK library. + + + +```typescript copy filename="BbsArticlesController.ts" +import { Controller } from "@nestjs/common"; + +import { IBbsArticle } from "@api/lib/structures/IBbsArticle"; + +@Controller("bbs/articles") +export class BbsArticlesController { + /** + * Store an article. + * + * @param input Content to store + * @returns Newly archived article + * @deprecated + */ + public async create( + @TypedBody() input: IBbsArticle.IStore, + ): Promise { + ... + } + + /** + * @internal + */ + public async update( + @TypedParam("id") id: string & tags.Format<"uuid">, + @TypedBody() input: IBbsArticle.IUpdate, + ): Promise { + ... + } + + /** + * @ignore + */ + public async erase( + @TypedParam("id") id: string & tags.Format<"uuid">, + ): Promise { + ... + } +} +``` + + +```typescript filename="src/api/functional/bbs/articles/index.ts" +/** + * @packageDocumentation + * @module api.functional.bbs.articles + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +//================================================================ +import type { IConnection, Primitive } from "@nestia/fetcher"; +import { PlainFetcher } from "@nestia/fetcher/lib/PlainFetcher"; +import type { Format } from "typia/lib/tags/Format"; + +import type { IBbsArticle } from "../../../structures/IBbsArticle"; + +/** + * Store an article. + * + * @param input Content to store + * @returns Newly archived article + * @deprecated + * + * @controller BbsArticlesController.store + * @path POST /bbs/articles + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export async function store( + connection: IConnection, + input: store.Input, +): Promise { + return PlainFetcher.fetch( + { + ...connection, + headers: { + ...(connection.headers ?? {}), + "Content-Type": "application/json", + }, + }, + { + ...store.METADATA, + path: store.path(), + } as const, + input, + ); +} +export namespace store { + export type Input = Primitive; + export type Output = Primitive; + + export const METADATA = { + method: "POST", + path: "/bbs/articles", + request: { + type: "application/json", + encrypted: false + }, + response: { + type: "application/json", + encrypted: false, + }, + status: null, + } as const; + + export const path = (): string => { + return `/bbs/articles`; + } +} + +/** + * + * @internal + * + * @controller BbsArticlesController.update + * @path PUT /bbs/articles/:id + * @nestia Generated by Nestia - https://github.com/samchon/nestia + */ +export async function update( + connection: IConnection, + id: string & Format<"uuid">, + input: update.Input, +): Promise { + return PlainFetcher.fetch( + { + ...connection, + headers: { + ...(connection.headers ?? {}), + "Content-Type": "application/json", + }, + }, + { + ...update.METADATA, + path: update.path(id), + } as const, + input, + ); +} +export namespace update { + export type Input = Primitive>; + + export const METADATA = { + method: "PUT", + path: "/bbs/articles/:id", + request: { + type: "application/json", + encrypted: false + }, + response: { + type: "application/json", + encrypted: false, + }, + status: null, + } as const; + + export const path = (id: string & Format<"uuid">): string => { + return `/bbs/articles/${encodeURIComponent(id ?? "null")}`; + } +} +``` + + + +### Headers +Also, SDK library of `@nestia/sdk` supports special comment tags configuring client headers. - `@setHeader` - `@assignHeaders` diff --git a/website/pages/docs/sdk/swagger.mdx b/website/pages/docs/sdk/swagger.mdx index ba0958d2e..26fabc3c7 100644 --- a/website/pages/docs/sdk/swagger.mdx +++ b/website/pages/docs/sdk/swagger.mdx @@ -545,6 +545,7 @@ Swagger generator `@nestia/sdk` supports three type of comment tags for controll - Hiding - `@deprecated`: mark as `deprecated` - `@internal`: hide, never be shown + - `@ignore`: hide, never be shown, even in the SDK side - Labeling - `@summary` : short description of endpoint - `@tag {name}`: grouppig @@ -553,7 +554,7 @@ Swagger generator `@nestia/sdk` supports three type of comment tags for controll - `@security {key}`: security scheme key - `@security {key} {...scopes}`: +scopes for OAuth2 type -At first, `@internal` tag is used to hide the controller method from the Swagger Documents. When you use it, the controller method would not be written in the `swagger.json` file. Otherwise, the `@deprecated` tag is used to mark the controller method as deprecated. When you use it, Swagger Editor will show the deprecated message about the route method like below. +At first, `@internal` and `@ignore` tags are used to hide the controller method from the Swagger Documents. When you use one of them, the controller method would not be written in the `swagger.json` file. Otherwise, the `@deprecated` tag is used to mark the controller method as deprecated. When you use it, Swagger Editor will show the deprecated message about the route method like below. Also, the `@summary` tag is used to write short description of the endpoint. By the way, the `@summary` tag can be replaced by writing top sentence ends with `.` symbol. The other one, `@tag {name}` tag is used for only groupping.