diff --git a/.env b/.env new file mode 100644 index 0000000..16b733a --- /dev/null +++ b/.env @@ -0,0 +1 @@ +DB_NAME=blog_test diff --git a/.gitignore b/.gitignore index c618d7f..cd2bc75 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ dist/ *.log .idea/ .vscode/ -coverage/ \ No newline at end of file +coverage/ +.env/ diff --git a/example_requests.http b/example_requests.http index a4789a5..5ded5a0 100644 --- a/example_requests.http +++ b/example_requests.http @@ -3,10 +3,16 @@ POST http://localhost:3000/api/articles Content-Type: application/json { - "title": "This is my first article", + "title": "This is my first article draft", "content": "Test article content" } +### + +@articleId = {{article.response.body.$.id}} + +PATCH http://localhost:3000/api/articles/{{articleId}}/publish + ### GET http://localhost:3000/api/articles @@ -19,9 +25,3 @@ Content-Type: application/json { "body": "Nice!" } - -### - -@articleId = {{article.response.body.$.id}} - -PATCH http://localhost:3000/api/articles/{{articleId}}/publish \ No newline at end of file diff --git a/package.json b/package.json index 0f01152..84169b3 100644 --- a/package.json +++ b/package.json @@ -15,21 +15,21 @@ "dependencies": { "awilix": "^4.3.4", "dotenv": "^10.0.0", - "express": "^4.17.1", + "fastify": "^3.22.0", + "fastify-swagger": "^4.12.4", "joi": "^17.4.1", "lodash.template": "^4.5.0", + "middie": "^5.3.0", "mongodb": "^4.0.0", "pino": "^6.12.0", "pino-http": "^5.5.0", "swagger-jsdoc": "^6.1.0", - "swagger-ui-express": "^4.1.6", "tsconfig-paths": "^3.10.1", "types-joi": "^2.1.0", "uuid": "^8.3.2", "uuid-mongodb": "^2.4.4" }, "devDependencies": { - "@types/express": "^4.17.13", "@types/jest": "^26.0.24", "@types/lodash.template": "^4.5.0", "@types/mongodb": "^3.6.20", @@ -37,7 +37,6 @@ "@types/pino": "^6.3.11", "@types/supertest": "^2.0.11", "@types/swagger-jsdoc": "^6.0.1", - "@types/swagger-ui-express": "^4.1.3", "@typescript-eslint/eslint-plugin": "^4.28.3", "@typescript-eslint/parser": "^4.28.3", "eslint": "^7.30.0", diff --git a/src/__tests__/TestControls.ts b/src/__tests__/TestControls.ts index 871b119..965d87a 100644 --- a/src/__tests__/TestControls.ts +++ b/src/__tests__/TestControls.ts @@ -40,6 +40,8 @@ const makeTestControls = async (): Promise => { const { server } = container.cradle; + await server.ready(); + const clearDatabase = container.build(makeClearDatabase); const cleanUp = withContext(async ({ app }) => { @@ -48,7 +50,7 @@ const makeTestControls = async (): Promise => { }); return { - request: () => supertest(server), + request: () => supertest(server.server), registry: container.cradle, clearDatabase, container, diff --git a/src/__tests__/setup.ts b/src/__tests__/setup.ts index 679f780..8061e31 100644 --- a/src/__tests__/setup.ts +++ b/src/__tests__/setup.ts @@ -10,5 +10,3 @@ const catchAll = new Proxy( ); jest.mock('pino', () => () => catchAll); - -console = catchAll; diff --git a/src/_boot/server.ts b/src/_boot/server.ts index 2380185..68af2a2 100644 --- a/src/_boot/server.ts +++ b/src/_boot/server.ts @@ -1,13 +1,15 @@ -import express, { Router, Application, json, urlencoded } from 'express'; +import Fastify, { FastifyInstance } from 'fastify'; import { asValue } from 'awilix'; import httpLogger from 'pino-http'; -import { createServer } from 'http'; +import middie from 'middie'; import { requestId } from '@/_lib/http/middlewares/requestId'; import { requestContainer } from '@/_lib/http/middlewares/requestContainer'; import { errorHandler } from '@/_lib/http/middlewares/errorHandler'; import { makeModule } from '@/context'; import { gracefulShutdown } from '@/_lib/http/middlewares/gracefulShutdown'; import { errorConverters } from '@/_sharedKernel/interface/http/ErrorConverters'; +import { ApiRouter } from '@/_lib/http/apiRouter'; +import { HttpStatus } from '@/_lib/http/HttpStatus'; type ServerConfig = { http: { @@ -20,40 +22,46 @@ const server = makeModule( 'server', async ({ app: { onBooted, onReady }, container, config: { cli, http, environment }, logger }) => { const { register } = container; - const server = express(); + const fastifyServer = Fastify(); - const httpServer = createServer(server); + await fastifyServer.register(middie); - const { shutdownHook, shutdownHandler } = gracefulShutdown(httpServer); + const { shutdownHook, shutdownHandler } = gracefulShutdown(fastifyServer.server); - server.use(shutdownHandler()); - server.use(requestId()); - server.use(requestContainer(container)); - server.use(httpLogger()); - server.use(json()); - server.use(urlencoded({ extended: false })); + fastifyServer.use(shutdownHandler()); - const rootRouter = Router(); - const apiRouter = Router(); + fastifyServer.use(requestId()); + fastifyServer.use(requestContainer(container)); + fastifyServer.use(httpLogger()); - rootRouter.use('/api', apiRouter); + fastifyServer.setErrorHandler(errorHandler(errorConverters, { logger })); - server.use(rootRouter); + const apiRouter: ApiRouter = (fn) => { + fastifyServer.register( + (fastify, _, done) => { + fn(fastify); + done(); + }, + { prefix: '/api' } + ); + }; - onBooted(async () => { - server.use((req, res) => { - res.sendStatus(404); + onBooted(() => { + fastifyServer.use((req, res) => { + res.writeHead(HttpStatus.NOT_FOUND).end(); }); - - server.use(errorHandler(errorConverters, { logger })); }); if (!cli && environment !== 'test') { onReady( - async () => - new Promise((resolve) => { - httpServer.listen(http.port, http.host, () => { - logger.info(`Webserver listening at: http://${http.host}:${http.port}`); + () => + new Promise((resolve, reject) => { + fastifyServer.listen(http.port, http.host, (error, address) => { + if (error) { + return reject(error); + } + + logger.info(`Webserver listening at: ${address}`); resolve(); }); }) @@ -61,8 +69,7 @@ const server = makeModule( } register({ - server: asValue(server), - rootRouter: asValue(rootRouter), + server: asValue(fastifyServer), apiRouter: asValue(apiRouter), }); @@ -74,9 +81,8 @@ const server = makeModule( type ServerRegistry = { requestId?: string; - server: Application; - rootRouter: Router; - apiRouter: Router; + server: FastifyInstance; + apiRouter: ApiRouter; }; export { server }; diff --git a/src/_boot/swagger.ts b/src/_boot/swagger.ts index cc50e01..1d6736d 100644 --- a/src/_boot/swagger.ts +++ b/src/_boot/swagger.ts @@ -1,7 +1,7 @@ import { makeModule } from '@/context'; import { resolve } from 'path'; import swaggerJSDoc from 'swagger-jsdoc'; -import swaggerUi from 'swagger-ui-express'; +import fastifySwagger from 'fastify-swagger'; type SwaggerConfig = { swagger: { @@ -29,7 +29,11 @@ const swagger = makeModule('swagger', async ({ container: { build }, config: { h const swaggerSpec = swaggerJSDoc(options); build(({ server }) => { - server.use(swagger.docEndpoint, swaggerUi.serve, swaggerUi.setup(swaggerSpec, { explorer: true })); + server.register(fastifySwagger, { + routePrefix: swagger.docEndpoint, + swagger: swaggerSpec, + exposeRoute: true, + }); }); }); diff --git a/src/_lib/Application.ts b/src/_lib/Application.ts index 1b4e016..08fbc45 100644 --- a/src/_lib/Application.ts +++ b/src/_lib/Application.ts @@ -1,4 +1,4 @@ -type HookFn = () => Promise; +type HookFn = () => void | Promise; type HookStore = { get: (lifecycle: Lifecycle) => HookFn[]; diff --git a/src/_lib/Context.ts b/src/_lib/Context.ts index f532e65..d0c1c8f 100644 --- a/src/_lib/Context.ts +++ b/src/_lib/Context.ts @@ -57,14 +57,16 @@ const makeContext = >( return (Array.isArray(fn) ? fn : [fn]).reduce( (chain, hook) => - chain.then(() => - hook().catch((err) => { + chain.then(async () => { + try { + return await hook(); + } catch (err) { logger.error( `Error while performing ${lifecycle.toLowerCase()} hook${isArray ? 's' : ''} from ${name} module.` ); logger.error(err); - }) - ), + } + }), Promise.resolve() ); }), @@ -75,10 +77,12 @@ const makeContext = >( app.onDisposing(async () => { logger.info(`Disposing ${name} module.`); - return result().catch((err) => { + try { + return await result(); + } catch (err) { logger.error(`Error while disposing of ${name} module. Trying to resume teardown`); logger.error(err); - }); + } }, 'prepend'); } }); diff --git a/src/_lib/http/RequestHandler.d.ts b/src/_lib/http/RequestHandler.d.ts new file mode 100644 index 0000000..0d427f3 --- /dev/null +++ b/src/_lib/http/RequestHandler.d.ts @@ -0,0 +1,10 @@ +import { FastifyReply, FastifyRequest } from 'fastify'; +import { IncomingMessage, ServerResponse } from 'http'; + +type NextFunction = (err?: any) => void; + +type RequestHandler = (req: IncomingMessage, res: ServerResponse, next: NextFunction) => void; + +type ErrorHandler = (error: Error, request: FastifyRequest, reply: FastifyReply) => void | Promise; + +export { RequestHandler, ErrorHandler }; diff --git a/src/_lib/http/apiRouter.d.ts b/src/_lib/http/apiRouter.d.ts new file mode 100644 index 0000000..ae73609 --- /dev/null +++ b/src/_lib/http/apiRouter.d.ts @@ -0,0 +1,6 @@ +import { FastifyInstance } from 'fastify'; + +type ApiRouterFn = (fastify: FastifyInstance) => void; +type ApiRouter = (fn: ApiRouterFn) => void; + +export { ApiRouter }; diff --git a/src/_lib/http/handler.ts b/src/_lib/http/handler.ts index b3ee92c..94849bc 100644 --- a/src/_lib/http/handler.ts +++ b/src/_lib/http/handler.ts @@ -1,20 +1,21 @@ -import { RequestHandler } from 'express'; import { asFunction } from 'awilix'; -import { AsyncHandler, runAsync } from '@/_lib/http/runAsync'; +import { FastifyRequest, FastifyReply } from 'fastify'; -type ControllerHandler = (dependencies: any) => AsyncHandler; +type FastifyHandler = (request: FastifyRequest, reply: FastifyReply) => any; -const handler = (handler: ControllerHandler): RequestHandler => { +type ControllerHandler = (dependencies: any) => FastifyHandler; + +const handler = (handler: ControllerHandler): FastifyHandler => { const resolver = asFunction(handler); - return (req, res, next) => { - if (!('container' in req)) { + return (request, reply) => { + if (!('container' in request.raw)) { throw new Error("Can't find the request container! Have you registered the `requestContainer` middleware?"); } - const injectedHandler = req.container.build(resolver); + const injectedHandler = request.raw.container.build(resolver); - return runAsync(injectedHandler)(req, res, next); + return injectedHandler(request, reply); }; }; diff --git a/src/_lib/http/middlewares/errorHandler.ts b/src/_lib/http/middlewares/errorHandler.ts index d7ceaeb..25146b2 100644 --- a/src/_lib/http/middlewares/errorHandler.ts +++ b/src/_lib/http/middlewares/errorHandler.ts @@ -1,5 +1,6 @@ -import { ErrorRequestHandler } from 'express'; import { Exception } from '@/_lib/errors/BaseError'; +import { HttpStatus } from '@/_lib/http/HttpStatus'; +import { ErrorHandler } from '@/_lib/http/RequestHandler'; type ErrorConverter = { test: (err: E | any) => err is E; @@ -27,14 +28,11 @@ const defaultOptions: ErrorHandlerOptions = { logger: console, }; -const errorHandler = ( - errorMap: ErrorConverter[], - options: Partial = {} -): ErrorRequestHandler => { +const errorHandler = (errorMap: ErrorConverter[], options: Partial = {}): ErrorHandler => { const { logger } = { ...defaultOptions, ...options }; const errorResponseBuilder = makeErrorResponseBuilder(errorMap); - return (err, req, res, next) => { + return (err, request, reply) => { logger.error(err.stack); const errorResponse = errorResponseBuilder(err); @@ -42,10 +40,11 @@ const errorHandler = ( if (errorResponse) { const { status, body } = errorResponse; - return res.status(status).json(typeof body === 'object' ? body : { error: body }); + reply.status(status).send(typeof body === 'object' ? body : { error: body }); + return; } - res.status(500).json({ error: err.message }); + reply.status(HttpStatus.INTERNAL_SERVER_ERROR).send({ error: err.message }); }; }; diff --git a/src/_lib/http/middlewares/gracefulShutdown.ts b/src/_lib/http/middlewares/gracefulShutdown.ts index 0e7c8fd..2da7b34 100644 --- a/src/_lib/http/middlewares/gracefulShutdown.ts +++ b/src/_lib/http/middlewares/gracefulShutdown.ts @@ -1,6 +1,6 @@ import { Server } from 'http'; import { logger } from '@/_lib/logger'; -import { RequestHandler } from 'express'; +import { RequestHandler } from '@/_lib/http/RequestHandler'; type ShutdownMiddleware = { shutdownHook: () => Promise; @@ -39,8 +39,8 @@ const gracefulShutdown = (server: Server, forceTimeout = 30000): ShutdownMiddlew return next(); } - res.set('Connection', 'close'); - res.status(503).send('Server is in the process of restarting.'); + res.writeHead(503, { Connection: 'close' }); + res.end('Server is in the process of restarting.'); }, shutdownHook, }; diff --git a/src/_lib/http/middlewares/requestContainer.ts b/src/_lib/http/middlewares/requestContainer.ts index a3b16a4..4a6e5bb 100644 --- a/src/_lib/http/middlewares/requestContainer.ts +++ b/src/_lib/http/middlewares/requestContainer.ts @@ -1,9 +1,8 @@ -import { asValue } from 'awilix'; -import { RequestHandler } from 'express'; -import { Container } from '@/container'; +import { asValue, AwilixContainer } from 'awilix'; +import { RequestHandler } from '@/_lib/http/RequestHandler'; const requestContainer = - (container: Container): RequestHandler => + (container: T): RequestHandler => (req, res, next) => { const scopedContainer = container.createScope(); diff --git a/src/_lib/http/middlewares/requestId.ts b/src/_lib/http/middlewares/requestId.ts index 195cc97..1bae995 100644 --- a/src/_lib/http/middlewares/requestId.ts +++ b/src/_lib/http/middlewares/requestId.ts @@ -1,5 +1,5 @@ import { v4 } from 'uuid'; -import { RequestHandler } from 'express'; +import { RequestHandler } from '@/_lib/http/RequestHandler'; const requestId = (idProvider: () => string = v4): RequestHandler => diff --git a/src/_lib/http/runAsync.ts b/src/_lib/http/runAsync.ts deleted file mode 100644 index 87d02c4..0000000 --- a/src/_lib/http/runAsync.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { NextFunction, Request, Response } from 'express'; - -type AsyncHandler = (req: Request, res: Response, next: NextFunction) => Promise; - -const runAsync = (handler: AsyncHandler) => (req: Request, res: Response, next: NextFunction) => - handler(req, res, next).catch(next); - -export { runAsync }; -export type { AsyncHandler }; diff --git a/src/_lib/http/validation/Paginator.ts b/src/_lib/http/validation/Paginator.ts index 2b02a15..91da7e0 100644 --- a/src/_lib/http/validation/Paginator.ts +++ b/src/_lib/http/validation/Paginator.ts @@ -1,4 +1,4 @@ -import { Request } from 'express'; +import { FastifyRequest } from 'fastify'; import Joi, { InterfaceFrom } from 'types-joi'; import { ValidationError } from '@/_lib/errors/ValidationError'; import { BadRequestError } from '@/_lib/errors/BadRequestError'; @@ -29,11 +29,11 @@ type PaginatorOptions> = { }; type Paginator>> = { - getPagination: (req: Request) => { page: number; pageSize: number }; + getPagination: (req: FastifyRequest) => { page: number; pageSize: number }; getFilter: ( - req: Request + req: FastifyRequest ) => T['filter'] extends Joi.BaseSchema ? NonNullable>> : any; - getSorter: (req: Request) => { field: string; direction: 'asc' | 'desc' }[]; + getSorter: (req: FastifyRequest) => { field: string; direction: 'asc' | 'desc' }[]; }; const defaultOptions = { @@ -70,9 +70,14 @@ const makePaginator = >(opts: Partial = {}): const getField = (field: string | FieldConfig): FieldConfig => typeof field === 'string' ? { name: field, from: 'query' } : field; - const fromRequest = (req: Request, field: FieldConfig) => req[field.from][field.name]; + const fromRequest = (req: FastifyRequest, field: FieldConfig): unknown => { + const fieldValue = req[field.from]; + if (typeof fieldValue === 'object' && fieldValue != null) { + return fieldValue[field.name]; + } + }; - const getPagination = (req: Request): { page: number; pageSize: number } => { + const getPagination = (req: FastifyRequest): { page: number; pageSize: number } => { const pageField = getField(fields.page); const pageSizeField = getField(fields.pageSize); @@ -91,7 +96,7 @@ const makePaginator = >(opts: Partial = {}): }; }; - const getSorter = (req: Request): { field: string; direction: 'asc' | 'desc' }[] => { + const getSorter = (req: FastifyRequest): { field: string; direction: 'asc' | 'desc' }[] => { const sortField = getField(fields.sort); const sortValues = fromRequest(req, sortField); @@ -110,7 +115,7 @@ const makePaginator = >(opts: Partial = {}): }; const getFilter = ( - req: Request + req: FastifyRequest ): T['filter'] extends Joi.BaseSchema ? NonNullable>> : any => { const filterField = getField(fields.filter); const filterValue = fromRequest(req, filterField); diff --git a/src/_lib/http/validation/Validator.ts b/src/_lib/http/validation/Validator.ts index fcfb6ee..d815a03 100644 --- a/src/_lib/http/validation/Validator.ts +++ b/src/_lib/http/validation/Validator.ts @@ -1,7 +1,7 @@ import * as Joi from 'types-joi'; -import { Request } from 'express'; import { InterfaceFrom } from 'types-joi'; import { ValidationError } from '@/_lib/errors/ValidationError'; +import { FastifyRequest } from 'fastify'; type ValidationSchemas = { body?: Joi.BaseSchema; @@ -14,15 +14,15 @@ type ValidationSchemas = { type ValidationType = T extends Joi.BaseSchema ? InterfaceFrom> : any; type ValidationHelpers = { - getBody(req: Request): ValidationType; - getParams(req: Request): ValidationType; - getQuery(req: Request): ValidationType; - getCookies(req: Request): ValidationType; - getHeaders(req: Request): ValidationType; + getBody(req: FastifyRequest): ValidationType; + getParams(req: FastifyRequest): ValidationType; + getQuery(req: FastifyRequest): ValidationType; + getCookies(req: FastifyRequest): ValidationType; + getHeaders(req: FastifyRequest): ValidationType; }; const makeValidator = (schemas: T): ValidationHelpers => { - const createValidator = (key: keyof ValidationSchemas) => (req: Request) => { + const createValidator = (key: keyof ValidationSchemas) => (req: FastifyRequest) => { if (!schemas[key]) { return req[key]; } diff --git a/src/article/interface/email/ArticleCreatedEmailListener.ts b/src/article/interface/email/ArticleCreatedEmailListener.ts index 14a4986..329a211 100644 --- a/src/article/interface/email/ArticleCreatedEmailListener.ts +++ b/src/article/interface/email/ArticleCreatedEmailListener.ts @@ -2,18 +2,20 @@ import { ArticleCreatedEvent } from '@/article/application/events/ArticleCreated import { ArticleCollection } from '@/article/infrastructure/ArticleCollection'; import { from } from 'uuid-mongodb'; import { eventConsumer } from '@/_lib/pubSub/EventEmitterConsumer'; +import { Logger } from 'pino'; type Dependencies = { articleCollection: ArticleCollection; + logger: Logger; }; const makeArticleCreatedEmailListener = eventConsumer( ArticleCreatedEvent, - ({ articleCollection }) => + ({ articleCollection, logger }) => async (event) => { const article = await articleCollection.findOne({ _id: from(event.payload.id.value) }); - console.log(article); + logger.info(article || {}); } ); diff --git a/src/article/interface/http/articleController/CreateArticleHandler.ts b/src/article/interface/http/articleController/CreateArticleHandler.ts index 43fda2c..d6261ee 100644 --- a/src/article/interface/http/articleController/CreateArticleHandler.ts +++ b/src/article/interface/http/articleController/CreateArticleHandler.ts @@ -1,7 +1,6 @@ import { CreateArticle } from '@/article/application/useCases/CreateArticle'; import { makeValidator } from '@/_lib/http/validation/Validator'; import { handler } from '@/_lib/http/handler'; -import { Request, Response } from 'express'; import Joi from 'types-joi'; import { HttpStatus } from '@/_lib/http/HttpStatus'; @@ -16,12 +15,11 @@ const { getBody } = makeValidator({ }).required(), }); -const createArticleHandler = handler(({ createArticle }: Dependencies) => async (req: Request, res: Response) => { - const { title, content } = getBody(req); - +const createArticleHandler = handler(({ createArticle }: Dependencies) => async (request, reply) => { + const { title, content } = getBody(request); const articleId = await createArticle({ title, content }); - res.status(HttpStatus.CREATED).json({ id: articleId }); + reply.status(HttpStatus.CREATED).send({ id: articleId }); }); export { createArticleHandler }; diff --git a/src/article/interface/http/articleController/DeleteArticleHandler.ts b/src/article/interface/http/articleController/DeleteArticleHandler.ts index 5f3ecc3..2666277 100644 --- a/src/article/interface/http/articleController/DeleteArticleHandler.ts +++ b/src/article/interface/http/articleController/DeleteArticleHandler.ts @@ -1,16 +1,25 @@ +import { makeValidator } from '@/_lib/http/validation/Validator'; import { DeleteArticle } from '@/article/application/useCases/DeleteArticle'; import { handler } from '@/_lib/http/handler'; +import { HttpStatus } from '@/_lib/http/HttpStatus'; +import Joi from 'types-joi'; type Dependencies = { deleteArticle: DeleteArticle; }; -const deleteArticleHandler = handler(({ deleteArticle }: Dependencies) => async (req, res) => { - const { articleId } = req.params; +const { getParams } = makeValidator({ + params: Joi.object({ + articleId: Joi.string().required(), + }).required(), +}); + +const deleteArticleHandler = handler(({ deleteArticle }: Dependencies) => async (request, reply) => { + const { articleId } = getParams(request); await deleteArticle(articleId); - res.sendStatus(204); + reply.status(HttpStatus.NO_CONTENT); }); export { deleteArticleHandler }; diff --git a/src/article/interface/http/articleController/FindArticlesHandler.ts b/src/article/interface/http/articleController/FindArticlesHandler.ts index f485187..d22511e 100644 --- a/src/article/interface/http/articleController/FindArticlesHandler.ts +++ b/src/article/interface/http/articleController/FindArticlesHandler.ts @@ -14,10 +14,10 @@ const { getFilter, getPagination, getSorter } = makePaginator({ }), }); -const findArticlesHandler = handler(({ findArticles }: Dependencies) => async (req, res) => { - const filter = getFilter(req); - const pagination = getPagination(req); - const sort = getSorter(req); +const findArticlesHandler = handler(({ findArticles }: Dependencies) => async (request, reply) => { + const filter = getFilter(request); + const pagination = getPagination(request); + const sort = getSorter(request); const articles = await findArticles({ filter, @@ -25,7 +25,7 @@ const findArticlesHandler = handler(({ findArticles }: Dependencies) => async (r pagination, }); - res.json(articles); + reply.send(articles); }); export { findArticlesHandler }; diff --git a/src/article/interface/http/articleController/PublishArticleHandler.ts b/src/article/interface/http/articleController/PublishArticleHandler.ts index 2c6c558..aa9f976 100644 --- a/src/article/interface/http/articleController/PublishArticleHandler.ts +++ b/src/article/interface/http/articleController/PublishArticleHandler.ts @@ -1,17 +1,25 @@ import { PublishArticle } from '@/article/application/useCases/PublishArticle'; import { handler } from '@/_lib/http/handler'; -import { Request, Response } from 'express'; +import { HttpStatus } from '@/_lib/http/HttpStatus'; +import { makeValidator } from '@/_lib/http/validation/Validator'; +import Joi from 'types-joi'; type Dependencies = { publishArticle: PublishArticle; }; -const publishArticleHandler = handler(({ publishArticle }: Dependencies) => async (req: Request, res: Response) => { - const { articleId } = req.params; +const { getParams } = makeValidator({ + params: Joi.object({ + articleId: Joi.string().required(), + }).required(), +}); + +const publishArticleHandler = handler(({ publishArticle }: Dependencies) => async (request, reply) => { + const { articleId } = getParams(request); await publishArticle(articleId); - res.sendStatus(204); + reply.status(HttpStatus.NO_CONTENT); }); export { publishArticleHandler }; diff --git a/src/article/interface/http/articleController/index.ts b/src/article/interface/http/articleController/index.ts index 7f82756..302c56f 100644 --- a/src/article/interface/http/articleController/index.ts +++ b/src/article/interface/http/articleController/index.ts @@ -1,40 +1,38 @@ import { deleteArticleHandler } from '@/article/interface/http/articleController/DeleteArticleHandler'; -import { Router } from 'express'; +import { ApiRouter } from '@/_lib/http/apiRouter'; import { createArticleHandler } from './CreateArticleHandler'; import { findArticlesHandler } from './FindArticlesHandler'; import { publishArticleHandler } from './PublishArticleHandler'; type Dependencies = { - apiRouter: Router; + apiRouter: ApiRouter; }; -const makeArticleController = ({ apiRouter }: Dependencies) => { - const router = Router(); - - /** - * @swagger - * - * /articles: - * get: - * tags: - * - Articles - * summary: The list of published articles - * produces: - * - application/json - * responses: - * 200: - * description: List of published articles - * schema: - * type: array - * items: - * $ref: '#/definitions/ArticleDTO' - */ - router.get('/articles', findArticlesHandler); - router.post('/articles', createArticleHandler); - router.delete('/articles/:articleId', deleteArticleHandler); - router.patch('/articles/:articleId/publish', publishArticleHandler); - - apiRouter.use(router); +const makeArticleController = ({ apiRouter }: Dependencies): void => { + apiRouter((router) => { + /** + * @swagger + * + * /articles: + * get: + * tags: + * - Articles + * summary: The list of published articles + * produces: + * - application/json + * responses: + * 200: + * description: List of published articles + * schema: + * type: array + * items: + * $ref: '#/definitions/ArticleDTO' + */ + router.get('/articles', findArticlesHandler); + router.post('/articles', createArticleHandler); + router.delete('/articles/:articleId', deleteArticleHandler); + router.patch('/articles/:articleId/publish', publishArticleHandler); + }); }; export { makeArticleController }; diff --git a/src/article/query/FindArticles.d.ts b/src/article/query/FindArticles.d.ts index d4839bf..269f43a 100644 --- a/src/article/query/FindArticles.d.ts +++ b/src/article/query/FindArticles.d.ts @@ -1,4 +1,4 @@ -import { PaginatedQuery, PaginatedQueryResult, QueryHandler, QueryResult, SortedPaginatedQuery } from '@/_lib/CQRS'; +import { PaginatedQueryResult, QueryHandler, SortedPaginatedQuery } from '@/_lib/CQRS'; type ArticleListItemDTO = Readonly<{ id: string; diff --git a/src/comment/interface/http/commentController/CreateCommentHandler.ts b/src/comment/interface/http/commentController/CreateCommentHandler.ts index be565f4..72a133c 100644 --- a/src/comment/interface/http/commentController/CreateCommentHandler.ts +++ b/src/comment/interface/http/commentController/CreateCommentHandler.ts @@ -22,7 +22,7 @@ const createCommentHandler = handler(({ createComment }: Dependencies) => async const id = await createComment({ body, articleId }); - res.json({ id }); + res.send({ id }); }); export { createCommentHandler }; diff --git a/src/comment/interface/http/commentController/index.ts b/src/comment/interface/http/commentController/index.ts index a1ffd32..f8df3e5 100644 --- a/src/comment/interface/http/commentController/index.ts +++ b/src/comment/interface/http/commentController/index.ts @@ -1,16 +1,14 @@ import { createCommentHandler } from '@/comment/interface/http/commentController/CreateCommentHandler'; -import { Router } from 'express'; +import { ApiRouter } from '@/_lib/http/apiRouter'; type Dependencies = { - apiRouter: Router; + apiRouter: ApiRouter; }; -const makeCommentController = ({ apiRouter }: Dependencies) => { - const router = Router(); - - router.post('/articles/:articleId/comments', createCommentHandler); - - apiRouter.use(router); +const makeCommentController = ({ apiRouter }: Dependencies): void => { + apiRouter((router) => { + router.post('/articles/:articleId/comments', createCommentHandler); + }); }; export { makeCommentController }; diff --git a/typings.d.ts b/typings.d.ts index d4f5ad7..82a7bdc 100644 --- a/typings.d.ts +++ b/typings.d.ts @@ -1,7 +1,6 @@ -declare namespace Express { - export interface Request { +declare module 'http' { + export interface IncomingMessage { id: string; - container: import("@/container").Container; - accessToken: any; + container: import('@/container').Container; } } diff --git a/yarn.lock b/yarn.lock index 9184130..dadb7d2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -356,6 +356,13 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@fastify/ajv-compiler@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@fastify/ajv-compiler/-/ajv-compiler-1.1.0.tgz#5ce80b1fc8bebffc8c5ba428d5e392d0f9ed10a1" + integrity sha512-gvCOUNpXsWrIQ3A4aXCLIdblL0tDq42BG/2Xw7oxbil9h11uow10ztS2GuFazNBfjbrsZ5nl+nPl5jDSjj5TSg== + dependencies: + ajv "^6.12.6" + "@hapi/bourne@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-2.0.0.tgz#5bb2193eb685c0007540ca61d166d4e1edaf918d" @@ -698,14 +705,6 @@ dependencies: "@babel/types" "^7.3.0" -"@types/body-parser@*": - version "1.19.1" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.1.tgz#0c0174c42a7d017b818303d4b5d969cb0b75929c" - integrity sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg== - dependencies: - "@types/connect" "*" - "@types/node" "*" - "@types/bson@*": version "4.0.4" resolved "https://registry.yarnpkg.com/@types/bson/-/bson-4.0.4.tgz#79d2d26e81070044db2a1a8b2cc2f673c840e1e5" @@ -713,37 +712,11 @@ dependencies: "@types/node" "*" -"@types/connect@*": - version "3.4.35" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" - integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== - dependencies: - "@types/node" "*" - "@types/cookiejar@*": version "2.1.2" resolved "https://registry.yarnpkg.com/@types/cookiejar/-/cookiejar-2.1.2.tgz#66ad9331f63fe8a3d3d9d8c6e3906dd10f6446e8" integrity sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog== -"@types/express-serve-static-core@^4.17.18": - version "4.17.24" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz#ea41f93bf7e0d59cd5a76665068ed6aab6815c07" - integrity sha512-3UJuW+Qxhzwjq3xhwXm2onQcFHn76frIYVbTu+kn24LFxI+dEhdfISDFovPB8VpEgW8oQCTpRuCe+0zJxB7NEA== - dependencies: - "@types/node" "*" - "@types/qs" "*" - "@types/range-parser" "*" - -"@types/express@*", "@types/express@^4.17.13": - version "4.17.13" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" - integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== - dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.18" - "@types/qs" "*" - "@types/serve-static" "*" - "@types/graceful-fs@^4.1.2": version "4.1.5" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" @@ -800,11 +773,6 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.172.tgz#aad774c28e7bfd7a67de25408e03ee5a8c3d028a" integrity sha512-/BHF5HAx3em7/KkzVKm3LrsD6HZAXuXO1AJZQ3cRRBZj4oHZDviWPYu0aEplAqDFNHZPW6d3G7KN+ONcCCC7pw== -"@types/mime@^1": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" - integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== - "@types/mongodb@^3.6.20": version "3.6.20" resolved "https://registry.yarnpkg.com/@types/mongodb/-/mongodb-3.6.20.tgz#b7c5c580644f6364002b649af1c06c3c0454e1d2" @@ -847,24 +815,6 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.3.2.tgz#fc8c2825e4ed2142473b4a81064e6e081463d1b3" integrity sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog== -"@types/qs@*": - version "6.9.7" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" - integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== - -"@types/range-parser@*": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" - integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== - -"@types/serve-static@*": - version "1.13.10" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" - integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ== - dependencies: - "@types/mime" "^1" - "@types/node" "*" - "@types/stack-utils@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" @@ -900,14 +850,6 @@ resolved "https://registry.yarnpkg.com/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.1.tgz#94a99aca0356cb64ad2a6eb903ed034703453801" integrity sha512-+MUpcbyxD528dECUBCEVm6abNuORdbuGjbrUdHDeAQ+rkPuo2a+L4N02WJHF3bonSSE6SJ3dUJwF2V6+cHnf0w== -"@types/swagger-ui-express@^4.1.3": - version "4.1.3" - resolved "https://registry.yarnpkg.com/@types/swagger-ui-express/-/swagger-ui-express-4.1.3.tgz#7adbbbf5343b45869debef1e9ff39c9ba73e380f" - integrity sha512-jqCjGU/tGEaqIplPy3WyQg+Nrp6y80DCFnDEAvVKWkJyv0VivSSDCChkppHRHAablvInZe6pijDFMnavtN0vqA== - dependencies: - "@types/express" "*" - "@types/serve-static" "*" - "@types/yargs-parser@*": version "20.2.1" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129" @@ -1001,13 +943,10 @@ abab@^2.0.3, abab@^2.0.5: resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== -accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== - dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" +abstract-logging@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839" + integrity sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA== acorn-globals@^6.0.0: version "6.0.0" @@ -1044,7 +983,7 @@ agent-base@6: dependencies: debug "4" -ajv@^6.10.0, ajv@^6.12.4: +ajv@^6.10.0, ajv@^6.11.0, ajv@^6.12.4, ajv@^6.12.6: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -1064,6 +1003,16 @@ ajv@^8.0.1: require-from-string "^2.0.2" uri-js "^4.2.2" +ajv@^8.1.0: + version "8.6.3" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.6.3.tgz#11a66527761dc3e9a3845ea775d2d3c0414e8764" + integrity sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + ansi-colors@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" @@ -1108,6 +1057,11 @@ anymatch@^3.0.3, anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +archy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= + arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" @@ -1135,11 +1089,6 @@ args@^5.0.1: leven "2.1.0" mri "1.1.4" -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" @@ -1160,6 +1109,16 @@ atomic-sleep@^1.0.0: resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== +avvio@^7.1.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/avvio/-/avvio-7.2.2.tgz#58e00e7968870026cd7b7d4f689d596db629e251" + integrity sha512-XW2CMCmZaCmCCsIaJaLKxAzPwF37fXi1KGxNOvedOpeisLdmxZnblGc3hpHWYnlP+KOUxZsazh43WXNHgXpbqw== + dependencies: + archy "^1.0.0" + debug "^4.0.0" + fastq "^1.6.1" + queue-microtask "^1.1.2" + awilix@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/awilix/-/awilix-4.3.4.tgz#aeecc662efa96256981af3bc6243eb201c8b4a4f" @@ -1244,22 +1203,6 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -body-parser@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== - dependencies: - bytes "3.1.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -1325,11 +1268,6 @@ buffer@^5.6.0: base64-js "^1.3.1" ieee754 "^1.1.13" -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== - call-bind@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -1498,18 +1436,13 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -content-disposition@0.5.3: +content-disposition@^0.5.3: version "0.5.3" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== dependencies: safe-buffer "5.1.2" -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.8.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" @@ -1517,15 +1450,10 @@ convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: dependencies: safe-buffer "~5.1.1" -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== +cookie@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" + integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== cookiejar@^2.1.2: version "2.1.2" @@ -1584,7 +1512,7 @@ debug@2.6.9: dependencies: ms "2.0.0" -debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: +debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: version "4.3.2" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== @@ -1709,6 +1637,11 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= +encoding-negotiator@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/encoding-negotiator/-/encoding-negotiator-2.0.1.tgz#79871bb5473b81f6a0670e8de5303fb5ee0868a3" + integrity sha512-GSK7qphNR4iPcejfAlZxKDoz3xMhnspwImK+Af5WhePS9jUpK/Oh7rUdyENWu+9rgDflOCTmAojBsgsvM8neAQ== + end-of-stream@^1.1.0: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" @@ -1957,41 +1890,10 @@ expect@^27.0.6: jest-message-util "^27.0.6" jest-regex-util "^27.0.6" -express@^4.17.1: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== - dependencies: - accepts "~1.3.7" - array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" - content-type "~1.0.4" - cookie "0.4.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" - range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" +fast-decode-uri-component@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543" + integrity sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg== fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" @@ -2019,6 +1921,16 @@ fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +fast-json-stringify@^2.5.2: + version "2.7.10" + resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-2.7.10.tgz#7afcdf2e8bfeee9d361b38781deadae8e154e8b0" + integrity sha512-MPuVXMMueV8e3TRVLOpxxicJnSdu5mwbHrsO9IZU15zqfay6k19OqIv7N2DCeNPDOCNOmZwjvMUTwvblZsUmFw== + dependencies: + ajv "^6.11.0" + deepmerge "^4.2.2" + rfdc "^1.2.0" + string-similarity "^4.0.1" + fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" @@ -2041,6 +1953,67 @@ fast-url-parser@^1.1.3: dependencies: punycode "^1.3.2" +fastify-error@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/fastify-error/-/fastify-error-0.3.1.tgz#8eb993e15e3cf57f0357fc452af9290f1c1278d2" + integrity sha512-oCfpcsDndgnDVgiI7bwFKAun2dO+4h84vBlkWsWnz/OUK9Reff5UFoFl241xTiLeHWX/vU9zkDVXqYUxjOwHcQ== + +fastify-plugin@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-3.0.0.tgz#cf1b8c8098e3b5a7c8c30e6aeb06903370c054ca" + integrity sha512-ZdCvKEEd92DNLps5n0v231Bha8bkz1DjnPP/aEz37rz/q42Z5JVLmgnqR4DYuNn3NXAO3IDCPyRvgvxtJ4Ym4w== + +fastify-static@^4.0.0: + version "4.4.2" + resolved "https://registry.yarnpkg.com/fastify-static/-/fastify-static-4.4.2.tgz#ff00437d6f8197170365b53b4bab4dbd01777920" + integrity sha512-qgMR7VZjZjo8iRs3Ea4YuStEii2MkgKVQDz3JFfd73i+rbgKHEsPaJcWAX2O/oHC6EI9vqOuSA6ziTYsuf79fQ== + dependencies: + content-disposition "^0.5.3" + encoding-negotiator "^2.0.1" + fastify-plugin "^3.0.0" + glob "^7.1.4" + p-limit "^3.1.0" + readable-stream "^3.4.0" + send "^0.17.1" + +fastify-swagger@^4.12.4: + version "4.12.4" + resolved "https://registry.yarnpkg.com/fastify-swagger/-/fastify-swagger-4.12.4.tgz#d7a53890f83b4fac5863709d44fb8937e1ccab29" + integrity sha512-M7sN9VDS0wt3w8A6RwZ06sMeUXKFwSSK8Q8u7BaGMqTZ1dE3cKUeIiQWToDWpb4eKjVK1xla3d4NgTtKB6jdAw== + dependencies: + fastify-plugin "^3.0.0" + fastify-static "^4.0.0" + js-yaml "^4.0.0" + json-schema-resolver "^1.3.0" + openapi-types "^9.1.0" + +fastify-warning@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/fastify-warning/-/fastify-warning-0.2.0.tgz#e717776026a4493dc9a2befa44db6d17f618008f" + integrity sha512-s1EQguBw/9qtc1p/WTY4eq9WMRIACkj+HTcOIK1in4MV5aFaQC9ZCIt0dJ7pr5bIf4lPpHvAtP2ywpTNgs7hqw== + +fastify@^3.22.0: + version "3.22.0" + resolved "https://registry.yarnpkg.com/fastify/-/fastify-3.22.0.tgz#c8d265f0117762c0139fb0b567e815165e02a5e1" + integrity sha512-JWNf/S90SOiOp6SwhMFdTT43+jT/gB2Yi2tPHQ/e7Kaua9PzFLm7Qmwhe2jBA3X6HPDKNugrRd7oPYeIb1Q3Zg== + dependencies: + "@fastify/ajv-compiler" "^1.0.0" + abstract-logging "^2.0.0" + avvio "^7.1.2" + fast-json-stringify "^2.5.2" + fastify-error "^0.3.0" + fastify-warning "^0.2.0" + find-my-way "^4.1.0" + flatstr "^1.0.12" + light-my-request "^4.2.0" + pino "^6.13.0" + proxy-addr "^2.0.7" + readable-stream "^3.4.0" + rfdc "^1.1.4" + secure-json-parse "^2.0.0" + semver "^7.3.2" + tiny-lru "^7.0.0" + fastq@^1.6.0: version "1.11.1" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.1.tgz#5d8175aae17db61947f8b162cfc7f63264d22807" @@ -2048,6 +2021,13 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +fastq@^1.6.1: + version "1.13.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" + integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + dependencies: + reusify "^1.0.4" + fb-watchman@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" @@ -2069,18 +2049,15 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== +find-my-way@^4.1.0: + version "4.3.3" + resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-4.3.3.tgz#2ab3880a03bcaa8594548d66b0cd1c5a6e98dd44" + integrity sha512-5E4bRdaATB1MewjOCBjx4xvD205a4t2ripCnXB+YFhYEJ0NABtrcC7XLXLq0TPoFe/WYGUFqys3Qk3HCOGeNcw== dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" + fast-decode-uri-component "^1.0.1" + fast-deep-equal "^3.1.3" + safe-regex2 "^2.0.0" + semver-store "^0.3.0" find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" @@ -2275,17 +2252,6 @@ html-escaper@^2.0.0: resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - http-errors@~1.7.2: version "1.7.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" @@ -2375,11 +2341,6 @@ inherits@2, inherits@2.0.4, inherits@^2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" @@ -2952,7 +2913,7 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^4.1.0: +js-yaml@^4.0.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== @@ -2997,6 +2958,15 @@ jsesc@^2.5.1: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +json-schema-resolver@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/json-schema-resolver/-/json-schema-resolver-1.3.0.tgz#0840864b06780363d31fb03cdfae5047e2f81fbb" + integrity sha512-EX7W1r8aZ/T3j8GbbBxPXi60bnsELfT90OiA1QrbGMvwzVSbyMNOAzvMFcFb8m7gKCXZLJpGe+cJOvWgoFl29A== + dependencies: + debug "^4.1.1" + rfdc "^1.1.4" + uri-js "^4.2.2" + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -3050,6 +3020,17 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +light-my-request@^4.2.0: + version "4.4.4" + resolved "https://registry.yarnpkg.com/light-my-request/-/light-my-request-4.4.4.tgz#051e0d440a7bdaea31bcbe6b480a67a8df77c203" + integrity sha512-nxYLB+Lke3wGQ55HQIo/CjSS18xGyHRF0y/u7YxEwp1YsqQTxObteBXYHZY3ELSvYmqy0pRLTWbI5//zRYTXlg== + dependencies: + ajv "^8.1.0" + cookie "^0.4.0" + fastify-warning "^0.2.0" + readable-stream "^3.6.0" + set-cookie-parser "^2.4.1" + locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -3145,21 +3126,11 @@ makeerror@1.0.x: dependencies: tmpl "1.0.x" -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - memory-pager@^1.0.2: version "1.5.0" resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5" integrity sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg== -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -3170,7 +3141,7 @@ merge2@^1.3.0: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -methods@^1.1.2, methods@~1.1.2: +methods@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= @@ -3183,12 +3154,21 @@ micromatch@^4.0.4: braces "^3.0.1" picomatch "^2.2.3" +middie@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/middie/-/middie-5.3.0.tgz#6c871b3efecdb65f86c67a7787336d39b03d626d" + integrity sha512-uq6Ob4dmmHeT6rJpBDWVwSxBzxzKlBvnrZdLSRJeuhHzljvZ6ccgLP/HaShgfiYrQvekRH0KUe/G1WTu/IrXsQ== + dependencies: + fastify-plugin "^3.0.0" + path-to-regexp "^6.1.0" + reusify "^1.0.4" + mime-db@1.48.0: version "1.48.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.48.0.tgz#e35b31045dd7eada3aaad537ed88a33afbef2d1d" integrity sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ== -mime-types@^2.1.12, mime-types@~2.1.24: +mime-types@^2.1.12: version "2.1.31" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.31.tgz#a00d76b74317c61f9c2db2218b8e9f8e9c5c9e6b" integrity sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg== @@ -3270,11 +3250,6 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - no-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" @@ -3341,6 +3316,11 @@ onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" +openapi-types@^9.1.0: + version "9.3.0" + resolved "https://registry.yarnpkg.com/openapi-types/-/openapi-types-9.3.0.tgz#2d90549edb928cf06cf83018485a1a5961fbd2b9" + integrity sha512-sR23YjmuwDSMsQVZDHbV9mPgi0RyniQlqR0AQxTC2/F3cpSjRFMH3CFPjoWvNqhC4OxPkDYNb2l8Mc1Me6D/KQ== + optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -3377,6 +3357,13 @@ p-limit@^2.2.0: dependencies: p-try "^2.0.0" +p-limit@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + p-locate@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" @@ -3401,11 +3388,6 @@ parse5@6.0.1: resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== -parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - pascal-case@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" @@ -3434,10 +3416,10 @@ path-parse@^1.0.6: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= +path-to-regexp@^6.1.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.0.tgz#f7b3803336104c346889adece614669230645f38" + integrity sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg== path-type@^4.0.0: version "4.0.0" @@ -3498,6 +3480,19 @@ pino@^6.0.0, pino@^6.12.0: quick-format-unescaped "^4.0.3" sonic-boom "^1.0.2" +pino@^6.13.0: + version "6.13.3" + resolved "https://registry.yarnpkg.com/pino/-/pino-6.13.3.tgz#60b93bcda1541f92fb37b3f2be0a25cf1d05b6fe" + integrity sha512-tJy6qVgkh9MwNgqX1/oYi3ehfl2Y9H0uHyEEMsBe74KinESIjdMrMQDWpcZPpPicg3VV35d/GLQZmo4QgU2Xkg== + dependencies: + fast-redact "^3.0.0" + fast-safe-stringify "^2.0.8" + fastify-warning "^0.2.0" + flatstr "^1.0.12" + pino-std-serializers "^3.1.0" + quick-format-unescaped "^4.0.3" + sonic-boom "^1.0.2" + pirates@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" @@ -3567,7 +3562,7 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" -proxy-addr@~2.0.5: +proxy-addr@^2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== @@ -3598,11 +3593,6 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== - qs@^6.9.4: version "6.10.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.1.tgz#4931482fa8d647a5aab799c5271d2133b981fb6a" @@ -3610,7 +3600,7 @@ qs@^6.9.4: dependencies: side-channel "^1.0.4" -queue-microtask@^1.2.2: +queue-microtask@^1.1.2, queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== @@ -3625,22 +3615,12 @@ range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== - dependencies: - bytes "3.1.0" - http-errors "1.7.2" - iconv-lite "0.4.24" - unpipe "1.0.0" - react-is@^17.0.1: version "17.0.2" resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== -readable-stream@^3.0.0, readable-stream@^3.6.0: +readable-stream@^3.0.0, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -3696,12 +3676,17 @@ resolve@^1.0.0, resolve@^1.10.1, resolve@^1.20.0: is-core-module "^2.2.0" path-parse "^1.0.6" +ret@~0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.2.2.tgz#b6861782a1f4762dce43402a71eb7a283f44573c" + integrity sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rfdc@^1.3.0: +rfdc@^1.1.4, rfdc@^1.2.0, rfdc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== @@ -3737,6 +3722,13 @@ safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-regex2@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/safe-regex2/-/safe-regex2-2.0.0.tgz#b287524c397c7a2994470367e0185e1916b1f5b9" + integrity sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ== + dependencies: + ret "~0.2.0" + "safer-buffer@>= 2.1.2 < 3": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -3756,6 +3748,16 @@ saxes@^5.0.1: dependencies: xmlchars "^2.2.0" +secure-json-parse@^2.0.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.4.0.tgz#5aaeaaef85c7a417f76271a4f5b0cc3315ddca85" + integrity sha512-Q5Z/97nbON5t/L/sH6mY2EacfjVGwrCcSi5D3btRO2GZ8pf1K1UN7Z9H5J57hjVU2Qzxr1xO+FmBhOvEkzCMmg== + +semver-store@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/semver-store/-/semver-store-0.3.0.tgz#ce602ff07df37080ec9f4fb40b29576547befbe9" + integrity sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg== + semver@7.x, semver@^7.2.1, semver@^7.3.2, semver@^7.3.5: version "7.3.5" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" @@ -3768,7 +3770,7 @@ semver@^6.0.0, semver@^6.1.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -send@0.17.1: +send@^0.17.1: version "0.17.1" resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== @@ -3787,15 +3789,10 @@ send@0.17.1: range-parser "~1.2.1" statuses "~1.5.0" -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.1" +set-cookie-parser@^2.4.1: + version "2.4.8" + resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz#d0da0ed388bc8f24e706a391f9c9e252a13c58b2" + integrity sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg== setprototypeof@1.1.1: version "1.1.1" @@ -3924,6 +3921,11 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" +string-similarity@^4.0.1: + version "4.0.4" + resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b" + integrity sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ== + string-width@^4.1.0, string-width@^4.2.0: version "4.2.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" @@ -4045,18 +4047,6 @@ swagger-parser@10.0.2: dependencies: "@apidevtools/swagger-parser" "10.0.2" -swagger-ui-dist@^3.18.1: - version "3.52.0" - resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-3.52.0.tgz#cb16ec6dcdf134ff47cbfe57cba7be7748429142" - integrity sha512-SGfhW8FCih00QG59PphdeAUtTNw7HS5k3iPqDZowerPw9mcbhKchUb12kbROk99c1X6RTWW1gB1kqgfnYGuCSg== - -swagger-ui-express@^4.1.6: - version "4.1.6" - resolved "https://registry.yarnpkg.com/swagger-ui-express/-/swagger-ui-express-4.1.6.tgz#682294af3d5c70f74a1fa4d6a9b503a9ee55ea82" - integrity sha512-Xs2BGGudvDBtL7RXcYtNvHsFtP1DBFPMJFRxHe5ez/VG/rzVOEjazJOOSc/kSCyxreCTKfJrII6MJlL9a6t8vw== - dependencies: - swagger-ui-dist "^3.18.1" - symbol-tree@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" @@ -4101,6 +4091,11 @@ throat@^6.0.1: resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375" integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w== +tiny-lru@^7.0.0: + version "7.0.6" + resolved "https://registry.yarnpkg.com/tiny-lru/-/tiny-lru-7.0.6.tgz#b0c3cdede1e5882aa2d1ae21cb2ceccf2a331f24" + integrity sha512-zNYO0Kvgn5rXzWpL0y3RS09sMK67eGaQj9805jlK9G6pSadfriTczzLHFXa/xcW4mIRfmlB9HyQ/+SgL0V1uow== + tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" @@ -4272,14 +4267,6 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== -type-is@~1.6.17, type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -4302,11 +4289,6 @@ universalify@^0.1.2: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -4319,11 +4301,6 @@ util-deprecate@^1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - uuid-mongodb@^2.4.4: version "2.4.4" resolved "https://registry.yarnpkg.com/uuid-mongodb/-/uuid-mongodb-2.4.4.tgz#c1ec4c30f52d6da9042297c4932fc3c148247516" @@ -4355,11 +4332,6 @@ validator@^13.6.0: resolved "https://registry.yarnpkg.com/validator/-/validator-13.6.0.tgz#1e71899c14cdc7b2068463cb24c1cc16f6ec7059" integrity sha512-gVgKbdbHgtxpRyR8K0O6oFZPhhB5tT1jeEHZR0Znr9Svg03U0+r9DXWMrnRAB+HtCStDQKlaIZm42tVsVjqtjg== -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - w3c-hr-time@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" @@ -4506,6 +4478,11 @@ yn@3.1.1: resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + z-schema@^4.2.3: version "4.2.4" resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-4.2.4.tgz#73102a49512179b12a8ec50b1daa676b984da6e4"