diff --git a/.eslintrc.json b/.eslintrc.json index aa150461..239e37dd 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -56,7 +56,8 @@ "no-console": "off", "@typescript-eslint/no-empty-function": "off", "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/no-explicit-any": "off" + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-non-null-assertion": "off" } } ] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 29e991f4..cc109020 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,10 +47,6 @@ jobs: RELEASE_VERSION: ${{ github.sha }} API_URL: http://localhost:3000/ OAUTH_CONFIG: undefined - - uses: actions/upload-artifact@v3 - with: - name: env-spa-prod - path: apps/spa/src/environments/environment.prod.ts - name: Create API Environment File run: | envsubst < apps/api/src/.env.template > apps/api/src/.env diff --git a/apps/api/dev-tokens.md b/apps/api/dev-tokens.md index 79dd469f..3020a795 100644 --- a/apps/api/dev-tokens.md +++ b/apps/api/dev-tokens.md @@ -5,9 +5,9 @@ API with pre-defined claims. The test users are equivalent to the users used in [E2Es](../spa-e2e/README.md) and the test users registered in the development application of our AAD. -| **Username** | **ID** (`oid`) | **First name** (`first_name`) | **Last name** (`last_name`) | **Emails** (`emails`) | Token | -| ------------ | ------------------------------------ | ----------------------------- | --------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| testuser | c0cc4404-7907-4480-86d3-ba4bfc513c6d | Test | User | testuser@kordis-leitstelle.de | `eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJvaWQiOiIxMjM0IiwiZW1haWxzIjpbInRlc3R1c2VyQHRlc3QuY29tIl0sImdpdmVuX25hbWUiOiJUZXN0IiwiZmFtaWx5X25hbWUiOiJVc2VyIDEifQ.` | +| **Username** | **ID** (`oid`) | **First name** (`first_name`) | **Last name** (`last_name`) | **Emails** (`emails`) | **Organization** (`organization`) | Token | +| ------------ | ------------------------------------ | ----------------------------- | --------------------------- | ----------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| testuser | c0cc4404-7907-4480-86d3-ba4bfc513c6d | Test | User | testuser@kordis-leitstelle.de | testorganization (dff7584efe2c174eee8bae45) | `eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJvaWQiOiIxMjM0IiwiZW1haWxzIjpbInRlc3R1c2VyQHRlc3QuY29tIl0sImdpdmVuX25hbWUiOiJUZXN0IiwiZmFtaWx5X25hbWUiOiJVc2VyIDEifQ.` | The claims will be mapped to the [AuthUser](../../libs/shared/auth/src/lib/auth-user.model.ts) Model in the diff --git a/apps/api/src/app/app.module.ts b/apps/api/src/app/app.module.ts index 1272d795..2b8a5053 100644 --- a/apps/api/src/app/app.module.ts +++ b/apps/api/src/app/app.module.ts @@ -1,18 +1,33 @@ +import { classes } from '@automapper/classes'; import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo'; import { Module } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { GraphQLModule } from '@nestjs/graphql'; import { MongooseModule } from '@nestjs/mongoose'; +import { AutomapperModule } from '@timonmasberg/automapper-nestjs'; import * as path from 'path'; import { AuthModule } from '@kordis/api/auth'; -import { SentryObservabilityModule } from '@kordis/api/observability'; -import { SharedKernel } from '@kordis/api/shared'; +import { + DevObservabilityModule, + SentryObservabilityModule, +} from '@kordis/api/observability'; +import { OrganizationModule } from '@kordis/api/organization'; +import { SharedKernel, errorFormatterFactory } from '@kordis/api/shared'; import { AppResolver } from './app.resolver'; import { AppService } from './app.service'; import { GraphqlSubscriptionsController } from './controllers/graphql-subscriptions.controller'; +const FEATURE_MODULES = [OrganizationModule]; +const UTILITY_MODULES = [ + SharedKernel, + AuthModule, + ...(process.env.NODE_ENV === 'production' && !process.env.GITHUB_ACTIONS + ? [SentryObservabilityModule] + : [DevObservabilityModule]), +]; + @Module({ imports: [ ConfigModule.forRoot({ @@ -32,6 +47,9 @@ import { GraphqlSubscriptionsController } from './controllers/graphql-subscripti 'graphql-ws': true, }, playground: config.get('NODE_ENV') !== 'production', + formatError: errorFormatterFactory( + config.get('NODE_ENV') === 'production', + ), }), inject: [ConfigService], }), @@ -42,11 +60,11 @@ import { GraphqlSubscriptionsController } from './controllers/graphql-subscripti }), inject: [ConfigService], }), - SharedKernel, - AuthModule, - ...(process.env.NODE_ENV === 'production' && !process.env.GITHUB_ACTIONS - ? [SentryObservabilityModule] - : []), + AutomapperModule.forRoot({ + strategyInitializer: classes(), + }), + ...UTILITY_MODULES, + ...FEATURE_MODULES, ], providers: [AppService, AppResolver], controllers: [GraphqlSubscriptionsController], diff --git a/apps/api/src/app/controllers/graphql-subscriptions.controller.spec.ts b/apps/api/src/app/controllers/graphql-subscriptions.controller.spec.ts index c29528ee..019791cf 100644 --- a/apps/api/src/app/controllers/graphql-subscriptions.controller.spec.ts +++ b/apps/api/src/app/controllers/graphql-subscriptions.controller.spec.ts @@ -28,10 +28,6 @@ describe('GraphqlSubscriptionsController', () => { ); }); - it('should be defined', () => { - expect(controller).toBeDefined(); - }); - it('should throw ServiceUnavailableException if handler not ready', () => { const requestEmuFn = () => controller.subscriptionHandler( diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts index e63b53bb..8ae10027 100644 --- a/apps/api/src/main.ts +++ b/apps/api/src/main.ts @@ -1,17 +1,23 @@ // @formatter:off otelSdk has to imported on the very top! // until https://github.com/open-telemetry/opentelemetry-js/issues/3450 is fixed, we have to import the oTel sdk via a relative path // eslint-disable-next-line @nx/enforce-module-boundaries -import '../../../libs/api/observability/src/lib/oTelSdk'; +import "../../../libs/api/observability/src/lib/oTelSdk"; -import {Logger} from '@nestjs/common'; -import {ConfigService} from '@nestjs/config'; -import {NestFactory} from '@nestjs/core'; +import {Logger, ValidationPipe} from "@nestjs/common"; +import {ConfigService} from "@nestjs/config"; +import {NestFactory} from "@nestjs/core"; -import {AppModule} from './app/app.module'; +import {AppModule} from "./app/app.module"; +import {PresentableValidationException} from "@kordis/api/shared"; async function bootstrap(): Promise { - const app = await NestFactory.create(AppModule, { cors: true }); + const app = await NestFactory.create(AppModule, { cors: true, bufferLogs: true }); + app.useLogger(app.get(Logger)); + app.useGlobalPipes(new ValidationPipe({ + exceptionFactory: (errors) => PresentableValidationException.fromClassValidationErrors(errors), + }) + ); const config = app.get(ConfigService); const envPort = config.get('PORT'); diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 00000000..5ed37bda --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,67 @@ +# Architecture + +This document introduces the general architecture of Kordis with a focus on the +API. In general, we want to follow the Clean Architecture Principle, which tries +to achieve a state where: + +1. we are independent of frameworks, +2. we ensure testability of our business logic, +3. we are independent of UI logic, +4. we are independent of the database and its access, +5. we are independent of external dependencies. + +Since architecture is a lot about trade-offs, not every point mentioned above +might be wise to follow in a project. The main goal is to have a solid +separation of concerns. Every change should only have an isolated impact, and +since Kordis is a System that will definitely grow over time with more features +and external dependencies to join as components, it is a requirement to allow +the system to be easily extendable and maintainable by multiple people. + +We aggregate the layers of the clean architecture approach in 2 layers, the +**Core** and the **Infrastructure** layer, which tries to achieve a solid +separation of concerns and a clear dependency direction, but also maintains a +good balance between the effort of maintaining the architecture and the value it +provides. + +**Core** (core) +Contains the business logic, entities, events and domain exceptions. Everything +in here is something business relevant, that should not be touched and +influenced by changes not related to the business logic, such as changes to the +database or the framework. Therefore, the layer should not have any dependency +on other layers or components from outside its scope. This ensures that we can +easily test the logic and that we can change the infrastructure without having +to change the business logic. Nevertheless, we made some tradeoffs in the core +layer. We allow the use of NestJS framework specific CQRS handler annotations, +class validator annotations and annotations in the entity model for GraphQL +input and argument models. This is due to the fact, that maintaining another +layer on top of these decorators would be pure overhead, that would +overcomplicate the codebase and does not outweigh the value of simpler changes +in the infrastructure layer. Also, maintaining Input Models for GraphQL that +share the same structure as the entity model would also not benefit the +complexity of the codebase. Therefore, we decided to allow these annotations in +the core layer, if they are unlikely to change on the Input/Argument side of the +GraphQL API and the structure is equal. + +**Infrastructure** (infra) +The infrastructure layer defines every external component the system interacts +with. It provides concert implementations such as the repositories (data +access), logging, external APIs, etc. The idea behind this is that all +dependencies point towards the core layer. At no time should the core layer be +based on any concrete implementation, framework or other specification. This +ensures that we are flexible with changes in our infrastructure and we allow our +domain to define what interfaces it requires. This should also result in easier +testing. The best example is the repository, where the core layer defines which +data it needs and the infrastructure layer implements this interface and hides +all the concrete database logic. + +## CQRS + +tbd by @JSPRH + +Some resources used for this architecture are: + +- https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html +- Clean Architecture: A Craftsman's Guide to Software Structure and Design + (Robert C. Martin Series) +- https://github.com/jasontaylordev/CleanArchitecture +- https://learn.microsoft.com/en-us/dotnet/architecture/modern-web-apps-azure/common-web-application-architectures#clean-architecture diff --git a/libs/api/auth/src/lib/auth-user-extractor-strategies/auth-user-extractor.strategy.ts b/libs/api/auth/src/lib/auth-user-extractor-strategies/auth-user-extractor.strategy.ts index eebd3e6b..8bd782ac 100644 --- a/libs/api/auth/src/lib/auth-user-extractor-strategies/auth-user-extractor.strategy.ts +++ b/libs/api/auth/src/lib/auth-user-extractor-strategies/auth-user-extractor.strategy.ts @@ -20,6 +20,7 @@ export class ExtractUserFromMsPrincipleHeader extends AuthUserExtractorStrategy emails: string[]; given_name: string; family_name: string; + organization: string; }; return { @@ -27,6 +28,7 @@ export class ExtractUserFromMsPrincipleHeader extends AuthUserExtractorStrategy email: decodedToken['emails'][0], firstName: decodedToken['given_name'], lastName: decodedToken['family_name'], + organization: decodedToken['organization'], }; } } diff --git a/libs/api/auth/src/lib/decorators/user.decorator.spec.ts b/libs/api/auth/src/lib/decorators/user.decorator.spec.ts index fa49231d..caac6394 100644 --- a/libs/api/auth/src/lib/decorators/user.decorator.spec.ts +++ b/libs/api/auth/src/lib/decorators/user.decorator.spec.ts @@ -16,6 +16,7 @@ describe('User Decorator', () => { email: 'someemail@gmail.com', firstName: 'somefirstname', lastName: 'somelastname', + organization: 'someorganization', }; const req = createMock({ user, diff --git a/libs/api/auth/src/lib/interceptors/auth.interceptor.spec.ts b/libs/api/auth/src/lib/interceptors/auth.interceptor.spec.ts index b4cc7d3e..a788dfdd 100644 --- a/libs/api/auth/src/lib/interceptors/auth.interceptor.spec.ts +++ b/libs/api/auth/src/lib/interceptors/auth.interceptor.spec.ts @@ -48,6 +48,7 @@ describe('AuthInterceptor', () => { firstName: 'foo', lastName: 'bar', email: 'foo@bar.de', + organization: 'testorg', }); const handler = createMock({ diff --git a/libs/api/auth/src/lib/interceptors/auth.interceptor.ts b/libs/api/auth/src/lib/interceptors/auth.interceptor.ts index eb27be5c..0df53628 100644 --- a/libs/api/auth/src/lib/interceptors/auth.interceptor.ts +++ b/libs/api/auth/src/lib/interceptors/auth.interceptor.ts @@ -2,18 +2,22 @@ import { CallHandler, ExecutionContext, Injectable, + Logger, NestInterceptor, UnauthorizedException, } from '@nestjs/common'; import { GqlContextType, GqlExecutionContext } from '@nestjs/graphql'; import { Observable, throwError } from 'rxjs'; +import { KordisLogger } from '@kordis/api/observability'; import { KordisGqlContext, KordisRequest } from '@kordis/api/shared'; import { AuthUserExtractorStrategy } from '../auth-user-extractor-strategies/auth-user-extractor.strategy'; @Injectable() export class AuthInterceptor implements NestInterceptor { + private readonly logger: KordisLogger = new Logger(AuthInterceptor.name); + constructor(private readonly authUserExtractor: AuthUserExtractorStrategy) {} intercept(context: ExecutionContext, next: CallHandler): Observable { @@ -28,6 +32,11 @@ export class AuthInterceptor implements NestInterceptor { const possibleAuthUser = this.authUserExtractor.getUserFromRequest(req); if (!possibleAuthUser) { + this.logger.warn('Request without any extractable auth user', { + headers: req.headers, + body: req.body, + params: req.params, + }); // This is just intended to be a fallback, as we currently only aim to support running the API behind an OAuth Proxy // You could write a custom auth user strategy which handles your auth process and return null if unauthorized return throwError(() => new UnauthorizedException()); diff --git a/libs/api/observability/src/index.ts b/libs/api/observability/src/index.ts index 84cd89bf..f30ea6d0 100644 --- a/libs/api/observability/src/index.ts +++ b/libs/api/observability/src/index.ts @@ -1,2 +1,4 @@ export * from './lib/sentry-observability.module'; +export * from './lib/dev-observability.module'; export * from './lib/decorators/trace.decorator'; +export * from './lib/services/kordis-logger.interface'; diff --git a/libs/api/observability/src/lib/dev-observability.module.ts b/libs/api/observability/src/lib/dev-observability.module.ts new file mode 100644 index 00000000..99490b77 --- /dev/null +++ b/libs/api/observability/src/lib/dev-observability.module.ts @@ -0,0 +1,19 @@ +import { Logger, Module } from '@nestjs/common'; + +import { KORDIS_LOGGER_SERVICE } from './services/kordis-logger-service.interface'; +import { KordisLoggerImpl } from './services/kordis.logger'; +import { PinoLogger } from './services/pino-logger.service'; + +@Module({ + providers: [ + { + provide: KORDIS_LOGGER_SERVICE, + useValue: new PinoLogger(true), + }, + { + provide: Logger, + useClass: KordisLoggerImpl, + }, + ], +}) +export class DevObservabilityModule {} diff --git a/libs/api/observability/src/lib/filters/exceptions.filter.spec.ts b/libs/api/observability/src/lib/filters/exceptions.filter.spec.ts new file mode 100644 index 00000000..24429532 --- /dev/null +++ b/libs/api/observability/src/lib/filters/exceptions.filter.spec.ts @@ -0,0 +1,63 @@ +import * as Sentry from '@sentry/node'; + +import { PresentableException } from '@kordis/api/shared'; + +import { SentryExceptionsFilter } from './sentry-exceptions.filter'; + +describe('ExceptionsFilter', () => { + let sentryExceptionsFilter: SentryExceptionsFilter; + let addBreadcrumbMock: jest.Mock; + let captureExceptionMock: jest.Mock; + + beforeEach(() => { + addBreadcrumbMock = jest.fn(); + captureExceptionMock = jest.fn(); + + (Sentry.addBreadcrumb as jest.Mock) = addBreadcrumbMock; + (Sentry.captureException as jest.Mock) = captureExceptionMock; + + sentryExceptionsFilter = new SentryExceptionsFilter(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should capture a presentable exception as an info message', () => { + class MockPresentableException extends PresentableException { + code = 'code'; + + constructor() { + super('message'); + } + } + + const presentableException = new MockPresentableException(); + + sentryExceptionsFilter.catch(presentableException); + + expect(addBreadcrumbMock).toHaveBeenCalledTimes(1); + expect(addBreadcrumbMock).toHaveBeenCalledWith({ + level: 'error', + message: 'message', + data: { + name: 'Error', + code: 'code', + stack: expect.any(String), + }, + }); + expect(captureExceptionMock).not.toHaveBeenCalled(); + }); + + it('should capture a non-presentable exception as an error', () => { + const exception = new Error('Some error'); + + sentryExceptionsFilter.catch(exception); + + expect(captureExceptionMock).toHaveBeenCalledTimes(1); + expect(captureExceptionMock).toHaveBeenCalledWith(exception, { + level: 'error', + }); + expect(addBreadcrumbMock).not.toHaveBeenCalled(); + }); +}); diff --git a/libs/api/observability/src/lib/filters/sentry-exceptions.filter.ts b/libs/api/observability/src/lib/filters/sentry-exceptions.filter.ts new file mode 100644 index 00000000..62a52efd --- /dev/null +++ b/libs/api/observability/src/lib/filters/sentry-exceptions.filter.ts @@ -0,0 +1,26 @@ +import { Catch, ExceptionFilter } from '@nestjs/common'; +import * as Sentry from '@sentry/node'; + +import { PresentableException } from '@kordis/api/shared'; + +@Catch() +export class SentryExceptionsFilter implements ExceptionFilter { + catch(exception: unknown): void { + if (exception instanceof PresentableException) { + // if this is a presentable error, such as a validation error, we don't want to log it as an error but rather as an information to have the context for possible future debugging + Sentry.addBreadcrumb({ + level: 'error', + message: exception.message, + data: { + code: exception.code, + name: exception.name, + stack: exception.stack, + }, + }); + } else { + Sentry.captureException(exception, { + level: 'error', + }); + } + } +} diff --git a/libs/api/observability/src/lib/interceptors/sentry-otel-user-context.interceptor.spec.ts b/libs/api/observability/src/lib/interceptors/sentry-otel-user-context.interceptor.spec.ts index 20add49c..2f9b50c6 100644 --- a/libs/api/observability/src/lib/interceptors/sentry-otel-user-context.interceptor.spec.ts +++ b/libs/api/observability/src/lib/interceptors/sentry-otel-user-context.interceptor.spec.ts @@ -27,6 +27,7 @@ describe('SentryOTelUserContextInterceptor', () => { email: 'test@example.com', firstName: 'John', lastName: 'Doe', + organization: 'testorg', }; const ctx = createGqlContextForRequest( diff --git a/libs/api/observability/src/lib/oTel.factory.ts b/libs/api/observability/src/lib/oTel.factory.ts index 42b68d17..b0f901c1 100644 --- a/libs/api/observability/src/lib/oTel.factory.ts +++ b/libs/api/observability/src/lib/oTel.factory.ts @@ -1,6 +1,7 @@ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc'; import { GraphQLInstrumentation } from '@opentelemetry/instrumentation-graphql'; import { MongooseInstrumentation } from '@opentelemetry/instrumentation-mongoose'; +import { PinoInstrumentation } from '@opentelemetry/instrumentation-pino'; import { NodeSDK } from '@opentelemetry/sdk-node'; import { SentryPropagator, @@ -11,8 +12,10 @@ export abstract class OTelSDKFactory { protected readonly defaultInstrumentations = [ new GraphQLInstrumentation(), new MongooseInstrumentation(), + new PinoInstrumentation(), ] as const; protected readonly serviceName = 'kordis-api'; + abstract makeSdk(): NodeSDK; } diff --git a/libs/api/observability/src/lib/sentry-observability.module.ts b/libs/api/observability/src/lib/sentry-observability.module.ts index 54e2410c..667406ef 100644 --- a/libs/api/observability/src/lib/sentry-observability.module.ts +++ b/libs/api/observability/src/lib/sentry-observability.module.ts @@ -1,16 +1,33 @@ -import { Module, OnModuleInit } from '@nestjs/common'; +import { Logger, Module, OnModuleInit } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; -import { APP_INTERCEPTOR, ModulesContainer } from '@nestjs/core'; +import { APP_FILTER, APP_INTERCEPTOR, ModulesContainer } from '@nestjs/core'; import { init as initSentry } from '@sentry/node'; import { ProfilingIntegration } from '@sentry/profiling-node'; +import { SentryExceptionsFilter } from './filters/sentry-exceptions.filter'; import { SentryOTelUserContextInterceptor } from './interceptors/sentry-otel-user-context.interceptor'; import oTelSDK from './oTelSdk'; +import { KORDIS_LOGGER_SERVICE } from './services/kordis-logger-service.interface'; +import { KordisLogger } from './services/kordis-logger.interface'; +import { KordisLoggerImpl } from './services/kordis.logger'; +import { SentryLogger } from './services/sentry-logger.service'; import { wrapProvidersWithTracingSpans } from './trace-wrapper'; // This Module must come after the AuthModule, because it depends on the use set by the AuthInterceptor @Module({ providers: [ + { + provide: Logger, + useClass: KordisLoggerImpl, + }, + { + provide: KORDIS_LOGGER_SERVICE, + useClass: SentryLogger, + }, + { + provide: APP_FILTER, + useClass: SentryExceptionsFilter, + }, { provide: APP_INTERCEPTOR, useClass: SentryOTelUserContextInterceptor, @@ -18,6 +35,10 @@ import { wrapProvidersWithTracingSpans } from './trace-wrapper'; ], }) export class SentryObservabilityModule implements OnModuleInit { + private readonly logger: KordisLogger = new Logger( + SentryObservabilityModule.name, + ); + constructor( private readonly config: ConfigService, private readonly modulesContainer: ModulesContainer, @@ -35,5 +56,7 @@ export class SentryObservabilityModule implements OnModuleInit { }); wrapProvidersWithTracingSpans(this.modulesContainer); oTelSDK.start(); + + this.logger.log('Sentry initialized'); } } diff --git a/libs/api/observability/src/lib/services/kordis-logger-service.interface.ts b/libs/api/observability/src/lib/services/kordis-logger-service.interface.ts new file mode 100644 index 00000000..f292531c --- /dev/null +++ b/libs/api/observability/src/lib/services/kordis-logger-service.interface.ts @@ -0,0 +1,15 @@ +import { LoggerService } from '@nestjs/common'; + +export const KORDIS_LOGGER_SERVICE = Symbol('KORDIS_LOGGER_SERVICE'); + +export interface KordisLoggerService extends LoggerService { + log(message: string, context?: string, args?: object): void; + + error(message: string, trace?: string, context?: string, args?: object): void; + + warn(message: string, context?: string, args?: object): void; + + debug(message: string, context?: string, args?: object): void; + + verbose(message: string, context?: string, args?: object): void; +} diff --git a/libs/api/observability/src/lib/services/kordis-logger.interface.ts b/libs/api/observability/src/lib/services/kordis-logger.interface.ts new file mode 100644 index 00000000..27175ec0 --- /dev/null +++ b/libs/api/observability/src/lib/services/kordis-logger.interface.ts @@ -0,0 +1,13 @@ +import { LoggerService } from '@nestjs/common'; + +export interface KordisLogger extends LoggerService { + log(message: string, args?: object): void; + + error(message: string, trace?: string, args?: object): void; + + warn(message: string, args?: object): void; + + debug(message: string, args?: object): void; + + verbose(message: string, args?: object): void; +} diff --git a/libs/api/observability/src/lib/services/kordis.logger.spec.ts b/libs/api/observability/src/lib/services/kordis.logger.spec.ts new file mode 100644 index 00000000..cc5b83b1 --- /dev/null +++ b/libs/api/observability/src/lib/services/kordis.logger.spec.ts @@ -0,0 +1,102 @@ +import { createMock } from '@golevelup/ts-jest'; + +import { KordisLoggerService } from './kordis-logger-service.interface'; +import { KordisLoggerImpl } from './kordis.logger'; + +describe('KordisLoggerImpl', () => { + let loggerServiceMock: KordisLoggerService; + let logger: KordisLoggerImpl; + + beforeEach(() => { + loggerServiceMock = createMock(); + logger = new KordisLoggerImpl(loggerServiceMock); + }); + + it('should call debug with correct parameter', () => { + logger.debug( + 'Test debug message', + { someProp: 'someValue' }, + 'nestJsInjectedContext', + ); + + expect(loggerServiceMock.debug).toHaveBeenCalledWith( + 'Test debug message', + 'nestJsInjectedContext', + { someProp: 'someValue' }, + ); + }); + + it('should call error with correct parameter', () => { + logger.error( + 'Test error message', + { someProp: 'someValue' }, + 'nestJsInjectedTrace', + 'nestJsInjectedContext', + ); + + expect(loggerServiceMock.error).toHaveBeenCalledWith( + 'Test error message', + 'nestJsInjectedTrace', + 'nestJsInjectedContext', + { someProp: 'someValue' }, + ); + }); + + it('should call error without trace and correct parameter', () => { + logger.error( + 'Test error message', + { someProp: 'someValue' }, + '', + 'nestJsInjectedContext', + ); + + expect(loggerServiceMock.error).toHaveBeenCalledWith( + 'Test error message', + undefined, + 'nestJsInjectedContext', + { someProp: 'someValue' }, + ); + }); + + it('should call log with correct parameter', () => { + logger.log( + 'Test log message', + { someProp: 'someValue' }, + 'nestJsInjectedContext', + ); + + expect(loggerServiceMock.log).toHaveBeenCalledWith( + 'Test log message', + 'nestJsInjectedContext', + { someProp: 'someValue' }, + ); + }); + + it('should call verbose with correct parameter', () => { + logger.verbose( + 'Test verbose message', + { someProp: 'someValue' }, + 'nestJsInjectedContext', + ); + + expect(loggerServiceMock.verbose).toHaveBeenCalledWith( + 'Test verbose message', + 'nestJsInjectedContext', + { someProp: 'someValue' }, + ); + }); + + it('should call warn with correct parameter', () => { + logger.warn( + 'Test warn message', + { someProp: 'someValue' }, + 'nestJsInjectedContext', + ); + + expect(loggerServiceMock.warn).toHaveBeenCalledWith( + 'Test warn message', + 'nestJsInjectedContext', + { someProp: 'someValue' }, + ); + }); +}); diff --git a/libs/api/observability/src/lib/services/kordis.logger.ts b/libs/api/observability/src/lib/services/kordis.logger.ts new file mode 100644 index 00000000..51ad6093 --- /dev/null +++ b/libs/api/observability/src/lib/services/kordis.logger.ts @@ -0,0 +1,69 @@ +import { Inject, LoggerService } from '@nestjs/common'; + +import { + KORDIS_LOGGER_SERVICE, + KordisLoggerService, +} from './kordis-logger-service.interface'; +import { KordisLogger } from './kordis-logger.interface'; + +export class KordisLoggerImpl implements LoggerService, KordisLogger { + constructor( + @Inject(KORDIS_LOGGER_SERVICE) private readonly logger: KordisLoggerService, + ) {} + + debug(message: string, ...optionalParams: unknown[]): void { + const { context, args } = this.getDestructedParams(optionalParams); + this.logger.debug(message, context, args); + } + + error(message: string, ...optionalParams: unknown[]): void { + const { context, args, leftOverParams } = + this.getDestructedParams(optionalParams); + const trace = + leftOverParams && leftOverParams.length > 0 + ? (leftOverParams[0] as string) || undefined + : undefined; + + this.logger.error(message, trace, context, args); + } + + log(message: string, ...optionalParams: unknown[]): void { + const { context, args } = this.getDestructedParams(optionalParams); + this.logger.log(message, context, args); + } + + verbose(message: string, ...optionalParams: unknown[]): void { + const { context, args } = this.getDestructedParams(optionalParams); + this.logger.verbose(message, context, args); + } + + warn(message: string, ...optionalParams: unknown[]): void { + const { context, args } = this.getDestructedParams(optionalParams); + this.logger.warn(message, context, args); + } + + private getDestructedParams(params: unknown[]): { + args: object | undefined; + context: string | undefined; + leftOverParams: unknown[] | undefined; + } { + let context: string | undefined; + let args: object | undefined; + let leftOverParams: unknown[] | undefined; + // context will be passed as last argument by nestjs, this is why we need the following + if (params.length > 0) { + const possibleContext = params[params.length - 1]; + if (typeof possibleContext === 'string') { + context = possibleContext; + } + + // the first argument can be an object, which will be passed as args to the logger, further parameters might be of interest, so we pass them as well + leftOverParams = params.slice(0, -1); + if (leftOverParams.length > 0 && typeof leftOverParams[0] === 'object') { + args = leftOverParams.shift() as object; + } + } + + return { context, args, leftOverParams }; + } +} diff --git a/libs/api/observability/src/lib/services/pino-logger.service.spec.ts b/libs/api/observability/src/lib/services/pino-logger.service.spec.ts new file mode 100644 index 00000000..fc3ccc81 --- /dev/null +++ b/libs/api/observability/src/lib/services/pino-logger.service.spec.ts @@ -0,0 +1,126 @@ +import pino from 'pino'; + +import { PinoLogger } from './pino-logger.service'; + +jest.mock('pino', () => { + return { + __esModule: true, + default: jest.fn().mockReturnValue({ + info: jest.fn(), + error: jest.fn(), + warn: jest.fn(), + debug: jest.fn(), + trace: jest.fn(), + }), + }; +}); + +describe('PinoLogger', () => { + let logger: PinoLogger; + const pinoMock = pino as unknown as jest.Mock; + const pinoLoggerMock: jest.Mocked = pinoMock(); + + it('should initialize pino with the correct configuration when debug is true', () => { + const debug = true; + logger = new PinoLogger(debug); + + expect(pinoMock).toHaveBeenCalledWith({ + level: 'trace', + transport: { + target: 'pino-pretty', + colorize: true, + translateTime: 'SYS:dd.mm.yyyy hh:MM:ss', + ignore: 'pid,hostname', + }, + }); + }); + + it('should initialize pino with the correct configuration when debug is false', () => { + const debug = false; + logger = new PinoLogger(debug); + + expect(pinoMock).toHaveBeenCalledWith({ + level: 'info', + }); + }); + + it('should call pino info on log', () => { + logger = new PinoLogger(false); + logger.log('message', 'context'); + + expect(pinoLoggerMock.info).toHaveBeenCalledWith( + { context: 'context' }, + 'message', + ); + + logger.log('message', 'context', { some: 'object' }); + expect(pinoLoggerMock.info).toHaveBeenCalledWith( + { some: 'object', context: 'context' }, + 'message', + ); + }); + + it('should call pino debug on debug', () => { + logger = new PinoLogger(false); + logger.debug('message', 'context'); + + expect(pinoLoggerMock.debug).toHaveBeenCalledWith( + { context: 'context' }, + 'message', + ); + + logger.debug('message', 'context', { some: 'object' }); + expect(pinoLoggerMock.debug).toHaveBeenCalledWith( + { some: 'object', context: 'context' }, + 'message', + ); + }); + + it('should call pino trace on verbose', () => { + logger = new PinoLogger(false); + logger.verbose('message', 'context'); + + expect(pinoLoggerMock.trace).toHaveBeenCalledWith( + { context: 'context' }, + 'message', + ); + + logger.verbose('message', 'context', { some: 'object' }); + expect(pinoLoggerMock.trace).toHaveBeenCalledWith( + { some: 'object', context: 'context' }, + 'message', + ); + }); + + it('should call pino warn on warn', () => { + logger = new PinoLogger(false); + logger.warn('message', 'context'); + + expect(pinoLoggerMock.warn).toHaveBeenCalledWith( + { context: 'context' }, + 'message', + ); + + logger.warn('message', 'context', { some: 'object' }); + expect(pinoLoggerMock.warn).toHaveBeenCalledWith( + { some: 'object', context: 'context' }, + 'message', + ); + }); + + it('should call pino error on error', () => { + logger = new PinoLogger(false); + logger.error('message', 'trace', 'context'); + + expect(pinoLoggerMock.error).toHaveBeenCalledWith( + { context: 'context', trace: 'trace' }, + 'message', + ); + + logger.error('message', 'trace', 'context', { some: 'object' }); + expect(pinoLoggerMock.error).toHaveBeenCalledWith( + { context: 'context', some: 'object', trace: 'trace' }, + 'message', + ); + }); +}); diff --git a/libs/api/observability/src/lib/services/pino-logger.service.ts b/libs/api/observability/src/lib/services/pino-logger.service.ts new file mode 100644 index 00000000..41262414 --- /dev/null +++ b/libs/api/observability/src/lib/services/pino-logger.service.ts @@ -0,0 +1,84 @@ +import pino from 'pino'; + +import { KordisLoggerService } from './kordis-logger-service.interface'; + +/* + * This logger is used for logging with pino to the console. If debug is set to false, it will only log info and above as json output, otherwise as a pretty print. + */ +export class PinoLogger implements KordisLoggerService { + private readonly logger: pino.Logger; + + constructor(debug: boolean) { + this.logger = pino( + debug + ? { + level: 'trace', + transport: { + target: 'pino-pretty', + colorize: true, + translateTime: 'SYS:dd.mm.yyyy hh:MM:ss', + ignore: 'pid,hostname', + }, + } + : { + level: 'info', + }, + ); + } + + log(message: string, context?: string, args?: object): void { + this.logger.info( + { + context, + ...args, + }, + message, + ); + } + + error( + message: string, + trace?: string, + context?: string, + args?: object, + ): void { + this.logger.error( + { + trace, + context, + ...args, + }, + message, + ); + } + + warn(message: string, context?: string, args?: object): void { + this.logger.warn( + { + context, + ...args, + }, + message, + ); + } + + debug(message: string, context?: string, args?: object): void { + this.logger.debug( + { + context, + ...args, + }, + message, + ); + } + + verbose(message: string, context?: string, args?: object): void { + this.logger.trace( + { + context, + ...args, + }, + message, + ); + } +} diff --git a/libs/api/observability/src/lib/services/sentry-logger.service.spec.ts b/libs/api/observability/src/lib/services/sentry-logger.service.spec.ts new file mode 100644 index 00000000..9313979f --- /dev/null +++ b/libs/api/observability/src/lib/services/sentry-logger.service.spec.ts @@ -0,0 +1,93 @@ +import * as Sentry from '@sentry/node'; + +import { PinoLogger } from './pino-logger.service'; +import { SentryLogger } from './sentry-logger.service'; + +jest.mock('@sentry/node', () => ({ + addBreadcrumb: jest.fn(), +})); + +// mock to disable console output +jest.mock('pino', () => { + return { + __esModule: true, + default: jest.fn().mockReturnValue({ + info: jest.fn(), + error: jest.fn(), + warn: jest.fn(), + debug: jest.fn(), + trace: jest.fn(), + }), + }; +}); + +describe('SentryLogger', () => { + let logger: SentryLogger; + let addBreadcrumbSpy: jest.SpyInstance; + + beforeEach(() => { + addBreadcrumbSpy = jest.spyOn(Sentry, 'addBreadcrumb').mockImplementation(); + logger = new SentryLogger(); + }); + + afterEach(() => { + addBreadcrumbSpy.mockClear(); + }); + + it('should call the log method of the parent class and add breadcrumb to Sentry', () => { + const message = 'Test log message'; + const context = 'Test context'; + const pinoLoggerSpy = jest.spyOn(PinoLogger.prototype, 'log'); + + logger.log(message, context, { some: 'object' }); + expect(pinoLoggerSpy).toHaveBeenCalledWith(message, context, { + some: 'object', + }); + expect(addBreadcrumbSpy).toHaveBeenCalledWith({ + message, + type: 'logger', + level: 'log', + data: { context, some: 'object' }, + }); + }); + + it('should call the error method of the parent class and add breadcrumb to Sentry', () => { + const message = 'Test error message'; + const trace = 'Test error trace'; + const context = 'Test context'; + const pinoLoggerSpy = jest.spyOn(PinoLogger.prototype, 'error'); + + logger.error(message, trace, context, { + some: 'object', + }); + expect(pinoLoggerSpy).toHaveBeenCalledWith(message, trace, context, { + some: 'object', + }); + expect(addBreadcrumbSpy).toHaveBeenCalledWith({ + message, + type: 'logger', + level: 'error', + data: { context, trace, some: 'object' }, + }); + }); + + it('should call the warn and add breadcrumb to Sentry', () => { + const message = 'Test warn message'; + const context = 'Test context'; + const pinoLoggerSpy = jest.spyOn(PinoLogger.prototype, 'warn'); + + logger.warn(message, context, { + some: 'object', + }); + + expect(pinoLoggerSpy).toHaveBeenCalledWith(message, context, { + some: 'object', + }); + expect(addBreadcrumbSpy).toHaveBeenCalledWith({ + message, + type: 'logger', + level: 'warning', + data: { context, some: 'object' }, + }); + }); +}); diff --git a/libs/api/observability/src/lib/services/sentry-logger.service.ts b/libs/api/observability/src/lib/services/sentry-logger.service.ts new file mode 100644 index 00000000..3e1d0b01 --- /dev/null +++ b/libs/api/observability/src/lib/services/sentry-logger.service.ts @@ -0,0 +1,47 @@ +import * as Sentry from '@sentry/node'; + +import { PinoLogger } from './pino-logger.service'; + +export class SentryLogger extends PinoLogger { + constructor() { + super(false); + } + + override log(message: string, context?: string, args?: object): void { + super.log(message, context, args); + + Sentry.addBreadcrumb({ + message, + type: 'logger', + level: 'log', + data: { context, ...args }, + }); + } + + override error( + message: string, + trace?: string, + context?: string, + args?: object, + ): void { + super.error(message, trace, context, args); + + Sentry.addBreadcrumb({ + message, + type: 'logger', + level: 'error', + data: { context, trace, ...args }, + }); + } + + override warn(message: string, context?: string, args?: object): void { + super.warn(message, context, args); + + Sentry.addBreadcrumb({ + message, + type: 'logger', + level: 'warning', + data: { context, ...args }, + }); + } +} diff --git a/libs/api/observability/tsconfig.json b/libs/api/observability/tsconfig.json index 18d14d61..f1edc0cf 100644 --- a/libs/api/observability/tsconfig.json +++ b/libs/api/observability/tsconfig.json @@ -7,7 +7,8 @@ "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": false, "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true + "noFallthroughCasesInSwitch": true, + "strictPropertyInitialization": false }, "files": [], "include": [], diff --git a/libs/api/organization/.eslintrc.json b/libs/api/organization/.eslintrc.json new file mode 100644 index 00000000..79fd7c1d --- /dev/null +++ b/libs/api/organization/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/libs/api/organization/jest.config.ts b/libs/api/organization/jest.config.ts new file mode 100644 index 00000000..5494e780 --- /dev/null +++ b/libs/api/organization/jest.config.ts @@ -0,0 +1,11 @@ +/* eslint-disable */ +export default { + displayName: 'api-organization', + preset: '../../../jest.preset.js', + testEnvironment: 'node', + transform: { + '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], + }, + moduleFileExtensions: ['ts', 'js', 'html'], + coverageDirectory: '../../../coverage/libs/api/organization', +}; diff --git a/libs/api/organization/project.json b/libs/api/organization/project.json new file mode 100644 index 00000000..3de67240 --- /dev/null +++ b/libs/api/organization/project.json @@ -0,0 +1,30 @@ +{ + "name": "api-organization", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/api/organization/src", + "projectType": "library", + "targets": { + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["libs/api/organization/**/*.ts"] + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/api/organization/jest.config.ts", + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "codeCoverage": true + } + } + } + }, + "tags": [] +} diff --git a/libs/api/organization/src/index.ts b/libs/api/organization/src/index.ts new file mode 100644 index 00000000..eac3f558 --- /dev/null +++ b/libs/api/organization/src/index.ts @@ -0,0 +1 @@ +export * from './lib/infra/organization.module'; diff --git a/libs/api/organization/src/lib/core/command/create-organization.command.ts b/libs/api/organization/src/lib/core/command/create-organization.command.ts new file mode 100644 index 00000000..9a668cd0 --- /dev/null +++ b/libs/api/organization/src/lib/core/command/create-organization.command.ts @@ -0,0 +1,51 @@ +import { Inject, Logger } from '@nestjs/common'; +import { CommandHandler, EventBus, ICommandHandler } from '@nestjs/cqrs'; + +import type { KordisLogger } from '@kordis/api/observability'; + +import { + Organization, + OrganizationGeoSettings, +} from '../entity/organization.entity'; +import { OrganizationCreatedEvent } from '../event/organization-created.event'; +import { + ORGANIZATION_REPOSITORY, + OrganizationRepository, +} from '../repository/organization.repository'; + +export class CreateOrganizationCommand { + constructor( + public readonly name: string, + public readonly geoSettings: OrganizationGeoSettings, + ) {} +} + +@CommandHandler(CreateOrganizationCommand) +export class CreateOrganizationHandler + implements ICommandHandler +{ + private readonly logger: KordisLogger = new Logger( + CreateOrganizationHandler.name, + ); + + constructor( + @Inject(ORGANIZATION_REPOSITORY) + private readonly repository: OrganizationRepository, + private readonly eventBus: EventBus, + ) {} + + async execute(command: CreateOrganizationCommand): Promise { + let org = new Organization(); + org.geoSettings = command.geoSettings; + org.name = command.name; + + await org.validOrThrow(); + + org = await this.repository.create(org); + this.logger.log('Organization created', { org }); + + this.eventBus.publish(new OrganizationCreatedEvent(org)); + + return org; + } +} diff --git a/libs/api/organization/src/lib/core/command/update-organization-geo-settings.command.spec.ts b/libs/api/organization/src/lib/core/command/update-organization-geo-settings.command.spec.ts new file mode 100644 index 00000000..a5de8c54 --- /dev/null +++ b/libs/api/organization/src/lib/core/command/update-organization-geo-settings.command.spec.ts @@ -0,0 +1,90 @@ +import { createMock } from '@golevelup/ts-jest'; +import { EventBus } from '@nestjs/cqrs'; + +import { + Organization, + OrganizationGeoSettings, +} from '../entity/organization.entity'; +import { OrganizationGeoSettingsUpdatedEvent } from '../event/organization-geo-settings-updated.event'; +import { OrganizationNotFoundException } from '../exceptions/organization-not-found.exception'; +import { OrganizationRepository } from '../repository/organization.repository'; +import { + UpdateOrganizationGeoSettingsCommand, + UpdateOrganizationGeoSettingsHandler, +} from './update-organization-geo-settings.command'; + +describe('UpdateOrganizationGeoSettingsHandler', () => { + let handler: UpdateOrganizationGeoSettingsHandler; + const repositoryMock = createMock(); + const eventBusMock = createMock(); + + beforeEach(() => { + handler = new UpdateOrganizationGeoSettingsHandler( + repositoryMock, + eventBusMock, + ); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + it('should update organization geo settings and publish an event', async () => { + const orgId = 'org-id'; + const geoSettings: OrganizationGeoSettings = { + bbox: { + bottomRight: { lon: 12, lat: 53.551086 }, + topLeft: { lon: 12, lat: 53.551086 }, + }, + centroid: { + lon: 12, + lat: 53.551086, + }, + }; + const org: { -readonly [K in keyof Organization]: Organization[K] } = + new Organization(); + org.id = orgId; + org.name = 'org name'; + org.geoSettings = {} as OrganizationGeoSettings; + + repositoryMock.findById.mockResolvedValueOnce(org); + repositoryMock.update.mockResolvedValueOnce(undefined); + + const eventPublishSpy = jest.spyOn(eventBusMock, 'publish'); + + const command = new UpdateOrganizationGeoSettingsCommand( + orgId, + geoSettings, + ); + const result = await handler.execute(command); + + expect(repositoryMock.findById).toHaveBeenCalledWith(orgId); + expect(eventPublishSpy).toHaveBeenCalledWith( + new OrganizationGeoSettingsUpdatedEvent(org.id, geoSettings), + ); + expect(result.geoSettings).toEqual(geoSettings); + }); + + it('should throw NotFoundException if organization is not found', async () => { + const orgId = 'org-id'; + const geoSettings: OrganizationGeoSettings = { + bbox: { + bottomRight: { lon: 9.993682, lat: 53.551086 }, + topLeft: { lon: 9.993682, lat: 53.551086 }, + }, + centroid: { + lon: 9.993682, + lat: 53.551086, + }, + }; + repositoryMock.findById.mockResolvedValueOnce(null); + + const command = new UpdateOrganizationGeoSettingsCommand( + orgId, + geoSettings, + ); + await expect(handler.execute(command)).rejects.toThrow( + OrganizationNotFoundException, + ); + }); +}); diff --git a/libs/api/organization/src/lib/core/command/update-organization-geo-settings.command.ts b/libs/api/organization/src/lib/core/command/update-organization-geo-settings.command.ts new file mode 100644 index 00000000..3667321a --- /dev/null +++ b/libs/api/organization/src/lib/core/command/update-organization-geo-settings.command.ts @@ -0,0 +1,60 @@ +import { Inject, Logger } from '@nestjs/common'; +import { CommandHandler, EventBus, ICommandHandler } from '@nestjs/cqrs'; + +import { KordisLogger } from '@kordis/api/observability'; + +import { + Organization, + OrganizationGeoSettings, +} from '../entity/organization.entity'; +import { OrganizationGeoSettingsUpdatedEvent } from '../event/organization-geo-settings-updated.event'; +import { OrganizationNotFoundException } from '../exceptions/organization-not-found.exception'; +import { + ORGANIZATION_REPOSITORY, + OrganizationRepository, +} from '../repository/organization.repository'; + +export class UpdateOrganizationGeoSettingsCommand { + constructor( + public readonly orgId: string, + public readonly geoSettings: OrganizationGeoSettings, + ) {} +} + +@CommandHandler(UpdateOrganizationGeoSettingsCommand) +export class UpdateOrganizationGeoSettingsHandler + implements ICommandHandler +{ + private readonly logger: KordisLogger = new Logger( + UpdateOrganizationGeoSettingsHandler.name, + ); + + constructor( + @Inject(ORGANIZATION_REPOSITORY) + private readonly repository: OrganizationRepository, + private readonly eventBus: EventBus, + ) {} + + async execute( + command: UpdateOrganizationGeoSettingsCommand, + ): Promise { + const org = await this.repository.findById(command.orgId); + + if (!org) { + throw new OrganizationNotFoundException(command.orgId); + } + + org.geoSettings = command.geoSettings; + + await org.validOrThrow(); + + await this.repository.update(org); + + this.logger.log('Organization geo settings updated', { updatedOrg: org }); + this.eventBus.publish( + new OrganizationGeoSettingsUpdatedEvent(org.id, org.geoSettings), + ); + + return org; + } +} diff --git a/libs/api/organization/src/lib/core/entity/bbox.validator.spec.ts b/libs/api/organization/src/lib/core/entity/bbox.validator.spec.ts new file mode 100644 index 00000000..65acb6fa --- /dev/null +++ b/libs/api/organization/src/lib/core/entity/bbox.validator.spec.ts @@ -0,0 +1,34 @@ +import { IsBBox } from './bbox.validator'; +import { BBox } from './organization.entity'; + +describe('BBox Validator', () => { + const bboxValidator = new IsBBox(); + it('should return true for a valid BBox', () => { + const bbox = new BBox(); + bbox.topLeft = { + lat: 53, + lon: 12, + }; + bbox.bottomRight = { + lat: 52, + lon: 14, + }; + + expect(bboxValidator.validate(bbox)).toBe(true); + }); + + it('should return false for an invalid BBox', () => { + const bbox = new BBox(); + + bbox.topLeft = { + lat: 52, + lon: 14, + }; + bbox.bottomRight = { + lat: 53, + lon: 12, + }; + + expect(bboxValidator.validate(bbox)).toBe(false); + }); +}); diff --git a/libs/api/organization/src/lib/core/entity/bbox.validator.ts b/libs/api/organization/src/lib/core/entity/bbox.validator.ts new file mode 100644 index 00000000..98b0973a --- /dev/null +++ b/libs/api/organization/src/lib/core/entity/bbox.validator.ts @@ -0,0 +1,13 @@ +import { + ValidatorConstraint, + ValidatorConstraintInterface, +} from 'class-validator'; + +import { BBox } from './organization.entity'; + +@ValidatorConstraint() +export class IsBBox implements ValidatorConstraintInterface { + validate({ topLeft, bottomRight }: BBox): boolean { + return topLeft.lat >= bottomRight.lat && topLeft.lon <= bottomRight.lon; + } +} diff --git a/libs/api/organization/src/lib/core/entity/organization.entity.ts b/libs/api/organization/src/lib/core/entity/organization.entity.ts new file mode 100644 index 00000000..28c2fabb --- /dev/null +++ b/libs/api/organization/src/lib/core/entity/organization.entity.ts @@ -0,0 +1,71 @@ +import { Field, Float, InputType, ObjectType } from '@nestjs/graphql'; +import { Type } from 'class-transformer'; +import { + IsLatitude, + IsLongitude, + IsNotEmpty, + IsString, + Validate, + ValidateNested, +} from 'class-validator'; + +import { BaseEntityModel } from '@kordis/api/shared'; + +import { IsBBox } from './bbox.validator'; + +@ObjectType() +@InputType('CoordinateInput') +export class Coordinate { + @IsLatitude({ message: 'Der Wert muss ein gültiger Längengrad sein.' }) + @Field(() => Float) + lat: number; + + @IsLongitude({ message: 'Der Wert muss ein gültiger Breitengrad sein.' }) + @Field(() => Float) + lon: number; +} + +@ObjectType() +@InputType('BBoxInput') +export class BBox { + @ValidateNested() + @Type(() => Coordinate) + @Field() + topLeft: Coordinate; + + @ValidateNested() + @Type(() => Coordinate) + @Field() + bottomRight: Coordinate; +} + +@ObjectType() +@InputType('OrganizationGeoSettingsInput') +export class OrganizationGeoSettings { + @ValidateNested() + @Type(() => Coordinate) + @Field() + centroid: Coordinate; + + @ValidateNested() + @Validate(IsBBox, { + message: + 'Für das Begrenzungsrechteck müssen die Ecken oben links und unten rechts angegeben werden.', + }) + @Type(() => BBox) + @Field() + bbox: BBox; +} + +@ObjectType() +export class Organization extends BaseEntityModel { + @IsString() + @IsNotEmpty({ message: 'Der Organisationsname darf nicht leer sein.' }) + @Field() + name: string; + + @ValidateNested() + @Type(() => OrganizationGeoSettings) + @Field() + geoSettings: OrganizationGeoSettings; +} diff --git a/libs/api/organization/src/lib/core/event/organization-created.event.ts b/libs/api/organization/src/lib/core/event/organization-created.event.ts new file mode 100644 index 00000000..d96124b2 --- /dev/null +++ b/libs/api/organization/src/lib/core/event/organization-created.event.ts @@ -0,0 +1,5 @@ +import { Organization } from '../entity/organization.entity'; + +export class OrganizationCreatedEvent { + constructor(public readonly org: Organization) {} +} diff --git a/libs/api/organization/src/lib/core/event/organization-geo-settings-updated.event.ts b/libs/api/organization/src/lib/core/event/organization-geo-settings-updated.event.ts new file mode 100644 index 00000000..b74f0ed0 --- /dev/null +++ b/libs/api/organization/src/lib/core/event/organization-geo-settings-updated.event.ts @@ -0,0 +1,8 @@ +import { OrganizationGeoSettings } from '../entity/organization.entity'; + +export class OrganizationGeoSettingsUpdatedEvent { + constructor( + public readonly orgId: string, + public readonly geoSettings: OrganizationGeoSettings, + ) {} +} diff --git a/libs/api/organization/src/lib/core/exceptions/organization-not-found.exception.ts b/libs/api/organization/src/lib/core/exceptions/organization-not-found.exception.ts new file mode 100644 index 00000000..cdec173b --- /dev/null +++ b/libs/api/organization/src/lib/core/exceptions/organization-not-found.exception.ts @@ -0,0 +1,5 @@ +export class OrganizationNotFoundException extends Error { + constructor(readonly orgId: string) { + super(`Organization ${orgId} not found.`); + } +} diff --git a/libs/api/organization/src/lib/core/query/get-organization.query.spec.ts b/libs/api/organization/src/lib/core/query/get-organization.query.spec.ts new file mode 100644 index 00000000..4cfe0c6e --- /dev/null +++ b/libs/api/organization/src/lib/core/query/get-organization.query.spec.ts @@ -0,0 +1,64 @@ +import { createMock } from '@golevelup/ts-jest'; +import { Test } from '@nestjs/testing'; + +import { Mutable } from '@kordis/api/shared'; + +import { Organization } from '../entity/organization.entity'; +import { OrganizationNotFoundException } from '../exceptions/organization-not-found.exception'; +import { + ORGANIZATION_REPOSITORY, + OrganizationRepository, +} from '../repository/organization.repository'; +import { + GetOrganizationHandler, + GetOrganizationQuery, +} from './get-organization.query'; + +describe('CreateOrganizationHandler', () => { + let getOrganizationHandler: GetOrganizationHandler; + let organizationRepository: OrganizationRepository; + + beforeEach(async () => { + const organizationRepositoryMock = createMock(); + + const moduleRef = await Test.createTestingModule({ + providers: [ + GetOrganizationHandler, + { + provide: ORGANIZATION_REPOSITORY, + useValue: organizationRepositoryMock, + }, + ], + }).compile(); + + getOrganizationHandler = moduleRef.get( + GetOrganizationHandler, + ); + organizationRepository = moduleRef.get( + ORGANIZATION_REPOSITORY, + ); + }); + + it('should return an organization', async () => { + const org: Mutable = new Organization(); + org.id = '123'; + + jest.spyOn(organizationRepository, 'findById').mockResolvedValueOnce(org); + + const query = new GetOrganizationQuery('123'); + + const result = await getOrganizationHandler.execute(query); + + expect(result).toEqual(org); + }); + + it('should throw OrganizationNotFoundException', async () => { + jest.spyOn(organizationRepository, 'findById').mockResolvedValueOnce(null); + + const query = new GetOrganizationQuery('invalidId'); + + await expect(getOrganizationHandler.execute(query)).rejects.toThrow( + OrganizationNotFoundException, + ); + }); +}); diff --git a/libs/api/organization/src/lib/core/query/get-organization.query.ts b/libs/api/organization/src/lib/core/query/get-organization.query.ts new file mode 100644 index 00000000..510d99a0 --- /dev/null +++ b/libs/api/organization/src/lib/core/query/get-organization.query.ts @@ -0,0 +1,33 @@ +import { Inject } from '@nestjs/common'; +import { IQueryHandler, QueryHandler } from '@nestjs/cqrs'; + +import { Organization } from '../entity/organization.entity'; +import { OrganizationNotFoundException } from '../exceptions/organization-not-found.exception'; +import { + ORGANIZATION_REPOSITORY, + OrganizationRepository, +} from '../repository/organization.repository'; + +export class GetOrganizationQuery { + constructor(public readonly id: string) {} +} + +@QueryHandler(GetOrganizationQuery) +export class GetOrganizationHandler + implements IQueryHandler +{ + constructor( + @Inject(ORGANIZATION_REPOSITORY) + private readonly repository: OrganizationRepository, + ) {} + + async execute({ id }: GetOrganizationQuery): Promise { + const org = await this.repository.findById(id); + + if (!org) { + throw new OrganizationNotFoundException(id); + } + + return org; + } +} diff --git a/libs/api/organization/src/lib/core/repository/organization.repository.ts b/libs/api/organization/src/lib/core/repository/organization.repository.ts new file mode 100644 index 00000000..32f43233 --- /dev/null +++ b/libs/api/organization/src/lib/core/repository/organization.repository.ts @@ -0,0 +1,11 @@ +import { Organization } from '../entity/organization.entity'; + +export const ORGANIZATION_REPOSITORY = Symbol('OrganizationRepository'); + +export interface OrganizationRepository { + findById(id: string): Promise; + + create(org: Organization): Promise; + + update(org: Organization): Promise; +} diff --git a/libs/api/organization/src/lib/infra/controller/organization.resolver.spec.ts b/libs/api/organization/src/lib/infra/controller/organization.resolver.spec.ts new file mode 100644 index 00000000..d1abe6c8 --- /dev/null +++ b/libs/api/organization/src/lib/infra/controller/organization.resolver.spec.ts @@ -0,0 +1,145 @@ +import { DeepMocked, createMock } from '@golevelup/ts-jest'; +import { CommandBus, QueryBus } from '@nestjs/cqrs'; +import { Test, TestingModule } from '@nestjs/testing'; + +import { + Mutable, + PresentableNotFoundException, + PresentableValidationException, + ValidationException, +} from '@kordis/api/shared'; + +import { CreateOrganizationCommand } from '../../core/command/create-organization.command'; +import { UpdateOrganizationGeoSettingsCommand } from '../../core/command/update-organization-geo-settings.command'; +import { + Organization, + OrganizationGeoSettings, +} from '../../core/entity/organization.entity'; +import { OrganizationNotFoundException } from '../../core/exceptions/organization-not-found.exception'; +import { OrganizationResolver } from './organization.resolver'; + +describe('OrganizationResolver', () => { + let resolver: OrganizationResolver; + let queryBusMock: DeepMocked; + let commandBusMock: DeepMocked; + + beforeEach(async () => { + queryBusMock = createMock(); + commandBusMock = createMock(); + + const module: TestingModule = await Test.createTestingModule({ + providers: [ + OrganizationResolver, + { + provide: QueryBus, + useValue: queryBusMock, + }, + { + provide: CommandBus, + useValue: commandBusMock, + }, + ], + }).compile(); + + resolver = module.get(OrganizationResolver); + }); + + describe('organization', () => { + it('should resolve organization', async () => { + const org: Mutable = new Organization(); + org.id = 'testorg'; + org.name = 'testorg'; + org.geoSettings = { + bbox: { + bottomRight: { lon: 9.993682, lat: 53.551086 }, + topLeft: { lon: 9.993682, lat: 53.551086 }, + }, + centroid: { + lon: 9.993682, + lat: 53.551086, + }, + }; + + queryBusMock.execute.mockResolvedValueOnce(org); + + await expect(resolver.organization('testorg')).resolves.toEqual(org); + }); + + it('should throw NotFoundException', async () => { + queryBusMock.execute.mockRejectedValueOnce( + new OrganizationNotFoundException('testorg'), + ); + await expect(resolver.organization('testorg')).rejects.toThrow( + PresentableNotFoundException, + ); + }); + }); + + describe('updateOrganizationGeoSettings', () => { + it('should dispatch update command', async () => { + queryBusMock.execute.mockRejectedValueOnce( + new OrganizationNotFoundException('testorg'), + ); + const geoSettings: OrganizationGeoSettings = { + bbox: { + bottomRight: { lon: 9.993682, lat: 53.551086 }, + topLeft: { lon: 9.993682, lat: 53.551086 }, + }, + centroid: { + lon: 9.993682, + lat: 53.551086, + }, + }; + await expect( + resolver.updateOrganizationGeoSettings('testorg', geoSettings), + ).resolves.toBeTruthy(); + expect(commandBusMock.execute).toHaveBeenCalledWith( + new UpdateOrganizationGeoSettingsCommand('testorg', geoSettings), + ); + }); + + it('should throw NotFoundException', async () => { + commandBusMock.execute.mockRejectedValueOnce( + new OrganizationNotFoundException('testorg'), + ); + await expect( + resolver.updateOrganizationGeoSettings('testorg', null), + ).rejects.toThrow(PresentableNotFoundException); + }); + + it('should throw PresentableValidationException', async () => { + commandBusMock.execute.mockRejectedValueOnce(new ValidationException([])); + await expect( + resolver.updateOrganizationGeoSettings('testorg', null), + ).rejects.toThrow(PresentableValidationException); + }); + }); + + describe('createOrganization', () => { + it('should dispatch create command', async () => { + const geoSettings: OrganizationGeoSettings = { + bbox: { + bottomRight: { lon: 9.993682, lat: 53.551086 }, + topLeft: { lon: 9.993682, lat: 53.551086 }, + }, + centroid: { + lon: 9.993682, + lat: 53.551086, + }, + }; + await expect( + resolver.createOrganization('testorg', geoSettings), + ).resolves.toBeTruthy(); + expect(commandBusMock.execute).toHaveBeenCalledWith( + new CreateOrganizationCommand('testorg', geoSettings), + ); + }); + + it('should throw PresentableValidationException', async () => { + commandBusMock.execute.mockRejectedValueOnce(new ValidationException([])); + await expect( + resolver.createOrganization('testorg', null), + ).rejects.toThrow(PresentableValidationException); + }); + }); +}); diff --git a/libs/api/organization/src/lib/infra/controller/organization.resolver.ts b/libs/api/organization/src/lib/infra/controller/organization.resolver.ts new file mode 100644 index 00000000..09a4d3ae --- /dev/null +++ b/libs/api/organization/src/lib/infra/controller/organization.resolver.ts @@ -0,0 +1,88 @@ +import { CommandBus, QueryBus } from '@nestjs/cqrs'; +import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'; + +import { + PresentableNotFoundException, + PresentableValidationException, + ValidationException, +} from '@kordis/api/shared'; + +import { CreateOrganizationCommand } from '../../core/command/create-organization.command'; +import { UpdateOrganizationGeoSettingsCommand } from '../../core/command/update-organization-geo-settings.command'; +import { + Organization, + OrganizationGeoSettings, +} from '../../core/entity/organization.entity'; +import { OrganizationNotFoundException } from '../../core/exceptions/organization-not-found.exception'; +import { GetOrganizationQuery } from '../../core/query/get-organization.query'; + +@Resolver(() => Organization) +export class OrganizationResolver { + constructor( + private readonly commandBus: CommandBus, + private readonly queryBus: QueryBus, + ) {} + + @Query(() => Organization) + async organization(@Args('id') id: string): Promise { + try { + return await this.queryBus.execute( + new GetOrganizationQuery(id), + ); + } catch (error) { + if (error instanceof OrganizationNotFoundException) { + throw new PresentableNotFoundException( + `Die Organisation mit der ID ${id} wurde nicht gefunden.`, + ); + } + + throw error; + } + } + + @Mutation(() => Organization) + async updateOrganizationGeoSettings( + @Args('id') id: string, + @Args('geoSettings') geoSettings: OrganizationGeoSettings, + ): Promise { + try { + return await this.commandBus.execute( + new UpdateOrganizationGeoSettingsCommand(id, geoSettings), + ); + } catch (error) { + if (error instanceof ValidationException) { + throw PresentableValidationException.fromCoreValidationException( + 'Die Einstellungen enthalten invalide Werte.', + error, + ); + } else if (error instanceof OrganizationNotFoundException) { + throw new PresentableNotFoundException( + `Die Organisation mit der ID ${error.orgId} wurde nicht gefunden.`, + ); + } + + throw error; + } + } + + @Mutation(() => Organization) + async createOrganization( + @Args('name') name: string, + @Args('geoSettings') geoSettings: OrganizationGeoSettings, + ): Promise { + try { + return await this.commandBus.execute( + new CreateOrganizationCommand(name, geoSettings), + ); + } catch (error) { + if (error instanceof ValidationException) { + throw PresentableValidationException.fromCoreValidationException( + 'Die Organisationsdaten enthalten invalide Werte.', + error, + ); + } + + throw error; + } + } +} diff --git a/libs/api/organization/src/lib/infra/organization.mapper-profile.ts b/libs/api/organization/src/lib/infra/organization.mapper-profile.ts new file mode 100644 index 00000000..84b4ea2a --- /dev/null +++ b/libs/api/organization/src/lib/infra/organization.mapper-profile.ts @@ -0,0 +1,39 @@ +import type { Mapper } from '@automapper/core'; +import { createMap, forMember, mapFrom } from '@automapper/core'; +import { Inject, Injectable } from '@nestjs/common'; +import { + AutomapperProfile, + getMapperToken, +} from '@timonmasberg/automapper-nestjs'; + +import { Organization as OrganizationEntity } from '../core/entity/organization.entity'; +import { OrganizationDocument } from './schema/organization.schema'; + +@Injectable() +export class OrganizationProfile extends AutomapperProfile { + constructor(@Inject(getMapperToken()) mapper: Mapper) { + super(mapper); + } + + override get profile() { + return (mapper: Mapper): void => { + createMap( + mapper, + OrganizationDocument, + OrganizationEntity, + forMember( + (d) => d.name, + mapFrom((s) => s.name), + ), + forMember( + (d) => d.geoSettings, + mapFrom((s) => s.geoSettings), + ), + forMember( + (d) => d.id, + mapFrom((s) => s._id.toString()), + ), + ); + }; + } +} diff --git a/libs/api/organization/src/lib/infra/organization.module.ts b/libs/api/organization/src/lib/infra/organization.module.ts new file mode 100644 index 00000000..7e7a5032 --- /dev/null +++ b/libs/api/organization/src/lib/infra/organization.module.ts @@ -0,0 +1,36 @@ +import { Module } from '@nestjs/common'; +import { CqrsModule } from '@nestjs/cqrs'; +import { MongooseModule } from '@nestjs/mongoose'; + +import { CreateOrganizationHandler } from '../core/command/create-organization.command'; +import { UpdateOrganizationGeoSettingsHandler } from '../core/command/update-organization-geo-settings.command'; +import { GetOrganizationHandler } from '../core/query/get-organization.query'; +import { ORGANIZATION_REPOSITORY } from '../core/repository/organization.repository'; +import { OrganizationResolver } from './controller/organization.resolver'; +import { OrganizationProfile } from './organization.mapper-profile'; +import { ImplOrganizationRepository } from './repository/organization.repository'; +import { + OrganizationDocument, + OrganizationSchema, +} from './schema/organization.schema'; + +@Module({ + imports: [ + MongooseModule.forFeature([ + { name: OrganizationDocument.name, schema: OrganizationSchema }, + ]), + CqrsModule, + ], + providers: [ + OrganizationProfile, + { + provide: ORGANIZATION_REPOSITORY, + useClass: ImplOrganizationRepository, + }, + OrganizationResolver, + UpdateOrganizationGeoSettingsHandler, + GetOrganizationHandler, + CreateOrganizationHandler, + ], +}) +export class OrganizationModule {} diff --git a/libs/api/organization/src/lib/infra/repository/organization.repository.ts b/libs/api/organization/src/lib/infra/repository/organization.repository.ts new file mode 100644 index 00000000..0677238b --- /dev/null +++ b/libs/api/organization/src/lib/infra/repository/organization.repository.ts @@ -0,0 +1,49 @@ +import { Mapper } from '@automapper/core'; +import { Inject } from '@nestjs/common'; +import { InjectModel } from '@nestjs/mongoose'; +import { getMapperToken } from '@timonmasberg/automapper-nestjs'; +import { Model } from 'mongoose'; + +import { + Organization, + Organization as OrganizationEntity, +} from '../../core/entity/organization.entity'; +import { OrganizationRepository } from '../../core/repository/organization.repository'; +import { OrganizationDocument } from '../schema/organization.schema'; + +export class ImplOrganizationRepository implements OrganizationRepository { + constructor( + @InjectModel(OrganizationDocument.name) + private readonly organizationModel: Model, + @Inject(getMapperToken()) private readonly mapper: Mapper, + ) {} + + async create(org: Organization): Promise { + const orgDoc = await this.organizationModel.create(org); + + return this.mapper.mapAsync( + orgDoc.toObject(), + OrganizationDocument, + OrganizationEntity, + ); + } + + async update(org: OrganizationEntity): Promise { + await this.organizationModel + .updateOne({ _id: org.id }, { $set: org }) + .exec(); + } + + async findById(id: string): Promise { + const orgDoc = await this.organizationModel.findById(id).exec(); + if (!orgDoc) { + return null; + } + + return this.mapper.mapAsync( + orgDoc.toObject(), + OrganizationDocument, + OrganizationEntity, + ); + } +} diff --git a/libs/api/organization/src/lib/infra/repository/organization.respository.spec.ts b/libs/api/organization/src/lib/infra/repository/organization.respository.spec.ts new file mode 100644 index 00000000..ad2cb0f7 --- /dev/null +++ b/libs/api/organization/src/lib/infra/repository/organization.respository.spec.ts @@ -0,0 +1,105 @@ +import { classes } from '@automapper/classes'; +import { DeepMocked, createMock } from '@golevelup/ts-jest'; +import { getModelToken } from '@nestjs/mongoose'; +import { Test } from '@nestjs/testing'; +import { AutomapperModule } from '@timonmasberg/automapper-nestjs'; +import { Model } from 'mongoose'; + +import { Mutable } from '@kordis/api/shared'; +import { mockModelMethodResult } from '@kordis/api/test-helpers'; + +import { Organization as OrganizationEntity } from '../../core/entity/organization.entity'; +import { OrganizationProfile } from '../organization.mapper-profile'; +import { OrganizationDocument } from '../schema/organization.schema'; +import { ImplOrganizationRepository } from './organization.repository'; + +describe('ImplOrganizationRepository', () => { + let repository: ImplOrganizationRepository; + let organizationModel: Model; + + beforeEach(async () => { + const moduleRef = await Test.createTestingModule({ + imports: [ + AutomapperModule.forRoot({ + strategyInitializer: classes(), + }), + ], + providers: [ + ImplOrganizationRepository, + OrganizationProfile, + { + provide: getModelToken(OrganizationDocument.name), + useValue: createMock>(), + }, + ], + }).compile(); + + repository = moduleRef.get( + ImplOrganizationRepository, + ); + organizationModel = moduleRef.get>( + getModelToken(OrganizationDocument.name), + ); + }); + + describe('update', () => { + it('should update the organization', async () => { + const org: Mutable = new OrganizationEntity(); + org.id = 'org-id'; + org.name = 'org-name'; + const updateOneSpy = jest.spyOn(organizationModel, 'updateOne'); + + await repository.update(org); + + expect(updateOneSpy).toHaveBeenCalledWith({ _id: org.id }, { $set: org }); + }); + }); + + describe('findById', () => { + it('should return mapped organization entity', async () => { + const orgId = 'org-id'; + const orgName = 'org-name'; + const geoSettings = { + bbox: { + bottomRight: { lon: 9.993682, lat: 53.551086 }, + topLeft: { lon: 9.993682, lat: 53.551086 }, + }, + centroid: { + lon: 9.993682, + lat: 53.551086, + }, + }; + const createdAt = new Date(); + const updatedAt = new Date(); + + const orgDoc: Mutable> = + createMock(); + orgDoc._id = orgId; + orgDoc.name = orgName; + orgDoc.geoSettings = geoSettings; + orgDoc.createdAt = createdAt; + orgDoc.updatedAt = updatedAt; + + const mappedOrg: Mutable = new OrganizationEntity(); + mappedOrg.id = orgId; + mappedOrg.name = orgName; + mappedOrg.geoSettings = geoSettings; + mappedOrg.createdAt = createdAt; + mappedOrg.updatedAt = updatedAt; + + mockModelMethodResult(organizationModel, orgDoc, 'findById'); + + const result = await repository.findById(orgId); + + expect(result).toStrictEqual(mappedOrg); + }); + + it('should return null if organization is not found', async () => { + mockModelMethodResult(organizationModel, null, 'findById'); + + const result = await repository.findById('unknown-org-id'); + + expect(result).toBeNull(); + }); + }); +}); diff --git a/libs/api/organization/src/lib/infra/schema/organization.schema.ts b/libs/api/organization/src/lib/infra/schema/organization.schema.ts new file mode 100644 index 00000000..e2f02906 --- /dev/null +++ b/libs/api/organization/src/lib/infra/schema/organization.schema.ts @@ -0,0 +1,39 @@ +import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; + +import { BaseDocument } from '@kordis/api/shared'; + +@Schema({ id: false }) +export class Coordinate { + @Prop() + lat: number; + @Prop() + lon: number; +} + +@Schema({ id: false }) +export class BBox { + @Prop() + topLeft: Coordinate; + @Prop() + bottomRight: Coordinate; +} + +@Schema({ id: false }) +export class OrganizationGeoSettings { + @Prop() + centroid: Coordinate; + @Prop() + bbox: BBox; +} + +@Schema({ timestamps: true, collection: 'organizations' }) +export class OrganizationDocument extends BaseDocument { + @Prop({ unique: true }) + name: string; + + @Prop() + geoSettings: OrganizationGeoSettings; +} + +export const OrganizationSchema = + SchemaFactory.createForClass(OrganizationDocument); diff --git a/libs/api/organization/tsconfig.json b/libs/api/organization/tsconfig.json new file mode 100644 index 00000000..25f7201d --- /dev/null +++ b/libs/api/organization/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "module": "commonjs" + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/libs/api/organization/tsconfig.lib.json b/libs/api/organization/tsconfig.lib.json new file mode 100644 index 00000000..91729a40 --- /dev/null +++ b/libs/api/organization/tsconfig.lib.json @@ -0,0 +1,16 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "declaration": true, + "types": ["node"], + "target": "es2021", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "strictPropertyInitialization": false + }, + "include": ["src/**/*.ts", "../../../reset.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/libs/api/organization/tsconfig.spec.json b/libs/api/organization/tsconfig.spec.json new file mode 100644 index 00000000..231650b3 --- /dev/null +++ b/libs/api/organization/tsconfig.spec.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/libs/api/shared/src/index.ts b/libs/api/shared/src/index.ts index dda210e7..63d8639b 100644 --- a/libs/api/shared/src/index.ts +++ b/libs/api/shared/src/index.ts @@ -1,3 +1,6 @@ export * from './lib/models/request.model'; +export * from './lib/models/base-entity.model'; +export * from './lib/models/base-document.model'; export * from './lib/kernel/graphql'; export * from './lib/kernel/shared-kernel.module'; +export * from './lib/exceptions'; diff --git a/libs/api/shared/src/lib/exceptions/README.md b/libs/api/shared/src/lib/exceptions/README.md new file mode 100644 index 00000000..84a35ff5 --- /dev/null +++ b/libs/api/shared/src/lib/exceptions/README.md @@ -0,0 +1,16 @@ +## Exceptions + +Exceptions are divided in _core_ and _presentable_ exceptions. A _core_ +exception is an exception that can be thrown in the domain layer. These are +common exceptions that can be thrown in any domain. A _presentable_ exception is +an exception that can be thrown in the _infra_/application layer. These are +exceptions that are likely to reach the client and therefor should only be +thrown from controllers such as GraphQL resolvers. An example of a _presentable_ +exception is a `NotFoundException` that can be thrown when a resource is not +found, the Domain would throw a more specific Exception such as +`OperationNotFoundException`. _Presentable_ exception messages have to be in +**German**, while _core_ exceptions can be in English. + +In production environments, all errors that are not `PresentableException` will +be converted to `UnknownException`. This is done to prevent leaking information +about the application to the client. diff --git a/libs/api/shared/src/lib/exceptions/core/validation.exception.ts b/libs/api/shared/src/lib/exceptions/core/validation.exception.ts new file mode 100644 index 00000000..e4c10214 --- /dev/null +++ b/libs/api/shared/src/lib/exceptions/core/validation.exception.ts @@ -0,0 +1,13 @@ +export interface ValidationExceptionEntry { + path: string[]; + errors: string[]; +} + +export class ValidationException extends Error { + constructor( + readonly errors: ValidationExceptionEntry[], + message = 'Validation Exception', + ) { + super(message); + } +} diff --git a/libs/api/shared/src/lib/exceptions/error-formatter.spec.ts b/libs/api/shared/src/lib/exceptions/error-formatter.spec.ts new file mode 100644 index 00000000..1e4fc7ce --- /dev/null +++ b/libs/api/shared/src/lib/exceptions/error-formatter.spec.ts @@ -0,0 +1,51 @@ +import { errorFormatterFactory } from './error-formatter'; +import { PresentableException } from './presentable/presentable.exception'; + +describe('errorFormatterFactory', () => { + class MockPresentableException extends PresentableException { + code = 'MOCK_PRESENTABLE_EXCEPTION'; + + constructor(message: string) { + super(message); + } + } + + it('should format presentable exception correctly', () => { + const formattedError = { message: 'Internal server error' }; + const presentableException = new MockPresentableException( + 'Custom error message', + ); + const error = { originalError: presentableException }; + const formatter = errorFormatterFactory(false); + + const result = formatter(formattedError, error); + + expect(result).toEqual({ + message: 'Custom error message', + extensions: { code: 'MOCK_PRESENTABLE_EXCEPTION' }, + }); + }); + + it('should format unknown exception when sanitizeErrors is true', () => { + const formattedError = { message: 'Internal server error' }; + const error = {}; + + const formatter = errorFormatterFactory(true); + const result = formatter(formattedError, error); + + expect(result).toEqual({ + message: 'Ein unbekannter Fehler ist aufgetreten.', + extensions: { code: 'UNKNOWN_EXCEPTION' }, + }); + }); + + it('should return formatted error when no presentable exception and sanitizeErrors is false', () => { + const formattedError = { message: 'Internal server error' }; + const error = {}; + + const formatter = errorFormatterFactory(false); + const result = formatter(formattedError, error); + + expect(result).toEqual(formattedError); + }); +}); diff --git a/libs/api/shared/src/lib/exceptions/error-formatter.ts b/libs/api/shared/src/lib/exceptions/error-formatter.ts new file mode 100644 index 00000000..86fa54d5 --- /dev/null +++ b/libs/api/shared/src/lib/exceptions/error-formatter.ts @@ -0,0 +1,36 @@ +import { GraphQLFormattedError } from 'graphql/error'; + +import GraphqlErrorConvertable from './graphql-error-convertable'; +import { PresentableUnknownException } from './presentable/presentable-unknown.exception'; +import { PresentableException } from './presentable/presentable.exception'; + +/** + * This acts as a safeguard for unhandled errors, since they get populated over graphql. + * Every unhandled error will result in an UnknownError. + */ +export const errorFormatterFactory = (sanitizeErrors?: boolean) => { + return ( + formattedError: GraphQLFormattedError, + error: unknown, + ): GraphQLFormattedError => { + if ( + typeof error === 'object' && + error != null && + 'originalError' in error && + error.originalError instanceof PresentableException + ) { + const convertableError: GraphqlErrorConvertable = error.originalError; + return { + ...formattedError, + ...convertableError.asGraphQLError(), + }; + } + + if (sanitizeErrors) { + // sanitize all unknown errors + return new PresentableUnknownException().asGraphQLError(); + } + + return formattedError; + }; +}; diff --git a/libs/api/shared/src/lib/exceptions/flatten-class-validation-errors.spec.ts b/libs/api/shared/src/lib/exceptions/flatten-class-validation-errors.spec.ts new file mode 100644 index 00000000..afb012e6 --- /dev/null +++ b/libs/api/shared/src/lib/exceptions/flatten-class-validation-errors.spec.ts @@ -0,0 +1,42 @@ +import { ValidationExceptionEntry } from './core/validation.exception'; +import { flattenValidationErrors } from './flatten-class-validation-errors'; + +describe('flattenValidationErrors', () => { + it('should flatten validation errors correctly', () => { + const errors = [ + { + property: 'username', + constraints: { + isNotEmpty: 'Username should not be empty', + maxLength: 'Username should not exceed 20 characters', + }, + children: [ + { + property: 'email', + constraints: { + isEmail: 'Email address is invalid', + }, + }, + ], + }, + ]; + + const expected: ValidationExceptionEntry[] = [ + { + path: ['username'], + errors: [ + 'Username should not be empty', + 'Username should not exceed 20 characters', + ], + }, + { + path: ['username', 'email'], + errors: ['Email address is invalid'], + }, + ]; + + const result = flattenValidationErrors(errors); + + expect(result).toEqual(expected); + }); +}); diff --git a/libs/api/shared/src/lib/exceptions/flatten-class-validation-errors.ts b/libs/api/shared/src/lib/exceptions/flatten-class-validation-errors.ts new file mode 100644 index 00000000..9673ad01 --- /dev/null +++ b/libs/api/shared/src/lib/exceptions/flatten-class-validation-errors.ts @@ -0,0 +1,28 @@ +import { ValidationError } from 'class-validator'; + +import { ValidationExceptionEntry } from './core/validation.exception'; + +export function flattenValidationErrors( + errors: ValidationError[], +): ValidationExceptionEntry[] { + const stack: { error: ValidationError; path: string[] }[] = errors.map( + (error) => ({ error, path: [] }), + ); + const entries: ValidationExceptionEntry[] = []; + while (stack.length > 0) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const { error, path } = stack.pop()!; + const currentPath = [...path, error.property]; + if (error.constraints) { + const errorMessages = Object.values(error.constraints); + entries.push({ path: currentPath, errors: errorMessages }); + } + if (error.children) { + for (const child of error.children) { + stack.push({ error: child, path: currentPath }); + } + } + } + + return entries; +} diff --git a/libs/api/shared/src/lib/exceptions/graphql-error-convertable.ts b/libs/api/shared/src/lib/exceptions/graphql-error-convertable.ts new file mode 100644 index 00000000..0cbeec33 --- /dev/null +++ b/libs/api/shared/src/lib/exceptions/graphql-error-convertable.ts @@ -0,0 +1,5 @@ +import { GraphQLFormattedError } from 'graphql/error'; + +export default interface GraphqlErrorConvertable { + asGraphQLError(): GraphQLFormattedError; +} diff --git a/libs/api/shared/src/lib/exceptions/index.ts b/libs/api/shared/src/lib/exceptions/index.ts new file mode 100644 index 00000000..3262ef90 --- /dev/null +++ b/libs/api/shared/src/lib/exceptions/index.ts @@ -0,0 +1,6 @@ +export * from './core/validation.exception'; +export * from './presentable/presentable-not-found.exception'; +export * from './presentable/presentable-unknown.exception'; +export * from './presentable/presentable-validation.exception'; +export * from './presentable/presentable.exception'; +export * from './error-formatter'; diff --git a/libs/api/shared/src/lib/exceptions/presentable/presentable-not-found.exception.ts b/libs/api/shared/src/lib/exceptions/presentable/presentable-not-found.exception.ts new file mode 100644 index 00000000..466c5043 --- /dev/null +++ b/libs/api/shared/src/lib/exceptions/presentable/presentable-not-found.exception.ts @@ -0,0 +1,9 @@ +import { PresentableException } from './presentable.exception'; + +export class PresentableNotFoundException extends PresentableException { + readonly code = 'NOT_FOUND_EXCEPTION'; + + constructor(message = 'Nicht gefunden') { + super(message); + } +} diff --git a/libs/api/shared/src/lib/exceptions/presentable/presentable-unknown.exception.ts b/libs/api/shared/src/lib/exceptions/presentable/presentable-unknown.exception.ts new file mode 100644 index 00000000..b674867a --- /dev/null +++ b/libs/api/shared/src/lib/exceptions/presentable/presentable-unknown.exception.ts @@ -0,0 +1,9 @@ +import { PresentableException } from './presentable.exception'; + +export class PresentableUnknownException extends PresentableException { + readonly code = 'UNKNOWN_EXCEPTION'; + + constructor() { + super('Ein unbekannter Fehler ist aufgetreten.'); + } +} diff --git a/libs/api/shared/src/lib/exceptions/presentable/presentable-validation.exception.spec.ts b/libs/api/shared/src/lib/exceptions/presentable/presentable-validation.exception.spec.ts new file mode 100644 index 00000000..b3c7d5ea --- /dev/null +++ b/libs/api/shared/src/lib/exceptions/presentable/presentable-validation.exception.spec.ts @@ -0,0 +1,51 @@ +import { ValidationError } from 'class-validator'; + +import { + ValidationException, + ValidationExceptionEntry, +} from '../core/validation.exception'; +import { PresentableValidationException } from '../presentable/presentable-validation.exception'; + +describe('PresentableValidationException', () => { + const message = 'PresentableValidationException error message'; + const errors: ValidationExceptionEntry[] = [ + { path: ['name'], errors: ['Name is required'] }, + { path: ['email'], errors: ['Invalid email format'] }, + ]; + + it('should create a PresentableValidationException from CoreValidationException', () => { + const coreValidationException = new ValidationException(errors); + + const exception = + PresentableValidationException.fromCoreValidationException( + message, + coreValidationException, + ); + + expect(exception).toBeInstanceOf(PresentableValidationException); + expect(exception.message).toBe(message); + const gqlExtensionErrors = exception.asGraphQLError().extensions! + .errors as []; + expect(gqlExtensionErrors).toHaveLength(2); + expect(gqlExtensionErrors).toEqual(expect.arrayContaining(errors)); + }); + + it('should create a PresentableValidationException from ClassValidationErrors', () => { + const validationErrors: ValidationError[] = [ + { property: 'name', constraints: { required: 'Name is required' } }, + { property: 'email', constraints: { email: 'Invalid email format' } }, + ]; + + const exception = + PresentableValidationException.fromClassValidationErrors( + validationErrors, + ); + + expect(exception).toBeInstanceOf(PresentableValidationException); + expect(exception.message).toBe('Validierungsfehler'); + const gqlExtensionErrors = exception.asGraphQLError().extensions! + .errors as []; + expect(gqlExtensionErrors).toHaveLength(2); + expect(gqlExtensionErrors).toEqual(expect.arrayContaining(errors)); + }); +}); diff --git a/libs/api/shared/src/lib/exceptions/presentable/presentable-validation.exception.ts b/libs/api/shared/src/lib/exceptions/presentable/presentable-validation.exception.ts new file mode 100644 index 00000000..0441ceb0 --- /dev/null +++ b/libs/api/shared/src/lib/exceptions/presentable/presentable-validation.exception.ts @@ -0,0 +1,50 @@ +import { ValidationError } from 'class-validator'; +import { GraphQLFormattedError } from 'graphql/error'; + +import { + ValidationException, + ValidationExceptionEntry, +} from '../core/validation.exception'; +import { flattenValidationErrors } from '../flatten-class-validation-errors'; +import { PresentableException } from './presentable.exception'; + +export class PresentableValidationException extends PresentableException { + readonly code = 'VALIDATION_EXCEPTION'; + readonly graphqlError = { + test: 123, + }; + + constructor( + message: string, + private readonly errors: ValidationExceptionEntry[], + ) { + super(message); + } + + static fromCoreValidationException( + message: string, + e: ValidationException, + ): PresentableValidationException { + return new PresentableValidationException(message, e.errors); + } + + static fromClassValidationErrors( + errors: ValidationError[], + ): PresentableValidationException { + const validationExceptionEntries: ValidationExceptionEntry[] = + flattenValidationErrors(errors); + + return new PresentableValidationException( + 'Validierungsfehler', + validationExceptionEntries, + ); + } + + override asGraphQLError(): GraphQLFormattedError { + const formattedError = super.asGraphQLError(); + if (!formattedError.extensions) formattedError.extensions = {}; + formattedError.extensions.errors = this.errors; + + return formattedError; + } +} diff --git a/libs/api/shared/src/lib/exceptions/presentable/presentable.exception.ts b/libs/api/shared/src/lib/exceptions/presentable/presentable.exception.ts new file mode 100644 index 00000000..dbf2970e --- /dev/null +++ b/libs/api/shared/src/lib/exceptions/presentable/presentable.exception.ts @@ -0,0 +1,28 @@ +import { GraphQLFormattedError } from 'graphql/error'; + +import GraphqlErrorConvertable from '../graphql-error-convertable'; + +/** + * Errors are exclusive. Only Errors of type PresentableError will be delivered to external layers. + */ +export abstract class PresentableException + extends Error + implements GraphqlErrorConvertable +{ + abstract code: string; + + protected constructor(message: string) { + super(message); + } + + asGraphQLError(): Mutable { + return { + message: this.message, + extensions: { + code: this.code, + }, + }; + } +} + +export type Mutable = { -readonly [k in keyof T]: T[k] }; diff --git a/libs/api/shared/src/lib/exceptions/presentable/unknown.exception.ts b/libs/api/shared/src/lib/exceptions/presentable/unknown.exception.ts new file mode 100644 index 00000000..59341b24 --- /dev/null +++ b/libs/api/shared/src/lib/exceptions/presentable/unknown.exception.ts @@ -0,0 +1,8 @@ +import PresentableException from './presentable.exception'; + +export class UnknownException extends PresentableException { + readonly code = 'UNKNOWN_EXCEPTION'; + constructor() { + super('Ein unbekannter Fehler ist aufgetreten.'); + } +} diff --git a/libs/api/shared/src/lib/kernel/shared-kernel.module.ts b/libs/api/shared/src/lib/kernel/shared-kernel.module.ts index 435dc774..e1eb220c 100644 --- a/libs/api/shared/src/lib/kernel/shared-kernel.module.ts +++ b/libs/api/shared/src/lib/kernel/shared-kernel.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { Logger, Module } from '@nestjs/common'; import { CqrsModule } from '@nestjs/cqrs'; import { GraphQLSubscriptionService } from './graphql/subscriptions/graphql-subscription.service'; @@ -6,5 +6,12 @@ import { GraphQLSubscriptionService } from './graphql/subscriptions/graphql-subs @Module({ imports: [CqrsModule], providers: [GraphQLSubscriptionService], + exports: [GraphQLSubscriptionService], }) -export class SharedKernel {} +export class SharedKernel { + private readonly logger = new Logger(SharedKernel.name); + + constructor() { + this.logger.log('SharedKernel loaded'); + } +} diff --git a/libs/api/shared/src/lib/models/base-document.model.ts b/libs/api/shared/src/lib/models/base-document.model.ts new file mode 100644 index 00000000..4254c780 --- /dev/null +++ b/libs/api/shared/src/lib/models/base-document.model.ts @@ -0,0 +1,15 @@ +import { AutoMap } from '@automapper/classes'; +import { Prop } from '@nestjs/mongoose'; +import { Document } from 'mongoose'; + +import { BaseModel } from './base-entity.model'; + +export abstract class BaseDocument extends Document implements BaseModel { + @Prop() + @AutoMap() + readonly createdAt: Date; + + @Prop() + @AutoMap() + readonly updatedAt: Date; +} diff --git a/libs/api/shared/src/lib/models/base-entity.model.spec.ts b/libs/api/shared/src/lib/models/base-entity.model.spec.ts new file mode 100644 index 00000000..2acc13af --- /dev/null +++ b/libs/api/shared/src/lib/models/base-entity.model.spec.ts @@ -0,0 +1,54 @@ +import { validate } from 'class-validator'; + +import { ValidationException } from '../exceptions/core/validation.exception'; +import { BaseEntityModel } from './base-entity.model'; + +declare function fail(error?: any): never; + +jest.mock('class-validator', () => ({ + validate: jest.fn(), +})); + +describe('BaseEntityModel', () => { + class ProxyBaseEntityModel extends BaseEntityModel {} + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should throw ValidationException when there are validation errors', async () => { + const model = new ProxyBaseEntityModel(); + (validate as jest.Mock).mockResolvedValue([ + { + property: 'name', + constraints: { + isNotEmpty: 'Name should not be empty', + }, + }, + ]); + + let error: any; + try { + await model.validOrThrow(); + fail('Expected validation to throw an exception'); + } catch (e) { + error = e; + } finally { + expect(error).toBeInstanceOf(ValidationException); + expect(error.message).toBe('ProxyBaseEntityModel validation failed.'); + expect(error.errors).toEqual([ + { path: ['name'], errors: ['Name should not be empty'] }, + ]); + } + + expect(validate).toHaveBeenCalledWith(model); + }); + + it('should not throw any exception when there are no validation errors', async () => { + const model = new ProxyBaseEntityModel(); + (validate as jest.Mock).mockResolvedValue([]); + + await expect(model.validOrThrow()).resolves.toBeUndefined(); + expect(validate).toHaveBeenCalledWith(model); + }); +}); diff --git a/libs/api/shared/src/lib/models/base-entity.model.ts b/libs/api/shared/src/lib/models/base-entity.model.ts new file mode 100644 index 00000000..541bc9fb --- /dev/null +++ b/libs/api/shared/src/lib/models/base-entity.model.ts @@ -0,0 +1,36 @@ +import { AutoMap } from '@automapper/classes'; +import { Field, ObjectType } from '@nestjs/graphql'; +import { validate } from 'class-validator'; + +import { ValidationException } from '../exceptions'; +import { flattenValidationErrors } from '../exceptions/flatten-class-validation-errors'; + +export interface BaseModel { + readonly createdAt: Date; + readonly updatedAt: Date; +} + +@ObjectType() +export abstract class BaseEntityModel implements BaseModel { + @Field() + readonly id: string; + @Field(() => String) + @AutoMap() + readonly createdAt: Date = new Date(); + @Field(() => String) + @AutoMap() + readonly updatedAt: Date; + + async validOrThrow(): Promise { + const errors = await validate(this); + + if (errors.length > 0) { + const validationErrors = flattenValidationErrors(errors); + + throw new ValidationException( + validationErrors, + `${this.constructor.name} validation failed.`, + ); + } + } +} diff --git a/libs/api/shared/tsconfig.json b/libs/api/shared/tsconfig.json index 8122543a..5c85cec6 100644 --- a/libs/api/shared/tsconfig.json +++ b/libs/api/shared/tsconfig.json @@ -2,12 +2,12 @@ "extends": "../../../tsconfig.base.json", "compilerOptions": { "module": "commonjs", - "forceConsistentCasingInFileNames": true, "strict": true, "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true + "noFallthroughCasesInSwitch": true, + "forceConsistentCasingInFileNames": true, + "strictPropertyInitialization": false }, "files": [], "include": [], diff --git a/libs/api/test-helpers/src/index.ts b/libs/api/test-helpers/src/index.ts index 8a24680f..6135e04a 100644 --- a/libs/api/test-helpers/src/index.ts +++ b/libs/api/test-helpers/src/index.ts @@ -1,3 +1,4 @@ export * from './lib/execution-context.test-helper'; export * from './lib/decorator.test-helper'; export * from './lib/observability.test-helper'; +export * from './lib/mongo.test-helper'; diff --git a/libs/api/test-helpers/src/lib/mongo.test-helper.ts b/libs/api/test-helpers/src/lib/mongo.test-helper.ts new file mode 100644 index 00000000..8a98ff30 --- /dev/null +++ b/libs/api/test-helpers/src/lib/mongo.test-helper.ts @@ -0,0 +1,18 @@ +import { Model } from 'mongoose'; + +export function mockModelMethodResult( + model: Model, + document: Record, + method: keyof Model, +) { + const findByIdSpy = jest.spyOn(model, method as any); + + findByIdSpy.mockReturnThis().mockReturnValue({ + exec: jest.fn().mockReturnValue({ + ...document, + toObject: jest.fn().mockReturnValue(document), + }), + } as any); + + return findByIdSpy; +} diff --git a/libs/api/test-helpers/src/lib/observability.test-helper.ts b/libs/api/test-helpers/src/lib/observability.test-helper.ts index 0e348a68..ba5b90ed 100644 --- a/libs/api/test-helpers/src/lib/observability.test-helper.ts +++ b/libs/api/test-helpers/src/lib/observability.test-helper.ts @@ -1,6 +1,6 @@ import { createMock } from '@golevelup/ts-jest'; import { Span, trace } from '@opentelemetry/api'; -import { Tracer } from '@opentelemetry/tracing'; +import { Tracer } from '@opentelemetry/sdk-trace-base'; export function getComparablePrototypeSnapshot(prototype: Record) { return JSON.stringify( diff --git a/libs/api/test-helpers/tsconfig.json b/libs/api/test-helpers/tsconfig.json index f2400abe..9bde1959 100644 --- a/libs/api/test-helpers/tsconfig.json +++ b/libs/api/test-helpers/tsconfig.json @@ -1,13 +1,7 @@ { "extends": "../../../tsconfig.base.json", "compilerOptions": { - "module": "commonjs", - "forceConsistentCasingInFileNames": true, - "strict": true, - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true + "module": "commonjs" }, "files": [], "include": [], diff --git a/libs/shared/auth/src/lib/auth-user.model.ts b/libs/shared/auth/src/lib/auth-user.model.ts index 0688f731..43805c21 100644 --- a/libs/shared/auth/src/lib/auth-user.model.ts +++ b/libs/shared/auth/src/lib/auth-user.model.ts @@ -3,4 +3,5 @@ export default interface AuthUser { firstName: string; lastName: string; email: string; + organization: string; } diff --git a/libs/spa/auth/src/lib/components/dev-login.component.ts b/libs/spa/auth/src/lib/components/dev-login.component.ts index a993240f..debce8a3 100644 --- a/libs/spa/auth/src/lib/components/dev-login.component.ts +++ b/libs/spa/auth/src/lib/components/dev-login.component.ts @@ -13,6 +13,7 @@ const TEST_USERS: Readonly = Object.freeze([ lastName: 'User', email: 'testuser@test.com', id: 'testuser@kordis-leitstelle.de', + organization: 'testorganization', }, ]); diff --git a/libs/spa/auth/src/lib/interceptors/dev-auth.interceptor.spec.ts b/libs/spa/auth/src/lib/interceptors/dev-auth.interceptor.spec.ts index 8ef25619..fb75fdf9 100644 --- a/libs/spa/auth/src/lib/interceptors/dev-auth.interceptor.spec.ts +++ b/libs/spa/auth/src/lib/interceptors/dev-auth.interceptor.spec.ts @@ -39,12 +39,13 @@ describe('DevAuthInterceptor', () => { it('should add an Authorization header with Bearer token when token is present', () => { const token = - 'eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJvaWQiOiIxYTJiM2M0ZCIsImVtYWlscyI6WyJqb2huLmRvZUBleGFtcGxlLmNvbSJdLCJnaXZlbl9uYW1lIjoiSm9obiIsImZhbWlseV9uYW1lIjoiRG9lIn0.'; + 'eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJvaWQiOiIxYTJiM2M0ZCIsImVtYWlscyI6WyJqb2huLmRvZUBleGFtcGxlLmNvbSJdLCJnaXZlbl9uYW1lIjoiSm9obiIsImZhbWlseV9uYW1lIjoiRG9lIiwiZXh0ZW5zaW9uX09yZ2FuaXNhdGlvbiI6InRlc3RvcmcifQ.'; authService.setSession({ id: '1a2b3c4d', firstName: 'John', lastName: 'Doe', email: 'john.doe@example.com', + organization: 'testorg', }); httpClient.get('/test').subscribe(); diff --git a/libs/spa/auth/src/lib/services/auth.service.ts b/libs/spa/auth/src/lib/services/auth.service.ts index cbaed151..cdf5d60f 100644 --- a/libs/spa/auth/src/lib/services/auth.service.ts +++ b/libs/spa/auth/src/lib/services/auth.service.ts @@ -47,6 +47,7 @@ export class ProdAuthService implements AuthService { firstName: claims['given_name'], lastName: claims['family_name'], email: claims['emails']?.[0], + organization: claims['extension_Organisation'], }; }), shareReplay({ bufferSize: 1, refCount: true }), diff --git a/libs/spa/auth/src/lib/services/dev-auth.service.spec.ts b/libs/spa/auth/src/lib/services/dev-auth.service.spec.ts index 41b20284..f71f122a 100644 --- a/libs/spa/auth/src/lib/services/dev-auth.service.spec.ts +++ b/libs/spa/auth/src/lib/services/dev-auth.service.spec.ts @@ -34,6 +34,7 @@ describe('DevAuthService', () => { lastName: 'Doe', email: 'johndoe@example.com', id: '1234', + organization: 'testorg', }; spectator.service.setSession(user); expect(localStorage.getItem('krdDevUser')).toBe(JSON.stringify(user)); diff --git a/libs/spa/auth/src/lib/services/dev-auth.service.ts b/libs/spa/auth/src/lib/services/dev-auth.service.ts index cc5816b3..0338f41b 100644 --- a/libs/spa/auth/src/lib/services/dev-auth.service.ts +++ b/libs/spa/auth/src/lib/services/dev-auth.service.ts @@ -54,12 +54,14 @@ export class DevAuthService implements AuthService { oid: string; given_name: string; family_name: string; + extension_Organisation: string; } { return { oid: authUser.id, emails: [authUser.email], given_name: authUser.firstName, family_name: authUser.lastName, + extension_Organisation: authUser.organization, }; } diff --git a/libs/spa/observability/src/index.ts b/libs/spa/observability/src/index.ts index e4d158c7..0d73195f 100644 --- a/libs/spa/observability/src/index.ts +++ b/libs/spa/observability/src/index.ts @@ -1,4 +1,4 @@ export * from './lib/sentry-observability.module'; export * from './lib/decorators'; -export * from './lib/sentry-observability.service'; +export * from './lib/services/sentry-observability.service'; export * from './lib/noop-observability.module'; diff --git a/libs/spa/observability/src/lib/noop-observability.module.ts b/libs/spa/observability/src/lib/noop-observability.module.ts index e88a97ca..aa230a7b 100644 --- a/libs/spa/observability/src/lib/noop-observability.module.ts +++ b/libs/spa/observability/src/lib/noop-observability.module.ts @@ -4,7 +4,7 @@ import { ModuleWithProviders, NgModule } from '@angular/core'; import { NoopObservabilityService, OBSERVABILITY_SERVICE, -} from './sentry-observability.service'; +} from './services/sentry-observability.service'; @NgModule({ imports: [CommonModule], diff --git a/libs/spa/observability/src/lib/sentry-observability.module.ts b/libs/spa/observability/src/lib/sentry-observability.module.ts index 0ad96f1b..5d8f286b 100644 --- a/libs/spa/observability/src/lib/sentry-observability.module.ts +++ b/libs/spa/observability/src/lib/sentry-observability.module.ts @@ -18,7 +18,7 @@ import { import { OBSERVABILITY_SERVICE, SentryObservabilityService, -} from './sentry-observability.service'; +} from './services/sentry-observability.service'; @NgModule({ imports: [CommonModule], diff --git a/libs/spa/observability/src/lib/sentry-observability.service.spec.ts b/libs/spa/observability/src/lib/services/sentry-observability.service.spec.ts similarity index 100% rename from libs/spa/observability/src/lib/sentry-observability.service.spec.ts rename to libs/spa/observability/src/lib/services/sentry-observability.service.spec.ts diff --git a/libs/spa/observability/src/lib/sentry-observability.service.ts b/libs/spa/observability/src/lib/services/sentry-observability.service.ts similarity index 100% rename from libs/spa/observability/src/lib/sentry-observability.service.ts rename to libs/spa/observability/src/lib/services/sentry-observability.service.ts diff --git a/package-lock.json b/package-lock.json index 03f4c1be..7a115836 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,8 @@ "@angular/platform-browser-dynamic": "16.1.2", "@angular/router": "16.1.2", "@apollo/server": "^4.5.0", + "@automapper/classes": "^8.7.7", + "@automapper/core": "^8.7.7", "@nestjs/apollo": "^12.0.3", "@nestjs/common": "10.0.3", "@nestjs/config": "^3.0.0", @@ -29,18 +31,24 @@ "@nestjs/platform-express": "10.0.3", "@opentelemetry/instrumentation-graphql": "^0.35.0", "@opentelemetry/instrumentation-mongoose": "^0.33.0", + "@opentelemetry/instrumentation-pino": "^0.33.3", "@opentelemetry/sdk-node": "^0.41.0", - "@opentelemetry/tracing": "^0.24.0", - "@sentry/angular-ivy": "^7.50.0", + "@opentelemetry/sdk-trace-base": "^1.14.0", + "@sentry/angular-ivy": "^7.57.0", + "@sentry/integrations": "^7.57.0", "@sentry/node": "^7.52.1", "@sentry/opentelemetry-node": "^7.52.1", - "@sentry/profiling-node": "^1.1.2", + "@sentry/profiling-node": "^1.0.0", + "@timonmasberg/automapper-nestjs": "^0.0.0", "angular-oauth2-oidc": "^15.0.1", "axios": "^1.0.0", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.0", "graphql": "^16.6.0", "graphql-sse": "^2.1.1", - "graphql-subscriptions": "^2.0.0", "mongoose": "^7.0.3", + "pino": "^8.14.1", + "pino-pretty": "^10.0.0", "reflect-metadata": "^0.1.13", "rxjs": "~7.8.0", "tslib": "^2.3.0", @@ -539,15 +547,6 @@ "typescript": "*" } }, - "node_modules/@angular-eslint/eslint-plugin-template/node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dev": true, - "dependencies": { - "dequal": "^2.0.3" - } - }, "node_modules/@angular-eslint/template-parser": { "version": "16.1.0", "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-16.1.0.tgz", @@ -591,15 +590,15 @@ } }, "node_modules/@angular/cli": { - "version": "16.1.1", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.1.1.tgz", - "integrity": "sha512-QrTgMqMnamteZu2x3JhLMo6wBjI05zMr9RQfMHWq4UrUpTqBcHAMqJIKSSbvrtuRbolLrQyLorwxzlmEOfEmbQ==", + "version": "16.1.4", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.1.4.tgz", + "integrity": "sha512-coSOLVLpOCOD5q9K9EAFFMrTES+HtdJiLy/iI9kdKNCKWUJpm8/svZ3JZOej3vPxYEp0AokXNOwORQnX21/qZQ==", "dev": true, "dependencies": { - "@angular-devkit/architect": "0.1601.1", - "@angular-devkit/core": "16.1.1", - "@angular-devkit/schematics": "16.1.1", - "@schematics/angular": "16.1.1", + "@angular-devkit/architect": "0.1601.4", + "@angular-devkit/core": "16.1.4", + "@angular-devkit/schematics": "16.1.4", + "@schematics/angular": "16.1.4", "@yarnpkg/lockfile": "1.1.0", "ansi-colors": "4.1.3", "ini": "4.1.1", @@ -611,7 +610,7 @@ "ora": "5.4.1", "pacote": "15.2.0", "resolve": "1.22.2", - "semver": "7.5.1", + "semver": "7.5.3", "symbol-observable": "4.0.0", "yargs": "17.7.2" }, @@ -624,6 +623,108 @@ "yarn": ">= 1.13.0" } }, + "node_modules/@angular/cli/node_modules/@angular-devkit/architect": { + "version": "0.1601.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1601.4.tgz", + "integrity": "sha512-OOSbNlDy+Q3jY0oFHaq8kkna9HYI1zaS8IHeCIDP6T/ZIAVad4+HqXAL4SKQrKJikkoBQv1Z/eaDBL5XPFK9Bw==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "16.1.4", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/cli/node_modules/@angular-devkit/core": { + "version": "16.1.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.1.4.tgz", + "integrity": "sha512-WCAzNi9LxpFIi2WVPaJQd2kHPqCnCexWzUZN05ltJuBGCQL1O+LgRHGwnQ4WZoqmrF5tcWt2a3GFtJ3DgMc1hw==", + "dev": true, + "dependencies": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular/cli/node_modules/@angular-devkit/schematics": { + "version": "16.1.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.1.4.tgz", + "integrity": "sha512-yjRgwHAfFaeuimgbQtjwSUyXzEHpMSdTRb2zg+TOp6skoGvHOG8xXFJ7DjBkSMeAQdFF0fkxhPS9YmlxqNc+7A==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "16.1.4", + "jsonc-parser": "3.2.0", + "magic-string": "0.30.0", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/cli/node_modules/@schematics/angular": { + "version": "16.1.4", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.1.4.tgz", + "integrity": "sha512-XfoeL+aBVIR/DzgVKGVhHW/TGQnqWvngyJVuCwXEVWzNfjxHYFkchXa78OItpAvTEr6/Y0Me9FQVAGVA4mMUyg==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "16.1.4", + "@angular-devkit/schematics": "16.1.4", + "jsonc-parser": "3.2.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/cli/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@angular/cli/node_modules/semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@angular/common": { "version": "16.1.2", "resolved": "https://registry.npmjs.org/@angular/common/-/common-16.1.2.tgz", @@ -717,9 +818,9 @@ } }, "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -1076,6 +1177,26 @@ "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==", "dev": true }, + "node_modules/@automapper/classes": { + "version": "8.7.7", + "resolved": "https://registry.npmjs.org/@automapper/classes/-/classes-8.7.7.tgz", + "integrity": "sha512-FSbvt6QE8XnhKKQZA3kpKLuLrr9x1iW+lNYTrawVLjxQ05zsCGccLxe7moMNrg1wFAVAouQKupFgCGQ7XRjmJw==", + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@automapper/core": "8.7.7", + "reflect-metadata": "~0.1.13" + } + }, + "node_modules/@automapper/core": { + "version": "8.7.7", + "resolved": "https://registry.npmjs.org/@automapper/core/-/core-8.7.7.tgz", + "integrity": "sha512-YfpDJ/xqwUuC0S+BLNk81ZJfeL7CmjirUX/Gk9eQyx146DKvneBZgeZ9v5rDB51Ti14jTxVHis+5JuT7W/q0TA==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@aws-crypto/crc32": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", @@ -1753,9 +1874,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.5.tgz", - "integrity": "sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", + "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -1792,9 +1913,9 @@ } }, "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -1840,16 +1961,16 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz", - "integrity": "sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz", + "integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.22.5", + "@babel/compat-data": "^7.22.9", "@babel/helper-validator-option": "^7.22.5", - "browserslist": "^4.21.3", + "browserslist": "^4.21.9", "lru-cache": "^5.1.1", - "semver": "^6.3.0" + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -1868,9 +1989,9 @@ } }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -1883,9 +2004,9 @@ "dev": true }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.5.tgz", - "integrity": "sha512-xkb58MyOYIslxu3gKmVXmjTtUPvBU4odYzbiIQbWwLKIHCsx6UGZGX6F1IznMFVnDdirseUZopzN+ZRt8Xb33Q==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.9.tgz", + "integrity": "sha512-Pwyi89uO4YrGKxL/eNJ8lfEH55DnRloGPOseaA8NFNL6jAUnn+KccaISiFazCj5IolPPDjGSdzQzXVzODVRqUQ==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", @@ -1893,10 +2014,10 @@ "@babel/helper-function-name": "^7.22.5", "@babel/helper-member-expression-to-functions": "^7.22.5", "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.5", - "semver": "^6.3.0" + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -1905,24 +2026,36 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.5.tgz", - "integrity": "sha512-1VpEFOIbMRaXyDeUwUfmTIxExLwQ+zkW+Bh5zXpApA3oQedBx9v/updixWxnx/bZpKw7u8VxWjb/qWpIcmPq8A==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.9.tgz", + "integrity": "sha512-+svjVa/tFwsNSG4NEy1h85+HQ5imbT92Q5/bgtS7P0GTQlP8WuFdqsiABmQouhiFGyV66oGxZFpeYHza1rNsKw==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "regexpu-core": "^5.3.1", - "semver": "^6.3.0" + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -1932,40 +2065,30 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.0.tgz", - "integrity": "sha512-RnanLx5ETe6aybRi1cO/edaRH+bNYWaryCEmjDDYyNr4wnSzyOp8T0dWipmqVHKEY3AbVKUom50AKSlj1zmKbg==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.1.tgz", + "integrity": "sha512-kX4oXixDxG197yhX+J3Wp+NpL2wuCFjWQAr6yX2jtCnflK9ulMI51ULFGIrWiX1jGfvAxdHp+XQCcP2bZGPs9A==", "dev": true, "dependencies": { - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", "debug": "^4.1.1", "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" + "resolve": "^1.14.2" }, "peerDependencies": { "@babel/core": "^7.4.0-0" } }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/helper-environment-visitor": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", @@ -2025,18 +2148,30 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz", - "integrity": "sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", + "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-module-imports": "^7.22.5", "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-module-transforms/node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { "@babel/types": "^7.22.5" }, "engines": { @@ -2065,15 +2200,14 @@ } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.5.tgz", - "integrity": "sha512-cU0Sq1Rf4Z55fgz7haOakIyM7+x/uCFwXpLPaeRzfoUtAEAuUZjZvFPjL/rk5rW693dIgn2hng1W7xbT7lWT4g==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz", + "integrity": "sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-wrap-function": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/helper-wrap-function": "^7.22.9" }, "engines": { "node": ">=6.9.0" @@ -2083,20 +2217,20 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.5.tgz", - "integrity": "sha512-aLdNM5I3kdI/V9xGNyKSF3X/gTyMUBohTZ+/3QdQKAA9vxIiy12E+8E2HoOP1/DjeqU+g6as35QHJNMDDYpuCg==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz", + "integrity": "sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-member-expression-to-functions": "^7.22.5", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/helper-optimise-call-expression": "^7.22.5" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-simple-access": { @@ -2163,14 +2297,13 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.5.tgz", - "integrity": "sha512-bYqLIBSEshYcYQyfks8ewYA8S30yaGSeRslcvKMvoUk6HHPySbxHq9YRi6ghhzEU+yhQv9bP/jXnygkStOcqZw==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.9.tgz", + "integrity": "sha512-sZ+QzfauuUEfxSEjKFmi3qDSHgLsTPK/pEpoD/qonZKOtTPTLbf59oabPQ4rKekt9lFcj/hTZaOhWwFYrgjk+Q==", "dev": true, "dependencies": { "@babel/helper-function-name": "^7.22.5", "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.5", "@babel/types": "^7.22.5" }, "engines": { @@ -2178,13 +2311,13 @@ } }, "node_modules/@babel/helpers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.5.tgz", - "integrity": "sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", + "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", "dev": true, "dependencies": { "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.5", + "@babel/traverse": "^7.22.6", "@babel/types": "^7.22.5" }, "engines": { @@ -2206,9 +2339,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz", - "integrity": "sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==", + "version": "7.22.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", + "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -2284,15 +2417,15 @@ } }, "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.22.5.tgz", - "integrity": "sha512-h8hlezQ4dl6ixodgXkH8lUfcD7x+WAuIqPUjwGoItynrXOAv4a4Tci1zA/qjzQjjcl0v3QpLdc2LM6ZACQuY7A==", + "version": "7.22.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.22.7.tgz", + "integrity": "sha512-omXqPF7Onq4Bb7wHxXjM3jSMSJvUUbvDvmmds7KI5n9Cq6Ln5I05I1W2nRlRof1rGdiUxJrxwe285WF96XlBXQ==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-replace-supers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", "@babel/plugin-syntax-decorators": "^7.22.5" }, "engines": { @@ -2302,6 +2435,18 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-proposal-decorators/node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/plugin-proposal-private-property-in-object": { "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", @@ -2638,9 +2783,9 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.5.tgz", - "integrity": "sha512-gGOEvFzm3fWoyD5uZq7vVTD57pPJ3PczPUD/xCFGjzBpUosnklmXyKnGQbbbGs1NPNPskFex0j93yKbHt0cHyg==", + "version": "7.22.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.7.tgz", + "integrity": "sha512-7HmE7pk/Fmke45TODvxvkxRMV9RazV+ZZzhOL9AG8G29TLrr3jkjwF7uJfxZ30EoXpO+LJkq4oA8NjO2DTnEDg==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.5", @@ -2736,19 +2881,19 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.5.tgz", - "integrity": "sha512-2edQhLfibpWpsVBx2n/GKOz6JdGQvLruZQfGr9l1qes2KQaWswjBzhQF7UDUZMNaMMQeYnQzxwOMPsbYF7wqPQ==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.6.tgz", + "integrity": "sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-function-name": "^7.22.5", "@babel/helper-optimise-call-expression": "^7.22.5", "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-replace-supers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", "globals": "^11.1.0" }, "engines": { @@ -2758,6 +2903,18 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/plugin-transform-computed-properties": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", @@ -3144,9 +3301,9 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.5.tgz", - "integrity": "sha512-AconbMKOMkyG+xCng2JogMCDcqW8wedQAqpVIL4cOSescZ7+iW8utC6YDZLMCSUIReEA733gzRSaOSXMAt/4WQ==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.6.tgz", + "integrity": "sha512-Vd5HiWml0mDVtcLHIoEU5sw6HOUW/Zk0acLs/SAeuLzkGNOPc9DB4nkUajemhCmTIz3eiaKREZn2hQQqF79YTg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -3276,9 +3433,9 @@ } }, "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -3361,13 +3518,13 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.5.tgz", - "integrity": "sha512-SMubA9S7Cb5sGSFFUlqxyClTA9zWJ8qGQrppNUm05LtFuN1ELRFNndkix4zUJrC9F+YivWwa1dHMSyo0e0N9dA==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.9.tgz", + "integrity": "sha512-BnVR1CpKiuD0iobHPaM1iLvcwPYN2uVFAqoLVSpEDKWuOikoCv5HbKLxclhKYUXlWkX86DoZGtqI4XhbOsyrMg==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.9", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-typescript": "^7.22.5" }, @@ -3536,9 +3693,9 @@ } }, "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -3612,18 +3769,18 @@ } }, "node_modules/@babel/traverse": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.5.tgz", - "integrity": "sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==", + "version": "7.22.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", + "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.5", + "@babel/generator": "^7.22.7", "@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-function-name": "^7.22.5", "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.5", - "@babel/parser": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.22.7", "@babel/types": "^7.22.5", "debug": "^4.1.0", "globals": "^11.1.0" @@ -3632,6 +3789,33 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/traverse/node_modules/@babel/generator": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz", + "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/types": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", @@ -4183,44 +4367,380 @@ "node": ">=10.0.0" } }, - "node_modules/@esbuild/linux-x64": { + "node_modules/@esbuild/android-arm": { "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", - "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", + "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", "cpu": [ - "x64" + "arm" ], "dev": true, "optional": true, "os": [ - "linux" + "android" ], "engines": { "node": ">=12" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "node_modules/@esbuild/android-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", + "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=12" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "node_modules/@esbuild/android-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", + "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", + "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", + "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", + "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", + "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", + "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", + "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", + "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", + "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", + "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", + "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", + "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", + "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", + "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", + "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", + "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", + "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", + "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", + "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", + "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { @@ -4335,9 +4855,9 @@ } }, "node_modules/@golevelup/ts-jest": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/@golevelup/ts-jest/-/ts-jest-0.3.7.tgz", - "integrity": "sha512-eoRfl9trBEt7BrQ6t3GHY/ZOcDOMBIOgqghd9qkIWMpcqQgWbU5Yf5UeHA6wwnLYpOMIJoKqazJ0cUDM79yr+g==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@golevelup/ts-jest/-/ts-jest-0.3.8.tgz", + "integrity": "sha512-2H4XzpCHwoUs2P13tzwVzj+AYspbFGKwMr94WK5eHiDBKgx0j4QGgLQh1wgM18DjhN7jdntrzVMoQRie6kZhnw==", "dev": true }, "node_modules/@graphql-tools/merge": { @@ -4387,9 +4907,9 @@ } }, "node_modules/@grpc/grpc-js": { - "version": "1.8.17", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.17.tgz", - "integrity": "sha512-DGuSbtMFbaRsyffMf+VEkVu8HkSXEUfO3UyGJNtqxW9ABdtTIA+2UXAJpwbJS+xfQxuwqLUeELmL6FuZkOqPxw==", + "version": "1.8.18", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.18.tgz", + "integrity": "sha512-2uWPtxhsXmVgd8WzDhfamSjHpZDXfMjMDciY6VRTq4Sn7rFzazyf0LLDa0oav+61UHIoEZb4KKaAV6S7NuJFbQ==", "dependencies": { "@grpc/proto-loader": "^0.7.0", "@types/node": ">=12.12.47" @@ -4399,14 +4919,14 @@ } }, "node_modules/@grpc/proto-loader": { - "version": "0.7.7", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.7.tgz", - "integrity": "sha512-1TIeXOi8TuSCQprPItwoMymZXxWT0CPxUhkrkeCUH+D8U7QDwQ6b7SUz2MaLuWM2llT+J/TVFLmQI5KtML3BhQ==", + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.8.tgz", + "integrity": "sha512-GU12e2c8dmdXb7XUlOgYWZ2o2i+z9/VeACkxTA/zzAe2IjclC5PnVL0lpgjhrqfpDYHzM8B1TF6pqWegMYAzlA==", "dependencies": { "@types/long": "^4.0.1", "lodash.camelcase": "^4.3.0", "long": "^4.0.0", - "protobufjs": "^7.0.0", + "protobufjs": "^7.2.4", "yargs": "^17.7.2" }, "bin": { @@ -4631,16 +5151,16 @@ } }, "node_modules/@jest/console": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", - "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.1.tgz", + "integrity": "sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1", "slash": "^3.0.0" }, "engines": { @@ -4718,16 +5238,16 @@ } }, "node_modules/@jest/core": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.5.0.tgz", - "integrity": "sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.1.tgz", + "integrity": "sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==", "dev": true, "dependencies": { - "@jest/console": "^29.5.0", - "@jest/reporters": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.6.1", + "@jest/reporters": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", @@ -4735,20 +5255,20 @@ "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-changed-files": "^29.5.0", - "jest-config": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", + "jest-config": "^29.6.1", + "jest-haste-map": "^29.6.1", + "jest-message-util": "^29.6.1", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-resolve-dependencies": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "jest-watcher": "^29.5.0", + "jest-resolve": "^29.6.1", + "jest-resolve-dependencies": "^29.6.1", + "jest-runner": "^29.6.1", + "jest-runtime": "^29.6.1", + "jest-snapshot": "^29.6.1", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", + "jest-watcher": "^29.6.1", "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -4823,12 +5343,12 @@ } }, "node_modules/@jest/core/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", + "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -4867,37 +5387,37 @@ } }, "node_modules/@jest/environment": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.5.0.tgz", - "integrity": "sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.1.tgz", + "integrity": "sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/fake-timers": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", - "jest-mock": "^29.5.0" + "jest-mock": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.1.tgz", + "integrity": "sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==", "dev": true, "dependencies": { - "expect": "^29.5.0", - "jest-snapshot": "^29.5.0" + "expect": "^29.6.1", + "jest-snapshot": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", - "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.1.tgz", + "integrity": "sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==", "dev": true, "dependencies": { "jest-get-type": "^29.4.3" @@ -4907,49 +5427,49 @@ } }, "node_modules/@jest/fake-timers": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.5.0.tgz", - "integrity": "sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.1.tgz", + "integrity": "sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" + "jest-message-util": "^29.6.1", + "jest-mock": "^29.6.1", + "jest-util": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.5.0.tgz", - "integrity": "sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.1.tgz", + "integrity": "sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==", "dev": true, "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/types": "^29.5.0", - "jest-mock": "^29.5.0" + "@jest/environment": "^29.6.1", + "@jest/expect": "^29.6.1", + "@jest/types": "^29.6.1", + "jest-mock": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.5.0.tgz", - "integrity": "sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.1.tgz", + "integrity": "sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/console": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", + "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", @@ -4961,9 +5481,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1", + "jest-worker": "^29.6.1", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -5052,24 +5572,24 @@ } }, "node_modules/@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "version": "29.6.0", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz", + "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.25.16" + "@sinclair/typebox": "^0.27.8" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/source-map": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.3.tgz", - "integrity": "sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w==", + "version": "29.6.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz", + "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.15", + "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" }, @@ -5078,13 +5598,13 @@ } }, "node_modules/@jest/test-result": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.5.0.tgz", - "integrity": "sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.1.tgz", + "integrity": "sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==", "dev": true, "dependencies": { - "@jest/console": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.6.1", + "@jest/types": "^29.6.1", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, @@ -5093,14 +5613,14 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz", - "integrity": "sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz", + "integrity": "sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==", "dev": true, "dependencies": { - "@jest/test-result": "^29.5.0", + "@jest/test-result": "^29.6.1", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.6.1", "slash": "^3.0.0" }, "engines": { @@ -5108,22 +5628,22 @@ } }, "node_modules/@jest/transform": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", - "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.1.tgz", + "integrity": "sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/types": "^29.6.1", + "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.6.1", "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", + "jest-util": "^29.6.1", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -5210,12 +5730,12 @@ } }, "node_modules/@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz", + "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -5334,9 +5854,9 @@ } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz", - "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", @@ -5390,14 +5910,14 @@ } }, "node_modules/@nestjs/apollo": { - "version": "12.0.3", - "resolved": "https://registry.npmjs.org/@nestjs/apollo/-/apollo-12.0.3.tgz", - "integrity": "sha512-y0KNQlq+czlp4RQ06XVRb1/ST03+i/hBdGH9CJOGQf41KNV89Yn8OfTq7p+U6mE5TizTRbE53CFuD7FekJU2GQ==", + "version": "12.0.7", + "resolved": "https://registry.npmjs.org/@nestjs/apollo/-/apollo-12.0.7.tgz", + "integrity": "sha512-snY8uM/ypE5TZOVChIIuNlTFWGCrwJ8U/xq3EFYE6A+dIqY7/B9sou79snevCm3zTde69KdsOYg5FBmznasxNg==", "dependencies": { "@apollo/server-plugin-landing-page-graphql-playground": "4.0.0", "iterall": "1.3.0", "lodash.omit": "4.5.0", - "tslib": "2.5.3" + "tslib": "2.6.0" }, "peerDependencies": { "@apollo/gateway": "^2.0.0", @@ -5421,11 +5941,6 @@ } } }, - "node_modules/@nestjs/apollo/node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==" - }, "node_modules/@nestjs/common": { "version": "10.0.3", "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.0.3.tgz", @@ -5531,9 +6046,9 @@ } }, "node_modules/@nestjs/graphql": { - "version": "12.0.3", - "resolved": "https://registry.npmjs.org/@nestjs/graphql/-/graphql-12.0.3.tgz", - "integrity": "sha512-EEB8SrH1mnIIO6N4JIA6a4GsxJsPk30jhB4Q/AnBtvkbf/dgcAAPzdF32FDrIHKNAfthxxwfV+9swkBshgaeOA==", + "version": "12.0.8", + "resolved": "https://registry.npmjs.org/@nestjs/graphql/-/graphql-12.0.8.tgz", + "integrity": "sha512-odYDHUdLOMCxjC5VSEmF/23r8cY40N1KCwBkWaCmI1IF76Ffe3srWRDv8HS9tcai9eSmOeSWuyLBEg2OSru0cQ==", "dependencies": { "@graphql-tools/merge": "9.0.0", "@graphql-tools/schema": "10.0.0", @@ -5542,11 +6057,11 @@ "chokidar": "3.5.3", "fast-glob": "3.2.12", "graphql-tag": "2.12.6", - "graphql-ws": "5.13.1", + "graphql-ws": "5.14.0", "lodash": "4.17.21", "normalize-path": "3.0.0", "subscriptions-transport-ws": "0.11.0", - "tslib": "2.5.3", + "tslib": "2.6.0", "uuid": "9.0.0", "ws": "8.13.0" }, @@ -5622,11 +6137,6 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/@nestjs/graphql/node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==" - }, "node_modules/@nestjs/mapped-types": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.2.tgz", @@ -5809,6 +6319,15 @@ "webpack": "^5.54.0" } }, + "node_modules/@nicolo-ribaudo/semver-v6": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz", + "integrity": "sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -7745,6 +8264,36 @@ "@opentelemetry/api": "^1.3.0" } }, + "node_modules/@opentelemetry/instrumentation-graphql/node_modules/@opentelemetry/instrumentation": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.41.0.tgz", + "integrity": "sha512-Ut9SnZfi7MexOk+GHCMjEtYHogIb6v1dfbnq+oTbQj0lOQUSNLtlO6bXwUdtmPhbvrx6bC0AGr1L6g3rNimv9w==", + "dependencies": { + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "1.4.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.1", + "shimmer": "^1.2.1", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-graphql/node_modules/import-in-the-middle": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.4.1.tgz", + "integrity": "sha512-hGG0PcCsykVo8MBVH8l0uEWLWW6DXMgJA9jvC0yps6M3uIJ8L/tagTCbyF8Ud5TtqJ8/jmZL1YkyySyeVkVQrA==", + "dependencies": { + "acorn": "^8.8.2", + "acorn-import-assertions": "^1.9.0", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, "node_modules/@opentelemetry/instrumentation-mongoose": { "version": "0.33.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.33.0.tgz", @@ -7762,6 +8311,46 @@ "@opentelemetry/api": "^1.3.0" } }, + "node_modules/@opentelemetry/instrumentation-pino": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pino/-/instrumentation-pino-0.33.4.tgz", + "integrity": "sha512-9jRkfICHBkwcP/O363Ft3cA2t7cuYgOyiW1L+hJ4rmnCmfAVOM+uNQ1dTezftkodgTvurlQbDjOBSKhvh2r2Pw==", + "dependencies": { + "@opentelemetry/instrumentation": "^0.40.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pino/node_modules/@opentelemetry/instrumentation": { + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.40.0.tgz", + "integrity": "sha512-23TzBKPflUS1uEq5SXymnQKQDSda35KvHjnvxdcDQGE+wg6hwDHgScUCWiBmZW4sxAaPcANfs+Wc9B7yDuyT6Q==", + "dependencies": { + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "1.3.5", + "require-in-the-middle": "^7.1.0", + "semver": "^7.3.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pino/node_modules/import-in-the-middle": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.3.5.tgz", + "integrity": "sha512-yzHlBqi1EBFrkieAnSt8eTgO5oLSl+YJ7qaOpUH/PMqQOMZoQ/RmDlwnTLQrwYto+gHYjRG+i/IbsB1eDx32NQ==", + "dependencies": { + "module-details-from-path": "^1.0.3" + } + }, "node_modules/@opentelemetry/otlp-exporter-base": { "version": "0.41.0", "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.41.0.tgz", @@ -7962,84 +8551,28 @@ "dependencies": { "@opentelemetry/context-async-hooks": "1.15.0", "@opentelemetry/core": "1.15.0", - "@opentelemetry/propagator-b3": "1.15.0", - "@opentelemetry/propagator-jaeger": "1.15.0", - "@opentelemetry/sdk-trace-base": "1.15.0", - "semver": "^7.5.1", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.5.0" - } - }, - "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.15.0.tgz", - "integrity": "sha512-f3wwFrFyCpGrFBrFs7lCUJSCSCGyeKG52c+EKeobs3Dd29M75yO6GYkt6PkYPfDawxSlV5p+4yJPPk8tPObzTQ==", - "dependencies": { - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/tracing": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/tracing/-/tracing-0.24.0.tgz", - "integrity": "sha512-sTLEs1SIon3xV8vLe53PzfbU0FahoxL9NPY/CYvA1mwGbMu4zHkHAjqy1Tc8JmqRrfa+XrHkmzeSM4hrvloBaA==", - "deprecated": "Package renamed to @opentelemetry/sdk-trace-base", - "dependencies": { - "@opentelemetry/core": "0.24.0", - "@opentelemetry/resources": "0.24.0", - "@opentelemetry/semantic-conventions": "0.24.0", - "lodash.merge": "^4.6.2" - }, - "engines": { - "node": ">=8.0.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.1" - } - }, - "node_modules/@opentelemetry/tracing/node_modules/@opentelemetry/core": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-0.24.0.tgz", - "integrity": "sha512-KpsfxBbFTZT9zaB4Es/fFLbvSzVl9Io/8UUu/TYl4/HgqkmyVInNlWTgRiKyz9nsHzFpGP1kdZJj+YIut0IFsw==", - "dependencies": { - "@opentelemetry/semantic-conventions": "0.24.0", - "semver": "^7.1.3" + "@opentelemetry/propagator-b3": "1.15.0", + "@opentelemetry/propagator-jaeger": "1.15.0", + "@opentelemetry/sdk-trace-base": "1.15.0", + "semver": "^7.5.1", + "tslib": "^2.3.1" }, "engines": { - "node": ">=8.5.0" + "node": ">=14" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.1" + "@opentelemetry/api": ">=1.0.0 <1.5.0" } }, - "node_modules/@opentelemetry/tracing/node_modules/@opentelemetry/resources": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-0.24.0.tgz", - "integrity": "sha512-uEr2m13IRkjQAjX6fsYqJ21aONCspRvuQunaCl8LbH1NS1Gj82TuRUHF6TM82ulBPK8pU+nrrqXKuky2cMcIzw==", + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.15.0.tgz", + "integrity": "sha512-f3wwFrFyCpGrFBrFs7lCUJSCSCGyeKG52c+EKeobs3Dd29M75yO6GYkt6PkYPfDawxSlV5p+4yJPPk8tPObzTQ==", "dependencies": { - "@opentelemetry/core": "0.24.0", - "@opentelemetry/semantic-conventions": "0.24.0" - }, - "engines": { - "node": ">=8.0.0" + "tslib": "^2.3.1" }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.1" - } - }, - "node_modules/@opentelemetry/tracing/node_modules/@opentelemetry/semantic-conventions": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-0.24.0.tgz", - "integrity": "sha512-a/szuMQV0Quy0/M7kKdglcbRSoorleyyOwbTNNJ32O+RBN766wbQlMTvdimImTmwYWGr+NJOni1EcC242WlRcA==", "engines": { - "node": ">=8.0.0" + "node": ">=14" } }, "node_modules/@parcel/watcher": { @@ -8171,46 +8704,13 @@ } }, "node_modules/@sentry-internal/tracing": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.57.0.tgz", - "integrity": "sha512-tpViyDd8AhQGYYhI94xi2aaDopXOPfL2Apwrtb3qirWkomIQ2K86W1mPmkce+B0cFOnW2Dxv/ZTFKz6ghjK75A==", - "dependencies": { - "@sentry/core": "7.57.0", - "@sentry/types": "7.57.0", - "@sentry/utils": "7.57.0", - "tslib": "^2.4.1 || ^1.9.3" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry-internal/tracing/node_modules/@sentry/core": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.57.0.tgz", - "integrity": "sha512-l014NudPH0vQlzybtXajPxYFfs9w762NoarjObC3gu76D1jzBBFzhdRelkGpDbSLNTIsKhEDDRpgAjBWJ9icfw==", - "dependencies": { - "@sentry/types": "7.57.0", - "@sentry/utils": "7.57.0", - "tslib": "^2.4.1 || ^1.9.3" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry-internal/tracing/node_modules/@sentry/types": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.57.0.tgz", - "integrity": "sha512-D7ifoUfxuVCUyktIr5Gc+jXUbtcUMmfHdTtTbf1XCZHua5mJceK9wtl3YCg3eq/HK2Ppd52BKnTzEcS5ZKQM+w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry-internal/tracing/node_modules/@sentry/utils": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.57.0.tgz", - "integrity": "sha512-YXrkMCiNklqkXctn4mKYkrzNCf/dfVcRUQrkXjeBC+PHXbcpPyaJgInNvztR7Skl8lE3JPGPN4v5XhLxK1bUUg==", + "version": "7.58.1", + "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.58.1.tgz", + "integrity": "sha512-kOWKqyjYdDgvO6CacXneE9UrFQHT3BXF1UpCAlnHchW/TqRFmg89sJAEUjEPGzN7y6IaX1G4j2dBPDE0OFQi3w==", "dependencies": { - "@sentry/types": "7.57.0", + "@sentry/core": "7.58.1", + "@sentry/types": "7.58.1", + "@sentry/utils": "7.58.1", "tslib": "^2.4.1 || ^1.9.3" }, "engines": { @@ -8218,13 +8718,13 @@ } }, "node_modules/@sentry/angular-ivy": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/angular-ivy/-/angular-ivy-7.57.0.tgz", - "integrity": "sha512-ENHV6JmQnUNXVeNp08Aq+oTdYl/oXVmW2cHcx/oqoEiww0+iYNGStmQsuKE7SXGBk1Uq8Jk+DMbPQBzqtdBmQA==", + "version": "7.58.1", + "resolved": "https://registry.npmjs.org/@sentry/angular-ivy/-/angular-ivy-7.58.1.tgz", + "integrity": "sha512-bxq8DbbrUjh2pyBiY41rcqGAhFcm2cHh0eSjozdgujfPZD5AMjf1Xe8o0ScczrhPcfjQ0h+oJs5dsgTsWUA+SQ==", "dependencies": { - "@sentry/browser": "7.57.0", - "@sentry/types": "7.57.0", - "@sentry/utils": "7.57.0", + "@sentry/browser": "7.58.1", + "@sentry/types": "7.58.1", + "@sentry/utils": "7.58.1", "tslib": "^2.4.1" }, "engines": { @@ -8237,121 +8737,72 @@ "rxjs": "^6.5.5 || ^7.x" } }, - "node_modules/@sentry/angular-ivy/node_modules/@sentry/types": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.57.0.tgz", - "integrity": "sha512-D7ifoUfxuVCUyktIr5Gc+jXUbtcUMmfHdTtTbf1XCZHua5mJceK9wtl3YCg3eq/HK2Ppd52BKnTzEcS5ZKQM+w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/angular-ivy/node_modules/@sentry/utils": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.57.0.tgz", - "integrity": "sha512-YXrkMCiNklqkXctn4mKYkrzNCf/dfVcRUQrkXjeBC+PHXbcpPyaJgInNvztR7Skl8lE3JPGPN4v5XhLxK1bUUg==", - "dependencies": { - "@sentry/types": "7.57.0", - "tslib": "^2.4.1 || ^1.9.3" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@sentry/browser": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.57.0.tgz", - "integrity": "sha512-E0HaYYlaqHFiIRZXxcvOO8Odvlt+TR1vFFXzqUWXPOvDRxURglTOCQ3EN/u6bxtAGJ6y/Zc2obgihTtypuel/w==", - "dependencies": { - "@sentry-internal/tracing": "7.57.0", - "@sentry/core": "7.57.0", - "@sentry/replay": "7.57.0", - "@sentry/types": "7.57.0", - "@sentry/utils": "7.57.0", + "version": "7.58.1", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.58.1.tgz", + "integrity": "sha512-7+6Z/T7m0A/2/ImMCakpMOaWTPxmENzTdaojhkyVQKuYUZr7mCe4nco0jsongwY634zSUziuVsibi0jxMMTdBA==", + "dependencies": { + "@sentry-internal/tracing": "7.58.1", + "@sentry/core": "7.58.1", + "@sentry/replay": "7.58.1", + "@sentry/types": "7.58.1", + "@sentry/utils": "7.58.1", "tslib": "^2.4.1 || ^1.9.3" }, "engines": { "node": ">=8" } }, - "node_modules/@sentry/browser/node_modules/@sentry/core": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.57.0.tgz", - "integrity": "sha512-l014NudPH0vQlzybtXajPxYFfs9w762NoarjObC3gu76D1jzBBFzhdRelkGpDbSLNTIsKhEDDRpgAjBWJ9icfw==", + "node_modules/@sentry/core": { + "version": "7.58.1", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.58.1.tgz", + "integrity": "sha512-hpeB5fZ5T6Jg1CBqz486jHgWuJ5R/HD0wyYX+S3LDDsHCJo6V3TxNuoxYDlTTerRRfZdTwr9GYJXskehpU26IA==", "dependencies": { - "@sentry/types": "7.57.0", - "@sentry/utils": "7.57.0", + "@sentry/types": "7.58.1", + "@sentry/utils": "7.58.1", "tslib": "^2.4.1 || ^1.9.3" }, "engines": { "node": ">=8" } }, - "node_modules/@sentry/browser/node_modules/@sentry/types": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.57.0.tgz", - "integrity": "sha512-D7ifoUfxuVCUyktIr5Gc+jXUbtcUMmfHdTtTbf1XCZHua5mJceK9wtl3YCg3eq/HK2Ppd52BKnTzEcS5ZKQM+w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/browser/node_modules/@sentry/utils": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.57.0.tgz", - "integrity": "sha512-YXrkMCiNklqkXctn4mKYkrzNCf/dfVcRUQrkXjeBC+PHXbcpPyaJgInNvztR7Skl8lE3JPGPN4v5XhLxK1bUUg==", + "node_modules/@sentry/hub": { + "version": "7.58.1", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-7.58.1.tgz", + "integrity": "sha512-t/6jnos7vhXoxKTa+PoUWZl8daGMIoq/kAqY2OakpdNn9bUXsHRBB4mjIsOANacoZU9jE0TbpgtzNH4g1ANs4A==", "dependencies": { - "@sentry/types": "7.57.0", + "@sentry/core": "7.58.1", + "@sentry/types": "7.58.1", + "@sentry/utils": "7.58.1", "tslib": "^2.4.1 || ^1.9.3" }, "engines": { "node": ">=8" } }, - "node_modules/@sentry/core": { - "version": "7.56.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.56.0.tgz", - "integrity": "sha512-Nuyyfh09Yz27kPo74fXHlrdmZeK6zrlJVtxQ6LkwuoaTBcNcesNXVaOtr6gjvUGUmsfriVPP3Jero5LXufV7GQ==", - "dependencies": { - "@sentry/types": "7.56.0", - "@sentry/utils": "7.56.0", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/core/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@sentry/hub": { - "version": "7.56.0", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-7.56.0.tgz", - "integrity": "sha512-d5AnPHk7PNhPFHyIuyMEnG+dtC8SHbCBffm05jMqL0+ocU1rSAJb4K6r5D1wrfQtHxPHNV+R3uwkvOWDekF+VA==", + "node_modules/@sentry/integrations": { + "version": "7.58.1", + "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.58.1.tgz", + "integrity": "sha512-fKZV/QDPM7rIZhaJpFwgxD4rzWLtRuag7cOWfvHCsezJnhXEF8u45sBak/VWmSr8SbcvJAIJSZbWYi0N91hNHQ==", "dependencies": { - "@sentry/core": "7.56.0", - "@sentry/types": "7.56.0", - "@sentry/utils": "7.56.0", - "tslib": "^1.9.3" + "@sentry/types": "7.58.1", + "@sentry/utils": "7.58.1", + "localforage": "^1.8.1", + "tslib": "^2.4.1 || ^1.9.3" }, "engines": { "node": ">=8" } }, - "node_modules/@sentry/hub/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, "node_modules/@sentry/node": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.57.0.tgz", - "integrity": "sha512-63mjyUVM6sfJFVQ5TGVRVGUsoEfESl5ABzIW1W0s9gUiQPaG8SOdaQJglb2VNrkMYxnRHgD8Q9LUh/qcmUyPGw==", - "dependencies": { - "@sentry-internal/tracing": "7.57.0", - "@sentry/core": "7.57.0", - "@sentry/types": "7.57.0", - "@sentry/utils": "7.57.0", + "version": "7.58.1", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.58.1.tgz", + "integrity": "sha512-XsSu0xg5SYcltMbatnRBcIZw9pXwGJoGbYDLuPhhuqBz2mnQ0mQ9Try9dn/agDU7KZzT0IyA1qkPXk0NkMe3rw==", + "dependencies": { + "@sentry-internal/tracing": "7.58.1", + "@sentry/core": "7.58.1", + "@sentry/types": "7.58.1", + "@sentry/utils": "7.58.1", "cookie": "^0.4.1", "https-proxy-agent": "^5.0.0", "lru_map": "^0.3.3", @@ -8361,47 +8812,14 @@ "node": ">=8" } }, - "node_modules/@sentry/node/node_modules/@sentry/core": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.57.0.tgz", - "integrity": "sha512-l014NudPH0vQlzybtXajPxYFfs9w762NoarjObC3gu76D1jzBBFzhdRelkGpDbSLNTIsKhEDDRpgAjBWJ9icfw==", - "dependencies": { - "@sentry/types": "7.57.0", - "@sentry/utils": "7.57.0", - "tslib": "^2.4.1 || ^1.9.3" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/node/node_modules/@sentry/types": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.57.0.tgz", - "integrity": "sha512-D7ifoUfxuVCUyktIr5Gc+jXUbtcUMmfHdTtTbf1XCZHua5mJceK9wtl3YCg3eq/HK2Ppd52BKnTzEcS5ZKQM+w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/node/node_modules/@sentry/utils": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.57.0.tgz", - "integrity": "sha512-YXrkMCiNklqkXctn4mKYkrzNCf/dfVcRUQrkXjeBC+PHXbcpPyaJgInNvztR7Skl8lE3JPGPN4v5XhLxK1bUUg==", - "dependencies": { - "@sentry/types": "7.57.0", - "tslib": "^2.4.1 || ^1.9.3" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@sentry/opentelemetry-node": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/opentelemetry-node/-/opentelemetry-node-7.57.0.tgz", - "integrity": "sha512-MAzW1R5tpxji9U2eRcVUW3ebgH/mWiOUYn5vgcHFrDxtg1Tjn7W4cmyi193lXwYalQHdR8KTThsHJlmmPfInYA==", + "version": "7.58.1", + "resolved": "https://registry.npmjs.org/@sentry/opentelemetry-node/-/opentelemetry-node-7.58.1.tgz", + "integrity": "sha512-Mwss+R1E6lOnReRzjZbmGV1Fl8A9tMjhg+ZVKbdgyHa4lckMRhT+ZXOO1alCxP3Fk6DoJOABsFuMs7JNER40Jg==", "dependencies": { - "@sentry/core": "7.57.0", - "@sentry/types": "7.57.0", - "@sentry/utils": "7.57.0" + "@sentry/core": "7.58.1", + "@sentry/types": "7.58.1", + "@sentry/utils": "7.58.1" }, "engines": { "node": ">=8" @@ -8413,39 +8831,6 @@ "@opentelemetry/semantic-conventions": "1.x" } }, - "node_modules/@sentry/opentelemetry-node/node_modules/@sentry/core": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.57.0.tgz", - "integrity": "sha512-l014NudPH0vQlzybtXajPxYFfs9w762NoarjObC3gu76D1jzBBFzhdRelkGpDbSLNTIsKhEDDRpgAjBWJ9icfw==", - "dependencies": { - "@sentry/types": "7.57.0", - "@sentry/utils": "7.57.0", - "tslib": "^2.4.1 || ^1.9.3" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/opentelemetry-node/node_modules/@sentry/types": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.57.0.tgz", - "integrity": "sha512-D7ifoUfxuVCUyktIr5Gc+jXUbtcUMmfHdTtTbf1XCZHua5mJceK9wtl3YCg3eq/HK2Ppd52BKnTzEcS5ZKQM+w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/opentelemetry-node/node_modules/@sentry/utils": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.57.0.tgz", - "integrity": "sha512-YXrkMCiNklqkXctn4mKYkrzNCf/dfVcRUQrkXjeBC+PHXbcpPyaJgInNvztR7Skl8lE3JPGPN4v5XhLxK1bUUg==", - "dependencies": { - "@sentry/types": "7.57.0", - "tslib": "^2.4.1 || ^1.9.3" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@sentry/profiling-node": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@sentry/profiling-node/-/profiling-node-1.1.2.tgz", @@ -8469,76 +8854,38 @@ } }, "node_modules/@sentry/replay": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.57.0.tgz", - "integrity": "sha512-pN4ryNS3J5EYbkXvR+O/+hseAJha7XDl8mPFtK0OGTHG10JzCi4tQJazblHQdpb5QBaMMPCeZ+isyfoQLDNXnw==", + "version": "7.58.1", + "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.58.1.tgz", + "integrity": "sha512-KKlpIxGrH1deTr/R3BErX8y16MnOzEylBVVn2I31BglLoZETFS9JAle6JNOgGxS5apFjwdQmD+69vX/mlVhMow==", "dependencies": { - "@sentry/core": "7.57.0", - "@sentry/types": "7.57.0", - "@sentry/utils": "7.57.0" + "@sentry/core": "7.58.1", + "@sentry/types": "7.58.1", + "@sentry/utils": "7.58.1" }, "engines": { "node": ">=12" } }, - "node_modules/@sentry/replay/node_modules/@sentry/core": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.57.0.tgz", - "integrity": "sha512-l014NudPH0vQlzybtXajPxYFfs9w762NoarjObC3gu76D1jzBBFzhdRelkGpDbSLNTIsKhEDDRpgAjBWJ9icfw==", - "dependencies": { - "@sentry/types": "7.57.0", - "@sentry/utils": "7.57.0", - "tslib": "^2.4.1 || ^1.9.3" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/replay/node_modules/@sentry/types": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.57.0.tgz", - "integrity": "sha512-D7ifoUfxuVCUyktIr5Gc+jXUbtcUMmfHdTtTbf1XCZHua5mJceK9wtl3YCg3eq/HK2Ppd52BKnTzEcS5ZKQM+w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/replay/node_modules/@sentry/utils": { - "version": "7.57.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.57.0.tgz", - "integrity": "sha512-YXrkMCiNklqkXctn4mKYkrzNCf/dfVcRUQrkXjeBC+PHXbcpPyaJgInNvztR7Skl8lE3JPGPN4v5XhLxK1bUUg==", - "dependencies": { - "@sentry/types": "7.57.0", - "tslib": "^2.4.1 || ^1.9.3" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@sentry/types": { - "version": "7.56.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.56.0.tgz", - "integrity": "sha512-5WjhVOQm75ItOytOx2jTx+5yw8/qJ316+g1Di8dS9+kgIi1zniqdMcX00C2yYe3FMUgFB49PegCUYulm9Evapw==", + "version": "7.58.1", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.58.1.tgz", + "integrity": "sha512-OnKG+yrilPBeVNQK3biF0u/4IDjwH+boJU1XzJOnYdMRO8uzTWxvaRqpt0C8sVE9VAetRi2eutkzOgCXZISRrw==", "engines": { "node": ">=8" } }, "node_modules/@sentry/utils": { - "version": "7.56.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.56.0.tgz", - "integrity": "sha512-wgeX7bufxc//TjjSIE+gCMm8hVId7Jzvc+f441bYrWnNZBuzPIDW2BummCcPrKzSYe5GeYZDTZGV8YZGMLGBjw==", + "version": "7.58.1", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.58.1.tgz", + "integrity": "sha512-iC9xZJBHp4+MDrZjKwcmMUhI5sTmpUcttwmsJL9HA6ACW+L1XX2eGSDky5pSlhhVFR7q7jJnQ7YUlMQ/jcd8eQ==", "dependencies": { - "@sentry/types": "7.56.0", - "tslib": "^1.9.3" + "@sentry/types": "7.58.1", + "tslib": "^2.4.1 || ^1.9.3" }, "engines": { "node": ">=8" } }, - "node_modules/@sentry/utils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, "node_modules/@sideway/address": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", @@ -8570,23 +8917,22 @@ } }, "node_modules/@sigstore/tuf": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.0.tgz", - "integrity": "sha512-bLzi9GeZgMCvjJeLUIfs8LJYCxrPRA8IXQkzUtaFKKVPTz0mucRyqFcV2U20yg9K+kYAD0YSitzGfRZCFLjdHQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.2.tgz", + "integrity": "sha512-vjwcYePJzM01Ha6oWWZ9gNcdIgnzyFxfqfWzph483DPJTH8Tb7f7bQRRll3CYVkyH56j0AgcPAcl6Vg95DPF+Q==", "dev": true, "dependencies": { "@sigstore/protobuf-specs": "^0.1.0", - "make-fetch-happen": "^11.0.1", - "tuf-js": "^1.1.3" + "tuf-js": "^1.1.7" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true }, "node_modules/@sinonjs/commons": { @@ -9203,6 +9549,15 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/@testing-library/dom/node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, "node_modules/@testing-library/dom/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -9258,6 +9613,19 @@ "node": ">=8" } }, + "node_modules/@timonmasberg/automapper-nestjs": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/@timonmasberg/automapper-nestjs/-/automapper-nestjs-0.0.0.tgz", + "integrity": "sha512-4DcUq8L0ffVTje5YsiBGTxMK9y/4eKEforEjJtS0FHcgxmm490SjPKRXYKhEMw0jTQxWHhWdXjp5YcqJ1OpSKA==", + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@automapper/core": "latest", + "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/core": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0" + } + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -9417,9 +9785,9 @@ } }, "node_modules/@tufjs/models/node_modules/minimatch": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.2.tgz", - "integrity": "sha512-PZOT9g5v2ojiTL7r1xF6plNHLtOeTpSlDI007As2NlA2aYBMfVom17yqa6QzhmDP8QOhn7LjHTg7DFCVSSa6yg==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -9515,9 +9883,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.40.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.40.2.tgz", - "integrity": "sha512-PRVjQ4Eh9z9pmmtaq8nTjZjQwKFk7YIHIud3lRoKRBgUQjgjRmoGxxGEPXQkF+lH7QkHJRNr5F4aBgYCW0lqpQ==", + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.0.tgz", + "integrity": "sha512-gsF+c/0XOguWgaOgvFs+xnnRqt9GwgTvIks36WpE6ueeI4KCEHHd8K/CKHqhOqrJKsYH8m27kRzQEvWXAwXUTw==", "dev": true, "dependencies": { "@types/estree": "*", @@ -9632,12 +10000,12 @@ } }, "node_modules/@types/jest/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", + "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -9804,6 +10172,11 @@ "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", "dev": true }, + "node_modules/@types/validator": { + "version": "13.7.17", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.17.tgz", + "integrity": "sha512-aqayTNmeWrZcvnG2MG9eGYI6b7S5fl+yKgPs6bAjOTwPS316R5SxBGKvtSExfyoJU7pIeHJfsHI0Ji41RVMkvQ==" + }, "node_modules/@types/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", @@ -9844,120 +10217,20 @@ }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.61.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.61.0.tgz", - "integrity": "sha512-A5l/eUAug103qtkwccSCxn8ZRwT+7RXWkFECdA4Cvl1dOlDUgTpAOfSEElZn2uSUxhdDpnCdetrf0jvU4qrL+g==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.61.0", - "@typescript-eslint/type-utils": "5.61.0", - "@typescript-eslint/utils": "5.61.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { - "version": "5.61.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.61.0.tgz", - "integrity": "sha512-kk8u//r+oVK2Aj3ph/26XdH0pbAkC2RiSjUYhKD+PExemG4XSjpGFeyZ/QM8lBOa7O8aGOU+/yEbMJgQv/DnCg==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "5.61.0", - "@typescript-eslint/utils": "5.61.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "5.61.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.61.0.tgz", - "integrity": "sha512-mV6O+6VgQmVE6+xzlA91xifndPW9ElFW8vbSF0xCT/czPXVhwDewKila1jOyRwa9AE19zKnrr7Cg5S3pJVrTWQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.61.0", - "@typescript-eslint/types": "5.61.0", - "@typescript-eslint/typescript-estree": "5.61.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.60.0.tgz", - "integrity": "sha512-ovid3u7CNBrr0Ct35LUPkNYH4e+z4Kc6dPfSG99oMmH9SfoEoefq09uSnJI4mUb/UM7a/peVM03G+MzLxrD16g==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.61.0.tgz", + "integrity": "sha512-A5l/eUAug103qtkwccSCxn8ZRwT+7RXWkFECdA4Cvl1dOlDUgTpAOfSEElZn2uSUxhdDpnCdetrf0jvU4qrL+g==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "5.60.0" + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.61.0", + "@typescript-eslint/type-utils": "5.61.0", + "@typescript-eslint/utils": "5.61.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -9967,51 +10240,24 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.60.0.tgz", - "integrity": "sha512-hakuzcxPwXi2ihf9WQu1BbRj1e/Pd8ZZwVTG9kfbxAMZstKz8/9OoexIwnmLzShtsdap5U/CoQGRCWlSuPbYxQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.60.0", - "@typescript-eslint/visitor-keys": "5.60.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/types": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.0.tgz", - "integrity": "sha512-ascOuoCpNZBccFVNJRSC6rPq4EmJ2NkuoKnd6LDNyAQmdDnziAtxbCGWCbefG1CNzmDvd05zO36AmB7H8RzKPA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.0.tgz", - "integrity": "sha512-R43thAuwarC99SnvrBmh26tc7F6sPa2B3evkXp/8q954kYL6Ro56AwASYWtEEi+4j09GbiNAHqYwNNZuNlARGQ==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { + "version": "5.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.61.0.tgz", + "integrity": "sha512-kk8u//r+oVK2Aj3ph/26XdH0pbAkC2RiSjUYhKD+PExemG4XSjpGFeyZ/QM8lBOa7O8aGOU+/yEbMJgQv/DnCg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.60.0", - "@typescript-eslint/visitor-keys": "5.60.0", + "@typescript-eslint/typescript-estree": "5.61.0", + "@typescript-eslint/utils": "5.61.0", "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", "tsutils": "^3.21.0" }, "engines": { @@ -10021,24 +10267,27 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, + "peerDependencies": { + "eslint": "*" + }, "peerDependenciesMeta": { "typescript": { "optional": true } } }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/utils": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.60.0.tgz", - "integrity": "sha512-ba51uMqDtfLQ5+xHtwlO84vkdjrqNzOnqrnwbMHMRY8Tqeme8C2Q8Fc7LajfGR+e3/4LoYiWXUM6BpIIbHJ4hQ==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "5.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.61.0.tgz", + "integrity": "sha512-mV6O+6VgQmVE6+xzlA91xifndPW9ElFW8vbSF0xCT/czPXVhwDewKila1jOyRwa9AE19zKnrr7Cg5S3pJVrTWQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.60.0", - "@typescript-eslint/types": "5.60.0", - "@typescript-eslint/typescript-estree": "5.60.0", + "@typescript-eslint/scope-manager": "5.61.0", + "@typescript-eslint/types": "5.61.0", + "@typescript-eslint/typescript-estree": "5.61.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -10053,24 +10302,7 @@ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.60.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.0.tgz", - "integrity": "sha512-wm9Uz71SbCyhUKgcaPRauBdTegUyY/ZWl8gLwD/i/ybJqscrrdVSFImpvUz16BLPChIeKBK5Fa9s6KDQjsjyWw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.60.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-scope": { + "node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", @@ -10083,7 +10315,7 @@ "node": ">=8.0.0" } }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/estraverse": { + "node_modules/@typescript-eslint/eslint-plugin/node_modules/estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", @@ -10092,6 +10324,25 @@ "node": ">=4.0" } }, + "node_modules/@typescript-eslint/experimental-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", + "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/@typescript-eslint/parser": { "version": "5.61.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.61.0.tgz", @@ -10617,6 +10868,17 @@ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -10630,9 +10892,9 @@ } }, "node_modules/acorn": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz", - "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "bin": { "acorn": "bin/acorn" }, @@ -10938,12 +11200,12 @@ } }, "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", "dev": true, "dependencies": { - "deep-equal": "^2.0.5" + "dequal": "^2.0.3" } }, "node_modules/array-buffer-byte-length": { @@ -11019,6 +11281,14 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/autoprefixer": { "version": "10.4.14", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", @@ -11097,12 +11367,12 @@ } }, "node_modules/babel-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz", - "integrity": "sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.1.tgz", + "integrity": "sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==", "dev": true, "dependencies": { - "@jest/transform": "^29.5.0", + "@jest/transform": "^29.6.1", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", "babel-preset-jest": "^29.5.0", @@ -11286,48 +11556,39 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.3.tgz", - "integrity": "sha512-bM3gHc337Dta490gg+/AseNB9L4YLHxq1nGKZZSHbhXv4aTYU2MD2cjza1Ru4S6975YLTaL1K8uJf6ukJhhmtw==", + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.4.tgz", + "integrity": "sha512-9WeK9snM1BfxB38goUEv2FLnA6ja07UMfazFHzCXUb3NyDZAwfXvQiURQ6guTTMeHcOsdknULm1PDhs4uWtKyA==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-define-polyfill-provider": "^0.4.0", - "semver": "^6.1.1" + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.4.1", + "@nicolo-ribaudo/semver-v6": "^6.3.3" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.1.tgz", - "integrity": "sha512-ikFrZITKg1xH6pLND8zT14UPgjKHiGLqex7rGEZCH2EvhsneJaJPemmpQaIZV5AL03II+lXylw3UmddDK8RU5Q==", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.2.tgz", + "integrity": "sha512-Cid+Jv1BrY9ReW9lIfNlNpsI53N+FN7gE+f73zLAUbr9C52W4gKLWSByx47pfDJsEysojKArqOtOKZSVIIUTuQ==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.0", - "core-js-compat": "^3.30.1" + "@babel/helper-define-polyfill-provider": "^0.4.1", + "core-js-compat": "^3.31.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.0.tgz", - "integrity": "sha512-hDJtKjMLVa7Z+LwnTCxoDLQj6wdc+B8dun7ayF2fYieI6OzfuvcLMB32ihJZ4UhCBwNYGl5bg/x/P9cMdnkc2g==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.1.tgz", + "integrity": "sha512-L8OyySuI6OSQ5hFy9O+7zFjyr4WhAfRjLIOkhQGYl+emwJkd/S4XXT1JpfrgR1jrQ1NcGiOh+yAdGlF8pnC3Jw==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.0" + "@babel/helper-define-polyfill-provider": "^0.4.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" @@ -11395,7 +11656,6 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, "funding": [ { "type": "github", @@ -11758,15 +12018,15 @@ } }, "node_modules/cacache/node_modules/glob": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.0.tgz", - "integrity": "sha512-AQ1/SB9HH0yCx1jXAT4vmCbTOPe5RQ+kCurjbel5xSCGhebumUv+GJZfa1rEqor3XIViqwSEmlkZCQD43RWrBg==", + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", + "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^2.0.3", "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2", - "path-scurry": "^1.7.0" + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" }, "bin": { "glob": "dist/cjs/src/bin.js" @@ -11779,9 +12039,9 @@ } }, "node_modules/cacache/node_modules/minimatch": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.2.tgz", - "integrity": "sha512-PZOT9g5v2ojiTL7r1xF6plNHLtOeTpSlDI007As2NlA2aYBMfVom17yqa6QzhmDP8QOhn7LjHTg7DFCVSSa6yg==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -11861,9 +12121,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001507", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001507.tgz", - "integrity": "sha512-SFpUDoSLCaE5XYL2jfqe9ova/pbQHEmbheDf5r4diNwbAgR3qxM9NQtfsiSscjqoya5K7kFcHPUQ+VsUkIJR4A==", + "version": "1.0.30001516", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001516.tgz", + "integrity": "sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g==", "dev": true, "funding": [ { @@ -11978,6 +12238,21 @@ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==" }, + "node_modules/class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==" + }, + "node_modules/class-validator": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.0.tgz", + "integrity": "sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==", + "dependencies": { + "@types/validator": "^13.7.10", + "libphonenumber-js": "^1.10.14", + "validator": "^13.7.0" + } + }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -12090,9 +12365,9 @@ } }, "node_modules/collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true }, "node_modules/color-convert": { @@ -12127,8 +12402,7 @@ "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" }, "node_modules/colors": { "version": "1.0.3", @@ -12447,6 +12721,34 @@ "webpack": "^5.1.0" } }, + "node_modules/copy-webpack-plugin/node_modules/fast-glob": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", + "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/copy-webpack-plugin/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -12460,14 +12762,14 @@ } }, "node_modules/copy-webpack-plugin/node_modules/globby": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.0.tgz", - "integrity": "sha512-jWsQfayf13NvqKUIL3Ta+CIqMnvlaIDFveWE/dpOZ9+3AMEJozsxDvKA02zync9UuvOM8rOXzsD5GqKP4OnWPQ==", + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", "dev": true, "dependencies": { "dir-glob": "^3.0.1", - "fast-glob": "^3.2.11", - "ignore": "^5.2.0", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", "merge2": "^1.4.1", "slash": "^4.0.0" }, @@ -12491,12 +12793,12 @@ } }, "node_modules/core-js-compat": { - "version": "3.31.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.31.0.tgz", - "integrity": "sha512-hM7YCu1cU6Opx7MXNu0NuumM0ezNeAeRKadixyiQELWY3vT3De9S4J5ZBMraWV2vZnrE1Cirl0GtFtDtMUXzPw==", + "version": "3.31.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.31.1.tgz", + "integrity": "sha512-wIDWd2s5/5aJSdpOJHfSibxNODxoGoWOBHt8JSPB41NOE94M7kuTPZCYLOlTtuoXTsBPKobpJ6T+y0SSy5L9SA==", "dev": true, "dependencies": { - "browserslist": "^4.21.5" + "browserslist": "^4.21.9" }, "funding": { "type": "opencollective", @@ -12980,6 +13282,14 @@ "node": ">=12" } }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "engines": { + "node": "*" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -13055,15 +13365,15 @@ "dev": true }, "node_modules/deep-equal": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.1.tgz", - "integrity": "sha512-lKdkdV6EOGoVn65XaOsPdH4rMxTZOnmFyuIkMjM1i5HHCbfjC97dawgTAy0deYNfuqUqW+Q5VrVaQYtUpSd6yQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", + "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", "call-bind": "^1.0.2", "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.0", + "get-intrinsic": "^1.2.1", "is-arguments": "^1.1.1", "is-array-buffer": "^3.0.2", "is-date-object": "^1.0.5", @@ -13441,9 +13751,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.440", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.440.tgz", - "integrity": "sha512-r6dCgNpRhPwiWlxbHzZQ/d9swfPaEJGi8ekqRBwQYaR3WmA5VkqQfBWSDDjuJU1ntO+W9tHx8OHV/96Q8e0dVw==", + "version": "1.4.461", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.461.tgz", + "integrity": "sha512-1JkvV2sgEGTDXjdsaQCeSwYYuhLRphRpc+g6EHTFELJXEiznLt3/0pZ9JuAOQ5p2rI3YxKTbivtvajirIfhrEQ==", "dev": true }, "node_modules/emittery": { @@ -13505,7 +13815,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "dependencies": { "once": "^1.4.0" } @@ -13689,15 +13998,14 @@ } }, "node_modules/escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", "dev": true, "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" + "esutils": "^2.0.2" }, "bin": { "escodegen": "bin/escodegen.js", @@ -13710,45 +14018,6 @@ "source-map": "~0.6.1" } }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/escodegen/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -13759,18 +14028,6 @@ "node": ">=0.10.0" } }, - "node_modules/escodegen/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/eslint": { "version": "8.45.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", @@ -13865,9 +14122,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.2.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.2.tgz", - "integrity": "sha512-euzbp06F934Z7UDl5ZUaRPLAc9MKjh0rMPERrHT7UhlCEwgb25kBj37TvMgWeHZVkR5I9CayswrpoaqZU1RImw==", + "version": "27.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.3.tgz", + "integrity": "sha512-sRLlSCpICzWuje66Gl9zvdF6mwD5X86I4u55hJyFBsxYOsBCmT5+kSUjf+fkFWVMMgpzNEupjW8WzUqi83hJAQ==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" @@ -13876,7 +14133,7 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0", "eslint": "^7.0.0 || ^8.0.0", "jest": "*" }, @@ -13911,9 +14168,9 @@ } }, "node_modules/eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.1.tgz", + "integrity": "sha512-CvefSOsDdaYYvxChovdrPo/ZGt8d5lrJWleAc1diXRKhHGiTYEI26cvo8Kle/wGnsizoCJjK73FMg1/IkIwiNA==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -14112,9 +14369,9 @@ } }, "node_modules/espree": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.0.tgz", - "integrity": "sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "dependencies": { "acorn": "^8.9.0", @@ -14191,6 +14448,14 @@ "node": ">= 0.6" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, "node_modules/eventemitter-asyncresource": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eventemitter-asyncresource/-/eventemitter-asyncresource-1.0.0.tgz", @@ -14207,7 +14472,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, "engines": { "node": ">=0.8.x" } @@ -14245,16 +14509,17 @@ } }, "node_modules/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.1.tgz", + "integrity": "sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==", "dev": true, "dependencies": { - "@jest/expect-utils": "^29.5.0", + "@jest/expect-utils": "^29.6.1", + "@types/node": "*", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0" + "jest-matcher-utils": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -14395,6 +14660,11 @@ "node": ">=0.6.0" } }, + "node_modules/fast-copy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", + "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -14428,6 +14698,14 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-redact": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.2.0.tgz", + "integrity": "sha512-zaTadChr+NekyzallAMXATXLOR8MNx3zqpZ0MUF2aGf4EathnG0f32VLODNlY8IuGY3HoRO2L6/6fSzNsLaHIw==", + "engines": { + "node": ">=6" + } + }, "node_modules/fast-safe-stringify": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", @@ -15247,17 +15525,6 @@ "graphql": ">=0.11 <=16" } }, - "node_modules/graphql-subscriptions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/graphql-subscriptions/-/graphql-subscriptions-2.0.0.tgz", - "integrity": "sha512-s6k2b8mmt9gF9pEfkxsaO1lTxaySfKoEJzEfmwguBbQ//Oq23hIXCfR1hm4kdh5hnR20RdwB+s3BCb+0duHSZA==", - "dependencies": { - "iterall": "^1.3.0" - }, - "peerDependencies": { - "graphql": "^15.7.2 || ^16.0.0" - } - }, "node_modules/graphql-tag": { "version": "2.12.6", "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", @@ -15273,9 +15540,9 @@ } }, "node_modules/graphql-ws": { - "version": "5.13.1", - "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.13.1.tgz", - "integrity": "sha512-eiX7ES/ZQr0q7hSM5UBOEIFfaAUmAY9/CSDyAnsETuybByU7l/v46drRg9DQoTvVABEHp3QnrvwgTRMhqy7zxQ==", + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.14.0.tgz", + "integrity": "sha512-itrUTQZP/TgswR4GSSYuwWUzrE/w5GhbwM2GX3ic2U7aw33jgEsayfIlvaj7/GcIvZgNMzsPTrE5hqPuFUiE5g==", "engines": { "node": ">=10" }, @@ -15422,6 +15689,65 @@ "he": "bin/he" } }, + "node_modules/help-me": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", + "integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==", + "dependencies": { + "glob": "^8.0.0", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/help-me/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/help-me/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/hexer": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/hexer/-/hexer-1.5.0.tgz", @@ -15507,9 +15833,9 @@ } }, "node_modules/html-entities": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.6.tgz", - "integrity": "sha512-9o0+dcpIw2/HxkNuYKxSJUF/MMRZQECK4GnF+oQOmJ83yCVHTWgCH5aOXxK5bozNRmM8wtgryjHD3uloPBDEGw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", + "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", "dev": true, "funding": [ { @@ -15822,7 +16148,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, "funding": [ { "type": "github", @@ -15869,9 +16194,9 @@ } }, "node_modules/ignore-walk/node_modules/minimatch": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.2.tgz", - "integrity": "sha512-PZOT9g5v2ojiTL7r1xF6plNHLtOeTpSlDI007As2NlA2aYBMfVom17yqa6QzhmDP8QOhn7LjHTg7DFCVSSa6yg==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -15896,10 +16221,15 @@ "node": ">=0.10.0" } }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" + }, "node_modules/immutable": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", - "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.1.tgz", + "integrity": "sha512-lj9cnmB/kVS0QHsJnYKD1uo3o39nrbKxszjnqS9Fr6NB7bZzW45U6WSGBPKXDL/CvDKqDNPA4r3DoDQ8GTxo2A==", "dev": true }, "node_modules/import-fresh": { @@ -16594,9 +16924,9 @@ } }, "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -16872,28 +17202,28 @@ } }, "node_modules/jest-circus": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.5.0.tgz", - "integrity": "sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.1.tgz", + "integrity": "sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==", "dev": true, "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.6.1", + "@jest/expect": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.5.0", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", + "jest-each": "^29.6.1", + "jest-matcher-utils": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-runtime": "^29.6.1", + "jest-snapshot": "^29.6.1", + "jest-util": "^29.6.1", "p-limit": "^3.1.0", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" @@ -16961,12 +17291,12 @@ } }, "node_modules/jest-circus/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", + "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -17005,21 +17335,21 @@ } }, "node_modules/jest-cli": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.5.0.tgz", - "integrity": "sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.1.tgz", + "integrity": "sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing==", "dev": true, "dependencies": { - "@jest/core": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/core": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/types": "^29.6.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-config": "^29.6.1", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", "prompts": "^2.0.1", "yargs": "^17.3.1" }, @@ -17109,31 +17439,31 @@ } }, "node_modules/jest-config": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.5.0.tgz", - "integrity": "sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.1.tgz", + "integrity": "sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.5.0", - "@jest/types": "^29.5.0", - "babel-jest": "^29.5.0", + "@jest/test-sequencer": "^29.6.1", + "@jest/types": "^29.6.1", + "babel-jest": "^29.6.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.5.0", - "jest-environment-node": "^29.5.0", + "jest-circus": "^29.6.1", + "jest-environment-node": "^29.6.1", "jest-get-type": "^29.4.3", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-resolve": "^29.6.1", + "jest-runner": "^29.6.1", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -17212,12 +17542,12 @@ } }, "node_modules/jest-config/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", + "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -17256,15 +17586,15 @@ } }, "node_modules/jest-diff": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", - "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.1.tgz", + "integrity": "sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==", "dev": true, "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.4.3", "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -17329,12 +17659,12 @@ } }, "node_modules/jest-diff/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", + "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -17385,16 +17715,16 @@ } }, "node_modules/jest-each": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.5.0.tgz", - "integrity": "sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.1.tgz", + "integrity": "sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", - "jest-util": "^29.5.0", - "pretty-format": "^29.5.0" + "jest-util": "^29.6.1", + "pretty-format": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -17459,12 +17789,12 @@ } }, "node_modules/jest-each/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", + "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -17530,17 +17860,17 @@ } }, "node_modules/jest-environment-node": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.5.0.tgz", - "integrity": "sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.1.tgz", + "integrity": "sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==", "dev": true, "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.6.1", + "@jest/fake-timers": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" + "jest-mock": "^29.6.1", + "jest-util": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -17556,20 +17886,20 @@ } }, "node_modules/jest-haste-map": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.5.0.tgz", - "integrity": "sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.1.tgz", + "integrity": "sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-util": "^29.6.1", + "jest-worker": "^29.6.1", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -17581,13 +17911,13 @@ } }, "node_modules/jest-leak-detector": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz", - "integrity": "sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz", + "integrity": "sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==", "dev": true, "dependencies": { "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -17606,12 +17936,12 @@ } }, "node_modules/jest-leak-detector/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", + "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -17626,15 +17956,15 @@ "dev": true }, "node_modules/jest-matcher-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", - "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz", + "integrity": "sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.5.0", + "jest-diff": "^29.6.1", "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -17699,12 +18029,12 @@ } }, "node_modules/jest-matcher-utils/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", + "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -17743,18 +18073,18 @@ } }, "node_modules/jest-message-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", - "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.1.tgz", + "integrity": "sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -17821,12 +18151,12 @@ } }, "node_modules/jest-message-util/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", + "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -17865,14 +18195,14 @@ } }, "node_modules/jest-mock": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.5.0.tgz", - "integrity": "sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.1.tgz", + "integrity": "sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/node": "*", - "jest-util": "^29.5.0" + "jest-util": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -17936,12 +18266,12 @@ } }, "node_modules/jest-preset-angular/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", + "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -17965,17 +18295,17 @@ } }, "node_modules/jest-resolve": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.5.0.tgz", - "integrity": "sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.1.tgz", + "integrity": "sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.6.1", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" @@ -17985,13 +18315,13 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz", - "integrity": "sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz", + "integrity": "sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==", "dev": true, "dependencies": { "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.5.0" + "jest-snapshot": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -18077,30 +18407,30 @@ } }, "node_modules/jest-runner": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.5.0.tgz", - "integrity": "sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.1.tgz", + "integrity": "sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==", "dev": true, "dependencies": { - "@jest/console": "^29.5.0", - "@jest/environment": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.6.1", + "@jest/environment": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-leak-detector": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-resolve": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-util": "^29.5.0", - "jest-watcher": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-environment-node": "^29.6.1", + "jest-haste-map": "^29.6.1", + "jest-leak-detector": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-resolve": "^29.6.1", + "jest-runtime": "^29.6.1", + "jest-util": "^29.6.1", + "jest-watcher": "^29.6.1", + "jest-worker": "^29.6.1", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -18198,31 +18528,31 @@ } }, "node_modules/jest-runtime": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.5.0.tgz", - "integrity": "sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/globals": "^29.5.0", - "@jest/source-map": "^29.4.3", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.1.tgz", + "integrity": "sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.6.1", + "@jest/fake-timers": "^29.6.1", + "@jest/globals": "^29.6.1", + "@jest/source-map": "^29.6.0", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", + "jest-haste-map": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-mock": "^29.6.1", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", + "jest-resolve": "^29.6.1", + "jest-snapshot": "^29.6.1", + "jest-util": "^29.6.1", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -18301,34 +18631,32 @@ } }, "node_modules/jest-snapshot": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.5.0.tgz", - "integrity": "sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.1.tgz", + "integrity": "sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/babel__traverse": "^7.0.6", + "@jest/expect-utils": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.5.0", + "expect": "^29.6.1", "graceful-fs": "^4.2.9", - "jest-diff": "^29.5.0", + "jest-diff": "^29.6.1", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", + "jest-matcher-utils": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1", "natural-compare": "^1.4.0", - "pretty-format": "^29.5.0", - "semver": "^7.3.5" + "pretty-format": "^29.6.1", + "semver": "^7.5.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -18392,13 +18720,25 @@ "node": ">=8" } }, + "node_modules/jest-snapshot/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jest-snapshot/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", + "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -18424,6 +18764,21 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jest-snapshot/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -18437,12 +18792,12 @@ } }, "node_modules/jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.1.tgz", + "integrity": "sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -18524,17 +18879,17 @@ } }, "node_modules/jest-validate": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.5.0.tgz", - "integrity": "sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.1.tgz", + "integrity": "sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "camelcase": "^6.2.0", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", "leven": "^3.1.0", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -18611,12 +18966,12 @@ } }, "node_modules/jest-validate/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", + "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -18655,18 +19010,18 @@ } }, "node_modules/jest-watcher": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.5.0.tgz", - "integrity": "sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.1.tgz", + "integrity": "sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==", "dev": true, "dependencies": { - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/test-result": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.5.0", + "jest-util": "^29.6.1", "string-length": "^4.0.1" }, "engines": { @@ -18744,13 +19099,13 @@ } }, "node_modules/jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz", + "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==", "dev": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.5.0", + "jest-util": "^29.6.1", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -18783,9 +19138,9 @@ } }, "node_modules/jiti": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.18.2.tgz", - "integrity": "sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz", + "integrity": "sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==", "dev": true, "bin": { "jiti": "bin/jiti.js" @@ -18804,6 +19159,14 @@ "@sideway/pinpoint": "^2.0.0" } }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "engines": { + "node": ">=10" + } + }, "node_modules/jquery": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz", @@ -19182,9 +19545,9 @@ } }, "node_modules/less/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "optional": true, "bin": { @@ -19223,6 +19586,11 @@ "node": ">= 0.8.0" } }, + "node_modules/libphonenumber-js": { + "version": "1.10.37", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.37.tgz", + "integrity": "sha512-Z10PCaOCiAxbUxLyR31DNeeNugSVP6iv/m7UrSKS5JHziEMApJtgku4e9Q69pzzSC9LnQiM09sqsGf2ticZnMw==" + }, "node_modules/license-webpack-plugin": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz", @@ -19240,6 +19608,14 @@ } } }, + "node_modules/lie": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", + "integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==", + "dependencies": { + "immediate": "~3.0.5" + } + }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -19276,6 +19652,14 @@ "node": ">= 12.13.0" } }, + "node_modules/localforage": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", + "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==", + "dependencies": { + "lie": "3.1.1" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -19529,9 +19913,9 @@ } }, "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -20318,9 +20702,9 @@ } }, "node_modules/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -20405,9 +20789,9 @@ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" }, "node_modules/node-releases": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", - "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==", + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", "dev": true }, "node_modules/nopt": { @@ -20600,9 +20984,9 @@ } }, "node_modules/nwsapi": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.5.tgz", - "integrity": "sha512-6xpotnECFy/og7tKSBVmUNft7J3jyXAka4XvG6AUhFWRz+Q/Ljus7znJAA3bxColfQLdS+XsjoodtJfCgeTEFQ==", + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", + "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", "dev": true }, "node_modules/nx": { @@ -20906,6 +21290,11 @@ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "dev": true }, + "node_modules/on-exit-leak-free": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz", + "integrity": "sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==" + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -21346,12 +21735,12 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-scurry": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.9.2.tgz", - "integrity": "sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", "dependencies": { - "lru-cache": "^9.1.1", - "minipass": "^5.0.0 || ^6.0.2" + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -21361,9 +21750,9 @@ } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.2.tgz", - "integrity": "sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.0.tgz", + "integrity": "sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==", "engines": { "node": "14 || >=16.14" } @@ -21408,6 +21797,181 @@ "node": ">=0.10.0" } }, + "node_modules/pino": { + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.14.1.tgz", + "integrity": "sha512-8LYNv7BKWXSfS+k6oEc6occy5La+q2sPwU3q2ljTX5AZk7v+5kND2o5W794FyRaqha6DJajmkNRsWtPpFyMUdw==", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "v1.0.0", + "pino-std-serializers": "^6.0.0", + "process-warning": "^2.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^3.1.0", + "thread-stream": "^2.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz", + "integrity": "sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==", + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/pino-abstract-transport/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/pino-abstract-transport/node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/pino-abstract-transport/node_modules/readable-stream": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", + "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/pino-abstract-transport/node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/pino-abstract-transport/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/pino-pretty": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.0.1.tgz", + "integrity": "sha512-yrn00+jNpkvZX/NrPVCPIVHAfTDy3ahF0PND9tKqZk4j9s+loK8dpzrJj4dGb7i+WLuR50ussuTAiWoMWU+qeA==", + "dependencies": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.0", + "fast-safe-stringify": "^2.1.1", + "help-me": "^4.0.1", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.0.0", + "pump": "^3.0.0", + "readable-stream": "^4.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/pino-pretty/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/pino-pretty/node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/pino-pretty/node_modules/readable-stream": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", + "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/pino-pretty/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", + "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" + }, "node_modules/pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", @@ -22342,6 +22906,11 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "node_modules/process-warning": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.2.0.tgz", + "integrity": "sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg==" + }, "node_modules/promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", @@ -22439,6 +23008,15 @@ "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", "dev": true }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", @@ -22512,6 +23090,11 @@ } ] }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" + }, "node_modules/quick-lru": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", @@ -22614,16 +23197,16 @@ } }, "node_modules/read-package-json/node_modules/glob": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.0.tgz", - "integrity": "sha512-AQ1/SB9HH0yCx1jXAT4vmCbTOPe5RQ+kCurjbel5xSCGhebumUv+GJZfa1rEqor3XIViqwSEmlkZCQD43RWrBg==", + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", + "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^2.0.3", "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2", - "path-scurry": "^1.7.0" + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" }, "bin": { "glob": "dist/cjs/src/bin.js" @@ -22657,9 +23240,9 @@ } }, "node_modules/read-package-json/node_modules/minimatch": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.2.tgz", - "integrity": "sha512-PZOT9g5v2ojiTL7r1xF6plNHLtOeTpSlDI007As2NlA2aYBMfVom17yqa6QzhmDP8QOhn7LjHTg7DFCVSSa6yg==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -22798,9 +23381,9 @@ } }, "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "bin": { "semver": "bin/semver" @@ -22850,6 +23433,14 @@ "node": ">=8.10.0" } }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", @@ -23103,9 +23694,9 @@ } }, "node_modules/require-in-the-middle": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.1.1.tgz", - "integrity": "sha512-OScOjQjrrjhAdFpQmnkE/qbIBGCRFhQB/YaJhcC3CPOlmhe7llnW46Ac1J5+EjcNXOTnDdpF96Erw/yedsGksQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz", + "integrity": "sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw==", "dependencies": { "debug": "^4.1.1", "module-details-from-path": "^1.0.3", @@ -23272,9 +23863,9 @@ } }, "node_modules/rollup": { - "version": "3.25.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.25.2.tgz", - "integrity": "sha512-VLnkxZMDr3jpxgtmS8pQZ0UvhslmF4ADq/9w4erkctbgjCqLW9oa89fJuXEs4ZmgyoF7Dm8rMDKSS5b5u2hHUg==", + "version": "3.26.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.2.tgz", + "integrity": "sha512-6umBIGVz93er97pMgQO08LuH3m6PUb3jlDUUGFsNJB6VgTCUaDFpupf5JfU30529m/UKOgmiX+uY6Sx8cOYpLA==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -23433,6 +24024,14 @@ } ] }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -23548,6 +24147,11 @@ "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", "dev": true }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" + }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -23824,15 +24428,14 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/sigstore": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.6.0.tgz", - "integrity": "sha512-QODKff/qW/TXOZI6V/Clqu74xnInAS6it05mufj4/fSewexLtfEntgLZZcBtUK44CDQyUE5TUXYy1ARYzlfG9g==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.7.0.tgz", + "integrity": "sha512-KP7QULhWdlu3hlp+jw2EvgWKlOGOY9McLj/jrchLjHNlNPK0KWIwF919cbmOp6QiKXLmPijR2qH/5KYWlbtG9Q==", "dev": true, "dependencies": { "@sigstore/protobuf-specs": "^0.1.0", - "@sigstore/tuf": "^1.0.0", - "make-fetch-happen": "^11.0.1", - "tuf-js": "^1.1.3" + "@sigstore/tuf": "^1.0.1", + "make-fetch-happen": "^11.0.1" }, "bin": { "sigstore": "bin/sigstore.js" @@ -23911,6 +24514,14 @@ "node": ">= 10" } }, + "node_modules/sonic-boom": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.3.0.tgz", + "integrity": "sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g==", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", @@ -24277,7 +24888,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -24434,9 +25044,9 @@ } }, "node_modules/sucrase": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.32.0.tgz", - "integrity": "sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==", + "version": "3.33.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.33.0.tgz", + "integrity": "sha512-ARGC7vbufOHfpvyGcZZXFaXCMZ9A4fffOGC5ucOW7+WHDGlAe8LJdf3Jts1sWhDeiI1RSWrKy5Hodl+JWGdW2A==", "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", @@ -24970,6 +25580,14 @@ "node": ">=0.8" } }, + "node_modules/thread-stream": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.3.0.tgz", + "integrity": "sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA==", + "dependencies": { + "real-require": "^0.2.0" + } + }, "node_modules/thriftrw": { "version": "3.11.4", "resolved": "https://registry.npmjs.org/thriftrw/-/thriftrw-3.11.4.tgz", @@ -25792,6 +26410,14 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/validator": { + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.9.0.tgz", + "integrity": "sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/value-or-promise": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.12.tgz", @@ -26361,9 +26987,9 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.10.tgz", + "integrity": "sha512-uxoA5vLUfRPdjCuJ1h5LlYdmTLbYfums398v3WLkM+i/Wltl2/XyZpQWKbN++ck5L64SR/grOHqtXCUKmlZPNA==", "dev": true, "dependencies": { "available-typed-arrays": "^1.0.5", @@ -26394,15 +27020,6 @@ "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", "dev": true }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/package.json b/package.json index 8a90c03b..0c6429c1 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,8 @@ "@angular/platform-browser-dynamic": "16.1.2", "@angular/router": "16.1.2", "@apollo/server": "^4.5.0", + "@automapper/classes": "^8.7.7", + "@automapper/core": "^8.7.7", "@nestjs/apollo": "^12.0.3", "@nestjs/common": "10.0.3", "@nestjs/config": "^3.0.0", @@ -95,20 +97,26 @@ "@nestjs/graphql": "^12.0.3", "@nestjs/mongoose": "^10.0.0", "@opentelemetry/instrumentation-graphql": "^0.35.0", + "@nestjs/platform-express": "10.0.3", + "@opentelemetry/instrumentation-pino": "^0.33.3", + "@opentelemetry/sdk-trace-base": "^1.14.0", + "@sentry/angular-ivy": "^7.57.0", + "@sentry/integrations": "^7.57.0", "@opentelemetry/instrumentation-mongoose": "^0.33.0", "@opentelemetry/sdk-node": "^0.41.0", - "@opentelemetry/tracing": "^0.24.0", - "@sentry/angular-ivy": "^7.50.0", "@sentry/node": "^7.52.1", "@sentry/opentelemetry-node": "^7.52.1", "@sentry/profiling-node": "^1.0.0", - "@nestjs/platform-express": "10.0.3", + "@timonmasberg/automapper-nestjs": "^0.0.0", "angular-oauth2-oidc": "^15.0.1", "axios": "^1.0.0", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.0", "graphql": "^16.6.0", "graphql-sse": "^2.1.1", - "graphql-subscriptions": "^2.0.0", "mongoose": "^7.0.3", + "pino": "^8.14.1", + "pino-pretty": "^10.0.0", "reflect-metadata": "^0.1.13", "rxjs": "~7.8.0", "tslib": "^2.3.0", diff --git a/sonar-project.properties b/sonar-project.properties index 0ea34506..28ff942b 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -6,4 +6,4 @@ sonar.exclusions=**/*e2e/**/support/** sonar.javascript.coveragePlugin=lcov sonar.javascript.lcov.reportPaths=./coverage/lcov.info sonar.test.inclusions=**/*.spec.ts -sonar.coverage.exclusions=**/*.js,**/src/*main*.ts,**/*polyfills*.ts,**/*environment*.ts,**/*module.ts,**/*-e2e/**,**/*.test-helper.ts +sonar.coverage.exclusions=**/*.js,**/src/*main*.ts,**/*polyfills*.ts,**/*environment*.ts,**/*module.ts,**/*-e2e/**,**/*.test-helper.ts,**/*.mapper-profile.ts diff --git a/tools/db/data/collection-data.model.ts b/tools/db/data/collection-data.model.ts index 8e193c5c..b98feb81 100644 --- a/tools/db/data/collection-data.model.ts +++ b/tools/db/data/collection-data.model.ts @@ -1,6 +1,10 @@ -import { Document, OptionalId } from 'mongodb'; +import { Types } from 'mongoose'; -export interface CollectionData { +import { BaseModel } from '../../../libs/api/shared/src'; + +type OptionalId = T & { _id?: Types.ObjectId }; + +export interface CollectionData { collectionName: string; - entries: OptionalId[]; + entries: OptionalId>[]; } diff --git a/tools/db/data/organizations.data.ts b/tools/db/data/organizations.data.ts new file mode 100644 index 00000000..e427d29f --- /dev/null +++ b/tools/db/data/organizations.data.ts @@ -0,0 +1,34 @@ +import { Types } from 'mongoose'; + +import { OrganizationDocument } from '../../../libs/api/organization/src/lib/infra/schema/organization.schema'; +import { CollectionData } from './collection-data.model'; + +const collectionData: CollectionData = { + collectionName: 'organizations', + entries: [ + { + _id: new Types.ObjectId('dff7584efe2c174eee8bae45'), + name: 'Test Organisation', + createdAt: new Date(), + // hamburg + geoSettings: { + bbox: { + topLeft: { + lat: 53.38, + lon: 9.65, + }, + bottomRight: { + lat: 53.75, + lon: 10.33, + }, + }, + centroid: { + lat: 53.551086, + lon: 9.993682, + }, + }, + }, + ], +}; + +export default collectionData; diff --git a/tools/db/data/placeholder.data.ts b/tools/db/data/placeholder.data.ts deleted file mode 100644 index b835b2f9..00000000 --- a/tools/db/data/placeholder.data.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { CollectionData } from './collection-data.model'; - -// this is just temporary until we have our first collections! -// mongo does not have an explicit "create db" command, -// therefor we need some data to feed the db with, so the E2Es won't fail due to a bad connection uri -const collectionData: CollectionData = { - collectionName: 'placeholder', - entries: [ - { - pleaseRemoveThis: 'when we have our first collection', - }, - ], -}; - -export default collectionData; diff --git a/tools/db/data/template.ts b/tools/db/data/template.ts index 7814b969..5bfc5161 100644 --- a/tools/db/data/template.ts +++ b/tools/db/data/template.ts @@ -1,10 +1,16 @@ +import { Types } from 'mongoose'; + import { CollectionData } from './collection-data.model'; -const collectionData: CollectionData = { +const collectionData: CollectionData<{ + propertyA: string; + propertyB: string; +}> = { collectionName: 'collectionXY', entries: [ // this is the data that will be imported into the collection { + _id: new Types.ObjectId('your custom id here'), // you can also override the default _id if you need it for "relations"" propertyA: 'test 1A', propertyB: 'test 1B', }, diff --git a/tsconfig.base.json b/tsconfig.base.json index 2f1fb89b..3c2fd85b 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -17,6 +17,7 @@ "paths": { "@kordis/api/auth": ["libs/api/auth/src/index.ts"], "@kordis/api/observability": ["libs/api/observability/src/index.ts"], + "@kordis/api/organization": ["libs/api/organization/src/index.ts"], "@kordis/api/shared": ["libs/api/shared/src/index.ts"], "@kordis/api/test-helpers": ["libs/api/test-helpers/src/index.ts"], "@kordis/shared/auth": ["libs/shared/auth/src/index.ts"],