diff --git a/backend/package.json b/backend/package.json index 7578c85c..8ab756dc 100644 --- a/backend/package.json +++ b/backend/package.json @@ -44,6 +44,7 @@ "@nestjs/common": "^10.0.0", "@nestjs/config": "^3.2.3", "@nestjs/core": "^10.0.0", + "@nestjs/event-emitter": "^2.0.4", "@nestjs/graphql": "^12.2.0", "@nestjs/platform-fastify": "^10.4.3", "@nestjs/schedule": "^4.1.0", diff --git a/backend/src/app.module.ts b/backend/src/app.module.ts index 7171aea5..dade2c61 100644 --- a/backend/src/app.module.ts +++ b/backend/src/app.module.ts @@ -12,6 +12,7 @@ import { BullModule } from '@nestjs/bullmq'; import configModule from './config'; import { AppController } from './app.controller'; import { BootstrapService } from './bootstrap.service'; +import { EventEmitterModule } from '@nestjs/event-emitter'; @Module({ imports: [ @@ -46,6 +47,7 @@ import { BootstrapService } from './bootstrap.service'; }, inject: [ConfigService], }), + EventEmitterModule.forRoot(), ScheduleModule.forRoot(), CoreModule, ApiModule, diff --git a/backend/src/core/indexer/flow/assets.flow.ts b/backend/src/core/indexer/flow/assets.flow.ts index b2ce52da..3db6c990 100644 --- a/backend/src/core/indexer/flow/assets.flow.ts +++ b/backend/src/core/indexer/flow/assets.flow.ts @@ -1,68 +1,51 @@ import { Logger } from '@nestjs/common'; import { AssetType, Chain } from '@prisma/client'; -import { EventEmitter } from 'node:events'; -import { CKB_MIN_SAFE_CONFIRMATIONS, CKB_ONE_DAY_BLOCKS } from 'src/constants'; -import { BlockchainService } from 'src/core/blockchain/blockchain.service'; -import { PrismaService } from 'src/core/database/prisma/prisma.service'; -import { IndexerQueueService } from '../indexer.queue'; +import { CKB_MIN_SAFE_CONFIRMATIONS } from 'src/constants'; import { CronExpression, SchedulerRegistry } from '@nestjs/schedule'; import { CronJob } from 'cron'; +import { PrismaService } from 'src/core/database/prisma/prisma.service'; +import { IndexerQueueService } from '../indexer.queue'; +import { EventEmitter2 } from '@nestjs/event-emitter'; +import { BlockchainService } from 'src/core/blockchain/blockchain.service'; -export enum IndexerAssetsEvent { - AssetIndexed = 'asset-indexed', - BlockAssetsIndexed = 'block-assets-indexed', -} - -export class IndexerAssetsFlow extends EventEmitter { +export class IndexerAssetsFlow { private readonly logger = new Logger(IndexerAssetsFlow.name); + public static readonly Event = { + AssetIndexed: 'asset-indexed', + }; + constructor( private chain: Chain, + private indexerQueueService: IndexerQueueService, private blockchainService: BlockchainService, private prismaService: PrismaService, - private indexerQueueService: IndexerQueueService, private schedulerRegistry: SchedulerRegistry, - ) { - super(); + public eventEmitter: EventEmitter2, + ) { } + + private async getLatestAssetBlockNumber() { + const latestAsset = await this.prismaService.asset.findFirst({ + select: { blockNumber: true }, + where: { chainId: this.chain.id }, + orderBy: { blockNumber: 'desc' }, + }); + return latestAsset?.blockNumber ?? -1; } public async start() { - const latestAsset = await this.getLatestAsset(); - if (latestAsset) { - this.logger.log(`Latest asset block number: ${latestAsset.blockNumber}`); - const tipBlockNumber = await this.blockchainService.getTipBlockNumber(); - if ( - tipBlockNumber - CKB_MIN_SAFE_CONFIRMATIONS - latestAsset.blockNumber < - CKB_ONE_DAY_BLOCKS - ) { - this.logger.log(`Latest asset is near tip block number, skip indexing assets...`); - this.setupBlockAssetsIndexedListener(); - this.startBlockAssetsIndexing(); - return; - } - } - const assetTypeScripts = await this.prismaService.assetType.findMany({ where: { chainId: this.chain.id }, }); this.logger.log(`Indexing ${assetTypeScripts.length} asset type scripts`); - assetTypeScripts.map((assetType) => this.indexAssets(assetType)); this.setupAssetIndexedListener(assetTypeScripts.length); + assetTypeScripts.map((assetType) => this.startAssetsIndexing(assetType)); } - private async getLatestAsset() { - const latestAsset = await this.prismaService.asset.findFirst({ - select: { blockNumber: true }, - where: { chainId: this.chain.id }, - orderBy: { blockNumber: 'desc' }, - }); - return latestAsset; - } - - private async indexAssets(assetType: AssetType) { + private async startAssetsIndexing(assetType: AssetType) { const cursor = await this.indexerQueueService.getLatestAssetJobCursor(assetType); if (cursor === '0x') { - this.emit(IndexerAssetsEvent.AssetIndexed, assetType); + this.eventEmitter.emit(IndexerAssetsFlow.Event.AssetIndexed, assetType); return; } await this.indexerQueueService.addAssetJob({ @@ -78,12 +61,11 @@ export class IndexerAssetsFlow extends EventEmitter { completed += 1; this.logger.log(`Asset type ${assetType.codeHash} indexed`); if (completed === totalAssetTypes) { - this.off(IndexerAssetsEvent.AssetIndexed, onAssetIndexed); - this.setupBlockAssetsIndexedListener(); + this.eventEmitter.off(IndexerAssetsFlow.Event.AssetIndexed, onAssetIndexed); this.startBlockAssetsIndexing(); } }; - this.on(IndexerAssetsEvent.AssetIndexed, onAssetIndexed); + this.eventEmitter.on(IndexerAssetsFlow.Event.AssetIndexed, onAssetIndexed); } private async startBlockAssetsIndexing() { @@ -93,40 +75,32 @@ export class IndexerAssetsFlow extends EventEmitter { this.chain.id, ); if (!latestIndexedBlockNumber) { - const latestAsset = await this.prismaService.asset.findFirst({ - select: { blockNumber: true }, - where: { chainId: this.chain.id }, - orderBy: { blockNumber: 'desc' }, - }); - latestIndexedBlockNumber = latestAsset!.blockNumber; + latestIndexedBlockNumber = await this.getLatestAssetBlockNumber(); } const targetBlockNumber = tipBlockNumber - CKB_MIN_SAFE_CONFIRMATIONS; if (targetBlockNumber <= latestIndexedBlockNumber) { - this.logger.log(`Block assets are up to date, latest indexed block number: ${latestIndexedBlockNumber}`); - this.emit(IndexerAssetsEvent.BlockAssetsIndexed, latestIndexedBlockNumber); - return; + this.logger.log(`Block assets are up to date: ${latestIndexedBlockNumber}`); + } else { + await this.indexerQueueService.addBlockAssetsJob({ + chainId: this.chain.id, + blockNumber: latestIndexedBlockNumber + 1, + targetBlockNumber, + }); } - - await this.indexerQueueService.addBlockAssetsJob({ - chainId: this.chain.id, - blockNumber: latestIndexedBlockNumber + 1, - targetBlockNumber, - }); + this.setupBlockAssetsCronJob(); } - private setupBlockAssetsIndexedListener() { + private setupBlockAssetsCronJob() { const cronJobName = `indexer-block-assets-${this.chain.id}-${process.pid}`; - this.on(IndexerAssetsEvent.BlockAssetsIndexed, () => { - if (this.schedulerRegistry.doesExist('cron', cronJobName)) { - return; - } + if (this.schedulerRegistry.doesExist('cron', cronJobName)) { + return; + } - this.logger.log(`Scheduling block assets indexing cron job`); - const job = new CronJob(CronExpression.EVERY_10_SECONDS, () => { - this.startBlockAssetsIndexing(); - }); - this.schedulerRegistry.addCronJob(cronJobName, job); - job.start(); + this.logger.log(`Scheduling block assets indexing cron job`); + const job = new CronJob(CronExpression.EVERY_10_SECONDS, () => { + this.startBlockAssetsIndexing(); }); + this.schedulerRegistry.addCronJob(cronJobName, job); + job.start(); } } diff --git a/backend/src/core/indexer/flow/transactions.flow.ts b/backend/src/core/indexer/flow/transactions.flow.ts index 59dda498..ec922b9f 100644 --- a/backend/src/core/indexer/flow/transactions.flow.ts +++ b/backend/src/core/indexer/flow/transactions.flow.ts @@ -2,34 +2,31 @@ import { Logger } from '@nestjs/common'; import { Chain } from '@prisma/client'; import { EventEmitter } from 'node:events'; import { CKB_MIN_SAFE_CONFIRMATIONS } from 'src/constants'; -import { BlockchainService } from 'src/core/blockchain/blockchain.service'; import { PrismaService } from 'src/core/database/prisma/prisma.service'; import { IndexerQueueService } from '../indexer.queue'; import { ONE_DAY_MS } from 'src/common/date'; import { CronExpression, SchedulerRegistry } from '@nestjs/schedule'; import { CronJob } from 'cron'; +import { EventEmitter2 } from '@nestjs/event-emitter'; +import { BlockchainService } from 'src/core/blockchain/blockchain.service'; const CKB_24_HOURS_BLOCK_NUMBER = ONE_DAY_MS / 10000; -export enum IndexerTransactionsEvent { - BlockIndexed = 'block-indexed', -} - export class IndexerTransactionsFlow extends EventEmitter { private readonly logger = new Logger(IndexerTransactionsFlow.name); constructor( private chain: Chain, + private indexerQueueService: IndexerQueueService, private blockchainService: BlockchainService, private prismaService: PrismaService, - private indexerQueueService: IndexerQueueService, private schedulerRegistry: SchedulerRegistry, + public eventEmitter: EventEmitter2, ) { super(); } public async start() { - this.setupBlockIndexedListener(); this.startBlockIndexing(); } @@ -46,31 +43,28 @@ export class IndexerTransactionsFlow extends EventEmitter { startBlockNumber = Math.max(startBlockNumber, block.number + 1); } - if (startBlockNumber >= targetBlockNumber) { - this.emit(IndexerTransactionsEvent.BlockIndexed); - return; + if (startBlockNumber < targetBlockNumber) { + this.logger.log(`Indexing blocks from ${startBlockNumber} to ${targetBlockNumber}`); + this.indexerQueueService.addBlockJob({ + chainId: this.chain.id, + blockNumber: startBlockNumber, + targetBlockNumber, + }); } - this.logger.log(`Indexing blocks from ${startBlockNumber} to ${targetBlockNumber}`); - this.indexerQueueService.addBlockJob({ - chainId: this.chain.id, - blockNumber: startBlockNumber, - targetBlockNumber, - }); + this.setupBlockIndexCronJob(); } - private setupBlockIndexedListener() { + private setupBlockIndexCronJob() { const cronJobName = `indexer-transactions-${this.chain.id}-${process.pid}`; - this.on(IndexerTransactionsEvent.BlockIndexed, () => { - if (this.schedulerRegistry.doesExist('cron', cronJobName)) { - return; - } + if (this.schedulerRegistry.doesExist('cron', cronJobName)) { + return; + } - this.logger.log(`Scheduling block transactions indexing cron job`); - const job = new CronJob(CronExpression.EVERY_10_SECONDS, () => { - this.startBlockIndexing(); - }); - this.schedulerRegistry.addCronJob(cronJobName, job); - job.start(); + this.logger.log(`Scheduling block transactions indexing cron job`); + const job = new CronJob(CronExpression.EVERY_10_SECONDS, () => { + this.startBlockIndexing(); }); + this.schedulerRegistry.addCronJob(cronJobName, job); + job.start(); } } diff --git a/backend/src/core/indexer/indexer.factory.ts b/backend/src/core/indexer/indexer.factory.ts index 093a4bd6..5037ca83 100644 --- a/backend/src/core/indexer/indexer.factory.ts +++ b/backend/src/core/indexer/indexer.factory.ts @@ -5,6 +5,7 @@ import { BlockchainServiceFactory } from '../blockchain/blockchain.factory'; import { IndexerQueueService } from './indexer.queue'; import { ModuleRef } from '@nestjs/core'; import { SchedulerRegistry } from '@nestjs/schedule'; +import { EventEmitter2 } from '@nestjs/event-emitter'; export class IndexerServiceFactoryError extends Error { constructor(message: string) { @@ -21,6 +22,7 @@ export class IndexerServiceFactory implements OnModuleDestroy { private blockchainServiceFactory: BlockchainServiceFactory, private prismaService: PrismaService, private schedulerRegistry: SchedulerRegistry, + private eventEmitter: EventEmitter2, private moduleRef: ModuleRef, ) {} @@ -42,10 +44,11 @@ export class IndexerServiceFactory implements OnModuleDestroy { const blockchainService = this.blockchainServiceFactory.getService(chain.id); const service = new IndexerService( chain, + indexerQueueService, blockchainService, this.prismaService, - indexerQueueService, this.schedulerRegistry, + this.eventEmitter, ); this.services.set(chain.id, service); } diff --git a/backend/src/core/indexer/indexer.service.ts b/backend/src/core/indexer/indexer.service.ts index 0e53181a..d76070ba 100644 --- a/backend/src/core/indexer/indexer.service.ts +++ b/backend/src/core/indexer/indexer.service.ts @@ -5,6 +5,7 @@ import { PrismaService } from '../database/prisma/prisma.service'; import { IndexerQueueService } from './indexer.queue'; import { IndexerTransactionsFlow } from './flow/transactions.flow'; import { SchedulerRegistry } from '@nestjs/schedule'; +import { EventEmitter2 } from '@nestjs/event-emitter'; export class IndexerService { public assetsFlow: IndexerAssetsFlow; @@ -12,33 +13,33 @@ export class IndexerService { constructor( private chain: Chain, + private indexerQueueService: IndexerQueueService, private blockchainService: BlockchainService, private prismaService: PrismaService, - private indexerQueueService: IndexerQueueService, private schedulerRegistry: SchedulerRegistry, + private eventEmitter: EventEmitter2, ) { this.assetsFlow = new IndexerAssetsFlow( this.chain, + this.indexerQueueService, this.blockchainService, this.prismaService, - this.indexerQueueService, this.schedulerRegistry, + this.eventEmitter, ); this.transactionsFlow = new IndexerTransactionsFlow( this.chain, + this.indexerQueueService, this.blockchainService, this.prismaService, - this.indexerQueueService, this.schedulerRegistry, + this.eventEmitter, ); } public async start() { await this.indexerQueueService.moveActiveJobToDelay(); - await Promise.all([ - this.assetsFlow.start(), - this.transactionsFlow.start(), - ]); + await Promise.all([this.assetsFlow.start(), this.transactionsFlow.start()]); } public async close() { diff --git a/backend/src/core/indexer/processor/assets.processor.ts b/backend/src/core/indexer/processor/assets.processor.ts index 63141995..cd8498e1 100644 --- a/backend/src/core/indexer/processor/assets.processor.ts +++ b/backend/src/core/indexer/processor/assets.processor.ts @@ -10,7 +10,7 @@ import { ModuleRef } from '@nestjs/core'; import { IndexerServiceFactory } from '../indexer.factory'; import { IndexerAssetsService } from '../service/assets.service'; import * as Sentry from '@sentry/node'; -import { IndexerAssetsEvent } from '../flow/assets.flow'; +import { IndexerAssetsFlow } from '../flow/assets.flow'; export const INDEXER_ASSETS_QUEUE = 'indexer-assets-queue'; @@ -24,7 +24,6 @@ const BATCH_SIZE = BI.from(400).toHexString(); @Processor(INDEXER_ASSETS_QUEUE, { stalledInterval: 60_000, - useWorkerThreads: true, }) export class IndexerAssetsProcessor extends WorkerHost { private logger = new Logger(IndexerAssetsProcessor.name); @@ -67,7 +66,7 @@ export class IndexerAssetsProcessor extends WorkerHost { if (cursor === '0x') { const indexerServiceFactory = this.moduleRef.get(IndexerServiceFactory); const indexerService = await indexerServiceFactory.getService(chainId); - indexerService.assetsFlow.emit(IndexerAssetsEvent.AssetIndexed, assetType); + indexerService.assetsFlow.eventEmitter.emit(IndexerAssetsFlow.Event.AssetIndexed, assetType); return; } diff --git a/backend/src/core/indexer/processor/block-assets.processor.ts b/backend/src/core/indexer/processor/block-assets.processor.ts index f84daf86..f3cdcced 100644 --- a/backend/src/core/indexer/processor/block-assets.processor.ts +++ b/backend/src/core/indexer/processor/block-assets.processor.ts @@ -8,9 +8,7 @@ import { PrismaService } from 'src/core/database/prisma/prisma.service'; import { IndexerQueueService } from '../indexer.queue'; import { IndexerAssetsService } from '../service/assets.service'; import { Cell, Transaction } from 'src/core/blockchain/blockchain.interface'; -import { IndexerServiceFactory } from '../indexer.factory'; import * as Sentry from '@sentry/node'; -import { IndexerAssetsEvent } from '../flow/assets.flow'; export const INDEXER_BLOCK_ASSETS_QUEUE = 'indexer-block-assets-queue'; @@ -22,7 +20,6 @@ export interface IndexerBlockAssetsJobData { @Processor(INDEXER_BLOCK_ASSETS_QUEUE, { stalledInterval: 60_000, - useWorkerThreads: true, }) export class IndexerBlockAssetsProcessor extends WorkerHost { private logger = new Logger(IndexerBlockAssetsProcessor.name); @@ -104,11 +101,6 @@ export class IndexerBlockAssetsProcessor extends WorkerHost { blockNumber: blockNumber + 1, targetBlockNumber, }); - } else { - const indexerServiceFactory = this.moduleRef.get(IndexerServiceFactory); - const indexerService = await indexerServiceFactory.getService(chainId); - indexerService.assetsFlow.emit(IndexerAssetsEvent.BlockAssetsIndexed, blockNumber); - return; } } diff --git a/backend/src/core/indexer/processor/block.processor.ts b/backend/src/core/indexer/processor/block.processor.ts index 10273632..28cd57a7 100644 --- a/backend/src/core/indexer/processor/block.processor.ts +++ b/backend/src/core/indexer/processor/block.processor.ts @@ -8,8 +8,6 @@ import { PrismaService } from 'src/core/database/prisma/prisma.service'; import * as Sentry from '@sentry/node'; import { toNumber } from 'lodash'; import { IndexerQueueService } from '../indexer.queue'; -import { IndexerServiceFactory } from '../indexer.factory'; -import { IndexerTransactionsEvent } from '../flow/transactions.flow'; export const INDEXER_BLOCK_QUEUE = 'indexer-block-queue'; @@ -21,7 +19,6 @@ export interface IndexerBlockJobData { @Processor(INDEXER_BLOCK_QUEUE, { stalledInterval: 60_000, - useWorkerThreads: true, }) export class IndexerBlockProcessor extends WorkerHost { private logger = new Logger(IndexerBlockProcessor.name); @@ -90,11 +87,6 @@ export class IndexerBlockProcessor extends WorkerHost { blockNumber: blockNumber + 1, targetBlockNumber, }); - } else { - const indexerServiceFactory = this.moduleRef.get(IndexerServiceFactory); - const indexerService = await indexerServiceFactory.getService(chainId); - indexerService.transactionsFlow.emit(IndexerTransactionsEvent.BlockIndexed, block); - return; } } diff --git a/backend/src/core/indexer/processor/lock.processor.ts b/backend/src/core/indexer/processor/lock.processor.ts index 7ae5d2c8..c90a3403 100644 --- a/backend/src/core/indexer/processor/lock.processor.ts +++ b/backend/src/core/indexer/processor/lock.processor.ts @@ -27,7 +27,6 @@ class IndexerLockError extends Error { @Processor(INDEXER_LOCK_QUEUE, { stalledInterval: 60_000, - useWorkerThreads: true, }) export class IndexerLockProcessor extends WorkerHost { private logger = new Logger(IndexerLockProcessor.name); diff --git a/backend/src/core/indexer/processor/transaction.processor.ts b/backend/src/core/indexer/processor/transaction.processor.ts index ce60bf65..cc042536 100644 --- a/backend/src/core/indexer/processor/transaction.processor.ts +++ b/backend/src/core/indexer/processor/transaction.processor.ts @@ -18,7 +18,6 @@ export interface IndexerTransactionJobData { @Processor(INDEXER_TRANSACTION_QUEUE, { stalledInterval: 60_000, - useWorkerThreads: true, }) export class IndexerTransactionProcessor extends WorkerHost { private logger = new Logger(IndexerTransactionProcessor.name); diff --git a/backend/src/core/indexer/processor/type.processor.ts b/backend/src/core/indexer/processor/type.processor.ts index bbe9e8d1..d5961e3a 100644 --- a/backend/src/core/indexer/processor/type.processor.ts +++ b/backend/src/core/indexer/processor/type.processor.ts @@ -15,7 +15,6 @@ export interface IndexerTypeJobData { @Processor(INDEXER_TYPE_QUEUE, { stalledInterval: 60_000, - useWorkerThreads: true, }) export class IndexerTypeProcessor extends WorkerHost { private logger = new Logger(IndexerTypeProcessor.name); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fdc99d14..d26daa68 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -55,6 +55,9 @@ importers: '@nestjs/core': specifier: ^10.0.0 version: 10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/event-emitter': + specifier: ^2.0.4 + version: 2.0.4(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(reflect-metadata@0.2.2)(rxjs@7.8.1)) '@nestjs/graphql': specifier: ^12.2.0 version: 12.2.0(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(reflect-metadata@0.2.2)(rxjs@7.8.1))(bufferutil@4.0.8)(graphql@16.9.0)(reflect-metadata@0.2.2)(ts-morph@21.0.1)(utf-8-validate@5.0.10) @@ -383,7 +386,7 @@ importers: version: 14.2.4(eslint@8.57.0)(typescript@5.5.3) eslint-plugin-import: specifier: ^2.29.0 - version: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + version: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) eslint-plugin-no-relative-import-paths: specifier: ^1.5.3 version: 1.5.5 @@ -2537,6 +2540,12 @@ packages: '@nestjs/websockets': optional: true + '@nestjs/event-emitter@2.0.4': + resolution: {integrity: sha512-quMiw8yOwoSul0pp3mOonGz8EyXWHSBTqBy8B0TbYYgpnG1Ix2wGUnuTksLWaaBiiOTDhciaZ41Y5fJZsSJE1Q==} + peerDependencies: + '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 + '@nestjs/core': ^8.0.0 || ^9.0.0 || ^10.0.0 + '@nestjs/graphql@12.2.0': resolution: {integrity: sha512-du/aI+EXADxtJrHF1mAXR6RYRHuEWPNnJyHTmIOPW2Wx5qN32P7lQoHGD7TySATMl5aa47w05lPzxcasdUmpMQ==} peerDependencies: @@ -5456,6 +5465,9 @@ packages: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} + eventemitter2@6.4.9: + resolution: {integrity: sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==} + eventemitter3@3.1.2: resolution: {integrity: sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==} @@ -11633,6 +11645,12 @@ snapshots: transitivePeerDependencies: - encoding + '@nestjs/event-emitter@2.0.4(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(reflect-metadata@0.2.2)(rxjs@7.8.1))': + dependencies: + '@nestjs/common': 10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/core': 10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(reflect-metadata@0.2.2)(rxjs@7.8.1) + eventemitter2: 6.4.9 + '@nestjs/graphql@12.2.0(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(reflect-metadata@0.2.2)(rxjs@7.8.1))(bufferutil@4.0.8)(graphql@16.9.0)(reflect-metadata@0.2.2)(ts-morph@21.0.1)(utf-8-validate@5.0.10)': dependencies: '@graphql-tools/merge': 9.0.4(graphql@16.9.0) @@ -15592,8 +15610,8 @@ snapshots: '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.9.0(eslint@8.57.0) eslint-plugin-react: 7.35.0(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) @@ -15615,13 +15633,13 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0))(eslint@8.57.0): + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0): dependencies: debug: 4.3.6 enhanced-resolve: 5.17.0 eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.6 is-core-module: 2.14.0 @@ -15632,18 +15650,18 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): dependencies: array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 @@ -15653,7 +15671,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.14.0 is-glob: 4.0.3 @@ -15842,6 +15860,8 @@ snapshots: event-target-shim@5.0.1: {} + eventemitter2@6.4.9: {} + eventemitter3@3.1.2: {} eventemitter3@4.0.7: {}