From d7d33ede1762a0e1892ee32b43c9ae0d294ab8f1 Mon Sep 17 00:00:00 2001 From: Arios67 Date: Mon, 4 Apr 2022 02:19:23 +0900 Subject: [PATCH] =?UTF-8?q?[#129]feat:=20=EA=B2=BD=EB=A7=A4=20API=20socket?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ars/package.json | 2 + ars/src/adapters/socket-io.adapters.ts | 9 ++ ars/src/apis/art/art.module.ts | 3 + ars/src/apis/art/entities/likeArt.entity.ts | 10 +- ars/src/apis/event/event.gateway.ts | 32 ++++++ ars/src/apis/event/event.module.ts | 8 ++ ars/src/apis/likeArt/likeArt.service.ts | 23 +++- ars/src/apis/payment/payment.module.ts | 3 +- ars/src/apis/payment/payment.resolver.ts | 4 +- ars/src/apis/payment/payment.service.ts | 9 +- ars/src/app.module.ts | 4 +- ars/src/main.ts | 6 +- ars/yarn.lock | 115 +++++++++++++++++++- 13 files changed, 199 insertions(+), 29 deletions(-) create mode 100644 ars/src/adapters/socket-io.adapters.ts create mode 100644 ars/src/apis/event/event.gateway.ts create mode 100644 ars/src/apis/event/event.module.ts diff --git a/ars/package.json b/ars/package.json index 57276a8..af59cdb 100644 --- a/ars/package.json +++ b/ars/package.json @@ -32,8 +32,10 @@ "@nestjs/jwt": "^8.0.0", "@nestjs/passport": "^8.1.0", "@nestjs/platform-express": "^8.0.0", + "@nestjs/platform-socket.io": "^8.4.3", "@nestjs/schedule": "^1.0.2", "@nestjs/typeorm": "^8.0.3", + "@nestjs/websockets": "^8.4.3", "@types/cache-manager": "^3.4.3", "apollo-server-express": "^3.6.2", "axios": "^0.26.0", diff --git a/ars/src/adapters/socket-io.adapters.ts b/ars/src/adapters/socket-io.adapters.ts new file mode 100644 index 0000000..740ca2f --- /dev/null +++ b/ars/src/adapters/socket-io.adapters.ts @@ -0,0 +1,9 @@ +import { IoAdapter } from '@nestjs/platform-socket.io'; + +export class SocketIoAdapter extends IoAdapter { + createIOServer(port: number, options?: any): any { + const server = super.createIOServer(port, options); + + return server; + } +} diff --git a/ars/src/apis/art/art.module.ts b/ars/src/apis/art/art.module.ts index 551b1e8..13abb77 100644 --- a/ars/src/apis/art/art.module.ts +++ b/ars/src/apis/art/art.module.ts @@ -6,6 +6,8 @@ import { import { TypeOrmModule } from '@nestjs/typeorm'; import { ArtImage } from '../artImage/entities/artImage.entity'; import { Engage } from '../engage/entities/engage.entity'; +import { EventGateway } from '../event/event.gateway'; +import { EventModule } from '../event/event.module'; import { FileService } from '../file/file.service'; import { LikeArtService } from '../likeArt/likeArt.service'; import { Payment } from '../payment/entities/payment.entity'; @@ -31,6 +33,7 @@ import { LikeArt } from './entities/likeArt.entity'; ElasticsearchModule.register({ node: 'http://elasticsearch:9200', }), + EventModule, ], providers: [ ArtResolver, // diff --git a/ars/src/apis/art/entities/likeArt.entity.ts b/ars/src/apis/art/entities/likeArt.entity.ts index 33ffe8d..a8f45ae 100644 --- a/ars/src/apis/art/entities/likeArt.entity.ts +++ b/ars/src/apis/art/entities/likeArt.entity.ts @@ -1,12 +1,6 @@ import { Field, ObjectType } from '@nestjs/graphql'; import { User } from 'src/apis/user/entities/user.entity'; -import { - Column, - Entity, - ManyToOne, - PrimaryColumn, - PrimaryGeneratedColumn, -} from 'typeorm'; +import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import { Art } from './art.entity'; @Entity() @@ -19,6 +13,6 @@ export class LikeArt { @Column() userId: string; - @ManyToOne(() => Art) + @ManyToOne(() => Art, { eager: true }) art: Art; } diff --git a/ars/src/apis/event/event.gateway.ts b/ars/src/apis/event/event.gateway.ts new file mode 100644 index 0000000..5137630 --- /dev/null +++ b/ars/src/apis/event/event.gateway.ts @@ -0,0 +1,32 @@ +import { + WebSocketGateway, + WebSocketServer, + OnGatewayConnection, + OnGatewayDisconnect, +} from '@nestjs/websockets'; +import { Server, Socket } from 'socket.io'; + +@WebSocketGateway({ + cors: { + origin: ['http://localhost:3000', 'https://mybackend.arios67.shop'], + }, + namespace: /./, +}) +export class EventGateway implements OnGatewayConnection, OnGatewayDisconnect { + constructor() {} + @WebSocketServer() + server: Server; + + //소켓 연결시 유저목록에 추가 + public handleConnection(client: Socket): void { + console.log('connected', client.id); + client.leave(client.id); + client.data.roomId = `room:lobby`; + client.join('room:lobby'); + } + + //소켓 연결 해제시 유저목록에서 제거 + public handleDisconnect(client: Socket): void { + console.log('disonnected', client.id); + } +} diff --git a/ars/src/apis/event/event.module.ts b/ars/src/apis/event/event.module.ts new file mode 100644 index 0000000..68d4905 --- /dev/null +++ b/ars/src/apis/event/event.module.ts @@ -0,0 +1,8 @@ +import { Module } from '@nestjs/common'; +import { EventGateway } from './event.gateway'; + +@Module({ + providers: [EventGateway], + exports: [EventGateway], +}) +export class EventModule {} diff --git a/ars/src/apis/likeArt/likeArt.service.ts b/ars/src/apis/likeArt/likeArt.service.ts index 4a2cd02..bd3bd39 100644 --- a/ars/src/apis/likeArt/likeArt.service.ts +++ b/ars/src/apis/likeArt/likeArt.service.ts @@ -16,21 +16,26 @@ export class LikeArtService { async find(userId, page) { const queryRunner = this.connection.createQueryRunner(); await queryRunner.connect(); - await queryRunner.startTransaction(); + await queryRunner.startTransaction('SERIALIZABLE'); try { let arts = []; if (page) { - arts = await queryRunner.manager.find(Art, { + arts = await queryRunner.manager.find(LikeArt, { take: 10, skip: 10 * (page - 1), where: { userId: userId }, + relations: ['art'], + lock: { mode: 'pessimistic_write' }, }); } else { arts = await queryRunner.manager.find(LikeArt, { where: { userId }, relations: ['art'], + lock: { mode: 'pessimistic_write' }, }); } + + await queryRunner.commitTransaction(); return arts.map((ele) => ele.art); } catch (error) { await queryRunner.rollbackTransaction(); @@ -43,14 +48,20 @@ export class LikeArtService { async like(artId, userId) { const queryRunner = this.connection.createQueryRunner(); await queryRunner.connect(); - await queryRunner.startTransaction(); + await queryRunner.startTransaction('SERIALIZABLE'); try { - const art = await queryRunner.manager.findOne(Art, { id: artId }); + const art = await queryRunner.manager.findOne(Art, { + where: { id: artId }, + lock: { mode: 'pessimistic_write' }, + }); + console.log(art); const prevLike = await queryRunner.manager.findOne(LikeArt, { where: { userId: userId, - art: artId, + art: art, }, + relations: ['art'], + lock: { mode: 'pessimistic_write' }, }); if (!prevLike) { await queryRunner.manager.save(LikeArt, { @@ -60,7 +71,7 @@ export class LikeArtService { await queryRunner.commitTransaction(); return true; } else { - await queryRunner.manager.delete(LikeArt, { art: artId }); + await queryRunner.manager.delete(LikeArt, { art: art }); await queryRunner.commitTransaction(); return false; } diff --git a/ars/src/apis/payment/payment.module.ts b/ars/src/apis/payment/payment.module.ts index 059160c..159083a 100644 --- a/ars/src/apis/payment/payment.module.ts +++ b/ars/src/apis/payment/payment.module.ts @@ -1,10 +1,10 @@ import { Module } from '@nestjs/common'; -import { ElasticsearchService } from '@nestjs/elasticsearch'; import { TypeOrmModule } from '@nestjs/typeorm'; import { ArtService } from '../art/art.service'; import { Art } from '../art/entities/art.entity'; import { ArtImage } from '../artImage/entities/artImage.entity'; import { Engage } from '../engage/entities/engage.entity'; +import { EventModule } from '../event/event.module'; import { User } from '../user/entities/user.entity'; import { UserService } from '../user/user.service'; import { Payment } from './entities/payment.entity'; @@ -20,6 +20,7 @@ import { PaymentService } from './payment.service'; Payment, Engage, ]), + EventModule, ], providers: [ PaymentResolver, // diff --git a/ars/src/apis/payment/payment.resolver.ts b/ars/src/apis/payment/payment.resolver.ts index 2800ce5..867ce30 100644 --- a/ars/src/apis/payment/payment.resolver.ts +++ b/ars/src/apis/payment/payment.resolver.ts @@ -39,6 +39,7 @@ export class PaymentResolver { } } + // 즉시 구매 @UseGuards(GqlAuthAccessGuard) @Mutation(() => String) async instantBid( @@ -55,7 +56,7 @@ export class PaymentResolver { return artId; } - // 입찰 API(임시) + // 레디스에 입찰 정보(작품, 현재 입찰가, 현재 상위 입찰자) @UseGuards(GqlAuthAccessGuard) @Mutation(() => [String]) async Bid( @@ -66,6 +67,7 @@ export class PaymentResolver { return await this.paymentService.call(artId, bid_price, currentUser.email); } + // DB 저장 @UseGuards(GqlAuthAccessGuard) @Mutation(() => String) async saveBid( diff --git a/ars/src/apis/payment/payment.service.ts b/ars/src/apis/payment/payment.service.ts index ac68135..0517ad2 100644 --- a/ars/src/apis/payment/payment.service.ts +++ b/ars/src/apis/payment/payment.service.ts @@ -4,6 +4,7 @@ import { Cache } from 'cache-manager'; import { Connection, LessThan, Repository } from 'typeorm'; import { Art } from '../art/entities/art.entity'; import { Engage } from '../engage/entities/engage.entity'; +import { EventGateway } from '../event/event.gateway'; import { History } from '../history/entities/history.entity'; import { User } from '../user/entities/user.entity'; import { Payment } from './entities/payment.entity'; @@ -23,6 +24,8 @@ export class PaymentService { @Inject(CACHE_MANAGER) private readonly cacheManager: Cache, + private eventGateway: EventGateway, + private readonly connection: Connection, ) {} @@ -98,10 +101,9 @@ export class PaymentService { await this.artRepository.softDelete({ id: artId }); } - // 입찰 + // 레디스에 입찰 정보(작품, 현재 입찰가, 현재 상위 입찰자) async call(artId, bid_price, email) { const art = await this.artRepository.findOne(artId); - const utc = new Date(); const KR_TIME_DIFF = 9 * 60 * 60 * 1000; const currentTime = new Date(Number(utc) + Number(KR_TIME_DIFF)); @@ -114,7 +116,9 @@ export class PaymentService { return [bid_price, email]; } + // DB 저장 async save(artId, userId, bid_price) { + this.eventGateway.server.emit('message', bid_price); const queryRunner = this.connection.createQueryRunner(); await queryRunner.connect(); await queryRunner.startTransaction(); @@ -125,7 +129,6 @@ export class PaymentService { art: artId, }, }); - await queryRunner.manager.update( Art, { id: artId }, diff --git a/ars/src/app.module.ts b/ars/src/app.module.ts index 2d5ec4b..eb7159f 100644 --- a/ars/src/app.module.ts +++ b/ars/src/app.module.ts @@ -15,7 +15,7 @@ import { ProfileModule } from './apis/profile/profile.module'; import { HistoryModule } from './apis/history/history.module'; import { ScheduleModule } from '@nestjs/schedule'; import { PaymentModule } from './apis/payment/payment.module'; -import { setgroups } from 'process'; +import { EventModule } from './apis/event/event.module'; @Module({ imports: [ @@ -28,6 +28,7 @@ import { setgroups } from 'process'; UserModule, PaymentModule, PointTransactionModule, + EventModule, ConfigModule.forRoot({ isGlobal: true, envFilePath: '.env', @@ -48,7 +49,6 @@ import { setgroups } from 'process'; entities: [__dirname + '/apis/**/*.entity.*'], synchronize: true, logging: true, - timezone: 'Asia/seoul', }), CacheModule.register({ store: redisStore, diff --git a/ars/src/main.ts b/ars/src/main.ts index f4f6b1f..fa71fc8 100644 --- a/ars/src/main.ts +++ b/ars/src/main.ts @@ -1,15 +1,17 @@ import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; -import * as cors from 'cors'; import { graphqlUploadExpress } from 'graphql-upload'; +import { SocketIoAdapter } from './adapters/socket-io.adapters'; +import { NestExpressApplication } from '@nestjs/platform-express'; async function bootstrap() { - const app = await NestFactory.create(AppModule); + const app = await NestFactory.create(AppModule); app.enableCors({ origin: 'http://localhost:3000', credentials: true, }); app.use(graphqlUploadExpress()); + app.useWebSocketAdapter(new SocketIoAdapter(app)); await app.listen(3000); } bootstrap(); diff --git a/ars/yarn.lock b/ars/yarn.lock index 542825d..0cb84c3 100644 --- a/ars/yarn.lock +++ b/ars/yarn.lock @@ -889,6 +889,14 @@ multer "1.4.4" tslib "2.3.1" +"@nestjs/platform-socket.io@^8.4.3": + version "8.4.3" + resolved "https://registry.yarnpkg.com/@nestjs/platform-socket.io/-/platform-socket.io-8.4.3.tgz#5340ef4ae7fd431825fa1da0c9f90a05e8efad66" + integrity sha512-9xb95ST7jvwsVaC/QMgWVzYsJrq/jn/3T8ox4T+x/K728e3m4Fpu62AzDEAs55Z5nEntXDafG/b5lS3duF7RUA== + dependencies: + socket.io "4.4.1" + tslib "2.3.1" + "@nestjs/schedule@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@nestjs/schedule/-/schedule-1.0.2.tgz#9c921105deabf91274479888c9b1df284bb3c38b" @@ -923,6 +931,15 @@ dependencies: uuid "8.3.2" +"@nestjs/websockets@^8.4.3": + version "8.4.3" + resolved "https://registry.yarnpkg.com/@nestjs/websockets/-/websockets-8.4.3.tgz#94c4130d8e4e24bafa482049af4f6365a2db97fb" + integrity sha512-5pfPvASyVqamdgI2xzSnpbuzfQAkUmqXzcINljZuOngsSgCJef2iRM1V7ZZvh6lCplR3mDA96Nl1unePQ9XjOg== + dependencies: + iterare "1.2.1" + object-hash "3.0.0" + tslib "2.3.1" + "@node-redis/bloom@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@node-redis/bloom/-/bloom-1.0.1.tgz#144474a0b7dc4a4b91badea2cfa9538ce0a1854e" @@ -1055,6 +1072,11 @@ dependencies: "@sinonjs/commons" "^1.7.0" +"@socket.io/base64-arraybuffer@~1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#568d9beae00b0d835f4f8c53fd55714986492e61" + integrity sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ== + "@sqltools/formatter@^1.2.2": version "1.2.3" resolved "https://registry.yarnpkg.com/@sqltools/formatter/-/formatter-1.2.3.tgz#1185726610acc37317ddab11c3c7f9066966bd20" @@ -1158,6 +1180,11 @@ resolved "https://registry.yarnpkg.com/@types/cache-manager/-/cache-manager-3.4.3.tgz#eba99bf795b997ad0c309658101398c34d7faecb" integrity sha512-71aBXoFYXZW4TnDHHH8gExw2lS28BZaWeKefgsiJI7QYZeJfUEbMKw6CQtzGjlYQcGIWwB76hcCrkVA3YHSvsw== +"@types/component-emitter@^1.2.10": + version "1.2.11" + resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.11.tgz#50d47d42b347253817a39709fef03ce66a108506" + integrity sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ== + "@types/connect@*": version "3.4.35" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" @@ -1170,6 +1197,11 @@ resolved "https://registry.yarnpkg.com/@types/content-disposition/-/content-disposition-0.5.4.tgz#de48cf01c79c9f1560bcfd8ae43217ab028657f8" integrity sha512-0mPF08jn9zYI0n0Q/Pnz7C4kThdSt+6LD4amsrYDDpgBfrVWa3TcCOxKX1zkGgYniGagRv8heN2cbh+CAn+uuQ== +"@types/cookie@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" + integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== + "@types/cookiejar@*": version "2.1.2" resolved "https://registry.yarnpkg.com/@types/cookiejar/-/cookiejar-2.1.2.tgz#66ad9331f63fe8a3d3d9d8c6e3906dd10f6446e8" @@ -1185,7 +1217,7 @@ "@types/keygrip" "*" "@types/node" "*" -"@types/cors@2.8.12": +"@types/cors@2.8.12", "@types/cors@^2.8.12": version "2.8.12" resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080" integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw== @@ -1369,6 +1401,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.21.tgz#864b987c0c68d07b4345845c3e63b75edd143644" integrity sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ== +"@types/node@>=10.0.0": + version "17.0.23" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.23.tgz#3b41a6e643589ac6442bdbd7a4a3ded62f33f7da" + integrity sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw== + "@types/node@^10.1.0": version "10.17.60" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" @@ -1749,7 +1786,7 @@ abort-controller@^3.0.0: dependencies: event-target-shim "^5.0.0" -accepts@^1.3.5, accepts@~1.3.8: +accepts@^1.3.5, accepts@~1.3.4, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== @@ -2171,6 +2208,11 @@ base64-js@^1.3.0, base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +base64id@2.0.0, base64id@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" + integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== + base64url@3.x.x: version "3.0.1" resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d" @@ -2568,7 +2610,7 @@ commander@^2.20.0, commander@^2.20.3: 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: +component-emitter@^1.3.0, 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== @@ -2641,7 +2683,7 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= -cookie@0.4.2: +cookie@0.4.2, cookie@~0.4.1: version "0.4.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== @@ -2656,7 +2698,7 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -cors@2.8.5, cors@^2.8.5: +cors@2.8.5, cors@^2.8.5, cors@~2.8.5: version "2.8.5" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== @@ -2751,6 +2793,13 @@ debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3: dependencies: ms "2.1.2" +debug@~4.3.1, debug@~4.3.2: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + decimal.js@^10.2.1: version "10.3.1" resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783" @@ -2960,6 +3009,29 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" +engine.io-parser@~5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.3.tgz#ca1f0d7b11e290b4bfda251803baea765ed89c09" + integrity sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg== + dependencies: + "@socket.io/base64-arraybuffer" "~1.0.2" + +engine.io@~6.1.0: + version "6.1.3" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.1.3.tgz#f156293d011d99a3df5691ac29d63737c3302e6f" + integrity sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA== + dependencies: + "@types/cookie" "^0.4.1" + "@types/cors" "^2.8.12" + "@types/node" ">=10.0.0" + accepts "~1.3.4" + base64id "2.0.0" + cookie "~0.4.1" + cors "~2.8.5" + debug "~4.3.1" + engine.io-parser "~5.0.3" + ws "~8.2.3" + enhanced-resolve@^5.0.0, enhanced-resolve@^5.7.0, enhanced-resolve@^5.8.3: version "5.9.2" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz#0224dcd6a43389ebfb2d55efee517e5466772dd9" @@ -4962,7 +5034,7 @@ moment-timezone@^0.5.x: dependencies: moment ">= 2.9.0" -"moment@>= 2.9.0", moment@>=2.14.0, moment@^2.29.1: +"moment@>= 2.9.0", moment@>=2.14.0: version "2.29.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== @@ -6025,6 +6097,32 @@ snakeize@^0.1.0: resolved "https://registry.yarnpkg.com/snakeize/-/snakeize-0.1.0.tgz#10c088d8b58eb076b3229bb5a04e232ce126422d" integrity sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0= +socket.io-adapter@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz#4d6111e4d42e9f7646e365b4f578269821f13486" + integrity sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ== + +socket.io-parser@~4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.0.4.tgz#9ea21b0d61508d18196ef04a2c6b9ab630f4c2b0" + integrity sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g== + dependencies: + "@types/component-emitter" "^1.2.10" + component-emitter "~1.3.0" + debug "~4.3.1" + +socket.io@4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.4.1.tgz#cd6de29e277a161d176832bb24f64ee045c56ab8" + integrity sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg== + dependencies: + accepts "~1.3.4" + base64id "~2.0.0" + debug "~4.3.2" + engine.io "~6.1.0" + socket.io-adapter "~2.3.3" + socket.io-parser "~4.0.4" + source-map-support@0.5.21, source-map-support@^0.5.20, source-map-support@^0.5.6, source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -6873,6 +6971,11 @@ ws@8.4.2: resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== +ws@~8.2.3: + version "8.2.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba" + integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA== + xdg-basedir@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"