├── .gitignore ├── config ├── default.ts └── custom-environment-variables.ts ├── Makefile ├── src ├── entities │ ├── model.entity.ts │ ├── post.entity.ts │ └── user.entity.ts ├── utils │ ├── appError.ts │ ├── validateEnv.ts │ ├── connectRedis.ts │ ├── data-source.ts │ ├── jwt.ts │ └── email.ts ├── routes │ ├── user.routes.ts │ ├── post.routes.ts │ └── auth.routes.ts ├── controllers │ ├── user.controller.ts │ ├── post.controller.ts │ └── auth.controller.ts ├── middleware │ ├── requireUser.ts │ ├── validate.ts │ └── deserializeUser.ts ├── views │ ├── verificationCode.pug │ ├── resetPassword.pug │ ├── base.pug │ └── _styles.pug ├── services │ ├── post.service.ts │ └── user.service.ts ├── schemas │ ├── post.schema.ts │ └── user.schema.ts ├── migrations │ └── 1665845958119-added-user-entity.ts └── app.ts ├── tsconfig.json ├── docker-compose.yml ├── package.json ├── example.env ├── README.md └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vscode/ 3 | node_modules/ 4 | build/ 5 | tmp/ 6 | temp/ 7 | .env 8 | -------------------------------------------------------------------------------- /config/default.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | origin: 'http://localhost:3000', 3 | accessTokenExpiresIn: 15, 4 | refreshTokenExpiresIn: 60, 5 | redisCacheExpiresIn: 60, 6 | emailFrom: 'contact@codevoweb.com', 7 | }; 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | dev: 2 | docker-compose up -d 3 | 4 | dev-down: 5 | docker-compose down 6 | 7 | dev-down-volume: 8 | docker-compose down 9 | 10 | migrate: 11 | rm -rf build && yarn build && yarn typeorm migration:generate ./src/migrations/added-active -d ./src/utils/data-source.ts 12 | 13 | 14 | db-push: 15 | yarn build && yarn typeorm migrate:run -------------------------------------------------------------------------------- /src/entities/model.entity.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CreateDateColumn, 3 | UpdateDateColumn, 4 | PrimaryGeneratedColumn, 5 | BaseEntity, 6 | } from 'typeorm'; 7 | 8 | export default abstract class Model extends BaseEntity { 9 | @PrimaryGeneratedColumn('uuid') 10 | id: string; 11 | 12 | @CreateDateColumn() 13 | created_at: Date; 14 | 15 | @UpdateDateColumn() 16 | updated_at: Date; 17 | } 18 | -------------------------------------------------------------------------------- /src/utils/appError.ts: -------------------------------------------------------------------------------- 1 | export default class AppError extends Error { 2 | status: string; 3 | isOperational: boolean; 4 | constructor(public statusCode: number = 500, public message: string) { 5 | super(message); 6 | this.status = `${statusCode}`.startsWith('4') ? 'fail' : 'error'; 7 | this.isOperational = true; 8 | 9 | Error.captureStackTrace(this, this.constructor); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2016", 4 | "experimentalDecorators": true, 5 | "emitDecoratorMetadata": true, 6 | "module": "commonjs", 7 | "esModuleInterop": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "strict": true, 10 | "strictPropertyInitialization": false, 11 | "skipLibCheck": true, 12 | "outDir": "./build", 13 | "rootDir": "." 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/routes/user.routes.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import { getMeHandler } from '../controllers/user.controller'; 3 | import { deserializeUser } from '../middleware/deserializeUser'; 4 | import { requireUser } from '../middleware/requireUser'; 5 | 6 | const router = express.Router(); 7 | 8 | router.use(deserializeUser, requireUser); 9 | 10 | // Get currently logged in user 11 | router.get('/me', getMeHandler); 12 | 13 | export default router; 14 | -------------------------------------------------------------------------------- /src/controllers/user.controller.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Request, Response } from 'express'; 2 | 3 | export const getMeHandler = async ( 4 | req: Request, 5 | res: Response, 6 | next: NextFunction 7 | ) => { 8 | try { 9 | const user = res.locals.user; 10 | 11 | res.status(200).status(200).json({ 12 | status: 'success', 13 | data: { 14 | user, 15 | }, 16 | }); 17 | } catch (err: any) { 18 | next(err); 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | postgres: 4 | image: postgres:latest 5 | container_name: postgres 6 | ports: 7 | - '6500:5432' 8 | volumes: 9 | - progresDB:/var/lib/postgresql/data 10 | env_file: 11 | - ./.env 12 | 13 | redis: 14 | image: redis:alpine 15 | container_name: redis 16 | ports: 17 | - '6379:6379' 18 | volumes: 19 | - redisDB:/data 20 | volumes: 21 | progresDB: 22 | redisDB: 23 | -------------------------------------------------------------------------------- /src/middleware/requireUser.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Request, Response } from 'express'; 2 | import AppError from '../utils/appError'; 3 | 4 | export const requireUser = ( 5 | req: Request, 6 | res: Response, 7 | next: NextFunction 8 | ) => { 9 | try { 10 | const user = res.locals.user; 11 | 12 | if (!user) { 13 | return next( 14 | new AppError(400, `Session has expired or user doesn't exist`) 15 | ); 16 | } 17 | 18 | next(); 19 | } catch (err: any) { 20 | next(err); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /src/entities/post.entity.ts: -------------------------------------------------------------------------------- 1 | import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm'; 2 | import Model from './model.entity'; 3 | import { User } from './user.entity'; 4 | 5 | @Entity('posts') 6 | export class Post extends Model { 7 | @Column({ 8 | unique: true, 9 | }) 10 | title: string; 11 | 12 | @Column() 13 | content: string; 14 | 15 | @Column({ 16 | default: 'default-post.png', 17 | }) 18 | image: string; 19 | 20 | @ManyToOne(() => User, (user) => user.posts) 21 | @JoinColumn() 22 | user: User; 23 | } 24 | -------------------------------------------------------------------------------- /src/views/verificationCode.pug: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block content 4 | p Hi #{firstName}, 5 | p Please verify your account to be able to login 6 | table.btn.btn-primary(role='presentation' border='0' cellpadding='0' cellspacing='0') 7 | tbody 8 | tr 9 | td(align='left') 10 | table(role='presentation' border='0' cellpadding='0' cellspacing='0') 11 | tbody 12 | tr 13 | td 14 | a(href=`${url}` target='_blank') Verify your account 15 | p Good luck! Codevo CEO. -------------------------------------------------------------------------------- /src/utils/validateEnv.ts: -------------------------------------------------------------------------------- 1 | import { cleanEnv, port, str } from 'envalid'; 2 | 3 | const validateEnv = () => { 4 | cleanEnv(process.env, { 5 | NODE_ENV: str(), 6 | PORT: port(), 7 | POSTGRES_HOST: str(), 8 | POSTGRES_PORT: port(), 9 | POSTGRES_USER: str(), 10 | POSTGRES_PASSWORD: str(), 11 | POSTGRES_DB: str(), 12 | JWT_ACCESS_TOKEN_PRIVATE_KEY: str(), 13 | JWT_ACCESS_TOKEN_PUBLIC_KEY: str(), 14 | JWT_REFRESH_TOKEN_PRIVATE_KEY: str(), 15 | JWT_REFRESH_TOKEN_PUBLIC_KEY: str(), 16 | }); 17 | }; 18 | 19 | export default validateEnv; 20 | -------------------------------------------------------------------------------- /src/utils/connectRedis.ts: -------------------------------------------------------------------------------- 1 | import { createClient } from 'redis'; 2 | 3 | const redisUrl = 'redis://localhost:6379'; 4 | 5 | const redisClient = createClient({ 6 | url: redisUrl, 7 | }); 8 | 9 | const connectRedis = async () => { 10 | try { 11 | await redisClient.connect(); 12 | console.log('Redis client connect successfully'); 13 | redisClient.set('try', 'Hello Welcome to Express with TypeORM'); 14 | } catch (error) { 15 | console.log(error); 16 | setTimeout(connectRedis, 5000); 17 | } 18 | }; 19 | 20 | connectRedis(); 21 | 22 | export default redisClient; 23 | -------------------------------------------------------------------------------- /src/views/resetPassword.pug: -------------------------------------------------------------------------------- 1 | extends base 2 | 3 | block content 4 | p Hi #{firstName}, 5 | p Forgot password? Send a PATCH request to with your password and passwordConfirm to #{url} 6 | table.btn.btn-primary(role='presentation' border='0' cellpadding='0' cellspacing='0') 7 | tbody 8 | tr 9 | td(align='left') 10 | table(role='presentation' border='0' cellpadding='0' cellspacing='0') 11 | tbody 12 | tr 13 | td 14 | a(href=`${url}` target='_blank') Reset password 15 | p If you didn't forget your password, please ignore this email 16 | p Good luck! Codevo CEO. -------------------------------------------------------------------------------- /src/utils/data-source.ts: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | import 'reflect-metadata'; 3 | import { DataSource } from 'typeorm'; 4 | import config from 'config'; 5 | 6 | const postgresConfig = config.get<{ 7 | host: string; 8 | port: number; 9 | username: string; 10 | password: string; 11 | database: string; 12 | }>('postgresConfig'); 13 | 14 | export const AppDataSource = new DataSource({ 15 | ...postgresConfig, 16 | type: 'postgres', 17 | synchronize: false, 18 | logging: false, 19 | entities: ['src/entities/**/*.entity{.ts,.js}'], 20 | migrations: ['src/migrations/**/*{.ts,.js}'], 21 | subscribers: ['src/subscribers/**/*{.ts,.js}'], 22 | }); 23 | -------------------------------------------------------------------------------- /config/custom-environment-variables.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | port: 'PORT', 3 | postgresConfig: { 4 | host: 'POSTGRES_HOST', 5 | port: 'POSTGRES_PORT', 6 | username: 'POSTGRES_USER', 7 | password: 'POSTGRES_PASSWORD', 8 | database: 'POSTGRES_DB', 9 | }, 10 | 11 | accessTokenPrivateKey: 'JWT_ACCESS_TOKEN_PRIVATE_KEY', 12 | accessTokenPublicKey: 'JWT_ACCESS_TOKEN_PUBLIC_KEY', 13 | refreshTokenPrivateKey: 'JWT_REFRESH_TOKEN_PRIVATE_KEY', 14 | refreshTokenPublicKey: 'JWT_REFRESH_TOKEN_PUBLIC_KEY', 15 | 16 | smtp: { 17 | host: 'EMAIL_HOST', 18 | pass: 'EMAIL_PASS', 19 | port: 'EMAIL_PORT', 20 | user: 'EMAIL_USER', 21 | }, 22 | }; 23 | -------------------------------------------------------------------------------- /src/middleware/validate.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response, NextFunction } from 'express'; 2 | import { AnyZodObject, ZodError } from 'zod'; 3 | 4 | export const validate = 5 | (schema: AnyZodObject) => 6 | (req: Request, res: Response, next: NextFunction) => { 7 | try { 8 | schema.parse({ 9 | params: req.params, 10 | query: req.query, 11 | body: req.body, 12 | }); 13 | 14 | next(); 15 | } catch (error) { 16 | if (error instanceof ZodError) { 17 | return res.status(400).json({ 18 | status: 'fail', 19 | errors: error.errors, 20 | }); 21 | } 22 | next(error); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /src/utils/jwt.ts: -------------------------------------------------------------------------------- 1 | import jwt, { SignOptions } from 'jsonwebtoken'; 2 | import config from 'config'; 3 | 4 | export const signJwt = ( 5 | payload: Object, 6 | keyName: 'accessTokenPrivateKey' | 'refreshTokenPrivateKey', 7 | options: SignOptions 8 | ) => { 9 | const privateKey = Buffer.from( 10 | config.get(keyName), 11 | 'base64' 12 | ).toString('ascii'); 13 | return jwt.sign(payload, privateKey, { 14 | ...(options && options), 15 | algorithm: 'RS256', 16 | }); 17 | }; 18 | 19 | export const verifyJwt = ( 20 | token: string, 21 | keyName: 'accessTokenPublicKey' | 'refreshTokenPublicKey' 22 | ): T | null => { 23 | try { 24 | const publicKey = Buffer.from( 25 | config.get(keyName), 26 | 'base64' 27 | ).toString('ascii'); 28 | const decoded = jwt.verify(token, publicKey) as T; 29 | 30 | return decoded; 31 | } catch (error) { 32 | return null; 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /src/services/post.service.ts: -------------------------------------------------------------------------------- 1 | import { 2 | FindOptionsRelations, 3 | FindOptionsSelect, 4 | FindOptionsWhere, 5 | Relation, 6 | RelationOptions, 7 | } from 'typeorm'; 8 | import { Post } from '../entities/post.entity'; 9 | import { User } from '../entities/user.entity'; 10 | import { AppDataSource } from '../utils/data-source'; 11 | 12 | const postRepository = AppDataSource.getRepository(Post); 13 | 14 | export const createPost = async (input: Partial, user: User) => { 15 | return await postRepository.save(postRepository.create({ ...input, user })); 16 | }; 17 | 18 | export const getPost = async (postId: string) => { 19 | return await postRepository.findOneBy({ id: postId }); 20 | }; 21 | 22 | export const findPosts = async ( 23 | where: FindOptionsWhere = {}, 24 | select: FindOptionsSelect = {}, 25 | relations: FindOptionsRelations = {} 26 | ) => { 27 | return await postRepository.find({ 28 | where, 29 | select, 30 | relations, 31 | }); 32 | }; 33 | -------------------------------------------------------------------------------- /src/routes/post.routes.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import { 3 | createPostHandler, 4 | deletePostHandler, 5 | getPostHandler, 6 | getPostsHandler, 7 | resizePostImage, 8 | updatePostHandler, 9 | uploadPostImage, 10 | } from '../controllers/post.controller'; 11 | import { deserializeUser } from '../middleware/deserializeUser'; 12 | import { requireUser } from '../middleware/requireUser'; 13 | import { validate } from '../middleware/validate'; 14 | import { 15 | createPostSchema, 16 | deletePostSchema, 17 | getPostSchema, 18 | updatePostSchema, 19 | } from '../schemas/post.schema'; 20 | 21 | const router = express.Router(); 22 | 23 | router.use(deserializeUser, requireUser); 24 | router 25 | .route('/') 26 | .post( 27 | uploadPostImage, 28 | resizePostImage, 29 | validate(createPostSchema), 30 | createPostHandler 31 | ) 32 | .get(getPostsHandler); 33 | 34 | router 35 | .route('/:postId') 36 | .get(validate(getPostSchema), getPostHandler) 37 | .patch(validate(updatePostSchema), updatePostHandler) 38 | .delete(validate(deletePostSchema), deletePostHandler); 39 | 40 | export default router; 41 | -------------------------------------------------------------------------------- /src/schemas/post.schema.ts: -------------------------------------------------------------------------------- 1 | import { object, string, TypeOf } from 'zod'; 2 | 3 | export const createPostSchema = object({ 4 | body: object({ 5 | title: string({ 6 | required_error: 'Title is required', 7 | }), 8 | content: string({ 9 | required_error: 'Content is required', 10 | }), 11 | image: string({ 12 | required_error: 'Image is required', 13 | }), 14 | }), 15 | }); 16 | 17 | const params = { 18 | params: object({ 19 | postId: string(), 20 | }), 21 | }; 22 | 23 | export const getPostSchema = object({ 24 | ...params, 25 | }); 26 | 27 | export const updatePostSchema = object({ 28 | ...params, 29 | body: object({ 30 | title: string(), 31 | content: string(), 32 | image: string(), 33 | }).partial(), 34 | }); 35 | 36 | export const deletePostSchema = object({ 37 | ...params, 38 | }); 39 | 40 | export type CreatePostInput = TypeOf['body']; 41 | export type GetPostInput = TypeOf['params']; 42 | export type UpdatePostInput = TypeOf; 43 | export type DeletePostInput = TypeOf['params']; 44 | -------------------------------------------------------------------------------- /src/routes/auth.routes.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import { 3 | loginUserHandler, 4 | logoutHandler, 5 | refreshAccessTokenHandler, 6 | registerUserHandler, 7 | verifyEmailHandler, 8 | } from '../controllers/auth.controller'; 9 | import { deserializeUser } from '../middleware/deserializeUser'; 10 | import { requireUser } from '../middleware/requireUser'; 11 | import { validate } from '../middleware/validate'; 12 | import { 13 | createUserSchema, 14 | loginUserSchema, 15 | verifyEmailSchema, 16 | } from '../schemas/user.schema'; 17 | 18 | const router = express.Router(); 19 | 20 | // Register user 21 | router.post('/register', validate(createUserSchema), registerUserHandler); 22 | 23 | // Login user 24 | router.post('/login', validate(loginUserSchema), loginUserHandler); 25 | 26 | // Logout user 27 | router.get('/logout', deserializeUser, requireUser, logoutHandler); 28 | 29 | // Refresh access token 30 | router.get('/refresh', refreshAccessTokenHandler); 31 | 32 | // Verify Email Address 33 | router.get( 34 | '/verifyemail/:verificationCode', 35 | validate(verifyEmailSchema), 36 | verifyEmailHandler 37 | ); 38 | 39 | export default router; 40 | -------------------------------------------------------------------------------- /src/services/user.service.ts: -------------------------------------------------------------------------------- 1 | import config from 'config'; 2 | import { omit } from 'lodash'; 3 | import { User } from '../entities/user.entity'; 4 | import redisClient from '../utils/connectRedis'; 5 | import { AppDataSource } from '../utils/data-source'; 6 | import { signJwt } from '../utils/jwt'; 7 | 8 | const userRepository = AppDataSource.getRepository(User); 9 | 10 | export const createUser = async (input: Partial) => { 11 | return await userRepository.save(userRepository.create(input)); 12 | }; 13 | 14 | export const findUserByEmail = async ({ email }: { email: string }) => { 15 | return await userRepository.findOneBy({ email }); 16 | }; 17 | 18 | export const findUserById = async (userId: string) => { 19 | return await userRepository.findOneBy({ id: userId }); 20 | }; 21 | 22 | export const findUser = async (query: Object) => { 23 | return await userRepository.findOneBy(query); 24 | }; 25 | export const signTokens = async (user: User) => { 26 | // 1. Create Session 27 | redisClient.set(user.id, JSON.stringify(user), { 28 | EX: config.get('redisCacheExpiresIn') * 60, 29 | }); 30 | 31 | // 2. Create Access and Refresh tokens 32 | const access_token = signJwt({ sub: user.id }, 'accessTokenPrivateKey', { 33 | expiresIn: `${config.get('accessTokenExpiresIn')}m`, 34 | }); 35 | 36 | const refresh_token = signJwt({ sub: user.id }, 'refreshTokenPrivateKey', { 37 | expiresIn: `${config.get('refreshTokenExpiresIn')}m`, 38 | }); 39 | 40 | return { access_token, refresh_token }; 41 | }; 42 | -------------------------------------------------------------------------------- /src/schemas/user.schema.ts: -------------------------------------------------------------------------------- 1 | import { object, string, TypeOf, z } from 'zod'; 2 | import { RoleEnumType } from '../entities/user.entity'; 3 | 4 | export const createUserSchema = object({ 5 | body: object({ 6 | name: string({ 7 | required_error: 'Name is required', 8 | }), 9 | email: string({ 10 | required_error: 'Email address is required', 11 | }).email('Invalid email address'), 12 | password: string({ 13 | required_error: 'Password is required', 14 | }) 15 | .min(8, 'Password must be more than 8 characters') 16 | .max(32, 'Password must be less than 32 characters'), 17 | passwordConfirm: string({ 18 | required_error: 'Please confirm your password', 19 | }), 20 | role: z.optional(z.nativeEnum(RoleEnumType)), 21 | }).refine((data) => data.password === data.passwordConfirm, { 22 | path: ['passwordConfirm'], 23 | message: 'Passwords do not match', 24 | }), 25 | }); 26 | 27 | export const loginUserSchema = object({ 28 | body: object({ 29 | email: string({ 30 | required_error: 'Email address is required', 31 | }).email('Invalid email address'), 32 | password: string({ 33 | required_error: 'Password is required', 34 | }).min(8, 'Invalid email or password'), 35 | }), 36 | }); 37 | 38 | export const verifyEmailSchema = object({ 39 | params: object({ 40 | verificationCode: string(), 41 | }), 42 | }); 43 | 44 | export type CreateUserInput = Omit< 45 | TypeOf['body'], 46 | 'passwordConfirm' 47 | >; 48 | 49 | export type LoginUserInput = TypeOf['body']; 50 | export type VerifyEmailInput = TypeOf['params']; 51 | -------------------------------------------------------------------------------- /src/middleware/deserializeUser.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Request, Response } from 'express'; 2 | import { findUserById } from '../services/user.service'; 3 | import AppError from '../utils/appError'; 4 | import redisClient from '../utils/connectRedis'; 5 | import { verifyJwt } from '../utils/jwt'; 6 | 7 | export const deserializeUser = async ( 8 | req: Request, 9 | res: Response, 10 | next: NextFunction 11 | ) => { 12 | try { 13 | let access_token; 14 | 15 | if ( 16 | req.headers.authorization && 17 | req.headers.authorization.startsWith('Bearer') 18 | ) { 19 | access_token = req.headers.authorization.split(' ')[1]; 20 | } else if (req.cookies.access_token) { 21 | access_token = req.cookies.access_token; 22 | } 23 | 24 | if (!access_token) { 25 | return next(new AppError(401, 'You are not logged in')); 26 | } 27 | 28 | // Validate the access token 29 | const decoded = verifyJwt<{ sub: string }>( 30 | access_token, 31 | 'accessTokenPublicKey' 32 | ); 33 | 34 | if (!decoded) { 35 | return next(new AppError(401, `Invalid token or user doesn't exist`)); 36 | } 37 | 38 | // Check if the user has a valid session 39 | const session = await redisClient.get(decoded.sub); 40 | 41 | if (!session) { 42 | return next(new AppError(401, `Invalid token or session has expired`)); 43 | } 44 | 45 | // Check if the user still exist 46 | const user = await findUserById(JSON.parse(session).id); 47 | 48 | if (!user) { 49 | return next(new AppError(401, `Invalid token or session has expired`)); 50 | } 51 | 52 | // Add user to res.locals 53 | res.locals.user = user; 54 | 55 | next(); 56 | } catch (err: any) { 57 | next(err); 58 | } 59 | }; 60 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jwt_auth_node_typeorm", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "start": "ts-node-dev --respawn --transpile-only --exit-child src/app.ts", 8 | "build": "tsc -p .", 9 | "typeorm": "typeorm-ts-node-commonjs", 10 | "migrate": "rm -rf build && yarn build && yarn typeorm migration:generate ./src/migrations/added-user-entity -d ./src/utils/data-source.ts", 11 | "db:push": "rm -rf build && yarn build && yarn typeorm migration:run -d src/utils/data-source.ts" 12 | }, 13 | "dependencies": { 14 | "bcryptjs": "^2.4.3", 15 | "body-parser": "^1.19.1", 16 | "config": "^3.3.7", 17 | "cookie-parser": "^1.4.6", 18 | "cors": "^2.8.5", 19 | "dotenv": "^16.0.0", 20 | "envalid": "^7.3.1", 21 | "express": "^4.18.1", 22 | "html-to-text": "^8.2.0", 23 | "jsonwebtoken": "^8.5.1", 24 | "lodash": "^4.17.21", 25 | "multer": "^1.4.4", 26 | "nodemailer": "^6.7.5", 27 | "pg": "^8.4.0", 28 | "pug": "^3.0.2", 29 | "redis": "^4.1.0", 30 | "reflect-metadata": "^0.1.13", 31 | "sharp": "^0.30.4", 32 | "typeorm": "0.3.6", 33 | "zod": "^3.14.4" 34 | }, 35 | "devDependencies": { 36 | "@types/bcryptjs": "^2.4.2", 37 | "@types/config": "^0.0.41", 38 | "@types/cookie-parser": "^1.4.3", 39 | "@types/cors": "^2.8.12", 40 | "@types/express": "^4.17.13", 41 | "@types/html-to-text": "^8.1.0", 42 | "@types/jsonwebtoken": "^8.5.8", 43 | "@types/lodash": "^4.14.182", 44 | "@types/morgan": "^1.9.3", 45 | "@types/multer": "^1.4.7", 46 | "@types/node": "^16.11.10", 47 | "@types/nodemailer": "^6.4.4", 48 | "@types/pug": "^2.0.6", 49 | "@types/sharp": "^0.30.2", 50 | "morgan": "^1.10.0", 51 | "ts-node": "10.7.0", 52 | "ts-node-dev": "^1.1.8", 53 | "typescript": "4.5.2" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/views/base.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | meta(name='viewport' content='width=device-width, initial-scale=1.0') 5 | meta(http-equiv='Content-Type' content='text/html; charset=UTF-8') 6 | title #{subject} 7 | include _styles 8 | body 9 | table.body(role='presentation' border='0' cellpadding='0' cellspacing='0') 10 | tbody 11 | tr 12 | td   13 | td.container 14 | .content 15 | // START CENTERED WHITE CONTAINER 16 | table.main(role='presentation') 17 | // START MAIN CONTENT AREA 18 | tbody 19 | tr 20 | td.wrapper 21 | table(role='presentation' border='0' cellpadding='0' cellspacing='0') 22 | tbody 23 | tr 24 | td 25 | block content 26 | // END MAIN CONTENT AREA 27 | // END CENTERED WHITE CONTAINER 28 | // START FOOTER 29 | .footer 30 | table(role='presentation' border='0' cellpadding='0' cellspacing='0') 31 | tbody 32 | tr 33 | td.content-block 34 | span.apple-link Company Inc, 3 Abbey Road, San Francisco CA 94102 35 | br 36 | | Don't like these emails? 37 | a(href='http://i.imgur.com/CScmqnj.gif') Unsubscribe 38 | | . 39 | tr 40 | td.content-block.powered-by 41 | | Powered by 42 | a(href='http://htmlemail.io') HTMLemail 43 | | . 44 | // END FOOTER 45 | td   46 | -------------------------------------------------------------------------------- /src/utils/email.ts: -------------------------------------------------------------------------------- 1 | import nodemailer from 'nodemailer'; 2 | import { User } from '../entities/user.entity'; 3 | import config from 'config'; 4 | import pug from 'pug'; 5 | import { convert } from 'html-to-text'; 6 | 7 | const smtp = config.get<{ 8 | host: string; 9 | port: number; 10 | user: string; 11 | pass: string; 12 | }>('smtp'); 13 | 14 | export default class Email { 15 | firstName: string; 16 | to: string; 17 | from: string; 18 | constructor(public user: User, public url: string) { 19 | this.firstName = user.name.split(' ')[0]; 20 | this.to = user.email; 21 | this.from = `Codevo ${config.get('emailFrom')}`; 22 | } 23 | 24 | private newTransport() { 25 | // if (process.env.NODE_ENV === 'production') { 26 | // console.log('Hello') 27 | // } 28 | 29 | return nodemailer.createTransport({ 30 | ...smtp, 31 | auth: { 32 | user: smtp.user, 33 | pass: smtp.pass, 34 | }, 35 | }); 36 | } 37 | 38 | private async send(template: string, subject: string) { 39 | // Generate HTML template based on the template string 40 | const html = pug.renderFile(`${__dirname}/../views/${template}.pug`, { 41 | firstName: this.firstName, 42 | subject, 43 | url: this.url, 44 | }); 45 | // Create mailOptions 46 | const mailOptions = { 47 | from: this.from, 48 | to: this.to, 49 | subject, 50 | text: convert(html), 51 | html, 52 | }; 53 | 54 | // Send email 55 | const info = await this.newTransport().sendMail(mailOptions); 56 | console.log(nodemailer.getTestMessageUrl(info)); 57 | } 58 | 59 | async sendVerificationCode() { 60 | await this.send('verificationCode', 'Your account verification code'); 61 | } 62 | 63 | async sendPasswordResetToken() { 64 | await this.send( 65 | 'resetPassword', 66 | 'Your password reset token (valid for only 10 minutes)' 67 | ); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/entities/user.entity.ts: -------------------------------------------------------------------------------- 1 | import crypto from 'crypto'; 2 | import { Entity, Column, Index, BeforeInsert, OneToMany } from 'typeorm'; 3 | import bcrypt from 'bcryptjs'; 4 | import Model from './model.entity'; 5 | import { Post } from './post.entity'; 6 | 7 | export enum RoleEnumType { 8 | USER = 'user', 9 | ADMIN = 'admin', 10 | } 11 | 12 | @Entity('users') 13 | export class User extends Model { 14 | @Column() 15 | name: string; 16 | 17 | @Index('email_index') 18 | @Column({ 19 | unique: true, 20 | }) 21 | email: string; 22 | 23 | @Column() 24 | password: string; 25 | 26 | @Column({ 27 | type: 'enum', 28 | enum: RoleEnumType, 29 | default: RoleEnumType.USER, 30 | }) 31 | role: RoleEnumType.USER; 32 | 33 | @Column({ 34 | default: 'default.png', 35 | }) 36 | photo: string; 37 | 38 | @Column({ 39 | default: false, 40 | }) 41 | verified: boolean; 42 | 43 | @Index('verificationCode_index') 44 | @Column({ 45 | type: 'text', 46 | nullable: true, 47 | }) 48 | verificationCode!: string | null; 49 | 50 | @OneToMany(() => Post, (post) => post.user) 51 | posts: Post[]; 52 | 53 | @BeforeInsert() 54 | async hashPassword() { 55 | this.password = await bcrypt.hash(this.password, 12); 56 | } 57 | 58 | static async comparePasswords( 59 | candidatePassword: string, 60 | hashedPassword: string 61 | ) { 62 | return await bcrypt.compare(candidatePassword, hashedPassword); 63 | } 64 | 65 | static createVerificationCode() { 66 | const verificationCode = crypto.randomBytes(32).toString('hex'); 67 | 68 | const hashedVerificationCode = crypto 69 | .createHash('sha256') 70 | .update(verificationCode) 71 | .digest('hex'); 72 | 73 | return { verificationCode, hashedVerificationCode }; 74 | } 75 | 76 | toJSON() { 77 | return { 78 | ...this, 79 | password: undefined, 80 | verified: undefined, 81 | verificationCode: undefined, 82 | }; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /example.env: -------------------------------------------------------------------------------- 1 | PORT=8000 2 | NODE_ENV=development 3 | 4 | POSTGRES_HOST=127.0.0.1 5 | POSTGRES_PORT=6500 6 | POSTGRES_USER=admin 7 | POSTGRES_PASSWORD=password123 8 | POSTGRES_DB=node_typeorm 9 | 10 | EMAIL_USER=ypi5eci55z2an5pm@ethereal.email 11 | EMAIL_PASS=5B2N9Pn1ETvmXxDCye 12 | EMAIL_HOST=smtp.ethereal.email 13 | EMAIL_PORT=587 14 | 15 | AWS_ACCESS_KEY_ID= 16 | AWS_SECRET_ACCESS_KEY= 17 | AWS_REGION= 18 | AWS_BUCKET_NAME= 19 | 20 | 21 | JWT_ACCESS_TOKEN_PRIVATE_KEY=LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlCT1FJQkFBSkJBSjdVblpyNUxpUGJxbDRENlo3VHVKK2NFMkI0Y3FzbnUzeUJaUHo2NmtqZDhJT1RFdjlNCkpEdmhMQ05PczYyWHBZcmFZYU5HS3UrN3Q4YVVjcWNoRzJNQ0F3RUFBUUpBRS84YXRKY29tdlVkOXVZeE5JRGQKWHFMc3dabUlma25yVGRxUWwxVVR5QWFPRWpIRGFnR0lGdEhRZE5IZTAybkp6a2Z1WkdWSkJVRmo1aTJJVyszMQpxUUloQU9LQVRxOVpSZHR0T0JDWWJLR3VpbjZnd1FVZ2YzUGkwSjh3Snh3cjNRVDFBaUVBczRRZ0lhR1c1V3NaCmNqWUQ3bVpwcXBiRkdubnBvMVR6QU1YS2psQ2dKL2NDSUQyZVZFbWx5cmhnSlNGMnBnN3lNZUV6RUcrNW9KTEIKUUtvZDZuWGloUFZGQWlCY0ZuUXhMR1p1NjhEUzhOaVZiQjNhYjV0TzJLazhxekE0L2ozSlFaeld3d0lnU2N1awoyZWlBM3E5ci9EdDQ3OUZHek4xSEVSdzJ2TXZjeEV6REZWRnV5aDg9Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0t 22 | JWT_ACCESS_TOKEN_PUBLIC_KEY=LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZ3d0RRWUpLb1pJaHZjTkFRRUJCUUFEU3dBd1NBSkJBSjdVblpyNUxpUGJxbDRENlo3VHVKK2NFMkI0Y3Fzbgp1M3lCWlB6NjZramQ4SU9URXY5TUpEdmhMQ05PczYyWHBZcmFZYU5HS3UrN3Q4YVVjcWNoRzJNQ0F3RUFBUT09Ci0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQ== 23 | JWT_REFRESH_TOKEN_PRIVATE_KEY=LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlCT0FJQkFBSkFmTmJzOVJhUGNnVG5RalB4cExLUXkvRHdBSVh5NFNiUWdlejFNU2pwWnozQ0tsTXdpWWwyCm5IUVg5Rk5NcU1pMmxnL29yUjJDTUJxRzFNdnlvN1EyTVFJREFRQUJBa0FKUStwU1JscGZHLzRONjgwRGJEMVMKNVk3cWV3YUxyMVhLVHN2ajJpVjRoQUdxb0d3K3NvbEZUalp1Y21xaW9vY1cydTNXYVdxdkNrVmtvamc2OFFBQgpBaUVBNElqNkFXbG91am84T1YvSEJ3elZpaDQzRllCNEpkZnd3SjFwYTBRVFlWRUNJUUNPVlhMdGZOTFh3cXFlCndZNVIrWktwY3JBb0tBMjVYM3M1cEhVNFhYVk80UUlnSDM0VzBxdmVMSUNPZ2QyVkpNQUFFMmM1Z3FLS040U2EKRituOEp6ZGRJSUVDSUZ4SllUeEU2L3lEdHRjNnpzbXVGWDhTNHM4V3NWZFpabStJaDR5bFpGTmhBaUFGRWJwSApqdlZqSHlPdlIyQ2F1clFmTmU3QldWVnVlODNQN3pYSXV3eHl5Zz09Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0t 24 | JWT_REFRESH_TOKEN_PUBLIC_KEY=LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZzd0RRWUpLb1pJaHZjTkFRRUJCUUFEU2dBd1J3SkFmTmJzOVJhUGNnVG5RalB4cExLUXkvRHdBSVh5NFNiUQpnZXoxTVNqcFp6M0NLbE13aVlsMm5IUVg5Rk5NcU1pMmxnL29yUjJDTUJxRzFNdnlvN1EyTVFJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0t -------------------------------------------------------------------------------- /src/migrations/1665845958119-added-user-entity.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | export class addedUserEntity1665845958119 implements MigrationInterface { 4 | name = 'addedUserEntity1665845958119' 5 | 6 | public async up(queryRunner: QueryRunner): Promise { 7 | await queryRunner.query(`CREATE TYPE "public"."users_role_enum" AS ENUM('user', 'admin')`); 8 | await queryRunner.query(`CREATE TABLE "users" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "created_at" TIMESTAMP NOT NULL DEFAULT now(), "updated_at" TIMESTAMP NOT NULL DEFAULT now(), "name" character varying NOT NULL, "email" character varying NOT NULL, "password" character varying NOT NULL, "role" "public"."users_role_enum" NOT NULL DEFAULT 'user', "photo" character varying NOT NULL DEFAULT 'default.png', "verified" boolean NOT NULL DEFAULT false, "verificationCode" text, CONSTRAINT "UQ_97672ac88f789774dd47f7c8be3" UNIQUE ("email"), CONSTRAINT "PK_a3ffb1c0c8416b9fc6f907b7433" PRIMARY KEY ("id"))`); 9 | await queryRunner.query(`CREATE INDEX "email_index" ON "users" ("email") `); 10 | await queryRunner.query(`CREATE INDEX "verificationCode_index" ON "users" ("verificationCode") `); 11 | await queryRunner.query(`CREATE TABLE "posts" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "created_at" TIMESTAMP NOT NULL DEFAULT now(), "updated_at" TIMESTAMP NOT NULL DEFAULT now(), "title" character varying NOT NULL, "content" character varying NOT NULL, "image" character varying NOT NULL DEFAULT 'default-post.png', "userId" uuid, CONSTRAINT "UQ_2d82eb2bb2ddd7a6bfac8804d8a" UNIQUE ("title"), CONSTRAINT "PK_2829ac61eff60fcec60d7274b9e" PRIMARY KEY ("id"))`); 12 | await queryRunner.query(`ALTER TABLE "posts" ADD CONSTRAINT "FK_ae05faaa55c866130abef6e1fee" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); 13 | } 14 | 15 | public async down(queryRunner: QueryRunner): Promise { 16 | await queryRunner.query(`ALTER TABLE "posts" DROP CONSTRAINT "FK_ae05faaa55c866130abef6e1fee"`); 17 | await queryRunner.query(`DROP TABLE "posts"`); 18 | await queryRunner.query(`DROP INDEX "public"."verificationCode_index"`); 19 | await queryRunner.query(`DROP INDEX "public"."email_index"`); 20 | await queryRunner.query(`DROP TABLE "users"`); 21 | await queryRunner.query(`DROP TYPE "public"."users_role_enum"`); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/app.ts: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | import express, { NextFunction, Request, Response } from 'express'; 3 | import config from 'config'; 4 | import morgan from 'morgan'; 5 | import cookieParser from 'cookie-parser'; 6 | import cors from 'cors'; 7 | import { AppDataSource } from './utils/data-source'; 8 | import AppError from './utils/appError'; 9 | import authRouter from './routes/auth.routes'; 10 | import userRouter from './routes/user.routes'; 11 | import postRouter from './routes/post.routes'; 12 | import validateEnv from './utils/validateEnv'; 13 | import cluster from 'cluster'; 14 | import os from 'os'; 15 | 16 | // import nodemailer from 'nodemailer'; 17 | // (async function () { 18 | // const credentials = await nodemailer.createTestAccount(); 19 | // console.log(credentials); 20 | // })(); 21 | 22 | const numCpus = os.cpus().length; 23 | AppDataSource.initialize() 24 | .then(async () => { 25 | // VALIDATE ENV 26 | validateEnv(); 27 | 28 | const app = express(); 29 | 30 | // TEMPLATE ENGINE 31 | app.set('view engine', 'pug'); 32 | app.set('views', `${__dirname}/views`); 33 | 34 | // MIDDLEWARE 35 | 36 | // 1. Body parser 37 | app.use(express.json({ limit: '10kb' })); 38 | 39 | // 2. Logger 40 | if (process.env.NODE_ENV === 'development') app.use(morgan('dev')); 41 | 42 | // 3. Cookie Parser 43 | app.use(cookieParser()); 44 | 45 | // 4. Cors 46 | app.use( 47 | cors({ 48 | origin: config.get('origin'), 49 | credentials: true, 50 | }) 51 | ); 52 | 53 | // ROUTES 54 | app.use('/api/auth', authRouter); 55 | app.use('/api/users', userRouter); 56 | app.use('/api/posts', postRouter); 57 | 58 | // HEALTH CHECKER 59 | app.get('/api/healthChecker', async (_, res: Response) => { 60 | // const message = await redisClient.get('try'); 61 | 62 | res.status(200).json({ 63 | status: 'success', 64 | message: 'Welcome to Node.js, we are happy to see you', 65 | }); 66 | }); 67 | 68 | // UNHANDLED ROUTE 69 | app.all('*', (req: Request, res: Response, next: NextFunction) => { 70 | next(new AppError(404, `Route ${req.originalUrl} not found`)); 71 | }); 72 | 73 | // GLOBAL ERROR HANDLER 74 | app.use( 75 | (error: AppError, req: Request, res: Response, next: NextFunction) => { 76 | error.status = error.status || 'error'; 77 | error.statusCode = error.statusCode || 500; 78 | 79 | res.status(error.statusCode).json({ 80 | status: error.status, 81 | message: error.message, 82 | }); 83 | } 84 | ); 85 | 86 | const port = config.get('port'); 87 | if (cluster.isPrimary) { 88 | for (let i = 0; i < numCpus; i++) { 89 | cluster.fork(); 90 | } 91 | 92 | cluster.on('exit', (worker, code, signal) => { 93 | console.log(`Worker pid: ${worker.process.pid} died`); 94 | cluster.fork(); 95 | }); 96 | } else { 97 | app.listen(port); 98 | console.log(`Server started with pid: ${process.pid} on port: ${port}`); 99 | } 100 | // app.listen(port); 101 | // console.log(`Server started with pid: ${process.pid} on port: ${port}`); 102 | }) 103 | .catch((error) => console.log(error)); 104 | -------------------------------------------------------------------------------- /src/controllers/post.controller.ts: -------------------------------------------------------------------------------- 1 | import { NextFunction, Request, Response } from 'express'; 2 | import { 3 | CreatePostInput, 4 | DeletePostInput, 5 | GetPostInput, 6 | UpdatePostInput, 7 | } from '../schemas/post.schema'; 8 | import { createPost, findPosts, getPost } from '../services/post.service'; 9 | import { findUserById } from '../services/user.service'; 10 | import AppError from '../utils/appError'; 11 | import multer from 'multer'; 12 | import sharp from 'sharp'; 13 | 14 | const multerStorage = multer.memoryStorage(); 15 | 16 | const multerFilter = ( 17 | req: Request, 18 | file: Express.Multer.File, 19 | cb: multer.FileFilterCallback 20 | ) => { 21 | if (!file.mimetype.startsWith('image')) { 22 | return cb(new multer.MulterError('LIMIT_UNEXPECTED_FILE')); 23 | } 24 | 25 | cb(null, true); 26 | }; 27 | 28 | const upload = multer({ 29 | storage: multerStorage, 30 | fileFilter: multerFilter, 31 | limits: { fileSize: 5000000, files: 1 }, 32 | }); 33 | 34 | export const uploadPostImage = upload.single('image'); 35 | 36 | export const resizePostImage = async ( 37 | req: Request, 38 | res: Response, 39 | next: NextFunction 40 | ) => { 41 | try { 42 | const file = req.file; 43 | if (!file) return next(); 44 | 45 | const user = res.locals.user; 46 | 47 | const fileName = `user-${user.id}-${Date.now()}.jpeg`; 48 | await sharp(req.file?.buffer) 49 | .resize(800, 450) 50 | .toFormat('jpeg') 51 | .jpeg({ quality: 90 }) 52 | .toFile(`${__dirname}/../../public/posts/${fileName}`); 53 | 54 | req.body.image = fileName; 55 | 56 | next(); 57 | } catch (err: any) { 58 | next(err); 59 | } 60 | }; 61 | 62 | export const createPostHandler = async ( 63 | req: Request<{}, {}, CreatePostInput>, 64 | res: Response, 65 | next: NextFunction 66 | ) => { 67 | try { 68 | const user = await findUserById(res.locals.user.id as string); 69 | 70 | const post = await createPost(req.body, user!); 71 | 72 | res.status(201).json({ 73 | status: 'success', 74 | data: { 75 | post, 76 | }, 77 | }); 78 | } catch (err: any) { 79 | if (err.code === '23505') { 80 | return res.status(409).json({ 81 | status: 'fail', 82 | message: 'Post with that title already exist', 83 | }); 84 | } 85 | next(err); 86 | } 87 | }; 88 | 89 | export const getPostHandler = async ( 90 | req: Request, 91 | res: Response, 92 | next: NextFunction 93 | ) => { 94 | try { 95 | const post = await getPost(req.params.postId); 96 | 97 | if (!post) { 98 | return next(new AppError(404, 'Post with that ID not found')); 99 | } 100 | 101 | res.status(200).json({ 102 | status: 'success', 103 | data: { 104 | post, 105 | }, 106 | }); 107 | } catch (err: any) { 108 | next(err); 109 | } 110 | }; 111 | 112 | export const getPostsHandler = async ( 113 | req: Request, 114 | res: Response, 115 | next: NextFunction 116 | ) => { 117 | try { 118 | const posts = await findPosts({}, {}, {}); 119 | 120 | res.status(200).json({ 121 | status: 'success', 122 | results: posts.length, 123 | data: { 124 | posts, 125 | }, 126 | }); 127 | } catch (err: any) { 128 | next(err); 129 | } 130 | }; 131 | 132 | export const updatePostHandler = async ( 133 | req: Request, 134 | res: Response, 135 | next: NextFunction 136 | ) => { 137 | try { 138 | const post = await getPost(req.params.postId); 139 | 140 | if (!post) { 141 | return next(new AppError(404, 'Post with that ID not found')); 142 | } 143 | 144 | Object.assign(post, req.body); 145 | 146 | const updatedPost = await post.save(); 147 | 148 | res.status(200).json({ 149 | status: 'success', 150 | data: { 151 | post: updatedPost, 152 | }, 153 | }); 154 | } catch (err: any) { 155 | next(err); 156 | } 157 | }; 158 | 159 | export const deletePostHandler = async ( 160 | req: Request, 161 | res: Response, 162 | next: NextFunction 163 | ) => { 164 | try { 165 | const post = await getPost(req.params.postId); 166 | 167 | if (!post) { 168 | return next(new AppError(404, 'Post with that ID not found')); 169 | } 170 | 171 | await post.remove(); 172 | 173 | res.status(204).json({ 174 | status: 'success', 175 | data: null, 176 | }); 177 | } catch (err: any) { 178 | next(err); 179 | } 180 | }; 181 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # API with Node.js + PostgreSQL + TypeORM 2 | 3 | ## API with Node.js + PostgreSQL + TypeORM: Project Setup 4 | 5 | ![API with Node.js + PostgreSQL + TypeORM: Project Setup](https://codevoweb.com/wp-content/uploads/2022/05/API-with-Node.js-PostgreSQL-TypeORM-Project-Setup.webp) 6 | 7 | In this article, you'll learn how to set up a Node.js project with TypeScript, ExpressJs, PostgreSQL, TypeORM, and Redis. Also, you will learn how to run Postgres and Redis servers with Docker. 8 | 9 | ### Topics Covered 10 | 11 | - Setup Node.js with Express, PostgreSQL, Redis, and TypeORM 12 | - Creating PostgreSQL and Redis Database with Docker 13 | - Setup Environment Variables with Dotenv 14 | - Initialize a New TypeORM Express App 15 | - Connecting an Express application with PostgreSQL 16 | - Connecting an ExpressJs application to Redis 17 | - Run the Express Server 18 | 19 | Read the entire article here: [https://codevoweb.com/api-node-postgresql-typeorm-project-setup](https://codevoweb.com/api-node-postgresql-typeorm-project-setup) 20 | 21 | ## API with Node.js + PostgreSQL + TypeORM: JWT Authentication 22 | 23 | ![API with Node.js + PostgreSQL + TypeORM: JWT Authentication](https://codevoweb.com/wp-content/uploads/2022/05/API-with-Node.js-PostgreSQL-TypeORM-JWT-Authentication.webp) 24 | 25 | This article will teach you how to implement JSON Web Token (JWT) Authentication with Node.js, PostgreSQL, TypeORM, ExpressJs, Redis, Docker, and Docker-compose. We will implement the assymetric (RS256 algorithm) JSON Web Token authentication manually without using any Node.js authentication library like PassportJs. 26 | 27 | ### Topics Covered 28 | 29 | - List the Node.js API Routes 30 | - User Login and Register Flow with JWT Authentication 31 | - Defining Base and User Entities with TypeORM 32 | - Defining Zod Schemas to Validate Request Body 33 | - Create Middleware to Parse Zod Schema 34 | - Password Management with Bcrypt 35 | - Create Services to Interact with the Database 36 | - Asymmetric Encryption (RS256 algorithm) Json Web Tokens 37 | - Service to Sign Access and Refresh Tokens 38 | - Error Handling in Express 39 | - Create Authentication Route Controllers 40 | - Create User Route Controller 41 | - Create Authentication Middleware Guard 42 | - Create the API Routes 43 | - Authentication Routes 44 | - User Routes 45 | - Add the Routes to the Express Middleware Stack 46 | - Run Database Migrations with TypeORM 47 | - Inspect the Data with VS Code MySQL Extension 48 | 49 | Read the entire article here: [https://codevoweb.com/api-node-postgresql-typeorm-jwt-authentication](https://codevoweb.com/api-node-postgresql-typeorm-jwt-authentication) 50 | 51 | ## API with Node.js + PostgreSQL + TypeORM: Send Emails 52 | 53 | ![API with Node.js + PostgreSQL + TypeORM: Send Emails](https://codevoweb.com/wp-content/uploads/2022/05/API-with-Node.js-PostgreSQL-TypeORM-Send-Emails.webp) 54 | 55 | In this article, you'll learn how to send development and production-ready emails with Nodemailer, Node.js, PostgreSQL, and TypeORM. We will include the Email verification feature in the API to ensure the users provide valid email addresses during the account registration process. 56 | 57 | ### Topics Covered 58 | 59 | - Setting up Express.js with Pug Templating Engine 60 | - Create a Utility Class to Send Emails 61 | - Require the Nodemailer Credentials 62 | - Define the Email Class Attributes 63 | - Create a Nodemailer Transporter 64 | - Create a Method to Generate the Email Templates 65 | - Create a Method to Send the Emails 66 | - Creating the Email Templates with Pug 67 | - Create the User Entity with TypeORM 68 | - Database Schema Migration with TypeORM 69 | - Update the User Register Controller 70 | - Add a Controller to Verify the Email 71 | - Update the Login Controller 72 | 73 | Read the entire article here: [https://codevoweb.com/api-node-postgresql-typeorm-send-emails](https://codevoweb.com/api-node-postgresql-typeorm-send-emails) 74 | 75 | 76 | ## Node.js, Express, TypeORM, PostgreSQL: CRUD Rest API 77 | 78 | ![Node.js, Express, TypeORM, PostgreSQL: CRUD Rest API](https://codevoweb.com/wp-content/uploads/2022/05/Node.js-Express-TypeORM-PostgreSQL-CRUD-Rest-API.webp) 79 | 80 | In this article, you'll learn how to build CRUD RESTful API with Node.js, ExpressJs, TypeORM, and PostgreSQL. We will define the database schema with TypeORM and run the migration command to push the TypeORM schema to the database. Next, we will create higher-level CRUD function to perform the CRUD operations. 81 | 82 | ### Topics Covered 83 | 84 | - Node.js, TypeORM, PostgreSQL CRUD RESTful API Overview 85 | - Project Structure 86 | - Model Data with TypeORM and PostgreSQL 87 | - Define a Base Entity 88 | - Add One-to-Many Relationship to User Entity 89 | - Complete User Entity 90 | - Create a Post Entity 91 | - Create Validation Schemas with Zod 92 | - Create Services to Communicate with Database 93 | - Create Route Controllers 94 | - Create a New Post Controller 95 | - Get a Single Post Controller 96 | - Get All Posts Controller 97 | - Update a Single Post Controller 98 | - Delete a Single Post Controller 99 | - Create Routes with Express 100 | - Add the Routes to the Express Middleware Pipeline 101 | - Run Database Migration with TypeORM 102 | 103 | Read the entire article here: [https://codevoweb.com/node-express-typeorm-postgresql-rest-api](https://codevoweb.com/node-express-typeorm-postgresql-rest-api) 104 | 105 | ## Node.js and PostgreSQL: Upload and Resize Multiple Images 106 | 107 | ![Node.js and PostgreSQL: Upload and Resize Multiple Images](https://codevoweb.com/wp-content/uploads/2022/05/Node.js-and-PostgreSQL-Upload-and-Resize-Multiple-Images.webp) 108 | 109 | In this article, you'll learn how to upload and resize single and multiple images with Node.js, TypeScript, Multer, and Sharp. The Node.js API will run on an Express.js HTTP server and use PostgreSQL database. 110 | 111 | ### Topics Covered 112 | 113 | - Upload Single Image With Multer 114 | - Using Multer to Upload a Single Image 115 | - Route Handler Functions 116 | - Upload Single Image with Multer and Sharp 117 | - Using Multer to Upload a Single Image 118 | - Using Sharp to Resize a Single Image 119 | - Create the API Route Handlers 120 | - Upload Multiple Images with Multer and Sharp 121 | - Using Multer to Upload Multiple Images 122 | - Using Sharp to Resize Multiple Images 123 | - Processing a single file 124 | - Processing multiple files 125 | - Create the Route Functions 126 | - Frontend for Uploading Either Single or Multiple Images 127 | 128 | Read the entire article here: [https://codevoweb.com/node-postgresql-upload-resize-multiple-images](https://codevoweb.com/node-postgresql-upload-resize-multiple-images) 129 | -------------------------------------------------------------------------------- /src/views/_styles.pug: -------------------------------------------------------------------------------- 1 | style. 2 | /* ------------------------------------- 3 | GLOBAL RESETS 4 | ------------------------------------- */ 5 | /*All the styling goes here*/ 6 | img { 7 | border: none; 8 | -ms-interpolation-mode: bicubic; 9 | max-width: 100%; 10 | } 11 | body { 12 | background-color: #f6f6f6; 13 | font-family: sans-serif; 14 | -webkit-font-smoothing: antialiased; 15 | font-size: 14px; 16 | line-height: 1.4; 17 | margin: 0; 18 | padding: 0; 19 | -ms-text-size-adjust: 100%; 20 | -webkit-text-size-adjust: 100%; 21 | } 22 | table { 23 | border-collapse: separate; 24 | mso-table-lspace: 0pt; 25 | mso-table-rspace: 0pt; 26 | width: 100%; } 27 | table td { 28 | font-family: sans-serif; 29 | font-size: 14px; 30 | vertical-align: top; 31 | } 32 | /* ------------------------------------- 33 | BODY & CONTAINER 34 | ------------------------------------- */ 35 | .body { 36 | background-color: #f6f6f6; 37 | width: 100%; 38 | } 39 | /* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */ 40 | .container { 41 | display: block; 42 | margin: 0 auto !important; 43 | /* makes it centered */ 44 | max-width: 580px; 45 | padding: 10px; 46 | width: 580px; 47 | } 48 | /* This should also be a block element, so that it will fill 100% of the .container */ 49 | .content { 50 | box-sizing: border-box; 51 | display: block; 52 | margin: 0 auto; 53 | max-width: 580px; 54 | padding: 10px; 55 | } 56 | /* ------------------------------------- 57 | HEADER, FOOTER, MAIN 58 | ------------------------------------- */ 59 | .main { 60 | background: #ffffff; 61 | border-radius: 3px; 62 | width: 100%; 63 | } 64 | .wrapper { 65 | box-sizing: border-box; 66 | padding: 20px; 67 | } 68 | .content-block { 69 | padding-bottom: 10px; 70 | padding-top: 10px; 71 | } 72 | .footer { 73 | clear: both; 74 | margin-top: 10px; 75 | text-align: center; 76 | width: 100%; 77 | } 78 | .footer td, 79 | .footer p, 80 | .footer span, 81 | .footer a { 82 | color: #999999; 83 | font-size: 12px; 84 | text-align: center; 85 | } 86 | /* ------------------------------------- 87 | TYPOGRAPHY 88 | ------------------------------------- */ 89 | h1, 90 | h2, 91 | h3, 92 | h4 { 93 | color: #000000; 94 | font-family: sans-serif; 95 | font-weight: 400; 96 | line-height: 1.4; 97 | margin: 0; 98 | margin-bottom: 30px; 99 | } 100 | h1 { 101 | font-size: 35px; 102 | font-weight: 300; 103 | text-align: center; 104 | text-transform: capitalize; 105 | } 106 | p, 107 | ul, 108 | ol { 109 | font-family: sans-serif; 110 | font-size: 14px; 111 | font-weight: normal; 112 | margin: 0; 113 | margin-bottom: 15px; 114 | } 115 | p li, 116 | ul li, 117 | ol li { 118 | list-style-position: inside; 119 | margin-left: 5px; 120 | } 121 | a { 122 | color: #3498db; 123 | text-decoration: underline; 124 | } 125 | /* ------------------------------------- 126 | BUTTONS 127 | ------------------------------------- */ 128 | .btn { 129 | box-sizing: border-box; 130 | width: 100%; } 131 | .btn > tbody > tr > td { 132 | padding-bottom: 15px; } 133 | .btn table { 134 | width: auto; 135 | } 136 | .btn table td { 137 | background-color: #ffffff; 138 | border-radius: 5px; 139 | text-align: center; 140 | } 141 | .btn a { 142 | background-color: #ffffff; 143 | border: solid 1px #3498db; 144 | border-radius: 5px; 145 | box-sizing: border-box; 146 | color: #3498db; 147 | cursor: pointer; 148 | display: inline-block; 149 | font-size: 14px; 150 | font-weight: bold; 151 | margin: 0; 152 | padding: 12px 25px; 153 | text-decoration: none; 154 | text-transform: capitalize; 155 | } 156 | .btn-primary table td { 157 | background-color: #3498db; 158 | } 159 | .btn-primary a { 160 | background-color: #3498db; 161 | border-color: #3498db; 162 | color: #ffffff; 163 | } 164 | /* ------------------------------------- 165 | OTHER STYLES THAT MIGHT BE USEFUL 166 | ------------------------------------- */ 167 | .last { 168 | margin-bottom: 0; 169 | } 170 | .first { 171 | margin-top: 0; 172 | } 173 | .align-center { 174 | text-align: center; 175 | } 176 | .align-right { 177 | text-align: right; 178 | } 179 | .align-left { 180 | text-align: left; 181 | } 182 | .clear { 183 | clear: both; 184 | } 185 | .mt0 { 186 | margin-top: 0; 187 | } 188 | .mb0 { 189 | margin-bottom: 0; 190 | } 191 | .preheader { 192 | color: transparent; 193 | display: none; 194 | height: 0; 195 | max-height: 0; 196 | max-width: 0; 197 | opacity: 0; 198 | overflow: hidden; 199 | mso-hide: all; 200 | visibility: hidden; 201 | width: 0; 202 | } 203 | .powered-by a { 204 | text-decoration: none; 205 | } 206 | hr { 207 | border: 0; 208 | border-bottom: 1px solid #f6f6f6; 209 | margin: 20px 0; 210 | } 211 | /* ------------------------------------- 212 | RESPONSIVE AND MOBILE FRIENDLY STYLES 213 | ------------------------------------- */ 214 | @media only screen and (max-width: 620px) { 215 | table.body h1 { 216 | font-size: 28px !important; 217 | margin-bottom: 10px !important; 218 | } 219 | table.body p, 220 | table.body ul, 221 | table.body ol, 222 | table.body td, 223 | table.body span, 224 | table.body a { 225 | font-size: 16px !important; 226 | } 227 | table.body .wrapper, 228 | table.body .article { 229 | padding: 10px !important; 230 | } 231 | table.body .content { 232 | padding: 0 !important; 233 | } 234 | table.body .container { 235 | padding: 0 !important; 236 | width: 100% !important; 237 | } 238 | table.body .main { 239 | border-left-width: 0 !important; 240 | border-radius: 0 !important; 241 | border-right-width: 0 !important; 242 | } 243 | table.body .btn table { 244 | width: 100% !important; 245 | } 246 | table.body .btn a { 247 | width: 100% !important; 248 | } 249 | table.body .img-responsive { 250 | height: auto !important; 251 | max-width: 100% !important; 252 | width: auto !important; 253 | } 254 | } 255 | /* ------------------------------------- 256 | PRESERVE THESE STYLES IN THE HEAD 257 | ------------------------------------- */ 258 | @media all { 259 | .ExternalClass { 260 | width: 100%; 261 | } 262 | .ExternalClass, 263 | .ExternalClass p, 264 | .ExternalClass span, 265 | .ExternalClass font, 266 | .ExternalClass td, 267 | .ExternalClass div { 268 | line-height: 100%; 269 | } 270 | .apple-link a { 271 | color: inherit !important; 272 | font-family: inherit !important; 273 | font-size: inherit !important; 274 | font-weight: inherit !important; 275 | line-height: inherit !important; 276 | text-decoration: none !important; 277 | } 278 | #MessageViewBody a { 279 | color: inherit; 280 | text-decoration: none; 281 | font-size: inherit; 282 | font-family: inherit; 283 | font-weight: inherit; 284 | line-height: inherit; 285 | } 286 | .btn-primary table td:hover { 287 | background-color: #34495e !important; 288 | } 289 | .btn-primary a:hover { 290 | background-color: #34495e !important; 291 | border-color: #34495e !important; 292 | } 293 | } -------------------------------------------------------------------------------- /src/controllers/auth.controller.ts: -------------------------------------------------------------------------------- 1 | import { CookieOptions, NextFunction, Request, Response } from 'express'; 2 | import config from 'config'; 3 | import crypto from 'crypto'; 4 | import { 5 | CreateUserInput, 6 | LoginUserInput, 7 | VerifyEmailInput, 8 | } from '../schemas/user.schema'; 9 | import { 10 | createUser, 11 | findUser, 12 | findUserByEmail, 13 | findUserById, 14 | signTokens, 15 | } from '../services/user.service'; 16 | import AppError from '../utils/appError'; 17 | import redisClient from '../utils/connectRedis'; 18 | import { signJwt, verifyJwt } from '../utils/jwt'; 19 | import { User } from '../entities/user.entity'; 20 | import Email from '../utils/email'; 21 | 22 | const cookiesOptions: CookieOptions = { 23 | httpOnly: true, 24 | sameSite: 'lax', 25 | }; 26 | 27 | if (process.env.NODE_ENV === 'production') cookiesOptions.secure = true; 28 | 29 | const accessTokenCookieOptions: CookieOptions = { 30 | ...cookiesOptions, 31 | expires: new Date( 32 | Date.now() + config.get('accessTokenExpiresIn') * 60 * 1000 33 | ), 34 | maxAge: config.get('accessTokenExpiresIn') * 60 * 1000, 35 | }; 36 | 37 | const refreshTokenCookieOptions: CookieOptions = { 38 | ...cookiesOptions, 39 | expires: new Date( 40 | Date.now() + config.get('refreshTokenExpiresIn') * 60 * 1000 41 | ), 42 | maxAge: config.get('refreshTokenExpiresIn') * 60 * 1000, 43 | }; 44 | 45 | export const registerUserHandler = async ( 46 | req: Request<{}, {}, CreateUserInput>, 47 | res: Response, 48 | next: NextFunction 49 | ) => { 50 | try { 51 | const { name, password, email } = req.body; 52 | 53 | const newUser = await createUser({ 54 | name, 55 | email: email.toLowerCase(), 56 | password, 57 | }); 58 | 59 | const { hashedVerificationCode, verificationCode } = 60 | User.createVerificationCode(); 61 | newUser.verificationCode = hashedVerificationCode; 62 | await newUser.save(); 63 | 64 | // Send Verification Email 65 | const redirectUrl = `${config.get( 66 | 'origin' 67 | )}/verifyemail/${verificationCode}`; 68 | 69 | try { 70 | await new Email(newUser, redirectUrl).sendVerificationCode(); 71 | 72 | res.status(201).json({ 73 | status: 'success', 74 | message: 75 | 'An email with a verification code has been sent to your email', 76 | }); 77 | } catch (error) { 78 | newUser.verificationCode = null; 79 | await newUser.save(); 80 | 81 | return res.status(500).json({ 82 | status: 'error', 83 | message: 'There was an error sending email, please try again', 84 | }); 85 | } 86 | } catch (err: any) { 87 | if (err.code === '23505') { 88 | return res.status(409).json({ 89 | status: 'fail', 90 | message: 'User with that email already exist', 91 | }); 92 | } 93 | next(err); 94 | } 95 | }; 96 | 97 | export const loginUserHandler = async ( 98 | req: Request<{}, {}, LoginUserInput>, 99 | res: Response, 100 | next: NextFunction 101 | ) => { 102 | try { 103 | const { email, password } = req.body; 104 | const user = await findUserByEmail({ email }); 105 | 106 | // 1. Check if user exist 107 | if (!user) { 108 | return next(new AppError(400, 'Invalid email or password')); 109 | } 110 | 111 | // 2.Check if user is verified 112 | if (!user.verified) { 113 | return next( 114 | new AppError( 115 | 401, 116 | 'You are not verified, check your email to verify your account' 117 | ) 118 | ); 119 | } 120 | 121 | //3. Check if password is valid 122 | if (!(await User.comparePasswords(password, user.password))) { 123 | return next(new AppError(400, 'Invalid email or password')); 124 | } 125 | 126 | // 4. Sign Access and Refresh Tokens 127 | const { access_token, refresh_token } = await signTokens(user); 128 | 129 | // 5. Add Cookies 130 | res.cookie('access_token', access_token, accessTokenCookieOptions); 131 | res.cookie('refresh_token', refresh_token, refreshTokenCookieOptions); 132 | res.cookie('logged_in', true, { 133 | ...accessTokenCookieOptions, 134 | httpOnly: false, 135 | }); 136 | 137 | // 6. Send response 138 | res.status(200).json({ 139 | status: 'success', 140 | access_token, 141 | }); 142 | } catch (err: any) { 143 | next(err); 144 | } 145 | }; 146 | 147 | export const verifyEmailHandler = async ( 148 | req: Request, 149 | res: Response, 150 | next: NextFunction 151 | ) => { 152 | try { 153 | const verificationCode = crypto 154 | .createHash('sha256') 155 | .update(req.params.verificationCode) 156 | .digest('hex'); 157 | 158 | const user = await findUser({ verificationCode }); 159 | 160 | if (!user) { 161 | return next(new AppError(401, 'Could not verify email')); 162 | } 163 | 164 | user.verified = true; 165 | user.verificationCode = null; 166 | await user.save(); 167 | 168 | res.status(200).json({ 169 | status: 'success', 170 | message: 'Email verified successfully', 171 | }); 172 | } catch (err: any) { 173 | next(err); 174 | } 175 | }; 176 | 177 | export const refreshAccessTokenHandler = async ( 178 | req: Request, 179 | res: Response, 180 | next: NextFunction 181 | ) => { 182 | try { 183 | const refresh_token = req.cookies.refresh_token; 184 | 185 | const message = 'Could not refresh access token'; 186 | 187 | if (!refresh_token) { 188 | return next(new AppError(403, message)); 189 | } 190 | 191 | // Validate refresh token 192 | const decoded = verifyJwt<{ sub: string }>( 193 | refresh_token, 194 | 'refreshTokenPublicKey' 195 | ); 196 | 197 | if (!decoded) { 198 | return next(new AppError(403, message)); 199 | } 200 | 201 | // Check if user has a valid session 202 | const session = await redisClient.get(decoded.sub); 203 | 204 | if (!session) { 205 | return next(new AppError(403, message)); 206 | } 207 | 208 | // Check if user still exist 209 | const user = await findUserById(JSON.parse(session).id); 210 | 211 | if (!user) { 212 | return next(new AppError(403, message)); 213 | } 214 | 215 | // Sign new access token 216 | const access_token = signJwt({ sub: user.id }, 'accessTokenPrivateKey', { 217 | expiresIn: `${config.get('accessTokenExpiresIn')}m`, 218 | }); 219 | 220 | // 4. Add Cookies 221 | res.cookie('access_token', access_token, accessTokenCookieOptions); 222 | res.cookie('logged_in', true, { 223 | ...accessTokenCookieOptions, 224 | httpOnly: false, 225 | }); 226 | 227 | // 5. Send response 228 | res.status(200).json({ 229 | status: 'success', 230 | access_token, 231 | }); 232 | } catch (err: any) { 233 | next(err); 234 | } 235 | }; 236 | 237 | const logout = (res: Response) => { 238 | res.cookie('access_token', '', { maxAge: 1 }); 239 | res.cookie('refresh_token', '', { maxAge: 1 }); 240 | res.cookie('logged_in', '', { maxAge: 1 }); 241 | }; 242 | 243 | export const logoutHandler = async ( 244 | req: Request, 245 | res: Response, 246 | next: NextFunction 247 | ) => { 248 | try { 249 | const user = res.locals.user; 250 | 251 | await redisClient.del(user.id); 252 | logout(res); 253 | 254 | res.status(200).json({ 255 | status: 'success', 256 | }); 257 | } catch (err: any) { 258 | next(err); 259 | } 260 | }; 261 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/helper-validator-identifier@^7.16.7": 6 | version "7.16.7" 7 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" 8 | integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== 9 | 10 | "@babel/parser@^7.6.0", "@babel/parser@^7.9.6": 11 | version "7.17.10" 12 | resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.10.tgz#873b16db82a8909e0fbd7f115772f4b739f6ce78" 13 | integrity sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ== 14 | 15 | "@babel/types@^7.6.1", "@babel/types@^7.9.6": 16 | version "7.17.10" 17 | resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.10.tgz#d35d7b4467e439fcf06d195f8100e0fea7fc82c4" 18 | integrity sha512-9O26jG0mBYfGkUYCYZRnBwbVLd1UZOICEr2Em6InB6jVfsAv1GKgwXHmrSg+WFWDmeKTA6vyTZiN8tCSM5Oo3A== 19 | dependencies: 20 | "@babel/helper-validator-identifier" "^7.16.7" 21 | to-fast-properties "^2.0.0" 22 | 23 | "@cspotcode/source-map-consumer@0.8.0": 24 | version "0.8.0" 25 | resolved "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz" 26 | integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== 27 | 28 | "@cspotcode/source-map-support@0.7.0": 29 | version "0.7.0" 30 | resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz" 31 | integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== 32 | dependencies: 33 | "@cspotcode/source-map-consumer" "0.8.0" 34 | 35 | "@redis/bloom@1.0.2": 36 | version "1.0.2" 37 | resolved "https://registry.yarnpkg.com/@redis/bloom/-/bloom-1.0.2.tgz#42b82ec399a92db05e29fffcdfd9235a5fc15cdf" 38 | integrity sha512-EBw7Ag1hPgFzdznK2PBblc1kdlj5B5Cw3XwI9/oG7tSn85/HKy3X9xHy/8tm/eNXJYHLXHJL/pkwBpFMVVefkw== 39 | 40 | "@redis/client@1.1.0": 41 | version "1.1.0" 42 | resolved "https://registry.yarnpkg.com/@redis/client/-/client-1.1.0.tgz#e52a85aee802796ceb14bf27daf9550f51f238b8" 43 | integrity sha512-xO9JDIgzsZYDl3EvFhl6LC52DP3q3GCMUer8zHgKV6qSYsq1zB+pZs9+T80VgcRogrlRYhi4ZlfX6A+bHiBAgA== 44 | dependencies: 45 | cluster-key-slot "1.1.0" 46 | generic-pool "3.8.2" 47 | yallist "4.0.0" 48 | 49 | "@redis/graph@1.0.1": 50 | version "1.0.1" 51 | resolved "https://registry.yarnpkg.com/@redis/graph/-/graph-1.0.1.tgz#eabc58ba99cd70d0c907169c02b55497e4ec8a99" 52 | integrity sha512-oDE4myMCJOCVKYMygEMWuriBgqlS5FqdWerikMoJxzmmTUErnTRRgmIDa2VcgytACZMFqpAOWDzops4DOlnkfQ== 53 | 54 | "@redis/json@1.0.3": 55 | version "1.0.3" 56 | resolved "https://registry.yarnpkg.com/@redis/json/-/json-1.0.3.tgz#a13fde1d22ebff0ae2805cd8e1e70522b08ea866" 57 | integrity sha512-4X0Qv0BzD9Zlb0edkUoau5c1bInWSICqXAGrpwEltkncUwcxJIGEcVryZhLgb0p/3PkKaLIWkjhHRtLe9yiA7Q== 58 | 59 | "@redis/search@1.0.6": 60 | version "1.0.6" 61 | resolved "https://registry.yarnpkg.com/@redis/search/-/search-1.0.6.tgz#53d7451c2783f011ebc48ec4c2891264e0b22f10" 62 | integrity sha512-pP+ZQRis5P21SD6fjyCeLcQdps+LuTzp2wdUbzxEmNhleighDDTD5ck8+cYof+WLec4csZX7ks+BuoMw0RaZrA== 63 | 64 | "@redis/time-series@1.0.3": 65 | version "1.0.3" 66 | resolved "https://registry.yarnpkg.com/@redis/time-series/-/time-series-1.0.3.tgz#4cfca8e564228c0bddcdf4418cba60c20b224ac4" 67 | integrity sha512-OFp0q4SGrTH0Mruf6oFsHGea58u8vS/iI5+NpYdicaM+7BgqBZH8FFvNZ8rYYLrUO/QRqMq72NpXmxLVNcdmjA== 68 | 69 | "@selderee/plugin-htmlparser2@^0.6.0": 70 | version "0.6.0" 71 | resolved "https://registry.yarnpkg.com/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.6.0.tgz#27e994afd1c2cb647ceb5406a185a5574188069d" 72 | integrity sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA== 73 | dependencies: 74 | domhandler "^4.2.0" 75 | selderee "^0.6.0" 76 | 77 | "@sqltools/formatter@^1.2.2": 78 | version "1.2.3" 79 | resolved "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.3.tgz" 80 | integrity sha512-O3uyB/JbkAEMZaP3YqyHH7TMnex7tWyCbCI4EfJdOCoN6HIhqdJBWTM6aCCiWQ/5f5wxjgU735QAIpJbjDvmzg== 81 | 82 | "@tsconfig/node10@^1.0.7": 83 | version "1.0.8" 84 | resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz" 85 | integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== 86 | 87 | "@tsconfig/node12@^1.0.7": 88 | version "1.0.9" 89 | resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz" 90 | integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== 91 | 92 | "@tsconfig/node14@^1.0.0": 93 | version "1.0.1" 94 | resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz" 95 | integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== 96 | 97 | "@tsconfig/node16@^1.0.2": 98 | version "1.0.2" 99 | resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz" 100 | integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== 101 | 102 | "@types/bcryptjs@^2.4.2": 103 | version "2.4.2" 104 | resolved "https://registry.yarnpkg.com/@types/bcryptjs/-/bcryptjs-2.4.2.tgz#e3530eac9dd136bfdfb0e43df2c4c5ce1f77dfae" 105 | integrity sha512-LiMQ6EOPob/4yUL66SZzu6Yh77cbzJFYll+ZfaPiPPFswtIlA/Fs1MzdKYA7JApHU49zQTbJGX3PDmCpIdDBRQ== 106 | 107 | "@types/body-parser@*": 108 | version "1.19.2" 109 | resolved "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz" 110 | integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== 111 | dependencies: 112 | "@types/connect" "*" 113 | "@types/node" "*" 114 | 115 | "@types/config@^0.0.41": 116 | version "0.0.41" 117 | resolved "https://registry.npmjs.org/@types/config/-/config-0.0.41.tgz" 118 | integrity sha512-HjXUmIld0gwvyG8MU/17QtLzOyuMX4jbGuijmS9sWsob5xxgZ/hY9cbRCaHIHqTQ3HMLhwS3F8uXq3Bt9zgzHA== 119 | 120 | "@types/connect@*": 121 | version "3.4.35" 122 | resolved "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz" 123 | integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== 124 | dependencies: 125 | "@types/node" "*" 126 | 127 | "@types/cookie-parser@^1.4.3": 128 | version "1.4.3" 129 | resolved "https://registry.yarnpkg.com/@types/cookie-parser/-/cookie-parser-1.4.3.tgz#3a01df117c5705cf89a84c876b50c5a1fd427a21" 130 | integrity sha512-CqSKwFwefj4PzZ5n/iwad/bow2hTCh0FlNAeWLtQM3JA/NX/iYagIpWG2cf1bQKQ2c9gU2log5VUCrn7LDOs0w== 131 | dependencies: 132 | "@types/express" "*" 133 | 134 | "@types/cors@^2.8.12": 135 | version "2.8.12" 136 | resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080" 137 | integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw== 138 | 139 | "@types/express-serve-static-core@^4.17.18": 140 | version "4.17.28" 141 | resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz" 142 | integrity sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig== 143 | dependencies: 144 | "@types/node" "*" 145 | "@types/qs" "*" 146 | "@types/range-parser" "*" 147 | 148 | "@types/express@*", "@types/express@^4.17.13": 149 | version "4.17.13" 150 | resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" 151 | integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== 152 | dependencies: 153 | "@types/body-parser" "*" 154 | "@types/express-serve-static-core" "^4.17.18" 155 | "@types/qs" "*" 156 | "@types/serve-static" "*" 157 | 158 | "@types/html-to-text@^8.1.0": 159 | version "8.1.0" 160 | resolved "https://registry.yarnpkg.com/@types/html-to-text/-/html-to-text-8.1.0.tgz#dad0bf5d199f7e3f67eae50a36c13eadb1b56d1b" 161 | integrity sha512-54YF2fGmN4g62/w+T85uQ8n0FyBhMY5cjKZ1imsbIh4Pgbeno1mAaQktC/pv/+C2ToUYkTZis9ADgn9GRRz9nQ== 162 | 163 | "@types/jsonwebtoken@^8.5.8": 164 | version "8.5.8" 165 | resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.5.8.tgz#01b39711eb844777b7af1d1f2b4cf22fda1c0c44" 166 | integrity sha512-zm6xBQpFDIDM6o9r6HSgDeIcLy82TKWctCXEPbJJcXb5AKmi5BNNdLXneixK4lplX3PqIVcwLBCGE/kAGnlD4A== 167 | dependencies: 168 | "@types/node" "*" 169 | 170 | "@types/lodash@^4.14.182": 171 | version "4.14.182" 172 | resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.182.tgz#05301a4d5e62963227eaafe0ce04dd77c54ea5c2" 173 | integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q== 174 | 175 | "@types/mime@^1": 176 | version "1.3.2" 177 | resolved "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz" 178 | integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== 179 | 180 | "@types/morgan@^1.9.3": 181 | version "1.9.3" 182 | resolved "https://registry.yarnpkg.com/@types/morgan/-/morgan-1.9.3.tgz#ae04180dff02c437312bc0cfb1e2960086b2f540" 183 | integrity sha512-BiLcfVqGBZCyNCnCH3F4o2GmDLrpy0HeBVnNlyZG4fo88ZiE9SoiBe3C+2ezuwbjlEyT+PDZ17//TAlRxAn75Q== 184 | dependencies: 185 | "@types/node" "*" 186 | 187 | "@types/multer@^1.4.7": 188 | version "1.4.7" 189 | resolved "https://registry.yarnpkg.com/@types/multer/-/multer-1.4.7.tgz#89cf03547c28c7bbcc726f029e2a76a7232cc79e" 190 | integrity sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA== 191 | dependencies: 192 | "@types/express" "*" 193 | 194 | "@types/node@*", "@types/node@^16.11.10": 195 | version "16.11.33" 196 | resolved "https://registry.npmjs.org/@types/node/-/node-16.11.33.tgz" 197 | integrity sha512-0PJ0vg+JyU0MIan58IOIFRtSvsb7Ri+7Wltx2qAg94eMOrpg4+uuP3aUHCpxXc1i0jCXiC+zIamSZh3l9AbcQA== 198 | 199 | "@types/nodemailer@^6.4.4": 200 | version "6.4.4" 201 | resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.4.tgz#c265f7e7a51df587597b3a49a023acaf0c741f4b" 202 | integrity sha512-Ksw4t7iliXeYGvIQcSIgWQ5BLuC/mljIEbjf615svhZL10PE9t+ei8O9gDaD3FPCasUJn9KTLwz2JFJyiiyuqw== 203 | dependencies: 204 | "@types/node" "*" 205 | 206 | "@types/pug@^2.0.6": 207 | version "2.0.6" 208 | resolved "https://registry.yarnpkg.com/@types/pug/-/pug-2.0.6.tgz#f830323c88172e66826d0bde413498b61054b5a6" 209 | integrity sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg== 210 | 211 | "@types/qs@*": 212 | version "6.9.7" 213 | resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz" 214 | integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== 215 | 216 | "@types/range-parser@*": 217 | version "1.2.4" 218 | resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz" 219 | integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== 220 | 221 | "@types/serve-static@*": 222 | version "1.13.10" 223 | resolved "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz" 224 | integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ== 225 | dependencies: 226 | "@types/mime" "^1" 227 | "@types/node" "*" 228 | 229 | "@types/sharp@^0.30.2": 230 | version "0.30.2" 231 | resolved "https://registry.yarnpkg.com/@types/sharp/-/sharp-0.30.2.tgz#df5ff34140b3bad165482e6f3d26b08e42a0503a" 232 | integrity sha512-uLCBwjDg/BTcQit0dpNGvkIjvH3wsb8zpaJePCjvONBBSfaKHoxXBIuq1MT8DMQEfk2fKYnpC9QExCgFhkGkMQ== 233 | dependencies: 234 | "@types/node" "*" 235 | 236 | "@types/strip-bom@^3.0.0": 237 | version "3.0.0" 238 | resolved "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz" 239 | integrity sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I= 240 | 241 | "@types/strip-json-comments@0.0.30": 242 | version "0.0.30" 243 | resolved "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz" 244 | integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ== 245 | 246 | accepts@~1.3.8: 247 | version "1.3.8" 248 | resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" 249 | integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== 250 | dependencies: 251 | mime-types "~2.1.34" 252 | negotiator "0.6.3" 253 | 254 | acorn-walk@^8.1.1: 255 | version "8.2.0" 256 | resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" 257 | integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== 258 | 259 | acorn@^7.1.1: 260 | version "7.4.1" 261 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" 262 | integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== 263 | 264 | acorn@^8.4.1: 265 | version "8.7.1" 266 | resolved "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz" 267 | integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== 268 | 269 | ansi-regex@^2.0.0: 270 | version "2.1.1" 271 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 272 | integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= 273 | 274 | ansi-regex@^5.0.1: 275 | version "5.0.1" 276 | resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" 277 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 278 | 279 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 280 | version "4.3.0" 281 | resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" 282 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 283 | dependencies: 284 | color-convert "^2.0.1" 285 | 286 | any-promise@^1.0.0: 287 | version "1.3.0" 288 | resolved "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz" 289 | integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= 290 | 291 | anymatch@~3.1.2: 292 | version "3.1.2" 293 | resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz" 294 | integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== 295 | dependencies: 296 | normalize-path "^3.0.0" 297 | picomatch "^2.0.4" 298 | 299 | app-root-path@^3.0.0: 300 | version "3.0.0" 301 | resolved "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz" 302 | integrity sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw== 303 | 304 | append-field@^1.0.0: 305 | version "1.0.0" 306 | resolved "https://registry.yarnpkg.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56" 307 | integrity sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY= 308 | 309 | aproba@^1.0.3: 310 | version "1.2.0" 311 | resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" 312 | integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== 313 | 314 | are-we-there-yet@~1.1.2: 315 | version "1.1.7" 316 | resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146" 317 | integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g== 318 | dependencies: 319 | delegates "^1.0.0" 320 | readable-stream "^2.0.6" 321 | 322 | arg@^4.1.0: 323 | version "4.1.3" 324 | resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" 325 | integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== 326 | 327 | argparse@^2.0.1: 328 | version "2.0.1" 329 | resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" 330 | integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 331 | 332 | array-flatten@1.1.1: 333 | version "1.1.1" 334 | resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" 335 | integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= 336 | 337 | asap@~2.0.3: 338 | version "2.0.6" 339 | resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" 340 | integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= 341 | 342 | assert-never@^1.2.1: 343 | version "1.2.1" 344 | resolved "https://registry.yarnpkg.com/assert-never/-/assert-never-1.2.1.tgz#11f0e363bf146205fb08193b5c7b90f4d1cf44fe" 345 | integrity sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw== 346 | 347 | babel-walk@3.0.0-canary-5: 348 | version "3.0.0-canary-5" 349 | resolved "https://registry.yarnpkg.com/babel-walk/-/babel-walk-3.0.0-canary-5.tgz#f66ecd7298357aee44955f235a6ef54219104b11" 350 | integrity sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw== 351 | dependencies: 352 | "@babel/types" "^7.9.6" 353 | 354 | balanced-match@^1.0.0: 355 | version "1.0.2" 356 | resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" 357 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 358 | 359 | base64-js@^1.3.1: 360 | version "1.5.1" 361 | resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" 362 | integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== 363 | 364 | basic-auth@~2.0.1: 365 | version "2.0.1" 366 | resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" 367 | integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== 368 | dependencies: 369 | safe-buffer "5.1.2" 370 | 371 | bcryptjs@^2.4.3: 372 | version "2.4.3" 373 | resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb" 374 | integrity sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms= 375 | 376 | binary-extensions@^2.0.0: 377 | version "2.2.0" 378 | resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" 379 | integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== 380 | 381 | bl@^4.0.3: 382 | version "4.1.0" 383 | resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" 384 | integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== 385 | dependencies: 386 | buffer "^5.5.0" 387 | inherits "^2.0.4" 388 | readable-stream "^3.4.0" 389 | 390 | body-parser@1.20.0, body-parser@^1.19.1: 391 | version "1.20.0" 392 | resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5" 393 | integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg== 394 | dependencies: 395 | bytes "3.1.2" 396 | content-type "~1.0.4" 397 | debug "2.6.9" 398 | depd "2.0.0" 399 | destroy "1.2.0" 400 | http-errors "2.0.0" 401 | iconv-lite "0.4.24" 402 | on-finished "2.4.1" 403 | qs "6.10.3" 404 | raw-body "2.5.1" 405 | type-is "~1.6.18" 406 | unpipe "1.0.0" 407 | 408 | brace-expansion@^1.1.7: 409 | version "1.1.11" 410 | resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" 411 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 412 | dependencies: 413 | balanced-match "^1.0.0" 414 | concat-map "0.0.1" 415 | 416 | braces@~3.0.2: 417 | version "3.0.2" 418 | resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" 419 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 420 | dependencies: 421 | fill-range "^7.0.1" 422 | 423 | buffer-equal-constant-time@1.0.1: 424 | version "1.0.1" 425 | resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" 426 | integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= 427 | 428 | buffer-from@^1.0.0: 429 | version "1.1.2" 430 | resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" 431 | integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== 432 | 433 | buffer-writer@2.0.0: 434 | version "2.0.0" 435 | resolved "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz" 436 | integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== 437 | 438 | buffer@^5.5.0: 439 | version "5.7.1" 440 | resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" 441 | integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== 442 | dependencies: 443 | base64-js "^1.3.1" 444 | ieee754 "^1.1.13" 445 | 446 | buffer@^6.0.3: 447 | version "6.0.3" 448 | resolved "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz" 449 | integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== 450 | dependencies: 451 | base64-js "^1.3.1" 452 | ieee754 "^1.2.1" 453 | 454 | busboy@^0.2.11: 455 | version "0.2.14" 456 | resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.14.tgz#6c2a622efcf47c57bbbe1e2a9c37ad36c7925453" 457 | integrity sha1-bCpiLvz0fFe7vh4qnDetNseSVFM= 458 | dependencies: 459 | dicer "0.2.5" 460 | readable-stream "1.1.x" 461 | 462 | bytes@3.1.2: 463 | version "3.1.2" 464 | resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" 465 | integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== 466 | 467 | call-bind@^1.0.0, call-bind@^1.0.2: 468 | version "1.0.2" 469 | resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" 470 | integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== 471 | dependencies: 472 | function-bind "^1.1.1" 473 | get-intrinsic "^1.0.2" 474 | 475 | chalk@^4.0.0, chalk@^4.1.0: 476 | version "4.1.2" 477 | resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" 478 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 479 | dependencies: 480 | ansi-styles "^4.1.0" 481 | supports-color "^7.1.0" 482 | 483 | character-parser@^2.2.0: 484 | version "2.2.0" 485 | resolved "https://registry.yarnpkg.com/character-parser/-/character-parser-2.2.0.tgz#c7ce28f36d4bcd9744e5ffc2c5fcde1c73261fc0" 486 | integrity sha1-x84o821LzZdE5f/CxfzeHHMmH8A= 487 | dependencies: 488 | is-regex "^1.0.3" 489 | 490 | chokidar@^3.5.1: 491 | version "3.5.3" 492 | resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" 493 | integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== 494 | dependencies: 495 | anymatch "~3.1.2" 496 | braces "~3.0.2" 497 | glob-parent "~5.1.2" 498 | is-binary-path "~2.1.0" 499 | is-glob "~4.0.1" 500 | normalize-path "~3.0.0" 501 | readdirp "~3.6.0" 502 | optionalDependencies: 503 | fsevents "~2.3.2" 504 | 505 | chownr@^1.1.1: 506 | version "1.1.4" 507 | resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" 508 | integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== 509 | 510 | cli-highlight@^2.1.11: 511 | version "2.1.11" 512 | resolved "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz" 513 | integrity sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg== 514 | dependencies: 515 | chalk "^4.0.0" 516 | highlight.js "^10.7.1" 517 | mz "^2.4.0" 518 | parse5 "^5.1.1" 519 | parse5-htmlparser2-tree-adapter "^6.0.0" 520 | yargs "^16.0.0" 521 | 522 | cliui@^7.0.2: 523 | version "7.0.4" 524 | resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz" 525 | integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== 526 | dependencies: 527 | string-width "^4.2.0" 528 | strip-ansi "^6.0.0" 529 | wrap-ansi "^7.0.0" 530 | 531 | cluster-key-slot@1.1.0: 532 | version "1.1.0" 533 | resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d" 534 | integrity sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw== 535 | 536 | code-point-at@^1.0.0: 537 | version "1.1.0" 538 | resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" 539 | integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= 540 | 541 | color-convert@^2.0.1: 542 | version "2.0.1" 543 | resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" 544 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 545 | dependencies: 546 | color-name "~1.1.4" 547 | 548 | color-name@^1.0.0, color-name@~1.1.4: 549 | version "1.1.4" 550 | resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" 551 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 552 | 553 | color-string@^1.9.0: 554 | version "1.9.1" 555 | resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" 556 | integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== 557 | dependencies: 558 | color-name "^1.0.0" 559 | simple-swizzle "^0.2.2" 560 | 561 | color@^4.2.3: 562 | version "4.2.3" 563 | resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a" 564 | integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A== 565 | dependencies: 566 | color-convert "^2.0.1" 567 | color-string "^1.9.0" 568 | 569 | commander@^2.19.0: 570 | version "2.20.3" 571 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" 572 | integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 573 | 574 | concat-map@0.0.1: 575 | version "0.0.1" 576 | resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" 577 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 578 | 579 | concat-stream@^1.5.2: 580 | version "1.6.2" 581 | resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" 582 | integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== 583 | dependencies: 584 | buffer-from "^1.0.0" 585 | inherits "^2.0.3" 586 | readable-stream "^2.2.2" 587 | typedarray "^0.0.6" 588 | 589 | config@^3.3.7: 590 | version "3.3.7" 591 | resolved "https://registry.npmjs.org/config/-/config-3.3.7.tgz" 592 | integrity sha512-mX/n7GKDYZMqvvkY6e6oBY49W8wxdmQt+ho/5lhwFDXqQW9gI+Ahp8EKp8VAbISPnmf2+Bv5uZK7lKXZ6pf1aA== 593 | dependencies: 594 | json5 "^2.1.1" 595 | 596 | console-control-strings@^1.0.0, console-control-strings@~1.1.0: 597 | version "1.1.0" 598 | resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" 599 | integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= 600 | 601 | constantinople@^4.0.1: 602 | version "4.0.1" 603 | resolved "https://registry.yarnpkg.com/constantinople/-/constantinople-4.0.1.tgz#0def113fa0e4dc8de83331a5cf79c8b325213151" 604 | integrity sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw== 605 | dependencies: 606 | "@babel/parser" "^7.6.0" 607 | "@babel/types" "^7.6.1" 608 | 609 | content-disposition@0.5.4: 610 | version "0.5.4" 611 | resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz" 612 | integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== 613 | dependencies: 614 | safe-buffer "5.2.1" 615 | 616 | content-type@~1.0.4: 617 | version "1.0.4" 618 | resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz" 619 | integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== 620 | 621 | cookie-parser@^1.4.6: 622 | version "1.4.6" 623 | resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.6.tgz#3ac3a7d35a7a03bbc7e365073a26074824214594" 624 | integrity sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA== 625 | dependencies: 626 | cookie "0.4.1" 627 | cookie-signature "1.0.6" 628 | 629 | cookie-signature@1.0.6: 630 | version "1.0.6" 631 | resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" 632 | integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= 633 | 634 | cookie@0.4.1: 635 | version "0.4.1" 636 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" 637 | integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== 638 | 639 | cookie@0.5.0: 640 | version "0.5.0" 641 | resolved "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz" 642 | integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== 643 | 644 | core-util-is@~1.0.0: 645 | version "1.0.3" 646 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" 647 | integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== 648 | 649 | cors@^2.8.5: 650 | version "2.8.5" 651 | resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" 652 | integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== 653 | dependencies: 654 | object-assign "^4" 655 | vary "^1" 656 | 657 | create-require@^1.1.0: 658 | version "1.1.1" 659 | resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" 660 | integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== 661 | 662 | date-fns@^2.28.0: 663 | version "2.28.0" 664 | resolved "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz" 665 | integrity sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw== 666 | 667 | debug@2.6.9: 668 | version "2.6.9" 669 | resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" 670 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 671 | dependencies: 672 | ms "2.0.0" 673 | 674 | debug@^4.3.3: 675 | version "4.3.4" 676 | resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" 677 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 678 | dependencies: 679 | ms "2.1.2" 680 | 681 | decompress-response@^6.0.0: 682 | version "6.0.0" 683 | resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" 684 | integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== 685 | dependencies: 686 | mimic-response "^3.1.0" 687 | 688 | deep-extend@^0.6.0: 689 | version "0.6.0" 690 | resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" 691 | integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== 692 | 693 | deepmerge@^4.2.2: 694 | version "4.2.2" 695 | resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" 696 | integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== 697 | 698 | delegates@^1.0.0: 699 | version "1.0.0" 700 | resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" 701 | integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= 702 | 703 | depd@2.0.0, depd@~2.0.0: 704 | version "2.0.0" 705 | resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" 706 | integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== 707 | 708 | destroy@1.2.0: 709 | version "1.2.0" 710 | resolved "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz" 711 | integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== 712 | 713 | detect-libc@^2.0.0, detect-libc@^2.0.1: 714 | version "2.0.1" 715 | resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" 716 | integrity sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w== 717 | 718 | dicer@0.2.5: 719 | version "0.2.5" 720 | resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.2.5.tgz#5996c086bb33218c812c090bddc09cd12facb70f" 721 | integrity sha1-WZbAhrszIYyBLAkL3cCc0S+stw8= 722 | dependencies: 723 | readable-stream "1.1.x" 724 | streamsearch "0.1.2" 725 | 726 | diff@^4.0.1: 727 | version "4.0.2" 728 | resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" 729 | integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== 730 | 731 | discontinuous-range@1.0.0: 732 | version "1.0.0" 733 | resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a" 734 | integrity sha1-44Mx8IRLukm5qctxx3FYWqsbxlo= 735 | 736 | doctypes@^1.1.0: 737 | version "1.1.0" 738 | resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9" 739 | integrity sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk= 740 | 741 | dom-serializer@^1.0.1: 742 | version "1.4.1" 743 | resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" 744 | integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== 745 | dependencies: 746 | domelementtype "^2.0.1" 747 | domhandler "^4.2.0" 748 | entities "^2.0.0" 749 | 750 | domelementtype@^2.0.1, domelementtype@^2.2.0: 751 | version "2.3.0" 752 | resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" 753 | integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== 754 | 755 | domhandler@^4.0.0, domhandler@^4.2.0: 756 | version "4.3.1" 757 | resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" 758 | integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== 759 | dependencies: 760 | domelementtype "^2.2.0" 761 | 762 | domutils@^2.5.2: 763 | version "2.8.0" 764 | resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" 765 | integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== 766 | dependencies: 767 | dom-serializer "^1.0.1" 768 | domelementtype "^2.2.0" 769 | domhandler "^4.2.0" 770 | 771 | dotenv@^16.0.0: 772 | version "16.0.0" 773 | resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz" 774 | integrity sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q== 775 | 776 | dynamic-dedupe@^0.3.0: 777 | version "0.3.0" 778 | resolved "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz" 779 | integrity sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE= 780 | dependencies: 781 | xtend "^4.0.0" 782 | 783 | ecdsa-sig-formatter@1.0.11: 784 | version "1.0.11" 785 | resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" 786 | integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== 787 | dependencies: 788 | safe-buffer "^5.0.1" 789 | 790 | ee-first@1.1.1: 791 | version "1.1.1" 792 | resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" 793 | integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= 794 | 795 | emoji-regex@^8.0.0: 796 | version "8.0.0" 797 | resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" 798 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 799 | 800 | encodeurl@~1.0.2: 801 | version "1.0.2" 802 | resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" 803 | integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= 804 | 805 | end-of-stream@^1.1.0, end-of-stream@^1.4.1: 806 | version "1.4.4" 807 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" 808 | integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== 809 | dependencies: 810 | once "^1.4.0" 811 | 812 | entities@^2.0.0: 813 | version "2.2.0" 814 | resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" 815 | integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== 816 | 817 | envalid@^7.3.1: 818 | version "7.3.1" 819 | resolved "https://registry.yarnpkg.com/envalid/-/envalid-7.3.1.tgz#5bf6bbb4effab2d64a1991d8078b4ae38924f0d2" 820 | integrity sha512-KL1YRwn8WcoF/Ty7t+yLLtZol01xr9ZJMTjzoGRM8NaSU+nQQjSWOQKKJhJP2P57bpdakJ9jbxqQX4fGTOicZg== 821 | dependencies: 822 | tslib "2.3.1" 823 | 824 | escalade@^3.1.1: 825 | version "3.1.1" 826 | resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" 827 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== 828 | 829 | escape-html@~1.0.3: 830 | version "1.0.3" 831 | resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" 832 | integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= 833 | 834 | etag@~1.8.1: 835 | version "1.8.1" 836 | resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" 837 | integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= 838 | 839 | expand-template@^2.0.3: 840 | version "2.0.3" 841 | resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" 842 | integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== 843 | 844 | express@^4.18.1: 845 | version "4.18.1" 846 | resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf" 847 | integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q== 848 | dependencies: 849 | accepts "~1.3.8" 850 | array-flatten "1.1.1" 851 | body-parser "1.20.0" 852 | content-disposition "0.5.4" 853 | content-type "~1.0.4" 854 | cookie "0.5.0" 855 | cookie-signature "1.0.6" 856 | debug "2.6.9" 857 | depd "2.0.0" 858 | encodeurl "~1.0.2" 859 | escape-html "~1.0.3" 860 | etag "~1.8.1" 861 | finalhandler "1.2.0" 862 | fresh "0.5.2" 863 | http-errors "2.0.0" 864 | merge-descriptors "1.0.1" 865 | methods "~1.1.2" 866 | on-finished "2.4.1" 867 | parseurl "~1.3.3" 868 | path-to-regexp "0.1.7" 869 | proxy-addr "~2.0.7" 870 | qs "6.10.3" 871 | range-parser "~1.2.1" 872 | safe-buffer "5.2.1" 873 | send "0.18.0" 874 | serve-static "1.15.0" 875 | setprototypeof "1.2.0" 876 | statuses "2.0.1" 877 | type-is "~1.6.18" 878 | utils-merge "1.0.1" 879 | vary "~1.1.2" 880 | 881 | fill-range@^7.0.1: 882 | version "7.0.1" 883 | resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" 884 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 885 | dependencies: 886 | to-regex-range "^5.0.1" 887 | 888 | finalhandler@1.2.0: 889 | version "1.2.0" 890 | resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz" 891 | integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== 892 | dependencies: 893 | debug "2.6.9" 894 | encodeurl "~1.0.2" 895 | escape-html "~1.0.3" 896 | on-finished "2.4.1" 897 | parseurl "~1.3.3" 898 | statuses "2.0.1" 899 | unpipe "~1.0.0" 900 | 901 | forwarded@0.2.0: 902 | version "0.2.0" 903 | resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" 904 | integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== 905 | 906 | fresh@0.5.2: 907 | version "0.5.2" 908 | resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" 909 | integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= 910 | 911 | fs-constants@^1.0.0: 912 | version "1.0.0" 913 | resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" 914 | integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== 915 | 916 | fs.realpath@^1.0.0: 917 | version "1.0.0" 918 | resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" 919 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 920 | 921 | fsevents@~2.3.2: 922 | version "2.3.2" 923 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" 924 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== 925 | 926 | function-bind@^1.1.1: 927 | version "1.1.1" 928 | resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" 929 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 930 | 931 | gauge@~2.7.3: 932 | version "2.7.4" 933 | resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" 934 | integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= 935 | dependencies: 936 | aproba "^1.0.3" 937 | console-control-strings "^1.0.0" 938 | has-unicode "^2.0.0" 939 | object-assign "^4.1.0" 940 | signal-exit "^3.0.0" 941 | string-width "^1.0.1" 942 | strip-ansi "^3.0.1" 943 | wide-align "^1.1.0" 944 | 945 | generic-pool@3.8.2: 946 | version "3.8.2" 947 | resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.8.2.tgz#aab4f280adb522fdfbdc5e5b64d718d3683f04e9" 948 | integrity sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg== 949 | 950 | get-caller-file@^2.0.5: 951 | version "2.0.5" 952 | resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" 953 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 954 | 955 | get-intrinsic@^1.0.2: 956 | version "1.1.1" 957 | resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz" 958 | integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== 959 | dependencies: 960 | function-bind "^1.1.1" 961 | has "^1.0.3" 962 | has-symbols "^1.0.1" 963 | 964 | github-from-package@0.0.0: 965 | version "0.0.0" 966 | resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" 967 | integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= 968 | 969 | glob-parent@~5.1.2: 970 | version "5.1.2" 971 | resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" 972 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 973 | dependencies: 974 | is-glob "^4.0.1" 975 | 976 | glob@^7.1.3, glob@^7.2.0: 977 | version "7.2.0" 978 | resolved "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz" 979 | integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== 980 | dependencies: 981 | fs.realpath "^1.0.0" 982 | inflight "^1.0.4" 983 | inherits "2" 984 | minimatch "^3.0.4" 985 | once "^1.3.0" 986 | path-is-absolute "^1.0.0" 987 | 988 | has-flag@^4.0.0: 989 | version "4.0.0" 990 | resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" 991 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 992 | 993 | has-symbols@^1.0.1, has-symbols@^1.0.2: 994 | version "1.0.3" 995 | resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" 996 | integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== 997 | 998 | has-tostringtag@^1.0.0: 999 | version "1.0.0" 1000 | resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" 1001 | integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== 1002 | dependencies: 1003 | has-symbols "^1.0.2" 1004 | 1005 | has-unicode@^2.0.0: 1006 | version "2.0.1" 1007 | resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" 1008 | integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= 1009 | 1010 | has@^1.0.3: 1011 | version "1.0.3" 1012 | resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" 1013 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 1014 | dependencies: 1015 | function-bind "^1.1.1" 1016 | 1017 | he@^1.2.0: 1018 | version "1.2.0" 1019 | resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" 1020 | integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== 1021 | 1022 | highlight.js@^10.7.1: 1023 | version "10.7.3" 1024 | resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz" 1025 | integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== 1026 | 1027 | html-to-text@^8.2.0: 1028 | version "8.2.0" 1029 | resolved "https://registry.yarnpkg.com/html-to-text/-/html-to-text-8.2.0.tgz#8b35e280ba7fc27710b7aa76d4500aab30731924" 1030 | integrity sha512-CLXExYn1b++Lgri+ZyVvbUEFwzkLZppjjZOwB7X1qv2jIi8MrMEvxWX5KQ7zATAzTvcqgmtO00M2kCRMtEdOKQ== 1031 | dependencies: 1032 | "@selderee/plugin-htmlparser2" "^0.6.0" 1033 | deepmerge "^4.2.2" 1034 | he "^1.2.0" 1035 | htmlparser2 "^6.1.0" 1036 | minimist "^1.2.6" 1037 | selderee "^0.6.0" 1038 | 1039 | htmlparser2@^6.1.0: 1040 | version "6.1.0" 1041 | resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" 1042 | integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== 1043 | dependencies: 1044 | domelementtype "^2.0.1" 1045 | domhandler "^4.0.0" 1046 | domutils "^2.5.2" 1047 | entities "^2.0.0" 1048 | 1049 | http-errors@2.0.0: 1050 | version "2.0.0" 1051 | resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz" 1052 | integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== 1053 | dependencies: 1054 | depd "2.0.0" 1055 | inherits "2.0.4" 1056 | setprototypeof "1.2.0" 1057 | statuses "2.0.1" 1058 | toidentifier "1.0.1" 1059 | 1060 | iconv-lite@0.4.24: 1061 | version "0.4.24" 1062 | resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" 1063 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 1064 | dependencies: 1065 | safer-buffer ">= 2.1.2 < 3" 1066 | 1067 | ieee754@^1.1.13, ieee754@^1.2.1: 1068 | version "1.2.1" 1069 | resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" 1070 | integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== 1071 | 1072 | inflight@^1.0.4: 1073 | version "1.0.6" 1074 | resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" 1075 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 1076 | dependencies: 1077 | once "^1.3.0" 1078 | wrappy "1" 1079 | 1080 | inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: 1081 | version "2.0.4" 1082 | resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" 1083 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 1084 | 1085 | ini@~1.3.0: 1086 | version "1.3.8" 1087 | resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" 1088 | integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== 1089 | 1090 | ipaddr.js@1.9.1: 1091 | version "1.9.1" 1092 | resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" 1093 | integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== 1094 | 1095 | is-arrayish@^0.3.1: 1096 | version "0.3.2" 1097 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" 1098 | integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== 1099 | 1100 | is-binary-path@~2.1.0: 1101 | version "2.1.0" 1102 | resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" 1103 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 1104 | dependencies: 1105 | binary-extensions "^2.0.0" 1106 | 1107 | is-core-module@^2.8.1: 1108 | version "2.9.0" 1109 | resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz" 1110 | integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== 1111 | dependencies: 1112 | has "^1.0.3" 1113 | 1114 | is-expression@^4.0.0: 1115 | version "4.0.0" 1116 | resolved "https://registry.yarnpkg.com/is-expression/-/is-expression-4.0.0.tgz#c33155962abf21d0afd2552514d67d2ec16fd2ab" 1117 | integrity sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A== 1118 | dependencies: 1119 | acorn "^7.1.1" 1120 | object-assign "^4.1.1" 1121 | 1122 | is-extglob@^2.1.1: 1123 | version "2.1.1" 1124 | resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" 1125 | integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= 1126 | 1127 | is-fullwidth-code-point@^1.0.0: 1128 | version "1.0.0" 1129 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" 1130 | integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= 1131 | dependencies: 1132 | number-is-nan "^1.0.0" 1133 | 1134 | is-fullwidth-code-point@^3.0.0: 1135 | version "3.0.0" 1136 | resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" 1137 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 1138 | 1139 | is-glob@^4.0.1, is-glob@~4.0.1: 1140 | version "4.0.3" 1141 | resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" 1142 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 1143 | dependencies: 1144 | is-extglob "^2.1.1" 1145 | 1146 | is-number@^7.0.0: 1147 | version "7.0.0" 1148 | resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" 1149 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 1150 | 1151 | is-promise@^2.0.0: 1152 | version "2.2.2" 1153 | resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" 1154 | integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== 1155 | 1156 | is-regex@^1.0.3: 1157 | version "1.1.4" 1158 | resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" 1159 | integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== 1160 | dependencies: 1161 | call-bind "^1.0.2" 1162 | has-tostringtag "^1.0.0" 1163 | 1164 | isarray@0.0.1: 1165 | version "0.0.1" 1166 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" 1167 | integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= 1168 | 1169 | isarray@~1.0.0: 1170 | version "1.0.0" 1171 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 1172 | integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= 1173 | 1174 | js-stringify@^1.0.2: 1175 | version "1.0.2" 1176 | resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db" 1177 | integrity sha1-Fzb939lyTyijaCrcYjCufk6Weds= 1178 | 1179 | js-yaml@^4.1.0: 1180 | version "4.1.0" 1181 | resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" 1182 | integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== 1183 | dependencies: 1184 | argparse "^2.0.1" 1185 | 1186 | json5@^2.1.1: 1187 | version "2.2.1" 1188 | resolved "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz" 1189 | integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== 1190 | 1191 | jsonwebtoken@^8.5.1: 1192 | version "8.5.1" 1193 | resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" 1194 | integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== 1195 | dependencies: 1196 | jws "^3.2.2" 1197 | lodash.includes "^4.3.0" 1198 | lodash.isboolean "^3.0.3" 1199 | lodash.isinteger "^4.0.4" 1200 | lodash.isnumber "^3.0.3" 1201 | lodash.isplainobject "^4.0.6" 1202 | lodash.isstring "^4.0.1" 1203 | lodash.once "^4.0.0" 1204 | ms "^2.1.1" 1205 | semver "^5.6.0" 1206 | 1207 | jstransformer@1.0.0: 1208 | version "1.0.0" 1209 | resolved "https://registry.yarnpkg.com/jstransformer/-/jstransformer-1.0.0.tgz#ed8bf0921e2f3f1ed4d5c1a44f68709ed24722c3" 1210 | integrity sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM= 1211 | dependencies: 1212 | is-promise "^2.0.0" 1213 | promise "^7.0.1" 1214 | 1215 | jwa@^1.4.1: 1216 | version "1.4.1" 1217 | resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" 1218 | integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== 1219 | dependencies: 1220 | buffer-equal-constant-time "1.0.1" 1221 | ecdsa-sig-formatter "1.0.11" 1222 | safe-buffer "^5.0.1" 1223 | 1224 | jws@^3.2.2: 1225 | version "3.2.2" 1226 | resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" 1227 | integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== 1228 | dependencies: 1229 | jwa "^1.4.1" 1230 | safe-buffer "^5.0.1" 1231 | 1232 | lodash.includes@^4.3.0: 1233 | version "4.3.0" 1234 | resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" 1235 | integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8= 1236 | 1237 | lodash.isboolean@^3.0.3: 1238 | version "3.0.3" 1239 | resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" 1240 | integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= 1241 | 1242 | lodash.isinteger@^4.0.4: 1243 | version "4.0.4" 1244 | resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" 1245 | integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= 1246 | 1247 | lodash.isnumber@^3.0.3: 1248 | version "3.0.3" 1249 | resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" 1250 | integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w= 1251 | 1252 | lodash.isplainobject@^4.0.6: 1253 | version "4.0.6" 1254 | resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" 1255 | integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= 1256 | 1257 | lodash.isstring@^4.0.1: 1258 | version "4.0.1" 1259 | resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" 1260 | integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= 1261 | 1262 | lodash.once@^4.0.0: 1263 | version "4.1.1" 1264 | resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" 1265 | integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= 1266 | 1267 | lodash@^4.17.21: 1268 | version "4.17.21" 1269 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 1270 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 1271 | 1272 | lru-cache@^6.0.0: 1273 | version "6.0.0" 1274 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" 1275 | integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== 1276 | dependencies: 1277 | yallist "^4.0.0" 1278 | 1279 | make-error@^1.1.1: 1280 | version "1.3.6" 1281 | resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" 1282 | integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== 1283 | 1284 | media-typer@0.3.0: 1285 | version "0.3.0" 1286 | resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" 1287 | integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= 1288 | 1289 | merge-descriptors@1.0.1: 1290 | version "1.0.1" 1291 | resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" 1292 | integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= 1293 | 1294 | methods@~1.1.2: 1295 | version "1.1.2" 1296 | resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" 1297 | integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= 1298 | 1299 | mime-db@1.52.0: 1300 | version "1.52.0" 1301 | resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" 1302 | integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== 1303 | 1304 | mime-types@~2.1.24, mime-types@~2.1.34: 1305 | version "2.1.35" 1306 | resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" 1307 | integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== 1308 | dependencies: 1309 | mime-db "1.52.0" 1310 | 1311 | mime@1.6.0: 1312 | version "1.6.0" 1313 | resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" 1314 | integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== 1315 | 1316 | mimic-response@^3.1.0: 1317 | version "3.1.0" 1318 | resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" 1319 | integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== 1320 | 1321 | minimatch@^3.0.4: 1322 | version "3.1.2" 1323 | resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" 1324 | integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== 1325 | dependencies: 1326 | brace-expansion "^1.1.7" 1327 | 1328 | minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6: 1329 | version "1.2.6" 1330 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" 1331 | integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== 1332 | 1333 | mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: 1334 | version "0.5.3" 1335 | resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" 1336 | integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== 1337 | 1338 | mkdirp@^0.5.4: 1339 | version "0.5.6" 1340 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" 1341 | integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== 1342 | dependencies: 1343 | minimist "^1.2.6" 1344 | 1345 | mkdirp@^1.0.4: 1346 | version "1.0.4" 1347 | resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" 1348 | integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== 1349 | 1350 | moo@^0.5.0, moo@^0.5.1: 1351 | version "0.5.1" 1352 | resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.1.tgz#7aae7f384b9b09f620b6abf6f74ebbcd1b65dbc4" 1353 | integrity sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w== 1354 | 1355 | morgan@^1.10.0: 1356 | version "1.10.0" 1357 | resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" 1358 | integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ== 1359 | dependencies: 1360 | basic-auth "~2.0.1" 1361 | debug "2.6.9" 1362 | depd "~2.0.0" 1363 | on-finished "~2.3.0" 1364 | on-headers "~1.0.2" 1365 | 1366 | ms@2.0.0: 1367 | version "2.0.0" 1368 | resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" 1369 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= 1370 | 1371 | ms@2.1.2: 1372 | version "2.1.2" 1373 | resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" 1374 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 1375 | 1376 | ms@2.1.3, ms@^2.1.1: 1377 | version "2.1.3" 1378 | resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" 1379 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 1380 | 1381 | multer@^1.4.4: 1382 | version "1.4.4" 1383 | resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.4.tgz#e2bc6cac0df57a8832b858d7418ccaa8ebaf7d8c" 1384 | integrity sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw== 1385 | dependencies: 1386 | append-field "^1.0.0" 1387 | busboy "^0.2.11" 1388 | concat-stream "^1.5.2" 1389 | mkdirp "^0.5.4" 1390 | object-assign "^4.1.1" 1391 | on-finished "^2.3.0" 1392 | type-is "^1.6.4" 1393 | xtend "^4.0.0" 1394 | 1395 | mz@^2.4.0: 1396 | version "2.7.0" 1397 | resolved "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz" 1398 | integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== 1399 | dependencies: 1400 | any-promise "^1.0.0" 1401 | object-assign "^4.0.1" 1402 | thenify-all "^1.0.0" 1403 | 1404 | napi-build-utils@^1.0.1: 1405 | version "1.0.2" 1406 | resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" 1407 | integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== 1408 | 1409 | nearley@^2.20.1: 1410 | version "2.20.1" 1411 | resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.20.1.tgz#246cd33eff0d012faf197ff6774d7ac78acdd474" 1412 | integrity sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ== 1413 | dependencies: 1414 | commander "^2.19.0" 1415 | moo "^0.5.0" 1416 | railroad-diagrams "^1.0.0" 1417 | randexp "0.4.6" 1418 | 1419 | negotiator@0.6.3: 1420 | version "0.6.3" 1421 | resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" 1422 | integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== 1423 | 1424 | node-abi@^3.3.0: 1425 | version "3.15.0" 1426 | resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.15.0.tgz#cd9ac8c58328129b49998cc6fa16aa5506152716" 1427 | integrity sha512-Ic6z/j6I9RLm4ov7npo1I48UQr2BEyFCqh6p7S1dhEx9jPO0GPGq/e2Rb7x7DroQrmiVMz/Bw1vJm9sPAl2nxA== 1428 | dependencies: 1429 | semver "^7.3.5" 1430 | 1431 | node-addon-api@^4.3.0: 1432 | version "4.3.0" 1433 | resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f" 1434 | integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== 1435 | 1436 | nodemailer@^6.7.5: 1437 | version "6.7.5" 1438 | resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.7.5.tgz#b30b1566f5fa2249f7bd49ced4c58bec6b25915e" 1439 | integrity sha512-6VtMpwhsrixq1HDYSBBHvW0GwiWawE75dS3oal48VqRhUvKJNnKnJo2RI/bCVQubj1vgrgscMNW4DHaD6xtMCg== 1440 | 1441 | normalize-path@^3.0.0, normalize-path@~3.0.0: 1442 | version "3.0.0" 1443 | resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" 1444 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 1445 | 1446 | npmlog@^4.0.1: 1447 | version "4.1.2" 1448 | resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" 1449 | integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== 1450 | dependencies: 1451 | are-we-there-yet "~1.1.2" 1452 | console-control-strings "~1.1.0" 1453 | gauge "~2.7.3" 1454 | set-blocking "~2.0.0" 1455 | 1456 | number-is-nan@^1.0.0: 1457 | version "1.0.1" 1458 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" 1459 | integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= 1460 | 1461 | object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: 1462 | version "4.1.1" 1463 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 1464 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 1465 | 1466 | object-inspect@^1.9.0: 1467 | version "1.12.0" 1468 | resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz" 1469 | integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== 1470 | 1471 | on-finished@2.4.1, on-finished@^2.3.0: 1472 | version "2.4.1" 1473 | resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz" 1474 | integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== 1475 | dependencies: 1476 | ee-first "1.1.1" 1477 | 1478 | on-finished@~2.3.0: 1479 | version "2.3.0" 1480 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" 1481 | integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= 1482 | dependencies: 1483 | ee-first "1.1.1" 1484 | 1485 | on-headers@~1.0.2: 1486 | version "1.0.2" 1487 | resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" 1488 | integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== 1489 | 1490 | once@^1.3.0, once@^1.3.1, once@^1.4.0: 1491 | version "1.4.0" 1492 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 1493 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 1494 | dependencies: 1495 | wrappy "1" 1496 | 1497 | packet-reader@1.0.0: 1498 | version "1.0.0" 1499 | resolved "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz" 1500 | integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ== 1501 | 1502 | parse5-htmlparser2-tree-adapter@^6.0.0: 1503 | version "6.0.1" 1504 | resolved "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz" 1505 | integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== 1506 | dependencies: 1507 | parse5 "^6.0.1" 1508 | 1509 | parse5@^5.1.1: 1510 | version "5.1.1" 1511 | resolved "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz" 1512 | integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== 1513 | 1514 | parse5@^6.0.1: 1515 | version "6.0.1" 1516 | resolved "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz" 1517 | integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== 1518 | 1519 | parseley@^0.7.0: 1520 | version "0.7.0" 1521 | resolved "https://registry.yarnpkg.com/parseley/-/parseley-0.7.0.tgz#9949e3a0ed05c5072adb04f013c2810cf49171a8" 1522 | integrity sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw== 1523 | dependencies: 1524 | moo "^0.5.1" 1525 | nearley "^2.20.1" 1526 | 1527 | parseurl@~1.3.3: 1528 | version "1.3.3" 1529 | resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" 1530 | integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== 1531 | 1532 | path-is-absolute@^1.0.0: 1533 | version "1.0.1" 1534 | resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" 1535 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 1536 | 1537 | path-parse@^1.0.7: 1538 | version "1.0.7" 1539 | resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" 1540 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== 1541 | 1542 | path-to-regexp@0.1.7: 1543 | version "0.1.7" 1544 | resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" 1545 | integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= 1546 | 1547 | pg-connection-string@^2.5.0: 1548 | version "2.5.0" 1549 | resolved "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz" 1550 | integrity sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ== 1551 | 1552 | pg-int8@1.0.1: 1553 | version "1.0.1" 1554 | resolved "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz" 1555 | integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== 1556 | 1557 | pg-pool@^3.5.1: 1558 | version "3.5.1" 1559 | resolved "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.1.tgz" 1560 | integrity sha512-6iCR0wVrro6OOHFsyavV+i6KYL4lVNyYAB9RD18w66xSzN+d8b66HiwuP30Gp1SH5O9T82fckkzsRjlrhD0ioQ== 1561 | 1562 | pg-protocol@^1.5.0: 1563 | version "1.5.0" 1564 | resolved "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz" 1565 | integrity sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ== 1566 | 1567 | pg-types@^2.1.0: 1568 | version "2.2.0" 1569 | resolved "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz" 1570 | integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== 1571 | dependencies: 1572 | pg-int8 "1.0.1" 1573 | postgres-array "~2.0.0" 1574 | postgres-bytea "~1.0.0" 1575 | postgres-date "~1.0.4" 1576 | postgres-interval "^1.1.0" 1577 | 1578 | pg@^8.4.0: 1579 | version "8.7.3" 1580 | resolved "https://registry.yarnpkg.com/pg/-/pg-8.7.3.tgz#8a5bdd664ca4fda4db7997ec634c6e5455b27c44" 1581 | integrity sha512-HPmH4GH4H3AOprDJOazoIcpI49XFsHCe8xlrjHkWiapdbHK+HLtbm/GQzXYAZwmPju/kzKhjaSfMACG+8cgJcw== 1582 | dependencies: 1583 | buffer-writer "2.0.0" 1584 | packet-reader "1.0.0" 1585 | pg-connection-string "^2.5.0" 1586 | pg-pool "^3.5.1" 1587 | pg-protocol "^1.5.0" 1588 | pg-types "^2.1.0" 1589 | pgpass "1.x" 1590 | 1591 | pgpass@1.x: 1592 | version "1.0.5" 1593 | resolved "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz" 1594 | integrity sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug== 1595 | dependencies: 1596 | split2 "^4.1.0" 1597 | 1598 | picomatch@^2.0.4, picomatch@^2.2.1: 1599 | version "2.3.1" 1600 | resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" 1601 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 1602 | 1603 | postgres-array@~2.0.0: 1604 | version "2.0.0" 1605 | resolved "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz" 1606 | integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== 1607 | 1608 | postgres-bytea@~1.0.0: 1609 | version "1.0.0" 1610 | resolved "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz" 1611 | integrity sha1-AntTPAqokOJtFy1Hz5zOzFIazTU= 1612 | 1613 | postgres-date@~1.0.4: 1614 | version "1.0.7" 1615 | resolved "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz" 1616 | integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q== 1617 | 1618 | postgres-interval@^1.1.0: 1619 | version "1.2.0" 1620 | resolved "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz" 1621 | integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ== 1622 | dependencies: 1623 | xtend "^4.0.0" 1624 | 1625 | prebuild-install@^7.0.1: 1626 | version "7.1.0" 1627 | resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.0.tgz#991b6ac16c81591ba40a6d5de93fb33673ac1370" 1628 | integrity sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA== 1629 | dependencies: 1630 | detect-libc "^2.0.0" 1631 | expand-template "^2.0.3" 1632 | github-from-package "0.0.0" 1633 | minimist "^1.2.3" 1634 | mkdirp-classic "^0.5.3" 1635 | napi-build-utils "^1.0.1" 1636 | node-abi "^3.3.0" 1637 | npmlog "^4.0.1" 1638 | pump "^3.0.0" 1639 | rc "^1.2.7" 1640 | simple-get "^4.0.0" 1641 | tar-fs "^2.0.0" 1642 | tunnel-agent "^0.6.0" 1643 | 1644 | process-nextick-args@~2.0.0: 1645 | version "2.0.1" 1646 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" 1647 | integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== 1648 | 1649 | promise@^7.0.1: 1650 | version "7.3.1" 1651 | resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" 1652 | integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== 1653 | dependencies: 1654 | asap "~2.0.3" 1655 | 1656 | proxy-addr@~2.0.7: 1657 | version "2.0.7" 1658 | resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" 1659 | integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== 1660 | dependencies: 1661 | forwarded "0.2.0" 1662 | ipaddr.js "1.9.1" 1663 | 1664 | pug-attrs@^3.0.0: 1665 | version "3.0.0" 1666 | resolved "https://registry.yarnpkg.com/pug-attrs/-/pug-attrs-3.0.0.tgz#b10451e0348165e31fad1cc23ebddd9dc7347c41" 1667 | integrity sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA== 1668 | dependencies: 1669 | constantinople "^4.0.1" 1670 | js-stringify "^1.0.2" 1671 | pug-runtime "^3.0.0" 1672 | 1673 | pug-code-gen@^3.0.2: 1674 | version "3.0.2" 1675 | resolved "https://registry.yarnpkg.com/pug-code-gen/-/pug-code-gen-3.0.2.tgz#ad190f4943133bf186b60b80de483100e132e2ce" 1676 | integrity sha512-nJMhW16MbiGRiyR4miDTQMRWDgKplnHyeLvioEJYbk1RsPI3FuA3saEP8uwnTb2nTJEKBU90NFVWJBk4OU5qyg== 1677 | dependencies: 1678 | constantinople "^4.0.1" 1679 | doctypes "^1.1.0" 1680 | js-stringify "^1.0.2" 1681 | pug-attrs "^3.0.0" 1682 | pug-error "^2.0.0" 1683 | pug-runtime "^3.0.0" 1684 | void-elements "^3.1.0" 1685 | with "^7.0.0" 1686 | 1687 | pug-error@^2.0.0: 1688 | version "2.0.0" 1689 | resolved "https://registry.yarnpkg.com/pug-error/-/pug-error-2.0.0.tgz#5c62173cb09c34de2a2ce04f17b8adfec74d8ca5" 1690 | integrity sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ== 1691 | 1692 | pug-filters@^4.0.0: 1693 | version "4.0.0" 1694 | resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-4.0.0.tgz#d3e49af5ba8472e9b7a66d980e707ce9d2cc9b5e" 1695 | integrity sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A== 1696 | dependencies: 1697 | constantinople "^4.0.1" 1698 | jstransformer "1.0.0" 1699 | pug-error "^2.0.0" 1700 | pug-walk "^2.0.0" 1701 | resolve "^1.15.1" 1702 | 1703 | pug-lexer@^5.0.1: 1704 | version "5.0.1" 1705 | resolved "https://registry.yarnpkg.com/pug-lexer/-/pug-lexer-5.0.1.tgz#ae44628c5bef9b190b665683b288ca9024b8b0d5" 1706 | integrity sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w== 1707 | dependencies: 1708 | character-parser "^2.2.0" 1709 | is-expression "^4.0.0" 1710 | pug-error "^2.0.0" 1711 | 1712 | pug-linker@^4.0.0: 1713 | version "4.0.0" 1714 | resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-4.0.0.tgz#12cbc0594fc5a3e06b9fc59e6f93c146962a7708" 1715 | integrity sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw== 1716 | dependencies: 1717 | pug-error "^2.0.0" 1718 | pug-walk "^2.0.0" 1719 | 1720 | pug-load@^3.0.0: 1721 | version "3.0.0" 1722 | resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-3.0.0.tgz#9fd9cda52202b08adb11d25681fb9f34bd41b662" 1723 | integrity sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ== 1724 | dependencies: 1725 | object-assign "^4.1.1" 1726 | pug-walk "^2.0.0" 1727 | 1728 | pug-parser@^6.0.0: 1729 | version "6.0.0" 1730 | resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-6.0.0.tgz#a8fdc035863a95b2c1dc5ebf4ecf80b4e76a1260" 1731 | integrity sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw== 1732 | dependencies: 1733 | pug-error "^2.0.0" 1734 | token-stream "1.0.0" 1735 | 1736 | pug-runtime@^3.0.0, pug-runtime@^3.0.1: 1737 | version "3.0.1" 1738 | resolved "https://registry.yarnpkg.com/pug-runtime/-/pug-runtime-3.0.1.tgz#f636976204723f35a8c5f6fad6acda2a191b83d7" 1739 | integrity sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg== 1740 | 1741 | pug-strip-comments@^2.0.0: 1742 | version "2.0.0" 1743 | resolved "https://registry.yarnpkg.com/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz#f94b07fd6b495523330f490a7f554b4ff876303e" 1744 | integrity sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ== 1745 | dependencies: 1746 | pug-error "^2.0.0" 1747 | 1748 | pug-walk@^2.0.0: 1749 | version "2.0.0" 1750 | resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-2.0.0.tgz#417aabc29232bb4499b5b5069a2b2d2a24d5f5fe" 1751 | integrity sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ== 1752 | 1753 | pug@^3.0.2: 1754 | version "3.0.2" 1755 | resolved "https://registry.yarnpkg.com/pug/-/pug-3.0.2.tgz#f35c7107343454e43bc27ae0ff76c731b78ea535" 1756 | integrity sha512-bp0I/hiK1D1vChHh6EfDxtndHji55XP/ZJKwsRqrz6lRia6ZC2OZbdAymlxdVFwd1L70ebrVJw4/eZ79skrIaw== 1757 | dependencies: 1758 | pug-code-gen "^3.0.2" 1759 | pug-filters "^4.0.0" 1760 | pug-lexer "^5.0.1" 1761 | pug-linker "^4.0.0" 1762 | pug-load "^3.0.0" 1763 | pug-parser "^6.0.0" 1764 | pug-runtime "^3.0.1" 1765 | pug-strip-comments "^2.0.0" 1766 | 1767 | pump@^3.0.0: 1768 | version "3.0.0" 1769 | resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" 1770 | integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== 1771 | dependencies: 1772 | end-of-stream "^1.1.0" 1773 | once "^1.3.1" 1774 | 1775 | qs@6.10.3: 1776 | version "6.10.3" 1777 | resolved "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz" 1778 | integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== 1779 | dependencies: 1780 | side-channel "^1.0.4" 1781 | 1782 | railroad-diagrams@^1.0.0: 1783 | version "1.0.0" 1784 | resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e" 1785 | integrity sha1-635iZ1SN3t+4mcG5Dlc3RVnN234= 1786 | 1787 | randexp@0.4.6: 1788 | version "0.4.6" 1789 | resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.6.tgz#e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3" 1790 | integrity sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ== 1791 | dependencies: 1792 | discontinuous-range "1.0.0" 1793 | ret "~0.1.10" 1794 | 1795 | range-parser@~1.2.1: 1796 | version "1.2.1" 1797 | resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" 1798 | integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== 1799 | 1800 | raw-body@2.5.1: 1801 | version "2.5.1" 1802 | resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz" 1803 | integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== 1804 | dependencies: 1805 | bytes "3.1.2" 1806 | http-errors "2.0.0" 1807 | iconv-lite "0.4.24" 1808 | unpipe "1.0.0" 1809 | 1810 | rc@^1.2.7: 1811 | version "1.2.8" 1812 | resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" 1813 | integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== 1814 | dependencies: 1815 | deep-extend "^0.6.0" 1816 | ini "~1.3.0" 1817 | minimist "^1.2.0" 1818 | strip-json-comments "~2.0.1" 1819 | 1820 | readable-stream@1.1.x: 1821 | version "1.1.14" 1822 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" 1823 | integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= 1824 | dependencies: 1825 | core-util-is "~1.0.0" 1826 | inherits "~2.0.1" 1827 | isarray "0.0.1" 1828 | string_decoder "~0.10.x" 1829 | 1830 | readable-stream@^2.0.6, readable-stream@^2.2.2: 1831 | version "2.3.7" 1832 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" 1833 | integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== 1834 | dependencies: 1835 | core-util-is "~1.0.0" 1836 | inherits "~2.0.3" 1837 | isarray "~1.0.0" 1838 | process-nextick-args "~2.0.0" 1839 | safe-buffer "~5.1.1" 1840 | string_decoder "~1.1.1" 1841 | util-deprecate "~1.0.1" 1842 | 1843 | readable-stream@^3.1.1, readable-stream@^3.4.0: 1844 | version "3.6.0" 1845 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" 1846 | integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== 1847 | dependencies: 1848 | inherits "^2.0.3" 1849 | string_decoder "^1.1.1" 1850 | util-deprecate "^1.0.1" 1851 | 1852 | readdirp@~3.6.0: 1853 | version "3.6.0" 1854 | resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" 1855 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== 1856 | dependencies: 1857 | picomatch "^2.2.1" 1858 | 1859 | redis@^4.1.0: 1860 | version "4.1.0" 1861 | resolved "https://registry.yarnpkg.com/redis/-/redis-4.1.0.tgz#6e400e8edf219e39281afe95e66a3d5f7dcf7289" 1862 | integrity sha512-5hvJ8wbzpCCiuN1ges6tx2SAh2XXCY0ayresBmu40/SGusWHFW86TAlIPpbimMX2DFHOX7RN34G2XlPA1Z43zg== 1863 | dependencies: 1864 | "@redis/bloom" "1.0.2" 1865 | "@redis/client" "1.1.0" 1866 | "@redis/graph" "1.0.1" 1867 | "@redis/json" "1.0.3" 1868 | "@redis/search" "1.0.6" 1869 | "@redis/time-series" "1.0.3" 1870 | 1871 | reflect-metadata@^0.1.13: 1872 | version "0.1.13" 1873 | resolved "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz" 1874 | integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg== 1875 | 1876 | require-directory@^2.1.1: 1877 | version "2.1.1" 1878 | resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" 1879 | integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= 1880 | 1881 | resolve@^1.0.0, resolve@^1.15.1: 1882 | version "1.22.0" 1883 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" 1884 | integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== 1885 | dependencies: 1886 | is-core-module "^2.8.1" 1887 | path-parse "^1.0.7" 1888 | supports-preserve-symlinks-flag "^1.0.0" 1889 | 1890 | ret@~0.1.10: 1891 | version "0.1.15" 1892 | resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" 1893 | integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== 1894 | 1895 | rimraf@^2.6.1: 1896 | version "2.7.1" 1897 | resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz" 1898 | integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== 1899 | dependencies: 1900 | glob "^7.1.3" 1901 | 1902 | safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: 1903 | version "5.1.2" 1904 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 1905 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 1906 | 1907 | safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@~5.2.0: 1908 | version "5.2.1" 1909 | resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" 1910 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 1911 | 1912 | "safer-buffer@>= 2.1.2 < 3": 1913 | version "2.1.2" 1914 | resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" 1915 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 1916 | 1917 | sax@>=0.6.0: 1918 | version "1.2.4" 1919 | resolved "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz" 1920 | integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== 1921 | 1922 | selderee@^0.6.0: 1923 | version "0.6.0" 1924 | resolved "https://registry.yarnpkg.com/selderee/-/selderee-0.6.0.tgz#f3bee66cfebcb6f33df98e4a1df77388b42a96f7" 1925 | integrity sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg== 1926 | dependencies: 1927 | parseley "^0.7.0" 1928 | 1929 | semver@^5.6.0: 1930 | version "5.7.1" 1931 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" 1932 | integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== 1933 | 1934 | semver@^7.3.5, semver@^7.3.7: 1935 | version "7.3.7" 1936 | resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" 1937 | integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== 1938 | dependencies: 1939 | lru-cache "^6.0.0" 1940 | 1941 | send@0.18.0: 1942 | version "0.18.0" 1943 | resolved "https://registry.npmjs.org/send/-/send-0.18.0.tgz" 1944 | integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== 1945 | dependencies: 1946 | debug "2.6.9" 1947 | depd "2.0.0" 1948 | destroy "1.2.0" 1949 | encodeurl "~1.0.2" 1950 | escape-html "~1.0.3" 1951 | etag "~1.8.1" 1952 | fresh "0.5.2" 1953 | http-errors "2.0.0" 1954 | mime "1.6.0" 1955 | ms "2.1.3" 1956 | on-finished "2.4.1" 1957 | range-parser "~1.2.1" 1958 | statuses "2.0.1" 1959 | 1960 | serve-static@1.15.0: 1961 | version "1.15.0" 1962 | resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz" 1963 | integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== 1964 | dependencies: 1965 | encodeurl "~1.0.2" 1966 | escape-html "~1.0.3" 1967 | parseurl "~1.3.3" 1968 | send "0.18.0" 1969 | 1970 | set-blocking@~2.0.0: 1971 | version "2.0.0" 1972 | resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" 1973 | integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= 1974 | 1975 | setprototypeof@1.2.0: 1976 | version "1.2.0" 1977 | resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" 1978 | integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== 1979 | 1980 | sha.js@^2.4.11: 1981 | version "2.4.11" 1982 | resolved "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz" 1983 | integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== 1984 | dependencies: 1985 | inherits "^2.0.1" 1986 | safe-buffer "^5.0.1" 1987 | 1988 | sharp@^0.30.4: 1989 | version "0.30.4" 1990 | resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.30.4.tgz#73d9daa63bbc20da189c9328d75d5d395fc8fb73" 1991 | integrity sha512-3Onig53Y6lji4NIZo69s14mERXXY/GV++6CzOYx/Rd8bnTwbhFbL09WZd7Ag/CCnA0WxFID8tkY0QReyfL6v0Q== 1992 | dependencies: 1993 | color "^4.2.3" 1994 | detect-libc "^2.0.1" 1995 | node-addon-api "^4.3.0" 1996 | prebuild-install "^7.0.1" 1997 | semver "^7.3.7" 1998 | simple-get "^4.0.1" 1999 | tar-fs "^2.1.1" 2000 | tunnel-agent "^0.6.0" 2001 | 2002 | side-channel@^1.0.4: 2003 | version "1.0.4" 2004 | resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz" 2005 | integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== 2006 | dependencies: 2007 | call-bind "^1.0.0" 2008 | get-intrinsic "^1.0.2" 2009 | object-inspect "^1.9.0" 2010 | 2011 | signal-exit@^3.0.0: 2012 | version "3.0.7" 2013 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" 2014 | integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== 2015 | 2016 | simple-concat@^1.0.0: 2017 | version "1.0.1" 2018 | resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" 2019 | integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== 2020 | 2021 | simple-get@^4.0.0, simple-get@^4.0.1: 2022 | version "4.0.1" 2023 | resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" 2024 | integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== 2025 | dependencies: 2026 | decompress-response "^6.0.0" 2027 | once "^1.3.1" 2028 | simple-concat "^1.0.0" 2029 | 2030 | simple-swizzle@^0.2.2: 2031 | version "0.2.2" 2032 | resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" 2033 | integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= 2034 | dependencies: 2035 | is-arrayish "^0.3.1" 2036 | 2037 | source-map-support@^0.5.12, source-map-support@^0.5.17: 2038 | version "0.5.21" 2039 | resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" 2040 | integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== 2041 | dependencies: 2042 | buffer-from "^1.0.0" 2043 | source-map "^0.6.0" 2044 | 2045 | source-map@^0.6.0: 2046 | version "0.6.1" 2047 | resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" 2048 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 2049 | 2050 | split2@^4.1.0: 2051 | version "4.1.0" 2052 | resolved "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz" 2053 | integrity sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ== 2054 | 2055 | statuses@2.0.1: 2056 | version "2.0.1" 2057 | resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" 2058 | integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== 2059 | 2060 | streamsearch@0.1.2: 2061 | version "0.1.2" 2062 | resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" 2063 | integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo= 2064 | 2065 | string-width@^1.0.1: 2066 | version "1.0.2" 2067 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" 2068 | integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= 2069 | dependencies: 2070 | code-point-at "^1.0.0" 2071 | is-fullwidth-code-point "^1.0.0" 2072 | strip-ansi "^3.0.0" 2073 | 2074 | "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: 2075 | version "4.2.3" 2076 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 2077 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 2078 | dependencies: 2079 | emoji-regex "^8.0.0" 2080 | is-fullwidth-code-point "^3.0.0" 2081 | strip-ansi "^6.0.1" 2082 | 2083 | string_decoder@^1.1.1: 2084 | version "1.3.0" 2085 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" 2086 | integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== 2087 | dependencies: 2088 | safe-buffer "~5.2.0" 2089 | 2090 | string_decoder@~0.10.x: 2091 | version "0.10.31" 2092 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" 2093 | integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= 2094 | 2095 | string_decoder@~1.1.1: 2096 | version "1.1.1" 2097 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" 2098 | integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== 2099 | dependencies: 2100 | safe-buffer "~5.1.0" 2101 | 2102 | strip-ansi@^3.0.0, strip-ansi@^3.0.1: 2103 | version "3.0.1" 2104 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 2105 | integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= 2106 | dependencies: 2107 | ansi-regex "^2.0.0" 2108 | 2109 | strip-ansi@^6.0.0, strip-ansi@^6.0.1: 2110 | version "6.0.1" 2111 | resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" 2112 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 2113 | dependencies: 2114 | ansi-regex "^5.0.1" 2115 | 2116 | strip-bom@^3.0.0: 2117 | version "3.0.0" 2118 | resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" 2119 | integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= 2120 | 2121 | strip-json-comments@^2.0.0, strip-json-comments@~2.0.1: 2122 | version "2.0.1" 2123 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" 2124 | integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= 2125 | 2126 | supports-color@^7.1.0: 2127 | version "7.2.0" 2128 | resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" 2129 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 2130 | dependencies: 2131 | has-flag "^4.0.0" 2132 | 2133 | supports-preserve-symlinks-flag@^1.0.0: 2134 | version "1.0.0" 2135 | resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" 2136 | integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== 2137 | 2138 | tar-fs@^2.0.0, tar-fs@^2.1.1: 2139 | version "2.1.1" 2140 | resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" 2141 | integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== 2142 | dependencies: 2143 | chownr "^1.1.1" 2144 | mkdirp-classic "^0.5.2" 2145 | pump "^3.0.0" 2146 | tar-stream "^2.1.4" 2147 | 2148 | tar-stream@^2.1.4: 2149 | version "2.2.0" 2150 | resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" 2151 | integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== 2152 | dependencies: 2153 | bl "^4.0.3" 2154 | end-of-stream "^1.4.1" 2155 | fs-constants "^1.0.0" 2156 | inherits "^2.0.3" 2157 | readable-stream "^3.1.1" 2158 | 2159 | thenify-all@^1.0.0: 2160 | version "1.6.0" 2161 | resolved "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz" 2162 | integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= 2163 | dependencies: 2164 | thenify ">= 3.1.0 < 4" 2165 | 2166 | "thenify@>= 3.1.0 < 4": 2167 | version "3.3.1" 2168 | resolved "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz" 2169 | integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== 2170 | dependencies: 2171 | any-promise "^1.0.0" 2172 | 2173 | to-fast-properties@^2.0.0: 2174 | version "2.0.0" 2175 | resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" 2176 | integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= 2177 | 2178 | to-regex-range@^5.0.1: 2179 | version "5.0.1" 2180 | resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" 2181 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 2182 | dependencies: 2183 | is-number "^7.0.0" 2184 | 2185 | toidentifier@1.0.1: 2186 | version "1.0.1" 2187 | resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" 2188 | integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== 2189 | 2190 | token-stream@1.0.0: 2191 | version "1.0.0" 2192 | resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-1.0.0.tgz#cc200eab2613f4166d27ff9afc7ca56d49df6eb4" 2193 | integrity sha1-zCAOqyYT9BZtJ/+a/HylbUnfbrQ= 2194 | 2195 | tree-kill@^1.2.2: 2196 | version "1.2.2" 2197 | resolved "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz" 2198 | integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== 2199 | 2200 | ts-node-dev@^1.1.8: 2201 | version "1.1.8" 2202 | resolved "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-1.1.8.tgz" 2203 | integrity sha512-Q/m3vEwzYwLZKmV6/0VlFxcZzVV/xcgOt+Tx/VjaaRHyiBcFlV0541yrT09QjzzCxlDZ34OzKjrFAynlmtflEg== 2204 | dependencies: 2205 | chokidar "^3.5.1" 2206 | dynamic-dedupe "^0.3.0" 2207 | minimist "^1.2.5" 2208 | mkdirp "^1.0.4" 2209 | resolve "^1.0.0" 2210 | rimraf "^2.6.1" 2211 | source-map-support "^0.5.12" 2212 | tree-kill "^1.2.2" 2213 | ts-node "^9.0.0" 2214 | tsconfig "^7.0.0" 2215 | 2216 | ts-node@10.7.0: 2217 | version "10.7.0" 2218 | resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz" 2219 | integrity sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A== 2220 | dependencies: 2221 | "@cspotcode/source-map-support" "0.7.0" 2222 | "@tsconfig/node10" "^1.0.7" 2223 | "@tsconfig/node12" "^1.0.7" 2224 | "@tsconfig/node14" "^1.0.0" 2225 | "@tsconfig/node16" "^1.0.2" 2226 | acorn "^8.4.1" 2227 | acorn-walk "^8.1.1" 2228 | arg "^4.1.0" 2229 | create-require "^1.1.0" 2230 | diff "^4.0.1" 2231 | make-error "^1.1.1" 2232 | v8-compile-cache-lib "^3.0.0" 2233 | yn "3.1.1" 2234 | 2235 | ts-node@^9.0.0: 2236 | version "9.1.1" 2237 | resolved "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz" 2238 | integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg== 2239 | dependencies: 2240 | arg "^4.1.0" 2241 | create-require "^1.1.0" 2242 | diff "^4.0.1" 2243 | make-error "^1.1.1" 2244 | source-map-support "^0.5.17" 2245 | yn "3.1.1" 2246 | 2247 | tsconfig@^7.0.0: 2248 | version "7.0.0" 2249 | resolved "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz" 2250 | integrity sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw== 2251 | dependencies: 2252 | "@types/strip-bom" "^3.0.0" 2253 | "@types/strip-json-comments" "0.0.30" 2254 | strip-bom "^3.0.0" 2255 | strip-json-comments "^2.0.0" 2256 | 2257 | tslib@2.3.1: 2258 | version "2.3.1" 2259 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" 2260 | integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== 2261 | 2262 | tslib@^2.3.1: 2263 | version "2.4.0" 2264 | resolved "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz" 2265 | integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== 2266 | 2267 | tunnel-agent@^0.6.0: 2268 | version "0.6.0" 2269 | resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" 2270 | integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= 2271 | dependencies: 2272 | safe-buffer "^5.0.1" 2273 | 2274 | type-is@^1.6.4, type-is@~1.6.18: 2275 | version "1.6.18" 2276 | resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" 2277 | integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== 2278 | dependencies: 2279 | media-typer "0.3.0" 2280 | mime-types "~2.1.24" 2281 | 2282 | typedarray@^0.0.6: 2283 | version "0.0.6" 2284 | resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" 2285 | integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= 2286 | 2287 | typeorm@0.3.6: 2288 | version "0.3.6" 2289 | resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.3.6.tgz#65203443a1b684bb746785913fe2b0877aa991c0" 2290 | integrity sha512-DRqgfqcelMiGgWSMbBmVoJNFN2nPNA3EeY2gC324ndr2DZoGRTb9ILtp2oGVGnlA+cu5zgQ6it5oqKFNkte7Aw== 2291 | dependencies: 2292 | "@sqltools/formatter" "^1.2.2" 2293 | app-root-path "^3.0.0" 2294 | buffer "^6.0.3" 2295 | chalk "^4.1.0" 2296 | cli-highlight "^2.1.11" 2297 | date-fns "^2.28.0" 2298 | debug "^4.3.3" 2299 | dotenv "^16.0.0" 2300 | glob "^7.2.0" 2301 | js-yaml "^4.1.0" 2302 | mkdirp "^1.0.4" 2303 | reflect-metadata "^0.1.13" 2304 | sha.js "^2.4.11" 2305 | tslib "^2.3.1" 2306 | uuid "^8.3.2" 2307 | xml2js "^0.4.23" 2308 | yargs "^17.3.1" 2309 | 2310 | typescript@4.5.2: 2311 | version "4.5.2" 2312 | resolved "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz" 2313 | integrity sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw== 2314 | 2315 | unpipe@1.0.0, unpipe@~1.0.0: 2316 | version "1.0.0" 2317 | resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" 2318 | integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= 2319 | 2320 | util-deprecate@^1.0.1, util-deprecate@~1.0.1: 2321 | version "1.0.2" 2322 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 2323 | integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= 2324 | 2325 | utils-merge@1.0.1: 2326 | version "1.0.1" 2327 | resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" 2328 | integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= 2329 | 2330 | uuid@^8.3.2: 2331 | version "8.3.2" 2332 | resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" 2333 | integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== 2334 | 2335 | v8-compile-cache-lib@^3.0.0: 2336 | version "3.0.1" 2337 | resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" 2338 | integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== 2339 | 2340 | vary@^1, vary@~1.1.2: 2341 | version "1.1.2" 2342 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" 2343 | integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= 2344 | 2345 | void-elements@^3.1.0: 2346 | version "3.1.0" 2347 | resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" 2348 | integrity sha1-YU9/v42AHwu18GYfWy9XhXUOTwk= 2349 | 2350 | wide-align@^1.1.0: 2351 | version "1.1.5" 2352 | resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" 2353 | integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== 2354 | dependencies: 2355 | string-width "^1.0.2 || 2 || 3 || 4" 2356 | 2357 | with@^7.0.0: 2358 | version "7.0.2" 2359 | resolved "https://registry.yarnpkg.com/with/-/with-7.0.2.tgz#ccee3ad542d25538a7a7a80aad212b9828495bac" 2360 | integrity sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w== 2361 | dependencies: 2362 | "@babel/parser" "^7.9.6" 2363 | "@babel/types" "^7.9.6" 2364 | assert-never "^1.2.1" 2365 | babel-walk "3.0.0-canary-5" 2366 | 2367 | wrap-ansi@^7.0.0: 2368 | version "7.0.0" 2369 | resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" 2370 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 2371 | dependencies: 2372 | ansi-styles "^4.0.0" 2373 | string-width "^4.1.0" 2374 | strip-ansi "^6.0.0" 2375 | 2376 | wrappy@1: 2377 | version "1.0.2" 2378 | resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" 2379 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 2380 | 2381 | xml2js@^0.4.23: 2382 | version "0.4.23" 2383 | resolved "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz" 2384 | integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== 2385 | dependencies: 2386 | sax ">=0.6.0" 2387 | xmlbuilder "~11.0.0" 2388 | 2389 | xmlbuilder@~11.0.0: 2390 | version "11.0.1" 2391 | resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz" 2392 | integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== 2393 | 2394 | xtend@^4.0.0: 2395 | version "4.0.2" 2396 | resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" 2397 | integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== 2398 | 2399 | y18n@^5.0.5: 2400 | version "5.0.8" 2401 | resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" 2402 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== 2403 | 2404 | yallist@4.0.0, yallist@^4.0.0: 2405 | version "4.0.0" 2406 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" 2407 | integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== 2408 | 2409 | yargs-parser@^20.2.2: 2410 | version "20.2.9" 2411 | resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz" 2412 | integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== 2413 | 2414 | yargs-parser@^21.0.0: 2415 | version "21.0.1" 2416 | resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz" 2417 | integrity sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg== 2418 | 2419 | yargs@^16.0.0: 2420 | version "16.2.0" 2421 | resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" 2422 | integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== 2423 | dependencies: 2424 | cliui "^7.0.2" 2425 | escalade "^3.1.1" 2426 | get-caller-file "^2.0.5" 2427 | require-directory "^2.1.1" 2428 | string-width "^4.2.0" 2429 | y18n "^5.0.5" 2430 | yargs-parser "^20.2.2" 2431 | 2432 | yargs@^17.3.1: 2433 | version "17.4.1" 2434 | resolved "https://registry.npmjs.org/yargs/-/yargs-17.4.1.tgz" 2435 | integrity sha512-WSZD9jgobAg3ZKuCQZSa3g9QOJeCCqLoLAykiWgmXnDo9EPnn4RPf5qVTtzgOx66o6/oqhcA5tHtJXpG8pMt3g== 2436 | dependencies: 2437 | cliui "^7.0.2" 2438 | escalade "^3.1.1" 2439 | get-caller-file "^2.0.5" 2440 | require-directory "^2.1.1" 2441 | string-width "^4.2.3" 2442 | y18n "^5.0.5" 2443 | yargs-parser "^21.0.0" 2444 | 2445 | yn@3.1.1: 2446 | version "3.1.1" 2447 | resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" 2448 | integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== 2449 | 2450 | zod@^3.14.4: 2451 | version "3.15.1" 2452 | resolved "https://registry.yarnpkg.com/zod/-/zod-3.15.1.tgz#9e404cd8002ccffb03baa94cff2e1638ed49d82f" 2453 | integrity sha512-WAdjcoOxa4S9oc/u7fTbC3CC7uVqptLLU0LKqS8RDBOrCXp2t5avM8BUfgNVZJymGWAx6SEUYxWPPoYuQ5rgwQ== 2454 | --------------------------------------------------------------------------------