diff --git a/.github/workflows/dev-deploy-api.yml b/.github/workflows/dev-deploy-api.yml index e2badbda237..ba86751ca37 100644 --- a/.github/workflows/dev-deploy-api.yml +++ b/.github/workflows/dev-deploy-api.yml @@ -41,10 +41,6 @@ jobs: steps: - run: echo ${{ matrix.projectName }} - uses: actions/checkout@v3 - - uses: ./.github/actions/checkout-submodules - with: - submodule_token: ${{ secrets.SUBMODULES_TOKEN }} - submodule_branch: "next" - uses: ./.github/actions/setup-project - uses: ./.github/actions/setup-redis-cluster - uses: mansagroup/nrwl-nx-action@v3 @@ -88,11 +84,6 @@ jobs: name: ['novu/api-ee', 'novu/api'] steps: - uses: actions/checkout@v3 - - uses: ./.github/actions/checkout-submodules - with: - enabled: ${{ contains (matrix.name,'ee') }} - submodule_token: ${{ secrets.SUBMODULES_TOKEN }} - submodule_branch: "next" - uses: ./.github/actions/setup-project - uses: ./.github/actions/docker/build-api id: docker_build diff --git a/.github/workflows/dev-deploy-worker.yml b/.github/workflows/dev-deploy-worker.yml index 0180cf43a2b..dabe27c4e7b 100644 --- a/.github/workflows/dev-deploy-worker.yml +++ b/.github/workflows/dev-deploy-worker.yml @@ -50,11 +50,6 @@ jobs: name: ['novu/worker-ee', 'novu/worker'] steps: - uses: actions/checkout@v3 - - uses: ./.github/actions/checkout-submodules - with: - enabled: ${{ contains (matrix.name,'ee') }} - submodule_token: ${{ secrets.SUBMODULES_TOKEN }} - submodule_branch: "next" - uses: ./.github/actions/setup-project - uses: ./.github/actions/docker/build-worker id: docker_build diff --git a/.github/workflows/prod-deploy-api.yml b/.github/workflows/prod-deploy-api.yml index b1d8b1fa3c6..8f886ad620f 100644 --- a/.github/workflows/prod-deploy-api.yml +++ b/.github/workflows/prod-deploy-api.yml @@ -30,10 +30,6 @@ jobs: steps: - run: echo ${{ matrix.projectName }} - uses: actions/checkout@v3 - - uses: ./.github/actions/checkout-submodules - with: - submodule_token: ${{ secrets.SUBMODULES_TOKEN }} - submodule_branch: "next" - uses: ./.github/actions/setup-project - uses: ./.github/actions/setup-redis-cluster - uses: mansagroup/nrwl-nx-action@v3 @@ -79,11 +75,6 @@ jobs: id-token: write steps: - uses: actions/checkout@v3 - - uses: ./.github/actions/checkout-submodules - with: - enabled: ${{ contains (matrix.name,'ee') }} - submodule_token: ${{ secrets.SUBMODULES_TOKEN }} - submodule_branch: "main" - uses: ./.github/actions/setup-project - name: build api diff --git a/.github/workflows/prod-deploy-worker.yml b/.github/workflows/prod-deploy-worker.yml index cd3b480e09c..8ce444cf0c9 100644 --- a/.github/workflows/prod-deploy-worker.yml +++ b/.github/workflows/prod-deploy-worker.yml @@ -38,11 +38,6 @@ jobs: id-token: write steps: - uses: actions/checkout@v3 - - uses: ./.github/actions/checkout-submodules - with: - enabled: ${{ contains (matrix.name,'ee') }} - submodule_token: ${{ secrets.SUBMODULES_TOKEN }} - submodule_branch: "main" - uses: ./.github/actions/setup-project - name: build worker diff --git a/.github/workflows/prod-deploy-ws.yml b/.github/workflows/prod-deploy-ws.yml index aef0b169635..87b98c2b825 100644 --- a/.github/workflows/prod-deploy-ws.yml +++ b/.github/workflows/prod-deploy-ws.yml @@ -23,6 +23,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 80 environment: Production + needs: + - test_ws strategy: matrix: name: [ 'novu/ws-ee', 'novu/ws' ] diff --git a/.github/workflows/reusable-api-e2e.yml b/.github/workflows/reusable-api-e2e.yml index 703863658f3..15ec2ecf64e 100644 --- a/.github/workflows/reusable-api-e2e.yml +++ b/.github/workflows/reusable-api-e2e.yml @@ -46,11 +46,6 @@ jobs: fi - uses: actions/checkout@v3 # checkout with submodules if token is provided - - uses: ./.github/actions/checkout-submodules - with: - enabled: ${{ steps.setup.outputs.has_token == 'true' }} - submodule_token: ${{ secrets.SUBMODULES_TOKEN }} - submodule_branch: ${{ inputs.submodule_branch }} - uses: ./.github/actions/setup-project - uses: ./.github/actions/setup-redis-cluster - uses: mansagroup/nrwl-nx-action@v3 diff --git a/.github/workflows/reusable-inbound-mail-e2e.yml b/.github/workflows/reusable-inbound-mail-e2e.yml index efb72234c81..35d50ef1fa8 100644 --- a/.github/workflows/reusable-inbound-mail-e2e.yml +++ b/.github/workflows/reusable-inbound-mail-e2e.yml @@ -38,11 +38,6 @@ jobs: steps: # checkout with submodules if token is provided - uses: actions/checkout@v3 - - uses: ./.github/actions/checkout-submodules - with: - enabled: ${{ steps.setup.outputs.has_token == 'true' }} - submodule_token: ${{ secrets.SUBMODULES_TOKEN }} - submodule_branch: ${{ inputs.submodule_branch }} - uses: ./.github/actions/setup-project - uses: ./.github/actions/setup-redis-cluster - uses: mansagroup/nrwl-nx-action@v3 diff --git a/.github/workflows/reusable-web-e2e.yml b/.github/workflows/reusable-web-e2e.yml index 4cbc5f16302..3970dc3d776 100644 --- a/.github/workflows/reusable-web-e2e.yml +++ b/.github/workflows/reusable-web-e2e.yml @@ -52,11 +52,6 @@ jobs: - uses: actions/checkout@v3 # checkout with submodules if token is provided - - uses: ./.github/actions/checkout-submodules - with: - enabled: ${{ steps.setup.outputs.has_token == 'true' }} - submodule_token: ${{ secrets.SUBMODULES_TOKEN }} - submodule_branch: ${{ inputs.submodule_branch }} - uses: ./.github/actions/setup-project id: setup-project with: diff --git a/.github/workflows/reusable-widget-e2e.yml b/.github/workflows/reusable-widget-e2e.yml index 2e786ce7ed2..f619bc64b39 100644 --- a/.github/workflows/reusable-widget-e2e.yml +++ b/.github/workflows/reusable-widget-e2e.yml @@ -51,12 +51,6 @@ jobs: fi - uses: actions/checkout@v3 # checkout with submodules if token is provided - - uses: ./.github/actions/checkout-submodules - with: - enabled: ${{ steps.setup.outputs.has_token == 'true' }} - submodule_token: ${{ secrets.SUBMODULES_TOKEN }} - submodule_branch: ${{ inputs.submodule_branch }} - - uses: ./.github/actions/setup-project id: setup-project with: diff --git a/.github/workflows/reusable-worker-e2e.yml b/.github/workflows/reusable-worker-e2e.yml index 976b6db593b..ce4a2bd04c9 100644 --- a/.github/workflows/reusable-worker-e2e.yml +++ b/.github/workflows/reusable-worker-e2e.yml @@ -46,11 +46,7 @@ jobs: fi - uses: actions/checkout@v3 # checkout with submodules if token is provided - - uses: ./.github/actions/checkout-submodules - with: - enabled: ${{ steps.setup.outputs.has_token == 'true' }} - submodule_token: ${{ secrets.SUBMODULES_TOKEN }} - submodule_branch: ${{ inputs.submodule_branch }} + - uses: ./.github/actions/setup-project - uses: ./.github/actions/setup-redis-cluster diff --git a/.github/workflows/reusable-ws-e2e.yml b/.github/workflows/reusable-ws-e2e.yml index 580ee7fee25..df4dd129fce 100644 --- a/.github/workflows/reusable-ws-e2e.yml +++ b/.github/workflows/reusable-ws-e2e.yml @@ -44,12 +44,6 @@ jobs: echo "has_token=false" >> $GITHUB_OUTPUT fi - uses: actions/checkout@v3 - # checkout with submodules if token is provided - - uses: ./.github/actions/checkout-submodules - with: - enabled: ${{ steps.setup.outputs.has_token == 'true' }} - submodule_token: ${{ secrets.SUBMODULES_TOKEN }} - submodule_branch: ${{ inputs.submodule_branch }} - uses: ./.github/actions/setup-project - uses: mansagroup/nrwl-nx-action@v3 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a90eb1a312a..241f4d9ab9b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -241,7 +241,7 @@ jobs: else echo "::set-output name=has_token::false" fi - + test_e2e_ee: name: Test E2E EE runs-on: ubuntu-latest @@ -260,10 +260,6 @@ jobs: steps: - run: echo ${{ matrix.projectName }} - uses: actions/checkout@v3 - - uses: ./.github/actions/checkout-submodules - with: - submodule_token: ${{ secrets.SUBMODULES_TOKEN }} - submodule_branch: "next" - uses: ./.github/actions/setup-project - uses: ./.github/actions/setup-redis-cluster - uses: mansagroup/nrwl-nx-action@v3 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 099f7c724d3..56d96ad01f7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,7 +20,7 @@ You can open a new issue with this [issue form](https://github.com/novuhq/novu/i ### Requirements -- Node.js version v14.19.3 +- Node.js version v16.15.1 - MongoDB - Redis. To install Redis on your O.S, please follow the below guides - [To install Redis on Windows](https://redis.io/docs/getting-started/installation/install-redis-on-windows/) @@ -33,8 +33,8 @@ You can open a new issue with this [issue form](https://github.com/novuhq/novu/i The project is a monorepo, meaning that it is a collection of multiple packages managed in the same repository. -To learn more about the project structure visit [https://docs.novu.co/community/monorepo-structure](https://docs.novu.co/community/monorepo-structure). +To learn more about the project structure and running the project locally, please have a look [here](https://docs.novu.co/community-support/introduction#run-novu-locally). After cloning your fork, you will need to run the `npm run setup:project` command to install and build all dependencies. To learn a detailed guide on running the project locally, checkout our guide on [how to run novu in local machine](https://docs.novu.co/community/run-in-local-machine). @@ -53,7 +53,7 @@ To ensure consistency throughout the source code, please keep these rules in min ## Need help? Questions and suggestions -Questions, suggestions, and thoughts are most welcome. Feel free to open a [GitHub Issue](https://github.com/novuhq/novu/issues/new/choose). We can also be reached in our [Discord Server](https://discord.novu.co). +Questions, suggestions, and thoughts are most welcome. Feel free to open a [GitHub Issue](https://github.com/novuhq/novu/issues/new/choose). We can also be reached on our [Discord Server](https://discord.novu.co). ## Ways to contribute diff --git a/README.md b/README.md index 75b0513ae83..bfa20cefb18 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ In addition to this repository, here are the other Novu repositories you can con - [Novu Go SDK](https://github.com/novuhq/go-novu/issues) - [Novu Java SDK](https://github.com/novuhq/novu-java/issues) - [Novu Kotlin SDK](https://github.com/novuhq/novu-kotlin/issues) +- [Novu Elixir SDK](https://github.com/novuhq/novu-elixir/issues) +- [Novu Rust SDK](https://github.com/novuhq/novu-rust/issues) Your contribution, no matter its size, holds immense value. We eagerly await to see the impact you'll make in our community! 🚀 @@ -202,10 +204,10 @@ Novu provides a single API to manage providers across multiple channels with a s #### 👇 Chat -- [x] Slack -- [x] Discord -- [x] MS Teams -- [x] Mattermost +- [x] [Slack](https://github.com/novuhq/novu/tree/main/providers/slack) +- [x] [Discord](https://github.com/novuhq/novu/tree/main/providers/discord) +- [x] [MS Teams](https://github.com/novuhq/novu/tree/main/providers/ms-teams) +- [x] [Mattermost](https://github.com/novuhq/novu/tree/main/providers/mattermost) #### 📱 In-App diff --git a/apps/api/e2e/compile-email-template.e2e.ts b/apps/api/e2e/compile-email-template.e2e.ts index aafb0b90d67..e9d54c4b40d 100644 --- a/apps/api/e2e/compile-email-template.e2e.ts +++ b/apps/api/e2e/compile-email-template.e2e.ts @@ -169,8 +169,8 @@ describe('Compile E-mail Template', function () { expect(senderName).to.equal(senderNameTest); }); - describe('Backwards compatability', function () { - it('should compile e-mail template for custom html without layouts attached for backwards compatability', async function () { + describe('Backwards compatibility', function () { + it('should compile e-mail template for custom html without layouts attached for backwards compatibility', async function () { const { html, subject } = await useCase.execute( CompileEmailTemplateCommand.create({ organizationId: session.organization._id, diff --git a/apps/api/migrations/subscriber-preferences-level/subscriber-preferences-level.migration.ts b/apps/api/migrations/subscriber-preferences-level/subscriber-preferences-level.migration.ts new file mode 100644 index 00000000000..76c5fdc4761 --- /dev/null +++ b/apps/api/migrations/subscriber-preferences-level/subscriber-preferences-level.migration.ts @@ -0,0 +1,33 @@ +import '../../src/config'; + +import { NestFactory } from '@nestjs/core'; +import { PreferenceLevelEnum, SubscriberPreferenceRepository } from '@novu/dal'; + +import { AppModule } from '../../src/app.module'; + +export async function addLevelPropertyToSubscriberPreferences() { + // eslint-disable-next-line no-console + console.log('start migration - add level property to subscriber preferences'); + const app = await NestFactory.create(AppModule, { + logger: false, + }); + + const subscriberPreferenceRepository = app.get(SubscriberPreferenceRepository); + // eslint-disable-next-line no-console + console.log('add level: PreferenceLevelEnum.TEMPLATE to all subscriber preferences without level property'); + + await subscriberPreferenceRepository._model.collection.updateMany( + { level: { $exists: false }, _templateId: { $exists: true } }, + { + $set: { level: PreferenceLevelEnum.TEMPLATE }, + } + ); + + // eslint-disable-next-line no-console + console.log('end migration- add level property to subscriber preferences'); + + app.close(); + process.exit(0); +} + +addLevelPropertyToSubscriberPreferences(); diff --git a/apps/api/package.json b/apps/api/package.json index 2059dbabbac..04b50c466e5 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -1,6 +1,6 @@ { "name": "@novu/api", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "description", "author": "", "private": "true", @@ -38,12 +38,12 @@ "@nestjs/platform-express": "^10.2.2", "@nestjs/swagger": "^7.1.8", "@nestjs/terminus": "^10.0.1", - "@novu/application-generic": "^0.19.0", - "@novu/dal": "^0.19.0", - "@novu/node": "^0.19.0", - "@novu/shared": "^0.19.0", - "@novu/stateless": "^0.19.0", - "@novu/testing": "^0.19.0", + "@novu/application-generic": "^0.20.0-alpha.0", + "@novu/dal": "^0.20.0-alpha.0", + "@novu/node": "^0.20.0-alpha.0", + "@novu/shared": "^0.20.0-alpha.0", + "@novu/stateless": "^0.20.0-alpha.0", + "@novu/testing": "^0.20.0-alpha.0", "@sendgrid/mail": "^7.6.0", "@sentry/hub": "^7.40.0", "@sentry/node": "^7.40.0", @@ -113,7 +113,9 @@ "@novu/ee-auth": "^0.19.0" }, "nx": { - "implicitDependencies": ["@novu/ee-auth"] + "implicitDependencies": [ + "@novu/ee-auth" + ] }, "lint-staged": { "*.{js,jsx,ts,tsx}": [ diff --git a/apps/api/src/app/events/usecases/parse-event-request/parse-event-request.e2e.ts b/apps/api/src/app/events/usecases/parse-event-request/parse-event-request.e2e.ts new file mode 100644 index 00000000000..cc38c8cc882 --- /dev/null +++ b/apps/api/src/app/events/usecases/parse-event-request/parse-event-request.e2e.ts @@ -0,0 +1,71 @@ +import { Test } from '@nestjs/testing'; +import { expect } from 'chai'; +import { v4 as uuid } from 'uuid'; + +import { SubscribersService, UserSession } from '@novu/testing'; +import { SubscriberRepository, NotificationTemplateEntity } from '@novu/dal'; +import { TriggerRecipients } from '@novu/shared'; + +import { SharedModule } from '../../../shared/shared.module'; +import { EventsModule } from '../../events.module'; +import { ParseEventRequestCommand } from './parse-event-request.command'; +import { ParseEventRequest } from './parse-event-request.usecase'; + +describe('ParseEventRequest Usecase', () => { + let session: UserSession; + let subscribersService: SubscribersService; + let parseEventRequestUsecase: ParseEventRequest; + let template: NotificationTemplateEntity; + + beforeEach(async () => { + const moduleRef = await Test.createTestingModule({ + imports: [SharedModule, EventsModule], + providers: [], + }).compile(); + + session = new UserSession(); + await session.initialize(); + + template = await session.createTemplate(); + parseEventRequestUsecase = moduleRef.get(ParseEventRequest); + subscribersService = new SubscribersService(session.organization._id, session.environment._id); + }); + + it('should throw exception when subscriber id sent as array', async () => { + const transactionId = uuid(); + const subscriberId = [SubscriberRepository.createObjectId()]; + + const command = buildCommand( + session, + transactionId, + [{ subscriberId: subscriberId } as unknown as string], + template.triggers[0].identifier + ); + + try { + await parseEventRequestUsecase.execute(command); + } catch (error) { + expect(error.message).to.be.eql( + 'subscriberId under property to is type array, which is not allowed please make sure all subscribers ids are strings' + ); + } + }); +}); + +const buildCommand = ( + session: UserSession, + transactionId: string, + to: TriggerRecipients, + identifier: string +): ParseEventRequestCommand => { + return ParseEventRequestCommand.create({ + organizationId: session.organization._id, + environmentId: session.environment._id, + to, + transactionId, + userId: session.user._id, + identifier, + payload: {}, + overrides: {}, + }); +}; diff --git a/apps/api/src/app/events/usecases/parse-event-request/parse-event-request.usecase.ts b/apps/api/src/app/events/usecases/parse-event-request/parse-event-request.usecase.ts index c0546cd5240..471e36388a0 100644 --- a/apps/api/src/app/events/usecases/parse-event-request/parse-event-request.usecase.ts +++ b/apps/api/src/app/events/usecases/parse-event-request/parse-event-request.usecase.ts @@ -164,7 +164,7 @@ export class ParseEventRequest { identifier, }); if (!found) { - throw new ApiException(`Tenant with identifier ${identifier} cound not be found`); + throw new ApiException(`Tenant with identifier ${identifier} could not be found`); } } @@ -173,6 +173,12 @@ export class ParseEventRequest { for (const subscriber of to) { const subscriberIdExists = typeof subscriber === 'string' ? subscriber : subscriber.subscriberId; + if (Array.isArray(subscriberIdExists)) { + throw new ApiException( + 'subscriberId under property to is type array, which is not allowed please make sure all subscribers ids are strings' + ); + } + if (!subscriberIdExists) { throw new ApiException( 'subscriberId under property to is not configured, please make sure all subscribers contains subscriberId property' diff --git a/apps/api/src/app/events/usecases/verify-payload/verify-payload.spec.ts b/apps/api/src/app/events/usecases/verify-payload/verify-payload.spec.ts index 579c1dc99a1..79173b5303a 100644 --- a/apps/api/src/app/events/usecases/verify-payload/verify-payload.spec.ts +++ b/apps/api/src/app/events/usecases/verify-payload/verify-payload.spec.ts @@ -9,7 +9,7 @@ import { ApiException } from '../../../shared/exceptions/api.exception'; describe('Verify Payload Usecase', function () { const verifyPayload = new VerifyPayload(); - it('should handle empty and undefiend strings', function () { + it('should handle empty and undefined strings', function () { const template = createTemplate([ { name: 'user.firstName', type: TemplateVariableTypeEnum.STRING, defaultValue: 'John', required: false }, { name: 'user.hej', type: TemplateVariableTypeEnum.STRING, required: false, defaultValue: '' }, diff --git a/apps/api/src/app/inbound-parse/e2e/inbound-email-parse.e2e.ts b/apps/api/src/app/inbound-parse/e2e/inbound-email-parse.e2e.ts index 5bc3218bc44..ef8f8a974d2 100644 --- a/apps/api/src/app/inbound-parse/e2e/inbound-email-parse.e2e.ts +++ b/apps/api/src/app/inbound-parse/e2e/inbound-email-parse.e2e.ts @@ -75,39 +75,38 @@ describe('Should handle the new arrived mail', () => { }); it('should not send webhook request with missing transactionId', async () => { - const message = await triggerEmail(); - - const mail = getMailData(message, false); - - const getStub = sandbox.stub(axios, 'post').resolves(); - - await inboundEmailParseUsecase.execute(InboundEmailParseCommand.create(mail)); - - sinon.assert.notCalled(getStub); + try { + const message = await triggerEmail(); + const mail = getMailData(message, false); + + await inboundEmailParseUsecase.execute(InboundEmailParseCommand.create(mail)); + } catch (e) { + expect(e.message).to.contains('Missing transactionId on address'); + } }); it('should not send webhook request with when domain white list', async () => { - const message = await triggerEmail(true, false); + try { + const message = await triggerEmail(true, false); - const mail = getMailData(message); + const mail = getMailData(message); - const getStub = sandbox.stub(axios, 'post').resolves(); - - await inboundEmailParseUsecase.execute(InboundEmailParseCommand.create(mail)); - - sinon.assert.notCalled(getStub); + await inboundEmailParseUsecase.execute(InboundEmailParseCommand.create(mail)); + } catch (e) { + expect(e.message).to.equal('Domain is not in environment white list'); + } }); it('should not send webhook request when missing replay callback url', async () => { - const message = await triggerEmail(true, true, true, false); - - const mail = getMailData(message); - - const getStub = sandbox.stub(axios, 'post').resolves(); + try { + const message = await triggerEmail(true, true, true, false); - await inboundEmailParseUsecase.execute(InboundEmailParseCommand.create(mail)); + const mail = getMailData(message); - sinon.assert.notCalled(getStub); + await inboundEmailParseUsecase.execute(InboundEmailParseCommand.create(mail)); + } catch (e) { + expect(e.message).to.contains('Missing parse webhook on template'); + } }); async function triggerEmail( diff --git a/apps/api/src/app/inbound-parse/services/inbound-parse.queue.service.ts b/apps/api/src/app/inbound-parse/services/inbound-parse.queue.service.ts index 2848eafbe72..dc4b3cf24ca 100644 --- a/apps/api/src/app/inbound-parse/services/inbound-parse.queue.service.ts +++ b/apps/api/src/app/inbound-parse/services/inbound-parse.queue.service.ts @@ -7,11 +7,13 @@ import { WorkerOptions, } from '@novu/application-generic'; import { JobTopicNameEnum } from '@novu/shared'; -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { InboundEmailParse } from '../usecases/inbound-email-parse/inbound-email-parse.usecase'; import { InboundEmailParseCommand } from '../usecases/inbound-email-parse/inbound-email-parse.command'; +const LOG_CONTEXT = 'InboundParseQueueService'; + @Injectable() export class InboundParseQueueService { public readonly queue: Queue; @@ -35,6 +37,7 @@ export class InboundParseQueueService { public getWorkerProcessor() { return async ({ data }: { data: InboundEmailParseCommand }) => { + Logger.verbose({ data }, 'Processing the inbound parsed email', LOG_CONTEXT); await this.emailParseUsecase.execute(InboundEmailParseCommand.create({ ...data })); }; } diff --git a/apps/api/src/app/inbound-parse/usecases/inbound-email-parse/inbound-email-parse.usecase.ts b/apps/api/src/app/inbound-parse/usecases/inbound-email-parse/inbound-email-parse.usecase.ts index c0545391f66..682dc6abbd0 100644 --- a/apps/api/src/app/inbound-parse/usecases/inbound-email-parse/inbound-email-parse.usecase.ts +++ b/apps/api/src/app/inbound-parse/usecases/inbound-email-parse/inbound-email-parse.usecase.ts @@ -1,4 +1,4 @@ -import { Injectable, Logger } from '@nestjs/common'; +import { BadRequestException, Injectable, Logger } from '@nestjs/common'; import { InboundEmailParseCommand } from './inbound-email-parse.command'; import { JobEntity, @@ -12,6 +12,8 @@ import axios from 'axios'; import { createHash } from '../../../shared/helpers/hmac.service'; import { CompileTemplate, CompileTemplateCommand } from '@novu/application-generic'; +const LOG_CONTEXT = 'InboundEmailParse'; + @Injectable() export class InboundEmailParse { constructor( @@ -21,55 +23,38 @@ export class InboundEmailParse { ) {} async execute(command: InboundEmailParseCommand) { - const { toDomain, toTransactionId, toEnvironmentId } = this.splitTo(command.to[0].address); - - Logger.debug('toDomain in InboundEmailParse is: ' + toDomain); - Logger.debug('toTransactionId in InboundEmailParse is: ' + toTransactionId); - - if (!toTransactionId) { - Logger.warn(`missing transactionId on address ${command.to[0].address}`); - - return; - } + const { domain, transactionId, environmentId } = this.splitTo(command.to[0].address); - Logger.debug('toEnvironmentId in InboundEmailParse is: ' + toEnvironmentId); - - if (!toEnvironmentId) { - Logger.warn(`missing environmentId on address ${command.to[0].address}`); - - return; - } + Logger.debug({ domain, transactionId, environmentId }, `Received new email to parse`, LOG_CONTEXT); const { template, notification, subscriber, environment, job, message } = await this.getEntities( - toTransactionId, - toEnvironmentId + transactionId, + environmentId ); - if (toDomain !== environment?.dns?.inboundParseDomain) { - Logger.warn('to domain is not in environment white list'); - - return; + if (domain !== environment?.dns?.inboundParseDomain) { + this.throwMiddleware('Domain is not in environment white list'); } const currentParseWebhook = template.steps.find((step) => step?._id?.toString() === job?.step?._id)?.replyCallback ?.url; if (!currentParseWebhook) { - Logger.warn(`missing parse webhook on template ${template._id} job ${job._id} transactionId ${toTransactionId}.`); - - return; + this.throwMiddleware( + `Missing parse webhook on template ${template._id} job ${job._id} transactionId ${transactionId}.` + ); } const compiledDomain = await this.compileTemplate.execute( CompileTemplateCommand.create({ - template: currentParseWebhook, + template: currentParseWebhook as string, data: job.payload, }) ); const userPayload: IUserWebhookPayload = { hmac: createHash(environment?.apiKeys[0]?.key, subscriber.subscriberId), - transactionId: toTransactionId, + transactionId: transactionId, payload: job.payload, templateIdentifier: job.identifier, template, @@ -84,11 +69,29 @@ export class InboundEmailParse { private splitTo(address: string) { const userNameDelimiter = '-nv-e='; - const [toUser, toDomain] = address.split('@'); - const toMetaIds = toUser.split('+')[1]; - const [toTransactionId, toEnvironmentId] = toMetaIds.split(userNameDelimiter); + const [user, domain] = address.split('@'); + const toMetaIds = user.split('+')[1]; + const [transactionId, environmentId] = toMetaIds.split(userNameDelimiter); + + if (!transactionId) { + this.throwMiddleware(`Missing transactionId on address ${address}`); + } + + if (!domain) { + this.throwMiddleware(`Missing domain on address ${address}`); + } + + if (!environmentId) { + this.throwMiddleware(`Missing environmentId on address ${address}`); + } + + return { domain, transactionId, environmentId }; + } + + private throwMiddleware(error: string) { + Logger.error(error, LOG_CONTEXT); - return { toDomain, toTransactionId, toEnvironmentId }; + throw new BadRequestException(error); } private async getEntities(transactionId: string, environmentId: string) { diff --git a/apps/api/src/app/shared/helpers/content.service.spec.ts b/apps/api/src/app/shared/helpers/content.service.spec.ts index 1dd0833410d..70f80455447 100644 --- a/apps/api/src/app/shared/helpers/content.service.spec.ts +++ b/apps/api/src/app/shared/helpers/content.service.spec.ts @@ -335,4 +335,99 @@ describe('ContentService', function () { expect(extractVariables[0].name).to.include('lastName'); }); }); + + describe('extractStepVariables', () => { + it('should not fail if no filters available', () => { + const contentService = new ContentService(); + const messages = [ + { + template: { + type: StepTypeEnum.EMAIL, + subject: 'Test {{subscriber.firstName}}', + content: [ + { + content: 'Test of {{subscriber.firstName}} {{lastName}}', + type: 'text', + }, + ], + }, + }, + ] as INotificationTemplateStep[]; + const variables = contentService.extractStepVariables(messages); + + expect(variables.length).to.equal(0); + }); + + it('should not fail if filters are set as non array', () => { + const contentService = new ContentService(); + const messages = [ + { + template: { + type: StepTypeEnum.EMAIL, + subject: 'Test {{subscriber.firstName}}', + content: [ + { + content: 'Test of {{subscriber.firstName}} {{lastName}}', + type: 'text', + }, + ], + }, + filters: {}, + }, + ] as INotificationTemplateStep[]; + const variables = contentService.extractStepVariables(messages); + + expect(variables.length).to.equal(0); + }); + + it('should not fail if filters are an empty array', () => { + const contentService = new ContentService(); + const messages = [ + { + template: { + type: StepTypeEnum.EMAIL, + subject: 'Test {{subscriber.firstName}}', + content: [ + { + content: 'Test of {{subscriber.firstName}} {{lastName}}', + type: 'text', + }, + ], + }, + filters: [], + }, + ] as INotificationTemplateStep[]; + const variables = contentService.extractStepVariables(messages); + + expect(variables.length).to.equal(0); + }); + + it('should not fail if filters have some wrong settings like missing children in filters', () => { + const contentService = new ContentService(); + const messages = [ + { + template: { + type: StepTypeEnum.EMAIL, + subject: 'Test {{subscriber.firstName}}', + content: [ + { + content: 'Test of {{subscriber.firstName}} {{lastName}}', + type: 'text', + }, + ], + }, + filters: [ + { + isNegated: false, + type: 'GROUP', + value: 'AND', + }, + ], + }, + ] as INotificationTemplateStep[]; + const variables = contentService.extractStepVariables(messages); + + expect(variables.length).to.equal(0); + }); + }); }); diff --git a/apps/api/src/app/shared/helpers/content.service.ts b/apps/api/src/app/shared/helpers/content.service.ts index 6dfcff38f89..4e5c14d9730 100644 --- a/apps/api/src/app/shared/helpers/content.service.ts +++ b/apps/api/src/app/shared/helpers/content.service.ts @@ -73,17 +73,19 @@ export class ContentService { for (const message of messages) { if (message.filters) { - const filterVariables = message.filters.flatMap((filter) => - filter.children - .filter((item) => item.on === FilterPartTypeEnum.PAYLOAD) - .map((item: IFieldFilterPart) => { - return { - name: item.field, - type: TemplateVariableTypeEnum.STRING, - }; - }) - ); - variables.push(...filterVariables); + const filters = Array.isArray(message.filters) ? message.filters : []; + const filteredVariables = filters.flatMap((filter) => { + const filteredChildren = filter.children?.filter((item) => item.on === FilterPartTypeEnum.PAYLOAD) || []; + const mappedChildren = filteredChildren.map((item: IFieldFilterPart) => { + return { + name: item.field, + type: TemplateVariableTypeEnum.STRING, + }; + }); + + return mappedChildren; + }); + variables.push(...filteredVariables); } if (message.metadata?.type === DelayTypeEnum.SCHEDULED && message.metadata.delayPath) { diff --git a/apps/api/src/app/subscribers/dtos/get-subscriber-preferences-response.dto.ts b/apps/api/src/app/subscribers/dtos/get-subscriber-preferences-response.dto.ts new file mode 100644 index 00000000000..52ea48a0af5 --- /dev/null +++ b/apps/api/src/app/subscribers/dtos/get-subscriber-preferences-response.dto.ts @@ -0,0 +1,71 @@ +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { ChannelTypeEnum, PreferenceOverrideSourceEnum } from '@novu/shared'; +import { PreferenceChannels } from '../../shared/dtos/preference-channels'; + +class TemplateResponse { + @ApiProperty({ + description: 'Unique identifier of the workflow', + type: String, + }) + _id: string; + + @ApiProperty({ + description: 'Name of the workflow', + type: String, + }) + name: string; + + @ApiProperty({ + description: + 'Critical templates will always be delivered to the end user and should be hidden from the subscriber preferences screen', + type: Boolean, + }) + critical: boolean; +} + +class Overrides { + @ApiProperty({ + type: ChannelTypeEnum, + description: 'The channel type which is overridden', + }) + channel: ChannelTypeEnum; + @ApiProperty({ + type: PreferenceOverrideSourceEnum, + description: 'The source of overrides', + }) + source: PreferenceOverrideSourceEnum; +} + +class Preference { + @ApiProperty({ + description: 'Sets if the workflow is fully enabled for all channels or not for the subscriber.', + type: Boolean, + }) + enabled: boolean; + + @ApiProperty({ + type: PreferenceChannels, + description: 'Subscriber preferences for the different channels regarding this workflow', + }) + channels: PreferenceChannels; + + @ApiPropertyOptional({ + type: Overrides, + description: 'Overrides for subscriber preferences for the different channels regarding this workflow', + }) + overrides?: Overrides; +} + +export class GetSubscriberPreferencesResponseDto { + @ApiPropertyOptional({ + type: TemplateResponse, + description: 'The workflow information and if it is critical or not', + }) + template?: TemplateResponse; + + @ApiProperty({ + type: Preference, + description: 'The preferences of the subscriber regarding the related workflow', + }) + preference: Preference; +} diff --git a/apps/api/src/app/subscribers/dtos/index.ts b/apps/api/src/app/subscribers/dtos/index.ts index 0593dafc420..85bbe277b7d 100644 --- a/apps/api/src/app/subscribers/dtos/index.ts +++ b/apps/api/src/app/subscribers/dtos/index.ts @@ -4,3 +4,5 @@ export * from './subscriber-response.dto'; export * from './subscribers-response.dto'; export * from './update-subscriber-channel-request.dto'; export * from './update-subscriber-request.dto'; +export * from './get-subscriber-preferences-response.dto'; +export * from './update-subscriber-global-preferences-request.dto'; diff --git a/apps/api/src/app/subscribers/dtos/update-subscriber-global-preferences-request.dto.ts b/apps/api/src/app/subscribers/dtos/update-subscriber-global-preferences-request.dto.ts new file mode 100644 index 00000000000..0572b978e0f --- /dev/null +++ b/apps/api/src/app/subscribers/dtos/update-subscriber-global-preferences-request.dto.ts @@ -0,0 +1,23 @@ +import { ApiPropertyOptional } from '@nestjs/swagger'; +import { IsBoolean, IsOptional, ValidateNested } from 'class-validator'; +import { Type } from 'class-transformer'; +import { ChannelPreference } from '../../shared/dtos/channel-preference'; + +export class UpdateSubscriberGlobalPreferencesRequestDto { + @ApiPropertyOptional({ + description: 'Enable or disable the subscriber global preferences.', + type: Boolean, + }) + @IsBoolean() + @IsOptional() + enabled?: boolean; + + @ApiPropertyOptional({ + type: [ChannelPreference], + description: 'The subscriber global preferences for every ChannelTypeEnum.', + }) + @IsOptional() + @ValidateNested() + @Type(() => ChannelPreference) + preferences?: ChannelPreference[]; +} diff --git a/apps/api/src/app/subscribers/e2e/helpers/index.ts b/apps/api/src/app/subscribers/e2e/helpers/index.ts index 4f7ea77b384..0ab317653f7 100644 --- a/apps/api/src/app/subscribers/e2e/helpers/index.ts +++ b/apps/api/src/app/subscribers/e2e/helpers/index.ts @@ -4,6 +4,7 @@ import axios from 'axios'; import { UpdateSubscriberOnlineFlagRequestDto } from '../../dtos/update-subscriber-online-flag-request.dto'; import { UpdateSubscriberPreferenceRequestDto } from '../../../widgets/dtos/update-subscriber-preference-request.dto'; +import { UpdateSubscriberGlobalPreferencesRequestDto } from '../../dtos/update-subscriber-global-preferences-request.dto'; const axiosInstance = axios.create(); @@ -65,3 +66,11 @@ export async function updatePreference( } ); } + +export async function updateGlobalPreferences(data: UpdateSubscriberGlobalPreferencesRequestDto, session: UserSession) { + return await axiosInstance.patch(`${session.serverUrl}/v1/subscribers/${session.subscriberId}/preferences`, data, { + headers: { + authorization: `ApiKey ${session.apiKey}`, + }, + }); +} diff --git a/apps/api/src/app/subscribers/e2e/update-global-preference.e2e.ts b/apps/api/src/app/subscribers/e2e/update-global-preference.e2e.ts new file mode 100644 index 00000000000..2da13942648 --- /dev/null +++ b/apps/api/src/app/subscribers/e2e/update-global-preference.e2e.ts @@ -0,0 +1,115 @@ +import { ChannelTypeEnum } from '@novu/shared'; +import { UserSession } from '@novu/testing'; +import { expect } from 'chai'; + +import { updateGlobalPreferences } from './helpers'; + +describe('Update Subscribers global preferences - /subscribers/:subscriberId/preferences (PATCH)', function () { + let session: UserSession; + + beforeEach(async () => { + session = new UserSession(); + await session.initialize(); + }); + + it('should validate the payload', async function () { + const badPayload = { + enabled: true, + preferences: false, + }; + + try { + const firstResponse = await updateGlobalPreferences(badPayload as any, session); + expect(firstResponse).to.not.be.ok; + } catch (error) { + expect(error.toJSON()).to.have.include({ + status: 400, + name: 'AxiosError', + message: 'Request failed with status code 400', + }); + } + + const yetAnotherBadPayload = { + enabled: 'hello', + preferences: [{ type: ChannelTypeEnum.EMAIL, enabled: true }], + }; + + try { + const secondResponse = await updateGlobalPreferences(yetAnotherBadPayload as any, session); + expect(secondResponse).to.not.be.ok; + } catch (error) { + expect(error.toJSON()).to.have.include({ + status: 400, + name: 'AxiosError', + message: 'Request failed with status code 400', + }); + } + }); + + it('should update user global preferences', async function () { + const payload = { + enabled: true, + preferences: [{ type: ChannelTypeEnum.EMAIL, enabled: true }], + }; + + const response = await updateGlobalPreferences(payload, session); + + expect(response.data.data.preference.enabled).to.eql(true); + expect(response.data.data.preference.channels).to.not.eql({ + [ChannelTypeEnum.IN_APP]: true, + }); + expect(response.data.data.preference.channels).to.eql({ + [ChannelTypeEnum.EMAIL]: true, + [ChannelTypeEnum.SMS]: true, + [ChannelTypeEnum.CHAT]: true, + [ChannelTypeEnum.PUSH]: true, + [ChannelTypeEnum.IN_APP]: true, + }); + }); + + it('should update user global preferences for multiple channels', async function () { + const payload = { + enabled: true, + preferences: [ + { type: ChannelTypeEnum.PUSH, enabled: true }, + { type: ChannelTypeEnum.IN_APP, enabled: false }, + { type: ChannelTypeEnum.SMS, enabled: true }, + ], + }; + + const response = await updateGlobalPreferences(payload, session); + + expect(response.data.data.preference.enabled).to.eql(true); + expect(response.data.data.preference.channels).to.eql({ + [ChannelTypeEnum.PUSH]: true, + [ChannelTypeEnum.IN_APP]: false, + [ChannelTypeEnum.SMS]: true, + [ChannelTypeEnum.EMAIL]: true, + [ChannelTypeEnum.CHAT]: true, + }); + }); + + it('should update user global preference and disable the flag for the future channels update', async function () { + const disablePreferenceData = { + enabled: false, + }; + + const response = await updateGlobalPreferences(disablePreferenceData, session); + + expect(response.data.data.preference.enabled).to.eql(false); + + const preferenceChannel = { + preferences: [{ type: ChannelTypeEnum.EMAIL, enabled: true }], + }; + + const res = await updateGlobalPreferences(preferenceChannel, session); + + expect(res.data.data.preference.channels).to.eql({ + [ChannelTypeEnum.EMAIL]: true, + [ChannelTypeEnum.SMS]: true, + [ChannelTypeEnum.CHAT]: true, + [ChannelTypeEnum.PUSH]: true, + [ChannelTypeEnum.IN_APP]: true, + }); + }); +}); diff --git a/apps/api/src/app/subscribers/params/get-subscriber-preferences-by-level.params.ts b/apps/api/src/app/subscribers/params/get-subscriber-preferences-by-level.params.ts new file mode 100644 index 00000000000..18196b59147 --- /dev/null +++ b/apps/api/src/app/subscribers/params/get-subscriber-preferences-by-level.params.ts @@ -0,0 +1,10 @@ +import { IsEnum, IsString } from 'class-validator'; +import { PreferenceLevelEnum } from '@novu/dal'; + +export class GetSubscriberPreferencesByLevelParams { + @IsEnum(PreferenceLevelEnum) + level: PreferenceLevelEnum; + + @IsString() + subscriberId: string; +} diff --git a/apps/api/src/app/subscribers/params/index.ts b/apps/api/src/app/subscribers/params/index.ts new file mode 100644 index 00000000000..cdca2379644 --- /dev/null +++ b/apps/api/src/app/subscribers/params/index.ts @@ -0,0 +1 @@ +export * from './get-subscriber-preferences-by-level.params'; diff --git a/apps/api/src/app/subscribers/subscribers.controller.ts b/apps/api/src/app/subscribers/subscribers.controller.ts index 85f0b987bb1..efc5eb97242 100644 --- a/apps/api/src/app/subscribers/subscribers.controller.ts +++ b/apps/api/src/app/subscribers/subscribers.controller.ts @@ -21,9 +21,9 @@ import { UpdateSubscriber, UpdateSubscriberCommand, } from '@novu/application-generic'; -import { ApiOperation, ApiTags, ApiNoContentResponse } from '@nestjs/swagger'; +import { ApiOperation, ApiTags, ApiNoContentResponse, ApiParam } from '@nestjs/swagger'; import { ButtonTypeEnum, ChatProviderIdEnum, IJwtPayload } from '@novu/shared'; -import { MessageEntity } from '@novu/dal'; +import { MessageEntity, PreferenceLevelEnum } from '@novu/dal'; import { RemoveSubscriber, RemoveSubscriberCommand } from './usecases/remove-subscriber'; import { JwtAuthGuard } from '../auth/framework/auth.guard'; @@ -33,15 +33,17 @@ import { BulkSubscriberCreateDto, CreateSubscriberRequestDto, DeleteSubscriberResponseDto, + GetSubscriberPreferencesResponseDto, SubscriberResponseDto, UpdateSubscriberChannelRequestDto, + UpdateSubscriberGlobalPreferencesRequestDto, UpdateSubscriberRequestDto, } from './dtos'; import { UpdateSubscriberChannel, UpdateSubscriberChannelCommand } from './usecases/update-subscriber-channel'; import { GetSubscribers, GetSubscribersCommand } from './usecases/get-subscribers'; import { GetSubscriber, GetSubscriberCommand } from './usecases/get-subscriber'; -import { GetPreferencesCommand } from './usecases/get-preferences/get-preferences.command'; -import { GetPreferences } from './usecases/get-preferences/get-preferences.usecase'; +import { GetPreferencesByLevelCommand } from './usecases/get-preferences-by-level/get-preferences-by-level.command'; +import { GetPreferencesByLevel } from './usecases/get-preferences-by-level/get-preferences-by-level.usecase'; import { UpdatePreference } from './usecases/update-preference/update-preference.usecase'; import { UpdateSubscriberPreferenceCommand } from './usecases/update-subscriber-preference'; import { UpdateSubscriberPreferenceResponseDto } from '../widgets/dtos/update-subscriber-preference-response.dto'; @@ -83,6 +85,11 @@ import { MarkAllMessagesAs } from '../widgets/usecases/mark-all-messages-as/mark import { MarkAllMessageAsRequestDto } from './dtos/mark-all-messages-as-request.dto'; import { BulkCreateSubscribers } from './usecases/bulk-create-subscribers/bulk-create-subscribers.usecase'; import { BulkCreateSubscribersCommand } from './usecases/bulk-create-subscribers'; +import { + UpdateSubscriberGlobalPreferences, + UpdateSubscriberGlobalPreferencesCommand, +} from './usecases/update-subscriber-global-preferences'; +import { GetSubscriberPreferencesByLevelParams } from './params'; @Controller('/subscribers') @ApiTags('Subscribers') @@ -95,8 +102,9 @@ export class SubscribersController { private removeSubscriberUsecase: RemoveSubscriber, private getSubscriberUseCase: GetSubscriber, private getSubscribersUsecase: GetSubscribers, - private getPreferenceUsecase: GetPreferences, + private getPreferenceUsecase: GetPreferencesByLevel, private updatePreferenceUsecase: UpdatePreference, + private updateGlobalPreferenceUsecase: UpdateSubscriberGlobalPreferences, private getNotificationsFeedUsecase: GetNotificationsFeed, private getFeedCountUsecase: GetFeedCount, private markMessageAsUsecase: MarkMessageAs, @@ -336,10 +344,34 @@ export class SubscribersController { @UserSession() user: IJwtPayload, @Param('subscriberId') subscriberId: string ): Promise { - const command = GetPreferencesCommand.create({ + const command = GetPreferencesByLevelCommand.create({ + organizationId: user.organizationId, + subscriberId: subscriberId, + environmentId: user.environmentId, + level: PreferenceLevelEnum.TEMPLATE, + }); + + return (await this.getPreferenceUsecase.execute(command)) as UpdateSubscriberPreferenceResponseDto[]; + } + + @Get('/:subscriberId/preferences/:level') + @ExternalApiAccessible() + @UseGuards(JwtAuthGuard) + @ApiResponse(GetSubscriberPreferencesResponseDto, 200, true) + @ApiOperation({ + summary: 'Get subscriber preferences by level', + }) + @ApiParam({ name: 'subscriberId', type: String, required: true }) + @ApiParam({ name: 'level', type: String, required: true }) + async getSubscriberPreferenceByLevel( + @UserSession() user: IJwtPayload, + @Param() { level, subscriberId }: GetSubscriberPreferencesByLevelParams + ): Promise { + const command = GetPreferencesByLevelCommand.create({ organizationId: user.organizationId, subscriberId: subscriberId, environmentId: user.environmentId, + level: level, }); return await this.getPreferenceUsecase.execute(command); @@ -370,6 +402,29 @@ export class SubscribersController { return await this.updatePreferenceUsecase.execute(command); } + @Patch('/:subscriberId/preferences') + @ExternalApiAccessible() + @UseGuards(JwtAuthGuard) + @ApiResponse(UpdateSubscriberPreferenceResponseDto) + @ApiOperation({ + summary: 'Update subscriber global preferences', + }) + async updateSubscriberGlobalPreferences( + @UserSession() user: IJwtPayload, + @Param('subscriberId') subscriberId: string, + @Body() body: UpdateSubscriberGlobalPreferencesRequestDto + ) { + const command = UpdateSubscriberGlobalPreferencesCommand.create({ + organizationId: user.organizationId, + subscriberId: subscriberId, + environmentId: user.environmentId, + enabled: body.enabled, + preferences: body.preferences, + }); + + return await this.updateGlobalPreferenceUsecase.execute(command); + } + @ExternalApiAccessible() @UseGuards(JwtAuthGuard) @Get('/:subscriberId/notifications/feed') diff --git a/apps/api/src/app/subscribers/usecases/get-preferences-by-level/get-preferences-by-level.command.ts b/apps/api/src/app/subscribers/usecases/get-preferences-by-level/get-preferences-by-level.command.ts new file mode 100644 index 00000000000..f1956f68bff --- /dev/null +++ b/apps/api/src/app/subscribers/usecases/get-preferences-by-level/get-preferences-by-level.command.ts @@ -0,0 +1,13 @@ +import { IsDefined, IsEnum, IsString } from 'class-validator'; +import { PreferenceLevelEnum } from '@novu/dal'; +import { EnvironmentCommand } from '../../../shared/commands/project.command'; + +export class GetPreferencesByLevelCommand extends EnvironmentCommand { + @IsString() + @IsDefined() + subscriberId: string; + + @IsEnum(PreferenceLevelEnum) + @IsDefined() + level: PreferenceLevelEnum; +} diff --git a/apps/api/src/app/subscribers/usecases/get-preferences-by-level/get-preferences-by-level.usecase.ts b/apps/api/src/app/subscribers/usecases/get-preferences-by-level/get-preferences-by-level.usecase.ts new file mode 100644 index 00000000000..47358c4e172 --- /dev/null +++ b/apps/api/src/app/subscribers/usecases/get-preferences-by-level/get-preferences-by-level.usecase.ts @@ -0,0 +1,39 @@ +import { Injectable } from '@nestjs/common'; +import { + GetSubscriberGlobalPreference, + GetSubscriberGlobalPreferenceCommand, + GetSubscriberPreference, + GetSubscriberPreferenceCommand, +} from '@novu/application-generic'; +import { PreferenceLevelEnum } from '@novu/dal'; + +import { GetPreferencesByLevelCommand } from './get-preferences-by-level.command'; + +@Injectable() +export class GetPreferencesByLevel { + constructor( + private getSubscriberPreferenceUsecase: GetSubscriberPreference, + private getSubscriberGlobalPreference: GetSubscriberGlobalPreference + ) {} + + async execute(command: GetPreferencesByLevelCommand) { + if (command.level === PreferenceLevelEnum.GLOBAL) { + const globalPreferenceCommand = GetSubscriberGlobalPreferenceCommand.create({ + organizationId: command.organizationId, + environmentId: command.environmentId, + subscriberId: command.subscriberId, + }); + const globalPreferences = await this.getSubscriberGlobalPreference.execute(globalPreferenceCommand); + + return [globalPreferences]; + } + + const preferenceCommand = GetSubscriberPreferenceCommand.create({ + organizationId: command.organizationId, + environmentId: command.environmentId, + subscriberId: command.subscriberId, + }); + + return await this.getSubscriberPreferenceUsecase.execute(preferenceCommand); + } +} diff --git a/apps/api/src/app/subscribers/usecases/get-preferences/get-preferences.command.ts b/apps/api/src/app/subscribers/usecases/get-preferences/get-preferences.command.ts deleted file mode 100644 index 6a9e257168d..00000000000 --- a/apps/api/src/app/subscribers/usecases/get-preferences/get-preferences.command.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { IsDefined, IsString } from 'class-validator'; -import { EnvironmentCommand } from '../../../shared/commands/project.command'; - -export class GetPreferencesCommand extends EnvironmentCommand { - @IsString() - @IsDefined() - subscriberId: string; -} diff --git a/apps/api/src/app/subscribers/usecases/get-preferences/get-preferences.usecase.ts b/apps/api/src/app/subscribers/usecases/get-preferences/get-preferences.usecase.ts deleted file mode 100644 index 57f8c647492..00000000000 --- a/apps/api/src/app/subscribers/usecases/get-preferences/get-preferences.usecase.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { GetSubscriberPreference, GetSubscriberPreferenceCommand } from '@novu/application-generic'; - -import { GetPreferencesCommand } from './get-preferences.command'; - -@Injectable() -export class GetPreferences { - constructor(private getSubscriberPreferenceUsecase: GetSubscriberPreference) {} - - async execute(command: GetPreferencesCommand) { - const preferenceCommand = GetSubscriberPreferenceCommand.create({ - organizationId: command.organizationId, - environmentId: command.environmentId, - subscriberId: command.subscriberId, - }); - - return await this.getSubscriberPreferenceUsecase.execute(preferenceCommand); - } -} diff --git a/apps/api/src/app/subscribers/usecases/index.ts b/apps/api/src/app/subscribers/usecases/index.ts index 2035c03160e..7569c1263fc 100644 --- a/apps/api/src/app/subscribers/usecases/index.ts +++ b/apps/api/src/app/subscribers/usecases/index.ts @@ -3,11 +3,12 @@ import { GetSubscriberTemplatePreference, UpdateSubscriber, CreateSubscriber, + GetSubscriberGlobalPreference, } from '@novu/application-generic'; import { GetSubscribers } from './get-subscribers'; import { GetSubscriber } from './get-subscriber'; -import { GetPreferences } from './get-preferences/get-preferences.usecase'; +import { GetPreferencesByLevel } from './get-preferences-by-level/get-preferences-by-level.usecase'; import { RemoveSubscriber } from './remove-subscriber'; import { SearchByExternalSubscriberIds } from './search-by-external-subscriber-ids'; import { UpdatePreference } from './update-preference/update-preference.usecase'; @@ -18,6 +19,7 @@ import { ChatOauth } from './chat-oauth/chat-oauth.usecase'; import { ChatOauthCallback } from './chat-oauth-callback/chat-oauth-callback.usecase'; import { DeleteSubscriberCredentials } from './delete-subscriber-credentials/delete-subscriber-credentials.usecase'; import { BulkCreateSubscribers } from './bulk-create-subscribers/bulk-create-subscribers.usecase'; +import { UpdateSubscriberGlobalPreferences } from './update-subscriber-global-preferences'; export { SearchByExternalSubscriberIds, @@ -30,7 +32,7 @@ export const USE_CASES = [ GetSubscriber, GetSubscriberPreference, GetSubscriberTemplatePreference, - GetPreferences, + GetPreferencesByLevel, RemoveSubscriber, SearchByExternalSubscriberIds, UpdatePreference, @@ -42,4 +44,6 @@ export const USE_CASES = [ ChatOauth, DeleteSubscriberCredentials, BulkCreateSubscribers, + UpdateSubscriberGlobalPreferences, + GetSubscriberGlobalPreference, ]; diff --git a/apps/api/src/app/subscribers/usecases/search-by-external-subscriber-ids/search-by-external-subscriber-ids.spec.ts b/apps/api/src/app/subscribers/usecases/search-by-external-subscriber-ids/search-by-external-subscriber-ids.spec.ts index 1b3d0866fce..3e5930b33d0 100644 --- a/apps/api/src/app/subscribers/usecases/search-by-external-subscriber-ids/search-by-external-subscriber-ids.spec.ts +++ b/apps/api/src/app/subscribers/usecases/search-by-external-subscriber-ids/search-by-external-subscriber-ids.spec.ts @@ -47,7 +47,7 @@ describe('SearchByExternalSubscriberIdsUseCase', () => { expect(res[1].subscriberId).to.eql(secondSubscriber.subscriberId); }); - it('should seach and find the subscribers existing by the external subscriber ids', async () => { + it('should search and find the subscribers existing by the external subscriber ids', async () => { const externalSubscriberIds = [secondSubscriber.subscriberId, 'non-existing-external-subscriber-id']; const command = SearchByExternalSubscriberIdsCommand.create({ environmentId: session.environment._id, diff --git a/apps/api/src/app/subscribers/usecases/update-subscriber-global-preferences/index.ts b/apps/api/src/app/subscribers/usecases/update-subscriber-global-preferences/index.ts new file mode 100644 index 00000000000..59adeb0c6ff --- /dev/null +++ b/apps/api/src/app/subscribers/usecases/update-subscriber-global-preferences/index.ts @@ -0,0 +1,2 @@ +export * from './update-subscriber-global-preferences.command'; +export * from './update-subscriber-global-preferences.usecase'; diff --git a/apps/api/src/app/subscribers/usecases/update-subscriber-global-preferences/update-subscriber-global-preferences.command.ts b/apps/api/src/app/subscribers/usecases/update-subscriber-global-preferences/update-subscriber-global-preferences.command.ts new file mode 100644 index 00000000000..9c3cf879b18 --- /dev/null +++ b/apps/api/src/app/subscribers/usecases/update-subscriber-global-preferences/update-subscriber-global-preferences.command.ts @@ -0,0 +1,15 @@ +import { Type } from 'class-transformer'; +import { IsBoolean, IsOptional, ValidateNested } from 'class-validator'; +import { EnvironmentWithSubscriber } from '../../../shared/commands/project.command'; +import { ChannelPreference } from '../../../shared/dtos/channel-preference'; + +export class UpdateSubscriberGlobalPreferencesCommand extends EnvironmentWithSubscriber { + @IsBoolean() + @IsOptional() + enabled?: boolean; + + @IsOptional() + @ValidateNested() + @Type(() => ChannelPreference) + preferences?: ChannelPreference[]; +} diff --git a/apps/api/src/app/subscribers/usecases/update-subscriber-global-preferences/update-subscriber-global-preferences.usecase.ts b/apps/api/src/app/subscribers/usecases/update-subscriber-global-preferences/update-subscriber-global-preferences.usecase.ts new file mode 100644 index 00000000000..580e5672423 --- /dev/null +++ b/apps/api/src/app/subscribers/usecases/update-subscriber-global-preferences/update-subscriber-global-preferences.usecase.ts @@ -0,0 +1,105 @@ +import { Injectable, NotFoundException } from '@nestjs/common'; +import { GetSubscriberGlobalPreference, GetSubscriberGlobalPreferenceCommand } from '@novu/application-generic'; +import { + ChannelTypeEnum, + PreferenceLevelEnum, + SubscriberEntity, + SubscriberPreferenceEntity, + SubscriberPreferenceRepository, + SubscriberRepository, +} from '@novu/dal'; + +import { UpdateSubscriberGlobalPreferencesCommand } from './update-subscriber-global-preferences.command'; + +@Injectable() +export class UpdateSubscriberGlobalPreferences { + constructor( + private subscriberPreferenceRepository: SubscriberPreferenceRepository, + private subscriberRepository: SubscriberRepository, + private getSubscriberGlobalPreference: GetSubscriberGlobalPreference + ) {} + + async execute(command: UpdateSubscriberGlobalPreferencesCommand) { + const subscriber = await this.subscriberRepository.findBySubscriberId(command.environmentId, command.subscriberId); + if (!subscriber) throw new NotFoundException(`Subscriber not found`); + + const userGlobalPreference = await this.subscriberPreferenceRepository.findOne({ + _organizationId: command.organizationId, + _environmentId: command.environmentId, + _subscriberId: subscriber._id, + level: PreferenceLevelEnum.GLOBAL, + }); + + if (!userGlobalPreference) { + await this.createUserPreference(command, subscriber); + } else { + await this.updateUserPreference(command, subscriber); + } + + return await this.getSubscriberGlobalPreference.execute( + GetSubscriberGlobalPreferenceCommand.create({ + organizationId: command.organizationId, + environmentId: command.environmentId, + subscriberId: command.subscriberId, + }) + ); + } + + private async createUserPreference( + command: UpdateSubscriberGlobalPreferencesCommand, + subscriber: SubscriberEntity + ): Promise { + const channelObj = {} as Record; + if (command.preferences && command.preferences.length > 0) { + for (const preference of command.preferences) { + if (preference.type) { + channelObj[preference.type] = preference.enabled; + } + } + } + + await this.subscriberPreferenceRepository.create({ + _environmentId: command.environmentId, + _organizationId: command.organizationId, + _subscriberId: subscriber._id, + /* + * Unless explicitly set to false when creating a user preference we want it to be enabled + * even if not passing at first enabled to true. + */ + enabled: command.enabled !== false, + channels: command.preferences && command.preferences.length > 0 ? channelObj : null, + level: PreferenceLevelEnum.GLOBAL, + }); + } + + private async updateUserPreference( + command: UpdateSubscriberGlobalPreferencesCommand, + subscriber: SubscriberEntity + ): Promise { + const updatePayload: Partial = {}; + + if (command.enabled != null) { + updatePayload.enabled = command.enabled; + } + + if (command.preferences && command.preferences.length > 0) { + for (const preference of command.preferences) { + if (preference.type) { + updatePayload[`channels.${preference.type}`] = preference.enabled; + } + } + } + + await this.subscriberPreferenceRepository.update( + { + _environmentId: command.environmentId, + _organizationId: command.organizationId, + _subscriberId: subscriber._id, + level: PreferenceLevelEnum.GLOBAL, + }, + { + $set: updatePayload, + } + ); + } +} diff --git a/apps/api/src/app/subscribers/usecases/update-subscriber-preference/update-subscriber-preference.usecase.ts b/apps/api/src/app/subscribers/usecases/update-subscriber-preference/update-subscriber-preference.usecase.ts index 9af25798015..ad62e702f54 100644 --- a/apps/api/src/app/subscribers/usecases/update-subscriber-preference/update-subscriber-preference.usecase.ts +++ b/apps/api/src/app/subscribers/usecases/update-subscriber-preference/update-subscriber-preference.usecase.ts @@ -6,6 +6,7 @@ import { SubscriberEntity, SubscriberRepository, MemberRepository, + PreferenceLevelEnum, } from '@novu/dal'; import { AnalyticsService, @@ -91,6 +92,7 @@ export class UpdateSubscriberPreference { */ enabled: command.enabled !== false, channels: command.channel?.type ? channelObj : null, + level: PreferenceLevelEnum.TEMPLATE, }); } diff --git a/apps/api/src/app/widgets/widgets.controller.ts b/apps/api/src/app/widgets/widgets.controller.ts index decc1d30260..cdff461f9b3 100644 --- a/apps/api/src/app/widgets/widgets.controller.ts +++ b/apps/api/src/app/widgets/widgets.controller.ts @@ -16,7 +16,7 @@ import { import { AuthGuard } from '@nestjs/passport'; import { ApiExcludeController, ApiNoContentResponse, ApiOperation, ApiQuery } from '@nestjs/swagger'; import { AnalyticsService, GetSubscriberPreference, GetSubscriberPreferenceCommand } from '@novu/application-generic'; -import { MessageEntity, SubscriberEntity } from '@novu/dal'; +import { MessageEntity, PreferenceLevelEnum, SubscriberEntity } from '@novu/dal'; import { MarkMessagesAsEnum, ButtonTypeEnum, MessageActionStatusEnum } from '@novu/shared'; import { SubscriberSession } from '../shared/framework/user.decorator'; @@ -54,6 +54,13 @@ import { LimitPipe } from './pipes/limit-pipe/limit-pipe'; import { RemoveAllMessagesCommand } from './usecases/remove-messages/remove-all-messages.command'; import { RemoveAllMessages } from './usecases/remove-messages/remove-all-messages.usecase'; import { RemoveAllMessagesDto } from './dtos/remove-all-messages.dto'; +import { + UpdateSubscriberGlobalPreferences, + UpdateSubscriberGlobalPreferencesCommand, +} from '../subscribers/usecases/update-subscriber-global-preferences'; +import { UpdateSubscriberGlobalPreferencesRequestDto } from '../subscribers/dtos/update-subscriber-global-preferences-request.dto'; +import { GetPreferencesByLevel } from '../subscribers/usecases/get-preferences-by-level/get-preferences-by-level.usecase'; +import { GetPreferencesByLevelCommand } from '../subscribers/usecases/get-preferences-by-level/get-preferences-by-level.command'; @Controller('/widgets') @ApiExcludeController() @@ -68,7 +75,9 @@ export class WidgetsController { private updateMessageActionsUsecase: UpdateMessageActions, private getOrganizationUsecase: GetOrganizationData, private getSubscriberPreferenceUsecase: GetSubscriberPreference, + private getSubscriberPreferenceByLevelUsecase: GetPreferencesByLevel, private updateSubscriberPreferenceUsecase: UpdateSubscriberPreference, + private updateSubscriberGlobalPreferenceUsecase: UpdateSubscriberGlobalPreferences, private markAllMessagesAsUsecase: MarkAllMessagesAs, private analyticsService: AnalyticsService ) {} @@ -350,6 +359,22 @@ export class WidgetsController { return await this.getSubscriberPreferenceUsecase.execute(command); } + @UseGuards(AuthGuard('subscriberJwt')) + @Get('/preferences/:level') + async getSubscriberPreferenceByLevel( + @SubscriberSession() subscriberSession: SubscriberEntity, + @Param('level') level: PreferenceLevelEnum + ) { + const command = GetPreferencesByLevelCommand.create({ + organizationId: subscriberSession._organizationId, + subscriberId: subscriberSession.subscriberId, + environmentId: subscriberSession._environmentId, + level, + }); + + return await this.getSubscriberPreferenceByLevelUsecase.execute(command); + } + @UseGuards(AuthGuard('subscriberJwt')) @Patch('/preferences/:templateId') async updateSubscriberPreference( @@ -369,6 +394,23 @@ export class WidgetsController { return await this.updateSubscriberPreferenceUsecase.execute(command); } + @UseGuards(AuthGuard('subscriberJwt')) + @Patch('/preferences') + async updateSubscriberGlobalPreference( + @SubscriberSession() subscriberSession: SubscriberEntity, + @Body() body: UpdateSubscriberGlobalPreferencesRequestDto + ) { + const command = UpdateSubscriberGlobalPreferencesCommand.create({ + organizationId: subscriberSession._organizationId, + subscriberId: subscriberSession.subscriberId, + environmentId: subscriberSession._environmentId, + preferences: body.preferences, + enabled: body.enabled, + }); + + return await this.updateSubscriberGlobalPreferenceUsecase.execute(command); + } + @UseGuards(AuthGuard('subscriberJwt')) @Post('/usage/log') async logUsage( diff --git a/apps/inbound-mail/package.json b/apps/inbound-mail/package.json index c6b33eddec1..d3631b027b5 100644 --- a/apps/inbound-mail/package.json +++ b/apps/inbound-mail/package.json @@ -1,6 +1,6 @@ { "name": "@novu/inbound-mail", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "", "author": "", "private": true, @@ -19,8 +19,8 @@ "test": "cross-env TS_NODE_COMPILER_OPTIONS='{\"strictNullChecks\": false}' TZ=UTC NODE_ENV=test E2E_RUNNER=true mocha --trace-warnings --timeout 10000 --require ts-node/register --exit --file e2e/setup.ts src/**/**/*.spec.ts" }, "dependencies": { - "@novu/application-generic": "^0.19.0", - "@novu/shared": "^0.19.0", + "@novu/application-generic": "^0.20.0-alpha.0", + "@novu/shared": "^0.20.0-alpha.0", "@sentry/node": "^7.12.1", "bluebird": "^2.9.30", "dotenv": "^8.6.0", @@ -39,7 +39,7 @@ "winston": "^3.9.0" }, "devDependencies": { - "@novu/testing": "^0.19.0", + "@novu/testing": "^0.20.0-alpha.0", "@types/chai": "^4.2.11", "@types/express": "^4.17.8", "@types/html-to-text": "^9.0.1", diff --git a/apps/inbound-mail/src/python/DNS/win32dns.py b/apps/inbound-mail/src/python/DNS/win32dns.py index 0b1acf19942..2761f9c399f 100644 --- a/apps/inbound-mail/src/python/DNS/win32dns.py +++ b/apps/inbound-mail/src/python/DNS/win32dns.py @@ -23,7 +23,7 @@ import _winreg def binipdisplay(s): - "convert a binary array of ip adresses to a python list" + "convert a binary array of ip addresses to a python list" if len(s)%4!= 0: raise EnvironmentError # well ... ol=[] diff --git a/apps/inbound-mail/src/python/dkim/__init__.py b/apps/inbound-mail/src/python/dkim/__init__.py index 36d6fb0e0fd..014299e5b0a 100644 --- a/apps/inbound-mail/src/python/dkim/__init__.py +++ b/apps/inbound-mail/src/python/dkim/__init__.py @@ -467,7 +467,7 @@ def sign(self, selector, domain, privkey, identity=None, sig2 = RSASSA_PKCS1_v1_5_sign(h, pk) except DigestTooLargeError: raise ParameterError("digest too large for modulus") - # Folding b= is explicity allowed, but yahoo and live.com are broken + # Folding b= is explicitly allowed, but yahoo and live.com are broken #sig_value += base64.b64encode(bytes(sig2)) # Instead of leaving unfolded (which lets an MTA fold it later and still # breaks yahoo and live.com), we change the default signing mode to diff --git a/apps/inbound-mail/src/python/ipaddr.py b/apps/inbound-mail/src/python/ipaddr.py index 0c8514329f9..987e3250f0a 100644 --- a/apps/inbound-mail/src/python/ipaddr.py +++ b/apps/inbound-mail/src/python/ipaddr.py @@ -1287,7 +1287,7 @@ def __init__(self, address, strict=False): '192.168.1.1' '192.168.1.1/255.255.255.255' '192.168.1.1/32' - are also functionaly equivalent. That is to say, failing to + are also functionally equivalent. That is to say, failing to provide a subnetmask will create an object with a mask of /32. If the mask (portion after the / in the argument) is given in diff --git a/apps/inbound-mail/src/python/spf.py b/apps/inbound-mail/src/python/spf.py index 56c2f0d8dc8..7899c4637fd 100644 --- a/apps/inbound-mail/src/python/spf.py +++ b/apps/inbound-mail/src/python/spf.py @@ -131,7 +131,7 @@ # Start fixing python3 bytes issue - Now works, but fails the non-ASCII exp test. # # Revision 1.108.2.76 2012/02/05 05:50:39 kitterma -# Fix a few stray print -> print() changes for python3 compatbility. +# Fix a few stray print -> print() changes for python3 compatibility. # # See pyspf_changelog.txt for earlier CVS commits. @@ -146,7 +146,7 @@ To test an SPF record: % python spf.py [-v] "v=spf1..." {ip} {sender} {helo} - % python spf.py "v=spf1 +mx +ip4:10.0.0.1 -all" 10.0.0.1 tway@foo.com a + % python spf.py "v=spf1 +mx +ip4:10.0.0.1 -all" 10.0.0.1 tway@foo.com a To fetch an SPF record: % python spf.py {domain} @@ -172,7 +172,7 @@ except ImportError: from email.Message import Message try: - # Python standard libarary as of python3.3 + # Python standard library as of python3.3 import ipaddress except ImportError: try: @@ -404,7 +404,7 @@ class query(object): This is also, by design, the same variables used in SPF macro expansion. - Also keeps cache: DNS cache. + Also keeps cache: DNS cache. """ def __init__(self, i, s, h, local=None, receiver=None, strict=True, timeout=MAX_PER_LOOKUP_TIME,verbose=False,querytime=0): @@ -447,7 +447,7 @@ def __init__(self, i, s, h, local=None, receiver=None, strict=True, # For IPv4, self.i = self.c, but not in IPv6 # self.iplist = list of IPv4/6 addresses that would pass, collected # when list or list6 is passed as 'i' - # self.addr = ipaddr/ipaddress object representing the connect IP + # self.addr = ipaddr/ipaddress object representing the connect IP self.default_modifier = True self.verbose = verbose self.authserv = None # Only used in A-R header generation tests @@ -543,7 +543,7 @@ def check(self, spf=None): >>> q.check(spf='v=spf1 redirect=controlledmail.com exp=_exp.controlledmail.com') ('fail', 550, 'SPF fail - not authorized') - + >>> q.check(spf='v=spf1 ip4:192.0.0.0/8 ?all moo') ('permerror', 550, 'SPF Permanent Error: Unknown mechanism found: moo') @@ -587,12 +587,12 @@ def check(self, spf=None): >>> q.check(spf='v=spf1 ip4:1.2.3.4 -all exp=_exp.controlledmail.com') ('fail', 550, 'Controlledmail.com does not send mail from itself.') - + >>> q.check(spf='v=spf1 ip4:1.2.3.4 ?all exp=_exp.controlledmail.com') ('neutral', 250, 'access neither permitted nor denied') """ self.mech = [] # unknown mechanisms - # If not strict, certain PermErrors (mispelled + # If not strict, certain PermErrors (misspelled # mechanisms, strict processing limits exceeded) # will continue processing. However, the exception # that strict processing would raise is saved here @@ -606,7 +606,7 @@ def check(self, spf=None): if not spf: spf = self.dns_spf(self.d) if self.verbose: self.log("top",self.d,spf) - if self.libspf_local and spf: + if self.libspf_local and spf: spf = insert_libspf_local_policy( spf, self.libspf_local) rc = self.check1(spf, self.d, 0) @@ -615,7 +615,7 @@ def check(self, spf=None): self.perm_error.ext = rc raise self.perm_error return rc - + except TempError as x: self.prob = x.msg if x.mech: @@ -693,14 +693,14 @@ def validate_mechanism(self, mech): >>> q.validate_mechanism('A/24//64') ('A/24//64', 'a', 'email.example.com', 24, 'pass') - + >>> q.validate_mechanism('?mx:%{d}/27') ('?mx:%{d}/27', 'mx', 'email.example.com', 27, 'neutral') >>> try: q.validate_mechanism('ip4:1.2.3.4/247') ... except PermError as x: print(x) Invalid IP4 CIDR length: ip4:1.2.3.4/247 - + >>> try: q.validate_mechanism('ip4:1.2.3.4/33') ... except PermError as x: print(x) Invalid IP4 CIDR length: ip4:1.2.3.4/33 @@ -708,15 +708,15 @@ def validate_mechanism(self, mech): >>> try: q.validate_mechanism('a:example.com:8080') ... except PermError as x: print(x) Invalid domain found (use FQDN): example.com:8080 - + >>> try: q.validate_mechanism('ip4:1.2.3.444/24') ... except PermError as x: print(x) Invalid IP4 address: ip4:1.2.3.444/24 - + >>> try: q.validate_mechanism('ip4:1.2.03.4/24') ... except PermError as x: print(x) Invalid IP4 address: ip4:1.2.03.4/24 - + >>> try: q.validate_mechanism('-all:3030') ... except PermError as x: print(x) Invalid all mechanism format - only qualifier allowed with all: -all:3030 @@ -732,10 +732,10 @@ def validate_mechanism(self, mech): >>> try: q.validate_mechanism('a:mail.example.com,') ... except PermError as x: print(x) - Do not separate mechnisms with commas: a:mail.example.com, + Do not separate mechanisms with commas: a:mail.example.com, >>> q = query(s='strong-bad@email.example.com', - ... h='mx.example.org', i='2001:db8:1234::face:b007') + ... h='mx.example.org', i='2001:db8:1234::face:b007') >>> q.validate_mechanism('A//64') ('A//64', 'a', 'email.example.com', 64, 'pass') @@ -747,7 +747,7 @@ def validate_mechanism(self, mech): """ if mech.endswith( "," ): - self.note_error('Do not separate mechnisms with commas', mech) + self.note_error('Do not separate mechanisms with commas', mech) mech = mech[:-1] # a mechanism m, arg, cidrlength, cidr6length = parse_mechanism(mech, self.d) @@ -1060,7 +1060,7 @@ def expand(self, str, stripdot=True): # macros='slodipvh' >>> q.expand('%{dr}') 'com.example.email' - + >>> q.expand('%{d2r}') 'example.email' @@ -1150,7 +1150,7 @@ def expand(self, str, stripdot=True): # macros='slodipvh' expansion = getattr(self, letter, self) if expansion: if expansion == self: - raise PermError('Unknown Macro Encountered', macro) + raise PermError('Unknown Macro Encountered', macro) e = expand_one(expansion, macro[3:-1], JOINERS.get(letter)) if letter != macro[2]: e = urllibparse.quote(e) @@ -1215,11 +1215,11 @@ def dns_spf(self, domain): # We work around this by assuming any UnicodeErrors coming from py3dns # are from a non-ascii SPF record (incorrect in general). Packages # should require py3dns != 3.0.2. - # + # # We cannot check for non-ascii here, because we must ignore non-SPF # records - even when they are non-ascii. So we return bytes. # The caller does the ascii check for SPF records and explanations. - # + # def dns_txt(self, domainname, rr='TXT'): "Get a list of TXT records for a domain name." if domainname: @@ -1307,7 +1307,7 @@ def dns_ptr(self, i): # We have to be careful which additional DNS RRs we cache. For # instance, PTR records are controlled by the connecting IP, and they - # could poison our local cache with bogus A and MX records. + # could poison our local cache with bogus A and MX records. SAFE2CACHE = { ('MX','A'): None, @@ -1432,7 +1432,7 @@ def cidrmatch(self, ipaddrs, n): def parse_header_ar(self, val): """Set SPF values from RFC 5451 Authentication Results header. - + Useful when SPF has already been run on a trusted gateway machine. Expects the entire header as an input. @@ -1465,7 +1465,7 @@ def parse_header_ar(self, val): def parse_header_spf(self, val): """Set SPF values from Received-SPF header. - + Useful when SPF has already been run on a trusted gateway machine. Examples: @@ -1512,7 +1512,7 @@ def parse_header_spf(self, val): def parse_header(self, val): """Set SPF values from Received-SPF or RFC 5451 Authentication Results header. - + Useful when SPF has already been run on a trusted gateway machine. Auto detects the header type and parses it. Use parse_header_spf or parse_header_ar for each type if required. @@ -1564,7 +1564,7 @@ def get_header(self, res, receiver=None, header_type='spf', aid=None, **kv): ('fail', 550, 'SPF fail - not authorized') >>> q.get_header('fail') 'Fail (abuse@kitterman.com: domain of email.example.com does not designate 192.0.2.3 as permitted sender) client-ip=192.0.2.3; envelope-from="strong-bad@email.example.com"; helo=mx.example.org; receiver=abuse@kitterman.com; mechanism=-all; identity=mailfrom' - + >>> q.check(spf='v=spf1 ip4:192.0.0.0/8 ?all moo') ('permerror', 550, 'SPF Permanent Error: Unknown mechanism found: moo') >>> q.get_header('permerror') @@ -1711,7 +1711,7 @@ def quote_value(s): Examples: >>> quote_value('foo@bar.com') '"foo@bar.com"' - + >>> quote_value('mail.example.com') 'mail.example.com' @@ -1869,7 +1869,7 @@ def split(str, delimiters, joiner=None): def insert_libspf_local_policy(spftxt, local=None): """Returns spftxt with local inserted just before last non-fail mechanism. This is how the libspf{2} libraries handle "local-policy". - + Examples: >>> insert_libspf_local_policy('v=spf1 -all') 'v=spf1 -all' @@ -1914,7 +1914,7 @@ def insert_libspf_local_policy(spftxt, local=None): return spftxt # No local policy adds for v=spf1 -all # Processing limits not applied to local policy. Suggest # inserting 'local' mechanism to handle this properly - #MAX_LOOKUP = 100 + #MAX_LOOKUP = 100 return 'v=spf1 '+local if sys.version_info[0] == 2: diff --git a/apps/web/.env b/apps/web/.env index 8977904e773..23c860488a3 100644 --- a/apps/web/.env +++ b/apps/web/.env @@ -1,5 +1,6 @@ SKIP_PREFLIGHT_CHECK=true REACT_APP_ENVIRONMENT=dev +REACT_APP_VERSION=$npm_package_version REACT_APP_API_URL= REACT_APP_WS_URL= REACT_APP_WEBHOOK_URL= diff --git a/apps/web/cypress/tests/integration-store.spec.ts b/apps/web/cypress/tests/integration-store.spec.ts index e671fb4f37f..b09c8c906b9 100644 --- a/apps/web/cypress/tests/integration-store.spec.ts +++ b/apps/web/cypress/tests/integration-store.spec.ts @@ -8,7 +8,7 @@ Cypress.on('window:before:load', (win) => { }; }); -describe('Integration store page', function () { +describe.skip('Integration store page', function () { beforeEach(function () { cy.initializeSession().as('session'); }); diff --git a/apps/web/package.json b/apps/web/package.json index 1fa2b8c0434..507a3701ea2 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "@novu/web", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "private": true, "scripts": { "start": "cross-env PORT=4200 react-app-rewired start", @@ -49,8 +49,8 @@ "@mantine/notifications": "^5.7.1", "@mantine/prism": "^5.7.1", "@mantine/spotlight": "^5.7.1", - "@novu/notification-center": "^0.19.0", - "@novu/shared": "^0.19.0", + "@novu/notification-center": "^0.20.0-alpha.0", + "@novu/shared": "^0.20.0-alpha.0", "@segment/analytics-next": "^1.48.0", "@sentry/react": "^7.40.0", "@sentry/tracing": "^7.40.0", @@ -118,7 +118,7 @@ "uuid": "8.3.2", "web-vitals": "^1.0.1", "webpack-dev-server": "4.11.1", - "zod": "^3.17.3" + "zod": "^3.22.4" }, "devDependencies": { "@babel/polyfill": "^7.12.1", @@ -126,8 +126,8 @@ "@babel/preset-react": "^7.13.13", "@babel/preset-typescript": "^7.13.0", "@babel/runtime": "^7.20.13", - "@novu/dal": "^0.19.0", - "@novu/testing": "^0.19.0", + "@novu/dal": "^0.20.0-alpha.0", + "@novu/testing": "^0.20.0-alpha.0", "@storybook/addon-actions": "^7.4.2", "@storybook/addon-essentials": "^7.4.2", "@storybook/addon-links": "^7.4.2", diff --git a/apps/web/public/static/images/providers/dark/mailtrap.svg b/apps/web/public/static/images/providers/dark/mailtrap.svg new file mode 100644 index 00000000000..4610e880fce --- /dev/null +++ b/apps/web/public/static/images/providers/dark/mailtrap.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/static/images/providers/dark/square/mailtrap.svg b/apps/web/public/static/images/providers/dark/square/mailtrap.svg new file mode 100644 index 00000000000..8662aaf658b --- /dev/null +++ b/apps/web/public/static/images/providers/dark/square/mailtrap.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/public/static/images/providers/light/mailtrap.svg b/apps/web/public/static/images/providers/light/mailtrap.svg new file mode 100644 index 00000000000..5ad1dd36ee9 --- /dev/null +++ b/apps/web/public/static/images/providers/light/mailtrap.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/web/public/static/images/providers/light/square/mailtrap.svg b/apps/web/public/static/images/providers/light/square/mailtrap.svg new file mode 100644 index 00000000000..ca91a016fb1 --- /dev/null +++ b/apps/web/public/static/images/providers/light/square/mailtrap.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/web/src/components/layout/components/HeaderNav.tsx b/apps/web/src/components/layout/components/HeaderNav.tsx index 214d5d62a0f..fb12825af38 100644 --- a/apps/web/src/components/layout/components/HeaderNav.tsx +++ b/apps/web/src/components/layout/components/HeaderNav.tsx @@ -5,7 +5,7 @@ import { Link } from 'react-router-dom'; import { useIntercom } from 'react-use-intercom'; import LogRocket from 'logrocket'; -import { CONTEXT_PATH, INTERCOM_APP_ID, IS_DOCKER_HOSTED, LOGROCKET_ID } from '../../../config'; +import { CONTEXT_PATH, INTERCOM_APP_ID, IS_DOCKER_HOSTED, LOGROCKET_ID, REACT_APP_VERSION } from '../../../config'; import { ROUTES } from '../../../constants/routes.enum'; import { colors, Dropdown, shadows, Text, Tooltip } from '../../../design-system'; import { Ellipse, Mail, Moon, Question, Sun, Trash } from '../../../design-system/icons'; @@ -158,6 +158,19 @@ export function HeaderNav({ isIntercomOpened }: Props) { , ]; + isSelfHosted && + profileMenuMantine.push( + + Version: {REACT_APP_VERSION} + + ); + return (
` cursor: default; } + .react-flow { + overflow: visible; + } + .react-flow__attribution { background: transparent; opacity: 0.5; } + .react-flow__attribution a { + position: relative; + font-size: initial; + top: 25px; + right: 173px; + } + + .react-flow__attribution a:hover { + color: lightpink !important; + } + .react-flow__handle { background: transparent; border: 1px solid ${({ theme }) => (theme.colorScheme === 'dark' ? colors.B40 : colors.B60)}; diff --git a/apps/web/src/config/index.ts b/apps/web/src/config/index.ts index f122903fef5..7fc49a1cc54 100644 --- a/apps/web/src/config/index.ts +++ b/apps/web/src/config/index.ts @@ -40,6 +40,8 @@ export const WIDGET_EMBED_PATH = export const IS_DOCKER_HOSTED = window._env_.REACT_APP_DOCKER_HOSTED_ENV === 'true' || process.env.REACT_APP_DOCKER_HOSTED_ENV === 'true'; +export const REACT_APP_VERSION = window._env_.REACT_APP_VERSION || process.env.REACT_APP_VERSION; + export const INTERCOM_APP_ID = window._env_.REACT_APP_INTERCOM_APP_ID || process.env.REACT_APP_INTERCOM_APP_ID; export const CONTEXT_PATH = getContextPath(NovuComponentEnum.WEB); diff --git a/apps/web/src/design-system/input/Input.tsx b/apps/web/src/design-system/input/Input.tsx index 8cda1ae07c8..aa32e5574bb 100644 --- a/apps/web/src/design-system/input/Input.tsx +++ b/apps/web/src/design-system/input/Input.tsx @@ -14,6 +14,7 @@ interface IInputProps extends SpacingProps { description?: string; onChange?: (event: ChangeEvent) => void; rightSection?: React.ReactNode; + rightSectionWidth?: React.CSSProperties['width']; type?: 'text' | 'password' | 'email' | 'search' | 'tel' | 'url' | 'number' | 'time'; min?: string | number; max?: string | number; @@ -26,13 +27,25 @@ interface IInputProps extends SpacingProps { * */ export const Input = React.forwardRef( - ({ value, rightSection, onChange, readOnly = false, disabled = false, type, ...props }: IInputProps, ref) => { + ( + { + value, + rightSection, + rightSectionWidth, + onChange, + readOnly = false, + disabled = false, + type, + ...props + }: IInputProps, + ref + ) => { const defaultDesign = { radius: 'md', size: 'md', styles: inputStyles, type: 'text' } as TextInputProps; return ( Sign In with GitHub - Sign In with Google - + */} Or} color={colors.B30} labelPosition="center" my="md" /> diff --git a/apps/web/src/pages/brand/tabs/BrandingForm.tsx b/apps/web/src/pages/brand/tabs/BrandingForm.tsx index fab56b60441..6abc74428c7 100644 --- a/apps/web/src/pages/brand/tabs/BrandingForm.tsx +++ b/apps/web/src/pages/brand/tabs/BrandingForm.tsx @@ -47,15 +47,11 @@ export function BrandingForm() { useEffect(() => { if (organization) { - if (organization.branding?.logo) { - setValue('image', organization.branding.logo); - } - if (organization.branding?.color) { - setValue('color', organization?.branding?.color); - } - if (organization.branding?.fontFamily) { - setValue('fontFamily', organization?.branding?.fontFamily); - } + organization?.branding?.logo ? setValue('image', organization.branding.logo) : setValue('image', ''); + organization?.branding?.color ? setValue('color', organization?.branding?.color) : setValue('color', '#f47373'); + organization?.branding?.fontFamily + ? setValue('fontFamily', organization?.branding?.fontFamily) + : setValue('fontFamily', 'inherit'); } }, [organization, setValue]); diff --git a/apps/web/src/pages/settings/tabs/ApiKeysCard.tsx b/apps/web/src/pages/settings/tabs/ApiKeysCard.tsx index 3e5ff7136ba..dab88ede4fb 100644 --- a/apps/web/src/pages/settings/tabs/ApiKeysCard.tsx +++ b/apps/web/src/pages/settings/tabs/ApiKeysCard.tsx @@ -3,12 +3,15 @@ import { useClipboard } from '@mantine/hooks'; import { useQuery } from '@tanstack/react-query'; import styled from '@emotion/styled'; -import { Input, Tooltip } from '../../../design-system'; +import { Input, Tooltip, colors } from '../../../design-system'; import { Check, Copy } from '../../../design-system/icons'; import { getApiKeys } from '../../../api/environment'; import { inputStyles } from '../../../design-system/config/inputs.styles'; import { useEnvController } from '../../../hooks'; import { Regenerate } from './components/Regenerate'; +import { When } from '../../../components/utils/When'; +import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons'; +import { useState } from 'react'; export const ApiKeysCard = () => { const clipboardApiKey = useClipboard({ timeout: 1000 }); @@ -22,6 +25,8 @@ export const ApiKeysCard = () => { const environmentIdentifier = environment?.identifier ? environment.identifier : ''; const environmentId = environment?._id ? environment._id : ''; + const [hidden, setHidden] = useState(true); + return ( <> @@ -32,17 +37,50 @@ export const ApiKeysCard = () => { > - clipboardApiKey.copy(apiKey)} - > - {clipboardApiKey.copied ? : } + <> + setHidden(!hidden)}> + + + + + + - + + clipboardApiKey.copy(apiKey)} + > + {clipboardApiKey.copied ? ( + + ) : ( + + )} + + + } value={apiKey} data-test-id="api-key-container" @@ -65,7 +103,19 @@ export const ApiKeysCard = () => { data-test-id={'application-identifier-copy'} onClick={() => clipboardEnvironmentIdentifier.copy(environmentIdentifier)} > - {clipboardEnvironmentIdentifier.copied ? : } + {clipboardEnvironmentIdentifier.copied ? ( + + ) : ( + + )} } @@ -85,7 +135,19 @@ export const ApiKeysCard = () => { data-test-id={'environment-id-copy'} onClick={() => clipboardEnvironmentId.copy(environmentId)} > - {clipboardEnvironmentId.copied ? : } + {clipboardEnvironmentId.copied ? ( + + ) : ( + + )} } diff --git a/apps/web/src/pages/settings/tabs/EmailSettings.tsx b/apps/web/src/pages/settings/tabs/EmailSettings.tsx index 010a611a233..ba18d2e9373 100644 --- a/apps/web/src/pages/settings/tabs/EmailSettings.tsx +++ b/apps/web/src/pages/settings/tabs/EmailSettings.tsx @@ -87,7 +87,19 @@ export const EmailSettings = () => { data-test-id={'mail-server-domiain-copy'} onClick={() => clipboardEnvironmentIdentifier.copy(mailServerDomain)} > - {clipboardEnvironmentIdentifier.copied ? : } + {clipboardEnvironmentIdentifier.copied ? ( + + ) : ( + + )} } diff --git a/apps/webhook/package.json b/apps/webhook/package.json index 4448c955d19..26de79fcf22 100644 --- a/apps/webhook/package.json +++ b/apps/webhook/package.json @@ -1,6 +1,6 @@ { "name": "@novu/webhook", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "", "author": "", "private": true, @@ -25,11 +25,11 @@ "@nestjs/core": "^10.2.2", "@nestjs/platform-express": "^10.2.2", "@nestjs/terminus": "^10.0.1", - "@novu/application-generic": "^0.19.0", - "@novu/dal": "^0.19.0", - "@novu/shared": "^0.19.0", - "@novu/stateless": "^0.19.0", - "@novu/testing": "^0.19.0", + "@novu/application-generic": "^0.20.0-alpha.0", + "@novu/dal": "^0.20.0-alpha.0", + "@novu/shared": "^0.20.0-alpha.0", + "@novu/stateless": "^0.20.0-alpha.0", + "@novu/testing": "^0.20.0-alpha.0", "@sentry/node": "^7.66.0", "axios": "^1.3.3", "class-transformer": "^0.5.1", diff --git a/apps/widget/.babelrc b/apps/widget/.babelrc new file mode 100644 index 00000000000..a4a5252063a --- /dev/null +++ b/apps/widget/.babelrc @@ -0,0 +1,23 @@ +{ + "presets": [ + "@babel/preset-typescript", + [ + "@babel/preset-react", + { + "runtime": "automatic" + } + ], + "@babel/preset-env" + ], + "plugins": [ + "@emotion", + "@babel/plugin-transform-react-display-name", + "@babel/plugin-proposal-optional-chaining", + [ + "@babel/plugin-transform-runtime", + { + "regenerator": true + } + ] + ] +} diff --git a/apps/widget/config-overrides.js b/apps/widget/config-overrides.js new file mode 100644 index 00000000000..404a228034a --- /dev/null +++ b/apps/widget/config-overrides.js @@ -0,0 +1,10 @@ +const { useBabelRc, override } = require('customize-cra'); +// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; + +function overrideConfig(config, env) { + const plugins = [...config.plugins, /* new BundleAnalyzerPlugin() */]; + + return { ...config, plugins }; +} + +module.exports = override(useBabelRc(), overrideConfig); diff --git a/apps/widget/craco.config.js b/apps/widget/craco.config.js deleted file mode 100644 index ba4487ae40b..00000000000 --- a/apps/widget/craco.config.js +++ /dev/null @@ -1,8 +0,0 @@ -const CracoAntDesignPlugin = require('craco-antd'); -const path = require('path'); - -module.exports = { - babel: { - plugins: ['@emotion'], - }, -}; diff --git a/apps/widget/package.json b/apps/widget/package.json index 64f36674b15..2aa0e0800fa 100644 --- a/apps/widget/package.json +++ b/apps/widget/package.json @@ -1,9 +1,9 @@ { "name": "@novu/widget", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "private": true, "scripts": { - "start": "craco start", + "start": "react-app-rewired start", "start:dev": "cross-env PORT=4500 pnpm start", "start:cli:local": "pnpm start:shell:test & pnpm start:shell:embed & cross-env PORT=3500 pnpm start", "start:test": "pnpm start:shell:test & pnpm start:shell:embed & cross-env NODE_ENV=test REACT_APP_API_URL=http://localhost:1336 REACT_APP_WS_URL=http://localhost:1340 PORT=3500 pnpm start", @@ -13,9 +13,8 @@ "start:docker": "pnpm build && pnpm start:static:build", "docker:build": "docker build -f ./Dockerfile -t novu-widget ./../..", "prebuild": "rimraf build", - "build": "cross-env NODE_OPTIONS=--max_old_space_size=4096 craco build", + "build": "cross-env NODE_OPTIONS=--max_old_space_size=4096 react-app-rewired --max_old_space_size=4096 build", "precommit": "lint-staged", - "eject": "craco eject", "lint": "eslint src", "cypress:run": "cypress run", "cypress:open": "cypress open", @@ -29,8 +28,8 @@ "@emotion/styled": "^11.6.0", "@mantine/core": "4.2.12", "@mantine/hooks": "4.2.12", - "@novu/notification-center": "^0.19.0", - "@novu/shared": "^0.19.0", + "@novu/notification-center": "^0.20.0-alpha.0", + "@novu/shared": "^0.20.0-alpha.0", "antd": "^4.10.0", "babel-plugin-import": "^1.13.3", "chroma-js": "^2.4.2", @@ -52,17 +51,27 @@ "webfontloader": "^1.6.28" }, "devDependencies": { - "@craco/craco": "^7.0.0", + "@babel/polyfill": "^7.12.1", + "@babel/preset-env": "^7.13.15", + "@babel/preset-react": "^7.13.13", + "@babel/preset-typescript": "^7.13.0", + "@babel/runtime": "^7.20.13", + "@babel/plugin-proposal-optional-chaining": "^7.20.7", + "@babel/plugin-transform-react-display-name": "^7.18.6", + "@babel/plugin-transform-runtime": "^7.19.6", "@emotion/babel-plugin": "^11.7.2", + "@emotion/react": "^11.7.1", + "@emotion/styled": "^11.6.0", + "react-app-rewired": "^2.2.1", + "customize-cra": "^1.0.0", "@faker-js/faker": "^6.0.0", - "@novu/dal": "^0.19.0", - "@novu/testing": "^0.19.0", + "@novu/dal": "^0.20.0-alpha.0", + "@novu/testing": "^0.20.0-alpha.0", "@types/jest": "^29.5.0", "@types/node": "^12.0.0", "@types/react": "17.0.62", "@types/react-dom": "17.0.20", "@types/react-router-dom": "^5.1.7", - "craco-antd": "^1.19.0", "cross-env": "^7.0.3", "cypress": "^12.17.2", "cypress-intellij-reporter": "^0.0.7", @@ -74,7 +83,7 @@ "less-loader": "4.1.0", "typescript": "4.9.5", "webpack-dev-server": "4.11.1", - "webpack": "^5.78.0" + "webpack": "5.78.0" }, "browserslist": { "production": [ @@ -109,8 +118,6 @@ "**/@cypress/**", "**/@storybook/**", "**/@storybook", - "**/@craco", - "**/@craco/**", "**/@babel", "**/@babel/**" ] diff --git a/apps/widget/src/components/notification-center/NotificationCenterWidget.tsx b/apps/widget/src/components/notification-center/NotificationCenterWidget.tsx index dd3d81444d1..f22bcc65b40 100644 --- a/apps/widget/src/components/notification-center/NotificationCenterWidget.tsx +++ b/apps/widget/src/components/notification-center/NotificationCenterWidget.tsx @@ -15,6 +15,7 @@ import type { INovuThemeProvider, INotificationCenterStyles } from '@novu/notifi import { IMessage, IOrganizationEntity, ButtonTypeEnum } from '@novu/shared'; import { API_URL, WS_URL } from '../../config'; +import { isCypress } from '../../utils/browser'; const DEFAULT_FONT_FAMILY = 'inherit'; interface INotificationCenterWidgetProps { @@ -102,7 +103,7 @@ export function NotificationCenterWidget(props: INotificationCenterWidgetProps) } }; - if (process.env.NODE_ENV === 'test') { + if (process.env.NODE_ENV === 'test' || isCypress) { // eslint-disable-next-line (window as any).initHandler = handler; } diff --git a/apps/widget/src/utils/browser.ts b/apps/widget/src/utils/browser.ts new file mode 100644 index 00000000000..0eacde3a0d0 --- /dev/null +++ b/apps/widget/src/utils/browser.ts @@ -0,0 +1,2 @@ +export const isBrowser = () => typeof window !== 'undefined'; +export const isCypress = (isBrowser() && (window as any).Cypress) || (isBrowser() && (window as any).parent.Cypress); diff --git a/apps/worker/package.json b/apps/worker/package.json index 1ed87723264..5ea2385c5b8 100644 --- a/apps/worker/package.json +++ b/apps/worker/package.json @@ -1,6 +1,6 @@ { "name": "@novu/worker", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "description", "author": "", "private": "true", @@ -29,11 +29,11 @@ "@nestjs/platform-express": "^10.2.2", "@nestjs/swagger": "^7.1.9", "@nestjs/terminus": "^10.0.1", - "@novu/application-generic": "^0.19.0", - "@novu/dal": "^0.19.0", - "@novu/shared": "^0.19.0", - "@novu/stateless": "^0.19.0", - "@novu/testing": "^0.19.0", + "@novu/application-generic": "^0.20.0-alpha.0", + "@novu/dal": "^0.20.0-alpha.0", + "@novu/shared": "^0.20.0-alpha.0", + "@novu/stateless": "^0.20.0-alpha.0", + "@novu/testing": "^0.20.0-alpha.0", "@sentry/node": "^7.40.0", "@sentry/tracing": "^7.40.0", "@types/newrelic": "^9.13.0", diff --git a/apps/worker/src/app/workflow/services/active-jobs-metric.service.ts b/apps/worker/src/app/workflow/services/active-jobs-metric.service.ts index 733b19994fd..5239f5be22f 100644 --- a/apps/worker/src/app/workflow/services/active-jobs-metric.service.ts +++ b/apps/worker/src/app/workflow/services/active-jobs-metric.service.ts @@ -112,7 +112,7 @@ export class ActiveJobsMetricService { return resolve(); } catch (error) { - Logger.error({ error }, 'Error occured while processing metrics', LOG_CONTEXT); + Logger.error({ error }, 'Error occurred while processing metrics', LOG_CONTEXT); return reject(error); } diff --git a/apps/worker/src/app/workflow/services/cold-start.service.ts b/apps/worker/src/app/workflow/services/cold-start.service.ts index 191223d7024..f132c7decf3 100644 --- a/apps/worker/src/app/workflow/services/cold-start.service.ts +++ b/apps/worker/src/app/workflow/services/cold-start.service.ts @@ -3,6 +3,7 @@ import { INovuWorker, ReadinessService } from '@novu/application-generic'; import { StandardWorker } from './standard.worker'; import { WorkflowWorker } from './workflow.worker'; +import { OldInstanceStandardWorker } from './old-instance-standard.worker'; import { OldInstanceWorkflowWorker } from './old-instance-workflow.worker'; /** @@ -11,9 +12,10 @@ import { OldInstanceWorkflowWorker } from './old-instance-workflow.worker'; const getWorkers = (app: INestApplication): INovuWorker[] => { const standardWorker = app.get(StandardWorker, { strict: false }); const workflowWorker = app.get(WorkflowWorker, { strict: false }); + const oldInstanceStandardWorker = app.get(OldInstanceStandardWorker, { strict: false }); const oldInstanceWorkflowWorker = app.get(OldInstanceWorkflowWorker, { strict: false }); - const workers: INovuWorker[] = [standardWorker, workflowWorker, oldInstanceWorkflowWorker]; + const workers: INovuWorker[] = [standardWorker, workflowWorker, oldInstanceStandardWorker, oldInstanceWorkflowWorker]; return workers; }; diff --git a/apps/worker/src/app/workflow/services/completed-jobs-metric.service.ts b/apps/worker/src/app/workflow/services/completed-jobs-metric.service.ts index 40d9fefce95..3bcad9e738d 100644 --- a/apps/worker/src/app/workflow/services/completed-jobs-metric.service.ts +++ b/apps/worker/src/app/workflow/services/completed-jobs-metric.service.ts @@ -110,7 +110,7 @@ export class CompletedJobsMetricService { return resolve(); } catch (error) { - Logger.error({ error }, 'Error occured while processing metrics', LOG_CONTEXT); + Logger.error({ error }, 'Error occurred while processing metrics', LOG_CONTEXT); return reject(error); } diff --git a/apps/worker/src/app/workflow/services/index.ts b/apps/worker/src/app/workflow/services/index.ts index 228b77b38c1..ee0d3b62794 100644 --- a/apps/worker/src/app/workflow/services/index.ts +++ b/apps/worker/src/app/workflow/services/index.ts @@ -2,4 +2,5 @@ export * from './active-jobs-metric.service'; export * from './completed-jobs-metric.service'; export * from './standard.worker'; export * from './workflow.worker'; +export * from './old-instance-standard.worker'; export * from './old-instance-workflow.worker'; diff --git a/apps/worker/src/app/workflow/services/old-instance-standard.worker.ts b/apps/worker/src/app/workflow/services/old-instance-standard.worker.ts new file mode 100644 index 00000000000..e8fdde4afd8 --- /dev/null +++ b/apps/worker/src/app/workflow/services/old-instance-standard.worker.ts @@ -0,0 +1,199 @@ +const nr = require('newrelic'); +import { forwardRef, Inject, Injectable, Logger } from '@nestjs/common'; +import { IJobData, ObservabilityBackgroundTransactionEnum } from '@novu/shared'; +import { + INovuWorker, + Job, + OldInstanceBullMqService, + PinoLogger, + storage, + Store, + OldInstanceStandardWorkerService, + WorkerOptions, +} from '@novu/application-generic'; + +import { + RunJob, + RunJobCommand, + SetJobAsCommand, + SetJobAsCompleted, + SetJobAsFailed, + SetJobAsFailedCommand, + WebhookFilterBackoffStrategy, + HandleLastFailedJobCommand, + HandleLastFailedJob, +} from '../usecases'; + +const LOG_CONTEXT = 'OldInstanceStandardWorker'; + +/** + * TODO: Temporary for migration to MemoryDB + */ +@Injectable() +export class OldInstanceStandardWorker extends OldInstanceStandardWorkerService implements INovuWorker { + constructor( + private handleLastFailedJob: HandleLastFailedJob, + private runJob: RunJob, + @Inject(forwardRef(() => SetJobAsCompleted)) private setJobAsCompleted: SetJobAsCompleted, + @Inject(forwardRef(() => SetJobAsFailed)) private setJobAsFailed: SetJobAsFailed, + @Inject(forwardRef(() => WebhookFilterBackoffStrategy)) + private webhookFilterBackoffStrategy: WebhookFilterBackoffStrategy + ) { + super(); + + this.initWorker(this.getWorkerProcessor(), this.getWorkerOptions()); + + if (this.bullMqService.enabled) { + this.worker.on('completed', async (job: Job): Promise => { + await this.jobHasCompleted(job); + }); + + this.worker.on('failed', async (job: Job, error: Error): Promise => { + await this.jobHasFailed(job, error); + }); + } + } + + private getWorkerOptions(): WorkerOptions { + return { + lockDuration: 90000, + concurrency: 200, + settings: { + backoffStrategy: this.getBackoffStrategies(), + }, + }; + } + + private extractMinimalJobData(job: any): { + environmentId: string; + organizationId: string; + jobId: string; + userId: string; + } { + const { _environmentId: environmentId, _id: jobId, _organizationId: organizationId, _userId: userId } = job; + + if (!environmentId || !jobId || !organizationId || !userId) { + const message = job.payload.message; + + return { + environmentId: message._environmentId, + jobId: message._jobId, + organizationId: message._organizationId, + userId: job.userId, + }; + } + + return { + environmentId, + jobId, + organizationId, + userId, + }; + } + + private getWorkerProcessor() { + return async ({ data }: { data: IJobData | any }) => { + const minimalJobData = this.extractMinimalJobData(data); + + Logger.verbose(`Job ${minimalJobData.jobId} is being processed in the old instance standard worker`, LOG_CONTEXT); + + return await new Promise(async (resolve, reject) => { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const _this = this; + + nr.startBackgroundTransaction( + ObservabilityBackgroundTransactionEnum.JOB_PROCESSING_QUEUE, + 'Trigger Engine', + function () { + const transaction = nr.getTransaction(); + + storage.run(new Store(PinoLogger.root), () => { + _this.runJob + .execute(RunJobCommand.create(minimalJobData)) + .then(resolve) + .catch((error) => { + Logger.error( + error, + `Failed to run the job ${minimalJobData.jobId} during worker processing`, + LOG_CONTEXT + ); + + return reject(error); + }) + .finally(() => { + transaction.end(); + }); + }); + } + ); + }); + }; + } + + private async jobHasCompleted(job: Job): Promise { + let jobId; + + try { + const minimalData = this.extractMinimalJobData(job.data); + jobId = minimalData.jobId; + const environmentId = minimalData.environmentId; + const userId = minimalData.userId; + + await this.setJobAsCompleted.execute( + SetJobAsCommand.create({ + environmentId, + jobId, + userId, + }) + ); + Logger.verbose({ job }, `Job ${jobId} set as completed`, LOG_CONTEXT); + } catch (error) { + Logger.error(error, `Failed to set job ${jobId} as completed`, LOG_CONTEXT); + } + } + + private async jobHasFailed(job: Job, error: Error): Promise { + let jobId; + + try { + const minimalData = this.extractMinimalJobData(job.data); + jobId = minimalData.jobId; + + const hasToBackoff = this.runJob.shouldBackoff(error); + const hasReachedMaxAttempts = job.attemptsMade >= this.DEFAULT_ATTEMPTS; + const shouldHandleLastFailedJob = hasToBackoff && hasReachedMaxAttempts; + + const shouldBeSetAsFailed = !hasToBackoff || shouldHandleLastFailedJob; + if (shouldBeSetAsFailed) { + await this.setJobAsFailed.execute(SetJobAsFailedCommand.create(minimalData), error); + } + + if (shouldHandleLastFailedJob) { + const handleLastFailedJobCommand = HandleLastFailedJobCommand.create({ + ...minimalData, + error, + }); + + await this.handleLastFailedJob.execute(handleLastFailedJobCommand); + } + Logger.verbose({ job }, `Job ${jobId} set as failed`, LOG_CONTEXT); + } catch (anotherError) { + Logger.error(anotherError, `Failed to set job ${jobId} as failed`, LOG_CONTEXT); + } + } + + private getBackoffStrategies = () => { + return async (attemptsMade: number, type: string, eventError: Error, eventJob: Job): Promise => { + const command = { + attemptsMade, + environmentId: eventJob?.data?._environmentId, + eventError, + eventJob, + organizationId: eventJob?.data?._organizationId, + userId: eventJob?.data?._userId, + }; + + return await this.webhookFilterBackoffStrategy.execute(command); + }; + }; +} diff --git a/apps/worker/src/app/workflow/services/old-instance-workflow.worker.ts b/apps/worker/src/app/workflow/services/old-instance-workflow.worker.ts index 56e7fa41ac0..60d6535c07f 100644 --- a/apps/worker/src/app/workflow/services/old-instance-workflow.worker.ts +++ b/apps/worker/src/app/workflow/services/old-instance-workflow.worker.ts @@ -9,21 +9,10 @@ import { storage, Store, OldInstanceWorkflowWorkerService, + TriggerEvent, WorkerOptions, } from '@novu/application-generic'; -import { - RunJob, - RunJobCommand, - SetJobAsCommand, - SetJobAsCompleted, - SetJobAsFailed, - SetJobAsFailedCommand, - WebhookFilterBackoffStrategy, - HandleLastFailedJobCommand, - HandleLastFailedJob, -} from '../usecases'; - const LOG_CONTEXT = 'OldInstanceWorkflowWorker'; /** @@ -31,93 +20,38 @@ const LOG_CONTEXT = 'OldInstanceWorkflowWorker'; */ @Injectable() export class OldInstanceWorkflowWorker extends OldInstanceWorkflowWorkerService implements INovuWorker { - constructor( - private handleLastFailedJob: HandleLastFailedJob, - private runJob: RunJob, - @Inject(forwardRef(() => SetJobAsCompleted)) private setJobAsCompleted: SetJobAsCompleted, - @Inject(forwardRef(() => SetJobAsFailed)) private setJobAsFailed: SetJobAsFailed, - @Inject(forwardRef(() => WebhookFilterBackoffStrategy)) - private webhookFilterBackoffStrategy: WebhookFilterBackoffStrategy - ) { + constructor(private triggerEventUsecase: TriggerEvent) { super(); this.initWorker(this.getWorkerProcessor(), this.getWorkerOptions()); - - if (this.bullMqService.enabled) { - this.worker.on('completed', async (job: Job): Promise => { - await this.jobHasCompleted(job); - }); - - this.worker.on('failed', async (job: Job, error: Error): Promise => { - await this.jobHasFailed(job, error); - }); - } } private getWorkerOptions(): WorkerOptions { return { lockDuration: 90000, concurrency: 200, - settings: { - backoffStrategy: this.getBackoffStrategies(), - }, - }; - } - - private extractMinimalJobData(job: any): { - environmentId: string; - organizationId: string; - jobId: string; - userId: string; - } { - const { _environmentId: environmentId, _id: jobId, _organizationId: organizationId, _userId: userId } = job; - - if (!environmentId || !jobId || !organizationId || !userId) { - const message = job.payload.message; - - return { - environmentId: message._environmentId, - jobId: message._jobId, - organizationId: message._organizationId, - userId: job.userId, - }; - } - - return { - environmentId, - jobId, - organizationId, - userId, }; } private getWorkerProcessor() { return async ({ data }: { data: IJobData | any }) => { - const minimalJobData = this.extractMinimalJobData(data); - return await new Promise(async (resolve, reject) => { // eslint-disable-next-line @typescript-eslint/no-this-alias const _this = this; + Logger.verbose(`Job ${data._id} is being processed in the old instance workflow worker`, LOG_CONTEXT); + nr.startBackgroundTransaction( - ObservabilityBackgroundTransactionEnum.JOB_PROCESSING_QUEUE, + ObservabilityBackgroundTransactionEnum.TRIGGER_HANDLER_QUEUE, 'Trigger Engine', function () { const transaction = nr.getTransaction(); storage.run(new Store(PinoLogger.root), () => { - _this.runJob - .execute(RunJobCommand.create(minimalJobData)) + _this.triggerEventUsecase + .execute(data) .then(resolve) - .catch((error) => { - Logger.error( - error, - `Failed to run the job ${minimalJobData.jobId} during worker processing`, - LOG_CONTEXT - ); - - return reject(error); - }) + .catch(reject) .finally(() => { transaction.end(); }); @@ -127,71 +61,4 @@ export class OldInstanceWorkflowWorker extends OldInstanceWorkflowWorkerService }); }; } - - private async jobHasCompleted(job: Job): Promise { - let jobId; - - try { - const minimalData = this.extractMinimalJobData(job.data); - jobId = minimalData.jobId; - const environmentId = minimalData.environmentId; - const userId = minimalData.userId; - - await this.setJobAsCompleted.execute( - SetJobAsCommand.create({ - environmentId, - jobId, - userId, - }) - ); - Logger.verbose({ job }, `Job ${jobId} set as completed`, LOG_CONTEXT); - } catch (error) { - Logger.error(error, `Failed to set job ${jobId} as completed`, LOG_CONTEXT); - } - } - - private async jobHasFailed(job: Job, error: Error): Promise { - let jobId; - - try { - const minimalData = this.extractMinimalJobData(job.data); - jobId = minimalData.jobId; - - const hasToBackoff = this.runJob.shouldBackoff(error); - const hasReachedMaxAttempts = job.attemptsMade >= this.DEFAULT_ATTEMPTS; - const shouldHandleLastFailedJob = hasToBackoff && hasReachedMaxAttempts; - - const shouldBeSetAsFailed = !hasToBackoff || shouldHandleLastFailedJob; - if (shouldBeSetAsFailed) { - await this.setJobAsFailed.execute(SetJobAsFailedCommand.create(minimalData), error); - } - - if (shouldHandleLastFailedJob) { - const handleLastFailedJobCommand = HandleLastFailedJobCommand.create({ - ...minimalData, - error, - }); - - await this.handleLastFailedJob.execute(handleLastFailedJobCommand); - } - Logger.verbose({ job }, `Job ${jobId} set as failed`, LOG_CONTEXT); - } catch (anotherError) { - Logger.error(anotherError, `Failed to set job ${jobId} as failed`, LOG_CONTEXT); - } - } - - private getBackoffStrategies = () => { - return async (attemptsMade: number, type: string, eventError: Error, eventJob: Job): Promise => { - const command = { - attemptsMade, - environmentId: eventJob?.data?._environmentId, - eventError, - eventJob, - organizationId: eventJob?.data?._organizationId, - userId: eventJob?.data?._userId, - }; - - return await this.webhookFilterBackoffStrategy.execute(command); - }; - }; } diff --git a/apps/worker/src/app/workflow/services/standard.worker.ts b/apps/worker/src/app/workflow/services/standard.worker.ts index a8dc38c9b15..3b4cca0254d 100644 --- a/apps/worker/src/app/workflow/services/standard.worker.ts +++ b/apps/worker/src/app/workflow/services/standard.worker.ts @@ -94,6 +94,8 @@ export class StandardWorker extends StandardWorkerService implements INovuWorker return async ({ data }: { data: IJobData | any }) => { const minimalJobData = this.extractMinimalJobData(data); + Logger.verbose(`Job ${minimalJobData.jobId} is being processed in the new instance standard worker`, LOG_CONTEXT); + return await new Promise(async (resolve, reject) => { // eslint-disable-next-line @typescript-eslint/no-this-alias const _this = this; diff --git a/apps/worker/src/app/workflow/services/workflow.worker.ts b/apps/worker/src/app/workflow/services/workflow.worker.ts index 4a7d9b309e7..34c67d1dd45 100644 --- a/apps/worker/src/app/workflow/services/workflow.worker.ts +++ b/apps/worker/src/app/workflow/services/workflow.worker.ts @@ -36,6 +36,8 @@ export class WorkflowWorker extends WorkflowWorkerService implements INovuWorker // eslint-disable-next-line @typescript-eslint/no-this-alias const _this = this; + Logger.verbose(`Job ${data.identifier} is being processed in the new instance workflow worker`, LOG_CONTEXT); + nr.startBackgroundTransaction( ObservabilityBackgroundTransactionEnum.TRIGGER_HANDLER_QUEUE, 'Trigger Engine', diff --git a/apps/worker/src/app/workflow/usecases/run-job/run-job.usecase.ts b/apps/worker/src/app/workflow/usecases/run-job/run-job.usecase.ts index f7b1f2b4e5b..8800afe06c4 100644 --- a/apps/worker/src/app/workflow/usecases/run-job/run-job.usecase.ts +++ b/apps/worker/src/app/workflow/usecases/run-job/run-job.usecase.ts @@ -1,3 +1,5 @@ +const nr = require('newrelic'); + import { Injectable, Logger } from '@nestjs/common'; import { JobEntity, JobRepository, JobStatusEnum } from '@novu/dal'; import { StepTypeEnum } from '@novu/shared'; @@ -33,14 +35,19 @@ export class RunJob { if (!job) throw new PlatformException(`Job with id ${command.jobId} not found`); try { - this.logger?.assign({ + const contextData = { transactionId: job.transactionId, environmentId: job._environmentId, organizationId: job._organizationId, jobId: job._id, - }); + jobType: job.type, + }; + + nr.addCustomAttributes(contextData); + + this.logger?.assign(contextData); } catch (e) { - Logger.error(e, 'RunJob'); + Logger.error(e, 'RunJob', LOG_CONTEXT); } const canceled = await this.delayedEventIsCanceled(job); diff --git a/apps/worker/src/app/workflow/usecases/send-message/send-message.usecase.ts b/apps/worker/src/app/workflow/usecases/send-message/send-message.usecase.ts index d68528ac9f0..41b4b112b48 100644 --- a/apps/worker/src/app/workflow/usecases/send-message/send-message.usecase.ts +++ b/apps/worker/src/app/workflow/usecases/send-message/send-message.usecase.ts @@ -19,6 +19,8 @@ import { GetSubscriberTemplatePreference, GetSubscriberTemplatePreferenceCommand, Instrument, + GetSubscriberGlobalPreference, + GetSubscriberGlobalPreferenceCommand, } from '@novu/application-generic'; import { JobEntity, @@ -51,6 +53,7 @@ export class SendMessage { private digest: Digest, private createExecutionDetails: CreateExecutionDetails, private getSubscriberTemplatePreferenceUsecase: GetSubscriberTemplatePreference, + private getSubscriberGlobalPreferenceUsecase: GetSubscriberGlobalPreference, private notificationTemplateRepository: NotificationTemplateRepository, private jobRepository: JobRepository, private sendMessageDelay: SendMessageDelay, @@ -85,7 +88,7 @@ export class SendMessage { }; } - this.analyticsService.track('Process Workflow Step - [Triggers]', command.userId, { + this.analyticsService.mixpanelTrack('Process Workflow Step - [Triggers]', '', { _template: command.job._templateId, _organization: command.organizationId, _environment: command.environmentId, @@ -200,6 +203,32 @@ export class SendMessage { }); if (!subscriber) throw new PlatformException('Subscriber not found with id ' + job._subscriberId); + const { preference: globalPreference } = await this.getSubscriberGlobalPreferenceUsecase.execute( + GetSubscriberGlobalPreferenceCommand.create({ + organizationId: job._organizationId, + environmentId: job._environmentId, + subscriberId: job.subscriberId, + }) + ); + + const globalPreferenceResult = this.stepPreferred(globalPreference, job); + + if (!globalPreferenceResult) { + await this.createExecutionDetails.execute( + CreateExecutionDetailsCommand.create({ + ...CreateExecutionDetailsCommand.getDetailsFromJob(job), + detail: DetailEnum.STEP_FILTERED_BY_GLOBAL_PREFERENCES, + source: ExecutionDetailsSourceEnum.INTERNAL, + status: ExecutionDetailsStatusEnum.SUCCESS, + isTest: false, + isRetry: false, + raw: JSON.stringify(globalPreference), + }) + ); + + return false; + } + const buildCommand = GetSubscriberTemplatePreferenceCommand.create({ organizationId: job._organizationId, subscriberId: subscriber.subscriberId, @@ -209,7 +238,6 @@ export class SendMessage { }); const { preference } = await this.getSubscriberTemplatePreferenceUsecase.execute(buildCommand); - const result = this.stepPreferred(preference, job); if (!result) { @@ -244,9 +272,12 @@ export class SendMessage { private stepPreferred(preference: { enabled: boolean; channels: IPreferenceChannels }, job: JobEntity) { const templatePreferred = preference.enabled; - const channelPreferred = Object.keys(preference.channels).some( - (channelKey) => channelKey === job.type && preference.channels[job.type] - ); + const channels = Object.keys(preference.channels); + // Handles the case where the channel is not defined in the preference. i.e, channels = {} + const channelPreferred = + channels.length > 0 + ? channels.some((channelKey) => channelKey === job.type && preference.channels[job.type]) + : true; return templatePreferred && channelPreferred; } diff --git a/apps/worker/src/app/workflow/workflow.module.ts b/apps/worker/src/app/workflow/workflow.module.ts index 5c60966f028..81dbc4731ce 100644 --- a/apps/worker/src/app/workflow/workflow.module.ts +++ b/apps/worker/src/app/workflow/workflow.module.ts @@ -15,6 +15,7 @@ import { GetNovuLayout, GetNovuProviderCredentials, GetSubscriberPreference, + GetSubscriberGlobalPreference, GetSubscriberTemplatePreference, ProcessTenant, OldInstanceBullMqService, @@ -34,6 +35,7 @@ import { StandardWorker, WorkflowWorker, OldInstanceWorkflowWorker, + OldInstanceStandardWorker, } from './services'; import { @@ -80,6 +82,7 @@ const USE_CASES = [ GetNovuProviderCredentials, SelectIntegration, GetSubscriberPreference, + GetSubscriberGlobalPreference, GetSubscriberTemplatePreference, HandleLastFailedJob, MessageMatcher, @@ -111,6 +114,7 @@ const PROVIDERS: Provider[] = [ StandardWorker, WorkflowWorker, OldInstanceBullMqService, + OldInstanceStandardWorker, OldInstanceWorkflowWorker, ]; diff --git a/apps/ws/package.json b/apps/ws/package.json index 50946b41473..69628c19e86 100644 --- a/apps/ws/package.json +++ b/apps/ws/package.json @@ -1,6 +1,6 @@ { "name": "@novu/ws", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "", "author": "", "private": true, @@ -28,10 +28,10 @@ "@nestjs/swagger": "^7.1.9", "@nestjs/terminus": "^10.0.1", "@nestjs/websockets": "^10.2.2", - "@novu/application-generic": "^0.19.0", - "@novu/dal": "^0.19.0", - "@novu/shared": "^0.19.0", - "@novu/testing": "^0.19.0", + "@novu/application-generic": "^0.20.0-alpha.0", + "@novu/dal": "^0.20.0-alpha.0", + "@novu/shared": "^0.20.0-alpha.0", + "@novu/testing": "^0.20.0-alpha.0", "@sentry/node": "^7.30.0", "@socket.io/redis-adapter": "^7.2.0", "class-transformer": "^0.5.1", diff --git a/apps/ws/src/socket/services/index.ts b/apps/ws/src/socket/services/index.ts index b03b9f0b02d..735d2d9ed04 100644 --- a/apps/ws/src/socket/services/index.ts +++ b/apps/ws/src/socket/services/index.ts @@ -1 +1,3 @@ +export { OldInstanceWebSocketsWorker } from './old-instance-web-sockets.worker'; +export { OldInstanceWebSocketsWorkerService } from './old-instance-web-sockets-worker.service'; export { WebSocketWorker } from './web-socket.worker'; diff --git a/apps/ws/src/socket/services/old-instance-web-sockets-worker.service.ts b/apps/ws/src/socket/services/old-instance-web-sockets-worker.service.ts new file mode 100644 index 00000000000..91ba7c714c6 --- /dev/null +++ b/apps/ws/src/socket/services/old-instance-web-sockets-worker.service.ts @@ -0,0 +1,91 @@ +import { IJobData, JobTopicNameEnum } from '@novu/shared'; +import { Inject, Injectable, Logger } from '@nestjs/common'; + +import { JobsOptions, OldInstanceBullMqService, Processor, Worker, WorkerOptions } from '@novu/application-generic'; + +const LOG_CONTEXT = 'OldInstanceWebSocketsWorkerService'; + +type WorkerProcessor = string | Processor | undefined; + +/** + * TODO: Temporary for migration to MemoryDB + */ +export class OldInstanceWebSocketsWorkerService { + private instance: OldInstanceBullMqService; + + public readonly DEFAULT_ATTEMPTS = 3; + public readonly topic: JobTopicNameEnum; + + constructor() { + this.topic = JobTopicNameEnum.WEB_SOCKETS; + this.instance = new OldInstanceBullMqService(); + if (this.instance.enabled) { + Logger.log(`Old instance Worker ${this.topic} instantiated`, LOG_CONTEXT); + } else { + Logger.warn( + `Old instance web sockets worker not instantiated as it is only needed for MemoryDB migration`, + LOG_CONTEXT + ); + } + } + + public get bullMqService(): OldInstanceBullMqService { + return this.instance; + } + + public get worker(): Worker { + return this.instance.worker; + } + + public initWorker(processor: WorkerProcessor, options?: WorkerOptions): void { + if (this.instance.enabled) { + this.createWorker(processor, options); + } + } + + public createWorker(processor: WorkerProcessor, options?: WorkerOptions): void { + if (this.instance.enabled) { + this.instance.createWorker(this.topic, processor, options); + } else { + Logger.log( + { enabled: this.instance.enabled }, + 'We are not running OldInstanceWorkflowWorkerService as it is not needed in this environment', + LOG_CONTEXT + ); + } + } + + public async isRunning(): Promise { + return await this.instance.isWorkerRunning(); + } + + public async isPaused(): Promise { + return await this.instance.isWorkerPaused(); + } + + public async pause(): Promise { + if (this.instance.enabled && this.worker) { + await this.instance.pauseWorker(); + } + } + + public async resume(): Promise { + if (this.instance.enabled && this.worker) { + await this.instance.resumeWorker(); + } + } + + public async gracefulShutdown(): Promise { + if (this.instance.enabled) { + Logger.log('Shutting the old web sockets Worker service down', LOG_CONTEXT); + + await this.instance.gracefulShutdown(); + + Logger.log('Shutting down the old web sockets Worker service has finished', LOG_CONTEXT); + } + } + + async onModuleDestroy(): Promise { + await this.gracefulShutdown(); + } +} diff --git a/apps/ws/src/socket/services/old-instance-web-sockets.worker.ts b/apps/ws/src/socket/services/old-instance-web-sockets.worker.ts new file mode 100644 index 00000000000..fea4f6138c6 --- /dev/null +++ b/apps/ws/src/socket/services/old-instance-web-sockets.worker.ts @@ -0,0 +1,71 @@ +const nr = require('newrelic'); +import { Injectable, Logger } from '@nestjs/common'; + +import { INovuWorker, WebSocketsWorkerService } from '@novu/application-generic'; + +import { ExternalServicesRoute, ExternalServicesRouteCommand } from '../usecases/external-services-route'; +import { ObservabilityBackgroundTransactionEnum } from '@novu/shared'; +import { OldInstanceWebSocketsWorkerService } from './old-instance-web-sockets-worker.service'; + +const LOG_CONTEXT = 'OldInstanceWebSocketsWorker'; + +@Injectable() +export class OldInstanceWebSocketsWorker extends OldInstanceWebSocketsWorkerService implements INovuWorker { + constructor(private externalServicesRoute: ExternalServicesRoute) { + super(); + + this.initWorker(this.getWorkerProcessor(), this.getWorkerOpts()); + } + + private getWorkerProcessor() { + return async (job) => { + return new Promise((resolve, reject) => { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const _this = this; + + Logger.verbose( + `Job ${job.id} / ${job.data.event} is being processed in the old instance web sockets worker`, + LOG_CONTEXT + ); + + nr.startBackgroundTransaction( + ObservabilityBackgroundTransactionEnum.WS_SOCKET_QUEUE, + 'WS Service', + function () { + const transaction = nr.getTransaction(); + + _this.externalServicesRoute + .execute( + ExternalServicesRouteCommand.create({ + userId: job.data.userId, + event: job.data.event, + payload: job.data.payload, + _environmentId: job.data._environmentId, + }) + ) + .then(resolve) + .catch((error) => { + Logger.error( + 'Unexpected exception occurred while handling external services route ', + error, + LOG_CONTEXT + ); + + reject(error); + }) + .finally(() => { + transaction.end(); + }); + } + ); + }); + }; + } + + private getWorkerOpts() { + return { + lockDuration: 90000, + concurrency: 100, + }; + } +} diff --git a/apps/ws/src/socket/services/web-socket.worker.ts b/apps/ws/src/socket/services/web-socket.worker.ts index 06bc7597074..dc07a2b3331 100644 --- a/apps/ws/src/socket/services/web-socket.worker.ts +++ b/apps/ws/src/socket/services/web-socket.worker.ts @@ -22,6 +22,11 @@ export class WebSocketWorker extends WebSocketsWorkerService implements INovuWor // eslint-disable-next-line @typescript-eslint/no-this-alias const _this = this; + Logger.verbose( + `Job ${job.id} / ${job.data.event} is being processed in the MemoryDB instance WebSocketWorker`, + LOG_CONTEXT + ); + nr.startBackgroundTransaction( ObservabilityBackgroundTransactionEnum.WS_SOCKET_QUEUE, 'WS Service', diff --git a/apps/ws/src/socket/socket.module.ts b/apps/ws/src/socket/socket.module.ts index 15173f355a1..2b29edf2f24 100644 --- a/apps/ws/src/socket/socket.module.ts +++ b/apps/ws/src/socket/socket.module.ts @@ -6,11 +6,17 @@ import { WSGateway } from './ws.gateway'; import { SharedModule } from '../shared/shared.module'; import { ExternalServicesRoute } from './usecases/external-services-route'; -import { WebSocketWorker } from './services'; +import { OldInstanceWebSocketsWorker, OldInstanceWebSocketsWorkerService, WebSocketWorker } from './services'; const USE_CASES: Provider[] = [ExternalServicesRoute]; -const PROVIDERS: Provider[] = [WSGateway, WebSocketsWorkerService, WebSocketWorker]; +const PROVIDERS: Provider[] = [ + WSGateway, + OldInstanceWebSocketsWorker, + OldInstanceWebSocketsWorkerService, + WebSocketsWorkerService, + WebSocketWorker, +]; @Module({ imports: [SharedModule], diff --git a/docker/Readme.md b/docker/Readme.md index 4cfac066b96..91bdc55bc5f 100644 --- a/docker/Readme.md +++ b/docker/Readme.md @@ -1,6 +1,6 @@ Docker is the easiest way to get started with self-hosted Novu, however if you want to set up the system on docker for local development look [here](local/Readme.md) -or if you want to deploy Novu to Kubernetes check [here](kubernetes/Readme.md) +or if you want to deploy Novu to Kubernetes using Helm check [here](kubernetes/helm/Readme.md) or using Kustomize check [here](kubernetes/helm/Readme.md). ## Before you begin diff --git a/enterprise/packages b/enterprise/packages deleted file mode 160000 index 8f0b31fcf98..00000000000 --- a/enterprise/packages +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8f0b31fcf987bd0626b80224d73349fcbf71ceea diff --git a/lerna.json b/lerna.json index d34c472a3d0..da11865f407 100644 --- a/lerna.json +++ b/lerna.json @@ -8,5 +8,5 @@ "message": "chore(release): publish - ci skip" } }, - "version": "0.19.0" + "version": "0.20.0-alpha.0" } diff --git a/libs/dal/package.json b/libs/dal/package.json index 876fa4ebaae..8a34231beeb 100644 --- a/libs/dal/package.json +++ b/libs/dal/package.json @@ -1,6 +1,6 @@ { "name": "@novu/dal", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "", "private": true, "scripts": { @@ -24,7 +24,7 @@ "@aws-sdk/client-s3": "^3.382.0", "@aws-sdk/s3-request-presigner": "^3.382.0", "@faker-js/faker": "^6.0.0", - "@novu/shared": "^0.19.0", + "@novu/shared": "^0.20.0-alpha.0", "@sendgrid/mail": "^7.4.2", "JSONStream": "^1.3.5", "archiver": "^5.0.0", diff --git a/libs/dal/src/repositories/subscriber-preference/subscriber-preference.entity.ts b/libs/dal/src/repositories/subscriber-preference/subscriber-preference.entity.ts index eb8c1a7ac13..c842f4829a4 100644 --- a/libs/dal/src/repositories/subscriber-preference/subscriber-preference.entity.ts +++ b/libs/dal/src/repositories/subscriber-preference/subscriber-preference.entity.ts @@ -13,14 +13,21 @@ export class SubscriberPreferenceEntity { _subscriberId: string; - _templateId: string; + _templateId?: string; enabled: boolean; channels: IPreferenceChannels; + + level: PreferenceLevelEnum; } export type SubscriberPreferenceDBModel = ChangePropsValueType< SubscriberPreferenceEntity, '_environmentId' | '_organizationId' | '_subscriberId' | '_templateId' >; + +export enum PreferenceLevelEnum { + GLOBAL = 'global', + TEMPLATE = 'template', +} diff --git a/libs/dal/src/repositories/subscriber-preference/subscriber-preference.schema.ts b/libs/dal/src/repositories/subscriber-preference/subscriber-preference.schema.ts index 4851e68efbf..f53ccc71729 100644 --- a/libs/dal/src/repositories/subscriber-preference/subscriber-preference.schema.ts +++ b/libs/dal/src/repositories/subscriber-preference/subscriber-preference.schema.ts @@ -2,7 +2,7 @@ import * as mongoose from 'mongoose'; import { Schema } from 'mongoose'; import { schemaOptions } from '../schema-default.options'; -import { SubscriberPreferenceDBModel } from './subscriber-preference.entity'; +import { PreferenceLevelEnum, SubscriberPreferenceDBModel } from './subscriber-preference.entity'; const subscriberPreferenceSchema = new Schema( { @@ -47,6 +47,10 @@ const subscriberPreferenceSchema = new Schema( type: Schema.Types.Boolean, }, }, + level: { + type: Schema.Types.String, + enum: PreferenceLevelEnum, + }, }, schemaOptions ); diff --git a/libs/embed/package.json b/libs/embed/package.json index af638ac532e..1eaa5658b1a 100644 --- a/libs/embed/package.json +++ b/libs/embed/package.json @@ -1,6 +1,6 @@ { "name": "@novu/embed", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "private": true, "description": "", "keywords": [], @@ -118,7 +118,7 @@ "typescript": "4.9.5" }, "dependencies": { - "@novu/notification-center": "^0.19.0", + "@novu/notification-center": "^0.20.0-alpha.0", "@types/iframe-resizer": "^3.5.8", "iframe-resizer": "^4.3.1" } diff --git a/libs/shared/package.json b/libs/shared/package.json index e4e85cfbe3f..a56af53b5ec 100644 --- a/libs/shared/package.json +++ b/libs/shared/package.json @@ -1,6 +1,6 @@ { "name": "@novu/shared", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "", "scripts": { "start": "npm run start:dev", diff --git a/libs/shared/src/consts/providers/channels/email.ts b/libs/shared/src/consts/providers/channels/email.ts index e15a681884d..c9aadaa8635 100644 --- a/libs/shared/src/consts/providers/channels/email.ts +++ b/libs/shared/src/consts/providers/channels/email.ts @@ -2,6 +2,7 @@ import { mailerSendConfig, mailgunConfig, mailjetConfig, + mailtrapConfig, mandrillConfig, netCoreConfig, nodemailerConfig, @@ -46,6 +47,14 @@ export const emailProviders: IProviderConfig[] = [ docReference: 'https://docs.novu.co/channels-and-providers/email/mailjet', logoFileName: { light: 'mailjet.png', dark: 'mailjet.png' }, }, + { + id: EmailProviderIdEnum.Mailtrap, + displayName: 'Mailtrap', + channel: ChannelTypeEnum.EMAIL, + credentials: mailtrapConfig, + docReference: 'https://docs.novu.co/channels-and-providers/email/mailtrap', + logoFileName: { light: 'mailtrap.svg', dark: 'mailtrap.svg' }, + }, { id: EmailProviderIdEnum.Mandrill, displayName: 'Mandrill', diff --git a/libs/shared/src/consts/providers/credentials/provider-credentials.ts b/libs/shared/src/consts/providers/credentials/provider-credentials.ts index 7df6a940ace..f48e8c106fe 100644 --- a/libs/shared/src/consts/providers/credentials/provider-credentials.ts +++ b/libs/shared/src/consts/providers/credentials/provider-credentials.ts @@ -220,6 +220,16 @@ export const resendConfig: IConfigCredentials[] = [ ...mailConfigBase, ]; +export const mailtrapConfig: IConfigCredentials[] = [ + { + key: CredentialsKeyEnum.ApiKey, + displayName: 'API Key', + type: 'string', + required: true, + }, + ...mailConfigBase, +]; + export const plunkConfig: IConfigCredentials[] = [ { key: CredentialsKeyEnum.ApiKey, diff --git a/libs/shared/src/consts/providers/provider.enum.ts b/libs/shared/src/consts/providers/provider.enum.ts index 2c763afc11d..9a59244472b 100644 --- a/libs/shared/src/consts/providers/provider.enum.ts +++ b/libs/shared/src/consts/providers/provider.enum.ts @@ -44,6 +44,7 @@ export enum EmailProviderIdEnum { Resend = 'resend', Plunk = 'plunk', MailerSend = 'mailersend', + Mailtrap = 'mailtrap', Clickatell = 'clickatell', Outlook365 = 'outlook365', Novu = 'novu-email', diff --git a/libs/shared/src/entities/subscriber-preference/subscriber-preference.interface.ts b/libs/shared/src/entities/subscriber-preference/subscriber-preference.interface.ts index 4a0628a5e90..10da9d797df 100644 --- a/libs/shared/src/entities/subscriber-preference/subscriber-preference.interface.ts +++ b/libs/shared/src/entities/subscriber-preference/subscriber-preference.interface.ts @@ -28,3 +28,8 @@ export interface ITemplateConfiguration { critical: boolean; tags?: string[]; } + +export enum PreferenceLevelEnum { + GLOBAL = 'global', + TEMPLATE = 'template', +} diff --git a/libs/testing/package.json b/libs/testing/package.json index 8f075822785..fa24b022bb3 100644 --- a/libs/testing/package.json +++ b/libs/testing/package.json @@ -1,6 +1,6 @@ { "name": "@novu/testing", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "", "private": true, "scripts": { @@ -22,8 +22,8 @@ "types": "dist/index.d.ts", "dependencies": { "@faker-js/faker": "^6.0.0", - "@novu/dal": "^0.19.0", - "@novu/shared": "^0.19.0", + "@novu/dal": "^0.20.0-alpha.0", + "@novu/shared": "^0.20.0-alpha.0", "JSONStream": "^1.3.5", "async": "^3.2.0", "axios": "^1.3.3", diff --git a/packages/application-generic/package.json b/packages/application-generic/package.json index 7629b5c35d8..02463908e22 100644 --- a/packages/application-generic/package.json +++ b/packages/application-generic/package.json @@ -1,6 +1,6 @@ { "name": "@novu/application-generic", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "Generic backend code used inside of Novu's different services", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -35,10 +35,10 @@ "peerDependencies": { "@nestjs/common": ">=10", "@nestjs/core": ">=10", + "@nestjs/jwt": "^10.1.0", "@nestjs/swagger": ">=6", "@nestjs/terminus": ">=10", "@nestjs/testing": ">=10", - "@nestjs/jwt": "^10.1.0", "newrelic": "^9", "reflect-metadata": "^0.1.13" }, @@ -47,52 +47,53 @@ "@aws-sdk/s3-request-presigner": "^3.382.0", "@azure/storage-blob": "^12.11.0", "@google-cloud/storage": "^6.2.3", - "@novu/africas-talking": "^0.19.0", - "@novu/apns": "^0.19.0", - "@novu/burst-sms": "^0.19.0", - "@novu/clickatell": "^0.19.0", - "@novu/dal": "^0.19.0", - "@novu/discord": "^0.19.0", - "@novu/email-webhook": "^0.19.0", - "@novu/emailjs": "^0.19.0", - "@novu/expo": "^0.19.0", - "@novu/fcm": "^0.19.0", - "@novu/firetext": "^0.19.0", - "@novu/forty-six-elks": "^0.19.0", - "@novu/gupshup": "^0.19.0", - "@novu/infobip": "^0.19.0", - "@novu/kannel": "^0.19.0", - "@novu/mailersend": "^0.19.0", - "@novu/mailgun": "^0.19.0", - "@novu/mailjet": "^0.19.0", - "@novu/mandrill": "^0.19.0", - "@novu/maqsam": "^0.19.0", - "@novu/mattermost": "^0.19.0", - "@novu/ms-teams": "^0.19.0", - "@novu/netcore": "^0.19.0", - "@novu/nodemailer": "^0.19.0", - "@novu/one-signal": "^0.19.0", - "@novu/outlook365": "^0.19.0", - "@novu/plivo": "^0.19.0", - "@novu/plunk": "^0.19.0", - "@novu/postmark": "^0.19.0", - "@novu/push-webhook": "^0.19.0", - "@novu/resend": "^0.19.0", - "@novu/sendchamp": "^0.19.0", - "@novu/sendgrid": "^0.19.0", - "@novu/sendinblue": "^0.19.0", - "@novu/ses": "^0.19.0", - "@novu/shared": "^0.19.0", - "@novu/slack": "^0.19.0", - "@novu/sms-central": "^0.19.0", - "@novu/sms77": "^0.19.0", - "@novu/sns": "^0.19.0", - "@novu/sparkpost": "^0.19.0", - "@novu/stateless": "^0.19.0", - "@novu/telnyx": "^0.19.0", - "@novu/termii": "^0.19.0", - "@novu/testing": "^0.19.0", - "@novu/twilio": "^0.19.0", + "@novu/africas-talking": "^0.20.0-alpha.0", + "@novu/apns": "^0.20.0-alpha.0", + "@novu/burst-sms": "^0.20.0-alpha.0", + "@novu/clickatell": "^0.20.0-alpha.0", + "@novu/dal": "^0.20.0-alpha.0", + "@novu/discord": "^0.20.0-alpha.0", + "@novu/email-webhook": "^0.20.0-alpha.0", + "@novu/emailjs": "^0.20.0-alpha.0", + "@novu/expo": "^0.20.0-alpha.0", + "@novu/fcm": "^0.20.0-alpha.0", + "@novu/firetext": "^0.20.0-alpha.0", + "@novu/forty-six-elks": "^0.20.0-alpha.0", + "@novu/gupshup": "^0.20.0-alpha.0", + "@novu/infobip": "^0.20.0-alpha.0", + "@novu/kannel": "^0.20.0-alpha.0", + "@novu/mailersend": "^0.20.0-alpha.0", + "@novu/mailgun": "^0.20.0-alpha.0", + "@novu/mailjet": "^0.20.0-alpha.0", + "@novu/mailtrap": "^0.20.0-alpha.0", + "@novu/mandrill": "^0.20.0-alpha.0", + "@novu/maqsam": "^0.20.0-alpha.0", + "@novu/mattermost": "^0.20.0-alpha.0", + "@novu/ms-teams": "^0.20.0-alpha.0", + "@novu/netcore": "^0.20.0-alpha.0", + "@novu/nodemailer": "^0.20.0-alpha.0", + "@novu/one-signal": "^0.20.0-alpha.0", + "@novu/outlook365": "^0.20.0-alpha.0", + "@novu/plivo": "^0.20.0-alpha.0", + "@novu/plunk": "^0.20.0-alpha.0", + "@novu/postmark": "^0.20.0-alpha.0", + "@novu/push-webhook": "^0.20.0-alpha.0", + "@novu/resend": "^0.20.0-alpha.0", + "@novu/sendchamp": "^0.20.0-alpha.0", + "@novu/sendgrid": "^0.20.0-alpha.0", + "@novu/sendinblue": "^0.20.0-alpha.0", + "@novu/ses": "^0.20.0-alpha.0", + "@novu/shared": "^0.20.0-alpha.0", + "@novu/slack": "^0.20.0-alpha.0", + "@novu/sms-central": "^0.20.0-alpha.0", + "@novu/sms77": "^0.20.0-alpha.0", + "@novu/sns": "^0.20.0-alpha.0", + "@novu/sparkpost": "^0.20.0-alpha.0", + "@novu/stateless": "^0.20.0-alpha.0", + "@novu/telnyx": "^0.20.0-alpha.0", + "@novu/termii": "^0.20.0-alpha.0", + "@novu/testing": "^0.20.0-alpha.0", + "@novu/twilio": "^0.20.0-alpha.0", "@sentry/node": "^7.12.1", "analytics-node": "^6.2.0", "bullmq": "^3.10.2", @@ -103,6 +104,7 @@ "ioredis": "^5.2.4", "launchdarkly-node-server-sdk": "^7.0.1", "lodash": "^4.17.15", + "mixpanel": "^0.17.0", "nestjs-pino": "^3.4.0", "node-fetch": "^3.2.10", "pino-http": "^8.3.3", diff --git a/packages/application-generic/src/factories/mail/handlers/index.ts b/packages/application-generic/src/factories/mail/handlers/index.ts index 439e1d4913a..78be1d72848 100644 --- a/packages/application-generic/src/factories/mail/handlers/index.ts +++ b/packages/application-generic/src/factories/mail/handlers/index.ts @@ -2,6 +2,7 @@ export * from './sendgrid.handler'; export * from './mailgun.handler'; export * from './emailjs.handler'; export * from './mailjet.handler'; +export * from './mailtrap.handler'; export * from './mandrill.handler'; export * from './nodemailer.handler'; export * from './postmark.handler'; diff --git a/packages/application-generic/src/factories/mail/handlers/mailtrap.handler.ts b/packages/application-generic/src/factories/mail/handlers/mailtrap.handler.ts new file mode 100644 index 00000000000..30fe3eecec2 --- /dev/null +++ b/packages/application-generic/src/factories/mail/handlers/mailtrap.handler.ts @@ -0,0 +1,22 @@ +import { + ChannelTypeEnum, + ICredentials, + EmailProviderIdEnum, +} from '@novu/shared'; +import { MailtrapEmailProvider } from '@novu/mailtrap'; +import { BaseHandler } from './base.handler'; + +export class MailtrapHandler extends BaseHandler { + constructor() { + super(EmailProviderIdEnum.Mailtrap, ChannelTypeEnum.EMAIL); + } + + buildProvider(credentials: ICredentials, from: string) { + const config: { apiKey: string; from: string } = { + from: from as string, + apiKey: credentials.apiKey as string, + }; + + this.provider = new MailtrapEmailProvider(config); + } +} diff --git a/packages/application-generic/src/factories/mail/handlers/resend.handler.ts b/packages/application-generic/src/factories/mail/handlers/resend.handler.ts index c2ff2108ba7..ee333d63d82 100644 --- a/packages/application-generic/src/factories/mail/handlers/resend.handler.ts +++ b/packages/application-generic/src/factories/mail/handlers/resend.handler.ts @@ -7,9 +7,10 @@ export class ResendHandler extends BaseHandler { super('resend', ChannelTypeEnum.EMAIL); } buildProvider(credentials: ICredentials, from?: string) { - const config: { apiKey: string; from: string } = { + const config: { apiKey: string; from: string; senderName?: string } = { from: from as string, apiKey: credentials.apiKey as string, + senderName: credentials.senderName, }; this.provider = new ResendEmailProvider(config); diff --git a/packages/application-generic/src/factories/mail/mail.factory.ts b/packages/application-generic/src/factories/mail/mail.factory.ts index 6d58f4acd2d..374e101f4d9 100644 --- a/packages/application-generic/src/factories/mail/mail.factory.ts +++ b/packages/application-generic/src/factories/mail/mail.factory.ts @@ -4,6 +4,7 @@ import { MailgunHandler, EmailJsHandler, MailjetHandler, + MailtrapHandler, MandrillHandler, NodemailerHandler, PostmarkHandler, @@ -28,6 +29,7 @@ export class MailFactory { new NetCoreHandler(), new EmailJsHandler(), new MailjetHandler(), + new MailtrapHandler(), new MandrillHandler(), new NodemailerHandler(), new PostmarkHandler(), diff --git a/packages/application-generic/src/modules/queues.module.ts b/packages/application-generic/src/modules/queues.module.ts index 63ff7946cde..5d2d1cfe771 100644 --- a/packages/application-generic/src/modules/queues.module.ts +++ b/packages/application-generic/src/modules/queues.module.ts @@ -29,6 +29,7 @@ import { StandardWorkerService, WebSocketsWorkerService, WorkflowWorkerService, + OldInstanceStandardWorkerService, OldInstanceWorkflowWorkerService, } from '../services/workers'; @@ -54,6 +55,7 @@ const PROVIDERS: Provider[] = [ WorkflowQueueService, WorkflowQueueServiceHealthIndicator, WorkflowWorkerService, + OldInstanceStandardWorkerService, OldInstanceWorkflowWorkerService, OldInstanceBullMqService, ]; diff --git a/packages/application-generic/src/services/analytics.service.ts b/packages/application-generic/src/services/analytics.service.ts index f91112773a7..47ecf50d732 100644 --- a/packages/application-generic/src/services/analytics.service.ts +++ b/packages/application-generic/src/services/analytics.service.ts @@ -1,5 +1,6 @@ import Analytics from 'analytics-node'; import { Logger } from '@nestjs/common'; +import * as Mixpanel from 'mixpanel'; // Due to problematic analytics-node types, we need to use require // eslint-disable-next-line @typescript-eslint/naming-convention @@ -23,7 +24,7 @@ const LOG_CONTEXT = 'AnalyticsService'; export class AnalyticsService { private segment: Analytics; - + private mixpanel: Mixpanel.Mixpanel; constructor(private segmentToken?: string | null, private batchSize = 100) {} async initialize() { @@ -32,6 +33,10 @@ export class AnalyticsService { flushAt: this.batchSize, }); } + + if (process.env.MIXPANEL_TOKEN) { + this.mixpanel = Mixpanel.init(process.env.MIXPANEL_TOKEN); + } } upsertGroup( @@ -104,6 +109,7 @@ export class AnalyticsService { { name, data, + source: 'segment', }, LOG_CONTEXT ); @@ -128,7 +134,46 @@ export class AnalyticsService { } } + mixpanelTrack( + name: string, + userId: string, + data: Record = {} + ) { + if (this.mixpanelEnabled) { + Logger.log( + 'Tracking event: ' + name, + { + name, + data, + source: 'mixpanel', + }, + LOG_CONTEXT + ); + + try { + this.mixpanel.track(name, { + distinct_id: userId, + ...data, + }); + } catch (error: any) { + Logger.error( + { + eventName: name, + usedId: userId, + message: error?.message, + }, + 'There has been an error when tracking mixpanel', + LOG_CONTEXT + ); + } + } + } + private get segmentEnabled() { return process.env.NODE_ENV !== 'test' && this.segment; } + + private get mixpanelEnabled() { + return process.env.NODE_ENV !== 'test' && this.mixpanel; + } } diff --git a/packages/application-generic/src/services/index.ts b/packages/application-generic/src/services/index.ts index f3f71f1989b..a6d6f0dcf89 100644 --- a/packages/application-generic/src/services/index.ts +++ b/packages/application-generic/src/services/index.ts @@ -16,6 +16,7 @@ export { BullMqService, Job, JobsOptions, + Processor, Queue, QueueBaseOptions, QueueOptions, diff --git a/packages/application-generic/src/services/workers/index.ts b/packages/application-generic/src/services/workers/index.ts index ee6f6d9b4dd..2a2eb18fb55 100644 --- a/packages/application-generic/src/services/workers/index.ts +++ b/packages/application-generic/src/services/workers/index.ts @@ -10,6 +10,7 @@ import { InboundParseWorkerService } from './inbound-parse-worker.service'; import { StandardWorkerService } from './standard-worker.service'; import { WebSocketsWorkerService } from './web-sockets-worker.service'; import { WorkflowWorkerService } from './workflow-worker.service'; +import { OldInstanceStandardWorkerService } from './old-instance-standard-worker.service'; import { OldInstanceWorkflowWorkerService } from './old-instance-workflow-worker.service'; export { @@ -22,5 +23,6 @@ export { WorkerOptions, WorkerProcessor, WorkflowWorkerService, + OldInstanceStandardWorkerService, OldInstanceWorkflowWorkerService, }; diff --git a/packages/application-generic/src/services/workers/old-instance-standard-worker.service.ts b/packages/application-generic/src/services/workers/old-instance-standard-worker.service.ts new file mode 100644 index 00000000000..03852a75223 --- /dev/null +++ b/packages/application-generic/src/services/workers/old-instance-standard-worker.service.ts @@ -0,0 +1,106 @@ +import { IJobData, JobTopicNameEnum } from '@novu/shared'; +import { Inject, Injectable, Logger } from '@nestjs/common'; + +import { + JobsOptions, + OldInstanceBullMqService, + Processor, + Worker, + WorkerOptions, +} from '../bull-mq'; + +const LOG_CONTEXT = 'OldInstanceStandardWorkerService'; + +type WorkerProcessor = string | Processor | undefined; + +/** + * TODO: Temporary for migration to MemoryDB + */ +export class OldInstanceStandardWorkerService { + private instance: OldInstanceBullMqService; + + public readonly DEFAULT_ATTEMPTS = 3; + public readonly topic: JobTopicNameEnum; + + constructor() { + this.topic = JobTopicNameEnum.STANDARD; + this.instance = new OldInstanceBullMqService(); + if (this.instance.enabled) { + Logger.log(`Worker ${this.topic} instantiated`, LOG_CONTEXT); + } else { + Logger.warn( + `Old instance standard worker not instantiated as it is only needed for MemoryDB migration`, + LOG_CONTEXT + ); + } + } + + public get bullMqService(): OldInstanceBullMqService { + return this.instance; + } + + public get worker(): Worker { + return this.instance.worker; + } + + public initWorker(processor: WorkerProcessor, options?: WorkerOptions): void { + if (this.instance.enabled) { + this.createWorker(processor, options); + } + } + + public createWorker( + processor: WorkerProcessor, + options: WorkerOptions + ): void { + if (this.instance.enabled) { + this.instance.createWorker(this.topic, processor, options); + } else { + Logger.log( + { enabled: this.instance.enabled }, + 'We are not running OldInstanceStandardWorkerService as it is not needed in this environment', + LOG_CONTEXT + ); + } + } + + public async isRunning(): Promise { + return await this.instance.isWorkerRunning(); + } + + public async isPaused(): Promise { + return await this.instance.isWorkerPaused(); + } + + public async pause(): Promise { + if (this.instance.enabled && this.worker) { + await this.instance.pauseWorker(); + } + } + + public async resume(): Promise { + if (this.instance.enabled && this.worker) { + await this.instance.resumeWorker(); + } + } + + public async gracefulShutdown(): Promise { + if (this.instance.enabled) { + Logger.log( + 'Shutting the old instance standard worker service down', + LOG_CONTEXT + ); + + await this.instance.gracefulShutdown(); + + Logger.log( + 'Shutting down the old instance standard worker service has finished', + LOG_CONTEXT + ); + } + } + + async onModuleDestroy(): Promise { + await this.gracefulShutdown(); + } +} diff --git a/packages/application-generic/src/services/workers/old-instance-workflow-worker.service.ts b/packages/application-generic/src/services/workers/old-instance-workflow-worker.service.ts index bca898a0118..74a04372f35 100644 --- a/packages/application-generic/src/services/workers/old-instance-workflow-worker.service.ts +++ b/packages/application-generic/src/services/workers/old-instance-workflow-worker.service.ts @@ -9,7 +9,7 @@ import { WorkerOptions, } from '../bull-mq'; -const LOG_CONTEXT = 'OldInstanceWorkerService'; +const LOG_CONTEXT = 'OldInstanceWorkflowWorkerService'; type WorkerProcessor = string | Processor | undefined; @@ -23,7 +23,7 @@ export class OldInstanceWorkflowWorkerService { public readonly topic: JobTopicNameEnum; constructor() { - this.topic = JobTopicNameEnum.STANDARD; + this.topic = JobTopicNameEnum.WORKFLOW; this.instance = new OldInstanceBullMqService(); if (this.instance.enabled) { Logger.log(`Worker ${this.topic} instantiated`, LOG_CONTEXT); @@ -86,11 +86,17 @@ export class OldInstanceWorkflowWorkerService { public async gracefulShutdown(): Promise { if (this.instance.enabled) { - Logger.log('Shutting the Worker service down', LOG_CONTEXT); + Logger.log( + 'Shutting the old instance workflow worker service down', + LOG_CONTEXT + ); await this.instance.gracefulShutdown(); - Logger.log('Shutting down the Worker service has finished', LOG_CONTEXT); + Logger.log( + 'Shutting down the old instance workflow worker service has finished', + LOG_CONTEXT + ); } } diff --git a/packages/application-generic/src/usecases/create-execution-details/types/index.ts b/packages/application-generic/src/usecases/create-execution-details/types/index.ts index 1c89c8ab2b0..73135d68abd 100644 --- a/packages/application-generic/src/usecases/create-execution-details/types/index.ts +++ b/packages/application-generic/src/usecases/create-execution-details/types/index.ts @@ -29,6 +29,7 @@ export enum DetailEnum { DIGESTED_EVENTS_PROVIDED = 'Steps to get digest events found', DIGEST_TRIGGERED_EVENTS = 'Digest triggered events', STEP_FILTERED_BY_PREFERENCES = 'Step filtered by subscriber preferences', + STEP_FILTERED_BY_GLOBAL_PREFERENCES = 'Step filtered by subscriber global preferences', WEBHOOK_FILTER_FAILED_RETRY = 'Webhook filter failed, retry will be executed', WEBHOOK_FILTER_FAILED_LAST_RETRY = 'Failed to get response from remote webhook filter on last retry', DIGEST_MERGED = 'Digest was merged with other digest', diff --git a/packages/application-generic/src/usecases/get-subscriber-global-preference/get-subscriber-global-preference.command.ts b/packages/application-generic/src/usecases/get-subscriber-global-preference/get-subscriber-global-preference.command.ts new file mode 100644 index 00000000000..54bf8e703cf --- /dev/null +++ b/packages/application-generic/src/usecases/get-subscriber-global-preference/get-subscriber-global-preference.command.ts @@ -0,0 +1,7 @@ +import { SubscriberEntity } from '@novu/dal'; + +import { EnvironmentWithSubscriber } from '../../commands'; + +export class GetSubscriberGlobalPreferenceCommand extends EnvironmentWithSubscriber { + subscriber?: SubscriberEntity; +} diff --git a/packages/application-generic/src/usecases/get-subscriber-global-preference/get-subscriber-global-preference.usecase.ts b/packages/application-generic/src/usecases/get-subscriber-global-preference/get-subscriber-global-preference.usecase.ts new file mode 100644 index 00000000000..cf1c53988b3 --- /dev/null +++ b/packages/application-generic/src/usecases/get-subscriber-global-preference/get-subscriber-global-preference.usecase.ts @@ -0,0 +1,84 @@ +import { Injectable } from '@nestjs/common'; +import { + PreferenceLevelEnum, + SubscriberEntity, + SubscriberPreferenceRepository, + SubscriberRepository, +} from '@novu/dal'; + +import { GetSubscriberGlobalPreferenceCommand } from './get-subscriber-global-preference.command'; +import { buildSubscriberKey, CachedEntity } from '../../services/cache'; +import { ApiException } from '../../utils/exceptions'; +import { IPreferenceChannels } from '@novu/shared'; + +@Injectable() +export class GetSubscriberGlobalPreference { + constructor( + private subscriberPreferenceRepository: SubscriberPreferenceRepository, + private subscriberRepository: SubscriberRepository + ) {} + + async execute(command: GetSubscriberGlobalPreferenceCommand) { + const subscriber = + command.subscriber ?? + (await this.fetchSubscriber({ + subscriberId: command.subscriberId, + _environmentId: command.environmentId, + })); + + if (!subscriber) { + throw new ApiException(`Subscriber ${command.subscriberId} not found`); + } + + const subscriberPreference = + await this.subscriberPreferenceRepository.findOne({ + _environmentId: command.environmentId, + _subscriberId: subscriber._id, + level: PreferenceLevelEnum.GLOBAL, + }); + + const subscriberChannelPreference = subscriberPreference?.channels; + const channels = this.updatePreferenceStateWithDefault( + subscriberChannelPreference ?? {} + ); + + return { + preference: { + enabled: subscriberPreference?.enabled ?? true, + channels, + }, + }; + } + + @CachedEntity({ + builder: (command: { subscriberId: string; _environmentId: string }) => + buildSubscriberKey({ + _environmentId: command._environmentId, + subscriberId: command.subscriberId, + }), + }) + private async fetchSubscriber({ + subscriberId, + _environmentId, + }: { + subscriberId: string; + _environmentId: string; + }): Promise { + return await this.subscriberRepository.findBySubscriberId( + _environmentId, + subscriberId + ); + } + // adds default state for missing channels + private updatePreferenceStateWithDefault(preference: IPreferenceChannels) { + const defaultPreference: IPreferenceChannels = { + email: true, + sms: true, + in_app: true, + chat: true, + push: true, + }; + + return { ...defaultPreference, ...preference }; + } +} diff --git a/packages/application-generic/src/usecases/get-subscriber-global-preference/index.ts b/packages/application-generic/src/usecases/get-subscriber-global-preference/index.ts new file mode 100644 index 00000000000..5393899f274 --- /dev/null +++ b/packages/application-generic/src/usecases/get-subscriber-global-preference/index.ts @@ -0,0 +1,2 @@ +export * from './get-subscriber-global-preference.usecase'; +export * from './get-subscriber-global-preference.command'; diff --git a/packages/application-generic/src/usecases/index.ts b/packages/application-generic/src/usecases/index.ts index cec41c573b7..bbbf703b03e 100644 --- a/packages/application-generic/src/usecases/index.ts +++ b/packages/application-generic/src/usecases/index.ts @@ -28,3 +28,4 @@ export * from './conditions-filter'; export * from './switch-environment'; export * from './switch-organization'; export * from './create-user'; +export * from './get-subscriber-global-preference'; diff --git a/packages/application-generic/src/usecases/trigger-event/trigger-event.usecase.ts b/packages/application-generic/src/usecases/trigger-event/trigger-event.usecase.ts index 3a46d709f48..85fdc5aa7aa 100644 --- a/packages/application-generic/src/usecases/trigger-event/trigger-event.usecase.ts +++ b/packages/application-generic/src/usecases/trigger-event/trigger-event.usecase.ts @@ -58,155 +58,172 @@ export class TriggerEvent { @InstrumentUsecase() async execute(command: TriggerEventCommand) { - const { - actor, - environmentId, - identifier, - organizationId, - to, - userId, - tenant, - } = command; + try { + const { + actor, + environmentId, + identifier, + organizationId, + to, + userId, + tenant, + } = command; - await this.validateTransactionIdProperty( - command.transactionId, - environmentId - ); - - Sentry.addBreadcrumb({ - message: 'Sending trigger', - data: { - triggerIdentifier: identifier, - }, - }); + await this.validateTransactionIdProperty( + command.transactionId, + environmentId + ); - this.logger.assign({ - transactionId: command.transactionId, - environmentId: command.environmentId, - organizationId: command.organizationId, - }); + Sentry.addBreadcrumb({ + message: 'Sending trigger', + data: { + triggerIdentifier: identifier, + }, + }); - const template = await this.getNotificationTemplateByTriggerIdentifier({ - environmentId: command.environmentId, - triggerIdentifier: command.identifier, - }); + this.logger.assign({ + transactionId: command.transactionId, + environmentId: command.environmentId, + organizationId: command.organizationId, + }); - /* - * Makes no sense to execute anything if template doesn't exist - * TODO: Send a 404? - */ - if (!template) { - const message = 'Notification template could not be found'; - const error = new ApiException(message); - throw error; - } + const template = await this.getNotificationTemplateByTriggerIdentifier({ + environmentId: command.environmentId, + triggerIdentifier: command.identifier, + }); - const templateProviderIds = await this.getProviderIdsForTemplate( - command.environmentId, - template - ); + /* + * Makes no sense to execute anything if template doesn't exist + * TODO: Send a 404? + */ + if (!template) { + const message = 'Notification template could not be found'; + const error = new ApiException(message); + Logger.error(error, message, LOG_CONTEXT); + throw error; + } - if (tenant) { - const tenantProcessed = await this.processTenant.execute( - ProcessTenantCommand.create({ - environmentId, - organizationId, - userId, - tenant, - }) + const templateProviderIds = await this.getProviderIdsForTemplate( + command.environmentId, + template ); - if (!tenantProcessed) { - Logger.warn( - `Tenant with identifier ${JSON.stringify( - tenant.identifier - )} of organization ${command.organizationId} in transaction ${ - command.transactionId - } could not be processed.`, - LOG_CONTEXT + if (tenant) { + const tenantProcessed = await this.processTenant.execute( + ProcessTenantCommand.create({ + environmentId, + organizationId, + userId, + tenant, + }) ); - } - } - - // We might have a single actor for every trigger, so we only need to check for it once - let actorProcessed; - if (actor) { - actorProcessed = await this.processSubscriber.execute( - ProcessSubscriberCommand.create({ - environmentId, - organizationId, - userId, - subscriber: actor, - }) - ); - } - for (const subscriber of to) { - this.analyticsService.track( - 'Notification event trigger - [Triggers]', - command.userId, - { - transactionId: command.transactionId, - _template: template._id, - _organization: command.organizationId, - channels: template?.steps.map((step) => step.template?.type), - source: command.payload.__source || 'api', + if (!tenantProcessed) { + Logger.warn( + `Tenant with identifier ${JSON.stringify( + tenant.identifier + )} of organization ${command.organizationId} in transaction ${ + command.transactionId + } could not be processed.`, + LOG_CONTEXT + ); } - ); - - const subscriberProcessed = await this.processSubscriber.execute( - ProcessSubscriberCommand.create({ - environmentId, - organizationId, - userId, - subscriber, - }) - ); + } - // If no subscriber makes no sense to try to create notification - if (subscriberProcessed) { - const createNotificationJobsCommand = - CreateNotificationJobsCommand.create({ + // We might have a single actor for every trigger, so we only need to check for it once + let actorProcessed; + if (actor) { + actorProcessed = await this.processSubscriber.execute( + ProcessSubscriberCommand.create({ environmentId, - identifier, organizationId, - overrides: command.overrides, - payload: command.payload, - subscriber: subscriberProcessed, - template, - templateProviderIds, - to: subscriber, - transactionId: command.transactionId, userId, - ...(actor && actorProcessed && { actor: actorProcessed }), - tenant, - }); + subscriber: actor, + }) + ); + } - const notificationJobs = await this.createNotificationJobs.execute( - createNotificationJobsCommand + for (const subscriber of to) { + this.analyticsService.mixpanelTrack( + 'Notification event trigger - [Triggers]', + '', + { + transactionId: command.transactionId, + _template: template._id, + _organization: command.organizationId, + channels: template?.steps.map((step) => step.template?.type), + source: command.payload.__source || 'api', + } ); - const storeSubscriberJobsCommand = StoreSubscriberJobsCommand.create({ - environmentId: command.environmentId, - jobs: notificationJobs, - organizationId: command.organizationId, - }); - await this.storeSubscriberJobs.execute(storeSubscriberJobsCommand); - } else { - /** - * TODO: Potentially add a CreateExecutionDetails entry. Right now we - * have the limitation we need a job to be created for that. Here there - * is no job at this point. - */ - Logger.warn( - `Subscriber ${JSON.stringify( - subscriber.subscriberId - )} of organization ${command.organizationId} in transaction ${ - command.transactionId - } was not processed. No jobs are created.`, - LOG_CONTEXT + const subscriberProcessed = await this.processSubscriber.execute( + ProcessSubscriberCommand.create({ + environmentId, + organizationId, + userId, + subscriber, + }) ); + + // If no subscriber makes no sense to try to create notification + if (subscriberProcessed) { + const createNotificationJobsCommand = + CreateNotificationJobsCommand.create({ + environmentId, + identifier, + organizationId, + overrides: command.overrides, + payload: command.payload, + subscriber: subscriberProcessed, + template, + templateProviderIds, + to: subscriber, + transactionId: command.transactionId, + userId, + ...(actor && actorProcessed && { actor: actorProcessed }), + tenant, + }); + + const notificationJobs = await this.createNotificationJobs.execute( + createNotificationJobsCommand + ); + + const storeSubscriberJobsCommand = StoreSubscriberJobsCommand.create({ + environmentId: command.environmentId, + jobs: notificationJobs, + organizationId: command.organizationId, + }); + await this.storeSubscriberJobs.execute(storeSubscriberJobsCommand); + } else { + /** + * TODO: Potentially add a CreateExecutionDetails entry. Right now we + * have the limitation we need a job to be created for that. Here there + * is no job at this point. + */ + Logger.warn( + `Subscriber ${JSON.stringify( + subscriber.subscriberId + )} of organization ${command.organizationId} in transaction ${ + command.transactionId + } was not processed. No jobs are created.`, + LOG_CONTEXT + ); + } } + } catch (e) { + Logger.error( + { + transactionId: command.transactionId, + organization: command.organizationId, + triggerIdentifier: command.identifier, + userId: command.userId, + error: e, + }, + 'Unexpected error has occurred when triggering event', + LOG_CONTEXT + ); + + throw e; } } diff --git a/packages/cli/package.json b/packages/cli/package.json index 6c6202214ac..4ac9c0f60a0 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "novu", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "On-Boarding Cli", "main": "index.js", "scripts": { @@ -31,7 +31,7 @@ "ncp": "^2.0.0" }, "dependencies": { - "@novu/shared": "^0.19.0", + "@novu/shared": "^0.20.0-alpha.0", "analytics-node": "^6.2.0", "axios": "^1.3.3", "chalk": "4.1.2", diff --git a/packages/client/package.json b/packages/client/package.json index 10dc8afdb89..b381d47eab4 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@novu/client", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "repository": "https://github.com/novuhq/novu", "description": "API client to be used in end user environments", "main": "dist/cjs/index.js", @@ -44,7 +44,7 @@ "node": ">=10" }, "dependencies": { - "@novu/shared": "^0.19.0" + "@novu/shared": "^0.20.0-alpha.0" }, "devDependencies": { "@types/jest": "29.5.2", diff --git a/packages/client/src/api/api.service.ts b/packages/client/src/api/api.service.ts index 081323989b3..dbdb9611ac4 100644 --- a/packages/client/src/api/api.service.ts +++ b/packages/client/src/api/api.service.ts @@ -12,6 +12,7 @@ import { IUserPreferenceSettings, IUnseenCountQuery, IUnreadCountQuery, + IUserGlobalPreferenceSettings, } from '../index'; export class ApiService { @@ -157,6 +158,10 @@ export class ApiService { return this.httpClient.get('/widgets/preferences'); } + async getUserGlobalPreference(): Promise { + return this.httpClient.get('/widgets/preferences/global'); + } + async updateSubscriberPreference( templateId: string, channelType: string, @@ -166,4 +171,17 @@ export class ApiService { channel: { type: channelType, enabled }, }); } + + async updateSubscriberGlobalPreference( + preferences: { channelType: string; enabled: boolean }[], + enabled?: boolean + ): Promise { + return await this.httpClient.patch(`/widgets/preferences`, { + preferences: preferences.map((preference) => ({ + ...preference, + type: preference.channelType, + })), + enabled, + }); + } } diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts index 038b8858bd7..0d63330f163 100644 --- a/packages/client/src/index.ts +++ b/packages/client/src/index.ts @@ -38,7 +38,15 @@ export interface IUserPreferenceSettings { tags?: string[]; data?: NotificationTemplateCustomData; }; - preference: { enabled: boolean; channels: IPreferenceChannels }; + preference: PreferenceSettingsType; } +export interface IUserGlobalPreferenceSettings { + preference: PreferenceSettingsType; +} + +export type PreferenceSettingsType = { + enabled: boolean; + channels: IPreferenceChannels; +}; export { ApiService } from './api/api.service'; diff --git a/packages/headless/package.json b/packages/headless/package.json index 07850801eea..37d01208275 100644 --- a/packages/headless/package.json +++ b/packages/headless/package.json @@ -1,6 +1,6 @@ { "name": "@novu/headless", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "repository": "https://github.com/novuhq/novu", "description": "Headless client package that is a thin abstraction layer over the API client + state and socket management", "keywords": [], @@ -28,8 +28,8 @@ "node": ">=10" }, "dependencies": { - "@novu/client": "^0.19.0", - "@novu/shared": "^0.19.0", + "@novu/client": "^0.20.0-alpha.0", + "@novu/shared": "^0.20.0-alpha.0", "@tanstack/query-core": "^4.15.1", "socket.io-client": "4.7.2" }, diff --git a/packages/headless/src/lib/headless.service.test.ts b/packages/headless/src/lib/headless.service.test.ts index 5b214c401ae..b833569ded3 100644 --- a/packages/headless/src/lib/headless.service.test.ts +++ b/packages/headless/src/lib/headless.service.test.ts @@ -1,4 +1,8 @@ -import { ApiService, IUserPreferenceSettings } from '@novu/client'; +import { + ApiService, + IUserGlobalPreferenceSettings, + IUserPreferenceSettings, +} from '@novu/client'; import { WebSocketEventEnum } from '@novu/shared'; import io from 'socket.io-client'; @@ -90,6 +94,20 @@ const mockUserPreferenceSetting: IUserPreferenceSettings = { }, }, }; + +const mockUserGlobalPreferenceSetting: IUserGlobalPreferenceSettings = { + preference: { + enabled: true, + channels: { + email: true, + sms: true, + in_app: true, + chat: true, + push: true, + }, + }, +}; + const mockUserPreferences = [mockUserPreferenceSetting]; const mockServiceInstance = { @@ -108,6 +126,9 @@ const mockServiceInstance = { updateSubscriberPreference: jest.fn(() => promiseResolveTimeout(0, mockUserPreferenceSetting) ), + updateSubscriberGlobalPreference: jest.fn(() => + promiseResolveTimeout(0, mockUserGlobalPreferenceSetting) + ), markMessageAs: jest.fn(), removeMessage: jest.fn(), updateAction: jest.fn(), @@ -923,6 +944,99 @@ describe('headless.service', () => { }); }); + describe('updateUserGlobalPreferences', () => { + test('calls updateUserGlobalPreferences successfully', async () => { + const payload = { + enabled: true, + preferences: [ + { + channelType: ChannelTypeEnum.EMAIL, + enabled: false, + }, + ], + }; + + const updatedUserGlobalPreferenceSetting = { + preference: { + enabled: true, + channels: { + email: false, + }, + }, + }; + mockServiceInstance.updateSubscriberGlobalPreference.mockImplementationOnce( + () => promiseResolveTimeout(0, updatedUserGlobalPreferenceSetting) + ); + const headlessService = new HeadlessService(options); + + const listener = jest.fn(); + const onSuccess = jest.fn(); + (headlessService as any).session = mockSession; + + headlessService.updateUserGlobalPreferences({ + preferences: payload.preferences, + enabled: payload.enabled, + listener, + onSuccess, + }); + + expect(listener).toBeCalledWith( + expect.objectContaining({ isLoading: true, data: undefined }) + ); + await promiseResolveTimeout(100); + + expect( + mockServiceInstance.updateSubscriberGlobalPreference + ).toBeCalledTimes(1); + + expect(onSuccess).toHaveBeenNthCalledWith( + 1, + updatedUserGlobalPreferenceSetting + ); + }); + + test('handles the error', async () => { + const payload = { + enabled: true, + preferences: [ + { + channelType: ChannelTypeEnum.EMAIL, + enabled: true, + }, + ], + }; + + const error = new Error('error'); + mockServiceInstance.updateSubscriberGlobalPreference.mockImplementationOnce( + () => promiseRejectTimeout(0, error) + ); + const headlessService = new HeadlessService(options); + const listener = jest.fn(); + const onError = jest.fn(); + (headlessService as any).session = mockSession; + + headlessService.updateUserGlobalPreferences({ + preferences: payload.preferences, + enabled: payload.enabled, + listener, + onError, + }); + expect(listener).toBeCalledWith( + expect.objectContaining({ isLoading: true, data: undefined }) + ); + await promiseResolveTimeout(100); + + expect( + mockServiceInstance.updateSubscriberGlobalPreference + ).toBeCalledTimes(1); + expect(onError).toHaveBeenCalledWith(error); + expect(listener).toHaveBeenNthCalledWith( + 2, + expect.objectContaining({ isLoading: false, data: undefined, error }) + ); + }); + }); + describe('markNotificationsAsRead', () => { test('calls markNotificationsAsRead successfully', async () => { const updatedNotification = { diff --git a/packages/headless/src/lib/headless.service.ts b/packages/headless/src/lib/headless.service.ts index 74d09e7010f..0290b0a192b 100644 --- a/packages/headless/src/lib/headless.service.ts +++ b/packages/headless/src/lib/headless.service.ts @@ -5,7 +5,12 @@ import { MutationObserverResult, } from '@tanstack/query-core'; import io from 'socket.io-client'; -import { ApiService, IUserPreferenceSettings, IStoreQuery } from '@novu/client'; +import { + ApiService, + IUserPreferenceSettings, + IStoreQuery, + IUserGlobalPreferenceSettings, +} from '@novu/client'; import { IOrganizationEntity, IMessage, @@ -21,6 +26,7 @@ import { SESSION_QUERY_KEY, UNREAD_COUNT_QUERY_KEY, UNSEEN_COUNT_QUERY_KEY, + USER_GLOBAL_PREFERENCES_QUERY_KEY, USER_PREFERENCES_QUERY_KEY, } from '../utils'; import { @@ -30,6 +36,7 @@ import { IMessageId, IUpdateActionVariables, IUpdateUserPreferencesVariables, + IUpdateUserGlobalPreferencesVariables, UpdateResult, } from './types'; @@ -104,6 +111,14 @@ export class HeadlessService { queryFn: () => this.api.getUserPreference(), }; + private userGlobalPreferencesQueryOptions: QueryObserverOptions< + IUserGlobalPreferenceSettings[], + unknown + > = { + queryKey: USER_GLOBAL_PREFERENCES_QUERY_KEY, + queryFn: () => this.api.getUserGlobalPreference(), + }; + constructor(private options: IHeadlessServiceOptions) { const backendUrl = options.backendUrl ?? 'https://api.novu.co'; const token = getToken(); @@ -456,6 +471,29 @@ export class HeadlessService { return unsubscribe; } + public fetchUserGlobalPreferences({ + listener, + onSuccess, + onError, + }: { + listener: (result: FetchResult) => void; + onSuccess?: (settings: IUserGlobalPreferenceSettings[]) => void; + onError?: (error: unknown) => void; + }) { + this.assertSessionInitialized(); + + const { unsubscribe } = this.queryService.subscribeQuery({ + options: { + ...this.userGlobalPreferencesQueryOptions, + onSuccess, + onError, + }, + listener: (result) => this.callFetchListener(result, listener), + }); + + return unsubscribe; + } + public async updateUserPreferences({ templateId, channelType, @@ -523,6 +561,63 @@ export class HeadlessService { }); } + public async updateUserGlobalPreferences({ + preferences, + enabled, + listener, + onSuccess, + onError, + }: { + preferences: IUpdateUserGlobalPreferencesVariables['preferences']; + enabled?: IUpdateUserGlobalPreferencesVariables['enabled']; + listener: ( + result: UpdateResult< + IUserGlobalPreferenceSettings, + unknown, + IUpdateUserGlobalPreferencesVariables + > + ) => void; + onSuccess?: (settings: IUserGlobalPreferenceSettings) => void; + onError?: (error: unknown) => void; + }) { + this.assertSessionInitialized(); + + const { result, unsubscribe } = this.queryService.subscribeMutation< + IUserGlobalPreferenceSettings, + unknown, + IUpdateUserGlobalPreferencesVariables + >({ + options: { + mutationFn: (variables) => + this.api.updateSubscriberGlobalPreference( + variables.preferences, + variables.enabled + ), + onSuccess: (data) => { + this.queryClient.setQueryData( + USER_GLOBAL_PREFERENCES_QUERY_KEY, + () => [data] + ); + }, + }, + listener: (res) => this.callUpdateListener(res, listener), + }); + + result + .mutate({ preferences, enabled }) + .then((data) => { + onSuccess?.(data); + + return data; + }) + .catch((error) => { + onError?.(error); + }) + .finally(() => { + unsubscribe(); + }); + } + public async markNotificationsAsRead({ messageId, listener, diff --git a/packages/headless/src/lib/types.ts b/packages/headless/src/lib/types.ts index 1a590248d54..8c654cfc255 100644 --- a/packages/headless/src/lib/types.ts +++ b/packages/headless/src/lib/types.ts @@ -2,7 +2,11 @@ import { QueryObserverResult, MutationObserverResult, } from '@tanstack/query-core'; -import { ButtonTypeEnum, MessageActionStatusEnum } from '@novu/shared'; +import { + ButtonTypeEnum, + ChannelTypeEnum, + MessageActionStatusEnum, +} from '@novu/shared'; export interface IHeadlessServiceOptions { backendUrl?: string; @@ -22,6 +26,11 @@ export interface IUpdateUserPreferencesVariables { checked: boolean; } +export interface IUpdateUserGlobalPreferencesVariables { + preferences?: { channelType: ChannelTypeEnum; enabled: boolean }[]; + enabled?: boolean; +} + export interface IUpdateActionVariables { messageId: string; actionButtonType: ButtonTypeEnum; diff --git a/packages/headless/src/utils/query-keys.ts b/packages/headless/src/utils/query-keys.ts index 2b24642c8e5..7e57fc69779 100644 --- a/packages/headless/src/utils/query-keys.ts +++ b/packages/headless/src/utils/query-keys.ts @@ -2,5 +2,6 @@ export const SESSION_QUERY_KEY = ['session']; export const ORGANIZATION_QUERY_KEY = ['organization']; export const NOTIFICATIONS_QUERY_KEY = ['notifications']; export const USER_PREFERENCES_QUERY_KEY = ['user_preferences']; +export const USER_GLOBAL_PREFERENCES_QUERY_KEY = ['user_global_preferences']; export const UNSEEN_COUNT_QUERY_KEY = ['unseen_count']; export const UNREAD_COUNT_QUERY_KEY = ['unread_count']; diff --git a/packages/nest/package.json b/packages/nest/package.json index 3a22c168038..d5381807bd9 100644 --- a/packages/nest/package.json +++ b/packages/nest/package.json @@ -1,6 +1,6 @@ { "name": "@novu/nest", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A nestjs wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -36,7 +36,7 @@ }, "dependencies": { "@nestjs/common": "^8.2.0", - "@novu/stateless": "^0.19.0" + "@novu/stateless": "^0.20.0-alpha.0" }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", diff --git a/packages/node/README.md b/packages/node/README.md index b175ab0410b..07f38a86e08 100644 --- a/packages/node/README.md +++ b/packages/node/README.md @@ -319,6 +319,27 @@ const novu = new Novu(''); await novu.subscribers.getPreference("subscriberId") ``` +- #### Get subscriber global preference +```ts +import { Novu } from '@novu/node'; + +const novu = new Novu(''); + +await novu.subscribers.getGlobalPreference("subscriberId" ) +``` + + +- #### Get subscriber preference by level +```ts +import { Novu, PreferenceLevelEnum } from '@novu/node'; + +const novu = new Novu(''); +// Get global level preference +await novu.subscribers.getPreferenceByLevel("subscriberId", PreferenceLevelEnum.GLOBAL) + +// Get template level preference +await novu.subscribers.getPreferenceByLevel("subscriberId", PreferenceLevelEnum.TEMPLATE) +``` - #### Update subscriber preference for a workflow ```ts import { Novu } from '@novu/node'; @@ -338,11 +359,30 @@ await novu.subscribers.updatePreference("subscriberId", "workflowId", { await novu.subscribers.updatePreference("subscriberId", "workflowId", { channel: { type: "email" - enabled: + enabled: false } }) ``` +- #### Update subscriber preference globally +```ts +import { Novu } from '@novu/node'; + +const novu = new Novu(''); + +// enable in-app channel and disable email channel +await novu.subscribers.updateGlobalPreference("subscriberId", { + enabled: true, + preferences: [{ + type: "in_app" + enabled: true + }, { + type: "email" + enabled: false + }] +}) +``` + - #### Get in-app messages (notifications) feed for a subscriber ```ts diff --git a/packages/node/package.json b/packages/node/package.json index db8274f4aba..95881a06969 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -1,6 +1,6 @@ { "name": "@novu/node", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "Notification Management Framework", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -42,7 +42,7 @@ "node": ">=10" }, "dependencies": { - "@novu/shared": "^0.19.0", + "@novu/shared": "^0.20.0-alpha.0", "handlebars": "^4.7.7", "lodash.get": "^4.4.2", "lodash.merge": "^4.6.2" diff --git a/packages/node/src/lib/subscribers/subscriber.interface.ts b/packages/node/src/lib/subscribers/subscriber.interface.ts index bb0d0a42afc..13a7e97a41d 100644 --- a/packages/node/src/lib/subscribers/subscriber.interface.ts +++ b/packages/node/src/lib/subscribers/subscriber.interface.ts @@ -5,9 +5,15 @@ import { ButtonTypeEnum, MessageActionStatusEnum, ISubscribersDefine, + PreferenceLevelEnum, } from '@novu/shared'; -export { ISubscriberPayload, ButtonTypeEnum, MessageActionStatusEnum }; +export { + ISubscriberPayload, + ButtonTypeEnum, + MessageActionStatusEnum, + PreferenceLevelEnum, +}; export interface ISubscribers { list(page: number, limit: number); @@ -28,11 +34,17 @@ export interface ISubscribers { unsetCredentials(subscriberId: string, providerId: string); updateOnlineStatus(subscriberId: string, online: boolean); getPreference(subscriberId: string); + getGlobalPreference(subscriberId: string); + getPreferenceByLevel(subscriberId: string, level: PreferenceLevelEnum); updatePreference( subscriberId: string, templateId: string, data: IUpdateSubscriberPreferencePayload ); + updateGlobalPreference( + subscriberId: string, + data: IUpdateSubscriberGlobalPreferencePayload + ); getNotificationsFeed( subscriberId: string, params: IGetSubscriberNotificationFeedParams @@ -62,6 +74,14 @@ export interface IUpdateSubscriberPreferencePayload { }; enabled?: boolean; } + +export interface IUpdateSubscriberGlobalPreferencePayload { + preferences?: { + type: ChannelTypeEnum; + enabled: boolean; + }[]; + enabled?: boolean; +} export interface IGetSubscriberNotificationFeedParams { page?: number; limit?: number; diff --git a/packages/node/src/lib/subscribers/subscribers.ts b/packages/node/src/lib/subscribers/subscribers.ts index 50326af4bd2..d54635e14c1 100644 --- a/packages/node/src/lib/subscribers/subscribers.ts +++ b/packages/node/src/lib/subscribers/subscribers.ts @@ -4,13 +4,14 @@ import { IChannelCredentials, ISubscribersDefine, } from '@novu/shared'; -import { MarkMessagesAsEnum } from '@novu/shared'; +import { MarkMessagesAsEnum, PreferenceLevelEnum } from '@novu/shared'; import { IGetSubscriberNotificationFeedParams, IMarkFields, IMarkMessageActionFields, ISubscriberPayload, ISubscribers, + IUpdateSubscriberGlobalPreferencePayload, IUpdateSubscriberPreferencePayload, } from './subscriber.interface'; import { WithHttp } from '../novu.interface'; @@ -91,6 +92,18 @@ export class Subscribers extends WithHttp implements ISubscribers { return await this.http.get(`/subscribers/${subscriberId}/preferences`); } + async getGlobalPreference(subscriberId: string) { + return await this.http.get( + `/subscribers/${subscriberId}/preferences/${PreferenceLevelEnum.GLOBAL}` + ); + } + + async getPreferenceByLevel(subscriberId: string, level: PreferenceLevelEnum) { + return await this.http.get( + `/subscribers/${subscriberId}/preferences/${level}` + ); + } + async updatePreference( subscriberId: string, templateId: string, @@ -104,6 +117,15 @@ export class Subscribers extends WithHttp implements ISubscribers { ); } + async updateGlobalPreference( + subscriberId: string, + data: IUpdateSubscriberGlobalPreferencePayload + ) { + return await this.http.patch(`/subscribers/${subscriberId}/preferences`, { + ...data, + }); + } + async getNotificationsFeed( subscriberId: string, { payload, ...rest }: IGetSubscriberNotificationFeedParams = {} diff --git a/packages/notification-center-angular/package.json b/packages/notification-center-angular/package.json index 255c50b94da..2f67455be9a 100644 --- a/packages/notification-center-angular/package.json +++ b/packages/notification-center-angular/package.json @@ -1,6 +1,6 @@ { "name": "@novu/notification-center-angular", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "scripts": { "ng": "ng", "start": "ng serve", @@ -37,7 +37,7 @@ "@angular/core": "~15.2.0", "@angular/platform-browser": "~15.2.0", "@angular/platform-browser-dynamic": "~15.2.0", - "@novu/notification-center": "^0.19.0", + "@novu/notification-center": "^0.20.0-alpha.0", "react": "^17.0.1", "react-dom": "^17.0.1", "tslib": "^2.3.0", diff --git a/packages/notification-center-vue/package.json b/packages/notification-center-vue/package.json index f7adebc96d6..c87cc31b17d 100644 --- a/packages/notification-center-vue/package.json +++ b/packages/notification-center-vue/package.json @@ -1,7 +1,7 @@ { "name": "@novu/notification-center-vue", "sideEffects": false, - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "Vue specific wrapper for notification-center", "repository": { "type": "git", @@ -22,7 +22,7 @@ "dependencies": { "@emotion/css": "^11.10.5", "@novu/floating-vue": "^2.0.3", - "@novu/notification-center": "^0.19.0", + "@novu/notification-center": "^0.20.0-alpha.0", "react": "^17.0.1", "react-dom": "^17.0.1" }, diff --git a/packages/notification-center/package.json b/packages/notification-center/package.json index 18a421b0847..765ad45c1eb 100644 --- a/packages/notification-center/package.json +++ b/packages/notification-center/package.json @@ -1,6 +1,6 @@ { "name": "@novu/notification-center", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "repository": "https://github.com/novuhq/novu", "description": "", "scripts": { @@ -80,8 +80,8 @@ "@emotion/styled": "^11.6.0", "@mantine/core": "^5.7.1", "@mantine/hooks": "^5.7.1", - "@novu/client": "^0.19.0", - "@novu/shared": "^0.19.0", + "@novu/client": "^0.20.0-alpha.0", + "@novu/shared": "^0.20.0-alpha.0", "@tanstack/react-query": "^4.20.4", "acorn-jsx": "^5.3.2", "axios": "^1.4.0", diff --git a/packages/notification-center/src/components/novu-provider/NovuProvider.tsx b/packages/notification-center/src/components/novu-provider/NovuProvider.tsx index 956f52e120f..8bf018272cb 100644 --- a/packages/notification-center/src/components/novu-provider/NovuProvider.tsx +++ b/packages/notification-center/src/components/novu-provider/NovuProvider.tsx @@ -29,6 +29,7 @@ const DEFAULT_FETCHING_STRATEGY: IFetchingStrategy = { fetchOrganization: true, fetchNotifications: false, fetchUserPreferences: false, + fetchUserGlobalPreferences: false, }; export interface INovuProviderProps { diff --git a/packages/notification-center/src/hooks/index.ts b/packages/notification-center/src/hooks/index.ts index 400f8aa67f4..5bd891e36d8 100644 --- a/packages/notification-center/src/hooks/index.ts +++ b/packages/notification-center/src/hooks/index.ts @@ -6,11 +6,13 @@ export * from './useNovuTheme'; export * from './useNotificationCenter'; export * from './useTranslations'; export * from './useUpdateUserPreferences'; +export * from './useUpdateUserGlobalPreferences'; export * from './useUpdateAction'; export * from './useFetchNotifications'; export * from './useFetchOrganization'; export * from './useFeedUnseenCount'; export * from './useFetchUserPreferences'; +export * from './useFetchUserGlobalPreferences'; export * from './useMarkNotificationsAs'; export * from './useRemoveNotification'; export * from './useRemoveAllNotifications'; diff --git a/packages/notification-center/src/hooks/queryKeys.ts b/packages/notification-center/src/hooks/queryKeys.ts index 78da8305273..86ac597d55b 100644 --- a/packages/notification-center/src/hooks/queryKeys.ts +++ b/packages/notification-center/src/hooks/queryKeys.ts @@ -2,5 +2,6 @@ export const SESSION_QUERY_KEY = ['session']; export const ORGANIZATION_QUERY_KEY = ['organization']; export const INFINITE_NOTIFICATIONS_QUERY_KEY = ['infinite_notifications']; export const USER_PREFERENCES_QUERY_KEY = ['user_preferences']; +export const USER_GLOBAL_PREFERENCES_QUERY_KEY = ['user_global_preferences']; export const UNSEEN_COUNT_QUERY_KEY = ['unseen_count']; export const FEED_UNSEEN_COUNT_QUERY_KEY = ['feed_unseen_count']; diff --git a/packages/notification-center/src/hooks/useFetchUserGlobalPreferences.ts b/packages/notification-center/src/hooks/useFetchUserGlobalPreferences.ts new file mode 100644 index 00000000000..0de51708b17 --- /dev/null +++ b/packages/notification-center/src/hooks/useFetchUserGlobalPreferences.ts @@ -0,0 +1,23 @@ +import type { IUserGlobalPreferenceSettings } from '@novu/client'; +import { useQuery, UseQueryOptions } from '@tanstack/react-query'; + +import { useFetchUserGlobalPreferencesQueryKey } from './useFetchUserGlobalPreferencesQueryKey'; +import { useNovuContext } from './useNovuContext'; + +export const useFetchUserGlobalPreferences = ( + options: UseQueryOptions = {} +) => { + const { apiService, isSessionInitialized, fetchingStrategy } = useNovuContext(); + const userGlobalPreferencesQueryKey = useFetchUserGlobalPreferencesQueryKey(); + + const result = useQuery( + userGlobalPreferencesQueryKey, + () => apiService.getUserGlobalPreference(), + { + ...options, + enabled: isSessionInitialized && fetchingStrategy.fetchUserGlobalPreferences, + } + ); + + return result; +}; diff --git a/packages/notification-center/src/hooks/useFetchUserGlobalPreferencesQueryKey.ts b/packages/notification-center/src/hooks/useFetchUserGlobalPreferencesQueryKey.ts new file mode 100644 index 00000000000..ad77a688a3c --- /dev/null +++ b/packages/notification-center/src/hooks/useFetchUserGlobalPreferencesQueryKey.ts @@ -0,0 +1,11 @@ +import { useMemo } from 'react'; + +import { USER_GLOBAL_PREFERENCES_QUERY_KEY } from './queryKeys'; +import { useSetQueryKey } from './useSetQueryKey'; + +export const useFetchUserGlobalPreferencesQueryKey = () => { + const setQueryKey = useSetQueryKey(); + const queryKey = useMemo(() => setQueryKey([...USER_GLOBAL_PREFERENCES_QUERY_KEY]), [setQueryKey]); + + return queryKey; +}; diff --git a/packages/notification-center/src/hooks/useUpdateUserGlobalPreferences.ts b/packages/notification-center/src/hooks/useUpdateUserGlobalPreferences.ts new file mode 100644 index 00000000000..66108c9f2d4 --- /dev/null +++ b/packages/notification-center/src/hooks/useUpdateUserGlobalPreferences.ts @@ -0,0 +1,71 @@ +import type { IUserGlobalPreferenceSettings } from '@novu/client'; +import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query'; +import { useCallback } from 'react'; + +import { useFetchUserGlobalPreferencesQueryKey } from './useFetchUserGlobalPreferencesQueryKey'; +import { useNovuContext } from './useNovuContext'; + +interface IUpdateUserGlobalPreferencesVariables { + preferences: { channelType: string; enabled: boolean }[]; + enabled?: boolean; +} + +export const useUpdateUserGlobalPreferences = ({ + onSuccess, + onError, + ...options +}: UseMutationOptions = {}) => { + const queryClient = useQueryClient(); + const { apiService } = useNovuContext(); + const userGlobalPreferencesQueryKey = useFetchUserGlobalPreferencesQueryKey(); + + const updateGlobalPreferenceChecked = useCallback( + ({ enabled, preferences }: IUpdateUserGlobalPreferencesVariables) => { + queryClient.setQueryData(userGlobalPreferencesQueryKey, (old) => { + return { + preference: { + enabled: enabled ?? old.preference.enabled, + channels: { + ...old.preference.channels, + ...preferences.reduce((acc, { channelType, enabled: channelEnabled }) => { + acc[channelType] = channelEnabled; + + return acc; + }, {} as Record), + }, + }, + }; + }); + }, + [queryClient] + ); + + const { mutate, ...result } = useMutation< + IUserGlobalPreferenceSettings, + Error, + IUpdateUserGlobalPreferencesVariables + >((variables) => apiService.updateSubscriberGlobalPreference(variables.preferences, variables.enabled), { + ...options, + onSuccess: (data, variables, context) => { + queryClient.setQueryData(userGlobalPreferencesQueryKey, () => [data]); + onSuccess?.(data, variables, context); + }, + onError: (error, variables, context) => { + updateGlobalPreferenceChecked({ + enabled: !variables.enabled ?? undefined, + preferences: variables.preferences, + }); + onError?.(error, variables, context); + }, + }); + + const updateUserGlobalPreferences = useCallback( + (variables: IUpdateUserGlobalPreferencesVariables) => { + updateGlobalPreferenceChecked(variables); + mutate(variables); + }, + [updateGlobalPreferenceChecked, mutate] + ); + + return { ...result, updateUserGlobalPreferences }; +}; diff --git a/packages/notification-center/src/shared/interfaces/index.ts b/packages/notification-center/src/shared/interfaces/index.ts index 0bc431e0381..f9f15034ba0 100644 --- a/packages/notification-center/src/shared/interfaces/index.ts +++ b/packages/notification-center/src/shared/interfaces/index.ts @@ -78,6 +78,7 @@ export interface IFetchingStrategy { fetchOrganization: boolean; fetchNotifications: boolean; fetchUserPreferences: boolean; + fetchUserGlobalPreferences: boolean; } export interface INovuProviderContext { diff --git a/packages/stateless/package.json b/packages/stateless/package.json index 1134dae4507..e0ba5bbfcff 100644 --- a/packages/stateless/package.json +++ b/packages/stateless/package.json @@ -1,6 +1,6 @@ { "name": "@novu/stateless", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "Notification Management Framework", "main": "build/main/index.js", "typings": "build/main/index.d.ts", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9f21418e9cc..a13cddc0096 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -119,7 +119,7 @@ importers: eslint: 8.38.0 eslint-config-airbnb-typescript: 17.0.0_awz7iagzjrkgdisnaft5immp6i eslint-config-prettier: 8.8.0_eslint@8.38.0 - eslint-import-resolver-webpack: 0.13.2_re6elnmjmviqdg6e3dtzej3oae + eslint-import-resolver-webpack: 0.13.2_2shkfpyvap4zatu4dplbemujdy eslint-plugin-eslint-comments: 3.2.0_eslint@8.38.0 eslint-plugin-functional: 3.7.2_ze6bmax3gcsfve3yrzu6npguhe eslint-plugin-import: 2.27.5_ow2j3yqjjpzplq4flnkwqs3k4u @@ -171,13 +171,13 @@ importers: '@nestjs/swagger': ^7.1.8 '@nestjs/terminus': ^10.0.1 '@nestjs/testing': ^10.2.2 - '@novu/application-generic': ^0.19.0 - '@novu/dal': ^0.19.0 + '@novu/application-generic': ^0.20.0-alpha.0 + '@novu/dal': ^0.20.0-alpha.0 '@novu/ee-auth': ^0.19.0 - '@novu/node': ^0.19.0 - '@novu/shared': ^0.19.0 - '@novu/stateless': ^0.19.0 - '@novu/testing': ^0.19.0 + '@novu/node': ^0.20.0-alpha.0 + '@novu/shared': ^0.20.0-alpha.0 + '@novu/stateless': ^0.20.0-alpha.0 + '@novu/testing': ^0.20.0-alpha.0 '@sendgrid/mail': ^7.6.0 '@sentry/hub': ^7.40.0 '@sentry/node': ^7.40.0 @@ -314,16 +314,16 @@ importers: mocha: 8.4.0 nodemon: 2.0.22 sinon: 9.2.4 - ts-loader: 9.4.2_rggdtlzfqxxwxudp3onsqdyocm + ts-loader: 9.4.2_fejcc7gjbwtmwzggoernzojija ts-node: 10.9.1_wh2cnrlliuuxb2etxm2m3ttgna tsconfig-paths: 4.1.2 typescript: 4.9.5 apps/inbound-mail: specifiers: - '@novu/application-generic': ^0.19.0 - '@novu/shared': ^0.19.0 - '@novu/testing': ^0.19.0 + '@novu/application-generic': ^0.20.0-alpha.0 + '@novu/shared': ^0.20.0-alpha.0 + '@novu/testing': ^0.20.0-alpha.0 '@sentry/node': ^7.12.1 '@types/chai': ^4.2.11 '@types/express': ^4.17.8 @@ -391,7 +391,7 @@ importers: prettier: 2.8.7 sinon: 9.2.4 ts-jest: 27.1.5_4aafjbpmnrfjtrzkyohogv4jce - ts-loader: 9.4.2_rggdtlzfqxxwxudp3onsqdyocm + ts-loader: 9.4.2_fejcc7gjbwtmwzggoernzojija ts-node: 10.9.1_wh2cnrlliuuxb2etxm2m3ttgna tsconfig-paths: 4.1.2 typescript: 4.9.5 @@ -428,10 +428,10 @@ importers: '@mantine/notifications': ^5.7.1 '@mantine/prism': ^5.7.1 '@mantine/spotlight': ^5.7.1 - '@novu/dal': ^0.19.0 - '@novu/notification-center': ^0.19.0 - '@novu/shared': ^0.19.0 - '@novu/testing': ^0.19.0 + '@novu/dal': ^0.20.0-alpha.0 + '@novu/notification-center': ^0.20.0-alpha.0 + '@novu/shared': ^0.20.0-alpha.0 + '@novu/testing': ^0.20.0-alpha.0 '@segment/analytics-next': ^1.48.0 '@sentry/react': ^7.40.0 '@sentry/tracing': ^7.40.0 @@ -523,7 +523,7 @@ importers: webpack: ^5.74.0 webpack-bundle-analyzer: ^4.9.0 webpack-dev-server: 4.11.1 - zod: ^3.17.3 + zod: ^3.22.4 dependencies: '@ant-design/icons': 4.8.0_sfoxds7t5ydpegc3knd667wn6m '@babel/plugin-proposal-optional-chaining': 7.21.0_@babel+core@7.22.11 @@ -619,7 +619,7 @@ importers: uuid: 8.3.2 web-vitals: 1.1.2 webpack-dev-server: 4.11.1_webpack@5.78.0 - zod: 3.21.4 + zod: 3.22.4 devDependencies: '@babel/polyfill': 7.12.1 '@babel/preset-env': 7.21.4_@babel+core@7.22.11 @@ -663,11 +663,11 @@ importers: '@nestjs/schematics': ^10.0.2 '@nestjs/terminus': ^10.0.1 '@nestjs/testing': ^10.2.2 - '@novu/application-generic': ^0.19.0 - '@novu/dal': ^0.19.0 - '@novu/shared': ^0.19.0 - '@novu/stateless': ^0.19.0 - '@novu/testing': ^0.19.0 + '@novu/application-generic': ^0.20.0-alpha.0 + '@novu/dal': ^0.20.0-alpha.0 + '@novu/shared': ^0.20.0-alpha.0 + '@novu/stateless': ^0.20.0-alpha.0 + '@novu/testing': ^0.20.0-alpha.0 '@sentry/node': ^7.66.0 '@types/chai': ^4.3.4 '@types/express': ^4.17.8 @@ -745,7 +745,7 @@ importers: sinon: 9.2.4 supertest: 6.3.3 ts-jest: 27.1.5_46h2nya7z2u3ruciguirufjle4 - ts-loader: 9.4.2_rggdtlzfqxxwxudp3onsqdyocm + ts-loader: 9.4.2_fejcc7gjbwtmwzggoernzojija ts-node: 10.9.1_wh2cnrlliuuxb2etxm2m3ttgna tsconfig-paths: 4.1.2 typescript: 4.9.5 @@ -753,17 +753,24 @@ importers: apps/widget: specifiers: '@ant-design/icons': ^4.5.0 - '@craco/craco': ^7.0.0 + '@babel/plugin-proposal-optional-chaining': ^7.20.7 + '@babel/plugin-transform-react-display-name': ^7.18.6 + '@babel/plugin-transform-runtime': ^7.19.6 + '@babel/polyfill': ^7.12.1 + '@babel/preset-env': ^7.13.15 + '@babel/preset-react': ^7.13.13 + '@babel/preset-typescript': ^7.13.0 + '@babel/runtime': ^7.20.13 '@emotion/babel-plugin': ^11.7.2 '@emotion/react': ^11.7.1 '@emotion/styled': ^11.6.0 '@faker-js/faker': ^6.0.0 '@mantine/core': 4.2.12 '@mantine/hooks': 4.2.12 - '@novu/dal': ^0.19.0 - '@novu/notification-center': ^0.19.0 - '@novu/shared': ^0.19.0 - '@novu/testing': ^0.19.0 + '@novu/dal': ^0.20.0-alpha.0 + '@novu/notification-center': ^0.20.0-alpha.0 + '@novu/shared': ^0.20.0-alpha.0 + '@novu/testing': ^0.20.0-alpha.0 '@types/jest': ^29.5.0 '@types/node': ^12.0.0 '@types/react': 17.0.62 @@ -772,8 +779,8 @@ importers: antd: ^4.10.0 babel-plugin-import: ^1.13.3 chroma-js: ^2.4.2 - craco-antd: ^1.19.0 cross-env: ^7.0.3 + customize-cra: ^1.0.0 cypress: ^12.17.2 cypress-intellij-reporter: ^0.0.7 cypress-network-idle: ^1.10.0 @@ -787,6 +794,7 @@ importers: less-loader: 4.1.0 polished: ^4.1.2 react: 17.0.2 + react-app-rewired: ^2.2.1 react-dom: 17.0.2 react-infinite-scroll-component: ^6.0.0 react-infinite-scroller: ^1.2.4 @@ -799,7 +807,7 @@ importers: typescript: 4.9.5 web-vitals: ^0.2.4 webfontloader: ^1.6.28 - webpack: ^5.78.0 + webpack: 5.78.0 webpack-dev-server: 4.11.1 dependencies: '@ant-design/icons': 4.8.0_sfoxds7t5ydpegc3knd667wn6m @@ -829,7 +837,14 @@ importers: web-vitals: 0.2.4 webfontloader: 1.6.28 devDependencies: - '@craco/craco': 7.1.0_s2wp4rvkjiflatocn7n5b6ts7m + '@babel/plugin-proposal-optional-chaining': 7.21.0_@babel+core@7.22.11 + '@babel/plugin-transform-react-display-name': 7.22.5_@babel+core@7.22.11 + '@babel/plugin-transform-runtime': 7.21.4_@babel+core@7.22.11 + '@babel/polyfill': 7.12.1 + '@babel/preset-env': 7.22.20_@babel+core@7.22.11 + '@babel/preset-react': 7.22.15_@babel+core@7.22.11 + '@babel/preset-typescript': 7.21.4_@babel+core@7.22.11 + '@babel/runtime': 7.21.0 '@emotion/babel-plugin': 11.10.6 '@faker-js/faker': 6.3.1 '@novu/dal': link:../../libs/dal @@ -839,19 +854,20 @@ importers: '@types/react': 17.0.62 '@types/react-dom': 17.0.20 '@types/react-router-dom': 5.3.3 - craco-antd: 1.19.0_3cpxdta34n6sqgppckwpiuxhwa cross-env: 7.0.3 + customize-cra: 1.0.0 cypress: 12.17.3 cypress-intellij-reporter: 0.0.7 cypress-network-idle: 1.14.2 - html-webpack-plugin: 5.5.3_webpack@5.88.2 + html-webpack-plugin: 5.5.3_webpack@5.78.0 http-server: 0.13.0 jest: 27.5.1 less: 4.1.3 - less-loader: 4.1.0_less@4.1.3+webpack@5.88.2 + less-loader: 4.1.0_less@4.1.3+webpack@5.78.0 + react-app-rewired: 2.2.1_react-scripts@5.0.1 typescript: 4.9.5 - webpack: 5.88.2 - webpack-dev-server: 4.11.1_webpack@5.88.2 + webpack: 5.78.0 + webpack-dev-server: 4.11.1_webpack@5.78.0 apps/worker: specifiers: @@ -865,11 +881,11 @@ importers: '@nestjs/swagger': ^7.1.9 '@nestjs/terminus': ^10.0.1 '@nestjs/testing': ^10.2.2 - '@novu/application-generic': ^0.19.0 - '@novu/dal': ^0.19.0 - '@novu/shared': ^0.19.0 - '@novu/stateless': ^0.19.0 - '@novu/testing': ^0.19.0 + '@novu/application-generic': ^0.20.0-alpha.0 + '@novu/dal': ^0.20.0-alpha.0 + '@novu/shared': ^0.20.0-alpha.0 + '@novu/stateless': ^0.20.0-alpha.0 + '@novu/testing': ^0.20.0-alpha.0 '@sentry/node': ^7.40.0 '@sentry/tracing': ^7.40.0 '@types/bcrypt': ^3.0.0 @@ -963,7 +979,7 @@ importers: sinon: 9.2.4 superagent-defaults: 0.1.14_superagent@8.0.9 supertest: 5.0.0 - ts-loader: 9.4.2_rggdtlzfqxxwxudp3onsqdyocm + ts-loader: 9.4.2_fejcc7gjbwtmwzggoernzojija ts-node: 10.9.1_wh2cnrlliuuxb2etxm2m3ttgna tsconfig-paths: 4.1.2 typescript: 4.9.5 @@ -982,10 +998,10 @@ importers: '@nestjs/terminus': ^10.0.1 '@nestjs/testing': ^10.2.2 '@nestjs/websockets': ^10.2.2 - '@novu/application-generic': ^0.19.0 - '@novu/dal': ^0.19.0 - '@novu/shared': ^0.19.0 - '@novu/testing': ^0.19.0 + '@novu/application-generic': ^0.20.0-alpha.0 + '@novu/dal': ^0.20.0-alpha.0 + '@novu/shared': ^0.20.0-alpha.0 + '@novu/testing': ^0.20.0-alpha.0 '@sentry/node': ^7.30.0 '@socket.io/redis-adapter': ^7.2.0 '@types/chai': ^4.2.11 @@ -1068,95 +1084,17 @@ importers: nodemon: 2.0.22 prettier: 2.8.7 supertest: 6.3.3 - ts-loader: 9.4.2_rggdtlzfqxxwxudp3onsqdyocm + ts-loader: 9.4.2_fejcc7gjbwtmwzggoernzojija ts-node: 10.9.1_wh2cnrlliuuxb2etxm2m3ttgna tsconfig-paths: 4.1.2 typescript: 4.9.5 - enterprise/packages/auth: - specifiers: - '@nestjs/common': '>=9.3.x' - '@nestjs/jwt': '>=9' - '@nestjs/passport': 9.0.3 - '@novu/application-generic': ^0.19.0 - '@novu/dal': ^0.19.0 - '@novu/shared': ^0.19.0 - '@types/chai': ^4.2.11 - '@types/mocha': ^8.0.1 - '@types/node': ^14.6.0 - '@types/sinon': ^9.0.0 - chai: ^4.2.0 - cross-env: ^7.0.3 - mocha: ^8.1.1 - nodemon: ^2.0.3 - passport: 0.6.0 - passport-google-oauth: ^2.0.0 - passport-oauth2: ^1.6.1 - sinon: ^9.2.4 - ts-node: ~10.9.1 - typescript: 4.9.5 - dependencies: - '@nestjs/common': 10.2.2_atc7tu2sld2m3nk4hmwkqn6qde - '@nestjs/jwt': 10.1.0_@nestjs+common@10.2.2 - '@nestjs/passport': 9.0.3_kn4ljbedllcoqpuu4ifhphsdsu - '@novu/application-generic': link:../../../packages/application-generic - '@novu/dal': link:../../../libs/dal - '@novu/shared': link:../../../libs/shared - passport: 0.6.0 - passport-google-oauth: 2.0.0 - passport-oauth2: 1.7.0 - devDependencies: - '@types/chai': 4.3.4 - '@types/mocha': 8.2.3 - '@types/node': 14.18.42 - '@types/sinon': 9.0.11 - chai: 4.3.7 - cross-env: 7.0.3 - mocha: 8.4.0 - nodemon: 2.0.22 - sinon: 9.2.4 - ts-node: 10.9.1_wh2cnrlliuuxb2etxm2m3ttgna - typescript: 4.9.5 - - enterprise/packages/digest-schedule: - specifiers: - '@novu/shared': ^0.19.0 - '@types/chai': ^4.2.11 - '@types/mocha': ^8.0.1 - '@types/node': ^14.6.0 - '@types/sinon': ^9.0.0 - chai: ^4.2.0 - cross-env: ^7.0.3 - date-fns: ^2.29.2 - mocha: ^8.1.1 - nodemon: ^2.0.3 - rrule: ^2.7.2 - sinon: ^9.2.4 - ts-node: ~10.9.1 - typescript: 4.9.5 - dependencies: - '@novu/shared': link:../../../libs/shared - date-fns: 2.29.3 - rrule: 2.7.2 - devDependencies: - '@types/chai': 4.3.4 - '@types/mocha': 8.2.3 - '@types/node': 14.18.42 - '@types/sinon': 9.0.11 - chai: 4.3.7 - cross-env: 7.0.3 - mocha: 8.4.0 - nodemon: 2.0.22 - sinon: 9.2.4 - ts-node: 10.9.1_wh2cnrlliuuxb2etxm2m3ttgna - typescript: 4.9.5 - libs/dal: specifiers: '@aws-sdk/client-s3': ^3.382.0 '@aws-sdk/s3-request-presigner': ^3.382.0 '@faker-js/faker': ^6.0.0 - '@novu/shared': ^0.19.0 + '@novu/shared': ^0.20.0-alpha.0 '@sendgrid/mail': ^7.4.2 '@types/async': ^3.2.1 '@types/bluebird': ^3.5.30 @@ -1232,7 +1170,7 @@ importers: specifiers: '@commitlint/cli': ^17.0.0 '@commitlint/config-conventional': ^17.0.0 - '@novu/notification-center': ^0.19.0 + '@novu/notification-center': ^0.20.0-alpha.0 '@rollup/plugin-node-resolve': ^6.0.0 '@rollup/plugin-replace': ^5.0.2 '@types/iframe-resizer': ^3.5.8 @@ -1321,8 +1259,8 @@ importers: libs/testing: specifiers: '@faker-js/faker': ^6.0.0 - '@novu/dal': ^0.19.0 - '@novu/shared': ^0.19.0 + '@novu/dal': ^0.20.0-alpha.0 + '@novu/shared': ^0.20.0-alpha.0 '@types/async': ^3.2.1 '@types/bluebird': ^3.5.30 '@types/node': ^14.6.0 @@ -1400,52 +1338,53 @@ importers: '@nestjs/swagger': '>=6' '@nestjs/terminus': '>=10' '@nestjs/testing': '>=10' - '@novu/africas-talking': ^0.19.0 - '@novu/apns': ^0.19.0 - '@novu/burst-sms': ^0.19.0 - '@novu/clickatell': ^0.19.0 - '@novu/dal': ^0.19.0 - '@novu/discord': ^0.19.0 - '@novu/email-webhook': ^0.19.0 - '@novu/emailjs': ^0.19.0 - '@novu/expo': ^0.19.0 - '@novu/fcm': ^0.19.0 - '@novu/firetext': ^0.19.0 - '@novu/forty-six-elks': ^0.19.0 - '@novu/gupshup': ^0.19.0 - '@novu/infobip': ^0.19.0 - '@novu/kannel': ^0.19.0 - '@novu/mailersend': ^0.19.0 - '@novu/mailgun': ^0.19.0 - '@novu/mailjet': ^0.19.0 - '@novu/mandrill': ^0.19.0 - '@novu/maqsam': ^0.19.0 - '@novu/mattermost': ^0.19.0 - '@novu/ms-teams': ^0.19.0 - '@novu/netcore': ^0.19.0 - '@novu/nodemailer': ^0.19.0 - '@novu/one-signal': ^0.19.0 - '@novu/outlook365': ^0.19.0 - '@novu/plivo': ^0.19.0 - '@novu/plunk': ^0.19.0 - '@novu/postmark': ^0.19.0 - '@novu/push-webhook': ^0.19.0 - '@novu/resend': ^0.19.0 - '@novu/sendchamp': ^0.19.0 - '@novu/sendgrid': ^0.19.0 - '@novu/sendinblue': ^0.19.0 - '@novu/ses': ^0.19.0 - '@novu/shared': ^0.19.0 - '@novu/slack': ^0.19.0 - '@novu/sms-central': ^0.19.0 - '@novu/sms77': ^0.19.0 - '@novu/sns': ^0.19.0 - '@novu/sparkpost': ^0.19.0 - '@novu/stateless': ^0.19.0 - '@novu/telnyx': ^0.19.0 - '@novu/termii': ^0.19.0 - '@novu/testing': ^0.19.0 - '@novu/twilio': ^0.19.0 + '@novu/africas-talking': ^0.20.0-alpha.0 + '@novu/apns': ^0.20.0-alpha.0 + '@novu/burst-sms': ^0.20.0-alpha.0 + '@novu/clickatell': ^0.20.0-alpha.0 + '@novu/dal': ^0.20.0-alpha.0 + '@novu/discord': ^0.20.0-alpha.0 + '@novu/email-webhook': ^0.20.0-alpha.0 + '@novu/emailjs': ^0.20.0-alpha.0 + '@novu/expo': ^0.20.0-alpha.0 + '@novu/fcm': ^0.20.0-alpha.0 + '@novu/firetext': ^0.20.0-alpha.0 + '@novu/forty-six-elks': ^0.20.0-alpha.0 + '@novu/gupshup': ^0.20.0-alpha.0 + '@novu/infobip': ^0.20.0-alpha.0 + '@novu/kannel': ^0.20.0-alpha.0 + '@novu/mailersend': ^0.20.0-alpha.0 + '@novu/mailgun': ^0.20.0-alpha.0 + '@novu/mailjet': ^0.20.0-alpha.0 + '@novu/mailtrap': ^0.20.0-alpha.0 + '@novu/mandrill': ^0.20.0-alpha.0 + '@novu/maqsam': ^0.20.0-alpha.0 + '@novu/mattermost': ^0.20.0-alpha.0 + '@novu/ms-teams': ^0.20.0-alpha.0 + '@novu/netcore': ^0.20.0-alpha.0 + '@novu/nodemailer': ^0.20.0-alpha.0 + '@novu/one-signal': ^0.20.0-alpha.0 + '@novu/outlook365': ^0.20.0-alpha.0 + '@novu/plivo': ^0.20.0-alpha.0 + '@novu/plunk': ^0.20.0-alpha.0 + '@novu/postmark': ^0.20.0-alpha.0 + '@novu/push-webhook': ^0.20.0-alpha.0 + '@novu/resend': ^0.20.0-alpha.0 + '@novu/sendchamp': ^0.20.0-alpha.0 + '@novu/sendgrid': ^0.20.0-alpha.0 + '@novu/sendinblue': ^0.20.0-alpha.0 + '@novu/ses': ^0.20.0-alpha.0 + '@novu/shared': ^0.20.0-alpha.0 + '@novu/slack': ^0.20.0-alpha.0 + '@novu/sms-central': ^0.20.0-alpha.0 + '@novu/sms77': ^0.20.0-alpha.0 + '@novu/sns': ^0.20.0-alpha.0 + '@novu/sparkpost': ^0.20.0-alpha.0 + '@novu/stateless': ^0.20.0-alpha.0 + '@novu/telnyx': ^0.20.0-alpha.0 + '@novu/termii': ^0.20.0-alpha.0 + '@novu/testing': ^0.20.0-alpha.0 + '@novu/twilio': ^0.20.0-alpha.0 '@sentry/node': ^7.12.1 '@taskforcesh/bullmq-pro': 5.1.14 '@types/analytics-node': ^3.1.9 @@ -1464,6 +1403,7 @@ importers: jest: ^27.1.0 launchdarkly-node-server-sdk: ^7.0.1 lodash: ^4.17.15 + mixpanel: ^0.17.0 nestjs-pino: ^3.4.0 newrelic: ^9 node-fetch: ^3.2.10 @@ -1509,6 +1449,7 @@ importers: '@novu/mailersend': link:../../providers/mailersend '@novu/mailgun': link:../../providers/mailgun '@novu/mailjet': link:../../providers/mailjet + '@novu/mailtrap': link:../../providers/mailtrap '@novu/mandrill': link:../../providers/mandrill '@novu/maqsam': link:../../providers/maqsam '@novu/mattermost': link:../../providers/mattermost @@ -1547,6 +1488,7 @@ importers: ioredis: 5.3.1 launchdarkly-node-server-sdk: 7.0.1 lodash: 4.17.21 + mixpanel: 0.17.0 nestjs-pino: 3.4.0_63skzxoikz7i6kgl2v2i7k2p4y newrelic: 9.15.0 node-fetch: 3.3.1 @@ -1577,7 +1519,7 @@ importers: packages/cli: specifiers: - '@novu/shared': ^0.19.0 + '@novu/shared': ^0.20.0-alpha.0 '@types/analytics-node': ^3.1.9 '@types/configstore': ^5.0.1 '@types/inquirer': ^8.2.0 @@ -1626,7 +1568,7 @@ importers: packages/client: specifiers: - '@novu/shared': ^0.19.0 + '@novu/shared': ^0.20.0-alpha.0 '@types/jest': 29.5.2 '@types/node': ^14.6.0 codecov: ^3.5.0 @@ -1653,8 +1595,8 @@ importers: specifiers: '@babel/preset-env': ^7.13.15 '@babel/preset-typescript': ^7.13.0 - '@novu/client': ^0.19.0 - '@novu/shared': ^0.19.0 + '@novu/client': ^0.20.0-alpha.0 + '@novu/shared': ^0.20.0-alpha.0 '@tanstack/query-core': ^4.15.1 '@types/jest': ^29.2.3 '@types/node': ^14.6.0 @@ -1684,7 +1626,7 @@ importers: specifiers: '@istanbuljs/nyc-config-typescript': ^1.0.1 '@nestjs/common': ^8.2.0 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': 29.5.2 codecov: ^3.5.0 cspell: ^4.1.0 @@ -1721,7 +1663,7 @@ importers: packages/node: specifiers: - '@novu/shared': ^0.19.0 + '@novu/shared': ^0.20.0-alpha.0 '@sendgrid/mail': ^7.4.6 '@types/jest': 29.5.2 '@types/lodash.get': ^4.4.6 @@ -1772,8 +1714,8 @@ importers: '@emotion/styled': ^11.6.0 '@mantine/core': ^5.7.1 '@mantine/hooks': ^5.7.1 - '@novu/client': ^0.19.0 - '@novu/shared': ^0.19.0 + '@novu/client': ^0.20.0-alpha.0 + '@novu/shared': ^0.20.0-alpha.0 '@storybook/addon-actions': ^7.4.2 '@storybook/addon-essentials': ^7.4.2 '@storybook/addon-interactions': ^7.4.2 @@ -1887,7 +1829,7 @@ importers: '@angular/core': ~15.2.0 '@angular/platform-browser': ~15.2.0 '@angular/platform-browser-dynamic': ~15.2.0 - '@novu/notification-center': ^0.19.0 + '@novu/notification-center': ^0.20.0-alpha.0 '@types/jasmine': ~4.3.0 jasmine-core: ~4.6.0 karma: ~6.4.0 @@ -1930,7 +1872,7 @@ importers: specifiers: '@emotion/css': ^11.10.5 '@novu/floating-vue': ^2.0.3 - '@novu/notification-center': ^0.19.0 + '@novu/notification-center': ^0.20.0-alpha.0 '@rushstack/eslint-patch': ^1.1.4 '@types/node': ^18.11.12 '@vitejs/plugin-vue': ^4.0.0 @@ -2013,7 +1955,7 @@ importers: providers/africas-talking: specifiers: '@istanbuljs/nyc-config-typescript': ~1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ~29.5.0 africastalking: ^0.6.2 cspell: ~6.19.2 @@ -2044,7 +1986,7 @@ importers: providers/apns: specifiers: '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@parse/node-apn': ^5.2.3 '@types/jest': ^29.5.0 codecov: ^3.5.0 @@ -2081,7 +2023,7 @@ importers: providers/burst-sms: specifiers: '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ^29.5.0 axios: ^1.3.3 codecov: ^3.5.0 @@ -2124,7 +2066,7 @@ importers: providers/clickatell: specifiers: '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ^29.5.0 axios: ^1.3.3 codecov: ^3.5.0 @@ -2161,7 +2103,7 @@ importers: providers/discord: specifiers: '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ^29.5.0 axios: ^1.3.3 codecov: ^3.5.0 @@ -2231,7 +2173,7 @@ importers: providers/emailjs: specifiers: '@istanbuljs/nyc-config-typescript': 1.0.2 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': 29.5.2 codecov: ^3.5.0 cspell: ^4.1.0 @@ -2270,7 +2212,7 @@ importers: providers/expo: specifiers: '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ^29.5.0 codecov: ^3.5.0 cspell: ^4.1.0 @@ -2309,7 +2251,7 @@ importers: providers/fcm: specifiers: '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ^29.5.0 '@types/mocha': ^8.0.1 codecov: ^3.5.0 @@ -2355,7 +2297,7 @@ importers: specifiers: '@babel/preset-env': ^7.13.15 '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ^29.5.0 '@types/uuid': ^8.3.4 codecov: ^3.5.0 @@ -2399,7 +2341,7 @@ importers: providers/forty-six-elks: specifiers: '@istanbuljs/nyc-config-typescript': ~1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ~29.5.0 axios: ^1.3.4 cspell: ~6.19.2 @@ -2431,7 +2373,7 @@ importers: specifiers: '@babel/preset-env': ^7.13.15 '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ^29.5.0 codecov: ^3.5.0 cspell: ^4.1.0 @@ -2472,7 +2414,7 @@ importers: specifiers: '@infobip-api/sdk': ^0.2.0 '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ^29.5.0 codecov: ^3.5.0 cspell: ^4.1.0 @@ -2510,7 +2452,7 @@ importers: providers/kannel: specifiers: '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ^29.5.0 axios: ^0.27.2 codecov: ^3.5.0 @@ -2549,7 +2491,7 @@ importers: providers/mailersend: specifiers: '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ^29.5.0 codecov: ^3.5.0 cspell: ^4.1.0 @@ -2588,7 +2530,7 @@ importers: providers/mailgun: specifiers: '@istanbuljs/nyc-config-typescript': 1.0.2 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': 29.5.2 codecov: ^3.5.0 cspell: ^4.1.0 @@ -2631,7 +2573,7 @@ importers: providers/mailjet: specifiers: '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': 29.5.2 '@types/node-mailjet': ^3.3.7 codecov: ^3.5.0 @@ -2669,11 +2611,42 @@ importers: typedoc: 0.24.6_typescript@4.9.5 typescript: 4.9.5 + providers/mailtrap: + specifiers: + '@istanbuljs/nyc-config-typescript': ~1.0.1 + '@novu/stateless': 0.20.0-alpha.0 + '@types/jest': ~27.5.2 + cspell: ~6.19.2 + jest: ~27.5.1 + mailtrap: ^3.1.1 + npm-run-all: ^4.1.5 + nyc: ~15.1.0 + prettier: ~2.8.0 + rimraf: ~3.0.2 + ts-jest: ~27.1.5 + ts-node: ~10.9.1 + typescript: 4.9.5 + dependencies: + '@novu/stateless': link:../../packages/stateless + mailtrap: 3.2.0 + devDependencies: + '@istanbuljs/nyc-config-typescript': 1.0.2_nyc@15.1.0 + '@types/jest': 27.5.2 + cspell: 6.19.2 + jest: 27.5.1_ts-node@10.9.1 + npm-run-all: 4.1.5 + nyc: 15.1.0 + prettier: 2.8.7 + rimraf: 3.0.2 + ts-jest: 27.1.5_tdguimvmawsauzyxxfukpkg77i + ts-node: 10.9.1_wh2cnrlliuuxb2etxm2m3ttgna + typescript: 4.9.5 + providers/mandrill: specifiers: '@istanbuljs/nyc-config-typescript': 1.0.2 '@mailchimp/mailchimp_transactional': ^1.0.46 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': 29.5.2 codecov: ^3.5.0 cspell: ^4.1.0 @@ -2715,7 +2688,7 @@ importers: providers/maqsam: specifiers: '@istanbuljs/nyc-config-typescript': ~1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ~29.5.0 axios: ^1.3.4 cspell: ~6.19.2 @@ -2750,7 +2723,7 @@ importers: providers/mattermost: specifiers: '@istanbuljs/nyc-config-typescript': ~1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ~29.5.0 axios: ^1.3.3 cspell: ~6.19.2 @@ -2822,7 +2795,7 @@ importers: providers/netcore: specifiers: '@istanbuljs/nyc-config-typescript': 1.0.2 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': 29.5.2 codecov: ^3.5.0 cspell: ^4.1.0 @@ -2861,7 +2834,7 @@ importers: providers/nexmo: specifiers: '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': 29.5.2 '@vonage/server-sdk': ^2.10.10 codecov: ^3.5.0 @@ -2900,7 +2873,7 @@ importers: providers/nodemailer: specifiers: '@istanbuljs/nyc-config-typescript': 1.0.2 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': 29.5.2 '@types/nodemailer': ^6.4.4 codecov: ^3.5.0 @@ -2941,7 +2914,7 @@ importers: providers/one-signal: specifiers: '@istanbuljs/nyc-config-typescript': ~1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ~29.5.0 cspell: ~6.19.2 jest: ~27.5.1 @@ -2972,8 +2945,9 @@ importers: providers/outlook365: specifiers: '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ^29.5.0 + '@types/nodemailer': ^6.4.11 codecov: ^3.5.0 cspell: ^4.1.0 gh-pages: ^3.1.0 @@ -2994,6 +2968,7 @@ importers: devDependencies: '@istanbuljs/nyc-config-typescript': 1.0.2_nyc@15.1.0 '@types/jest': 29.5.1 + '@types/nodemailer': 6.4.11 codecov: 3.8.3 cspell: 4.2.8 gh-pages: 3.2.3 @@ -3011,7 +2986,7 @@ importers: providers/plivo: specifiers: '@istanbuljs/nyc-config-typescript': 1.0.2 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': 29.5.2 codecov: ^3.5.0 cspell: ^4.1.0 @@ -3050,7 +3025,7 @@ importers: providers/plunk: specifiers: '@istanbuljs/nyc-config-typescript': ~1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@plunk/node': 2.0.0 '@types/jest': ~27.5.2 cspell: ~6.19.2 @@ -3081,7 +3056,7 @@ importers: providers/postmark: specifiers: '@istanbuljs/nyc-config-typescript': 1.0.2 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': 29.5.2 axios: ^1.3.6 codecov: ^3.5.0 @@ -3122,7 +3097,7 @@ importers: providers/push-webhook: specifiers: '@istanbuljs/nyc-config-typescript': ~1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ~29.5.0 axios: ^1.3.5 cspell: ~6.19.2 @@ -3153,7 +3128,7 @@ importers: providers/resend: specifiers: '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ^29.5.0 codecov: ^3.5.0 cspell: ^4.1.0 @@ -3192,7 +3167,7 @@ importers: providers/sendchamp: specifiers: '@istanbuljs/nyc-config-typescript': ~1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ~27.5.2 axios: ^1.4.0 cspell: ~6.19.2 @@ -3223,7 +3198,7 @@ importers: providers/sendgrid: specifiers: '@istanbuljs/nyc-config-typescript': 1.0.2 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@sendgrid/mail': ^7.4.6 '@types/jest': 29.5.2 codecov: ^3.5.0 @@ -3262,7 +3237,7 @@ importers: providers/sendinblue: specifiers: '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@sendinblue/client': ^3.0.1 '@types/jest': 29.5.2 codecov: ^3.5.0 @@ -3302,7 +3277,7 @@ importers: specifiers: '@aws-sdk/client-ses': 3.382.0 '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': 29.5.2 codecov: ^3.5.0 cspell: ^4.1.0 @@ -3342,7 +3317,7 @@ importers: providers/slack: specifiers: '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ^29.5.0 axios: ^1.3.3 codecov: ^3.5.0 @@ -3413,7 +3388,7 @@ importers: specifiers: '@babel/preset-env': ^7.13.15 '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': 29.5.2 codecov: ^3.5.0 cspell: ^4.1.0 @@ -3456,7 +3431,7 @@ importers: specifiers: '@aws-sdk/client-sns': ^3.382.0 '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': 29.5.2 codecov: ^3.5.0 cspell: ^4.1.0 @@ -3494,7 +3469,7 @@ importers: providers/sparkpost: specifiers: '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ^29.5.0 '@types/sparkpost': ^2.1.5 codecov: ^3.5.0 @@ -3535,7 +3510,7 @@ importers: providers/telnyx: specifiers: '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ^29.5.0 codecov: ^3.5.0 cspell: ^4.1.0 @@ -3575,7 +3550,7 @@ importers: specifiers: '@babel/preset-env': ^7.13.15 '@istanbuljs/nyc-config-typescript': ^1.0.1 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': ^29.5.0 codecov: ^3.5.0 cspell: ^4.1.0 @@ -3615,7 +3590,7 @@ importers: providers/twilio: specifiers: '@istanbuljs/nyc-config-typescript': 1.0.2 - '@novu/stateless': ^0.19.0 + '@novu/stateless': ^0.20.0-alpha.0 '@types/jest': 29.5.2 codecov: ^3.5.0 cspell: ^4.1.0 @@ -4091,9 +4066,11 @@ packages: resolution: {integrity: sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==} dependencies: '@ctrl/tinycolor': 3.6.0 + dev: false /@ant-design/icons-svg/4.2.1: resolution: {integrity: sha512-EB0iwlKDGpG93hW8f85CTJTs4SvMX7tt5ceupvhALp1IF44SeUFOMhKUOYqpsoYWQKAOuTRDMqn75rEaKDp0Xw==} + dev: false /@ant-design/icons/4.8.0_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-T89P2jG2vM7OJ0IfGx2+9FC5sQjtTzRSz+mCHTXkFn/ELZc2YpfStmYHmqzq2Jx55J0F7+O6i5/ZKFSVNWCKNg==} @@ -4109,6 +4086,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /@ant-design/react-slick/0.29.2_react@17.0.2: resolution: {integrity: sha512-kgjtKmkGHa19FW21lHnAfyyH9AAoh35pBdcJ53rHmQ3O+cfFHGHnUbj/HFrRNJ5vIts09FKJVAD8RpaC+RaWfA==} @@ -4121,6 +4099,7 @@ packages: lodash: 4.17.21 react: 17.0.2 resize-observer-polyfill: 1.5.1 + dev: false /@apideck/better-ajv-errors/0.3.6_ajv@8.12.0: resolution: {integrity: sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==} @@ -5370,7 +5349,7 @@ packages: /@babel/code-frame/7.12.11: resolution: {integrity: sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==} dependencies: - '@babel/highlight': 7.18.6 + '@babel/highlight': 7.22.13 dev: true /@babel/code-frame/7.21.4: @@ -5386,19 +5365,10 @@ packages: '@babel/highlight': 7.22.13 chalk: 2.4.2 - /@babel/compat-data/7.21.4: - resolution: {integrity: sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==} - engines: {node: '>=6.9.0'} - /@babel/compat-data/7.22.20: resolution: {integrity: sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==} engines: {node: '>=6.9.0'} - /@babel/compat-data/7.22.9: - resolution: {integrity: sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==} - engines: {node: '>=6.9.0'} - dev: true - /@babel/core/7.19.3: resolution: {integrity: sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==} engines: {node: '>=6.9.0'} @@ -5406,13 +5376,13 @@ packages: '@ampproject/remapping': 2.2.1 '@babel/code-frame': 7.22.13 '@babel/generator': 7.21.4 - '@babel/helper-compilation-targets': 7.21.4_@babel+core@7.19.3 - '@babel/helper-module-transforms': 7.21.2 + '@babel/helper-compilation-targets': 7.22.15 + '@babel/helper-module-transforms': 7.22.20_@babel+core@7.19.3 '@babel/helpers': 7.21.0 - '@babel/parser': 7.21.4 - '@babel/template': 7.20.7 + '@babel/parser': 7.22.16 + '@babel/template': 7.22.15 '@babel/traverse': 7.21.4 - '@babel/types': 7.21.4 + '@babel/types': 7.22.19 convert-source-map: 1.9.0 debug: 4.3.4 gensync: 1.0.0-beta.2 @@ -5429,13 +5399,13 @@ packages: '@ampproject/remapping': 2.2.1 '@babel/code-frame': 7.22.13 '@babel/generator': 7.21.4 - '@babel/helper-compilation-targets': 7.21.4_@babel+core@7.20.12 - '@babel/helper-module-transforms': 7.21.2 + '@babel/helper-compilation-targets': 7.22.15 + '@babel/helper-module-transforms': 7.22.20_@babel+core@7.20.12 '@babel/helpers': 7.21.0 - '@babel/parser': 7.21.4 - '@babel/template': 7.20.7 + '@babel/parser': 7.22.16 + '@babel/template': 7.22.15 '@babel/traverse': 7.21.4 - '@babel/types': 7.21.4 + '@babel/types': 7.22.19 convert-source-map: 1.9.0 debug: 4.3.4 gensync: 1.0.0-beta.2 @@ -5452,13 +5422,13 @@ packages: '@ampproject/remapping': 2.2.1 '@babel/code-frame': 7.22.13 '@babel/generator': 7.21.4 - '@babel/helper-compilation-targets': 7.21.4_@babel+core@7.21.4 - '@babel/helper-module-transforms': 7.21.2 + '@babel/helper-compilation-targets': 7.22.15 + '@babel/helper-module-transforms': 7.22.20_@babel+core@7.21.4 '@babel/helpers': 7.21.0 - '@babel/parser': 7.21.4 - '@babel/template': 7.20.7 + '@babel/parser': 7.22.16 + '@babel/template': 7.22.15 '@babel/traverse': 7.21.4 - '@babel/types': 7.21.4 + '@babel/types': 7.22.19 convert-source-map: 1.9.0 debug: 4.3.4 gensync: 1.0.0-beta.2 @@ -5506,7 +5476,7 @@ packages: resolution: {integrity: sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.21.4 + '@babel/types': 7.22.19 '@jridgewell/gen-mapping': 0.3.3 jsesc: 2.5.2 dev: true @@ -5534,6 +5504,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.22.19 + dev: true /@babel/helper-annotate-as-pure/7.22.5: resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} @@ -5541,71 +5512,11 @@ packages: dependencies: '@babel/types': 7.22.19 - /@babel/helper-builder-binary-assignment-operator-visitor/7.18.9: - resolution: {integrity: sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-explode-assignable-expression': 7.18.6 - '@babel/types': 7.22.19 - /@babel/helper-builder-binary-assignment-operator-visitor/7.22.15: resolution: {integrity: sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.22.19 - dev: true - - /@babel/helper-compilation-targets/7.21.4_@babel+core@7.19.3: - resolution: {integrity: sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/compat-data': 7.21.4 - '@babel/core': 7.19.3 - '@babel/helper-validator-option': 7.21.0 - browserslist: 4.21.10 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - - /@babel/helper-compilation-targets/7.21.4_@babel+core@7.20.12: - resolution: {integrity: sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/compat-data': 7.21.4 - '@babel/core': 7.20.12 - '@babel/helper-validator-option': 7.21.0 - browserslist: 4.21.10 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - - /@babel/helper-compilation-targets/7.21.4_@babel+core@7.21.4: - resolution: {integrity: sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/compat-data': 7.21.4 - '@babel/core': 7.21.4 - '@babel/helper-validator-option': 7.21.0 - browserslist: 4.21.10 - lru-cache: 5.1.1 - semver: 6.3.1 - - /@babel/helper-compilation-targets/7.22.10: - resolution: {integrity: sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.22.9 - '@babel/helper-validator-option': 7.22.15 - browserslist: 4.21.10 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true /@babel/helper-compilation-targets/7.22.15: resolution: {integrity: sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==} @@ -5617,43 +5528,6 @@ packages: lru-cache: 5.1.1 semver: 6.3.1 - /@babel/helper-create-class-features-plugin/7.21.4_@babel+core@7.20.12: - resolution: {integrity: sha512-46QrX2CQlaFRF4TkwfTt6nJD7IHq8539cCL7SDpqWSDeJKY1xylKKY5F/33mJhLZ3mFvKv2gGrVS6NkyF6qs+Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.5 - '@babel/helper-function-name': 7.22.5 - '@babel/helper-member-expression-to-functions': 7.21.0 - '@babel/helper-optimise-call-expression': 7.18.6 - '@babel/helper-replace-supers': 7.20.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - '@babel/helper-split-export-declaration': 7.22.6 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-create-class-features-plugin/7.21.4_@babel+core@7.22.11: - resolution: {integrity: sha512-46QrX2CQlaFRF4TkwfTt6nJD7IHq8539cCL7SDpqWSDeJKY1xylKKY5F/33mJhLZ3mFvKv2gGrVS6NkyF6qs+Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.22.11 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.22.5 - '@babel/helper-member-expression-to-functions': 7.21.0 - '@babel/helper-optimise-call-expression': 7.18.6 - '@babel/helper-replace-supers': 7.20.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - '@babel/helper-split-export-declaration': 7.22.6 - transitivePeerDependencies: - - supports-color - /@babel/helper-create-class-features-plugin/7.22.15_@babel+core@7.20.12: resolution: {integrity: sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==} engines: {node: '>=6.9.0'} @@ -5707,8 +5581,8 @@ packages: '@babel/helper-split-export-declaration': 7.22.6 semver: 6.3.1 - /@babel/helper-create-regexp-features-plugin/7.21.4_@babel+core@7.20.12: - resolution: {integrity: sha512-M00OuhU+0GyZ5iBBN9czjugzWrEq2vDpf/zCYHxxf93ul/Q5rv+a5h+/+0WnI1AebHNVtl5bFV0qsJoH23DbfA==} + /@babel/helper-create-regexp-features-plugin/7.22.15_@babel+core@7.20.12: + resolution: {integrity: sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -5716,18 +5590,9 @@ packages: '@babel/core': 7.20.12 '@babel/helper-annotate-as-pure': 7.22.5 regexpu-core: 5.3.2 + semver: 6.3.1 dev: true - /@babel/helper-create-regexp-features-plugin/7.21.4_@babel+core@7.22.11: - resolution: {integrity: sha512-M00OuhU+0GyZ5iBBN9czjugzWrEq2vDpf/zCYHxxf93ul/Q5rv+a5h+/+0WnI1AebHNVtl5bFV0qsJoH23DbfA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.22.11 - '@babel/helper-annotate-as-pure': 7.22.5 - regexpu-core: 5.3.2 - /@babel/helper-create-regexp-features-plugin/7.22.15_@babel+core@7.22.11: resolution: {integrity: sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==} engines: {node: '>=6.9.0'} @@ -5738,7 +5603,6 @@ packages: '@babel/helper-annotate-as-pure': 7.22.5 regexpu-core: 5.3.2 semver: 6.3.1 - dev: true /@babel/helper-define-polyfill-provider/0.3.3_@babel+core@7.20.12: resolution: {integrity: sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==} @@ -5784,26 +5648,11 @@ packages: resolve: 1.22.2 transitivePeerDependencies: - supports-color - dev: true - - /@babel/helper-environment-visitor/7.18.9: - resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==} - engines: {node: '>=6.9.0'} /@babel/helper-environment-visitor/7.22.20: resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} engines: {node: '>=6.9.0'} - /@babel/helper-environment-visitor/7.22.5: - resolution: {integrity: sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==} - engines: {node: '>=6.9.0'} - - /@babel/helper-explode-assignable-expression/7.18.6: - resolution: {integrity: sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.22.19 - /@babel/helper-function-name/7.22.5: resolution: {integrity: sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==} engines: {node: '>=6.9.0'} @@ -5811,25 +5660,12 @@ packages: '@babel/template': 7.22.15 '@babel/types': 7.22.19 - /@babel/helper-hoist-variables/7.18.6: - resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.22.19 - dev: true - /@babel/helper-hoist-variables/7.22.5: resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.22.19 - /@babel/helper-member-expression-to-functions/7.21.0: - resolution: {integrity: sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.22.19 - /@babel/helper-member-expression-to-functions/7.22.15: resolution: {integrity: sha512-qLNsZbgrNh0fDQBCPocSL8guki1hcPvltGDv/NxvUoABwFq7GkKSu1nRXeJkVZc+wJvne2E0RKQz+2SQrz6eAA==} engines: {node: '>=6.9.0'} @@ -5848,60 +5684,59 @@ packages: dependencies: '@babel/types': 7.22.19 - /@babel/helper-module-imports/7.22.5: - resolution: {integrity: sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==} + /@babel/helper-module-transforms/7.22.20_@babel+core@7.19.3: + resolution: {integrity: sha512-dLT7JVWIUUxKOs1UnJUBR3S70YK+pKX6AbJgB2vMIvEkZkrfJDbYDJesnPshtKV4LhDOR3Oc5YULeDizRek+5A==} engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 dependencies: - '@babel/types': 7.22.11 + '@babel/core': 7.19.3 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.20 dev: true - /@babel/helper-module-transforms/7.21.2: - resolution: {integrity: sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-module-imports': 7.21.4 - '@babel/helper-simple-access': 7.20.2 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/helper-validator-identifier': 7.19.1 - '@babel/template': 7.22.5 - '@babel/traverse': 7.22.11 - '@babel/types': 7.22.19 - transitivePeerDependencies: - - supports-color - - /@babel/helper-module-transforms/7.22.20_@babel+core@7.22.11: + /@babel/helper-module-transforms/7.22.20_@babel+core@7.20.12: resolution: {integrity: sha512-dLT7JVWIUUxKOs1UnJUBR3S70YK+pKX6AbJgB2vMIvEkZkrfJDbYDJesnPshtKV4LhDOR3Oc5YULeDizRek+5A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-module-imports': 7.22.15 '@babel/helper-simple-access': 7.22.5 '@babel/helper-split-export-declaration': 7.22.6 '@babel/helper-validator-identifier': 7.22.20 + dev: true - /@babel/helper-module-transforms/7.22.9_@babel+core@7.20.12: - resolution: {integrity: sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==} + /@babel/helper-module-transforms/7.22.20_@babel+core@7.21.4: + resolution: {integrity: sha512-dLT7JVWIUUxKOs1UnJUBR3S70YK+pKX6AbJgB2vMIvEkZkrfJDbYDJesnPshtKV4LhDOR3Oc5YULeDizRek+5A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.20.12 - '@babel/helper-environment-visitor': 7.22.5 - '@babel/helper-module-imports': 7.22.5 + '@babel/core': 7.21.4 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.22.15 '@babel/helper-simple-access': 7.22.5 '@babel/helper-split-export-declaration': 7.22.6 - '@babel/helper-validator-identifier': 7.22.5 - dev: true + '@babel/helper-validator-identifier': 7.22.20 - /@babel/helper-optimise-call-expression/7.18.6: - resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==} + /@babel/helper-module-transforms/7.22.20_@babel+core@7.22.11: + resolution: {integrity: sha512-dLT7JVWIUUxKOs1UnJUBR3S70YK+pKX6AbJgB2vMIvEkZkrfJDbYDJesnPshtKV4LhDOR3Oc5YULeDizRek+5A==} engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 dependencies: - '@babel/types': 7.22.19 + '@babel/core': 7.22.11 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.20 /@babel/helper-optimise-call-expression/7.22.5: resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} @@ -5917,34 +5752,17 @@ packages: resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} engines: {node: '>=6.9.0'} - /@babel/helper-remap-async-to-generator/7.18.9_@babel+core@7.20.12: - resolution: {integrity: sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==} + /@babel/helper-remap-async-to-generator/7.22.20_@babel+core@7.20.12: + resolution: {integrity: sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.20.12 '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.5 - '@babel/helper-wrap-function': 7.20.5 - '@babel/types': 7.22.11 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-remap-async-to-generator/7.18.9_@babel+core@7.22.11: - resolution: {integrity: sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.22.11 - '@babel/helper-annotate-as-pure': 7.22.5 '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-wrap-function': 7.20.5 - '@babel/types': 7.22.19 - transitivePeerDependencies: - - supports-color + '@babel/helper-wrap-function': 7.22.20 + dev: true /@babel/helper-remap-async-to-generator/7.22.20_@babel+core@7.22.11: resolution: {integrity: sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==} @@ -5956,20 +5774,6 @@ packages: '@babel/helper-annotate-as-pure': 7.22.5 '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-wrap-function': 7.22.20 - dev: true - - /@babel/helper-replace-supers/7.20.7: - resolution: {integrity: sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-member-expression-to-functions': 7.21.0 - '@babel/helper-optimise-call-expression': 7.18.6 - '@babel/template': 7.22.15 - '@babel/traverse': 7.22.11 - '@babel/types': 7.22.19 - transitivePeerDependencies: - - supports-color /@babel/helper-replace-supers/7.22.20_@babel+core@7.20.12: resolution: {integrity: sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==} @@ -6006,24 +5810,12 @@ packages: '@babel/helper-member-expression-to-functions': 7.22.15 '@babel/helper-optimise-call-expression': 7.22.5 - /@babel/helper-simple-access/7.20.2: - resolution: {integrity: sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.22.19 - /@babel/helper-simple-access/7.22.5: resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.22.19 - /@babel/helper-skip-transparent-expression-wrappers/7.20.0: - resolution: {integrity: sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.22.19 - /@babel/helper-skip-transparent-expression-wrappers/7.22.5: resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} engines: {node: '>=6.9.0'} @@ -6035,6 +5827,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.22.19 + dev: true /@babel/helper-split-export-declaration/7.22.6: resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} @@ -6042,46 +5835,23 @@ packages: dependencies: '@babel/types': 7.22.19 - /@babel/helper-string-parser/7.19.4: - resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} - engines: {node: '>=6.9.0'} - /@babel/helper-string-parser/7.22.5: resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} engines: {node: '>=6.9.0'} - /@babel/helper-validator-identifier/7.19.1: - resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} - engines: {node: '>=6.9.0'} - /@babel/helper-validator-identifier/7.22.20: resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} engines: {node: '>=6.9.0'} - /@babel/helper-validator-identifier/7.22.5: - resolution: {integrity: sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==} - engines: {node: '>=6.9.0'} - dev: true - /@babel/helper-validator-option/7.21.0: resolution: {integrity: sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==} engines: {node: '>=6.9.0'} + dev: true /@babel/helper-validator-option/7.22.15: resolution: {integrity: sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==} engines: {node: '>=6.9.0'} - /@babel/helper-wrap-function/7.20.5: - resolution: {integrity: sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-function-name': 7.22.5 - '@babel/template': 7.22.15 - '@babel/traverse': 7.22.11 - '@babel/types': 7.22.19 - transitivePeerDependencies: - - supports-color - /@babel/helper-wrap-function/7.22.20: resolution: {integrity: sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==} engines: {node: '>=6.9.0'} @@ -6089,13 +5859,12 @@ packages: '@babel/helper-function-name': 7.22.5 '@babel/template': 7.22.15 '@babel/types': 7.22.19 - dev: true /@babel/helpers/7.21.0: resolution: {integrity: sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/template': 7.22.5 + '@babel/template': 7.22.15 '@babel/traverse': 7.22.11 '@babel/types': 7.22.19 transitivePeerDependencies: @@ -6111,15 +5880,6 @@ packages: transitivePeerDependencies: - supports-color - /@babel/highlight/7.18.6: - resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.22.5 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: true - /@babel/highlight/7.22.13: resolution: {integrity: sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==} engines: {node: '>=6.9.0'} @@ -6128,20 +5888,6 @@ packages: chalk: 2.4.2 js-tokens: 4.0.0 - /@babel/parser/7.21.4: - resolution: {integrity: sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.22.19 - - /@babel/parser/7.22.14: - resolution: {integrity: sha512-1KucTHgOvaw/LzCVrEOAyXkr9rQlp0A1HiHRYnSUE9dmb8PvPW7o5sscg+5169r54n3vGlbx6GevTE/Iw/P3AQ==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.22.19 - /@babel/parser/7.22.16: resolution: {integrity: sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==} engines: {node: '>=6.0.0'} @@ -6149,24 +5895,25 @@ packages: dependencies: '@babel/types': 7.22.19 - /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.18.6_@babel+core@7.20.12: + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.18.6_@babel+core@7.22.11: resolution: {integrity: sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.18.6_@babel+core@7.22.11: - resolution: {integrity: sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==} + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.22.15_@babel+core@7.20.12: + resolution: {integrity: sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.22.15_@babel+core@7.22.11: resolution: {integrity: sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==} @@ -6176,30 +5923,30 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.20.7_@babel+core@7.20.12: + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.20.7_@babel+core@7.22.11: resolution: {integrity: sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.13.0 dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - '@babel/plugin-proposal-optional-chaining': 7.21.0_@babel+core@7.20.12 + '@babel/core': 7.22.11 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/plugin-proposal-optional-chaining': 7.21.0_@babel+core@7.22.11 dev: true - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.20.7_@babel+core@7.22.11: - resolution: {integrity: sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==} + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.22.15_@babel+core@7.20.12: + resolution: {integrity: sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.13.0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - '@babel/plugin-proposal-optional-chaining': 7.21.0_@babel+core@7.22.11 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/plugin-transform-optional-chaining': 7.22.15_@babel+core@7.20.12 + dev: true /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.22.15_@babel+core@7.22.11: resolution: {integrity: sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==} @@ -6211,7 +5958,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 '@babel/plugin-transform-optional-chaining': 7.22.15_@babel+core@7.22.11 - dev: true /@babel/plugin-proposal-async-generator-functions/7.20.7_@babel+core@7.20.12: resolution: {integrity: sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==} @@ -6220,12 +5966,10 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-remap-async-to-generator': 7.18.9_@babel+core@7.20.12 + '@babel/helper-remap-async-to-generator': 7.22.20_@babel+core@7.20.12 '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.20.12 - transitivePeerDependencies: - - supports-color dev: true /@babel/plugin-proposal-async-generator-functions/7.20.7_@babel+core@7.22.11: @@ -6237,10 +5981,9 @@ packages: '@babel/core': 7.22.11 '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-remap-async-to-generator': 7.18.9_@babel+core@7.22.11 + '@babel/helper-remap-async-to-generator': 7.22.20_@babel+core@7.22.11 '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.22.11 - transitivePeerDependencies: - - supports-color + dev: true /@babel/plugin-proposal-class-properties/7.18.6_@babel+core@7.20.12: resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} @@ -6270,11 +6013,9 @@ packages: '@babel/core': ^7.12.0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-create-class-features-plugin': 7.21.4_@babel+core@7.20.12 + '@babel/helper-create-class-features-plugin': 7.22.15_@babel+core@7.20.12 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.20.12 - transitivePeerDependencies: - - supports-color dev: true /@babel/plugin-proposal-class-static-block/7.21.0_@babel+core@7.22.11: @@ -6284,11 +6025,10 @@ packages: '@babel/core': ^7.12.0 dependencies: '@babel/core': 7.22.11 - '@babel/helper-create-class-features-plugin': 7.21.4_@babel+core@7.22.11 + '@babel/helper-create-class-features-plugin': 7.22.15_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.22.11 - transitivePeerDependencies: - - supports-color + dev: true /@babel/plugin-proposal-decorators/7.21.0_@babel+core@7.22.11: resolution: {integrity: sha512-MfgX49uRrFUTL/HvWtmx3zmpyzMMr4MTj3d527MLlr/4RTT9G/ytFFP7qet2uM2Ve03b+BkpWUpK+lRXnQ+v9w==} @@ -6323,6 +6063,7 @@ packages: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.22.11 + dev: true /@babel/plugin-proposal-export-namespace-from/7.18.9_@babel+core@7.20.12: resolution: {integrity: sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==} @@ -6344,6 +6085,7 @@ packages: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.22.11 + dev: true /@babel/plugin-proposal-json-strings/7.18.6_@babel+core@7.20.12: resolution: {integrity: sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==} @@ -6365,6 +6107,7 @@ packages: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.22.11 + dev: true /@babel/plugin-proposal-logical-assignment-operators/7.20.7_@babel+core@7.20.12: resolution: {integrity: sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==} @@ -6386,6 +6129,7 @@ packages: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.22.11 + dev: true /@babel/plugin-proposal-nullish-coalescing-operator/7.18.6_@babel+core@7.20.12: resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} @@ -6440,7 +6184,7 @@ packages: '@babel/helper-compilation-targets': 7.22.15 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.20.12 - '@babel/plugin-transform-parameters': 7.21.3_@babel+core@7.20.12 + '@babel/plugin-transform-parameters': 7.22.15_@babel+core@7.20.12 dev: true /@babel/plugin-proposal-object-rest-spread/7.20.7_@babel+core@7.22.11: @@ -6454,7 +6198,8 @@ packages: '@babel/helper-compilation-targets': 7.22.15 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.22.11 - '@babel/plugin-transform-parameters': 7.21.3_@babel+core@7.22.11 + '@babel/plugin-transform-parameters': 7.22.15_@babel+core@7.22.11 + dev: true /@babel/plugin-proposal-optional-catch-binding/7.18.6_@babel+core@7.20.12: resolution: {integrity: sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==} @@ -6476,10 +6221,12 @@ packages: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.22.11 + dev: true /@babel/plugin-proposal-optional-chaining/7.21.0_@babel+core@7.20.12: resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==} engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead. peerDependencies: '@babel/core': ^7.0.0-0 dependencies: @@ -6492,6 +6239,7 @@ packages: /@babel/plugin-proposal-optional-chaining/7.21.0_@babel+core@7.22.11: resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==} engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead. peerDependencies: '@babel/core': ^7.0.0-0 dependencies: @@ -6507,10 +6255,8 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-create-class-features-plugin': 7.21.4_@babel+core@7.20.12 + '@babel/helper-create-class-features-plugin': 7.22.15_@babel+core@7.20.12 '@babel/helper-plugin-utils': 7.22.5 - transitivePeerDependencies: - - supports-color dev: true /@babel/plugin-proposal-private-methods/7.18.6_@babel+core@7.22.11: @@ -6520,10 +6266,8 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.22.11 - '@babel/helper-create-class-features-plugin': 7.21.4_@babel+core@7.22.11 + '@babel/helper-create-class-features-plugin': 7.22.15_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 - transitivePeerDependencies: - - supports-color /@babel/plugin-proposal-private-property-in-object/7.21.0-placeholder-for-preset-env.2_@babel+core@7.22.11: resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} @@ -6532,7 +6276,6 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.22.11 - dev: true /@babel/plugin-proposal-private-property-in-object/7.21.0_@babel+core@7.20.12: resolution: {integrity: sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==} @@ -6541,12 +6284,10 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-create-class-features-plugin': 7.21.4_@babel+core@7.20.12 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-create-class-features-plugin': 7.22.15_@babel+core@7.20.12 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.20.12 - transitivePeerDependencies: - - supports-color dev: true /@babel/plugin-proposal-private-property-in-object/7.21.0_@babel+core@7.22.11: @@ -6557,11 +6298,9 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.21.4_@babel+core@7.22.11 + '@babel/helper-create-class-features-plugin': 7.22.15_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.22.11 - transitivePeerDependencies: - - supports-color /@babel/plugin-proposal-unicode-property-regex/7.18.6_@babel+core@7.20.12: resolution: {integrity: sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==} @@ -6570,7 +6309,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-create-regexp-features-plugin': 7.21.4_@babel+core@7.20.12 + '@babel/helper-create-regexp-features-plugin': 7.22.15_@babel+core@7.20.12 '@babel/helper-plugin-utils': 7.22.5 dev: true @@ -6581,8 +6320,9 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.22.11 - '@babel/helper-create-regexp-features-plugin': 7.21.4_@babel+core@7.22.11 + '@babel/helper-create-regexp-features-plugin': 7.22.15_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.20.12: resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} @@ -6721,24 +6461,25 @@ packages: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-syntax-import-assertions/7.20.0_@babel+core@7.20.12: + /@babel/plugin-syntax-import-assertions/7.20.0_@babel+core@7.22.11: resolution: {integrity: sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-import-assertions/7.20.0_@babel+core@7.22.11: - resolution: {integrity: sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==} + /@babel/plugin-syntax-import-assertions/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-syntax-import-assertions/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==} @@ -6748,7 +6489,6 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/plugin-syntax-import-attributes/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==} @@ -6758,7 +6498,6 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/plugin-syntax-import-meta/7.10.4_@babel+core@7.21.4: resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} @@ -6801,25 +6540,16 @@ packages: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - /@babel/plugin-syntax-jsx/7.21.4_@babel+core@7.21.4: - resolution: {integrity: sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==} + /@babel/plugin-syntax-jsx/7.22.5_@babel+core@7.21.4: + resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.21.4 - '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-jsx/7.21.4_@babel+core@7.22.11: - resolution: {integrity: sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.20.2 - /@babel/plugin-syntax-jsx/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==} engines: {node: '>=6.9.0'} @@ -7054,26 +6784,26 @@ packages: '@babel/core': 7.22.11 '@babel/helper-create-regexp-features-plugin': 7.22.15_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-transform-arrow-functions/7.20.7_@babel+core@7.20.12: + /@babel/plugin-transform-arrow-functions/7.20.7_@babel+core@7.22.11: resolution: {integrity: sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-arrow-functions/7.20.7_@babel+core@7.22.11: - resolution: {integrity: sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==} + /@babel/plugin-transform-arrow-functions/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-arrow-functions/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==} @@ -7083,7 +6813,6 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/plugin-transform-async-generator-functions/7.22.15_@babel+core@7.22.11: resolution: {integrity: sha512-jBm1Es25Y+tVoTi5rfd5t1KLmL8ogLKpXszboWOTTtGFGz2RKnQe2yn7HbZ+kb/B8N0FVSGQo874NSlOU1T4+w==} @@ -7096,7 +6825,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-remap-async-to-generator': 7.22.20_@babel+core@7.22.11 '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.22.11 - dev: true /@babel/plugin-transform-async-to-generator/7.20.7_@babel+core@7.20.12: resolution: {integrity: sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==} @@ -7107,9 +6835,7 @@ packages: '@babel/core': 7.20.12 '@babel/helper-module-imports': 7.22.15 '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-remap-async-to-generator': 7.18.9_@babel+core@7.20.12 - transitivePeerDependencies: - - supports-color + '@babel/helper-remap-async-to-generator': 7.22.20_@babel+core@7.20.12 dev: true /@babel/plugin-transform-async-to-generator/7.20.7_@babel+core@7.22.11: @@ -7121,9 +6847,20 @@ packages: '@babel/core': 7.22.11 '@babel/helper-module-imports': 7.22.15 '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-remap-async-to-generator': 7.18.9_@babel+core@7.22.11 - transitivePeerDependencies: - - supports-color + '@babel/helper-remap-async-to-generator': 7.22.20_@babel+core@7.22.11 + dev: true + + /@babel/plugin-transform-async-to-generator/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-remap-async-to-generator': 7.22.20_@babel+core@7.20.12 + dev: true /@babel/plugin-transform-async-to-generator/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==} @@ -7135,26 +6872,26 @@ packages: '@babel/helper-module-imports': 7.22.15 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-remap-async-to-generator': 7.22.20_@babel+core@7.22.11 - dev: true - /@babel/plugin-transform-block-scoped-functions/7.18.6_@babel+core@7.20.12: + /@babel/plugin-transform-block-scoped-functions/7.18.6_@babel+core@7.22.11: resolution: {integrity: sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-block-scoped-functions/7.18.6_@babel+core@7.22.11: - resolution: {integrity: sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==} + /@babel/plugin-transform-block-scoped-functions/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-block-scoped-functions/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==} @@ -7164,26 +6901,26 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-transform-block-scoping/7.21.0_@babel+core@7.20.12: + /@babel/plugin-transform-block-scoping/7.21.0_@babel+core@7.22.11: resolution: {integrity: sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-block-scoping/7.21.0_@babel+core@7.22.11: - resolution: {integrity: sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==} + /@babel/plugin-transform-block-scoping/7.22.15_@babel+core@7.20.12: + resolution: {integrity: sha512-G1czpdJBZCtngoK1sJgloLiOHUnkb/bLZwqVZD8kXmq0ZnVfTTWUcs9OWtp0mBtYJ+4LQY1fllqBkOIPhXmFmw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-block-scoping/7.22.15_@babel+core@7.22.11: resolution: {integrity: sha512-G1czpdJBZCtngoK1sJgloLiOHUnkb/bLZwqVZD8kXmq0ZnVfTTWUcs9OWtp0mBtYJ+4LQY1fllqBkOIPhXmFmw==} @@ -7193,7 +6930,6 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/plugin-transform-class-properties/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==} @@ -7204,7 +6940,6 @@ packages: '@babel/core': 7.22.11 '@babel/helper-create-class-features-plugin': 7.22.15_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/plugin-transform-class-static-block/7.22.11_@babel+core@7.22.11: resolution: {integrity: sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g==} @@ -7216,46 +6951,42 @@ packages: '@babel/helper-create-class-features-plugin': 7.22.15_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.22.11 - dev: true - /@babel/plugin-transform-classes/7.21.0_@babel+core@7.20.12: + /@babel/plugin-transform-classes/7.21.0_@babel+core@7.22.11: resolution: {integrity: sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-compilation-targets': 7.22.10 - '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-compilation-targets': 7.22.15 + '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-function-name': 7.22.5 - '@babel/helper-optimise-call-expression': 7.18.6 + '@babel/helper-optimise-call-expression': 7.22.5 '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-replace-supers': 7.20.7 + '@babel/helper-replace-supers': 7.22.20_@babel+core@7.22.11 '@babel/helper-split-export-declaration': 7.22.6 globals: 11.12.0 - transitivePeerDependencies: - - supports-color dev: true - /@babel/plugin-transform-classes/7.21.0_@babel+core@7.22.11: - resolution: {integrity: sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==} + /@babel/plugin-transform-classes/7.22.15_@babel+core@7.20.12: + resolution: {integrity: sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-annotate-as-pure': 7.22.5 '@babel/helper-compilation-targets': 7.22.15 '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-function-name': 7.22.5 - '@babel/helper-optimise-call-expression': 7.18.6 + '@babel/helper-optimise-call-expression': 7.22.5 '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-replace-supers': 7.20.7 + '@babel/helper-replace-supers': 7.22.20_@babel+core@7.20.12 '@babel/helper-split-export-declaration': 7.22.6 globals: 11.12.0 - transitivePeerDependencies: - - supports-color + dev: true /@babel/plugin-transform-classes/7.22.15_@babel+core@7.22.11: resolution: {integrity: sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==} @@ -7273,28 +7004,28 @@ packages: '@babel/helper-replace-supers': 7.22.20_@babel+core@7.22.11 '@babel/helper-split-export-declaration': 7.22.6 globals: 11.12.0 - dev: true - /@babel/plugin-transform-computed-properties/7.20.7_@babel+core@7.20.12: + /@babel/plugin-transform-computed-properties/7.20.7_@babel+core@7.22.11: resolution: {integrity: sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/template': 7.22.15 dev: true - /@babel/plugin-transform-computed-properties/7.20.7_@babel+core@7.22.11: - resolution: {integrity: sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==} + /@babel/plugin-transform-computed-properties/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 '@babel/template': 7.22.15 + dev: true /@babel/plugin-transform-computed-properties/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==} @@ -7305,26 +7036,26 @@ packages: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/template': 7.22.15 - dev: true - /@babel/plugin-transform-destructuring/7.21.3_@babel+core@7.20.12: + /@babel/plugin-transform-destructuring/7.21.3_@babel+core@7.22.11: resolution: {integrity: sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-destructuring/7.21.3_@babel+core@7.22.11: - resolution: {integrity: sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==} + /@babel/plugin-transform-destructuring/7.22.15_@babel+core@7.20.12: + resolution: {integrity: sha512-HzG8sFl1ZVGTme74Nw+X01XsUTqERVQ6/RLHo3XjGRzm7XD6QTtfS3NJotVgCGy8BzkDqRjRBD8dAyJn5TuvSQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-destructuring/7.22.15_@babel+core@7.22.11: resolution: {integrity: sha512-HzG8sFl1ZVGTme74Nw+X01XsUTqERVQ6/RLHo3XjGRzm7XD6QTtfS3NJotVgCGy8BzkDqRjRBD8dAyJn5TuvSQ==} @@ -7334,28 +7065,28 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-transform-dotall-regex/7.18.6_@babel+core@7.20.12: + /@babel/plugin-transform-dotall-regex/7.18.6_@babel+core@7.22.11: resolution: {integrity: sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 - '@babel/helper-create-regexp-features-plugin': 7.21.4_@babel+core@7.20.12 + '@babel/core': 7.22.11 + '@babel/helper-create-regexp-features-plugin': 7.22.15_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-dotall-regex/7.18.6_@babel+core@7.22.11: - resolution: {integrity: sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==} + /@babel/plugin-transform-dotall-regex/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 - '@babel/helper-create-regexp-features-plugin': 7.21.4_@babel+core@7.22.11 + '@babel/core': 7.20.12 + '@babel/helper-create-regexp-features-plugin': 7.22.15_@babel+core@7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-dotall-regex/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==} @@ -7366,26 +7097,26 @@ packages: '@babel/core': 7.22.11 '@babel/helper-create-regexp-features-plugin': 7.22.15_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-transform-duplicate-keys/7.18.9_@babel+core@7.20.12: + /@babel/plugin-transform-duplicate-keys/7.18.9_@babel+core@7.22.11: resolution: {integrity: sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-duplicate-keys/7.18.9_@babel+core@7.22.11: - resolution: {integrity: sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==} + /@babel/plugin-transform-duplicate-keys/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-duplicate-keys/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==} @@ -7395,7 +7126,6 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/plugin-transform-dynamic-import/7.22.11_@babel+core@7.22.11: resolution: {integrity: sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA==} @@ -7406,28 +7136,28 @@ packages: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.22.11 - dev: true - /@babel/plugin-transform-exponentiation-operator/7.18.6_@babel+core@7.20.12: + /@babel/plugin-transform-exponentiation-operator/7.18.6_@babel+core@7.22.11: resolution: {integrity: sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 - '@babel/helper-builder-binary-assignment-operator-visitor': 7.18.9 + '@babel/core': 7.22.11 + '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.15 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-exponentiation-operator/7.18.6_@babel+core@7.22.11: - resolution: {integrity: sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==} + /@babel/plugin-transform-exponentiation-operator/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 - '@babel/helper-builder-binary-assignment-operator-visitor': 7.18.9 + '@babel/core': 7.20.12 + '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.15 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-exponentiation-operator/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==} @@ -7438,7 +7168,6 @@ packages: '@babel/core': 7.22.11 '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.15 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/plugin-transform-export-namespace-from/7.22.11_@babel+core@7.22.11: resolution: {integrity: sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw==} @@ -7449,7 +7178,6 @@ packages: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.22.11 - dev: true /@babel/plugin-transform-flow-strip-types/7.21.0_@babel+core@7.22.11: resolution: {integrity: sha512-FlFA2Mj87a6sDkW4gfGrQQqwY/dLlBAyJa2dJEZ+FHXUVHBflO2wyKvg+OOEzXfrKYIa4HWl0mgmbCzt0cMb7w==} @@ -7472,24 +7200,25 @@ packages: '@babel/plugin-syntax-flow': 7.22.5_@babel+core@7.22.11 dev: true - /@babel/plugin-transform-for-of/7.21.0_@babel+core@7.20.12: + /@babel/plugin-transform-for-of/7.21.0_@babel+core@7.22.11: resolution: {integrity: sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-for-of/7.21.0_@babel+core@7.22.11: - resolution: {integrity: sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ==} + /@babel/plugin-transform-for-of/7.22.15_@babel+core@7.20.12: + resolution: {integrity: sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-for-of/7.22.15_@babel+core@7.22.11: resolution: {integrity: sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==} @@ -7499,30 +7228,30 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-transform-function-name/7.18.9_@babel+core@7.20.12: + /@babel/plugin-transform-function-name/7.18.9_@babel+core@7.22.11: resolution: {integrity: sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 - '@babel/helper-compilation-targets': 7.22.10 + '@babel/core': 7.22.11 + '@babel/helper-compilation-targets': 7.22.15 '@babel/helper-function-name': 7.22.5 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-function-name/7.18.9_@babel+core@7.22.11: - resolution: {integrity: sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==} + /@babel/plugin-transform-function-name/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-compilation-targets': 7.22.15 '@babel/helper-function-name': 7.22.5 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-function-name/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==} @@ -7534,7 +7263,6 @@ packages: '@babel/helper-compilation-targets': 7.22.15 '@babel/helper-function-name': 7.22.5 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/plugin-transform-json-strings/7.22.11_@babel+core@7.22.11: resolution: {integrity: sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw==} @@ -7545,26 +7273,26 @@ packages: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.22.11 - dev: true - /@babel/plugin-transform-literals/7.18.9_@babel+core@7.20.12: + /@babel/plugin-transform-literals/7.18.9_@babel+core@7.22.11: resolution: {integrity: sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-literals/7.18.9_@babel+core@7.22.11: - resolution: {integrity: sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==} + /@babel/plugin-transform-literals/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-literals/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==} @@ -7574,7 +7302,6 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/plugin-transform-logical-assignment-operators/7.22.11_@babel+core@7.22.11: resolution: {integrity: sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ==} @@ -7585,26 +7312,26 @@ packages: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.22.11 - dev: true - /@babel/plugin-transform-member-expression-literals/7.18.6_@babel+core@7.20.12: + /@babel/plugin-transform-member-expression-literals/7.18.6_@babel+core@7.22.11: resolution: {integrity: sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-member-expression-literals/7.18.6_@babel+core@7.22.11: - resolution: {integrity: sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==} + /@babel/plugin-transform-member-expression-literals/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-member-expression-literals/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==} @@ -7614,28 +7341,28 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-transform-modules-amd/7.20.11_@babel+core@7.20.12: + /@babel/plugin-transform-modules-amd/7.20.11_@babel+core@7.22.11: resolution: {integrity: sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 - '@babel/helper-module-transforms': 7.22.9_@babel+core@7.20.12 + '@babel/core': 7.22.11 + '@babel/helper-module-transforms': 7.22.20_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-modules-amd/7.20.11_@babel+core@7.22.11: - resolution: {integrity: sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==} + /@babel/plugin-transform-modules-amd/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 - '@babel/helper-module-transforms': 7.22.20_@babel+core@7.22.11 + '@babel/core': 7.20.12 + '@babel/helper-module-transforms': 7.22.20_@babel+core@7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-modules-amd/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==} @@ -7646,30 +7373,30 @@ packages: '@babel/core': 7.22.11 '@babel/helper-module-transforms': 7.22.20_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-transform-modules-commonjs/7.21.2_@babel+core@7.20.12: + /@babel/plugin-transform-modules-commonjs/7.21.2_@babel+core@7.22.11: resolution: {integrity: sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 - '@babel/helper-module-transforms': 7.22.9_@babel+core@7.20.12 + '@babel/core': 7.22.11 + '@babel/helper-module-transforms': 7.22.20_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-simple-access': 7.20.2 + '@babel/helper-simple-access': 7.22.5 dev: true - /@babel/plugin-transform-modules-commonjs/7.21.2_@babel+core@7.22.11: - resolution: {integrity: sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==} + /@babel/plugin-transform-modules-commonjs/7.22.15_@babel+core@7.20.12: + resolution: {integrity: sha512-jWL4eh90w0HQOTKP2MoXXUpVxilxsB2Vl4ji69rSjS3EcZ/v4sBmn+A3NpepuJzBhOaEBbR7udonlHHn5DWidg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 - '@babel/helper-module-transforms': 7.22.20_@babel+core@7.22.11 + '@babel/core': 7.20.12 + '@babel/helper-module-transforms': 7.22.20_@babel+core@7.20.12 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-simple-access': 7.22.5 + dev: true /@babel/plugin-transform-modules-commonjs/7.22.15_@babel+core@7.22.11: resolution: {integrity: sha512-jWL4eh90w0HQOTKP2MoXXUpVxilxsB2Vl4ji69rSjS3EcZ/v4sBmn+A3NpepuJzBhOaEBbR7udonlHHn5DWidg==} @@ -7682,30 +7409,31 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-simple-access': 7.22.5 - /@babel/plugin-transform-modules-systemjs/7.20.11_@babel+core@7.20.12: + /@babel/plugin-transform-modules-systemjs/7.20.11_@babel+core@7.22.11: resolution: {integrity: sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 - '@babel/helper-hoist-variables': 7.18.6 - '@babel/helper-module-transforms': 7.22.9_@babel+core@7.20.12 + '@babel/core': 7.22.11 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-module-transforms': 7.22.20_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-validator-identifier': 7.19.1 + '@babel/helper-validator-identifier': 7.22.20 dev: true - /@babel/plugin-transform-modules-systemjs/7.20.11_@babel+core@7.22.11: - resolution: {integrity: sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==} + /@babel/plugin-transform-modules-systemjs/7.22.11_@babel+core@7.20.12: + resolution: {integrity: sha512-rIqHmHoMEOhI3VkVf5jQ15l539KrwhzqcBO6wdCNWPWc/JWt9ILNYNUssbRpeq0qWns8svuw8LnMNCvWBIJ8wA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-module-transforms': 7.22.20_@babel+core@7.22.11 + '@babel/helper-module-transforms': 7.22.20_@babel+core@7.20.12 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-validator-identifier': 7.22.20 + dev: true /@babel/plugin-transform-modules-systemjs/7.22.11_@babel+core@7.22.11: resolution: {integrity: sha512-rIqHmHoMEOhI3VkVf5jQ15l539KrwhzqcBO6wdCNWPWc/JWt9ILNYNUssbRpeq0qWns8svuw8LnMNCvWBIJ8wA==} @@ -7718,28 +7446,28 @@ packages: '@babel/helper-module-transforms': 7.22.20_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-validator-identifier': 7.22.20 - dev: true - /@babel/plugin-transform-modules-umd/7.18.6_@babel+core@7.20.12: + /@babel/plugin-transform-modules-umd/7.18.6_@babel+core@7.22.11: resolution: {integrity: sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 - '@babel/helper-module-transforms': 7.22.9_@babel+core@7.20.12 + '@babel/core': 7.22.11 + '@babel/helper-module-transforms': 7.22.20_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-modules-umd/7.18.6_@babel+core@7.22.11: - resolution: {integrity: sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==} + /@babel/plugin-transform-modules-umd/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 - '@babel/helper-module-transforms': 7.22.20_@babel+core@7.22.11 + '@babel/core': 7.20.12 + '@babel/helper-module-transforms': 7.22.20_@babel+core@7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-modules-umd/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==} @@ -7750,28 +7478,28 @@ packages: '@babel/core': 7.22.11 '@babel/helper-module-transforms': 7.22.20_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-transform-named-capturing-groups-regex/7.20.5_@babel+core@7.20.12: + /@babel/plugin-transform-named-capturing-groups-regex/7.20.5_@babel+core@7.22.11: resolution: {integrity: sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.20.12 - '@babel/helper-create-regexp-features-plugin': 7.21.4_@babel+core@7.20.12 + '@babel/core': 7.22.11 + '@babel/helper-create-regexp-features-plugin': 7.22.15_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-named-capturing-groups-regex/7.20.5_@babel+core@7.22.11: - resolution: {integrity: sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==} + /@babel/plugin-transform-named-capturing-groups-regex/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.22.11 - '@babel/helper-create-regexp-features-plugin': 7.21.4_@babel+core@7.22.11 + '@babel/core': 7.20.12 + '@babel/helper-create-regexp-features-plugin': 7.22.15_@babel+core@7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-named-capturing-groups-regex/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==} @@ -7782,26 +7510,26 @@ packages: '@babel/core': 7.22.11 '@babel/helper-create-regexp-features-plugin': 7.22.15_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-transform-new-target/7.18.6_@babel+core@7.20.12: + /@babel/plugin-transform-new-target/7.18.6_@babel+core@7.22.11: resolution: {integrity: sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-new-target/7.18.6_@babel+core@7.22.11: - resolution: {integrity: sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==} + /@babel/plugin-transform-new-target/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-new-target/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==} @@ -7811,7 +7539,6 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/plugin-transform-nullish-coalescing-operator/7.22.11_@babel+core@7.22.11: resolution: {integrity: sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg==} @@ -7822,7 +7549,6 @@ packages: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.22.11 - dev: true /@babel/plugin-transform-numeric-separator/7.22.11_@babel+core@7.22.11: resolution: {integrity: sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg==} @@ -7833,7 +7559,6 @@ packages: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.22.11 - dev: true /@babel/plugin-transform-object-rest-spread/7.22.15_@babel+core@7.22.11: resolution: {integrity: sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q==} @@ -7847,32 +7572,28 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.22.11 '@babel/plugin-transform-parameters': 7.22.15_@babel+core@7.22.11 - dev: true - /@babel/plugin-transform-object-super/7.18.6_@babel+core@7.20.12: + /@babel/plugin-transform-object-super/7.18.6_@babel+core@7.22.11: resolution: {integrity: sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-replace-supers': 7.20.7 - transitivePeerDependencies: - - supports-color + '@babel/helper-replace-supers': 7.22.20_@babel+core@7.22.11 dev: true - /@babel/plugin-transform-object-super/7.18.6_@babel+core@7.22.11: - resolution: {integrity: sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==} + /@babel/plugin-transform-object-super/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-replace-supers': 7.20.7 - transitivePeerDependencies: - - supports-color + '@babel/helper-replace-supers': 7.22.20_@babel+core@7.20.12 + dev: true /@babel/plugin-transform-object-super/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==} @@ -7883,7 +7604,6 @@ packages: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-replace-supers': 7.22.20_@babel+core@7.22.11 - dev: true /@babel/plugin-transform-optional-catch-binding/7.22.11_@babel+core@7.22.11: resolution: {integrity: sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ==} @@ -7894,6 +7614,17 @@ packages: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.22.11 + + /@babel/plugin-transform-optional-chaining/7.22.15_@babel+core@7.20.12: + resolution: {integrity: sha512-ngQ2tBhq5vvSJw2Q2Z9i7ealNkpDMU0rGWnHPKqRZO0tzZ5tlaoz4hDvhXioOoaE0X2vfNss1djwg0DXlfu30A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.20.12 dev: true /@babel/plugin-transform-optional-chaining/7.22.15_@babel+core@7.22.11: @@ -7906,26 +7637,26 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.22.11 - dev: true - /@babel/plugin-transform-parameters/7.21.3_@babel+core@7.20.12: + /@babel/plugin-transform-parameters/7.21.3_@babel+core@7.22.11: resolution: {integrity: sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-parameters/7.21.3_@babel+core@7.22.11: - resolution: {integrity: sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==} + /@babel/plugin-transform-parameters/7.22.15_@babel+core@7.20.12: + resolution: {integrity: sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-parameters/7.22.15_@babel+core@7.22.11: resolution: {integrity: sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==} @@ -7935,7 +7666,6 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/plugin-transform-private-methods/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==} @@ -7946,7 +7676,6 @@ packages: '@babel/core': 7.22.11 '@babel/helper-create-class-features-plugin': 7.22.15_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/plugin-transform-private-property-in-object/7.22.11_@babel+core@7.22.11: resolution: {integrity: sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ==} @@ -7959,26 +7688,26 @@ packages: '@babel/helper-create-class-features-plugin': 7.22.15_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.22.11 - dev: true - /@babel/plugin-transform-property-literals/7.18.6_@babel+core@7.20.12: + /@babel/plugin-transform-property-literals/7.18.6_@babel+core@7.22.11: resolution: {integrity: sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-property-literals/7.18.6_@babel+core@7.22.11: - resolution: {integrity: sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==} + /@babel/plugin-transform-property-literals/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-property-literals/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==} @@ -7988,7 +7717,6 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/plugin-transform-react-constant-elements/7.21.3_@babel+core@7.22.11: resolution: {integrity: sha512-4DVcFeWe/yDYBLp0kBmOGFJ6N2UYg7coGid1gdxb4co62dy/xISDMaYBXBVXEDhfgMk7qkbcYiGtwd5Q/hwDDQ==} @@ -8016,7 +7744,6 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/plugin-transform-react-jsx-development/7.18.6_@babel+core@7.22.11: resolution: {integrity: sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==} @@ -8025,7 +7752,8 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.22.11 - '@babel/plugin-transform-react-jsx': 7.21.0_@babel+core@7.22.11 + '@babel/plugin-transform-react-jsx': 7.22.15_@babel+core@7.22.11 + dev: true /@babel/plugin-transform-react-jsx-development/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==} @@ -8035,7 +7763,6 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/plugin-transform-react-jsx': 7.22.15_@babel+core@7.22.11 - dev: true /@babel/plugin-transform-react-jsx/7.21.0_@babel+core@7.22.11: resolution: {integrity: sha512-6OAWljMvQrZjR2DaNhVfRz6dkCAVV+ymcLUmaf8bccGOHn2v5rHJK3tTpij0BuhdYWP4LLaqj5lwcdlpAAPuvg==} @@ -8044,11 +7771,12 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.22.11 - '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-module-imports': 7.21.4 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-jsx': 7.21.4_@babel+core@7.22.11 - '@babel/types': 7.21.4 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-jsx': 7.22.5_@babel+core@7.22.11 + '@babel/types': 7.22.19 + dev: true /@babel/plugin-transform-react-jsx/7.22.15_@babel+core@7.22.11: resolution: {integrity: sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA==} @@ -8070,8 +7798,9 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.22.11 - '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-react-pure-annotations/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA==} @@ -8082,28 +7811,28 @@ packages: '@babel/core': 7.22.11 '@babel/helper-annotate-as-pure': 7.22.5 '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-transform-regenerator/7.20.5_@babel+core@7.20.12: + /@babel/plugin-transform-regenerator/7.20.5_@babel+core@7.22.11: resolution: {integrity: sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - regenerator-transform: 0.15.1 + regenerator-transform: 0.15.2 dev: true - /@babel/plugin-transform-regenerator/7.20.5_@babel+core@7.22.11: - resolution: {integrity: sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==} + /@babel/plugin-transform-regenerator/7.22.10_@babel+core@7.20.12: + resolution: {integrity: sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 - regenerator-transform: 0.15.1 + regenerator-transform: 0.15.2 + dev: true /@babel/plugin-transform-regenerator/7.22.10_@babel+core@7.22.11: resolution: {integrity: sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==} @@ -8114,26 +7843,26 @@ packages: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 regenerator-transform: 0.15.2 - dev: true - /@babel/plugin-transform-reserved-words/7.18.6_@babel+core@7.20.12: + /@babel/plugin-transform-reserved-words/7.18.6_@babel+core@7.22.11: resolution: {integrity: sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-reserved-words/7.18.6_@babel+core@7.22.11: - resolution: {integrity: sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==} + /@babel/plugin-transform-reserved-words/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-reserved-words/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==} @@ -8143,7 +7872,6 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/plugin-transform-runtime/7.19.6_@babel+core@7.20.12: resolution: {integrity: sha512-PRH37lz4JU156lYFW1p8OxE5i7d6Sl/zV58ooyr+q1J1lnQPyg5tIiXlIwNVhJaY4W3TmOtdc8jqdXQcB1v5Yw==} @@ -8152,8 +7880,8 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-module-imports': 7.21.4 - '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-plugin-utils': 7.22.5 babel-plugin-polyfill-corejs2: 0.3.3_@babel+core@7.20.12 babel-plugin-polyfill-corejs3: 0.6.0_@babel+core@7.20.12 babel-plugin-polyfill-regenerator: 0.4.1_@babel+core@7.20.12 @@ -8178,24 +7906,25 @@ packages: transitivePeerDependencies: - supports-color - /@babel/plugin-transform-shorthand-properties/7.18.6_@babel+core@7.20.12: + /@babel/plugin-transform-shorthand-properties/7.18.6_@babel+core@7.22.11: resolution: {integrity: sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-shorthand-properties/7.18.6_@babel+core@7.22.11: - resolution: {integrity: sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==} + /@babel/plugin-transform-shorthand-properties/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-shorthand-properties/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==} @@ -8205,28 +7934,28 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-transform-spread/7.20.7_@babel+core@7.20.12: + /@babel/plugin-transform-spread/7.20.7_@babel+core@7.22.11: resolution: {integrity: sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 + '@babel/core': 7.22.11 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 dev: true - /@babel/plugin-transform-spread/7.20.7_@babel+core@7.22.11: - resolution: {integrity: sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==} + /@babel/plugin-transform-spread/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + dev: true /@babel/plugin-transform-spread/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==} @@ -8237,26 +7966,26 @@ packages: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - dev: true - /@babel/plugin-transform-sticky-regex/7.18.6_@babel+core@7.20.12: + /@babel/plugin-transform-sticky-regex/7.18.6_@babel+core@7.22.11: resolution: {integrity: sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-sticky-regex/7.18.6_@babel+core@7.22.11: - resolution: {integrity: sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==} + /@babel/plugin-transform-sticky-regex/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-sticky-regex/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==} @@ -8266,26 +7995,26 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-transform-template-literals/7.18.9_@babel+core@7.20.12: + /@babel/plugin-transform-template-literals/7.18.9_@babel+core@7.22.11: resolution: {integrity: sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-template-literals/7.18.9_@babel+core@7.22.11: - resolution: {integrity: sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==} + /@babel/plugin-transform-template-literals/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-template-literals/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==} @@ -8295,26 +8024,26 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-transform-typeof-symbol/7.18.9_@babel+core@7.20.12: + /@babel/plugin-transform-typeof-symbol/7.18.9_@babel+core@7.22.11: resolution: {integrity: sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-typeof-symbol/7.18.9_@babel+core@7.22.11: - resolution: {integrity: sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==} + /@babel/plugin-transform-typeof-symbol/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-typeof-symbol/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==} @@ -8324,7 +8053,6 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/plugin-transform-typescript/7.21.3_@babel+core@7.21.4: resolution: {integrity: sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==} @@ -8351,24 +8079,25 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-typescript': 7.21.4_@babel+core@7.22.11 - /@babel/plugin-transform-unicode-escapes/7.18.10_@babel+core@7.20.12: + /@babel/plugin-transform-unicode-escapes/7.18.10_@babel+core@7.22.11: resolution: {integrity: sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-unicode-escapes/7.18.10_@babel+core@7.22.11: - resolution: {integrity: sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==} + /@babel/plugin-transform-unicode-escapes/7.22.10_@babel+core@7.20.12: + resolution: {integrity: sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-unicode-escapes/7.22.10_@babel+core@7.22.11: resolution: {integrity: sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==} @@ -8378,7 +8107,6 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/plugin-transform-unicode-property-regex/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==} @@ -8389,28 +8117,28 @@ packages: '@babel/core': 7.22.11 '@babel/helper-create-regexp-features-plugin': 7.22.15_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-transform-unicode-regex/7.18.6_@babel+core@7.20.12: + /@babel/plugin-transform-unicode-regex/7.18.6_@babel+core@7.22.11: resolution: {integrity: sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.20.12 - '@babel/helper-create-regexp-features-plugin': 7.21.4_@babel+core@7.20.12 + '@babel/core': 7.22.11 + '@babel/helper-create-regexp-features-plugin': 7.22.15_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-transform-unicode-regex/7.18.6_@babel+core@7.22.11: - resolution: {integrity: sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==} + /@babel/plugin-transform-unicode-regex/7.22.5_@babel+core@7.20.12: + resolution: {integrity: sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.11 - '@babel/helper-create-regexp-features-plugin': 7.21.4_@babel+core@7.22.11 + '@babel/core': 7.20.12 + '@babel/helper-create-regexp-features-plugin': 7.22.15_@babel+core@7.20.12 '@babel/helper-plugin-utils': 7.22.5 + dev: true /@babel/plugin-transform-unicode-regex/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==} @@ -8421,7 +8149,6 @@ packages: '@babel/core': 7.22.11 '@babel/helper-create-regexp-features-plugin': 7.22.15_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/plugin-transform-unicode-sets-regex/7.22.5_@babel+core@7.22.11: resolution: {integrity: sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==} @@ -8432,7 +8159,6 @@ packages: '@babel/core': 7.22.11 '@babel/helper-create-regexp-features-plugin': 7.22.15_@babel+core@7.22.11 '@babel/helper-plugin-utils': 7.22.5 - dev: true /@babel/polyfill/7.12.1: resolution: {integrity: sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g==} @@ -8448,13 +8174,13 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.21.4 + '@babel/compat-data': 7.22.20 '@babel/core': 7.20.12 - '@babel/helper-compilation-targets': 7.21.4_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-validator-option': 7.21.0 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.20.7_@babel+core@7.20.12 + '@babel/helper-compilation-targets': 7.22.15 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-validator-option': 7.22.15 + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.22.15_@babel+core@7.20.12 + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.22.15_@babel+core@7.20.12 '@babel/plugin-proposal-async-generator-functions': 7.20.7_@babel+core@7.20.12 '@babel/plugin-proposal-class-properties': 7.18.6_@babel+core@7.20.12 '@babel/plugin-proposal-class-static-block': 7.21.0_@babel+core@7.20.12 @@ -8475,7 +8201,7 @@ packages: '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.20.12 '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.20.12 '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.20.12 - '@babel/plugin-syntax-import-assertions': 7.20.0_@babel+core@7.20.12 + '@babel/plugin-syntax-import-assertions': 7.22.5_@babel+core@7.20.12 '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.20.12 '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.20.12 '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.20.12 @@ -8485,44 +8211,44 @@ packages: '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.20.12 '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.20.12 '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.20.12 - '@babel/plugin-transform-arrow-functions': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-transform-async-to-generator': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-transform-block-scoped-functions': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-block-scoping': 7.21.0_@babel+core@7.20.12 - '@babel/plugin-transform-classes': 7.21.0_@babel+core@7.20.12 - '@babel/plugin-transform-computed-properties': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-transform-destructuring': 7.21.3_@babel+core@7.20.12 - '@babel/plugin-transform-dotall-regex': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-duplicate-keys': 7.18.9_@babel+core@7.20.12 - '@babel/plugin-transform-exponentiation-operator': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-for-of': 7.21.0_@babel+core@7.20.12 - '@babel/plugin-transform-function-name': 7.18.9_@babel+core@7.20.12 - '@babel/plugin-transform-literals': 7.18.9_@babel+core@7.20.12 - '@babel/plugin-transform-member-expression-literals': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-modules-amd': 7.20.11_@babel+core@7.20.12 - '@babel/plugin-transform-modules-commonjs': 7.21.2_@babel+core@7.20.12 - '@babel/plugin-transform-modules-systemjs': 7.20.11_@babel+core@7.20.12 - '@babel/plugin-transform-modules-umd': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-named-capturing-groups-regex': 7.20.5_@babel+core@7.20.12 - '@babel/plugin-transform-new-target': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-object-super': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-parameters': 7.21.3_@babel+core@7.20.12 - '@babel/plugin-transform-property-literals': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-regenerator': 7.20.5_@babel+core@7.20.12 - '@babel/plugin-transform-reserved-words': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-shorthand-properties': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-spread': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-transform-sticky-regex': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-template-literals': 7.18.9_@babel+core@7.20.12 - '@babel/plugin-transform-typeof-symbol': 7.18.9_@babel+core@7.20.12 - '@babel/plugin-transform-unicode-escapes': 7.18.10_@babel+core@7.20.12 - '@babel/plugin-transform-unicode-regex': 7.18.6_@babel+core@7.20.12 + '@babel/plugin-transform-arrow-functions': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-async-to-generator': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-block-scoped-functions': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-block-scoping': 7.22.15_@babel+core@7.20.12 + '@babel/plugin-transform-classes': 7.22.15_@babel+core@7.20.12 + '@babel/plugin-transform-computed-properties': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-destructuring': 7.22.15_@babel+core@7.20.12 + '@babel/plugin-transform-dotall-regex': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-duplicate-keys': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-exponentiation-operator': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-for-of': 7.22.15_@babel+core@7.20.12 + '@babel/plugin-transform-function-name': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-literals': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-member-expression-literals': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-modules-amd': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-modules-commonjs': 7.22.15_@babel+core@7.20.12 + '@babel/plugin-transform-modules-systemjs': 7.22.11_@babel+core@7.20.12 + '@babel/plugin-transform-modules-umd': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-new-target': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-object-super': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-parameters': 7.22.15_@babel+core@7.20.12 + '@babel/plugin-transform-property-literals': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-regenerator': 7.22.10_@babel+core@7.20.12 + '@babel/plugin-transform-reserved-words': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-shorthand-properties': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-spread': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-sticky-regex': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-template-literals': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-typeof-symbol': 7.22.5_@babel+core@7.20.12 + '@babel/plugin-transform-unicode-escapes': 7.22.10_@babel+core@7.20.12 + '@babel/plugin-transform-unicode-regex': 7.22.5_@babel+core@7.20.12 '@babel/preset-modules': 0.1.5_@babel+core@7.20.12 - '@babel/types': 7.21.4 + '@babel/types': 7.22.19 babel-plugin-polyfill-corejs2: 0.3.3_@babel+core@7.20.12 babel-plugin-polyfill-corejs3: 0.6.0_@babel+core@7.20.12 babel-plugin-polyfill-regenerator: 0.4.1_@babel+core@7.20.12 - core-js-compat: 3.30.0 + core-js-compat: 3.32.2 semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -8612,6 +8338,7 @@ packages: semver: 6.3.1 transitivePeerDependencies: - supports-color + dev: true /@babel/preset-env/7.22.20_@babel+core@7.22.11: resolution: {integrity: sha512-11MY04gGC4kSzlPHRfvVkNAZhUxOvm7DCJ37hPDnUENwe06npjIRAfInEMTGSb4LZK5ZgDFkv5hw0lGebHeTyg==} @@ -8702,7 +8429,6 @@ packages: semver: 6.3.1 transitivePeerDependencies: - supports-color - dev: true /@babel/preset-flow/7.22.15_@babel+core@7.22.11: resolution: {integrity: sha512-dB5aIMqpkgbTfN5vDdTRPzjqtWiZcRESNR88QYnoPR+bmdYoluOzMX9tQerTv0XzSgZYctPfO1oc0N5zdog1ew==} @@ -8724,7 +8450,7 @@ packages: '@babel/core': 7.20.12 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-proposal-unicode-property-regex': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-dotall-regex': 7.18.6_@babel+core@7.20.12 + '@babel/plugin-transform-dotall-regex': 7.22.5_@babel+core@7.20.12 '@babel/types': 7.22.19 esutils: 2.0.3 dev: true @@ -8737,9 +8463,10 @@ packages: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-proposal-unicode-property-regex': 7.18.6_@babel+core@7.22.11 - '@babel/plugin-transform-dotall-regex': 7.18.6_@babel+core@7.22.11 + '@babel/plugin-transform-dotall-regex': 7.22.5_@babel+core@7.22.11 '@babel/types': 7.22.19 esutils: 2.0.3 + dev: true /@babel/preset-modules/0.1.6-no-external-plugins_@babel+core@7.22.11: resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} @@ -8750,7 +8477,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 '@babel/types': 7.22.19 esutils: 2.0.3 - dev: true /@babel/preset-react/7.18.6_@babel+core@7.22.11: resolution: {integrity: sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==} @@ -8765,6 +8491,7 @@ packages: '@babel/plugin-transform-react-jsx': 7.21.0_@babel+core@7.22.11 '@babel/plugin-transform-react-jsx-development': 7.18.6_@babel+core@7.22.11 '@babel/plugin-transform-react-pure-annotations': 7.18.6_@babel+core@7.22.11 + dev: true /@babel/preset-react/7.22.15_@babel+core@7.22.11: resolution: {integrity: sha512-Csy1IJ2uEh/PecCBXXoZGAZBeCATTuePzCSB7dLYWS0vOEj6CNpjxIhW4duWwZodBNueH7QO14WbGn8YyeuN9w==} @@ -8779,7 +8506,6 @@ packages: '@babel/plugin-transform-react-jsx': 7.22.15_@babel+core@7.22.11 '@babel/plugin-transform-react-jsx-development': 7.22.5_@babel+core@7.22.11 '@babel/plugin-transform-react-pure-annotations': 7.22.5_@babel+core@7.22.11 - dev: true /@babel/preset-typescript/7.21.4_@babel+core@7.22.11: resolution: {integrity: sha512-sMLNWY37TCdRH/bJ6ZeeOH1nPuanED7Ai9Y/vH31IPqalioJ6ZNFUWONsakhv4r4n+I6gm5lmoE0olkgib/j/A==} @@ -8836,8 +8562,9 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.22.13 - '@babel/parser': 7.22.14 + '@babel/parser': 7.22.16 '@babel/types': 7.22.19 + dev: true /@babel/template/7.22.15: resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==} @@ -8847,25 +8574,17 @@ packages: '@babel/parser': 7.22.16 '@babel/types': 7.22.19 - /@babel/template/7.22.5: - resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.22.13 - '@babel/parser': 7.22.14 - '@babel/types': 7.22.19 - /@babel/traverse/7.21.4: resolution: {integrity: sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==} engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.22.13 '@babel/generator': 7.22.10 - '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-function-name': 7.22.5 '@babel/helper-hoist-variables': 7.22.5 '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.22.14 + '@babel/parser': 7.22.16 '@babel/types': 7.22.19 debug: 4.3.4 globals: 11.12.0 @@ -8889,23 +8608,6 @@ packages: transitivePeerDependencies: - supports-color - /@babel/types/7.21.4: - resolution: {integrity: sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.19.4 - '@babel/helper-validator-identifier': 7.19.1 - to-fast-properties: 2.0.0 - - /@babel/types/7.22.11: - resolution: {integrity: sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.22.5 - '@babel/helper-validator-identifier': 7.22.20 - to-fast-properties: 2.0.0 - dev: true - /@babel/types/7.22.19: resolution: {integrity: sha512-P7LAw/LbojPzkgp5oznjE6tQEIWbp4PkkfrZDINTro9zgBRtI324/EYsiSI7lhPbpIQ+DCeR2NNmMWANGGfZsg==} engines: {node: '>=6.9.0'} @@ -9232,29 +8934,6 @@ packages: dev: false optional: true - /@craco/craco/7.1.0_s2wp4rvkjiflatocn7n5b6ts7m: - resolution: {integrity: sha512-oRAcPIKYrfPXp9rSzlsDNeOaVtDiKhoyqSXUoqiK24jCkHr4T8m/a2f74yXIzCbIheoUWDOIfWZyRgFgT+cpqA==} - engines: {node: '>=6'} - hasBin: true - peerDependencies: - react-scripts: ^5.0.0 - dependencies: - autoprefixer: 10.4.14_postcss@8.4.29 - cosmiconfig: 7.1.0 - cosmiconfig-typescript-loader: 1.0.9_5kbyudrvu2mmx7hr4ww4jk565e - cross-spawn: 7.0.3 - lodash: 4.17.21 - react-scripts: 5.0.1_2xn6hao67zmtzyfac7qsgeyxpu - semver: 7.4.0 - webpack-merge: 5.8.0 - transitivePeerDependencies: - - '@swc/core' - - '@swc/wasm' - - '@types/node' - - postcss - - typescript - dev: true - /@cspell/cspell-bundled-dicts/6.19.2: resolution: {integrity: sha512-dbzMGK1JHRTUJ8Pkw/EYbj02RMYhM1/vfrAzgRpqogj83m0cfBC/0IHELkVIl3taC1KdFZ1XHXPp7310LZ6+ww==} engines: {node: '>=14'} @@ -9903,6 +9582,7 @@ packages: /@ctrl/tinycolor/3.6.0: resolution: {integrity: sha512-/Z3l6pXthq0JvMYdUFyX9j0MaCltlIn6mfh9jLyQwg5aPKxkyNa0PTHtU1AlFXLNk55ZuAeJRcpvq+tmLfKmaQ==} engines: {node: '>=10'} + dev: false /@cypress/react/7.0.3_a5iav5bdwa3paydmmfzr63dd4m: resolution: {integrity: sha512-YseqnMugTbdPV9YCYEMXVqIf+P7x+pfjXOdjv4dnDFqNCZeHaZfOZVFZ4XfEHVxMv0aDszxlaLiIp3QDPhr12w==} @@ -10848,7 +10528,7 @@ packages: ajv: 6.12.6 debug: 4.3.4 espree: 7.3.1 - globals: 13.20.0 + globals: 13.21.0 ignore: 4.0.6 import-fresh: 3.3.0 js-yaml: 3.14.1 @@ -13103,26 +12783,6 @@ packages: - webpack-cli dev: true - /@nestjs/common/10.2.2_atc7tu2sld2m3nk4hmwkqn6qde: - resolution: {integrity: sha512-TCOJK2K4FDT3GxFfURjngnjBewS/hizKNFSLBXtX4TTQm0dVQOtESnnVdP14sEiPM6suuWlrGnXW9UDqItGWiQ==} - peerDependencies: - class-transformer: '*' - class-validator: '*' - reflect-metadata: ^0.1.12 - rxjs: ^7.1.0 - peerDependenciesMeta: - class-transformer: - optional: true - class-validator: - optional: true - dependencies: - iterare: 1.2.1 - reflect-metadata: 0.1.13 - rxjs: 7.8.1 - tslib: 2.6.2 - uid: 2.0.2 - dev: false - /@nestjs/common/10.2.2_j3td4gnlgk75ora6o6suo62byy: resolution: {integrity: sha512-TCOJK2K4FDT3GxFfURjngnjBewS/hizKNFSLBXtX4TTQm0dVQOtESnnVdP14sEiPM6suuWlrGnXW9UDqItGWiQ==} peerDependencies: @@ -13352,16 +13012,6 @@ packages: passport: 0.6.0 dev: false - /@nestjs/passport/9.0.3_kn4ljbedllcoqpuu4ifhphsdsu: - resolution: {integrity: sha512-HplSJaimEAz1IOZEu+pdJHHJhQyBOPAYWXYHfAPQvRqWtw4FJF1VXl1Qtk9dcXQX1eKytDtH+qBzNQc19GWNEg==} - peerDependencies: - '@nestjs/common': ^8.0.0 || ^9.0.0 - passport: ^0.4.0 || ^0.5.0 || ^0.6.0 - dependencies: - '@nestjs/common': 10.2.2_atc7tu2sld2m3nk4hmwkqn6qde - passport: 0.6.0 - dev: false - /@nestjs/platform-express/10.2.2_h33h3l6i5mruhsbo3bha6vy2fi: resolution: {integrity: sha512-g5AeXgPQrVm62JOl9FXk0w3Tq1tD4f6ouGikLYs/Aahy0q/Z2HNP9NjXZYpqcjHrpafPYnc3bfBuUwedKW1oHg==} peerDependencies: @@ -14896,46 +14546,7 @@ packages: undici: 5.23.0 dev: false - /@pmmmwh/react-refresh-webpack-plugin/0.5.10_2kpgiq4mtlettjqmb64nc4esa4: - resolution: {integrity: sha512-j0Ya0hCFZPd4x40qLzbhGsh9TMtdb+CJQiso+WxLOPNasohq9cc5SNUcwsZaRH6++Xh91Xkm/xHCkuIiIu0LUA==} - engines: {node: '>= 10.13'} - peerDependencies: - '@types/webpack': 4.x || 5.x - react-refresh: '>=0.10.0 <1.0.0' - sockjs-client: ^1.4.0 - type-fest: '>=0.17.0 <4.0.0' - webpack: '>=4.43.0 <6.0.0' - webpack-dev-server: 3.x || 4.x - webpack-hot-middleware: 2.x - webpack-plugin-serve: 0.x || 1.x - peerDependenciesMeta: - '@types/webpack': - optional: true - sockjs-client: - optional: true - type-fest: - optional: true - webpack-dev-server: - optional: true - webpack-hot-middleware: - optional: true - webpack-plugin-serve: - optional: true - dependencies: - ansi-html-community: 0.0.8 - common-path-prefix: 3.0.0 - core-js-pure: 3.30.0 - error-stack-parser: 2.1.4 - find-up: 5.0.0 - html-entities: 2.3.3 - loader-utils: 2.0.4 - react-refresh: 0.11.0 - schema-utils: 3.3.0 - source-map: 0.7.4 - webpack: 5.88.2_w67ycjwq2niq3jlxgktvf5aow4 - dev: true - - /@pmmmwh/react-refresh-webpack-plugin/0.5.10_aaw3q2lthy6zceet2ugelootve: + /@pmmmwh/react-refresh-webpack-plugin/0.5.10_kwexxzmt7sjpqjleraytwi4jvu: resolution: {integrity: sha512-j0Ya0hCFZPd4x40qLzbhGsh9TMtdb+CJQiso+WxLOPNasohq9cc5SNUcwsZaRH6++Xh91Xkm/xHCkuIiIu0LUA==} engines: {node: '>= 10.13'} peerDependencies: @@ -14971,10 +14582,10 @@ packages: react-refresh: 0.11.0 schema-utils: 3.3.0 source-map: 0.7.4 - webpack: 5.88.2 - webpack-dev-server: 4.11.1_webpack@5.88.2 + webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau + webpack-dev-server: 4.11.1_webpack@5.78.0 - /@pmmmwh/react-refresh-webpack-plugin/0.5.10_kwexxzmt7sjpqjleraytwi4jvu: + /@pmmmwh/react-refresh-webpack-plugin/0.5.10_u6erfrjwlwtxmtcht2oxrgpjdy: resolution: {integrity: sha512-j0Ya0hCFZPd4x40qLzbhGsh9TMtdb+CJQiso+WxLOPNasohq9cc5SNUcwsZaRH6++Xh91Xkm/xHCkuIiIu0LUA==} engines: {node: '>= 10.13'} peerDependencies: @@ -15010,8 +14621,8 @@ packages: react-refresh: 0.11.0 schema-utils: 3.3.0 source-map: 0.7.4 - webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau - webpack-dev-server: 4.11.1_webpack@5.78.0 + webpack: 5.78.0_w67ycjwq2niq3jlxgktvf5aow4 + dev: true /@pmmmwh/react-refresh-webpack-plugin/0.5.10_wik2mtfr6ctscewm36ogu5s3j4: resolution: {integrity: sha512-j0Ya0hCFZPd4x40qLzbhGsh9TMtdb+CJQiso+WxLOPNasohq9cc5SNUcwsZaRH6++Xh91Xkm/xHCkuIiIu0LUA==} @@ -16247,6 +15858,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /@react-email/render/0.0.5: resolution: {integrity: sha512-EE9mCvR3lXeZEJaldCEaEc4msCwPQwZfXbhuPVl3SpRsiHiMK0wNm2X39vVpqzCzxrm0wljCoLruT7Klp9DZAw==} @@ -18791,31 +18403,31 @@ packages: '@swc/core': 1.3.49 '@types/node': 16.11.7 '@types/semver': 7.3.13 - babel-loader: 9.1.2_7nqnrdwtl44yxbgqpombxtkqjy + babel-loader: 9.1.2_5nlhjoewt6bwtyl7wlqhrgzuxm babel-plugin-named-exports-order: 0.0.2 browser-assert: 1.2.1 case-sensitive-paths-webpack-plugin: 2.4.0 constants-browserify: 1.0.0 - css-loader: 6.7.3_webpack@5.88.2 + css-loader: 6.7.3_webpack@5.78.0 express: 4.18.2 - fork-ts-checker-webpack-plugin: 8.0.0_rggdtlzfqxxwxudp3onsqdyocm + fork-ts-checker-webpack-plugin: 8.0.0_fejcc7gjbwtmwzggoernzojija fs-extra: 11.1.1 - html-webpack-plugin: 5.5.3_webpack@5.88.2 + html-webpack-plugin: 5.5.3_webpack@5.78.0 path-browserify: 1.0.1 process: 0.11.10 react: 17.0.2 react-dom: 17.0.2_react@17.0.2 semver: 7.5.4 - style-loader: 3.3.2_webpack@5.88.2 - swc-loader: 0.2.3_zpsjxul5gtyjq5vu5uxru46xsq - terser-webpack-plugin: 5.3.9_2pue2hesc4kyarjonhtsco4zxm + style-loader: 3.3.2_webpack@5.78.0 + swc-loader: 0.2.3_wvz5dn57l37py5yhasbcqqk6hi + terser-webpack-plugin: 5.3.9_dnqqsr3phzjhopay4d6e5ziqz4 ts-dedent: 2.2.0 typescript: 4.9.5 url: 0.11.0 util: 0.12.5 util-deprecate: 1.0.2 - webpack: 5.88.2_w67ycjwq2niq3jlxgktvf5aow4 - webpack-dev-middleware: 6.1.1_webpack@5.88.2 + webpack: 5.78.0_w67ycjwq2niq3jlxgktvf5aow4 + webpack-dev-middleware: 6.1.1_webpack@5.78.0 webpack-hot-middleware: 2.25.3 webpack-virtual-modules: 0.5.0 transitivePeerDependencies: @@ -18859,31 +18471,31 @@ packages: '@swc/core': 1.3.49 '@types/node': 16.11.7 '@types/semver': 7.3.13 - babel-loader: 9.1.2_7nqnrdwtl44yxbgqpombxtkqjy + babel-loader: 9.1.2_5nlhjoewt6bwtyl7wlqhrgzuxm babel-plugin-named-exports-order: 0.0.2 browser-assert: 1.2.1 case-sensitive-paths-webpack-plugin: 2.4.0 constants-browserify: 1.0.0 - css-loader: 6.7.3_webpack@5.88.2 + css-loader: 6.7.3_webpack@5.78.0 express: 4.18.2 - fork-ts-checker-webpack-plugin: 8.0.0_rggdtlzfqxxwxudp3onsqdyocm + fork-ts-checker-webpack-plugin: 8.0.0_fejcc7gjbwtmwzggoernzojija fs-extra: 11.1.1 - html-webpack-plugin: 5.5.3_webpack@5.88.2 + html-webpack-plugin: 5.5.3_webpack@5.78.0 path-browserify: 1.0.1 process: 0.11.10 react: 17.0.2 react-dom: 17.0.2_react@17.0.2 semver: 7.5.4 - style-loader: 3.3.2_webpack@5.88.2 - swc-loader: 0.2.3_zpsjxul5gtyjq5vu5uxru46xsq - terser-webpack-plugin: 5.3.9_2pue2hesc4kyarjonhtsco4zxm + style-loader: 3.3.2_webpack@5.78.0 + swc-loader: 0.2.3_wvz5dn57l37py5yhasbcqqk6hi + terser-webpack-plugin: 5.3.9_dnqqsr3phzjhopay4d6e5ziqz4 ts-dedent: 2.2.0 typescript: 4.9.5 url: 0.11.0 util: 0.12.5 util-deprecate: 1.0.2 - webpack: 5.88.2_u5c4qderjagc6tepfyiby6xhau - webpack-dev-middleware: 6.1.1_webpack@5.88.2 + webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau + webpack-dev-middleware: 6.1.1_webpack@5.78.0 webpack-hot-middleware: 2.25.3 webpack-virtual-modules: 0.5.0 transitivePeerDependencies: @@ -19267,12 +18879,12 @@ packages: '@babel/core': 7.22.11 '@babel/preset-flow': 7.22.15_@babel+core@7.22.11 '@babel/preset-react': 7.22.15_@babel+core@7.22.11 - '@pmmmwh/react-refresh-webpack-plugin': 0.5.10_2kpgiq4mtlettjqmb64nc4esa4 + '@pmmmwh/react-refresh-webpack-plugin': 0.5.10_u6erfrjwlwtxmtcht2oxrgpjdy '@storybook/core-webpack': 7.4.2 '@storybook/docs-tools': 7.4.2 '@storybook/node-logger': 7.4.2 '@storybook/react': 7.4.2_jgxnvbe4faw3ohf4h6p42qq6oy - '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0_rggdtlzfqxxwxudp3onsqdyocm + '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0_fejcc7gjbwtmwzggoernzojija '@types/node': 16.11.7 '@types/semver': 7.3.13 babel-plugin-add-react-displayname: 0.0.5 @@ -19283,7 +18895,7 @@ packages: react-refresh: 0.11.0 semver: 7.5.4 typescript: 4.9.5 - webpack: 5.88.2_w67ycjwq2niq3jlxgktvf5aow4 + webpack: 5.78.0_w67ycjwq2niq3jlxgktvf5aow4 transitivePeerDependencies: - '@swc/core' - '@types/webpack' @@ -19316,12 +18928,12 @@ packages: '@babel/core': 7.22.11 '@babel/preset-flow': 7.22.15_@babel+core@7.22.11 '@babel/preset-react': 7.22.15_@babel+core@7.22.11 - '@pmmmwh/react-refresh-webpack-plugin': 0.5.10_aaw3q2lthy6zceet2ugelootve + '@pmmmwh/react-refresh-webpack-plugin': 0.5.10_kwexxzmt7sjpqjleraytwi4jvu '@storybook/core-webpack': 7.4.2 '@storybook/docs-tools': 7.4.2 '@storybook/node-logger': 7.4.2 '@storybook/react': 7.4.2_jgxnvbe4faw3ohf4h6p42qq6oy - '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0_rggdtlzfqxxwxudp3onsqdyocm + '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0_fejcc7gjbwtmwzggoernzojija '@types/node': 16.11.7 '@types/semver': 7.3.13 babel-plugin-add-react-displayname: 0.0.5 @@ -19332,7 +18944,7 @@ packages: react-refresh: 0.11.0 semver: 7.5.4 typescript: 4.9.5 - webpack: 5.88.2_u5c4qderjagc6tepfyiby6xhau + webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau transitivePeerDependencies: - '@swc/core' - '@types/webpack' @@ -19389,25 +19001,6 @@ packages: - supports-color dev: true - /@storybook/react-docgen-typescript-plugin/1.0.6--canary.9.0c3f3b7.0_rggdtlzfqxxwxudp3onsqdyocm: - resolution: {integrity: sha512-KUqXC3oa9JuQ0kZJLBhVdS4lOneKTOopnNBK4tUAgoxWQ3u/IjzdueZjFr7gyBrXMoU6duutk3RQR9u8ZpYJ4Q==} - peerDependencies: - typescript: '>= 4.x' - webpack: '>= 4' - dependencies: - debug: 4.3.4 - endent: 2.1.0 - find-cache-dir: 3.3.2 - flat-cache: 3.1.0 - micromatch: 4.0.5 - react-docgen-typescript: 2.2.2_typescript@4.9.5 - tslib: 2.6.2 - typescript: 4.9.5 - webpack: 5.88.2_u5c4qderjagc6tepfyiby6xhau - transitivePeerDependencies: - - supports-color - dev: true - /@storybook/react-dom-shim/7.4.2_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-9Ae2As3Hf//mdFEAv58VgDbi9R5JRGne8Ai6Vspc5FZMCJIjr5kullckBi3n9uKRg2L8V7wjDRK8Cql2tEr0Yg==} peerDependencies: @@ -19687,8 +19280,8 @@ packages: dependencies: '@babel/core': 7.22.11 '@babel/plugin-transform-react-constant-elements': 7.21.3_@babel+core@7.22.11 - '@babel/preset-env': 7.21.4_@babel+core@7.22.11 - '@babel/preset-react': 7.18.6_@babel+core@7.22.11 + '@babel/preset-env': 7.22.20_@babel+core@7.22.11 + '@babel/preset-react': 7.22.15_@babel+core@7.22.11 '@svgr/core': 5.5.0 '@svgr/plugin-jsx': 5.5.0 '@svgr/plugin-svgo': 5.5.0 @@ -20674,6 +20267,12 @@ packages: dev: true optional: true + /@types/nodemailer/6.4.11: + resolution: {integrity: sha512-Ld2c0frwpGT4VseuoeboCXQ7UJIkK3X7Lx/4YsZEiUHtHsthWAOCYtf6PAiLhMtfwV0cWJRabLBS3+LD8x6Nrw==} + dependencies: + '@types/node': 14.18.42 + dev: true + /@types/nodemailer/6.4.7: resolution: {integrity: sha512-f5qCBGAn/f0qtRcd4SEn88c8Fp3Swct1731X4ryPKqS61/A3LmmzN8zaEz7hneJvpjFbUUgY7lru/B/7ODTazg==} dependencies: @@ -21441,11 +21040,11 @@ packages: /@vue/babel-plugin-jsx/1.1.1_@babel+core@7.21.4: resolution: {integrity: sha512-j2uVfZjnB5+zkcbc/zsOc0fSNGCMMjaEXP52wdwdIfn0qjFfEYpYZBFKFg+HHnQeJCVrjOeO0YxgaL7DMrym9w==} dependencies: - '@babel/helper-module-imports': 7.21.4 - '@babel/plugin-syntax-jsx': 7.21.4_@babel+core@7.21.4 - '@babel/template': 7.20.7 + '@babel/helper-module-imports': 7.22.15 + '@babel/plugin-syntax-jsx': 7.22.5_@babel+core@7.21.4 + '@babel/template': 7.22.15 '@babel/traverse': 7.21.4 - '@babel/types': 7.21.4 + '@babel/types': 7.22.19 '@vue/babel-helper-vue-transform-on': 1.0.2 camelcase: 6.3.0 html-tags: 3.3.1 @@ -21458,7 +21057,7 @@ packages: /@vue/compiler-core/3.2.47: resolution: {integrity: sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==} dependencies: - '@babel/parser': 7.22.14 + '@babel/parser': 7.22.16 '@vue/shared': 3.2.47 estree-walker: 2.0.2 source-map: 0.6.1 @@ -21472,7 +21071,7 @@ packages: /@vue/compiler-sfc/3.2.47: resolution: {integrity: sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==} dependencies: - '@babel/parser': 7.21.4 + '@babel/parser': 7.22.16 '@vue/compiler-core': 3.2.47 '@vue/compiler-dom': 3.2.47 '@vue/compiler-ssr': 3.2.47 @@ -21525,7 +21124,7 @@ packages: /@vue/reactivity-transform/3.2.47: resolution: {integrity: sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==} dependencies: - '@babel/parser': 7.22.14 + '@babel/parser': 7.22.16 '@vue/compiler-core': 3.2.47 '@vue/shared': 3.2.47 estree-walker: 2.0.2 @@ -21583,24 +21182,28 @@ packages: dependencies: '@webassemblyjs/helper-numbers': 1.11.5 '@webassemblyjs/helper-wasm-bytecode': 1.11.5 + dev: true /@webassemblyjs/floating-point-hex-parser/1.11.1: resolution: {integrity: sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==} /@webassemblyjs/floating-point-hex-parser/1.11.5: resolution: {integrity: sha512-1j1zTIC5EZOtCplMBG/IEwLtUojtwFVwdyVMbL/hwWqbzlQoJsWCOavrdnLkemwNoC/EOwtUFch3fuo+cbcXYQ==} + dev: true /@webassemblyjs/helper-api-error/1.11.1: resolution: {integrity: sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==} /@webassemblyjs/helper-api-error/1.11.5: resolution: {integrity: sha512-L65bDPmfpY0+yFrsgz8b6LhXmbbs38OnwDCf6NpnMUYqa+ENfE5Dq9E42ny0qz/PdR0LJyq/T5YijPnU8AXEpA==} + dev: true /@webassemblyjs/helper-buffer/1.11.1: resolution: {integrity: sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==} /@webassemblyjs/helper-buffer/1.11.5: resolution: {integrity: sha512-fDKo1gstwFFSfacIeH5KfwzjykIE6ldh1iH9Y/8YkAZrhmu4TctqYjSh7t0K2VyDSXOZJ1MLhht/k9IvYGcIxg==} + dev: true /@webassemblyjs/helper-numbers/1.11.1: resolution: {integrity: sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==} @@ -21615,12 +21218,14 @@ packages: '@webassemblyjs/floating-point-hex-parser': 1.11.5 '@webassemblyjs/helper-api-error': 1.11.5 '@xtuc/long': 4.2.2 + dev: true /@webassemblyjs/helper-wasm-bytecode/1.11.1: resolution: {integrity: sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==} /@webassemblyjs/helper-wasm-bytecode/1.11.5: resolution: {integrity: sha512-oC4Qa0bNcqnjAowFn7MPCETQgDYytpsfvz4ujZz63Zu/a/v71HeCAAmZsgZ3YVKec3zSPYytG3/PrRCqbtcAvA==} + dev: true /@webassemblyjs/helper-wasm-section/1.11.1: resolution: {integrity: sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==} @@ -21637,6 +21242,7 @@ packages: '@webassemblyjs/helper-buffer': 1.11.5 '@webassemblyjs/helper-wasm-bytecode': 1.11.5 '@webassemblyjs/wasm-gen': 1.11.5 + dev: true /@webassemblyjs/ieee754/1.11.1: resolution: {integrity: sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==} @@ -21647,6 +21253,7 @@ packages: resolution: {integrity: sha512-37aGq6qVL8A8oPbPrSGMBcp38YZFXcHfiROflJn9jxSdSMMM5dS5P/9e2/TpaJuhE+wFrbukN2WI6Hw9MH5acg==} dependencies: '@xtuc/ieee754': 1.2.0 + dev: true /@webassemblyjs/leb128/1.11.1: resolution: {integrity: sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==} @@ -21657,12 +21264,14 @@ packages: resolution: {integrity: sha512-ajqrRSXaTJoPW+xmkfYN6l8VIeNnR4vBOTQO9HzR7IygoCcKWkICbKFbVTNMjMgMREqXEr0+2M6zukzM47ZUfQ==} dependencies: '@xtuc/long': 4.2.2 + dev: true /@webassemblyjs/utf8/1.11.1: resolution: {integrity: sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==} /@webassemblyjs/utf8/1.11.5: resolution: {integrity: sha512-WiOhulHKTZU5UPlRl53gHR8OxdGsSOxqfpqWeA2FmcwBMaoEdz6b2x2si3IwC9/fSPLfe8pBMRTHVMk5nlwnFQ==} + dev: true /@webassemblyjs/wasm-edit/1.11.1: resolution: {integrity: sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==} @@ -21687,6 +21296,7 @@ packages: '@webassemblyjs/wasm-opt': 1.11.5 '@webassemblyjs/wasm-parser': 1.11.5 '@webassemblyjs/wast-printer': 1.11.5 + dev: true /@webassemblyjs/wasm-gen/1.11.1: resolution: {integrity: sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==} @@ -21705,6 +21315,7 @@ packages: '@webassemblyjs/ieee754': 1.11.5 '@webassemblyjs/leb128': 1.11.5 '@webassemblyjs/utf8': 1.11.5 + dev: true /@webassemblyjs/wasm-opt/1.11.1: resolution: {integrity: sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==} @@ -21721,6 +21332,7 @@ packages: '@webassemblyjs/helper-buffer': 1.11.5 '@webassemblyjs/wasm-gen': 1.11.5 '@webassemblyjs/wasm-parser': 1.11.5 + dev: true /@webassemblyjs/wasm-parser/1.11.1: resolution: {integrity: sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==} @@ -21741,6 +21353,7 @@ packages: '@webassemblyjs/ieee754': 1.11.5 '@webassemblyjs/leb128': 1.11.5 '@webassemblyjs/utf8': 1.11.5 + dev: true /@webassemblyjs/wast-printer/1.11.1: resolution: {integrity: sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==} @@ -21753,6 +21366,7 @@ packages: dependencies: '@webassemblyjs/ast': 1.11.5 '@xtuc/long': 4.2.2 + dev: true /@webpack-cli/configtest/2.1.1_g5qtztmog4wkrsqodniltwrmwa: resolution: {integrity: sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==} @@ -22256,6 +21870,7 @@ packages: react: 17.0.2 react-dom: 17.0.2_react@17.0.2 scroll-into-view-if-needed: 2.2.31 + dev: false /any-observable/0.3.0_rxjs@6.6.7: resolution: {integrity: sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==} @@ -22589,6 +22204,7 @@ packages: /array-tree-filter/2.1.0: resolution: {integrity: sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==} + dev: false /array-union/1.0.2: resolution: {integrity: sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==} @@ -22764,6 +22380,7 @@ packages: /async-validator/4.2.5: resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} + dev: false /async/2.6.4: resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==} @@ -22863,22 +22480,6 @@ packages: postcss: 8.4.21 postcss-value-parser: 4.2.0 - /autoprefixer/10.4.14_postcss@8.4.29: - resolution: {integrity: sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==} - engines: {node: ^10 || ^12 || >=14} - hasBin: true - peerDependencies: - postcss: ^8.1.0 - dependencies: - browserslist: 4.21.10 - caniuse-lite: 1.0.30001525 - fraction.js: 4.2.0 - normalize-range: 0.1.2 - picocolors: 1.0.0 - postcss: 8.4.29 - postcss-value-parser: 4.2.0 - dev: true - /autoprefixer/9.8.8: resolution: {integrity: sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==} hasBin: true @@ -23079,21 +22680,7 @@ packages: webpack: 5.82.1_w67ycjwq2niq3jlxgktvf5aow4 dev: true - /babel-loader/8.3.0_vymqytky47ah5a633vjyq2m3sy: - resolution: {integrity: sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==} - engines: {node: '>= 8.9'} - peerDependencies: - '@babel/core': ^7.0.0 - webpack: '>=2' - dependencies: - '@babel/core': 7.21.4 - find-cache-dir: 3.3.2 - loader-utils: 2.0.4 - make-dir: 3.1.0 - schema-utils: 2.7.1 - webpack: 5.88.2 - - /babel-loader/9.1.2_7nqnrdwtl44yxbgqpombxtkqjy: + /babel-loader/9.1.2_5nlhjoewt6bwtyl7wlqhrgzuxm: resolution: {integrity: sha512-mN14niXW43tddohGl8HPu5yfQq70iUThvFL/4QzESA7GcZoC0eVOhvWdQ8+3UlSjaDE9MVtsW9mxDY07W7VpVA==} engines: {node: '>= 14.15.0'} peerDependencies: @@ -23103,7 +22690,7 @@ packages: '@babel/core': 7.22.11 find-cache-dir: 3.3.2 schema-utils: 4.0.0 - webpack: 5.88.2_u5c4qderjagc6tepfyiby6xhau + webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau dev: true /babel-loader/9.1.2_vbwv3zr3kwaf4v2iytwakh6feu: @@ -23140,6 +22727,7 @@ packages: resolution: {integrity: sha512-N7FYnGh0DFsvDRkAPsvFq/metVfVD7P2h1rokOPpEH4cZbdRHCW+2jbXt0nnuqowkm/xhh2ww1anIdEpfYa7ZA==} dependencies: '@babel/helper-module-imports': 7.21.4 + dev: false /babel-plugin-istanbul/6.1.1: resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} @@ -23235,7 +22823,6 @@ packages: semver: 6.3.1 transitivePeerDependencies: - supports-color - dev: true /babel-plugin-polyfill-corejs3/0.6.0_@babel+core@7.20.12: resolution: {integrity: sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==} @@ -23270,7 +22857,6 @@ packages: core-js-compat: 3.32.2 transitivePeerDependencies: - supports-color - dev: true /babel-plugin-polyfill-regenerator/0.4.1_@babel+core@7.20.12: resolution: {integrity: sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==} @@ -23302,7 +22888,6 @@ packages: '@babel/helper-define-polyfill-provider': 0.4.2_@babel+core@7.22.11 transitivePeerDependencies: - supports-color - dev: true /babel-plugin-react-docgen/4.2.1: resolution: {integrity: sha512-UQ0NmGHj/HAqi5Bew8WvNfCk8wSsmdgNd8ZdMjBCICtyCJCq9LiqgqvjCYe570/Wg7AQArSq1VQ60Dd/CHN7mQ==} @@ -23411,10 +22996,10 @@ packages: '@babel/plugin-proposal-private-methods': 7.18.6_@babel+core@7.22.11 '@babel/plugin-proposal-private-property-in-object': 7.21.0_@babel+core@7.22.11 '@babel/plugin-transform-flow-strip-types': 7.21.0_@babel+core@7.22.11 - '@babel/plugin-transform-react-display-name': 7.18.6_@babel+core@7.22.11 + '@babel/plugin-transform-react-display-name': 7.22.5_@babel+core@7.22.11 '@babel/plugin-transform-runtime': 7.21.4_@babel+core@7.22.11 - '@babel/preset-env': 7.21.4_@babel+core@7.22.11 - '@babel/preset-react': 7.18.6_@babel+core@7.22.11 + '@babel/preset-env': 7.22.20_@babel+core@7.22.11 + '@babel/preset-react': 7.22.15_@babel+core@7.22.11 '@babel/preset-typescript': 7.21.4_@babel+core@7.22.11 '@babel/runtime': 7.21.0 babel-plugin-macros: 3.1.0 @@ -23775,7 +23360,7 @@ packages: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} /buffer-equal-constant-time/1.0.1: - resolution: {integrity: sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=} + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} dev: false /buffer-from/1.1.2: @@ -24407,6 +23992,7 @@ packages: /classnames/2.3.2: resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==} + dev: false /clean-css/4.2.4: resolution: {integrity: sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==} @@ -24866,9 +24452,10 @@ packages: /compute-scroll-into-view/1.0.20: resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==} + dev: false /concat-map/0.0.1: - resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} /concat-stream/1.6.2: resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} @@ -25115,6 +24702,7 @@ packages: resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} dependencies: toggle-selection: 1.0.6 + dev: false /copy-webpack-plugin/11.0.0_webpack@5.76.1: resolution: {integrity: sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==} @@ -25135,6 +24723,7 @@ packages: resolution: {integrity: sha512-P5A2h/9mRYZFIAP+5Ab8ns6083IyVpSclU74UNvbGVQ8VM7n3n3/g2yF3AkKQ9NXz2O+ioxLbEWKnDtgsFamhg==} dependencies: browserslist: 4.21.10 + dev: true /core-js-compat/3.32.2: resolution: {integrity: sha512-+GjlguTDINOijtVRUxrQOv3kfu9rl+qPNdX2LTbJ/ZyVTuxK+ksVSAGX1nHstu4hrv1En/uPTtWgq2gI5wt4AQ==} @@ -25173,23 +24762,6 @@ packages: engines: {node: '>= 0.4.0'} dev: true - /cosmiconfig-typescript-loader/1.0.9_5kbyudrvu2mmx7hr4ww4jk565e: - resolution: {integrity: sha512-tRuMRhxN4m1Y8hP9SNYfz7jRwt8lZdWxdjg/ohg5esKmsndJIn4yT96oJVcf5x0eA11taXl+sIp+ielu529k6g==} - engines: {node: '>=12', npm: '>=6'} - peerDependencies: - '@types/node': '*' - cosmiconfig: '>=7' - typescript: '>=3' - dependencies: - '@types/node': 12.20.55 - cosmiconfig: 7.1.0 - ts-node: 10.9.1_prfxyxghnskheluimpb6dvby4q - typescript: 4.9.5 - transitivePeerDependencies: - - '@swc/core' - - '@swc/wasm' - dev: true - /cosmiconfig-typescript-loader/4.3.0_b5dwmsbekyevytdgwiizfpibom: resolution: {integrity: sha512-NTxV1MFfZDLPiBMjxbHRwSh5LaLcPMwNdCutmnHJCKoVnlvldPWlllonKwrsRJ5pYZBIBGRWWU2tfvzxgeSW5Q==} engines: {node: '>=12', npm: '>=6'} @@ -25323,37 +24895,6 @@ packages: - supports-color dev: true - /craco-antd/1.19.0_3cpxdta34n6sqgppckwpiuxhwa: - resolution: {integrity: sha512-MpbF2LQxb/POiR003oOkuAhHwpyRx1w5opyg7SA4/2og/FMRR/2oca/eqKYQ7vre2dOpt64gkQ5xWETktHWCQQ==} - peerDependencies: - '@craco/craco': ^5.5.0 - antd: '>= 3.0.0' - react-scripts: ^3.4.3 - dependencies: - '@craco/craco': 7.1.0_s2wp4rvkjiflatocn7n5b6ts7m - antd: 4.24.8_sfoxds7t5ydpegc3knd667wn6m - babel-plugin-import: 1.13.6 - craco-less: 1.17.0_ir2lcvgs2do7bdjsff3lxwyn5m - less-vars-to-js: 1.3.0 - react-scripts: 5.0.1_2xn6hao67zmtzyfac7qsgeyxpu - transitivePeerDependencies: - - webpack - dev: true - - /craco-less/1.17.0_ir2lcvgs2do7bdjsff3lxwyn5m: - resolution: {integrity: sha512-G+GPEKPPKiSvYDsnQWuj1C4CIuaY8w+iHvULHkNf5QWLE0LkPfSRf3frhRDJjFxtkThpLPSLjWndD9kx8bCWzw==} - peerDependencies: - '@craco/craco': ^5.5.0 - react-scripts: ^3.3.0 - dependencies: - '@craco/craco': 7.1.0_s2wp4rvkjiflatocn7n5b6ts7m - less: 3.13.1 - less-loader: 6.2.0_webpack@5.88.2 - react-scripts: 5.0.1_2xn6hao67zmtzyfac7qsgeyxpu - transitivePeerDependencies: - - webpack - dev: true - /crc-32/1.2.2: resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} engines: {node: '>=0.8'} @@ -25778,22 +25319,6 @@ packages: semver: 7.5.4 webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau - /css-loader/6.7.3_webpack@5.88.2: - resolution: {integrity: sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ==} - engines: {node: '>= 12.13.0'} - peerDependencies: - webpack: ^5.0.0 - dependencies: - icss-utils: 5.1.0_postcss@8.4.29 - postcss: 8.4.29 - postcss-modules-extract-imports: 3.0.0_postcss@8.4.29 - postcss-modules-local-by-default: 4.0.0_postcss@8.4.29 - postcss-modules-scope: 3.0.0_postcss@8.4.29 - postcss-modules-values: 4.0.0_postcss@8.4.29 - postcss-value-parser: 4.2.0 - semver: 7.5.4 - webpack: 5.88.2 - /css-minimizer-webpack-plugin/3.4.1_rw5du4nyxcvxj5knuew24gpv6a: resolution: {integrity: sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==} engines: {node: '>= 12.13.0'} @@ -25822,7 +25347,7 @@ packages: source-map: 0.6.1 webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau - /css-minimizer-webpack-plugin/3.4.1_webpack@5.88.2: + /css-minimizer-webpack-plugin/3.4.1_webpack@5.78.0: resolution: {integrity: sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==} engines: {node: '>= 12.13.0'} peerDependencies: @@ -25847,7 +25372,8 @@ packages: schema-utils: 4.0.0 serialize-javascript: 6.0.1 source-map: 0.6.1 - webpack: 5.88.2 + webpack: 5.78.0 + dev: false /css-prefers-color-scheme/6.0.3_postcss@8.4.21: resolution: {integrity: sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==} @@ -26043,7 +25569,6 @@ packages: resolution: {integrity: sha512-DbtaLuy59224U+xCiukkxSq8clq++MOtJ1Et7LED1fLszWe88EoblEYFBJ895sB1mC6B4uu3xPT/IjClELhMbA==} dependencies: lodash.flow: 3.5.0 - dev: false /cycle/1.0.3: resolution: {integrity: sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==} @@ -26722,6 +26247,7 @@ packages: /dom-align/1.12.4: resolution: {integrity: sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==} + dev: false /dom-converter/0.2.0: resolution: {integrity: sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==} @@ -27221,6 +26747,7 @@ packages: /es-module-lexer/1.2.1: resolution: {integrity: sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==} + dev: true /es-set-tostringtag/2.0.1: resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} @@ -27495,7 +27022,7 @@ packages: transitivePeerDependencies: - supports-color - /eslint-import-resolver-webpack/0.13.2_re6elnmjmviqdg6e3dtzej3oae: + /eslint-import-resolver-webpack/0.13.2_2shkfpyvap4zatu4dplbemujdy: resolution: {integrity: sha512-XodIPyg1OgE2h5BDErz3WJoK7lawxKTJNhgPNafRST6csC/MZC+L5P6kKqsZGRInpbgc02s/WZMrb4uGJzcuRg==} engines: {node: '>= 6'} peerDependencies: @@ -27514,7 +27041,7 @@ packages: lodash: 4.17.21 resolve: 1.22.2 semver: 5.7.1 - webpack: 5.88.2_@swc+core@1.3.49 + webpack: 5.78.0_@swc+core@1.3.49 transitivePeerDependencies: - supports-color dev: true @@ -27572,7 +27099,7 @@ packages: debug: 3.2.7 eslint: 8.38.0 eslint-import-resolver-node: 0.3.7 - eslint-import-resolver-webpack: 0.13.2_re6elnmjmviqdg6e3dtzej3oae + eslint-import-resolver-webpack: 0.13.2_2shkfpyvap4zatu4dplbemujdy transitivePeerDependencies: - supports-color dev: true @@ -27868,7 +27395,7 @@ packages: object.values: 1.1.6 prop-types: 15.8.1 resolve: 2.0.0-next.4 - semver: 6.3.0 + semver: 6.3.1 string.prototype.matchall: 4.0.8 /eslint-plugin-spellcheck/0.0.20_eslint@8.38.0: @@ -27985,21 +27512,6 @@ packages: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - /eslint-webpack-plugin/3.2.0_3hr2pwtplkwedgf6lcivtacw3q: - resolution: {integrity: sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w==} - engines: {node: '>= 12.13.0'} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - webpack: ^5.0.0 - dependencies: - '@types/eslint': 8.44.2 - eslint: 8.48.0 - jest-worker: 28.1.3 - micromatch: 4.0.5 - normalize-path: 3.0.0 - schema-utils: 4.0.0 - webpack: 5.88.2 - /eslint-webpack-plugin/3.2.0_hzv2vgrkwrkjb5sk6efnemby4e: resolution: {integrity: sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w==} engines: {node: '>= 12.13.0'} @@ -28769,19 +28281,9 @@ packages: webpack: ^4.0.0 || ^5.0.0 dependencies: loader-utils: 2.0.4 - schema-utils: 3.1.2 + schema-utils: 3.3.0 webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau - /file-loader/6.2.0_webpack@5.88.2: - resolution: {integrity: sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==} - engines: {node: '>= 10.13.0'} - peerDependencies: - webpack: ^4.0.0 || ^5.0.0 - dependencies: - loader-utils: 2.0.4 - schema-utils: 3.1.2 - webpack: 5.88.2 - /file-selector/0.6.0: resolution: {integrity: sha512-QlZ5yJC0VxHxQQsQhXvBaC7VRJ2uaxTf+Tfpu4Z/OcVQJVpZO+DGU0rkoVW5ce2SccxugvpBJoMvUs59iILYdw==} engines: {node: '>= 12'} @@ -29089,37 +28591,6 @@ packages: /forever-agent/0.6.1: resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} - /fork-ts-checker-webpack-plugin/6.5.3_rjadthzu3mzu3rpkl7r437txge: - resolution: {integrity: sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==} - engines: {node: '>=10', yarn: '>=1.0.0'} - peerDependencies: - eslint: '>= 6' - typescript: '>= 2.7' - vue-template-compiler: '*' - webpack: '>= 4' - peerDependenciesMeta: - eslint: - optional: true - vue-template-compiler: - optional: true - dependencies: - '@babel/code-frame': 7.22.13 - '@types/json-schema': 7.0.12 - chalk: 4.1.2 - chokidar: 3.5.3 - cosmiconfig: 6.0.0 - deepmerge: 4.3.1 - eslint: 8.48.0 - fs-extra: 9.1.0 - glob: 7.2.3 - memfs: 3.5.0 - minimatch: 3.1.2 - schema-utils: 2.7.0 - semver: 7.5.4 - tapable: 1.1.3 - typescript: 4.9.5 - webpack: 5.88.2 - /fork-ts-checker-webpack-plugin/6.5.3_vq6t4wvflba3b6dvvfvomzl76u: resolution: {integrity: sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==} engines: {node: '>=10', yarn: '>=1.0.0'} @@ -29151,7 +28622,7 @@ packages: typescript: 4.9.5 webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau - /fork-ts-checker-webpack-plugin/8.0.0_rggdtlzfqxxwxudp3onsqdyocm: + /fork-ts-checker-webpack-plugin/8.0.0_fejcc7gjbwtmwzggoernzojija: resolution: {integrity: sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==} engines: {node: '>=12.13.0', yarn: '>=1.0.0'} peerDependencies: @@ -29171,7 +28642,7 @@ packages: semver: 7.5.4 tapable: 2.2.1 typescript: 4.9.5 - webpack: 5.88.2_u5c4qderjagc6tepfyiby6xhau + webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau dev: true /fork-ts-checker-webpack-plugin/8.0.0_wlox7xpecxj4rvkt6b6o7frtlu: @@ -30620,19 +30091,6 @@ packages: tapable: 2.2.1 webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau - /html-webpack-plugin/5.5.3_webpack@5.88.2: - resolution: {integrity: sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg==} - engines: {node: '>=10.13.0'} - peerDependencies: - webpack: ^5.20.0 - dependencies: - '@types/html-minifier-terser': 6.1.0 - html-minifier-terser: 6.1.0 - lodash: 4.17.21 - pretty-error: 4.0.0 - tapable: 2.2.1 - webpack: 5.88.2 - /htmlencode/0.0.4: resolution: {integrity: sha512-0uDvNVpzj/E2TfvLLyyXhKBRvF1y84aZsyRxRXFsQobnHaL4pcaXk+Y9cnFlvnxrBLeXDNq/VJBD+ngdBgQG1w==} dev: false @@ -30789,6 +30247,16 @@ packages: - supports-color dev: true + /https-proxy-agent/5.0.0: + resolution: {integrity: sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + /https-proxy-agent/5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} @@ -33366,7 +32834,7 @@ packages: engines: {node: '>=12.0.0'} hasBin: true dependencies: - '@babel/parser': 7.22.14 + '@babel/parser': 7.22.16 '@jsdoc/salty': 0.2.5 '@types/markdown-it': 12.2.3 bluebird: 3.7.2 @@ -33519,6 +32987,7 @@ packages: resolution: {integrity: sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==} dependencies: string-convert: 0.2.1 + dev: false /json5/1.0.2: resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} @@ -33942,57 +33411,6 @@ packages: webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau dev: true - /less-loader/4.1.0_less@4.1.3+webpack@5.88.2: - resolution: {integrity: sha512-KNTsgCE9tMOM70+ddxp9yyt9iHqgmSs0yTZc5XH5Wo+g80RWRIYNqE58QJKm/yMud5wZEvz50ugRDuzVIkyahg==} - engines: {node: '>= 4.8 < 5.0.0 || >= 5.10'} - peerDependencies: - less: ^2.3.1 || ^3.0.0 - webpack: ^2.0.0 || ^3.0.0 || ^4.0.0 - dependencies: - clone: 2.1.2 - less: 4.1.3 - loader-utils: 1.4.2 - pify: 3.0.0 - webpack: 5.88.2 - dev: true - - /less-loader/6.2.0_webpack@5.88.2: - resolution: {integrity: sha512-Cl5h95/Pz/PWub/tCBgT1oNMFeH1WTD33piG80jn5jr12T4XbxZcjThwNXDQ7AG649WEynuIzO4b0+2Tn9Qolg==} - engines: {node: '>= 10.13.0'} - peerDependencies: - webpack: ^4.0.0 || ^5.0.0 - dependencies: - clone: 2.1.2 - less: 3.13.1 - loader-utils: 2.0.4 - schema-utils: 2.7.1 - webpack: 5.88.2 - dev: true - - /less-vars-to-js/1.3.0: - resolution: {integrity: sha512-xeiLLn/IMCGtdyCkYQnW8UuzoW2oYMCKg9boZRaGI58fLz5r90bNJDlqGzmVt/1Uqk75/DxIVtQSNCMkE5fRZQ==} - engines: {node: '>=8'} - dependencies: - strip-json-comments: 2.0.1 - dev: true - - /less/3.13.1: - resolution: {integrity: sha512-SwA1aQXGUvp+P5XdZslUOhhLnClSLIjWvJhmd+Vgib5BFIr9lMNlQwmwUNOjXThF/A0x+MCYYPeWEfeWiLRnTw==} - engines: {node: '>=6'} - hasBin: true - dependencies: - copy-anything: 2.0.6 - tslib: 1.14.1 - optionalDependencies: - errno: 0.1.8 - graceful-fs: 4.2.11 - image-size: 0.5.5 - make-dir: 2.1.0 - mime: 1.6.0 - native-request: 1.1.0 - source-map: 0.6.1 - dev: true - /less/4.1.3: resolution: {integrity: sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==} engines: {node: '>=6'} @@ -34348,7 +33766,6 @@ packages: /lodash.flow/3.5.0: resolution: {integrity: sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw==} - dev: false /lodash.get/4.4.2: resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} @@ -34698,6 +34115,23 @@ packages: uue: 3.1.2 dev: false + /mailtrap/3.2.0: + resolution: {integrity: sha512-G5CwjtVqakHVvTZtPsHp9YTr0PdvmcKTT8leQRIP/ZqhG9nL+F2VifKZggdUSu25uMtCrnEKc3HwWXdzZcjGvQ==} + engines: {node: '>=16.20.1', yarn: '>=1.22.17'} + peerDependencies: + '@types/nodemailer': ^6.4.9 + nodemailer: ^6.9.4 + peerDependenciesMeta: + '@types/nodemailer': + optional: true + nodemailer: + optional: true + dependencies: + axios: 1.4.0 + transitivePeerDependencies: + - debug + dev: false + /make-dir/2.1.0: resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} engines: {node: '>=6'} @@ -35548,15 +34982,6 @@ packages: schema-utils: 4.0.0 webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau - /mini-css-extract-plugin/2.7.5_webpack@5.88.2: - resolution: {integrity: sha512-9HaR++0mlgom81s95vvNjxkg52n2b5s//3ZTI1EtzFb98awsLSivs2LMsVqnQ3ay0PVhqWcGNyDaTE961FOcjQ==} - engines: {node: '>= 12.13.0'} - peerDependencies: - webpack: ^5.0.0 - dependencies: - schema-utils: 4.0.0 - webpack: 5.88.2 - /minimalistic-assert/1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} @@ -35755,6 +35180,15 @@ packages: is-extendable: 1.0.1 dev: true + /mixpanel/0.17.0: + resolution: {integrity: sha512-DY5WeOy/hmkPrNiiZugJpWR0iMuOwuj1a3u0bgwB2eUFRV6oIew/pIahhpawdbNjb+Bye4a8ID3gefeNPvL81g==} + engines: {node: '>=10.0'} + dependencies: + https-proxy-agent: 5.0.0 + transitivePeerDependencies: + - supports-color + dev: false + /mkdirp-classic/0.5.3: resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} dev: true @@ -35850,6 +35284,7 @@ packages: /moment/2.29.4: resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==} + dev: false /mongodb-connection-string-url/2.6.0: resolution: {integrity: sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==} @@ -36070,12 +35505,6 @@ packages: undici: 5.23.0 dev: false - /native-request/1.1.0: - resolution: {integrity: sha512-uZ5rQaeRn15XmpgE0xoPL8YWqcX90VtCFglYwAgkvKM5e8fog+vePLAhHxuuv/gRkrQxIeh5U3q9sMNUrENqWw==} - requiresBuild: true - dev: true - optional: true - /natural-compare-lite/1.4.0: resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} @@ -37903,27 +37332,6 @@ packages: passport-oauth2: 1.7.0 dev: false - /passport-google-oauth/2.0.0: - resolution: {integrity: sha512-JKxZpBx6wBQXX1/a1s7VmdBgwOugohH+IxCy84aPTZNq/iIPX6u7Mqov1zY7MKRz3niFPol0KJz8zPLBoHKtYA==} - engines: {node: '>= 0.4.0'} - dependencies: - passport-google-oauth1: 1.0.0 - passport-google-oauth20: 2.0.0 - dev: false - - /passport-google-oauth1/1.0.0: - resolution: {integrity: sha512-qpCEhuflJgYrdg5zZIpAq/K3gTqa1CtHjbubsEsidIdpBPLkEVq6tB1I8kBNcH89RdSiYbnKpCBXAZXX/dtx1Q==} - dependencies: - passport-oauth1: 1.3.0 - dev: false - - /passport-google-oauth20/2.0.0: - resolution: {integrity: sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==} - engines: {node: '>= 0.4.0'} - dependencies: - passport-oauth2: 1.7.0 - dev: false - /passport-jwt/4.0.1: resolution: {integrity: sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==} dependencies: @@ -37931,15 +37339,6 @@ packages: passport-strategy: 1.0.0 dev: false - /passport-oauth1/1.3.0: - resolution: {integrity: sha512-8T/nX4gwKTw0PjxP1xfD0QhrydQNakzeOpZ6M5Uqdgz9/a/Ag62RmJxnZQ4LkbdXGrRehQHIAHNAu11rCP46Sw==} - engines: {node: '>= 0.4.0'} - dependencies: - oauth: 0.9.15 - passport-strategy: 1.0.0 - utils-merge: 1.0.1 - dev: false - /passport-oauth2/1.7.0: resolution: {integrity: sha512-j2gf34szdTF2Onw3+76alNnaAExlUmHvkc7cL+cmaS5NzHzDP/BvFHJruueQ9XAeNOdpI+CH+PWid8RA7KCwAQ==} engines: {node: '>= 0.4.0'} @@ -38641,19 +38040,6 @@ packages: semver: 7.5.4 webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau - /postcss-loader/6.2.1_spab46aedetttbaa4fvapwm3fq: - resolution: {integrity: sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==} - engines: {node: '>= 12.13.0'} - peerDependencies: - postcss: ^7.0.0 || ^8.0.1 - webpack: ^5.0.0 - dependencies: - cosmiconfig: 7.1.0 - klona: 2.0.6 - postcss: 8.4.21 - semver: 7.5.4 - webpack: 5.88.2 - /postcss-loader/7.0.2_mquw4qchulb5tpkmg3p2j6qala: resolution: {integrity: sha512-fUJzV/QH7NXUAqV8dWJ9Lg4aTkDCezpTS5HgJ2DvqznexTbSTxgi/dTECvTZ15BwKTtk8G/bqI/QTu2HPd3ZCg==} engines: {node: '>= 14.15.0'} @@ -39680,6 +39066,7 @@ packages: react: 17.0.2 react-dom: 17.0.2_react@17.0.2 resize-observer-polyfill: 1.5.1 + dev: false /rc-cascader/3.7.2_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-5nPEM76eMyikd0NFiy1gjwiB9m+bOzjY6Lnd5bVC6Ar3XLlOpOnlCcV3oBFWLN3f7B18tAGpaAVlT2uyEDCv9w==} @@ -39695,6 +39082,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-checkbox/2.3.2_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-afVi1FYiGv1U0JlpNH/UaEXdh6WUJjcWokj/nUN2TgG80bfG+MDdbfHKlLcNNba94mbjy2/SXJ1HDgrOkXGAjg==} @@ -39706,6 +39094,7 @@ packages: classnames: 2.3.2 react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-collapse/3.4.2_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-jpTwLgJzkhAgp2Wpi3xmbTbbYExg6fkptL67Uu5LCRVEj6wqmy0DHTjjeynsjOLsppHGHu41t1ELntZ0lEvS/Q==} @@ -39720,6 +39109,7 @@ packages: react: 17.0.2 react-dom: 17.0.2_react@17.0.2 shallowequal: 1.1.0 + dev: false /rc-dialog/9.0.2_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-s3U+24xWUuB6Bn2Lk/Qt6rufy+uT+QvWkiFhNBcO9APLxcFFczWamaq7x9h8SCuhfc1nHcW4y8NbMsnAjNnWyg==} @@ -39734,6 +39124,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-drawer/6.1.5_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-MDRomQXFi+tvDuwsRAddJ2Oy2ayLCZ29weMzp3rJFO9UNEVLEVV7nuyx5lEgNJIdM//tE6wWQV95cTUiMVqD6w==} @@ -39748,6 +39139,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-dropdown/4.0.1_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-OdpXuOcme1rm45cR0Jzgfl1otzmU4vuBVb+etXM8vcaULGokAKVpKlw8p6xzspG7jGd/XxShvq+N3VNEfk/l5g==} @@ -39761,6 +39153,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-field-form/1.27.4_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-PQColQnZimGKArnOh8V2907+VzDCXcqtFvHgevDLtqWc/P7YASb/FqntSmdS8q3VND5SHX3Y1vgMIzY22/f/0Q==} @@ -39774,6 +39167,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-image/5.13.0_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-iZTOmw5eWo2+gcrJMMcnd7SsxVHl3w5xlyCgsULUdJhJbnuI8i/AL0tVOsE7aLn9VfOh1qgDT3mC2G75/c7mqg==} @@ -39789,6 +39183,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-input-number/7.3.11_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-aMWPEjFeles6PQnMqP5eWpxzsvHm9rh1jQOWXExUEIxhX62Fyl/ptifLHOn17+waDG1T/YUb6flfJbvwRhHrbA==} @@ -39801,6 +39196,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-input/0.1.4_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-FqDdNz+fV2dKNgfXzcSLKvC+jEs1709t7nD+WdfjrdSaOcefpgc7BUJYadc3usaING+b7ediMTfKxuJBsEFbXA==} @@ -39813,6 +39209,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-mentions/1.13.1_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-FCkaWw6JQygtOz0+Vxz/M/NWqrWHB9LwqlY2RtcuFqWJNFK9njijOOzTSsBGANliGufVUzx/xuPHmZPBV0+Hgw==} @@ -39828,6 +39225,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-menu/9.8.4_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-lmw2j8I2fhdIzHmC9ajfImfckt0WDb2KVJJBBRIsxPEw2kGkEfjLMUoB1NgiNT/Q5cC8PdjGOGQjHJIJMwyNMw==} @@ -39843,6 +39241,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-motion/2.6.3_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-xFLkes3/7VL/J+ah9jJruEW/Akbx5F6jVa2wG5o/ApGKQKSOd5FR3rseHLL9+xtJg4PmCwo6/1tqhDO/T+jFHA==} @@ -39855,6 +39254,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-notification/4.6.1_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-NSmFYwrrdY3+un1GvDAJQw62Xi9LNMSsoQyo95tuaYrcad5Bn9gJUL8AREufRxSQAQnr64u3LtP3EUyLYT6bhw==} @@ -39869,6 +39269,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-overflow/1.3.0_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-p2Qt4SWPTHAYl4oAao1THy669Fm5q8pYBDBHRaFOekCvcdcrgIx0ByXQMEkyPm8wUDX4BK6aARWecvCRc/7CTA==} @@ -39882,6 +39283,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-pagination/3.2.0_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-5tIXjB670WwwcAJzAqp2J+cOBS9W3cH/WU1EiYwXljuZ4vtZXKlY2Idq8FZrnYBz8KhN3vwPo9CoV/SJS6SL1w==} @@ -39893,6 +39295,7 @@ packages: classnames: 2.3.2 react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-picker/2.7.0_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-oZH6FZ3j4iuBxHB4NvQ6ABRsS2If/Kpty1YFFsji7/aej6ruGmfM7WnJWQ88AoPfpJ++ya5z+nVEA8yCRYGKyw==} @@ -39911,6 +39314,7 @@ packages: react: 17.0.2 react-dom: 17.0.2_react@17.0.2 shallowequal: 1.1.0 + dev: false /rc-progress/3.4.1_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-eAFDHXlk8aWpoXl0llrenPMt9qKHQXphxcVsnKs0FHC6eCSk1ebJtyaVjJUzKe0233ogiLDeEFK1Uihz3s67hw==} @@ -39923,6 +39327,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-rate/2.9.2_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-SaiZFyN8pe0Fgphv8t3+kidlej+cq/EALkAJAc3A0w0XcPaH2L1aggM8bhe1u6GAGuQNAoFvTLjw4qLPGRKV5g==} @@ -39936,6 +39341,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-resize-observer/1.3.1_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-iFUdt3NNhflbY3mwySv5CA1TC06zdJ+pfo0oc27xpf4PIOvfZwZGtD9Kz41wGYqC4SLio93RVAirSSpYlV/uYg==} @@ -39949,6 +39355,7 @@ packages: react: 17.0.2 react-dom: 17.0.2_react@17.0.2 resize-observer-polyfill: 1.5.1 + dev: false /rc-segmented/2.1.2_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-qGo1bCr83ESXpXVOCXjFe1QJlCAQXyi9KCiy8eX3rIMYlTeJr/ftySIaTnYsitL18SvWf5ZEHsfqIWoX0EMfFQ==} @@ -39962,6 +39369,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-select/14.1.17_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-6qQhMqtoUkkboRqXKKFRR5Nu1mrnw2mC1uxIBIczg7aiJ94qCZBg4Ww8OLT9f4xdyCgbFSGh6r3yB9EBsjoHGA==} @@ -39979,6 +39387,7 @@ packages: rc-virtual-list: 3.4.13_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-slider/10.0.1_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-igTKF3zBet7oS/3yNiIlmU8KnZ45npmrmHlUUio8PNbIhzMcsh+oE/r2UD42Y6YD2D/s+kzCQkzQrPD6RY435Q==} @@ -39993,6 +39402,7 @@ packages: react: 17.0.2 react-dom: 17.0.2_react@17.0.2 shallowequal: 1.1.0 + dev: false /rc-steps/5.0.0_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-9TgRvnVYirdhbV0C3syJFj9EhCRqoJAsxt4i1rED5o8/ZcSv5TLIYyo4H8MCjLPvbe2R+oBAm/IYBEtC+OS1Rw==} @@ -40006,6 +39416,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-switch/3.2.2_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-+gUJClsZZzvAHGy1vZfnwySxj+MjLlGRyXKXScrtCTcmiYNPzxDFOxdQ/3pK1Kt/0POvwJ/6ALOR8gwdXGhs+A==} @@ -40018,6 +39429,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-table/7.26.0_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-0cD8e6S+DTGAt5nBZQIPFYEaIukn17sfa5uFL98faHlH/whZzD8ii3dbFL4wmUDEL4BLybhYop+QUfZJ4CPvNQ==} @@ -40033,6 +39445,7 @@ packages: react: 17.0.2 react-dom: 17.0.2_react@17.0.2 shallowequal: 1.1.0 + dev: false /rc-tabs/12.5.10_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-Ay0l0jtd4eXepFH9vWBvinBjqOpqzcsJTerBGwJy435P2S90Uu38q8U/mvc1sxUEVOXX5ZCFbxcWPnfG3dH+tQ==} @@ -40050,6 +39463,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-textarea/0.4.7_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-IQPd1CDI3mnMlkFyzt2O4gQ2lxUsnBAeJEoZGJnkkXgORNqyM9qovdrCj9NzcRfpHgLdzaEbU3AmobNFGUznwQ==} @@ -40064,6 +39478,7 @@ packages: react: 17.0.2 react-dom: 17.0.2_react@17.0.2 shallowequal: 1.1.0 + dev: false /rc-tooltip/5.2.2_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-jtQzU/18S6EI3lhSGoDYhPqNpWajMtS5VV/ld1LwyfrDByQpYmw/LW6U7oFXXLukjfDHQ7Ju705A82PRNFWYhg==} @@ -40076,6 +39491,7 @@ packages: rc-trigger: 5.3.4_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-tree-select/5.5.5_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-k2av7jF6tW9bIO4mQhaVdV4kJ1c54oxV3/hHVU+oD251Gb5JN+m1RbJFTMf1o0rAFqkvto33rxMdpafaGKQRJw==} @@ -40090,6 +39506,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-tree/5.7.3_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-Oql2S9+ZmT+mfTp5SNo1XM0QvkENjc0mPRFsHWRFSPuKird0OYMZZKmLznUJ+0aGDeFFWN42wiUZJtMFhrLgLw==} @@ -40105,6 +39522,7 @@ packages: rc-virtual-list: 3.4.13_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-trigger/5.3.4_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-mQv+vas0TwKcjAO2izNPkqR4j86OemLRmvL2nOzdP9OWNWA1ivoTt5hzFqYNW9zACwmTezRiN8bttrC7cZzYSw==} @@ -40120,6 +39538,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-upload/4.3.4_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-uVbtHFGNjHG/RyAfm9fluXB6pvArAGyAx8z7XzXXyorEgVIWj6mOlriuDm0XowDHYz4ycNK0nE0oP3cbFnzxiQ==} @@ -40132,6 +39551,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc-util/5.29.3_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-wX6ZwQTzY2v7phJBquN4mSEIFR0E0qumlENx0zjENtDvoVSq2s7cR95UidKRO1hOHfDsecsfM9D1gO4Kebs7fA==} @@ -40143,6 +39563,7 @@ packages: react: 17.0.2 react-dom: 17.0.2_react@17.0.2 react-is: 16.13.1 + dev: false /rc-virtual-list/3.4.13_sfoxds7t5ydpegc3knd667wn6m: resolution: {integrity: sha512-cPOVDmcNM7rH6ANotanMDilW/55XnFPw0Jh/GQYtrzZSy3AmWvCnqVNyNC/pgg3lfVmX2994dlzAhuUrd4jG7w==} @@ -40157,6 +39578,7 @@ packages: rc-util: 5.29.3_sfoxds7t5ydpegc3knd667wn6m react: 17.0.2 react-dom: 17.0.2_react@17.0.2 + dev: false /rc/1.2.8: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} @@ -40202,7 +39624,6 @@ packages: dependencies: react-scripts: 5.0.1_sq2rawq4ox4a7yhpjmexqgy4wu semver: 5.7.1 - dev: false /react-chartjs-2/4.3.1_5vgmout2ofjcau3vzj5upbaj34: resolution: {integrity: sha512-5i3mjP6tU7QSn0jvb8I4hudTzHJqS8l00ORJnVwI2sYu0ihpj83Lv2YzfxunfxTZkscKvZu2F2w9LkwNBhj6xA==} @@ -40260,47 +39681,6 @@ packages: react-dom: 17.0.2_react@17.0.2 dev: false - /react-dev-utils/12.0.1_rjadthzu3mzu3rpkl7r437txge: - resolution: {integrity: sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==} - engines: {node: '>=14'} - peerDependencies: - typescript: '>=2.7' - webpack: '>=4' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@babel/code-frame': 7.21.4 - address: 1.2.2 - browserslist: 4.21.10 - chalk: 4.1.2 - cross-spawn: 7.0.3 - detect-port-alt: 1.1.6 - escape-string-regexp: 4.0.0 - filesize: 8.0.7 - find-up: 5.0.0 - fork-ts-checker-webpack-plugin: 6.5.3_rjadthzu3mzu3rpkl7r437txge - global-modules: 2.0.0 - globby: 11.1.0 - gzip-size: 6.0.0 - immer: 9.0.21 - is-root: 2.1.0 - loader-utils: 3.2.1 - open: 8.4.2 - pkg-up: 3.1.0 - prompts: 2.4.2 - react-error-overlay: 6.0.11 - recursive-readdir: 2.2.3 - shell-quote: 1.8.1 - strip-ansi: 6.0.1 - text-table: 0.2.0 - typescript: 4.9.5 - webpack: 5.88.2 - transitivePeerDependencies: - - eslint - - supports-color - - vue-template-compiler - /react-dev-utils/12.0.1_vq6t4wvflba3b6dvvfvomzl76u: resolution: {integrity: sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==} engines: {node: '>=14'} @@ -40311,7 +39691,7 @@ packages: typescript: optional: true dependencies: - '@babel/code-frame': 7.21.4 + '@babel/code-frame': 7.22.13 address: 1.2.2 browserslist: 4.21.10 chalk: 4.1.2 @@ -40698,54 +40078,54 @@ packages: optional: true dependencies: '@babel/core': 7.21.4 - '@pmmmwh/react-refresh-webpack-plugin': 0.5.10_aaw3q2lthy6zceet2ugelootve + '@pmmmwh/react-refresh-webpack-plugin': 0.5.10_kwexxzmt7sjpqjleraytwi4jvu '@svgr/webpack': 5.5.0 babel-jest: 27.5.1_@babel+core@7.21.4 - babel-loader: 8.3.0_vymqytky47ah5a633vjyq2m3sy + babel-loader: 8.3.0_2bpkfvz2mezbew2j5yjox7n6pu babel-plugin-named-asset-import: 0.3.8_@babel+core@7.21.4 babel-preset-react-app: 10.0.1 bfj: 7.0.2 browserslist: 4.21.5 camelcase: 6.3.0 case-sensitive-paths-webpack-plugin: 2.4.0 - css-loader: 6.7.3_webpack@5.88.2 - css-minimizer-webpack-plugin: 3.4.1_webpack@5.88.2 + css-loader: 6.7.3_webpack@5.78.0 + css-minimizer-webpack-plugin: 3.4.1_webpack@5.78.0 dotenv: 10.0.0 dotenv-expand: 5.1.0 eslint: 8.48.0 eslint-config-react-app: 7.0.1_sbdixes4cky6hqsocdpcwctiue - eslint-webpack-plugin: 3.2.0_3hr2pwtplkwedgf6lcivtacw3q - file-loader: 6.2.0_webpack@5.88.2 + eslint-webpack-plugin: 3.2.0_hzv2vgrkwrkjb5sk6efnemby4e + file-loader: 6.2.0_webpack@5.78.0 fs-extra: 10.1.0 - html-webpack-plugin: 5.5.3_webpack@5.88.2 + html-webpack-plugin: 5.5.3_webpack@5.78.0 identity-obj-proxy: 3.0.0 jest: 27.5.1 jest-resolve: 27.5.1 jest-watch-typeahead: 1.1.0_jest@27.5.1 - mini-css-extract-plugin: 2.7.5_webpack@5.88.2 + mini-css-extract-plugin: 2.7.5_webpack@5.78.0 postcss: 8.4.21 postcss-flexbugs-fixes: 5.0.2_postcss@8.4.21 - postcss-loader: 6.2.1_spab46aedetttbaa4fvapwm3fq + postcss-loader: 6.2.1_2izhiogyhzv3k6gmxpzxzwhblu postcss-normalize: 10.0.1_jrpp4geoaqu5dz2gragkckznb4 postcss-preset-env: 7.8.3_postcss@8.4.21 prompts: 2.4.2 react: 17.0.2 react-app-polyfill: 3.0.0 - react-dev-utils: 12.0.1_rjadthzu3mzu3rpkl7r437txge + react-dev-utils: 12.0.1_vq6t4wvflba3b6dvvfvomzl76u react-refresh: 0.11.0 resolve: 1.22.2 resolve-url-loader: 4.0.0 - sass-loader: 12.6.0_webpack@5.88.2 + sass-loader: 12.6.0_webpack@5.78.0 semver: 7.4.0 - source-map-loader: 3.0.2_webpack@5.88.2 - style-loader: 3.3.2_webpack@5.88.2 + source-map-loader: 3.0.2_webpack@5.78.0 + style-loader: 3.3.2_webpack@5.78.0 tailwindcss: 3.3.1_postcss@8.4.21 - terser-webpack-plugin: 5.3.7_webpack@5.88.2 + terser-webpack-plugin: 5.3.7_webpack@5.78.0 typescript: 4.9.5 - webpack: 5.88.2 - webpack-dev-server: 4.11.1_webpack@5.88.2 - webpack-manifest-plugin: 4.1.1_webpack@5.88.2 - workbox-webpack-plugin: 6.5.4_webpack@5.88.2 + webpack: 5.78.0 + webpack-dev-server: 4.11.1_webpack@5.78.0 + webpack-manifest-plugin: 4.1.1_webpack@5.78.0 + workbox-webpack-plugin: 6.5.4_webpack@5.78.0 optionalDependencies: fsevents: 2.3.3 transitivePeerDependencies: @@ -40780,6 +40160,7 @@ packages: - webpack-cli - webpack-hot-middleware - webpack-plugin-serve + dev: false /react-scripts/5.0.1_sq2rawq4ox4a7yhpjmexqgy4wu: resolution: {integrity: sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==} @@ -41336,16 +40717,10 @@ packages: /regenerator-runtime/0.13.11: resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} - /regenerator-transform/0.15.1: - resolution: {integrity: sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==} - dependencies: - '@babel/runtime': 7.21.0 - /regenerator-transform/0.15.2: resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} dependencies: '@babel/runtime': 7.21.0 - dev: true /regex-cache/0.4.4: resolution: {integrity: sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==} @@ -41613,6 +40988,7 @@ packages: /resize-observer-polyfill/1.5.1: resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} + dev: false /resolve-cwd/3.0.0: resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} @@ -42063,29 +41439,6 @@ packages: neo-async: 2.6.2 webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau - /sass-loader/12.6.0_webpack@5.88.2: - resolution: {integrity: sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==} - engines: {node: '>= 12.13.0'} - peerDependencies: - fibers: '>= 3.1.0' - node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - sass: ^1.3.0 - sass-embedded: '*' - webpack: ^5.0.0 - peerDependenciesMeta: - fibers: - optional: true - node-sass: - optional: true - sass: - optional: true - sass-embedded: - optional: true - dependencies: - klona: 2.0.6 - neo-async: 2.6.2 - webpack: 5.88.2 - /sass-loader/13.2.0_sass@1.58.1+webpack@5.76.1: resolution: {integrity: sha512-JWEp48djQA4nbZxmgC02/Wh0eroSUutulROUusYJO9P9zltRbNN80JCBHqRGzjd4cmZCa/r88xgfkjGD0TXsHg==} engines: {node: '>= 14.15.0'} @@ -42186,6 +41539,7 @@ packages: '@types/json-schema': 7.0.12 ajv: 6.12.6 ajv-keywords: 3.5.2_ajv@6.12.6 + dev: true /schema-utils/3.3.0: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} @@ -42212,6 +41566,7 @@ packages: resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==} dependencies: compute-scroll-into-view: 1.0.20 + dev: false /scroll/3.0.1: resolution: {integrity: sha512-pz7y517OVls1maEzlirKO5nPYle9AXsFzTMNJrRGmT951mzpIBy7sNHOg5o/0MQd/NqliCiWnAi0kZneMPFLcg==} @@ -42481,6 +41836,7 @@ packages: /shallowequal/1.1.0: resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} + dev: false /shebang-command/1.2.0: resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} @@ -42852,17 +42208,6 @@ packages: source-map-js: 1.0.2 webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau - /source-map-loader/3.0.2_webpack@5.88.2: - resolution: {integrity: sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==} - engines: {node: '>= 12.13.0'} - peerDependencies: - webpack: ^5.0.0 - dependencies: - abab: 2.0.6 - iconv-lite: 0.6.3 - source-map-js: 1.0.2 - webpack: 5.88.2 - /source-map-loader/4.0.1_webpack@5.76.1: resolution: {integrity: sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA==} engines: {node: '>= 14.15.0'} @@ -43281,6 +42626,7 @@ packages: /string-convert/0.2.1: resolution: {integrity: sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==} + dev: false /string-length/4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} @@ -43539,14 +42885,6 @@ packages: dependencies: webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau - /style-loader/3.3.2_webpack@5.88.2: - resolution: {integrity: sha512-RHs/vcrKdQK8wZliteNK4NKzxvLBzpuHMqYmUVWeKa6MkaIQ97ZTOS0b+zapZhy6GcrgWnvWYCMHRirC3FsUmw==} - engines: {node: '>= 12.13.0'} - peerDependencies: - webpack: ^5.0.0 - dependencies: - webpack: 5.88.2 - /stylehacks/5.1.1_postcss@8.4.25: resolution: {integrity: sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==} engines: {node: ^10 || ^12 || >=14.0} @@ -43790,14 +43128,14 @@ packages: upper-case: 1.1.3 dev: true - /swc-loader/0.2.3_zpsjxul5gtyjq5vu5uxru46xsq: + /swc-loader/0.2.3_wvz5dn57l37py5yhasbcqqk6hi: resolution: {integrity: sha512-D1p6XXURfSPleZZA/Lipb3A8pZ17fP4NObZvFCDjK/OKljroqDpPmsBdTraWhVBqUNpcWBQY1imWdoPScRlQ7A==} peerDependencies: '@swc/core': ^1.2.147 webpack: '>=2' dependencies: '@swc/core': 1.3.49 - webpack: 5.88.2_u5c4qderjagc6tepfyiby6xhau + webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau dev: true /symbol-observable/1.2.0: @@ -44060,7 +43398,7 @@ packages: terser: 5.19.3 webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau - /terser-webpack-plugin/5.3.7_webpack@5.88.2: + /terser-webpack-plugin/5.3.7_webpack@5.78.0: resolution: {integrity: sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -44081,9 +43419,10 @@ packages: schema-utils: 3.3.0 serialize-javascript: 6.0.1 terser: 5.19.3 - webpack: 5.88.2 + webpack: 5.78.0 + dev: false - /terser-webpack-plugin/5.3.9_2pue2hesc4kyarjonhtsco4zxm: + /terser-webpack-plugin/5.3.9_aka7ue4sjkoeo6uo4dlqntmpgy: resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -44099,17 +43438,17 @@ packages: uglify-js: optional: true dependencies: - '@jridgewell/trace-mapping': 0.3.19 + '@jridgewell/trace-mapping': 0.3.18 '@swc/core': 1.3.49 esbuild: 0.18.20 jest-worker: 27.5.1 schema-utils: 3.1.2 serialize-javascript: 6.0.1 - terser: 5.19.3 - webpack: 5.88.2_u5c4qderjagc6tepfyiby6xhau + terser: 5.16.9 + webpack: 5.82.1_w67ycjwq2niq3jlxgktvf5aow4 dev: true - /terser-webpack-plugin/5.3.9_aka7ue4sjkoeo6uo4dlqntmpgy: + /terser-webpack-plugin/5.3.9_dnqqsr3phzjhopay4d6e5ziqz4: resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -44125,17 +43464,16 @@ packages: uglify-js: optional: true dependencies: - '@jridgewell/trace-mapping': 0.3.18 + '@jridgewell/trace-mapping': 0.3.19 '@swc/core': 1.3.49 esbuild: 0.18.20 jest-worker: 27.5.1 - schema-utils: 3.1.2 + schema-utils: 3.3.0 serialize-javascript: 6.0.1 - terser: 5.16.9 - webpack: 5.82.1_w67ycjwq2niq3jlxgktvf5aow4 - dev: true + terser: 5.19.3 + webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau - /terser-webpack-plugin/5.3.9_dnqqsr3phzjhopay4d6e5ziqz4: + /terser-webpack-plugin/5.3.9_webpack@5.76.1: resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -44152,15 +43490,14 @@ packages: optional: true dependencies: '@jridgewell/trace-mapping': 0.3.19 - '@swc/core': 1.3.49 - esbuild: 0.18.20 jest-worker: 27.5.1 - schema-utils: 3.1.2 + schema-utils: 3.3.0 serialize-javascript: 6.0.1 terser: 5.19.3 - webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau + webpack: 5.76.1 + dev: true - /terser-webpack-plugin/5.3.9_webpack@5.76.1: + /terser-webpack-plugin/5.3.9_webpack@5.78.0: resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -44178,11 +43515,10 @@ packages: dependencies: '@jridgewell/trace-mapping': 0.3.19 jest-worker: 27.5.1 - schema-utils: 3.1.2 + schema-utils: 3.3.0 serialize-javascript: 6.0.1 terser: 5.19.3 - webpack: 5.76.1 - dev: true + webpack: 5.78.0 /terser-webpack-plugin/5.3.9_webpack@5.88.2: resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} @@ -44202,12 +43538,13 @@ packages: dependencies: '@jridgewell/trace-mapping': 0.3.19 jest-worker: 27.5.1 - schema-utils: 3.1.2 + schema-utils: 3.3.0 serialize-javascript: 6.0.1 terser: 5.19.3 webpack: 5.88.2 + dev: true - /terser-webpack-plugin/5.3.9_zpsjxul5gtyjq5vu5uxru46xsq: + /terser-webpack-plugin/5.3.9_wvz5dn57l37py5yhasbcqqk6hi: resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -44226,10 +43563,10 @@ packages: '@jridgewell/trace-mapping': 0.3.19 '@swc/core': 1.3.49 jest-worker: 27.5.1 - schema-utils: 3.1.2 + schema-utils: 3.3.0 serialize-javascript: 6.0.1 terser: 5.19.3 - webpack: 5.88.2_@swc+core@1.3.49 + webpack: 5.78.0_@swc+core@1.3.49 dev: true /terser/4.8.1: @@ -44460,6 +43797,7 @@ packages: /toggle-selection/1.0.6: resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} + dev: false /toidentifier/1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} @@ -44618,7 +43956,7 @@ packages: json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 - semver: 7.4.0 + semver: 7.5.4 typescript: 4.9.5 yargs-parser: 20.2.9 dev: true @@ -44687,7 +44025,7 @@ packages: json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 - semver: 7.4.0 + semver: 7.5.4 typescript: 4.9.5 yargs-parser: 20.2.9 dev: true @@ -44722,7 +44060,7 @@ packages: json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 - semver: 7.4.0 + semver: 7.5.4 typescript: 4.9.5 yargs-parser: 20.2.9 dev: true @@ -44796,7 +44134,7 @@ packages: yargs-parser: 21.1.1 dev: true - /ts-loader/9.4.2_hybrf64lftnf5l2xwgg7goi2iu: + /ts-loader/9.4.2_fejcc7gjbwtmwzggoernzojija: resolution: {integrity: sha512-OmlC4WVmFv5I0PpaxYb+qGeGOdm5giHU7HwDDUjw59emP2UYMHy9fFSDcYgSNoH8sXcj4hGCSEhlDZ9ULeDraA==} engines: {node: '>=12.0.0'} peerDependencies: @@ -44808,10 +44146,10 @@ packages: micromatch: 4.0.5 semver: 7.5.2 typescript: 4.9.5 - webpack: 5.82.1_w67ycjwq2niq3jlxgktvf5aow4 + webpack: 5.78.0 dev: true - /ts-loader/9.4.2_rggdtlzfqxxwxudp3onsqdyocm: + /ts-loader/9.4.2_hybrf64lftnf5l2xwgg7goi2iu: resolution: {integrity: sha512-OmlC4WVmFv5I0PpaxYb+qGeGOdm5giHU7HwDDUjw59emP2UYMHy9fFSDcYgSNoH8sXcj4hGCSEhlDZ9ULeDraA==} engines: {node: '>=12.0.0'} peerDependencies: @@ -44823,7 +44161,7 @@ packages: micromatch: 4.0.5 semver: 7.5.2 typescript: 4.9.5 - webpack: 5.88.2 + webpack: 5.82.1_w67ycjwq2niq3jlxgktvf5aow4 dev: true /ts-node/10.9.1_3oc4l4vkwjasz4xtxrjz3zw4u4: @@ -44891,37 +44229,6 @@ packages: yn: 3.1.1 dev: true - /ts-node/10.9.1_prfxyxghnskheluimpb6dvby4q: - resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.9 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.3 - '@types/node': 12.20.55 - acorn: 8.10.0 - acorn-walk: 8.2.0 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 4.9.5 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - dev: true - /ts-node/10.9.1_u2ngtadnsu6rqlw26gb7xq6vqq: resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true @@ -46217,20 +45524,7 @@ packages: mime-types: 2.1.35 range-parser: 1.2.1 schema-utils: 4.0.0 - webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau - - /webpack-dev-middleware/5.3.3_webpack@5.88.2: - resolution: {integrity: sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==} - engines: {node: '>= 12.13.0'} - peerDependencies: - webpack: ^4.0.0 || ^5.0.0 - dependencies: - colorette: 2.0.19 - memfs: 3.5.0 - mime-types: 2.1.35 - range-parser: 1.2.1 - schema-utils: 4.0.0 - webpack: 5.88.2 + webpack: 5.78.0 /webpack-dev-middleware/6.0.1_webpack@5.76.1: resolution: {integrity: sha512-PZPZ6jFinmqVPJZbisfggDiC+2EeGZ1ZByyMP5sOFJcPPWSexalISz+cvm+j+oYPT7FIJyxT76esjnw9DhE5sw==} @@ -46246,7 +45540,7 @@ packages: webpack: 5.76.1 dev: true - /webpack-dev-middleware/6.1.1_webpack@5.88.2: + /webpack-dev-middleware/6.1.1_webpack@5.78.0: resolution: {integrity: sha512-y51HrHaFeeWir0YO4f0g+9GwZawuigzcAdRNon6jErXy/SqV/+O6eaVAzDqE6t3e3NpGeR5CS+cCDaTC+V3yEQ==} engines: {node: '>= 14.15.0'} peerDependencies: @@ -46260,7 +45554,7 @@ packages: mime-types: 2.1.35 range-parser: 1.2.1 schema-utils: 4.0.0 - webpack: 5.88.2_u5c4qderjagc6tepfyiby6xhau + webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau dev: true /webpack-dev-server/4.11.1_webpack@5.76.1: @@ -46358,53 +45652,6 @@ packages: - supports-color - utf-8-validate - /webpack-dev-server/4.11.1_webpack@5.88.2: - resolution: {integrity: sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw==} - engines: {node: '>= 12.13.0'} - hasBin: true - peerDependencies: - webpack: ^4.37.0 || ^5.0.0 - webpack-cli: '*' - peerDependenciesMeta: - webpack-cli: - optional: true - dependencies: - '@types/bonjour': 3.5.10 - '@types/connect-history-api-fallback': 1.3.5 - '@types/express': 4.17.17 - '@types/serve-index': 1.9.1 - '@types/serve-static': 1.15.1 - '@types/sockjs': 0.3.33 - '@types/ws': 8.5.4 - ansi-html-community: 0.0.8 - bonjour-service: 1.1.1 - chokidar: 3.5.3 - colorette: 2.0.19 - compression: 1.7.4 - connect-history-api-fallback: 2.0.0 - default-gateway: 6.0.3 - express: 4.18.2 - graceful-fs: 4.2.11 - html-entities: 2.3.3 - http-proxy-middleware: 2.0.6_@types+express@4.17.17 - ipaddr.js: 2.0.1 - open: 8.4.2 - p-retry: 4.6.2 - rimraf: 3.0.2 - schema-utils: 4.0.0 - selfsigned: 2.1.1 - serve-index: 1.9.1 - sockjs: 0.3.24 - spdy: 4.0.2 - webpack: 5.88.2 - webpack-dev-middleware: 5.3.3_webpack@5.88.2 - ws: 8.13.0 - transitivePeerDependencies: - - bufferutil - - debug - - supports-color - - utf-8-validate - /webpack-hot-middleware/2.25.3: resolution: {integrity: sha512-IK/0WAHs7MTu1tzLTjio73LjS3Ov+VvBKQmE8WPlJutgG5zT6Urgq/BbAdRrHTRpyzK0dvAvFh1Qg98akxgZpA==} dependencies: @@ -46423,16 +45670,6 @@ packages: webpack: 5.78.0_u5c4qderjagc6tepfyiby6xhau webpack-sources: 2.3.1 - /webpack-manifest-plugin/4.1.1_webpack@5.88.2: - resolution: {integrity: sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==} - engines: {node: '>=12.22.0'} - peerDependencies: - webpack: ^4.44.2 || ^5.47.0 - dependencies: - tapable: 2.2.1 - webpack: 5.88.2 - webpack-sources: 2.3.1 - /webpack-merge/5.8.0: resolution: {integrity: sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==} engines: {node: '>=10.0.0'} @@ -46519,7 +45756,7 @@ packages: - uglify-js dev: true - /webpack/5.78.0_u5c4qderjagc6tepfyiby6xhau: + /webpack/5.78.0: resolution: {integrity: sha512-gT5DP72KInmE/3azEaQrISjTvLYlSM0j1Ezhht/KLVkrqtv10JoP/RXhwmX/frrutOPuSq3o5Vq0ehR/4Vmd1g==} engines: {node: '>=10.13.0'} hasBin: true @@ -46536,7 +45773,7 @@ packages: '@webassemblyjs/wasm-parser': 1.11.1 acorn: 8.10.0 acorn-import-assertions: 1.9.0_acorn@8.10.0 - browserslist: 4.21.5 + browserslist: 4.21.10 chrome-trace-event: 1.0.3 enhanced-resolve: 5.15.0 es-module-lexer: 0.9.3 @@ -46550,7 +45787,7 @@ packages: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.9_dnqqsr3phzjhopay4d6e5ziqz4 + terser-webpack-plugin: 5.3.9_webpack@5.78.0 watchpack: 2.4.0 webpack-sources: 3.2.3 transitivePeerDependencies: @@ -46558,8 +45795,8 @@ packages: - esbuild - uglify-js - /webpack/5.82.1_w67ycjwq2niq3jlxgktvf5aow4: - resolution: {integrity: sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw==} + /webpack/5.78.0_@swc+core@1.3.49: + resolution: {integrity: sha512-gT5DP72KInmE/3azEaQrISjTvLYlSM0j1Ezhht/KLVkrqtv10JoP/RXhwmX/frrutOPuSq3o5Vq0ehR/4Vmd1g==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -46569,16 +45806,16 @@ packages: optional: true dependencies: '@types/eslint-scope': 3.7.4 - '@types/estree': 1.0.0 - '@webassemblyjs/ast': 1.11.5 - '@webassemblyjs/wasm-edit': 1.11.5 - '@webassemblyjs/wasm-parser': 1.11.5 - acorn: 8.8.2 - acorn-import-assertions: 1.8.0_acorn@8.8.2 - browserslist: 4.21.5 + '@types/estree': 0.0.51 + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/wasm-edit': 1.11.1 + '@webassemblyjs/wasm-parser': 1.11.1 + acorn: 8.10.0 + acorn-import-assertions: 1.9.0_acorn@8.10.0 + browserslist: 4.21.10 chrome-trace-event: 1.0.3 enhanced-resolve: 5.15.0 - es-module-lexer: 1.2.1 + es-module-lexer: 0.9.3 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -46587,11 +45824,10 @@ packages: loader-runner: 4.3.0 mime-types: 2.1.35 neo-async: 2.6.2 - schema-utils: 3.1.2 + schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.9_aka7ue4sjkoeo6uo4dlqntmpgy + terser-webpack-plugin: 5.3.9_wvz5dn57l37py5yhasbcqqk6hi watchpack: 2.4.0 - webpack-cli: 5.1.4_jwpra7xq62zw3tehur2jwszlsq webpack-sources: 3.2.3 transitivePeerDependencies: - '@swc/core' @@ -46599,8 +45835,8 @@ packages: - uglify-js dev: true - /webpack/5.88.2: - resolution: {integrity: sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==} + /webpack/5.78.0_u5c4qderjagc6tepfyiby6xhau: + resolution: {integrity: sha512-gT5DP72KInmE/3azEaQrISjTvLYlSM0j1Ezhht/KLVkrqtv10JoP/RXhwmX/frrutOPuSq3o5Vq0ehR/4Vmd1g==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -46610,16 +45846,16 @@ packages: optional: true dependencies: '@types/eslint-scope': 3.7.4 - '@types/estree': 1.0.1 - '@webassemblyjs/ast': 1.11.5 - '@webassemblyjs/wasm-edit': 1.11.5 - '@webassemblyjs/wasm-parser': 1.11.5 + '@types/estree': 0.0.51 + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/wasm-edit': 1.11.1 + '@webassemblyjs/wasm-parser': 1.11.1 acorn: 8.10.0 acorn-import-assertions: 1.9.0_acorn@8.10.0 browserslist: 4.21.10 chrome-trace-event: 1.0.3 enhanced-resolve: 5.15.0 - es-module-lexer: 1.2.1 + es-module-lexer: 0.9.3 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -46630,7 +45866,7 @@ packages: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.9_webpack@5.88.2 + terser-webpack-plugin: 5.3.9_dnqqsr3phzjhopay4d6e5ziqz4 watchpack: 2.4.0 webpack-sources: 3.2.3 transitivePeerDependencies: @@ -46638,8 +45874,8 @@ packages: - esbuild - uglify-js - /webpack/5.88.2_@swc+core@1.3.49: - resolution: {integrity: sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==} + /webpack/5.78.0_w67ycjwq2niq3jlxgktvf5aow4: + resolution: {integrity: sha512-gT5DP72KInmE/3azEaQrISjTvLYlSM0j1Ezhht/KLVkrqtv10JoP/RXhwmX/frrutOPuSq3o5Vq0ehR/4Vmd1g==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -46649,16 +45885,16 @@ packages: optional: true dependencies: '@types/eslint-scope': 3.7.4 - '@types/estree': 1.0.1 - '@webassemblyjs/ast': 1.11.5 - '@webassemblyjs/wasm-edit': 1.11.5 - '@webassemblyjs/wasm-parser': 1.11.5 + '@types/estree': 0.0.51 + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/wasm-edit': 1.11.1 + '@webassemblyjs/wasm-parser': 1.11.1 acorn: 8.10.0 acorn-import-assertions: 1.9.0_acorn@8.10.0 browserslist: 4.21.10 chrome-trace-event: 1.0.3 enhanced-resolve: 5.15.0 - es-module-lexer: 1.2.1 + es-module-lexer: 0.9.3 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -46669,8 +45905,9 @@ packages: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.9_zpsjxul5gtyjq5vu5uxru46xsq + terser-webpack-plugin: 5.3.9_dnqqsr3phzjhopay4d6e5ziqz4 watchpack: 2.4.0 + webpack-cli: 5.1.4_jwpra7xq62zw3tehur2jwszlsq webpack-sources: 3.2.3 transitivePeerDependencies: - '@swc/core' @@ -46678,8 +45915,8 @@ packages: - uglify-js dev: true - /webpack/5.88.2_u5c4qderjagc6tepfyiby6xhau: - resolution: {integrity: sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==} + /webpack/5.82.1_w67ycjwq2niq3jlxgktvf5aow4: + resolution: {integrity: sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -46689,13 +45926,13 @@ packages: optional: true dependencies: '@types/eslint-scope': 3.7.4 - '@types/estree': 1.0.1 + '@types/estree': 1.0.0 '@webassemblyjs/ast': 1.11.5 '@webassemblyjs/wasm-edit': 1.11.5 '@webassemblyjs/wasm-parser': 1.11.5 - acorn: 8.10.0 - acorn-import-assertions: 1.9.0_acorn@8.10.0 - browserslist: 4.21.10 + acorn: 8.8.2 + acorn-import-assertions: 1.8.0_acorn@8.8.2 + browserslist: 4.21.5 chrome-trace-event: 1.0.3 enhanced-resolve: 5.15.0 es-module-lexer: 1.2.1 @@ -46707,10 +45944,11 @@ packages: loader-runner: 4.3.0 mime-types: 2.1.35 neo-async: 2.6.2 - schema-utils: 3.3.0 + schema-utils: 3.1.2 tapable: 2.2.1 - terser-webpack-plugin: 5.3.9_2pue2hesc4kyarjonhtsco4zxm + terser-webpack-plugin: 5.3.9_aka7ue4sjkoeo6uo4dlqntmpgy watchpack: 2.4.0 + webpack-cli: 5.1.4_jwpra7xq62zw3tehur2jwszlsq webpack-sources: 3.2.3 transitivePeerDependencies: - '@swc/core' @@ -46718,7 +45956,7 @@ packages: - uglify-js dev: true - /webpack/5.88.2_w67ycjwq2niq3jlxgktvf5aow4: + /webpack/5.88.2: resolution: {integrity: sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==} engines: {node: '>=10.13.0'} hasBin: true @@ -46749,9 +45987,8 @@ packages: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.9_2pue2hesc4kyarjonhtsco4zxm + terser-webpack-plugin: 5.3.9_webpack@5.88.2 watchpack: 2.4.0 - webpack-cli: 5.1.4_jwpra7xq62zw3tehur2jwszlsq webpack-sources: 3.2.3 transitivePeerDependencies: - '@swc/core' @@ -46979,7 +46216,7 @@ packages: dependencies: '@apideck/better-ajv-errors': 0.3.6_ajv@8.12.0 '@babel/core': 7.22.11 - '@babel/preset-env': 7.21.4_@babel+core@7.22.11 + '@babel/preset-env': 7.22.20_@babel+core@7.22.11 '@babel/runtime': 7.21.0 '@rollup/plugin-babel': 5.3.1_lnssqozl4dgplk3xebfs3yicbq '@rollup/plugin-node-resolve': 11.2.1_rollup@2.79.1 @@ -47102,22 +46339,6 @@ packages: - '@types/babel__core' - supports-color - /workbox-webpack-plugin/6.5.4_webpack@5.88.2: - resolution: {integrity: sha512-LmWm/zoaahe0EGmMTrSLUi+BjyR3cdGEfU3fS6PN1zKFYbqAKuQ+Oy/27e4VSXsyIwAw8+QDfk1XHNGtZu9nQg==} - engines: {node: '>=10.0.0'} - peerDependencies: - webpack: ^4.4.0 || ^5.9.0 - dependencies: - fast-json-stable-stringify: 2.1.0 - pretty-bytes: 5.6.0 - upath: 1.2.0 - webpack: 5.88.2 - webpack-sources: 1.4.3 - workbox-build: 6.5.4 - transitivePeerDependencies: - - '@types/babel__core' - - supports-color - /workbox-window/6.5.4: resolution: {integrity: sha512-HnLZJDwYBE+hpG25AQBO8RUWBJRaCsI9ksQJEp3aCOFCaG5kqaToAYXFRAHxzRluM2cQbGzdQF5rjKPWPA1fug==} dependencies: @@ -47549,8 +46770,8 @@ packages: readable-stream: 3.6.2 dev: false - /zod/3.21.4: - resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==} + /zod/3.22.4: + resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} dev: false /zone.js/0.12.0: diff --git a/providers/africas-talking/package.json b/providers/africas-talking/package.json index 1d309105880..5bf268e0251 100644 --- a/providers/africas-talking/package.json +++ b/providers/africas-talking/package.json @@ -1,6 +1,6 @@ { "name": "@novu/africas-talking", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "An Africa's Talking wrapper for Novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -34,7 +34,7 @@ "pnpm": "^7.26.0" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "africastalking": "^0.6.2" }, "devDependencies": { diff --git a/providers/apns/package.json b/providers/apns/package.json index 322e2f381f2..0d539293d49 100644 --- a/providers/apns/package.json +++ b/providers/apns/package.json @@ -1,6 +1,6 @@ { "name": "@novu/apns", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A apns wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -36,7 +36,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "@parse/node-apn": "^5.2.3" }, "devDependencies": { diff --git a/providers/burst-sms/package.json b/providers/burst-sms/package.json index 370f87c8a95..d52eafa0e13 100644 --- a/providers/burst-sms/package.json +++ b/providers/burst-sms/package.json @@ -1,6 +1,6 @@ { "name": "@novu/burst-sms", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A burstSms wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -37,7 +37,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "axios": "^1.3.3", "qs": "^6.11.0" }, diff --git a/providers/clickatell/package.json b/providers/clickatell/package.json index 9b8b1861d4e..d11e3e17845 100644 --- a/providers/clickatell/package.json +++ b/providers/clickatell/package.json @@ -1,6 +1,6 @@ { "name": "@novu/clickatell", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A clickatell SMS provider wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -31,7 +31,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "axios": "^1.3.3" }, "devDependencies": { diff --git a/providers/discord/package.json b/providers/discord/package.json index 15a6bdc4b39..e3eda6bb0fd 100644 --- a/providers/discord/package.json +++ b/providers/discord/package.json @@ -1,6 +1,6 @@ { "name": "@novu/discord", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A discord wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -32,7 +32,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "axios": "^1.3.3" }, "devDependencies": { diff --git a/providers/email-webhook/package.json b/providers/email-webhook/package.json index acad833538d..c7e428f9e81 100644 --- a/providers/email-webhook/package.json +++ b/providers/email-webhook/package.json @@ -1,6 +1,6 @@ { "name": "@novu/email-webhook", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "An email channel webhook provider wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", diff --git a/providers/emailjs/package.json b/providers/emailjs/package.json index e86b805827d..7e0027b2979 100644 --- a/providers/emailjs/package.json +++ b/providers/emailjs/package.json @@ -1,6 +1,6 @@ { "name": "@novu/emailjs", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "An emailjs provider for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -45,7 +45,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "emailjs": "^3.6.0" }, "devDependencies": { diff --git a/providers/expo/package.json b/providers/expo/package.json index 70bb32c8ded..08a2eb1c395 100644 --- a/providers/expo/package.json +++ b/providers/expo/package.json @@ -1,6 +1,6 @@ { "name": "@novu/expo", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A expo wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -32,7 +32,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "expo-server-sdk": "^3.6.0" }, "devDependencies": { diff --git a/providers/fcm/package.json b/providers/fcm/package.json index 41d8fecacd5..4e124097fb9 100644 --- a/providers/fcm/package.json +++ b/providers/fcm/package.json @@ -1,6 +1,6 @@ { "name": "@novu/fcm", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A fcm wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -32,7 +32,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "firebase-admin": "^11.10.1" }, "devDependencies": { diff --git a/providers/firetext/package.json b/providers/firetext/package.json index 56c85340d56..4e987a77b7e 100644 --- a/providers/firetext/package.json +++ b/providers/firetext/package.json @@ -1,6 +1,6 @@ { "name": "@novu/firetext", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A firetext wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -32,7 +32,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "node-fetch": "^3.2.10" }, "devDependencies": { diff --git a/providers/forty-six-elks/package.json b/providers/forty-six-elks/package.json index a9a4db2c215..cb024285c0c 100644 --- a/providers/forty-six-elks/package.json +++ b/providers/forty-six-elks/package.json @@ -1,6 +1,6 @@ { "name": "@novu/forty-six-elks", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A 46elks wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -33,7 +33,7 @@ "pnpm": "^7.26.0" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "axios": "^1.3.4" }, "devDependencies": { diff --git a/providers/gupshup/package.json b/providers/gupshup/package.json index fb1cf1eab7f..16de2e73239 100644 --- a/providers/gupshup/package.json +++ b/providers/gupshup/package.json @@ -1,6 +1,6 @@ { "name": "@novu/gupshup", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A gupshup wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -32,7 +32,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "node-fetch": "^3.2.10" }, "devDependencies": { diff --git a/providers/infobip/package.json b/providers/infobip/package.json index 3c4705daf6c..d50878c4d9c 100644 --- a/providers/infobip/package.json +++ b/providers/infobip/package.json @@ -1,6 +1,6 @@ { "name": "@novu/infobip", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A infobip wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -33,7 +33,7 @@ }, "dependencies": { "@infobip-api/sdk": "^0.2.0", - "@novu/stateless": "^0.19.0" + "@novu/stateless": "^0.20.0-alpha.0" }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", diff --git a/providers/kannel/package.json b/providers/kannel/package.json index 091f11e2d70..32e5bd09e32 100644 --- a/providers/kannel/package.json +++ b/providers/kannel/package.json @@ -1,6 +1,6 @@ { "name": "@novu/kannel", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A kannel wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -32,7 +32,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "axios": "^0.27.2" }, "devDependencies": { diff --git a/providers/mailersend/package.json b/providers/mailersend/package.json index a8043ac137a..87967d95e79 100644 --- a/providers/mailersend/package.json +++ b/providers/mailersend/package.json @@ -1,6 +1,6 @@ { "name": "@novu/mailersend", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A mailersend wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -32,7 +32,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "mailersend": "^1.3.1" }, "devDependencies": { diff --git a/providers/mailgun/package.json b/providers/mailgun/package.json index 04121153fb7..00972d34bc6 100644 --- a/providers/mailgun/package.json +++ b/providers/mailgun/package.json @@ -1,6 +1,6 @@ { "name": "@novu/mailgun", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A mailgun wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -44,7 +44,7 @@ "access": "public" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "form-data": "^4.0.0", "mailgun.js": "^8.0.1", "nock": "^13.1.3" diff --git a/providers/mailjet/package.json b/providers/mailjet/package.json index 59270cf5aa1..3488d17060c 100644 --- a/providers/mailjet/package.json +++ b/providers/mailjet/package.json @@ -1,6 +1,6 @@ { "name": "@novu/mailjet", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A mailjet wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -32,7 +32,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "node-mailjet": "^6.0.4" }, "devDependencies": { diff --git a/providers/mailtrap/.czrc b/providers/mailtrap/.czrc new file mode 100644 index 00000000000..d1bcc209ca1 --- /dev/null +++ b/providers/mailtrap/.czrc @@ -0,0 +1,3 @@ +{ + "path": "cz-conventional-changelog" +} diff --git a/providers/mailtrap/.eslintrc.json b/providers/mailtrap/.eslintrc.json new file mode 100644 index 00000000000..ec40100be69 --- /dev/null +++ b/providers/mailtrap/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "../../.eslintrc.js" +} diff --git a/providers/mailtrap/.gitignore b/providers/mailtrap/.gitignore new file mode 100644 index 00000000000..963d5292865 --- /dev/null +++ b/providers/mailtrap/.gitignore @@ -0,0 +1,9 @@ +.idea/* +.nyc_output +build +node_modules +test +src/**.js +coverage +*.log +package-lock.json diff --git a/providers/mailtrap/README.md b/providers/mailtrap/README.md new file mode 100644 index 00000000000..9280b3dd9e0 --- /dev/null +++ b/providers/mailtrap/README.md @@ -0,0 +1,13 @@ +# Novu Mailtrap Provider + +A Mailtrap email provider library for [@novu/node](https://github.com/novuhq/novu) + +## Usage + +```javascript +import { MailtrapEmailProvider } from '@novu/mailtrap'; + +const provider = new MailtrapEmailProvider({ + apiKey: process.env.MAILTRAP_API_KEY +}); +``` diff --git a/providers/mailtrap/jest.config.js b/providers/mailtrap/jest.config.js new file mode 100644 index 00000000000..61faa20934a --- /dev/null +++ b/providers/mailtrap/jest.config.js @@ -0,0 +1,8 @@ +/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + moduleNameMapper: { + axios: 'axios/dist/node/axios.cjs', + }, +}; diff --git a/providers/mailtrap/package.json b/providers/mailtrap/package.json new file mode 100644 index 00000000000..25f6732c0c4 --- /dev/null +++ b/providers/mailtrap/package.json @@ -0,0 +1,82 @@ +{ + "name": "@novu/mailtrap", + "version": "0.20.0-alpha.0", + "description": "A mailtrap wrapper for novu", + "main": "build/main/index.js", + "typings": "build/main/index.d.ts", + "module": "build/module/index.js", + "private": false, + "repository": "https://github.com/novuhq/novu", + "license": "MIT", + "keywords": [], + "scripts": { + "prebuild": "rimraf build", + "build": "run-p build:*", + "build:main": "tsc -p tsconfig.json", + "build:module": "tsc -p tsconfig.module.json", + "fix": "run-s fix:*", + "fix:prettier": "prettier \"src/**/*.ts\" --write", + "fix:lint": "eslint src --ext .ts --fix", + "test": "run-s test:*", + "lint": "eslint src --ext .ts", + "test:unit": "jest src", + "watch:build": "tsc -p tsconfig.json -w", + "watch:test": "jest src --watch", + "reset-hard": "git clean -dfx && git reset --hard && yarn", + "prepare-release": "run-s reset-hard test" + }, + "publishConfig": { + "access": "public" + }, + "engines": { + "node": ">=13.0.0 <17.0.0", + "pnpm": "^7.26.0" + }, + "dependencies": { + "@novu/stateless": "0.20.0-alpha.0", + "mailtrap": "^3.1.1" + }, + "devDependencies": { + "@istanbuljs/nyc-config-typescript": "~1.0.1", + "@types/jest": "~27.5.2", + "cspell": "~6.19.2", + "jest": "~27.5.1", + "npm-run-all": "^4.1.5", + "nyc": "~15.1.0", + "prettier": "~2.8.0", + "rimraf": "~3.0.2", + "ts-jest": "~27.1.5", + "ts-node": "~10.9.1", + "typescript": "4.9.5" + }, + "files": [ + "build/main", + "build/module", + "!**/*.spec.*", + "!**/*.json", + "CHANGELOG.md", + "LICENSE", + "README.md" + ], + "ava": { + "failFast": true, + "timeout": "60s", + "typescript": { + "rewritePaths": { + "src/": "build/main/" + } + }, + "files": [ + "!build/module/**" + ] + }, + "prettier": { + "singleQuote": true + }, + "nyc": { + "extends": "@istanbuljs/nyc-config-typescript", + "exclude": [ + "**/*.spec.js" + ] + } +} diff --git a/providers/mailtrap/src/index.ts b/providers/mailtrap/src/index.ts new file mode 100644 index 00000000000..8f0fa44883c --- /dev/null +++ b/providers/mailtrap/src/index.ts @@ -0,0 +1 @@ +export * from './lib/mailtrap.provider'; diff --git a/providers/mailtrap/src/lib/mailtrap.provider.spec.ts b/providers/mailtrap/src/lib/mailtrap.provider.spec.ts new file mode 100644 index 00000000000..c7386f2fdb1 --- /dev/null +++ b/providers/mailtrap/src/lib/mailtrap.provider.spec.ts @@ -0,0 +1,64 @@ +import { MailtrapEmailProvider } from './mailtrap.provider'; +import { MailtrapClient, SendResponse } from 'mailtrap'; +import { CheckIntegrationResponseEnum } from '@novu/stateless'; + +const mockConfig = { + apiKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', + from: 'test@test.com', +}; + +const mockNovuMessage = { + from: 'test@test.com', + to: ['test@test.com'], + html: '
Mail Content
', + subject: 'Test subject', + attachments: [ + { + mime: 'text/plain', + file: Buffer.from('test'), + name: 'test.txt', + }, + ], +}; + +const mockMailtrapResponse: SendResponse = { + success: true, + message_ids: ['0c7fd939-02cf-11ed-88c2-0a58a9feac02'], +}; + +test('should trigger mailtrap library correctly', async () => { + const provider = new MailtrapEmailProvider(mockConfig); + const spy = jest + .spyOn(provider, 'sendMessage') + .mockImplementation(async () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return {} as any; + }); + + await provider.sendMessage(mockNovuMessage); + + expect(spy).toBeCalled(); + expect(spy).toBeCalledWith({ + from: mockNovuMessage.from, + to: mockNovuMessage.to, + html: mockNovuMessage.html, + subject: mockNovuMessage.subject, + attachments: mockNovuMessage.attachments, + }); +}); + +test('should check integration successfully', async () => { + const provider = new MailtrapEmailProvider(mockConfig); + const spy = jest + .spyOn(MailtrapClient.prototype, 'send') + .mockImplementation(async () => mockMailtrapResponse); + + const messageResponse = await provider.checkIntegration(mockNovuMessage); + + expect(spy).toHaveBeenCalled(); + expect(messageResponse).toStrictEqual({ + success: true, + message: 'Integrated successfully!', + code: CheckIntegrationResponseEnum.SUCCESS, + }); +}); diff --git a/providers/mailtrap/src/lib/mailtrap.provider.ts b/providers/mailtrap/src/lib/mailtrap.provider.ts new file mode 100644 index 00000000000..1880bd87397 --- /dev/null +++ b/providers/mailtrap/src/lib/mailtrap.provider.ts @@ -0,0 +1,78 @@ +import { + ChannelTypeEnum, + ISendMessageSuccessResponse, + IEmailOptions, + IEmailProvider, + ICheckIntegrationResponse, + CheckIntegrationResponseEnum, +} from '@novu/stateless'; +import { MailtrapClient, Address } from 'mailtrap'; + +export class MailtrapEmailProvider implements IEmailProvider { + id = 'mailtrap'; + channelType = ChannelTypeEnum.EMAIL as ChannelTypeEnum.EMAIL; + private readonly mailtrapClient: MailtrapClient; + + constructor( + private config: { + apiKey: string; + from: string; + } + ) { + this.mailtrapClient = new MailtrapClient({ + token: config.apiKey, + }); + } + + async checkIntegration( + options: IEmailOptions + ): Promise { + try { + const result = await this.sendWithMailtrap(options); + + return { + success: result.success, + message: 'Integrated successfully!', + code: CheckIntegrationResponseEnum.SUCCESS, + }; + } catch (error) { + return { + success: false, + message: error?.message || 'Integration check failed.', + code: CheckIntegrationResponseEnum.FAILED, + }; + } + } + + async sendMessage( + options: IEmailOptions + ): Promise { + const response = await this.sendWithMailtrap(options); + + return { + id: response.message_ids[0], + date: new Date().toISOString(), + }; + } + + private sendWithMailtrap(options: IEmailOptions) { + return this.mailtrapClient.send({ + to: options.to.map(this.mapAddress), + from: this.mapAddress(options.from || this.config.from), + subject: options.subject, + text: options.text, + html: options.html, + bcc: options.bcc?.map(this.mapAddress), + cc: options.cc?.map(this.mapAddress), + attachments: options.attachments?.map((attachment) => ({ + filename: attachment.name, + content: attachment.file, + type: attachment.mime, + })), + }); + } + + private mapAddress(email: string): Address { + return { email }; + } +} diff --git a/providers/mailtrap/tsconfig.json b/providers/mailtrap/tsconfig.json new file mode 100644 index 00000000000..5b8120fea36 --- /dev/null +++ b/providers/mailtrap/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "build/main", + "rootDir": "src", + "types": ["node", "jest"] + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules/**"] +} diff --git a/providers/mailtrap/tsconfig.module.json b/providers/mailtrap/tsconfig.module.json new file mode 100644 index 00000000000..79be3a5c40b --- /dev/null +++ b/providers/mailtrap/tsconfig.module.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig", + "compilerOptions": { + "target": "esnext", + "outDir": "build/module", + "module": "esnext" + }, + "exclude": ["node_modules/**"] +} diff --git a/providers/mandrill/package.json b/providers/mandrill/package.json index 31d252461f9..46fbcc2fd6b 100644 --- a/providers/mandrill/package.json +++ b/providers/mandrill/package.json @@ -1,6 +1,6 @@ { "name": "@novu/mandrill", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A mandrill wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -42,7 +42,7 @@ }, "dependencies": { "@mailchimp/mailchimp_transactional": "^1.0.46", - "@novu/stateless": "^0.19.0" + "@novu/stateless": "^0.20.0-alpha.0" }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "1.0.2", diff --git a/providers/maqsam/package.json b/providers/maqsam/package.json index 87fce89928b..939fc363a42 100644 --- a/providers/maqsam/package.json +++ b/providers/maqsam/package.json @@ -1,6 +1,6 @@ { "name": "@novu/maqsam", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A maqsam wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -33,7 +33,7 @@ "pnpm": "^7.26.0" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "axios": "^1.3.4", "date-fns": "2.29.3", "moment": "^2.29.4" diff --git a/providers/mattermost/package.json b/providers/mattermost/package.json index 72184969a98..bb072b30ca3 100644 --- a/providers/mattermost/package.json +++ b/providers/mattermost/package.json @@ -1,6 +1,6 @@ { "name": "@novu/mattermost", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A mattermost wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -33,7 +33,7 @@ "pnpm": "^7.26.0" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "axios": "^1.3.3" }, "devDependencies": { diff --git a/providers/ms-teams/package.json b/providers/ms-teams/package.json index a743ce7c003..d0f5b932248 100644 --- a/providers/ms-teams/package.json +++ b/providers/ms-teams/package.json @@ -1,6 +1,6 @@ { "name": "@novu/ms-teams", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A MS-Teams wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", diff --git a/providers/netcore/package.json b/providers/netcore/package.json index 128ca8c8eae..8d6a6d08d71 100644 --- a/providers/netcore/package.json +++ b/providers/netcore/package.json @@ -1,6 +1,6 @@ { "name": "@novu/netcore", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A netcore wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -45,7 +45,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "pepipost": "^5.0.0" }, "devDependencies": { diff --git a/providers/nexmo/package.json b/providers/nexmo/package.json index 7e81bb67369..b06c49cbfa0 100644 --- a/providers/nexmo/package.json +++ b/providers/nexmo/package.json @@ -1,6 +1,6 @@ { "name": "@novu/nexmo", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A nexmo wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -32,7 +32,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "@vonage/server-sdk": "^2.10.10" }, "devDependencies": { diff --git a/providers/nodemailer/package.json b/providers/nodemailer/package.json index 2021ca2c435..216785c8e0b 100644 --- a/providers/nodemailer/package.json +++ b/providers/nodemailer/package.json @@ -1,6 +1,6 @@ { "name": "@novu/nodemailer", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A nodemailer wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -45,7 +45,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "nodemailer": "^6.6.5" }, "devDependencies": { diff --git a/providers/nodemailer/src/lib/nodemailer.provider.spec.ts b/providers/nodemailer/src/lib/nodemailer.provider.spec.ts index 082f51037ed..ddd50218a2b 100644 --- a/providers/nodemailer/src/lib/nodemailer.provider.spec.ts +++ b/providers/nodemailer/src/lib/nodemailer.provider.spec.ts @@ -44,6 +44,7 @@ describe('Config is set to secure=false but not user and password set', () => { expect(nodemailer.createTransport).toHaveBeenCalled(); expect(nodemailer.createTransport).toHaveBeenCalledWith({ + name: config.host, host: config.host, port: config.port, secure: config.secure, @@ -95,6 +96,7 @@ describe('Config is set to secure=false (default; TLS used if server supports ST expect(nodemailer.createTransport).toHaveBeenCalled(); expect(nodemailer.createTransport).toHaveBeenCalledWith({ + name: mockConfig.host, host: mockConfig.host, port: mockConfig.port, secure: mockConfig.secure, diff --git a/providers/nodemailer/src/lib/nodemailer.provider.ts b/providers/nodemailer/src/lib/nodemailer.provider.ts index 7c52a221827..0d929257159 100644 --- a/providers/nodemailer/src/lib/nodemailer.provider.ts +++ b/providers/nodemailer/src/lib/nodemailer.provider.ts @@ -44,6 +44,7 @@ export class NodemailerProvider implements IEmailProvider { const tls: ConnectionOptions = this.getTlsOptions(); const smtpTransportOptions: SMTPTransport.Options = { + name: this.config.host, host: this.config.host, port: this.config.port, secure: this.config.secure, diff --git a/providers/one-signal/package.json b/providers/one-signal/package.json index 81a38f9a2cf..5399541be66 100644 --- a/providers/one-signal/package.json +++ b/providers/one-signal/package.json @@ -1,6 +1,6 @@ { "name": "@novu/one-signal", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A OneSignal wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -34,7 +34,7 @@ "pnpm": "^7.26.0" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "onesignal-node": "^3.4.0" }, "devDependencies": { diff --git a/providers/outlook365/package.json b/providers/outlook365/package.json index a3cfd739b8e..29bb8e2ba7a 100644 --- a/providers/outlook365/package.json +++ b/providers/outlook365/package.json @@ -1,6 +1,6 @@ { "name": "@novu/outlook365", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A outlook365 wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -32,12 +32,13 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "nodemailer": "^6.6.5" }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", "@types/jest": "^29.5.0", + "@types/nodemailer": "^6.4.11", "codecov": "^3.5.0", "cspell": "^4.1.0", "gh-pages": "^3.1.0", diff --git a/providers/outlook365/src/lib/outlook365.provider.ts b/providers/outlook365/src/lib/outlook365.provider.ts index e5eca88fb66..36da19f76c2 100644 --- a/providers/outlook365/src/lib/outlook365.provider.ts +++ b/providers/outlook365/src/lib/outlook365.provider.ts @@ -24,7 +24,7 @@ export class Outlook365Provider implements IEmailProvider { host: 'smtp.office365.com', port: 587, requireTLS: true, - connectionTImeout: 30000, + connectionTimeout: 30000, auth: { user: this.config.from, pass: this.config.password, diff --git a/providers/plivo/package.json b/providers/plivo/package.json index ecdcc4ed78d..ff7d82ce7cd 100644 --- a/providers/plivo/package.json +++ b/providers/plivo/package.json @@ -1,6 +1,6 @@ { "name": "@novu/plivo", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A plivo wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -44,7 +44,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "plivo": "^4.22.4" }, "devDependencies": { diff --git a/providers/plunk/package.json b/providers/plunk/package.json index 0cbf2a42b90..1a3493fa17c 100644 --- a/providers/plunk/package.json +++ b/providers/plunk/package.json @@ -1,6 +1,6 @@ { "name": "@novu/plunk", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A plunk wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -33,7 +33,7 @@ "pnpm": "^7.26.0" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "@plunk/node": "2.0.0" }, "devDependencies": { diff --git a/providers/postmark/package.json b/providers/postmark/package.json index e5d6a2f31f2..03a3aec4268 100644 --- a/providers/postmark/package.json +++ b/providers/postmark/package.json @@ -1,6 +1,6 @@ { "name": "@novu/postmark", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A postmark wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -45,7 +45,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "axios": "^1.3.6", "postmark": "^2.7.8" }, diff --git a/providers/push-webhook/package.json b/providers/push-webhook/package.json index 626d75b315b..5278eb91677 100644 --- a/providers/push-webhook/package.json +++ b/providers/push-webhook/package.json @@ -1,6 +1,6 @@ { "name": "@novu/push-webhook", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A push-webhook wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -34,7 +34,7 @@ "pnpm": "^7.26.0" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "axios": "^1.3.5" }, "devDependencies": { diff --git a/providers/resend/package.json b/providers/resend/package.json index 7686b1838e4..8f2a56c7730 100644 --- a/providers/resend/package.json +++ b/providers/resend/package.json @@ -1,6 +1,6 @@ { "name": "@novu/resend", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A resend wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -32,7 +32,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "resend": "^0.11.0" }, "devDependencies": { diff --git a/providers/resend/src/lib/resend.provider.spec.ts b/providers/resend/src/lib/resend.provider.spec.ts index 8e70b07088c..27b05cb95f8 100644 --- a/providers/resend/src/lib/resend.provider.spec.ts +++ b/providers/resend/src/lib/resend.provider.spec.ts @@ -1,5 +1,5 @@ import { ResendEmailProvider } from './resend.provider'; - +import { Resend } from 'resend'; const mockConfig = { apiKey: 'this-api-key-from-resend', from: 'test@test.com', @@ -39,3 +39,34 @@ test('should trigger resend library correctly', async () => { attachments: mockNovuMessage.attachments, }); }); + +test('should trigger resend email with From Name', async () => { + const mockConfigWithSenderName = { + ...mockConfig, + senderName: 'Test User', + }; + + const provider = new ResendEmailProvider(mockConfigWithSenderName); + const spy = jest + .spyOn(Resend.prototype, 'sendEmail') + .mockImplementation(async () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return {} as any; + }); + + await provider.sendMessage(mockNovuMessage); + + expect(spy).toHaveBeenCalled(); + expect(spy).toHaveBeenCalledWith({ + from: `${mockConfigWithSenderName.senderName} <${mockNovuMessage.from}>`, + to: mockNovuMessage.to, + html: mockNovuMessage.html, + subject: mockNovuMessage.subject, + attachments: mockNovuMessage.attachments.map((attachment) => ({ + filename: attachment?.name, + content: attachment.file, + })), + cc: undefined, + bcc: undefined, + }); +}); diff --git a/providers/resend/src/lib/resend.provider.ts b/providers/resend/src/lib/resend.provider.ts index b8e7823f237..49f4fed42e2 100644 --- a/providers/resend/src/lib/resend.provider.ts +++ b/providers/resend/src/lib/resend.provider.ts @@ -17,6 +17,7 @@ export class ResendEmailProvider implements IEmailProvider { private config: { apiKey: string; from: string; + senderName?: string; } ) { this.resendClient = new Resend(this.config.apiKey); @@ -25,8 +26,11 @@ export class ResendEmailProvider implements IEmailProvider { async sendMessage( options: IEmailOptions ): Promise { + const senderName = this.config?.senderName; + const fromAddress = options.from || this.config.from; + const response: any = await this.resendClient.sendEmail({ - from: options.from || this.config.from, + from: senderName ? `${senderName} <${fromAddress}>` : fromAddress, to: options.to, subject: options.subject, text: options.text, diff --git a/providers/sendchamp/package.json b/providers/sendchamp/package.json index ca84ca8fdfc..e506a48789b 100644 --- a/providers/sendchamp/package.json +++ b/providers/sendchamp/package.json @@ -1,6 +1,6 @@ { "name": "@novu/sendchamp", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A sendchamp wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -33,7 +33,7 @@ "pnpm": "^7.26.0" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "axios": "^1.4.0" }, "devDependencies": { diff --git a/providers/sendgrid/package.json b/providers/sendgrid/package.json index 1f5da967e6b..3c7b8a6c6c8 100644 --- a/providers/sendgrid/package.json +++ b/providers/sendgrid/package.json @@ -1,6 +1,6 @@ { "name": "@novu/sendgrid", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A sendgrid wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -45,7 +45,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "@sendgrid/mail": "^7.4.6" }, "devDependencies": { diff --git a/providers/sendgrid/src/lib/sendgrid.provider.spec.ts b/providers/sendgrid/src/lib/sendgrid.provider.spec.ts index ebad0ec3edd..0b60953acb5 100644 --- a/providers/sendgrid/src/lib/sendgrid.provider.spec.ts +++ b/providers/sendgrid/src/lib/sendgrid.provider.spec.ts @@ -58,6 +58,19 @@ test('should trigger sendgrid correctly', async () => { novuTransactionId: undefined, novuWorkflowIdentifier: undefined, }, + personalizations: [ + { + to: [ + { + email: mockNovuMessage.to[0], + }, + ], + cc: undefined, + bcc: undefined, + dynamicTemplateData: undefined, + }, + ], + templateId: undefined, }); }); diff --git a/providers/sendgrid/src/lib/sendgrid.provider.ts b/providers/sendgrid/src/lib/sendgrid.provider.ts index f74203f12d4..acaa71ec49d 100644 --- a/providers/sendgrid/src/lib/sendgrid.provider.ts +++ b/providers/sendgrid/src/lib/sendgrid.provider.ts @@ -65,6 +65,15 @@ export class SendgridEmailProvider implements IEmailProvider { } private createMailData(options: IEmailOptions) { + const dynamicTemplateData = options.customData?.dynamicTemplateData; + const templateId = options.customData?.templateId as unknown as string; + /* + * deleted below values from customData to avoid passing them + * in customArgs because customArgs has max limit of 10,000 bytes + */ + delete options.customData?.dynamicTemplateData; + delete options.customData?.templateId; + const mailData: Partial = { from: { email: options.from || this.config.from, @@ -93,6 +102,15 @@ export class SendgridEmailProvider implements IEmailProvider { type: attachment.mime, }; }), + personalizations: [ + { + to: options.to.map((email) => ({ email })), + cc: options.cc?.map((ccItem) => ({ email: ccItem })), + bcc: options.bcc?.map((bccItem) => ({ email: bccItem })), + dynamicTemplateData: dynamicTemplateData, + }, + ], + templateId: templateId, }; if (options.replyTo) { diff --git a/providers/sendinblue/package.json b/providers/sendinblue/package.json index 74c64a7073f..07c7b8bf375 100644 --- a/providers/sendinblue/package.json +++ b/providers/sendinblue/package.json @@ -1,6 +1,6 @@ { "name": "@novu/sendinblue", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A sendinblue wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -32,7 +32,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "@sendinblue/client": "^3.0.1" }, "devDependencies": { diff --git a/providers/ses/package.json b/providers/ses/package.json index d976f97fe80..a5bbc189caf 100644 --- a/providers/ses/package.json +++ b/providers/ses/package.json @@ -1,6 +1,6 @@ { "name": "@novu/ses", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A ses wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -33,7 +33,7 @@ }, "dependencies": { "@aws-sdk/client-ses": "3.382.0", - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "nodemailer": "^6.6.5" }, "devDependencies": { diff --git a/providers/slack/package.json b/providers/slack/package.json index f6f4965b7ed..d734d58a109 100644 --- a/providers/slack/package.json +++ b/providers/slack/package.json @@ -1,6 +1,6 @@ { "name": "@novu/slack", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A slack wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -32,7 +32,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "axios": "^1.3.3" }, "devDependencies": { diff --git a/providers/sms-central/package.json b/providers/sms-central/package.json index fb9e80dd2d1..c89b91e28e0 100644 --- a/providers/sms-central/package.json +++ b/providers/sms-central/package.json @@ -1,6 +1,6 @@ { "name": "@novu/sms-central", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A sms-central wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", diff --git a/providers/sms77/package.json b/providers/sms77/package.json index 1c189002aa4..a1b81954906 100644 --- a/providers/sms77/package.json +++ b/providers/sms77/package.json @@ -1,6 +1,6 @@ { "name": "@novu/sms77", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A sms77 wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -32,7 +32,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "node-fetch": "^2.6.7", "sms77-client": "^2.14.0" }, diff --git a/providers/sns/package.json b/providers/sns/package.json index f6be0962da7..bec123b17de 100644 --- a/providers/sns/package.json +++ b/providers/sns/package.json @@ -1,6 +1,6 @@ { "name": "@novu/sns", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A sns wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -33,7 +33,7 @@ }, "dependencies": { "@aws-sdk/client-sns": "^3.382.0", - "@novu/stateless": "^0.19.0" + "@novu/stateless": "^0.20.0-alpha.0" }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", diff --git a/providers/sparkpost/package.json b/providers/sparkpost/package.json index 01729ec4dee..35d82a46fbf 100644 --- a/providers/sparkpost/package.json +++ b/providers/sparkpost/package.json @@ -1,6 +1,6 @@ { "name": "@novu/sparkpost", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A sparkpost wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -32,7 +32,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "sparkpost": "^2.1.4" }, "devDependencies": { diff --git a/providers/telnyx/package.json b/providers/telnyx/package.json index c14e580093b..b95b2429956 100644 --- a/providers/telnyx/package.json +++ b/providers/telnyx/package.json @@ -1,6 +1,6 @@ { "name": "@novu/telnyx", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A telnyx wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -32,7 +32,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "telnyx": "^1.23.0" }, "devDependencies": { diff --git a/providers/termii/package.json b/providers/termii/package.json index 6b73d023051..938d45fd752 100644 --- a/providers/termii/package.json +++ b/providers/termii/package.json @@ -1,6 +1,6 @@ { "name": "@novu/termii", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A termii wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -32,7 +32,7 @@ "node": ">=10" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "node-fetch": "^3.2.10" }, "devDependencies": { diff --git a/providers/twilio/package.json b/providers/twilio/package.json index 789dc690783..4bbc18c5f28 100644 --- a/providers/twilio/package.json +++ b/providers/twilio/package.json @@ -1,6 +1,6 @@ { "name": "@novu/twilio", - "version": "0.19.0", + "version": "0.20.0-alpha.0", "description": "A twilio wrapper for novu", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -44,7 +44,7 @@ "access": "public" }, "dependencies": { - "@novu/stateless": "^0.19.0", + "@novu/stateless": "^0.20.0-alpha.0", "twilio": "^4.14.1" }, "devDependencies": {