From ae9693391b9936b784ca1bd8866e09fd9c74ada7 Mon Sep 17 00:00:00 2001 From: Konstantin Tsabolov <konstantin.tsabolov@spherity.com> Date: Wed, 20 Dec 2023 23:05:58 +0100 Subject: [PATCH] feat: refactor connection manager --- apps/connection-manager/package.json | 53 +- .../connection-manager/src/app.module.spec.ts | 27 - apps/connection-manager/src/app.module.ts | 51 - apps/connection-manager/src/application.ts | 72 ++ .../src/client/config.client.ts | 20 - .../src/client/nats.client.ts | 79 -- .../src/client/rest.client.ts | 16 - .../src/common/constants.ts | 34 +- .../src/common/date.utils.ts | 5 - .../src/common/exception.handler.ts | 42 - .../connection-manager/src/common/response.ts | 6 - apps/connection-manager/src/config/config.ts | 34 - .../src/config/http.config.ts | 6 + .../src/config/nats.config.ts | 6 + .../src/config/ssi.config.ts | 5 + .../src/config/validation.ts | 20 +- .../src/connections/connections.controller.ts | 303 +++++ .../src/connections/connections.module.ts | 10 + .../src/connections/connections.service.ts | 71 ++ .../connections/controller/controller.spec.ts | 754 ----------- .../src/connections/controller/controller.ts | 779 ----------- .../src/connections/dto/block.dto.ts | 12 + .../src/connections/dto/get-by-id.dto.ts | 12 + .../AcceptConnectionInvitationBody.ts | 9 - .../entities/InvitationDto.entity.ts | 21 - .../connectionCreateInvitationDto.entity.ts | 20 - .../entities/connectionStateDto.entity.ts | 51 - .../connectionSubscribeEndPoint.entity.ts | 11 - .../src/connections/entities/entity.ts | 41 - .../src/connections/module.spec.ts | 7 - .../src/connections/module.ts | 35 - .../repository/connection.repository.ts | 97 -- .../scheduler/scheduler.service.ts | 106 -- .../src/connections/services/service.spec.ts | 469 ------- .../src/connections/services/service.ts | 266 ---- .../src/health/health.controller.ts | 42 - .../src/health/health.spec.ts | 26 - .../invitations/dto/receive-invitation.dto.ts | 13 + .../src/invitations/invitations.controller.ts | 158 +++ .../src/invitations/invitations.module.ts | 10 + .../src/invitations/invitations.service.ts | 48 + apps/connection-manager/src/main.ts | 22 +- .../src/middleware/auth.middleware.ts | 86 -- .../src/prisma/prisma.module.spec.ts | 7 - .../src/prisma/prisma.module.ts | 9 - .../src/prisma/prisma.service.ts | 29 - .../src/prisma/schema.prisma | 26 - .../src/utils/exceptionsFilter.ts | 82 -- .../src/utils/logger.spec.ts | 12 - apps/connection-manager/src/utils/logger.ts | 17 - apps/connection-manager/src/utils/nats.ts | 40 - .../src/utils/pagination.spec.ts | 17 - .../src/utils/pagination.ts | 16 - apps/shared/package.json | 14 +- pnpm-lock.yaml | 1135 ++++++++++++++--- 55 files changed, 1689 insertions(+), 3670 deletions(-) delete mode 100644 apps/connection-manager/src/app.module.spec.ts delete mode 100644 apps/connection-manager/src/app.module.ts create mode 100644 apps/connection-manager/src/application.ts delete mode 100644 apps/connection-manager/src/client/config.client.ts delete mode 100644 apps/connection-manager/src/client/nats.client.ts delete mode 100644 apps/connection-manager/src/client/rest.client.ts delete mode 100644 apps/connection-manager/src/common/date.utils.ts delete mode 100644 apps/connection-manager/src/common/exception.handler.ts delete mode 100644 apps/connection-manager/src/common/response.ts delete mode 100644 apps/connection-manager/src/config/config.ts create mode 100644 apps/connection-manager/src/config/http.config.ts create mode 100644 apps/connection-manager/src/config/nats.config.ts create mode 100644 apps/connection-manager/src/config/ssi.config.ts create mode 100644 apps/connection-manager/src/connections/connections.controller.ts create mode 100644 apps/connection-manager/src/connections/connections.module.ts create mode 100644 apps/connection-manager/src/connections/connections.service.ts delete mode 100644 apps/connection-manager/src/connections/controller/controller.spec.ts delete mode 100644 apps/connection-manager/src/connections/controller/controller.ts create mode 100644 apps/connection-manager/src/connections/dto/block.dto.ts create mode 100644 apps/connection-manager/src/connections/dto/get-by-id.dto.ts delete mode 100644 apps/connection-manager/src/connections/entities/AcceptConnectionInvitationBody.ts delete mode 100644 apps/connection-manager/src/connections/entities/InvitationDto.entity.ts delete mode 100644 apps/connection-manager/src/connections/entities/connectionCreateInvitationDto.entity.ts delete mode 100644 apps/connection-manager/src/connections/entities/connectionStateDto.entity.ts delete mode 100644 apps/connection-manager/src/connections/entities/connectionSubscribeEndPoint.entity.ts delete mode 100644 apps/connection-manager/src/connections/entities/entity.ts delete mode 100644 apps/connection-manager/src/connections/module.spec.ts delete mode 100644 apps/connection-manager/src/connections/module.ts delete mode 100644 apps/connection-manager/src/connections/repository/connection.repository.ts delete mode 100644 apps/connection-manager/src/connections/scheduler/scheduler.service.ts delete mode 100644 apps/connection-manager/src/connections/services/service.spec.ts delete mode 100644 apps/connection-manager/src/connections/services/service.ts delete mode 100644 apps/connection-manager/src/health/health.controller.ts delete mode 100644 apps/connection-manager/src/health/health.spec.ts create mode 100644 apps/connection-manager/src/invitations/dto/receive-invitation.dto.ts create mode 100644 apps/connection-manager/src/invitations/invitations.controller.ts create mode 100644 apps/connection-manager/src/invitations/invitations.module.ts create mode 100644 apps/connection-manager/src/invitations/invitations.service.ts delete mode 100644 apps/connection-manager/src/middleware/auth.middleware.ts delete mode 100644 apps/connection-manager/src/prisma/prisma.module.spec.ts delete mode 100644 apps/connection-manager/src/prisma/prisma.module.ts delete mode 100644 apps/connection-manager/src/prisma/prisma.service.ts delete mode 100644 apps/connection-manager/src/prisma/schema.prisma delete mode 100644 apps/connection-manager/src/utils/exceptionsFilter.ts delete mode 100644 apps/connection-manager/src/utils/logger.spec.ts delete mode 100644 apps/connection-manager/src/utils/logger.ts delete mode 100644 apps/connection-manager/src/utils/nats.ts delete mode 100644 apps/connection-manager/src/utils/pagination.spec.ts delete mode 100644 apps/connection-manager/src/utils/pagination.ts diff --git a/apps/connection-manager/package.json b/apps/connection-manager/package.json index 4eacd37..fd4a702 100644 --- a/apps/connection-manager/package.json +++ b/apps/connection-manager/package.json @@ -12,12 +12,7 @@ "build": "nest build", "prebuild:production": "pnpm clean", "build:production": "pnpm prisma:generate && nest build -p tsconfig.production.json", - "prisma:dbpush": "prisma db push --schema=./src/prisma/schema.prisma", - "prisma:generate": "prisma generate --schema=./src/prisma/schema.prisma", - "prisma:migrate": "prisma migrate deploy --schema=./src/prisma/schema.prisma", - "prisma:studio": "prisma studio", - "start": "nest start", - "start:dev": "nest start --watch --preserveWatchOutput", + "start": "nest start --watch --preserveWatchOutput", "test": "jest", "test:watch": "jest --watch", "test:cov": "jest --coverage", @@ -25,53 +20,35 @@ "test:e2e": "jest --config ./test/jest.config.js" }, "dependencies": { - "@elastic/ecs-winston-format": "^1.5.0", - "@nestjs/axios": "^3.0.1", - "@nestjs/common": "^10.2.8", + "@nestjs/common": "^10.3.0", "@nestjs/config": "^3.1.1", - "@nestjs/core": "^10.2.8", - "@nestjs/mapped-types": "^2.0.4", - "@nestjs/microservices": "^10.2.8", - "@nestjs/platform-express": "^10.2.8", + "@nestjs/core": "^10.3.0", + "@nestjs/microservices": "^10.3.0", + "@nestjs/platform-express": "^10.3.0", "@nestjs/schedule": "^4.0.0", - "@nestjs/swagger": "^7.1.16", - "@nestjs/terminus": "^10.1.1", - "@prisma/client": "^5.6.0", + "@nestjs/swagger": "^7.1.17", + "@ocm/shared": "workspace:*", + "class-transformer": "^0.5.1", "class-validator": "^0.14.0", "express": "^4.17.3", "joi": "^17.11.0", - "jsonwebtoken": "^9.0.2", - "jwks-rsa": "^3.1.0", - "moment": "^2.29.4", "nats": "^2.18.0", "reflect-metadata": "^0.1.13", - "rxjs": "^7.8.1", - "winston": "^3.11.0", - "winston-elasticsearch": "^0.17.4" + "rxjs": "^7.8.1" }, "devDependencies": { "@jest/globals": "^29.7.0", "@nestjs/cli": "^10.2.1", "@nestjs/schematics": "^10.0.3", - "@nestjs/testing": "^10.2.8", - "@swc/cli": "^0.1.62", - "@swc/core": "^1.3.96", + "@nestjs/testing": "^10.3.0", + "@swc/cli": "^0.1.63", + "@swc/core": "^1.3.101", "@swc/jest": "^0.2.29", "@types/express": "^4.17.21", - "@types/jest": "27.0.2", - "@types/jsonwebtoken": "^9.0.5", - "@types/node": "^20.9.0", - "@types/simple-oauth2": "^5.0.7", - "@types/supertest": "^2.0.16", - "dotenv-cli": "^7.3.0", + "@types/jest": "29.5.11", + "@types/node": "^20.10.5", "jest": "^29.7.0", - "node-mocks-http": "^1.13.0", - "prisma": "^5.6.0", "rimraf": "^5.0.5", - "source-map-support": "^0.5.21", - "supertest": "^6.3.3", - "swagger-ui-express": "^5.0.0", - "ts-node": "^10.9.1", - "typescript": "^5.2.2" + "typescript": "^5.3.3" } } diff --git a/apps/connection-manager/src/app.module.spec.ts b/apps/connection-manager/src/app.module.spec.ts deleted file mode 100644 index e5e685c..0000000 --- a/apps/connection-manager/src/app.module.spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { INestApplication } from '@nestjs/common'; -import type { TestingModule } from '@nestjs/testing'; - -import { Test } from '@nestjs/testing'; - -import AppModule from './app.module.js'; - -describe('App Module', () => { - let app: INestApplication; - - beforeAll(async () => { - const moduleFixture: TestingModule = await Test.createTestingModule({ - imports: [AppModule], - }).compile(); - - app = moduleFixture.createNestApplication(); - await app.init(); - }); - - it('should work', () => { - expect(true).toBe(true); - }); - - afterAll(async () => { - await app.close(); - }); -}); diff --git a/apps/connection-manager/src/app.module.ts b/apps/connection-manager/src/app.module.ts deleted file mode 100644 index 97bc132..0000000 --- a/apps/connection-manager/src/app.module.ts +++ /dev/null @@ -1,51 +0,0 @@ -import type { MiddlewareConsumer, NestModule } from '@nestjs/common'; - -import { Module, RequestMethod } from '@nestjs/common'; -import { ConfigModule } from '@nestjs/config'; -import { APP_FILTER } from '@nestjs/core'; -import { ScheduleModule } from '@nestjs/schedule'; -import { TerminusModule } from '@nestjs/terminus'; - -import ExceptionHandler from './common/exception.handler.js'; -import config from './config/config.js'; -import validationSchema from './config/validation.js'; -import ConnectionsModule from './connections/module.js'; -import SchedulerService from './connections/scheduler/scheduler.service.js'; -import HealthController from './health/health.controller.js'; -import { AuthMiddleware } from './middleware/auth.middleware.js'; -import PrismaModule from './prisma/prisma.module.js'; - -@Module({ - imports: [ - ScheduleModule.forRoot(), - TerminusModule, - ConfigModule.forRoot({ - isGlobal: true, - load: [config], - validationSchema, - }), - PrismaModule, - ConnectionsModule, - ], - controllers: [HealthController], - providers: [ - { - provide: APP_FILTER, - useClass: ExceptionHandler, - }, - SchedulerService, - ], -}) -export default class AppModule implements NestModule { - // eslint-disable-next-line class-methods-use-this - public configure(consumer: MiddlewareConsumer) { - // eslint-disable-line - consumer - .apply(AuthMiddleware) - .exclude({ - path: 'v1/health', - method: RequestMethod.GET, - }) - .forRoutes('*'); - } -} diff --git a/apps/connection-manager/src/application.ts b/apps/connection-manager/src/application.ts new file mode 100644 index 0000000..575ee56 --- /dev/null +++ b/apps/connection-manager/src/application.ts @@ -0,0 +1,72 @@ +import type { ConfigType } from '@nestjs/config'; + +import { Module } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; +import { RouterModule } from '@nestjs/core'; +import { ClientsModule, Transport } from '@nestjs/microservices'; +import { HealthModule } from '@ocm/shared'; + +import { NATS_CLIENT } from './common/constants.js'; +import { httpConfig } from './config/http.config.js'; +import { natsConfig } from './config/nats.config.js'; +import { ssiConfig } from './config/ssi.config.js'; +import { validationSchema } from './config/validation.js'; +import { ConnectionsModule } from './connections/connections.module.js'; +import { InvitationsModule } from './invitations/invitations.module.js'; + +@Module({ + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + load: [httpConfig, natsConfig, ssiConfig], + cache: true, + expandVariables: true, + validationSchema, + validationOptions: { + allowUnknown: true, + abortEarly: true, + }, + }), + + ClientsModule.registerAsync({ + isGlobal: true, + clients: [ + { + name: NATS_CLIENT, + inject: [natsConfig.KEY], + useFactory: (config: ConfigType<typeof natsConfig>) => ({ + transport: Transport.NATS, + options: { + url: config.url as string, + }, + }), + }, + ], + }), + + HealthModule.registerAsync({ + inject: [natsConfig.KEY], + useFactory: (config: ConfigType<typeof natsConfig>) => { + const options: Parameters<typeof HealthModule.register>[0] = {}; + + if (config.monitoringUrl) { + options.nats = { + monitoringUrl: config.monitoringUrl as string, + }; + } + + return options; + }, + }), + + ConnectionsModule, + InvitationsModule, + + RouterModule.register([ + { module: HealthModule, path: '/health' }, + { module: ConnectionsModule, path: '/connections' }, + { module: InvitationsModule, path: '/invitations' }, + ]), + ], +}) +export class Application {} diff --git a/apps/connection-manager/src/client/config.client.ts b/apps/connection-manager/src/client/config.client.ts deleted file mode 100644 index b40504f..0000000 --- a/apps/connection-manager/src/client/config.client.ts +++ /dev/null @@ -1,20 +0,0 @@ -export default class ConfigClient { - /** - * - * If there is no Limit to check expire till date return false - * @returns Number to calculate end date - */ - public static checkExpireTill(): Date | false { - const days = 2; - const tillDate = new Date(); - tillDate.setDate(tillDate.getDate() - days); - return tillDate; - } - - public static getConnectionExpire(): Date | false { - const min = 30; - const connectionExpire = min * 60 * 1000; - const compareDateTime = new Date(new Date().getTime() - connectionExpire); - return compareDateTime; - } -} diff --git a/apps/connection-manager/src/client/nats.client.ts b/apps/connection-manager/src/client/nats.client.ts deleted file mode 100644 index a982dae..0000000 --- a/apps/connection-manager/src/client/nats.client.ts +++ /dev/null @@ -1,79 +0,0 @@ -import type ResponseType from '../common/response.js'; -import type ConnectionSubscriptionEndpointDto from '../connections/entities/connectionSubscribeEndPoint.entity.js'; - -import { Inject, Injectable } from '@nestjs/common'; -import { ClientProxy } from '@nestjs/microservices'; -import { lastValueFrom } from 'rxjs'; - -import { - Attestation, - NATSServices, - Principal, - ProofManager, -} from '../common/constants.js'; -import logger from '../utils/logger.js'; - -@Injectable() -export default class NatsClientService { - public constructor( - @Inject(NATSServices.SERVICE_NAME) private client: ClientProxy, - ) {} - - public sendConnectionStatusPrincipalManager( - status: string, - connectionId: string, - theirLabel: string, - participantDID: string, - theirDid: string, - ) { - const pattern = { - endpoint: `${Principal.NATS_ENDPOINT}/${Principal.CONNECTION_COMPLETE_STATUS}`, - }; - const payload = { - status, - connectionId, - theirLabel, - participantDID, - theirDid, - }; - logger.info(`before nats call to principal manager ${payload}`); - return lastValueFrom(this.client.send<ResponseType>(pattern, payload)); - } - - public getIssueCredentials(connectionId: string) { - const pattern = { - endpoint: `${Attestation.NATS_ENDPOINT}/${Attestation.GET_ISSUE_CREDENTIALS}`, - }; - const payload = { - connectionId, - }; - return lastValueFrom(this.client.send<ResponseType>(pattern, payload)); - } - - public sendMembershipProofRequestToProofManager(connectionId: string) { - const pattern = { - endpoint: `${ProofManager.NATS_ENDPOINT}/${ProofManager.SEND_MEMBERSHIP_PROOF_REQUEST}`, - }; - const payload = { - connectionId, - }; - return lastValueFrom(this.client.send<ResponseType>(pattern, payload)); - } - - public getPresentProofs(connectionId: string) { - const pattern = { - endpoint: `${ProofManager.NATS_ENDPOINT}/${ProofManager.GET_PRESENT_PROOFS}`, - }; - const payload = { - connectionId, - }; - return lastValueFrom(this.client.send<ResponseType>(pattern, payload)); - } - - public publishConnection(data: ConnectionSubscriptionEndpointDto) { - this.client.emit( - `${NATSServices.SERVICE_NAME}/${NATSServices.CONNECTION_SUBSCRIBER_ENDPOINT}`, - data, - ); - } -} diff --git a/apps/connection-manager/src/client/rest.client.ts b/apps/connection-manager/src/client/rest.client.ts deleted file mode 100644 index 14c1329..0000000 --- a/apps/connection-manager/src/client/rest.client.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { HttpService } from '@nestjs/axios'; -import { Injectable } from '@nestjs/common'; -import { lastValueFrom, map } from 'rxjs'; - -@Injectable() -export default class RestClientService { - public constructor(private readonly httpService: HttpService) {} - - public async post(url: string, payload: object) { - return lastValueFrom( - this.httpService - .post(url, payload) - .pipe(map((response) => response.data)), - ); - } -} diff --git a/apps/connection-manager/src/common/constants.ts b/apps/connection-manager/src/common/constants.ts index c1a9f76..5122ca1 100644 --- a/apps/connection-manager/src/common/constants.ts +++ b/apps/connection-manager/src/common/constants.ts @@ -1,32 +1,2 @@ -export enum NATSServices { - SERVICE_NAME = 'CONNECTION_MANAGER_SERVICE', - CONNECTION_SUBSCRIBER_ENDPOINT = 'ConnectionSubscriberEndpoint', -} - -export enum LoggerConfig { - FILE_PATH = 'logs/log.json', - LOG_DIR = './logs', -} - -export enum Abstraction { - NATS_ENDPOINT = 'SSI_ABSTRACTION_SERVICE', - CONNECTION_STATE_CHANGED = 'ConnectionStateChanged', -} - -export enum Principal { - NATS_ENDPOINT = 'PRINCIPAL_MANAGER_SERVICE', - CONNECTION_COMPLETE_STATUS = 'connectionCompleteStatus', -} - -export enum Attestation { - NATS_ENDPOINT = 'ATTESTATION_MANAGER_SERVICE', - GET_ISSUE_CREDENTIALS = 'getIssueCredentials', -} - -export enum ProofManager { - NATS_ENDPOINT = 'PROOF_MANAGER_SERVICE', - GET_PRESENT_PROOFS = 'getPresentProofs', - SEND_MEMBERSHIP_PROOF_REQUEST = 'sendMembershipProofRequest', -} - -export const RECEIVED_CONNECTION_ALIAS = 'connection-received'; +export const SERVICE_NAME = 'SCHEMA_MANAGER_SERVICE'; +export const NATS_CLIENT = Symbol('NATS_CLIENT'); diff --git a/apps/connection-manager/src/common/date.utils.ts b/apps/connection-manager/src/common/date.utils.ts deleted file mode 100644 index a6d0cac..0000000 --- a/apps/connection-manager/src/common/date.utils.ts +++ /dev/null @@ -1,5 +0,0 @@ -import moment from 'moment'; - -const getDate = () => moment().format('MM-DD-YYYY, h:mm:ss a'); - -export default getDate; diff --git a/apps/connection-manager/src/common/exception.handler.ts b/apps/connection-manager/src/common/exception.handler.ts deleted file mode 100644 index aab81f9..0000000 --- a/apps/connection-manager/src/common/exception.handler.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type ResponseType from './response.js'; -import type { ArgumentsHost, ExceptionFilter } from '@nestjs/common'; - -import { Catch, HttpException, HttpStatus } from '@nestjs/common'; -import { HttpAdapterHost } from '@nestjs/core'; - -@Catch() -export default class ExceptionHandler implements ExceptionFilter { - public constructor(private readonly httpAdapterHost: HttpAdapterHost) {} - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - public catch(exception: any, host: ArgumentsHost): void { - // In certain situations `httpAdapter` might not be available in the - // constructor method, thus we should resolve it here. - const { httpAdapter } = this.httpAdapterHost; - - const ctx = host.switchToHttp(); - const response = ctx.getResponse(); - - let statusCode = HttpStatus.INTERNAL_SERVER_ERROR; - let message = - exception.message.error || exception.message || 'Something went wrong!'; - - if (exception instanceof HttpException) { - const errorResponse: string | object = exception.getResponse(); - - statusCode = exception.getStatus(); - message = - (typeof errorResponse === 'object' && - Reflect.get(errorResponse, 'error')) || - message; - } - - const responseBody: ResponseType = { - statusCode, - message, - error: exception.message, - }; - - httpAdapter.reply(response, responseBody, statusCode); - } -} diff --git a/apps/connection-manager/src/common/response.ts b/apps/connection-manager/src/common/response.ts deleted file mode 100644 index 45f4ccb..0000000 --- a/apps/connection-manager/src/common/response.ts +++ /dev/null @@ -1,6 +0,0 @@ -export default interface ResponseType { - statusCode: number; - message: string; - data?: unknown; - error?: unknown; -} diff --git a/apps/connection-manager/src/config/config.ts b/apps/connection-manager/src/config/config.ts deleted file mode 100644 index b13ab0b..0000000 --- a/apps/connection-manager/src/config/config.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { fileURLToPath } from 'node:url'; - -const parentDirectory = fileURLToPath(new URL('..', import.meta.url)); - -const config = () => ({ - PORT: Number(process.env.PORT), - APP_URL: process.env.CONNECTION_MANAGER_URL, - auth: { - useAuth: process.env.USE_AUTH || 'false', - clientId: process.env.OAUTH_CLIENT_ID, - clientSecret: process.env.OAUTH_CLIENT_SECRET, - tokenUrl: process.env.OAUTH_TOKEN_URL, - }, - nats: { - url: process.env.NATS_URL, - }, - database: { - type: 'postgres', - host: process.env.DB_HOST, - username: process.env.DB_USERNAME, - password: process.env.DB_PASSWORD, - database: process.env.DB_DATABASE, - port: 5432, - synchronize: false, - logging: false, - entities: [`${parentDirectory}/../**/**.model{.ts,.js}`], - DATABASE_URL: process.env.DATABASE_URL, - }, - agent: { - agentUrl: process.env.AGENT_URL, - }, - ECSURL: process.env.ECSURL, -}); -export default config; diff --git a/apps/connection-manager/src/config/http.config.ts b/apps/connection-manager/src/config/http.config.ts new file mode 100644 index 0000000..906f6c8 --- /dev/null +++ b/apps/connection-manager/src/config/http.config.ts @@ -0,0 +1,6 @@ +import { registerAs } from '@nestjs/config'; + +export const httpConfig = registerAs('http', () => ({ + host: process.env.HTTP_HOST, + port: Number(process.env.HTTP_PORT), +})); diff --git a/apps/connection-manager/src/config/nats.config.ts b/apps/connection-manager/src/config/nats.config.ts new file mode 100644 index 0000000..023e923 --- /dev/null +++ b/apps/connection-manager/src/config/nats.config.ts @@ -0,0 +1,6 @@ +import { registerAs } from '@nestjs/config'; + +export const natsConfig = registerAs('nats', () => ({ + url: process.env.NATS_URL, + monitoringUrl: process.env.NATS_MONITORING_URL, +})); diff --git a/apps/connection-manager/src/config/ssi.config.ts b/apps/connection-manager/src/config/ssi.config.ts new file mode 100644 index 0000000..1779919 --- /dev/null +++ b/apps/connection-manager/src/config/ssi.config.ts @@ -0,0 +1,5 @@ +import { registerAs } from '@nestjs/config'; + +export const ssiConfig = registerAs('ssi', () => ({ + agentUrl: process.env.SSI_AGENT_URL, +})); diff --git a/apps/connection-manager/src/config/validation.ts b/apps/connection-manager/src/config/validation.ts index 5973fca..a7fe2f8 100644 --- a/apps/connection-manager/src/config/validation.ts +++ b/apps/connection-manager/src/config/validation.ts @@ -1,15 +1,11 @@ import Joi from 'joi'; -const validationSchema = Joi.object({ - DATABASE_URL: Joi.string().required(), - NATS_URL: Joi.string().required(), - PORT: Joi.number().required(), - CONNECTION_MANAGER_URL: Joi.string().required(), - USE_AUTH: Joi.string(), - AGENT_URL: Joi.string().required(), - OAUTH_CLIENT_ID: Joi.string(), - OAUTH_CLIENT_SECRET: Joi.string(), - OAUTH_TOKEN_URL: Joi.string(), -}); +export const validationSchema = Joi.object({ + HTTP_HOST: Joi.string().default('0.0.0.0'), + HTTP_PORT: Joi.number().default(3000), + + NATS_URL: Joi.string().uri().default('nats://localhost:4222'), + NATS_MONITORING_URL: Joi.string().uri().default('http://localhost:8222'), -export default validationSchema; + SSI_AGENT_URL: Joi.string().default('http://localhost:3010'), +}); diff --git a/apps/connection-manager/src/connections/connections.controller.ts b/apps/connection-manager/src/connections/connections.controller.ts new file mode 100644 index 0000000..f8db8f8 --- /dev/null +++ b/apps/connection-manager/src/connections/connections.controller.ts @@ -0,0 +1,303 @@ +import { + Controller, + Get, + HttpStatus, + Param, + Post, + Query, + UseInterceptors, + UsePipes, + ValidationPipe, +} from '@nestjs/common'; +import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; +import { MultitenancyParams, ResponseFormatInterceptor } from '@ocm/shared'; + +import { ConnectionsService } from './connections.service.js'; +import { BlockParams } from './dto/block.dto.js'; +import { GetByIdParams } from './dto/get-by-id.dto.js'; + +@Controller() +@UsePipes(new ValidationPipe({ transform: true, whitelist: true })) +@UseInterceptors(ResponseFormatInterceptor) +@ApiTags('Connections') +export class ConnectionsController { + public constructor(private readonly service: ConnectionsService) {} + + @Get() + @ApiOperation({ + summary: 'Fetch a list of connections', + description: 'This call provides a list of connections for a given tenant', + }) + @ApiResponse({ + status: HttpStatus.OK, + description: 'Connections fetched successfully', + content: { + 'application/json': { + schema: {}, + examples: { + 'Connections fetched successfully': { + value: { + statusCode: 200, + message: 'Connections fetched successfully', + data: [], + }, + }, + }, + }, + }, + }) + @ApiResponse({ + status: HttpStatus.NOT_FOUND, + description: 'Tenant not found', + content: { + 'application/json': { + schema: {}, + examples: { + 'Tenant not found': { + value: { + statusCode: 404, + message: 'Tenant not found', + data: null, + }, + }, + }, + }, + }, + }) + @ApiResponse({ + status: HttpStatus.INTERNAL_SERVER_ERROR, + description: 'Internal server error', + content: { + 'application/json': { + schema: {}, + examples: { + 'Internal server error': { + value: { + statusCode: 500, + message: 'Internal server error', + data: null, + }, + }, + }, + }, + }, + }) + public getAll( + @Query() { tenantId }: MultitenancyParams, + ): ReturnType<ConnectionsService['getAllConnections']> { + return this.service.getAllConnections(tenantId); + } + + @Get(':connectionId') + @ApiOperation({ + summary: 'Fetch a connection by ID', + description: + 'This call provides a connection for a given tenant and connection ID', + }) + @ApiResponse({ + status: HttpStatus.OK, + description: 'Connection fetched successfully', + content: { + 'application/json': { + schema: {}, + examples: { + 'Connection fetched successfully': { + value: { + statusCode: 200, + message: 'Connection fetched successfully', + data: {}, + }, + }, + }, + }, + }, + }) + @ApiResponse({ + status: HttpStatus.NOT_FOUND, + description: 'Connection not found', + content: { + 'application/json': { + schema: {}, + examples: { + 'Tenant not found': { + value: { + statusCode: 404, + message: 'Tenant not found', + data: null, + }, + }, + 'Connection not found': { + value: { + statusCode: 404, + message: 'Connection not found', + data: null, + }, + }, + }, + }, + }, + }) + @ApiResponse({ + status: HttpStatus.INTERNAL_SERVER_ERROR, + description: 'Internal server error', + content: { + 'application/json': { + schema: {}, + examples: { + 'Internal server error': { + value: { + statusCode: 500, + message: 'Internal server error', + data: null, + }, + }, + }, + }, + }, + }) + public getById( + @Param() { connectionId }: GetByIdParams, + @Query() { tenantId }: MultitenancyParams, + ): ReturnType<ConnectionsService['getConnectionById']> { + return this.service.getConnectionById(tenantId, connectionId); + } + + @Post() + @ApiOperation({ + summary: 'Create a connection', + description: 'This call creates a self connection for a given tenant', + }) + @ApiResponse({ + status: HttpStatus.CREATED, + description: 'Connection created successfully', + content: { + 'application/json': { + schema: {}, + examples: { + 'Connection created successfully': { + value: { + statusCode: 201, + message: 'Connection created successfully', + data: {}, + }, + }, + }, + }, + }, + }) + @ApiResponse({ + status: HttpStatus.NOT_FOUND, + description: 'Tenant not found', + content: { + 'application/json': { + schema: {}, + examples: { + 'Tenant not found': { + value: { + statusCode: 404, + message: 'Tenant not found', + data: null, + }, + }, + }, + }, + }, + }) + @ApiResponse({ + status: HttpStatus.INTERNAL_SERVER_ERROR, + description: 'Internal server error', + content: { + 'application/json': { + schema: {}, + examples: { + 'Internal server error': { + value: { + statusCode: 500, + message: 'Internal server error', + data: null, + }, + }, + }, + }, + }, + }) + public createWithSelf( + @Query() { tenantId }: MultitenancyParams, + ): ReturnType<ConnectionsService['createConnectionWithSelf']> { + return this.service.createConnectionWithSelf(tenantId); + } + + @Post(':idOrDid/block') + @ApiOperation({ + summary: 'Block a connection', + description: + 'This call blocks a connection for a given tenant and connection ID', + }) + @ApiResponse({ + status: HttpStatus.OK, + description: 'Connection blocked successfully', + content: { + 'application/json': { + schema: {}, + examples: { + 'Connection blocked successfully': { + value: { + statusCode: 200, + message: 'Connection blocked successfully', + data: {}, + }, + }, + }, + }, + }, + }) + @ApiResponse({ + status: HttpStatus.NOT_FOUND, + description: 'Connection not found', + content: { + 'application/json': { + schema: {}, + examples: { + 'Tenant not found': { + value: { + statusCode: 404, + message: 'Tenant not found', + data: null, + }, + }, + 'Connection not found': { + value: { + statusCode: 404, + message: 'Connection not found', + data: null, + }, + }, + }, + }, + }, + }) + @ApiResponse({ + status: HttpStatus.INTERNAL_SERVER_ERROR, + description: 'Internal server error', + content: { + 'application/json': { + schema: {}, + examples: { + 'Internal server error': { + value: { + statusCode: 500, + message: 'Internal server error', + data: null, + }, + }, + }, + }, + }, + }) + public block( + @Param() { idOrDid }: BlockParams, + @Query() { tenantId }: MultitenancyParams, + ): ReturnType<ConnectionsService['blockConnection']> { + return this.service.blockConnection(tenantId, idOrDid); + } +} diff --git a/apps/connection-manager/src/connections/connections.module.ts b/apps/connection-manager/src/connections/connections.module.ts new file mode 100644 index 0000000..6231fe9 --- /dev/null +++ b/apps/connection-manager/src/connections/connections.module.ts @@ -0,0 +1,10 @@ +import { Module } from '@nestjs/common'; + +import { ConnectionsController } from './connections.controller.js'; +import { ConnectionsService } from './connections.service.js'; + +@Module({ + providers: [ConnectionsService], + controllers: [ConnectionsController], +}) +export class ConnectionsModule {} diff --git a/apps/connection-manager/src/connections/connections.service.ts b/apps/connection-manager/src/connections/connections.service.ts new file mode 100644 index 0000000..4d969e7 --- /dev/null +++ b/apps/connection-manager/src/connections/connections.service.ts @@ -0,0 +1,71 @@ +import type { + EventDidcommConnectionsBlockInput, + EventDidcommConnectionsGetAllInput, + EventDidcommConnectionsGetByIdInput, +} from '@ocm/shared'; +import type { Observable } from 'rxjs'; + +import { Inject, Injectable } from '@nestjs/common'; +import { ClientProxy } from '@nestjs/microservices'; +import { + EventDidcommConnectionsBlock, + EventDidcommConnectionsCreateWithSelf, + EventDidcommConnectionsGetAll, + EventDidcommConnectionsGetById, +} from '@ocm/shared'; +import { map } from 'rxjs'; + +import { NATS_CLIENT } from '../common/constants.js'; + +@Injectable() +export class ConnectionsService { + public constructor( + @Inject(NATS_CLIENT) private readonly natsClient: ClientProxy, + ) {} + + public getAllConnections( + tenantId: string, + ): Observable<EventDidcommConnectionsGetAll['data']> { + return this.natsClient + .send<EventDidcommConnectionsGetAll, EventDidcommConnectionsGetAllInput>( + EventDidcommConnectionsGetAll.token, + { tenantId }, + ) + .pipe(map((result) => result.data)); + } + + public getConnectionById( + tenantId: string, + id: string, + ): Observable<EventDidcommConnectionsGetById['data']> { + return this.natsClient + .send< + EventDidcommConnectionsGetById, + EventDidcommConnectionsGetByIdInput + >(EventDidcommConnectionsGetById.token, { tenantId, id }) + .pipe(map((result) => result.data)); + } + + public createConnectionWithSelf( + tenantId: string, + ): Observable<EventDidcommConnectionsCreateWithSelf['data']> { + return this.natsClient + .send<EventDidcommConnectionsCreateWithSelf>( + EventDidcommConnectionsCreateWithSelf.token, + { tenantId }, + ) + .pipe(map((result) => result.data)); + } + + public blockConnection( + tenantId: string, + idOrDid: string, + ): Observable<EventDidcommConnectionsBlock['data']> { + return this.natsClient + .send<EventDidcommConnectionsBlock, EventDidcommConnectionsBlockInput>( + EventDidcommConnectionsBlock.token, + { tenantId, idOrDid }, + ) + .pipe(map((result) => result.data)); + } +} diff --git a/apps/connection-manager/src/connections/controller/controller.spec.ts b/apps/connection-manager/src/connections/controller/controller.spec.ts deleted file mode 100644 index f6839dd..0000000 --- a/apps/connection-manager/src/connections/controller/controller.spec.ts +++ /dev/null @@ -1,754 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import type ConnectionStateDto from '../entities/connectionStateDto.entity.js'; -import type { TestingModule } from '@nestjs/testing'; - -import { HttpModule } from '@nestjs/axios'; -import { HttpStatus } from '@nestjs/common'; -import { ConfigModule } from '@nestjs/config'; -import { ClientsModule, Transport } from '@nestjs/microservices'; -import { Test } from '@nestjs/testing'; -import { createResponse } from 'node-mocks-http'; - -import NatsClientService from '../../client/nats.client.js'; -import RestClientService from '../../client/rest.client.js'; -import { NATSServices } from '../../common/constants.js'; -import PrismaService from '../../prisma/prisma.service.js'; -import ConnectionsService from '../services/service.js'; - -import ConnectionsController from './controller.js'; - -describe.skip('ConnectionsController', () => { - let connectionController: ConnectionsController; - let connectionService: ConnectionsService; - // const connection = new ConnectionDto(); - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - imports: [ - ConfigModule, - HttpModule, - ClientsModule.register([ - { - name: NATSServices.SERVICE_NAME, - transport: Transport.NATS, - }, - ]), - ], - controllers: [ConnectionsController], - providers: [ - ConnectionsService, - PrismaService, - NatsClientService, - RestClientService, - ], - exports: [PrismaService], - }).compile(); - connectionService = module.get<ConnectionsService>(ConnectionsService); - connectionController = module.get<ConnectionsController>( - ConnectionsController, - ); - }); - it('should be defined', () => { - expect(connectionController).toBeDefined(); - }); - - describe('Get all connections', () => { - it('should return an array of connection', async () => { - const param = {}; - const serviceResult: any = [ - 1, - { - id: '1a7f0b09-b20e-4971-b9b1-7adde7256bbc', - connectionId: '7b821264-2ae3-4459-b45f-19fa975d91f7', - participantId: '7780cd24-af13-423e-b1ff-ae944ab6fd71', - status: 'trusted', - participantDid: 'SU1SHqQiDcc6gDvqH8wwYF', - theirDid: 'Ax9xMqE89F9LStfGnTpDzg', - theirLabel: 'sagar@getnada.com', - createdDate: '2022-04-18T11:03:58.099Z', - updatedDate: '2022-04-18T11:05:10.004Z', - isActive: true, - }, - ]; - - const result: any = { - count: 1, - records: { - id: '1a7f0b09-b20e-4971-b9b1-7adde7256bbc', - connectionId: '7b821264-2ae3-4459-b45f-19fa975d91f7', - participantId: '7780cd24-af13-423e-b1ff-ae944ab6fd71', - status: 'trusted', - participantDid: 'SU1SHqQiDcc6gDvqH8wwYF', - theirDid: 'Ax9xMqE89F9LStfGnTpDzg', - theirLabel: 'sagar@getnada.com', - createdDate: '2022-04-18T11:03:58.099Z', - updatedDate: '2022-04-18T11:05:10.004Z', - isActive: true, - }, - }; - - const response = createResponse(); - - jest - .spyOn(connectionService, 'findConnections') - .mockResolvedValueOnce(serviceResult); - - const res: any = await connectionController.getConnection( - param, - response, - ); - - const resData = res._getData(); - - expect(res.statusCode).toBe(HttpStatus.OK); - expect(JSON.parse(resData).data).toStrictEqual(result); - }); - - it('If Not provided required parameter response should be bad request', async () => { - const param = {}; - const serviceResult: any = [ - 1, - { - id: '1a7f0b09-b20e-4971-b9b1-7adde7256bbc', - connectionId: '7b821264-2ae3-4459-b45f-19fa975d91f7', - participantId: '7780cd24-af13-423e-b1ff-ae944ab6fd71', - status: 'trusted', - participantDid: 'SU1SHqQiDcc6gDvqH8wwYF', - theirDid: 'Ax9xMqE89F9LStfGnTpDzg', - theirLabel: 'sagar@getnada.com', - createdDate: '2022-04-18T11:03:58.099Z', - updatedDate: '2022-04-18T11:05:10.004Z', - isActive: true, - }, - ]; - - const response = createResponse(); - - jest - .spyOn(connectionService, 'findConnections') - .mockResolvedValueOnce(serviceResult); - - const res = await connectionController.getConnection(param, response); - const resData = res._getData(); - - expect(res.statusCode).toBe(HttpStatus.BAD_REQUEST); - expect(JSON.parse(resData).message).toStrictEqual( - 'Participant ID/ connection ID / participant DID must be provided', - ); - }); - - it('Get connection against connection id', async () => { - const param = { - connectionId: '7b821264-2ae3-4459-b45f-19fa975d91f7', - }; - - const serviceResult: any = { - id: '1a7f0b09-b20e-4971-b9b1-7adde7256bbc', - connectionId: '7b821264-2ae3-4459-b45f-19fa975d91f7', - status: 'trusted', - participantDid: 'SU1SHqQiDcc6gDvqH8wwYF', - theirDid: 'Ax9xMqE89F9LStfGnTpDzg', - theirLabel: 'sagar@getnada.com', - createdDate: '2022-04-18T11:03:58.099Z', - updatedDate: '2022-04-18T11:05:10.004Z', - isActive: true, - }; - - const result: any = { - statusCode: 200, - message: 'Connections fetch successfully', - data: { - records: { - id: '1a7f0b09-b20e-4971-b9b1-7adde7256bbc', - connectionId: '7b821264-2ae3-4459-b45f-19fa975d91f7', - participantId: '7780cd24-af13-423e-b1ff-ae944ab6fd71', - status: 'trusted', - participantDid: 'SU1SHqQiDcc6gDvqH8wwYF', - theirDid: 'Ax9xMqE89F9LStfGnTpDzg', - theirLabel: 'sagar@getnada.com', - createdDate: '2022-04-18T11:03:58.099Z', - updatedDate: '2022-04-18T11:05:10.004Z', - isActive: true, - }, - }, - }; - - const response = createResponse(); - jest - .spyOn(connectionService, 'findConnections') - .mockResolvedValueOnce(serviceResult); - const res: any = await connectionController.getConnection( - param, - response, - ); - // eslint-disable-next-line no-underscore-dangle - const resData = res._getData(); - expect(res.statusCode).toBe(HttpStatus.OK); - expect(JSON.parse(resData)).toStrictEqual(result); - }); - - it('Not fount if data is not present against connection id', async () => { - const param = { - connectionId: '7b821264-2ae3-4459-b45f-19fa975d91f7', - }; - const serviceResult: any = { - id: '1a7f0b09-b20e-4971-b9b1-7adde7256bbc', - connectionId: '7b821264-2ae3-4459-b45f-19fa975d91f7', - status: 'trusted', - participantDid: 'SU1SHqQiDcc6gDvqH8wwYF', - theirDid: 'Ax9xMqE89F9LStfGnTpDzg', - theirLabel: 'sagar@getnada.com', - createdDate: '2022-04-18T11:03:58.099Z', - updatedDate: '2022-04-18T11:05:10.004Z', - isActive: false, - }; - - const result: any = { - statusCode: HttpStatus.NOT_FOUND, - message: 'No Data found', - }; - - const response = createResponse(); - jest - .spyOn(connectionService, 'findConnections') - .mockResolvedValueOnce(serviceResult); - const res: any = await connectionController.getConnection( - param, - response, - ); - // eslint-disable-next-line no-underscore-dangle - const resData = res._getData(); - expect(res.statusCode).toBe(HttpStatus.NOT_FOUND); - expect(JSON.parse(resData)).toStrictEqual(result); - }); - - it('should return an array of connection with status filter', async () => { - const param = {}; - const serviceResult: any = [ - 1, - { - id: '1a7f0b09-b20e-4971-b9b1-7adde7256bbc', - connectionId: '7b821264-2ae3-4459-b45f-19fa975d91f7', - participantId: '7780cd24-af13-423e-b1ff-ae944ab6fd71', - status: 'trusted', - participantDid: 'SU1SHqQiDcc6gDvqH8wwYF', - theirDid: 'Ax9xMqE89F9LStfGnTpDzg', - theirLabel: 'sagar@getnada.com', - createdDate: '2022-04-18T11:03:58.099Z', - updatedDate: '2022-04-18T11:05:10.004Z', - isActive: true, - }, - ]; - - const result: any = { - count: 1, - records: { - id: '1a7f0b09-b20e-4971-b9b1-7adde7256bbc', - connectionId: '7b821264-2ae3-4459-b45f-19fa975d91f7', - participantId: '7780cd24-af13-423e-b1ff-ae944ab6fd71', - status: 'trusted', - participantDid: 'SU1SHqQiDcc6gDvqH8wwYF', - theirDid: 'Ax9xMqE89F9LStfGnTpDzg', - theirLabel: 'sagar@getnada.com', - createdDate: '2022-04-18T11:03:58.099Z', - updatedDate: '2022-04-18T11:05:10.004Z', - isActive: true, - }, - }; - - const response = createResponse(); - jest - .spyOn(connectionService, 'findConnections') - .mockResolvedValueOnce(serviceResult); - const res: any = await connectionController.getConnection( - param, - response, - ); - // eslint-disable-next-line no-underscore-dangle - const resData = res._getData(); - expect(res.statusCode).toBe(HttpStatus.OK); - expect(JSON.parse(resData).data).toStrictEqual(result); - }); - }); - - describe('Connection webhook calls', () => { - it('Create connection webhook call', async () => { - const webHook: ConnectionStateDto = { - _tags: {}, - metadata: {}, - id: '7edc871d-9fa3-4f30-8763-59c80bf346f5', - createdAt: '2022-04-21T10:52:27.151Z', - did: 'DD8Aue5tuohjBaCLM9GMU7', - didDoc: { - '@context': 'https://w3id.org/did/v1', - publicKey: [ - [ - { - id: 'C1buxAXWiisjFpVVyUGM5D#1', - controller: 'C1buxAXWiisjFpVVyUGM5D', - type: 'Ed25519VerificationKey2018', - publicKeyBase58: '714U4GdQqyeqhCANgJmTrGqUPg4QTGuEhJcEGYAvEH1Y', - }, - ], - ], - service: [ - { - id: 'C1buxAXWiisjFpVVyUGM5D#IndyAgentService', - serviceEndpoint: 'http://localhost:4011', - type: 'IndyAgent', - priority: 0, - recipientKeys: ['714U4GdQqyeqhCANgJmTrGqUPg4QTGuEhJcEGYAvEH1Y'], - routingKeys: [], - }, - ], - authentication: [[Object]], - id: 'DD8Aue5tuohjBaCLM9GMU7', - }, - theirDid: '', - theirLabel: '', - verkey: '7exBgFhenY8hqBwBF56D8sp6akLstqXxS1MUUCpDErvX', - state: 'invited', - role: 'inviter', - alias: 'member', - invitation: { - '@type': 'https://didcomm.org/connections/1.0/invitation', - '@id': '8578735f-eef8-4748-b791-ba2f8f7002e2', - label: 'State_University', - recipientKeys: ['7exBgFhenY8hqBwBF56D8sp6akLstqXxS1MUUCpDErvX'], - serviceEndpoint: 'http://localhost:4017', - routingKeys: [], - }, - multiUseInvitation: false, - }; - const serviceResult: any = {}; - jest - .spyOn(connectionService, 'createConnections') - .mockResolvedValueOnce(serviceResult); - const res: any = await connectionController.createConnection({ - body: webHook, - }); - - expect(res.statusCode).toBe(HttpStatus.CREATED); - // expect(JSON.parse(resData).data).toStrictEqual(result); - }); - - it('Update connection webhook call -> member flow', async () => { - const webHook: ConnectionStateDto = { - _tags: {}, - metadata: {}, - id: '72534911-9be0-4e3f-8539-2a8a09e4e409', - createdAt: '2022-04-21T10:52:27.151Z', - did: 'DD8Aue5tuohjBaCLM9GMU7', - didDoc: { - '@context': 'https://w3id.org/did/v1', - publicKey: [ - [ - { - id: 'C1buxAXWiisjFpVVyUGM5D#1', - controller: 'C1buxAXWiisjFpVVyUGM5D', - type: 'Ed25519VerificationKey2018', - publicKeyBase58: '714U4GdQqyeqhCANgJmTrGqUPg4QTGuEhJcEGYAvEH1Y', - }, - ], - ], - service: [ - { - id: 'C1buxAXWiisjFpVVyUGM5D#IndyAgentService', - serviceEndpoint: 'http://localhost:4011', - type: 'IndyAgent', - priority: 0, - recipientKeys: ['714U4GdQqyeqhCANgJmTrGqUPg4QTGuEhJcEGYAvEH1Y'], - routingKeys: [], - }, - ], - authentication: [[Object]], - id: 'DD8Aue5tuohjBaCLM9GMU7', - }, - theirDid: '', - theirLabel: '', - verkey: '7exBgFhenY8hqBwBF56D8sp6akLstqXxS1MUUCpDErvX', - state: 'complete', - role: 'inviter', - alias: 'member', - invitation: { - '@type': 'https://didcomm.org/connections/1.0/invitation', - '@id': '8578735f-eef8-4748-b791-ba2f8f7002e2', - label: 'State_University', - recipientKeys: ['7exBgFhenY8hqBwBF56D8sp6akLstqXxS1MUUCpDErvX'], - serviceEndpoint: 'http://localhost:4017', - routingKeys: [], - }, - multiUseInvitation: false, - }; - - const restConnection: any = { - id: '29701e41-60e8-4fca-8504-ea3bcefa6486', - connectionId: '72534911-9be0-4e3f-8539-2a8a09e4e409', - participantId: '662dc769-a4de-4c95-934c-f6dab8cf432c', - status: 'trusted', - participantDid: 'PyLDJRKzmKmJShyEtjC4AQ', - theirDid: 'UgR1Rrp6p3VJGwLFZnBdwB', - theirLabel: 'Attest12', - createdDate: '2022-04-15T11:30:04.660Z', - updatedDate: '2022-04-15T11:36:58.560Z', - isActive: true, - }; - const serviceResult: any = {}; - jest - .spyOn(connectionService, 'updateStatusByConnectionId') - .mockResolvedValueOnce(serviceResult); - - jest - .spyOn(connectionService, 'getConnectionByID') - .mockResolvedValueOnce(restConnection); - const res: any = await connectionController.createConnection({ - body: webHook, - }); - - expect(res.statusCode).toBe(HttpStatus.OK); - // expect(JSON.parse(resData).data).toStrictEqual(result); - }); - - it('Update connection webhook call -> subscriber flow', async () => { - const webHook: ConnectionStateDto = { - _tags: {}, - metadata: {}, - id: '72534911-9be0-4e3f-8539-2a8a09e4e409', - createdAt: '2022-04-21T10:52:27.151Z', - did: 'DD8Aue5tuohjBaCLM9GMU7', - didDoc: { - '@context': 'https://w3id.org/did/v1', - publicKey: [ - [ - { - id: 'C1buxAXWiisjFpVVyUGM5D#1', - controller: 'C1buxAXWiisjFpVVyUGM5D', - type: 'Ed25519VerificationKey2018', - publicKeyBase58: '714U4GdQqyeqhCANgJmTrGqUPg4QTGuEhJcEGYAvEH1Y', - }, - ], - ], - service: [ - { - id: 'C1buxAXWiisjFpVVyUGM5D#IndyAgentService', - serviceEndpoint: 'http://localhost:4011', - type: 'IndyAgent', - priority: 0, - recipientKeys: ['714U4GdQqyeqhCANgJmTrGqUPg4QTGuEhJcEGYAvEH1Y'], - routingKeys: [], - }, - ], - authentication: [[Object]], - id: 'DD8Aue5tuohjBaCLM9GMU7', - }, - theirDid: '', - theirLabel: '', - verkey: '7exBgFhenY8hqBwBF56D8sp6akLstqXxS1MUUCpDErvX', - state: 'complete', - role: 'inviter', - alias: 'subscriber', - invitation: { - '@type': 'https://didcomm.org/connections/1.0/invitation', - '@id': '8578735f-eef8-4748-b791-ba2f8f7002e2', - label: 'State_University', - recipientKeys: ['7exBgFhenY8hqBwBF56D8sp6akLstqXxS1MUUCpDErvX'], - serviceEndpoint: 'http://localhost:4017', - routingKeys: [], - }, - multiUseInvitation: false, - }; - - const restConnection: any = { - id: '29701e41-60e8-4fca-8504-ea3bcefa6486', - connectionId: '72534911-9be0-4e3f-8539-2a8a09e4e409', - participantId: '662dc769-a4de-4c95-934c-f6dab8cf432c', - status: 'trusted', - participantDid: 'PyLDJRKzmKmJShyEtjC4AQ', - theirDid: 'UgR1Rrp6p3VJGwLFZnBdwB', - theirLabel: 'Attest12', - createdDate: '2022-04-15T11:30:04.660Z', - updatedDate: '2022-04-15T11:36:58.560Z', - isActive: true, - }; - const serviceResult: any = {}; - jest - .spyOn(connectionService, 'updateStatusByConnectionId') - .mockResolvedValueOnce(serviceResult); - - jest - .spyOn(connectionService, 'getConnectionByID') - .mockResolvedValueOnce(restConnection); - const res: any = await connectionController.createConnection({ - body: webHook, - }); - - expect(res.statusCode).toBe(HttpStatus.OK); - // expect(JSON.parse(resData).data).toStrictEqual(result); - }); - - it('Connection webhook call with wrong role', async () => { - const webHook: ConnectionStateDto = { - _tags: {}, - metadata: {}, - id: '72534911-9be0-4e3f-8539-2a8a09e4e409', - createdAt: '2022-04-21T10:52:27.151Z', - did: 'DD8Aue5tuohjBaCLM9GMU7', - didDoc: { - '@context': 'https://w3id.org/did/v1', - publicKey: [ - [ - { - id: 'C1buxAXWiisjFpVVyUGM5D#1', - controller: 'C1buxAXWiisjFpVVyUGM5D', - type: 'Ed25519VerificationKey2018', - publicKeyBase58: '714U4GdQqyeqhCANgJmTrGqUPg4QTGuEhJcEGYAvEH1Y', - }, - ], - ], - service: [ - { - id: 'C1buxAXWiisjFpVVyUGM5D#IndyAgentService', - serviceEndpoint: 'http://localhost:4011', - type: 'IndyAgent', - priority: 0, - recipientKeys: ['714U4GdQqyeqhCANgJmTrGqUPg4QTGuEhJcEGYAvEH1Y'], - routingKeys: [], - }, - ], - authentication: [[Object]], - id: 'DD8Aue5tuohjBaCLM9GMU7', - }, - theirDid: '', - theirLabel: '', - verkey: '7exBgFhenY8hqBwBF56D8sp6akLstqXxS1MUUCpDErvX', - state: 'complete', - role: 'invitee', - alias: 'subscriber', - invitation: { - '@type': 'https://didcomm.org/connections/1.0/invitation', - '@id': '8578735f-eef8-4748-b791-ba2f8f7002e2', - label: 'State_University', - recipientKeys: ['7exBgFhenY8hqBwBF56D8sp6akLstqXxS1MUUCpDErvX'], - serviceEndpoint: 'http://localhost:4017', - routingKeys: [], - }, - multiUseInvitation: false, - }; - - const restConnection = { - id: '29701e41-60e8-4fca-8504-ea3bcefa6486', - connectionId: '72534911-9be0-4e3f-8539-2a8a09e4e409', - participantId: '662dc769-a4de-4c95-934c-f6dab8cf432c', - status: 'trusted', - participantDid: 'PyLDJRKzmKmJShyEtjC4AQ', - theirDid: 'UgR1Rrp6p3VJGwLFZnBdwB', - theirLabel: 'Attest12', - createdDate: '2022-04-15T11:30:04.660Z', - updatedDate: '2022-04-15T11:36:58.560Z', - isActive: true, - }; - const serviceResult = {}; - - jest - .spyOn(connectionService, 'updateStatusByConnectionId') - .mockResolvedValueOnce(serviceResult); - - jest - .spyOn(connectionService, 'getConnectionByID') - .mockResolvedValueOnce(restConnection); - const res = await connectionController.createConnection({ - body: webHook, - }); - - expect(res.statusCode).toBe(HttpStatus.BAD_REQUEST); - // expect(JSON.parse(resData).data).toStrictEqual(result); - }); - }); - - describe('Get invitation URL', () => { - it('Get Member invitation URL', async () => { - const body = { - autoAcceptConnection: true, - }; - const query = { - participantId: '7780cd24-af13-423e-b1ff-ae944ab6fd71', - process: 'member', - }; - const serviceResult: any = { - invitationUrl: - 'http://localhost:4005?c_i=eyJAdHlwZSI6ImRpZDpzb3Y6QnpDYnNOWWhNcmpIaXFaRFRVQVNIZztzcGVjL2Nvbm5lY3Rpb25zLzEuMC9pbnZpdGF0aW9uIiwiQGlkIjoiYWMzYjE0NjktY2Y0Ni00M2ZjLWE4M2EtZGNmZjJjMDA1YjRlIiwibGFiZWwiOiJ0ZWNobmljYV9jb3JwIiwicmVjaXBpZW50S2V5cyI6WyI1bml1NWZmZmVnYkZlS2F3bU5OblRBTEpzaHB1cXpjRm5CUGpBOFFWU2dtWCJdLCJzZXJ2aWNlRW5kcG9pbnQiOiJodHRwOi8vMy4xMTEuNzcuMzg6NDAwNSIsInJvdXRpbmdLZXlzIjpbXX0', - invitation: { - '@type': - 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/invitation', - '@id': 'ac3b1469-cf46-43fc-a83a-dcff2c005b4e', - label: 'technica_corp', - recipientKeys: ['5niu5fffegbFeKawmNNnTALJshpuqzcFnBPjA8QVSgmX'], - serviceEndpoint: 'http://localhost:4005', - routingKeys: [], - }, - connection: { - _tags: {}, - metadata: {}, - id: 'c1d73d9e-6988-4c84-9ebc-068c265d2fb6', - createdAt: '2022-04-21T10:52:18.161Z', - did: '9nYw7CSdHPqXf6ayfA7Wo2', - didDoc: { - '@context': 'https://w3id.org/did/v1', - publicKey: [ - { - id: '9nYw7CSdHPqXf6ayfA7Wo2#1', - controller: '9nYw7CSdHPqXf6ayfA7Wo2', - type: 'Ed25519VerificationKey2018', - publicKeyBase58: '5niu5fffegbFeKawmNNnTALJshpuqzcFnBPjA8QVSgmX', - }, - ], - service: [ - { - id: '9nYw7CSdHPqXf6ayfA7Wo2#In7780cd24-af13-423e-b1ff-ae944ab6fd71dyAgentService', - serviceEndpoint: 'http://localhost:4005', - type: 'IndyAgent', - priority: 0, - recipientKeys: ['5niu5fffegbFeKawmNNnTALJshpuqzcFnBPjA8QVSgmX'], - routingKeys: [], - }, - ], - authentication: [ - { - publicKey: '9nYw7CSdHPqXf6ayfA7Wo2#1', - type: 'Ed25519SignatureAuthentication2018', - }, - ], - id: '9nYw7CSdHPqXf6ayfA7Wo2', - }, - verkey: '5niu5fffegbFeKawmNNnTALJshpuqzcFnBPjA8QVSgmX', - state: 'invited', - role: 'inviter', - alias: 'member', - autoAcceptConnection: true, - invitation: { - '@type': 'https://didcomm.org/connections/1.0/invitation', - '@id': 'ac3b1469-cf46-43fc-a83a-dcff2c005b4e', - label: 'technica_corp', - recipientKeys: ['5niu5fffegbFeKawmNNnTALJshpuqzcFnBPjA8QVSgmX'], - serviceEndpoint: 'http://localhost:4005', - routingKeys: [], - }, - multiUseInvitation: false, - }, - }; - - const result: any = { - statusCode: 200, - message: 'Connection created successfully', - data: { - invitationUrl: - 'http://localhost:4005?c_i=eyJAdHlwZSI6ImRpZDpzb3Y6QnpDYnNOWWhNcmpIaXFaRFRVQVNIZztzcGVjL2Nvbm5lY3Rpb25zLzEuMC9pbnZpdGF0aW9uIiwiQGlkIjoiYWMzYjE0NjktY2Y0Ni00M2ZjLWE4M2EtZGNmZjJjMDA1YjRlIiwibGFiZWwiOiJ0ZWNobmljYV9jb3JwIiwicmVjaXBpZW50S2V5cyI6WyI1bml1NWZmZmVnYkZlS2F3bU5OblRBTEpzaHB1cXpjRm5CUGpBOFFWU2dtWCJdLCJzZXJ2aWNlRW5kcG9pbnQiOiJodHRwOi8vMy4xMTEuNzcuMzg6NDAwNSIsInJvdXRpbmdLZXlzIjpbXX0', - invitation: { - '@type': - 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/invitation', - '@id': 'ac3b1469-cf46-43fc-a83a-dcff2c005b4e', - label: 'technica_corp', - recipientKeys: ['5niu5fffegbFeKawmNNnTALJshpuqzcFnBPjA8QVSgmX'], - serviceEndpoint: 'http://localhost:4005', - routingKeys: [], - }, - connection: { - _tags: {}, - metadata: {}, - id: 'c1d73d9e-6988-4c84-9ebc-068c265d2fb6', - createdAt: '2022-04-21T10:52:18.161Z', - did: '9nYw7CSdHPqXf6ayfA7Wo2', - didDoc: { - '@context': 'https://w3id.org/did/v1', - publicKey: [ - { - id: '9nYw7CSdHPqXf6ayfA7Wo2#1', - controller: '9nYw7CSdHPqXf6ayfA7Wo2', - type: 'Ed25519VerificationKey2018', - publicKeyBase58: - '5niu5fffegbFeKawmNNnTALJshpuqzcFnBPjA8QVSgmX', - }, - ], - service: [ - { - id: '9nYw7CSdHPqXf6ayfA7Wo2#In7780cd24-af13-423e-b1ff-ae944ab6fd71dyAgentService', - serviceEndpoint: 'http://localhost:4005', - type: 'IndyAgent', - priority: 0, - recipientKeys: [ - '5niu5fffegbFeKawmNNnTALJshpuqzcFnBPjA8QVSgmX', - ], - routingKeys: [], - }, - ], - authentication: [ - { - publicKey: '9nYw7CSdHPqXf6ayfA7Wo2#1', - type: 'Ed25519SignatureAuthentication2018', - }, - ], - id: '9nYw7CSdHPqXf6ayfA7Wo2', - }, - verkey: '5niu5fffegbFeKawmNNnTALJshpuqzcFnBPjA8QVSgmX', - state: 'invited', - role: 'inviter', - alias: 'member', - autoAcceptConnection: true, - invitation: { - '@type': 'https://didcomm.org/connections/1.0/invitation', - '@id': 'ac3b1469-cf46-43fc-a83a-dcff2c005b4e', - label: 'technica_corp', - recipientKeys: ['5niu5fffegbFeKawmNNnTALJshpuqzcFnBPjA8QVSgmX'], - serviceEndpoint: 'http://localhost:4005', - routingKeys: [], - }, - multiUseInvitation: false, - }, - }, - }; - - const response = createResponse(); - jest - .spyOn(connectionService, 'createInvitationURL') - .mockResolvedValueOnce(serviceResult); - const res: any = await connectionController.createConnectionInvitation( - body, - query, - response, - ); - // eslint-disable-next-line no-underscore-dangle - const resData = res._getData(); - expect(res.statusCode).toBe(HttpStatus.OK); - expect(resData).toStrictEqual(result); - }); - - it('Get Member invitation URL-> Agent is not present', async () => { - const body = { - autoAcceptConnection: true, - }; - const query = { - participantId: '7780cd24-af13-423e-b1ff-ae944ab6fd71', - process: 'member', - }; - const serviceResult: any = undefined; - - const result: any = { - statusCode: HttpStatus.NOT_FOUND, - message: 'Agent Data not found.', - }; - - const response = createResponse(); - jest - .spyOn(connectionService, 'createInvitationURL') - .mockResolvedValueOnce(serviceResult); - const res: any = await connectionController.createConnectionInvitation( - body, - query, - response, - ); - // eslint-disable-next-line no-underscore-dangle - const resData = res._getData(); - expect(res.statusCode).toBe(HttpStatus.NOT_FOUND); - expect(resData).toStrictEqual(result); - }); - }); -}); diff --git a/apps/connection-manager/src/connections/controller/controller.ts b/apps/connection-manager/src/connections/controller/controller.ts deleted file mode 100644 index 0dc1b2d..0000000 --- a/apps/connection-manager/src/connections/controller/controller.ts +++ /dev/null @@ -1,779 +0,0 @@ -import type ResponseType from '../../common/response.js'; -import type ConnectionStateDto from '../entities/connectionStateDto.entity.js'; -import type ConnectionSubscriptionEndpointDto from '../entities/connectionSubscribeEndPoint.entity.js'; -import type ConnectionDto from '../entities/entity.js'; -// eslint-disable-next-line @typescript-eslint/consistent-type-imports -import type { Response } from 'express'; - -import { - Body, - Controller, - Get, - HttpStatus, - Param, - Post, - Query, - Res, - Version, -} from '@nestjs/common'; -import { MessagePattern } from '@nestjs/microservices'; -import { - ApiBody, - ApiExcludeEndpoint, - ApiOperation, - ApiQuery, - ApiResponse, - ApiTags, -} from '@nestjs/swagger'; - -import { - Abstraction, - NATSServices, - RECEIVED_CONNECTION_ALIAS, -} from '../../common/constants.js'; -import logger from '../../utils/logger.js'; -import AcceptConnectionInvitationBody from '../entities/AcceptConnectionInvitationBody.js'; -import ConnectionCreateInvitationDto from '../entities/connectionCreateInvitationDto.entity.js'; -import ConnectionsService from '../services/service.js'; - -@ApiTags('Connections') -@Controller() -export default class ConnectionsController { - public constructor(private readonly connectionsService: ConnectionsService) {} - - @MessagePattern({ - endpoint: `${Abstraction.NATS_ENDPOINT}/${Abstraction.CONNECTION_STATE_CHANGED}`, - }) - public async createConnection(body: { - connectionRecord: ConnectionStateDto; - }) { - const connection = body.connectionRecord; - - const connectionObj: ConnectionDto = { - connectionId: connection.id ? connection.id : '', - status: connection.state ? connection.state : '', - participantDid: connection.did ? connection.did : '', - theirDid: connection.theirDid ? connection.theirDid : '', - theirLabel: connection.theirLabel ? connection.theirLabel : '', - isReceived: connection.alias === RECEIVED_CONNECTION_ALIAS, - }; - - /** - * Sent Connection updates to subscriber - */ - const connectionSubscriptionEndpointDto: ConnectionSubscriptionEndpointDto = - { - connectionId: connectionObj.connectionId, - status: connectionObj.status, - }; - this.connectionsService.publishConnectionSubscriberEndpoint( - connectionSubscriptionEndpointDto, - ); - - if (connection.state === ConnectionsService.status.INVITED) { - connectionObj.invitation = { - serviceEndpoint: connection.invitation.serviceEndpoint, - }; - const res: ResponseType = { - statusCode: HttpStatus.CREATED, - message: 'Connection established successfully', - data: await this.connectionsService.createConnections(connectionObj), - }; - return res; - } - if (connection.state === ConnectionsService.status.COMPLETE) { - logger.info('connection is in complete state'); - if ( - connection.alias === RECEIVED_CONNECTION_ALIAS || - connection.alias === ConnectionsService.connectionAlias.TRUST - ) { - connectionObj.status = ConnectionsService.status.TRUSTED; - } else { - const resConnection = await this.connectionsService.getConnectionByID( - connection.id, - ); - - if (resConnection) { - if (connection.alias === ConnectionsService.connectionAlias.MEMBER) { - logger.info( - `connection.alias ===${ConnectionsService.connectionAlias.MEMBER}`, - ); - await this.connectionsService.sendConnectionStatusToPrincipal( - connection.state, - connection.id, - connection.theirLabel, - connection.did, - connection.theirDid, - ); - } - - if ( - connection.alias === ConnectionsService.connectionAlias.SUBSCRIBER - ) { - await this.connectionsService.sendMembershipProofRequestToProofManager( - connection.id, - ); - } - } - } - } - - const res: ResponseType = { - statusCode: HttpStatus.OK, - message: 'Connection status Updated successfully', - data: await this.connectionsService.updateStatusByConnectionId( - connectionObj, - ), - }; - - return res; - } - - @Version(['1']) - @ApiBody({ type: ConnectionCreateInvitationDto }) - @Post('invitation-url') - @ApiOperation({ - summary: 'Create new connection invitation', - description: - "This call provides the capability to create new connection invitation by providing alias parameter for taht connection in the body of request. Alias can be one of value: trust/subscriber/trust. This call returns an object contains three fields. invitationUrl, invitationUrlShort, invitation object and connection object. You can use invitationUrlShort or invitationUrl to create QR code which can be scanned by PCM. It's better to use invitationUrlShort because long string of invitationUrl replaced with short id and QR code can be displayed properly", - }) - @ApiResponse({ - status: HttpStatus.OK, - description: 'Connection created successfully', - content: { - 'application/json': { - schema: {}, - examples: { - 'Connection created successfully': { - value: { - statusCode: 200, - message: 'Connection created successfully', - data: { - invitationUrl: - 'https://serviceEndpointUrl.com:443/ocm/didcomm?c_i=eyJAdHlwZSI6Imh0dHBzOi', - invitation: { - '@type': 'https://didcomm.org/connections/1.0/invitation', - '@id': 'efe3fe97', - label: 'ssi-abstraction-agent', - recipientKeys: ['8iT6AAmbj9P'], - serviceEndpoint: - 'https://serviceEndpointUrl.com:443/ocm/didcomm', - routingKeys: [], - }, - connection: { - _tags: {}, - metadata: {}, - id: '507de3ab', - createdAt: '1970-01-01T00:00:00.358Z', - did: 'F9xYT1m', - didDoc: { - '@context': 'https://w3id.org/did/v1', - publicKey: [ - { - id: 'F9xYT1m', - controller: 'F9xYT1m', - type: 'Ed25519VerificationKey2018', - publicKeyBase58: '8iT6AAmbj9P', - }, - ], - service: [ - { - id: 'F9xYT1m#IndyAgentService', - serviceEndpoint: - 'https://serviceEndpointUrl.com:443/ocm/didcomm', - type: 'IndyAgent', - priority: 0, - recipientKeys: ['8iT6AAmbj9P'], - routingKeys: [], - }, - ], - authentication: [ - { - publicKey: 'F9xYT1m', - type: 'Ed25519SignatureAuthentication2018', - }, - ], - id: 'F9xYT1m', - }, - verkey: '8iT6AAmbj9P', - state: 'invited', - role: 'inviter', - alias: 'trust', - invitation: { - '@type': 'https://didcomm.org/connections/1.0/invitation', - '@id': 'efe3fe97', - label: 'ssi-abstraction-agent', - recipientKeys: ['8iT6AAmbj9P'], - serviceEndpoint: - 'https://serviceEndpointUrl.com:443/ocm/didcomm', - routingKeys: [], - }, - multiUseInvitation: false, - }, - invitationUrlShort: - 'https://serviceEndpointUrl.com/ocm/connection/v1/url/1234abc', - }, - }, - }, - }, - }, - }, - }) - @ApiResponse({ - status: HttpStatus.BAD_REQUEST, - description: 'Alias must be provided', - content: { - 'application/json': { - schema: {}, - examples: { - 'Alias must be provided': { - value: { - statusCode: 400, - message: 'Alias must be provided', - }, - }, - }, - }, - }, - }) - @ApiResponse({ - status: HttpStatus.NOT_FOUND, - description: 'Agent Data not found.', - content: { - 'application/json': { - schema: {}, - examples: { - 'Agent Data not found.': { - value: { - statusCode: 400, - message: 'Agent Data not found.', - }, - }, - }, - }, - }, - }) - @ApiQuery({ name: 'alias', required: true }) - public async createConnectionInvitation( - @Body() connectionCreate: ConnectionCreateInvitationDto, - @Query() query: { alias: string }, - @Res() response: Response, - ) { - logger.info(JSON.stringify(query)); - let res: ResponseType; - - if ( - !( - query.alias === ConnectionsService.connectionAlias.MEMBER || - query.alias === ConnectionsService.connectionAlias.SUBSCRIBER || - query.alias === ConnectionsService.connectionAlias.TRUST - ) - ) { - response.status(HttpStatus.BAD_REQUEST); - res = { - statusCode: HttpStatus.BAD_REQUEST, - message: 'Alias must be provided', - }; - return response.send(res); - } - const createConnectionPayload = { - ...connectionCreate, - alias: query.alias, - }; - const result = await this.connectionsService.createInvitationURL( - createConnectionPayload, - ); - if (result) { - res = { - statusCode: HttpStatus.OK, - message: 'Connection created successfully', - data: result, - }; - return response.send(res); - } - response.status(HttpStatus.NOT_FOUND); - res = { - statusCode: HttpStatus.NOT_FOUND, - message: 'Agent Data not found.', - }; - - return response.send(res); - } - - @Version(['1']) - @Get('url/:id') - @ApiOperation({ - summary: 'Get full url from short url id', - description: 'Get full url from short url id', - }) - @ApiExcludeEndpoint() - public async redirectToConnectionUrl( - @Param() params: { id: string }, - @Res() response: Response, - ) { - const result = await this.connectionsService.findConnectionByShortUrlId( - params.id, - ); - if (!result) { - throw new Error('Not found'); - } - response.writeHead(302, { - location: result.connectionUrl, - }); - return response.end(); - } - - @Version(['1']) - @Get('connection-information') - @ApiOperation({ - summary: 'Fetch connection information by id or did', - description: - 'This call provides the capability to get information about connection by connectionId or did. This call returns issued credentials and requested proof to that connection', - }) - @ApiQuery({ name: 'connectionId', required: false }) - @ApiQuery({ name: 'did', required: false }) - @ApiResponse({ - status: HttpStatus.OK, - description: 'Connection information fetched successfully', - content: { - 'application/json': { - schema: {}, - examples: { - 'Connection information fetched successfully': { - value: { - statusCode: 200, - message: 'Connection information fetched successfully', - data: { - records: { - issueCredentials: [ - { - id: '6a6ee15d', - credentialId: '624a76fd', - credDefId: '8y8oycXjn', - threadId: '9f95a52a', - state: 'done', - principalDid: 'KGaeQVa', - connectionId: '12cd39de', - createdDate: '1970-01-01T00:00:00.149Z', - updatedDate: '1970-01-01T00:00:00.467Z', - expirationDate: null, - }, - ], - presentProofs: [], - }, - }, - }, - }, - }, - }, - }, - }) - @ApiResponse({ - status: HttpStatus.BAD_REQUEST, - description: 'connection ID / DID must be provided', - content: { - 'application/json': { - schema: {}, - examples: { - 'connection ID / DID must be provided': { - value: { - statusCode: 400, - message: 'connection ID / DID must be provided', - }, - }, - }, - }, - }, - }) - @ApiResponse({ - status: HttpStatus.BAD_REQUEST, - description: 'Invalid connection ID / DID', - content: { - 'application/json': { - schema: {}, - examples: { - 'Invalid connection ID / DID': { - value: { - statusCode: 400, - message: 'Invalid connection ID / DID', - }, - }, - }, - }, - }, - }) - public async getConnectionInformationRequest( - @Query() query: { connectionId: string; did: string }, - @Res() response: Response, - ) { - let res: ResponseType; - - if (!query.connectionId && !query.did) { - response.status(HttpStatus.BAD_REQUEST); - res = { - statusCode: HttpStatus.BAD_REQUEST, - message: 'connection ID / DID must be provided', - }; - return response.json(res); - } - - const result = - await this.connectionsService.getConnectionInformationRequest( - query.connectionId || '', - query.did || '', - ); - - if (!result) { - response.status(HttpStatus.BAD_REQUEST); - res = { - statusCode: HttpStatus.BAD_REQUEST, - message: 'Invalid connection ID / DID', - }; - return response.json(res); - } - - res = { - statusCode: HttpStatus.OK, - message: 'Connection information fetched successfully', - data: { - records: result, - }, - }; - return response.json(res); - } - - @Version(['1']) - @Get('connections') - @ApiOperation({ - summary: 'Fetch list of connections', - description: - 'This call provides the capability to search connections by using pagination and filter parameters. This call returns a list of connections and overall count of records. This endpoint supports followinng query filter parameters: participantDID, status, pageSize, page', - }) - @ApiQuery({ name: 'page', required: false }) - @ApiQuery({ name: 'pageSize', required: false }) - @ApiQuery({ name: 'status', required: false }) - @ApiQuery({ name: 'participantDID', required: false }) - @ApiResponse({ - status: HttpStatus.OK, - description: 'Connections fetched successfully', - content: { - 'application/json': { - schema: {}, - examples: { - 'Connections fetched successfully': { - value: { - statusCode: 200, - message: 'Connections fetched successfully', - data: { - count: 1, - records: [ - { - id: '089e1b95', - connectionId: 'e7361a1b', - status: 'invited', - participantDid: 'Kv6NS9y', - theirDid: '', - theirLabel: '', - createdDate: '1970-01-01T00:00:00.617Z', - updatedDate: '1970-01-01T00:00:00.617Z', - isActive: false, - isReceived: false, - }, - ], - }, - }, - }, - }, - }, - }, - }) - @ApiResponse({ - status: HttpStatus.NOT_FOUND, - description: 'No Data found', - content: { - 'application/json': { - schema: {}, - examples: { - 'No Data found': { - value: { - statusCode: 404, - message: 'No Data found', - }, - }, - }, - }, - }, - }) - public async getConnectionLists( - @Param() params: { connectionId: string }, - @Query() - query: { - participantDID?: string; - pageSize?: string; - page?: string; - status?: string; - }, - @Res() response: Response, - ) { - let res: ResponseType; - - const result = await this.connectionsService.findConnections( - query.pageSize ? parseInt(query.pageSize, 10) : 10, - query.page ? parseInt(query.page, 10) : 0, - query.status ? query.status : false, - params?.connectionId ? params.connectionId : undefined, - query.participantDID, - ); - - if (Array.isArray(result) && result[0] > 0) { - res = { - statusCode: HttpStatus.OK, - message: 'Connections fetched successfully', - data: { - count: result[0], - records: result[1], - }, - }; - return response.json(res); - } - - if (result && !Array.isArray(result) && result.isActive) { - res = { - statusCode: HttpStatus.OK, - message: 'Connections fetched successfully', - data: { - records: result, - }, - }; - return response.json(res); - } - - response.status(HttpStatus.NOT_FOUND); - res = { - statusCode: HttpStatus.NOT_FOUND, - message: 'No Data found', - }; - return response.json(res); - } - - @Version(['1']) - @Get('connections/:connectionId') - @ApiOperation({ - summary: 'Fetch connection by id', - description: - 'This call provides the capability to get connection data by providing connectionId. The connection data is the same which is returned from /v1/connections endpoint and contains generic information about connection like connectionId, status, dids and so on.', - }) - @ApiResponse({ - status: HttpStatus.OK, - description: 'Connections fetched successfully', - content: { - 'application/json': { - schema: {}, - examples: { - 'Connections fetched successfully': { - value: { - statusCode: 200, - message: 'Connections fetched successfully', - data: { - count: 1, - records: [ - { - id: '089e1b95', - connectionId: 'e7361a1b', - status: 'invited', - participantDid: 'Kv6NS9y', - theirDid: '', - theirLabel: '', - createdDate: '1970-01-01T00:00:00.617Z', - updatedDate: '1970-01-01T00:00:00.617Z', - isActive: false, - isReceived: false, - }, - ], - }, - }, - }, - }, - }, - }, - }) - @ApiResponse({ - status: HttpStatus.NOT_FOUND, - description: 'No Data found', - content: { - 'application/json': { - schema: {}, - examples: { - 'No Data found': { - value: { - statusCode: 404, - message: 'No Data found', - }, - }, - }, - }, - }, - }) - public async getConnection( - @Param() params: { connectionId: string }, - @Res() response: Response, - ) { - return this.getConnectionLists(params, {}, response); - } - - @MessagePattern({ - endpoint: `${NATSServices.SERVICE_NAME}/getConnectionById`, - }) - public async getConnectionById(data: { connectionId: string }) { - const result = await this.connectionsService.findConnections( - -1, - -1, - false, - data.connectionId, - ); - return result; - } - - @MessagePattern({ - endpoint: `${NATSServices.SERVICE_NAME}/makeConnectionTrusted`, - }) - public async makeConnectionTrusted(data: { connectionId: string }) { - const result = await this.connectionsService.makeConnectionTrusted( - data.connectionId, - ); - return result; - } - - @Version(['1']) - @ApiBody({ type: AcceptConnectionInvitationBody }) - @Post('accept-connection-invitation') - @ApiOperation({ - summary: 'Accept connection invitation', - description: - 'This call provides the capability to receive connection invitation as invitee by invitationUrl and create connection. If auto accepting is enabled via either the config passed in the function or the global agent config, a connection request message will be send.', - }) - @ApiResponse({ - status: HttpStatus.ACCEPTED, - description: 'Accepted Connection Request', - content: { - 'application/json': { - schema: {}, - examples: { - 'Accepted Connection Request': { - value: { - statusCode: 202, - message: 'Accepted Connection Request', - data: { - _tags: { - invitationKey: '5Nj', - state: 'invited', - role: 'invitee', - verkey: 'F6d', - }, - metadata: {}, - id: 'e6d30380', - createdAt: '1970-01-01T00:00:00.103Z', - did: 'Ss8', - didDoc: { - '@context': 'https://w3id.org/did/v1', - publicKey: [ - { - id: 'Ss8#1', - controller: 'Ss8', - type: 'Ed25519VerificationKey2018', - publicKeyBase58: 'F6d', - }, - ], - service: [ - { - id: 'Ss8', - serviceEndpoint: - 'https://serviceEndpointUrl.com:443/ocm/didcomm', - type: 'IndyAgent', - priority: 0, - recipientKeys: ['F6d'], - routingKeys: [], - }, - ], - authentication: [ - { - publicKey: 'Ss8#1', - type: 'Ed25519SignatureAuthentication2018', - }, - ], - id: 'Ss8', - }, - verkey: 'F6d', - theirLabel: 'ssi-abstraction-agent', - state: 'requested', - role: 'invitee', - alias: 'connection-received', - autoAcceptConnection: true, - invitation: { - '@type': 'https://didcomm.org/connections/1.0/invitation', - '@id': '12ebbf61', - label: 'ssi-abstraction-agent', - recipientKeys: ['5Nj'], - serviceEndpoint: - 'https://serviceEndpointUrl.com:443/ocm/didcomm', - routingKeys: [], - }, - multiUseInvitation: false, - }, - }, - }, - }, - }, - }, - }) - @ApiResponse({ - status: HttpStatus.INTERNAL_SERVER_ERROR, - description: 'Internal Server Error or Bad Request', - content: { - 'application/json': { - schema: {}, - examples: { - 'Internal Server Error or Bad Request': { - value: { - statusCode: 500, - timestamp: '1970-01-01T00:00:00.668Z', - message: 'something went wrong: Lorem Ipsum', - }, - }, - }, - }, - }, - }) - public async acceptConnectionInvitation( - @Body() body: AcceptConnectionInvitationBody, - @Res() response: Response, - ) { - const { invitationUrl, autoAcceptConnection } = body; - - const { agentUrl } = this.connectionsService.getAgentUrl(); - - const responseData: ResponseType = { - statusCode: HttpStatus.ACCEPTED, - message: 'Accepted Connection Request', - data: await this.connectionsService.acceptConnectionInvitation(agentUrl, { - invitationUrl, - autoAcceptConnection, - alias: RECEIVED_CONNECTION_ALIAS, - }), - }; - - return response.status(responseData.statusCode).send(responseData); - } - - @MessagePattern({ - endpoint: `${NATSServices.SERVICE_NAME}/getReceivedConnections`, - }) - public async getReceivedConnections() { - let result: object[] = []; - const connections = await this.connectionsService.getReceivedConnections(); - if (connections[0]) { - [, result] = connections; - } - return result; - } -} diff --git a/apps/connection-manager/src/connections/dto/block.dto.ts b/apps/connection-manager/src/connections/dto/block.dto.ts new file mode 100644 index 0000000..71c8618 --- /dev/null +++ b/apps/connection-manager/src/connections/dto/block.dto.ts @@ -0,0 +1,12 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsNotEmpty, IsString } from 'class-validator'; + +export class BlockParams { + @IsString() + @IsNotEmpty() + @ApiProperty({ + description: 'The connection ID or DID', + example: '8d74c6ec-fa3e-4a09-91fb-5fd0062da835', + }) + public idOrDid: string; +} diff --git a/apps/connection-manager/src/connections/dto/get-by-id.dto.ts b/apps/connection-manager/src/connections/dto/get-by-id.dto.ts new file mode 100644 index 0000000..a1b8bc9 --- /dev/null +++ b/apps/connection-manager/src/connections/dto/get-by-id.dto.ts @@ -0,0 +1,12 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsNotEmpty, IsString } from 'class-validator'; + +export class GetByIdParams { + @IsString() + @IsNotEmpty() + @ApiProperty({ + description: 'The connection ID', + example: '71b784a3', + }) + public connectionId: string; +} diff --git a/apps/connection-manager/src/connections/entities/AcceptConnectionInvitationBody.ts b/apps/connection-manager/src/connections/entities/AcceptConnectionInvitationBody.ts deleted file mode 100644 index 57c85fb..0000000 --- a/apps/connection-manager/src/connections/entities/AcceptConnectionInvitationBody.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; - -export default class AcceptConnectionInvitationBody { - @ApiProperty() - public invitationUrl: string; - - @ApiProperty() - public autoAcceptConnection: boolean; -} diff --git a/apps/connection-manager/src/connections/entities/InvitationDto.entity.ts b/apps/connection-manager/src/connections/entities/InvitationDto.entity.ts deleted file mode 100644 index b10c4a2..0000000 --- a/apps/connection-manager/src/connections/entities/InvitationDto.entity.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { IsString } from 'class-validator'; - -export default class InvitationDTO { - @IsString() - public serviceEndpoint?: string; - - @IsString() - public ['@type']?: string; - - @IsString() - public ['@id']?: string; - - @IsString() - public label?: string; - - @IsString() - public recipientKeys?: [string]; - - @IsString() - public routingKeys?: []; -} diff --git a/apps/connection-manager/src/connections/entities/connectionCreateInvitationDto.entity.ts b/apps/connection-manager/src/connections/entities/connectionCreateInvitationDto.entity.ts deleted file mode 100644 index 1f41f25..0000000 --- a/apps/connection-manager/src/connections/entities/connectionCreateInvitationDto.entity.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { IsString } from 'class-validator'; - -export default class ConnectionCreateInvitationDto { - @IsString() - @ApiProperty() - public autoAcceptConnection?: boolean; - - @IsString() - @ApiProperty() - public alias?: string; - - @IsString() - @ApiProperty() - public myLabel?: string; - - @IsString() - @ApiProperty() - public myImageUrl?: string; -} diff --git a/apps/connection-manager/src/connections/entities/connectionStateDto.entity.ts b/apps/connection-manager/src/connections/entities/connectionStateDto.entity.ts deleted file mode 100644 index d6380ac..0000000 --- a/apps/connection-manager/src/connections/entities/connectionStateDto.entity.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { IsBooleanString, IsNotEmpty, IsString } from 'class-validator'; - -import InvitationDTO from './InvitationDto.entity.js'; - -export default class ConnectionStateDto { - @IsString() - public _tags?: string; - - @IsString() - public metadata?: string; - - @IsString() - public didDoc?: string; - - @IsString() - public verkey?: string; - - @IsString() - public createdAt?: string; - - @IsString() - @IsNotEmpty() - public role: string; - - @IsString() - @IsNotEmpty() - public state: string; - - @IsString() - @IsNotEmpty() - public id: string; - - @IsString() - @IsNotEmpty() - public did: string; - - @IsString() - public theirDid: string; - - @IsString() - public theirLabel: string; - - @IsString() - public invitation: InvitationDTO; - - @IsString() - public alias: string; - - @IsBooleanString() - public multiUseInvitation?: boolean; -} diff --git a/apps/connection-manager/src/connections/entities/connectionSubscribeEndPoint.entity.ts b/apps/connection-manager/src/connections/entities/connectionSubscribeEndPoint.entity.ts deleted file mode 100644 index cbd2454..0000000 --- a/apps/connection-manager/src/connections/entities/connectionSubscribeEndPoint.entity.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { IsString, IsNotEmpty } from 'class-validator'; - -export default class ConnectionSubscriptionEndpointDto { - @IsString() - @IsNotEmpty() - public connectionId: string; - - @IsString() - @IsNotEmpty() - public status: string; -} diff --git a/apps/connection-manager/src/connections/entities/entity.ts b/apps/connection-manager/src/connections/entities/entity.ts deleted file mode 100644 index a683eda..0000000 --- a/apps/connection-manager/src/connections/entities/entity.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { IsString, IsNotEmpty, IsDate, IsBoolean } from 'class-validator'; - -import InvitationDTO from './InvitationDto.entity.js'; - -export default class ConnectionDto { - @IsString() - public id?: string; - - @IsDate() - public connectionDate?: Date; - - @IsDate() - public createdDate?: Date; - - @IsDate() - public updatedDate?: Date; - - @IsString() - @IsNotEmpty() - public participantDid: string; - - @IsString() - @IsNotEmpty() - public status: string; - - @IsString() - @IsNotEmpty() - public connectionId: string; - - @IsString() - public theirDid: string; - - @IsString() - public theirLabel: string; - - @IsBoolean() - public isReceived: boolean; - - @IsString() - public invitation?: InvitationDTO; -} diff --git a/apps/connection-manager/src/connections/module.spec.ts b/apps/connection-manager/src/connections/module.spec.ts deleted file mode 100644 index 0964656..0000000 --- a/apps/connection-manager/src/connections/module.spec.ts +++ /dev/null @@ -1,7 +0,0 @@ -import ConnectionsModule from './module'; - -describe('Check if the module is working', () => { - it('should be defined', () => { - expect(ConnectionsModule).toBeDefined(); - }); -}); diff --git a/apps/connection-manager/src/connections/module.ts b/apps/connection-manager/src/connections/module.ts deleted file mode 100644 index 21f1184..0000000 --- a/apps/connection-manager/src/connections/module.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { HttpModule } from '@nestjs/axios'; -import { Module } from '@nestjs/common'; -import { ClientsModule, Transport } from '@nestjs/microservices'; - -import NatsClientService from '../client/nats.client.js'; -import RestClientService from '../client/rest.client.js'; -import { NATSServices } from '../common/constants.js'; -import config from '../config/config.js'; -import PrismaService from '../prisma/prisma.service.js'; - -import ConnectionsController from './controller/controller.js'; -import ConnectionsService from './services/service.js'; - -@Module({ - imports: [ - HttpModule, - ClientsModule.register([ - { - name: NATSServices.SERVICE_NAME, - transport: Transport.NATS, - options: { - servers: [config().nats.url as string], - }, - }, - ]), - ], - controllers: [ConnectionsController], - providers: [ - ConnectionsService, - PrismaService, - NatsClientService, - RestClientService, - ], -}) -export default class ConnectionsModule {} diff --git a/apps/connection-manager/src/connections/repository/connection.repository.ts b/apps/connection-manager/src/connections/repository/connection.repository.ts deleted file mode 100644 index f1cfb58..0000000 --- a/apps/connection-manager/src/connections/repository/connection.repository.ts +++ /dev/null @@ -1,97 +0,0 @@ -import type { Prisma } from '@prisma/client'; - -import { Injectable } from '@nestjs/common'; - -import PrismaService from '../../prisma/prisma.service.js'; - -@Injectable() -export default class ConnectionRepository { - public constructor(private readonly prismaService: PrismaService) {} - - public async createConnection(data: Prisma.ConnectionCreateInput) { - return this.prismaService.connection.create({ data }); - } - - public async createShortUrl(connectionUrl: string) { - return this.prismaService.shortUrlConnection.create({ - data: { connectionUrl }, - }); - } - - public async getShortUrl(id: string) { - return this.prismaService.shortUrlConnection.findUnique({ - where: { id }, - }); - } - - public async updateConnection(params: { - where: Prisma.ConnectionWhereUniqueInput; - data: Prisma.ConnectionUpdateInput; - }) { - const { where, data } = params; - - return this.prismaService.connection.update({ - data, - where, - }); - } - - public async updateManyConnection(params: { - where: Prisma.ConnectionWhereInput; - data: Prisma.ConnectionUpdateInput; - }) { - const { where, data } = params; - - return this.prismaService.connection.updateMany({ - data, - where, - }); - } - - public async findConnections(params: { - skip?: number; - take?: number; - cursor?: Prisma.ConnectionWhereUniqueInput; - where?: Prisma.ConnectionWhereInput; - orderBy?: Prisma.ConnectionOrderByWithRelationInput; - select?: Prisma.ConnectionSelect; - }) { - const { skip, take, cursor, where, orderBy, select } = params; - - if (where) { - where.isActive = true; - } - - return this.prismaService.$transaction([ - this.prismaService.connection.count({ where }), - this.prismaService.connection.findMany({ - skip, - take, - cursor, - where, - orderBy, - select, - }), - ]); - } - - public async findUniqueConnection(params: { - where: Prisma.ConnectionWhereUniqueInput; - }) { - const { where } = params; - - return this.prismaService.connection.findUnique({ - where, - }); - } - - public findByConnectionId(connectionId: string) { - const query = { where: { connectionId } }; - return this.findUniqueConnection(query); - } - - public findByConnectionByParticipantDID(participantDid: string) { - const query = { where: { participantDid } }; - return this.findUniqueConnection(query); - } -} diff --git a/apps/connection-manager/src/connections/scheduler/scheduler.service.ts b/apps/connection-manager/src/connections/scheduler/scheduler.service.ts deleted file mode 100644 index 69492c4..0000000 --- a/apps/connection-manager/src/connections/scheduler/scheduler.service.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { - Controller, - Injectable, - InternalServerErrorException, -} from '@nestjs/common'; -import { Cron, CronExpression } from '@nestjs/schedule'; - -import ConfigClient from '../../client/config.client.js'; -import PrismaService from '../../prisma/prisma.service.js'; -import logger from '../../utils/logger.js'; -import ConnectionRepository from '../repository/connection.repository.js'; -import ConnectionsService from '../services/service.js'; - -@Injectable() -@Controller() -export default class SchedulerService { - private connectionRepository; - - public constructor(private readonly prismaService: PrismaService) { - this.connectionRepository = new ConnectionRepository(this.prismaService); - } - - @Cron(CronExpression.EVERY_30_SECONDS) - public async expireNonCompleteConnection() { - const compareDateTime = ConfigClient.getConnectionExpire(); - if (compareDateTime) { - const checkExpireTillDateTime = ConfigClient.checkExpireTill(); - - const query = { - where: { - AND: [ - { - OR: [ - { - status: ConnectionsService.status.INVITED, - }, - { - status: ConnectionsService.status.REQUESTED, - }, - { - status: ConnectionsService.status.RESPONDED, - }, - ], - }, - { - isActive: true, - }, - { - createdDate: { - lt: compareDateTime, - ...(checkExpireTillDateTime && { gt: checkExpireTillDateTime }), - }, - }, - ], - }, - data: { - isActive: false, - }, - }; - const result = - await this.connectionRepository.updateManyConnection(query); - logger.info(JSON.stringify(result)); - } else { - throw new InternalServerErrorException( - 'Connection Expire period is mandatory', - ); - } - } - - @Cron(CronExpression.EVERY_30_SECONDS) - public async expireNonTrustedConnection() { - const compareDateTime = ConfigClient.getConnectionExpire(); - if (compareDateTime) { - const checkExpireTillDateTime = ConfigClient.checkExpireTill(); - - const query = { - where: { - AND: [ - { - status: ConnectionsService.status.COMPLETE, - }, - { - isActive: true, - }, - { - createdDate: { - lt: compareDateTime, - ...(checkExpireTillDateTime && { gt: checkExpireTillDateTime }), - }, - }, - ], - }, - data: { - isActive: false, - }, - }; - const result = - await this.connectionRepository.updateManyConnection(query); - logger.info(JSON.stringify(result)); - } else { - throw new InternalServerErrorException( - 'Connection Expire period is mandatory', - ); - } - } -} diff --git a/apps/connection-manager/src/connections/services/service.spec.ts b/apps/connection-manager/src/connections/services/service.spec.ts deleted file mode 100644 index ac71026..0000000 --- a/apps/connection-manager/src/connections/services/service.spec.ts +++ /dev/null @@ -1,469 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import type ConnectionDto from '../entities/entity.js'; -import type { TestingModule } from '@nestjs/testing'; - -import { HttpModule } from '@nestjs/axios'; -import { ConfigModule } from '@nestjs/config'; -import { ClientsModule, Transport } from '@nestjs/microservices'; -import { Test } from '@nestjs/testing'; - -import NatsClientService from '../../client/nats.client.js'; -import RestClientService from '../../client/rest.client.js'; -import { NATSServices } from '../../common/constants.js'; -import PrismaService from '../../prisma/prisma.service.js'; - -import ConnectionsService from './service.js'; - -describe('ConnectionsService', () => { - let service: ConnectionsService; - let prismaService: PrismaService; - let restClientService: RestClientService; - let natsClient: NatsClientService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - imports: [ - ConfigModule, - HttpModule, - ClientsModule.register([ - { - name: NATSServices.SERVICE_NAME, - transport: Transport.NATS, - }, - ]), - ], - providers: [ - ConnectionsService, - PrismaService, - NatsClientService, - RestClientService, - ], - exports: [PrismaService], - }).compile(); - prismaService = module.get<PrismaService>(PrismaService); - service = module.get<ConnectionsService>(ConnectionsService); - restClientService = module.get<RestClientService>(RestClientService); - natsClient = module.get<NatsClientService>(NatsClientService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); - - describe('find Connection function', () => { - it('find connection by connection Id', async () => { - const repositoryResult: any = { - id: '1a7f0b09-b20e-4971-b9b1-7adde7256bbc', - connectionId: '7b821264-2ae3-4459-b45f-19fa975d91f7', - participantId: '7780cd24-af13-423e-b1ff-ae944ab6fd71', - status: 'trusted', - participantDid: 'SU1SHqQiDcc6gDvqH8wwYF', - theirDid: 'Ax9xMqE89F9LStfGnTpDzg', - theirLabel: 'sagar@getnada.com', - createdDate: '2022-04-18T11:03:58.099Z', - updatedDate: '2022-04-18T11:05:10.004Z', - isActive: true, - }; - - const result: any = { - id: '1a7f0b09-b20e-4971-b9b1-7adde7256bbc', - connectionId: '7b821264-2ae3-4459-b45f-19fa975d91f7', - participantId: '7780cd24-af13-423e-b1ff-ae944ab6fd71', - status: 'trusted', - participantDid: 'SU1SHqQiDcc6gDvqH8wwYF', - theirDid: 'Ax9xMqE89F9LStfGnTpDzg', - theirLabel: 'sagar@getnada.com', - createdDate: '2022-04-18T11:03:58.099Z', - updatedDate: '2022-04-18T11:05:10.004Z', - isActive: true, - }; - - jest - .spyOn(prismaService.connection, 'findUnique') - .mockResolvedValueOnce(repositoryResult); - - const res: any = await service.findConnections( - NaN, - -1, - false, - '', - '7b821264-2ae3-4459-b45f-19fa975d91f7', - ); - - expect(res).toStrictEqual(result); - }); - - it('find connection by participant DID', async () => { - const repositoryResult: any = { - id: '1a7f0b09-b20e-4971-b9b1-7adde7256bbc', - connectionId: '7b821264-2ae3-4459-b45f-19fa975d91f7', - participantId: '7780cd24-af13-423e-b1ff-ae944ab6fd71', - status: 'trusted', - participantDid: 'SU1SHqQiDcc6gDvqH8wwYF', - theirDid: 'Ax9xMqE89F9LStfGnTpDzg', - theirLabel: 'sagar@getnada.com', - createdDate: '2022-04-18T11:03:58.099Z', - updatedDate: '2022-04-18T11:05:10.004Z', - isActive: true, - }; - - const result: any = { - id: '1a7f0b09-b20e-4971-b9b1-7adde7256bbc', - connectionId: '7b821264-2ae3-4459-b45f-19fa975d91f7', - participantId: '7780cd24-af13-423e-b1ff-ae944ab6fd71', - status: 'trusted', - participantDid: 'SU1SHqQiDcc6gDvqH8wwYF', - theirDid: 'Ax9xMqE89F9LStfGnTpDzg', - theirLabel: 'sagar@getnada.com', - createdDate: '2022-04-18T11:03:58.099Z', - updatedDate: '2022-04-18T11:05:10.004Z', - isActive: true, - }; - - jest - .spyOn(prismaService.connection, 'findUnique') - .mockResolvedValueOnce(repositoryResult); - - const res: any = await service.findConnections( - NaN, - -1, - '', - '', - 'SU1SHqQiDcc6gDvqH8wwYF', - ); - - expect(res).toStrictEqual(result); - }); - - it('find connection by participant id', async () => { - const repositoryResult: any = [ - 3, - [ - { - id: '977c7cd6-a1af-4a5a-bd51-03758d8db50f', - connectionId: '19694476-cc8e-42a3-a5ea-0b2503133348', - participantId: '13f412e2-2749-462a-a10a-54f25e326641', - status: 'invited', - participantDid: 'UVE8wxzGEYGjTWWcudc2nB', - theirDid: '', - theirLabel: '', - createdDate: '2022-04-22T12:15:59.365Z', - updatedDate: '2022-04-22T12:15:59.365Z', - isActive: true, - }, - { - id: 'a453d1ae-f95d-4485-8a1a-3c4347450537', - connectionId: '24fcc8b7-3cfa-4d46-a14a-9b6297e81d7e', - participantId: '13f412e2-2749-462a-a10a-54f25e326641', - status: 'trusted', - participantDid: '3X5jtG9CJFgsDFyXjUDRNp', - theirDid: 'Us8ZgUGXZ5P7GTF8q5NEgh', - theirLabel: 'tango@vomoto.com', - createdDate: '2022-04-22T12:18:42.273Z', - updatedDate: '2022-04-22T12:23:09.183Z', - isActive: true, - }, - { - id: 'ccde23e4-5a21-44d8-a90b-beeba526d5f4', - connectionId: 'ff468f45-7fe8-4964-abb4-d2dd90b6aed3', - participantId: '13f412e2-2749-462a-a10a-54f25e326641', - status: 'responded', - participantDid: 'WYcecJk6ZbWvoF2VD9xTey', - theirDid: '3NigtUWR68H3HPQiuwgfEk', - theirLabel: 'arnold@vomoto.com', - createdDate: '2022-04-22T12:16:03.614Z', - updatedDate: '2022-04-22T12:16:56.132Z', - isActive: true, - }, - ], - ]; - - const result: any = [ - 3, - [ - { - id: '977c7cd6-a1af-4a5a-bd51-03758d8db50f', - connectionId: '19694476-cc8e-42a3-a5ea-0b2503133348', - participantId: '13f412e2-2749-462a-a10a-54f25e326641', - status: 'invited', - participantDid: 'UVE8wxzGEYGjTWWcudc2nB', - theirDid: '', - theirLabel: '', - createdDate: '2022-04-22T12:15:59.365Z', - updatedDate: '2022-04-22T12:15:59.365Z', - isActive: true, - }, - { - id: 'a453d1ae-f95d-4485-8a1a-3c4347450537', - connectionId: '24fcc8b7-3cfa-4d46-a14a-9b6297e81d7e', - participantId: '13f412e2-2749-462a-a10a-54f25e326641', - status: 'trusted', - participantDid: '3X5jtG9CJFgsDFyXjUDRNp', - theirDid: 'Us8ZgUGXZ5P7GTF8q5NEgh', - theirLabel: 'tango@vomoto.com', - createdDate: '2022-04-22T12:18:42.273Z', - updatedDate: '2022-04-22T12:23:09.183Z', - isActive: true, - }, - { - id: 'ccde23e4-5a21-44d8-a90b-beeba526d5f4', - connectionId: 'ff468f45-7fe8-4964-abb4-d2dd90b6aed3', - participantId: '13f412e2-2749-462a-a10a-54f25e326641', - status: 'responded', - participantDid: 'WYcecJk6ZbWvoF2VD9xTey', - theirDid: '3NigtUWR68H3HPQiuwgfEk', - theirLabel: 'arnold@vomoto.com', - createdDate: '2022-04-22T12:16:03.614Z', - updatedDate: '2022-04-22T12:16:56.132Z', - isActive: true, - }, - ], - ]; - - jest - .spyOn(prismaService, '$transaction') - .mockResolvedValueOnce(repositoryResult); - - const res: any = await service.findConnections(NaN, -1, '', '', ''); - - expect(res).toStrictEqual(result); - }); - - it.skip('find connections by participant Id and status', async () => { - const repositoryResult = [ - 3, - [ - { - id: '977c7cd6-a1af-4a5a-bd51-03758d8db50f', - connectionId: '19694476-cc8e-42a3-a5ea-0b2503133348', - participantId: '13f412e2-2749-462a-a10a-54f25e326641', - status: 'invited', - participantDid: 'UVE8wxzGEYGjTWWcudc2nB', - theirDid: '', - theirLabel: '', - createdDate: '2022-04-22T12:15:59.365Z', - updatedDate: '2022-04-22T12:15:59.365Z', - isActive: true, - }, - { - id: 'a453d1ae-f95d-4485-8a1a-3c4347450537', - connectionId: '24fcc8b7-3cfa-4d46-a14a-9b6297e81d7e', - participantId: '13f412e2-2749-462a-a10a-54f25e326641', - status: 'trusted', - participantDid: '3X5jtG9CJFgsDFyXjUDRNp', - theirDid: 'Us8ZgUGXZ5P7GTF8q5NEgh', - theirLabel: 'tango@vomoto.com', - createdDate: '2022-04-22T12:18:42.273Z', - updatedDate: '2022-04-22T12:23:09.183Z', - isActive: true, - }, - { - id: 'ccde23e4-5a21-44d8-a90b-beeba526d5f4', - connectionId: 'ff468f45-7fe8-4964-abb4-d2dd90b6aed3', - participantId: '13f412e2-2749-462a-a10a-54f25e326641', - status: 'responded', - participantDid: 'WYcecJk6ZbWvoF2VD9xTey', - theirDid: '3NigtUWR68H3HPQiuwgfEk', - theirLabel: 'arnold@vomoto.com', - createdDate: '2022-04-22T12:16:03.614Z', - updatedDate: '2022-04-22T12:16:56.132Z', - isActive: true, - }, - ], - ]; - - const result = [ - 3, - [ - { - id: '977c7cd6-a1af-4a5a-bd51-03758d8db50f', - connectionId: '19694476-cc8e-42a3-a5ea-0b2503133348', - participantId: '13f412e2-2749-462a-a10a-54f25e326641', - status: 'invited', - participantDid: 'UVE8wxzGEYGjTWWcudc2nB', - theirDid: '', - theirLabel: '', - createdDate: '2022-04-22T12:15:59.365Z', - updatedDate: '2022-04-22T12:15:59.365Z', - isActive: true, - }, - { - id: 'a453d1ae-f95d-4485-8a1a-3c4347450537', - connectionId: '24fcc8b7-3cfa-4d46-a14a-9b6297e81d7e', - participantId: '13f412e2-2749-462a-a10a-54f25e326641', - status: 'trusted', - participantDid: '3X5jtG9CJFgsDFyXjUDRNp', - theirDid: 'Us8ZgUGXZ5P7GTF8q5NEgh', - theirLabel: 'tango@vomoto.com', - createdDate: '2022-04-22T12:18:42.273Z', - updatedDate: '2022-04-22T12:23:09.183Z', - isActive: true, - }, - { - id: 'ccde23e4-5a21-44d8-a90b-beeba526d5f4', - connectionId: 'ff468f45-7fe8-4964-abb4-d2dd90b6aed3', - participantId: '13f412e2-2749-462a-a10a-54f25e326641', - status: 'responded', - participantDid: 'WYcecJk6ZbWvoF2VD9xTey', - theirDid: '3NigtUWR68H3HPQiuwgfEk', - theirLabel: 'arnold@vomoto.com', - createdDate: '2022-04-22T12:16:03.614Z', - updatedDate: '2022-04-22T12:16:56.132Z', - isActive: true, - }, - ], - ]; - - jest - .spyOn(prismaService, '$transaction') - .mockResolvedValueOnce(repositoryResult); - - const res = await service.findConnections( - -1, - -1, - 'trusted,complete,responded,invited', - undefined, - '13f412e2-2749-462a-a10a-54f25e326641', - ); - - expect(res).toStrictEqual(result); - }); - }); - - describe.skip('create invitation', () => { - it('Create invitation-> member flow', async () => { - const serviceResult: any = { - invitationUrl: - 'http://localhost:4005?c_i=eyJAdHlwZSI6ImRpZDpzb3Y6QnpDYnNOWWhNcmpIaXFaRFRVQVNIZztzcGVjL2Nvbm5lY3Rpb25zLzEuMC9pbnZpdGF0aW9uIiwiQGlkIjoiYWMzYjE0NjktY2Y0Ni00M2ZjLWE4M2EtZGNmZjJjMDA1YjRlIiwibGFiZWwiOiJ0ZWNobmljYV9jb3JwIiwicmVjaXBpZW50S2V5cyI6WyI1bml1NWZmZmVnYkZlS2F3bU5OblRBTEpzaHB1cXpjRm5CUGpBOFFWU2dtWCJdLCJzZXJ2aWNlRW5kcG9pbnQiOiJodHRwOi8vMy4xMTEuNzcuMzg6NDAwNSIsInJvdXRpbmdLZXlzIjpbXX0', - invitation: { - '@type': - 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/connections/1.0/invitation', - '@id': 'ac3b1469-cf46-43fc-a83a-dcff2c005b4e', - label: 'technica_corp', - recipientKeys: ['5niu5fffegbFeKawmNNnTALJshpuqzcFnBPjA8QVSgmX'], - serviceEndpoint: 'http://localhost:4005', - routingKeys: [], - }, - connection: { - _tags: {}, - metadata: {}, - id: 'c1d73d9e-6988-4c84-9ebc-068c265d2fb6', - createdAt: '2022-04-21T10:52:18.161Z', - did: '9nYw7CSdHPqXf6ayfA7Wo2', - didDoc: { - '@context': 'https://w3id.org/did/v1', - publicKey: [ - { - id: '9nYw7CSdHPqXf6ayfA7Wo2#1', - controller: '9nYw7CSdHPqXf6ayfA7Wo2', - type: 'Ed25519VerificationKey2018', - publicKeyBase58: '5niu5fffegbFeKawmNNnTALJshpuqzcFnBPjA8QVSgmX', - }, - ], - service: [ - { - id: '9nYw7CSdHPqXf6ayfA7Wo2#In7780cd24-af13-423e-b1ff-ae944ab6fd71dyAgentService', - serviceEndpoint: 'http://localhost:4005', - type: 'IndyAgent', - priority: 0, - recipientKeys: ['5niu5fffegbFeKawmNNnTALJshpuqzcFnBPjA8QVSgmX'], - routingKeys: [], - }, - ], - authentication: [ - { - publicKey: '9nYw7CSdHPqXf6ayfA7Wo2#1', - type: 'Ed25519SignatureAuthentication2018', - }, - ], - id: '9nYw7CSdHPqXf6ayfA7Wo2', - }, - verkey: '5niu5fffegbFeKawmNNnTALJshpuqzcFnBPjA8QVSgmX', - state: 'invited', - role: 'inviter', - alias: 'member', - autoAcceptConnection: true, - invitation: { - '@type': 'https://didcomm.org/connections/1.0/invitation', - '@id': 'ac3b1469-cf46-43fc-a83a-dcff2c005b4e', - label: 'technica_corp', - recipientKeys: ['5niu5fffegbFeKawmNNnTALJshpuqzcFnBPjA8QVSgmX'], - serviceEndpoint: 'http://localhost:4005', - routingKeys: [], - }, - multiUseInvitation: false, - }, - }; - - const agent: any = { - status: 200, - message: 'Agent Data', - data: { - service_endpoint: 'agent URL', - }, - }; - - const result = serviceResult; - - jest - .spyOn(natsClient, 'getAgentByParticipantId') - .mockResolvedValueOnce(agent); - - jest - .spyOn(restClientService, 'post') - .mockResolvedValueOnce(serviceResult); - - const res = await service.createInvitationURL( - { autoAcceptConnection: true, alias: 'member' }, - 'participantId', - ); - - expect(res).toStrictEqual(result); - }); - }); - - describe.skip('Create connection', () => { - it('should create', async () => { - const connectionObj: ConnectionDto = { - connectionId: '7b821264-2ae3-4459-b45f-19fa975d91f7', - status: 'complete', - participantDid: 'SU1SHqQiDcc6gDvqH8wwYF', - theirDid: 'Ax9xMqE89F9LStfGnTpDzg', - theirLabel: 'sagar@getnada.com', - }; - - const agent: any = { - status: 200, - message: 'Agent Data', - data: { - service_endpoint: 'agent URL', - }, - }; - - const repositoryResult: any = { - id: '52d499e0-f76a-4b25-9c2a-f357bf6b73be', - connectionId: '7b821264-2ae3-4459-b45f-19fa975d91f7', - participantId: '', - status: 'complete', - participantDid: 'SU1SHqQiDcc6gDvqH8wwYF', - theirDid: 'Ax9xMqE89F9LStfGnTpDzg', - theirLabel: 'sagar@getnada.com', - createdDate: '2022-04-27T06:55:01.643Z', - updatedDate: '2022-04-27T06:55:01.643Z', - isActive: true, - }; - - const result = repositoryResult; - - jest.spyOn(natsClient, 'getAgentByURL').mockResolvedValueOnce(agent); - - jest - .spyOn(prismaService.connection, 'create') - .mockResolvedValueOnce(repositoryResult); - - const res = await service.createConnections(connectionObj); - - expect(res).toStrictEqual(result); - }); - }); -}); diff --git a/apps/connection-manager/src/connections/services/service.ts b/apps/connection-manager/src/connections/services/service.ts deleted file mode 100644 index 1bfe8a4..0000000 --- a/apps/connection-manager/src/connections/services/service.ts +++ /dev/null @@ -1,266 +0,0 @@ -import type ConnectionCreateInvitationDto from '../entities/connectionCreateInvitationDto.entity.js'; -import type ConnectionSubscriptionEndpointDto from '../entities/connectionSubscribeEndPoint.entity.js'; -import type ConnectionDto from '../entities/entity.js'; -import type { Connection, Prisma } from '@prisma/client'; - -import { Injectable } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; - -import NatsClientService from '../../client/nats.client.js'; -import RestClientService from '../../client/rest.client.js'; -import PrismaService from '../../prisma/prisma.service.js'; -import logger from '../../utils/logger.js'; -import pagination from '../../utils/pagination.js'; -import ConnectionRepository from '../repository/connection.repository.js'; - -@Injectable() -export default class ConnectionsService { - private connectionRepository: ConnectionRepository; - - public constructor( - private readonly prismaService: PrismaService, - private readonly natsClient: NatsClientService, - private readonly restClient: RestClientService, - private readonly configService: ConfigService, - ) { - this.connectionRepository = new ConnectionRepository(this.prismaService); - } - - public static readonly connectionAlias = { - MEMBER: 'member', - SUBSCRIBER: 'subscriber', - TRUST: 'trust', - }; - - public static readonly status = { - DEFAULT: 'invited', - INVITED: 'invited', - REQUESTED: 'requested', - RESPONDED: 'responded', - COMPLETE: 'complete', - TRUSTED: 'trusted', - }; - - public static readonly roles = { - INVITER: 'inviter', - INVITEE: 'invitee', - }; - - public async createConnections(connection: ConnectionDto) { - logger.info( - `connection service create connection connection?.invitation?.serviceEndpoint is ${connection?.invitation?.serviceEndpoint}`, - ); - const insertData = { - ...connection, - }; - delete insertData.invitation; - return this.connectionRepository.createConnection({ - ...insertData, - }); - } - - public async sendConnectionStatusToPrincipal( - status: string, - connectionId: string, - theirLabel: string, - participantDID: string, - theirDid: string, - ) { - try { - const response = - await this.natsClient.sendConnectionStatusPrincipalManager( - status, - connectionId, - theirLabel, - participantDID, - theirDid, - ); - return response; - } catch (error: unknown) { - logger.error(String(error)); - return error; - } - } - - public async sendMembershipProofRequestToProofManager(connectionId: string) { - try { - const response = - await this.natsClient.sendMembershipProofRequestToProofManager( - connectionId, - ); - return response; - } catch (error: unknown) { - logger.error(String(error)); - return error; - } - } - - public async updateStatusByConnectionId(connection: ConnectionDto) { - return this.connectionRepository.updateConnection({ - where: { connectionId: connection.connectionId }, - data: { - status: connection.status, - theirDid: connection.theirDid, - theirLabel: connection.theirLabel, - updatedDate: new Date(), - }, - }); - } - - public getConnectionByID(connectionId: string) { - return this.connectionRepository.findByConnectionId(connectionId); - } - - public getAgentUrl() { - return this.configService.get('agent'); - } - - public getAppUrl() { - return this.configService.get('APP_URL'); - } - - public async findConnections( - pageSize: number, - page: number, - status: string | false, - connectionId = '', - participantDid = '', - ) { - let query: { - skip?: number; - take?: number; - cursor?: Prisma.ConnectionWhereUniqueInput; - where?: Prisma.ConnectionWhereInput; - orderBy?: Prisma.ConnectionOrderByWithRelationInput; - } = {}; - - if (connectionId) { - return this.connectionRepository.findByConnectionId(connectionId); - } - - if (participantDid) { - return this.connectionRepository.findByConnectionByParticipantDID( - participantDid, - ); - } - - if (status) { - const statuses: string[] = status.split(','); - query.where = { status: { in: statuses } }; - } - - query = { ...query, ...pagination(pageSize, page) }; - - return this.connectionRepository.findConnections(query); - } - - public async createInvitationURL( - connectionCreate: ConnectionCreateInvitationDto, - ) { - const { agentUrl } = this.getAgentUrl(); - const appUrl = this.getAppUrl(); - const responseData = await this.restClient.post( - `${agentUrl}/connections/create-invitation`, - connectionCreate, - ); - - const shortRow = await this.connectionRepository.createShortUrl( - responseData.invitationUrl, - ); - responseData.invitationUrlShort = `${appUrl}/v1/url/${shortRow.id}`; - return responseData; - } - - public async findConnectionByShortUrlId(id: string) { - return this.connectionRepository.getShortUrl(id); - } - - public async getConnectionInformationRequest(connectionId = '', did = '') { - try { - let connectionDetails: Connection | null = null; - - if (connectionId) { - connectionDetails = - await this.connectionRepository.findByConnectionId(connectionId); - } - - if (did && !connectionDetails) { - connectionDetails = - await this.connectionRepository.findByConnectionByParticipantDID(did); - } - - if (!connectionDetails) { - return null; - } - - const response = { - issueCredentials: [], - presentProofs: [], - }; - - const issueCredentials = await this.natsClient.getIssueCredentials( - connectionDetails.connectionId, - ); - - if ( - issueCredentials && - Array.isArray(issueCredentials) && - !!issueCredentials[1] - ) { - const [, issueCredentialsArr] = issueCredentials; - response.issueCredentials = issueCredentialsArr; - } - - const presentProofs = await this.natsClient.getPresentProofs( - connectionDetails.connectionId, - ); - - if (presentProofs && Array.isArray(presentProofs) && !!presentProofs[1]) { - const [, presentProofsArr] = presentProofs; - response.presentProofs = presentProofsArr; - } - - return response; - } catch (error) { - logger.error(JSON.stringify(error)); - return error; - } - } - - public async makeConnectionTrusted(connectionId: string) { - return this.connectionRepository.updateConnection({ - where: { connectionId }, - data: { - status: ConnectionsService.status.TRUSTED, - updatedDate: new Date(), - }, - }); - } - - public publishConnectionSubscriberEndpoint( - data: ConnectionSubscriptionEndpointDto, - ) { - this.natsClient.publishConnection(data); - } - - public async acceptConnectionInvitation( - agentURL: string, - payload: { - invitationUrl: string; - autoAcceptConnection: boolean; - alias: string; - }, - ) { - return this.restClient.post( - `${agentURL}/connections/receive-invitation-url`, - payload, - ); - } - - public async getReceivedConnections() { - return this.connectionRepository.findConnections({ - where: { isReceived: true }, - select: { connectionId: true }, - }); - } -} diff --git a/apps/connection-manager/src/health/health.controller.ts b/apps/connection-manager/src/health/health.controller.ts deleted file mode 100644 index d298ca3..0000000 --- a/apps/connection-manager/src/health/health.controller.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type ResponseType from '../common/response.js'; - -import { Controller, Get, HttpStatus, Version } from '@nestjs/common'; -import { ApiOperation, ApiResponse } from '@nestjs/swagger'; - -@Controller('health') -export default class HealthController { - private res: ResponseType; - - @Version(['1']) - @Get() - @ApiOperation({ - summary: 'Health check', - description: - 'This call provides the capability to check the service is working and up. The call returns 200 Status Code and current server time in json body', - }) - @ApiResponse({ - status: HttpStatus.OK, - description: 'Service is up and running.', - content: { - 'application/json': { - schema: {}, - examples: { - 'Service is up and running.': { - value: { - statusCode: 200, - message: - 'Thu Jan 01 1970 00:00:00 GMT+0000 (Coordinated Universal Time)', - }, - }, - }, - }, - }, - }) - public getHealth() { - this.res = { - statusCode: HttpStatus.OK, - message: `${new Date()}`, - }; - return this.res; - } -} diff --git a/apps/connection-manager/src/health/health.spec.ts b/apps/connection-manager/src/health/health.spec.ts deleted file mode 100644 index 05fa679..0000000 --- a/apps/connection-manager/src/health/health.spec.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { TestingModule } from '@nestjs/testing'; - -import { HttpStatus } from '@nestjs/common'; -import { Test } from '@nestjs/testing'; - -import HealthController from './health.controller'; - -describe('Health', () => { - let healthController: HealthController; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - imports: [], - controllers: [HealthController], - providers: [], - }).compile(); - healthController = module.get<HealthController>(HealthController); - }); - it('should be defined', () => { - expect(healthController).toBeDefined(); - }); - - it('should call getHealth', () => { - const response = healthController.getHealth(); - expect(response.statusCode).toBe(HttpStatus.OK); - }); -}); diff --git a/apps/connection-manager/src/invitations/dto/receive-invitation.dto.ts b/apps/connection-manager/src/invitations/dto/receive-invitation.dto.ts new file mode 100644 index 0000000..24fd1d8 --- /dev/null +++ b/apps/connection-manager/src/invitations/dto/receive-invitation.dto.ts @@ -0,0 +1,13 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsNotEmpty, IsString, IsUrl } from 'class-validator'; + +export class ReceiveInvitationPayload { + @IsString() + @IsNotEmpty() + @IsUrl({ require_tld: false }) + @ApiProperty({ + description: 'The invitation URL to receive', + example: 'https://example.com/invitation', + }) + public invitationUrl: string; +} diff --git a/apps/connection-manager/src/invitations/invitations.controller.ts b/apps/connection-manager/src/invitations/invitations.controller.ts new file mode 100644 index 0000000..278810c --- /dev/null +++ b/apps/connection-manager/src/invitations/invitations.controller.ts @@ -0,0 +1,158 @@ +import { + Body, + Controller, + HttpStatus, + Post, + Query, + UseInterceptors, + UsePipes, + ValidationPipe, +} from '@nestjs/common'; +import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; +import { MultitenancyParams, ResponseFormatInterceptor } from '@ocm/shared'; + +import { ReceiveInvitationPayload } from './dto/receive-invitation.dto.js'; +import { InvitationsService } from './invitations.service.js'; + +@Controller() +@UsePipes(new ValidationPipe({ transform: true, whitelist: true })) +@UseInterceptors(ResponseFormatInterceptor) +@ApiTags('Invitations') +export class InvitationsController { + public constructor(private readonly service: InvitationsService) {} + + @Post() + @ApiOperation({ + summary: 'Create a new invitation', + description: 'This call creates a new invitation for a given tenant', + }) + @ApiResponse({ + status: HttpStatus.OK, + description: 'Invitation created successfully', + content: { + 'application/json': { + schema: {}, + examples: { + 'Invitation created successfully': { + value: { + statusCode: 200, + message: 'Invitation created successfully', + data: { + invitationUrl: 'https://example.com/invitation', + }, + }, + }, + }, + }, + }, + }) + @ApiResponse({ + status: HttpStatus.NOT_FOUND, + description: 'Tenant not found', + content: { + 'application/json': { + schema: {}, + examples: { + 'Tenant not found': { + value: { + statusCode: 404, + message: 'Tenant not found', + data: null, + }, + }, + }, + }, + }, + }) + @ApiResponse({ + status: HttpStatus.INTERNAL_SERVER_ERROR, + description: 'Failed to create invitation', + content: { + 'application/json': { + schema: {}, + examples: { + 'Failed to create invitation': { + value: { + statusCode: 500, + message: 'Failed to create invitation', + data: null, + }, + }, + }, + }, + }, + }) + public createInvitation( + @Query() { tenantId }: MultitenancyParams, + ): ReturnType<InvitationsService['createInvitation']> { + return this.service.createInvitation(tenantId); + } + + @Post('receive') + @ApiOperation({ + summary: 'Receive an invitation', + description: 'This call receives an invitation for a given tenant', + }) + @ApiResponse({ + status: HttpStatus.OK, + description: 'Invitation received successfully', + content: { + 'application/json': { + schema: {}, + examples: { + 'Invitation received successfully': { + value: { + statusCode: 200, + message: 'Invitation received successfully', + data: { + connectionId: '123', + }, + }, + }, + }, + }, + }, + }) + @ApiResponse({ + status: HttpStatus.NOT_FOUND, + description: 'Tenant not found', + content: { + 'application/json': { + schema: {}, + examples: { + 'Tenant not found': { + value: { + statusCode: 404, + message: 'Tenant not found', + data: null, + }, + }, + }, + }, + }, + }) + @ApiResponse({ + status: HttpStatus.INTERNAL_SERVER_ERROR, + description: 'Failed to receive invitation', + content: { + 'application/json': { + schema: {}, + examples: { + 'Failed to receive invitation': { + value: { + statusCode: 500, + message: 'Failed to receive invitation', + data: null, + }, + }, + }, + }, + }, + }) + public receiveInvitation( + @Query() { tenantId }: MultitenancyParams, + @Body() { invitationUrl }: ReceiveInvitationPayload, + ): ReturnType<InvitationsService['receiveInvitationFromURL']> { + return this.service.receiveInvitationFromURL(tenantId, invitationUrl); + } +} diff --git a/apps/connection-manager/src/invitations/invitations.module.ts b/apps/connection-manager/src/invitations/invitations.module.ts new file mode 100644 index 0000000..880695c --- /dev/null +++ b/apps/connection-manager/src/invitations/invitations.module.ts @@ -0,0 +1,10 @@ +import { Module } from '@nestjs/common'; + +import { InvitationsController } from './invitations.controller.js'; +import { InvitationsService } from './invitations.service.js'; + +@Module({ + providers: [InvitationsService], + controllers: [InvitationsController], +}) +export class InvitationsModule {} diff --git a/apps/connection-manager/src/invitations/invitations.service.ts b/apps/connection-manager/src/invitations/invitations.service.ts new file mode 100644 index 0000000..6ece9eb --- /dev/null +++ b/apps/connection-manager/src/invitations/invitations.service.ts @@ -0,0 +1,48 @@ +import type { + EventDidcommConnectionsCreateInvitationInput, + EventDidcommConnectionsReceiveInvitationFromUrlInput, +} from '@ocm/shared'; +import type { Observable } from 'rxjs'; + +import { Inject, Injectable } from '@nestjs/common'; +import { ClientProxy } from '@nestjs/microservices'; +import { + EventDidcommConnectionsCreateInvitation, + EventDidcommConnectionsReceiveInvitationFromUrl, +} from '@ocm/shared'; +import { map } from 'rxjs'; + +import { NATS_CLIENT } from '../common/constants.js'; + +@Injectable() +export class InvitationsService { + public constructor( + @Inject(NATS_CLIENT) private readonly natsClient: ClientProxy, + ) {} + + public createInvitation( + tenantId: string, + ): Observable<EventDidcommConnectionsCreateInvitation['data']> { + return this.natsClient + .send< + EventDidcommConnectionsCreateInvitation, + EventDidcommConnectionsCreateInvitationInput + >(EventDidcommConnectionsCreateInvitation.token, { tenantId }) + .pipe(map(({ data }) => data)); + } + + public receiveInvitationFromURL( + tenantId: string, + invitationUrl: string, + ): Observable<EventDidcommConnectionsReceiveInvitationFromUrl['data']> { + return this.natsClient + .send< + EventDidcommConnectionsReceiveInvitationFromUrl, + EventDidcommConnectionsReceiveInvitationFromUrlInput + >(EventDidcommConnectionsReceiveInvitationFromUrl.token, { + tenantId, + invitationUrl, + }) + .pipe(map(({ data }) => data)); + } +} diff --git a/apps/connection-manager/src/main.ts b/apps/connection-manager/src/main.ts index 9049f62..0490cd5 100644 --- a/apps/connection-manager/src/main.ts +++ b/apps/connection-manager/src/main.ts @@ -1,16 +1,15 @@ +/* c8 ignore start */ import type { MicroserviceOptions } from '@nestjs/microservices'; import { VersioningType } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; -import { HttpAdapterHost, NestFactory } from '@nestjs/core'; +import { NestFactory } from '@nestjs/core'; import { Transport } from '@nestjs/microservices'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; -import AppModule from './app.module.js'; -import AllExceptionsFilter from './utils/exceptionsFilter.js'; -import logger from './utils/logger.js'; +import { Application } from './application.js'; -const app = await NestFactory.create(AppModule); +const app = await NestFactory.create(Application); const configService = app.get(ConfigService); app.enableCors(); @@ -22,15 +21,14 @@ app.connectMicroservice<MicroserviceOptions>({ }); app.enableVersioning({ - defaultVersion: ['1', '2'], + defaultVersion: ['1'], type: VersioningType.URI, }); const swaggerConfig = new DocumentBuilder() - .setTitle('Gaia-x Connection Manager API') + .setTitle('Gaia-X Connection Manager API') .setDescription('API documentation for GAIA-X Connection Manager') .setVersion('1.0') - .addServer(`http://localhost:${configService.get('PORT')}`) .build(); const document = SwaggerModule.createDocument(app, swaggerConfig); @@ -38,9 +36,5 @@ const document = SwaggerModule.createDocument(app, swaggerConfig); SwaggerModule.setup('/swagger', app, document); await app.startAllMicroservices(); -const httpAdapter = app.get(HttpAdapterHost); -app.useGlobalFilters(new AllExceptionsFilter(httpAdapter)); - -await app.listen(configService.get('PORT') || 3000, () => { - logger.info(`Listening on Port:${configService.get('PORT')}` || 3000); -}); +await app.listen(configService.get('http.port') as number); +/* c8 ignore stop */ diff --git a/apps/connection-manager/src/middleware/auth.middleware.ts b/apps/connection-manager/src/middleware/auth.middleware.ts deleted file mode 100644 index 40549bf..0000000 --- a/apps/connection-manager/src/middleware/auth.middleware.ts +++ /dev/null @@ -1,86 +0,0 @@ -import type { NestMiddleware } from '@nestjs/common'; -import type { NextFunction, Request, Response } from 'express'; - -import { HttpStatus, Injectable } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; -import jwt from 'jsonwebtoken'; -import jwksClient from 'jwks-rsa'; - -import logger from '../utils/logger.js'; - -@Injectable() -export class AuthMiddleware implements NestMiddleware { - public constructor(private readonly configService: ConfigService) {} - - /* eslint-disable */ - async use(req: Request, res: Response, next: NextFunction) { - if (this.configService.get('auth.useAuth') === 'false') { - return next(); - } - - logger.info('Request at middleware'); - - const authHeader = req.headers.authorization; - const authToken = authHeader && authHeader.split(' ')[1]; - - if (!authToken) { - logger.error('No access token provided.'); - res.json({ - status: HttpStatus.UNAUTHORIZED, - message: 'Unauthorized. No Access token provided.', - data: undefined, - }); - return; - } - - const getKey = ( - header: jwt.JwtHeader, - callback: jwt.SigningKeyCallback, - ): void => { - const jwksUri = this.configService.get('auth.tokenUrl') || ''; - const client = jwksClient({ jwksUri, timeout: 30000 }); - - client - .getSigningKey(header.kid) - .then((key) => callback(null, key.getPublicKey())) - .catch(callback); - }; - - function verify(token: string): Promise<any> | undefined { - return new Promise( - (resolve: (decoded: any) => void, reject: (error: Error) => void) => { - const verifyCallback: jwt.VerifyCallback<jwt.JwtPayload | string> = ( - error: jwt.VerifyErrors | null, - decoded: any, - ): void => { - if (error) { - return reject(error); - } - return resolve(decoded); - }; - - jwt.verify(token, getKey, verifyCallback); - }, - ); - } - - const result = await verify(authToken); - - if (!result) { - logger.error('Invalid access token provided.'); - res.json({ - status: HttpStatus.UNAUTHORIZED, - message: 'Unauthorized. Invalid Access token provided.', - data: undefined, - }); - return; - } - - next(); - } - /* eslint-enable */ -} - -export default { - AuthMiddleware, -}; diff --git a/apps/connection-manager/src/prisma/prisma.module.spec.ts b/apps/connection-manager/src/prisma/prisma.module.spec.ts deleted file mode 100644 index 1f7b6e3..0000000 --- a/apps/connection-manager/src/prisma/prisma.module.spec.ts +++ /dev/null @@ -1,7 +0,0 @@ -import PrismaModule from './prisma.module.js'; - -describe('Check if the module is working', () => { - it('should be defined', () => { - expect(PrismaModule).toBeDefined(); - }); -}); diff --git a/apps/connection-manager/src/prisma/prisma.module.ts b/apps/connection-manager/src/prisma/prisma.module.ts deleted file mode 100644 index c0d718c..0000000 --- a/apps/connection-manager/src/prisma/prisma.module.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Module } from '@nestjs/common'; - -import PrismaService from './prisma.service.js'; - -@Module({ - providers: [PrismaService], - exports: [PrismaService], -}) -export default class PrismaModule {} diff --git a/apps/connection-manager/src/prisma/prisma.service.ts b/apps/connection-manager/src/prisma/prisma.service.ts deleted file mode 100644 index b27f2bf..0000000 --- a/apps/connection-manager/src/prisma/prisma.service.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { OnModuleDestroy, OnModuleInit } from '@nestjs/common'; - -import { Injectable } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; -import { PrismaClient } from '@prisma/client'; - -@Injectable() -export default class PrismaService - extends PrismaClient - implements OnModuleInit, OnModuleDestroy -{ - public constructor(private configService: ConfigService) { - super({ - datasources: { - db: { - url: configService.get('DATABASE_URL'), - }, - }, - }); - } - - public async onModuleInit() { - await this.$connect(); - } - - public async onModuleDestroy() { - await this.$disconnect(); - } -} diff --git a/apps/connection-manager/src/prisma/schema.prisma b/apps/connection-manager/src/prisma/schema.prisma deleted file mode 100644 index 58c5c2d..0000000 --- a/apps/connection-manager/src/prisma/schema.prisma +++ /dev/null @@ -1,26 +0,0 @@ -generator client { - provider = "prisma-client-js" -} - -datasource db { - provider = "postgresql" - url = env("DATABASE_URL") -} - -model Connection { - id String @id @default(uuid()) - connectionId String @unique @map("connection_id") - status String - participantDid String @unique @map("participant_did") - theirDid String @map("their_did") - theirLabel String @map("their_label") - createdDate DateTime @default(now()) @map("created_date") - updatedDate DateTime @default(now()) @map("updated_date") - isActive Boolean @default(true) @map("is_active") - isReceived Boolean @map("is_received") -} - -model ShortUrlConnection { - id String @id @default(uuid()) - connectionUrl String -} diff --git a/apps/connection-manager/src/utils/exceptionsFilter.ts b/apps/connection-manager/src/utils/exceptionsFilter.ts deleted file mode 100644 index 196efca..0000000 --- a/apps/connection-manager/src/utils/exceptionsFilter.ts +++ /dev/null @@ -1,82 +0,0 @@ -import type { ArgumentsHost, ExceptionFilter } from '@nestjs/common'; -import type { Request } from 'express'; - -import { Catch, HttpException, HttpStatus, Logger } from '@nestjs/common'; -import { HttpAdapterHost } from '@nestjs/core'; -import { Prisma } from '@prisma/client'; - -const { PrismaClientKnownRequestError, PrismaClientValidationError } = Prisma; - -@Catch() -export default class AllExceptionsFilter implements ExceptionFilter { - public constructor(private readonly httpAdapterHost: HttpAdapterHost) {} - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - public catch(exception: any, host: ArgumentsHost): void { - const { httpAdapter } = this.httpAdapterHost; - - const ctx = host.switchToHttp(); - const request = ctx.getRequest<Request>(); - - let httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; - let message = ''; - switch (exception.constructor) { - case HttpException: - httpStatus = (exception as HttpException).getStatus(); - message = exception?.message || 'Internal server error'; - break; - case PrismaClientKnownRequestError: - switch (exception.code) { - case 'P2002': // Unique constraint failed on the {constraint} - case 'P2000': // The provided value for the column is too long for the column's type. Column: {column_name} - case 'P2001': // The record searched for in the where condition ({model_name}.{argument_name} = {argument_value}) does not exist - case 'P2005': // The value {field_value} stored in the database for the field {field_name} is invalid for the field's type - case 'P2006': // The provided value {field_value} for {model_name} field {field_name} is not valid - case 'P2010': // Raw query failed. Code: {code}. Message: {message} - case 'P2011': // Null constraint violation on the {constraint} - case 'P2017': // The records for relation {relation_name} between the {parent_name} and {child_name} models are not connected. - case 'P2021': // The table {table} does not exist in the current database. - case 'P2022': // The column {column} does not exist in the current database. - httpStatus = HttpStatus.BAD_REQUEST; - message = exception?.message; - break; - case 'P2018': // The required connected records were not found. {details} - case 'P2025': // An operation failed because it depends on one or more records that were required but not found. {cause} - case 'P2015': // A related record could not be found. {details} - httpStatus = HttpStatus.NOT_FOUND; - message = exception?.message; - break; - default: - httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; - message = exception?.message || 'Internal server error'; - } - break; - case PrismaClientValidationError: - httpStatus = HttpStatus.BAD_REQUEST; - message = exception?.message; - break; - default: - httpStatus = - exception.response?.status || HttpStatus.INTERNAL_SERVER_ERROR; - message = - exception.response?.data?.message || - exception?.message || - 'Internal server error'; - } - - Logger.error( - 'Exception Filter :', - message, - (exception as Error).stack, - `${request.method} ${request.url}`, - ); - - const responseBody = { - statusCode: httpStatus, - timestamp: new Date().toISOString(), - message, - }; - - httpAdapter.reply(ctx.getResponse(), responseBody, httpStatus); - } -} diff --git a/apps/connection-manager/src/utils/logger.spec.ts b/apps/connection-manager/src/utils/logger.spec.ts deleted file mode 100644 index 04293dc..0000000 --- a/apps/connection-manager/src/utils/logger.spec.ts +++ /dev/null @@ -1,12 +0,0 @@ -import fs from 'node:fs'; - -describe('Logger', () => { - it('should create a directory if not exists', async () => { - jest.spyOn(fs, 'existsSync').mockImplementation(() => false); - jest.spyOn(fs, 'mkdirSync').mockImplementation(() => 'mocked'); - const logger = await import('./logger.js'); - expect(logger).toBeDefined(); - expect(fs.existsSync).toHaveBeenCalled(); - expect(fs.mkdirSync).toHaveBeenCalled(); - }); -}); diff --git a/apps/connection-manager/src/utils/logger.ts b/apps/connection-manager/src/utils/logger.ts deleted file mode 100644 index b1958d5..0000000 --- a/apps/connection-manager/src/utils/logger.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { Logger } from 'winston'; - -import { ecsFormat } from '@elastic/ecs-winston-format'; -import { createLogger, transports } from 'winston'; - -const logger: Logger = createLogger({ - format: ecsFormat({ convertReqRes: true }), - - transports: [new transports.Console()], -}); - -logger.on('error', (error) => { - // eslint-disable-next-line no-console - console.error('Error in logger caught', error); -}); - -export default logger; diff --git a/apps/connection-manager/src/utils/nats.ts b/apps/connection-manager/src/utils/nats.ts deleted file mode 100644 index 6eede1a..0000000 --- a/apps/connection-manager/src/utils/nats.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { NatsConnection } from 'nats'; - -import { connect, StringCodec } from 'nats'; - -const sc = StringCodec(); - -export default class Nats { - private static nc: NatsConnection | null = null; - - public static async initialize(natsConfig: { - servers: Array<string> | string; - name: string; - }): Promise<NatsConnection | null> { - this.nc = await connect(natsConfig); - - return this.nc; - } - - public static async publish(subject: string, payload: string) { - if (this.nc) { - this.nc.publish(subject, sc.encode(payload)); - } else { - throw new Error('Initialize Nats First!!'); - } - } - - public static async subscribe( - subject: string, - cb: (...args: unknown[]) => unknown, - ) { - if (this.nc) { - const sub = this.nc.subscribe(subject); - for await (const m of sub) { - cb(sc.decode(m.data)); - } - } else { - throw new Error('Initialize Nats First!!'); - } - } -} diff --git a/apps/connection-manager/src/utils/pagination.spec.ts b/apps/connection-manager/src/utils/pagination.spec.ts deleted file mode 100644 index e517f67..0000000 --- a/apps/connection-manager/src/utils/pagination.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -import pagination from './pagination.js'; - -describe('Check if the module is working', () => { - it('should be defined', () => { - expect(pagination).toBeDefined(); - }); - - it('should be return default value', () => { - const result = { skip: 0, take: 1000 }; - expect(pagination(0, 0)).toStrictEqual(result); - }); - - it('should be return next page value', () => { - const result = { skip: 0, take: 10 }; - expect(pagination(10, 0)).toStrictEqual(result); - }); -}); diff --git a/apps/connection-manager/src/utils/pagination.ts b/apps/connection-manager/src/utils/pagination.ts deleted file mode 100644 index a498e61..0000000 --- a/apps/connection-manager/src/utils/pagination.ts +++ /dev/null @@ -1,16 +0,0 @@ -const pagination = (pageSize: number, page: number) => { - const query: { - skip?: number; - take?: number; - } = {}; - if (pageSize && (page || page === 0)) { - query.skip = page * pageSize; - query.take = pageSize; - } else { - query.skip = 0; - query.take = 1000; - } - return query; -}; - -export default pagination; diff --git a/apps/shared/package.json b/apps/shared/package.json index b2bba58..7058964 100644 --- a/apps/shared/package.json +++ b/apps/shared/package.json @@ -26,22 +26,22 @@ "@aries-framework/tenants": "^0.4.2", "@elastic/ecs-winston-format": "^1.5.0", "@nestjs/axios": "^3.0.1", - "@nestjs/common": "^10.2.10", + "@nestjs/common": "^10.3.0", "@nestjs/config": "^3.1.1", - "@nestjs/microservices": "^10.2.10", - "@nestjs/swagger": "^7.1.16", - "@nestjs/terminus": "^10.1.1", + "@nestjs/microservices": "^10.3.0", + "@nestjs/swagger": "^7.1.17", + "@nestjs/terminus": "^10.2.0", "axios": "^1.6.2", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", "joi": "^17.6.0", "nats": "^2.18.0", - "rxjs": "^7.2.0", + "rxjs": "^7.8.1", "winston": "^3.11.0" }, "devDependencies": { "@nestjs/cli": "^10.2.1", - "@nestjs/testing": "^10.2.10", + "@nestjs/testing": "^10.3.0", "@types/jest": "^29.5.9", "@types/node": "^20.9.3", "rimraf": "^5.0.5", @@ -49,6 +49,6 @@ "ts-jest": "^29.1.1", "ts-node": "^10.0.0", "tsconfig-paths": "^4.2.0", - "typescript": "~5.3.2" + "typescript": "^5.3.3" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 66e7a66..7b98974 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,16 +10,16 @@ importers: devDependencies: '@commitlint/cli': specifier: ^18.4.2 - version: 18.4.3(typescript@5.3.2) + version: 18.4.3(typescript@5.3.3) '@commitlint/config-conventional': specifier: ^18.4.2 version: 18.4.3 '@typescript-eslint/eslint-plugin': specifier: ^6.12.0 - version: 6.12.0(@typescript-eslint/parser@6.12.0)(eslint@8.54.0)(typescript@5.3.2) + version: 6.12.0(@typescript-eslint/parser@6.12.0)(eslint@8.54.0)(typescript@5.3.3) '@typescript-eslint/parser': specifier: ^6.12.0 - version: 6.12.0(eslint@8.54.0)(typescript@5.3.2) + version: 6.12.0(eslint@8.54.0)(typescript@5.3.3) eslint: specifier: ^8.54.0 version: 8.54.0 @@ -195,42 +195,33 @@ importers: apps/connection-manager: dependencies: - '@elastic/ecs-winston-format': - specifier: ^1.5.0 - version: 1.5.0 - '@nestjs/axios': - specifier: ^3.0.1 - version: 3.0.1(@nestjs/common@10.2.8)(axios@1.6.2)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@nestjs/common': - specifier: ^10.2.8 - version: 10.2.8(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + specifier: ^10.3.0 + version: 10.3.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@nestjs/config': specifier: ^3.1.1 - version: 3.1.1(@nestjs/common@10.2.8)(reflect-metadata@0.1.13) + version: 3.1.1(@nestjs/common@10.3.0)(reflect-metadata@0.1.13) '@nestjs/core': - specifier: ^10.2.8 - version: 10.2.8(@nestjs/common@10.2.8)(@nestjs/microservices@10.2.8)(@nestjs/platform-express@10.2.8)(reflect-metadata@0.1.13)(rxjs@7.8.1) - '@nestjs/mapped-types': - specifier: ^2.0.4 - version: 2.0.4(@nestjs/common@10.2.8)(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13) + specifier: ^10.3.0 + version: 10.3.0(@nestjs/common@10.3.0)(@nestjs/microservices@10.3.0)(@nestjs/platform-express@10.3.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@nestjs/microservices': - specifier: ^10.2.8 - version: 10.2.8(@nestjs/common@10.2.8)(@nestjs/core@10.2.8)(nats@2.18.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + specifier: ^10.3.0 + version: 10.3.0(@nestjs/common@10.3.0)(@nestjs/core@10.3.0)(nats@2.18.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@nestjs/platform-express': - specifier: ^10.2.8 - version: 10.2.8(@nestjs/common@10.2.8)(@nestjs/core@10.2.8) + specifier: ^10.3.0 + version: 10.3.0(@nestjs/common@10.3.0)(@nestjs/core@10.3.0) '@nestjs/schedule': specifier: ^4.0.0 - version: 4.0.0(@nestjs/common@10.2.8)(@nestjs/core@10.2.8)(reflect-metadata@0.1.13) + version: 4.0.0(@nestjs/common@10.3.0)(@nestjs/core@10.3.0)(reflect-metadata@0.1.13) '@nestjs/swagger': - specifier: ^7.1.16 - version: 7.1.16(@nestjs/common@10.2.8)(@nestjs/core@10.2.8)(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13) - '@nestjs/terminus': - specifier: ^10.1.1 - version: 10.1.1(@nestjs/axios@3.0.1)(@nestjs/common@10.2.8)(@nestjs/core@10.2.8)(@nestjs/microservices@10.2.8)(@prisma/client@5.6.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) - '@prisma/client': - specifier: ^5.6.0 - version: 5.6.0(prisma@5.6.0) + specifier: ^7.1.17 + version: 7.1.17(@nestjs/common@10.3.0)(@nestjs/core@10.3.0)(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13) + '@ocm/shared': + specifier: workspace:* + version: link:../shared + class-transformer: + specifier: ^0.5.1 + version: 0.5.1 class-validator: specifier: ^0.14.0 version: 0.14.0 @@ -240,15 +231,6 @@ importers: joi: specifier: ^17.11.0 version: 17.11.0 - jsonwebtoken: - specifier: ^9.0.2 - version: 9.0.2 - jwks-rsa: - specifier: ^3.1.0 - version: 3.1.0 - moment: - specifier: ^2.29.4 - version: 2.29.4 nats: specifier: ^2.18.0 version: 2.18.0 @@ -258,82 +240,46 @@ importers: rxjs: specifier: ^7.8.1 version: 7.8.1 - winston: - specifier: ^3.11.0 - version: 3.11.0 - winston-elasticsearch: - specifier: ^0.17.4 - version: 0.17.4 devDependencies: '@jest/globals': specifier: ^29.7.0 version: 29.7.0 '@nestjs/cli': specifier: ^10.2.1 - version: 10.2.1(@swc/cli@0.1.63)(@swc/core@1.3.96) + version: 10.2.1(@swc/cli@0.1.63)(@swc/core@1.3.101) '@nestjs/schematics': specifier: ^10.0.3 - version: 10.0.3(chokidar@3.5.3)(typescript@5.2.2) + version: 10.0.3(typescript@5.3.3) '@nestjs/testing': - specifier: ^10.2.8 - version: 10.2.8(@nestjs/common@10.2.8)(@nestjs/core@10.2.8)(@nestjs/microservices@10.2.8)(@nestjs/platform-express@10.2.8) + specifier: ^10.3.0 + version: 10.3.0(@nestjs/common@10.3.0)(@nestjs/core@10.3.0)(@nestjs/microservices@10.3.0)(@nestjs/platform-express@10.3.0) '@swc/cli': - specifier: ^0.1.62 - version: 0.1.63(@swc/core@1.3.96) + specifier: ^0.1.63 + version: 0.1.63(@swc/core@1.3.101) '@swc/core': - specifier: ^1.3.96 - version: 1.3.96 + specifier: ^1.3.101 + version: 1.3.101 '@swc/jest': specifier: ^0.2.29 - version: 0.2.29(@swc/core@1.3.96) + version: 0.2.29(@swc/core@1.3.101) '@types/express': specifier: ^4.17.21 version: 4.17.21 '@types/jest': - specifier: 27.0.2 - version: 27.0.2 - '@types/jsonwebtoken': - specifier: ^9.0.5 - version: 9.0.5 + specifier: 29.5.11 + version: 29.5.11 '@types/node': - specifier: ^20.9.0 - version: 20.9.0 - '@types/simple-oauth2': - specifier: ^5.0.7 - version: 5.0.7 - '@types/supertest': - specifier: ^2.0.16 - version: 2.0.16 - dotenv-cli: - specifier: ^7.3.0 - version: 7.3.0 + specifier: ^20.10.5 + version: 20.10.5 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.9.0)(ts-node@10.9.1) - node-mocks-http: - specifier: ^1.13.0 - version: 1.13.0 - prisma: - specifier: ^5.6.0 - version: 5.6.0 + version: 29.7.0(@types/node@20.10.5) rimraf: specifier: ^5.0.5 version: 5.0.5 - source-map-support: - specifier: ^0.5.21 - version: 0.5.21 - supertest: - specifier: ^6.3.3 - version: 6.3.3 - swagger-ui-express: - specifier: ^5.0.0 - version: 5.0.0(express@4.18.2) - ts-node: - specifier: ^10.9.1 - version: 10.9.1(@swc/core@1.3.96)(@types/node@20.9.0)(typescript@5.2.2) typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 apps/credential-manager: dependencies: @@ -421,7 +367,7 @@ importers: version: 8.54.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.9.4) + version: 29.7.0(@types/node@20.9.4)(ts-node@10.9.1) rimraf: specifier: ^5.0.5 version: 5.0.5 @@ -657,7 +603,7 @@ importers: version: 8.54.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.9.4) + version: 29.7.0(@types/node@20.9.4)(ts-node@10.9.1) rimraf: specifier: ^5.0.5 version: 5.0.5 @@ -681,22 +627,22 @@ importers: version: 1.5.0 '@nestjs/axios': specifier: ^3.0.1 - version: 3.0.1(@nestjs/common@10.2.10)(axios@1.6.2)(reflect-metadata@0.1.13)(rxjs@7.8.1) + version: 3.0.1(@nestjs/common@10.3.0)(axios@1.6.2)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@nestjs/common': - specifier: ^10.2.10 - version: 10.2.10(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + specifier: ^10.3.0 + version: 10.3.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@nestjs/config': specifier: ^3.1.1 - version: 3.1.1(@nestjs/common@10.2.10)(reflect-metadata@0.1.13) + version: 3.1.1(@nestjs/common@10.3.0)(reflect-metadata@0.1.13) '@nestjs/microservices': - specifier: ^10.2.10 - version: 10.2.10(@nestjs/common@10.2.10)(@nestjs/core@10.2.10)(nats@2.18.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + specifier: ^10.3.0 + version: 10.3.0(@nestjs/common@10.3.0)(@nestjs/core@10.3.0)(nats@2.18.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@nestjs/swagger': - specifier: ^7.1.16 - version: 7.1.16(@nestjs/common@10.2.10)(@nestjs/core@10.2.10)(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13) + specifier: ^7.1.17 + version: 7.1.17(@nestjs/common@10.3.0)(@nestjs/core@10.3.0)(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13) '@nestjs/terminus': - specifier: ^10.1.1 - version: 10.1.1(@nestjs/axios@3.0.1)(@nestjs/common@10.2.10)(@nestjs/core@10.2.10)(@nestjs/microservices@10.2.10)(reflect-metadata@0.1.13)(rxjs@7.8.1) + specifier: ^10.2.0 + version: 10.2.0(@nestjs/axios@3.0.1)(@nestjs/common@10.3.0)(@nestjs/core@10.3.0)(@nestjs/microservices@10.3.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) axios: specifier: ^1.6.2 version: 1.6.2 @@ -713,7 +659,7 @@ importers: specifier: ^2.18.0 version: 2.18.0 rxjs: - specifier: ^7.2.0 + specifier: ^7.8.1 version: 7.8.1 winston: specifier: ^3.11.0 @@ -723,8 +669,8 @@ importers: specifier: ^10.2.1 version: 10.2.1 '@nestjs/testing': - specifier: ^10.2.10 - version: 10.2.10(@nestjs/common@10.2.10)(@nestjs/core@10.2.10)(@nestjs/microservices@10.2.10)(@nestjs/platform-express@10.2.8) + specifier: ^10.3.0 + version: 10.3.0(@nestjs/common@10.3.0)(@nestjs/core@10.3.0)(@nestjs/microservices@10.3.0)(@nestjs/platform-express@10.3.0) '@types/jest': specifier: ^29.5.9 version: 29.5.10 @@ -739,16 +685,16 @@ importers: version: 6.3.3 ts-jest: specifier: ^29.1.1 - version: 29.1.1(@babel/core@7.23.0)(jest@29.7.0)(typescript@5.3.2) + version: 29.1.1(@babel/core@7.23.0)(jest@29.7.0)(typescript@5.3.3) ts-node: specifier: ^10.0.0 - version: 10.9.1(@types/node@20.9.4)(typescript@5.3.2) + version: 10.9.1(@types/node@20.9.4)(typescript@5.3.3) tsconfig-paths: specifier: ^4.2.0 version: 4.2.0 typescript: - specifier: ~5.3.2 - version: 5.3.2 + specifier: ^5.3.3 + version: 5.3.3 apps/ssi-abstraction: dependencies: @@ -2648,14 +2594,14 @@ packages: engines: {node: '>=0.1.90'} dev: false - /@commitlint/cli@18.4.3(typescript@5.3.2): + /@commitlint/cli@18.4.3(typescript@5.3.3): resolution: {integrity: sha512-zop98yfB3A6NveYAZ3P1Mb6bIXuCeWgnUfVNkH4yhIMQpQfzFwseadazOuSn0OOfTt0lWuFauehpm9GcqM5lww==} engines: {node: '>=v18'} hasBin: true dependencies: '@commitlint/format': 18.4.3 '@commitlint/lint': 18.4.3 - '@commitlint/load': 18.4.3(typescript@5.3.2) + '@commitlint/load': 18.4.3(typescript@5.3.3) '@commitlint/read': 18.4.3 '@commitlint/types': 18.4.3 execa: 5.1.1 @@ -2725,7 +2671,7 @@ packages: '@commitlint/types': 18.4.3 dev: true - /@commitlint/load@18.4.3(typescript@5.3.2): + /@commitlint/load@18.4.3(typescript@5.3.3): resolution: {integrity: sha512-v6j2WhvRQJrcJaj5D+EyES2WKTxPpxENmNpNG3Ww8MZGik3jWRXtph0QTzia5ZJyPh2ib5aC/6BIDymkUUM58Q==} engines: {node: '>=v18'} dependencies: @@ -2735,8 +2681,8 @@ packages: '@commitlint/types': 18.4.3 '@types/node': 18.18.10 chalk: 4.1.2 - cosmiconfig: 8.3.6(typescript@5.3.2) - cosmiconfig-typescript-loader: 5.0.0(@types/node@18.18.10)(cosmiconfig@8.3.6)(typescript@5.3.2) + cosmiconfig: 8.3.6(typescript@5.3.3) + cosmiconfig-typescript-loader: 5.0.0(@types/node@18.18.10)(cosmiconfig@8.3.6)(typescript@5.3.3) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -3500,7 +3446,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.9.4 + '@types/node': 20.10.5 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -3571,7 +3517,7 @@ packages: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.9.4 + '@types/node': 20.10.5 jest-mock: 29.7.0 /@jest/expect-utils@29.7.0: @@ -3597,7 +3543,7 @@ packages: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.9.4 + '@types/node': 20.10.5 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -3629,7 +3575,7 @@ packages: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.19 - '@types/node': 20.9.4 + '@types/node': 20.10.5 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -3715,7 +3661,7 @@ packages: dependencies: '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.2 - '@types/node': 20.9.4 + '@types/node': 20.10.5 '@types/yargs': 15.0.18 chalk: 4.1.2 dev: false @@ -3727,7 +3673,7 @@ packages: dependencies: '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.2 - '@types/node': 20.9.4 + '@types/node': 20.10.5 '@types/yargs': 16.0.6 chalk: 4.1.2 @@ -3738,7 +3684,7 @@ packages: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.2 - '@types/node': 20.9.4 + '@types/node': 20.10.5 '@types/yargs': 17.0.31 chalk: 4.1.2 @@ -3848,6 +3794,20 @@ packages: rxjs: 7.8.1 dev: false + /@nestjs/axios@3.0.1(@nestjs/common@10.3.0)(axios@1.6.2)(reflect-metadata@0.1.13)(rxjs@7.8.1): + resolution: {integrity: sha512-VlOZhAGDmOoFdsmewn8AyClAdGpKXQQaY1+3PGB+g6ceurGIdTxZgRX3VXc1T6Zs60PedWjg3A82TDOB05mrzQ==} + peerDependencies: + '@nestjs/common': ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 + axios: ^1.3.1 + reflect-metadata: ^0.1.12 + rxjs: ^6.0.0 || ^7.0.0 + dependencies: + '@nestjs/common': 10.3.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + axios: 1.6.2 + reflect-metadata: 0.1.13 + rxjs: 7.8.1 + dev: false + /@nestjs/cli@10.2.1: resolution: {integrity: sha512-CAJAQwmxFZfB3RTvqz/eaXXWpyU+mZ4QSqfBYzjneTsPgF+uyOAW3yQpaLNn9Dfcv39R9UxSuAhayv6yuFd+Jg==} engines: {node: '>= 16.14'} @@ -3890,6 +3850,50 @@ packages: - webpack-cli dev: true + /@nestjs/cli@10.2.1(@swc/cli@0.1.63)(@swc/core@1.3.101): + resolution: {integrity: sha512-CAJAQwmxFZfB3RTvqz/eaXXWpyU+mZ4QSqfBYzjneTsPgF+uyOAW3yQpaLNn9Dfcv39R9UxSuAhayv6yuFd+Jg==} + engines: {node: '>= 16.14'} + hasBin: true + peerDependencies: + '@swc/cli': ^0.1.62 + '@swc/core': ^1.3.62 + peerDependenciesMeta: + '@swc/cli': + optional: true + '@swc/core': + optional: true + dependencies: + '@angular-devkit/core': 16.2.8(chokidar@3.5.3) + '@angular-devkit/schematics': 16.2.8(chokidar@3.5.3) + '@angular-devkit/schematics-cli': 16.2.8(chokidar@3.5.3) + '@nestjs/schematics': 10.0.3(chokidar@3.5.3)(typescript@5.2.2) + '@swc/cli': 0.1.63(@swc/core@1.3.101) + '@swc/core': 1.3.101 + chalk: 4.1.2 + chokidar: 3.5.3 + cli-table3: 0.6.3 + commander: 4.1.1 + fork-ts-checker-webpack-plugin: 9.0.2(typescript@5.2.2)(webpack@5.89.0) + glob: 10.3.10 + inquirer: 8.2.6 + node-emoji: 1.11.0 + ora: 5.4.1 + os-name: 4.0.1 + rimraf: 4.4.1 + shelljs: 0.8.5 + source-map-support: 0.5.21 + tree-kill: 1.2.2 + tsconfig-paths: 4.2.0 + tsconfig-paths-webpack-plugin: 4.1.0 + typescript: 5.2.2 + webpack: 5.89.0(@swc/core@1.3.101) + webpack-node-externals: 3.0.0 + transitivePeerDependencies: + - esbuild + - uglify-js + - webpack-cli + dev: true + /@nestjs/cli@10.2.1(@swc/cli@0.1.63)(@swc/core@1.3.96): resolution: {integrity: sha512-CAJAQwmxFZfB3RTvqz/eaXXWpyU+mZ4QSqfBYzjneTsPgF+uyOAW3yQpaLNn9Dfcv39R9UxSuAhayv6yuFd+Jg==} engines: {node: '>= 16.14'} @@ -3976,6 +3980,27 @@ packages: tslib: 2.6.2 uid: 2.0.2 + /@nestjs/common@10.3.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1): + resolution: {integrity: sha512-DGv34UHsZBxCM3H5QGE2XE/+oLJzz5+714JQjBhjD9VccFlQs3LRxo/epso4l7nJIiNlZkPyIUC8WzfU/5RTsQ==} + peerDependencies: + class-transformer: '*' + class-validator: '*' + reflect-metadata: ^0.1.12 + rxjs: ^7.1.0 + peerDependenciesMeta: + class-transformer: + optional: true + class-validator: + optional: true + dependencies: + class-transformer: 0.5.1 + class-validator: 0.14.0 + iterare: 1.2.1 + reflect-metadata: 0.1.13 + rxjs: 7.8.1 + tslib: 2.6.2 + uid: 2.0.2 + /@nestjs/config@3.1.1(@nestjs/common@10.2.10)(reflect-metadata@0.1.13): resolution: {integrity: sha512-qu5QlNiJdqQtOsnB6lx4JCXPQ96jkKUsOGd+JXfXwqJqZcOSAq6heNFg0opW4pq4J/VZoNwoo87TNnx9wthnqQ==} peerDependencies: @@ -4004,6 +4029,20 @@ packages: uuid: 9.0.0 dev: false + /@nestjs/config@3.1.1(@nestjs/common@10.3.0)(reflect-metadata@0.1.13): + resolution: {integrity: sha512-qu5QlNiJdqQtOsnB6lx4JCXPQ96jkKUsOGd+JXfXwqJqZcOSAq6heNFg0opW4pq4J/VZoNwoo87TNnx9wthnqQ==} + peerDependencies: + '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 + reflect-metadata: ^0.1.13 + dependencies: + '@nestjs/common': 10.3.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + dotenv: 16.3.1 + dotenv-expand: 10.0.0 + lodash: 4.17.21 + reflect-metadata: 0.1.13 + uuid: 9.0.0 + dev: false + /@nestjs/core@10.2.10(@nestjs/common@10.2.10)(@nestjs/microservices@10.2.10)(@nestjs/platform-express@10.2.8)(reflect-metadata@0.1.13)(rxjs@7.8.1): resolution: {integrity: sha512-+ckOI6BPi2ZMHikT9MCG4ctHDc4OnjhoIytrn7f2AYMMXI4bnutJhqyQKc30VDka5x3Wq6QAD57pgSP7y+JjJg==} requiresBuild: true @@ -4068,6 +4107,38 @@ packages: transitivePeerDependencies: - encoding + /@nestjs/core@10.3.0(@nestjs/common@10.3.0)(@nestjs/microservices@10.3.0)(@nestjs/platform-express@10.3.0)(reflect-metadata@0.1.13)(rxjs@7.8.1): + resolution: {integrity: sha512-N06P5ncknW/Pm8bj964WvLIZn2gNhHliCBoAO1LeBvNImYkecqKcrmLbY49Fa1rmMfEM3MuBHeDys3edeuYAOA==} + requiresBuild: true + peerDependencies: + '@nestjs/common': ^10.0.0 + '@nestjs/microservices': ^10.0.0 + '@nestjs/platform-express': ^10.0.0 + '@nestjs/websockets': ^10.0.0 + reflect-metadata: ^0.1.12 + rxjs: ^7.1.0 + peerDependenciesMeta: + '@nestjs/microservices': + optional: true + '@nestjs/platform-express': + optional: true + '@nestjs/websockets': + optional: true + dependencies: + '@nestjs/common': 10.3.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/microservices': 10.3.0(@nestjs/common@10.3.0)(@nestjs/core@10.3.0)(nats@2.18.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/platform-express': 10.3.0(@nestjs/common@10.3.0)(@nestjs/core@10.3.0) + '@nuxtjs/opencollective': 0.3.2 + fast-safe-stringify: 2.1.1 + iterare: 1.2.1 + path-to-regexp: 3.2.0 + reflect-metadata: 0.1.13 + rxjs: 7.8.1 + tslib: 2.6.2 + uid: 2.0.2 + transitivePeerDependencies: + - encoding + /@nestjs/mapped-types@2.0.3(@nestjs/common@10.2.10)(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13): resolution: {integrity: sha512-40Zdqg98lqoF0+7ThWIZFStxgzisK6GG22+1ABO4kZiGF/Tu2FE+DYLw+Q9D94vcFWizJ+MSjNN4ns9r6hIGxw==} peerDependencies: @@ -4125,6 +4196,25 @@ packages: reflect-metadata: 0.1.13 dev: false + /@nestjs/mapped-types@2.0.4(@nestjs/common@10.3.0)(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13): + resolution: {integrity: sha512-xl+gUSp0B+ln1VSNoUftlglk8dfpUes3DHGxKZ5knuBxS5g2H/8p9/DSBOYWUfO5f4u9s6ffBPZ71WO+tbe5SA==} + peerDependencies: + '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 + class-transformer: ^0.4.0 || ^0.5.0 + class-validator: ^0.13.0 || ^0.14.0 + reflect-metadata: ^0.1.12 + peerDependenciesMeta: + class-transformer: + optional: true + class-validator: + optional: true + dependencies: + '@nestjs/common': 10.3.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + class-transformer: 0.5.1 + class-validator: 0.14.0 + reflect-metadata: 0.1.13 + dev: false + /@nestjs/microservices@10.2.10(@nestjs/common@10.2.10)(@nestjs/core@10.2.10)(nats@2.18.0)(reflect-metadata@0.1.13)(rxjs@7.8.1): resolution: {integrity: sha512-vebXc4lF67grtLr3UXc+rPErH5aCzCez1Y2Oec4k2K4ObhjftNug7L2O9W3XiprHlwPhPXc51VQ9nhKn7IFAxw==} peerDependencies: @@ -4213,20 +4303,64 @@ packages: rxjs: 7.8.1 tslib: 2.6.2 - /@nestjs/platform-express@10.2.8(@nestjs/common@10.2.10)(@nestjs/core@10.2.10): - resolution: {integrity: sha512-WoSSVtwIRc5AdGMHWVzWZK4JZLT0f4o2xW8P9gQvcX+omL8W1kXCfY8GQYXNBG84XmBNYH8r0FtC8oMe/lH5NQ==} + /@nestjs/microservices@10.3.0(@nestjs/common@10.3.0)(@nestjs/core@10.3.0)(nats@2.18.0)(reflect-metadata@0.1.13)(rxjs@7.8.1): + resolution: {integrity: sha512-CZj27dEN4Rh6t9cRXv5EEg+HwkOUk02DDdS7x4eLcphnP4wgsLNDEo8vQ2gbQHFGpZhLUyeeynjNGkpV9T3+og==} peerDependencies: + '@grpc/grpc-js': '*' '@nestjs/common': ^10.0.0 '@nestjs/core': ^10.0.0 - dependencies: - '@nestjs/common': 10.2.10(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) - '@nestjs/core': 10.2.10(@nestjs/common@10.2.10)(@nestjs/microservices@10.2.10)(@nestjs/platform-express@10.2.8)(reflect-metadata@0.1.13)(rxjs@7.8.1) - body-parser: 1.20.2 - cors: 2.8.5 - express: 4.18.2 - multer: 1.4.4-lts.1 - tslib: 2.6.2 - transitivePeerDependencies: + '@nestjs/websockets': ^10.0.0 + amqp-connection-manager: '*' + amqplib: '*' + cache-manager: '*' + ioredis: '*' + kafkajs: '*' + mqtt: '*' + nats: '*' + reflect-metadata: ^0.1.12 + rxjs: ^7.1.0 + peerDependenciesMeta: + '@grpc/grpc-js': + optional: true + '@nestjs/websockets': + optional: true + amqp-connection-manager: + optional: true + amqplib: + optional: true + cache-manager: + optional: true + ioredis: + optional: true + kafkajs: + optional: true + mqtt: + optional: true + nats: + optional: true + dependencies: + '@nestjs/common': 10.3.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/core': 10.3.0(@nestjs/common@10.3.0)(@nestjs/microservices@10.3.0)(@nestjs/platform-express@10.3.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + iterare: 1.2.1 + nats: 2.18.0 + reflect-metadata: 0.1.13 + rxjs: 7.8.1 + tslib: 2.6.2 + + /@nestjs/platform-express@10.2.8(@nestjs/common@10.2.10)(@nestjs/core@10.2.10): + resolution: {integrity: sha512-WoSSVtwIRc5AdGMHWVzWZK4JZLT0f4o2xW8P9gQvcX+omL8W1kXCfY8GQYXNBG84XmBNYH8r0FtC8oMe/lH5NQ==} + peerDependencies: + '@nestjs/common': ^10.0.0 + '@nestjs/core': ^10.0.0 + dependencies: + '@nestjs/common': 10.2.10(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/core': 10.2.10(@nestjs/common@10.2.10)(@nestjs/microservices@10.2.10)(@nestjs/platform-express@10.2.8)(reflect-metadata@0.1.13)(rxjs@7.8.1) + body-parser: 1.20.2 + cors: 2.8.5 + express: 4.18.2 + multer: 1.4.4-lts.1 + tslib: 2.6.2 + transitivePeerDependencies: - supports-color /@nestjs/platform-express@10.2.8(@nestjs/common@10.2.8)(@nestjs/core@10.2.8): @@ -4245,15 +4379,31 @@ packages: transitivePeerDependencies: - supports-color - /@nestjs/schedule@4.0.0(@nestjs/common@10.2.8)(@nestjs/core@10.2.8)(reflect-metadata@0.1.13): + /@nestjs/platform-express@10.3.0(@nestjs/common@10.3.0)(@nestjs/core@10.3.0): + resolution: {integrity: sha512-E4hUW48bYv8OHbP9XQg6deefmXb0pDSSuE38SdhA0mJ37zGY7C5EqqBUdlQk4ttfD+OdnbIgJ1zOokT6dd2d7A==} + peerDependencies: + '@nestjs/common': ^10.0.0 + '@nestjs/core': ^10.0.0 + dependencies: + '@nestjs/common': 10.3.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/core': 10.3.0(@nestjs/common@10.3.0)(@nestjs/microservices@10.3.0)(@nestjs/platform-express@10.3.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + body-parser: 1.20.2 + cors: 2.8.5 + express: 4.18.2 + multer: 1.4.4-lts.1 + tslib: 2.6.2 + transitivePeerDependencies: + - supports-color + + /@nestjs/schedule@4.0.0(@nestjs/common@10.3.0)(@nestjs/core@10.3.0)(reflect-metadata@0.1.13): resolution: {integrity: sha512-zz4h54m/F/1qyQKvMJCRphmuwGqJltDAkFxUXCVqJBXEs5kbPt93Pza3heCQOcMH22MZNhGlc9DmDMLXVHmgVQ==} peerDependencies: '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 '@nestjs/core': ^8.0.0 || ^9.0.0 || ^10.0.0 reflect-metadata: ^0.1.12 dependencies: - '@nestjs/common': 10.2.8(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) - '@nestjs/core': 10.2.8(@nestjs/common@10.2.8)(@nestjs/microservices@10.2.8)(@nestjs/platform-express@10.2.8)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/common': 10.3.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/core': 10.3.0(@nestjs/common@10.3.0)(@nestjs/microservices@10.3.0)(@nestjs/platform-express@10.3.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) cron: 3.1.3 reflect-metadata: 0.1.13 uuid: 9.0.1 @@ -4289,6 +4439,21 @@ packages: - chokidar dev: true + /@nestjs/schematics@10.0.3(typescript@5.3.3): + resolution: {integrity: sha512-2BRujK0GqGQ7j1Zpz+obVfskDnnOeVKt5aXoSaVngKo8Oczy8uYCY+R547TQB+Kf35epdfFER2pVnQrX3/It5A==} + peerDependencies: + typescript: '>=4.8.2' + dependencies: + '@angular-devkit/core': 16.2.8(chokidar@3.5.3) + '@angular-devkit/schematics': 16.2.8(chokidar@3.5.3) + comment-json: 4.2.3 + jsonc-parser: 3.2.0 + pluralize: 8.0.0 + typescript: 5.3.3 + transitivePeerDependencies: + - chokidar + dev: true + /@nestjs/swagger@7.1.16(@nestjs/common@10.2.10)(@nestjs/core@10.2.10)(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13): resolution: {integrity: sha512-f9KBk/BX9MUKPTj7tQNYJ124wV/jP5W2lwWHLGwe/4qQXixuDOo39zP55HIJ44LE7S04B7BOeUOo9GBJD/vRcw==} peerDependencies: @@ -4347,6 +4512,35 @@ packages: swagger-ui-dist: 5.9.1 dev: false + /@nestjs/swagger@7.1.17(@nestjs/common@10.3.0)(@nestjs/core@10.3.0)(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13): + resolution: {integrity: sha512-ASCxBrvMEN2o/8vEEmrIPMNzrr/hVi7QIR4y1oNYvoBNXHuwoF1VSI3+4Rq/3xmwVnVveJxHlBIs2u5xY9VgGQ==} + peerDependencies: + '@fastify/static': ^6.0.0 + '@nestjs/common': ^9.0.0 || ^10.0.0 + '@nestjs/core': ^9.0.0 || ^10.0.0 + class-transformer: '*' + class-validator: '*' + reflect-metadata: ^0.1.12 + peerDependenciesMeta: + '@fastify/static': + optional: true + class-transformer: + optional: true + class-validator: + optional: true + dependencies: + '@nestjs/common': 10.3.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/core': 10.3.0(@nestjs/common@10.3.0)(@nestjs/microservices@10.3.0)(@nestjs/platform-express@10.3.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/mapped-types': 2.0.4(@nestjs/common@10.3.0)(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13) + class-transformer: 0.5.1 + class-validator: 0.14.0 + js-yaml: 4.1.0 + lodash: 4.17.21 + path-to-regexp: 3.2.0 + reflect-metadata: 0.1.13 + swagger-ui-dist: 5.10.3 + dev: false + /@nestjs/terminus@10.1.1(@nestjs/axios@3.0.1)(@nestjs/common@10.2.10)(@nestjs/core@10.2.10)(@nestjs/microservices@10.2.10)(reflect-metadata@0.1.13)(rxjs@7.8.1): resolution: {integrity: sha512-aDoPK/uaR9PHn56xzand6zqpp+S3Ibm+y/OrG3M01F1WnScLfo29hbS6MdnIMqmVRAS11r/8X3xWTSo8TT/Lig==} peerDependencies: @@ -4464,6 +4658,64 @@ packages: rxjs: 7.8.1 dev: false + /@nestjs/terminus@10.2.0(@nestjs/axios@3.0.1)(@nestjs/common@10.3.0)(@nestjs/core@10.3.0)(@nestjs/microservices@10.3.0)(reflect-metadata@0.1.13)(rxjs@7.8.1): + resolution: {integrity: sha512-zPs98xvJ4ogEimRQOz8eU90mb7z+W/kd/mL4peOgrJ/VqER+ibN2Cboj65uJZW3XuNhpOqaeYOJte86InJd44A==} + peerDependencies: + '@grpc/grpc-js': '*' + '@grpc/proto-loader': '*' + '@mikro-orm/core': '*' + '@mikro-orm/nestjs': '*' + '@nestjs/axios': ^1.0.0 || ^2.0.0 || ^3.0.0 + '@nestjs/common': ^9.0.0 || ^10.0.0 + '@nestjs/core': ^9.0.0 || ^10.0.0 + '@nestjs/microservices': ^9.0.0 || ^10.0.0 + '@nestjs/mongoose': ^9.0.0 || ^10.0.0 + '@nestjs/sequelize': ^9.0.0 || ^10.0.0 + '@nestjs/typeorm': ^9.0.0 || ^10.0.0 + '@prisma/client': '*' + mongoose: '*' + reflect-metadata: 0.1.x + rxjs: 7.x + sequelize: '*' + typeorm: '*' + peerDependenciesMeta: + '@grpc/grpc-js': + optional: true + '@grpc/proto-loader': + optional: true + '@mikro-orm/core': + optional: true + '@mikro-orm/nestjs': + optional: true + '@nestjs/axios': + optional: true + '@nestjs/microservices': + optional: true + '@nestjs/mongoose': + optional: true + '@nestjs/sequelize': + optional: true + '@nestjs/typeorm': + optional: true + '@prisma/client': + optional: true + mongoose: + optional: true + sequelize: + optional: true + typeorm: + optional: true + dependencies: + '@nestjs/axios': 3.0.1(@nestjs/common@10.3.0)(axios@1.6.2)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/common': 10.3.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/core': 10.3.0(@nestjs/common@10.3.0)(@nestjs/microservices@10.3.0)(@nestjs/platform-express@10.3.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/microservices': 10.3.0(@nestjs/common@10.3.0)(@nestjs/core@10.3.0)(nats@2.18.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + boxen: 5.1.2 + check-disk-space: 3.4.0 + reflect-metadata: 0.1.13 + rxjs: 7.8.1 + dev: false + /@nestjs/testing@10.2.10(@nestjs/common@10.2.10)(@nestjs/core@10.2.10)(@nestjs/microservices@10.2.10)(@nestjs/platform-express@10.2.8): resolution: {integrity: sha512-IVLUnPz/+fkBtPATYfqTIP+phN9yjkXejmj+JyhmcfPJZpxBmD1i9VSMqa4u54l37j0xkGPscQ0IXpbhqMYUKw==} peerDependencies: @@ -4504,6 +4756,26 @@ packages: tslib: 2.6.2 dev: true + /@nestjs/testing@10.3.0(@nestjs/common@10.3.0)(@nestjs/core@10.3.0)(@nestjs/microservices@10.3.0)(@nestjs/platform-express@10.3.0): + resolution: {integrity: sha512-8DM+bw1qASCvaEnoHUQhypCOf54+G5R21MeFBMvnSk5DtKaWVZuzDP2GjLeYCpTH19WeP6LrrjHv3rX2LKU02A==} + peerDependencies: + '@nestjs/common': ^10.0.0 + '@nestjs/core': ^10.0.0 + '@nestjs/microservices': ^10.0.0 + '@nestjs/platform-express': ^10.0.0 + peerDependenciesMeta: + '@nestjs/microservices': + optional: true + '@nestjs/platform-express': + optional: true + dependencies: + '@nestjs/common': 10.3.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/core': 10.3.0(@nestjs/common@10.3.0)(@nestjs/microservices@10.3.0)(@nestjs/platform-express@10.3.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/microservices': 10.3.0(@nestjs/common@10.3.0)(@nestjs/core@10.3.0)(nats@2.18.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/platform-express': 10.3.0(@nestjs/common@10.3.0)(@nestjs/core@10.3.0) + tslib: 2.6.2 + dev: true + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -5015,6 +5287,26 @@ packages: resolution: {integrity: sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==} dev: false + /@swc/cli@0.1.63(@swc/core@1.3.101): + resolution: {integrity: sha512-EM9oxxHzmmsprYRbGqsS2M4M/Gr5Gkcl0ROYYIdlUyTkhOiX822EQiRCpPCwdutdnzH2GyaTN7wc6i0Y+CKd3A==} + engines: {node: '>= 12.13'} + hasBin: true + peerDependencies: + '@swc/core': ^1.2.66 + chokidar: ^3.5.1 + peerDependenciesMeta: + chokidar: + optional: true + dependencies: + '@mole-inc/bin-wrapper': 8.0.1 + '@swc/core': 1.3.101 + commander: 7.2.0 + fast-glob: 3.3.2 + semver: 7.5.4 + slash: 3.0.0 + source-map: 0.7.4 + dev: true + /@swc/cli@0.1.63(@swc/core@1.3.96): resolution: {integrity: sha512-EM9oxxHzmmsprYRbGqsS2M4M/Gr5Gkcl0ROYYIdlUyTkhOiX822EQiRCpPCwdutdnzH2GyaTN7wc6i0Y+CKd3A==} engines: {node: '>= 12.13'} @@ -5035,6 +5327,15 @@ packages: source-map: 0.7.4 dev: true + /@swc/core-darwin-arm64@1.3.101: + resolution: {integrity: sha512-mNFK+uHNPRXSnfTOG34zJOeMl2waM4hF4a2NY7dkMXrPqw9CoJn4MwTXJcyMiSz1/BnNjjTCHF3Yhj0jPxmkzQ==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@swc/core-darwin-arm64@1.3.96: resolution: {integrity: sha512-8hzgXYVd85hfPh6mJ9yrG26rhgzCmcLO0h1TIl8U31hwmTbfZLzRitFQ/kqMJNbIBCwmNH1RU2QcJnL3d7f69A==} engines: {node: '>=10'} @@ -5044,6 +5345,15 @@ packages: dev: true optional: true + /@swc/core-darwin-x64@1.3.101: + resolution: {integrity: sha512-B085j8XOx73Fg15KsHvzYWG262bRweGr3JooO1aW5ec5pYbz5Ew9VS5JKYS03w2UBSxf2maWdbPz2UFAxg0whw==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@swc/core-darwin-x64@1.3.96: resolution: {integrity: sha512-mFp9GFfuPg+43vlAdQZl0WZpZSE8sEzqL7sr/7Reul5McUHP0BaLsEzwjvD035ESfkY8GBZdLpMinblIbFNljQ==} engines: {node: '>=10'} @@ -5053,6 +5363,15 @@ packages: dev: true optional: true + /@swc/core-linux-arm-gnueabihf@1.3.101: + resolution: {integrity: sha512-9xLKRb6zSzRGPqdz52Hy5GuB1lSjmLqa0lST6MTFads3apmx4Vgs8Y5NuGhx/h2I8QM4jXdLbpqQlifpzTlSSw==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@swc/core-linux-arm-gnueabihf@1.3.96: resolution: {integrity: sha512-8UEKkYJP4c8YzYIY/LlbSo8z5Obj4hqcv/fUTHiEePiGsOddgGf7AWjh56u7IoN/0uEmEro59nc1ChFXqXSGyg==} engines: {node: '>=10'} @@ -5062,6 +5381,15 @@ packages: dev: true optional: true + /@swc/core-linux-arm64-gnu@1.3.101: + resolution: {integrity: sha512-oE+r1lo7g/vs96Weh2R5l971dt+ZLuhaUX+n3BfDdPxNHfObXgKMjO7E+QS5RbGjv/AwiPCxQmbdCp/xN5ICJA==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@swc/core-linux-arm64-gnu@1.3.96: resolution: {integrity: sha512-c/IiJ0s1y3Ymm2BTpyC/xr6gOvoqAVETrivVXHq68xgNms95luSpbYQ28rqaZC8bQC8M5zdXpSc0T8DJu8RJGw==} engines: {node: '>=10'} @@ -5071,6 +5399,15 @@ packages: dev: true optional: true + /@swc/core-linux-arm64-musl@1.3.101: + resolution: {integrity: sha512-OGjYG3H4BMOTnJWJyBIovCez6KiHF30zMIu4+lGJTCrxRI2fAjGLml3PEXj8tC3FMcud7U2WUn6TdG0/te2k6g==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@swc/core-linux-arm64-musl@1.3.96: resolution: {integrity: sha512-i5/UTUwmJLri7zhtF6SAo/4QDQJDH2fhYJaBIUhrICmIkRO/ltURmpejqxsM/ye9Jqv5zG7VszMC0v/GYn/7BQ==} engines: {node: '>=10'} @@ -5080,6 +5417,15 @@ packages: dev: true optional: true + /@swc/core-linux-x64-gnu@1.3.101: + resolution: {integrity: sha512-/kBMcoF12PRO/lwa8Z7w4YyiKDcXQEiLvM+S3G9EvkoKYGgkkz4Q6PSNhF5rwg/E3+Hq5/9D2R+6nrkF287ihg==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@swc/core-linux-x64-gnu@1.3.96: resolution: {integrity: sha512-USdaZu8lTIkm4Yf9cogct/j5eqtdZqTgcTib4I+NloUW0E/hySou3eSyp3V2UAA1qyuC72ld1otXuyKBna0YKQ==} engines: {node: '>=10'} @@ -5089,6 +5435,15 @@ packages: dev: true optional: true + /@swc/core-linux-x64-musl@1.3.101: + resolution: {integrity: sha512-kDN8lm4Eew0u1p+h1l3JzoeGgZPQ05qDE0czngnjmfpsH2sOZxVj1hdiCwS5lArpy7ktaLu5JdRnx70MkUzhXw==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@swc/core-linux-x64-musl@1.3.96: resolution: {integrity: sha512-QYErutd+G2SNaCinUVobfL7jWWjGTI0QEoQ6hqTp7PxCJS/dmKmj3C5ZkvxRYcq7XcZt7ovrYCTwPTHzt6lZBg==} engines: {node: '>=10'} @@ -5098,6 +5453,15 @@ packages: dev: true optional: true + /@swc/core-win32-arm64-msvc@1.3.101: + resolution: {integrity: sha512-9Wn8TTLWwJKw63K/S+jjrZb9yoJfJwCE2RV5vPCCWmlMf3U1AXj5XuWOLUX+Rp2sGKau7wZKsvywhheWm+qndQ==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@swc/core-win32-arm64-msvc@1.3.96: resolution: {integrity: sha512-hjGvvAduA3Un2cZ9iNP4xvTXOO4jL3G9iakhFsgVhpkU73SGmK7+LN8ZVBEu4oq2SUcHO6caWvnZ881cxGuSpg==} engines: {node: '>=10'} @@ -5107,6 +5471,15 @@ packages: dev: true optional: true + /@swc/core-win32-ia32-msvc@1.3.101: + resolution: {integrity: sha512-onO5KvICRVlu2xmr4//V2je9O2XgS1SGKpbX206KmmjcJhXN5EYLSxW9qgg+kgV5mip+sKTHTAu7IkzkAtElYA==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@swc/core-win32-ia32-msvc@1.3.96: resolution: {integrity: sha512-Far2hVFiwr+7VPCM2GxSmbh3ikTpM3pDombE+d69hkedvYHYZxtTF+2LTKl/sXtpbUnsoq7yV/32c9R/xaaWfw==} engines: {node: '>=10'} @@ -5116,6 +5489,15 @@ packages: dev: true optional: true + /@swc/core-win32-x64-msvc@1.3.101: + resolution: {integrity: sha512-T3GeJtNQV00YmiVw/88/nxJ/H43CJvFnpvBHCVn17xbahiVUOPOduh3rc9LgAkKiNt/aV8vU3OJR+6PhfMR7UQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@swc/core-win32-x64-msvc@1.3.96: resolution: {integrity: sha512-4VbSAniIu0ikLf5mBX81FsljnfqjoVGleEkCQv4+zRlyZtO3FHoDPkeLVoy6WRlj7tyrRcfUJ4mDdPkbfTO14g==} engines: {node: '>=10'} @@ -5125,6 +5507,31 @@ packages: dev: true optional: true + /@swc/core@1.3.101: + resolution: {integrity: sha512-w5aQ9qYsd/IYmXADAnkXPGDMTqkQalIi+kfFf/MHRKTpaOL7DHjMXwPp/n8hJ0qNjRvchzmPtOqtPBiER50d8A==} + engines: {node: '>=10'} + requiresBuild: true + peerDependencies: + '@swc/helpers': ^0.5.0 + peerDependenciesMeta: + '@swc/helpers': + optional: true + dependencies: + '@swc/counter': 0.1.2 + '@swc/types': 0.1.5 + optionalDependencies: + '@swc/core-darwin-arm64': 1.3.101 + '@swc/core-darwin-x64': 1.3.101 + '@swc/core-linux-arm-gnueabihf': 1.3.101 + '@swc/core-linux-arm64-gnu': 1.3.101 + '@swc/core-linux-arm64-musl': 1.3.101 + '@swc/core-linux-x64-gnu': 1.3.101 + '@swc/core-linux-x64-musl': 1.3.101 + '@swc/core-win32-arm64-msvc': 1.3.101 + '@swc/core-win32-ia32-msvc': 1.3.101 + '@swc/core-win32-x64-msvc': 1.3.101 + dev: true + /@swc/core@1.3.96: resolution: {integrity: sha512-zwE3TLgoZwJfQygdv2SdCK9mRLYluwDOM53I+dT6Z5ZvrgVENmY3txvWDvduzkV+/8IuvrRbVezMpxcojadRdQ==} engines: {node: '>=10'} @@ -5154,6 +5561,17 @@ packages: resolution: {integrity: sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==} dev: true + /@swc/jest@0.2.29(@swc/core@1.3.101): + resolution: {integrity: sha512-8reh5RvHBsSikDC3WGCd5ZTd2BXKkyOdK7QwynrCH58jk2cQFhhHhFBg/jvnWZehUQe/EoOImLENc9/DwbBFow==} + engines: {npm: '>= 7.0.0'} + peerDependencies: + '@swc/core': '*' + dependencies: + '@jest/create-cache-key-function': 27.5.1 + '@swc/core': 1.3.101 + jsonc-parser: 3.2.0 + dev: true + /@swc/jest@0.2.29(@swc/core@1.3.96): resolution: {integrity: sha512-8reh5RvHBsSikDC3WGCd5ZTd2BXKkyOdK7QwynrCH58jk2cQFhhHhFBg/jvnWZehUQe/EoOImLENc9/DwbBFow==} engines: {npm: '>= 7.0.0'} @@ -5229,21 +5647,21 @@ packages: resolution: {integrity: sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ==} dependencies: '@types/connect': 3.4.36 - '@types/node': 20.9.4 + '@types/node': 20.10.5 /@types/cacheable-request@6.0.3: resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} dependencies: '@types/http-cache-semantics': 4.0.4 '@types/keyv': 3.1.4 - '@types/node': 20.9.4 + '@types/node': 20.10.5 '@types/responselike': 1.0.3 dev: true /@types/connect@3.4.36: resolution: {integrity: sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.5 /@types/cookiejar@2.1.2: resolution: {integrity: sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==} @@ -5270,7 +5688,7 @@ packages: /@types/express-serve-static-core@4.17.37: resolution: {integrity: sha512-ZohaCYTgGFcOP7u6aJOhY9uIZQgZ2vxC2yWoArY+FeDXlqeH66ZVBjgvg+RLVAS/DWNq4Ap9ZXu1+SUQiiWYMg==} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.5 '@types/qs': 6.9.8 '@types/range-parser': 1.2.5 '@types/send': 0.17.2 @@ -5286,7 +5704,7 @@ packages: /@types/graceful-fs@4.1.7: resolution: {integrity: sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.5 dev: true /@types/http-cache-semantics@4.0.4: @@ -5309,15 +5727,15 @@ packages: dependencies: '@types/istanbul-lib-report': 3.0.1 - /@types/jest@27.0.2: - resolution: {integrity: sha512-4dRxkS/AFX0c5XW6IPMNOydLn2tEhNhJV7DnYK+0bjoJZ+QTmfucBlihX7aoEsh/ocYtkLC73UbnBXBXIxsULA==} + /@types/jest@29.5.10: + resolution: {integrity: sha512-tE4yxKEphEyxj9s4inideLHktW/x6DwesIwWZ9NN1FKf9zbJYsnhBoA9vrHA/IuIOKwPa5PcFBNV4lpMIOEzyQ==} dependencies: - jest-diff: 27.5.1 - pretty-format: 27.5.1 + expect: 29.7.0 + pretty-format: 29.7.0 dev: true - /@types/jest@29.5.10: - resolution: {integrity: sha512-tE4yxKEphEyxj9s4inideLHktW/x6DwesIwWZ9NN1FKf9zbJYsnhBoA9vrHA/IuIOKwPa5PcFBNV4lpMIOEzyQ==} + /@types/jest@29.5.11: + resolution: {integrity: sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==} dependencies: expect: 29.7.0 pretty-format: 29.7.0 @@ -5341,12 +5759,12 @@ packages: /@types/jsonwebtoken@9.0.5: resolution: {integrity: sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==} dependencies: - '@types/node': 20.9.0 + '@types/node': 20.9.4 /@types/keyv@3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.5 dev: true /@types/luxon@3.3.4: @@ -5376,10 +5794,16 @@ packages: undici-types: 5.26.5 dev: true + /@types/node@20.10.5: + resolution: {integrity: sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==} + dependencies: + undici-types: 5.26.5 + /@types/node@20.9.0: resolution: {integrity: sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==} dependencies: undici-types: 5.26.5 + dev: true /@types/node@20.9.4: resolution: {integrity: sha512-wmyg8HUhcn6ACjsn8oKYjkN/zUzQeNtMy44weTJSM6p4MMzEOuKbA3OjJ267uPCOW7Xex9dyrNTful8XTQYoDA==} @@ -5411,7 +5835,7 @@ packages: /@types/responselike@1.0.3: resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.5 dev: true /@types/semver@7.5.3: @@ -5422,18 +5846,14 @@ packages: resolution: {integrity: sha512-aAG6yRf6r0wQ29bkS+x97BIs64ZLxeE/ARwyS6wrldMm3C1MdKwCcnnEwMC1slI8wuxJOpiUH9MioC0A0i+GJw==} dependencies: '@types/mime': 1.3.3 - '@types/node': 20.9.4 + '@types/node': 20.10.5 /@types/serve-static@1.15.3: resolution: {integrity: sha512-yVRvFsEMrv7s0lGhzrggJjNOSmZCdgCjw9xWrPr/kNNLp6FaDfMC1KaYl3TSJ0c58bECwNBMoQrZJ8hA8E1eFg==} dependencies: '@types/http-errors': 2.0.2 '@types/mime': 3.0.2 - '@types/node': 20.9.4 - - /@types/simple-oauth2@5.0.7: - resolution: {integrity: sha512-8JbWVJbiTSBQP/7eiyGKyXWAqp3dKQZpaA+pdW16FCi32ujkzRMG8JfjoAzdWt6W8U591ZNdHcPtP2D7ILTKuA==} - dev: true + '@types/node': 20.10.5 /@types/stack-utils@2.0.1: resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} @@ -5513,6 +5933,35 @@ packages: - supports-color dev: true + /@typescript-eslint/eslint-plugin@6.12.0(@typescript-eslint/parser@6.12.0)(eslint@8.54.0)(typescript@5.3.3): + resolution: {integrity: sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.9.1 + '@typescript-eslint/parser': 6.12.0(eslint@8.54.0)(typescript@5.3.3) + '@typescript-eslint/scope-manager': 6.12.0 + '@typescript-eslint/type-utils': 6.12.0(eslint@8.54.0)(typescript@5.3.3) + '@typescript-eslint/utils': 6.12.0(eslint@8.54.0)(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.12.0 + debug: 4.3.4 + eslint: 8.54.0 + graphemer: 1.4.0 + ignore: 5.2.4 + natural-compare: 1.4.0 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/parser@6.12.0(eslint@8.54.0)(typescript@5.3.2): resolution: {integrity: sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==} engines: {node: ^16.0.0 || >=18.0.0} @@ -5534,6 +5983,27 @@ packages: - supports-color dev: true + /@typescript-eslint/parser@6.12.0(eslint@8.54.0)(typescript@5.3.3): + resolution: {integrity: sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 6.12.0 + '@typescript-eslint/types': 6.12.0 + '@typescript-eslint/typescript-estree': 6.12.0(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.12.0 + debug: 4.3.4 + eslint: 8.54.0 + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/scope-manager@6.12.0: resolution: {integrity: sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==} engines: {node: ^16.0.0 || >=18.0.0} @@ -5562,12 +6032,53 @@ packages: - supports-color dev: true + /@typescript-eslint/type-utils@6.12.0(eslint@8.54.0)(typescript@5.3.3): + resolution: {integrity: sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 6.12.0(typescript@5.3.3) + '@typescript-eslint/utils': 6.12.0(eslint@8.54.0)(typescript@5.3.3) + debug: 4.3.4 + eslint: 8.54.0 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/types@6.12.0: resolution: {integrity: sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==} engines: {node: ^16.0.0 || >=18.0.0} dev: true - /@typescript-eslint/typescript-estree@6.12.0(typescript@5.3.2): + /@typescript-eslint/typescript-estree@6.12.0(typescript@5.3.2): + resolution: {integrity: sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 6.12.0 + '@typescript-eslint/visitor-keys': 6.12.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.3.2) + typescript: 5.3.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/typescript-estree@6.12.0(typescript@5.3.3): resolution: {integrity: sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -5582,8 +6093,8 @@ packages: globby: 11.1.0 is-glob: 4.0.3 semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.3.2) - typescript: 5.3.2 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true @@ -5607,6 +6118,25 @@ packages: - typescript dev: true + /@typescript-eslint/utils@6.12.0(eslint@8.54.0)(typescript@5.3.3): + resolution: {integrity: sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.54.0) + '@types/json-schema': 7.0.13 + '@types/semver': 7.5.3 + '@typescript-eslint/scope-manager': 6.12.0 + '@typescript-eslint/types': 6.12.0 + '@typescript-eslint/typescript-estree': 6.12.0(typescript@5.3.3) + eslint: 8.54.0 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + /@typescript-eslint/visitor-keys@6.12.0: resolution: {integrity: sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==} engines: {node: ^16.0.0 || >=18.0.0} @@ -7296,7 +7826,7 @@ packages: object-assign: 4.1.1 vary: 1.1.2 - /cosmiconfig-typescript-loader@5.0.0(@types/node@18.18.10)(cosmiconfig@8.3.6)(typescript@5.3.2): + /cosmiconfig-typescript-loader@5.0.0(@types/node@18.18.10)(cosmiconfig@8.3.6)(typescript@5.3.3): resolution: {integrity: sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==} engines: {node: '>=v16'} peerDependencies: @@ -7305,9 +7835,9 @@ packages: typescript: '>=4' dependencies: '@types/node': 18.18.10 - cosmiconfig: 8.3.6(typescript@5.3.2) + cosmiconfig: 8.3.6(typescript@5.3.3) jiti: 1.21.0 - typescript: 5.3.2 + typescript: 5.3.3 dev: true /cosmiconfig@5.2.1: @@ -7337,7 +7867,7 @@ packages: typescript: 5.2.2 dev: true - /cosmiconfig@8.3.6(typescript@5.3.2): + /cosmiconfig@8.3.6(typescript@5.3.3): resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} engines: {node: '>=14'} peerDependencies: @@ -7350,7 +7880,26 @@ packages: js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 - typescript: 5.3.2 + typescript: 5.3.3 + dev: true + + /create-jest@29.7.0(@types/node@20.10.5): + resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@20.10.5) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node dev: true /create-jest@29.7.0(@types/node@20.9.0)(ts-node@10.9.1): @@ -7714,11 +8263,6 @@ packages: resolution: {integrity: sha512-S6fWHvCXkZg2IhS4RcVHxwuyVejPR7c+a4Go0xbQ9ps5kILa8viiYQgrM4gfTyeTjJ0ekgJH9gk/BawTpmkbZA==} dev: false - /diff-sequences@27.5.1: - resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dev: true - /diff-sequences@29.6.3: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -8106,7 +8650,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 6.12.0(eslint@8.54.0)(typescript@5.3.2) + '@typescript-eslint/parser': 6.12.0(eslint@8.54.0)(typescript@5.3.3) debug: 3.2.7 eslint: 8.54.0 eslint-import-resolver-node: 0.3.9 @@ -8125,7 +8669,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 6.12.0(eslint@8.54.0)(typescript@5.3.2) + '@typescript-eslint/parser': 6.12.0(eslint@8.54.0)(typescript@5.3.3) array-includes: 3.1.7 array.prototype.findlastindex: 1.2.3 array.prototype.flat: 1.3.2 @@ -10194,7 +10738,7 @@ packages: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.9.4 + '@types/node': 20.10.5 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.1 @@ -10215,7 +10759,7 @@ packages: - supports-color dev: true - /jest-cli@29.7.0(@types/node@20.9.0)(ts-node@10.9.1): + /jest-cli@29.7.0(@types/node@20.10.5): resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -10229,10 +10773,10 @@ packages: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.9.0)(ts-node@10.9.1) + create-jest: 29.7.0(@types/node@20.10.5) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.9.0)(ts-node@10.9.1) + jest-config: 29.7.0(@types/node@20.10.5) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -10243,7 +10787,7 @@ packages: - ts-node dev: true - /jest-cli@29.7.0(@types/node@20.9.4): + /jest-cli@29.7.0(@types/node@20.9.0)(ts-node@10.9.1): resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -10257,10 +10801,10 @@ packages: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.9.4)(ts-node@10.9.1) + create-jest: 29.7.0(@types/node@20.9.0)(ts-node@10.9.1) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.9.4)(ts-node@10.9.1) + jest-config: 29.7.0(@types/node@20.9.0)(ts-node@10.9.1) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -10299,6 +10843,46 @@ packages: - ts-node dev: true + /jest-config@29.7.0(@types/node@20.10.5): + resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + dependencies: + '@babel/core': 7.23.0 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.10.5 + babel-jest: 29.7.0(@babel/core@7.23.0) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + dev: true + /jest-config@29.7.0(@types/node@20.9.0)(ts-node@10.9.1): resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -10381,16 +10965,6 @@ packages: - supports-color dev: true - /jest-diff@27.5.1: - resolution: {integrity: sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dependencies: - chalk: 4.1.2 - diff-sequences: 27.5.1 - jest-get-type: 27.5.1 - pretty-format: 27.5.1 - dev: true - /jest-diff@29.7.0: resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -10430,11 +11004,6 @@ packages: jest-mock: 29.7.0 jest-util: 29.7.0 - /jest-get-type@27.5.1: - resolution: {integrity: sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dev: true - /jest-get-type@29.6.3: resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -10445,7 +11014,7 @@ packages: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.7 - '@types/node': 20.9.4 + '@types/node': 20.10.5 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -10495,7 +11064,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.9.4 + '@types/node': 20.10.5 jest-util: 29.7.0 /jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -10638,7 +11207,7 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/types': 27.5.1 - '@types/node': 20.9.4 + '@types/node': 20.10.5 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -10674,7 +11243,7 @@ packages: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.9.4 + '@types/node': 20.10.5 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -10686,7 +11255,7 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.5 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -10694,13 +11263,13 @@ packages: resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.5 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true - /jest@29.7.0(@types/node@20.9.0)(ts-node@10.9.1): + /jest@29.7.0(@types/node@20.10.5): resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -10713,7 +11282,7 @@ packages: '@jest/core': 29.7.0(ts-node@10.9.1) '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.9.0)(ts-node@10.9.1) + jest-cli: 29.7.0(@types/node@20.10.5) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -10721,7 +11290,7 @@ packages: - ts-node dev: true - /jest@29.7.0(@types/node@20.9.4): + /jest@29.7.0(@types/node@20.9.0)(ts-node@10.9.1): resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -10734,7 +11303,7 @@ packages: '@jest/core': 29.7.0(ts-node@10.9.1) '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.9.4) + jest-cli: 29.7.0(@types/node@20.9.0)(ts-node@10.9.1) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -13018,15 +13587,6 @@ packages: dev: false optional: true - /pretty-format@27.5.1: - resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dependencies: - ansi-regex: 5.0.1 - ansi-styles: 5.2.0 - react-is: 17.0.2 - dev: true - /pretty-format@29.7.0: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -13254,6 +13814,8 @@ packages: /react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + dev: false + optional: true /react-is@18.2.0: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} @@ -14476,6 +15038,10 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + /swagger-ui-dist@5.10.3: + resolution: {integrity: sha512-fu3aozjxFWsmcO1vyt1q1Ji2kN7KlTd1vHy27E9WgPyXo9nrEzhQPqgxaAjbMsOmb8XFKNGo4Sa3Q+84Fh+pFw==} + dev: false + /swagger-ui-dist@5.9.0: resolution: {integrity: sha512-NUHSYoe5XRTk/Are8jPJ6phzBh3l9l33nEyXosM17QInoV95/jng8+PuSGtbD407QoPf93MH3Bkh773OgesJpA==} @@ -14573,6 +15139,31 @@ packages: dev: false optional: true + /terser-webpack-plugin@5.3.9(@swc/core@1.3.101)(webpack@5.89.0): + resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: + optional: true + dependencies: + '@jridgewell/trace-mapping': 0.3.19 + '@swc/core': 1.3.101 + jest-worker: 27.5.1 + schema-utils: 3.3.0 + serialize-javascript: 6.0.1 + terser: 5.21.0 + webpack: 5.89.0(@swc/core@1.3.101) + dev: true + /terser-webpack-plugin@5.3.9(@swc/core@1.3.96)(webpack@5.89.0): resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} engines: {node: '>= 10.13.0'} @@ -14781,6 +15372,15 @@ packages: typescript: 5.3.2 dev: true + /ts-api-utils@1.0.3(typescript@5.3.3): + resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} + engines: {node: '>=16.13.0'} + peerDependencies: + typescript: '>=4.2.0' + dependencies: + typescript: 5.3.3 + dev: true + /ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} dev: false @@ -14820,6 +15420,40 @@ packages: yargs-parser: 21.1.1 dev: true + /ts-jest@29.1.1(@babel/core@7.23.0)(jest@29.7.0)(typescript@5.3.3): + resolution: {integrity: sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + '@babel/core': '>=7.0.0-beta.0 <8' + '@jest/types': ^29.0.0 + babel-jest: ^29.0.0 + esbuild: '*' + jest: ^29.0.0 + typescript: '>=4.3 <6' + peerDependenciesMeta: + '@babel/core': + optional: true + '@jest/types': + optional: true + babel-jest: + optional: true + esbuild: + optional: true + dependencies: + '@babel/core': 7.23.0 + bs-logger: 0.2.6 + fast-json-stable-stringify: 2.1.0 + jest: 29.7.0(@types/node@20.9.4)(ts-node@10.9.1) + jest-util: 29.7.0 + json5: 2.2.3 + lodash.memoize: 4.1.2 + make-error: 1.3.6 + semver: 7.5.4 + typescript: 5.3.3 + yargs-parser: 21.1.1 + dev: true + /ts-node@10.9.1(@swc/core@1.3.96)(@types/node@20.9.0)(typescript@5.2.2): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true @@ -14883,6 +15517,37 @@ packages: yn: 3.1.1 dev: true + /ts-node@10.9.1(@types/node@20.9.4)(typescript@5.3.3): + resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 20.9.4 + acorn: 8.10.0 + acorn-walk: 8.2.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.3.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + dev: true + /tsconfig-paths-webpack-plugin@4.1.0: resolution: {integrity: sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA==} engines: {node: '>=10.13.0'} @@ -15054,6 +15719,12 @@ packages: hasBin: true dev: true + /typescript@5.3.3: + resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} + engines: {node: '>=14.17'} + hasBin: true + dev: true + /ua-parser-js@1.0.37: resolution: {integrity: sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==} dev: false @@ -15417,6 +16088,46 @@ packages: - uglify-js dev: true + /webpack@5.89.0(@swc/core@1.3.101): + resolution: {integrity: sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + dependencies: + '@types/eslint-scope': 3.7.5 + '@types/estree': 1.0.2 + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/wasm-edit': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 + acorn: 8.10.0 + acorn-import-assertions: 1.9.0(acorn@8.10.0) + browserslist: 4.22.1 + chrome-trace-event: 1.0.3 + enhanced-resolve: 5.15.0 + es-module-lexer: 1.3.1 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 3.3.0 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.9(@swc/core@1.3.101)(webpack@5.89.0) + watchpack: 2.4.0 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + dev: true + /webpack@5.89.0(@swc/core@1.3.96): resolution: {integrity: sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==} engines: {node: '>=10.13.0'} -- GitLab