From d4c9981f9a0b1a79919ef8cfb1d5f5eb3936e62b Mon Sep 17 00:00:00 2001 From: Matthew Hoover Date: Wed, 21 Feb 2024 13:48:13 -0500 Subject: [PATCH] Added Swagger API Explorer for Auth Server --- api/package.json | 3 +++ api/src/router.ts | 26 ++++++++++++++---- api/src/server.ts | 3 ++- pnpm-lock.yaml | 69 ++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 94 insertions(+), 7 deletions(-) diff --git a/api/package.json b/api/package.json index f210366..30a3ee8 100644 --- a/api/package.json +++ b/api/package.json @@ -20,6 +20,8 @@ "googleapis-common": "^7.0.1", "reflect-metadata": "^0.1.13", "routing-controllers": "^0.10.4", + "routing-controllers-openapi": "^4.0.0", + "swagger-ui-express": "^5.0.0", "typedi": "^0.10.0", "winston": "^3.11.0" }, @@ -31,6 +33,7 @@ "@types/node": "^20.8.10", "@types/sinon": "^17.0.3", "@types/supertest": "^2.0.15", + "@types/swagger-ui-express": "^4.1.6", "@typescript-eslint/eslint-plugin": "^6.9.1", "@typescript-eslint/parser": "^6.9.1", "chai": "^4.3.10", diff --git a/api/src/router.ts b/api/src/router.ts index 351e575..d51c40f 100644 --- a/api/src/router.ts +++ b/api/src/router.ts @@ -1,17 +1,33 @@ -import { useContainer, useExpressServer } from "routing-controllers"; -import { Container } from "typedi"; import { Router } from "express"; +import { getMetadataArgsStorage, RoutingControllersOptions, useContainer, useExpressServer } from "routing-controllers"; +import { routingControllersToSpec } from "routing-controllers-openapi"; +import { serve, setup } from "swagger-ui-express"; +import { Container } from "typedi"; import "reflect-metadata"; import { AccessController } from "./controllers/access-controller.js"; import "./logger.js"; -export const router = Router() +// Declare router +export const router = Router(); -useContainer(Container); -useExpressServer(router, { +// Define configuration for RoutingControllers +const options: RoutingControllersOptions = { routePrefix: "/api", controllers: [ AccessController, ] +}; + +// Setup routing-controllers server +useContainer(Container); +useExpressServer(router, options); + +// Setup Swagger explorer +const swaggerSpec = routingControllersToSpec(getMetadataArgsStorage(), options, { + info: { + title: "FamiLAB Access Control", + version: "4" + } }); +router.use('/explorer', serve, setup(swaggerSpec)); diff --git a/api/src/server.ts b/api/src/server.ts index 0085433..afff9ec 100644 --- a/api/src/server.ts +++ b/api/src/server.ts @@ -1,6 +1,7 @@ import express from "express"; import { Container } from "typedi"; import { Logger } from "winston"; + import { env } from "./env.js"; import { router } from "./router.js"; @@ -12,5 +13,5 @@ app.use(router); // Start the server const port = env.serverPort; app.listen(port, () => { - logger.info(`Server started at http://localhost:${port}.`); + logger.info(`Server started. Explore API at http://localhost:${port}/explorer.`); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e476c2d..0e2c66f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -34,6 +34,12 @@ importers: routing-controllers: specifier: ^0.10.4 version: 0.10.4(class-transformer@0.5.1)(class-validator@0.14.1) + routing-controllers-openapi: + specifier: ^4.0.0 + version: 4.0.0(routing-controllers@0.10.4) + swagger-ui-express: + specifier: ^5.0.0 + version: 5.0.0(express@4.18.2) typedi: specifier: ^0.10.0 version: 0.10.0 @@ -62,6 +68,9 @@ importers: '@types/supertest': specifier: ^2.0.15 version: 2.0.16 + '@types/swagger-ui-express': + specifier: ^4.1.6 + version: 4.1.6 '@typescript-eslint/eslint-plugin': specifier: ^6.9.1 version: 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3) @@ -779,6 +788,13 @@ packages: '@types/superagent': 8.1.3 dev: true + /@types/swagger-ui-express@4.1.6: + resolution: {integrity: sha512-UVSiGYXa5IzdJJG3hrc86e8KdZWLYxyEsVoUI4iPXc7CO4VZ3AfNP8d/8+hrDRIqz+HAaSMtZSqAsF3Nq2X/Dg==} + dependencies: + '@types/express': 4.17.21 + '@types/serve-static': 1.15.5 + dev: true + /@types/triple-beam@1.3.5: resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} @@ -2555,13 +2571,20 @@ packages: p-locate: 5.0.0 dev: true + /lodash.capitalize@4.2.1: + resolution: {integrity: sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==} + dev: false + /lodash.get@4.4.2: resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} dev: true /lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true + + /lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + dev: false /log-symbols@4.1.0: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} @@ -2859,6 +2882,12 @@ packages: dev: false optional: true + /openapi3-ts@2.0.2: + resolution: {integrity: sha512-TxhYBMoqx9frXyOgnRHufjQfPXomTIHYKhSKJ6jHfj13kS8OEIhvmE8CTuQyKtjjWttAjX5DPxM1vmalEpo8Qw==} + dependencies: + yaml: 1.10.2 + dev: false + /optionator@0.9.3: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} engines: {node: '>= 0.8.0'} @@ -3087,6 +3116,21 @@ packages: glob: 7.2.3 dev: true + /routing-controllers-openapi@4.0.0(routing-controllers@0.10.4): + resolution: {integrity: sha512-rObiqX3nLN63ARMj/uf1YKr3WYR8mmny0YR68U70EU5IH3MLe+2uA3r//EkPBj+kKrnOtL2NcfQwhlLiJsQlMg==} + peerDependencies: + routing-controllers: ^0.10.0 + dependencies: + lodash.capitalize: 4.2.1 + lodash.merge: 4.6.2 + lodash.startcase: 4.4.0 + openapi3-ts: 2.0.2 + path-to-regexp: 6.2.1 + reflect-metadata: 0.1.14 + routing-controllers: 0.10.4(class-transformer@0.5.1)(class-validator@0.14.1) + tslib: 2.6.2 + dev: false + /routing-controllers@0.10.4(class-transformer@0.5.1)(class-validator@0.14.1): resolution: {integrity: sha512-o7EANDC78u/Hh8mLyPbc5noJYf/hOruk0CIcuMdpZM/jvlrgMTGObpcPNfm6HBi/lLhRlI3/ma/I6hCPKpucBQ==} peerDependencies: @@ -3377,6 +3421,20 @@ packages: has-flag: 4.0.0 dev: true + /swagger-ui-dist@5.11.7: + resolution: {integrity: sha512-8xqfJFRVEEU3Zxe8vQvC4g827lDOqV9haougR3tnlgF/PkDN//9Y6kGV9qsT0A9vawlbdF8dF/R6HrlDyHvbEQ==} + dev: false + + /swagger-ui-express@5.0.0(express@4.18.2): + resolution: {integrity: sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==} + engines: {node: '>= v0.10.32'} + peerDependencies: + express: '>=4.0.0 || >=5.0.0-beta' + dependencies: + express: 4.18.2 + swagger-ui-dist: 5.11.7 + dev: false + /template-url@1.0.0: resolution: {integrity: sha512-QUjZNE7yTdIzB91sITTSYcSX5GRF5FulKvIYCqV5350NfSNfiuuCYQIJZ5PIN7k/uJ+kpurEEv9hFqRRc+JilA==} dev: false @@ -3494,6 +3552,10 @@ packages: yn: 3.1.1 dev: true + /tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + dev: false + /tsscmp@1.0.6: resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==} engines: {node: '>=0.6.x'} @@ -3706,6 +3768,11 @@ packages: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: true + /yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + dev: false + /yargs-parser@20.2.4: resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} engines: {node: '>=10'}