From 1da31eb07dd2ac3c9469a94a13babc01f04660bc Mon Sep 17 00:00:00 2001 From: mugifly Date: Fri, 21 Jun 2024 16:03:45 +0900 Subject: [PATCH] feat(server): Support for little complex (but common) API document --- README.md | 4 +++- server/src/helper.ts | 16 ++++++++++++++++ server/src/main.ts | 8 ++++---- server/src/openapi-doc-generator.ts | 23 ++++++++++++++--------- 4 files changed, 37 insertions(+), 14 deletions(-) create mode 100644 server/src/helper.ts diff --git a/README.md b/README.md index 854de15..bb99fce 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,8 @@ $ npm run start:dev Finally, open the web browser and navigate to `http://localhost:4200/`. Also, when you edit the frontend source-code, auto-reloading applies your changes to the browser immediately. +An API documentation is generated by Swagger UI, and you can access it at `http://localhost:4200/api/docs`. + See the [Wiki](https://github.com/mugifly/angular-nest/wiki/) for additional information. You'll find tips for implementing database connectivity, guides for future updates, and more. @@ -111,7 +113,7 @@ https://github.com/mugifly/angular-nest/wiki/#Deployments - Unit tests for backend:   `npm run test -w server` - E2E tests for backend:   `npm run test:e2e -w server` -### Install npm modules1 +### Install npm modules - Install for frontend: `npm install -w client XXXXX` - Install for backend: `npm install -w server XXXXX`
(e.g. `npm install -w server @nestjs/typeorm typeorm`) diff --git a/server/src/helper.ts b/server/src/helper.ts new file mode 100644 index 0000000..db7eeb1 --- /dev/null +++ b/server/src/helper.ts @@ -0,0 +1,16 @@ +import { INestApplication } from '@nestjs/common'; +import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; + +export class Helper { + static getOpenAPIDoc(app: INestApplication) { + const doc_options = new DocumentBuilder() + .setTitle(`API Document`) + // Output securitySchemes to support Bearer authentication + // See: https://docs.nestjs.com/openapi/security#bearer-authentication + .addBearerAuth() + .build(); + + const doc = SwaggerModule.createDocument(app, doc_options); + return doc; + } +} diff --git a/server/src/main.ts b/server/src/main.ts index a4827ed..f4974a3 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -1,6 +1,7 @@ import { NestFactory } from '@nestjs/core'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { AppModule } from './app.module'; +import { Helper } from './helper'; async function bootstrap() { const app = await NestFactory.create(AppModule); @@ -8,11 +9,10 @@ async function bootstrap() { // Change the URL prefix to `/api` on backend app.setGlobalPrefix('api'); - // Build the OpenAPI document (published under `/api/docs`) with Swagger - const doc_options = new DocumentBuilder().setTitle(`API Document`).build(); - const doc = SwaggerModule.createDocument(app, doc_options); + // Enable Swagger UI for development env if (process.env.NODE_ENV && process.env.NODE_ENV === 'development') { - // Enable Swagger UI for development env + // Build the OpenAPI document (published under `/api/docs`) with Swagger + const doc = Helper.getOpenAPIDoc(app); SwaggerModule.setup('api/docs', app, doc); } diff --git a/server/src/openapi-doc-generator.ts b/server/src/openapi-doc-generator.ts index ae0c0a0..2c83db7 100644 --- a/server/src/openapi-doc-generator.ts +++ b/server/src/openapi-doc-generator.ts @@ -2,6 +2,7 @@ import { Test } from '@nestjs/testing'; import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; import * as fs from 'fs'; import { AppModule } from './app.module'; +import { Helper } from './helper'; async function bootstrap(): Promise { // Get the modules included by AppModule @@ -18,16 +19,21 @@ async function bootstrap(): Promise { providers = providers.concat(Reflect.getMetadata('providers', mod)); } - // Generate a mock - const mockedProviders = providers.map((provider: any) => { - return { - provide: provider, - useValue: {}, - }; - }); + // Generate the mock providers + const mockedProviders = providers + .filter((provider: any) => { + return provider !== undefined; + }) + .map((provider: any) => { + return { + provide: provider, + useValue: {}, + }; + }); // Generate an application instance const testingModule = await Test.createTestingModule({ + imports: [AppModule], controllers: controllers, providers: mockedProviders, }).compile(); @@ -38,8 +44,7 @@ async function bootstrap(): Promise { app.setGlobalPrefix('api'); // Generate API JSON - const doc_options = new DocumentBuilder().setTitle(`API Document`).build(); - const doc = SwaggerModule.createDocument(app, doc_options); + const doc = Helper.getOpenAPIDoc(app); const docJson = JSON.stringify(doc); // Check the argument