diff --git a/nest-cli.json b/nest-cli.json index 56167b3..14a0394 100644 --- a/nest-cli.json +++ b/nest-cli.json @@ -1,4 +1,9 @@ { + "$schema": "https://json.schemastore.org/nest-cli", "collection": "@nestjs/schematics", - "sourceRoot": "src" + "sourceRoot": "src", + "generateOptions": { + "spec": false + }, + "exec": "pog" } diff --git a/package.json b/package.json index dfb5a88..6719960 100644 --- a/package.json +++ b/package.json @@ -6,13 +6,14 @@ "license": "GPL-3.0", "repository": "https://github.com/rubikscraft/Imagur-Backend", "author": "Rubikscraft ", + "type": "module", "scripts": { "prebuild": "rimraf dist", "build": "nest build", - "start": "nest start", - "start:dev": "nest start --watch", - "start:debug": "nest start --debug --watch", - "start:prod": "node dist/main", + "start": "nest start --exec \"node --experimental-specifier-resolution=node\"", + "start:dev": "nest start --watch --exec \"node --experimental-specifier-resolution=node\"", + "start:debug": "nest start --debug --watch --exec \"node --experimental-specifier-resolution=node\"", + "start:prod": "node --experimental-specifier-resolution=node dist/main", "devdb:start": "podman-compose -f ./dev/docker-compose.yml up -d", "devdb:stop": "podman-compose -f ./dev/docker-compose.yml down", "format": "prettier --write \"src/**/*.ts\"", @@ -28,6 +29,9 @@ "bcrypt": "^5.0.1", "class-transformer": "^0.5.1", "class-validator": "^0.13.2", + "fastify": "^3.27.2", + "fastify-multipart": "^5.3.1", + "file-type": "^17.1.1", "passport": "^0.5.2", "passport-jwt": "^4.0.0", "passport-local": "^1.0.0", @@ -42,7 +46,7 @@ "@nestjs/schematics": "^8.0.4", "@nestjs/testing": "^8.1.1", "@types/bcrypt": "^5.0.0", - "@types/express": "^4.17.13", + "@types/multer": "^1.4.7", "@types/node": "^16.11.1", "@types/passport-jwt": "^3.0.6", "@types/passport-local": "^1.0.34", @@ -54,11 +58,10 @@ "eslint-plugin-prettier": "^3.4.1", "prettier": "^2.4.1", "source-map-support": "^0.5.20", - "supertest": "^6.1.6", "ts-loader": "^9.2.6", "ts-node": "^10.3.0", "tsconfig-paths": "^3.11.0", - "typescript": "^4.4.4", + "typescript": "^4.7.0-dev.20220221", "webpack": "^5.69.1" } } diff --git a/src/app.module.ts b/src/app.module.ts index 0422da2..1a8a3a2 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -3,7 +3,10 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { AuthModule } from './auth/auth.module'; import { UserEntity } from './users/user.entity'; import { UsersModule } from './users/users.module'; +import { RootModule } from './root/root.module'; import Config from './env'; +import { ImageEntity } from './images/image.entity'; +import { SafeImagesModule } from './safeimages/safeimages.module'; @Module({ imports: [ @@ -14,14 +17,14 @@ import Config from './env'; username: Config.database.username, password: Config.database.password, database: Config.database.database, - - autoLoadEntities: true, synchronize: true, - entities: [UserEntity], + entities: [UserEntity, ImageEntity], }), AuthModule, UsersModule, + RootModule, + SafeImagesModule, ], }) export class AppModule {} diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 4038007..b16d170 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -5,6 +5,9 @@ import { Request, Body, Get, + ConflictException, + NotFoundException, + InternalServerErrorException, } from '@nestjs/common'; import { LocalAuthGuard } from './local-auth.guard'; import { @@ -15,8 +18,7 @@ import { import { AuthService } from './auth.service'; import { JwtAuthGuard } from './jwt.guard'; import { AdminGuard } from './admin.guard'; -import { Nothing, AsyncMaybe, Maybe } from 'src/lib/maybe'; -import { User } from 'src/users/user.dto'; +import { HasFailed } from 'src/lib/maybe'; @Controller('auth') export class AuthController { @@ -40,9 +42,7 @@ export class AuthController { register.password, ); - if (user === Nothing) { - throw new Error('User already exists'); - } + if (HasFailed(user)) throw new ConflictException('User already exists'); if (register.isAdmin) { await this.authService.makeAdmin(user); @@ -55,10 +55,7 @@ export class AuthController { @Post('delete') async delete(@Request() req, @Body() deleteData: DeleteRequestDto) { const user = await this.authService.deleteUser(deleteData.username); - - if (user === Nothing) { - throw new Error('User does not exist'); - } + if (HasFailed(user)) throw new NotFoundException('User does not exist'); return this.authService.userEntityToUser(user); } @@ -66,6 +63,11 @@ export class AuthController { @UseGuards(JwtAuthGuard, AdminGuard) @Get('list') async listUsers(@Request() req) { - return this.authService.listUsers(); + const users = this.authService.listUsers(); + + if (HasFailed(users)) + throw new InternalServerErrorException('Could not list users'); + + return users; } } diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index 42b6df2..1716a5a 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import * as bcrypt from 'bcrypt'; -import { AsyncMaybe, Nothing } from 'src/lib/maybe'; +import { AsyncFailable, Fail, HasFailed } from 'src/lib/maybe'; import { User } from 'src/users/user.dto'; import { UserEntity } from 'src/users/user.entity'; import { UsersService } from 'src/users/users.service'; @@ -14,29 +14,35 @@ export class AuthService { private jwtService: JwtService, ) {} - async createUser(username: string, password: string): AsyncMaybe { + async createUser( + username: string, + password: string, + ): AsyncFailable { const hashedPassword = await bcrypt.hash(password, 12); return this.usersService.createUser(username, hashedPassword); } - async deleteUser(user: string | UserEntity): AsyncMaybe { + async deleteUser(user: string | UserEntity): AsyncFailable { return this.usersService.removeUser(user); } - async listUsers(): Promise { + async listUsers(): AsyncFailable { const users = await this.usersService.findAll(); + if (HasFailed(users)) return users; + return users.map((user) => this.userEntityToUser(user)); } async authenticate( username: string, password: string, - ): AsyncMaybe { + ): AsyncFailable { const user = await this.usersService.findOne(username); - if (user === Nothing) return Nothing; + if (HasFailed(user)) return user; - if (!(await bcrypt.compare(password, user.password))) return Nothing; + if (!(await bcrypt.compare(password, user.password))) + return Fail('Wrong password'); return user; } @@ -52,11 +58,11 @@ export class AuthService { return this.jwtService.signAsync(jwtData); } - async makeAdmin(user: string | UserEntity): Promise { + async makeAdmin(user: string | UserEntity): AsyncFailable { return this.usersService.modifyAdmin(user, true); } - async revokeAdmin(user: string | UserEntity): Promise { + async revokeAdmin(user: string | UserEntity): AsyncFailable { return this.usersService.modifyAdmin(user, false); } diff --git a/src/auth/local.strategy.ts b/src/auth/local.strategy.ts index 2c1382f..fb247a1 100644 --- a/src/auth/local.strategy.ts +++ b/src/auth/local.strategy.ts @@ -2,7 +2,7 @@ import { Strategy } from 'passport-local'; import { PassportStrategy } from '@nestjs/passport'; import { Injectable, UnauthorizedException } from '@nestjs/common'; import { AuthService } from './auth.service'; -import { AsyncMaybe, Nothing } from 'src/lib/maybe'; +import { AsyncFailable, HasFailed } from 'src/lib/maybe'; import { UserEntity } from 'src/users/user.entity'; @Injectable() @@ -11,9 +11,12 @@ export class LocalStrategy extends PassportStrategy(Strategy) { super(); } - async validate(username: string, password: string): AsyncMaybe { + async validate( + username: string, + password: string, + ): AsyncFailable { const user = await this.authService.authenticate(username, password); - if (user === Nothing) { + if (HasFailed(user)) { throw new UnauthorizedException(); } return user; diff --git a/src/images/image.entity.ts b/src/images/image.entity.ts new file mode 100644 index 0000000..3159b5f --- /dev/null +++ b/src/images/image.entity.ts @@ -0,0 +1,19 @@ +import { Column, Entity, Index, PrimaryGeneratedColumn, Unique } from 'typeorm'; +import { SupportedMime, SupportedMimes } from './mimes.service'; + +@Entity() +export class ImageEntity { + @PrimaryGeneratedColumn() + id: number; + + @Index() + @Column({ unique: true }) + hash: string; + + // Binary data + @Column({ type: 'bytea', nullable: false }) + data: Buffer; + + @Column({ enum: SupportedMimes }) + mime: SupportedMime; +} diff --git a/src/images/images.module.ts b/src/images/images.module.ts new file mode 100644 index 0000000..63cef86 --- /dev/null +++ b/src/images/images.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { ImageEntity } from './image.entity'; +import { ImagesService } from './images.service'; +import { MimesService } from './mimes.service'; + +@Module({ + imports: [TypeOrmModule.forFeature([ImageEntity])], + providers: [ImagesService, MimesService], + exports: [ImagesService, MimesService], +}) +export class ImagesModule {} diff --git a/src/images/images.service.ts b/src/images/images.service.ts new file mode 100644 index 0000000..213cba9 --- /dev/null +++ b/src/images/images.service.ts @@ -0,0 +1,56 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { ImageEntity } from './image.entity'; +import Crypto from 'crypto'; +import { AsyncFailable, Fail, HasFailed, HasSuccess } from 'src/lib/maybe'; +import { SupportedMime } from './mimes.service'; + +@Injectable() +export class ImagesService { + constructor( + @InjectRepository(ImageEntity) + private imageRepository: Repository, + ) {} + + async create(image: Buffer, type: SupportedMime): AsyncFailable { + const hash = this.hash(image); + const find = await this.findOne(hash); + if (HasSuccess(find)) return find; + + const imageEntity = new ImageEntity(); + imageEntity.data = image; + imageEntity.mime = type; + imageEntity.hash = hash; + try { + await this.imageRepository.save(imageEntity); + } catch (e) { + return Fail(e.message); + } + + return imageEntity; + } + + async findOne(hash: string): AsyncFailable { + const found = await this.imageRepository.findOne({ where: { hash } }); + if (found === undefined) return Fail('Image not found'); + return found; + } + + async delete(hash: string): AsyncFailable { + const image = await this.findOne(hash); + + if (HasFailed(image)) return image; + + try { + await this.imageRepository.delete(image); + } catch (e) { + return Fail(e.message); + } + return true; + } + + hash(image: Buffer): string { + return Crypto.createHash('sha256').update(image).digest('hex'); + } +} diff --git a/src/images/mimes.service.ts b/src/images/mimes.service.ts new file mode 100644 index 0000000..c0ea8f8 --- /dev/null +++ b/src/images/mimes.service.ts @@ -0,0 +1,47 @@ +import { Injectable } from '@nestjs/common'; +import { Fail, Failable } from 'src/lib/maybe'; + +const tuple = (...args: T): T => args; + +// Config + +const SupportedImageMimesTuple = tuple( + 'image/jpeg', + 'image/png', + 'image/webp', + 'image/tiff', + 'image/bmp', + 'image/x-icon', +); + +const SupportedAnimMimesTuple = tuple('image/apng', 'image/gif'); + +// Derivatives + +export const SupportedImageMimes: string[] = SupportedImageMimesTuple; +export const SupportedAnimMimes: string[] = SupportedAnimMimesTuple; + +export const SupportedMimes: string[] = [ + ...SupportedImageMimes, + ...SupportedAnimMimes, +]; +export type SupportedMime = typeof SupportedMimes[number]; +export type SupportedMimeCategory = 'image' | 'anim'; + +export interface FullMime { + mime: SupportedMime; + type: SupportedMimeCategory; +} + +@Injectable() +export class MimesService { + getFullMime(mime: string): Failable { + if (SupportedImageMimes.includes(mime)) { + return { mime, type: 'image' }; + } + if (SupportedAnimMimes.includes(mime)) { + return { mime, type: 'anim' }; + } + return Fail('Unsupported mime type'); + } +} diff --git a/src/lib/maybe.ts b/src/lib/maybe.ts index 53d5826..ab2e09e 100644 --- a/src/lib/maybe.ts +++ b/src/lib/maybe.ts @@ -1,5 +1,23 @@ -export const Nothing = undefined; -export type Nothing = undefined; -export type Maybe = T | Nothing; +export class Failure { + constructor(private readonly reason?: string) {} -export type AsyncMaybe = Promise>; + getReason(): string { + return this.reason ?? 'Unknown'; + } +} + +export function Fail(reason?: string): Failure { + return new Failure(reason); +} + +export type Failable = T | Failure; + +export type AsyncFailable = Promise>; + +export function HasFailed(failable: Failable): failable is Failure { + return failable instanceof Failure; +} + +export function HasSuccess(failable: Failable): failable is T { + return !(failable instanceof Failure); +} diff --git a/src/main.ts b/src/main.ts index 76e7c47..506e2f7 100644 --- a/src/main.ts +++ b/src/main.ts @@ -6,10 +6,15 @@ import { } from '@nestjs/platform-fastify'; import { AppModule } from './app.module'; +import * as multipart from 'fastify-multipart'; + async function bootstrap() { + const fastifyAdapter = new FastifyAdapter(); + fastifyAdapter.register(multipart as any); + const app = await NestFactory.create( AppModule, - new FastifyAdapter(), + fastifyAdapter, ); app.useGlobalPipes(new ValidationPipe({ disableErrorMessages: true })); await app.listen(3000); diff --git a/src/root/root.controller.ts b/src/root/root.controller.ts new file mode 100644 index 0000000..3bdb503 --- /dev/null +++ b/src/root/root.controller.ts @@ -0,0 +1,66 @@ +import { + BadRequestException, + Body, + Controller, + Get, + InternalServerErrorException, + NotFoundException, + Param, + Post, + Req, + Res, + UploadedFile, + UseInterceptors, +} from '@nestjs/common'; +import { isArray } from 'class-validator'; +import { FastifyReply, FastifyRequest } from 'fastify'; +import { Multipart, MultipartFields, MultipartFile } from 'fastify-multipart'; +import { HasFailed } from 'src/lib/maybe'; +import { SafeImagesService } from 'src/safeimages/safeimages.service'; + +@Controller() +export class RootController { + constructor(private readonly imagesService: SafeImagesService) {} + + @Get('i/:hash') + async getImage( + @Res({ passthrough: true }) res: FastifyReply, + @Param('hash') hash: string, + ) { + if (!this.imagesService.validateHash(hash)) + throw new BadRequestException('Invalid hash'); + + const image = await this.imagesService.retrieveImage(hash); + if (HasFailed(image)) + throw new NotFoundException('Failed to retrieve image'); + + res.type(image.mime); + return image.data; + } + + @Post('i') + async uploadImage(@Req() req: FastifyRequest) { + if (!req.isMultipart()) + throw new BadRequestException('Not a multipart request'); + + const file = await req.file({ limits: {} }); + if (file === undefined) throw new BadRequestException('No file uploaded'); + + const allFields: Multipart[] = Object.values(file.fields).filter( + (entry) => entry, + ) as any; + + const options = allFields.filter((entry) => entry.file === undefined); + const files = allFields.filter((entry) => entry.file !== undefined); + + if (files.length !== 1) throw new BadRequestException('Invalid file'); + + const image = await files[0].toBuffer(); + + const hash = await this.imagesService.uploadImage(image); + if (HasFailed(hash)) + throw new InternalServerErrorException('Failed to upload image'); + + return { hash }; + } +} diff --git a/src/root/root.module.ts b/src/root/root.module.ts new file mode 100644 index 0000000..9411a3c --- /dev/null +++ b/src/root/root.module.ts @@ -0,0 +1,10 @@ +import { Module } from '@nestjs/common'; +import { ImagesModule } from 'src/images/images.module'; +import { SafeImagesModule } from 'src/safeimages/safeimages.module'; +import { RootController } from './root.controller'; + +@Module({ + imports: [SafeImagesModule], + controllers: [RootController], +}) +export class RootModule {} diff --git a/src/safeimages/safeimages.module.ts b/src/safeimages/safeimages.module.ts new file mode 100644 index 0000000..6247eaa --- /dev/null +++ b/src/safeimages/safeimages.module.ts @@ -0,0 +1,10 @@ +import { Module } from '@nestjs/common'; +import { ImagesModule } from 'src/images/images.module'; +import { SafeImagesService } from './safeimages.service'; + +@Module({ + imports: [ImagesModule], + providers: [SafeImagesService], + exports: [SafeImagesService], +}) +export class SafeImagesModule {} diff --git a/src/safeimages/safeimages.service.ts b/src/safeimages/safeimages.service.ts new file mode 100644 index 0000000..ce2cca6 --- /dev/null +++ b/src/safeimages/safeimages.service.ts @@ -0,0 +1,44 @@ +import { Injectable } from '@nestjs/common'; +import { fileTypeFromBuffer } from 'file-type'; +import { ImageEntity } from 'src/images/image.entity'; +import { ImagesService } from 'src/images/images.service'; +import { FullMime, MimesService } from 'src/images/mimes.service'; +import { AsyncFailable, Fail, HasFailed } from 'src/lib/maybe'; + +@Injectable() +export class SafeImagesService { + constructor( + private readonly imagesService: ImagesService, + private readonly mimesService: MimesService, + ) {} + + async uploadImage(image: Buffer): AsyncFailable { + const { mime } = await fileTypeFromBuffer(image); + const fullMime = await this.mimesService.getFullMime(mime); + if (HasFailed(fullMime)) return fullMime; + + const processedImage: Buffer = await this.processImage(image, fullMime); + + const imageEntity = await this.imagesService.create( + processedImage, + fullMime.mime, + ); + if (HasFailed(imageEntity)) return imageEntity; + + return imageEntity.hash; + } + + private async processImage(image: Buffer, mime: FullMime): Promise { + return image; + } + + async retrieveImage(hash: string): AsyncFailable { + if (!this.validateHash(hash)) return Fail('Invalid hash'); + + return await this.imagesService.findOne(hash); + } + + validateHash(hash: string): boolean { + return /^[a-f0-9]{64}$/.test(hash); + } +} diff --git a/src/users/user.entity.ts b/src/users/user.entity.ts index d1c7026..130ab76 100644 --- a/src/users/user.entity.ts +++ b/src/users/user.entity.ts @@ -1,10 +1,11 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'; @Entity() export class UserEntity { @PrimaryGeneratedColumn() id: number; + @Index() @Column({ unique: true }) username: string; diff --git a/src/users/users.service.ts b/src/users/users.service.ts index cc5d1e0..2a8ccaa 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -1,7 +1,13 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { AsyncMaybe, Nothing } from 'src/lib/maybe'; -import { Not, Repository } from 'typeorm'; +import { + AsyncFailable, + Fail, + Failure, + HasFailed, + HasSuccess, +} from 'src/lib/maybe'; +import { Repository } from 'typeorm'; import { UserEntity } from './user.entity'; @Injectable() @@ -14,46 +20,65 @@ export class UsersService { async createUser( username: string, hashedPassword: string, - ): AsyncMaybe { - if (await this.exists(username)) return Nothing; + ): AsyncFailable { + if (await this.exists(username)) return Fail('User already exists'); const user = new UserEntity(); user.username = username; user.password = hashedPassword; - await this.usersRepository.save(user); + + try { + await this.usersRepository.save(user); + } catch (e) { + return Fail(e.message); + } return user; } - async removeUser(user: string | UserEntity): AsyncMaybe { + async removeUser(user: string | UserEntity): AsyncFailable { const userToModify = await this.resolveUser(user); - if (user === Nothing) return Nothing; + if (HasFailed(userToModify)) return userToModify; - await this.usersRepository.remove(userToModify); + try { + await this.usersRepository.remove(userToModify); + } catch (e) { + return Fail(e.message); + } return userToModify; } - async findOne(username: string): AsyncMaybe { - return await this.usersRepository.findOne({ where: { username } }); + async findOne(username: string): AsyncFailable { + try { + const found = await this.usersRepository.findOne({ where: { username } }); + if (!found) return Fail('User not found'); + return found; + } catch (e) { + return Fail(e.message); + } } - async findAll(): Promise { - return await this.usersRepository.find(); + async findAll(): AsyncFailable { + try { + return await this.usersRepository.find(); + } catch (e) { + return Fail(e.message); + } } async exists(username: string): Promise { - return (await this.findOne(username)) !== Nothing; + return HasSuccess(await this.findOne(username)); } async modifyAdmin( user: string | UserEntity, admin: boolean, - ): Promise { + ): AsyncFailable { const userToModify = await this.resolveUser(user); - if (userToModify === Nothing) return false; + if (HasFailed(userToModify)) return userToModify; userToModify.isAdmin = admin; await this.usersRepository.save(userToModify); @@ -61,7 +86,9 @@ export class UsersService { return true; } - private async resolveUser(user: string | UserEntity): Promise { + private async resolveUser( + user: string | UserEntity, + ): AsyncFailable { if (typeof user === 'string') { return await this.findOne(user); } else { diff --git a/tsconfig.json b/tsconfig.json index d8e88dc..42a880f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,12 +1,14 @@ { "compilerOptions": { - "module": "commonjs", + "module": "es2020", + "moduleResolution": "node", + "esModuleInterop": true, "declaration": true, "removeComments": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "allowSyntheticDefaultImports": true, - "target": "es2017", + "target": "es2020", "sourceMap": true, "outDir": "./dist", "baseUrl": "./", diff --git a/yarn.lock b/yarn.lock index 58f0732..37ec43a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -122,6 +122,13 @@ dependencies: ajv "^6.12.6" +"@fastify/busboy@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-1.0.0.tgz#f73182e61955ab91f8ec5a137fda2c9cee366dbd" + integrity sha512-tzTXX1TFEjWCseEsNdIlXXkD+48uJoN+zpqIojUX4pSoMscsbhO/UuVEB5SzJucexqDWOo2ma0ECwdD7hZdrzg== + dependencies: + text-decoding "^1.0.0" + "@humanwhocodes/config-array@^0.5.0": version "0.5.0" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" @@ -289,6 +296,11 @@ resolved "https://registry.yarnpkg.com/@sqltools/formatter/-/formatter-1.2.3.tgz#1185726610acc37317ddab11c3c7f9066966bd20" integrity sha512-O3uyB/JbkAEMZaP3YqyHH7TMnex7tWyCbCI4EfJdOCoN6HIhqdJBWTM6aCCiWQ/5f5wxjgU735QAIpJbjDvmzg== +"@tokenizer/token@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276" + integrity sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A== + "@tsconfig/node10@^1.0.7": version "1.0.8" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" @@ -371,7 +383,7 @@ "@types/qs" "*" "@types/range-parser" "*" -"@types/express@*", "@types/express@^4.17.13": +"@types/express@*": version "4.17.13" resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== @@ -410,6 +422,13 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== +"@types/multer@^1.4.7": + version "1.4.7" + resolved "https://registry.yarnpkg.com/@types/multer/-/multer-1.4.7.tgz#89cf03547c28c7bbcc726f029e2a76a7232cc79e" + integrity sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA== + dependencies: + "@types/express" "*" + "@types/node@*": version "17.0.18" resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.18.tgz#3b4fed5cfb58010e3a2be4b6e74615e4847f1074" @@ -870,21 +889,11 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -asap@^2.0.0: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= - astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - at-least-node@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" @@ -1001,14 +1010,6 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -call-bind@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -1173,13 +1174,6 @@ colors@1.4.0: resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== -combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - commander@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" @@ -1190,11 +1184,6 @@ commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -component-emitter@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1215,11 +1204,6 @@ cookie@^0.4.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== -cookiejar@^2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc" - integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== - cosmiconfig@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" @@ -1245,7 +1229,7 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" -debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3: +debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.1, debug@^4.3.1: version "4.3.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== @@ -1269,11 +1253,6 @@ defaults@^1.0.3: dependencies: clone "^1.0.2" -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" @@ -1284,14 +1263,6 @@ detect-libc@^1.0.3: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= -dezalgo@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" - integrity sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY= - dependencies: - asap "^2.0.0" - wrappy "1" - diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -1333,7 +1304,7 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -end-of-stream@^1.1.0: +end-of-stream@^1.1.0, end-of-stream@^1.4.4: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -1595,7 +1566,7 @@ fast-redact@^3.0.0: resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.1.0.tgz#37c26cda9cab70bc04393f7ba1feb2d176da6c6b" integrity sha512-dir8LOnvialLxiXDPESMDHGp82CHi6ZEYTVkcvdn5d7psdv9ZkkButXrOeXST4aqreIRR+N7CYlsrwFuorurVg== -fast-safe-stringify@2.1.1, fast-safe-stringify@^2.0.8, fast-safe-stringify@^2.1.1: +fast-safe-stringify@2.1.1, fast-safe-stringify@^2.0.8: version "2.1.1" resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== @@ -1620,6 +1591,20 @@ fastify-formbody@5.2.0: dependencies: fastify-plugin "^3.0.0" +fastify-multipart@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/fastify-multipart/-/fastify-multipart-5.3.1.tgz#05254d8aa43dc02af6ce01f4e513a6c30bea2886" + integrity sha512-c2pnGfkJmiNpYqzFYT2QfBg/06AxG531O+n1elqc8YUbWPRzufdqn3yfGAIV3RA7J4Vnf7Pfvgx0iaWqaRTOVA== + dependencies: + "@fastify/busboy" "^1.0.0" + deepmerge "^4.2.2" + end-of-stream "^1.4.4" + fastify-error "^0.3.0" + fastify-plugin "^3.0.0" + hexoid "^1.0.0" + secure-json-parse "^2.4.0" + stream-wormhole "^1.1.0" + fastify-plugin@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-3.0.1.tgz#79e84c29f401020f38b524f59f2402103fd21ed2" @@ -1651,6 +1636,27 @@ fastify@3.27.1: semver "^7.3.2" tiny-lru "^7.0.0" +fastify@^3.27.2: + version "3.27.2" + resolved "https://registry.yarnpkg.com/fastify/-/fastify-3.27.2.tgz#61fd226dd72b2d8b6b82e6bf71c18e495026545d" + integrity sha512-InZSbbfdBV8yfsTzX0Ei7aF3r7FjC+DPIf27IlTP5EIhSsvTjvlRNwxDPYYGi2NX2K654Vh+zCGCy/GaSigIuw== + dependencies: + "@fastify/ajv-compiler" "^1.0.0" + abstract-logging "^2.0.0" + avvio "^7.1.2" + fast-json-stringify "^2.5.2" + fastify-error "^0.3.0" + find-my-way "^4.5.0" + flatstr "^1.0.12" + light-my-request "^4.2.0" + pino "^6.13.0" + process-warning "^1.0.0" + proxy-addr "^2.0.7" + rfdc "^1.1.4" + secure-json-parse "^2.0.0" + semver "^7.3.2" + tiny-lru "^8.0.1" + fastq@^1.6.0, fastq@^1.6.1: version "1.13.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" @@ -1672,6 +1678,15 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" +file-type@^17.1.1: + version "17.1.1" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-17.1.1.tgz#24c59bc663df0c0c181b31dfacde25e06431afbe" + integrity sha512-heRUMZHby2Qj6wZAA3YHeMlRmZNQTcb6VxctkGmM+mcM6ROQKvHpr7SS6EgdfEhH+s25LDshBjvPx/Ecm+bOVQ== + dependencies: + readable-web-to-node-stream "^3.0.2" + strtok3 "^7.0.0-alpha.7" + token-types "^5.0.0-alpha.2" + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -1731,25 +1746,6 @@ fork-ts-checker-webpack-plugin@6.5.0: semver "^7.3.2" tapable "^1.0.0" -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -formidable@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/formidable/-/formidable-2.0.1.tgz#4310bc7965d185536f9565184dee74fbb75557ff" - integrity sha512-rjTMNbp2BpfQShhFbR3Ruk3qk2y9jKpvMW78nJgx8QKtxjDVrwbZG+wvDOmVbifHyOUOQJXxqEy6r0faRrPzTQ== - dependencies: - dezalgo "1.0.3" - hexoid "1.0.0" - once "1.4.0" - qs "6.9.3" - forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -1826,15 +1822,6 @@ get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.2: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - get-stream@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" @@ -1900,11 +1887,6 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbols@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" - integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== - has-unicode@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -1917,7 +1899,7 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -hexoid@1.0.0: +hexoid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/hexoid/-/hexoid-1.0.0.tgz#ad10c6573fb907de23d9ec63a711267d9dc9bc18" integrity sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g== @@ -2360,11 +2342,6 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -methods@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - micromatch@^4.0.0, micromatch@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" @@ -2387,18 +2364,13 @@ mime-db@1.51.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== -mime-types@^2.1.12, mime-types@^2.1.27: +mime-types@^2.1.27: version "2.1.34" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== dependencies: mime-db "1.51.0" -mime@^2.5.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" - integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== - mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -2533,12 +2505,7 @@ object-hash@2.2.0: resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5" integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== -object-inspect@^1.9.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" - integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== - -once@1.4.0, once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= @@ -2699,6 +2666,11 @@ pause@0.0.1: resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" integrity sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10= +peek-readable@^5.0.0-alpha.5: + version "5.0.0-alpha.5" + resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-5.0.0-alpha.5.tgz#ace5dfedf7bc33f17c9b5170b9d54f69a4fba79b" + integrity sha512-pJohF/tDwV3ntnT5+EkUo4E700q/j/OCDuPxtM+5/kFGjyOai/sK4/We4Cy1MB2OiTQliWU5DxPvYIKQAdPqAA== + pg-connection-string@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.5.0.tgz#538cadd0f7e603fc09a12590f3b8a452c2c0cf34" @@ -2853,18 +2825,6 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -qs@6.9.3: - version "6.9.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.3.tgz#bfadcd296c2d549f1dffa560619132c977f5008e" - integrity sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw== - -qs@^6.10.1: - version "6.10.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" - integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== - dependencies: - side-channel "^1.0.4" - queue-microtask@^1.1.2, queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -2891,6 +2851,13 @@ readable-stream@^3.4.0, readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-web-to-node-stream@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz#5d52bb5df7b54861fd48d015e93a2cb87b3ee0bb" + integrity sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw== + dependencies: + readable-stream "^3.6.0" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -3035,7 +3002,7 @@ schema-utils@^3.1.0, schema-utils@^3.1.1: ajv "^6.12.5" ajv-keywords "^3.5.2" -secure-json-parse@^2.0.0: +secure-json-parse@^2.0.0, secure-json-parse@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.4.0.tgz#5aaeaaef85c7a417f76271a4f5b0cc3315ddca85" integrity sha512-Q5Z/97nbON5t/L/sH6mY2EacfjVGwrCcSi5D3btRO2GZ8pf1K1UN7Z9H5J57hjVU2Qzxr1xO+FmBhOvEkzCMmg== @@ -3108,15 +3075,6 @@ shelljs@0.8.5: interpret "^1.0.0" rechoir "^0.6.2" -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" @@ -3177,6 +3135,11 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= +stream-wormhole@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/stream-wormhole/-/stream-wormhole-1.1.0.tgz#300aff46ced553cfec642a05251885417693c33d" + integrity sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew== + string-similarity@^4.0.1: version "4.0.4" resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b" @@ -3220,30 +3183,13 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -superagent@^7.1.0: - version "7.1.1" - resolved "https://registry.yarnpkg.com/superagent/-/superagent-7.1.1.tgz#2ab187d38c3078c31c3771c0b751f10163a27136" - integrity sha512-CQ2weSS6M+doIwwYFoMatklhRbx6sVNdB99OEJ5czcP3cng76Ljqus694knFWgOj3RkrtxZqIgpe6vhe0J7QWQ== +strtok3@^7.0.0-alpha.7: + version "7.0.0-alpha.8" + resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-7.0.0-alpha.8.tgz#23a7870974e0494b58b14af6dd1c2c67cf13314d" + integrity sha512-u+k19v+rTxBjGYxncRQjGvZYwYvEd0uP3D+uHKe/s4WB1eXS5ZwpZsTlBu5xSS4zEd89mTXECXg6WW3FSeV8cA== dependencies: - component-emitter "^1.3.0" - cookiejar "^2.1.3" - debug "^4.3.3" - fast-safe-stringify "^2.1.1" - form-data "^4.0.0" - formidable "^2.0.1" - methods "^1.1.2" - mime "^2.5.0" - qs "^6.10.1" - readable-stream "^3.6.0" - semver "^7.3.5" - -supertest@^6.1.6: - version "6.2.2" - resolved "https://registry.yarnpkg.com/supertest/-/supertest-6.2.2.tgz#04a5998fd3efaff187cb69f07a169755d655b001" - integrity sha512-wCw9WhAtKJsBvh07RaS+/By91NNE0Wh0DN19/hWPlBOU8tAfOtbZoVSV4xXeoKoxgPx0rx2y+y+8660XtE7jzg== - dependencies: - methods "^1.1.2" - superagent "^7.1.0" + "@tokenizer/token" "^0.3.0" + peek-readable "^5.0.0-alpha.5" supports-color@^5.3.0: version "5.5.0" @@ -3329,6 +3275,11 @@ terser@^5.7.2: source-map "~0.7.2" source-map-support "~0.5.20" +text-decoding@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/text-decoding/-/text-decoding-1.0.0.tgz#38a5692d23b5c2b12942d6e245599cb58b1bc52f" + integrity sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA== + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -3358,6 +3309,11 @@ tiny-lru@^7.0.0: resolved "https://registry.yarnpkg.com/tiny-lru/-/tiny-lru-7.0.6.tgz#b0c3cdede1e5882aa2d1ae21cb2ceccf2a331f24" integrity sha512-zNYO0Kvgn5rXzWpL0y3RS09sMK67eGaQj9805jlK9G6pSadfriTczzLHFXa/xcW4mIRfmlB9HyQ/+SgL0V1uow== +tiny-lru@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/tiny-lru/-/tiny-lru-8.0.1.tgz#c1d77d806e68035aaa2253e253d212291240ece2" + integrity sha512-eBIAYA0BzSjxBedCaO0CSjertD+u+IvNuFkyD7ESf+qjqHKBr5wFqvEYl91+ZQd7jjq2pO6/fBVwFgb6bxvorw== + tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -3372,6 +3328,14 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +token-types@^5.0.0-alpha.2: + version "5.0.0-alpha.2" + resolved "https://registry.yarnpkg.com/token-types/-/token-types-5.0.0-alpha.2.tgz#e43d63b2a8223a593d1c782a5149bec18f1abf97" + integrity sha512-EsG9UxAW4M6VATrEEjhPFTKEUi1OiJqTUMIZOGBN49fGxYjZB36k0p7to3HZSmWRoHm1QfZgrg3e02fpqAt5fQ== + dependencies: + "@tokenizer/token" "^0.3.0" + ieee754 "^1.2.1" + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -3487,11 +3451,16 @@ typeorm@^0.2.43: yargs "^17.0.1" zen-observable-ts "^1.0.0" -typescript@4.5.5, typescript@^4.4.4: +typescript@4.5.5: version "4.5.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== +typescript@^4.7.0-dev.20220221: + version "4.7.0-dev.20220221" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.0-dev.20220221.tgz#c1b20e391f2d324d9b4f7f32d467949dd9f3954f" + integrity sha512-KG/K5SboPsuI/1HIJvqCdegnrVTp13uHrSuIVtLexe5FC3d1uasepzRP7tuglmoaPxE3qaoya3eeGa1/V9N4Dg== + universalify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"