feat: add media service
This commit is contained in:
parent
36c058f885
commit
b2e02e0ae2
@ -41,6 +41,7 @@
|
|||||||
"class-validator": "^0.14.3",
|
"class-validator": "^0.14.3",
|
||||||
"cookie-parser": "^1.4.7",
|
"cookie-parser": "^1.4.7",
|
||||||
"cross-env": "^10.1.0",
|
"cross-env": "^10.1.0",
|
||||||
|
"multer": "^2.1.1",
|
||||||
"prom-client": "^15.1.3",
|
"prom-client": "^15.1.3",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rxjs": "^7.8.1"
|
"rxjs": "^7.8.1"
|
||||||
@ -55,6 +56,7 @@
|
|||||||
"@types/cookie-parser": "^1.4.10",
|
"@types/cookie-parser": "^1.4.10",
|
||||||
"@types/express": "^5.0.0",
|
"@types/express": "^5.0.0",
|
||||||
"@types/jest": "^30.0.0",
|
"@types/jest": "^30.0.0",
|
||||||
|
"@types/multer": "^2.1.0",
|
||||||
"@types/node": "^22.10.7",
|
"@types/node": "^22.10.7",
|
||||||
"@types/supertest": "^6.0.2",
|
"@types/supertest": "^6.0.2",
|
||||||
"eslint": "^9.18.0",
|
"eslint": "^9.18.0",
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { PassportModule } from '@teacinema/passport'
|
|||||||
|
|
||||||
import { AccountModule } from '../modules/account/account.module'
|
import { AccountModule } from '../modules/account/account.module'
|
||||||
import { AuthModule } from '../modules/auth/auth.module'
|
import { AuthModule } from '../modules/auth/auth.module'
|
||||||
|
import { MediaModule } from '../modules/media/media.module'
|
||||||
import { UsersModule } from '../modules/users/users.module'
|
import { UsersModule } from '../modules/users/users.module'
|
||||||
import { ObservabilityModule } from '../observability/observability.module'
|
import { ObservabilityModule } from '../observability/observability.module'
|
||||||
|
|
||||||
@ -24,6 +25,7 @@ import { getPassportConfig } from './config'
|
|||||||
ObservabilityModule,
|
ObservabilityModule,
|
||||||
AuthModule,
|
AuthModule,
|
||||||
AccountModule,
|
AccountModule,
|
||||||
|
MediaModule,
|
||||||
UsersModule,
|
UsersModule,
|
||||||
PassportModule.registerAsync({
|
PassportModule.registerAsync({
|
||||||
useFactory: getPassportConfig,
|
useFactory: getPassportConfig,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { Injectable } from '@nestjs/common'
|
import { Injectable } from '@nestjs/common'
|
||||||
import type { ClientGrpc } from '@nestjs/microservices'
|
import type { ClientGrpc } from '@nestjs/microservices'
|
||||||
import { InjectGrpc } from '@teacinema/common'
|
import { InjectGrpc } from '@teacinema/common'
|
||||||
import { AccountServiceClient } from '@teacinema/contracts/gen/account'
|
import { AccountServiceClient } from '@teacinema/contracts/gen/ts/account'
|
||||||
|
|
||||||
import { AbstractGrpcClient } from '../../shared/grpc/abstract-grpc.client'
|
import { AbstractGrpcClient } from '../../shared/grpc/abstract-grpc.client'
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { Injectable } from '@nestjs/common'
|
import { Injectable } from '@nestjs/common'
|
||||||
import type { ClientGrpc } from '@nestjs/microservices'
|
import type { ClientGrpc } from '@nestjs/microservices'
|
||||||
import { InjectGrpc } from '@teacinema/common'
|
import { InjectGrpc } from '@teacinema/common'
|
||||||
import { AuthServiceClient } from '@teacinema/contracts/gen/auth'
|
import { AuthServiceClient } from '@teacinema/contracts/gen/ts/auth'
|
||||||
|
|
||||||
import { AbstractGrpcClient } from '../../shared/grpc/abstract-grpc.client'
|
import { AbstractGrpcClient } from '../../shared/grpc/abstract-grpc.client'
|
||||||
|
|
||||||
|
|||||||
13
src/modules/media/media.grpc.ts
Normal file
13
src/modules/media/media.grpc.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { Injectable } from '@nestjs/common'
|
||||||
|
import type { ClientGrpc } from '@nestjs/microservices'
|
||||||
|
import { InjectGrpc } from '@teacinema/common'
|
||||||
|
import { MediaServiceClient } from '@teacinema/contracts/gen/ts/media'
|
||||||
|
|
||||||
|
import { AbstractGrpcClient } from '../../shared/grpc/abstract-grpc.client'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class MediaClientGrpc extends AbstractGrpcClient<MediaServiceClient> {
|
||||||
|
constructor(@InjectGrpc('MEDIA_PACKAGE') client: ClientGrpc) {
|
||||||
|
super(client, 'MediaService')
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/modules/media/media.module.ts
Normal file
11
src/modules/media/media.module.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { Module } from '@nestjs/common'
|
||||||
|
import { GrpcModule } from '@teacinema/common'
|
||||||
|
|
||||||
|
import { MediaClientGrpc } from './media.grpc'
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [GrpcModule.register(['MEDIA_PACKAGE'])],
|
||||||
|
providers: [MediaClientGrpc],
|
||||||
|
exports: [MediaClientGrpc]
|
||||||
|
})
|
||||||
|
export class MediaModule {}
|
||||||
@ -1,14 +1,28 @@
|
|||||||
import {
|
import {
|
||||||
Body,
|
Body,
|
||||||
Controller,
|
Controller,
|
||||||
|
FileTypeValidator,
|
||||||
Get,
|
Get,
|
||||||
HttpCode,
|
HttpCode,
|
||||||
HttpStatus,
|
HttpStatus,
|
||||||
Patch
|
MaxFileSizeValidator,
|
||||||
|
ParseFilePipe,
|
||||||
|
Patch,
|
||||||
|
UploadedFile,
|
||||||
|
UseInterceptors
|
||||||
} from '@nestjs/common'
|
} from '@nestjs/common'
|
||||||
import { ApiBearerAuth, ApiOkResponse, ApiOperation } from '@nestjs/swagger'
|
import { FileInterceptor } from '@nestjs/platform-express'
|
||||||
|
import {
|
||||||
|
ApiBearerAuth,
|
||||||
|
ApiBody,
|
||||||
|
ApiConsumes,
|
||||||
|
ApiOkResponse,
|
||||||
|
ApiOperation
|
||||||
|
} from '@nestjs/swagger'
|
||||||
|
import { randomBytes } from 'node:crypto'
|
||||||
|
|
||||||
import { CurrentUser, Protected } from '../../shared/decorators'
|
import { CurrentUser, Protected } from '../../shared/decorators'
|
||||||
|
import { MediaClientGrpc } from '../media/media.grpc'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
GetMeResponseDto,
|
GetMeResponseDto,
|
||||||
@ -17,9 +31,15 @@ import {
|
|||||||
} from './dto'
|
} from './dto'
|
||||||
import { UsersClientGrpc } from './users.grpc'
|
import { UsersClientGrpc } from './users.grpc'
|
||||||
|
|
||||||
|
const AVATAR_MAX_SIZE = 10_485_760 // 10 MB
|
||||||
|
const AVATAR_ALLOWED_MIME_TYPES = /image\/(jpg|jpeg|gif|png)/
|
||||||
|
|
||||||
@Controller('users')
|
@Controller('users')
|
||||||
export class UsersController {
|
export class UsersController {
|
||||||
constructor(private readonly client: UsersClientGrpc) {}
|
constructor(
|
||||||
|
private readonly users: UsersClientGrpc,
|
||||||
|
private readonly media: MediaClientGrpc
|
||||||
|
) {}
|
||||||
|
|
||||||
@ApiOperation({
|
@ApiOperation({
|
||||||
summary: 'Get Me',
|
summary: 'Get Me',
|
||||||
@ -31,7 +51,7 @@ export class UsersController {
|
|||||||
@Get('me')
|
@Get('me')
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
public async getMe(@CurrentUser() userId: string) {
|
public async getMe(@CurrentUser() userId: string) {
|
||||||
const { user } = await this.client.call('getMe', { id: userId })
|
const { user } = await this.users.call('getMe', { id: userId })
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,6 +68,62 @@ export class UsersController {
|
|||||||
@CurrentUser() userId: string,
|
@CurrentUser() userId: string,
|
||||||
@Body() dto: PatchUserRequestDto
|
@Body() dto: PatchUserRequestDto
|
||||||
) {
|
) {
|
||||||
return this.client.call('patchUser', { userId, ...dto })
|
return this.users.call('patchUser', { userId, ...dto })
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation({
|
||||||
|
summary: 'Update user avatar',
|
||||||
|
description: 'Update user avatar'
|
||||||
|
})
|
||||||
|
@ApiConsumes('multipart/form-data')
|
||||||
|
@ApiBody({
|
||||||
|
description: 'Avatar file',
|
||||||
|
schema: {
|
||||||
|
type: 'object',
|
||||||
|
properties: { file: { type: 'string', format: 'binary' } },
|
||||||
|
required: ['file']
|
||||||
|
}
|
||||||
|
})
|
||||||
|
@ApiBearerAuth()
|
||||||
|
@ApiOkResponse({ type: PatchUserResponseDto })
|
||||||
|
@ApiConsumes('multipart/form-data')
|
||||||
|
@ApiBody({
|
||||||
|
schema: {
|
||||||
|
type: 'object',
|
||||||
|
properties: { file: { type: 'string', format: 'binary' } },
|
||||||
|
required: ['file']
|
||||||
|
}
|
||||||
|
})
|
||||||
|
@UseInterceptors(
|
||||||
|
FileInterceptor('file', { limits: { fileSize: AVATAR_MAX_SIZE } })
|
||||||
|
)
|
||||||
|
@Protected()
|
||||||
|
@Patch('me/avatar')
|
||||||
|
@HttpCode(HttpStatus.OK)
|
||||||
|
public async changeAvatar(
|
||||||
|
@CurrentUser() userId: string,
|
||||||
|
@UploadedFile(
|
||||||
|
new ParseFilePipe({
|
||||||
|
validators: [
|
||||||
|
new MaxFileSizeValidator({ maxSize: AVATAR_MAX_SIZE }),
|
||||||
|
new FileTypeValidator({ fileType: AVATAR_ALLOWED_MIME_TYPES })
|
||||||
|
]
|
||||||
|
})
|
||||||
|
)
|
||||||
|
file: Express.Multer.File
|
||||||
|
) {
|
||||||
|
const response = await this.media.call('upload', {
|
||||||
|
fileName: randomBytes(16).toString('hex'),
|
||||||
|
folder: 'users',
|
||||||
|
contentType: file.mimetype,
|
||||||
|
data: new Uint8Array(file.buffer),
|
||||||
|
resizeWidth: 512,
|
||||||
|
resizeHeight: 512
|
||||||
|
})
|
||||||
|
|
||||||
|
return this.users.call('patchUser', {
|
||||||
|
userId,
|
||||||
|
avatar: response.key
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { Injectable } from '@nestjs/common'
|
import { Injectable } from '@nestjs/common'
|
||||||
import type { ClientGrpc } from '@nestjs/microservices'
|
import type { ClientGrpc } from '@nestjs/microservices'
|
||||||
import { InjectGrpc } from '@teacinema/common'
|
import { InjectGrpc } from '@teacinema/common'
|
||||||
import { UsersServiceClient } from '@teacinema/contracts/gen/users'
|
import { UsersServiceClient } from '@teacinema/contracts/gen/ts/users'
|
||||||
|
|
||||||
import { AbstractGrpcClient } from '../../shared/grpc/abstract-grpc.client'
|
import { AbstractGrpcClient } from '../../shared/grpc/abstract-grpc.client'
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
import { Module } from '@nestjs/common'
|
import { Module } from '@nestjs/common'
|
||||||
import { GrpcModule } from '@teacinema/common'
|
import { GrpcModule } from '@teacinema/common'
|
||||||
|
|
||||||
|
import { MediaModule } from '../media/media.module'
|
||||||
|
|
||||||
import { UsersController } from './users.controller'
|
import { UsersController } from './users.controller'
|
||||||
import { UsersClientGrpc } from './users.grpc'
|
import { UsersClientGrpc } from './users.grpc'
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [GrpcModule.register(['USERS_PACKAGE'])],
|
imports: [GrpcModule.register(['USERS_PACKAGE']), MediaModule],
|
||||||
controllers: [UsersController],
|
controllers: [UsersController],
|
||||||
providers: [UsersClientGrpc],
|
providers: [UsersClientGrpc],
|
||||||
exports: [UsersClientGrpc]
|
exports: [UsersClientGrpc]
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { applyDecorators, UseGuards } from '@nestjs/common'
|
import { applyDecorators, UseGuards } from '@nestjs/common'
|
||||||
import { Role } from '@teacinema/contracts/gen/account'
|
import { Role } from '@teacinema/contracts/gen/ts/account'
|
||||||
|
|
||||||
import { AuthGuard, RolesGuard } from '../guards'
|
import { AuthGuard, RolesGuard } from '../guards'
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { SetMetadata } from '@nestjs/common'
|
import { SetMetadata } from '@nestjs/common'
|
||||||
import { Role } from '@teacinema/contracts/gen/account'
|
import { Role } from '@teacinema/contracts/gen/ts/account'
|
||||||
|
|
||||||
export const ROLES_KEY = 'required_roles'
|
export const ROLES_KEY = 'required_roles'
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import {
|
|||||||
NotFoundException
|
NotFoundException
|
||||||
} from '@nestjs/common'
|
} from '@nestjs/common'
|
||||||
import { Reflector } from '@nestjs/core'
|
import { Reflector } from '@nestjs/core'
|
||||||
import { Role } from '@teacinema/contracts/gen/account'
|
import { Role } from '@teacinema/contracts/gen/ts/account'
|
||||||
import { Request } from 'express'
|
import { Request } from 'express'
|
||||||
|
|
||||||
import { AccountClientGrpc } from '../../modules/account/account.grpc'
|
import { AccountClientGrpc } from '../../modules/account/account.grpc'
|
||||||
|
|||||||
67
yarn.lock
67
yarn.lock
@ -329,9 +329,9 @@
|
|||||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||||
|
|
||||||
"@borewit/text-codec@^0.2.1":
|
"@borewit/text-codec@^0.2.1":
|
||||||
version "0.2.1"
|
version "0.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/@borewit/text-codec/-/text-codec-0.2.1.tgz#5d171538907a8cb395fdc2eb5e8f7947d96c7f2f"
|
resolved "https://registry.yarnpkg.com/@borewit/text-codec/-/text-codec-0.2.2.tgz#75025f735c0983b3a871668804a57387e3649375"
|
||||||
integrity sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw==
|
integrity sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==
|
||||||
|
|
||||||
"@bufbuild/protobuf@^2.0.0", "@bufbuild/protobuf@^2.10.2":
|
"@bufbuild/protobuf@^2.0.0", "@bufbuild/protobuf@^2.10.2":
|
||||||
version "2.11.0"
|
version "2.11.0"
|
||||||
@ -1028,12 +1028,12 @@
|
|||||||
tslib "2.8.1"
|
tslib "2.8.1"
|
||||||
|
|
||||||
"@nestjs/common@^11.1.16":
|
"@nestjs/common@^11.1.16":
|
||||||
version "11.1.16"
|
version "11.1.17"
|
||||||
resolved "https://registry.yarnpkg.com/@nestjs/common/-/common-11.1.16.tgz#1f4061f66d7ae63e407f8d2be2aaeaf83097332b"
|
resolved "https://registry.yarnpkg.com/@nestjs/common/-/common-11.1.17.tgz#58a330f3f6748cf92b0a244a2a232cfddba1bfd2"
|
||||||
integrity sha512-JSIeW+USuMJkkcNbiOdcPkVCeI3TSnXstIVEPpp3HiaKnPRuSbUUKm9TY9o/XpIcPHWUOQItAtC5BiAwFdVITQ==
|
integrity sha512-hLODw5Abp8OQgA+mUO4tHou4krKgDtUcM9j5Ihxncst9XeyxYBTt2bwZm4e4EQr5E352S4Fyy6V3iFx9ggxKAg==
|
||||||
dependencies:
|
dependencies:
|
||||||
uid "2.0.2"
|
uid "2.0.2"
|
||||||
file-type "21.3.0"
|
file-type "21.3.2"
|
||||||
iterare "1.2.1"
|
iterare "1.2.1"
|
||||||
load-esm "1.0.3"
|
load-esm "1.0.3"
|
||||||
tslib "2.8.1"
|
tslib "2.8.1"
|
||||||
@ -1094,9 +1094,9 @@
|
|||||||
tslib "2.8.1"
|
tslib "2.8.1"
|
||||||
|
|
||||||
"@nestjs/microservices@^11.1.16":
|
"@nestjs/microservices@^11.1.16":
|
||||||
version "11.1.16"
|
version "11.1.17"
|
||||||
resolved "https://registry.yarnpkg.com/@nestjs/microservices/-/microservices-11.1.16.tgz#6f445c44adcee88af983830e0667c93ccefe2869"
|
resolved "https://registry.yarnpkg.com/@nestjs/microservices/-/microservices-11.1.17.tgz#f2b1aa25e24532377477a437583f1af002118602"
|
||||||
integrity sha512-eG/ArIq0UJyR3i/GTYuApA4OZylhuLGacVaVT9mMxQgT7ZTpp5CZgOwLNdcUUdOS6qypK3waG1m2AC54xzdf0Q==
|
integrity sha512-rubBPEEXS9PwA3LwdNN/ytjEUmON+d8+4fbiUCIFGW8i+rR/g36vrpwuvoAzcGpxlu45/TpZPfHTb0nJciG9Yw==
|
||||||
dependencies:
|
dependencies:
|
||||||
iterare "1.2.1"
|
iterare "1.2.1"
|
||||||
tslib "2.8.1"
|
tslib "2.8.1"
|
||||||
@ -1997,9 +1997,9 @@
|
|||||||
"@sinonjs/commons" "^3.0.1"
|
"@sinonjs/commons" "^3.0.1"
|
||||||
|
|
||||||
"@teacinema/common@^1.0.0":
|
"@teacinema/common@^1.0.0":
|
||||||
version "1.1.3"
|
version "1.1.6"
|
||||||
resolved "https://git.ksv741.keenetic.pro/api/packages/teacinema/npm/%40teacinema%2Fcommon/-/1.1.3/common-1.1.3.tgz#73c8e3642f37d9c6574f6a1e5b542dd6cbfdbf2f"
|
resolved "https://git.ksv741.keenetic.pro/api/packages/teacinema/npm/%40teacinema%2Fcommon/-/1.1.6/common-1.1.6.tgz#4b43fc7c1f19cef0ba138a3a7988918f54f52ebb"
|
||||||
integrity sha512-Bk2JzG3P1K7YFoFywtSP3zHxNfUpy+NyboqChj+4GZ6JuoWg2V1wkrjMljeE90cPOaqCiNHxk08zX037waiKJg==
|
integrity sha512-a0wU0EaJ92PdMlwFQ5pA0EZ9G1/f9Gca8CCN2qUy75q0HldNTGKKYUEyDHx4Y0z16N1e3/RO12gagebOrV6Nbg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nestjs/common" "^11.1.16"
|
"@nestjs/common" "^11.1.16"
|
||||||
"@nestjs/config" "^4.0.3"
|
"@nestjs/config" "^4.0.3"
|
||||||
@ -2007,9 +2007,9 @@
|
|||||||
"@teacinema/contracts" "^1.1.3"
|
"@teacinema/contracts" "^1.1.3"
|
||||||
|
|
||||||
"@teacinema/contracts@^1.0.0", "@teacinema/contracts@^1.1.3":
|
"@teacinema/contracts@^1.0.0", "@teacinema/contracts@^1.1.3":
|
||||||
version "1.1.3"
|
version "1.1.8"
|
||||||
resolved "https://git.ksv741.keenetic.pro/api/packages/teacinema/npm/%40teacinema%2Fcontracts/-/1.1.3/contracts-1.1.3.tgz#e08600a8dc09977dae35654d372e29e411029e33"
|
resolved "https://git.ksv741.keenetic.pro/api/packages/teacinema/npm/%40teacinema%2Fcontracts/-/1.1.8/contracts-1.1.8.tgz#e96c23a957d2682503c157250672eb4c46bf4ef9"
|
||||||
integrity sha512-kwcSh2YIxmoBJQ56L+tQpGj12ySwNwf9KRNcUqhPffLPO60PR5aiKA2eN2SfKc23TKp0YoSkdC9LWeor0a9Ysg==
|
integrity sha512-wSFTntA0IoQrC/iYz3rylJW6qK6KGWa25oQrl/n55aSOcMk1ACmSBt0aqAPML86SQWAsn7yikpr/foaTgJH3zg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nestjs/microservices" "^11.1.12"
|
"@nestjs/microservices" "^11.1.12"
|
||||||
protoc "33.4.0"
|
protoc "33.4.0"
|
||||||
@ -2186,7 +2186,7 @@
|
|||||||
"@types/range-parser" "*"
|
"@types/range-parser" "*"
|
||||||
"@types/send" "*"
|
"@types/send" "*"
|
||||||
|
|
||||||
"@types/express@^5.0.0":
|
"@types/express@*", "@types/express@^5.0.0":
|
||||||
version "5.0.6"
|
version "5.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/@types/express/-/express-5.0.6.tgz#2d724b2c990dcb8c8444063f3580a903f6d500cc"
|
resolved "https://registry.yarnpkg.com/@types/express/-/express-5.0.6.tgz#2d724b2c990dcb8c8444063f3580a903f6d500cc"
|
||||||
integrity sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==
|
integrity sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==
|
||||||
@ -2244,6 +2244,13 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/methods/-/methods-1.1.4.tgz#d3b7ac30ac47c91054ea951ce9eed07b1051e547"
|
resolved "https://registry.yarnpkg.com/@types/methods/-/methods-1.1.4.tgz#d3b7ac30ac47c91054ea951ce9eed07b1051e547"
|
||||||
integrity sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==
|
integrity sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==
|
||||||
|
|
||||||
|
"@types/multer@^2.1.0":
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/multer/-/multer-2.1.0.tgz#c6ae866b9a3d9310b477d021a78b33feda092358"
|
||||||
|
integrity sha512-zYZb0+nJhOHtPpGDb3vqPjwpdeGlGC157VpkqNQL+UU2qwoacoQ7MpsAmUptI/0Oa127X32JzWDqQVEXp2RcIA==
|
||||||
|
dependencies:
|
||||||
|
"@types/express" "*"
|
||||||
|
|
||||||
"@types/mysql@2.15.27":
|
"@types/mysql@2.15.27":
|
||||||
version "2.15.27"
|
version "2.15.27"
|
||||||
resolved "https://registry.yarnpkg.com/@types/mysql/-/mysql-2.15.27.tgz#fb13b0e8614d39d42f40f381217ec3215915f1e9"
|
resolved "https://registry.yarnpkg.com/@types/mysql/-/mysql-2.15.27.tgz#fb13b0e8614d39d42f40f381217ec3215915f1e9"
|
||||||
@ -3846,6 +3853,16 @@ file-type@21.3.0:
|
|||||||
token-types "^6.1.1"
|
token-types "^6.1.1"
|
||||||
uint8array-extras "^1.4.0"
|
uint8array-extras "^1.4.0"
|
||||||
|
|
||||||
|
file-type@21.3.2:
|
||||||
|
version "21.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/file-type/-/file-type-21.3.2.tgz#b28bb3a19ea4b03f59af31546b9d95ee8a3623eb"
|
||||||
|
integrity sha512-DLkUvGwep3poOV2wpzbHCOnSKGk1LzyXTv+aHFgN2VFl96wnp8YA9YjO2qPzg5PuL8q/SW9Pdi6WTkYOIh995w==
|
||||||
|
dependencies:
|
||||||
|
"@tokenizer/inflate" "^0.4.1"
|
||||||
|
strtok3 "^10.3.4"
|
||||||
|
token-types "^6.1.1"
|
||||||
|
uint8array-extras "^1.4.0"
|
||||||
|
|
||||||
fill-range@^7.1.1:
|
fill-range@^7.1.1:
|
||||||
version "7.1.1"
|
version "7.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
|
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
|
||||||
@ -5093,6 +5110,16 @@ multer@2.0.2:
|
|||||||
type-is "^1.6.18"
|
type-is "^1.6.18"
|
||||||
xtend "^4.0.2"
|
xtend "^4.0.2"
|
||||||
|
|
||||||
|
multer@^2.1.1:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/multer/-/multer-2.1.1.tgz#122d819244fbdfee1efddd9147426691014385b7"
|
||||||
|
integrity sha512-mo+QTzKlx8R7E5ylSXxWzGoXoZbOsRMpyitcht8By2KHvMbf3tjwosZ/Mu/XYU6UuJ3VZnODIrak5ZrPiPyB6A==
|
||||||
|
dependencies:
|
||||||
|
append-field "^1.0.0"
|
||||||
|
busboy "^1.6.0"
|
||||||
|
concat-stream "^2.0.0"
|
||||||
|
type-is "^1.6.18"
|
||||||
|
|
||||||
mute-stream@^2.0.0:
|
mute-stream@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-2.0.0.tgz#a5446fc0c512b71c83c44d908d5c7b7b4c493b2b"
|
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-2.0.0.tgz#a5446fc0c512b71c83c44d908d5c7b7b4c493b2b"
|
||||||
@ -5883,9 +5910,9 @@ strip-json-comments@^3.1.1:
|
|||||||
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
||||||
|
|
||||||
strtok3@^10.3.4:
|
strtok3@^10.3.4:
|
||||||
version "10.3.4"
|
version "10.3.5"
|
||||||
resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-10.3.4.tgz#793ebd0d59df276a085586134b73a406e60be9c1"
|
resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-10.3.5.tgz#7213285da0dc3dec0fc8ce5df4b8b7a733f14360"
|
||||||
integrity sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==
|
integrity sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@tokenizer/token" "^0.3.0"
|
"@tokenizer/token" "^0.3.0"
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user