From d7289e4ac36af84e3eaf7efb82a0c63848aced5a Mon Sep 17 00:00:00 2001 From: memplethee-lab Date: Mon, 22 Jun 2026 16:53:02 +0100 Subject: [PATCH 1/2] fix: remove duplicate DelegationService class and fix TypeScript type error in governance services --- src/governance/services/index.ts | 396 ++----------------------------- 1 file changed, 15 insertions(+), 381 deletions(-) diff --git a/src/governance/services/index.ts b/src/governance/services/index.ts index 24af6d0..1f9bd62 100644 --- a/src/governance/services/index.ts +++ b/src/governance/services/index.ts @@ -1,21 +1,26 @@ import { Injectable, Logger, NotFoundException, BadRequestException, ForbiddenException } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; +import { EventEmitter2 } from '@nestjs/event-emitter'; +// Entities +import { GovernanceProposal } from '../entities/governance-proposal.entity'; +import { GovernanceVote } from '../entities/governance-vote.entity'; +import { GovernanceDiscussion } from '../entities/governance-discussion.entity'; +import { VoteDelegation } from '../entities/vote-delegation.entity'; +import { GovernanceExecution } from '../entities/governance-execution.entity'; +import { TokenHolding } from '../entities/token-holding.entity'; +// Enums import { - GovernanceProposal, - GovernanceVote, - GovernanceDiscussion, - VoteDelegation, - GovernanceExecution, ProposalStatus, ProposalType, VoteType, DiscussionMessageType, ExecutionStatus, - TokenHolding, - GOVERNANCE_PARAMS, -} from '../constants/governance.constants'; +} from '../enums/governance.enum'; +// Constants +import { GOVERNANCE_PARAMS } from '../constants/governance.constants'; import { GovernanceService } from './governance.service'; +export { GovernanceService } from './governance.service'; @Injectable() export class ProposalExecutionService { @@ -64,371 +69,6 @@ export class ProposalExecutionService { } } -@Injectable() -export class ProposalManagementService { - private readonly logger = new Logger(ProposalManagementService.name); - - constructor( - @InjectRepository(GovernanceProposal) - private readonly proposalRepo: Repository, - @InjectRepository(GovernanceVote) - private readonly voteRepo: Repository, - @InjectRepository(GovernanceDiscussion) - private readonly discussionRepo: Repository, - @InjectRepository(TokenHolding) - private readonly holdingRepo: Repository, - @InjectRepository(VoteDelegation) - private readonly delegationRepo: Repository, - private readonly governanceService: GovernanceService, - ) {} - - async createProposal( - proposerId: string, - proposerAddress: string, - type: ProposalType, - title: string, - description: string, - parameters: Record, - executionPayload?: Record, - ): Promise { - const threshold = await this.governanceService.getMinTokenThreshold(); - const balance = await this.governanceService.getTokenBalance(proposerId); - - if (balance < threshold) { - throw new ForbiddenException( - `Minimum token threshold not met. Required: ${threshold}, Current: ${balance}`, - ); - } - - const votingPeriodDays = type === ProposalType.EMERGENCY - ? await this.governanceService.getEmergencyVotingPeriodDays() - : await this.governanceService.getVotingPeriodDays(); - - const startTime = new Date(); - const endTime = new Date(); - endTime.setDate(endTime.getDate() + votingPeriodDays); - - const proposal = this.proposalRepo.create({ - proposerId, - proposerAddress, - type, - title, - description, - parameters, - executionPayload, - status: ProposalStatus.PENDING, - forVotes: 0, - againstVotes: 0, - abstainVotes: 0, - quorumVotes: GOVERNANCE_PARAMS.QUORUM_PERCENTAGE.value, - totalSupply: balance, - votingPeriodDays, - startTime, - endTime, - }); - - return this.proposalRepo.save(proposal); - } - - async approveProposal(proposalId: string, actorId: string): Promise { - const proposal = await this.proposalRepo.findOne({ where: { id: proposalId } }); - if (!proposal) { - throw new NotFoundException(`Proposal ${proposalId} not found`); - } - - const votingPeriodDays = proposal.type === ProposalType.EMERGENCY - ? await this.governanceService.getEmergencyVotingPeriodDays() - : await this.governanceService.getVotingPeriodDays(); - - const startTime = new Date(); - const endTime = new Date(); - endTime.setDate(endTime.getDate() + votingPeriodDays); - - proposal.status = ProposalStatus.ACTIVE; - proposal.startTime = startTime; - proposal.endTime = endTime; - proposal.votingPeriodDays = votingPeriodDays; - - return this.proposalRepo.save(proposal); - } - - async cancelProposal(proposalId: string, reason: string): Promise { - const proposal = await this.proposalRepo.findOne({ where: { id: proposalId } }); - if (!proposal) { - throw new NotFoundException(`Proposal ${proposalId} not found`); - } - - if (proposal.status === ProposalStatus.ACTIVE || proposal.status === ProposalStatus.EXECUTED) { - throw new BadRequestException(`Cannot cancel proposal in status ${proposal.status}`); - } - - proposal.status = ProposalStatus.CANCELLED; - proposal.cancellationReason = reason; - return this.proposalRepo.save(proposal); - } - - async finalizeProposal(proposalId: string): Promise { - const proposal = await this.proposalRepo.findOne({ where: { id: proposalId } }); - if (!proposal) { - throw new NotFoundException(`Proposal ${proposalId} not found`); - } - - if (proposal.status !== ProposalStatus.ACTIVE) { - throw new BadRequestException(`Only active proposals can be finalized`); - } - - const now = new Date(); - if (now < proposal.endTime) { - throw new BadRequestException(`Voting period has not ended yet`); - } - - proposal.totalSupply = proposal.totalSupply || (proposal.forVotes + proposal.againstVotes + proposal.abstainVotes); - - const hasPassed = await this.governanceService.proposalHasPassed(proposalId); - proposal.status = hasPassed ? ProposalStatus.PASSED : ProposalStatus.DEFEATED; - - return this.proposalRepo.save(proposal); - } -} - -@Injectable() -export class VotingService { - constructor( - @InjectRepository(GovernanceVote) - private readonly voteRepo: Repository, - @InjectRepository(GovernanceProposal) - private readonly proposalRepo: Repository, - @InjectRepository(VoteDelegation) - private readonly delegationRepo: Repository, - private readonly governanceService: GovernanceService, - ) {} - - async castVote( - proposalId: string, - voterId: string, - voterAddress: string, - voteType: VoteType, - reason?: string, - ): Promise { - const canVote = await this.governanceService.canUserVote(voterId, proposalId); - if (!canVote.allowed) { - throw new ForbiddenException(canVote.reason); - } - - if (!Object.values(VoteType).includes(voteType)) { - throw new BadRequestException(`Invalid vote type: ${voteType}`); - } - - const proposal = await this.proposalRepo.findOne({ where: { id: proposalId } }); - if (!proposal) { - throw new NotFoundException(`Proposal ${proposalId} not found`); - } - - const votingPower = await this.governanceService.getEffectiveVotingPower(voterId, proposalId); - if (votingPower <= 0) { - throw new BadRequestException('No voting power available'); - } - - const vote = this.voteRepo.create({ - proposalId, - voterId, - voterAddress, - voteType, - weight: votingPower, - balanceAtVote: await this.governanceService.getTokenBalance(voterId), - delegateTo: null, - timestamp: new Date(), - reason: reason ?? null, - }); - - const saved = await this.voteRepo.save(vote); - - if (voteType === VoteType.FOR) { - proposal.forVotes += votingPower; - } else if (voteType === VoteType.AGAINST) { - proposal.againstVotes += votingPower; - } else if (voteType === VoteType.ABSTAIN) { - proposal.abstainVotes += votingPower; - } - - await this.proposalRepo.save(proposal); - return saved; - } -} - -@Injectable() -export class DelegationService { - constructor( - @InjectRepository(VoteDelegation) - private readonly delegationRepo: Repository, - private readonly governanceService: GovernanceService, - ) {} - - async delegateVotes( - delegatorId: string, - delegateeId: string, - delegationDays: number = 30, - ): Promise { - if (delegatorId === delegateeId) { - throw new BadRequestException('Cannot delegate to yourself'); - } - - const existing = await this.delegationRepo.findOne({ - where: { delegatorId, delegateeId, isActive: true }, - }); - - if (existing) { - throw new BadRequestException('Active delegation already exists for this delegatee'); - } - - const balance = await this.governanceService.getTokenBalance(delegatorId); - if (balance <= 0) { - throw new BadRequestException('Cannot delegate without token holdings'); - } - - const endTime = new Date(); - endTime.setDate(endTime.getDate() + delegationDays); - - const delegation = this.delegationRepo.create({ - delegatorId, - delegatorAddress: `0x${delegatorId}`, - delegateeId, - delegateeAddress: `0x${delegateeId}`, - delegatedBalance: balance, - isActive: true, - startTime: new Date(), - endTime, - }); - - return this.delegationRepo.save(delegation); - } - - async revokeDelegation(delegationId: string): Promise { - const delegation = await this.delegationRepo.findOne({ where: { id: delegationId } }); - if (!delegation) { - throw new BadRequestException('Delegation not found'); - } - if (!delegation.isActive) { - throw new BadRequestException('Delegation is already inactive'); - } - - delegation.isActive = false; - delegation.endTime = new Date(); - return this.delegationRepo.save(delegation); - } - - async getActiveDelegations(delegatorId: string): Promise { - return this.delegationRepo.find({ - where: { delegatorId, isActive: true }, - order: { createdAt: 'DESC' }, - }); - } - - async getDelegatorsForUser(delegateeId: string): Promise { - return this.delegationRepo.find({ - where: { delegateeId, isActive: true }, - order: { createdAt: 'DESC' }, - }); - } -} - -@Injectable() -export class DiscussionService { - constructor( - @InjectRepository(GovernanceDiscussion) - private readonly discussionRepo: Repository, - ) {} - - async addMessage( - proposalId: string, - authorId: string, - authorAddress: string, - messageType: DiscussionMessageType, - content: string, - ): Promise { - const discussion = this.discussionRepo.create({ - proposalId, - authorId, - authorAddress, - messageType, - content, - }); - - return this.discussionRepo.save(discussion); - } - - async getDiscussionThread(proposalId: string): Promise { - return this.discussionRepo.find({ - where: { proposalId }, - order: { createdAt: 'ASC' }, - }); - } -} - - - if (proposal.status !== ProposalStatus.PASSED) { - throw new BadRequestException('Only passed proposals can be executed'); - } - - const execution = this.execRepo.create({ - proposalId, - executionStatus: ExecutionStatus.PENDING, - executedBy: { actorId, timestamp: new Date().toISOString() }, - }); - - try { - proposal.status = ProposalStatus.EXECUTED; - proposal.executedAt = new Date(); - await this.proposalRepo.save(proposal); - execution.executionStatus = ExecutionStatus.SUCCESS; - execution.transactionHash = `exec_${Date.now()}_${Math.random().toString(36).substring(7)}`; - } catch (err) { - this.logger.error(`Failed to execute proposal ${proposalId}`, err); - proposal.status = ProposalStatus.PASSED; - proposal.executionReason = (err as Error).message; - await this.proposalRepo.save(proposal); - execution.executionStatus = ExecutionStatus.FAILED; - execution.errorMessage = (err as Error).message; - } - - const saved = await this.execRepo.save(execution); - this.eventEmitter.emit('governance.proposal.executed', { proposalId, status: execution.executionStatus }); - return saved; - } -} - - if (proposal.status !== ProposalStatus.PASSED) { - throw new BadRequestException('Only passed proposals can be executed'); - } - - const execution = this.execRepo.create({ - proposalId, - executionStatus: ExecutionStatus.PENDING, - executedBy: { actorId, timestamp: new Date().toISOString() }, - }); - - try { - proposal.status = ProposalStatus.EXECUTED; - proposal.executedAt = new Date(); - await this.proposalRepo.save(proposal); - execution.executionStatus = ExecutionStatus.SUCCESS; - execution.transactionHash = `exec_${Date.now()}_${Math.random().toString(36).substring(7)}`; - } catch (err) { - this.logger.error(`Failed to execute proposal ${proposalId}`, err); - proposal.status = ProposalStatus.PASSED; - proposal.executionReason = (err as Error).message; - await this.proposalRepo.save(proposal); - execution.executionStatus = ExecutionStatus.FAILED; - execution.errorMessage = (err as Error).message; - } - - const saved = await this.execRepo.save(execution); - this.eventEmitter.emit('governance.proposal.executed', { proposalId, status: execution.executionStatus }); - - return saved; - } -} - @Injectable() export class ProposalManagementService { private readonly logger = new Logger(ProposalManagementService.name); @@ -561,8 +201,6 @@ export class ProposalManagementService { @Injectable() export class VotingService { - private readonly logger = new Logger(VotingService.name); - constructor( @InjectRepository(GovernanceVote) private readonly voteRepo: Repository, @@ -610,7 +248,7 @@ export class VotingService { delegateTo: null, timestamp: new Date(), reason: reason ?? null, - }); + } as unknown as GovernanceVote); const saved = await this.voteRepo.save(vote); @@ -630,8 +268,6 @@ export class VotingService { @Injectable() export class DelegationService { - private readonly logger = new Logger(DelegationService.name); - constructor( @InjectRepository(VoteDelegation) private readonly delegationRepo: Repository, @@ -708,8 +344,6 @@ export class DelegationService { @Injectable() export class DiscussionService { - private readonly logger = new Logger(DiscussionService.name); - constructor( @InjectRepository(GovernanceDiscussion) private readonly discussionRepo: Repository, @@ -739,4 +373,4 @@ export class DiscussionService { order: { createdAt: 'ASC' }, }); } -} +} \ No newline at end of file From 6153849e750894ef74c64684b23dd5c85745ac97 Mon Sep 17 00:00:00 2001 From: memplethee-lab Date: Mon, 22 Jun 2026 16:53:18 +0100 Subject: [PATCH 2/2] updated --- .env.example | 15 +- package-lock.json | 3159 ++++++++++++++++- src/app.module.ts | 12 +- src/auth/auth.controller.ts | 7 +- src/auth/mfa.controller.ts | 4 +- src/common/enums/notification-channel.enum.ts | 5 + .../enums/notification-event-type.enum.ts | 7 +- src/common/enums/notification-status.enum.ts | 7 +- src/common/logging/audit_service.ts | 4 +- .../interceptors/monitoring.interceptor.ts | 4 +- src/governance/constants/index.ts | 2 +- src/governance/controllers/index.ts | 1 + .../entities/governance-proposal.entity.ts | 8 +- .../entities/governance-vote.entity.ts | 9 +- src/governance/entities/index.ts | 7 + src/governance/services/governance.service.ts | 6 +- src/identity/admin/admin.controller.ts | 12 +- .../admin/services/role-management.service.ts | 22 +- .../roles/controllers/roles.controller.ts | 6 +- .../roles/services/role-management.service.ts | 16 +- src/mobile/mobile.controller.ts | 5 +- .../config/default-preferences.config.ts | 45 + .../controllers/notifications.controller.ts | 52 + .../dto/mark-notification-read.dto.ts | 7 + .../dto/send-notification.dto.ts | 23 + .../update-notification-preferences.dto.ts | 41 + .../entities/notification.entity.ts | 71 + .../user-notification-preferences.entity.ts | 48 + .../gateways/notifications.gateway.ts | 75 + src/notifications/notifications.module.ts | 50 + src/notifications/services/email.service.ts | 56 + .../services/notification.processor.ts | 103 + .../services/notifications.service.ts | 207 ++ src/notifications/services/push.service.ts | 67 + src/notifications/services/sms.service.ts | 52 + .../services/templates.service.ts | 55 + .../templates/i18n/en/notifications.json | 72 + .../templates/i18n/es/notifications.json | 72 + .../templates/i18n/zh/notifications.json | 72 + src/notifications/usage-examples.ts | 106 + src/user/user.controller.ts | 5 +- 41 files changed, 4492 insertions(+), 105 deletions(-) create mode 100644 src/common/enums/notification-channel.enum.ts create mode 100644 src/governance/controllers/index.ts create mode 100644 src/governance/entities/index.ts create mode 100644 src/notifications/config/default-preferences.config.ts create mode 100644 src/notifications/controllers/notifications.controller.ts create mode 100644 src/notifications/dto/mark-notification-read.dto.ts create mode 100644 src/notifications/dto/send-notification.dto.ts create mode 100644 src/notifications/dto/update-notification-preferences.dto.ts create mode 100644 src/notifications/entities/notification.entity.ts create mode 100644 src/notifications/entities/user-notification-preferences.entity.ts create mode 100644 src/notifications/gateways/notifications.gateway.ts create mode 100644 src/notifications/notifications.module.ts create mode 100644 src/notifications/services/email.service.ts create mode 100644 src/notifications/services/notification.processor.ts create mode 100644 src/notifications/services/notifications.service.ts create mode 100644 src/notifications/services/push.service.ts create mode 100644 src/notifications/services/sms.service.ts create mode 100644 src/notifications/services/templates.service.ts create mode 100644 src/notifications/templates/i18n/en/notifications.json create mode 100644 src/notifications/templates/i18n/es/notifications.json create mode 100644 src/notifications/templates/i18n/zh/notifications.json create mode 100644 src/notifications/usage-examples.ts diff --git a/.env.example b/.env.example index 602b510..96fef8c 100644 --- a/.env.example +++ b/.env.example @@ -48,6 +48,19 @@ QUEUE_REMOVE_ON_FAIL=false JWT_SECRET=your-super-secret-jwt-key-change-this-in-production JWT_EXPIRES_IN=3600 JWT_REFRESH_SECRET=your-refresh-secret-key-change-this-in-production + +# Email (SMTP) Configuration - Nodemailer +SMTP_HOST=smtp.example.com +SMTP_PORT=587 +SMTP_SECURE=false +SMTP_USER=noreply@swaptrade.com +SMTP_PASSWORD=your-smtp-password +EMAIL_FROM=noreply@swaptrade.com + +# SMS Configuration - Twilio +TWILIO_ACCOUNT_SID=your-twilio-account-sid +TWILIO_AUTH_TOKEN=your-twilio-auth-token +TWILIO_PHONE_NUMBER=+1234567890 JWT_REFRESH_EXPIRES_IN=604800 BCRYPT_ROUNDS=12 AUTH_MAX_LOGIN_ATTEMPTS=5 @@ -119,4 +132,4 @@ OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318/v1/traces # Sampling rate: 1.0 = 100 % of traces, 0.1 = 10 %, etc. OTEL_SAMPLING_RATE=1.0 # How often (ms) the batch processor flushes spans in production -OTEL_EXPORT_INTERVAL=5000 +OTEL_EXPORT_INTERVAL=5000 \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 2c6dedb..6690ba0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,8 +31,12 @@ "@nestjs/typeorm": "^11.0.0", "@nestjs/websockets": "^11.0.1", "@opentelemetry/api": "^1.8.0", + "@opentelemetry/auto-instrumentations-node": "^0.48.0", + "@opentelemetry/context-async-hooks": "^1.22.0", + "@opentelemetry/exporter-trace-otlp-http": "^0.49.1", "@opentelemetry/resources": "^1.22.0", "@opentelemetry/sdk-node": "^0.49.1", + "@opentelemetry/sdk-trace-node": "^1.22.0", "@opentelemetry/semantic-conventions": "^1.22.0", "@tensorflow/tfjs": "^4.20.0", "@tensorflow/tfjs-node": "^4.20.0", @@ -3696,6 +3700,421 @@ "node": ">=14" } }, + "node_modules/@opentelemetry/auto-instrumentations-node": { + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.48.0.tgz", + "integrity": "sha512-meON9LM9dyPun8ZlIs90BzqHAIWfWkC8g+OoPuIEeV5UOSyKqMsWtbMyiTbs/k/i7k1V4miJQMX/PcLbD7pWcQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/instrumentation-amqplib": "^0.39.0", + "@opentelemetry/instrumentation-aws-lambda": "^0.43.0", + "@opentelemetry/instrumentation-aws-sdk": "^0.43.0", + "@opentelemetry/instrumentation-bunyan": "^0.40.0", + "@opentelemetry/instrumentation-cassandra-driver": "^0.40.0", + "@opentelemetry/instrumentation-connect": "^0.38.0", + "@opentelemetry/instrumentation-cucumber": "^0.8.0", + "@opentelemetry/instrumentation-dataloader": "^0.11.0", + "@opentelemetry/instrumentation-dns": "^0.38.0", + "@opentelemetry/instrumentation-express": "^0.41.0", + "@opentelemetry/instrumentation-fastify": "^0.38.0", + "@opentelemetry/instrumentation-fs": "^0.14.0", + "@opentelemetry/instrumentation-generic-pool": "^0.38.0", + "@opentelemetry/instrumentation-graphql": "^0.42.0", + "@opentelemetry/instrumentation-grpc": "^0.52.0", + "@opentelemetry/instrumentation-hapi": "^0.40.0", + "@opentelemetry/instrumentation-http": "^0.52.0", + "@opentelemetry/instrumentation-ioredis": "^0.42.0", + "@opentelemetry/instrumentation-knex": "^0.38.0", + "@opentelemetry/instrumentation-koa": "^0.42.0", + "@opentelemetry/instrumentation-lru-memoizer": "^0.39.0", + "@opentelemetry/instrumentation-memcached": "^0.38.0", + "@opentelemetry/instrumentation-mongodb": "^0.46.0", + "@opentelemetry/instrumentation-mongoose": "^0.40.0", + "@opentelemetry/instrumentation-mysql": "^0.40.0", + "@opentelemetry/instrumentation-mysql2": "^0.40.0", + "@opentelemetry/instrumentation-nestjs-core": "^0.39.0", + "@opentelemetry/instrumentation-net": "^0.38.0", + "@opentelemetry/instrumentation-pg": "^0.43.0", + "@opentelemetry/instrumentation-pino": "^0.41.0", + "@opentelemetry/instrumentation-redis": "^0.41.0", + "@opentelemetry/instrumentation-redis-4": "^0.41.0", + "@opentelemetry/instrumentation-restify": "^0.40.0", + "@opentelemetry/instrumentation-router": "^0.39.0", + "@opentelemetry/instrumentation-socket.io": "^0.41.0", + "@opentelemetry/instrumentation-tedious": "^0.12.0", + "@opentelemetry/instrumentation-undici": "^0.4.0", + "@opentelemetry/instrumentation-winston": "^0.39.0", + "@opentelemetry/resource-detector-alibaba-cloud": "^0.28.10", + "@opentelemetry/resource-detector-aws": "^1.5.2", + "@opentelemetry/resource-detector-azure": "^0.2.9", + "@opentelemetry/resource-detector-container": "^0.3.11", + "@opentelemetry/resource-detector-gcp": "^0.29.10", + "@opentelemetry/resources": "^1.24.0", + "@opentelemetry/sdk-node": "^0.52.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.4.1" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/context-async-hooks": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.25.1.tgz", + "integrity": "sha512-UW/ge9zjvAEmRWVapOP0qyCvPulWU6cQxGxDbWEFfGOj1VBBZAuOqTo3X6yWmDTD3Xe15ysCZChHncr2xFMIfQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/core": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.25.1.tgz", + "integrity": "sha512-GeT/l6rBYWVQ4XArluLVB6WWQ8flHbdb6r2FCHC3smtdOAbrJBIv35tpV/yp9bmYUJf+xmZpu9DRTIeJVhFbEQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/exporter-trace-otlp-grpc": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.52.1.tgz", + "integrity": "sha512-pVkSH20crBwMTqB3nIN4jpQKUEoB0Z94drIHpYyEqs7UBr+I0cpYyOR3bqjA/UasQUMROb3GX8ZX4/9cVRqGBQ==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "1.25.1", + "@opentelemetry/otlp-grpc-exporter-base": "0.52.1", + "@opentelemetry/otlp-transformer": "0.52.1", + "@opentelemetry/resources": "1.25.1", + "@opentelemetry/sdk-trace-base": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/exporter-trace-otlp-http": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.52.1.tgz", + "integrity": "sha512-05HcNizx0BxcFKKnS5rwOV+2GevLTVIRA0tRgWYyw4yCgR53Ic/xk83toYKts7kbzcI+dswInUg/4s8oyA+tqg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.25.1", + "@opentelemetry/otlp-exporter-base": "0.52.1", + "@opentelemetry/otlp-transformer": "0.52.1", + "@opentelemetry/resources": "1.25.1", + "@opentelemetry/sdk-trace-base": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/exporter-trace-otlp-proto": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.52.1.tgz", + "integrity": "sha512-pt6uX0noTQReHXNeEslQv7x311/F1gJzMnp1HD2qgypLRPbXDeMzzeTngRTUaUbP6hqWNtPxuLr4DEoZG+TcEQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.25.1", + "@opentelemetry/otlp-exporter-base": "0.52.1", + "@opentelemetry/otlp-transformer": "0.52.1", + "@opentelemetry/resources": "1.25.1", + "@opentelemetry/sdk-trace-base": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/exporter-zipkin": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-1.25.1.tgz", + "integrity": "sha512-RmOwSvkimg7ETwJbUOPTMhJm9A9bG1U8s7Zo3ajDh4zM7eYcycQ0dM7FbLD6NXWbI2yj7UY4q8BKinKYBQksyw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.25.1", + "@opentelemetry/resources": "1.25.1", + "@opentelemetry/sdk-trace-base": "1.25.1", + "@opentelemetry/semantic-conventions": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/otlp-exporter-base": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.52.1.tgz", + "integrity": "sha512-z175NXOtX5ihdlshtYBe5RpGeBoTXVCKPPLiQlD6FHvpM4Ch+p2B0yWKYSrBfLH24H9zjJiBdTrtD+hLlfnXEQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.25.1", + "@opentelemetry/otlp-transformer": "0.52.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/otlp-grpc-exporter-base": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.52.1.tgz", + "integrity": "sha512-zo/YrSDmKMjG+vPeA9aBBrsQM9Q/f2zo6N04WMB3yNldJRsgpRBeLLwvAt/Ba7dpehDLOEFBd1i2JCoaFtpCoQ==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "1.25.1", + "@opentelemetry/otlp-exporter-base": "0.52.1", + "@opentelemetry/otlp-transformer": "0.52.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/otlp-transformer": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.52.1.tgz", + "integrity": "sha512-I88uCZSZZtVa0XniRqQWKbjAUm73I8tpEy/uJYPPYw5d7BRdVk0RfTBQw8kSUl01oVWEuqxLDa802222MYyWHg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@opentelemetry/core": "1.25.1", + "@opentelemetry/resources": "1.25.1", + "@opentelemetry/sdk-logs": "0.52.1", + "@opentelemetry/sdk-metrics": "1.25.1", + "@opentelemetry/sdk-trace-base": "1.25.1", + "protobufjs": "^7.3.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/propagator-b3": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-1.25.1.tgz", + "integrity": "sha512-p6HFscpjrv7//kE+7L+3Vn00VEDUJB0n6ZrjkTYHrJ58QZ8B3ajSJhRbCcY6guQ3PDjTbxWklyvIN2ojVbIb1A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/propagator-jaeger": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.25.1.tgz", + "integrity": "sha512-nBprRf0+jlgxks78G/xq72PipVK+4or9Ypntw0gVZYNTCSK8rg5SeaGV19tV920CMqBD/9UIOiFr23Li/Q8tiA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/resources": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.25.1.tgz", + "integrity": "sha512-pkZT+iFYIZsVn6+GzM0kSX+u3MSLCY9md+lIJOoKl/P+gJFfxJte/60Usdp8Ce4rOs8GduUpSPNe1ddGyDT1sQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.25.1", + "@opentelemetry/semantic-conventions": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/sdk-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.52.1.tgz", + "integrity": "sha512-MBYh+WcPPsN8YpRHRmK1Hsca9pVlyyKd4BxOC4SsgHACnl/bPp4Cri9hWhVm5+2tiQ9Zf4qSc1Jshw9tOLGWQA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@opentelemetry/core": "1.25.1", + "@opentelemetry/resources": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/sdk-metrics": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.25.1.tgz", + "integrity": "sha512-9Mb7q5ioFL4E4dDrc4wC/A3NTHDat44v4I3p2pLPSxRvqUbDIQyMVr9uK+EU69+HWhlET1VaSrRzwdckWqY15Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.25.1", + "@opentelemetry/resources": "1.25.1", + "lodash.merge": "^4.6.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/sdk-node": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.52.1.tgz", + "integrity": "sha512-uEG+gtEr6eKd8CVWeKMhH2olcCHM9dEK68pe0qE0be32BcCRsvYURhHaD1Srngh1SQcnQzZ4TP324euxqtBOJA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@opentelemetry/core": "1.25.1", + "@opentelemetry/exporter-trace-otlp-grpc": "0.52.1", + "@opentelemetry/exporter-trace-otlp-http": "0.52.1", + "@opentelemetry/exporter-trace-otlp-proto": "0.52.1", + "@opentelemetry/exporter-zipkin": "1.25.1", + "@opentelemetry/instrumentation": "0.52.1", + "@opentelemetry/resources": "1.25.1", + "@opentelemetry/sdk-logs": "0.52.1", + "@opentelemetry/sdk-metrics": "1.25.1", + "@opentelemetry/sdk-trace-base": "1.25.1", + "@opentelemetry/sdk-trace-node": "1.25.1", + "@opentelemetry/semantic-conventions": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.25.1.tgz", + "integrity": "sha512-C8k4hnEbc5FamuZQ92nTOp8X/diCY56XUTnMiv9UTuJitCzaNNHAVsdm5+HLCdI8SLQsLWIrG38tddMxLVoftw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.25.1", + "@opentelemetry/resources": "1.25.1", + "@opentelemetry/semantic-conventions": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/sdk-trace-node": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.25.1.tgz", + "integrity": "sha512-nMcjFIKxnFqoez4gUmihdBrbpsEnAX/Xj16sGvZm+guceYE0NE00vLhpDVK6f3q8Q4VFI5xG8JjlXKMB/SkTTQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/context-async-hooks": "1.25.1", + "@opentelemetry/core": "1.25.1", + "@opentelemetry/propagator-b3": "1.25.1", + "@opentelemetry/propagator-jaeger": "1.25.1", + "@opentelemetry/sdk-trace-base": "1.25.1", + "semver": "^7.5.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", + "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, "node_modules/@opentelemetry/context-async-hooks": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.22.0.tgz", @@ -3877,107 +4296,2442 @@ "integrity": "sha512-0VoAlT6x+Xzik1v9goJ3pZ2ppi6+xd3aUfg4brfrLkDBHRIVjMP0eBHrKrhB+NKcDyMAg8fAbGL3Npg/F6AwWA==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/semantic-conventions": "1.22.0" + "@opentelemetry/semantic-conventions": "1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.9.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/resources": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.22.0.tgz", + "integrity": "sha512-+vNeIFPH2hfcNL0AJk/ykJXoUCtR1YaDUZM+p3wZNU4Hq98gzq+7b43xbkXjadD9VhWIUQqEwXyY64q6msPj6A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.22.0", + "@opentelemetry/semantic-conventions": "1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.9.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.22.0.tgz", + "integrity": "sha512-CAOgFOKLybd02uj/GhCdEeeBjOS0yeoDeo/CA7ASBSmenpZHAKGB3iDm/rv3BQLcabb/OprDEsSQ1y0P8A7Siw==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/exporter-zipkin": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-1.22.0.tgz", + "integrity": "sha512-XcFs6rGvcTz0qW5uY7JZDYD0yNEXdekXAb6sFtnZgY/cHY6BQ09HMzOjv9SX+iaXplRDcHr1Gta7VQKM1XXM6g==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.22.0", + "@opentelemetry/resources": "1.22.0", + "@opentelemetry/sdk-trace-base": "1.22.0", + "@opentelemetry/semantic-conventions": "1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/core": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.22.0.tgz", + "integrity": "sha512-0VoAlT6x+Xzik1v9goJ3pZ2ppi6+xd3aUfg4brfrLkDBHRIVjMP0eBHrKrhB+NKcDyMAg8fAbGL3Npg/F6AwWA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.9.0" + } + }, + "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/resources": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.22.0.tgz", + "integrity": "sha512-+vNeIFPH2hfcNL0AJk/ykJXoUCtR1YaDUZM+p3wZNU4Hq98gzq+7b43xbkXjadD9VhWIUQqEwXyY64q6msPj6A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.22.0", + "@opentelemetry/semantic-conventions": "1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.9.0" + } + }, + "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.22.0.tgz", + "integrity": "sha512-CAOgFOKLybd02uj/GhCdEeeBjOS0yeoDeo/CA7ASBSmenpZHAKGB3iDm/rv3BQLcabb/OprDEsSQ1y0P8A7Siw==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation": { + "version": "0.49.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.49.1.tgz", + "integrity": "sha512-0DLtWtaIppuNNRRllSD4bjU8ZIiLp1cDXvJEbp752/Zf+y3gaLNaoGRGIlX4UHhcsrmtL+P2qxi3Hodi8VuKiQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.49.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "1.7.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-amqplib": { + "version": "0.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.39.0.tgz", + "integrity": "sha512-i9SccU5bbHivmmN8ba8HitLnM915BWdGwk5Jl6dwHTp0eV4KpoprZLE/jXUY1AAP/LXpTrM7NgVHmslFSVWRYA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-amqplib/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-amqplib/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-amqplib/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-aws-lambda": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-lambda/-/instrumentation-aws-lambda-0.43.0.tgz", + "integrity": "sha512-pSxcWlsE/pCWQRIw92sV2C+LmKXelYkjkA7C5s39iPUi4pZ2lA1nIiw+1R/y2pDEhUHcaKkNyljQr3cx9ZpVlQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/propagator-aws-xray": "^1.3.1", + "@opentelemetry/resources": "^1.8.0", + "@opentelemetry/semantic-conventions": "^1.22.0", + "@types/aws-lambda": "8.10.122" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-aws-lambda/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-aws-lambda/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-aws-lambda/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-aws-sdk": { + "version": "0.43.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-sdk/-/instrumentation-aws-sdk-0.43.1.tgz", + "integrity": "sha512-qLT2cCniJ5W+6PFzKbksnoIQuq9pS83nmgaExfUwXVvlwi0ILc50dea0tWBHZMkdIDa/zZdcuFrJ7+fUcSnRow==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/propagation-utils": "^0.30.10", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-aws-sdk/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-aws-sdk/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-aws-sdk/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-bunyan": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-bunyan/-/instrumentation-bunyan-0.40.0.tgz", + "integrity": "sha512-aZ4cXaGWwj79ZXSYrgFVsrDlE4mmf2wfvP9bViwRc0j75A6eN6GaHYHqufFGMTCqASQn5pIjjP+Bx+PWTGiofw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "^0.52.0", + "@opentelemetry/instrumentation": "^0.52.0", + "@types/bunyan": "1.8.9" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-bunyan/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-bunyan/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-bunyan/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-cassandra-driver": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cassandra-driver/-/instrumentation-cassandra-driver-0.40.0.tgz", + "integrity": "sha512-JxbM39JU7HxE9MTKKwi6y5Z3mokjZB2BjwfqYi4B3Y29YO3I42Z7eopG6qq06yWZc+nQli386UDQe0d9xKmw0A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-cassandra-driver/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-cassandra-driver/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-cassandra-driver/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-connect": { + "version": "0.38.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.38.0.tgz", + "integrity": "sha512-2/nRnx3pjYEmdPIaBwtgtSviTKHWnDZN3R+TkRUnhIVrvBKVcq+I5B2rtd6mr6Fe9cHlZ9Ojcuh7pkNh/xdWWg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.22.0", + "@types/connect": "3.4.36" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-connect/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-connect/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-connect/node_modules/@types/connect": { + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", + "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@opentelemetry/instrumentation-connect/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-cucumber": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cucumber/-/instrumentation-cucumber-0.8.0.tgz", + "integrity": "sha512-ieTm4RBIlZt2brPwtX5aEZYtYnkyqhAVXJI9RIohiBVMe5DxiwCwt+2Exep/nDVqGPX8zRBZUl4AEw423OxJig==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/instrumentation-cucumber/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-cucumber/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-cucumber/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-dataloader": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.11.0.tgz", + "integrity": "sha512-27urJmwkH4KDaMJtEv1uy2S7Apk4XbN4AgWMdfMJbi7DnOduJmeuA+DpJCwXB72tEWXo89z5T3hUVJIDiSNmNw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-dataloader/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-dataloader/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-dataloader/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-dns": { + "version": "0.38.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dns/-/instrumentation-dns-0.38.0.tgz", + "integrity": "sha512-Um07I0TQXDWa+ZbEAKDFUxFH40dLtejtExDOMLNJ1CL8VmOmA71qx93Qi/QG4tGkiI1XWqr7gF/oiMCJ4m8buQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-dns/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-dns/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-dns/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-express": { + "version": "0.41.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.41.1.tgz", + "integrity": "sha512-uRx0V3LPGzjn2bxAnV8eUsDT82vT7NTwI0ezEuPMBOTOsnPpGhWdhcdNdhH80sM4TrWrOfXm9HGEdfWE3TRIww==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-express/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-express/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-express/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-fastify": { + "version": "0.38.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.38.0.tgz", + "integrity": "sha512-HBVLpTSYpkQZ87/Df3N0gAw7VzYZV3n28THIBrJWfuqw3Or7UqdhnjeuMIPQ04BKk3aZc0cWn2naSQObbh5vXw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-fastify/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-fastify/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-fastify/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-fs": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.14.0.tgz", + "integrity": "sha512-pVc8P5AgliC1DphyyBUgsxXlm2XaPH4BpYvt7rAZDMIqUpRk8gs19SioABtKqqxvFzg5jPtgJfJsdxq0Y+maLw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.52.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-fs/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-fs/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-fs/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-generic-pool": { + "version": "0.38.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.38.1.tgz", + "integrity": "sha512-WvssuKCuavu/hlq661u82UWkc248cyI/sT+c2dEIj6yCk0BUkErY1D+9XOO+PmHdJNE+76i2NdcvQX5rJrOe/w==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-generic-pool/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-generic-pool/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-generic-pool/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-graphql": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.42.0.tgz", + "integrity": "sha512-N8SOwoKL9KQSX7z3gOaw5UaTeVQcfDO1c21csVHnmnmGUoqsXbArK2B8VuwPWcv6/BC/i3io+xTo7QGRZ/z28Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-graphql/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-graphql/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-graphql/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-grpc": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-grpc/-/instrumentation-grpc-0.52.1.tgz", + "integrity": "sha512-EdSDiDSAO+XRXk/ZN128qQpBo1I51+Uay/LUPcPQhSRGf7fBPIEUBeOLQiItguGsug5MGOYjql2w/1wCQF3fdQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "0.52.1", + "@opentelemetry/semantic-conventions": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-grpc/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-grpc/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-grpc/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", + "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-grpc/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-hapi": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.40.0.tgz", + "integrity": "sha512-8U/w7Ifumtd2bSN1OLaSwAAFhb9FyqWUki3lMMB0ds+1+HdSxYBe9aspEJEgvxAqOkrQnVniAPTEGf1pGM7SOw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-hapi/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-hapi/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-hapi/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-http": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.52.1.tgz", + "integrity": "sha512-dG/aevWhaP+7OLv4BQQSEKMJv8GyeOp3Wxl31NHqE8xo9/fYMfEljiZphUHIfyg4gnZ9swMyWjfOQs5GUQe54Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.25.1", + "@opentelemetry/instrumentation": "0.52.1", + "@opentelemetry/semantic-conventions": "1.25.1", + "semver": "^7.5.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/core": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.25.1.tgz", + "integrity": "sha512-GeT/l6rBYWVQ4XArluLVB6WWQ8flHbdb6r2FCHC3smtdOAbrJBIv35tpV/yp9bmYUJf+xmZpu9DRTIeJVhFbEQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "1.25.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", + "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-http/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-ioredis": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.42.0.tgz", + "integrity": "sha512-P11H168EKvBB9TUSasNDOGJCSkpT44XgoM6d3gRIWAa9ghLpYhl0uRkS8//MqPzcJVHr3h3RmfXIpiYLjyIZTw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/redis-common": "^0.36.2", + "@opentelemetry/semantic-conventions": "^1.23.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-ioredis/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-ioredis/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-ioredis/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-knex": { + "version": "0.38.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.38.0.tgz", + "integrity": "sha512-EFef6Ss5ATsf5AxJOLE+pxkfupcWDaejkPH+2q7TNeG1UwsBFobfiWM+iHROZ1Cl/y3mTi60MW70FxsaX2/TjA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-knex/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-knex/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-knex/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-koa": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.42.0.tgz", + "integrity": "sha512-H1BEmnMhho8o8HuNRq5zEI4+SIHDIglNB7BPKohZyWG4fWNuR7yM4GTlR01Syq21vODAS7z5omblScJD/eZdKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-koa/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-koa/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-koa/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-lru-memoizer": { + "version": "0.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.39.0.tgz", + "integrity": "sha512-eU1Wx1RRTR/2wYXFzH9gcpB8EPmhYlNDIUHzUXjyUE0CAXEJhBLkYNlzdaVCoQDw2neDqS+Woshiia6+emWK9A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-lru-memoizer/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-lru-memoizer/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-lru-memoizer/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-memcached": { + "version": "0.38.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-memcached/-/instrumentation-memcached-0.38.0.tgz", + "integrity": "sha512-tPmyqQEZNyrvg6G+iItdlguQEcGzfE+bJkpQifmBXmWBnoS5oU3UxqtyYuXGL2zI9qQM5yMBHH4nRXWALzy7WA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.23.0", + "@types/memcached": "^2.2.6" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-memcached/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-memcached/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-memcached/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-mongodb": { + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.46.0.tgz", + "integrity": "sha512-VF/MicZ5UOBiXrqBslzwxhN7TVqzu1/LN/QDpkskqM0Zm0aZ4CVRbUygL8d7lrjLn15x5kGIe8VsSphMfPJzlA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/sdk-metrics": "^1.9.1", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongodb/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-mongodb/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongodb/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-mongoose": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.40.0.tgz", + "integrity": "sha512-niRi5ZUnkgzRhIGMOozTyoZIvJKNJyhijQI4nF4iFSb+FUx2v5fngfR+8XLmdQAO7xmsD8E5vEGdDVYVtKbZew==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongoose/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-mongoose/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongoose/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.40.0.tgz", + "integrity": "sha512-d7ja8yizsOCNMYIJt5PH/fKZXjb/mS48zLROO4BzZTtDfhNCl2UM/9VIomP2qkGIFVouSJrGr/T00EzY7bPtKA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.22.0", + "@types/mysql": "2.15.22" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql2": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.40.0.tgz", + "integrity": "sha512-0xfS1xcqUmY7WE1uWjlmI67Xg3QsSUlNT+AcXHeA4BDUPwZtWqF4ezIwLgpVZfHOnkAEheqGfNSWd1PIu3Wnfg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.22.0", + "@opentelemetry/sql-common": "^0.40.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql2/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql2/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql2/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-nestjs-core": { + "version": "0.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.39.0.tgz", + "integrity": "sha512-mewVhEXdikyvIZoMIUry8eb8l3HUjuQjSjVbmLVTt4NQi35tkpnHQrG9bTRBrl3403LoWZ2njMPJyg4l6HfKvA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.23.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-nestjs-core/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-nestjs-core/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-nestjs-core/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-net": { + "version": "0.38.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-net/-/instrumentation-net-0.38.0.tgz", + "integrity": "sha512-stjow1PijcmUquSmRD/fSihm/H61DbjPlJuJhWUe7P22LFPjFhsrSeiB5vGj3vn+QGceNAs+kioUTzMGPbNxtg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.23.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-net/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-net/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-net/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-pg": { + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.43.0.tgz", + "integrity": "sha512-og23KLyoxdnAeFs1UWqzSonuCkePUzCX30keSYigIzJe/6WSYA8rnEI5lobcxPEzg+GcU06J7jzokuEHbjVJNw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.22.0", + "@opentelemetry/sql-common": "^0.40.1", + "@types/pg": "8.6.1", + "@types/pg-pool": "2.0.4" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pg/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-pg/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pg/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-pino": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pino/-/instrumentation-pino-0.41.0.tgz", + "integrity": "sha512-Kpv0fJRk/8iMzMk5Ue5BsUJfHkBJ2wQoIi/qduU1a1Wjx9GLj6J2G17PHjPK5mnZjPNzkFOXFADZMfgDioliQw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "^0.52.0", + "@opentelemetry/core": "^1.25.0", + "@opentelemetry/instrumentation": "^0.52.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pino/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-pino/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pino/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-redis": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.41.0.tgz", + "integrity": "sha512-RJ1pwI3btykp67ts+5qZbaFSAAzacucwBet5/5EsKYtWBpHbWwV/qbGN/kIBzXg5WEZBhXLrR/RUq0EpEUpL3A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/redis-common": "^0.36.2", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-redis-4": { + "version": "0.41.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.41.1.tgz", + "integrity": "sha512-UqJAbxraBk7s7pQTlFi5ND4sAUs4r/Ai7gsAVZTQDbHl2kSsOp7gpHcpIuN5dpcI2xnuhM2tkH4SmEhbrv2S6Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/redis-common": "^0.36.2", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-redis-4/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-redis-4/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-redis-4/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-redis/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-redis/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-redis/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-restify": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-restify/-/instrumentation-restify-0.40.0.tgz", + "integrity": "sha512-sm/rH/GysY/KOEvZqYBZSLYFeXlBkHCgqPDgWc07tz+bHCN6mPs9P3otGOSTe7o3KAIM8Nc6ncCO59vL+jb2cA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-restify/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-restify/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-restify/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-router": { + "version": "0.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-router/-/instrumentation-router-0.39.0.tgz", + "integrity": "sha512-LaXnVmD69WPC4hNeLzKexCCS19hRLrUw3xicneAMkzJSzNJvPyk7G6I7lz7VjQh1cooObPBt9gNyd3hhTCUrag==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-router/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-router/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-router/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-socket.io": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-socket.io/-/instrumentation-socket.io-0.41.0.tgz", + "integrity": "sha512-7fzDe9/FpO6NFizC/wnzXXX7bF9oRchsD//wFqy5g5hVEgXZCQ70IhxjrKdBvgjyIejR9T9zTvfQ6PfVKfkCAw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-socket.io/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-socket.io/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-socket.io/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-tedious": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.12.0.tgz", + "integrity": "sha512-53xx7WQmpBPfxtVxOKRzzZxOjv9JzSdoy1aIvCtPM5/O407aYcdvj8wXxCQEiEfctFEovEHG4QgmdHz9BKidSQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/semantic-conventions": "^1.22.0", + "@types/tedious": "^4.0.10" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-tedious/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-tedious/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { "node": ">=14" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.9.0" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/resources": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.22.0.tgz", - "integrity": "sha512-+vNeIFPH2hfcNL0AJk/ykJXoUCtR1YaDUZM+p3wZNU4Hq98gzq+7b43xbkXjadD9VhWIUQqEwXyY64q6msPj6A==", + "node_modules/@opentelemetry/instrumentation-tedious/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "1.22.0", - "@opentelemetry/semantic-conventions": "1.22.0" + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@opentelemetry/instrumentation-undici": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.4.0.tgz", + "integrity": "sha512-UdMQBpz11SqtWlmDnk5SoqF5QDom4VmW8SVDt9Q2xuMWVh8lc0kVROfoo2pl7zU6H6gFR8eudb3eFXIdrFn0ew==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.52.0" }, "engines": { "node": ">=14" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.9.0" + "@opentelemetry/api": "^1.7.0" } }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.22.0.tgz", - "integrity": "sha512-CAOgFOKLybd02uj/GhCdEeeBjOS0yeoDeo/CA7ASBSmenpZHAKGB3iDm/rv3BQLcabb/OprDEsSQ1y0P8A7Siw==", + "node_modules/@opentelemetry/instrumentation-undici/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, "engines": { "node": ">=14" } }, - "node_modules/@opentelemetry/exporter-zipkin": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-1.22.0.tgz", - "integrity": "sha512-XcFs6rGvcTz0qW5uY7JZDYD0yNEXdekXAb6sFtnZgY/cHY6BQ09HMzOjv9SX+iaXplRDcHr1Gta7VQKM1XXM6g==", + "node_modules/@opentelemetry/instrumentation-undici/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "1.22.0", - "@opentelemetry/resources": "1.22.0", - "@opentelemetry/sdk-trace-base": "1.22.0", - "@opentelemetry/semantic-conventions": "1.22.0" + "@opentelemetry/api-logs": "0.52.1", + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { "node": ">=14" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/core": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.22.0.tgz", - "integrity": "sha512-0VoAlT6x+Xzik1v9goJ3pZ2ppi6+xd3aUfg4brfrLkDBHRIVjMP0eBHrKrhB+NKcDyMAg8fAbGL3Npg/F6AwWA==", + "node_modules/@opentelemetry/instrumentation-undici/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/semantic-conventions": "1.22.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.9.0" + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" } }, - "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/resources": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.22.0.tgz", - "integrity": "sha512-+vNeIFPH2hfcNL0AJk/ykJXoUCtR1YaDUZM+p3wZNU4Hq98gzq+7b43xbkXjadD9VhWIUQqEwXyY64q6msPj6A==", + "node_modules/@opentelemetry/instrumentation-winston": { + "version": "0.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-winston/-/instrumentation-winston-0.39.0.tgz", + "integrity": "sha512-v/1xziLJ9CyB3YDjBSBzbB70Qd0JwWTo36EqWK5m3AR0CzsyMQQmf3ZIZM6sgx7hXMcRQ0pnEYhg6nhrUQPm9A==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "1.22.0", - "@opentelemetry/semantic-conventions": "1.22.0" + "@opentelemetry/api-logs": "^0.52.0", + "@opentelemetry/instrumentation": "^0.52.0" }, "engines": { "node": ">=14" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.9.0" + "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.22.0.tgz", - "integrity": "sha512-CAOgFOKLybd02uj/GhCdEeeBjOS0yeoDeo/CA7ASBSmenpZHAKGB3iDm/rv3BQLcabb/OprDEsSQ1y0P8A7Siw==", + "node_modules/@opentelemetry/instrumentation-winston/node_modules/@opentelemetry/api-logs": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", + "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, "engines": { "node": ">=14" } }, - "node_modules/@opentelemetry/instrumentation": { - "version": "0.49.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.49.1.tgz", - "integrity": "sha512-0DLtWtaIppuNNRRllSD4bjU8ZIiLp1cDXvJEbp752/Zf+y3gaLNaoGRGIlX4UHhcsrmtL+P2qxi3Hodi8VuKiQ==", + "node_modules/@opentelemetry/instrumentation-winston/node_modules/@opentelemetry/instrumentation": { + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", + "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/api-logs": "0.49.1", + "@opentelemetry/api-logs": "0.52.1", "@types/shimmer": "^1.0.2", - "import-in-the-middle": "1.7.1", + "import-in-the-middle": "^1.8.1", "require-in-the-middle": "^7.1.1", "semver": "^7.5.2", "shimmer": "^1.2.1" @@ -3989,6 +6743,18 @@ "@opentelemetry/api": "^1.3.0" } }, + "node_modules/@opentelemetry/instrumentation-winston/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, "node_modules/@opentelemetry/otlp-exporter-base": { "version": "0.49.1", "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.49.1.tgz", @@ -4172,6 +6938,30 @@ "node": ">=14" } }, + "node_modules/@opentelemetry/propagation-utils": { + "version": "0.30.16", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagation-utils/-/propagation-utils-0.30.16.tgz", + "integrity": "sha512-ZVQ3Z/PQ+2GQlrBfbMMMT0U7MzvYZLCPP800+ooyaBqm4hMvuQHfP028gB9/db0mwkmyEAMad9houukUVxhwcw==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/propagator-aws-xray": { + "version": "1.26.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-aws-xray/-/propagator-aws-xray-1.26.2.tgz", + "integrity": "sha512-k43wxTjKYvwfce9L4eT8fFYy/ATmCfPHZPZsyT/6ABimf2KE1HafoOsIcxLOtmNSZt6dCvBIYCrXaOWta20xJg==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, "node_modules/@opentelemetry/propagator-b3": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-1.22.0.tgz", @@ -4250,6 +7040,99 @@ "node": ">=14" } }, + "node_modules/@opentelemetry/redis-common": { + "version": "0.36.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.36.2.tgz", + "integrity": "sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/resource-detector-alibaba-cloud": { + "version": "0.28.10", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-alibaba-cloud/-/resource-detector-alibaba-cloud-0.28.10.tgz", + "integrity": "sha512-TZv/1Y2QCL6sJ+X9SsPPBXe4786bc/Qsw0hQXFsNTbJzDTGGUmOAlSZ2qPiuqAd4ZheUYfD+QA20IvAjUz9Hhg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/resources": "^1.0.0", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/resource-detector-aws": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-aws/-/resource-detector-aws-1.12.0.tgz", + "integrity": "sha512-Cvi7ckOqiiuWlHBdA1IjS0ufr3sltex2Uws2RK6loVp4gzIJyOijsddAI6IZ5kiO8h/LgCWe8gxPmwkTKImd+Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.0.0", + "@opentelemetry/resources": "^1.10.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/resource-detector-azure": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-azure/-/resource-detector-azure-0.2.12.tgz", + "integrity": "sha512-iIarQu6MiCjEEp8dOzmBvCSlRITPFTinFB2oNKAjU6xhx8d7eUcjNOKhBGQTvuCriZrxrEvDaEEY9NfrPQ6uYQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.25.1", + "@opentelemetry/resources": "^1.10.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/resource-detector-container": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-container/-/resource-detector-container-0.3.11.tgz", + "integrity": "sha512-22ndMDakxX+nuhAYwqsciexV8/w26JozRUV0FN9kJiqSWtA1b5dCVtlp3J6JivG5t8kDN9UF5efatNnVbqRT9Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/resources": "^1.0.0", + "@opentelemetry/semantic-conventions": "^1.22.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/resource-detector-gcp": { + "version": "0.29.13", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.29.13.tgz", + "integrity": "sha512-vdotx+l3Q+89PeyXMgKEGnZ/CwzwMtuMi/ddgD9/5tKZ08DfDGB2Npz9m2oXPHRCjc4Ro6ifMqFlRyzIvgOjhg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.0.0", + "@opentelemetry/resources": "^1.10.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "gcp-metadata": "^6.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, "node_modules/@opentelemetry/resources": { "version": "1.30.1", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", @@ -4566,6 +7449,21 @@ "node": ">=14" } }, + "node_modules/@opentelemetry/sql-common": { + "version": "0.40.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.40.1.tgz", + "integrity": "sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.1.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0" + } + }, "node_modules/@otplib/core": { "version": "13.4.1", "resolved": "https://registry.npmjs.org/@otplib/core/-/core-13.4.1.tgz", @@ -5203,6 +8101,12 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/aws-lambda": { + "version": "8.10.122", + "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.122.tgz", + "integrity": "sha512-vBkIh9AY22kVOCEKo5CJlyCgmSWvasC+SWUxL/x/vOwRobMpI/HG1xp/Ae3AqmSiZeLUbOhW0FCD3ZjqqUxmXw==", + "license": "MIT" + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -5268,6 +8172,15 @@ "@types/node": "*" } }, + "node_modules/@types/bunyan": { + "version": "1.8.9", + "resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.9.tgz", + "integrity": "sha512-ZqS9JGpBxVOvsawzmVt30sP++gSQMTejCkIAQ3VdadOcRE8izTyW66hufvwLeH+YEGP6Js2AW7Gz+RMyvrEbmw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/connect": { "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", @@ -5421,6 +8334,15 @@ "integrity": "sha512-H3iskjFIAn5SlJU7OuxUmTEpebK6TKB8rxZShDslBMZJ5u9S//KM1sbdAisiSrqwLQncVjnpi2OK2J51h+4lsg==", "license": "MIT" }, + "node_modules/@types/memcached": { + "version": "2.2.10", + "resolved": "https://registry.npmjs.org/@types/memcached/-/memcached-2.2.10.tgz", + "integrity": "sha512-AM9smvZN55Gzs2wRrqeMHVP7KE8KWgCJO/XL5yCly2xF6EKa4YlbpK+cLSAH4NG/Ah64HrlegmGqW8kYws7Vxg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/methods": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", @@ -5428,6 +8350,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/mysql": { + "version": "2.15.22", + "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.22.tgz", + "integrity": "sha512-wK1pzsJVVAjYCSZWQoWHziQZbNggXFDUEIGf54g4ZM/ERuP86uGdWeKZWMYlqTPMZfHJJvLPyogXGvCOg87yLQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "22.19.21", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.21.tgz", @@ -5453,6 +8384,26 @@ "integrity": "sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q==", "license": "MIT" }, + "node_modules/@types/pg": { + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", + "integrity": "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^2.2.0" + } + }, + "node_modules/@types/pg-pool": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.4.tgz", + "integrity": "sha512-qZAvkv1K3QbmHHFYSNRYPkRjOWRLBYrL4B9c+wG0GSVGBw0NtJwPcgx/DSddeDJvRGMHCEQ4VMEVfuJ/0gZ3XQ==", + "license": "MIT", + "dependencies": { + "@types/pg": "*" + } + }, "node_modules/@types/qs": { "version": "6.15.1", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz", @@ -5531,6 +8482,15 @@ "@types/superagent": "^8.1.0" } }, + "node_modules/@types/tedious": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", + "integrity": "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/triple-beam": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", @@ -6418,6 +9378,15 @@ "acorn": "^8" } }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^8" + } + }, "node_modules/acorn-import-phases": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", @@ -9220,6 +12189,12 @@ "node": ">=6.6.0" } }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -9757,6 +12732,72 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "license": "ISC" }, + "node_modules/gaxios": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", + "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/gaxios/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/gaxios/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/gaxios/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/gcp-metadata": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz", + "integrity": "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^6.1.1", + "google-logging-utils": "^0.0.2", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/generic-pool": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", @@ -9953,6 +12994,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/google-logging-utils": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz", + "integrity": "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, "node_modules/google-protobuf": { "version": "3.21.4", "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.4.tgz", @@ -11571,6 +14621,15 @@ "node": ">=6" } }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", diff --git a/src/app.module.ts b/src/app.module.ts index 0d71e5e..efa1167 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -73,6 +73,7 @@ import { PoolSwap } from './exchange/entities/pool-swap.entity'; import { EmergencyWithdrawal } from './exchange/entities/emergency-withdrawal.entity'; import { ExchangeModule } from './exchange/exchange.module'; import { MobileModule } from './mobile/mobile.module'; +import { NotificationsModule } from './notifications/notifications.module'; @Module({ imports: [ @@ -81,7 +82,7 @@ import { MobileModule } from './mobile/mobile.module'; I18nModule.forRoot({ fallbackLanguage: 'en', loaderOptions: { - path: path.join(__dirname, '/i18n/'), + path: path.join(__dirname, '/notifications/templates/i18n/'), watch: true, }, resolvers: [ @@ -103,7 +104,7 @@ import { MobileModule } from './mobile/mobile.module'; imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService) => ({ - type: configService.get('DB_TYPE', 'postgres') as '' | 'sqlite', + type: configService.get('DB_TYPE', 'postgres') as 'postgres' | 'sqlite', host: configService.get('DB_HOST', 'localhost'), port: configService.get('DB_PORT', 5432), username: configService.get('DB_USERNAME', 'postgres'), @@ -169,17 +170,20 @@ import { MobileModule } from './mobile/mobile.module'; // ── Trading Features — Advanced Order Types (issue #382) ── OrdersModule, - // ── Mobile Integration ── + // Mobile Integration ── MobileModule, // ── Institutional Portal ── InstitutionalModule, // ── AI Features — Trading Assistant (issue #395) ── AiTradingAssistantModule, + // ── Notifications Module ── + NotificationsModule, + // ── Error Handling ── ErrorModule, ], controllers: [AppController], providers: [AppService], }) -export class AppModule {} +export class AppModule {} \ No newline at end of file diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 78e79eb..eccd61b 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -17,7 +17,7 @@ import { ApiResponse, ApiTags, } from '@nestjs/swagger'; -import { Request } from 'express'; +import type { Request } from 'express'; import { AuthService } from './auth.service'; import { RegisterDto } from './dto/register.dto'; @@ -29,7 +29,8 @@ import { ChangePasswordDto, } from './dto/password-reset.dto'; import { Enable2FADto, TwoFADto, Verify2FASetupDto } from './dto/2fa.dto'; -import { JwtAuthGuard, JwtPayload } from './guards/jwt-auth.guard'; +import { JwtAuthGuard } from './guards/jwt-auth.guard'; +import type { JwtPayload } from './guards/jwt-auth.guard'; import { CurrentUser } from './decorators/current-user.decorator'; import { Public } from './decorators/public.decorator'; import { ApiAuthErrorResponses } from '../common/decorators/swagger-error-responses.decorator'; @@ -201,4 +202,4 @@ export class AuthController { disable2FA(@CurrentUser() user: JwtPayload, @Body() dto: TwoFADto) { return this.authService.disable2FA(user.sub, dto); } -} +} \ No newline at end of file diff --git a/src/auth/mfa.controller.ts b/src/auth/mfa.controller.ts index 8671527..7239572 100644 --- a/src/auth/mfa.controller.ts +++ b/src/auth/mfa.controller.ts @@ -4,7 +4,7 @@ import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagg import { MFAService } from './mfa.service'; import { JwtAuthGuard } from './guards/jwt-auth.guard'; import { CurrentUser } from './decorators/current-user.decorator'; -import { JwtPayload } from './guards/jwt-auth.guard'; +import type { JwtPayload } from './guards/jwt-auth.guard'; @ApiTags('identity/auth/mfa') @UseGuards(JwtAuthGuard) @@ -53,4 +53,4 @@ export class MFAController { const isValid = await this.mfaService.verifyToken(user.sub, body.token); return { success: isValid }; } -} +} \ No newline at end of file diff --git a/src/common/enums/notification-channel.enum.ts b/src/common/enums/notification-channel.enum.ts new file mode 100644 index 0000000..e281921 --- /dev/null +++ b/src/common/enums/notification-channel.enum.ts @@ -0,0 +1,5 @@ +export enum NotificationChannel { + EMAIL = 'EMAIL', + SMS = 'SMS', + PUSH = 'PUSH', +} \ No newline at end of file diff --git a/src/common/enums/notification-event-type.enum.ts b/src/common/enums/notification-event-type.enum.ts index 4c7e277..27500df 100644 --- a/src/common/enums/notification-event-type.enum.ts +++ b/src/common/enums/notification-event-type.enum.ts @@ -1,5 +1,10 @@ export enum NotificationEventType { ORDER_FILLED = 'ORDER_FILLED', + TRADE_EXECUTED = 'TRADE_EXECUTED', + LIQUIDATION = 'LIQUIDATION', + DEPOSIT_RECEIVED = 'DEPOSIT_RECEIVED', PRICE_ALERT = 'PRICE_ALERT', ACHIEVEMENT_UNLOCKED = 'ACHIEVEMENT_UNLOCKED', -} + WITHDRAWAL_COMPLETED = 'WITHDRAWAL_COMPLETED', + SECURITY_ALERT = 'SECURITY_ALERT', +} \ No newline at end of file diff --git a/src/common/enums/notification-status.enum.ts b/src/common/enums/notification-status.enum.ts index 145e1ba..2dd4200 100644 --- a/src/common/enums/notification-status.enum.ts +++ b/src/common/enums/notification-status.enum.ts @@ -1,5 +1,10 @@ export enum NotificationStatus { + PENDING = 'PENDING', + PROCESSING = 'PROCESSING', + RETRYING = 'RETRYING', SENT = 'SENT', + DELIVERED = 'DELIVERED', READ = 'READ', FAILED = 'FAILED', -} + PERMANENTLY_FAILED = 'PERMANENTLY_FAILED', +} \ No newline at end of file diff --git a/src/common/logging/audit_service.ts b/src/common/logging/audit_service.ts index 478b445..b569091 100644 --- a/src/common/logging/audit_service.ts +++ b/src/common/logging/audit_service.ts @@ -56,7 +56,7 @@ interface UserAuditData { } interface CreateEntryDto { - userId: number; + userId: string; eventType: string; entityType: string; entityId: string; @@ -278,4 +278,4 @@ export class AuditService { this.logger.audit(auditData); } -} +} \ No newline at end of file diff --git a/src/common/monitoring/interceptors/monitoring.interceptor.ts b/src/common/monitoring/interceptors/monitoring.interceptor.ts index cddf640..83a1490 100644 --- a/src/common/monitoring/interceptors/monitoring.interceptor.ts +++ b/src/common/monitoring/interceptors/monitoring.interceptor.ts @@ -126,8 +126,6 @@ export class MonitoringInterceptor implements NestInterceptor { // eslint-disable-next-line @typescript-eslint/no-this-alias const self = this; - context.active(); // keep TypeScript happy — using OTel context below - // Bind the handler execution to the active span context const handlerResult$ = ( require('@opentelemetry/api').context as typeof import('@opentelemetry/api').context @@ -211,4 +209,4 @@ export class MonitoringInterceptor implements NestInterceptor { .subscribe(subscriber); }); } -} +} \ No newline at end of file diff --git a/src/governance/constants/index.ts b/src/governance/constants/index.ts index b689ce8..57a1c0c 100644 --- a/src/governance/constants/index.ts +++ b/src/governance/constants/index.ts @@ -1 +1 @@ -export * from './constants/governance.constants'; +export * from './governance.constants'; \ No newline at end of file diff --git a/src/governance/controllers/index.ts b/src/governance/controllers/index.ts new file mode 100644 index 0000000..beb498a --- /dev/null +++ b/src/governance/controllers/index.ts @@ -0,0 +1 @@ +export * from './governance.controller'; \ No newline at end of file diff --git a/src/governance/entities/governance-proposal.entity.ts b/src/governance/entities/governance-proposal.entity.ts index 85f20d0..ce1477b 100644 --- a/src/governance/entities/governance-proposal.entity.ts +++ b/src/governance/entities/governance-proposal.entity.ts @@ -74,4 +74,10 @@ export class GovernanceProposal { @UpdateDateColumn() updatedAt: Date; -} + + @Column('decimal', { precision: 18, scale: 8, default: 51 }) + passThresholdVotes: number; + + @Column({ nullable: true }) + executionReason: string; +} \ No newline at end of file diff --git a/src/governance/entities/governance-vote.entity.ts b/src/governance/entities/governance-vote.entity.ts index e6ab8ea..15fcd3b 100644 --- a/src/governance/entities/governance-vote.entity.ts +++ b/src/governance/entities/governance-vote.entity.ts @@ -3,6 +3,7 @@ import { PrimaryGeneratedColumn, Column, CreateDateColumn, + UpdateDateColumn, Index, } from 'typeorm'; @@ -40,4 +41,10 @@ export class GovernanceVote { @Column('text', { nullable: true }) reason: string; -} + + @CreateDateColumn() + createdAt: Date; + + @UpdateDateColumn() + updatedAt: Date; +} \ No newline at end of file diff --git a/src/governance/entities/index.ts b/src/governance/entities/index.ts new file mode 100644 index 0000000..c36c1b2 --- /dev/null +++ b/src/governance/entities/index.ts @@ -0,0 +1,7 @@ +export * from './governance-config.entity'; +export * from './governance-discussion.entity'; +export * from './governance-execution.entity'; +export * from './governance-proposal.entity'; +export * from './governance-vote.entity'; +export * from './token-holding.entity'; +export * from './vote-delegation.entity'; \ No newline at end of file diff --git a/src/governance/services/governance.service.ts b/src/governance/services/governance.service.ts index 77681fb..bef4b76 100644 --- a/src/governance/services/governance.service.ts +++ b/src/governance/services/governance.service.ts @@ -6,8 +6,8 @@ import { ProposalType, VoteType, DiscussionMessageType, - GOVERNANCE_PARAMS, -} from '../constants/governance.constants'; +} from '../enums/governance.enum'; +import { GOVERNANCE_PARAMS } from '../constants/governance.constants'; import { GovernanceProposal, GovernanceVote, @@ -176,4 +176,4 @@ export class GovernanceService { take: limit, }); } -} +} \ No newline at end of file diff --git a/src/identity/admin/admin.controller.ts b/src/identity/admin/admin.controller.ts index be262ef..a45862c 100644 --- a/src/identity/admin/admin.controller.ts +++ b/src/identity/admin/admin.controller.ts @@ -21,7 +21,7 @@ import { UserRole } from '../roles/enums/user-role.enum'; interface AuthenticatedRequest extends ExpressRequest { user: { - id: number; + id: string; roles: UserRole[]; }; } @@ -39,7 +39,7 @@ export class IdentityAdminController { @HttpCode(HttpStatus.OK) @RequirePermissions('users.write') async assignRole( - @Param('userId') userId: number, + @Param('userId') userId: string, @Body() dto: RoleAssignmentDto, @Request() req: AuthenticatedRequest, ) { @@ -57,7 +57,7 @@ export class IdentityAdminController { @HttpCode(HttpStatus.OK) @RequirePermissions('users.write') async revokeRole( - @Param('userId') userId: number, + @Param('userId') userId: string, @Param('role') role: UserRole, @Request() req: AuthenticatedRequest, ) { @@ -73,7 +73,7 @@ export class IdentityAdminController { */ @Get(':userId/roles') @RequirePermissions('users.read') - async getUserRoles(@Param('userId') userId: number) { + async getUserRoles(@Param('userId') userId: string) { return this.roleManagementService.getUserRoles(userId); } @@ -85,7 +85,7 @@ export class IdentityAdminController { @HttpCode(HttpStatus.OK) @RequirePermissions('users.write') async suspendUser( - @Param('userId') userId: number, + @Param('userId') userId: string, @Body() body: { reason: string }, @Request() req: AuthenticatedRequest, ) { @@ -104,7 +104,7 @@ export class IdentityAdminController { @HttpCode(HttpStatus.OK) @RequirePermissions('users.write') async unsuspendUser( - @Param('userId') userId: number, + @Param('userId') userId: string, @Request() req: AuthenticatedRequest, ) { return this.roleManagementService.unsuspendUser(userId, { diff --git a/src/identity/admin/services/role-management.service.ts b/src/identity/admin/services/role-management.service.ts index b07c570..5a608b6 100644 --- a/src/identity/admin/services/role-management.service.ts +++ b/src/identity/admin/services/role-management.service.ts @@ -28,9 +28,9 @@ export class RoleManagementService { * Performs role compatibility checks and publishes RoleAssigned event */ async assignRole( - userId: number, + userId: string, dto: RoleAssignmentDto, - assignedBy: { id: number; roles: UserRole[] }, + assignedBy: { id: string; roles: UserRole[] }, ): Promise { const user = await this.userRepo.findOne({ where: { id: userId } }); if (!user) { @@ -76,9 +76,9 @@ export class RoleManagementService { * Publishes RoleRevoked event */ async revokeRole( - userId: number, + userId: string, roleToRevoke: UserRole, - revokedBy: { id: number; roles: UserRole[] }, + revokedBy: { id: string; roles: UserRole[] }, ): Promise { const user = await this.userRepo.findOne({ where: { id: userId } }); if (!user) { @@ -118,7 +118,7 @@ export class RoleManagementService { /** * Get all roles assigned to a user */ - async getUserRoles(userId: number): Promise { + async getUserRoles(userId: string): Promise { const user = await this.userRepo.findOne({ where: { id: userId } }); if (!user) { throw new NotFoundException('User not found'); @@ -131,8 +131,8 @@ export class RoleManagementService { * Publishes UserSuspended event */ async suspendUser( - userId: number, - suspendedBy: { id: number; roles: UserRole[] }, + userId: string, + suspendedBy: { id: string; roles: UserRole[] }, reason: string, ): Promise { const user = await this.userRepo.findOne({ where: { id: userId } }); @@ -165,8 +165,8 @@ export class RoleManagementService { * Publishes UserActivated event */ async unsuspendUser( - userId: number, - unsuspendedBy: { id: number; roles: UserRole[] }, + userId: string, + unsuspendedBy: { id: string; roles: UserRole[] }, ): Promise { const user = await this.userRepo.findOne({ where: { id: userId } }); if (!user) { @@ -180,8 +180,8 @@ export class RoleManagementService { } user.isSuspended = false; - user.suspensionReason = null; - user.suspendedAt = null; + user.suspensionReason = null as unknown as string; + user.suspendedAt = null as unknown as Date; await this.userRepo.save(user); await this.auditService.createEntry({ diff --git a/src/identity/roles/controllers/roles.controller.ts b/src/identity/roles/controllers/roles.controller.ts index 8114f79..075cd6d 100644 --- a/src/identity/roles/controllers/roles.controller.ts +++ b/src/identity/roles/controllers/roles.controller.ts @@ -75,8 +75,8 @@ export class RolesController { @Roles(UserRole.ADMIN, UserRole.SUPER_ADMIN, UserRole.SUPPORT_AGENT) @RequirePermissions('roles.read') @ApiOperation({ summary: 'Get all roles and permissions for a user' }) - @ApiParam({ name: 'userId', type: Number }) - getUserRoles(@Param('userId', ParseIntPipe) userId: number) { + @ApiParam({ name: 'userId', type: String }) + getUserRoles(@Param('userId') userId: string) { return this.roleManagement.getUserRoles(userId); } -} +} \ No newline at end of file diff --git a/src/identity/roles/services/role-management.service.ts b/src/identity/roles/services/role-management.service.ts index b123adb..346dc5e 100644 --- a/src/identity/roles/services/role-management.service.ts +++ b/src/identity/roles/services/role-management.service.ts @@ -22,7 +22,7 @@ import { ROLE_METADATA } from '../types/role-metadata'; /** Events emitted by this service */ export class RoleAssignedEvent { constructor( - public readonly userId: number, + public readonly userId: string, public readonly roles: UserRole[], public readonly actorId: string, ) {} @@ -30,7 +30,7 @@ export class RoleAssignedEvent { export class RoleRevokedEvent { constructor( - public readonly userId: number, + public readonly userId: string, public readonly roles: UserRole[], public readonly actorId: string, ) {} @@ -142,7 +142,7 @@ export class RoleManagementService { // ─── User Role Assignment ──────────────────────────────────────────────────── async assignRolesToUser(dto: AssignRoleDto, actorId: string): Promise { - const user = await this.userRepo.findOne({ where: { id: dto.userId } }); + const user = await this.userRepo.findOne({ where: { id: String(dto.userId) } }); if (!user) throw new NotFoundException(`User ${dto.userId} not found`); const validation = this.roleService.validateRoleCombination([ @@ -173,14 +173,14 @@ export class RoleManagementService { this.eventEmitter.emit( 'role.assigned', - new RoleAssignedEvent(dto.userId, dto.roles, actorId), + new RoleAssignedEvent(String(dto.userId), dto.roles, actorId), ); return savedUser; } async revokeRolesFromUser(dto: RevokeRoleDto, actorId: string): Promise { - const user = await this.userRepo.findOne({ where: { id: dto.userId } }); + const user = await this.userRepo.findOne({ where: { id: String(dto.userId) } }); if (!user) throw new NotFoundException(`User ${dto.userId} not found`); const beforeState = { roles: [...user.roles] }; @@ -207,13 +207,13 @@ export class RoleManagementService { this.eventEmitter.emit( 'role.revoked', - new RoleRevokedEvent(dto.userId, dto.roles, actorId), + new RoleRevokedEvent(String(dto.userId), dto.roles, actorId), ); return savedUser; } - async getUserRoles(userId: number): Promise<{ + async getUserRoles(userId: string): Promise<{ roles: UserRole[]; primaryRole: UserRole; permissions: string[]; @@ -232,4 +232,4 @@ export class RoleManagementService { permissions, }; } -} +} \ No newline at end of file diff --git a/src/mobile/mobile.controller.ts b/src/mobile/mobile.controller.ts index 8589c97..b7ff12c 100644 --- a/src/mobile/mobile.controller.ts +++ b/src/mobile/mobile.controller.ts @@ -18,7 +18,8 @@ import { ApiTags, } from '@nestjs/swagger'; -import { JwtAuthGuard, JwtPayload } from '../auth/guards/jwt-auth.guard'; +import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; +import type { JwtPayload } from '../auth/guards/jwt-auth.guard'; import { CurrentUser } from '../auth/decorators/current-user.decorator'; import { Public } from '../auth/decorators/public.decorator'; @@ -267,4 +268,4 @@ function resolveDeepLinkPath(linkPath: string): { } return { screen: 'HomeScreen', params: {} }; -} +} \ No newline at end of file diff --git a/src/notifications/config/default-preferences.config.ts b/src/notifications/config/default-preferences.config.ts new file mode 100644 index 0000000..c495f27 --- /dev/null +++ b/src/notifications/config/default-preferences.config.ts @@ -0,0 +1,45 @@ +import { NotificationEventType } from '../../common/enums/notification-event-type.enum'; +import { NotificationChannel } from '../../common/enums/notification-channel.enum'; + +export const defaultPreferences = { + [NotificationEventType.TRADE_EXECUTED]: { + [NotificationChannel.EMAIL]: { enabled: true }, + [NotificationChannel.PUSH]: { enabled: true }, + [NotificationChannel.SMS]: { enabled: false }, + }, + [NotificationEventType.LIQUIDATION]: { + [NotificationChannel.EMAIL]: { enabled: true }, + [NotificationChannel.PUSH]: { enabled: true }, + [NotificationChannel.SMS]: { enabled: true }, // Critical alert - SMS enabled by default + }, + [NotificationEventType.DEPOSIT_RECEIVED]: { + [NotificationChannel.EMAIL]: { enabled: true }, + [NotificationChannel.PUSH]: { enabled: true }, + [NotificationChannel.SMS]: { enabled: false }, + }, + [NotificationEventType.WITHDRAWAL_COMPLETED]: { + [NotificationChannel.EMAIL]: { enabled: true }, + [NotificationChannel.PUSH]: { enabled: true }, + [NotificationChannel.SMS]: { enabled: false }, + }, + [NotificationEventType.SECURITY_ALERT]: { + [NotificationChannel.EMAIL]: { enabled: true }, + [NotificationChannel.PUSH]: { enabled: true }, + [NotificationChannel.SMS]: { enabled: true }, // Critical security alert - SMS enabled + }, + [NotificationEventType.ORDER_FILLED]: { + [NotificationChannel.EMAIL]: { enabled: true }, + [NotificationChannel.PUSH]: { enabled: true }, + [NotificationChannel.SMS]: { enabled: false }, + }, + [NotificationEventType.PRICE_ALERT]: { + [NotificationChannel.EMAIL]: { enabled: false }, + [NotificationChannel.PUSH]: { enabled: true }, + [NotificationChannel.SMS]: { enabled: false }, + }, + [NotificationEventType.ACHIEVEMENT_UNLOCKED]: { + [NotificationChannel.EMAIL]: { enabled: true }, + [NotificationChannel.PUSH]: { enabled: true }, + [NotificationChannel.SMS]: { enabled: false }, + }, +}; \ No newline at end of file diff --git a/src/notifications/controllers/notifications.controller.ts b/src/notifications/controllers/notifications.controller.ts new file mode 100644 index 0000000..a1f3359 --- /dev/null +++ b/src/notifications/controllers/notifications.controller.ts @@ -0,0 +1,52 @@ +import { + Controller, + Get, + Put, + Body, + Param, + Query, + UseGuards, + ParseUUIDPipe, +} from '@nestjs/common'; +import { JwtAuthGuard } from '../../auth/guards/jwt-auth.guard'; +import type { JwtPayload } from '../../auth/guards/jwt-auth.guard'; +import { NotificationsService } from '../services/notifications.service'; +import { UpdateNotificationPreferencesDto } from '../dto/update-notification-preferences.dto'; +import { MarkNotificationReadDto } from '../dto/mark-notification-read.dto'; +import { CurrentUser } from '../../auth/decorators/current-user.decorator'; + +@UseGuards(JwtAuthGuard) +@Controller('notifications') +export class NotificationsController { + constructor(private readonly notificationsService: NotificationsService) {} + + @Get('preferences') + async getPreferences(@CurrentUser('sub', ParseUUIDPipe) userId: string) { + return this.notificationsService.getUserPreferences(userId); + } + + @Put('preferences') + async updatePreferences( + @CurrentUser('sub', ParseUUIDPipe) userId: string, + @Body() updateDto: UpdateNotificationPreferencesDto, + ) { + return this.notificationsService.updatePreferences(userId, updateDto); + } + + @Get() + async getNotifications( + @CurrentUser('sub', ParseUUIDPipe) userId: string, + @Query('page') page: number = 1, + @Query('limit') limit: number = 20, + ) { + return this.notificationsService.getUserNotifications(userId, page, limit); + } + + @Put(':id/mark-read') + async markAsRead( + @CurrentUser('sub', ParseUUIDPipe) userId: string, + @Param('id', ParseUUIDPipe) notificationId: string, + ) { + return this.notificationsService.markAsRead(userId, notificationId); + } +} \ No newline at end of file diff --git a/src/notifications/dto/mark-notification-read.dto.ts b/src/notifications/dto/mark-notification-read.dto.ts new file mode 100644 index 0000000..87311a9 --- /dev/null +++ b/src/notifications/dto/mark-notification-read.dto.ts @@ -0,0 +1,7 @@ +import { IsNotEmpty, IsUUID } from 'class-validator'; + +export class MarkNotificationReadDto { + @IsNotEmpty() + @IsUUID() + notificationId: string; +} \ No newline at end of file diff --git a/src/notifications/dto/send-notification.dto.ts b/src/notifications/dto/send-notification.dto.ts new file mode 100644 index 0000000..9fdfd8c --- /dev/null +++ b/src/notifications/dto/send-notification.dto.ts @@ -0,0 +1,23 @@ +import { IsNotEmpty, IsString, IsObject, IsOptional, IsUUID } from 'class-validator'; +import { NotificationEventType } from '../../common/enums/notification-event-type.enum'; +import { NotificationChannel } from '../../common/enums/notification-channel.enum'; + +export class SendNotificationDto { + @IsNotEmpty() + @IsUUID() + userId: string; + + @IsNotEmpty() + type: NotificationEventType; + + @IsNotEmpty() + @IsObject() + data: Record; + + @IsOptional() + @IsString() + language?: string; + + @IsOptional() + forceChannels?: NotificationChannel[]; +} \ No newline at end of file diff --git a/src/notifications/dto/update-notification-preferences.dto.ts b/src/notifications/dto/update-notification-preferences.dto.ts new file mode 100644 index 0000000..0418293 --- /dev/null +++ b/src/notifications/dto/update-notification-preferences.dto.ts @@ -0,0 +1,41 @@ +import { IsOptional, IsBoolean, IsString, IsObject, IsArray } from 'class-validator'; +import { NotificationEventType } from '../../common/enums/notification-event-type.enum'; +import { NotificationChannel } from '../../common/enums/notification-channel.enum'; + +interface ChannelPreferenceDto { + enabled: boolean; +} + +interface EventPreferenceUpdateDto { + [NotificationChannel.EMAIL]?: ChannelPreferenceDto; + [NotificationChannel.SMS]?: ChannelPreferenceDto; + [NotificationChannel.PUSH]?: ChannelPreferenceDto; +} + +export class UpdateNotificationPreferencesDto { + @IsOptional() + @IsString() + preferredLanguage?: string; + + @IsOptional() + @IsObject() + preferences?: Partial<{ + [key in NotificationEventType]?: EventPreferenceUpdateDto; + }>; + + @IsOptional() + @IsString() + email?: string; + + @IsOptional() + @IsString() + phoneNumber?: string; + + @IsOptional() + @IsArray() + pushDeviceTokens?: string[]; + + @IsOptional() + @IsBoolean() + allNotificationsEnabled?: boolean; +} \ No newline at end of file diff --git a/src/notifications/entities/notification.entity.ts b/src/notifications/entities/notification.entity.ts new file mode 100644 index 0000000..1b9bfa7 --- /dev/null +++ b/src/notifications/entities/notification.entity.ts @@ -0,0 +1,71 @@ +import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn } from 'typeorm'; +import { NotificationEventType } from '../../common/enums/notification-event-type.enum'; +import { NotificationStatus } from '../../common/enums/notification-status.enum'; +import { NotificationChannel } from '../../common/enums/notification-channel.enum'; + +@Entity('notifications') +export class Notification { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column() + userId: string; + + @Column({ + type: 'varchar', + enum: NotificationEventType, + }) + type: NotificationEventType; + + @Column({ + type: 'varchar', + enum: NotificationChannel, + }) + channel: NotificationChannel; + + @Column({ + type: 'varchar', + enum: NotificationStatus, + default: NotificationStatus.PENDING, + }) + status: NotificationStatus; + + @Column('jsonb') + data: Record; + + @Column({ nullable: true }) + recipient: string; // Email for EMAIL, phone for SMS, device token for PUSH + + @Column({ nullable: true }) + subject: string; + + @Column({ type: 'text', nullable: true }) + body: string; + + @Column({ default: 0 }) + retryCount: number; + + @Column({ nullable: true }) + lastRetryAt: Date; + + @Column({ nullable: true }) + sentAt: Date; + + @Column({ nullable: true }) + deliveredAt: Date; + + @Column({ nullable: true }) + readAt: Date; + + @Column({ nullable: true }) + errorMessage: string; + + @Column('jsonb', { nullable: true }) + metadata: Record; + + @CreateDateColumn() + createdAt: Date; + + @UpdateDateColumn() + updatedAt: Date; +} \ No newline at end of file diff --git a/src/notifications/entities/user-notification-preferences.entity.ts b/src/notifications/entities/user-notification-preferences.entity.ts new file mode 100644 index 0000000..65bccef --- /dev/null +++ b/src/notifications/entities/user-notification-preferences.entity.ts @@ -0,0 +1,48 @@ +import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn } from 'typeorm'; +import { NotificationEventType } from '../../common/enums/notification-event-type.enum'; +import { NotificationChannel } from '../../common/enums/notification-channel.enum'; + +interface ChannelPreference { + enabled: boolean; +} + +type EventPreferences = { + [key in NotificationEventType]?: { + [NotificationChannel.EMAIL]?: ChannelPreference; + [NotificationChannel.SMS]?: ChannelPreference; + [NotificationChannel.PUSH]?: ChannelPreference; + }; +} + +@Entity('user_notification_preferences') +export class UserNotificationPreferences { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column({ unique: true }) + userId: string; + + @Column({ default: 'en' }) + preferredLanguage: string; + + @Column('jsonb') + preferences: EventPreferences; + + @Column({ nullable: true }) + email: string; + + @Column({ nullable: true }) + phoneNumber: string; + + @Column('jsonb', { default: [] }) + pushDeviceTokens: string[]; + + @Column({ default: true }) + allNotificationsEnabled: boolean; + + @CreateDateColumn() + createdAt: Date; + + @UpdateDateColumn() + updatedAt: Date; +} \ No newline at end of file diff --git a/src/notifications/gateways/notifications.gateway.ts b/src/notifications/gateways/notifications.gateway.ts new file mode 100644 index 0000000..3a034d0 --- /dev/null +++ b/src/notifications/gateways/notifications.gateway.ts @@ -0,0 +1,75 @@ +import { + WebSocketGateway, + WebSocketServer, + OnGatewayConnection, + OnGatewayDisconnect, + SubscribeMessage, +} from '@nestjs/websockets'; +import { Server, Socket } from 'socket.io'; +import { Logger } from '@nestjs/common'; +import { PushService } from '../services/push.service'; +import { JwtService } from '@nestjs/jwt'; +import { ConfigService } from '@nestjs/config'; + +@WebSocketGateway({ + cors: { + origin: '*', + }, +}) +export class NotificationsGateway implements OnGatewayConnection, OnGatewayDisconnect { + @WebSocketServer() + server: Server; + + private readonly logger = new Logger(NotificationsGateway.name); + private userSocketMap: Map = new Map(); // socketId -> userId + + constructor( + private readonly pushService: PushService, + private readonly jwtService: JwtService, + private readonly configService: ConfigService, + ) {} + + async handleConnection(client: Socket) { + try { + const token = client.handshake.auth.token || client.handshake.query.token; + if (!token) { + this.logger.warn(`Client ${client.id} connected without token`); + client.disconnect(); + return; + } + + const payload = this.jwtService.verify(token, { + secret: this.configService.get('JWT_SECRET'), + }); + + const userId = payload.sub; + this.userSocketMap.set(client.id, userId); + this.pushService.registerDevice(userId, client.id); + + this.logger.log(`Client ${client.id} connected for user ${userId}`); + client.emit('connected', { success: true, userId }); + } catch (error) { + this.logger.error(`Failed to authenticate client ${client.id}`, error.stack); + client.disconnect(); + } + } + + handleDisconnect(client: Socket) { + const userId = this.userSocketMap.get(client.id); + if (userId) { + this.pushService.unregisterDevice(userId, client.id); + this.userSocketMap.delete(client.id); + this.logger.log(`Client ${client.id} disconnected for user ${userId}`); + } + } + + @SubscribeMessage('mark_read') + handleMarkRead(client: Socket, notificationId: string) { + this.logger.log(`Notification ${notificationId} marked as read by user`); + client.emit('notification_read', { notificationId }); + } + + getServer(): Server { + return this.server; + } +} \ No newline at end of file diff --git a/src/notifications/notifications.module.ts b/src/notifications/notifications.module.ts new file mode 100644 index 0000000..ef06bd6 --- /dev/null +++ b/src/notifications/notifications.module.ts @@ -0,0 +1,50 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { BullModule } from '@nestjs/bull'; +import { JwtModule } from '@nestjs/jwt'; +import { ConfigModule, ConfigService } from '@nestjs/config'; +import { QueueName } from '../queue/queue.constants'; +import { Notification } from './entities/notification.entity'; +import { UserNotificationPreferences } from './entities/user-notification-preferences.entity'; +import { NotificationsService } from './services/notifications.service'; +import { EmailService } from './services/email.service'; +import { SmsService } from './services/sms.service'; +import { PushService } from './services/push.service'; +import { TemplatesService } from './services/templates.service'; +import { NotificationProcessor } from './services/notification.processor'; +import { NotificationsGateway } from './gateways/notifications.gateway'; +import { NotificationsController } from './controllers/notifications.controller'; +import { NotificationEventListeners } from './usage-examples'; + +@Module({ + imports: [ + TypeOrmModule.forFeature([ + Notification, + UserNotificationPreferences, + ]), + BullModule.registerQueue({ + name: QueueName.NOTIFICATIONS, + }), + JwtModule.registerAsync({ + imports: [ConfigModule], + useFactory: (configService: ConfigService) => ({ + secret: configService.get('JWT_SECRET'), + signOptions: { expiresIn: '1d' }, + }), + inject: [ConfigService], + }), + ], + controllers: [NotificationsController], + providers: [ + NotificationsService, + EmailService, + SmsService, + PushService, + TemplatesService, + NotificationProcessor, + NotificationsGateway, + NotificationEventListeners, + ], + exports: [NotificationsService], +}) +export class NotificationsModule {} \ No newline at end of file diff --git a/src/notifications/services/email.service.ts b/src/notifications/services/email.service.ts new file mode 100644 index 0000000..762c9bb --- /dev/null +++ b/src/notifications/services/email.service.ts @@ -0,0 +1,56 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import * as nodemailer from 'nodemailer'; +import { Notification } from '../entities/notification.entity'; + +@Injectable() +export class EmailService { + private readonly logger = new Logger(EmailService.name); + private transporter: nodemailer.Transporter; + + constructor(private configService: ConfigService) { + this.initializeTransporter(); + } + + private initializeTransporter() { + const smtpConfig = { + host: this.configService.get('SMTP_HOST'), + port: this.configService.get('SMTP_PORT', 587), + secure: this.configService.get('SMTP_SECURE', false), + auth: { + user: this.configService.get('SMTP_USER'), + pass: this.configService.get('SMTP_PASSWORD'), + }, + }; + + this.transporter = nodemailer.createTransport(smtpConfig); + } + + async sendEmail(notification: Notification): Promise { + try { + const mailOptions = { + from: this.configService.get('EMAIL_FROM', 'notifications@swaptrade.com'), + to: notification.recipient, + subject: notification.subject, + html: notification.body, + }; + + const info = await this.transporter.sendMail(mailOptions); + this.logger.log(`Email sent to ${notification.recipient}, messageId: ${info.messageId}`); + return true; + } catch (error) { + this.logger.error(`Failed to send email to ${notification.recipient}`, error.stack); + throw error; + } + } + + async verifyConnection(): Promise { + try { + await this.transporter.verify(); + return true; + } catch (error) { + this.logger.error('SMTP connection failed', error.stack); + return false; + } + } +} \ No newline at end of file diff --git a/src/notifications/services/notification.processor.ts b/src/notifications/services/notification.processor.ts new file mode 100644 index 0000000..fcbd07e --- /dev/null +++ b/src/notifications/services/notification.processor.ts @@ -0,0 +1,103 @@ +import { Process, Processor } from '@nestjs/bull'; +import { Logger } from '@nestjs/common'; +import type { Job } from 'bull'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { QueueName } from '../../queue/queue.constants'; +import { Notification } from '../entities/notification.entity'; +import { EmailService } from './email.service'; +import { SmsService } from './sms.service'; +import { PushService } from './push.service'; +import { NotificationsGateway } from '../gateways/notifications.gateway'; +import { NotificationStatus } from '../../common/enums/notification-status.enum'; +import { NotificationChannel } from '../../common/enums/notification-channel.enum'; + +@Processor(QueueName.NOTIFICATIONS) +export class NotificationProcessor { + private readonly logger = new Logger(NotificationProcessor.name); + private readonly maxRetries = 5; + + constructor( + @InjectRepository(Notification) + private readonly notificationRepository: Repository, + private readonly emailService: EmailService, + private readonly smsService: SmsService, + private readonly pushService: PushService, + private readonly notificationsGateway: NotificationsGateway, + ) {} + + @Process('send') + async processNotification(job: Job<{ notificationId: string }>) { + const { notificationId } = job.data; + const notification = await this.notificationRepository.findOneBy({ id: notificationId }); + + if (!notification) { + this.logger.error(`Notification ${notificationId} not found`); + return; + } + + try { + await this.notificationRepository.update(notificationId, { + status: NotificationStatus.PROCESSING, + }); + + this.logger.log(`Processing notification ${notificationId} of type ${notification.channel}`); + + let success = false; + + switch (notification.channel) { + case NotificationChannel.EMAIL: + success = await this.emailService.sendEmail(notification); + break; + case NotificationChannel.SMS: + success = await this.smsService.sendSms(notification); + break; + case NotificationChannel.PUSH: + success = await this.pushService.sendPushNotification( + notification, + this.notificationsGateway.getServer() + ); + break; + } + + if (success) { + await this.notificationRepository.update(notificationId, { + status: NotificationStatus.SENT, + sentAt: new Date(), + }); + this.logger.log(`Notification ${notificationId} sent successfully`); + } else { + throw new Error(`Failed to send notification through ${notification.channel}`); + } + } catch (error) { + this.logger.error(`Failed to process notification ${notificationId}`, error.stack); + + const currentRetryCount = notification.retryCount; + if (currentRetryCount < this.maxRetries) { + await this.notificationRepository.update(notificationId, { + status: NotificationStatus.RETRYING, + retryCount: currentRetryCount + 1, + lastRetryAt: new Date(), + errorMessage: error.message, + }); + + // Exponential backoff: 1min, 5min, 15min, 1hr, 6hr + const delayMs = this.calculateExponentialBackoff(currentRetryCount); + this.logger.log(`Scheduling retry ${currentRetryCount + 1} for notification ${notificationId} in ${delayMs}ms`); + + throw new Error(`Will retry notification ${notificationId} (attempt ${currentRetryCount + 1}/${this.maxRetries})`); + } else { + await this.notificationRepository.update(notificationId, { + status: NotificationStatus.PERMANENTLY_FAILED, + errorMessage: error.message, + }); + this.logger.error(`Notification ${notificationId} permanently failed after ${this.maxRetries} retries`); + } + } + } + + private calculateExponentialBackoff(retryNumber: number): number { + const delays = [60000, 300000, 900000, 3600000, 21600000]; // 1min, 5min, 15min, 1hr, 6hr + return delays[retryNumber] || delays[delays.length - 1]; + } +} \ No newline at end of file diff --git a/src/notifications/services/notifications.service.ts b/src/notifications/services/notifications.service.ts new file mode 100644 index 0000000..0367dac --- /dev/null +++ b/src/notifications/services/notifications.service.ts @@ -0,0 +1,207 @@ +import { Injectable, Logger, NotFoundException } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { InjectQueue } from '@nestjs/bull'; +import type { Queue } from 'bull'; +import { QueueName } from '../../queue/queue.constants'; +import { Notification } from '../entities/notification.entity'; +import { UserNotificationPreferences } from '../entities/user-notification-preferences.entity'; +import { SendNotificationDto } from '../dto/send-notification.dto'; +import { UpdateNotificationPreferencesDto } from '../dto/update-notification-preferences.dto'; +import { TemplatesService } from './templates.service'; +import { NotificationEventType } from '../../common/enums/notification-event-type.enum'; +import { NotificationChannel } from '../../common/enums/notification-channel.enum'; +import { NotificationStatus } from '../../common/enums/notification-status.enum'; +import { defaultPreferences } from '../config/default-preferences.config'; + +@Injectable() +export class NotificationsService { + private readonly logger = new Logger(NotificationsService.name); + + constructor( + @InjectRepository(Notification) + private readonly notificationRepository: Repository, + @InjectRepository(UserNotificationPreferences) + private readonly preferencesRepository: Repository, + @InjectQueue(QueueName.NOTIFICATIONS) + private readonly notificationsQueue: Queue, + private readonly templatesService: TemplatesService, + ) {} + + async sendNotification(sendNotificationDto: SendNotificationDto) { + const { userId, type, data, language, forceChannels } = sendNotificationDto; + + // Get or create user preferences + let preferences = await this.preferencesRepository.findOneBy({ userId }); + if (!preferences) { + preferences = this.preferencesRepository.create({ + userId, + preferredLanguage: language || 'en', + preferences: defaultPreferences, + allNotificationsEnabled: true, + }); + await this.preferencesRepository.save(preferences); + } + + const userLang = language || preferences.preferredLanguage; + const eventPrefs = preferences.preferences[type]; + + if (!eventPrefs) { + this.logger.warn(`No preferences found for event type ${type}, using defaults`); + return; + } + + if (!preferences.allNotificationsEnabled) { + this.logger.log(`All notifications disabled for user ${userId}, skipping`); + return; + } + + // Process each enabled channel + const channelsToProcess = forceChannels || this.getEnabledChannels(eventPrefs); + + for (const channel of channelsToProcess) { + if (!eventPrefs[channel]?.enabled && !forceChannels?.includes(channel)) { + continue; + } + + // Validate recipient information exists for this channel + const recipient = this.getRecipientForChannel(preferences, channel); + if (!recipient && channel !== NotificationChannel.PUSH) { + this.logger.warn(`No recipient found for channel ${channel} for user ${userId}`); + continue; + } + + // Render template + const { subject, body } = await this.templatesService.renderTemplate( + type, + channel, + data, + userLang, + ); + + // Create notification record + const notification = this.notificationRepository.create({ + userId, + type, + channel, + status: NotificationStatus.PENDING, + data, + recipient: channel === NotificationChannel.PUSH ? undefined : (recipient || undefined), + subject, + body, + retryCount: 0, + }); + + const savedNotification = await this.notificationRepository.save(notification); + + // Add to queue for processing + await this.notificationsQueue.add('send', { + notificationId: savedNotification.id, + }, { + attempts: 5, + backoff: { + type: 'exponential', + delay: 1000, + }, + }); + + this.logger.log(`Notification ${savedNotification.id} queued for ${channel} to user ${userId}`); + } + } + + async getUserPreferences(userId: string): Promise { + let preferences = await this.preferencesRepository.findOneBy({ userId }); + if (!preferences) { + preferences = this.preferencesRepository.create({ + userId, + preferredLanguage: 'en', + preferences: defaultPreferences, + allNotificationsEnabled: true, + }); + await this.preferencesRepository.save(preferences); + } + return preferences; + } + + async updatePreferences( + userId: string, + updateDto: UpdateNotificationPreferencesDto, + ): Promise { + let preferences = await this.preferencesRepository.findOneBy({ userId }); + + if (!preferences) { + preferences = this.preferencesRepository.create({ + userId, + preferredLanguage: 'en', + preferences: defaultPreferences, + allNotificationsEnabled: true, + }); + } + + Object.assign(preferences, updateDto); + + // Merge preferences if they're being updated + if (updateDto.preferences) { + preferences.preferences = { + ...preferences.preferences, + ...updateDto.preferences, + }; + } + + return this.preferencesRepository.save(preferences); + } + + async getUserNotifications( + userId: string, + page: number = 1, + limit: number = 20, + ): Promise<{ notifications: Notification[]; total: number }> { + const [notifications, total] = await this.notificationRepository.findAndCount({ + where: { userId }, + order: { createdAt: 'DESC' }, + skip: (page - 1) * limit, + take: limit, + }); + + return { notifications, total }; + } + + async markAsRead(userId: string, notificationId: string): Promise { + const notification = await this.notificationRepository.findOneBy({ + id: notificationId, + userId + }); + + if (!notification) { + throw new NotFoundException(`Notification ${notificationId} not found`); + } + + notification.status = NotificationStatus.READ; + notification.readAt = new Date(); + + return this.notificationRepository.save(notification); + } + + private getEnabledChannels(eventPrefs: any): NotificationChannel[] { + const channels: NotificationChannel[] = []; + Object.entries(eventPrefs).forEach(([channel, prefs]: [string, any]) => { + if (prefs?.enabled) { + channels.push(channel as NotificationChannel); + } + }); + return channels; + } + + private getRecipientForChannel(preferences: UserNotificationPreferences, channel: NotificationChannel): string | null { + switch (channel) { + case NotificationChannel.EMAIL: + return preferences.email; + case NotificationChannel.SMS: + return preferences.phoneNumber; + case NotificationChannel.PUSH: + return null; // Push uses socket connections + default: + return null; + } + } +} \ No newline at end of file diff --git a/src/notifications/services/push.service.ts b/src/notifications/services/push.service.ts new file mode 100644 index 0000000..b8a2466 --- /dev/null +++ b/src/notifications/services/push.service.ts @@ -0,0 +1,67 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { Notification } from '../entities/notification.entity'; + +@Injectable() +export class PushService { + private readonly logger = new Logger(PushService.name); + private pushSubscriptions: Map> = new Map(); // userId -> set of socketIds + + registerDevice(userId: string, socketId: string) { + if (!this.pushSubscriptions.has(userId)) { + this.pushSubscriptions.set(userId, new Set()); + } + this.pushSubscriptions.get(userId)!.add(socketId); + this.logger.log(`User ${userId} registered for push notifications with socket ${socketId}`); + } + + unregisterDevice(userId: string, socketId: string) { + if (this.pushSubscriptions.has(userId)) { + this.pushSubscriptions.get(userId)!.delete(socketId); + if (this.pushSubscriptions.get(userId)!.size === 0) { + this.pushSubscriptions.delete(userId); + } + this.logger.log(`User ${userId} unregistered from push notifications for socket ${socketId}`); + } + } + + async sendPushNotification(notification: Notification, socketServer?: any): Promise { + try { + const userSubscriptions = this.pushSubscriptions.get(notification.userId); + + if (!userSubscriptions || userSubscriptions.size === 0) { + this.logger.warn(`No active push subscriptions for user ${notification.userId}`); + return false; + } + + if (socketServer) { + const payload = { + id: notification.id, + type: notification.type, + data: notification.data, + createdAt: notification.createdAt, + }; + + userSubscriptions.forEach(socketId => { + socketServer.to(socketId).emit('notification', payload); + }); + + this.logger.log(`Push notification sent to user ${notification.userId} to ${userSubscriptions.size} connected devices`); + return true; + } else { + this.logger.warn('Socket server not available for push notifications'); + return false; + } + } catch (error) { + this.logger.error(`Failed to send push notification to user ${notification.userId}`, error.stack); + throw error; + } + } + + getConnectedUsers(): string[] { + return Array.from(this.pushSubscriptions.keys()); + } + + getActiveConnectionsForUser(userId: string): number { + return this.pushSubscriptions.get(userId)?.size || 0; + } +} \ No newline at end of file diff --git a/src/notifications/services/sms.service.ts b/src/notifications/services/sms.service.ts new file mode 100644 index 0000000..9084d37 --- /dev/null +++ b/src/notifications/services/sms.service.ts @@ -0,0 +1,52 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { Twilio } from 'twilio'; +import { Notification } from '../entities/notification.entity'; + +@Injectable() +export class SmsService { + private readonly logger = new Logger(SmsService.name); + private twilioClient: Twilio; + private fromNumber: string; + + constructor(private configService: ConfigService) { + this.initializeTwilio(); + } + + private initializeTwilio() { + const accountSid = this.configService.get('TWILIO_ACCOUNT_SID'); + const authToken = this.configService.get('TWILIO_AUTH_TOKEN'); + this.fromNumber = this.configService.get('TWILIO_PHONE_NUMBER')!; + + if (accountSid && authToken) { + this.twilioClient = new Twilio(accountSid, authToken); + this.logger.log('Twilio client initialized'); + } else { + this.logger.warn('Twilio credentials not configured, SMS service will be unavailable'); + } + } + + async sendSms(notification: Notification): Promise { + if (!this.twilioClient) { + throw new Error('Twilio client not initialized'); + } + + try { + const message = await this.twilioClient.messages.create({ + body: notification.body, + from: this.fromNumber, + to: notification.recipient, + }); + + this.logger.log(`SMS sent to ${notification.recipient}, messageId: ${message.sid}`); + return true; + } catch (error) { + this.logger.error(`Failed to send SMS to ${notification.recipient}`, error.stack); + throw error; + } + } + + isAvailable(): boolean { + return !!this.twilioClient; + } +} \ No newline at end of file diff --git a/src/notifications/services/templates.service.ts b/src/notifications/services/templates.service.ts new file mode 100644 index 0000000..e324cda --- /dev/null +++ b/src/notifications/services/templates.service.ts @@ -0,0 +1,55 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { I18nService } from 'nestjs-i18n'; +import { NotificationEventType } from '../../common/enums/notification-event-type.enum'; +import { NotificationChannel } from '../../common/enums/notification-channel.enum'; + +interface RenderedTemplate { + subject: string; + body: string; +} + +@Injectable() +export class TemplatesService { + private readonly logger = new Logger(TemplatesService.name); + + constructor(private readonly i18n: I18nService) {} + + async renderTemplate( + eventType: NotificationEventType, + channel: NotificationChannel, + data: Record, + language: string = 'en', + ): Promise { + const translationKey = `notifications.${eventType.toLowerCase()}.${channel.toLowerCase()}`; + + try { + const subject = await this.i18n.translate(`${translationKey}.subject`, { + lang: language, + args: data, + }); + + const body = await this.i18n.translate(`${translationKey}.body`, { + lang: language, + args: data, + }); + + return { subject, body }; + } catch (error) { + this.logger.error(`Failed to render template for ${eventType} in ${language}`, error.stack); + // Fallback to English + const fallbackSubject = await this.i18n.translate(`${translationKey}.subject`, { + lang: 'en', + args: data, + }); + const fallbackBody = await this.i18n.translate(`${translationKey}.body`, { + lang: 'en', + args: data, + }); + return { subject: fallbackSubject, body: fallbackBody }; + } + } + + getSupportedLanguages(): string[] { + return ['en', 'es', 'zh']; + } +} \ No newline at end of file diff --git a/src/notifications/templates/i18n/en/notifications.json b/src/notifications/templates/i18n/en/notifications.json new file mode 100644 index 0000000..1a11d8e --- /dev/null +++ b/src/notifications/templates/i18n/en/notifications.json @@ -0,0 +1,72 @@ +{ + "trade_executed": { + "email": { + "subject": "Your Trade Has Been Executed Successfully", + "body": "

Trade Executed!

Your trade for {{amount}} {{asset}} has been executed at {{price}}.

Total value: {{totalValue}}

" + }, + "sms": { + "subject": "Trade Executed", + "body": "SwapTrade: Your trade for {{amount}} {{asset}} has been executed at ${{price}}. Total: ${{totalValue}}." + }, + "push": { + "subject": "Trade Executed", + "body": "Your {{asset}} trade completed successfully!" + } + }, + "liquidation": { + "email": { + "subject": "URGENT: Position Liquidation Notice", + "body": "

⚠️ Position Liquidated

Your position of {{amount}} {{asset}} has been liquidated at {{price}}.

If you have questions, please contact support immediately." + }, + "sms": { + "subject": "URGENT: Liquidation", + "body": "URGENT SwapTrade: Your {{asset}} position has been liquidated. Check your account now." + }, + "push": { + "subject": "⚠️ Position Liquidated", + "body": "Your {{asset}} position was liquidated. View details in your account." + } + }, + "deposit_received": { + "email": { + "subject": "Deposit Received Successfully", + "body": "

Deposit Confirmed!

We've received your deposit of {{amount}} {{asset}}.

Transaction hash: {{txHash}}

The funds are now available in your account." + }, + "sms": { + "subject": "Deposit Received", + "body": "SwapTrade: Deposit of {{amount}} {{asset}} received! Tx: {{txHash}}. Funds available now." + }, + "push": { + "subject": "Deposit Received", + "body": "{{amount}} {{asset}} deposited to your account!" + } + }, + "withdrawal_completed": { + "email": { + "subject": "Withdrawal Processed Successfully", + "body": "

Withdrawal Complete

Your withdrawal of {{amount}} {{asset}} has been processed.

Destination address: {{address}}

Transaction hash: {{txHash}}

" + }, + "sms": { + "subject": "Withdrawal Complete", + "body": "SwapTrade: Withdrawal of {{amount}} {{asset}} processed. Tx: {{txHash}}" + }, + "push": { + "subject": "Withdrawal Processed", + "body": "{{amount}} {{asset}} withdrawal completed" + } + }, + "security_alert": { + "email": { + "subject": "Security Alert: New Login Detected", + "body": "

⚠️ New Login Detected

A new login was detected on your account from {{ipAddress}} at {{timestamp}}.

If this wasn't you, please secure your account immediately." + }, + "sms": { + "subject": "Security Alert", + "body": "SwapTrade SECURITY: New login from {{ipAddress}}. If not you, reset your password now." + }, + "push": { + "subject": "⚠️ Security Alert", + "body": "New login detected on your account" + } + } +} \ No newline at end of file diff --git a/src/notifications/templates/i18n/es/notifications.json b/src/notifications/templates/i18n/es/notifications.json new file mode 100644 index 0000000..1f692ad --- /dev/null +++ b/src/notifications/templates/i18n/es/notifications.json @@ -0,0 +1,72 @@ +{ + "trade_executed": { + "email": { + "subject": "Tu Operación se Ha Ejecutado Exitosamente", + "body": "

¡Operación Ejecutada!

Tu operación por {{amount}} {{asset}} ha sido ejecutada a {{price}}.

Valor total: {{totalValue}}

" + }, + "sms": { + "subject": "Operación Ejecutada", + "body": "SwapTrade: Tu operación por {{amount}} {{asset}} se ejecutó a ${{price}}. Total: ${{totalValue}}." + }, + "push": { + "subject": "Operación Ejecutada", + "body": "¡Tu operación de {{asset}} se completó exitosamente!" + } + }, + "liquidation": { + "email": { + "subject": "URGENTE: Aviso de Liquidación de Posición", + "body": "

⚠️ Posición Liquidad

Tu posición de {{amount}} {{asset}} ha sido liquidada a {{price}}.

Si tienes preguntas, contacta a soporte inmediatamente." + }, + "sms": { + "subject": "URGENTE: Liquidación", + "body": "URGENTE SwapTrade: Tu posición de {{asset}} ha sido liquidada. Revisa tu cuenta ahora." + }, + "push": { + "subject": "⚠️ Posición Liquidad", + "body": "Tu posición de {{asset}} fue liquidada. Ver detalles en tu cuenta." + } + }, + "deposit_received": { + "email": { + "subject": "Depósito Recibido Exitosamente", + "body": "

¡Depósito Confirmado!

Hemos recibido tu depósito de {{amount}} {{asset}}.

Hash de transacción: {{txHash}}

Los fondos están disponibles en tu cuenta." + }, + "sms": { + "subject": "Depósito Recibido", + "body": "SwapTrade: ¡Depósito de {{amount}} {{asset}} recibido! Tx: {{txHash}}. Fondos disponibles ahora." + }, + "push": { + "subject": "Depósito Recibido", + "body": "¡{{amount}} {{asset}} depositados en tu cuenta!" + } + }, + "withdrawal_completed": { + "email": { + "subject": "Retiro Procesado Exitosamente", + "body": "

Retiro Completado

Tu retiro de {{amount}} {{asset}} ha sido procesado.

Dirección de destino: {{address}}

Hash de transacción: {{txHash}}

" + }, + "sms": { + "subject": "Retiro Completado", + "body": "SwapTrade: Retiro de {{amount}} {{asset}} procesado. Tx: {{txHash}}" + }, + "push": { + "subject": "Retiro Procesado", + "body": "Retiro de {{amount}} {{asset}} completado" + } + }, + "security_alert": { + "email": { + "subject": "Alerta de Seguridad: Nuevo Inicio de Sesión Detectado", + "body": "

⚠️ Nuevo Inicio de Sesión Detectado

Se detectó un nuevo inicio de sesión en tu cuenta desde {{ipAddress}} a las {{timestamp}}.

Si no fuiste tú, por favor asegura tu cuenta inmediatamente." + }, + "sms": { + "subject": "Alerta de Seguridad", + "body": "SwapTrade SEGURIDAD: Nuevo inicio de sesión desde {{ipAddress}}. Si no fuiste tú, restablece tu contraseña ahora." + }, + "push": { + "subject": "⚠️ Alerta de Seguridad", + "body": "Nuevo inicio de sesión detectado en tu cuenta" + } + } +} \ No newline at end of file diff --git a/src/notifications/templates/i18n/zh/notifications.json b/src/notifications/templates/i18n/zh/notifications.json new file mode 100644 index 0000000..e3c351a --- /dev/null +++ b/src/notifications/templates/i18n/zh/notifications.json @@ -0,0 +1,72 @@ +{ + "trade_executed": { + "email": { + "subject": "您的交易已成功执行", + "body": "

交易已执行!

您的{{amount}} {{asset}}交易已以{{price}}的价格执行。

总价值:{{totalValue}}

" + }, + "sms": { + "subject": "交易已执行", + "body": "SwapTrade:您的{{amount}} {{asset}}交易已以${{price}}执行。总计:${{totalValue}}。" + }, + "push": { + "subject": "交易已执行", + "body": "您的{{asset}}交易成功完成!" + } + }, + "liquidation": { + "email": { + "subject": "紧急:仓位清算通知", + "body": "

⚠️ 仓位已清算

您的{{amount}} {{asset}}仓位已以{{price}}的价格清算。

如有疑问,请立即联系客服。" + }, + "sms": { + "subject": "紧急:清算通知", + "body": "紧急SwapTrade:您的{{asset}}仓位已被清算。请立即查看您的账户。" + }, + "push": { + "subject": "⚠️ 仓位已清算", + "body": "您的{{asset}}仓位已被清算。请在账户中查看详情。" + } + }, + "deposit_received": { + "email": { + "subject": "充值已成功到账", + "body": "

充值已确认!

我们已收到您的{{amount}} {{asset}}充值。

交易哈希:{{txHash}}

资金现已在您的账户中可用。" + }, + "sms": { + "subject": "充值已到账", + "body": "SwapTrade:已收到{{amount}} {{asset}}充值!交易号:{{txHash}}。资金现已可用。" + }, + "push": { + "subject": "充值已到账", + "body": "{{amount}} {{asset}}已存入您的账户!" + } + }, + "withdrawal_completed": { + "email": { + "subject": "提现已成功处理", + "body": "

提现完成

您的{{amount}} {{asset}}提现已处理完成。

目标地址:{{address}}

交易哈希:{{txHash}}

" + }, + "sms": { + "subject": "提现完成", + "body": "SwapTrade:{{amount}} {{asset}}提现已处理。交易号:{{txHash}}" + }, + "push": { + "subject": "提现已处理", + "body": "{{amount}} {{asset}}提现完成" + } + }, + "security_alert": { + "email": { + "subject": "安全提醒:检测到新登录", + "body": "

⚠️ 检测到新登录

检测到从{{ipAddress}}在{{timestamp}}登录了您的账户。

如果这不是您本人,请立即保护您的账户安全。" + }, + "sms": { + "subject": "安全提醒", + "body": "SwapTrade安全警告:从{{ipAddress}}检测到新登录。如果不是您,请立即重置密码。" + }, + "push": { + "subject": "⚠️ 安全提醒", + "body": "您的账户检测到新登录" + } + } +} \ No newline at end of file diff --git a/src/notifications/usage-examples.ts b/src/notifications/usage-examples.ts new file mode 100644 index 0000000..02e28c6 --- /dev/null +++ b/src/notifications/usage-examples.ts @@ -0,0 +1,106 @@ +import { Injectable } from '@nestjs/common'; +import { OnEvent } from '@nestjs/event-emitter'; +import { NotificationsService } from './services/notifications.service'; +import { NotificationEventType } from '../common/enums/notification-event-type.enum'; +import { NotificationChannel } from '../common/enums/notification-channel.enum'; + +@Injectable() +export class NotificationEventListeners { + constructor(private readonly notificationsService: NotificationsService) {} + + @OnEvent('trade.executed') + async handleTradeExecuted(payload: { + userId: string; + amount: number; + asset: string; + price: number; + totalValue: number; + }) { + await this.notificationsService.sendNotification({ + userId: payload.userId, + type: NotificationEventType.TRADE_EXECUTED, + data: { + amount: payload.amount, + asset: payload.asset, + price: payload.price, + totalValue: payload.totalValue, + }, + }); + } + + @OnEvent('deposit.received') + async handleDepositReceived(payload: { + userId: string; + amount: number; + asset: string; + txHash: string; + }) { + await this.notificationsService.sendNotification({ + userId: payload.userId, + type: NotificationEventType.DEPOSIT_RECEIVED, + data: { + amount: payload.amount, + asset: payload.asset, + txHash: payload.txHash, + }, + }); + } + + @OnEvent('position.liquidated') + async handleLiquidation(payload: { + userId: string; + amount: number; + asset: string; + price: number; + }) { + // Liquidations are critical - force SMS even if user has it disabled + await this.notificationsService.sendNotification({ + userId: payload.userId, + type: NotificationEventType.LIQUIDATION, + data: { + amount: payload.amount, + asset: payload.asset, + price: payload.price, + }, + forceChannels: [NotificationChannel.EMAIL, NotificationChannel.SMS, NotificationChannel.PUSH], // Always send all channels for liquidations + }); + } + + @OnEvent('withdrawal.completed') + async handleWithdrawalCompleted(payload: { + userId: string; + amount: number; + asset: string; + address: string; + txHash: string; + }) { + await this.notificationsService.sendNotification({ + userId: payload.userId, + type: NotificationEventType.WITHDRAWAL_COMPLETED, + data: { + amount: payload.amount, + asset: payload.asset, + address: payload.address, + txHash: payload.txHash, + }, + }); + } + + @OnEvent('security.login_detected') + async handleSecurityAlert(payload: { + userId: string; + ipAddress: string; + timestamp: string; + }) { + // Security alerts are critical - force all channels + await this.notificationsService.sendNotification({ + userId: payload.userId, + type: NotificationEventType.SECURITY_ALERT, + data: { + ipAddress: payload.ipAddress, + timestamp: payload.timestamp, + }, + forceChannels: [NotificationChannel.EMAIL, NotificationChannel.SMS, NotificationChannel.PUSH], + }); + } +} \ No newline at end of file diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 462b5a9..14090e6 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -21,7 +21,8 @@ import { UserService } from './user.service'; import { UpdateUserDto } from './dto/update-user.dto'; import { UpdateUserStatusDto } from './dto/user-status.dto'; import { PortfolioStatsDto } from './dto/portfolio-stats.dto'; -import { JwtAuthGuard, JwtPayload } from '../auth/guards/jwt-auth.guard'; +import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; +import type { JwtPayload } from '../auth/guards/jwt-auth.guard'; import { CurrentUser } from '../auth/decorators/current-user.decorator'; import { ApiErrorResponses } from '../common/decorators/swagger-error-responses.decorator'; import { AccountStatus } from '../auth/entities/auth.entity'; @@ -145,4 +146,4 @@ export class UserController { ) { return this.userService.deactivate(id, body.reason); } -} +} \ No newline at end of file