From a68a18f11918d905454b396c51596374a27e81dc Mon Sep 17 00:00:00 2001 From: Jeongho Nam Date: Thu, 26 Sep 2024 00:20:39 +0900 Subject: [PATCH] Close #1046: support ``@ApiProduces()` decorator of `@nestjs/swagger` --- benchmark/package.json | 2 +- package.json | 2 +- packages/core/package.json | 6 +++--- packages/fetcher/package.json | 2 +- packages/sdk/package.json | 10 +++++----- .../analyses/ReflectHttpOperationResponseAnalyzer.ts | 6 ++++-- test/features/plain/src/controllers/PlainController.ts | 3 ++- .../src/test/features/api/test_api_plain_template.ts | 1 + test/features/plain/swagger.json | 2 +- test/package.json | 8 ++++---- 10 files changed, 23 insertions(+), 19 deletions(-) diff --git a/benchmark/package.json b/benchmark/package.json index 3a42c27b2..ff72f30ad 100644 --- a/benchmark/package.json +++ b/benchmark/package.json @@ -42,7 +42,7 @@ "reflect-metadata": "^0.2.2", "tgrid": "^1.0.3", "tstl": "^3.0.0", - "typia": "^6.10.0" + "typia": "^6.10.4" }, "devDependencies": { "@types/autocannon": "^7.9.0", diff --git a/package.json b/package.json index ac3700acf..33bd4396c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@nestia/station", - "version": "3.14.0", + "version": "3.14.1", "description": "Nestia station", "scripts": { "build": "node build/index.js", diff --git a/packages/core/package.json b/packages/core/package.json index 487d53f2a..e0b0033bb 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@nestia/core", - "version": "3.14.0", + "version": "3.14.1", "description": "Super-fast validation decorators of NestJS", "main": "lib/index.js", "typings": "lib/index.d.ts", @@ -36,7 +36,7 @@ }, "homepage": "https://nestia.io", "dependencies": { - "@nestia/fetcher": "^3.14.0", + "@nestia/fetcher": "^3.14.1", "@nestjs/common": ">=7.0.1", "@nestjs/core": ">=7.0.1", "@samchon/openapi": "^1.0.2", @@ -53,7 +53,7 @@ "ws": "^7.5.3" }, "peerDependencies": { - "@nestia/fetcher": ">=3.14.0", + "@nestia/fetcher": ">=3.14.1", "@nestjs/common": ">=7.0.1", "@nestjs/core": ">=7.0.1", "reflect-metadata": ">=0.1.12", diff --git a/packages/fetcher/package.json b/packages/fetcher/package.json index 62d125bd8..d583fc644 100644 --- a/packages/fetcher/package.json +++ b/packages/fetcher/package.json @@ -1,6 +1,6 @@ { "name": "@nestia/fetcher", - "version": "3.14.0", + "version": "3.14.1", "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 19a5a5867..49b522c19 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@nestia/sdk", - "version": "3.14.0", + "version": "3.14.1", "description": "Nestia SDK and Swagger generator", "main": "lib/index.js", "typings": "lib/index.d.ts", @@ -32,8 +32,8 @@ }, "homepage": "https://nestia.io", "dependencies": { - "@nestia/core": "^3.14.0", - "@nestia/fetcher": "^3.14.0", + "@nestia/core": "^3.14.1", + "@nestia/fetcher": "^3.14.1", "@samchon/openapi": "^1.0.2", "cli": "^1.0.1", "get-function-location": "^2.0.0", @@ -47,8 +47,8 @@ "typia": "^6.10.0" }, "peerDependencies": { - "@nestia/core": ">=3.14.0", - "@nestia/fetcher": ">=3.14.0", + "@nestia/core": ">=3.14.1", + "@nestia/fetcher": ">=3.14.1", "@nestjs/common": ">=7.0.1", "@nestjs/core": ">=7.0.1", "reflect-metadata": ">=0.1.12", diff --git a/packages/sdk/src/analyses/ReflectHttpOperationResponseAnalyzer.ts b/packages/sdk/src/analyses/ReflectHttpOperationResponseAnalyzer.ts index c9b0cff6c..d61991d73 100644 --- a/packages/sdk/src/analyses/ReflectHttpOperationResponseAnalyzer.ts +++ b/packages/sdk/src/analyses/ReflectHttpOperationResponseAnalyzer.ts @@ -50,12 +50,14 @@ export namespace ReflectHttpOperationResponseAnalyzer { function: ctx.function, }) ? "application/x-www-form-urlencoded" - : Reflect.getMetadata(HEADERS_METADATA, ctx.function)?.find( + : (Reflect.getMetadata(HEADERS_METADATA, ctx.function)?.find( (h: Record) => typeof h?.name === "string" && typeof h?.value === "string" && h.name.toLowerCase() === "content-type", - )?.value ?? (ctx.httpMethod === "HEAD" ? null : "application/json"); + )?.value ?? + Reflect.getMetadata("swagger/apiProduces", ctx.function)?.[0] ?? + (ctx.httpMethod === "HEAD" ? null : "application/json")); const schema = contentType === "application/json" diff --git a/test/features/plain/src/controllers/PlainController.ts b/test/features/plain/src/controllers/PlainController.ts index dc1007135..4fabe2ac7 100644 --- a/test/features/plain/src/controllers/PlainController.ts +++ b/test/features/plain/src/controllers/PlainController.ts @@ -1,5 +1,6 @@ import core from "@nestia/core"; import { Controller, Header, Post } from "@nestjs/common"; +import { ApiProduces } from "@nestjs/swagger"; @Controller("plain") export class PlainController { @@ -9,7 +10,7 @@ export class PlainController { return body; } - @Header("Content-Type", "text/plain") + @ApiProduces("text/plain") @Post("template") public async template( @core.PlainBody() diff --git a/test/features/plain/src/test/features/api/test_api_plain_template.ts b/test/features/plain/src/test/features/api/test_api_plain_template.ts index 431925420..0d3953027 100644 --- a/test/features/plain/src/test/features/api/test_api_plain_template.ts +++ b/test/features/plain/src/test/features/api/test_api_plain_template.ts @@ -7,6 +7,7 @@ export const test_api_plan_template = async ( ): Promise => { const x = "something_123_interesting_abc_is_not_true_it?"; const y: string = await api.functional.plain.template(connection, x); + TestValidator.equals("template")(x as string)(y); // TestValidator.error("wrong template")( diff --git a/test/features/plain/swagger.json b/test/features/plain/swagger.json index 11584f242..993bb7e08 100644 --- a/test/features/plain/swagger.json +++ b/test/features/plain/swagger.json @@ -1 +1 @@ -{"openapi":"3.1.0","servers":[{"url":"https://github.com/samchon/nestia","description":"insert your server url"}],"info":{"version":"3.13.0-dev.2024910","title":"@samchon/nestia-test","description":"Test program of Nestia","license":{"name":"MIT"}},"paths":{"/health":{"get":{"tags":[],"parameters":[],"responses":{"200":{"description":"","content":{"application/json":{}}}}}},"/performance":{"get":{"tags":[],"parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IPerformance"}}}}}}},"/plain/string":{"post":{"tags":[],"parameters":[],"requestBody":{"content":{"text/plain":{"schema":{"type":"string"}}},"required":true},"responses":{"201":{"description":"","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/plain/template":{"post":{"tags":[],"parameters":[],"requestBody":{"content":{"text/plain":{"schema":{"type":"string","pattern":"^((something_[+-]?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?_interesting_(.*)_is_not_false_it\\?)|(something_[+-]?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?_interesting_(.*)_is_not_true_it\\?))$"}}},"required":true},"responses":{"201":{"description":"","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/plain/constant":{"post":{"tags":[],"parameters":[],"requestBody":{"content":{"text/plain":{"schema":{"oneOf":[{"const":"A"},{"const":"B"},{"const":"C"}]}}},"required":true},"responses":{"201":{"description":"","content":{"text/plain":{"schema":{"type":"string"}}}}}}}},"components":{"schemas":{"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"}},"required":["cpu","memory","resource"],"description":"Performance info."},"process.global.NodeJS.CpuUsage":{"type":"object","properties":{"user":{"type":"number"},"system":{"type":"number"}},"required":["user","system"]},"process.global.NodeJS.MemoryUsage":{"type":"object","properties":{"rss":{"type":"number"},"heapTotal":{"type":"number"},"heapUsed":{"type":"number"},"external":{"type":"number"},"arrayBuffers":{"type":"number"}},"required":["rss","heapTotal","heapUsed","external","arrayBuffers"]},"process.global.NodeJS.ResourceUsage":{"type":"object","properties":{"fsRead":{"type":"number"},"fsWrite":{"type":"number"},"involuntaryContextSwitches":{"type":"number"},"ipcReceived":{"type":"number"},"ipcSent":{"type":"number"},"majorPageFault":{"type":"number"},"maxRSS":{"type":"number"},"minorPageFault":{"type":"number"},"sharedMemorySize":{"type":"number"},"signalsCount":{"type":"number"},"swappedOut":{"type":"number"},"systemCPUTime":{"type":"number"},"unsharedDataSize":{"type":"number"},"unsharedStackSize":{"type":"number"},"userCPUTime":{"type":"number"},"voluntaryContextSwitches":{"type":"number"}},"required":["fsRead","fsWrite","involuntaryContextSwitches","ipcReceived","ipcSent","majorPageFault","maxRSS","minorPageFault","sharedMemorySize","signalsCount","swappedOut","systemCPUTime","unsharedDataSize","unsharedStackSize","userCPUTime","voluntaryContextSwitches"]}},"securitySchemes":{"bearer":{"type":"apiKey"}}},"tags":[],"x-samchon-emended":true} \ No newline at end of file +{"openapi":"3.1.0","servers":[{"url":"https://github.com/samchon/nestia","description":"insert your server url"}],"info":{"version":"3.14.1-dev.20240925","title":"@samchon/nestia-test","description":"Test program of Nestia","license":{"name":"MIT"}},"paths":{"/health":{"get":{"tags":[],"parameters":[],"responses":{"200":{"description":"","content":{"application/json":{}}}}}},"/performance":{"get":{"tags":[],"parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IPerformance"}}}}}}},"/plain/string":{"post":{"tags":[],"parameters":[],"requestBody":{"content":{"text/plain":{"schema":{"type":"string"}}},"required":true},"responses":{"201":{"description":"","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/plain/template":{"post":{"tags":[],"parameters":[],"requestBody":{"content":{"text/plain":{"schema":{"type":"string","pattern":"^((something_[+-]?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?_interesting_(.*)_is_not_false_it\\?)|(something_[+-]?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?_interesting_(.*)_is_not_true_it\\?))$"}}},"required":true},"responses":{"201":{"description":"","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/plain/constant":{"post":{"tags":[],"parameters":[],"requestBody":{"content":{"text/plain":{"schema":{"oneOf":[{"const":"A"},{"const":"B"},{"const":"C"}]}}},"required":true},"responses":{"201":{"description":"","content":{"text/plain":{"schema":{"type":"string"}}}}}}}},"components":{"schemas":{"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"}},"required":["cpu","memory","resource"],"description":"Performance info."},"process.global.NodeJS.CpuUsage":{"type":"object","properties":{"user":{"type":"number"},"system":{"type":"number"}},"required":["user","system"]},"process.global.NodeJS.MemoryUsage":{"type":"object","properties":{"rss":{"type":"number"},"heapTotal":{"type":"number"},"heapUsed":{"type":"number"},"external":{"type":"number"},"arrayBuffers":{"type":"number"}},"required":["rss","heapTotal","heapUsed","external","arrayBuffers"]},"process.global.NodeJS.ResourceUsage":{"type":"object","properties":{"fsRead":{"type":"number"},"fsWrite":{"type":"number"},"involuntaryContextSwitches":{"type":"number"},"ipcReceived":{"type":"number"},"ipcSent":{"type":"number"},"majorPageFault":{"type":"number"},"maxRSS":{"type":"number"},"minorPageFault":{"type":"number"},"sharedMemorySize":{"type":"number"},"signalsCount":{"type":"number"},"swappedOut":{"type":"number"},"systemCPUTime":{"type":"number"},"unsharedDataSize":{"type":"number"},"unsharedStackSize":{"type":"number"},"userCPUTime":{"type":"number"},"voluntaryContextSwitches":{"type":"number"}},"required":["fsRead","fsWrite","involuntaryContextSwitches","ipcReceived","ipcSent","majorPageFault","maxRSS","minorPageFault","sharedMemorySize","signalsCount","swappedOut","systemCPUTime","unsharedDataSize","unsharedStackSize","userCPUTime","voluntaryContextSwitches"]}},"securitySchemes":{"bearer":{"type":"apiKey"}}},"tags":[],"x-samchon-emended":true} \ No newline at end of file diff --git a/test/package.json b/test/package.json index 296cc3a66..fd0f2dfd0 100644 --- a/test/package.json +++ b/test/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@samchon/nestia-test", - "version": "3.14.0", + "version": "3.14.1", "description": "Test program of Nestia", "main": "index.js", "scripts": { @@ -26,7 +26,7 @@ }, "homepage": "https://nestia.io", "devDependencies": { - "@nestia/sdk": "^3.14.0", + "@nestia/sdk": "^3.14.1", "@nestjs/swagger": "^7.4.2", "@samchon/openapi": "^1.0.2", "@types/express": "^4.17.17", @@ -40,9 +40,9 @@ }, "dependencies": { "@fastify/multipart": "^8.1.0", - "@nestia/core": "^3.14.0", + "@nestia/core": "^3.14.1", "@nestia/e2e": "^0.7.0", - "@nestia/fetcher": "^3.14.0", + "@nestia/fetcher": "^3.14.1", "@nestjs/common": "^10.4.3", "@nestjs/core": "^10.4.3", "@nestjs/platform-express": "^10.4.3",