diff --git a/.gitignore b/.gitignore index a75d7f33..0f330719 100644 --- a/.gitignore +++ b/.gitignore @@ -32,7 +32,8 @@ yarn-error.log* .vercel # database -db/db.sqlite3 +config/db/db.sqlite3 +config/settings.json # dist files -dist \ No newline at end of file +dist diff --git a/db/.gitkeep b/config/.gitkeep similarity index 100% rename from db/.gitkeep rename to config/.gitkeep diff --git a/config/db/.gitkeep b/config/db/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/ormconfig.js b/ormconfig.js index 75883d12..96d7611d 100644 --- a/ormconfig.js +++ b/ormconfig.js @@ -1,6 +1,6 @@ const devConfig = { type: 'sqlite', - database: 'db/db.sqlite3', + database: 'config/db/db.sqlite3', synchronize: true, logging: true, entities: ['server/entity/**/*.ts'], @@ -13,7 +13,7 @@ const devConfig = { const prodConfig = { type: 'sqlite', - database: 'db/db.sqlite3', + database: 'config/db/db.sqlite3', synchronize: false, logging: false, entities: ['dist/server/entity/**/*.js'], diff --git a/package.json b/package.json index 43cc5a52..05cc022d 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "nodemon -e ts --watch server -x ts-node --project server/tsconfig.json server/index.ts", + "dev": "nodemon -e ts --watch server -e .json,.ts,.yml -x ts-node --files --project server/tsconfig.json server/index.ts", "build:server": "tsc --project server/tsconfig.json", "build:next": "next build", "build": "yarn build:next && yarn build:server", @@ -18,6 +18,7 @@ "connect-typeorm": "^1.1.4", "cookie-parser": "^1.4.5", "express": "^4.17.1", + "express-openapi-validator": "^3.16.11", "express-session": "^1.17.1", "next": "9.5.3", "react": "16.13.1", @@ -25,7 +26,9 @@ "react-transition-group": "^4.4.1", "reflect-metadata": "^0.1.13", "sqlite3": "^5.0.0", - "typeorm": "^0.2.25" + "swagger-ui-express": "^4.1.4", + "typeorm": "^0.2.25", + "yamljs": "^0.3.0" }, "devDependencies": { "@commitlint/cli": "^9.1.2", @@ -38,6 +41,8 @@ "@types/react": "^16.9.49", "@types/react-transition-group": "^4.4.0", "@typescript-eslint/eslint-plugin": "^4.0.0", + "@types/swagger-ui-express": "^4.1.2", + "@types/yamljs": "^0.2.31", "@typescript-eslint/parser": "^3.10.1", "commitizen": "^4.2.1", "cz-conventional-changelog": "^3.3.0", diff --git a/server/entity/User.ts b/server/entity/User.ts index a91122bc..911af457 100644 --- a/server/entity/User.ts +++ b/server/entity/User.ts @@ -8,6 +8,10 @@ import { @Entity() export class User { + public static filterMany(users: User[]): Partial[] { + return users.map((u) => u.filter()); + } + @PrimaryGeneratedColumn() public id: number; @@ -15,7 +19,7 @@ export class User { public email: string; @Column({ nullable: true }) - public plexToken: string; + public plexToken?: string; @CreateDateColumn() public createdAt: Date; @@ -26,4 +30,13 @@ export class User { constructor(init?: Partial) { Object.assign(this, init); } + + public filter(): Partial { + return { + id: this.id, + email: this.email, + createdAt: this.createdAt, + updatedAt: this.updatedAt, + }; + } } diff --git a/server/index.ts b/server/index.ts index 6f59a812..317bc56a 100644 --- a/server/index.ts +++ b/server/index.ts @@ -1,12 +1,19 @@ -import express from 'express'; +import express, { Request, Response, NextFunction } from 'express'; import next from 'next'; +import path from 'path'; import { createConnection, getRepository } from 'typeorm'; import routes from './routes'; import bodyParser from 'body-parser'; import cookieParser from 'cookie-parser'; import session from 'express-session'; import { TypeormStore } from 'connect-typeorm/out'; +import YAML from 'yamljs'; +import swaggerUi from 'swagger-ui-express'; +import { OpenApiValidator } from 'express-openapi-validator'; import { Session } from './entity/Session'; +import { getSettings } from './lib/settings'; + +const API_SPEC_PATH = path.join(__dirname, 'overseerr-api.yml'); const dev = process.env.NODE_ENV !== 'production'; const app = next({ dev }); @@ -16,7 +23,10 @@ createConnection(); app .prepare() - .then(() => { + .then(async () => { + // Load Settings + getSettings().load(); + const server = express(); server.use(cookieParser()); server.use(bodyParser.json()); @@ -35,8 +45,41 @@ app }).connect(sessionRespository), }) ); - server.use('/api', routes); + const apiDocs = YAML.load(API_SPEC_PATH); + server.use('/api-docs', swaggerUi.serve, swaggerUi.setup(apiDocs)); + await new OpenApiValidator({ + apiSpec: API_SPEC_PATH, + validateRequests: true, + validateResponses: true, + }).install(server); + /** + * This is a workaround to convert dates to strings before they are validated by + * OpenAPI validator. Otherwise, they are treated as objects instead of strings + * and response validation will fail + */ + server.use((req, res, next) => { + const original = res.json; + res.json = function jsonp(json) { + return original.call(this, JSON.parse(JSON.stringify(json))); + }; + next(); + }); + server.use('/api/v1', routes); server.get('*', (req, res) => handle(req, res)); + server.use( + ( + err: { status: number; message: string; errors: string[] }, + req: Request, + res: Response, + _next: NextFunction + ) => { + // format error + res.status(err.status || 500).json({ + message: err.message, + errors: err.errors, + }); + } + ); const port = Number(process.env.PORT) || 3000; server.listen(port, (err) => { diff --git a/server/lib/settings.ts b/server/lib/settings.ts new file mode 100644 index 00000000..55b6cbd0 --- /dev/null +++ b/server/lib/settings.ts @@ -0,0 +1,149 @@ +import fs from 'fs'; +import path from 'path'; + +interface Library { + id: string; + name: string; + enabled: boolean; +} + +interface PlexSettings { + name: string; + machineId: string; + ip: string; + port: number; + libraries: Library[]; +} + +interface DVRSettings { + id: number; + name: string; + hostname: string; + port: number; + apiKey: string; + useSsl: boolean; + baseUrl?: string; + activeProfile: string; + activeDirectory: string; + is4k: boolean; +} + +export interface RadarrSettings extends DVRSettings { + minimumAvailability: string; +} + +export interface SonarrSettings extends DVRSettings { + activeAnimeProfile?: string; + activeAnimeDirectory?: string; + enableSeasonFolders: boolean; +} + +interface MainSettings { + apiKey: string; +} + +interface AllSettings { + main: MainSettings; + plex: PlexSettings; + radarr: RadarrSettings[]; + sonarr: SonarrSettings[]; +} + +const SETTINGS_PATH = path.join(__dirname, '../../config/settings.json'); + +class Settings { + private data: AllSettings; + + constructor(initialSettings?: AllSettings) { + this.data = { + main: { + apiKey: 'temp', + }, + plex: { + name: 'Main Server', + ip: '127.0.0.1', + port: 32400, + machineId: '', + libraries: [], + }, + radarr: [], + sonarr: [], + }; + if (initialSettings) { + Object.assign(this.data, initialSettings); + } + } + + get main(): MainSettings { + return this.data.main; + } + + set main(data: MainSettings) { + this.data.main = data; + } + + get plex(): PlexSettings { + return this.data.plex; + } + + set plex(data: PlexSettings) { + this.data.plex = data; + } + + get radarr(): RadarrSettings[] { + return this.data.radarr; + } + + set radarr(data: RadarrSettings[]) { + this.data.radarr = data; + } + + get sonarr(): SonarrSettings[] { + return this.data.sonarr; + } + + set sonarr(data: SonarrSettings[]) { + this.data.sonarr = data; + } + + /** + * Settings Load + * + * This will load settings from file unless an optional argument of the object structure + * is passed in. + * @param overrideSettings If passed in, will override all existing settings with these + * values + */ + public load(overrideSettings?: AllSettings): AllSettings { + if (overrideSettings) { + this.data = overrideSettings; + return this.data; + } + + if (!fs.existsSync(SETTINGS_PATH)) { + this.save(); + } + const data = fs.readFileSync(SETTINGS_PATH, 'utf-8'); + + if (data) { + this.data = JSON.parse(data); + } + return this.data; + } + + public save(): void { + fs.writeFileSync(SETTINGS_PATH, JSON.stringify(this.data, undefined, ' ')); + } +} + +let settings: Settings | undefined; + +export const getSettings = (initialSettings?: AllSettings): Settings => { + if (!settings) { + settings = new Settings(initialSettings); + } + + return settings; +}; + +export default Settings; diff --git a/server/middleware/auth.ts b/server/middleware/auth.ts index 6330721c..a0a625ea 100644 --- a/server/middleware/auth.ts +++ b/server/middleware/auth.ts @@ -1,6 +1,5 @@ import { getRepository } from 'typeorm'; import { User } from '../entity/User'; -import { Middleware } from '../types/express'; export const checkUser: Middleware = async (req, _res, next) => { if (req.session?.userId) { diff --git a/server/overseerr-api.yml b/server/overseerr-api.yml new file mode 100644 index 00000000..e0d0b6b6 --- /dev/null +++ b/server/overseerr-api.yml @@ -0,0 +1,482 @@ +openapi: '3.0.2' +info: + title: 'Overseerr API' + version: '1.0.0' +servers: + - url: /api/v1 + +components: + schemas: + User: + type: object + properties: + id: + type: integer + example: 1 + email: + type: string + example: 'hey@itsme.com' + plexToken: + type: string + createdAt: + type: string + example: '2020-09-02T05:02:23.000Z' + updatedAt: + type: string + example: '2020-09-02T05:02:23.000Z' + required: + - id + - email + - createdAt + - updatedAt + MainSettings: + type: object + properties: + apiKey: + type: string + example: 'anapikey' + required: + - apiKey + PlexLibrary: + type: object + properties: + id: + type: string + name: + type: string + example: Movies + enabled: + type: boolean + example: false + required: + - id + - name + - enabled + PlexSettings: + type: object + properties: + name: + type: string + example: 'Main Server' + machineId: + type: string + example: '1234-1234-1234-1234' + ip: + type: string + example: '127.0.0.1' + port: + type: number + example: 32400 + libraries: + type: array + items: + $ref: '#/components/schemas/PlexLibrary' + required: + - name + - machineId + - ip + - port + RadarrSettings: + type: object + properties: + id: + type: number + example: 0 + readOnly: true + name: + type: string + example: 'Radarr Main' + hostname: + type: string + example: '127.0.0.1' + port: + type: number + example: 7878 + apiKey: + type: string + example: 'exampleapikey' + useSsl: + type: boolean + example: false + baseUrl: + type: string + activeProfile: + type: string + example: '1080p' + activeDirectory: + type: string + example: '/movies' + is4k: + type: boolean + example: false + minimumAvailability: + type: string + example: 'In Cinema' + required: + - name + - hostname + - port + - apiKey + - useSsl + - activeProfile + - activeDirectory + - is4k + - minimumAvailability + SonarrSettings: + type: object + properties: + id: + type: number + example: 0 + readOnly: true + name: + type: string + example: 'Sonarr Main' + hostname: + type: string + example: '127.0.0.1' + port: + type: number + example: 8989 + apiKey: + type: string + example: 'exampleapikey' + useSsl: + type: boolean + example: false + baseUrl: + type: string + activeProfile: + type: string + example: '1080p' + activeDirectory: + type: string + example: '/movies' + activeAnimeProfile: + type: string + nullable: true + activeAnimeDirectory: + type: string + nullable: true + is4k: + type: boolean + example: false + enableSeasonFolders: + type: boolean + example: false + required: + - name + - hostname + - port + - apiKey + - useSsl + - activeProfile + - activeDirectory + - is4k + - enableSeasonFolders + AllSettings: + type: object + properties: + main: + $ref: '#/components/schemas/MainSettings' + plex: + $ref: '#/components/schemas/PlexSettings' + radarr: + type: array + items: + $ref: '#/components/schemas/RadarrSettings' + sonarr: + type: array + items: + $ref: '#/components/schemas/SonarrSettings' + required: + - main + - plex + - radarr + - sonarr + + securitySchemes: + cookieAuth: + type: apiKey + name: connect.sid + in: cookie + +paths: + /settings/main: + get: + summary: Returns main settings + description: Retreives all main settings in JSON format + tags: + - settings + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/MainSettings' + post: + summary: Update main settings + description: Update current main settings with provided values + tags: + - settings + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/MainSettings' + responses: + '200': + description: 'Values were sucessfully updated' + content: + application/json: + schema: + $ref: '#/components/schemas/MainSettings' + /settings/plex: + get: + summary: Returns plex settings + description: Retrieves current Plex settings + tags: + - settings + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/PlexSettings' + post: + summary: Update plex settings + description: Update the current plex settings with provided values + tags: + - settings + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PlexSettings' + responses: + '200': + description: 'Values were successfully updated' + content: + application/json: + schema: + $ref: '#/components/schemas/PlexSettings' + /settings/radarr: + get: + summary: Get all radarr settings + description: Returns all radarr settings in a JSON array + tags: + - settings + responses: + '200': + description: 'Values were returned' + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/RadarrSettings' + post: + summary: Create new radarr instance + description: Creates a new radarr instance from the request body + tags: + - settings + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RadarrSettings' + responses: + '201': + description: 'New Radarr instance created' + content: + application/json: + schema: + $ref: '#/components/schemas/RadarrSettings' + /settings/radarr/{radarrId}: + put: + summary: Update existing radarr instance + description: Updates an existing radarr instance with values from request body + tags: + - settings + parameters: + - in: path + name: radarrId + required: true + schema: + type: integer + description: Radarr instance ID + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RadarrSettings' + responses: + '200': + description: 'Radarr instance updated' + content: + application/json: + schema: + $ref: '#/components/schemas/RadarrSettings' + delete: + summary: Delete existing radarr instance + description: Deletes an existing radarr instance based on id parameter + tags: + - settings + parameters: + - in: path + name: radarrId + required: true + schema: + type: integer + description: Radarr Instance ID + responses: + '200': + description: 'Radarr instance updated' + content: + application/json: + schema: + $ref: '#/components/schemas/RadarrSettings' + /settings/sonarr: + get: + summary: Get all sonarr settings + description: Returns all sonarr settings in a JSON array + tags: + - settings + responses: + '200': + description: 'Values were returned' + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/SonarrSettings' + post: + summary: Create new Sonarr instance + description: Creates a new Sonarr instance from the request body + tags: + - settings + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SonarrSettings' + responses: + '201': + description: 'New Sonarr instance created' + content: + application/json: + schema: + $ref: '#/components/schemas/SonarrSettings' + /settings/sonarr/{sonarrId}: + put: + summary: Update existing sonarr instance + description: Updates an existing sonarr instance with values from request body + tags: + - settings + parameters: + - in: path + name: sonarrId + required: true + schema: + type: integer + description: Sonarr instance ID + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SonarrSettings' + responses: + '200': + description: 'Sonarr instance updated' + content: + application/json: + schema: + $ref: '#/components/schemas/SonarrSettings' + delete: + summary: Delete existing sonarr instance + description: Deletes an existing sonarr instance based on id parameter + tags: + - settings + parameters: + - in: path + name: sonarrId + required: true + schema: + type: integer + description: Sonarr Instance ID + responses: + '200': + description: 'Sonarr instance updated' + content: + application/json: + schema: + $ref: '#/components/schemas/SonarrSettings' + /auth/me: + get: + summary: Returns the currently logged in user + description: Returns the currently logged in user + tags: + - auth + - users + responses: + '200': + description: Object containing the logged in user in JSON + content: + application/json: + schema: + $ref: '#/components/schemas/User' + /auth/login: + post: + summary: Login using a plex auth token + description: Takes an `authToken` (plex token) to log the user in. Generates a session cookie for use in further requests. If the user does not exist, and there are no other users, then a user will be created with full admin privileges. If a user logs in with access to the main plex server, they will also have an account created, but without any permissions. + security: [] + tags: + - auth + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + status: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + authToken: + type: string + required: + - authToken + + /user: + get: + summary: Returns a list of all users + description: Requests all users and returns them in a large array + tags: + - users + responses: + '200': + description: A JSON array of all users + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' +security: + - cookieAuth: [] diff --git a/server/routes/auth.ts b/server/routes/auth.ts index 1ab0ca14..ca428bbd 100644 --- a/server/routes/auth.ts +++ b/server/routes/auth.ts @@ -2,9 +2,26 @@ import { Router } from 'express'; import { getRepository } from 'typeorm'; import { User } from '../entity/User'; import PlexTvAPI from '../api/plextv'; +import { isAuthenticated } from '../middleware/auth'; const authRoutes = Router(); +authRoutes.get('/me', isAuthenticated, async (req, res) => { + const userRepository = getRepository(User); + if (!req.user) { + return res.status(500).json({ + status: 500, + error: + 'Requsted user endpoint withuot valid authenticated user in session', + }); + } + const user = await userRepository.findOneOrFail({ + where: { id: req.user.id }, + }); + + return res.status(200).json(user.filter()); +}); + authRoutes.post('/login', async (req, res) => { const userRepository = getRepository(User); const body = req.body as { authToken?: string }; diff --git a/server/routes/index.ts b/server/routes/index.ts index 50dedc42..19e5d063 100644 --- a/server/routes/index.ts +++ b/server/routes/index.ts @@ -2,11 +2,13 @@ import { Router } from 'express'; import user from './user'; import authRoutes from './auth'; import { checkUser, isAuthenticated } from '../middleware/auth'; +import settingsRoutes from './settings'; const router = Router(); router.use(checkUser); router.use('/user', isAuthenticated, user); +router.use('/settings', isAuthenticated, settingsRoutes); router.use('/auth', authRoutes); router.get('/', (req, res) => { @@ -16,8 +18,4 @@ router.get('/', (req, res) => { }); }); -router.all('*', (req, res) => - res.status(404).json({ status: 404, message: '404 Not Found' }) -); - export default router; diff --git a/server/routes/settings.ts b/server/routes/settings.ts new file mode 100644 index 00000000..6f885dab --- /dev/null +++ b/server/routes/settings.ts @@ -0,0 +1,156 @@ +import { Router } from 'express'; +import { getSettings, RadarrSettings, SonarrSettings } from '../lib/settings'; + +const settingsRoutes = Router(); + +settingsRoutes.get('/main', (_req, res) => { + const settings = getSettings(); + + res.status(200).json(settings.main); +}); + +settingsRoutes.post('/main', (req, res) => { + const settings = getSettings(); + + settings.main = req.body; + settings.save(); + + return res.status(200).json(settings.main); +}); + +settingsRoutes.get('/plex', (_req, res) => { + const settings = getSettings(); + + res.status(200).json(settings.plex); +}); + +settingsRoutes.post('/plex', (req, res) => { + const settings = getSettings(); + + settings.plex = req.body; + settings.save(); + + return res.status(200).json(settings.plex); +}); + +settingsRoutes.get('/radarr', (req, res) => { + const settings = getSettings(); + + res.status(200).json(settings.radarr); +}); + +settingsRoutes.post('/radarr', (req, res) => { + const settings = getSettings(); + + const newRadarr = req.body as RadarrSettings; + const lastItem = settings.radarr[settings.radarr.length - 1]; + newRadarr.id = lastItem ? lastItem.id + 1 : 0; + + settings.radarr = [...settings.radarr, newRadarr]; + settings.save(); + + return res.status(201).json(newRadarr); +}); + +settingsRoutes.put<{ id: string }>('/radarr/:id', (req, res) => { + const settings = getSettings(); + + const radarrIndex = settings.radarr.findIndex( + (r) => r.id === Number(req.params.id) + ); + + if (radarrIndex === -1) { + return res + .status(404) + .json({ status: '404', message: 'Settings instance not found' }); + } + + settings.radarr[radarrIndex] = { + ...req.body, + id: Number(req.params.id), + } as RadarrSettings; + settings.save(); + + return res.status(200).json(settings.radarr[radarrIndex]); +}); + +settingsRoutes.delete<{ id: string }>('/radarr/:id', (req, res) => { + const settings = getSettings(); + + const radarrIndex = settings.radarr.findIndex( + (r) => r.id === Number(req.params.id) + ); + + if (radarrIndex === -1) { + return res + .status(404) + .json({ status: '404', message: 'Settings instance not found' }); + } + + const removed = settings.radarr.splice(radarrIndex, 1); + settings.save(); + + return res.status(200).json(removed[0]); +}); + +settingsRoutes.get('/sonarr', (req, res) => { + const settings = getSettings(); + + res.status(200).json(settings.sonarr); +}); + +settingsRoutes.post('/sonarr', (req, res) => { + const settings = getSettings(); + + const newSonarr = req.body as SonarrSettings; + const lastItem = settings.sonarr[settings.sonarr.length - 1]; + newSonarr.id = lastItem ? lastItem.id + 1 : 0; + + settings.sonarr = [...settings.sonarr, newSonarr]; + settings.save(); + + return res.status(201).json(newSonarr); +}); + +settingsRoutes.put<{ id: string }>('/sonarr/:id', (req, res) => { + const settings = getSettings(); + + const sonarrIndex = settings.sonarr.findIndex( + (r) => r.id === Number(req.params.id) + ); + + if (sonarrIndex === -1) { + return res + .status(404) + .json({ status: '404', message: 'Settings instance not found' }); + } + + settings.sonarr[sonarrIndex] = { + ...req.body, + id: Number(req.params.id), + } as SonarrSettings; + settings.save(); + + return res.status(200).json(settings.sonarr[sonarrIndex]); +}); + +settingsRoutes.delete<{ id: string }>('/sonarr/:id', (req, res) => { + const settings = getSettings(); + + const sonarrIndex = settings.sonarr.findIndex( + (r) => r.id === Number(req.params.id) + ); + + if (sonarrIndex === -1) { + return res + .status(404) + .json({ status: '404', message: 'Settings instance not found' }); + } + + const removed = settings.sonarr.splice(sonarrIndex, 1); + settings.save(); + + return res.status(200).json(removed[0]); +}); + +export default settingsRoutes; diff --git a/server/routes/user.ts b/server/routes/user.ts index e108727e..1941eaea 100644 --- a/server/routes/user.ts +++ b/server/routes/user.ts @@ -9,7 +9,7 @@ router.get('/', async (req, res) => { const users = await userRepository.find(); - return res.status(200).json(users); + return res.status(200).json(User.filterMany(users)); }); export default router; diff --git a/server/tsconfig.json b/server/tsconfig.json index 4edf3b65..ac9f60f1 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -6,8 +6,7 @@ "noEmit": false, "strictPropertyInitialization": false, "experimentalDecorators": true, - "emitDecoratorMetadata": true, - "typeRoots": ["types"] + "emitDecoratorMetadata": true }, - "include": ["**/*.ts", "**/*.tsx"] + "include": ["**/*.ts"] } diff --git a/server/types/express.d.ts b/server/types/express.d.ts index 8b1487c1..61f30f0f 100644 --- a/server/types/express.d.ts +++ b/server/types/express.d.ts @@ -12,10 +12,10 @@ declare global { user?: User; } } -} -export type Middleware = ( - req: Request, - res: Response, - next: NextFunction -) => Promise | void | NextFunction; + export type Middleware = ( + req: Request, + res: Response, + next: NextFunction + ) => Promise | void | NextFunction; +} diff --git a/yarn.lock b/yarn.lock index 653ad497..4eee5b32 100644 --- a/yarn.lock +++ b/yarn.lock @@ -53,6 +53,15 @@ dependencies: cross-fetch "3.0.5" +"@apidevtools/json-schema-ref-parser@9.0.6": + version "9.0.6" + resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.6.tgz#5d9000a3ac1fd25404da886da6b266adcd99cf1c" + integrity sha512-M3YgsLjI0lZxvrpeGVk9Ap032W6TPQkH6pRAZz81Ac3WUNF79VQooAFnp8umjvVzUmD93NkogxEwbSce7qMsUg== + dependencies: + "@jsdevtools/ono" "^7.1.3" + call-me-maybe "^1.0.1" + js-yaml "^3.13.1" + "@babel/code-frame@7.10.4", "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.5.5": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" @@ -1198,6 +1207,11 @@ postcss "7.0.32" purgecss "^2.3.0" +"@jsdevtools/ono@7.1.3", "@jsdevtools/ono@^7.1.3": + version "7.1.3" + resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" + integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== + "@next/react-dev-overlay@9.5.3": version "9.5.3" resolved "https://registry.yarnpkg.com/@next/react-dev-overlay/-/react-dev-overlay-9.5.3.tgz#3275301f08045ecc709e3273031973a1f5e81427" @@ -1408,6 +1422,19 @@ "@types/express-serve-static-core" "*" "@types/mime" "*" +"@types/swagger-ui-express@^4.1.2": + version "4.1.2" + resolved "https://registry.yarnpkg.com/@types/swagger-ui-express/-/swagger-ui-express-4.1.2.tgz#cfc884904a104c3193f46f423d04ee0416be1ef4" + integrity sha512-t9teFTU8dKe69rX9EwL6OM2hbVquYdFM+sQ0REny4RalPlxAm+zyP04B12j4c7qEuDS6CnlwICywqWStPA3v4g== + dependencies: + "@types/express" "*" + "@types/serve-static" "*" + +"@types/yamljs@^0.2.31": + version "0.2.31" + resolved "https://registry.yarnpkg.com/@types/yamljs/-/yamljs-0.2.31.tgz#b1a620b115c96db7b3bfdf0cf54aee0c57139245" + integrity sha512-QcJ5ZczaXAqbVD3o8mw/mEBhRvO5UAdTtbvgwL/OgoWubvNBh6/MxLBAigtcgIFaq3shon9m3POIxQaLQt4fxQ== + "@typescript-eslint/eslint-plugin@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.0.0.tgz#99349a501447fed91de18346705c0c65cf603bee" @@ -1877,6 +1904,11 @@ app-root-path@^3.0.0: resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-3.0.0.tgz#210b6f43873227e18a4b810a032283311555d5ad" integrity sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw== +append-field@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56" + integrity sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY= + aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -2373,6 +2405,14 @@ builtin-status-codes@^3.0.0: resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= +busboy@^0.2.11: + version "0.2.14" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.14.tgz#6c2a622efcf47c57bbbe1e2a9c37ad36c7925453" + integrity sha1-bCpiLvz0fFe7vh4qnDetNseSVFM= + dependencies: + dicer "0.2.5" + readable-stream "1.1.x" + bytes@3.1.0, bytes@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" @@ -2456,6 +2496,11 @@ cachedir@2.2.0: resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.2.0.tgz#19afa4305e05d79e417566882e0c8f960f62ff0e" integrity sha512-VvxA0xhNqIIfg0V9AmJkDg91DaJwryutH5rVEZAhcNi4iJFj9f+QxmAjgK1LT9I8OgToX27fypX6/MeCXVbBjQ== +call-me-maybe@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" + integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -2844,7 +2889,7 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@^1.5.0: +concat-stream@^1.5.0, concat-stream@^1.5.2: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -2898,7 +2943,7 @@ content-disposition@0.5.3: dependencies: safe-buffer "5.1.2" -content-type@~1.0.4: +content-type@^1.0.4, 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== @@ -3276,6 +3321,14 @@ data-uri-to-buffer@3.0.0: dependencies: buffer-from "^1.1.1" +deasync@^0.1.20: + version "0.1.20" + resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.20.tgz#546fd2660688a1eeed55edce2308c5cf7104f9da" + integrity sha512-E1GI7jMI57hL30OX6Ht/hfQU8DO4AuB9m72WFm4c38GNbUD4Q03//XZaOIHZiY+H1xUaomcot5yk2q/qIZQkGQ== + dependencies: + bindings "^1.5.0" + node-addon-api "^1.7.1" + debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -3433,6 +3486,14 @@ detective@^5.2.0: defined "^1.0.0" minimist "^1.1.1" +dicer@0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.2.5.tgz#5996c086bb33218c812c090bddc09cd12facb70f" + integrity sha1-WZbAhrszIYyBLAkL3cCc0S+stw8= + dependencies: + readable-stream "1.1.x" + streamsearch "0.1.2" + diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -3958,6 +4019,25 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" +express-openapi-validator@^3.16.11: + version "3.16.11" + resolved "https://registry.yarnpkg.com/express-openapi-validator/-/express-openapi-validator-3.16.11.tgz#18be9f0a3b8b5684a12dfa606344c4f2734baba8" + integrity sha512-ZZuCcFhJWNl/bWxo42oOfhnJRYaqGuef4E2Drvj5rEuOJqXdbrUsBFKQFDswuk/v43qn2Ulner3HfZNGPjrI3Q== + dependencies: + ajv "^6.12.3" + content-type "^1.0.4" + js-yaml "^3.14.0" + json-schema-ref-parser "^9.0.6" + lodash.merge "^4.6.2" + lodash.uniq "^4.5.0" + lodash.zipobject "^4.1.3" + media-typer "^1.1.0" + multer "^1.4.2" + ono "^7.1.3" + path-to-regexp "^6.1.0" + optionalDependencies: + deasync "^0.1.20" + express-session@^1.15.6, express-session@^1.17.1: version "1.17.1" resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.17.1.tgz#36ecbc7034566d38c8509885c044d461c11bf357" @@ -4486,7 +4566,7 @@ glob@7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -5199,6 +5279,11 @@ is-yarn-global@^0.3.0: resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -5239,7 +5324,7 @@ jest-worker@24.9.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^3.13.1: +js-yaml@^3.13.1, js-yaml@^3.14.0: version "3.14.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== @@ -5272,6 +5357,13 @@ json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== +json-schema-ref-parser@^9.0.6: + version "9.0.6" + resolved "https://registry.yarnpkg.com/json-schema-ref-parser/-/json-schema-ref-parser-9.0.6.tgz#fc89a5e6b853f2abe8c0af30d3874196526adb60" + integrity sha512-z0JGv7rRD3CnJbZY/qCpscyArdtLJhr/wRBmFUdoZ8xMjsFyNdILSprG2degqRLjBjyhZHAEBpGOxniO9rKTxA== + dependencies: + "@apidevtools/json-schema-ref-parser" "9.0.6" + 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" @@ -5503,6 +5595,11 @@ lodash.map@^4.5.1: resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM= +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" @@ -5528,6 +5625,16 @@ lodash.toarray@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561" integrity sha1-JMS/zWsvuji/0FlNsRedjptlZWE= +lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= + +lodash.zipobject@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/lodash.zipobject/-/lodash.zipobject-4.1.3.tgz#b399f5aba8ff62a746f6979bf20b214f964dbef8" + integrity sha1-s5n1q6j/YqdG9peb8gshT5ZNvvg= + lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" @@ -5642,6 +5749,11 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= +media-typer@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-1.1.0.tgz#6ab74b8f2d3320f2064b2a87a38e7931ff3a5561" + integrity sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw== + memory-fs@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" @@ -5921,6 +6033,20 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +multer@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.2.tgz#2f1f4d12dbaeeba74cb37e623f234bf4d3d2057a" + integrity sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg== + dependencies: + append-field "^1.0.0" + busboy "^0.2.11" + concat-stream "^1.5.2" + mkdirp "^0.5.1" + object-assign "^4.1.1" + on-finished "^2.3.0" + type-is "^1.6.4" + xtend "^4.0.0" + mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" @@ -6068,6 +6194,11 @@ node-addon-api@2.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.0.tgz#f9afb8d777a91525244b01775ea0ddbe1125483b" integrity sha512-ASCL5U13as7HhOExbT6OlWJJUV/lLzL2voOSP1UVehpRD8FbSrSDjfScK/KwAvVTI5AS6r4VwbOMlIqtvRidnA== +node-addon-api@^1.7.1: + version "1.7.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.2.tgz#3df30b95720b53c24e59948b49532b662444f54d" + integrity sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg== + node-emoji@^1.8.1: version "1.10.0" resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.10.0.tgz#8886abd25d9c7bb61802a658523d1f8d2a89b2da" @@ -6375,7 +6506,7 @@ object.values@^1.1.1: function-bind "^1.1.1" has "^1.0.3" -on-finished@~2.3.0: +on-finished@^2.3.0, on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= @@ -6408,6 +6539,13 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" +ono@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/ono/-/ono-7.1.3.tgz#a054e96a388f566a6c4c95e1e92b9b253722d286" + integrity sha512-9jnfVriq7uJM4o5ganUY54ntUm+5EK21EGaQ5NWnkWg3zz5ywbbonlBguRcnmF1/HDiIe3zxNxXcO1YPBmPcQQ== + dependencies: + "@jsdevtools/ono" "7.1.3" + opencollective-postinstall@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259" @@ -6622,6 +6760,11 @@ path-to-regexp@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.1.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.1.0.tgz#0b18f88b7a0ce0bfae6a25990c909ab86f512427" + integrity sha512-h9DqehX3zZZDCEm+xbfU0ZmwCGFCAAraPJWMXJ4+v32NjZJilVg3k1TcKsRgIb8IQ/izZSaydDc1OhJCZvs2Dw== + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -7382,6 +7525,16 @@ read-pkg@^5.2.0: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@1.1.x: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + "readable-stream@2 || 3", readable-stream@^3.5.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" @@ -8202,6 +8355,11 @@ stream-shift@^1.0.0: resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== +streamsearch@0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" + integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo= + string-argv@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" @@ -8282,6 +8440,11 @@ string_decoder@^1.0.0, string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -8416,6 +8579,18 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +swagger-ui-dist@^3.18.1: + version "3.32.5" + resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-3.32.5.tgz#52fc8b714db113c0b5a0cf9ad12ad039fe5b87df" + integrity sha512-3SKHv8UVqsKKknivtACHbFDGcn297jkoZN2h6zAZ7b2yoaJNMaRadQpC3qFw3GobZTGzqHCgHph4ZH9NkaCjrQ== + +swagger-ui-express@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/swagger-ui-express/-/swagger-ui-express-4.1.4.tgz#8b814ad998b850a1cf90e71808d6d0a8a8daf742" + integrity sha512-Ea96ecpC+Iq9GUqkeD/LFR32xSs8gYqmTW1gXCuKg81c26WV6ZC2FsBSPVExQP6WkyUuz5HEiR0sEv/HCC343g== + dependencies: + swagger-ui-dist "^3.18.1" + table@^5.2.3: version "5.4.6" resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" @@ -8734,7 +8909,7 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -type-is@~1.6.17, type-is@~1.6.18: +type-is@^1.6.4, 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== @@ -9220,6 +9395,14 @@ yaml@^1.10.0, yaml@^1.7.2: resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== +yamljs@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/yamljs/-/yamljs-0.3.0.tgz#dc060bf267447b39f7304e9b2bfbe8b5a7ddb03b" + integrity sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ== + dependencies: + argparse "^1.0.7" + glob "^7.0.5" + yargonaut@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/yargonaut/-/yargonaut-1.1.4.tgz#c64f56432c7465271221f53f5cc517890c3d6e0c"