upload works

This commit is contained in:
rubikscraft
2022-02-21 22:17:44 +01:00
parent d9e7ae06fb
commit 754debbcf8
20 changed files with 514 additions and 206 deletions

View File

@@ -1,4 +1,9 @@
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src"
"sourceRoot": "src",
"generateOptions": {
"spec": false
},
"exec": "pog"
}

View File

@@ -6,13 +6,14 @@
"license": "GPL-3.0",
"repository": "https://github.com/rubikscraft/Imagur-Backend",
"author": "Rubikscraft <contact@rubikscraft.nl>",
"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"
}
}

View File

@@ -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 {}

View File

@@ -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;
}
}

View File

@@ -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<UserEntity> {
async createUser(
username: string,
password: string,
): AsyncFailable<UserEntity> {
const hashedPassword = await bcrypt.hash(password, 12);
return this.usersService.createUser(username, hashedPassword);
}
async deleteUser(user: string | UserEntity): AsyncMaybe<UserEntity> {
async deleteUser(user: string | UserEntity): AsyncFailable<UserEntity> {
return this.usersService.removeUser(user);
}
async listUsers(): Promise<User[]> {
async listUsers(): AsyncFailable<User[]> {
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<UserEntity> {
): AsyncFailable<UserEntity> {
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<boolean> {
async makeAdmin(user: string | UserEntity): AsyncFailable<true> {
return this.usersService.modifyAdmin(user, true);
}
async revokeAdmin(user: string | UserEntity): Promise<boolean> {
async revokeAdmin(user: string | UserEntity): AsyncFailable<true> {
return this.usersService.modifyAdmin(user, false);
}

View File

@@ -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<UserEntity> {
async validate(
username: string,
password: string,
): AsyncFailable<UserEntity> {
const user = await this.authService.authenticate(username, password);
if (user === Nothing) {
if (HasFailed(user)) {
throw new UnauthorizedException();
}
return user;

View File

@@ -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;
}

View File

@@ -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 {}

View File

@@ -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<ImageEntity>,
) {}
async create(image: Buffer, type: SupportedMime): AsyncFailable<ImageEntity> {
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<ImageEntity> {
const found = await this.imageRepository.findOne({ where: { hash } });
if (found === undefined) return Fail('Image not found');
return found;
}
async delete(hash: string): AsyncFailable<true> {
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');
}
}

View File

@@ -0,0 +1,47 @@
import { Injectable } from '@nestjs/common';
import { Fail, Failable } from 'src/lib/maybe';
const tuple = <T extends string[]>(...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<FullMime> {
if (SupportedImageMimes.includes(mime)) {
return { mime, type: 'image' };
}
if (SupportedAnimMimes.includes(mime)) {
return { mime, type: 'anim' };
}
return Fail('Unsupported mime type');
}
}

View File

@@ -1,5 +1,23 @@
export const Nothing = undefined;
export type Nothing = undefined;
export type Maybe<T> = T | Nothing;
export class Failure {
constructor(private readonly reason?: string) {}
export type AsyncMaybe<T> = Promise<Maybe<T>>;
getReason(): string {
return this.reason ?? 'Unknown';
}
}
export function Fail(reason?: string): Failure {
return new Failure(reason);
}
export type Failable<T> = T | Failure;
export type AsyncFailable<T> = Promise<Failable<T>>;
export function HasFailed<T>(failable: Failable<T>): failable is Failure {
return failable instanceof Failure;
}
export function HasSuccess<T>(failable: Failable<T>): failable is T {
return !(failable instanceof Failure);
}

View File

@@ -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<NestFastifyApplication>(
AppModule,
new FastifyAdapter(),
fastifyAdapter,
);
app.useGlobalPipes(new ValidationPipe({ disableErrorMessages: true }));
await app.listen(3000);

View File

@@ -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 };
}
}

10
src/root/root.module.ts Normal file
View File

@@ -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 {}

View File

@@ -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 {}

View File

@@ -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<string> {
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<Buffer> {
return image;
}
async retrieveImage(hash: string): AsyncFailable<ImageEntity> {
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);
}
}

View File

@@ -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;

View File

@@ -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<UserEntity> {
if (await this.exists(username)) return Nothing;
): AsyncFailable<UserEntity> {
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<UserEntity> {
async removeUser(user: string | UserEntity): AsyncFailable<UserEntity> {
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<UserEntity> {
return await this.usersRepository.findOne({ where: { username } });
async findOne(username: string): AsyncFailable<UserEntity> {
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<UserEntity[]> {
return await this.usersRepository.find();
async findAll(): AsyncFailable<UserEntity[]> {
try {
return await this.usersRepository.find();
} catch (e) {
return Fail(e.message);
}
}
async exists(username: string): Promise<boolean> {
return (await this.findOne(username)) !== Nothing;
return HasSuccess(await this.findOne(username));
}
async modifyAdmin(
user: string | UserEntity,
admin: boolean,
): Promise<boolean> {
): AsyncFailable<true> {
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<UserEntity> {
private async resolveUser(
user: string | UserEntity,
): AsyncFailable<UserEntity> {
if (typeof user === 'string') {
return await this.findOne(user);
} else {

View File

@@ -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": "./",

267
yarn.lock
View File

@@ -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"