From 0238e2baec1a73bc848bdee997296939ea47f91c Mon Sep 17 00:00:00 2001 From: Richard Fontein <32132657+rifont@users.noreply.github.com> Date: Thu, 7 Nov 2024 10:48:15 +0100 Subject: [PATCH 01/29] feat(framework): Add support for specifying mock results (#6878) --- packages/framework/src/client.test.ts | 156 ++++++++++++++++++++++++++ packages/framework/src/client.ts | 23 +++- 2 files changed, 177 insertions(+), 2 deletions(-) diff --git a/packages/framework/src/client.test.ts b/packages/framework/src/client.test.ts index cb7a7fa78e4..4892340afc0 100644 --- a/packages/framework/src/client.test.ts +++ b/packages/framework/src/client.test.ts @@ -4,6 +4,7 @@ import { Client } from './client'; import { ExecutionEventPayloadInvalidError, ExecutionStateCorruptError, + ExecutionStateResultInvalidError, ProviderExecutionFailedError, StepExecutionFailedError, StepNotFoundError, @@ -1472,6 +1473,161 @@ describe('Novu Client', () => { expect(metadata.duration).toEqual(expect.any(Number)); }); + it('should use the provided state to mock non previewed step outputs', async () => { + const newWorkflow = workflow( + 'test-workflow', + async ({ step }) => { + const digestOutput = await step.digest('digest-output', async () => ({ + type: 'regular', + amount: 1, + unit: 'seconds', + })); + + await step.inApp( + 'send-email', + async () => ({ + body: digestOutput.events.map((event) => event.payload.comment).join(','), + }), + { + skip: () => true, + } + ); + }, + { + payloadSchema: { + type: 'object', + properties: { + comment: { type: 'string' }, + }, + required: ['comment'], + } as const, + } + ); + + client.addWorkflows([newWorkflow]); + + const event: Event = { + action: PostActionEnum.PREVIEW, + workflowId: 'test-workflow', + stepId: 'send-email', + subscriber: {}, + state: [ + { + stepId: 'digest-output', + state: { + status: 'success', + }, + outputs: { + events: [ + { + id: '1', + time: '2024-01-01T00:00:00.000Z', + payload: { + comment: 'Hello', + }, + }, + { + id: '2', + time: '2024-01-01T00:00:00.000Z', + payload: { + comment: 'World', + }, + }, + ], + }, + }, + ], + payload: {}, + controls: {}, + }; + + const executionResult = await client.executeWorkflow(event); + + expect(executionResult).toBeDefined(); + expect(executionResult.outputs).toBeDefined(); + if (!executionResult.outputs) throw new Error('executionResult.outputs is undefined'); + + const { body } = executionResult.outputs; + expect(body).toBe('Hello,World'); + + expect(executionResult.providers).toEqual({}); + + const { metadata } = executionResult; + expect(metadata.status).toBe('success'); + expect(metadata.error).toBe(false); + expect(metadata.duration).toEqual(expect.any(Number)); + }); + + it('should throw an error when the provided preview state is invalid', async () => { + const newWorkflow = workflow( + 'test-workflow', + async ({ step }) => { + const digestOutput = await step.digest('digest-output', async () => ({ + type: 'regular', + amount: 1, + unit: 'seconds', + })); + + await step.inApp( + 'send-email', + async () => ({ + body: digestOutput.events.map((event) => event.payload.comment).join(','), + }), + { + skip: () => true, + } + ); + }, + { + payloadSchema: { + type: 'object', + properties: { + comment: { type: 'string' }, + }, + required: ['comment'], + } as const, + } + ); + + client.addWorkflows([newWorkflow]); + + const event: Event = { + action: PostActionEnum.PREVIEW, + workflowId: 'test-workflow', + stepId: 'send-email', + subscriber: {}, + state: [ + { + stepId: 'digest-output', + state: { + status: 'success', + }, + outputs: { + events: [ + { + time: '2024-01-01T00:00:00.000Z', + payload: { + comment: 'Hello', + }, + }, + { + id: '2', + time: '2024-01-01T00:00:00.000Z', + payload: { + comment: 'World', + }, + }, + ], + }, + }, + ], + payload: {}, + controls: {}, + }; + + await expect(client.executeWorkflow(event)).rejects.toThrow(ExecutionStateResultInvalidError); + }); + it('should throw an error when workflow ID is invalid', async () => { // non-existing workflow ID const event: Event = { diff --git a/packages/framework/src/client.ts b/packages/framework/src/client.ts index 2643ab14903..5fe458cfe64 100644 --- a/packages/framework/src/client.ts +++ b/packages/framework/src/client.ts @@ -31,6 +31,7 @@ import type { HealthCheck, Schema, Skip, + State, ValidationError, Workflow, } from './types'; @@ -634,7 +635,7 @@ export class Client { } } else { try { - const result = event.state.find((state) => state.stepId === step.stepId); + const result = this.getStepState(event, step.stepId); if (result) { const validatedOutput = await this.validate( @@ -723,7 +724,21 @@ export class Client { providers: await this.executeProviders(event, step, validatedOutput), }; } else { - const mockResult = this.mock(step.results.schema); + let mockResult: Record; + const suppliedResult = this.getStepState(event, step.stepId); + + if (suppliedResult) { + mockResult = await this.validate( + suppliedResult.outputs, + step.results.unknownSchema, + 'step', + 'result', + event.workflowId, + step.stepId + ); + } else { + mockResult = this.mock(step.results.schema); + } console.log(` ${EMOJI.MOCK} Mocked stepId: \`${step.stepId}\``); @@ -743,6 +758,10 @@ export class Client { } } + private getStepState(event: Event, stepId: string): State | undefined { + return event.state.find((state) => state.stepId === stepId); + } + private getStepCode(workflowId: string, stepId: string): CodeResult { const step = this.getStep(workflowId, stepId); From f6ed024f9b15e6e1612bc3f56aa561329e1b4345 Mon Sep 17 00:00:00 2001 From: Richard Fontein <32132657+rifont@users.noreply.github.com> Date: Thu, 7 Nov 2024 11:19:51 +0100 Subject: [PATCH 02/29] fix(framework): Stop validating controls for non previewed step (#6876) --- packages/framework/src/client.test.ts | 69 ++++++++++++++++++++++++++- packages/framework/src/client.ts | 24 +++++----- 2 files changed, 81 insertions(+), 12 deletions(-) diff --git a/packages/framework/src/client.test.ts b/packages/framework/src/client.test.ts index 4892340afc0..679fd7f29ee 100644 --- a/packages/framework/src/client.test.ts +++ b/packages/framework/src/client.test.ts @@ -1351,7 +1351,15 @@ describe('Novu Client', () => { workflowId: 'test-workflow', stepId: 'active-step-id', subscriber: {}, - state: [], + state: [ + { + stepId: 'skipped-step-id', + outputs: {}, + state: { + status: 'success', + }, + }, + ], payload: {}, controls: {}, }; @@ -1434,6 +1442,65 @@ describe('Novu Client', () => { expect(metadata.duration).toEqual(expect.any(Number)); }); + it('should preview a non-first step in a workflow successfully when action is preview', async () => { + const newWorkflow = workflow('test-workflow', async ({ step }) => { + await step.delay( + 'delay-step', + async (controls) => ({ + amount: controls.amount, + unit: controls.unit, + }), + { + controlSchema: { + type: 'object', + properties: { + amount: { type: 'number' }, + unit: { + type: 'string', + enum: ['seconds', 'minutes', 'hours', 'days', 'weeks', 'months'], + }, + }, + required: ['amount', 'unit'], + additionalProperties: false, + } as const, + } + ); + + await step.inApp('send-in-app', async () => ({ body: 'Test Body', subject: 'Subject' })); + }); + + client.addWorkflows([newWorkflow]); + + const event: Event = { + action: PostActionEnum.PREVIEW, + workflowId: 'test-workflow', + stepId: 'send-in-app', + subscriber: {}, + state: [], + payload: {}, + controls: {}, + }; + + const executionResult = await client.executeWorkflow(event); + + expect(executionResult).toBeDefined(); + expect(executionResult.outputs).toBeDefined(); + if (!executionResult.outputs) throw new Error('executionResult.outputs is undefined'); + + const { body } = executionResult.outputs; + expect(body).toBe('Test Body'); + + const { subject } = executionResult.outputs; + expect(subject).toBe('Subject'); + + expect(executionResult.providers).toEqual({}); + + const { metadata } = executionResult; + expect(metadata.status).toBe('success'); + expect(metadata.error).toBe(false); + expect(metadata.duration).toEqual(expect.any(Number)); + }); + it('should preview workflow successfully when action is preview and skipped', async () => { const newWorkflow = workflow('test-workflow', async ({ step }) => { await step.email('send-email', async () => ({ body: 'Test Body', subject: 'Subject' }), { diff --git a/packages/framework/src/client.ts b/packages/framework/src/client.ts index 5fe458cfe64..ebd0ce6a4a4 100644 --- a/packages/framework/src/client.ts +++ b/packages/framework/src/client.ts @@ -278,25 +278,27 @@ export class Client { } const step = this.getStep(event.workflowId, stepId); - const controls = await this.createStepControls(step, event); const isPreview = event.action === PostActionEnum.PREVIEW; - if (!isPreview && (await this.shouldSkip(options?.skip as typeof step.options.skip, controls))) { - if (stepId === event.stepId) { - // Only set the result when the step is the current step. + // Only evaluate a skip condition when the step is the current step and not in preview mode. + if (!isPreview && stepId === event.stepId) { + const controls = await this.createStepControls(step, event); + const shouldSkip = await this.shouldSkip(options?.skip as typeof step.options.skip, controls); + + if (shouldSkip) { setResult({ options: { skip: true }, outputs: {}, providers: {}, }); - } - /* - * Return an empty object for results when a step is skipped. - * TODO: fix typings when `skip` is specified to return `Partial` - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return {} as any; + /* + * Return an empty object for results when a step is skipped. + * TODO: fix typings when `skip` is specified to return `Partial` + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return {} as any; + } } const previewStepHandler = this.previewStep.bind(this); From a2d727062e719f79e7b06b4e976498bef7a7f235 Mon Sep 17 00:00:00 2001 From: George Djabarov <39195835+djabarovgeorge@users.noreply.github.com> Date: Thu, 7 Nov 2024 12:45:13 +0200 Subject: [PATCH 03/29] refactor(api): new test-data endpoint to pass dynamic data (#6871) Co-authored-by: GalT <39020298+tatarco@users.noreply.github.com> --- .../shared/build-string-schema.ts | 20 ++++ .../get-step-schema/get-step-data.usecase.ts | 24 +--- .../usecases/test-data/test-data.usecase.ts | 108 ++++++++++++------ .../workflows-v2/workflow.controller.e2e.ts | 76 ++++++++++++ .../shared/src/clients/workflows-client.ts | 1 + .../src/dto/workflows/create-workflow-dto.ts | 1 - 6 files changed, 170 insertions(+), 60 deletions(-) create mode 100644 apps/api/src/app/workflows-v2/shared/build-string-schema.ts diff --git a/apps/api/src/app/workflows-v2/shared/build-string-schema.ts b/apps/api/src/app/workflows-v2/shared/build-string-schema.ts new file mode 100644 index 00000000000..92d413018a0 --- /dev/null +++ b/apps/api/src/app/workflows-v2/shared/build-string-schema.ts @@ -0,0 +1,20 @@ +import { JSONSchema } from 'json-schema-to-ts'; + +/** + * Builds a JSON schema object where each variable becomes a string property. + */ +export function buildJSONSchema(variables: Record): JSONSchema { + const properties: Record = {}; + + for (const [variableKey, variableValue] of Object.entries(variables)) { + properties[variableKey] = { + type: 'string', + default: variableValue, + }; + } + + return { + type: 'object', + properties, + }; +} diff --git a/apps/api/src/app/workflows-v2/usecases/get-step-schema/get-step-data.usecase.ts b/apps/api/src/app/workflows-v2/usecases/get-step-schema/get-step-data.usecase.ts index e4f731acab7..9d8b67bb501 100644 --- a/apps/api/src/app/workflows-v2/usecases/get-step-schema/get-step-data.usecase.ts +++ b/apps/api/src/app/workflows-v2/usecases/get-step-schema/get-step-data.usecase.ts @@ -7,6 +7,7 @@ import { mapStepTypeToResult } from '../../shared'; import { GetWorkflowByIdsUseCase } from '../get-workflow-by-ids/get-workflow-by-ids.usecase'; import { InvalidStepException } from '../../exceptions/invalid-step.exception'; import { BuildDefaultPayloadUseCase } from '../build-payload-from-placeholder'; +import { buildJSONSchema } from '../../shared/build-string-schema'; @Injectable() export class GetStepDataUsecase { @@ -39,12 +40,12 @@ export class GetStepDataUsecase { }; } - private buildPayloadSchema(controlValues: Record) { + private buildPayloadSchema(controlValues: Record) { const payloadVariables = this.buildDefaultPayloadUseCase.execute({ controlValues, }).previewPayload.payload; - return buildStringSchema(payloadVariables || {}); + return buildJSONSchema(payloadVariables || {}); } private async fetchWorkflow(command: GetStepDataCommand) { @@ -158,22 +159,3 @@ function buildPreviousStepsSchema(previousSteps: NotificationStepEntity[] | unde description: 'Previous Steps Results', } as const satisfies JSONSchema; } - -/** - * Builds a JSON schema object where each variable becomes a string property. - */ -function buildStringSchema(variables: Record): JSONSchema { - const properties: Record = {}; - - for (const [variableKey, variableValue] of Object.entries(variables)) { - properties[variableKey] = { - type: 'string', - default: variableValue, - }; - } - - return { - type: 'object', - properties, - }; -} diff --git a/apps/api/src/app/workflows-v2/usecases/test-data/test-data.usecase.ts b/apps/api/src/app/workflows-v2/usecases/test-data/test-data.usecase.ts index bf1e5d8f583..b27bc27a002 100644 --- a/apps/api/src/app/workflows-v2/usecases/test-data/test-data.usecase.ts +++ b/apps/api/src/app/workflows-v2/usecases/test-data/test-data.usecase.ts @@ -1,57 +1,89 @@ import { JSONSchema } from 'json-schema-to-ts'; import { Injectable } from '@nestjs/common'; -import { NotificationTemplateEntity } from '@novu/dal'; -import { UserSessionData, WorkflowTestDataResponseDto } from '@novu/shared'; +import { ControlValuesRepository, NotificationStepEntity, NotificationTemplateEntity } from '@novu/dal'; +import { ControlValuesLevelEnum, StepTypeEnum, UserSessionData, WorkflowTestDataResponseDto } from '@novu/shared'; import { WorkflowTestDataCommand } from './test-data.command'; import { GetWorkflowByIdsUseCase } from '../get-workflow-by-ids/get-workflow-by-ids.usecase'; import { GetWorkflowByIdsCommand } from '../get-workflow-by-ids/get-workflow-by-ids.command'; - -const buildToFieldSchema = ({ user }: { user: UserSessionData }) => - ({ - type: 'object', - properties: { - subscriberId: { type: 'string', default: user._id }, - /* - * TODO: the email and phone fields should be dynamic based on the workflow steps - * if the workflow has has an email step, then email is required etc - */ - email: { type: 'string', default: user.email ?? '', format: 'email' }, - phone: { type: 'string', default: '' }, - }, - required: ['subscriberId', 'email', 'phone'], - additionalProperties: false, - }) as const satisfies JSONSchema; - -const buildPayloadSchema = () => - ({ - type: 'object', - description: 'Schema representing the workflow payload', - properties: { - /* - * TODO: the properties should be dynamic based on the workflow variables - */ - example: { type: 'string', description: 'Example field', default: 'payload.example' }, - }, - required: ['subscriberId', 'email', 'phone'], - additionalProperties: false, - }) as const satisfies JSONSchema; +import { BuildDefaultPayloadUseCase } from '../build-payload-from-placeholder'; +import { buildJSONSchema } from '../../shared/build-string-schema'; @Injectable() export class WorkflowTestDataUseCase { - constructor(private getWorkflowByIdsUseCase: GetWorkflowByIdsUseCase) {} + constructor( + private getWorkflowByIdsUseCase: GetWorkflowByIdsUseCase, + private controlValuesRepository: ControlValuesRepository, + private buildDefaultPayloadUseCase: BuildDefaultPayloadUseCase + ) {} async execute(command: WorkflowTestDataCommand): Promise { - const _workflowEntity: NotificationTemplateEntity | null = await this.getWorkflowByIdsUseCase.execute( + const _workflowEntity: NotificationTemplateEntity = await this.fetchWorkflow(command); + const toSchema = buildToFieldSchema({ user: command.user, steps: _workflowEntity.steps }); + const payloadSchema = await this.buildPayloadSchema(command, _workflowEntity); + + return { + to: toSchema, + payload: payloadSchema, + }; + } + + private async fetchWorkflow(command: WorkflowTestDataCommand): Promise { + return await this.getWorkflowByIdsUseCase.execute( GetWorkflowByIdsCommand.create({ ...command, identifierOrInternalId: command.identifierOrInternalId, }) ); + } - return { - to: buildToFieldSchema({ user: command.user }), - payload: buildPayloadSchema(), - }; + private async buildPayloadSchema(command: WorkflowTestDataCommand, _workflowEntity: NotificationTemplateEntity) { + let payloadVariables: Record = {}; + for (const step of _workflowEntity.steps) { + const newValues = await this.getValues(command.user, step._templateId, _workflowEntity._id); + + /* + * we need to build the payload defaults for each step, + * because of possible duplicated values (like subject, body, etc...) + */ + const currPayloadVariables = this.buildDefaultPayloadUseCase.execute({ + controlValues: newValues, + }).previewPayload.payload; + payloadVariables = { ...payloadVariables, ...currPayloadVariables }; + } + + return buildJSONSchema(payloadVariables || {}); + } + + private async getValues(user: UserSessionData, _stepId: string, _workflowId: string) { + const controlValuesEntity = await this.controlValuesRepository.findOne({ + _environmentId: user.environmentId, + _organizationId: user.organizationId, + _workflowId, + _stepId, + level: ControlValuesLevelEnum.STEP_CONTROLS, + }); + + return controlValuesEntity?.controls || {}; } } + +const buildToFieldSchema = ({ user, steps }: { user: UserSessionData; steps: NotificationStepEntity[] }) => { + const isEmailExist = isContainsStepType(steps, StepTypeEnum.EMAIL); + const isSmsExist = isContainsStepType(steps, StepTypeEnum.SMS); + + return { + type: 'object', + properties: { + subscriberId: { type: 'string', default: user._id }, + ...(isEmailExist ? { email: { type: 'string', default: user.email ?? '', format: 'email' } } : {}), + ...(isSmsExist ? { phone: { type: 'string', default: '' } } : {}), + }, + required: ['subscriberId', ...(isEmailExist ? ['email'] : []), ...(isSmsExist ? ['phone'] : [])], + additionalProperties: false, + } as const satisfies JSONSchema; +}; + +function isContainsStepType(steps: NotificationStepEntity[], type: StepTypeEnum) { + return steps.some((step) => step.template?.type === type); +} diff --git a/apps/api/src/app/workflows-v2/workflow.controller.e2e.ts b/apps/api/src/app/workflows-v2/workflow.controller.e2e.ts index 62816b8ab91..7094dd0f212 100644 --- a/apps/api/src/app/workflows-v2/workflow.controller.e2e.ts +++ b/apps/api/src/app/workflows-v2/workflow.controller.e2e.ts @@ -462,6 +462,70 @@ describe('Workflow Controller E2E API Testing', () => { }); }); + describe('Get Test Data Permutations', () => { + it('should get test data', async () => { + const steps = [ + { + ...buildEmailStep(), + controlValues: { + body: 'Welcome to our newsletter {{bodyText}}{{bodyText2}}{{payload.emailPrefixBodyText}}', + subject: 'Welcome to our newsletter {{subjectText}} {{payload.prefixSubjectText}}', + }, + }, + { ...buildInAppStep(), controlValues: { subject: 'Welcome to our newsletter {{payload.inAppSubjectText}}' } }, + ]; + const createWorkflowDto: CreateWorkflowDto = buildCreateWorkflowDto('', { steps }); + const res = await session.testAgent.post(`${v2Prefix}/workflows`).send(createWorkflowDto); + expect(res.status).to.be.equal(201); + const workflowCreated: WorkflowResponseDto = res.body.data; + const workflowTestData = await getWorkflowTestData(workflowCreated._id); + + expect(workflowTestData).to.be.ok; + expect(workflowTestData.payload).to.deep.equal({ + type: 'object', + properties: { + emailPrefixBodyText: { + type: 'string', + default: '{{payload.emailPrefixBodyText}}', + }, + prefixSubjectText: { + type: 'string', + default: '{{payload.prefixSubjectText}}', + }, + inAppSubjectText: { + type: 'string', + default: '{{payload.inAppSubjectText}}', + }, + }, + }); + + /* + * Validate the 'to' schema + * Note: Can't use deep comparison since emails differ between local and CI environments due to user sessions + */ + const toSchema = workflowTestData.to; + if ( + typeof toSchema === 'boolean' || + typeof toSchema.properties?.subscriberId === 'boolean' || + typeof toSchema.properties?.email === 'boolean' + ) { + expect((toSchema as any).type).to.be.a('boolean'); + expect(((toSchema as any).properties?.subscriberId as any).type).to.be.a('boolean'); + expect(((toSchema as any).properties?.email as any).type).to.be.a('boolean'); + throw new Error('To schema is not a boolean'); + } + expect(toSchema.type).to.equal('object'); + expect(toSchema.properties?.subscriberId.type).to.equal('string'); + expect(toSchema.properties?.subscriberId.default).to.equal(session.user._id); + expect(toSchema.properties?.email.type).to.equal('string'); + expect(toSchema.properties?.email.format).to.equal('email'); + expect(toSchema.properties?.email.default).to.be.a('string'); + expect(toSchema.properties?.email.default).to.not.equal(''); + expect(toSchema.required).to.deep.equal(['subscriberId', 'email']); + expect(toSchema.additionalProperties).to.be.false; + }); + }); + async function updateWorkflowRest(id: string, workflow: UpdateWorkflowDto): Promise { const novuRestResult = await workflowsClient.updateWorkflow(id, workflow); if (novuRestResult.isSuccessResult()) { @@ -522,6 +586,18 @@ describe('Workflow Controller E2E API Testing', () => { return value; } + async function getWorkflowTestData(workflowId: string, envId?: string) { + const novuRestResult = await createWorkflowClient(session.serverUrl, getHeaders(envId)).getWorkflowTestData( + workflowId + ); + if (!novuRestResult.isSuccessResult()) { + throw new Error(novuRestResult.error!.responseText); + } + const { value } = novuRestResult; + + return value; + } + async function getWorkflowStepControlValues( workflow: WorkflowResponseDto, step: StepDto & { _id: string; slug: Slug; stepId: string }, diff --git a/packages/shared/src/clients/workflows-client.ts b/packages/shared/src/clients/workflows-client.ts index 55a20ac23b0..47828c16f1b 100644 --- a/packages/shared/src/clients/workflows-client.ts +++ b/packages/shared/src/clients/workflows-client.ts @@ -46,6 +46,7 @@ export const createWorkflowClient = (baseUrl: string, headers: HeadersInit = {}) ): Promise> => { return await baseClient.safeGet(`/v2/workflows/${workflowId}/steps/${stepId}`); }; + const deleteWorkflow = async (workflowId: string): Promise> => { return await baseClient.safeDelete(`/v2/workflows/${workflowId}`); }; diff --git a/packages/shared/src/dto/workflows/create-workflow-dto.ts b/packages/shared/src/dto/workflows/create-workflow-dto.ts index 460cb1a4f98..ad5a58b0b58 100644 --- a/packages/shared/src/dto/workflows/create-workflow-dto.ts +++ b/packages/shared/src/dto/workflows/create-workflow-dto.ts @@ -1,4 +1,3 @@ -import { IsDefined, IsNotEmpty, IsString } from 'class-validator'; import { PreferencesRequestDto, StepCreateDto, WorkflowCommonsFields } from './workflow-commons-fields'; import { WorkflowCreationSourceEnum } from '../../types'; From 445ef50456c6cd94c12b1435555312d7e02ad774 Mon Sep 17 00:00:00 2001 From: George Desipris <73396808+desiprisg@users.noreply.github.com> Date: Thu, 7 Nov 2024 13:03:23 +0200 Subject: [PATCH 04/29] feat(dashboard): Save immediately when a step is added (#6882) --- .../workflow-editor-provider.tsx | 8 ++++- apps/dashboard/src/hooks/use-form-autosave.ts | 29 +++++++++---------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/apps/dashboard/src/components/workflow-editor/workflow-editor-provider.tsx b/apps/dashboard/src/components/workflow-editor/workflow-editor-provider.tsx index 875f745d395..718a4353c8b 100644 --- a/apps/dashboard/src/components/workflow-editor/workflow-editor-provider.tsx +++ b/apps/dashboard/src/components/workflow-editor/workflow-editor-provider.tsx @@ -28,7 +28,7 @@ import { AlertDialogHeader, AlertDialogTitle, } from '@/components/primitives/alert-dialog'; -import { Button, buttonVariants } from '@/components/primitives/button'; +import { buttonVariants } from '@/components/primitives/button'; import { RiAlertFill } from 'react-icons/ri'; import { Separator } from '@/components/primitives/separator'; @@ -128,6 +128,12 @@ export const WorkflowEditorProvider = ({ children }: { children: ReactNode }) => updateWorkflow({ id: workflow._id, workflow: { ...workflow, ...data } as any }); }, enabled: !isReadOnly, + shouldSaveImmediately: (previousData, data) => { + const currentStepsLength = data?.steps?.length ?? 0; + const wasStepsLengthAltered = previousData.steps != null && currentStepsLength !== previousData.steps?.length; + + return wasStepsLengthAltered; + }, }); const addStep = useCallback( diff --git a/apps/dashboard/src/hooks/use-form-autosave.ts b/apps/dashboard/src/hooks/use-form-autosave.ts index e0361130f17..9e68e0e8a8d 100644 --- a/apps/dashboard/src/hooks/use-form-autosave.ts +++ b/apps/dashboard/src/hooks/use-form-autosave.ts @@ -1,21 +1,25 @@ -import { FieldValues, SubmitHandler, UseFormReturn, useWatch } from 'react-hook-form'; +import { DeepPartialSkipArrayKey, FieldValues, SubmitHandler, UseFormReturn, useWatch } from 'react-hook-form'; import useDeepCompareEffect from 'use-deep-compare-effect'; import { useDebounce } from './use-debounce'; import { useDataRef } from './use-data-ref'; -import { useCallback, useRef } from 'react'; +import { useRef } from 'react'; export const useFormAutoSave = ({ onSubmit, form, enabled = true, + shouldSaveImmediately, }: { onSubmit: SubmitHandler; form: UseFormReturn; enabled?: boolean; + shouldSaveImmediately?: ( + watchedData: DeepPartialSkipArrayKey, + previousWatchedData: DeepPartialSkipArrayKey | null + ) => boolean; }) => { const onSubmitRef = useDataRef(onSubmit); const { formState, control, handleSubmit } = form; - const previousStepsLength = useRef(null); const watchedData = useWatch({ control, @@ -29,29 +33,22 @@ export const useFormAutoSave = ({ const debouncedSave = useDebounce(save, 500); - const checkStepsDeleted = useCallback(() => { - const currentStepsLength = watchedData.steps?.length ?? 0; - const wasStepDeleted = previousStepsLength.current !== null && currentStepsLength < previousStepsLength.current; - - previousStepsLength.current = currentStepsLength; - - return wasStepDeleted; - }, [watchedData]); + const previousWatchedData = useRef | null>(null); useDeepCompareEffect(() => { if (!formState.isDirty) { - // set the previous steps length to the current steps length upon mount - previousStepsLength.current = watchedData.steps?.length ?? 0; - + previousWatchedData.current = watchedData; return; } - const wasStepsDeleted = checkStepsDeleted(); + const immediateSave = shouldSaveImmediately?.(watchedData, previousWatchedData.current) || false; - if (wasStepsDeleted) { + if (immediateSave) { save(); } else { debouncedSave(); } + + previousWatchedData.current = watchedData; }, [watchedData]); }; From 5685a85f1ff4c6de0703154962632f414e98c17e Mon Sep 17 00:00:00 2001 From: Dima Grossman Date: Thu, 7 Nov 2024 13:58:39 +0200 Subject: [PATCH 05/29] feat(novu): update novu init landing page (#6805) --- .../layout/components/v2/SyncInfoModal.tsx | 2 +- packages/novu/package.json | 4 +- packages/novu/src/commands/init/create-app.ts | 6 + packages/novu/src/commands/init/index.ts | 12 + .../ts/app/api/dev-studio-status/route.ts | 32 + .../ts/app/api/events/route.ts | 32 + .../ts/app/api/trigger/route.ts | 24 + .../Notifications.module.css | 80 + .../NotificationToast/Notifications.tsx | 66 + .../ts/app/fonts/GeistMonoVF.woff | Bin 0 -> 67864 bytes .../app-react-email/ts/app/fonts/GeistVF.woff | Bin 0 -> 66268 bytes .../app-react-email/ts/app/globals.css | 49 +- .../app-react-email/ts/app/layout.tsx | 21 +- .../welcome-onboarding-email/schemas.ts | 12 + .../welcome-onboarding-email/workflow.ts | 8 + .../app-react-email/ts/app/page.module.css | 437 +++++ .../templates/app-react-email/ts/app/page.tsx | 572 +++++-- .../app-react-email/ts/public/file.svg | 1 + .../app-react-email/ts/public/globe.svg | 1 + .../app-react-email/ts/public/novu.svg | 24 + .../app-react-email/ts/public/vercel.svg | 2 +- .../app-react-email/ts/public/window.svg | 1 + .../init/templates/app/ts/.env.example | 3 - .../init/templates/app/ts/README-template.md | 31 - .../templates/app/ts/app/api/novu/route.ts | 4 - .../init/templates/app/ts/app/favicon.ico | Bin 25931 -> 0 bytes .../init/templates/app/ts/app/globals.css | 107 -- .../init/templates/app/ts/app/layout.tsx | 22 - .../templates/app/ts/app/novu/workflows.ts | 30 - .../init/templates/app/ts/app/page.module.css | 230 --- .../init/templates/app/ts/app/page.tsx | 95 -- .../init/templates/app/ts/eslintrc.json | 3 - .../commands/init/templates/app/ts/gitignore | 36 - .../init/templates/app/ts/next-env.d.ts | 7 - .../init/templates/app/ts/next.config.mjs | 4 - .../init/templates/app/ts/public/next.svg | 1 - .../init/templates/app/ts/public/vercel.svg | 1 - .../init/templates/app/ts/tsconfig.json | 26 - .../novu/src/commands/init/templates/index.ts | 5 + .../novu/src/commands/init/templates/types.ts | 2 + pnpm-lock.yaml | 1459 ++++++++--------- 41 files changed, 1938 insertions(+), 1514 deletions(-) create mode 100644 packages/novu/src/commands/init/templates/app-react-email/ts/app/api/dev-studio-status/route.ts create mode 100644 packages/novu/src/commands/init/templates/app-react-email/ts/app/api/events/route.ts create mode 100644 packages/novu/src/commands/init/templates/app-react-email/ts/app/api/trigger/route.ts create mode 100644 packages/novu/src/commands/init/templates/app-react-email/ts/app/components/NotificationToast/Notifications.module.css create mode 100644 packages/novu/src/commands/init/templates/app-react-email/ts/app/components/NotificationToast/Notifications.tsx create mode 100644 packages/novu/src/commands/init/templates/app-react-email/ts/app/fonts/GeistMonoVF.woff create mode 100644 packages/novu/src/commands/init/templates/app-react-email/ts/app/fonts/GeistVF.woff create mode 100644 packages/novu/src/commands/init/templates/app-react-email/ts/app/page.module.css create mode 100644 packages/novu/src/commands/init/templates/app-react-email/ts/public/file.svg create mode 100644 packages/novu/src/commands/init/templates/app-react-email/ts/public/globe.svg create mode 100644 packages/novu/src/commands/init/templates/app-react-email/ts/public/novu.svg create mode 100644 packages/novu/src/commands/init/templates/app-react-email/ts/public/window.svg delete mode 100644 packages/novu/src/commands/init/templates/app/ts/.env.example delete mode 100644 packages/novu/src/commands/init/templates/app/ts/README-template.md delete mode 100644 packages/novu/src/commands/init/templates/app/ts/app/api/novu/route.ts delete mode 100644 packages/novu/src/commands/init/templates/app/ts/app/favicon.ico delete mode 100644 packages/novu/src/commands/init/templates/app/ts/app/globals.css delete mode 100644 packages/novu/src/commands/init/templates/app/ts/app/layout.tsx delete mode 100644 packages/novu/src/commands/init/templates/app/ts/app/novu/workflows.ts delete mode 100644 packages/novu/src/commands/init/templates/app/ts/app/page.module.css delete mode 100644 packages/novu/src/commands/init/templates/app/ts/app/page.tsx delete mode 100644 packages/novu/src/commands/init/templates/app/ts/eslintrc.json delete mode 100644 packages/novu/src/commands/init/templates/app/ts/gitignore delete mode 100644 packages/novu/src/commands/init/templates/app/ts/next-env.d.ts delete mode 100644 packages/novu/src/commands/init/templates/app/ts/next.config.mjs delete mode 100644 packages/novu/src/commands/init/templates/app/ts/public/next.svg delete mode 100644 packages/novu/src/commands/init/templates/app/ts/public/vercel.svg delete mode 100644 packages/novu/src/commands/init/templates/app/ts/tsconfig.json diff --git a/apps/web/src/components/layout/components/v2/SyncInfoModal.tsx b/apps/web/src/components/layout/components/v2/SyncInfoModal.tsx index 7cab230a898..9f3a57132af 100644 --- a/apps/web/src/components/layout/components/v2/SyncInfoModal.tsx +++ b/apps/web/src/components/layout/components/v2/SyncInfoModal.tsx @@ -92,7 +92,7 @@ export const SyncInfoModal: FC = ({ isOpen, toggleOpen, refe href="https://docs.novu.co/deployment/syncing" target={'_blank'} className={css({ - textDecoration: 'underline !important', + textDecoration: '!important underline', })} > our docs. diff --git a/packages/novu/package.json b/packages/novu/package.json index a5b6387cbad..05e2c19f59c 100644 --- a/packages/novu/package.json +++ b/packages/novu/package.json @@ -1,6 +1,6 @@ { "name": "novu", - "version": "2.1.0", + "version": "2.2.0-rc.2", "description": "Novu CLI. Run Novu Studio and sync workflows with Novu Cloud", "main": "src/index.js", "publishConfig": { @@ -68,7 +68,7 @@ }, "dependencies": { "@novu/ntfr-client": "^0.0.4", - "@novu/shared": "workspace:*", + "@novu/shared": "2.1.1", "@segment/analytics-node": "^1.1.4", "axios": "^1.6.8", "chalk": "4.1.2", diff --git a/packages/novu/src/commands/init/create-app.ts b/packages/novu/src/commands/init/create-app.ts index 976703ed183..643d9169e6c 100644 --- a/packages/novu/src/commands/init/create-app.ts +++ b/packages/novu/src/commands/init/create-app.ts @@ -21,6 +21,8 @@ export async function createApp({ srcDir, importAlias, secretKey, + applicationId, + userId, }: { appPath: string; packageManager: PackageManager; @@ -29,6 +31,8 @@ export async function createApp({ srcDir: boolean; importAlias: string; secretKey: string; + applicationId: string; + userId: string; }): Promise { let repoInfo: RepoInfo | undefined; const mode: TemplateMode = typescript ? 'ts' : 'js'; @@ -73,6 +77,8 @@ export async function createApp({ srcDir, importAlias, secretKey, + applicationId, + userId, }); if (tryGitInit(root)) { diff --git a/packages/novu/src/commands/init/index.ts b/packages/novu/src/commands/init/index.ts index a68f79ac44d..78cc95c78e2 100644 --- a/packages/novu/src/commands/init/index.ts +++ b/packages/novu/src/commands/init/index.ts @@ -93,6 +93,7 @@ export async function init(program: IInitCommandOptions, anonymousId?: string): process.exit(1); } + let applicationId: string; let userId: string; // if no secret key is supplied set to empty string if (!program.secretKey) { @@ -114,6 +115,15 @@ export async function init(program: IInitCommandOptions, anonymousId?: string): userId = user.data?._id; + const integrationsResponse = await fetch(`${program.apiUrl}/v1/environments/me`, { + headers: { + Authorization: `ApiKey ${program.secretKey}`, + }, + }); + + const environment = await integrationsResponse.json(); + applicationId = environment.data.identifier; + analytics.alias({ previousId: anonymousId, userId, @@ -172,6 +182,8 @@ export async function init(program: IInitCommandOptions, anonymousId?: string): srcDir: defaults.srcDir as boolean, importAlias: defaults.importAlias as string, secretKey: program.secretKey, + applicationId, + userId, }); if (userId || anonymousId) { diff --git a/packages/novu/src/commands/init/templates/app-react-email/ts/app/api/dev-studio-status/route.ts b/packages/novu/src/commands/init/templates/app-react-email/ts/app/api/dev-studio-status/route.ts new file mode 100644 index 00000000000..5d5e635a419 --- /dev/null +++ b/packages/novu/src/commands/init/templates/app-react-email/ts/app/api/dev-studio-status/route.ts @@ -0,0 +1,32 @@ +export async function GET() { + try { + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 3000); + + const response = await fetch("http://localhost:2022/.well-known/novu", { + signal: controller.signal, + headers: { + Accept: "application/json", + }, + }); + + clearTimeout(timeoutId); + + if (response.ok) { + const data = await response.json(); + if (data.port && data.route) { + return Response.json({ connected: true, data }); + } + } + + return Response.json({ + connected: false, + error: await response.text(), + }); + } catch (error) { + return Response.json({ + connected: false, + error: error instanceof Error ? error.message : "Unknown error", + }); + } +} diff --git a/packages/novu/src/commands/init/templates/app-react-email/ts/app/api/events/route.ts b/packages/novu/src/commands/init/templates/app-react-email/ts/app/api/events/route.ts new file mode 100644 index 00000000000..ba897d9d2bc --- /dev/null +++ b/packages/novu/src/commands/init/templates/app-react-email/ts/app/api/events/route.ts @@ -0,0 +1,32 @@ +export async function POST(request: Request) { + try { + const body = await request.json(); + + const response = await fetch("https://api.novu.co/v1/telemetry/measure", { + headers: { + Accept: "application/json", + "Content-Type": "application/json", + Authorization: `ApiKey ${process.env.NOVU_SECRET_KEY}`, + }, + method: "POST", + body: JSON.stringify({ + event: body.event, + data: body.data, + }), + }); + + if (response.ok) { + return Response.json({ success: true }); + } + + return Response.json({ + connected: false, + error: await response.text(), + }); + } catch (error) { + return Response.json({ + connected: false, + error: error instanceof Error ? error.message : "Unknown error", + }); + } +} diff --git a/packages/novu/src/commands/init/templates/app-react-email/ts/app/api/trigger/route.ts b/packages/novu/src/commands/init/templates/app-react-email/ts/app/api/trigger/route.ts new file mode 100644 index 00000000000..0459ac751d3 --- /dev/null +++ b/packages/novu/src/commands/init/templates/app-react-email/ts/app/api/trigger/route.ts @@ -0,0 +1,24 @@ +import { NextResponse } from "next/server"; +import { welcomeOnboardingEmail } from "../../novu/workflows"; + +export async function POST() { + try { + await welcomeOnboardingEmail.trigger({ + to: process.env.NEXT_PUBLIC_NOVU_SUBSCRIBER_ID || "", + payload: {}, + }); + + return NextResponse.json({ + message: "Notification triggered successfully", + }); + } catch (error: unknown) { + const errorMessage = + error instanceof Error ? error.message : "Unknown error occurred"; + console.error("Error triggering notification:", errorMessage); + + return NextResponse.json( + { message: "Error triggering notification", error: errorMessage }, + { status: 500 }, + ); + } +} diff --git a/packages/novu/src/commands/init/templates/app-react-email/ts/app/components/NotificationToast/Notifications.module.css b/packages/novu/src/commands/init/templates/app-react-email/ts/app/components/NotificationToast/Notifications.module.css new file mode 100644 index 00000000000..f35c3d40d74 --- /dev/null +++ b/packages/novu/src/commands/init/templates/app-react-email/ts/app/components/NotificationToast/Notifications.module.css @@ -0,0 +1,80 @@ +.toast { + position: fixed; + background: linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%); + border-radius: 16px; + padding: 18px 24px; + box-shadow: + 0 10px 25px rgba(0, 0, 0, 0.1), + 0 6px 12px rgba(0, 0, 0, 0.08), + 0 0 0 1px rgba(255, 255, 255, 0.5) inset; + z-index: 1000; + width: 90%; + max-width: 400px; + right: 24px; + top: 24px; + border: 1px solid rgba(0, 0, 0, 0.06); + animation: slideIn 0.5s cubic-bezier(0.34, 1.56, 0.64, 1); + backdrop-filter: blur(10px); + transform-origin: top right; +} + +.toastContent { + display: flex; + flex-direction: column; + gap: 10px; + position: relative; + overflow: hidden; + font-weight: 600; + background: linear-gradient(90deg, #1a1a1a 0%, #404040 100%); + -webkit-background-clip: text; + color: transparent; + font-size: 1rem; + letter-spacing: -0.02em; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.toastContent::before { + content: ''; + position: absolute; + top: -50%; + left: -50%; + width: 200%; + height: 200%; + background: linear-gradient(45deg, + transparent 0%, + rgba(255, 255, 255, 0.1) 50%, + transparent 100%); + animation: shimmer 2s infinite; +} + +@keyframes slideIn { + 0% { + transform: translateY(-120%) scale(0.9); + opacity: 0; + } + + 100% { + transform: translateY(0) scale(1); + opacity: 1; + } +} + +@keyframes shimmer { + 0% { + transform: translateX(-100%) rotate(45deg); + } + + 100% { + transform: translateX(100%) rotate(45deg); + } +} + +@media (prefers-reduced-motion: reduce) { + .toast { + animation: none; + } + + .toastContent::before { + animation: none; + } +} \ No newline at end of file diff --git a/packages/novu/src/commands/init/templates/app-react-email/ts/app/components/NotificationToast/Notifications.tsx b/packages/novu/src/commands/init/templates/app-react-email/ts/app/components/NotificationToast/Notifications.tsx new file mode 100644 index 00000000000..43cdd43d22c --- /dev/null +++ b/packages/novu/src/commands/init/templates/app-react-email/ts/app/components/NotificationToast/Notifications.tsx @@ -0,0 +1,66 @@ +"use client"; + +import { Novu } from "@novu/js"; +import { useEffect, useState } from "react"; +import { Inbox } from "@novu/nextjs"; +import styles from "./Notifications.module.css"; // You'll need to create this + +const NotificationToast = () => { + const novu = new Novu({ + subscriberId: process.env.NEXT_PUBLIC_NOVU_SUBSCRIBER_ID || "", + applicationIdentifier: + process.env.NEXT_PUBLIC_NOVU_APPLICATION_IDENTIFIER || "", + }); + + const [showToast, setShowToast] = useState(false); + + useEffect(() => { + const listener = ({ result: notification }: { result: any }) => { + console.log("Received notification:", notification); + setShowToast(true); + + setTimeout(() => { + setShowToast(false); + }, 2500); + }; + + console.log("Setting up Novu notification listener"); + novu.on("notifications.notification_received", listener); + + return () => { + novu.off("notifications.notification_received", listener); + }; + }, [novu]); + + if (!showToast) return null; + + return ( +
+
New In-App Notification
+
+ ); +}; + +export default NotificationToast; + +const novuConfig = { + applicationIdentifier: + process.env.NEXT_PUBLIC_NOVU_APPLICATION_IDENTIFIER || "", + subscriberId: process.env.NEXT_PUBLIC_NOVU_SUBSCRIBER_ID || "", + appearance: { + elements: { + bellContainer: { + width: "30px", + height: "30px", + }, + bellIcon: { + width: "30px", + height: "30px", + }, + }, + }, +}; + +export function NovuInbox() { + return ; +} diff --git a/packages/novu/src/commands/init/templates/app-react-email/ts/app/fonts/GeistMonoVF.woff b/packages/novu/src/commands/init/templates/app-react-email/ts/app/fonts/GeistMonoVF.woff new file mode 100644 index 0000000000000000000000000000000000000000..f2ae185cbfd16946a534d819e9eb03924abbcc49 GIT binary patch literal 67864 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ϣ%UY8`RWp~V-U_7 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 CLkb=M literal 0 HcmV?d00001 diff --git a/packages/novu/src/commands/init/templates/app-react-email/ts/app/fonts/GeistVF.woff b/packages/novu/src/commands/init/templates/app-react-email/ts/app/fonts/GeistVF.woff new file mode 100644 index 0000000000000000000000000000000000000000..1b62daacff96dad6584e71cd962051b82957c313 GIT binary patch literal 66268 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 >-Aun5A4Gp>4U0IQJ zJSDj%uq;_-j;8!z8*BN3#G5`ojMF>mZtK$CmJZ>LZBP#+{!QxI(n!6=j?D+5s8yl| zCqq%@Li|olF66yc&uRtqxK_{9<1Bz%WM|3)$GtRZvu6gM<72a@tfd#+V6(pWfBD**uQxR;owP8FIttM>^4T=+ zFYN&$EludBGthdY*q;-P4l)cZvz=S2KfBDRiZdk$T!jv@&mB^%V^Q1_xXKs?qV=+O z7JK9WX_6hj5rQ5#_#XZR<>aHdT&e4ifAZwWse0~aHapMWG&cBWv{?RZ`hEHB@_nuF zy}fbqt#tNX)bur{>6ftehFiZkNd>Ryw`lrJv#{N3PTAXz)`CuJPCB~geMIozQlm#$5l!D;X zfUQ1!IFD;IjI^b*Mkgk>MUhTnv4a>qY7RRms)c0?WH-vw-S9;aXwyNe7Ta*5``;;g^I(Vd`+I0u7da=e}#F;{J_6W$C;2b`UBI+E~4_A_HQQ5 zEQ&p-|FvZ}rahkr&RN0U9c#S3P4p`5%G$~Q1Gow$7~C7M`U(n zH^FiFC6R_ryR#`dH%S4ZDE#M*I!7-^?m}M>oyQ08|KKpz^j+15&QmYy$Q`n%QO3zYhIp< zL@=uru9zHQ&p+^Mf`TE$N6+X3DXHLFHM7ULndU-NzDCgbzO@DRYM`}{g9Ucx2d0wT zg|vXtmgY(G{#9P|@KChWPlr8W`g(H1hNk~a>J&0B02gHsTNjj>*_i%Cgna)s>-q)} zxaIxqdlH*u{aqw9fqCww89ikAvHf?Q$#we#8Dn1}a=W$}OpqPy5^-&9Avuoir=($k?pgH2#cR*9FeVS_gLRc7U0k+2y92<1`CP zAP|x#R&QbPF}jnpTfaTSa3cH#v3D)=rS=>G23m#FFV*t7k4bvAKuVE8{3!#`2WN3wo)f6L0KwAkO>ECG`!KDm9U&Aj#-xeF?-Sk^#N4MY2 zU*K+D^9rFIH3hnht<#=H3WI*w_w%358;ibQ@gDcbe2?DO{khi%(YMbMP~(*oqXD#| zcd^%2_HY!2T)|3<7?dgI2@9=B zrQ>K)@X=?cYYwfUkafI;oV=Cl_)4^L)F~LK{e60f@)nUL_9PX7=P} z4(!MF^v4eT3Q6*RSm+w(M0qf7p-4!W{W=i;s*Nsw$amYf+IzTPq>erZZ$br>9Ku&G# zQ>k{y#@X0ocWW8vySn!eNXe`O3Y%_3`aNctsL8LKLf? z?6Zw>jM~rIAuZvY#F}!9x!2wyPHmY$t9Fb&-`GKKZtd5(a>#|`JwQMTK7EN7xJCFH z?SA3--bMO8tizXeA7jb64@jMGRAQ`)dyb1xr!5igNHU={3!alyt;=AmJY-u{FksRd zKX>P|+llT7=eS4T8e4a7uDcqQW855ncNZYo3G@y_xJTk2gJ92)L&;q2Qw7vz<6RhI zw69j=^56RYvX6_shj#K6oiw|&A4v9{sZgJ$*|?6mI630@V9j*%BPhV#=cM2qrIK|D zX~^2=#b_BJqjw6f(B9|fXc@G*vQPEeI0i=Wm_W(7i#qPuA#2z`m8LZXr_mU+T&hip zwl-wZS{Y*pGz4Z}7;?O?OauSAbKuX!kzq>kN!N}2zjcsT{WY;-f&2fqYxuuLt!}); zzFGn$l7;uW0FrtCtIWI(Z~-)N;#jTou6vwTdnnBt`K1nSXBWmDFf<|}SXlju8GT7c zDzz2vK5<9i|zx4aAwo>ml>7lgPd0s?QLl96URHi1yXy{%tO~s zB1rNfQ*OVcj6eJ36ND}6NeSvvnD7AKoH&5?A)dpd(bEr_K-F`5po-tN#zPiNm{fog zdTEAB$lHrs zvw2rdi&jvE*CC3{axexwRt7rIAKxW_`XF@}WU&<5Z!0Wu;|bkB=ic3t$g&s+{2=$K z31U7BBzu;|A(UkB{WVO#wKG;tPY!tm5^&I1j@<`TW zkOVQAZ7Fn3%tLi74>1hKdVCHA_siV;g=!pmqjfY@GpjhDBI`Ay&i(cDCaAr;sNF}{ z_kj!Uu;)iyu9|=&`(2GdpWSTTKSM@R6& z_?=updf73kQ0!e#x@RSg&bHodW%ofewxmL3UKv zTMJ+1vpAkWpANd$2jXtUM&UExm{Z0s*l-=Y=Amon3s0XrKTWp64IaR6*IF*$ZlUF& zIa$HMA-IAs1;!zJvsLuuvRVDy=Ijm$-`+)cj)UC@f1XM8eW_21cZw$=l-n&w$;qW9 zw`=bbZ=$nvGk%9hwTpl&c2mBe(xewGT=s0(E3A&8b1SOyS+$zk1YstbRUOg4qAl?> zwUCFwW8|FHZyoTgmud9>M}*D2IgOi#rM=uE;hQPB(l6b)Wm13d4|wPgP?H;qBq1JD zF-T_-*oR@T#)eJ+)A2>XeCadW_4;=!b4G?0~@LZY}0}fduLs=7p)>B0refS&IQ9HKyv$5Pm zG2O=VfCUAZ~&T8i~ub~MczSu)OH0Fc$8 zf#Fc77^^Tg=?-zqya)SOEr4lvciFmRh*NhwJEDl@WZI6vSQo#5X=lF}2BaMt?@+-P zEZ?dxju%+o4;6=74l={_n9x4T5I8M&UM+WK1uU2NU{7;60+}QrnOR9Ut41MqZpz>p zh46foHsXHtJm>WQTrDzft)Mw3m;$6GosoWZGT41ae13Au)u$Y(VOHATaIkeC(3Q&h z>VcPSZj`Mn;h^HXguh5)NH}XsFdQVdb%#_A_OYu;LNZ&5?Ckc5_S}UrpoM7W9e5G{H zH+LUjKRzIQpdf#+d{>tE85lf@s0+&|psOfF4I-zv&4ue#K$t&4(^&sDu= zpkFh5ae=>o9qEGs20d`c@@}}I`WHt+Y*%OaV)k!@w9a^Ccff>gYVJu5nGLi0%Eaxl z&4@=evMRjrkBM^cx%8ev=mjNp(JM5@4%^i1gWr<1!#UL)ny%Qi14)}Khz>lf)f)cd z#7#$U1fU)wQgLlm_!2yy^Y?&;-4P-XPYLlBela3c2=tLy#@u4wd1MVQ=I%fT@s284 z%HFf)FPIh|;ZB!vP2Y>(f-n$HMRt^yq`E^xYjjtBQP&WEbmPq>zVN&dnc(NpMgL^q zza9tZX=1W}Jsz233Ho}iweZR5Q^J14W3NT*V z&7`Y7z^4H(?Xq-rifx^#A)EE5_)J=zO1N~}z2}3DO}ps{3MJ=d-9>`_W&!#6&Sj7F zamHoZs_&S!*u>A%ER(KDhZ?|G0MFsW4r)OZS*@P^qaRDCoN`Ex;TKsANj{RI|6>|` zri8nBpAJfnX&-F5{c=#rif)dOs}Tq1g{%_YXthK!-KoV z{6mExa$bu*P!#;cn?y@l3HKMdUzfn0>5OpwCm8Flit9&qnU7EHQG42)JnmZ)(zdWQ zn(qC5G;*-r2sZ2VE3R9B3eUidt$(JwOhtd>EaX+O;n*OUqW^3hEz;-V`1~9Zv$3Z%2oX{`zyV*ZFoG#P_kv`siRF*W_g!otEmF)`6%U>cM7b8UK*-Ic(t z`NMNiU0vfG+qKR*&yr!`h07%UrAhyX(&mcoIsJVS^yrV@Ca-mQX0>S)mQ`^YmT7VN zVNGJu5!*d?QR^@Oq7m{9lq9WJQ=dWZ7X1e821ESUNV+1IoAMQED_lLg$z&KGl9z-n zXjxeRkdZVlf{b{?pL03 zQ*!BF198koVI*OzF)zBmeO)epNeN`$ehx6+x~2KsXLort#=Fk_;g+O$FQnKk3Vlf7 zpVNa_dGCm7c(zZcRWiw#sCP3>XMi;hr%gPp7gRm_eyvP|uUB9nRb3@tHwnE+>U8Yc zQaaS|a!X1*F!2!4Oyvcvu*rP1d}kt!5YAta^C7!oG+DQFmP*Ee*QJ zJQ8EpEHes3HOfI4kFJ7q|x*TFy`wax^-(b+5A`^^82E0<*bsX z-j?}yIXsACCY5AP8IotnI~TsiYU5&4emqafJZnP=H#V198~1Z7`w$g}Gp}fC_BcUB z*7?Wim_qy6UW32J82DI$|LWNGdltd94axExv&+@uL`aY0p;UIaU~AUfGVp!Uv?4vw z(U(>B)^E7*ZBhPwJ9Gjg!zQDGIpz?HA=GlhgBKc&<=W~cvU=t^VwXoBLD>#BSu{E| zi}a)h@p0GgMj0!IDnJWLXTk?QSu_9CWYcH*hKY2qJo-M$fnp3TwLQL>!Xg9OtDbE> za8=rqhm?}bo5;fv zU0{?;@sFUQ1PrMZeO!p*P=~=*T;{=1N1ME2@D|MVWTF15zQ`h3uU4g?Ua(ZM@b2X9 zhaZhP9~vZ1fJ%#Zi)O7+OUCDi9SnNFeC1A1p=$6rq#M3kDWf~*i=esSP2fHZU2X2} zcpt}y9*i&Ahsgfqm-l|2c*a<8HH=Q&AGhF)&@*(U;SOkz2Fdapo!v8vQjZoRQM3@T zqVXxE<0h6yewonzhCZn;fmJSiwUc1wiz&agR;S@@0e0Jo(c8jij7?lVZN=bRnC`vg z=W-Lpm&6-4DiOV#@}JfU5a*ph-fW|`4lbXbm_39hP$`0Ud^oSZ#aASh<98CzeYE6r zh;WO-kf0DZmIiJCMn8|VEe3(t`eIJW6e zY}1hXwPkhS7-KH$vwZzo-IO0>^d3zI8biH(%6x5~j)xLs`UK8Rl?$2`F1l7DnxTY} zmXsEJXVc?*_@{bOXl!$#1`b!XOKN>V{3km}0>_rb@Cz7!?ucFLSfMPouHnk?x5wUL zX`VGNw;3^UD{SA=kHc|@6rB|yC3!;OrEcGWv4VtHI4g@4##`+w*xX9GusX_`xyUMt zksR|DcXpM>h)#JBGx7gaPl27M-IB+8>-ipJQ8Z0?kmH}=Jz5_aiB;(g@dt|d)+3R7 zXsez%aLI`=s>N=J^dQ?5RODWZ{LGz_re&(YJTr+`t3T;}2yLTQtRl_m8sJ`pSs>e4 z?mD>7H#qfXGPGQzqiqhdFcx14^chAee!tQ?Mo0f{)M=QS(jHqIS@aU|I)QiOX6LTl zM*yxN$Ni>eo27sfpQt)5_0rP(*Ew_{oloN*obq~cUA`MVi*=I46*cuU>j#=96SX`> z%rPTz(FA3%xHQnen;k(NwKE61i+;bNV7(K25_td-@Lc-7;;B`ztagmRGkU?+4|z)6 zH|14o%^EEz^JNixm7Z+YkfS)V;d;QR75_9H(*q_b6_9+T)35W|n?m3-Az4=Pa*$U{$1hr^Z!Cz$X*WHAbO6o$&C$H${4HGHkB%MEI*-t zu<6pAo8MY4q}RQ{(O22?Or+GML~y5eIHCi+(PhfX|ES!5Zu+7=O*yDOwPWi&4kPMy z!z}TWVBybuKhr?9=Q43d_@EtP40dv=J)&W|+;s99N%$p1kO4QhxxYL28=E;mp|?0aB56{dI!8UAfElgz zXR#B#DY$T*!>Cnc$e41`L}6%7mEDvUk|pJsIi+hY&`QZlK&+>wB8bh?mV;Z@N&|xX zYs8T-Hqod0mv`l>(n0gVrhDRatwsY3YX#8DK)pjZM&-OJMunYK)v_i|V-*>_Re`C` z<%`mx8=hZrRS2$MPS+I(1ELVf^*^;}U51lwR*>)t(Qo4Ts%6=jc1v5SlyQ*hq6j&< z&x8(3X%8>(%xVA~-X+S_)qC28Ib#Z6*m1@TV4;uStfz!4X-0H6ExaSt7}A%w1Zt?t&Idal)10W>YDZK8p)5W*u2 zFes$Bazzdg7ruNoHD97OIZG&orKig0>xRF}$e&c}9|UaQ{f3iY|i?2RPP(-=l2(!Lp#90zHaE87&$4~*c1q4*!1Bu*t4|Y8^{xm(Y z>@D#Kb1qH8w>t;kLhRf88W!K6P2ZcrAD|a*HihoM$w{F0Ca37Z-AxRMqsDU%bM9`u z^8lMdq-Lat6>seS7Zea@p4DI0D_ijKEmPWFJHKl9^>x3!1~t;yHUhgcv1+1XeBEL@ zot-X;y7Rm}3Mm{!$;3_^s(X-dya@tBm7j(zc`8Hj#+(ynF>Y40;wmbl62XElt(CJE z9z1_kY_8MNLR(aYo;)dSVKKNDOogYwRz+RJQ%;Ru_#pD^bn)#WD~?gvsnQYpDvWSH zihsm$VZdJz`g-wmc4EL^5c)dt9e>?yyBXu5bKQhO=Vje|@5%kVVsyfoer|8l8Y7=~E?%T9 zR@QxP9_@@*Fj{TIw(OEc{j^eHi%_*;RHO4OznSC9VFNn?EcB}y2YeDP1BDft6`K{E z^%o{i9C#RfAbBT^=ij@4aqvUPR7h$ldIDukZQxSM7D0Ijdy#($I}v}1dXxP<_XUZ~ zMQ5zvn3*)u_-NjKKO~z=RmxTN#WvMt@1y5p*F=7k`6_<=9Y`2B8~A~fBBzq+N+rlpH+L46(|$A z3=yHT&`7ZgR<-=JMp^HBTi3_2EwJg30i3FuvH{kX)~5i?mu8`>4z3y5CdaEHuIV}^ z%d0Z3nVTlht3pp{d?wSYQcoG3CfBQCPw74;+pBU*hL=xT1H`xDrldRxI8;$d#B9V< zu2T+EE>ljjF0xLtZc{y+iT6lmT*I8h+`|UA)8N$<_C$Na$E3%`$EaojPH9dpPVr7b zPK8cMPK`>(*5}$6+I!k(+DF<~+Pm5k!qM1eRB56X<>%%yPIv{UKfTvK9Xl^gH^i#j zpiN;8I2WFD$S!QHPGm!{2v@pN=1j)Cu7D|9D|4{SF2c;U!kY6o`>PaU(SlA)=P1f~ zo_#0_NW8AJSLLqATAac*qf^*!%3B&|cWf?#Z_pkmGSphNAHQ#Fimvsp`LroSbH~#! zsGK?fy}eId6KEZU=7nc%R5fsph+|eHF2F6oCBP#i+c3ZPvDe6LBg<1SGG%D?-)6`r zD_t&dGH^0*GjK8R)Ns~t*KpPF*m2tZ+}A!IMJz!9T8AJS;Oz~lS zU#ON1Hn^6NHprGZ#Fn2>SW%p-DQA+l87V8YlXhE|Mmjv(`Ko(}s>c!o+gaN7WR=T| z)zD^VUx(6IRTea3*X0U4gZEYJSVX2J*E81y`XiniRE5tH2I2zccwu{;zq@aA4USu2 zjLhxT+_?Hz=;=N=o>#30?Wx1!oO5ejFsI9=9_bd_eFMYFft6%O4iqg>!ZfQ0)K-Lv z^JM!jVDgQTp9X#rl76h@ikCvVl0ElVqI*1X9l9S&COz@R5c)(@7=>B2T;?uyaX)nL zhWec$K!2K4N}uBl8r#DSJ8GvvP&g)RKcm7Kl@c&!IZ)E&N@Xc=MbC2uvT)ICaQQ$K z3Df}zxi<3&zM-6BPON72w`L8$YWD<;3nZFu`;kS$W6&jf1)KUzkz=L G)cz05(PHWV literal 0 HcmV?d00001 diff --git a/packages/novu/src/commands/init/templates/app-react-email/ts/app/globals.css b/packages/novu/src/commands/init/templates/app-react-email/ts/app/globals.css index 875c01e819b..e3734be15e1 100644 --- a/packages/novu/src/commands/init/templates/app-react-email/ts/app/globals.css +++ b/packages/novu/src/commands/init/templates/app-react-email/ts/app/globals.css @@ -1,33 +1,42 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - :root { - --foreground-rgb: 0, 0, 0; - --background-start-rgb: 214, 219, 220; - --background-end-rgb: 255, 255, 255; + --background: #ffffff; + --foreground: #171717; } @media (prefers-color-scheme: dark) { :root { - --foreground-rgb: 255, 255, 255; - --background-start-rgb: 0, 0, 0; - --background-end-rgb: 0, 0, 0; + --background: #0a0a0a; + --foreground: #ededed; } } +html, body { - color: rgb(var(--foreground-rgb)); - background: linear-gradient( - to bottom, - transparent, - rgb(var(--background-end-rgb)) - ) - rgb(var(--background-start-rgb)); + max-width: 100vw; + overflow-x: hidden; } -@layer utilities { - .text-balance { - text-wrap: balance; +body { + color: var(--foreground); + background: var(--background); + font-family: Arial, Helvetica, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +* { + box-sizing: border-box; + padding: 0; + margin: 0; +} + +a { + color: inherit; + text-decoration: none; +} + +@media (prefers-color-scheme: dark) { + html { + color-scheme: dark; } } diff --git a/packages/novu/src/commands/init/templates/app-react-email/ts/app/layout.tsx b/packages/novu/src/commands/init/templates/app-react-email/ts/app/layout.tsx index 2010b28c893..dca06aee771 100644 --- a/packages/novu/src/commands/init/templates/app-react-email/ts/app/layout.tsx +++ b/packages/novu/src/commands/init/templates/app-react-email/ts/app/layout.tsx @@ -1,12 +1,21 @@ import type { Metadata } from "next"; -import { Inter } from "next/font/google"; +import localFont from "next/font/local"; import "./globals.css"; -const inter = Inter({ subsets: ["latin"] }); +const geistSans = localFont({ + src: "./fonts/GeistVF.woff", + variable: "--font-geist-sans", + weight: "100 900", +}); +const geistMono = localFont({ + src: "./fonts/GeistMonoVF.woff", + variable: "--font-geist-mono", + weight: "100 900", +}); export const metadata: Metadata = { - title: "Create Novu App", - description: "Generated by create novu app", + title: "Create Next App", + description: "Generated by create next app", }; export default function RootLayout({ @@ -16,7 +25,9 @@ export default function RootLayout({ }>) { return ( - {children} + + {children} + ); } diff --git a/packages/novu/src/commands/init/templates/app-react-email/ts/app/novu/workflows/welcome-onboarding-email/schemas.ts b/packages/novu/src/commands/init/templates/app-react-email/ts/app/novu/workflows/welcome-onboarding-email/schemas.ts index 7568126511e..34376685b6e 100644 --- a/packages/novu/src/commands/init/templates/app-react-email/ts/app/novu/workflows/welcome-onboarding-email/schemas.ts +++ b/packages/novu/src/commands/init/templates/app-react-email/ts/app/novu/workflows/welcome-onboarding-email/schemas.ts @@ -2,6 +2,18 @@ import { z } from "zod"; // Learn more about zod at the official website: https://zod.dev/ export const payloadSchema = z.object({ + inAppSubject: z + .string() + .describe("The subject of the notification") + .default("**Welcome to Novu!**"), + inAppBody: z + .string() + .describe("The body of the notification") + .default("This is an in-app notification powered by Novu."), + inAppAvatar: z + .string() + .describe("The avatar of the notification") + .default("https://avatars.githubusercontent.com/u/77433905?s=200&v=4"), teamImage: z .string() .url() diff --git a/packages/novu/src/commands/init/templates/app-react-email/ts/app/novu/workflows/welcome-onboarding-email/workflow.ts b/packages/novu/src/commands/init/templates/app-react-email/ts/app/novu/workflows/welcome-onboarding-email/workflow.ts index 02b60eeed30..c02c97b9b26 100644 --- a/packages/novu/src/commands/init/templates/app-react-email/ts/app/novu/workflows/welcome-onboarding-email/workflow.ts +++ b/packages/novu/src/commands/init/templates/app-react-email/ts/app/novu/workflows/welcome-onboarding-email/workflow.ts @@ -17,6 +17,14 @@ export const welcomeOnboardingEmail = workflow( controlSchema: emailControlSchema, }, ); + + await step.inApp("In-App Step", async () => { + return { + subject: payload.inAppSubject, + body: payload.inAppBody, + avatar: payload.inAppAvatar, + }; + }); }, { payloadSchema, diff --git a/packages/novu/src/commands/init/templates/app-react-email/ts/app/page.module.css b/packages/novu/src/commands/init/templates/app-react-email/ts/app/page.module.css new file mode 100644 index 00000000000..631465cd91f --- /dev/null +++ b/packages/novu/src/commands/init/templates/app-react-email/ts/app/page.module.css @@ -0,0 +1,437 @@ +.container { + min-height: 100vh; + background: #f8fafc; + display: flex; + flex-direction: column; +} + +.main { + flex: 1; + padding: 3rem 2rem; + display: flex; + justify-content: center; + align-items: center; +} + +.card { + width: 100%; + max-width: 64rem; + background: #ffffff; + border: 1px solid #e2e8f0; + border-radius: 1rem; + padding: 2rem; + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); +} + +.header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 2rem; +} + +.header h1 { + font-size: 1.875rem; + font-weight: 700; + color: #1e293b; + letter-spacing: -0.025em; +} + +.header p { + color: #64748b; + margin-top: 0.5rem; + font-size: 1.1rem; +} + +.content { + display: flex; + gap: 2rem; +} + +.infoSection { + flex: 1; + max-width: 32rem; +} + +.accordion { + border: 1px solid #e2e8f0; + border-radius: 8px; + margin-bottom: 1rem; + background: #ffffff; + overflow: hidden; +} + +.accordion:last-child { + margin-bottom: 0; +} + +.accordionHeader { + padding: 1rem; + cursor: pointer; + display: flex; + align-items: center; + justify-content: space-between; + font-weight: 800; + background: #ffffff; + border: none; + width: 100%; + text-align: left; + color: #334155; +} + +.accordionHeader:hover { + background: #f8fafc; +} + +.accordionContent { + padding: 0 1rem 1rem 1rem; + color: #64748b; +} + +.stepList { + display: flex; + flex-direction: column; + gap: 1rem; + margin-top: 1rem; + +} + +.step { + display: flex; + gap: 1rem; + align-items: flex-start; +} + +.stepNumber { + width: 28px; + height: 28px; + border-radius: 50%; + background: #f1f5f9; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + font-weight: 500; + font-size: 0.875rem; +} + +.stepContent { + flex: 1; + color: #334155; +} + +.stepTitle { + font-weight: 400; + margin-bottom: 0.25rem; + color: #1e293b; + +} + +.stepDescription { + color: #64748b; + font-size: 0.875rem; + line-height: 1.5; +} + +.codeBlock { + background: var(--muted-background); + padding: 1rem; + border-radius: 6px; + margin: 1rem 0; + font-family: monospace; + font-size: 0.875rem; +} + +.bulletList { + display: flex; + flex-direction: column; + gap: 0.5rem; + margin-top: 0.5rem; +} + +.bulletItem { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 0.875rem; + color: #64748b; + margin-bottom: 0.2rem; +} + +.bullet { + width: 6px; + height: 6px; + border-radius: 50%; + background: var(--primary); + flex-shrink: 0; +} + +.link { + display: inline-flex; + align-items: center; + gap: 0.5rem; + color: #0081f1; + font-size: 0.875rem; + text-decoration: none; + margin-top: 1rem; +} + +.link:hover { + opacity: 0.8; +} + +.description { + color: var(--muted-foreground); + font-size: 0.875rem; + line-height: 1.5; + margin-bottom: 1rem; +} + +.description a { + color: #0081f1; +} + +.divider { + width: 1px; + background: #e2e8f0; +} + +.buttonSection { + display: flex; + flex-direction: column; + margin-top: 1rem; + gap: 1rem; + align-items: flex-start; + padding: 1rem; + position: relative; + width: 400px; + height: 100%; +} + +.footer { + border-top: 1px solid #e2e8f0; + background: #eef2f5; + padding: 4rem 2rem 2rem; + margin-top: auto; +} + +.footerContent { + max-width: 72rem; + margin: 0 auto; + display: grid; + grid-template-columns: 2fr 1fr 1fr 1fr; + gap: 4rem; +} + +.footerLogo { + display: flex; + flex-direction: column; +} + +.footerLogo p { + color: #64748b; + font-size: 0.95rem; + line-height: 1.7; + max-width: 24rem; +} + +.socialLinks { + display: flex; + gap: 1rem; + margin-top: 0.5rem; +} + +.socialLinks a { + display: flex; + align-items: center; + justify-content: center; + width: 2.5rem; + height: 2.5rem; + border-radius: 0.5rem; + background: #ffffff; + border: 1px solid #e2e8f0; + color: #64748b; + transition: all 0.2s ease; +} + +.socialLinks a:hover { + background: #f8fafc; + color: #334155; + transform: translateY(-2px); + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); +} + +.footerSection h3 { + font-weight: 600; + margin-bottom: 1.5rem; + color: #1e293b; + font-size: 1.1rem; + letter-spacing: -0.01em; +} + +.footerSection ul { + list-style: none; + padding: 0; + display: flex; + flex-direction: column; + gap: 0.875rem; +} + +.footerSection li { + margin: 0; +} + +.footerSection a { + color: #64748b; + font-size: 0.95rem; + text-decoration: none; + transition: all 0.2s ease; + display: inline-flex; + align-items: center; + gap: 0.5rem; +} + +.footerSection a:hover { + color: #334155; +} + +.footerBottom { + margin-top: 4rem; + padding-top: 2rem; + border-top: 1px solid #e2e8f0; + display: flex; + justify-content: space-between; + align-items: center; + color: #64748b; + font-size: 0.875rem; +} + +.footerBottom a { + color: #64748b; + text-decoration: none; + transition: color 0.2s ease; +} + +.footerBottom a:hover { + color: #334155; +} + +@media (max-width: 1024px) { + .footerContent { + grid-template-columns: 1.5fr 1fr 1fr; + gap: 3rem; + } +} + +@media (max-width: 768px) { + .footerContent { + grid-template-columns: 1fr 1fr; + gap: 2.5rem; + } + + .footerLogo { + grid-column: 1 / -1; + } + + .footerBottom { + flex-direction: column; + gap: 1rem; + text-align: center; + } +} + +@media (max-width: 640px) { + .footerContent { + grid-template-columns: 1fr; + gap: 2rem; + } + + .footer { + padding: 3rem 1.5rem 1.5rem; + } +} + +.button { + display: inline-flex; + gap: 0.5rem; + padding: 0.75rem 1.5rem; + margin-top: 5rem; + font-size: 0.95rem; + font-weight: 500; + color: #ffffff; + background: #0081f1; + border: none; + border-radius: 0.5rem; + cursor: pointer; + transition: all 0.2s ease; + margin-left: 5rem; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +.button:hover { + background: #0081f1; + transform: translateY(-1px); + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); +} + +.button:active { + transform: translateY(0); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.button:disabled { + background: #94a3b8; + cursor: not-allowed; + transform: none; + box-shadow: none; +} + +.connectionMessage { + background: linear-gradient(135deg, #f8f9ff 0%, #f0f4ff 100%); + border: 1px solid #e0e7ff; + border-radius: 0.75rem; + margin-top: 1rem; + padding: 1rem 1.40rem; + display: flex; + align-items: center; + gap: 0.75rem; + box-shadow: 0 2px 8px rgba(79, 70, 229, 0.08); + width: 100%; + box-sizing: border-box; +} + +.connectionText { + color: #4B5563; + font-size: 0.95rem; + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.5rem; + width: 100%; +} + +.connectionText code { + background-color: rgba(255, 255, 255, 0.8); + padding: 0.375rem 0.75rem; + border-radius: 0.375rem; + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; + font-size: 0.9rem; + color: #4f46e5; + border: 1px solid rgba(224, 231, 255, 0.6); + font-weight: 500; +} + +.successMessage { + color: #16a34a; + margin-top: 8px; + margin-left: 5rem; + text-align: center; + font-size: 0.9rem; +} + +.complianceBadges { + display: flex; + gap: 1rem; + align-items: center; + margin-top: 0.5rem; +} \ No newline at end of file diff --git a/packages/novu/src/commands/init/templates/app-react-email/ts/app/page.tsx b/packages/novu/src/commands/init/templates/app-react-email/ts/app/page.tsx index 5705d4ea045..d93d5718b3c 100644 --- a/packages/novu/src/commands/init/templates/app-react-email/ts/app/page.tsx +++ b/packages/novu/src/commands/init/templates/app-react-email/ts/app/page.tsx @@ -1,113 +1,473 @@ +"use client"; + +import { useState, useEffect } from "react"; import Image from "next/image"; +import styles from "./page.module.css"; +import NotificationToast, { + NovuInbox, +} from "./components/NotificationToast/Notifications"; export default function Home() { + const [isNovuConnected, setIsNovuConnected] = useState(false); + const [showSuccess, setShowSuccess] = useState(false); + + useEffect(() => { + (async () => { + await fetch("/api/events", { + method: "POST", + body: JSON.stringify({ + event: "Starter Page Visit - [Next.js Starter]", + data: {}, + }), + }); + })(); + }, []); + + useEffect(() => { + const checkNovuConnection = async () => { + try { + const response = await fetch("/api/dev-studio-status"); + const data = await response.json(); + setIsNovuConnected(data.connected); + + if (!data.connected) { + console.log("Novu connection failed:", data.error); + } + } catch (error) { + console.error("Novu connection error:", error); + setIsNovuConnected(false); + } + }; + + checkNovuConnection(); + const interval = setInterval(checkNovuConnection, 3000); + + return () => clearInterval(interval); + }, []); + + const triggerNotification = async () => { + try { + const response = await fetch("/api/trigger", { + method: "POST", + }); + + if (!response.ok) { + throw new Error("Failed to trigger notification"); + } + + const data = await response.json(); + console.log("Notification triggered:", data); + setShowSuccess(true); + setTimeout(() => setShowSuccess(false), 3000); // Hide after 3 seconds + + await fetch("/api/events", { + method: "POST", + body: JSON.stringify({ + event: "Notification Triggered - [Next.js Starter]", + data: {}, + }), + }); + } catch (error) { + console.error("Error triggering notification:", error); + } + }; + return ( -
-
-

- Get started by editing  - app/page.tsx -

-
- - By{" "} - Vercel Logo - +
+ +
+
+ {/* Header */} +
+
+

Novu + Next.js Starter

+

Trigger notifications with a single button

+
+ +
+ {/* Content */} +
+ {/* Info Section */} +
+ {/* Create a workflow */} +
+ + Create a workflow + +
+

+ In Novu, all notifications are sent via a workflow. Each + workflow acts as a container for the logic and templates + that are associated with a kind of notification in your + system. +

+
+
+
1
+
+
+ Name and Identifier +
+

+ Every workflow will have a name and trigger + identifier. The workflow trigger identifier is used to + uniquely identify each workflow. +

+
+
+ +
+
2
+
+
Trigger
+

+ The Trigger refers to an event or action that + initiates the workflow. It signifies a call to the + Novu API with a specified workflow trigger identifier. +

+
+
+ +
+
3
+
+
Steps
+

+ Within the Novu framework, steps are categorized into + various types, each of which is linked with at least + one corresponding action. +

+
+
+
+ + + Learn more about workflows + + + + +
+
+ {/* Add Inbox to your app */} +
+ + Add In-App notifications + +
+

+ The Inbox component enables a rich context-aware in-app + notifications center directly in your application, and with + minimal effort. +

+
+                    {``}
+                  
+
+

+ Check out the{" "} + + Inbox Playground + + . You can customize the Inbox component to match your + application's design. +

+
+ + Learn more about Inbox + + + + +
+
+ {/* Digest multiple notifications */} +
+ + Digest multiple notifications + +
+

+ The digest engine collects multiple trigger events, + aggregates them into a single message and delivers it to the + subscriber. +

+
+ Example: +

+ A user receives 100 notifications in a short amount of + time, but you only want to notify them once per hour. +

+
+ + Learn more about Digest + + + + +
+
+ {/* Schedule / Delay notifications */} +
+ + Schedule / Delay notifications + +
+

+ The schedule or delay{" "} + action awaits a specified amount of time before moving on to + trigger the following steps of the workflow. +

+ +

Common Use Cases:

+
    +
  • +
    - Send a follow-up + email 24 hours after user registration +
  • +
  • +
    - Trigger a reminder + notification if user hasn't completed an action +
  • +
  • +
    - Schedule + notifications for specific dates +
  • +
  • +
    - Allow the user some + time to cancel an action +
  • +
+ + + Learn more about Delay + + + + +
+
+ {/* Preferences */} +
+ + Preferences + +
+

+ Novu provides a way to store subscriber preferences. This + allows subscribers, your users, to specify and manage their + preferences and customize their notifications experience. +

+ +

Levels of preferences:

+
    +
  • +
    - Workflow channel + preferences +
  • +
  • +
    - Subscriber channel + preferences per workflow +
  • +
  • +
    - Subscriber global + preferences +
  • +
+ + + Learn more about Preferences + + + + +
+
+
+ +
+ +
+ {isNovuConnected ? ( + <> + + {showSuccess && ( +

+ ✓ Notification triggered successfully! +

+ )} + + ) : ( +
+
+
+

Connection Required

+
+

Run the following command to start:

+ + npx novu@latest dev --port 4000 + +
+
+ )} +
+
+
+
+ +
- -
- Next.js Logo -
- - -
+ + ); } diff --git a/packages/novu/src/commands/init/templates/app-react-email/ts/public/file.svg b/packages/novu/src/commands/init/templates/app-react-email/ts/public/file.svg new file mode 100644 index 00000000000..004145cddf3 --- /dev/null +++ b/packages/novu/src/commands/init/templates/app-react-email/ts/public/file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/novu/src/commands/init/templates/app-react-email/ts/public/globe.svg b/packages/novu/src/commands/init/templates/app-react-email/ts/public/globe.svg new file mode 100644 index 00000000000..567f17b0d7c --- /dev/null +++ b/packages/novu/src/commands/init/templates/app-react-email/ts/public/globe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/novu/src/commands/init/templates/app-react-email/ts/public/novu.svg b/packages/novu/src/commands/init/templates/app-react-email/ts/public/novu.svg new file mode 100644 index 00000000000..a3fb4b72b4e --- /dev/null +++ b/packages/novu/src/commands/init/templates/app-react-email/ts/public/novu.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/novu/src/commands/init/templates/app-react-email/ts/public/vercel.svg b/packages/novu/src/commands/init/templates/app-react-email/ts/public/vercel.svg index d2f84222734..77053960334 100644 --- a/packages/novu/src/commands/init/templates/app-react-email/ts/public/vercel.svg +++ b/packages/novu/src/commands/init/templates/app-react-email/ts/public/vercel.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/packages/novu/src/commands/init/templates/app-react-email/ts/public/window.svg b/packages/novu/src/commands/init/templates/app-react-email/ts/public/window.svg new file mode 100644 index 00000000000..b2b2a44f6eb --- /dev/null +++ b/packages/novu/src/commands/init/templates/app-react-email/ts/public/window.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/novu/src/commands/init/templates/app/ts/.env.example b/packages/novu/src/commands/init/templates/app/ts/.env.example deleted file mode 100644 index ce586fad292..00000000000 --- a/packages/novu/src/commands/init/templates/app/ts/.env.example +++ /dev/null @@ -1,3 +0,0 @@ -# Rename this file to `.env.local` to use environment variables locally with `next dev` -# https://nextjs.org/docs/app/building-your-application/configuring/environment-variables -MY_HOST="example.com" diff --git a/packages/novu/src/commands/init/templates/app/ts/README-template.md b/packages/novu/src/commands/init/templates/app/ts/README-template.md deleted file mode 100644 index fe81da46744..00000000000 --- a/packages/novu/src/commands/init/templates/app/ts/README-template.md +++ /dev/null @@ -1,31 +0,0 @@ -# Novu Bridge App - -This is a [Novu](https://novu.co/) bridge application bootstrapped with [`npx novu init`](https://www.npmjs.com/package/novu) - -## Getting Started - -To run the development server, run: - -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev -``` - -By default, the [Next.js](https://nextjs.org/) server will start and your state can be synchronized with Novu Cloud via the Bridge Endpoint (default is `/api/novu`). Your server will by default run on [http://localhost:4000](http://localhost:4000). - -## Your first workflow - -Your first email workflow can be edited in `./app/novu/workflows.ts`. You can adjust your workflow to your liking. - -## Learn More - -To learn more about Novu, take a look at the following resources: - -- [Novu](https://novu.co/) - -You can check out [Novu GitHub repository](https://github.com/novuhq/novu) - your feedback and contributions are welcome! diff --git a/packages/novu/src/commands/init/templates/app/ts/app/api/novu/route.ts b/packages/novu/src/commands/init/templates/app/ts/app/api/novu/route.ts deleted file mode 100644 index 1d917a15e6e..00000000000 --- a/packages/novu/src/commands/init/templates/app/ts/app/api/novu/route.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { serve } from "@novu/framework/next"; -import { myWorkflow } from "../../novu/workflows"; - -export const { GET, POST, OPTIONS } = serve({ workflows: [myWorkflow] }); diff --git a/packages/novu/src/commands/init/templates/app/ts/app/favicon.ico b/packages/novu/src/commands/init/templates/app/ts/app/favicon.ico deleted file mode 100644 index 718d6fea4835ec2d246af9800eddb7ffb276240c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25931 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 LrJugUA?W`A8`#=m diff --git a/packages/novu/src/commands/init/templates/app/ts/app/globals.css b/packages/novu/src/commands/init/templates/app/ts/app/globals.css deleted file mode 100644 index f4bd77c0cca..00000000000 --- a/packages/novu/src/commands/init/templates/app/ts/app/globals.css +++ /dev/null @@ -1,107 +0,0 @@ -:root { - --max-width: 1100px; - --border-radius: 12px; - --font-mono: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", - "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro", - "Fira Mono", "Droid Sans Mono", "Courier New", monospace; - - --foreground-rgb: 0, 0, 0; - --background-start-rgb: 214, 219, 220; - --background-end-rgb: 255, 255, 255; - - --primary-glow: conic-gradient( - from 180deg at 50% 50%, - #16abff33 0deg, - #0885ff33 55deg, - #54d6ff33 120deg, - #0071ff33 160deg, - transparent 360deg - ); - --secondary-glow: radial-gradient( - rgba(255, 255, 255, 1), - rgba(255, 255, 255, 0) - ); - - --tile-start-rgb: 239, 245, 249; - --tile-end-rgb: 228, 232, 233; - --tile-border: conic-gradient( - #00000080, - #00000040, - #00000030, - #00000020, - #00000010, - #00000010, - #00000080 - ); - - --callout-rgb: 238, 240, 241; - --callout-border-rgb: 172, 175, 176; - --card-rgb: 180, 185, 188; - --card-border-rgb: 131, 134, 135; -} - -@media (prefers-color-scheme: dark) { - :root { - --foreground-rgb: 255, 255, 255; - --background-start-rgb: 0, 0, 0; - --background-end-rgb: 0, 0, 0; - - --primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0)); - --secondary-glow: linear-gradient( - to bottom right, - rgba(1, 65, 255, 0), - rgba(1, 65, 255, 0), - rgba(1, 65, 255, 0.3) - ); - - --tile-start-rgb: 2, 13, 46; - --tile-end-rgb: 2, 5, 19; - --tile-border: conic-gradient( - #ffffff80, - #ffffff40, - #ffffff30, - #ffffff20, - #ffffff10, - #ffffff10, - #ffffff80 - ); - - --callout-rgb: 20, 20, 20; - --callout-border-rgb: 108, 108, 108; - --card-rgb: 100, 100, 100; - --card-border-rgb: 200, 200, 200; - } -} - -* { - box-sizing: border-box; - padding: 0; - margin: 0; -} - -html, -body { - max-width: 100vw; - overflow-x: hidden; -} - -body { - color: rgb(var(--foreground-rgb)); - background: linear-gradient( - to bottom, - transparent, - rgb(var(--background-end-rgb)) - ) - rgb(var(--background-start-rgb)); -} - -a { - color: inherit; - text-decoration: none; -} - -@media (prefers-color-scheme: dark) { - html { - color-scheme: dark; - } -} diff --git a/packages/novu/src/commands/init/templates/app/ts/app/layout.tsx b/packages/novu/src/commands/init/templates/app/ts/app/layout.tsx deleted file mode 100644 index 2010b28c893..00000000000 --- a/packages/novu/src/commands/init/templates/app/ts/app/layout.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import type { Metadata } from "next"; -import { Inter } from "next/font/google"; -import "./globals.css"; - -const inter = Inter({ subsets: ["latin"] }); - -export const metadata: Metadata = { - title: "Create Novu App", - description: "Generated by create novu app", -}; - -export default function RootLayout({ - children, -}: Readonly<{ - children: React.ReactNode; -}>) { - return ( - - {children} - - ); -} diff --git a/packages/novu/src/commands/init/templates/app/ts/app/novu/workflows.ts b/packages/novu/src/commands/init/templates/app/ts/app/novu/workflows.ts deleted file mode 100644 index aa297e2357c..00000000000 --- a/packages/novu/src/commands/init/templates/app/ts/app/novu/workflows.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* eslint-disable max-len */ -import { workflow } from "@novu/framework"; - -export const myWorkflow = workflow("onboarding", async ({ step }) => { - await step.email("send-email", async () => { - return { - subject: "Welcome to Novu! Ready to code?", - body: ` - - Notification workflows rooted in how YOU work - - - - -
- -
-

Notification workflows rooted in how YOU work

-

Hi!

-

Good to have you here! We continuously work on giving you the flexibility to - build any notification setup you need - through code, right from your IDE - and to give your managers an easy way to adjust the notification content. Check - out our docs to learn more.

-

Questions or problems? Our Discord support channel is here for you.

-

Feedback? Head over to our public roadmap to submit it, or simply poke us on Discord or via email. We’re here to make your life easier!

-

Cheers,
Novu Team

- - `, - }; - }); -}); diff --git a/packages/novu/src/commands/init/templates/app/ts/app/page.module.css b/packages/novu/src/commands/init/templates/app/ts/app/page.module.css deleted file mode 100644 index 5c4b1e6a2c6..00000000000 --- a/packages/novu/src/commands/init/templates/app/ts/app/page.module.css +++ /dev/null @@ -1,230 +0,0 @@ -.main { - display: flex; - flex-direction: column; - justify-content: space-between; - align-items: center; - padding: 6rem; - min-height: 100vh; -} - -.description { - display: inherit; - justify-content: inherit; - align-items: inherit; - font-size: 0.85rem; - max-width: var(--max-width); - width: 100%; - z-index: 2; - font-family: var(--font-mono); -} - -.description a { - display: flex; - justify-content: center; - align-items: center; - gap: 0.5rem; -} - -.description p { - position: relative; - margin: 0; - padding: 1rem; - background-color: rgba(var(--callout-rgb), 0.5); - border: 1px solid rgba(var(--callout-border-rgb), 0.3); - border-radius: var(--border-radius); -} - -.code { - font-weight: 700; - font-family: var(--font-mono); -} - -.grid { - display: grid; - grid-template-columns: repeat(4, minmax(25%, auto)); - max-width: 100%; - width: var(--max-width); -} - -.card { - padding: 1rem 1.2rem; - border-radius: var(--border-radius); - background: rgba(var(--card-rgb), 0); - border: 1px solid rgba(var(--card-border-rgb), 0); - transition: background 200ms, border 200ms; -} - -.card span { - display: inline-block; - transition: transform 200ms; -} - -.card h2 { - font-weight: 600; - margin-bottom: 0.7rem; -} - -.card p { - margin: 0; - opacity: 0.6; - font-size: 0.9rem; - line-height: 1.5; - max-width: 30ch; - text-wrap: balance; -} - -.center { - display: flex; - justify-content: center; - align-items: center; - position: relative; - padding: 4rem 0; -} - -.center::before { - background: var(--secondary-glow); - border-radius: 50%; - width: 480px; - height: 360px; - margin-left: -400px; -} - -.center::after { - background: var(--primary-glow); - width: 240px; - height: 180px; - z-index: -1; -} - -.center::before, -.center::after { - content: ""; - left: 50%; - position: absolute; - filter: blur(45px); - transform: translateZ(0); -} - -.logo { - position: relative; -} -/* Enable hover only on non-touch devices */ -@media (hover: hover) and (pointer: fine) { - .card:hover { - background: rgba(var(--card-rgb), 0.1); - border: 1px solid rgba(var(--card-border-rgb), 0.15); - } - - .card:hover span { - transform: translateX(4px); - } -} - -@media (prefers-reduced-motion) { - .card:hover span { - transform: none; - } -} - -/* Mobile */ -@media (max-width: 700px) { - .content { - padding: 4rem; - } - - .grid { - grid-template-columns: 1fr; - margin-bottom: 120px; - max-width: 320px; - text-align: center; - } - - .card { - padding: 1rem 2.5rem; - } - - .card h2 { - margin-bottom: 0.5rem; - } - - .center { - padding: 8rem 0 6rem; - } - - .center::before { - transform: none; - height: 300px; - } - - .description { - font-size: 0.8rem; - } - - .description a { - padding: 1rem; - } - - .description p, - .description div { - display: flex; - justify-content: center; - position: fixed; - width: 100%; - } - - .description p { - align-items: center; - inset: 0 0 auto; - padding: 2rem 1rem 1.4rem; - border-radius: 0; - border: none; - border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25); - background: linear-gradient( - to bottom, - rgba(var(--background-start-rgb), 1), - rgba(var(--callout-rgb), 0.5) - ); - background-clip: padding-box; - backdrop-filter: blur(24px); - } - - .description div { - align-items: flex-end; - pointer-events: none; - inset: auto 0 0; - padding: 2rem; - height: 200px; - background: linear-gradient( - to bottom, - transparent 0%, - rgb(var(--background-end-rgb)) 40% - ); - z-index: 1; - } -} - -/* Tablet and Smaller Desktop */ -@media (min-width: 701px) and (max-width: 1120px) { - .grid { - grid-template-columns: repeat(2, 50%); - } -} - -@media (prefers-color-scheme: dark) { - .vercelLogo { - filter: invert(1); - } - - .logo { - filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70); - } -} - -@keyframes rotate { - from { - transform: rotate(360deg); - } - to { - transform: rotate(0deg); - } -} diff --git a/packages/novu/src/commands/init/templates/app/ts/app/page.tsx b/packages/novu/src/commands/init/templates/app/ts/app/page.tsx deleted file mode 100644 index 810709063d5..00000000000 --- a/packages/novu/src/commands/init/templates/app/ts/app/page.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import Image from "next/image"; -import styles from "./page.module.css"; - -export default function Home() { - return ( -
-
-

- Get started by editing  - app/page.tsx -

- -
- -
- Next.js Logo -
- - -
- ); -} diff --git a/packages/novu/src/commands/init/templates/app/ts/eslintrc.json b/packages/novu/src/commands/init/templates/app/ts/eslintrc.json deleted file mode 100644 index bffb357a712..00000000000 --- a/packages/novu/src/commands/init/templates/app/ts/eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "next/core-web-vitals" -} diff --git a/packages/novu/src/commands/init/templates/app/ts/gitignore b/packages/novu/src/commands/init/templates/app/ts/gitignore deleted file mode 100644 index fd3dbb571a1..00000000000 --- a/packages/novu/src/commands/init/templates/app/ts/gitignore +++ /dev/null @@ -1,36 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js -.yarn/install-state.gz - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# local env files -.env*.local - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts diff --git a/packages/novu/src/commands/init/templates/app/ts/next-env.d.ts b/packages/novu/src/commands/init/templates/app/ts/next-env.d.ts deleted file mode 100644 index 2c37b401d72..00000000000 --- a/packages/novu/src/commands/init/templates/app/ts/next-env.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -/// -/// - -/* - * NOTE: This file should not be edited - * see https://nextjs.org/docs/basic-features/typescript for more information. - */ diff --git a/packages/novu/src/commands/init/templates/app/ts/next.config.mjs b/packages/novu/src/commands/init/templates/app/ts/next.config.mjs deleted file mode 100644 index 4678774e6d6..00000000000 --- a/packages/novu/src/commands/init/templates/app/ts/next.config.mjs +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = {}; - -export default nextConfig; diff --git a/packages/novu/src/commands/init/templates/app/ts/public/next.svg b/packages/novu/src/commands/init/templates/app/ts/public/next.svg deleted file mode 100644 index 5174b28c565..00000000000 --- a/packages/novu/src/commands/init/templates/app/ts/public/next.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/novu/src/commands/init/templates/app/ts/public/vercel.svg b/packages/novu/src/commands/init/templates/app/ts/public/vercel.svg deleted file mode 100644 index d2f84222734..00000000000 --- a/packages/novu/src/commands/init/templates/app/ts/public/vercel.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/novu/src/commands/init/templates/app/ts/tsconfig.json b/packages/novu/src/commands/init/templates/app/ts/tsconfig.json deleted file mode 100644 index e7ff90fd276..00000000000 --- a/packages/novu/src/commands/init/templates/app/ts/tsconfig.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "incremental": true, - "plugins": [ - { - "name": "next" - } - ], - "paths": { - "@/*": ["./*"] - } - }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] -} diff --git a/packages/novu/src/commands/init/templates/index.ts b/packages/novu/src/commands/init/templates/index.ts index 71d71b8b57b..9524a0dcde0 100644 --- a/packages/novu/src/commands/init/templates/index.ts +++ b/packages/novu/src/commands/init/templates/index.ts @@ -39,6 +39,8 @@ export const installTemplate = async ({ srcDir, importAlias, secretKey, + applicationId, + userId, }: InstallTemplateArgs) => { console.log(bold(`Using ${packageManager}.`)); @@ -170,6 +172,8 @@ export const installTemplate = async ({ /* write .env file */ const val = Object.entries({ NOVU_SECRET_KEY: secretKey, + NEXT_PUBLIC_NOVU_APPLICATION_IDENTIFIER: applicationId, + NEXT_PUBLIC_NOVU_SUBSCRIBER_ID: userId, }).reduce((acc, [key, value]) => { return `${acc}${key}=${value}${os.EOL}`; }, ""); @@ -204,6 +208,7 @@ export const installTemplate = async ({ "react-dom": "^18", next: version, "@novu/framework": "latest", + "@novu/nextjs": "^2.5.0", }, devDependencies: {}, }; diff --git a/packages/novu/src/commands/init/templates/types.ts b/packages/novu/src/commands/init/templates/types.ts index e3d97de97bd..53d740bef88 100644 --- a/packages/novu/src/commands/init/templates/types.ts +++ b/packages/novu/src/commands/init/templates/types.ts @@ -29,4 +29,6 @@ export interface InstallTemplateArgs { srcDir: boolean; importAlias: string; secretKey: string; + applicationId: string; + userId: string; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4b208e218a5..89276a512da 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -338,7 +338,7 @@ importers: version: 7.1.0 ts-jest: specifier: 27.1.5 - version: 27.1.5(@babel/core@7.25.2)(@types/jest@29.5.13)(babel-jest@27.5.1(@babel/core@7.25.2))(jest@29.7.0(@types/node@18.16.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2) + version: 27.1.5(@babel/core@7.24.3)(@types/jest@29.5.13)(babel-jest@27.5.1(@babel/core@7.24.3))(jest@29.7.0(@types/node@18.16.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2) ts-node: specifier: ~10.9.1 version: 10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2) @@ -1014,13 +1014,13 @@ importers: dependencies: '@babel/plugin-proposal-optional-chaining': specifier: ^7.20.7 - version: 7.21.0(@babel/core@7.21.4) + version: 7.21.0(@babel/core@7.22.11) '@babel/plugin-transform-react-display-name': specifier: ^7.18.6 - version: 7.18.6(@babel/core@7.21.4) + version: 7.18.6(@babel/core@7.22.11) '@babel/plugin-transform-runtime': specifier: ^7.23.2 - version: 7.23.2(@babel/core@7.21.4) + version: 7.23.2(@babel/core@7.22.11) '@clerk/clerk-js': specifier: ^5.10.0 version: 5.10.1(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -1209,7 +1209,7 @@ importers: version: 11.9.0 html-webpack-plugin: specifier: 5.5.3 - version: 5.5.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + version: 5.5.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) js-cookie: specifier: ^3.0.5 version: 3.0.5 @@ -1245,7 +1245,7 @@ importers: version: 4.3.2 mdx-bundler: specifier: 10.0.2 - version: 10.0.2(esbuild@0.23.1) + version: 10.0.2(esbuild@0.18.20) mixpanel-browser: specifier: ^2.52.0 version: 2.53.0 @@ -1348,13 +1348,13 @@ importers: version: 7.12.1 '@babel/preset-env': specifier: ^7.23.2 - version: 7.23.2(@babel/core@7.21.4) + version: 7.23.2(@babel/core@7.22.11) '@babel/preset-react': specifier: ^7.13.13 - version: 7.18.6(@babel/core@7.21.4) + version: 7.18.6(@babel/core@7.22.11) '@babel/preset-typescript': specifier: ^7.13.0 - version: 7.21.4(@babel/core@7.21.4) + version: 7.21.4(@babel/core@7.22.11) '@babel/runtime': specifier: ^7.20.13 version: 7.21.0 @@ -1399,13 +1399,13 @@ importers: version: 7.4.2 '@storybook/preset-create-react-app': specifier: ^7.4.2 - version: 7.4.2(f7avyblvzm233o6g7idqcb345u) + version: 7.4.2(ucmnrhmq4kewpo24xrp57f5r6y) '@storybook/react': specifier: ^7.4.2 version: 7.4.2(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2) '@storybook/react-webpack5': specifier: ^7.4.2 - version: 7.4.2(@babel/core@7.21.4)(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1))(encoding@0.1.13)(esbuild@0.23.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)))(webpack-hot-middleware@2.26.1) + version: 7.4.2(@babel/core@7.22.11)(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20))(encoding@0.1.13)(esbuild@0.18.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)))(webpack-hot-middleware@2.26.1) '@testing-library/jest-dom': specifier: ^4.2.4 version: 4.2.4 @@ -1432,16 +1432,16 @@ importers: version: 0.13.0 less-loader: specifier: 4.1.0 - version: 4.1.0(less@4.1.3)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + version: 4.1.0(less@4.1.3)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) react-app-rewired: specifier: ^2.2.1 - version: 2.2.1(react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.21.4))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.21.4))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1))(esbuild@0.23.1)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1)) + version: 2.2.1(react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.22.11))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.22.11))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20))(esbuild@0.18.20)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1)) react-error-overlay: specifier: 6.0.11 version: 6.0.11 react-scripts: specifier: ^5.0.1 - version: 5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.21.4))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.21.4))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1))(esbuild@0.23.1)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1) + version: 5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.22.11))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.22.11))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20))(esbuild@0.18.20)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1) sinon: specifier: 9.2.4 version: 9.2.4 @@ -1453,13 +1453,13 @@ importers: version: 5.6.2 webpack: specifier: 5.78.0 - version: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + version: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) webpack-bundle-analyzer: specifier: ^4.9.0 version: 4.9.0 webpack-dev-server: specifier: 4.11.1 - version: 4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + version: 4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) apps/webhook: dependencies: @@ -1758,34 +1758,34 @@ importers: version: 1.14.2 html-webpack-plugin: specifier: 5.5.3 - version: 5.5.3(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) + version: 5.5.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) http-server: specifier: ^0.13.0 version: 0.13.0 jest: specifier: 27.5.1 - version: 27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) + version: 27.5.1(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) less: specifier: ^4.1.0 version: 4.1.3 less-loader: specifier: 4.1.0 - version: 4.1.0(less@4.1.3)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) + version: 4.1.0(less@4.1.3)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) react-app-rewired: specifier: ^2.2.1 - version: 2.2.1(react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12)))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1)) + version: 2.2.1(react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12)))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1)) react-scripts: specifier: ^5.0.1 - version: 5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12)))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1) + version: 5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12)))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1) typescript: specifier: 5.6.2 version: 5.6.2 webpack: specifier: 5.78.0 - version: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + version: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) webpack-dev-server: specifier: 4.11.1 - version: 4.11.1(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) + version: 4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) apps/worker: dependencies: @@ -2777,7 +2777,7 @@ importers: version: 20.16.5 jest: specifier: ^29.4.1 - version: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) + version: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) jest-environment-jsdom: specifier: ^29.4.1 version: 29.5.0 @@ -2789,7 +2789,7 @@ importers: version: 16.10.0(@swc-node/register@1.8.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.3.107(@swc/helpers@0.5.12)) ts-jest: specifier: ^29.1.0 - version: 29.1.2(@babel/core@7.24.4)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.4))(jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2) + version: 29.1.2(@babel/core@7.25.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2) typescript: specifier: 5.6.2 version: 5.6.2 @@ -2947,13 +2947,13 @@ importers: version: 7.4.2(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2) '@storybook/react-webpack5': specifier: ^7.4.2 - version: 7.4.2(@babel/core@7.22.11)(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20))(encoding@0.1.13)(esbuild@0.18.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)))(webpack-hot-middleware@2.26.1) + version: 7.4.2(@babel/core@7.23.2)(@swc/core@1.7.26(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12)))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-hot-middleware@2.26.1) '@storybook/theming': specifier: ^7.4.2 version: 7.4.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@testing-library/jest-dom': specifier: ^6.4.1 - version: 6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.13)(jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(vitest@1.2.1(@edge-runtime/vm@4.0.2)(@types/node@20.16.5)(jsdom@24.0.0)(less@4.2.0)(lightningcss@1.26.0)(sass@1.77.8)(sugarss@4.0.1(postcss@8.4.47))(terser@5.31.6)) + version: 6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.13)(jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(vitest@1.2.1(@edge-runtime/vm@4.0.2)(@types/node@20.16.5)(jsdom@24.0.0)(less@4.2.0)(lightningcss@1.26.0)(sass@1.77.8)(sugarss@4.0.1(postcss@8.4.47))(terser@5.31.6)) '@testing-library/react': specifier: ^12.1.5 version: 12.1.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -2998,13 +2998,13 @@ importers: version: 7.4.2(encoding@0.1.13) ts-loader: specifier: ~9.4.0 - version: 9.4.4(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) + version: 9.4.4(typescript@5.6.2)(webpack@5.94.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) typescript: specifier: 5.6.2 version: 5.6.2 url-loader: specifier: ^4.1.1 - version: 4.1.1(file-loader@6.2.0(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)))(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) + version: 4.1.1(file-loader@6.2.0(webpack@5.94.0(@swc/core@1.7.26(@swc/helpers@0.5.12))))(webpack@5.94.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) vite: specifier: ^4.5.2 version: 4.5.2(@types/node@20.16.5)(less@4.2.0)(lightningcss@1.26.0)(sass@1.77.8)(sugarss@4.0.1(postcss@8.4.47))(terser@5.31.6) @@ -3195,7 +3195,7 @@ importers: version: 8.1.1 '@testing-library/jest-dom': specifier: ^6.4.1 - version: 6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.13)(jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(vitest@1.2.1(@edge-runtime/vm@4.0.2)(@types/node@20.16.5)(jsdom@25.0.0)(less@4.2.0)(lightningcss@1.26.0)(sass@1.77.8)(sugarss@4.0.1(postcss@8.4.38))(terser@5.31.6)) + version: 6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.13)(jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(vitest@1.2.1(@edge-runtime/vm@4.0.2)(@types/node@20.16.5)(jsdom@25.0.0)(less@4.2.0)(lightningcss@1.26.0)(sass@1.77.8)(sugarss@4.0.1(postcss@8.4.38))(terser@5.31.6)) '@testing-library/react': specifier: ^12.1.5 version: 12.1.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -3374,7 +3374,7 @@ importers: version: 3.8.3(encoding@0.1.13) jest: specifier: ^27.0.6 - version: 27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) + version: 27.5.1(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) npm-run-all: specifier: ^4.1.5 version: 4.1.5 @@ -3383,7 +3383,7 @@ importers: version: 3.0.2 ts-jest: specifier: ^27.0.5 - version: 27.1.5(@babel/core@7.25.2)(@types/jest@29.5.2)(babel-jest@27.5.1(@babel/core@7.25.2))(jest@27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2) + version: 27.1.5(@babel/core@7.25.2)(@types/jest@29.5.2)(babel-jest@27.5.1(@babel/core@7.25.2))(jest@27.5.1(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2) typedoc: specifier: ^0.24.0 version: 0.24.6(typescript@5.6.2) @@ -3462,7 +3462,7 @@ importers: version: 8.0.0(typescript@5.6.2) next: specifier: ^13.5.4 - version: 13.5.6(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8) + version: 13.5.6(@babel/core@7.24.3)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8) prettier: specifier: ^3.2.5 version: 3.3.2 @@ -3523,7 +3523,7 @@ importers: version: 29.5.0 ts-jest: specifier: ^29.0.3 - version: 29.1.0(@babel/core@7.25.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(esbuild@0.18.20)(jest@29.5.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2) + version: 29.1.0(@babel/core@7.25.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.5.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2) typedoc: specifier: ^0.24.0 version: 0.24.6(typescript@5.6.2) @@ -3723,7 +3723,7 @@ importers: version: link:../react next: specifier: '>=13' - version: 13.5.6(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8) + version: 13.5.6(@babel/core@7.24.3)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8) react: specifier: '>=17' version: 18.3.1 @@ -3794,7 +3794,7 @@ importers: version: 3.8.3(encoding@0.1.13) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) + version: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) nock: specifier: ^13.1.3 version: 13.3.0 @@ -3812,7 +3812,7 @@ importers: version: 0.0.0 ts-jest: specifier: ^29.1.2 - version: 29.1.2(@babel/core@7.25.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2) + version: 29.1.2(@babel/core@7.25.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(esbuild@0.23.1)(jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2) typedoc: specifier: ^0.24.0 version: 0.24.6(typescript@5.6.2) @@ -3903,7 +3903,7 @@ importers: version: 7.4.2(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2) '@storybook/react-webpack5': specifier: ^7.4.2 - version: 7.4.2(@babel/core@7.25.2)(@swc/core@1.7.26(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0)))(encoding@0.1.13)(esbuild@0.18.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0))(webpack-dev-server@4.11.1(webpack-cli@5.1.4)(webpack@5.78.0))(webpack-hot-middleware@2.26.1) + version: 7.4.2(@babel/core@7.25.2)(@swc/core@1.7.26(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0)))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0))(webpack-hot-middleware@2.26.1) '@testing-library/dom': specifier: ^9.3.0 version: 9.3.0 @@ -3936,10 +3936,10 @@ importers: version: 8.8.2 babel-loader: specifier: ^8.2.4 - version: 8.3.0(@babel/core@7.25.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) + version: 8.3.0(@babel/core@7.25.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) compression-webpack-plugin: specifier: ^10.0.0 - version: 10.0.0(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) + version: 10.0.0(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) jest: specifier: ^29.3.1 version: 29.5.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) @@ -3963,28 +3963,28 @@ importers: version: 7.4.2(encoding@0.1.13) terser-webpack-plugin: specifier: ^5.3.9 - version: 5.3.10(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) + version: 5.3.10(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) ts-jest: specifier: ^29.0.3 - version: 29.1.0(@babel/core@7.25.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(esbuild@0.18.20)(jest@29.5.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2) + version: 29.1.0(@babel/core@7.25.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.5.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2) ts-loader: specifier: ~9.4.0 - version: 9.4.4(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) + version: 9.4.4(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) typescript: specifier: 5.6.2 version: 5.6.2 url-loader: specifier: ^4.1.1 - version: 4.1.1(file-loader@6.2.0(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) + version: 4.1.1(file-loader@6.2.0(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) webpack: specifier: ^5.74.0 - version: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) + version: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) webpack-bundle-analyzer: specifier: ^4.9.0 version: 4.9.0 webpack-cli: specifier: ^5.1.4 - version: 5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0) + version: 5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0) packages/novu: dependencies: @@ -3992,8 +3992,8 @@ importers: specifier: ^0.0.4 version: 0.0.4 '@novu/shared': - specifier: workspace:* - version: link:../shared + specifier: 2.1.1 + version: 2.1.1(@nestjs/common@10.4.1(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.1(@nestjs/common@10.4.1(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.1)(@nestjs/websockets@10.4.1)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2) '@segment/analytics-node': specifier: ^1.1.4 version: 1.1.4(encoding@0.1.13) @@ -4404,7 +4404,7 @@ importers: version: 3.8.3(encoding@0.1.13) jest: specifier: ^27.0.6 - version: 27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) + version: 27.5.1(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) npm-run-all: specifier: ^4.1.5 version: 4.1.5 @@ -4419,7 +4419,7 @@ importers: version: 0.0.0 ts-jest: specifier: ^27.0.5 - version: 27.1.5(@babel/core@7.25.2)(@types/jest@29.5.2)(babel-jest@27.5.1(@babel/core@7.25.2))(jest@27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2) + version: 27.1.5(@babel/core@7.25.2)(@types/jest@29.5.2)(babel-jest@27.5.1(@babel/core@7.25.2))(jest@27.5.1(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2) typedoc: specifier: ^0.24.0 version: 0.24.6(typescript@5.6.2) @@ -4534,7 +4534,7 @@ importers: version: 0.439.0(react@18.3.1) next: specifier: 14.2.4 - version: 14.2.4(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(@playwright/test@1.46.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8) + version: 14.2.4(@babel/core@7.24.3)(@opentelemetry/api@1.9.0)(@playwright/test@1.46.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8) react: specifier: ^18 version: 18.3.1 @@ -10397,6 +10397,9 @@ packages: resolution: {integrity: sha512-/9q+qGFHHFwMsuqoLwTADMjSx2JPagpJpm7jOZRzQZgSEDg9kwNAhADneRzVYhMyjdEXIQyjTmX/oP8ABAavFw==} engines: {node: '>=18.0.0'} + '@novu/shared@2.1.1': + resolution: {integrity: sha512-jwwtFezpy7ofTQJ9ibatcUzz163/KHqhwDSYWFEbBc4HNYPONyyBZHZGZAnqaJVH4tnIBS+F+iTl90+zszdkOQ==} + '@npmcli/arborist@5.3.0': resolution: {integrity: sha512-+rZ9zgL1lnbl8Xbb1NQdMjveOMwj4lIYfcDtyJHHi5x4X8jtR6m8SXooJMZy5vmFVZ8w7A2Bnd/oX9eTuU8w5A==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -29651,7 +29654,6 @@ packages: engines: {node: '>=0.6.0', teleport: '>=0.2.0'} deprecated: |- You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other. - (For a CapTP with native promises, see @endo/eventual-send and @endo/captp) qrcode.react@3.1.0: @@ -38069,6 +38071,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-module-transforms@7.22.20(@babel/core@7.22.11)': + dependencies: + '@babel/core': 7.22.11 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.24.7 + '@babel/helper-simple-access': 7.24.7 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.24.7 + transitivePeerDependencies: + - supports-color + '@babel/helper-module-transforms@7.22.20(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 @@ -38594,6 +38607,13 @@ snapshots: '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.21.4) + '@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.22.11)': + dependencies: + '@babel/core': 7.22.11 + '@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) + '@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 @@ -38669,6 +38689,12 @@ snapshots: '@babel/core': 7.21.4 '@babel/helper-plugin-utils': 7.24.8 + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.24.3)': + dependencies: + '@babel/core': 7.24.3 + '@babel/helper-plugin-utils': 7.24.8 + optional: true + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.24.4)': dependencies: '@babel/core': 7.24.4 @@ -38804,14 +38830,14 @@ snapshots: '@babel/core': 7.21.4 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-flow@7.24.7(@babel/core@7.21.4)': + '@babel/plugin-syntax-flow@7.24.7(@babel/core@7.22.11)': dependencies: - '@babel/core': 7.21.4 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-flow@7.24.7(@babel/core@7.22.11)': + '@babel/plugin-syntax-flow@7.24.7(@babel/core@7.23.2)': dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-syntax-flow@7.24.7(@babel/core@7.24.3)': @@ -38944,6 +38970,11 @@ snapshots: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.23.2)': + dependencies: + '@babel/core': 7.23.2 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.24.4)': dependencies: '@babel/core': 7.24.4 @@ -38954,9 +38985,9 @@ snapshots: '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.21.4)': + '@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.22.11)': dependencies: - '@babel/core': 7.21.4 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.24.3)': @@ -39179,9 +39210,9 @@ snapshots: '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-typescript@7.21.4(@babel/core@7.21.4)': + '@babel/plugin-syntax-typescript@7.21.4(@babel/core@7.22.11)': dependencies: - '@babel/core': 7.21.4 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-syntax-typescript@7.21.4(@babel/core@7.25.2)': @@ -39850,18 +39881,18 @@ snapshots: '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-syntax-flow': 7.22.5(@babel/core@7.21.4) - '@babel/plugin-transform-flow-strip-types@7.25.2(@babel/core@7.21.4)': - dependencies: - '@babel/core': 7.21.4 - '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-flow': 7.24.7(@babel/core@7.21.4) - '@babel/plugin-transform-flow-strip-types@7.25.2(@babel/core@7.22.11)': dependencies: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-syntax-flow': 7.24.7(@babel/core@7.22.11) + '@babel/plugin-transform-flow-strip-types@7.25.2(@babel/core@7.23.2)': + dependencies: + '@babel/core': 7.23.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/plugin-syntax-flow': 7.24.7(@babel/core@7.23.2) + '@babel/plugin-transform-flow-strip-types@7.25.2(@babel/core@7.24.3)': dependencies: '@babel/core': 7.24.3 @@ -40136,10 +40167,10 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-commonjs@7.22.15(@babel/core@7.21.4)': + '@babel/plugin-transform-modules-commonjs@7.22.15(@babel/core@7.22.11)': dependencies: - '@babel/core': 7.21.4 - '@babel/helper-module-transforms': 7.22.20(@babel/core@7.21.4) + '@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.22.5 transitivePeerDependencies: @@ -40790,6 +40821,11 @@ snapshots: '@babel/core': 7.21.4 '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-transform-react-display-name@7.18.6(@babel/core@7.22.11)': + dependencies: + '@babel/core': 7.22.11 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-transform-react-display-name@7.22.5(@babel/core@7.21.4)': dependencies: '@babel/core': 7.21.4 @@ -40800,6 +40836,11 @@ snapshots: '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-transform-react-display-name@7.22.5(@babel/core@7.23.2)': + dependencies: + '@babel/core': 7.23.2 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-transform-react-display-name@7.22.5(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 @@ -40815,16 +40856,21 @@ snapshots: '@babel/core': 7.21.4 '@babel/plugin-transform-react-jsx': 7.21.0(@babel/core@7.21.4) - '@babel/plugin-transform-react-jsx-development@7.22.5(@babel/core@7.21.4)': + '@babel/plugin-transform-react-jsx-development@7.18.6(@babel/core@7.22.11)': dependencies: - '@babel/core': 7.21.4 - '@babel/plugin-transform-react-jsx': 7.22.15(@babel/core@7.21.4) + '@babel/core': 7.22.11 + '@babel/plugin-transform-react-jsx': 7.21.0(@babel/core@7.22.11) '@babel/plugin-transform-react-jsx-development@7.22.5(@babel/core@7.22.11)': dependencies: '@babel/core': 7.22.11 '@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.23.2)': + dependencies: + '@babel/core': 7.23.2 + '@babel/plugin-transform-react-jsx': 7.22.15(@babel/core@7.23.2) + '@babel/plugin-transform-react-jsx-development@7.22.5(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 @@ -40876,14 +40922,14 @@ snapshots: '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.21.4) '@babel/types': 7.22.19 - '@babel/plugin-transform-react-jsx@7.22.15(@babel/core@7.21.4)': + '@babel/plugin-transform-react-jsx@7.21.0(@babel/core@7.22.11)': dependencies: - '@babel/core': 7.21.4 - '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/core': 7.22.11 + '@babel/helper-annotate-as-pure': 7.18.6 '@babel/helper-module-imports': 7.22.15 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.21.4) - '@babel/types': 7.24.0 + '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.11) + '@babel/types': 7.22.19 '@babel/plugin-transform-react-jsx@7.22.15(@babel/core@7.22.11)': dependencies: @@ -40894,6 +40940,15 @@ snapshots: '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.11) '@babel/types': 7.24.0 + '@babel/plugin-transform-react-jsx@7.22.15(@babel/core@7.23.2)': + dependencies: + '@babel/core': 7.23.2 + '@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.23.2) + '@babel/types': 7.24.0 + '@babel/plugin-transform-react-jsx@7.22.15(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 @@ -40914,13 +40969,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.21.4)': + '@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.22.11)': dependencies: - '@babel/core': 7.21.4 + '@babel/core': 7.22.11 '@babel/helper-annotate-as-pure': 7.24.7 '@babel/helper-module-imports': 7.24.7 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.21.4) + '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.22.11) '@babel/types': 7.25.6 transitivePeerDependencies: - supports-color @@ -40953,10 +41008,10 @@ snapshots: '@babel/helper-annotate-as-pure': 7.18.6 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-transform-react-pure-annotations@7.22.5(@babel/core@7.21.4)': + '@babel/plugin-transform-react-pure-annotations@7.18.6(@babel/core@7.22.11)': dependencies: - '@babel/core': 7.21.4 - '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/core': 7.22.11 + '@babel/helper-annotate-as-pure': 7.18.6 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-transform-react-pure-annotations@7.22.5(@babel/core@7.22.11)': @@ -40965,6 +41020,12 @@ snapshots: '@babel/helper-annotate-as-pure': 7.22.5 '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-transform-react-pure-annotations@7.22.5(@babel/core@7.23.2)': + dependencies: + '@babel/core': 7.23.2 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-transform-react-pure-annotations@7.22.5(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 @@ -41055,6 +41116,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-runtime@7.23.2(@babel/core@7.22.11)': + dependencies: + '@babel/core': 7.22.11 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-plugin-utils': 7.22.5 + babel-plugin-polyfill-corejs2: 0.4.6(@babel/core@7.22.11) + babel-plugin-polyfill-corejs3: 0.8.5(@babel/core@7.22.11) + babel-plugin-polyfill-regenerator: 0.5.3(@babel/core@7.22.11) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-runtime@7.23.2(@babel/core@7.24.4)': dependencies: '@babel/core': 7.24.4 @@ -41239,13 +41312,13 @@ snapshots: '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-typescript@7.21.3(@babel/core@7.21.4)': + '@babel/plugin-transform-typescript@7.21.3(@babel/core@7.22.11)': dependencies: - '@babel/core': 7.21.4 + '@babel/core': 7.22.11 '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.21.4) + '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.22.11) '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-typescript': 7.21.4(@babel/core@7.21.4) + '@babel/plugin-syntax-typescript': 7.21.4(@babel/core@7.22.11) '@babel/plugin-transform-typescript@7.21.3(@babel/core@7.25.2)': dependencies: @@ -41941,19 +42014,19 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/preset-flow@7.22.15(@babel/core@7.21.4)': + '@babel/preset-flow@7.22.15(@babel/core@7.22.11)': dependencies: - '@babel/core': 7.21.4 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-validator-option': 7.24.8 - '@babel/plugin-transform-flow-strip-types': 7.25.2(@babel/core@7.21.4) + '@babel/plugin-transform-flow-strip-types': 7.25.2(@babel/core@7.22.11) - '@babel/preset-flow@7.22.15(@babel/core@7.22.11)': + '@babel/preset-flow@7.22.15(@babel/core@7.23.2)': dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.23.2 '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-validator-option': 7.24.8 - '@babel/plugin-transform-flow-strip-types': 7.25.2(@babel/core@7.22.11) + '@babel/plugin-transform-flow-strip-types': 7.25.2(@babel/core@7.23.2) '@babel/preset-flow@7.22.15(@babel/core@7.25.2)': dependencies: @@ -42021,15 +42094,15 @@ snapshots: '@babel/plugin-transform-react-jsx-development': 7.18.6(@babel/core@7.21.4) '@babel/plugin-transform-react-pure-annotations': 7.18.6(@babel/core@7.21.4) - '@babel/preset-react@7.22.15(@babel/core@7.21.4)': + '@babel/preset-react@7.18.6(@babel/core@7.22.11)': dependencies: - '@babel/core': 7.21.4 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-validator-option': 7.22.15 - '@babel/plugin-transform-react-display-name': 7.22.5(@babel/core@7.21.4) - '@babel/plugin-transform-react-jsx': 7.22.15(@babel/core@7.21.4) - '@babel/plugin-transform-react-jsx-development': 7.22.5(@babel/core@7.21.4) - '@babel/plugin-transform-react-pure-annotations': 7.22.5(@babel/core@7.21.4) + '@babel/core': 7.22.11 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-validator-option': 7.21.0 + '@babel/plugin-transform-react-display-name': 7.18.6(@babel/core@7.22.11) + '@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) '@babel/preset-react@7.22.15(@babel/core@7.22.11)': dependencies: @@ -42041,6 +42114,16 @@ snapshots: '@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) + '@babel/preset-react@7.22.15(@babel/core@7.23.2)': + dependencies: + '@babel/core': 7.23.2 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-validator-option': 7.22.15 + '@babel/plugin-transform-react-display-name': 7.22.5(@babel/core@7.23.2) + '@babel/plugin-transform-react-jsx': 7.22.15(@babel/core@7.23.2) + '@babel/plugin-transform-react-jsx-development': 7.22.5(@babel/core@7.23.2) + '@babel/plugin-transform-react-pure-annotations': 7.22.5(@babel/core@7.23.2) + '@babel/preset-react@7.22.15(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 @@ -42063,14 +42146,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/preset-typescript@7.21.4(@babel/core@7.21.4)': + '@babel/preset-typescript@7.21.4(@babel/core@7.22.11)': dependencies: - '@babel/core': 7.21.4 + '@babel/core': 7.22.11 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-validator-option': 7.22.15 - '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.21.4) - '@babel/plugin-transform-modules-commonjs': 7.22.15(@babel/core@7.21.4) - '@babel/plugin-transform-typescript': 7.21.3(@babel/core@7.21.4) + '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.11) + '@babel/plugin-transform-modules-commonjs': 7.22.15(@babel/core@7.22.11) + '@babel/plugin-transform-typescript': 7.21.3(@babel/core@7.22.11) transitivePeerDependencies: - supports-color @@ -43649,11 +43732,11 @@ snapshots: to-pascal-case: 1.0.0 unescape-js: 1.1.4 - '@esbuild-plugins/node-resolve@0.2.2(esbuild@0.23.1)': + '@esbuild-plugins/node-resolve@0.2.2(esbuild@0.18.20)': dependencies: '@types/resolve': 1.20.2 debug: 4.3.6(supports-color@8.1.1) - esbuild: 0.23.1 + esbuild: 0.18.20 escape-string-regexp: 4.0.0 resolve: 1.22.8 transitivePeerDependencies: @@ -44615,7 +44698,7 @@ snapshots: - ts-node - utf-8-validate - '@jest/core@27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2))': + '@jest/core@27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@22.7.4)(typescript@5.6.2))': dependencies: '@jest/console': 27.5.1 '@jest/reporters': 27.5.1 @@ -44629,7 +44712,7 @@ snapshots: exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 27.5.1 - jest-config: 27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) + jest-config: 27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@22.7.4)(typescript@5.6.2)) jest-haste-map: 27.5.1 jest-message-util: 27.5.1 jest-regex-util: 27.5.1 @@ -44652,44 +44735,42 @@ snapshots: - ts-node - utf-8-validate - '@jest/core@27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@22.7.4)(typescript@5.6.2))': + '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))': dependencies: - '@jest/console': 27.5.1 - '@jest/reporters': 27.5.1 - '@jest/test-result': 27.5.1 - '@jest/transform': 27.5.1 - '@jest/types': 27.5.1 + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 '@types/node': 20.16.5 ansi-escapes: 4.3.2 chalk: 4.1.2 - emittery: 0.8.1 + ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 - jest-changed-files: 27.5.1 - jest-config: 27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@22.7.4)(typescript@5.6.2)) - jest-haste-map: 27.5.1 - jest-message-util: 27.5.1 - jest-regex-util: 27.5.1 - jest-resolve: 27.5.1 - jest-resolve-dependencies: 27.5.1 - jest-runner: 27.5.1 - jest-runtime: 27.5.1 - jest-snapshot: 27.5.1 - jest-util: 27.5.1 - jest-validate: 27.5.1 - jest-watcher: 27.5.1 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 micromatch: 4.0.8 - rimraf: 3.0.2 + pretty-format: 29.7.0 slash: 3.0.0 strip-ansi: 6.0.1 transitivePeerDependencies: - - bufferutil - - canvas + - babel-plugin-macros - supports-color - ts-node - - utf-8-validate - '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))': + '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 @@ -44703,7 +44784,7 @@ snapshots: exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) + jest-config: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -44724,7 +44805,7 @@ snapshots: - supports-color - ts-node - '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2))': + '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 @@ -44738,7 +44819,7 @@ snapshots: exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) + jest-config: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -45968,11 +46049,11 @@ snapshots: - encoding - supports-color - '@mdx-js/esbuild@3.0.1(esbuild@0.23.1)': + '@mdx-js/esbuild@3.0.1(esbuild@0.18.20)': dependencies: '@mdx-js/mdx': 3.0.1 '@types/unist': 3.0.2 - esbuild: 0.23.1 + esbuild: 0.18.20 vfile: 6.0.1 vfile-message: 4.0.2 transitivePeerDependencies: @@ -46638,6 +46719,17 @@ snapshots: - supports-color - utf-8-validate + '@novu/shared@2.1.1(@nestjs/common@10.4.1(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.1(@nestjs/common@10.4.1(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.1)(@nestjs/websockets@10.4.1)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1))(reflect-metadata@0.2.2)': + dependencies: + '@nestjs/swagger': 7.4.0(@nestjs/common@10.4.1(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.4.1(@nestjs/common@10.4.1(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.4.1)(@nestjs/websockets@10.4.1)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1))(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2) + class-transformer: 0.5.1 + class-validator: 0.14.1 + transitivePeerDependencies: + - '@fastify/static' + - '@nestjs/common' + - '@nestjs/core' + - reflect-metadata + '@npmcli/arborist@5.3.0': dependencies: '@isaacs/string-locale-compare': 1.1.0 @@ -46844,6 +46936,21 @@ snapshots: - typescript - verdaccio + '@nrwl/js@19.8.2(@babel/traverse@7.25.6)(@swc-node/register@1.10.9(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(nx@19.8.2(@swc-node/register@1.10.9(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.3.107(@swc/helpers@0.5.12)))(typescript@5.4.3)(verdaccio@5.32.1(encoding@0.1.13)(typanion@3.14.0))': + dependencies: + '@nx/js': 19.8.2(@babel/traverse@7.25.6)(@swc-node/register@1.10.9(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(nx@19.8.2(@swc-node/register@1.10.9(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.3.107(@swc/helpers@0.5.12)))(typescript@5.4.3)(verdaccio@5.32.1(encoding@0.1.13)(typanion@3.14.0)) + transitivePeerDependencies: + - '@babel/traverse' + - '@swc-node/register' + - '@swc/core' + - '@swc/wasm' + - '@types/node' + - debug + - nx + - supports-color + - typescript + - verdaccio + '@nrwl/js@19.8.2(@babel/traverse@7.25.6)(@swc-node/register@1.10.9(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(nx@19.8.2(@swc-node/register@1.10.9(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.3.107(@swc/helpers@0.5.12)))(typescript@5.6.2)(verdaccio@5.32.1(encoding@0.1.13)(typanion@3.14.0))': dependencies: '@nx/js': 19.8.2(@babel/traverse@7.25.6)(@swc-node/register@1.10.9(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(nx@19.8.2(@swc-node/register@1.10.9(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.3.107(@swc/helpers@0.5.12)))(typescript@5.6.2)(verdaccio@5.32.1(encoding@0.1.13)(typanion@3.14.0)) @@ -47170,7 +47277,7 @@ snapshots: '@babel/preset-env': 7.25.4(@babel/core@7.25.2) '@babel/preset-typescript': 7.23.2(@babel/core@7.25.2) '@babel/runtime': 7.25.6 - '@nrwl/js': 19.8.2(@babel/traverse@7.25.6)(@swc-node/register@1.10.9(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(nx@19.8.2(@swc-node/register@1.10.9(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.3.107(@swc/helpers@0.5.12)))(typescript@5.6.2)(verdaccio@5.32.1(encoding@0.1.13)(typanion@3.14.0)) + '@nrwl/js': 19.8.2(@babel/traverse@7.25.6)(@swc-node/register@1.10.9(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(nx@19.8.2(@swc-node/register@1.10.9(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.3.107(@swc/helpers@0.5.12)))(typescript@5.4.3)(verdaccio@5.32.1(encoding@0.1.13)(typanion@3.14.0)) '@nx/devkit': 19.8.2(nx@19.8.2(@swc-node/register@1.10.9(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.3.107(@swc/helpers@0.5.12))) '@nx/workspace': 19.8.2(@swc-node/register@1.10.9(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.3.107(@swc/helpers@0.5.12)) babel-plugin-const-enum: 1.2.0(@babel/core@7.25.2) @@ -49285,7 +49392,7 @@ snapshots: webpack-dev-server: 4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) webpack-hot-middleware: 2.26.1 - '@pmmmwh/react-refresh-webpack-plugin@0.5.10(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1))(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)))(webpack-hot-middleware@2.26.1)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1))': + '@pmmmwh/react-refresh-webpack-plugin@0.5.10(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12)))(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(webpack-hot-middleware@2.26.1)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)))': dependencies: ansi-html-community: 0.0.8 common-path-prefix: 3.0.0 @@ -49297,14 +49404,14 @@ snapshots: react-refresh: 0.11.0 schema-utils: 3.3.0 source-map: 0.7.4 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) optionalDependencies: - '@types/webpack': 5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + '@types/webpack': 5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12)) type-fest: 2.19.0 - webpack-dev-server: 4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + webpack-dev-server: 4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) webpack-hot-middleware: 2.26.1 - '@pmmmwh/react-refresh-webpack-plugin@0.5.10(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0)))(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.11.1(webpack-cli@5.1.4)(webpack@5.78.0))(webpack-hot-middleware@2.26.1)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4))': + '@pmmmwh/react-refresh-webpack-plugin@0.5.10(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0)))(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-hot-middleware@2.26.1)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4))': dependencies: ansi-html-community: 0.0.8 common-path-prefix: 3.0.0 @@ -49316,14 +49423,13 @@ snapshots: react-refresh: 0.11.0 schema-utils: 3.3.0 source-map: 0.7.4 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) optionalDependencies: - '@types/webpack': 5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0)) + '@types/webpack': 5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0)) type-fest: 2.19.0 - webpack-dev-server: 4.11.1(webpack-cli@5.1.4)(webpack@5.78.0) webpack-hot-middleware: 2.26.1 - '@pmmmwh/react-refresh-webpack-plugin@0.5.10(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12)))(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))))(webpack-hot-middleware@2.26.1)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)))': + '@pmmmwh/react-refresh-webpack-plugin@0.5.10(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12)))(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-hot-middleware@2.26.1)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)))': dependencies: ansi-html-community: 0.0.8 common-path-prefix: 3.0.0 @@ -49339,7 +49445,6 @@ snapshots: optionalDependencies: '@types/webpack': 5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12)) type-fest: 2.19.0 - webpack-dev-server: 4.11.1(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) webpack-hot-middleware: 2.26.1 '@pnpm/cli-meta@5.0.0': @@ -54334,7 +54439,7 @@ snapshots: - uglify-js - webpack-cli - '@storybook/builder-webpack5@7.4.2(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(encoding@0.1.13)(esbuild@0.18.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0))': + '@storybook/builder-webpack5@7.4.2(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)': dependencies: '@babel/core': 7.23.2 '@storybook/addons': 7.4.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -54356,30 +54461,30 @@ snapshots: '@swc/core': 1.3.107(@swc/helpers@0.5.12) '@types/node': 16.11.7 '@types/semver': 7.3.13 - babel-loader: 9.1.2(@babel/core@7.23.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) + babel-loader: 9.1.2(@babel/core@7.23.2)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) 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.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) + css-loader: 6.7.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) express: 4.21.0 - fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) + fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) fs-extra: 11.2.0 - html-webpack-plugin: 5.5.3(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) + html-webpack-plugin: 5.5.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) path-browserify: 1.0.1 process: 0.11.10 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) semver: 7.6.3 - style-loader: 3.3.2(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) - swc-loader: 0.2.3(@swc/core@1.3.107(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) - terser-webpack-plugin: 5.3.10(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) + style-loader: 3.3.2(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) + swc-loader: 0.2.3(@swc/core@1.3.107(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) + terser-webpack-plugin: 5.3.10(@swc/core@1.3.107(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) ts-dedent: 2.2.0 url: 0.11.4 util: 0.12.5 util-deprecate: 1.0.2 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0)) - webpack-dev-middleware: 6.1.1(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) + webpack-dev-middleware: 6.1.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) webpack-hot-middleware: 2.25.3 webpack-virtual-modules: 0.5.0 optionalDependencies: @@ -54394,7 +54499,7 @@ snapshots: - uglify-js - webpack-cli - '@storybook/builder-webpack5@7.4.2(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(encoding@0.1.13)(esbuild@0.23.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)': + '@storybook/builder-webpack5@7.4.2(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0))': dependencies: '@babel/core': 7.23.2 '@storybook/addons': 7.4.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -54416,30 +54521,30 @@ snapshots: '@swc/core': 1.3.107(@swc/helpers@0.5.12) '@types/node': 16.11.7 '@types/semver': 7.3.13 - babel-loader: 9.1.2(@babel/core@7.23.2)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + babel-loader: 9.1.2(@babel/core@7.23.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) 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.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + css-loader: 6.7.3(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) express: 4.21.0 - fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) fs-extra: 11.2.0 - html-webpack-plugin: 5.5.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + html-webpack-plugin: 5.5.3(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) path-browserify: 1.0.1 process: 0.11.10 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) semver: 7.6.3 - style-loader: 3.3.2(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) - swc-loader: 0.2.3(@swc/core@1.3.107(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) - terser-webpack-plugin: 5.3.10(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + style-loader: 3.3.2(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + swc-loader: 0.2.3(@swc/core@1.3.107(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + terser-webpack-plugin: 5.3.10(@swc/core@1.3.107(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) ts-dedent: 2.2.0 url: 0.11.4 util: 0.12.5 util-deprecate: 1.0.2 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) - webpack-dev-middleware: 6.1.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0)) + webpack-dev-middleware: 6.1.1(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) webpack-hot-middleware: 2.25.3 webpack-virtual-modules: 0.5.0 optionalDependencies: @@ -55090,16 +55195,16 @@ snapshots: '@storybook/postinstall@7.4.2': {} - '@storybook/preset-create-react-app@7.4.2(f7avyblvzm233o6g7idqcb345u)': + '@storybook/preset-create-react-app@7.4.2(ucmnrhmq4kewpo24xrp57f5r6y)': dependencies: - '@babel/core': 7.21.4 - '@pmmmwh/react-refresh-webpack-plugin': 0.5.10(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1))(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)))(webpack-hot-middleware@2.26.1)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) - '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + '@babel/core': 7.22.11 + '@pmmmwh/react-refresh-webpack-plugin': 0.5.10(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20))(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)))(webpack-hot-middleware@2.26.1)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) + '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) '@storybook/types': 7.4.2 '@types/babel__core': 7.20.0 babel-plugin-react-docgen: 4.2.1 pnp-webpack-plugin: 1.7.0(typescript@5.6.2) - react-scripts: 5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.21.4))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.21.4))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1))(esbuild@0.23.1)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1) + react-scripts: 5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.22.11))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.22.11))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20))(esbuild@0.18.20)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1) semver: 7.5.4 transitivePeerDependencies: - '@types/webpack' @@ -55113,16 +55218,16 @@ snapshots: - webpack-hot-middleware - webpack-plugin-serve - '@storybook/preset-react-webpack@7.4.2(@babel/core@7.21.4)(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1))(encoding@0.1.13)(esbuild@0.23.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)))(webpack-hot-middleware@2.26.1)': + '@storybook/preset-react-webpack@7.4.2(@babel/core@7.22.11)(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20))(encoding@0.1.13)(esbuild@0.18.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)))(webpack-hot-middleware@2.26.1)': dependencies: - '@babel/preset-flow': 7.22.15(@babel/core@7.21.4) - '@babel/preset-react': 7.22.15(@babel/core@7.21.4) - '@pmmmwh/react-refresh-webpack-plugin': 0.5.10(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1))(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)))(webpack-hot-middleware@2.26.1)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + '@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(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20))(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)))(webpack-hot-middleware@2.26.1)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) '@storybook/core-webpack': 7.4.2(encoding@0.1.13) '@storybook/docs-tools': 7.4.2(encoding@0.1.13) '@storybook/node-logger': 7.4.2 '@storybook/react': 7.4.2(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2) - '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) '@types/node': 16.11.7 '@types/semver': 7.5.8 babel-plugin-add-react-displayname: 0.0.5 @@ -55132,9 +55237,9 @@ snapshots: react-dom: 18.3.1(react@18.3.1) react-refresh: 0.11.0 semver: 7.6.3 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) optionalDependencies: - '@babel/core': 7.21.4 + '@babel/core': 7.22.11 typescript: 5.6.2 transitivePeerDependencies: - '@swc/core' @@ -55150,16 +55255,16 @@ snapshots: - webpack-hot-middleware - webpack-plugin-serve - '@storybook/preset-react-webpack@7.4.2(@babel/core@7.22.11)(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20))(encoding@0.1.13)(esbuild@0.18.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)))(webpack-hot-middleware@2.26.1)': + '@storybook/preset-react-webpack@7.4.2(@babel/core@7.23.2)(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12)))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-hot-middleware@2.26.1)': dependencies: - '@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(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20))(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)))(webpack-hot-middleware@2.26.1)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) + '@babel/preset-flow': 7.22.15(@babel/core@7.23.2) + '@babel/preset-react': 7.22.15(@babel/core@7.23.2) + '@pmmmwh/react-refresh-webpack-plugin': 0.5.10(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12)))(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-hot-middleware@2.26.1)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) '@storybook/core-webpack': 7.4.2(encoding@0.1.13) '@storybook/docs-tools': 7.4.2(encoding@0.1.13) '@storybook/node-logger': 7.4.2 '@storybook/react': 7.4.2(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2) - '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) + '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) '@types/node': 16.11.7 '@types/semver': 7.5.8 babel-plugin-add-react-displayname: 0.0.5 @@ -55169,9 +55274,9 @@ snapshots: react-dom: 18.3.1(react@18.3.1) react-refresh: 0.11.0 semver: 7.6.3 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) optionalDependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.23.2 typescript: 5.6.2 transitivePeerDependencies: - '@swc/core' @@ -55187,16 +55292,16 @@ snapshots: - webpack-hot-middleware - webpack-plugin-serve - '@storybook/preset-react-webpack@7.4.2(@babel/core@7.25.2)(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0)))(encoding@0.1.13)(esbuild@0.18.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0))(webpack-dev-server@4.11.1(webpack-cli@5.1.4)(webpack@5.78.0))(webpack-hot-middleware@2.26.1)': + '@storybook/preset-react-webpack@7.4.2(@babel/core@7.25.2)(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0)))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0))(webpack-hot-middleware@2.26.1)': dependencies: '@babel/preset-flow': 7.22.15(@babel/core@7.25.2) '@babel/preset-react': 7.22.15(@babel/core@7.25.2) - '@pmmmwh/react-refresh-webpack-plugin': 0.5.10(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0)))(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.11.1(webpack-cli@5.1.4)(webpack@5.78.0))(webpack-hot-middleware@2.26.1)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) + '@pmmmwh/react-refresh-webpack-plugin': 0.5.10(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0)))(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-hot-middleware@2.26.1)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) '@storybook/core-webpack': 7.4.2(encoding@0.1.13) '@storybook/docs-tools': 7.4.2(encoding@0.1.13) '@storybook/node-logger': 7.4.2 '@storybook/react': 7.4.2(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2) - '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) + '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) '@types/node': 16.11.7 '@types/semver': 7.5.8 babel-plugin-add-react-displayname: 0.0.5 @@ -55206,7 +55311,7 @@ snapshots: react-dom: 18.3.1(react@18.3.1) react-refresh: 0.11.0 semver: 7.6.3 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) optionalDependencies: '@babel/core': 7.25.2 typescript: 5.6.2 @@ -55310,7 +55415,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1))': + '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4))': dependencies: debug: 4.3.6(supports-color@8.1.1) endent: 2.1.0 @@ -55320,11 +55425,11 @@ snapshots: react-docgen-typescript: 2.2.2(typescript@5.6.2) tslib: 2.7.0 typescript: 5.6.2 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) transitivePeerDependencies: - supports-color - '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4))': + '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)))': dependencies: debug: 4.3.6(supports-color@8.1.1) endent: 2.1.0 @@ -55334,7 +55439,7 @@ snapshots: react-docgen-typescript: 2.2.2(typescript@5.6.2) tslib: 2.7.0 typescript: 5.6.2 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) transitivePeerDependencies: - supports-color @@ -55374,34 +55479,6 @@ snapshots: - vite-plugin-glimmerx - webpack-sources - '@storybook/react-webpack5@7.4.2(@babel/core@7.21.4)(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1))(encoding@0.1.13)(esbuild@0.23.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)))(webpack-hot-middleware@2.26.1)': - dependencies: - '@storybook/builder-webpack5': 7.4.2(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(encoding@0.1.13)(esbuild@0.23.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2) - '@storybook/preset-react-webpack': 7.4.2(@babel/core@7.21.4)(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1))(encoding@0.1.13)(esbuild@0.23.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)))(webpack-hot-middleware@2.26.1) - '@storybook/react': 7.4.2(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2) - '@types/node': 16.11.7 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@babel/core': 7.21.4 - typescript: 5.6.2 - transitivePeerDependencies: - - '@swc/core' - - '@swc/helpers' - - '@types/react' - - '@types/react-dom' - - '@types/webpack' - - encoding - - esbuild - - sockjs-client - - supports-color - - type-fest - - uglify-js - - webpack-cli - - webpack-dev-server - - webpack-hot-middleware - - webpack-plugin-serve - '@storybook/react-webpack5@7.4.2(@babel/core@7.22.11)(@swc/core@1.3.107(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20))(encoding@0.1.13)(esbuild@0.18.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)))(webpack-hot-middleware@2.26.1)': dependencies: '@storybook/builder-webpack5': 7.4.2(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(encoding@0.1.13)(esbuild@0.18.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2) @@ -55430,10 +55507,38 @@ snapshots: - webpack-hot-middleware - webpack-plugin-serve - '@storybook/react-webpack5@7.4.2(@babel/core@7.25.2)(@swc/core@1.7.26(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0)))(encoding@0.1.13)(esbuild@0.18.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0))(webpack-dev-server@4.11.1(webpack-cli@5.1.4)(webpack@5.78.0))(webpack-hot-middleware@2.26.1)': + '@storybook/react-webpack5@7.4.2(@babel/core@7.23.2)(@swc/core@1.7.26(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12)))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-hot-middleware@2.26.1)': dependencies: - '@storybook/builder-webpack5': 7.4.2(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(encoding@0.1.13)(esbuild@0.18.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0)) - '@storybook/preset-react-webpack': 7.4.2(@babel/core@7.25.2)(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0)))(encoding@0.1.13)(esbuild@0.18.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0))(webpack-dev-server@4.11.1(webpack-cli@5.1.4)(webpack@5.78.0))(webpack-hot-middleware@2.26.1) + '@storybook/builder-webpack5': 7.4.2(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2) + '@storybook/preset-react-webpack': 7.4.2(@babel/core@7.23.2)(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12)))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-hot-middleware@2.26.1) + '@storybook/react': 7.4.2(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2) + '@types/node': 16.11.7 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@babel/core': 7.23.2 + typescript: 5.6.2 + transitivePeerDependencies: + - '@swc/core' + - '@swc/helpers' + - '@types/react' + - '@types/react-dom' + - '@types/webpack' + - encoding + - esbuild + - sockjs-client + - supports-color + - type-fest + - uglify-js + - webpack-cli + - webpack-dev-server + - webpack-hot-middleware + - webpack-plugin-serve + + '@storybook/react-webpack5@7.4.2(@babel/core@7.25.2)(@swc/core@1.7.26(@swc/helpers@0.5.12))(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0)))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0))(webpack-hot-middleware@2.26.1)': + dependencies: + '@storybook/builder-webpack5': 7.4.2(@swc/helpers@0.5.12)(@types/react-dom@18.3.0)(@types/react@18.3.3)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0)) + '@storybook/preset-react-webpack': 7.4.2(@babel/core@7.25.2)(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0)))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0))(webpack-hot-middleware@2.26.1) '@storybook/react': 7.4.2(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2) '@types/node': 16.11.7 react: 18.3.1 @@ -56078,7 +56183,7 @@ snapshots: pretty-format: 24.9.0 redent: 3.0.0 - '@testing-library/jest-dom@6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.13)(jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(vitest@1.2.1(@edge-runtime/vm@4.0.2)(@types/node@20.16.5)(jsdom@24.0.0)(less@4.2.0)(lightningcss@1.26.0)(sass@1.77.8)(sugarss@4.0.1(postcss@8.4.47))(terser@5.31.6))': + '@testing-library/jest-dom@6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.13)(jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(vitest@1.2.1(@edge-runtime/vm@4.0.2)(@types/node@20.16.5)(jsdom@24.0.0)(less@4.2.0)(lightningcss@1.26.0)(sass@1.77.8)(sugarss@4.0.1(postcss@8.4.47))(terser@5.31.6))': dependencies: '@adobe/css-tools': 4.3.3 '@babel/runtime': 7.23.2 @@ -56091,10 +56196,10 @@ snapshots: optionalDependencies: '@jest/globals': 29.7.0 '@types/jest': 29.5.13 - jest: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) + jest: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) vitest: 1.2.1(@edge-runtime/vm@4.0.2)(@types/node@20.16.5)(jsdom@24.0.0)(less@4.2.0)(lightningcss@1.26.0)(sass@1.77.8)(sugarss@4.0.1(postcss@8.4.47))(terser@5.31.6) - '@testing-library/jest-dom@6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.13)(jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(vitest@1.2.1(@edge-runtime/vm@4.0.2)(@types/node@20.16.5)(jsdom@25.0.0)(less@4.2.0)(lightningcss@1.26.0)(sass@1.77.8)(sugarss@4.0.1(postcss@8.4.38))(terser@5.31.6))': + '@testing-library/jest-dom@6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.13)(jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(vitest@1.2.1(@edge-runtime/vm@4.0.2)(@types/node@20.16.5)(jsdom@25.0.0)(less@4.2.0)(lightningcss@1.26.0)(sass@1.77.8)(sugarss@4.0.1(postcss@8.4.38))(terser@5.31.6))': dependencies: '@adobe/css-tools': 4.3.3 '@babel/runtime': 7.23.2 @@ -56107,7 +56212,7 @@ snapshots: optionalDependencies: '@jest/globals': 29.7.0 '@types/jest': 29.5.13 - jest: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) + jest: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) vitest: 1.2.1(@edge-runtime/vm@4.0.2)(@types/node@20.16.5)(jsdom@25.0.0)(less@4.2.0)(lightningcss@1.26.0)(sass@1.77.8)(sugarss@4.0.1(postcss@8.4.38))(terser@5.31.6) '@testing-library/react-hooks@8.0.1(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': @@ -57252,11 +57357,11 @@ snapshots: '@types/webidl-conversions@7.0.3': optional: true - '@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)': + '@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))': dependencies: '@types/node': 20.16.5 tapable: 2.2.1 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) transitivePeerDependencies: - '@swc/core' - esbuild @@ -57264,11 +57369,11 @@ snapshots: - webpack-cli optional: true - '@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)': + '@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)': dependencies: '@types/node': 20.16.5 tapable: 2.2.1 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) transitivePeerDependencies: - '@swc/core' - esbuild @@ -57288,11 +57393,11 @@ snapshots: - webpack-cli optional: true - '@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0))': + '@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0))': dependencies: '@types/node': 20.16.5 tapable: 2.2.1 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) transitivePeerDependencies: - '@swc/core' - esbuild @@ -58870,32 +58975,30 @@ snapshots: webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-bundle-analyzer@4.10.1)(webpack@5.78.0) - '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4))': + '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4))': dependencies: - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0) '@webpack-cli/info@2.0.2(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.1)(webpack@5.78.0))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4))': dependencies: webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-bundle-analyzer@4.10.1)(webpack@5.78.0) - '@webpack-cli/info@2.0.2(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4))': + '@webpack-cli/info@2.0.2(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4))': dependencies: - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0) '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.1)(webpack@5.78.0))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4))': dependencies: webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-bundle-analyzer@4.10.1)(webpack@5.78.0) - '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0))(webpack-dev-server@4.11.1(webpack-cli@5.1.4)(webpack@5.78.0))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4))': + '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4))': dependencies: - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0) - optionalDependencies: - webpack-dev-server: 4.11.1(webpack-cli@5.1.4)(webpack@5.78.0) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0) '@wry/context@0.4.4': dependencies: @@ -60018,42 +60121,43 @@ snapshots: transitivePeerDependencies: - supports-color - babel-jest@27.5.1(@babel/core@7.24.4): + babel-jest@27.5.1(@babel/core@7.24.3): dependencies: - '@babel/core': 7.24.4 + '@babel/core': 7.24.3 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 '@types/babel__core': 7.20.3 babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 27.5.1(@babel/core@7.24.4) + babel-preset-jest: 27.5.1(@babel/core@7.24.3) chalk: 4.1.2 graceful-fs: 4.2.11 slash: 3.0.0 transitivePeerDependencies: - supports-color + optional: true - babel-jest@27.5.1(@babel/core@7.25.2): + babel-jest@27.5.1(@babel/core@7.24.4): dependencies: - '@babel/core': 7.25.2 + '@babel/core': 7.24.4 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 '@types/babel__core': 7.20.3 babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 27.5.1(@babel/core@7.25.2) + babel-preset-jest: 27.5.1(@babel/core@7.24.4) chalk: 4.1.2 graceful-fs: 4.2.11 slash: 3.0.0 transitivePeerDependencies: - supports-color - optional: true - babel-jest@29.7.0(@babel/core@7.24.4): + babel-jest@27.5.1(@babel/core@7.25.2): dependencies: - '@babel/core': 7.24.4 - '@jest/transform': 29.7.0 - '@types/babel__core': 7.20.5 + '@babel/core': 7.25.2 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/babel__core': 7.20.3 babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.24.4) + babel-preset-jest: 27.5.1(@babel/core@7.25.2) chalk: 4.1.2 graceful-fs: 4.2.11 slash: 3.0.0 @@ -60074,32 +60178,32 @@ snapshots: transitivePeerDependencies: - supports-color - babel-loader@8.3.0(@babel/core@7.21.4)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + babel-loader@8.3.0(@babel/core@7.21.4)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)): 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.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) - babel-loader@8.3.0(@babel/core@7.21.4)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): + babel-loader@8.3.0(@babel/core@7.21.4)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): 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.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) - babel-loader@8.3.0(@babel/core@7.25.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)): + babel-loader@8.3.0(@babel/core@7.25.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: '@babel/core': 7.25.2 find-cache-dir: 3.3.2 loader-utils: 2.0.4 make-dir: 3.1.0 schema-utils: 2.7.1 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) babel-loader@9.1.2(@babel/core@7.23.2)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)): dependencies: @@ -60108,19 +60212,19 @@ snapshots: schema-utils: 4.0.0 webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) - babel-loader@9.1.2(@babel/core@7.23.2)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + babel-loader@9.1.2(@babel/core@7.23.2)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: '@babel/core': 7.23.2 find-cache-dir: 3.3.2 schema-utils: 4.0.0 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) - babel-loader@9.1.2(@babel/core@7.23.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)): + babel-loader@9.1.2(@babel/core@7.23.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: '@babel/core': 7.23.2 find-cache-dir: 3.3.2 schema-utils: 4.0.0 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) babel-plugin-add-react-displayname@0.0.5: {} @@ -60390,6 +60494,23 @@ snapshots: '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.21.4) '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.21.4) + babel-preset-current-node-syntax@1.0.1(@babel/core@7.24.3): + dependencies: + '@babel/core': 7.24.3 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.3) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.24.3) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.3) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.3) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.3) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.3) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.3) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.3) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.3) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.3) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.3) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.3) + optional: true + babel-preset-current-node-syntax@1.0.1(@babel/core@7.24.4): dependencies: '@babel/core': 7.24.4 @@ -60428,6 +60549,13 @@ snapshots: babel-plugin-jest-hoist: 27.5.1 babel-preset-current-node-syntax: 1.0.1(@babel/core@7.21.4) + babel-preset-jest@27.5.1(@babel/core@7.24.3): + dependencies: + '@babel/core': 7.24.3 + babel-plugin-jest-hoist: 27.5.1 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.3) + optional: true + babel-preset-jest@27.5.1(@babel/core@7.24.4): dependencies: '@babel/core': 7.24.4 @@ -60441,13 +60569,6 @@ snapshots: babel-preset-current-node-syntax: 1.0.1(@babel/core@7.25.2) optional: true - babel-preset-jest@29.6.3(@babel/core@7.24.4): - dependencies: - '@babel/core': 7.24.4 - babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.4) - optional: true - babel-preset-jest@29.6.3(@babel/core@7.25.2): dependencies: '@babel/core': 7.25.2 @@ -61714,17 +61835,17 @@ snapshots: dependencies: mime-db: 1.52.0 - compression-webpack-plugin@10.0.0(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)): + compression-webpack-plugin@10.0.0(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4)): dependencies: schema-utils: 4.0.0 serialize-javascript: 6.0.1 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4) - compression-webpack-plugin@10.0.0(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4)): + compression-webpack-plugin@10.0.0(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: schema-utils: 4.0.0 serialize-javascript: 6.0.1 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) compression@1.7.4: dependencies: @@ -62042,13 +62163,13 @@ snapshots: - supports-color - ts-node - create-jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)): + create-jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) + jest-config: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -62057,13 +62178,13 @@ snapshots: - supports-color - ts-node - create-jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)): + create-jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) + jest-config: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -62411,19 +62532,7 @@ snapshots: semver: 7.6.3 webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) - css-loader@6.7.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): - dependencies: - icss-utils: 5.1.0(postcss@8.4.47) - postcss: 8.4.47 - postcss-modules-extract-imports: 3.0.0(postcss@8.4.47) - postcss-modules-local-by-default: 4.0.0(postcss@8.4.47) - postcss-modules-scope: 3.0.0(postcss@8.4.47) - postcss-modules-values: 4.0.0(postcss@8.4.47) - postcss-value-parser: 4.2.0 - semver: 7.6.3 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) - - css-loader@6.7.3(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)): + css-loader@6.7.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: icss-utils: 5.1.0(postcss@8.4.47) postcss: 8.4.47 @@ -62433,9 +62542,9 @@ snapshots: postcss-modules-values: 4.0.0(postcss@8.4.47) postcss-value-parser: 4.2.0 semver: 7.6.3 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) - css-loader@6.7.3(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): + css-loader@6.7.3(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: icss-utils: 5.1.0(postcss@8.4.47) postcss: 8.4.47 @@ -62445,9 +62554,9 @@ snapshots: postcss-modules-values: 4.0.0(postcss@8.4.47) postcss-value-parser: 4.2.0 semver: 7.6.3 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) - css-minimizer-webpack-plugin@3.4.1(esbuild@0.23.1)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + css-minimizer-webpack-plugin@3.4.1(esbuild@0.18.20)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)): dependencies: cssnano: 5.1.15(postcss@8.4.47) jest-worker: 27.5.1 @@ -62455,11 +62564,11 @@ snapshots: schema-utils: 4.0.0 serialize-javascript: 6.0.2 source-map: 0.6.1 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) optionalDependencies: - esbuild: 0.23.1 + esbuild: 0.18.20 - css-minimizer-webpack-plugin@3.4.1(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): + css-minimizer-webpack-plugin@3.4.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: cssnano: 5.1.15(postcss@8.4.47) jest-worker: 27.5.1 @@ -62467,7 +62576,7 @@ snapshots: schema-utils: 4.0.0 serialize-javascript: 6.0.2 source-map: 0.6.1 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) css-prefers-color-scheme@6.0.3(postcss@8.4.47): dependencies: @@ -64065,7 +64174,7 @@ snapshots: dependencies: eslint: 8.57.1 - eslint-config-react-app@7.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.21.4))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.21.4))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(jest@27.5.1(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2): + eslint-config-react-app@7.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.22.11))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.22.11))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(jest@27.5.1(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2): dependencies: '@babel/core': 7.21.4 '@babel/eslint-parser': 7.25.1(@babel/core@7.21.4)(eslint@9.9.1(jiti@1.21.6)) @@ -64075,7 +64184,7 @@ snapshots: babel-preset-react-app: 10.0.1 confusing-browser-globals: 1.0.11 eslint: 9.9.1(jiti@1.21.6) - eslint-plugin-flowtype: 8.0.3(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.21.4))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.21.4))(eslint@9.9.1(jiti@1.21.6)) + eslint-plugin-flowtype: 8.0.3(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.22.11))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.22.11))(eslint@9.9.1(jiti@1.21.6)) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.62.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6)) eslint-plugin-jest: 25.7.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2))(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2))(eslint@9.9.1(jiti@1.21.6))(jest@27.5.1(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2) eslint-plugin-jsx-a11y: 6.9.0(eslint@9.9.1(jiti@1.21.6)) @@ -64092,7 +64201,7 @@ snapshots: - jest - supports-color - eslint-config-react-app@7.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(jest@27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2): + eslint-config-react-app@7.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(jest@27.5.1(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2): dependencies: '@babel/core': 7.21.4 '@babel/eslint-parser': 7.25.1(@babel/core@7.21.4)(eslint@9.9.1(jiti@1.21.6)) @@ -64104,7 +64213,7 @@ snapshots: eslint: 9.9.1(jiti@1.21.6) eslint-plugin-flowtype: 8.0.3(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(eslint@9.9.1(jiti@1.21.6)) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.62.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6)) - eslint-plugin-jest: 25.7.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2))(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2))(eslint@9.9.1(jiti@1.21.6))(jest@27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2) + eslint-plugin-jest: 25.7.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2))(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2))(eslint@9.9.1(jiti@1.21.6))(jest@27.5.1(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2) eslint-plugin-jsx-a11y: 6.9.0(eslint@9.9.1(jiti@1.21.6)) eslint-plugin-react: 7.35.0(eslint@9.9.1(jiti@1.21.6)) eslint-plugin-react-hooks: 4.6.2(eslint@9.9.1(jiti@1.21.6)) @@ -64200,10 +64309,10 @@ snapshots: eslint: 8.57.1 ignore: 5.3.2 - eslint-plugin-flowtype@8.0.3(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.21.4))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.21.4))(eslint@9.9.1(jiti@1.21.6)): + eslint-plugin-flowtype@8.0.3(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.22.11))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.22.11))(eslint@9.9.1(jiti@1.21.6)): dependencies: - '@babel/plugin-syntax-flow': 7.24.7(@babel/core@7.21.4) - '@babel/plugin-transform-react-jsx': 7.25.2(@babel/core@7.21.4) + '@babel/plugin-syntax-flow': 7.24.7(@babel/core@7.22.11) + '@babel/plugin-transform-react-jsx': 7.25.2(@babel/core@7.22.11) eslint: 9.9.1(jiti@1.21.6) lodash: 4.17.21 string-natural-compare: 3.0.1 @@ -64311,17 +64420,6 @@ snapshots: - supports-color - typescript - eslint-plugin-jest@25.7.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2))(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2))(eslint@9.9.1(jiti@1.21.6))(jest@27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2): - dependencies: - '@typescript-eslint/experimental-utils': 5.58.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2) - eslint: 9.9.1(jiti@1.21.6) - optionalDependencies: - '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2))(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2) - jest: 27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) - transitivePeerDependencies: - - supports-color - - typescript - eslint-plugin-jest@28.8.0(@typescript-eslint/eslint-plugin@8.3.0(@typescript-eslint/parser@8.3.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(jest@29.7.0(@types/node@18.16.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2): dependencies: '@typescript-eslint/utils': 8.3.0(eslint@8.57.1)(typescript@5.6.2) @@ -64640,7 +64738,7 @@ snapshots: eslint-visitor-keys@4.0.0: {} - eslint-webpack-plugin@3.2.0(eslint@9.9.1(jiti@1.21.6))(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + eslint-webpack-plugin@3.2.0(eslint@9.9.1(jiti@1.21.6))(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)): dependencies: '@types/eslint': 8.56.12 eslint: 9.9.1(jiti@1.21.6) @@ -64648,9 +64746,9 @@ snapshots: micromatch: 4.0.8 normalize-path: 3.0.0 schema-utils: 4.0.0 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) - eslint-webpack-plugin@3.2.0(eslint@9.9.1(jiti@1.21.6))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): + eslint-webpack-plugin@3.2.0(eslint@9.9.1(jiti@1.21.6))(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: '@types/eslint': 8.56.12 eslint: 9.9.1(jiti@1.21.6) @@ -64658,7 +64756,7 @@ snapshots: micromatch: 4.0.8 normalize-path: 3.0.0 schema-utils: 4.0.0 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) eslint@8.57.1: dependencies: @@ -65385,26 +65483,26 @@ snapshots: loader-utils: 2.0.4 schema-utils: 3.3.0 webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) - optional: true - file-loader@6.2.0(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + file-loader@6.2.0(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) - file-loader@6.2.0(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)): + file-loader@6.2.0(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) optional: true - file-loader@6.2.0(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): + file-loader@6.2.0(webpack@5.94.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + webpack: 5.94.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + optional: true file-selector@0.6.0: dependencies: @@ -65638,7 +65736,7 @@ snapshots: forever-agent@0.6.1: {} - fork-ts-checker-webpack-plugin@6.5.3(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + fork-ts-checker-webpack-plugin@6.5.3(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)): dependencies: '@babel/code-frame': 7.24.7 '@types/json-schema': 7.0.15 @@ -65654,12 +65752,12 @@ snapshots: semver: 7.6.3 tapable: 1.1.3 typescript: 5.6.2 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) optionalDependencies: eslint: 9.9.1(jiti@1.21.6) vue-template-compiler: 2.7.16 - fork-ts-checker-webpack-plugin@6.5.3(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): + fork-ts-checker-webpack-plugin@6.5.3(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: '@babel/code-frame': 7.24.7 '@types/json-schema': 7.0.15 @@ -65675,7 +65773,7 @@ snapshots: semver: 7.6.3 tapable: 1.1.3 typescript: 5.6.2 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) optionalDependencies: eslint: 9.9.1(jiti@1.21.6) vue-template-compiler: 2.7.16 @@ -65697,7 +65795,7 @@ snapshots: typescript: 5.6.2 webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) - fork-ts-checker-webpack-plugin@8.0.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + fork-ts-checker-webpack-plugin@8.0.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: '@babel/code-frame': 7.24.7 chalk: 4.1.2 @@ -65712,9 +65810,9 @@ snapshots: semver: 7.6.3 tapable: 2.2.1 typescript: 5.6.2 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) - fork-ts-checker-webpack-plugin@8.0.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)): + fork-ts-checker-webpack-plugin@8.0.0(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: '@babel/code-frame': 7.24.7 chalk: 4.1.2 @@ -65729,7 +65827,7 @@ snapshots: semver: 7.6.3 tapable: 2.2.1 typescript: 5.6.2 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) fork-ts-checker-webpack-plugin@9.0.2(typescript@5.3.3)(webpack@5.94.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): dependencies: @@ -66949,32 +67047,23 @@ snapshots: tapable: 2.2.1 webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) - html-webpack-plugin@5.5.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + html-webpack-plugin@5.5.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): 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.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) - html-webpack-plugin@5.5.3(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)): + html-webpack-plugin@5.5.3(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): 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.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) - - html-webpack-plugin@5.5.3(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): - 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.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) htmlparser2@6.1.0: dependencies: @@ -68132,27 +68221,6 @@ snapshots: - ts-node - utf-8-validate - jest-cli@27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)): - dependencies: - '@jest/core': 27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) - '@jest/test-result': 27.5.1 - '@jest/types': 27.5.1 - chalk: 4.1.2 - exit: 0.1.2 - graceful-fs: 4.2.11 - import-local: 3.1.0 - jest-config: 27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) - jest-util: 27.5.1 - jest-validate: 27.5.1 - prompts: 2.4.2 - yargs: 16.2.0 - transitivePeerDependencies: - - bufferutil - - canvas - - supports-color - - ts-node - - utf-8-validate - jest-cli@27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@22.7.4)(typescript@5.6.2)): dependencies: '@jest/core': 27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@22.7.4)(typescript@5.6.2)) @@ -68213,16 +68281,16 @@ snapshots: - supports-color - ts-node - jest-cli@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)): + jest-cli@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)): dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) + '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) + create-jest: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) + jest-config: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -68232,16 +68300,16 @@ snapshots: - supports-color - ts-node - jest-cli@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)): + jest-cli@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)): dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) + '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) + create-jest: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) + jest-config: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -68372,7 +68440,7 @@ snapshots: - supports-color - utf-8-validate - jest-config@27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)): + jest-config@27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@22.7.4)(typescript@5.6.2)): dependencies: '@babel/core': 7.24.4 '@jest/test-sequencer': 27.5.1 @@ -68399,48 +68467,45 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - ts-node: 10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2) + ts-node: 10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@22.7.4)(typescript@5.6.2) transitivePeerDependencies: - bufferutil - canvas - supports-color - utf-8-validate - jest-config@27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@22.7.4)(typescript@5.6.2)): + jest-config@29.7.0(@types/node@18.16.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)): dependencies: - '@babel/core': 7.24.4 - '@jest/test-sequencer': 27.5.1 - '@jest/types': 27.5.1 - babel-jest: 27.5.1(@babel/core@7.24.4) + '@babel/core': 7.25.2 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.25.2) chalk: 4.1.2 - ci-info: 3.8.0 + ci-info: 3.9.0 deepmerge: 4.3.1 glob: 7.2.3 graceful-fs: 4.2.11 - jest-circus: 27.5.1 - jest-environment-jsdom: 27.5.1 - jest-environment-node: 27.5.1 - jest-get-type: 27.5.1 - jest-jasmine2: 27.5.1 - jest-regex-util: 27.5.1 - jest-resolve: 27.5.1 - jest-runner: 27.5.1 - jest-util: 27.5.1 - jest-validate: 27.5.1 - micromatch: 4.0.5 + jest-circus: 29.7.0(babel-plugin-macros@3.1.0) + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.8 parse-json: 5.2.0 - pretty-format: 27.5.1 + pretty-format: 29.7.0 slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - ts-node: 10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@22.7.4)(typescript@5.6.2) + '@types/node': 18.16.9 + ts-node: 10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2) transitivePeerDependencies: - - bufferutil - - canvas + - babel-plugin-macros - supports-color - - utf-8-validate - jest-config@29.7.0(@types/node@18.16.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)): + jest-config@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)): dependencies: '@babel/core': 7.25.2 '@jest/test-sequencer': 29.7.0 @@ -68465,13 +68530,13 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 18.16.9 + '@types/node': 20.16.5 ts-node: 10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2) transitivePeerDependencies: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)): + jest-config@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)): dependencies: '@babel/core': 7.25.2 '@jest/test-sequencer': 29.7.0 @@ -68497,12 +68562,12 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 20.16.5 - ts-node: 10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2) + ts-node: 10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2) transitivePeerDependencies: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)): + jest-config@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)): dependencies: '@babel/core': 7.25.2 '@jest/test-sequencer': 29.7.0 @@ -68528,7 +68593,7 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 20.16.5 - ts-node: 10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2) + ts-node: 10.9.2(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -69115,17 +69180,6 @@ snapshots: string-length: 5.0.1 strip-ansi: 7.1.0 - jest-watch-typeahead@1.1.0(jest@27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2))): - dependencies: - ansi-escapes: 4.3.2 - chalk: 4.1.2 - jest: 27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) - jest-regex-util: 28.0.2 - jest-watcher: 28.1.3 - slash: 4.0.0 - string-length: 5.0.1 - strip-ansi: 7.1.0 - jest-watcher@27.5.1: dependencies: '@jest/test-result': 27.5.1 @@ -69219,18 +69273,6 @@ snapshots: - ts-node - utf-8-validate - jest@27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)): - dependencies: - '@jest/core': 27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) - import-local: 3.1.0 - jest-cli: 27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) - transitivePeerDependencies: - - bufferutil - - canvas - - supports-color - - ts-node - - utf-8-validate - jest@27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@22.7.4)(typescript@5.6.2)): dependencies: '@jest/core': 27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@22.7.4)(typescript@5.6.2)) @@ -69267,24 +69309,24 @@ snapshots: - supports-color - ts-node - jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)): + jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)): dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) + '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) + jest-cli: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros - supports-color - ts-node - jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)): + jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)): dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) + '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) + jest-cli: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -69906,21 +69948,21 @@ snapshots: - encoding - supports-color - less-loader@4.1.0(less@4.1.3)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + less-loader@4.1.0(less@4.1.3)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)): dependencies: clone: 2.1.2 less: 4.1.3 loader-utils: 1.4.2 pify: 3.0.0 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) - less-loader@4.1.0(less@4.1.3)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): + less-loader@4.1.0(less@4.1.3)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: clone: 2.1.2 less: 4.1.3 loader-utils: 1.4.2 pify: 3.0.0 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) less@4.1.3: dependencies: @@ -71048,13 +71090,13 @@ snapshots: mdurl@2.0.0: {} - mdx-bundler@10.0.2(esbuild@0.23.1): + mdx-bundler@10.0.2(esbuild@0.18.20): dependencies: '@babel/runtime': 7.24.7 - '@esbuild-plugins/node-resolve': 0.2.2(esbuild@0.23.1) + '@esbuild-plugins/node-resolve': 0.2.2(esbuild@0.18.20) '@fal-works/esbuild-plugin-global-externals': 2.1.2 - '@mdx-js/esbuild': 3.0.1(esbuild@0.23.1) - esbuild: 0.23.1 + '@mdx-js/esbuild': 3.0.1(esbuild@0.18.20) + esbuild: 0.18.20 gray-matter: 4.0.3 remark-frontmatter: 5.0.0 remark-mdx-frontmatter: 4.0.0 @@ -71714,15 +71756,15 @@ snapshots: min-indent@1.0.1: {} - mini-css-extract-plugin@2.7.5(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + mini-css-extract-plugin@2.7.5(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)): dependencies: schema-utils: 4.0.0 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) - mini-css-extract-plugin@2.7.5(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): + mini-css-extract-plugin@2.7.5(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: schema-utils: 4.0.0 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) minimalistic-assert@1.0.1: {} @@ -72328,7 +72370,7 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - next@13.5.6(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8): + next@13.5.6(@babel/core@7.24.3)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8): dependencies: '@next/env': 13.5.6 '@swc/helpers': 0.5.2 @@ -72337,7 +72379,7 @@ snapshots: postcss: 8.4.31 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - styled-jsx: 5.1.1(@babel/core@7.25.2)(babel-plugin-macros@3.1.0)(react@18.3.1) + styled-jsx: 5.1.1(@babel/core@7.24.3)(babel-plugin-macros@3.1.0)(react@18.3.1) watchpack: 2.4.0 optionalDependencies: '@next/swc-darwin-arm64': 13.5.6 @@ -72355,7 +72397,7 @@ snapshots: - '@babel/core' - babel-plugin-macros - next@14.2.4(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(@playwright/test@1.46.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8): + next@14.2.4(@babel/core@7.24.3)(@opentelemetry/api@1.9.0)(@playwright/test@1.46.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8): dependencies: '@next/env': 14.2.4 '@swc/helpers': 0.5.5 @@ -72365,7 +72407,7 @@ snapshots: postcss: 8.4.31 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - styled-jsx: 5.1.1(@babel/core@7.25.2)(babel-plugin-macros@3.1.0)(react@18.3.1) + styled-jsx: 5.1.1(@babel/core@7.24.3)(babel-plugin-macros@3.1.0)(react@18.3.1) optionalDependencies: '@next/swc-darwin-arm64': 14.2.4 '@next/swc-darwin-x64': 14.2.4 @@ -74331,21 +74373,21 @@ snapshots: tsx: 4.19.0 yaml: 2.5.0 - postcss-loader@6.2.1(postcss@8.4.47)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + postcss-loader@6.2.1(postcss@8.4.47)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)): dependencies: cosmiconfig: 7.1.0 klona: 2.0.6 postcss: 8.4.47 semver: 7.6.3 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) - postcss-loader@6.2.1(postcss@8.4.47)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): + postcss-loader@6.2.1(postcss@8.4.47)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: cosmiconfig: 7.1.0 klona: 2.0.6 postcss: 8.4.47 semver: 7.6.3 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) postcss-logical@5.0.4(postcss@8.4.47): dependencies: @@ -75928,14 +75970,14 @@ snapshots: regenerator-runtime: 0.13.11 whatwg-fetch: 3.6.2 - react-app-rewired@2.2.1(react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.21.4))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.21.4))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1))(esbuild@0.23.1)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1)): + react-app-rewired@2.2.1(react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.22.11))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.22.11))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20))(esbuild@0.18.20)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1)): dependencies: - react-scripts: 5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.21.4))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.21.4))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1))(esbuild@0.23.1)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1) + react-scripts: 5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.22.11))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.22.11))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20))(esbuild@0.18.20)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1) semver: 5.7.2 - react-app-rewired@2.2.1(react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12)))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1)): + react-app-rewired@2.2.1(react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12)))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1)): dependencies: - react-scripts: 5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12)))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1) + react-scripts: 5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12)))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1) semver: 5.7.2 react-chartjs-2@4.3.1(chart.js@3.9.1)(react@18.3.1): @@ -75971,7 +76013,7 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-dev-utils@12.0.1(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + react-dev-utils@12.0.1(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)): dependencies: '@babel/code-frame': 7.24.2 address: 1.2.2 @@ -75982,7 +76024,7 @@ snapshots: escape-string-regexp: 4.0.0 filesize: 8.0.7 find-up: 5.0.0 - fork-ts-checker-webpack-plugin: 6.5.3(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + fork-ts-checker-webpack-plugin: 6.5.3(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) global-modules: 2.0.0 globby: 11.1.0 gzip-size: 6.0.0 @@ -75997,7 +76039,7 @@ snapshots: shell-quote: 1.8.1 strip-ansi: 6.0.1 text-table: 0.2.0 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: @@ -76005,7 +76047,7 @@ snapshots: - supports-color - vue-template-compiler - react-dev-utils@12.0.1(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): + react-dev-utils@12.0.1(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: '@babel/code-frame': 7.24.2 address: 1.2.2 @@ -76016,7 +76058,7 @@ snapshots: escape-string-regexp: 4.0.0 filesize: 8.0.7 find-up: 5.0.0 - fork-ts-checker-webpack-plugin: 6.5.3(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) + fork-ts-checker-webpack-plugin: 6.5.3(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) global-modules: 2.0.0 globby: 11.1.0 gzip-size: 6.0.0 @@ -76031,7 +76073,7 @@ snapshots: shell-quote: 1.8.1 strip-ansi: 6.0.1 text-table: 0.2.0 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: @@ -76329,56 +76371,56 @@ snapshots: transitivePeerDependencies: - supports-color - react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.21.4))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.21.4))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1))(esbuild@0.23.1)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1): + react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.22.11))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.22.11))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20))(esbuild@0.18.20)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1): dependencies: '@babel/core': 7.21.4 - '@pmmmwh/react-refresh-webpack-plugin': 0.5.10(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1))(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)))(webpack-hot-middleware@2.26.1)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + '@pmmmwh/react-refresh-webpack-plugin': 0.5.10(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20))(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)))(webpack-hot-middleware@2.26.1)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) '@svgr/webpack': 5.5.0 babel-jest: 27.5.1(@babel/core@7.21.4) - babel-loader: 8.3.0(@babel/core@7.21.4)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + babel-loader: 8.3.0(@babel/core@7.21.4)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) 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.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) - css-minimizer-webpack-plugin: 3.4.1(esbuild@0.23.1)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + css-loader: 6.7.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) + css-minimizer-webpack-plugin: 3.4.1(esbuild@0.18.20)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) dotenv: 10.0.0 dotenv-expand: 5.1.0 eslint: 9.9.1(jiti@1.21.6) - eslint-config-react-app: 7.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.21.4))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.21.4))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(jest@27.5.1(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2) - eslint-webpack-plugin: 3.2.0(eslint@9.9.1(jiti@1.21.6))(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) - file-loader: 6.2.0(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + eslint-config-react-app: 7.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.22.11))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.22.11))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(jest@27.5.1(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2) + eslint-webpack-plugin: 3.2.0(eslint@9.9.1(jiti@1.21.6))(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) + file-loader: 6.2.0(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) fs-extra: 10.1.0 - html-webpack-plugin: 5.5.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + html-webpack-plugin: 5.5.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) identity-obj-proxy: 3.0.0 jest: 27.5.1(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) jest-resolve: 27.5.1 jest-watch-typeahead: 1.1.0(jest@27.5.1(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))) - mini-css-extract-plugin: 2.7.5(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + mini-css-extract-plugin: 2.7.5(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) postcss: 8.4.47 postcss-flexbugs-fixes: 5.0.2(postcss@8.4.47) - postcss-loader: 6.2.1(postcss@8.4.47)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + postcss-loader: 6.2.1(postcss@8.4.47)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) postcss-normalize: 10.0.1(browserslist@4.21.5)(postcss@8.4.47) postcss-preset-env: 7.8.3(postcss@8.4.47) prompts: 2.4.2 react: 18.3.1 react-app-polyfill: 3.0.0 - react-dev-utils: 12.0.1(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + react-dev-utils: 12.0.1(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) react-refresh: 0.11.0 resolve: 1.22.2 resolve-url-loader: 4.0.0 - sass-loader: 12.6.0(sass@1.77.8)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + sass-loader: 12.6.0(sass@1.77.8)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) semver: 7.5.4 - source-map-loader: 3.0.2(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) - style-loader: 3.3.2(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + source-map-loader: 3.0.2(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) + style-loader: 3.3.2(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) tailwindcss: 3.4.13(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) - terser-webpack-plugin: 5.3.7(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) - webpack-dev-server: 4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) - webpack-manifest-plugin: 4.1.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) - workbox-webpack-plugin: 6.5.4(@types/babel__core@7.20.5)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + terser-webpack-plugin: 5.3.7(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) + webpack-dev-server: 4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) + webpack-manifest-plugin: 4.1.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) + workbox-webpack-plugin: 6.5.4(@types/babel__core@7.20.5)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) optionalDependencies: fsevents: 2.3.3 typescript: 5.6.2 @@ -76415,56 +76457,56 @@ snapshots: - webpack-hot-middleware - webpack-plugin-serve - react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12)))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1): + react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/babel__core@7.20.5)(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12)))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(react@18.3.1)(sass@1.77.8)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack-hot-middleware@2.26.1): dependencies: '@babel/core': 7.21.4 - '@pmmmwh/react-refresh-webpack-plugin': 0.5.10(@types/webpack@5.28.5(@swc/core@1.7.26(@swc/helpers@0.5.12)))(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))))(webpack-hot-middleware@2.26.1)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) + '@pmmmwh/react-refresh-webpack-plugin': 0.5.10(@types/webpack@5.28.5(@swc/core@1.3.107(@swc/helpers@0.5.12)))(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(webpack-hot-middleware@2.26.1)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) '@svgr/webpack': 5.5.0 babel-jest: 27.5.1(@babel/core@7.21.4) - babel-loader: 8.3.0(@babel/core@7.21.4)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) + babel-loader: 8.3.0(@babel/core@7.21.4)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) 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.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) - css-minimizer-webpack-plugin: 3.4.1(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) + css-loader: 6.7.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) + css-minimizer-webpack-plugin: 3.4.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) dotenv: 10.0.0 dotenv-expand: 5.1.0 eslint: 9.9.1(jiti@1.21.6) - eslint-config-react-app: 7.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(jest@27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2) - eslint-webpack-plugin: 3.2.0(eslint@9.9.1(jiti@1.21.6))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) - file-loader: 6.2.0(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) + eslint-config-react-app: 7.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))))(eslint@9.9.1(jiti@1.21.6))(jest@27.5.1(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2) + eslint-webpack-plugin: 3.2.0(eslint@9.9.1(jiti@1.21.6))(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) + file-loader: 6.2.0(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) fs-extra: 10.1.0 - html-webpack-plugin: 5.5.3(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) + html-webpack-plugin: 5.5.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) identity-obj-proxy: 3.0.0 - jest: 27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) + jest: 27.5.1(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) jest-resolve: 27.5.1 - jest-watch-typeahead: 1.1.0(jest@27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2))) - mini-css-extract-plugin: 2.7.5(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) + jest-watch-typeahead: 1.1.0(jest@27.5.1(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2))) + mini-css-extract-plugin: 2.7.5(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) postcss: 8.4.47 postcss-flexbugs-fixes: 5.0.2(postcss@8.4.47) - postcss-loader: 6.2.1(postcss@8.4.47)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) + postcss-loader: 6.2.1(postcss@8.4.47)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) postcss-normalize: 10.0.1(browserslist@4.21.5)(postcss@8.4.47) postcss-preset-env: 7.8.3(postcss@8.4.47) prompts: 2.4.2 react: 18.3.1 react-app-polyfill: 3.0.0 - react-dev-utils: 12.0.1(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) + react-dev-utils: 12.0.1(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)(vue-template-compiler@2.7.16)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) react-refresh: 0.11.0 resolve: 1.22.2 resolve-url-loader: 4.0.0 - sass-loader: 12.6.0(sass@1.77.8)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) + sass-loader: 12.6.0(sass@1.77.8)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) semver: 7.5.4 - source-map-loader: 3.0.2(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) - style-loader: 3.3.2(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) - tailwindcss: 3.4.13(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) - terser-webpack-plugin: 5.3.7(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) - webpack-dev-server: 4.11.1(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) - webpack-manifest-plugin: 4.1.1(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) - workbox-webpack-plugin: 6.5.4(@types/babel__core@7.20.5)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) + source-map-loader: 3.0.2(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) + style-loader: 3.3.2(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) + tailwindcss: 3.4.13(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) + terser-webpack-plugin: 5.3.7(@swc/core@1.3.107(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) + webpack-dev-server: 4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) + webpack-manifest-plugin: 4.1.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) + workbox-webpack-plugin: 6.5.4(@types/babel__core@7.20.5)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) optionalDependencies: fsevents: 2.3.3 typescript: 5.6.2 @@ -77478,19 +77520,19 @@ snapshots: sanitize.css@13.0.0: {} - sass-loader@12.6.0(sass@1.77.8)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + sass-loader@12.6.0(sass@1.77.8)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)): dependencies: klona: 2.0.6 neo-async: 2.6.2 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) optionalDependencies: sass: 1.77.8 - sass-loader@12.6.0(sass@1.77.8)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): + sass-loader@12.6.0(sass@1.77.8)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: klona: 2.0.6 neo-async: 2.6.2 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) optionalDependencies: sass: 1.77.8 @@ -78129,19 +78171,19 @@ snapshots: source-map-js@1.2.1: {} - source-map-loader@3.0.2(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + source-map-loader@3.0.2(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)): dependencies: abab: 2.0.6 iconv-lite: 0.6.3 source-map-js: 1.2.1 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) - source-map-loader@3.0.2(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): + source-map-loader@3.0.2(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: abab: 2.0.6 iconv-lite: 0.6.3 source-map-js: 1.2.1 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) source-map-resolve@0.5.3: dependencies: @@ -78678,17 +78720,13 @@ snapshots: dependencies: webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) - style-loader@3.3.2(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): - dependencies: - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) - - style-loader@3.3.2(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)): + style-loader@3.3.2(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) - style-loader@3.3.2(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): + style-loader@3.3.2(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) style-mod@4.1.2: {} @@ -78700,12 +78738,12 @@ snapshots: dependencies: inline-style-parser: 0.2.3 - styled-jsx@5.1.1(@babel/core@7.25.2)(babel-plugin-macros@3.1.0)(react@18.3.1): + styled-jsx@5.1.1(@babel/core@7.24.3)(babel-plugin-macros@3.1.0)(react@18.3.1): dependencies: client-only: 0.0.1 react: 18.3.1 optionalDependencies: - '@babel/core': 7.25.2 + '@babel/core': 7.24.3 babel-plugin-macros: 3.1.0 stylehacks@5.1.1(postcss@8.4.47): @@ -78975,15 +79013,15 @@ snapshots: '@swc/core': 1.3.107(@swc/helpers@0.5.12) webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) - swc-loader@0.2.3(@swc/core@1.3.107(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + swc-loader@0.2.3(@swc/core@1.3.107(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: '@swc/core': 1.3.107(@swc/helpers@0.5.12) - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) - swc-loader@0.2.3(@swc/core@1.3.107(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)): + swc-loader@0.2.3(@swc/core@1.3.107(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: '@swc/core': 1.3.107(@swc/helpers@0.5.12) - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) swr@2.2.5(react@18.3.1): dependencies: @@ -79061,33 +79099,6 @@ snapshots: transitivePeerDependencies: - ts-node - tailwindcss@3.4.13(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)): - dependencies: - '@alloc/quick-lru': 5.2.0 - arg: 5.0.2 - chokidar: 3.6.0 - didyoumean: 1.2.2 - dlv: 1.1.3 - fast-glob: 3.3.1 - glob-parent: 6.0.2 - is-glob: 4.0.3 - jiti: 1.21.6 - lilconfig: 2.1.0 - micromatch: 4.0.8 - normalize-path: 3.0.0 - object-hash: 3.0.0 - picocolors: 1.1.0 - postcss: 8.4.47 - postcss-import: 15.1.0(postcss@8.4.47) - postcss-js: 4.0.1(postcss@8.4.47) - postcss-load-config: 4.0.2(postcss@8.4.47)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) - postcss-nested: 6.0.1(postcss@8.4.47) - postcss-selector-parser: 6.1.2 - resolve: 1.22.8 - sucrase: 3.35.0 - transitivePeerDependencies: - - ts-node - tailwindcss@3.4.13(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@22.7.4)(typescript@5.6.2)): dependencies: '@alloc/quick-lru': 5.2.0 @@ -79297,29 +79308,27 @@ snapshots: '@swc/core': 1.3.107(@swc/helpers@0.5.12) esbuild: 0.18.20 - terser-webpack-plugin@5.3.10(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)): + terser-webpack-plugin@5.3.10(@swc/core@1.3.107(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 terser: 5.31.6 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) optionalDependencies: '@swc/core': 1.3.107(@swc/helpers@0.5.12) - esbuild: 0.18.20 - terser-webpack-plugin@5.3.10(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + terser-webpack-plugin@5.3.10(@swc/core@1.3.107(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 terser: 5.31.6 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) optionalDependencies: '@swc/core': 1.3.107(@swc/helpers@0.5.12) - esbuild: 0.23.1 terser-webpack-plugin@5.3.10(@swc/core@1.3.107(@swc/helpers@0.5.12))(webpack@5.94.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: @@ -79332,29 +79341,28 @@ snapshots: optionalDependencies: '@swc/core': 1.3.107(@swc/helpers@0.5.12) - terser-webpack-plugin@5.3.10(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)): + terser-webpack-plugin@5.3.10(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 terser: 5.31.6 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4) optionalDependencies: '@swc/core': 1.7.26(@swc/helpers@0.5.12) - esbuild: 0.18.20 + esbuild: 0.23.1 - terser-webpack-plugin@5.3.10(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4)): + terser-webpack-plugin@5.3.10(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 terser: 5.31.6 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) optionalDependencies: '@swc/core': 1.7.26(@swc/helpers@0.5.12) - esbuild: 0.23.1 terser-webpack-plugin@5.3.10(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): dependencies: @@ -79378,28 +79386,28 @@ snapshots: optionalDependencies: '@swc/core': 1.7.26(@swc/helpers@0.5.12) - terser-webpack-plugin@5.3.7(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + terser-webpack-plugin@5.3.7(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 terser: 5.31.6 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) optionalDependencies: '@swc/core': 1.3.107(@swc/helpers@0.5.12) - esbuild: 0.23.1 + esbuild: 0.18.20 - terser-webpack-plugin@5.3.7(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): + terser-webpack-plugin@5.3.7(@swc/core@1.3.107(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 terser: 5.31.6 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) optionalDependencies: - '@swc/core': 1.7.26(@swc/helpers@0.5.12) + '@swc/core': 1.3.107(@swc/helpers@0.5.12) terser-webpack-plugin@5.3.9(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4)): dependencies: @@ -79739,11 +79747,11 @@ snapshots: dependencies: tslib: 1.14.1 - ts-jest@27.1.5(@babel/core@7.24.4)(@types/jest@29.5.2)(babel-jest@27.5.1(@babel/core@7.24.4))(jest@27.5.1(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2): + ts-jest@27.1.5(@babel/core@7.24.3)(@types/jest@29.5.13)(babel-jest@27.5.1(@babel/core@7.24.3))(jest@29.7.0(@types/node@18.16.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 - jest: 27.5.1(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) + jest: 29.7.0(@types/node@18.16.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) jest-util: 27.5.1 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -79752,11 +79760,11 @@ snapshots: typescript: 5.6.2 yargs-parser: 20.2.9 optionalDependencies: - '@babel/core': 7.24.4 - '@types/jest': 29.5.2 - babel-jest: 27.5.1(@babel/core@7.24.4) + '@babel/core': 7.24.3 + '@types/jest': 29.5.13 + babel-jest: 27.5.1(@babel/core@7.24.3) - ts-jest@27.1.5(@babel/core@7.25.2)(@types/jest@29.5.1)(babel-jest@27.5.1(@babel/core@7.25.2))(jest@27.5.1(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2): + ts-jest@27.1.5(@babel/core@7.24.4)(@types/jest@29.5.2)(babel-jest@27.5.1(@babel/core@7.24.4))(jest@27.5.1(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 @@ -79769,15 +79777,15 @@ snapshots: typescript: 5.6.2 yargs-parser: 20.2.9 optionalDependencies: - '@babel/core': 7.25.2 - '@types/jest': 29.5.1 - babel-jest: 27.5.1(@babel/core@7.25.2) + '@babel/core': 7.24.4 + '@types/jest': 29.5.2 + babel-jest: 27.5.1(@babel/core@7.24.4) - ts-jest@27.1.5(@babel/core@7.25.2)(@types/jest@29.5.13)(babel-jest@27.5.1(@babel/core@7.25.2))(jest@29.7.0(@types/node@18.16.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2): + ts-jest@27.1.5(@babel/core@7.25.2)(@types/jest@29.5.1)(babel-jest@27.5.1(@babel/core@7.25.2))(jest@27.5.1(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@18.16.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) + jest: 27.5.1(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) jest-util: 27.5.1 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -79787,7 +79795,7 @@ snapshots: yargs-parser: 20.2.9 optionalDependencies: '@babel/core': 7.25.2 - '@types/jest': 29.5.13 + '@types/jest': 29.5.1 babel-jest: 27.5.1(@babel/core@7.25.2) ts-jest@27.1.5(@babel/core@7.25.2)(@types/jest@29.5.13)(babel-jest@27.5.1(@babel/core@7.25.2))(jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2): @@ -79807,11 +79815,11 @@ snapshots: '@types/jest': 29.5.13 babel-jest: 27.5.1(@babel/core@7.25.2) - ts-jest@27.1.5(@babel/core@7.25.2)(@types/jest@29.5.2)(babel-jest@27.5.1(@babel/core@7.25.2))(jest@27.5.1(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@22.7.4)(typescript@5.6.2)))(typescript@5.6.2): + ts-jest@27.1.5(@babel/core@7.25.2)(@types/jest@29.5.2)(babel-jest@27.5.1(@babel/core@7.25.2))(jest@27.5.1(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 - jest: 27.5.1(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@22.7.4)(typescript@5.6.2)) + jest: 27.5.1(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) jest-util: 27.5.1 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -79824,11 +79832,11 @@ snapshots: '@types/jest': 29.5.2 babel-jest: 27.5.1(@babel/core@7.25.2) - ts-jest@27.1.5(@babel/core@7.25.2)(@types/jest@29.5.2)(babel-jest@27.5.1(@babel/core@7.25.2))(jest@27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2): + ts-jest@27.1.5(@babel/core@7.25.2)(@types/jest@29.5.2)(babel-jest@27.5.1(@babel/core@7.25.2))(jest@27.5.1(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@22.7.4)(typescript@5.6.2)))(typescript@5.6.2): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 - jest: 27.5.1(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) + jest: 27.5.1(ts-node@10.9.1(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@22.7.4)(typescript@5.6.2)) jest-util: 27.5.1 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -79858,7 +79866,7 @@ snapshots: '@types/jest': 29.5.2 babel-jest: 27.5.1(@babel/core@7.25.2) - ts-jest@29.1.0(@babel/core@7.25.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(esbuild@0.18.20)(jest@29.5.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2): + ts-jest@29.1.0(@babel/core@7.25.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.5.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 @@ -79874,24 +79882,6 @@ snapshots: '@babel/core': 7.25.2 '@jest/types': 29.6.3 babel-jest: 29.7.0(@babel/core@7.25.2) - esbuild: 0.18.20 - - ts-jest@29.1.2(@babel/core@7.24.4)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.4))(jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2): - dependencies: - bs-logger: 0.2.6 - fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) - jest-util: 29.7.0 - json5: 2.2.3 - lodash.memoize: 4.1.2 - make-error: 1.3.6 - semver: 7.6.3 - typescript: 5.6.2 - yargs-parser: 21.1.1 - optionalDependencies: - '@babel/core': 7.24.4 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.24.4) ts-jest@29.1.2(@babel/core@7.25.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(esbuild@0.23.1)(jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2): dependencies: @@ -79911,11 +79901,11 @@ snapshots: babel-jest: 29.7.0(@babel/core@7.25.2) esbuild: 0.23.1 - ts-jest@29.1.2(@babel/core@7.25.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2): + ts-jest@29.1.2(@babel/core@7.25.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)))(typescript@5.6.2): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@18.16.9)(typescript@5.6.2)) + jest: 29.7.0(@types/node@20.16.5)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -79937,32 +79927,23 @@ snapshots: typescript: 5.6.2 webpack: 5.94.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) - ts-loader@9.4.4(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)): - dependencies: - chalk: 4.1.2 - enhanced-resolve: 5.17.1 - micromatch: 4.0.8 - semver: 7.6.3 - typescript: 5.6.2 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) - - ts-loader@9.4.4(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)): + ts-loader@9.4.4(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4)): dependencies: chalk: 4.1.2 enhanced-resolve: 5.17.1 micromatch: 4.0.8 semver: 7.6.3 typescript: 5.6.2 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4) - ts-loader@9.4.4(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4)): + ts-loader@9.4.4(typescript@5.6.2)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: chalk: 4.1.2 enhanced-resolve: 5.17.1 micromatch: 4.0.8 semver: 7.6.3 typescript: 5.6.2 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) ts-loader@9.4.4(typescript@5.6.2)(webpack@5.94.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): dependencies: @@ -80123,6 +80104,27 @@ snapshots: optionalDependencies: '@swc/core': 1.3.107(@swc/helpers@0.5.12) + ts-node@10.9.2(@swc/core@1.3.107(@swc/helpers@0.5.12))(@types/node@20.16.5)(typescript@5.6.2): + 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': 20.16.5 + acorn: 8.12.1 + acorn-walk: 8.3.2 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.6.2 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + optionalDependencies: + '@swc/core': 1.3.107(@swc/helpers@0.5.12) + optional: true + ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.12))(@types/node@20.14.10)(typescript@5.6.2): dependencies: '@cspotcode/source-map-support': 0.8.1 @@ -80921,23 +80923,23 @@ snapshots: url-join@5.0.0: {} - url-loader@4.1.1(file-loader@6.2.0(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)))(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)): + url-loader@4.1.1(file-loader@6.2.0(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: loader-utils: 2.0.4 mime-types: 2.1.35 schema-utils: 3.3.0 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) optionalDependencies: - file-loader: 6.2.0(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) + file-loader: 6.2.0(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) - url-loader@4.1.1(file-loader@6.2.0(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)): + url-loader@4.1.1(file-loader@6.2.0(webpack@5.94.0(@swc/core@1.7.26(@swc/helpers@0.5.12))))(webpack@5.94.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): dependencies: loader-utils: 2.0.4 mime-types: 2.1.35 schema-utils: 3.3.0 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) + webpack: 5.94.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) optionalDependencies: - file-loader: 6.2.0(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) + file-loader: 6.2.0(webpack@5.94.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) url-parse@1.5.10: dependencies: @@ -81978,12 +81980,12 @@ snapshots: optionalDependencies: webpack-bundle-analyzer: 4.10.1 - webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0): + webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0): dependencies: '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0))(webpack-dev-server@4.11.1(webpack-cli@5.1.4)(webpack@5.78.0))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) + '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) + '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) colorette: 2.0.20 commander: 10.0.1 cross-spawn: 7.0.3 @@ -81992,11 +81994,10 @@ snapshots: import-local: 3.1.0 interpret: 3.1.1 rechoir: 0.8.0 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) webpack-merge: 5.9.0 optionalDependencies: webpack-bundle-analyzer: 4.9.0 - webpack-dev-server: 4.11.1(webpack-cli@5.1.4)(webpack@5.78.0) webpack-dev-middleware@5.3.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)): dependencies: @@ -82006,35 +82007,15 @@ snapshots: range-parser: 1.2.1 schema-utils: 4.0.0 webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) - optional: true - - webpack-dev-middleware@5.3.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): - 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.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) - - webpack-dev-middleware@5.3.3(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)): - 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.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) - optional: true - webpack-dev-middleware@5.3.3(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): + webpack-dev-middleware@5.3.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): 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.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) webpack-dev-middleware@6.1.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)): dependencies: @@ -82046,7 +82027,7 @@ snapshots: optionalDependencies: webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) - webpack-dev-middleware@6.1.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + webpack-dev-middleware@6.1.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: colorette: 2.0.19 memfs: 3.5.0 @@ -82054,9 +82035,9 @@ snapshots: range-parser: 1.2.1 schema-utils: 4.0.0 optionalDependencies: - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) - webpack-dev-middleware@6.1.1(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)): + webpack-dev-middleware@6.1.1(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)): dependencies: colorette: 2.0.19 memfs: 3.5.0 @@ -82064,48 +82045,7 @@ snapshots: range-parser: 1.2.1 schema-utils: 4.0.0 optionalDependencies: - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) - - webpack-dev-server@4.11.1(webpack-cli@5.1.4)(webpack@5.78.0): - 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.21.0 - 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.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4) - webpack-dev-middleware: 5.3.3(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) - ws: 8.13.0 - optionalDependencies: - webpack-cli: 5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0) - transitivePeerDependencies: - - bufferutil - - debug - - supports-color - - utf-8-validate - optional: true + webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4) webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)): dependencies: @@ -82144,9 +82084,8 @@ snapshots: - debug - supports-color - utf-8-validate - optional: true - webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: '@types/bonjour': 3.5.10 '@types/connect-history-api-fallback': 1.3.5 @@ -82175,46 +82114,8 @@ snapshots: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) - webpack-dev-middleware: 5.3.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) - ws: 8.13.0 - transitivePeerDependencies: - - bufferutil - - debug - - supports-color - - utf-8-validate - - webpack-dev-server@4.11.1(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): - 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.21.0 - 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.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) - webpack-dev-middleware: 5.3.3(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) + webpack-dev-middleware: 5.3.3(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) ws: 8.13.0 transitivePeerDependencies: - bufferutil @@ -82235,16 +82136,16 @@ snapshots: strip-ansi: 6.0.1 optional: true - webpack-manifest-plugin@4.1.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + webpack-manifest-plugin@4.1.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)): dependencies: tapable: 2.2.1 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) webpack-sources: 2.3.1 - webpack-manifest-plugin@4.1.1(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): + webpack-manifest-plugin@4.1.1(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: tapable: 2.2.1 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) webpack-sources: 2.3.1 webpack-merge@5.9.0: @@ -82270,7 +82171,7 @@ snapshots: webpack-virtual-modules@0.6.2: {} - webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20): + webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)): dependencies: '@types/eslint-scope': 3.7.4 '@types/estree': 0.0.51 @@ -82293,7 +82194,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) + terser-webpack-plugin: 5.3.10(@swc/core@1.3.107(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))) watchpack: 2.4.2 webpack-sources: 3.2.3 transitivePeerDependencies: @@ -82301,7 +82202,7 @@ snapshots: - esbuild - uglify-js - webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0)): + webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20): dependencies: '@types/eslint-scope': 3.7.4 '@types/estree': 0.0.51 @@ -82324,17 +82225,15 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) + terser-webpack-plugin: 5.3.10(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)) watchpack: 2.4.2 webpack-sources: 3.2.3 - optionalDependencies: - webpack-cli: 5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0) transitivePeerDependencies: - '@swc/core' - esbuild - uglify-js - webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1): + webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(webpack-cli@5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0)): dependencies: '@types/eslint-scope': 3.7.4 '@types/estree': 0.0.51 @@ -82357,9 +82256,11 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)) + terser-webpack-plugin: 5.3.10(@swc/core@1.3.107(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) watchpack: 2.4.2 webpack-sources: 3.2.3 + optionalDependencies: + webpack-cli: 5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0) transitivePeerDependencies: - '@swc/core' - esbuild @@ -82396,7 +82297,7 @@ snapshots: - esbuild - uglify-js - webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4): + webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4): dependencies: '@types/eslint-scope': 3.7.4 '@types/estree': 0.0.51 @@ -82419,17 +82320,17 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.18.20)(webpack-cli@5.1.4)) + terser-webpack-plugin: 5.3.10(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4)) watchpack: 2.4.2 webpack-sources: 3.2.3 optionalDependencies: - webpack-cli: 5.1.4(webpack-bundle-analyzer@4.9.0)(webpack-dev-server@4.11.1)(webpack@5.78.0) + webpack-cli: 5.1.4(webpack-bundle-analyzer@4.10.1)(webpack@5.78.0) transitivePeerDependencies: - '@swc/core' - esbuild - uglify-js - webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4): + webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4): dependencies: '@types/eslint-scope': 3.7.4 '@types/estree': 0.0.51 @@ -82452,11 +82353,11 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(esbuild@0.23.1)(webpack-cli@5.1.4)) + terser-webpack-plugin: 5.3.10(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))(webpack-cli@5.1.4)) watchpack: 2.4.2 webpack-sources: 3.2.3 optionalDependencies: - webpack-cli: 5.1.4(webpack-bundle-analyzer@4.10.1)(webpack@5.78.0) + webpack-cli: 5.1.4(webpack-bundle-analyzer@4.9.0)(webpack@5.78.0) transitivePeerDependencies: - '@swc/core' - esbuild @@ -82830,24 +82731,24 @@ snapshots: workbox-sw@6.5.4: {} - workbox-webpack-plugin@6.5.4(@types/babel__core@7.20.5)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1)): + workbox-webpack-plugin@6.5.4(@types/babel__core@7.20.5)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20)): dependencies: fast-json-stable-stringify: 2.1.0 pretty-bytes: 5.6.0 upath: 1.2.0 - webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.23.1) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))(esbuild@0.18.20) webpack-sources: 1.4.3 workbox-build: 6.5.4(@types/babel__core@7.20.5) transitivePeerDependencies: - '@types/babel__core' - supports-color - workbox-webpack-plugin@6.5.4(@types/babel__core@7.20.5)(webpack@5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12))): + workbox-webpack-plugin@6.5.4(@types/babel__core@7.20.5)(webpack@5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12))): dependencies: fast-json-stable-stringify: 2.1.0 pretty-bytes: 5.6.0 upath: 1.2.0 - webpack: 5.78.0(@swc/core@1.7.26(@swc/helpers@0.5.12)) + webpack: 5.78.0(@swc/core@1.3.107(@swc/helpers@0.5.12)) webpack-sources: 1.4.3 workbox-build: 6.5.4(@types/babel__core@7.20.5) transitivePeerDependencies: From b427d72d0fea6f331f80ac74242df7ddc5bc4fb4 Mon Sep 17 00:00:00 2001 From: Adam Chmara Date: Thu, 7 Nov 2024 13:02:44 +0100 Subject: [PATCH 06/29] feat(web): v3 dashboard opt-in widget (#6873) --- .source | 2 +- .../components/v2/NewDashboardOptInWidget.tsx | 112 ++++++++++++++++++ apps/web/src/components/nav/RootNavMenu.tsx | 2 + packages/shared/src/types/clerk/types.ts | 14 +++ .../src/types/feature-flags/feature-flags.ts | 1 + 5 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 apps/web/src/components/layout/components/v2/NewDashboardOptInWidget.tsx diff --git a/.source b/.source index eaa283b302c..9e5c90cd7b8 160000 --- a/.source +++ b/.source @@ -1 +1 @@ -Subproject commit eaa283b302c4ae7ede66b89d628971e6a8d96b8a +Subproject commit 9e5c90cd7b890fb05d35e0c489e59c976a98efa6 diff --git a/apps/web/src/components/layout/components/v2/NewDashboardOptInWidget.tsx b/apps/web/src/components/layout/components/v2/NewDashboardOptInWidget.tsx new file mode 100644 index 00000000000..439468bf3e8 --- /dev/null +++ b/apps/web/src/components/layout/components/v2/NewDashboardOptInWidget.tsx @@ -0,0 +1,112 @@ +import { Card } from '@mantine/core'; +import { css } from '@novu/novui/css'; +import { Text, Title, Button, IconButton } from '@novu/novui'; +import { IconOutlineClose } from '@novu/novui/icons'; +import { useUser } from '@clerk/clerk-react'; +import { FeatureFlagsKeysEnum, NewDashboardOptInStatusEnum } from '@novu/shared'; +import { IS_SELF_HOSTED } from '../../../../config'; +import { useFeatureFlag } from '../../../../hooks'; + +export function NewDashboardOptInWidget() { + const { user } = useUser(); + const isNewDashboardEnabled = useFeatureFlag(FeatureFlagsKeysEnum.IS_NEW_DASHBOARD_ENABLED); + + const isDismissed = user?.unsafeMetadata?.newDashboardOptInStatus === NewDashboardOptInStatusEnum.DISMISSED; + + if (IS_SELF_HOSTED || isDismissed || !isNewDashboardEnabled) { + return null; + } + + const updateUserOptInStatus = (status: NewDashboardOptInStatusEnum) => { + if (!user) return; + + user.update({ + unsafeMetadata: { + ...user.unsafeMetadata, + newDashboardOptInStatus: status, + }, + }); + }; + + function handleOptIn() { + const newDashboardUrl = process.env.NEW_DASHBOARD_URL; + if (!newDashboardUrl || !user) return; + + updateUserOptInStatus(NewDashboardOptInStatusEnum.OPTED_IN); + window.location.href = newDashboardUrl; + } + + function handleDismiss() { + updateUserOptInStatus(NewDashboardOptInStatusEnum.DISMISSED); + } + + return ( + +
+
+ + <span style={{ marginRight: '4px' }}>🎉</span> You're invited! + + +
+ + We’d love to extend you the access for the new workflows dashboard that we’re building. + +
+
+ +
+
+ ); +} + +const styles = { + card: css({ + padding: '9px 16px !important', + backgroundColor: 'surface.popover !important', + _before: { + content: '""', + position: 'absolute', + width: '50', + top: '0', + right: '0', + bottom: '0', + left: '0', + borderTopLeftRadius: '100', + borderBottomLeftRadius: '100', + bgGradient: `to-b`, + gradientFrom: 'colorPalette.start', + gradientTo: 'colorPalette.end', + }, + }), + content: css({ + display: 'flex', + flexDirection: 'column', + gap: '4px', + alignSelf: 'stretch', + }), + header: css({ + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', + gap: '8px', + }), + title: css({ + fontSize: '12px', + fontWeight: '700 ', + lineHeight: '20px', + }), + text: css({ + fontSize: '12px', + lineHeight: '16px', + fontWeight: '500', + fontStyle: 'normal', + }), + buttonContainer: css({ + display: 'flex', + alignItems: 'center', + justifyContent: 'flex-end', + }), +}; diff --git a/apps/web/src/components/nav/RootNavMenu.tsx b/apps/web/src/components/nav/RootNavMenu.tsx index ad87b9aad02..fe74056496a 100644 --- a/apps/web/src/components/nav/RootNavMenu.tsx +++ b/apps/web/src/components/nav/RootNavMenu.tsx @@ -39,6 +39,7 @@ import { SidebarFooter } from '../layout/components/LocalStudioSidebar/SidebarFo import { useNavigateToLocalStudio } from '../../studio/hooks/useNavigateToLocalStudio'; import { OpenLocalStudioModal } from '../../studio/components/OpenLocalStudioModal'; import { OutlineButton } from '../../studio/components/OutlineButton'; +import { NewDashboardOptInWidget } from '../layout/components/v2/NewDashboardOptInWidget'; const getEnvPageRoute = (route: ROUTES, env: BaseEnvironmentEnum) => parseUrl(route, { env }); @@ -161,6 +162,7 @@ export const RootNavMenu: React.FC = () => { {isV2Enabled ? ( <> + Open Local Studio diff --git a/packages/shared/src/types/clerk/types.ts b/packages/shared/src/types/clerk/types.ts index c34be4aeb4d..310e354c2af 100644 --- a/packages/shared/src/types/clerk/types.ts +++ b/packages/shared/src/types/clerk/types.ts @@ -19,3 +19,17 @@ export type UserPublicMetadata = { servicesHashes?: IServicesHashes; jobTitle?: JobTitleEnum; }; + +/** + * Unsafe metadata can be updated from the frontend directly + */ +export type UserUnsafeMetadata = { + newDashboardOptInStatus?: NewDashboardOptInStatusEnum; +}; + +export enum NewDashboardOptInStatusEnum { + OPTED_IN = 'opted_in', // user switched to the new dashboard + DISMISSED = 'dismissed', // user dismissed the opt-in widget + OPTED_OUT = 'opted_out', // user switched back to the old dashboard + // undefined -> user has not interacted with the widget yet +} diff --git a/packages/shared/src/types/feature-flags/feature-flags.ts b/packages/shared/src/types/feature-flags/feature-flags.ts index e892e4f5ef1..ce3af8ec06f 100644 --- a/packages/shared/src/types/feature-flags/feature-flags.ts +++ b/packages/shared/src/types/feature-flags/feature-flags.ts @@ -16,4 +16,5 @@ export enum FeatureFlagsKeysEnum { IS_INTEGRATION_INVALIDATION_DISABLED = 'IS_INTEGRATION_INVALIDATION_DISABLED', IS_EMAIL_INLINE_CSS_DISABLED = 'IS_EMAIL_INLINE_CSS_DISABLED', IS_CONTROLS_AUTOCOMPLETE_ENABLED = 'IS_CONTROLS_AUTOCOMPLETE_ENABLED', + IS_NEW_DASHBOARD_ENABLED = 'IS_NEW_DASHBOARD_ENABLED', } From c1f3f4aeff5f8a3676a82302d45be8adf33a161c Mon Sep 17 00:00:00 2001 From: Sokratis Vidros Date: Thu, 7 Nov 2024 16:09:00 +0200 Subject: [PATCH 07/29] fix(dashboard): Make step prefix shorter --- apps/dashboard/src/components/workflow-editor/schema.ts | 2 +- packages/shared/src/types/shared/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/dashboard/src/components/workflow-editor/schema.ts b/apps/dashboard/src/components/workflow-editor/schema.ts index 96c21c672ff..0c78ace3da1 100644 --- a/apps/dashboard/src/components/workflow-editor/schema.ts +++ b/apps/dashboard/src/components/workflow-editor/schema.ts @@ -30,7 +30,7 @@ export const workflowSchema = z.object({ type: z.nativeEnum(StepTypeEnum), _id: z.string(), stepId: z.string(), - slug: z.literal('_stp_'), + slug: z.literal('_st_'), }) .passthrough() ), diff --git a/packages/shared/src/types/shared/index.ts b/packages/shared/src/types/shared/index.ts index e3a9be3e98d..137eb7113ae 100644 --- a/packages/shared/src/types/shared/index.ts +++ b/packages/shared/src/types/shared/index.ts @@ -33,7 +33,7 @@ export type WorkflowName = string; export enum ShortIsPrefixEnum { WORKFLOW = 'wf_', - STEP = 'stp_', + STEP = 'st_', ENVIRONMENT = 'env_', } From 580f65070931682224c8446b8252083dbeaf05f3 Mon Sep 17 00:00:00 2001 From: Sokratis Vidros Date: Thu, 7 Nov 2024 16:20:26 +0200 Subject: [PATCH 08/29] fix(api): Remove caching from fetching topics per subscriber Prevent stale responses --- .../usecases/get-subscriber/get-subscriber.usecase.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/apps/api/src/app/subscribers/usecases/get-subscriber/get-subscriber.usecase.ts b/apps/api/src/app/subscribers/usecases/get-subscriber/get-subscriber.usecase.ts index 1d8a4987421..86460f542ae 100644 --- a/apps/api/src/app/subscribers/usecases/get-subscriber/get-subscriber.usecase.ts +++ b/apps/api/src/app/subscribers/usecases/get-subscriber/get-subscriber.usecase.ts @@ -48,13 +48,6 @@ export class GetSubscriber { return await this.subscriberRepository.findBySubscriberId(_environmentId, subscriberId); } - @CachedEntity({ - builder: (command: { subscriberId: string; _environmentId: string }) => - buildSubscriberTopicsKey({ - _environmentId: command._environmentId, - subscriberId: command.subscriberId, - }), - }) private async fetchSubscriberTopics({ subscriberId, _environmentId, From 4e7a42916f1757a78f0dca46eca0396ce98a0dd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Tymczuk?= Date: Thu, 7 Nov 2024 18:01:42 +0100 Subject: [PATCH 09/29] feat(dashboard): in-app editor form driven by BE schema (#6877) --- .../shared/schemas/in-app-control.schema.ts | 18 +- apps/dashboard/package.json | 1 + apps/dashboard/src/api/steps.ts | 14 + .../primitives/form/avatar-picker.tsx | 24 +- .../src/components/primitives/form/form.tsx | 49 ++-- .../src/components/primitives/sonner.tsx | 2 +- .../src/components/primitives/url-input.tsx | 69 ----- .../workflow-editor/action-picker.tsx | 247 ------------------ .../workflow-editor/steps/component-utils.tsx | 30 +++ .../configure-in-app-step-template-tabs.tsx | 147 ----------- .../workflow-editor/steps/configure-step.tsx | 4 +- .../steps/edit-step-sidebar.tsx | 70 +---- ...eview.tsx => configure-in-app-preview.tsx} | 2 +- .../{in-app.tsx => configure-in-app.tsx} | 6 +- .../steps/in-app/in-app-action.tsx | 203 ++++++++++++++ .../steps/in-app/in-app-avatar.tsx | 24 ++ .../steps/in-app/in-app-body.tsx | 46 ++++ .../in-app-editor-preview.tsx} | 2 +- .../steps/in-app/in-app-editor.tsx | 52 ++++ .../steps/in-app/in-app-redirect.tsx | 21 ++ .../steps/in-app/in-app-subject.tsx | 46 ++++ .../steps/in-app/in-app-tabs.tsx | 143 ++++++++++ .../workflow-editor/steps/step-editor.tsx | 23 +- .../components/workflow-editor/url-input.tsx | 103 ++++++++ .../workflow-editor-provider.tsx | 2 +- apps/dashboard/src/hooks/use-fetch-step.tsx | 20 ++ .../src/hooks/use-update-workflow.ts | 6 +- apps/dashboard/src/utils/schema.ts | 167 ++++++++++++ .../shared/src/dto/workflows/step-data.dto.ts | 1 + pnpm-lock.yaml | 20 +- 30 files changed, 989 insertions(+), 573 deletions(-) create mode 100644 apps/dashboard/src/api/steps.ts delete mode 100644 apps/dashboard/src/components/primitives/url-input.tsx delete mode 100644 apps/dashboard/src/components/workflow-editor/action-picker.tsx create mode 100644 apps/dashboard/src/components/workflow-editor/steps/component-utils.tsx delete mode 100644 apps/dashboard/src/components/workflow-editor/steps/configure-in-app-template/configure-in-app-step-template-tabs.tsx rename apps/dashboard/src/components/workflow-editor/steps/in-app/{edit-step-in-app-preview.tsx => configure-in-app-preview.tsx} (93%) rename apps/dashboard/src/components/workflow-editor/steps/in-app/{in-app.tsx => configure-in-app.tsx} (84%) create mode 100644 apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-action.tsx create mode 100644 apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-avatar.tsx create mode 100644 apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-body.tsx rename apps/dashboard/src/components/workflow-editor/steps/{configure-in-app-template/configure-in-app-step-template-preview.tsx => in-app/in-app-editor-preview.tsx} (98%) create mode 100644 apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-editor.tsx create mode 100644 apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-redirect.tsx create mode 100644 apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-subject.tsx create mode 100644 apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-tabs.tsx create mode 100644 apps/dashboard/src/components/workflow-editor/url-input.tsx create mode 100644 apps/dashboard/src/hooks/use-fetch-step.tsx create mode 100644 apps/dashboard/src/utils/schema.ts diff --git a/apps/api/src/app/workflows-v2/shared/schemas/in-app-control.schema.ts b/apps/api/src/app/workflows-v2/shared/schemas/in-app-control.schema.ts index bf2650f7c05..587e9c41e86 100644 --- a/apps/api/src/app/workflows-v2/shared/schemas/in-app-control.schema.ts +++ b/apps/api/src/app/workflows-v2/shared/schemas/in-app-control.schema.ts @@ -1,5 +1,5 @@ import { JSONSchema } from 'json-schema-to-ts'; -import { UiComponentEnum, UiSchema, UiSchemaGroupEnum } from '@novu/shared'; +import { UiComponentEnum, UiSchema, UiSchemaGroupEnum, UiSchemaProperty } from '@novu/shared'; const ABSOLUTE_AND_RELATIVE_URL_REGEX = '^(?!mailto:)(?:(https?):\\/\\/[^\\s/$.?#].[^\\s]*)|^(\\/[^\\s]*)$'; @@ -44,26 +44,42 @@ export const inAppControlSchema = { required: ['body'], additionalProperties: false, } as const satisfies JSONSchema; + +const redirectPlaceholder = { + url: { + placeholder: '', + }, + target: { + placeholder: '_self', + }, +}; + export const InAppUiSchema: UiSchema = { group: UiSchemaGroupEnum.IN_APP, properties: { body: { component: UiComponentEnum.IN_APP_BODY, + placeholder: '', }, avatar: { component: UiComponentEnum.IN_APP_AVATAR, + placeholder: '', }, subject: { component: UiComponentEnum.IN_APP_SUBJECT, + placeholder: '', }, primaryAction: { component: UiComponentEnum.IN_APP_BUTTON_DROPDOWN, + placeholder: null, }, secondaryAction: { component: UiComponentEnum.IN_APP_BUTTON_DROPDOWN, + placeholder: null, }, redirect: { component: UiComponentEnum.URL_TEXT_BOX, + placeholder: redirectPlaceholder, }, }, }; diff --git a/apps/dashboard/package.json b/apps/dashboard/package.json index 3b52879aae4..61f03fc29fb 100644 --- a/apps/dashboard/package.json +++ b/apps/dashboard/package.json @@ -76,6 +76,7 @@ "devDependencies": { "@clerk/types": "^4.6.1", "@eslint/js": "^9.9.0", + "@hookform/devtools": "^4.3.0", "@playwright/test": "^1.44.0", "@sentry/vite-plugin": "^2.22.6", "@types/lodash.debounce": "^4.0.9", diff --git a/apps/dashboard/src/api/steps.ts b/apps/dashboard/src/api/steps.ts new file mode 100644 index 00000000000..10af3c76415 --- /dev/null +++ b/apps/dashboard/src/api/steps.ts @@ -0,0 +1,14 @@ +import { getV2 } from './api.client'; +import type { StepDataDto } from '@novu/shared'; + +export const fetchStep = async ({ + workflowSlug, + stepSlug, +}: { + workflowSlug: string; + stepSlug: string; +}): Promise => { + const { data } = await getV2<{ data: StepDataDto }>(`/workflows/${workflowSlug}/steps/${stepSlug}`); + + return data; +}; diff --git a/apps/dashboard/src/components/primitives/form/avatar-picker.tsx b/apps/dashboard/src/components/primitives/form/avatar-picker.tsx index f5c36d87e5e..b89c4a3bd64 100644 --- a/apps/dashboard/src/components/primitives/form/avatar-picker.tsx +++ b/apps/dashboard/src/components/primitives/form/avatar-picker.tsx @@ -1,15 +1,14 @@ -'use client'; - import { Avatar, AvatarImage } from '@/components/primitives/avatar'; import { Button } from '@/components/primitives/button'; -import { FormControl, FormMessage } from '@/components/primitives/form/form'; +import { FormMessage } from '@/components/primitives/form/form'; import { Input, InputField } from '@/components/primitives/input'; import { Label } from '@/components/primitives/label'; import { Popover, PopoverContent, PopoverTrigger } from '@/components/primitives/popover'; import { Separator } from '@/components/primitives/separator'; import TextSeparator from '@/components/primitives/text-separator'; import { useState, forwardRef } from 'react'; -import { RiEdit2Line, RiImageEditFill } from 'react-icons/ri'; +import { RiEdit2Line, RiErrorWarningFill, RiImageEditFill } from 'react-icons/ri'; +import { useFormField } from './form-context'; const predefinedAvatars = [ `${window.location.origin}/images/avatar.svg`, @@ -30,6 +29,7 @@ type AvatarPickerProps = React.InputHTMLAttributes; export const AvatarPicker = forwardRef(({ id, ...props }, ref) => { const [isOpen, setIsOpen] = useState(false); + const { error } = useFormField(); const handlePredefinedAvatarClick = (url: string) => { props.onChange?.({ target: { value: url } } as React.ChangeEvent); @@ -40,14 +40,17 @@ export const AvatarPicker = forwardRef(({ i
- @@ -59,11 +62,9 @@ export const AvatarPicker = forwardRef(({ i
- - - - - + + +
@@ -80,7 +81,6 @@ export const AvatarPicker = forwardRef(({ i - ); }); diff --git a/apps/dashboard/src/components/primitives/form/form.tsx b/apps/dashboard/src/components/primitives/form/form.tsx index a54d3250235..9da0b29f8a7 100644 --- a/apps/dashboard/src/components/primitives/form/form.tsx +++ b/apps/dashboard/src/components/primitives/form/form.tsx @@ -101,28 +101,35 @@ const formMessageVariants = cva('flex items-center gap-1', { }, }); -const FormMessage = React.forwardRef>( - ({ className, children, ...props }, ref) => { - const { error, formMessageId } = useFormField(); - const body = error ? String(error?.message) : children; +const FormMessagePure = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes & { error?: string } +>(({ className, children, error, id, ...props }, ref) => { + const body = error ? error : children; + + if (!body) { + return null; + } - if (!body) { - return null; - } + return ( +

+ {error ? : } + {body} +

+ ); +}); +FormMessagePure.displayName = 'FormMessagePure'; - return ( -

- {error ? : } - {body} -

- ); - } -); +const FormMessage = React.forwardRef>((props, ref) => { + const { error, formMessageId } = useFormField(); + + return ; +}); FormMessage.displayName = 'FormMessage'; -export { Form, FormItem, FormLabel, FormControl, FormDescription, FormMessage, FormField }; +export { Form, FormItem, FormLabel, FormControl, FormDescription, FormMessage, FormMessagePure, FormField }; diff --git a/apps/dashboard/src/components/primitives/sonner.tsx b/apps/dashboard/src/components/primitives/sonner.tsx index cb5601952b5..1e122464fbf 100644 --- a/apps/dashboard/src/components/primitives/sonner.tsx +++ b/apps/dashboard/src/components/primitives/sonner.tsx @@ -91,7 +91,7 @@ const Toaster = ({ ...props }: ToasterProps) => { toastOptions={{ classNames: { toast: - 'group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg text-foreground-950', + 'group toast group-[.toaster]:bg-transparent group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg text-foreground-950', description: 'group-[.toast]:text-foreground-600', actionButton: 'group-[.toast]:bg-primary group-[.toast]:text-primary-foreground', cancelButton: 'group-[.toast]:bg-muted group-[.toast]:text-muted-foreground', diff --git a/apps/dashboard/src/components/primitives/url-input.tsx b/apps/dashboard/src/components/primitives/url-input.tsx deleted file mode 100644 index 688a8d86aed..00000000000 --- a/apps/dashboard/src/components/primitives/url-input.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { forwardRef } from 'react'; -import { liquid } from '@codemirror/lang-liquid'; -import { EditorView } from '@uiw/react-codemirror'; -import { RedirectTargetEnum } from '@novu/shared'; -import { Input, InputField, InputFieldProps, InputProps } from '@/components/primitives/input'; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/primitives/select'; -import { Editor } from './editor'; - -type URLValue = { - type: string; - url: string; -}; - -type URLInputProps = Omit & { - options: string[]; - value: URLValue; - onChange: (value: URLValue) => void; - asEditor?: boolean; -} & Pick; - -export const URLInput = forwardRef((props, ref) => { - const { options, value, onChange, size = 'default', asEditor = false, placeholder, ...rest } = props; - - return ( -
-
- - {asEditor ? ( - onChange({ ...value, url: val })} - height={size === 'md' ? '38px' : '30px'} - extensions={[ - liquid({ - variables: [{ type: 'variable', label: 'asdf' }], - }), - EditorView.lineWrapping, - ]} - /> - ) : ( - onChange({ ...value, url: e.target.value })} - {...rest} - /> - )} - - -
-
- ); -}); diff --git a/apps/dashboard/src/components/workflow-editor/action-picker.tsx b/apps/dashboard/src/components/workflow-editor/action-picker.tsx deleted file mode 100644 index 6a41c7c397c..00000000000 --- a/apps/dashboard/src/components/workflow-editor/action-picker.tsx +++ /dev/null @@ -1,247 +0,0 @@ -import { ComponentProps } from 'react'; -import { zodResolver } from '@hookform/resolvers/zod'; -import { useForm } from 'react-hook-form'; -import { RiEdit2Line, RiExpandUpDownLine, RiForbid2Line } from 'react-icons/ri'; -import { z } from 'zod'; -import { liquid } from '@codemirror/lang-liquid'; -import { EditorView } from '@uiw/react-codemirror'; -import { RedirectTargetEnum } from '@novu/shared'; -import { Button, buttonVariants } from '@/components/primitives/button'; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from '@/components/primitives/dropdown-menu'; -import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/primitives/form/form'; -import { InputField } from '@/components/primitives/input'; -import { Popover, PopoverContent, PopoverTrigger } from '@/components/primitives/popover'; -import { Separator } from '@/components/primitives/separator'; -import { URLInput } from '@/components/primitives/url-input'; -import { cn } from '@/utils/ui'; -import { urlTargetTypes } from '@/utils/url'; -import { Editor } from '../primitives/editor'; - -type Action = { - label: string; - redirect: { - url: string; - type: string; - }; -}; - -type Actions = { - primaryAction?: Action; - secondaryAction?: Action; -}; - -type ActionPickerProps = { - className?: string; - value: Actions | undefined; - onChange: (value: Actions) => void; -}; - -export const ActionPicker = (props: ActionPickerProps) => { - const { className, value, onChange } = props; - const primaryAction = value?.primaryAction; - const secondaryAction = value?.secondaryAction; - - return ( -
-
- {!primaryAction && !secondaryAction && ( -
- - No action -
- )} - {primaryAction && ( - { - onChange({ primaryAction, secondaryAction }); - }} - > - - - )} - {secondaryAction && ( - { - onChange({ primaryAction, secondaryAction }); - }} - > - - - )} -
- - - - - - { - onChange({}); - }} - > -
- - No action -
-
- { - onChange({ - primaryAction: value?.primaryAction || { - label: 'Primary action', - redirect: { type: '_self', url: '' }, - }, - secondaryAction: undefined, - }); - }} - > -
- Primary action -
-
- { - onChange({ - primaryAction: value?.primaryAction || { - label: 'Primary action', - redirect: { type: '_self', url: '' }, - }, - secondaryAction: value?.secondaryAction || { - label: 'Secondary action', - redirect: { type: '_self', url: '' }, - }, - }); - }} - > -
- Primary action -
-
- Secondary action -
-
-
-
-
- ); -}; - -const formSchema = z.object({ - label: z.string(), - redirect: z.object({ - url: z.string(), - type: z.union([ - z.literal(RedirectTargetEnum.BLANK), - z.literal(RedirectTargetEnum.PARENT), - z.literal(RedirectTargetEnum.SELF), - z.literal(RedirectTargetEnum.TOP), - z.literal(RedirectTargetEnum.UNFENCED_TOP), - ]), - }), -}); - -const ConfigureActionPopover = ( - props: ComponentProps & { action: Action; setAction: (action: Action) => void } -) => { - const { setAction, action, ...rest } = props; - - const form = useForm({ - resolver: zodResolver(formSchema), - defaultValues: { - label: action.label, - redirect: action.redirect, - }, - }); - - return ( - { - if (!open) { - form.handleSubmit((values) => { - setAction(values); - })(); - } - }} - > - - -
- -
-
- Customize button -
- - ( - -
- Button text -
- - - - - - -
- )} - /> - - ( - -
- Redirect URL -
- - field.onChange(val)} - asEditor - /> - - -
- )} - /> -
-
- -
-
- ); -}; diff --git a/apps/dashboard/src/components/workflow-editor/steps/component-utils.tsx b/apps/dashboard/src/components/workflow-editor/steps/component-utils.tsx new file mode 100644 index 00000000000..338c335a381 --- /dev/null +++ b/apps/dashboard/src/components/workflow-editor/steps/component-utils.tsx @@ -0,0 +1,30 @@ +import { UiComponentEnum } from '@novu/shared'; + +import { InAppAction } from '@/components/workflow-editor/steps/in-app/in-app-action'; +import { InAppSubject } from '@/components/workflow-editor/steps/in-app/in-app-subject'; +import { InAppBody } from '@/components/workflow-editor/steps/in-app/in-app-body'; +import { InAppAvatar } from '@/components/workflow-editor/steps/in-app/in-app-avatar'; +import { InAppRedirect } from '@/components/workflow-editor/steps/in-app/in-app-redirect'; + +export const getComponentByType = ({ component }: { component?: UiComponentEnum }) => { + switch (component) { + case UiComponentEnum.IN_APP_AVATAR: { + return ; + } + case UiComponentEnum.IN_APP_SUBJECT: { + return ; + } + case UiComponentEnum.IN_APP_BODY: { + return ; + } + case UiComponentEnum.IN_APP_BUTTON_DROPDOWN: { + return ; + } + case UiComponentEnum.URL_TEXT_BOX: { + return ; + } + default: { + return null; + } + } +}; diff --git a/apps/dashboard/src/components/workflow-editor/steps/configure-in-app-template/configure-in-app-step-template-tabs.tsx b/apps/dashboard/src/components/workflow-editor/steps/configure-in-app-template/configure-in-app-step-template-tabs.tsx deleted file mode 100644 index 545e123ac45..00000000000 --- a/apps/dashboard/src/components/workflow-editor/steps/configure-in-app-template/configure-in-app-step-template-tabs.tsx +++ /dev/null @@ -1,147 +0,0 @@ -import { useState } from 'react'; -import { RiEdit2Line, RiInformationFill, RiPencilRuler2Line } from 'react-icons/ri'; -import { Cross2Icon } from '@radix-ui/react-icons'; -import { useNavigate } from 'react-router-dom'; -import { useFormContext } from 'react-hook-form'; -import * as z from 'zod'; -import { liquid } from '@codemirror/lang-liquid'; -import { EditorView } from '@uiw/react-codemirror'; -import { RedirectTargetEnum } from '@novu/shared'; - -import { Notification5Fill } from '@/components/icons'; -import { Button } from '@/components/primitives/button'; -import { Editor } from '@/components/primitives/editor'; -import { AvatarPicker } from '@/components/primitives/form/avatar-picker'; -import { InputField } from '@/components/primitives/input'; -import { Separator } from '@/components/primitives/separator'; -import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/primitives/tabs'; -import { URLInput } from '@/components/primitives/url-input'; -import { urlTargetTypes } from '@/utils/url'; -import { ActionPicker } from '../../action-picker'; -import { workflowSchema } from '../../schema'; -import { ConfigureInAppStepTemplatePreview } from '@/components/workflow-editor/steps/configure-in-app-template/configure-in-app-step-template-preview'; - -const tabsContentClassName = 'h-full w-full px-3 py-3.5'; - -export const ConfigureInAppStepTemplateTabs = () => { - const navigate = useNavigate(); - const { formState } = useFormContext>(); - - const [subject, setSubject] = useState(''); - const [body, setBody] = useState(''); - - return ( - -
-
- - Configure Template -
- - - - Editor - - - - Preview - - - - -
- - -
-
- - In-app Template -
-
-
- - - - -
- - - -
- - - {'This supports markdown and variables, type { for more.'} - -
- {}} - className="mt-3" - /> -
-
- - console.log(val)} - placeholder="Redirect URL" - size="md" - asEditor - /> -
-
-
- - - - -
- -
-
- ); -}; diff --git a/apps/dashboard/src/components/workflow-editor/steps/configure-step.tsx b/apps/dashboard/src/components/workflow-editor/steps/configure-step.tsx index 9fecf97aa0c..64393aae649 100644 --- a/apps/dashboard/src/components/workflow-editor/steps/configure-step.tsx +++ b/apps/dashboard/src/components/workflow-editor/steps/configure-step.tsx @@ -8,7 +8,7 @@ import { useEnvironment } from '@/context/environment/hooks'; import { StepTypeEnum } from '@/utils/enums'; import { buildRoute, ROUTES } from '@/utils/routes'; import { motion } from 'framer-motion'; -import { InApp } from './in-app/in-app'; +import { ConfigureInApp } from './in-app/configure-in-app'; import { useStep } from './use-step'; import Chat from './chat'; import { useState } from 'react'; @@ -102,7 +102,7 @@ export function ConfigureStep() { const Step = ({ stepType }: { stepType?: StepTypeEnum }) => { switch (stepType) { case StepTypeEnum.IN_APP: - return ; + return ; /** * TODO: Add other step types here diff --git a/apps/dashboard/src/components/workflow-editor/steps/edit-step-sidebar.tsx b/apps/dashboard/src/components/workflow-editor/steps/edit-step-sidebar.tsx index 603d25fa187..1c7bc926a5d 100644 --- a/apps/dashboard/src/components/workflow-editor/steps/edit-step-sidebar.tsx +++ b/apps/dashboard/src/components/workflow-editor/steps/edit-step-sidebar.tsx @@ -1,59 +1,23 @@ -import { Form } from '@/components/primitives/form/form'; -import { Sheet, SheetOverlay, SheetPortal } from '@/components/primitives/sheet'; -import { useFetchWorkflow, useUpdateWorkflow } from '@/hooks'; -import { handleValidationIssues } from '@/utils/handleValidationIssues'; -import { zodResolver } from '@hookform/resolvers/zod'; +import { useMemo } from 'react'; import { motion } from 'framer-motion'; -import { useLayoutEffect, useMemo } from 'react'; -import { useForm } from 'react-hook-form'; -import { useNavigate, useParams } from 'react-router-dom'; -import * as z from 'zod'; -import { workflowSchema } from '../schema'; -import { StepEditor } from './step-editor'; +import { useParams } from 'react-router-dom'; + +import { Sheet, SheetOverlay, SheetPortal } from '@/components/primitives/sheet'; +import { useFetchWorkflow } from '@/hooks/use-fetch-workflow'; +import { StepEditor } from '@/components/workflow-editor/steps/step-editor'; +import { useFetchStep } from '@/hooks/use-fetch-step'; const transitionSetting = { ease: [0.29, 0.83, 0.57, 0.99], duration: 0.4 }; export const EditStepSidebar = () => { const { workflowSlug = '', stepSlug = '' } = useParams<{ workflowSlug: string; stepSlug: string }>(); - const navigate = useNavigate(); - const form = useForm>({ mode: 'onSubmit', resolver: zodResolver(workflowSchema) }); - const { reset, setError } = form; - const { workflow, error } = useFetchWorkflow({ + const { workflow } = useFetchWorkflow({ workflowSlug, }); - const step = useMemo(() => workflow?.steps.find((el) => el.slug === stepSlug), [stepSlug, workflow]); - - useLayoutEffect(() => { - if (!workflow) { - return; - } - - reset({ ...workflow, steps: workflow.steps.map((step) => ({ ...step })) }); - }, [workflow, error, navigate, reset]); - - const { updateWorkflow } = useUpdateWorkflow({ - onSuccess: (data) => { - reset({ ...data, steps: data.steps.map((step) => ({ ...step })) }); - - if (data.issues) { - // TODO: remove the as any cast when BE issues are typed - handleValidationIssues({ fields: form.getValues(), issues: data.issues as any, setError }); - } - - // TODO: show the toast - navigate(`../`, { relative: 'path' }); - }, - }); - - const onSubmit = (data: z.infer) => { - if (!workflow) { - return; - } - - updateWorkflow({ id: workflow._id, workflow: { ...workflow, ...data } as any }); - }; + const { step } = useFetchStep({ workflowSlug, stepSlug }); + const stepType = useMemo(() => workflow?.steps.find((el) => el.slug === stepSlug)?.type, [stepSlug, workflow]); return ( @@ -87,18 +51,8 @@ export const EditStepSidebar = () => { 'bg-background fixed inset-y-0 right-0 z-50 flex h-full w-3/4 flex-col border-l shadow-lg sm:max-w-[600px]' } > -
- { - event.preventDefault(); - event.stopPropagation(); - form.handleSubmit(onSubmit)(event); - }} - > - {step && } - - + {/* TODO: show loading indicator */} + {workflow && step && stepType && }
diff --git a/apps/dashboard/src/components/workflow-editor/steps/in-app/edit-step-in-app-preview.tsx b/apps/dashboard/src/components/workflow-editor/steps/in-app/configure-in-app-preview.tsx similarity index 93% rename from apps/dashboard/src/components/workflow-editor/steps/in-app/edit-step-in-app-preview.tsx rename to apps/dashboard/src/components/workflow-editor/steps/in-app/configure-in-app-preview.tsx index a27e2479e87..bac9a5eedab 100644 --- a/apps/dashboard/src/components/workflow-editor/steps/in-app/edit-step-in-app-preview.tsx +++ b/apps/dashboard/src/components/workflow-editor/steps/in-app/configure-in-app-preview.tsx @@ -3,7 +3,7 @@ import { useParams } from 'react-router-dom'; import { usePreviewStep } from '@/hooks'; import { InAppPreview } from '@/components/workflow-editor/in-app-preview'; -export function EditStepInAppPreview() { +export function ConfigureInAppPreview() { const { previewStep, data } = usePreviewStep(); const { workflowSlug, stepSlug } = useParams<{ workflowSlug: string; diff --git a/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app.tsx b/apps/dashboard/src/components/workflow-editor/steps/in-app/configure-in-app.tsx similarity index 84% rename from apps/dashboard/src/components/workflow-editor/steps/in-app/in-app.tsx rename to apps/dashboard/src/components/workflow-editor/steps/in-app/configure-in-app.tsx index 51f5ef007ea..31b099f7e3e 100644 --- a/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app.tsx +++ b/apps/dashboard/src/components/workflow-editor/steps/in-app/configure-in-app.tsx @@ -4,9 +4,9 @@ import { Button } from '../../../primitives/button'; import { Separator } from '../../../primitives/separator'; import { CommonFields } from '../common-fields'; import { SidebarContent } from '@/components/side-navigation/Sidebar'; -import { EditStepInAppPreview } from '@/components/workflow-editor/steps/in-app/edit-step-in-app-preview'; +import { ConfigureInAppPreview } from './configure-in-app-preview'; -export function InApp() { +export function ConfigureInApp() { return ( <> @@ -21,7 +21,7 @@ export function InApp() { - + ); diff --git a/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-action.tsx b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-action.tsx new file mode 100644 index 00000000000..a962661513f --- /dev/null +++ b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-action.tsx @@ -0,0 +1,203 @@ +import { ComponentProps } from 'react'; +import { useFormContext, useWatch } from 'react-hook-form'; +import { RiEdit2Line, RiExpandUpDownLine, RiForbid2Line } from 'react-icons/ri'; +import { liquid } from '@codemirror/lang-liquid'; +import { EditorView } from '@uiw/react-codemirror'; + +import { Button, buttonVariants } from '@/components/primitives/button'; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from '@/components/primitives/dropdown-menu'; +import { + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, + FormMessagePure, +} from '@/components/primitives/form/form'; +import { InputField } from '@/components/primitives/input'; +import { Popover, PopoverContent, PopoverTrigger } from '@/components/primitives/popover'; +import { Separator } from '@/components/primitives/separator'; +import { URLInput } from '@/components/workflow-editor/url-input'; +import { cn } from '@/utils/ui'; +import { urlTargetTypes } from '@/utils/url'; +import { Editor } from '@/components/primitives/editor'; + +const primaryActionKey = 'primaryAction'; +const secondaryActionKey = 'secondaryAction'; + +export const InAppAction = () => { + const { control, setValue, getFieldState } = useFormContext(); + const primaryAction = useWatch({ control, name: primaryActionKey }); + const secondaryAction = useWatch({ control, name: secondaryActionKey }); + const primaryActionLabel = getFieldState(`${primaryActionKey}.label`); + const primaryActionRedirectUrl = getFieldState(`${primaryActionKey}.redirect.url`); + const secondaryActionLabel = getFieldState(`${secondaryActionKey}.label`); + const secondaryActionRedirectUrl = getFieldState(`${secondaryActionKey}.redirect.url`); + const error = + primaryActionLabel.error || + primaryActionRedirectUrl.error || + secondaryActionLabel.error || + secondaryActionRedirectUrl.error; + + return ( + <> +
+
+ {!primaryAction && !secondaryAction && ( +
+ + No action +
+ )} + {primaryAction && ( + + + + )} + {secondaryAction && ( + + + + )} +
+ + + + + + { + setValue(primaryActionKey, undefined, { shouldDirty: true, shouldValidate: false }); + setValue(secondaryActionKey, undefined, { shouldDirty: true, shouldValidate: false }); + }} + > +
+ + No action +
+
+ { + setValue( + primaryActionKey, + { + label: 'Primary action', + redirect: { target: '_self', url: '' }, + }, + { shouldDirty: true, shouldValidate: false } + ); + setValue(secondaryActionKey, undefined, { shouldDirty: true, shouldValidate: false }); + }} + > +
+ Primary action +
+
+ { + setValue( + primaryActionKey, + { + label: 'Primary action', + redirect: { target: '_self', url: '' }, + }, + { shouldDirty: true, shouldValidate: false } + ); + setValue( + secondaryActionKey, + { + label: 'Secondary action', + redirect: { target: '_self', url: '' }, + }, + { shouldDirty: true, shouldValidate: false } + ); + }} + > +
+ Primary action +
+
+ Secondary action +
+
+
+
+
+ + + ); +}; + +const ConfigureActionPopover = (props: ComponentProps & { fields: { actionKey: string } }) => { + const { + fields: { actionKey }, + ...rest + } = props; + const { control } = useFormContext(); + + return ( + + + +
+
+ Customize button +
+ + ( + +
+ Button text +
+ + + + + + +
+ )} + /> +
+ Redirect URL + +
+
+
+
+ ); +}; diff --git a/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-avatar.tsx b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-avatar.tsx new file mode 100644 index 00000000000..9ac39abaf41 --- /dev/null +++ b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-avatar.tsx @@ -0,0 +1,24 @@ +import { useFormContext } from 'react-hook-form'; + +import { FormControl, FormField, FormItem } from '@/components/primitives/form/form'; +import { AvatarPicker } from '@/components/primitives/form/avatar-picker'; + +const avatarKey = 'avatar'; + +export const InAppAvatar = () => { + const { control } = useFormContext(); + + return ( + ( + + + + + + )} + /> + ); +}; diff --git a/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-body.tsx b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-body.tsx new file mode 100644 index 00000000000..b43e4e801da --- /dev/null +++ b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-body.tsx @@ -0,0 +1,46 @@ +import { useFormContext } from 'react-hook-form'; +import { liquid } from '@codemirror/lang-liquid'; +import { EditorView } from '@uiw/react-codemirror'; + +import { FormControl, FormField, FormItem, FormMessage } from '@/components/primitives/form/form'; +import { InputField } from '@/components/primitives/input'; +import { Editor } from '@/components/primitives/editor'; +import { capitalize } from '@/utils/string'; + +const bodyKey = 'body'; + +export const InAppBody = () => { + const { + control, + formState: { errors }, + } = useFormContext(); + + return ( + ( + + + + field.onChange(val)} + /> + + + + + )} + /> + ); +}; diff --git a/apps/dashboard/src/components/workflow-editor/steps/configure-in-app-template/configure-in-app-step-template-preview.tsx b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-editor-preview.tsx similarity index 98% rename from apps/dashboard/src/components/workflow-editor/steps/configure-in-app-template/configure-in-app-step-template-preview.tsx rename to apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-editor-preview.tsx index 4ab3669af05..4fff3697a7f 100644 --- a/apps/dashboard/src/components/workflow-editor/steps/configure-in-app-template/configure-in-app-step-template-preview.tsx +++ b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-editor-preview.tsx @@ -11,7 +11,7 @@ import { useParams } from 'react-router-dom'; import { InAppPreview } from '@/components/workflow-editor/in-app-preview'; import { loadLanguage } from '@uiw/codemirror-extensions-langs'; -export const ConfigureInAppStepTemplatePreview = () => { +export const InAppEditorPreview = () => { const [editorValue, setEditorValue] = useState('{}'); const [isEditorOpen, setIsEditorOpen] = useState(true); const { previewStep, data } = usePreviewStep(); diff --git a/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-editor.tsx b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-editor.tsx new file mode 100644 index 00000000000..dbe546dc7b2 --- /dev/null +++ b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-editor.tsx @@ -0,0 +1,52 @@ +import { RiPencilRuler2Line } from 'react-icons/ri'; +import { UiSchemaGroupEnum, type UiSchema } from '@novu/shared'; + +import { getComponentByType } from '@/components/workflow-editor/steps/component-utils'; + +const avatarKey = 'avatar'; +const subjectKey = 'subject'; +const bodyKey = 'body'; +const redirectKey = 'redirect'; +const primaryActionKey = 'primaryAction'; +const secondaryActionKey = 'secondaryAction'; + +export const InAppEditor = ({ uiSchema }: { uiSchema?: UiSchema }) => { + if (!uiSchema || uiSchema?.group !== UiSchemaGroupEnum.IN_APP) { + return null; + } + + const { + [avatarKey]: avatar, + [subjectKey]: subject, + [bodyKey]: body, + [redirectKey]: redirect, + [primaryActionKey]: primaryAction, + [secondaryActionKey]: secondaryAction, + } = uiSchema.properties ?? {}; + + return ( +
+
+ + In-app Template +
+
+ {(avatar || subject) && ( +
+ {avatar && getComponentByType({ component: avatar.component })} + {subject && getComponentByType({ component: subject.component })} +
+ )} + {body && getComponentByType({ component: body.component })} + {(primaryAction || secondaryAction) && + getComponentByType({ + component: primaryAction.component || secondaryAction.component, + })} +
+ {redirect && + getComponentByType({ + component: redirect.component, + })} +
+ ); +}; diff --git a/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-redirect.tsx b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-redirect.tsx new file mode 100644 index 00000000000..1dddbd7f4fc --- /dev/null +++ b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-redirect.tsx @@ -0,0 +1,21 @@ +import { FormLabel } from '@/components/primitives/form/form'; +import { URLInput } from '../../url-input'; +import { urlTargetTypes } from '@/utils/url'; + +export const InAppRedirect = () => { + return ( +
+ Redirect URL + +
+ ); +}; diff --git a/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-subject.tsx b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-subject.tsx new file mode 100644 index 00000000000..0daf67acd71 --- /dev/null +++ b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-subject.tsx @@ -0,0 +1,46 @@ +import { useFormContext } from 'react-hook-form'; +import { liquid } from '@codemirror/lang-liquid'; +import { EditorView } from '@uiw/react-codemirror'; + +import { FormControl, FormField, FormItem, FormMessage } from '@/components/primitives/form/form'; +import { InputField } from '@/components/primitives/input'; +import { Editor } from '@/components/primitives/editor'; +import { capitalize } from '@/utils/string'; + +const subjectKey = 'subject'; + +export const InAppSubject = () => { + const { + control, + formState: { errors }, + } = useFormContext(); + + return ( + ( + + + + field.onChange(val)} + /> + + + + + )} + /> + ); +}; diff --git a/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-tabs.tsx b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-tabs.tsx new file mode 100644 index 00000000000..d257a1acacf --- /dev/null +++ b/apps/dashboard/src/components/workflow-editor/steps/in-app/in-app-tabs.tsx @@ -0,0 +1,143 @@ +import { RiEdit2Line, RiPencilRuler2Line } from 'react-icons/ri'; +import { Cross2Icon } from '@radix-ui/react-icons'; +import { useNavigate, useParams } from 'react-router-dom'; +import { useForm } from 'react-hook-form'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { type WorkflowResponseDto, type StepDataDto, type StepUpdateDto } from '@novu/shared'; + +import { Form } from '@/components/primitives/form/form'; +import { Notification5Fill } from '@/components/icons'; +import { Button } from '@/components/primitives/button'; +import { Separator } from '@/components/primitives/separator'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/primitives/tabs'; +import { InAppEditorPreview } from '@/components/workflow-editor/steps/in-app/in-app-editor-preview'; +import { useUpdateWorkflow } from '@/hooks/use-update-workflow'; +import { buildDynamicZodSchema, buildDefaultValues } from '@/utils/schema'; +import { InAppEditor } from '@/components/workflow-editor/steps/in-app/in-app-editor'; +import { showToast } from '@/components/primitives/sonner-helpers'; +import { ToastIcon } from '@/components/primitives/sonner'; + +const tabsContentClassName = 'h-full w-full px-3 py-3.5'; + +export const InAppTabs = ({ workflow, step }: { workflow: WorkflowResponseDto; step: StepDataDto }) => { + const { stepSlug = '' } = useParams<{ stepSlug: string }>(); + const { dataSchema, uiSchema } = step.controls; + const navigate = useNavigate(); + const schema = buildDynamicZodSchema(dataSchema ?? {}); + const form = useForm({ + mode: 'onSubmit', + resolver: zodResolver(schema), + resetOptions: { keepDirtyValues: true }, + defaultValues: buildDefaultValues(uiSchema ?? {}), + values: step.controls.values, + }); + const { reset, formState } = form; + + const { updateWorkflow } = useUpdateWorkflow({ + onSuccess: () => { + showToast({ + children: () => ( + <> + + Saved + + ), + options: { + position: 'bottom-right', + classNames: { + toast: 'ml-10 mb-4', + }, + }, + }); + }, + onError: () => { + showToast({ + children: () => ( + <> + + Failed to save + + ), + options: { + position: 'bottom-right', + classNames: { + toast: 'ml-10 mb-4', + }, + }, + }); + }, + }); + + const onSubmit = async (data: any) => { + await updateWorkflow({ + id: workflow._id, + workflow: { + ...workflow, + steps: workflow.steps.map((step) => + step.slug === stepSlug ? ({ ...step, controlValues: { ...data } } as StepUpdateDto) : step + ), + }, + }); + reset({ ...data }); + }; + + return ( +
+ { + event.preventDefault(); + event.stopPropagation(); + form.handleSubmit(onSubmit)(event); + }} + > + +
+
+ + Configure Template +
+ + + + Editor + + + + Preview + + + + +
+ + + + + + + + +
+ +
+
+
+ + ); +}; diff --git a/apps/dashboard/src/components/workflow-editor/steps/step-editor.tsx b/apps/dashboard/src/components/workflow-editor/steps/step-editor.tsx index 1394068af6d..b6dda55c497 100644 --- a/apps/dashboard/src/components/workflow-editor/steps/step-editor.tsx +++ b/apps/dashboard/src/components/workflow-editor/steps/step-editor.tsx @@ -1,10 +1,13 @@ -import { ConfigureInAppStepTemplateTabs } from '@/components/workflow-editor/steps/configure-in-app-template/configure-in-app-step-template-tabs'; -import { StepTypeEnum } from '@novu/shared'; +import { type StepDataDto, StepTypeEnum, type WorkflowResponseDto } from '@novu/shared'; +import { InAppTabs } from '@/components/workflow-editor/steps/in-app/in-app-tabs'; -const STEP_TYPE_TO_EDITOR: Record React.JSX.Element> = { +const STEP_TYPE_TO_EDITOR: Record< + StepTypeEnum, + (args: { workflow: WorkflowResponseDto; step: StepDataDto }) => React.JSX.Element +> = { [StepTypeEnum.EMAIL]: () =>
EMAIL Editor
, [StepTypeEnum.CHAT]: () =>
CHAT Editor
, - [StepTypeEnum.IN_APP]: ConfigureInAppStepTemplateTabs, + [StepTypeEnum.IN_APP]: InAppTabs, [StepTypeEnum.SMS]: () =>
SMS Editor
, [StepTypeEnum.PUSH]: () =>
PUSH Editor
, [StepTypeEnum.DIGEST]: () =>
DIGEST Editor
, @@ -13,7 +16,15 @@ const STEP_TYPE_TO_EDITOR: Record React.JSX.Element> = { [StepTypeEnum.CUSTOM]: () =>
CUSTOM Editor
, }; -export const StepEditor = ({ stepType }: { stepType: StepTypeEnum }) => { +export const StepEditor = ({ + workflow, + step, + stepType, +}: { + workflow: WorkflowResponseDto; + step: StepDataDto; + stepType: StepTypeEnum; +}) => { const Editor = STEP_TYPE_TO_EDITOR[stepType]; - return ; + return ; }; diff --git a/apps/dashboard/src/components/workflow-editor/url-input.tsx b/apps/dashboard/src/components/workflow-editor/url-input.tsx new file mode 100644 index 00000000000..4b28f712856 --- /dev/null +++ b/apps/dashboard/src/components/workflow-editor/url-input.tsx @@ -0,0 +1,103 @@ +import { liquid } from '@codemirror/lang-liquid'; +import { EditorView } from '@uiw/react-codemirror'; +import { useFormContext } from 'react-hook-form'; + +import { Input, InputField, InputFieldProps, InputProps } from '@/components/primitives/input'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/primitives/select'; +import { Editor } from '@/components/primitives/editor'; +import { FormControl, FormField, FormItem, FormMessagePure } from '@/components/primitives/form/form'; +import { cn } from '@/utils/ui'; + +type URLInputProps = Omit & { + options: string[]; + asEditor?: boolean; + withHint?: boolean; + fields: { + urlKey: string; + targetKey: string; + }; +} & Pick; + +export const URLInput = ({ + options, + size = 'default', + asEditor = false, + placeholder, + fields: { urlKey, targetKey }, + withHint = true, +}: URLInputProps) => { + const { control, getFieldState } = useFormContext(); + const url = getFieldState(`${urlKey}`); + const target = getFieldState(`${targetKey}`); + const error = url.error || target.error; + + return ( +
+
+
+ + ( + + + {asEditor ? ( + + ) : ( + + )} + + + )} + /> + ( + + + + + + )} + /> + +
+
+ + {withHint && 'This support variables and relative URLs i.e /tasks/{{taskId}}'} + +
+ ); +}; diff --git a/apps/dashboard/src/components/workflow-editor/workflow-editor-provider.tsx b/apps/dashboard/src/components/workflow-editor/workflow-editor-provider.tsx index 718a4353c8b..9540d1fcdb8 100644 --- a/apps/dashboard/src/components/workflow-editor/workflow-editor-provider.tsx +++ b/apps/dashboard/src/components/workflow-editor/workflow-editor-provider.tsx @@ -47,7 +47,7 @@ const STEP_NAME_BY_TYPE: Record = { const createStep = (type: StepTypeEnum): Step => ({ name: STEP_NAME_BY_TYPE[type], stepId: '', - slug: '_stp_', + slug: '_st_', type, _id: crypto.randomUUID(), }); diff --git a/apps/dashboard/src/hooks/use-fetch-step.tsx b/apps/dashboard/src/hooks/use-fetch-step.tsx new file mode 100644 index 00000000000..f0fc1b99377 --- /dev/null +++ b/apps/dashboard/src/hooks/use-fetch-step.tsx @@ -0,0 +1,20 @@ +import { useQuery } from '@tanstack/react-query'; +import type { StepDataDto } from '@novu/shared'; +import { QueryKeys } from '@/utils/query-keys'; +import { useEnvironment } from '@/context/environment/hooks'; +import { fetchStep } from '@/api/steps'; + +export const useFetchStep = ({ workflowSlug, stepSlug }: { workflowSlug: string; stepSlug: string }) => { + const { currentEnvironment } = useEnvironment(); + const { data, isPending, error } = useQuery({ + queryKey: [QueryKeys.fetchWorkflow, currentEnvironment?._id, workflowSlug, stepSlug], + queryFn: () => fetchStep({ workflowSlug, stepSlug }), + enabled: !!currentEnvironment?._id && !!stepSlug, + }); + + return { + step: data, + isPending, + error, + }; +}; diff --git a/apps/dashboard/src/hooks/use-update-workflow.ts b/apps/dashboard/src/hooks/use-update-workflow.ts index a646cd3e990..e2827ccaa9e 100644 --- a/apps/dashboard/src/hooks/use-update-workflow.ts +++ b/apps/dashboard/src/hooks/use-update-workflow.ts @@ -2,11 +2,15 @@ import { useMutation } from '@tanstack/react-query'; import type { UpdateWorkflowDto, WorkflowResponseDto } from '@novu/shared'; import { updateWorkflow } from '@/api/workflows'; -export const useUpdateWorkflow = ({ onSuccess }: { onSuccess?: (data: WorkflowResponseDto) => void } = {}) => { +export const useUpdateWorkflow = ({ + onSuccess, + onError, +}: { onSuccess?: (data: WorkflowResponseDto) => void; onError?: (error: unknown) => void } = {}) => { const { mutateAsync, isPending, error, data } = useMutation({ mutationFn: async ({ id, workflow }: { id: string; workflow: UpdateWorkflowDto }) => updateWorkflow({ id, workflow }), onSuccess, + onError, }); return { diff --git a/apps/dashboard/src/utils/schema.ts b/apps/dashboard/src/utils/schema.ts new file mode 100644 index 00000000000..a3aa6928290 --- /dev/null +++ b/apps/dashboard/src/utils/schema.ts @@ -0,0 +1,167 @@ +import * as z from 'zod'; +import { UiSchema, WorkflowTestDataResponseDto } from '@novu/shared'; +import { capitalize } from './string'; + +type JSONSchema = WorkflowTestDataResponseDto['to']; + +type ZodValue = + | z.AnyZodObject + | z.ZodString + | z.ZodNumber + | z.ZodEffects + | z.ZodDefault + | z.ZodEnum<[string, ...string[]]> + | z.ZodOptional; + +const handleStringFormat = ({ value, key, format }: { value: z.ZodString; key: string; format: string }) => { + if (format === 'email') { + return value.email(`${capitalize(key)} must be a valid email`); + } else if (format === 'uri') { + return value + .transform((val) => (val === '' ? undefined : val)) + .refine((val) => !val || z.string().url().safeParse(val).success, { + message: `${capitalize(key)} must be a valid URI`, + }); + } + + return value; +}; + +const handleStringPattern = ({ value, key, pattern }: { value: z.ZodString; key: string; pattern: string }) => { + return value + .transform((val) => (val === '' ? undefined : val)) + .refine((val) => !val || z.string().regex(new RegExp(pattern)).safeParse(val).success, { + message: `${capitalize(key)} must be a valid value`, + }); +}; + +const handleStringEnum = ({ key, enumValues }: { key: string; enumValues: [string, ...string[]] }) => { + return z.enum(enumValues, { message: `${capitalize(key)} must be one of ${enumValues.join(', ')}` }); +}; + +const handleStringType = ({ + key, + format, + pattern, + enumValues, + defaultValue, + requiredFields, +}: { + key: string; + format?: string; + pattern?: string; + enumValues?: unknown; + defaultValue?: unknown; + requiredFields: Readonly>; +}) => { + const isRequired = requiredFields.includes(key); + + let stringValue: + | z.ZodString + | z.ZodEffects + | z.ZodEnum<[string, ...string[]]> + | z.ZodDefault = z.string(); + + if (format) { + stringValue = handleStringFormat({ + value: stringValue, + key, + format, + }); + } else if (pattern) { + stringValue = handleStringPattern({ + value: stringValue, + key, + pattern, + }); + } else if (enumValues) { + stringValue = handleStringEnum({ + key, + enumValues: enumValues as [string, ...string[]], + }); + } else if (isRequired) { + stringValue = stringValue.min(1, `${capitalize(key)} is required`); + } + + if (defaultValue) { + stringValue = stringValue.default(defaultValue as string); + } + + // remove empty strings + return stringValue.transform((val) => (val === '' ? undefined : val)); +}; + +/** + * Transform JSONSchema to Zod schema. + * The function will recursively build the schema based on the JSONSchema object. + * It removes empty strings and objects with empty required fields during the transformation phase after parsing. + */ +export const buildDynamicZodSchema = (obj: JSONSchema): z.AnyZodObject => { + const properties = typeof obj === 'object' ? (obj.properties ?? {}) : {}; + const requiredFields = typeof obj === 'object' ? (obj.required ?? []) : []; + + const keys: Record = Object.keys(properties).reduce((acc, key) => { + const jsonSchemaProp = properties[key]; + if (typeof jsonSchemaProp !== 'object') { + return acc; + } + + let zodValue: ZodValue; + const { type, format, pattern, enum: enumValues, default: defaultValue, required } = jsonSchemaProp; + const isRequired = requiredFields.includes(key); + + if (type === 'object') { + zodValue = buildDynamicZodSchema(jsonSchemaProp); + if (defaultValue) { + zodValue = zodValue.default(defaultValue); + } + zodValue = zodValue.transform((val) => { + const hasAnyRequiredEmpty = required?.some((field) => val[field] === '' || val[field] === undefined); + // remove object if any required field is empty or undefined + return hasAnyRequiredEmpty ? undefined : val; + }); + } else if (type === 'string') { + zodValue = handleStringType({ key, requiredFields, format, pattern, enumValues, defaultValue }); + } else { + zodValue = z.number(isRequired ? { message: `${capitalize(key)} is required` } : undefined); + if (defaultValue) { + zodValue = zodValue.default(defaultValue as number); + } + } + + if (!isRequired) { + zodValue = zodValue.optional() as ZodValue; + } + + return { ...acc, [key]: zodValue }; + }, {}); + + return z.object({ ...keys }); +}; + +/** + * Build default values based on the UI Schema object. + */ +export const buildDefaultValues = (uiSchema: UiSchema): object => { + const properties = typeof uiSchema === 'object' ? (uiSchema.properties ?? {}) : {}; + + const keys: Record = Object.keys(properties).reduce((acc, key) => { + const property = properties[key]; + if (typeof property !== 'object') { + return acc; + } + + const { placeholder: defaultValue } = property; + if (defaultValue === null || typeof defaultValue === 'undefined') { + return acc; + } + + if (typeof defaultValue === 'object') { + return { ...acc, [key]: buildDefaultValues({ properties: { ...defaultValue } }) }; + } + + return { ...acc, [key]: defaultValue }; + }, {}); + + return keys; +}; diff --git a/packages/shared/src/dto/workflows/step-data.dto.ts b/packages/shared/src/dto/workflows/step-data.dto.ts index a922899d049..6a8563762f0 100644 --- a/packages/shared/src/dto/workflows/step-data.dto.ts +++ b/packages/shared/src/dto/workflows/step-data.dto.ts @@ -25,6 +25,7 @@ export enum UiComponentEnum { } export class UiSchemaProperty { + placeholder?: unknown; component: UiComponentEnum; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 89276a512da..54020f41c27 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -807,6 +807,9 @@ importers: '@eslint/js': specifier: ^9.9.0 version: 9.9.1 + '@hookform/devtools': + specifier: ^4.3.0 + version: 4.3.1(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@playwright/test': specifier: ^1.44.0 version: 1.46.1 @@ -43674,6 +43677,19 @@ snapshots: optionalDependencies: '@types/react': 18.3.3 + '@emotion/styled@11.10.6(@emotion/react@11.11.1(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1)': + dependencies: + '@babel/runtime': 7.23.2 + '@emotion/babel-plugin': 11.10.6 + '@emotion/is-prop-valid': 1.2.0 + '@emotion/react': 11.11.1(@types/react@18.3.3)(react@18.3.1) + '@emotion/serialize': 1.1.1 + '@emotion/use-insertion-effect-with-fallbacks': 1.0.0(react@18.3.1) + '@emotion/utils': 1.2.0 + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.3 + '@emotion/unitless@0.7.5': {} '@emotion/unitless@0.8.0': {} @@ -44478,8 +44494,8 @@ snapshots: '@hookform/devtools@4.3.1(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@emotion/react': 11.10.6(@types/react@18.3.3)(react@18.3.1) - '@emotion/styled': 11.10.6(@emotion/react@11.10.6(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) + '@emotion/react': 11.11.1(@types/react@18.3.3)(react@18.3.1) + '@emotion/styled': 11.10.6(@emotion/react@11.11.1(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@types/lodash': 4.14.192 little-state-machine: 4.8.0(react@18.3.1) lodash: 4.17.21 From 0385564e0cc019dba930436751620b79c9431980 Mon Sep 17 00:00:00 2001 From: Sokratis Vidros Date: Thu, 7 Nov 2024 22:29:17 +0200 Subject: [PATCH 10/29] chore(web): Remove Clerk sign-in patch (#6888) --- .source | 2 +- apps/web/package.json | 1 - .../src/components/providers/AuthProvider.tsx | 7 + .../src/ee/clerk/providers/ClerkProvider.tsx | 20 +-- .../src/ee/clerk/providers/clerk-singleton.ts | 48 ----- pnpm-lock.yaml | 164 ++---------------- 6 files changed, 25 insertions(+), 217 deletions(-) delete mode 100644 apps/web/src/ee/clerk/providers/clerk-singleton.ts diff --git a/.source b/.source index 9e5c90cd7b8..750ab915fc5 160000 --- a/.source +++ b/.source @@ -1 +1 @@ -Subproject commit 9e5c90cd7b890fb05d35e0c489e59c976a98efa6 +Subproject commit 750ab915fc5f957ef025936ee6b7dafbe1f8a021 diff --git a/apps/web/package.json b/apps/web/package.json index 74523fcefa9..e675d7fb859 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -36,7 +36,6 @@ "@babel/plugin-proposal-optional-chaining": "^7.20.7", "@babel/plugin-transform-react-display-name": "^7.18.6", "@babel/plugin-transform-runtime": "^7.23.2", - "@clerk/clerk-js": "^5.10.0", "@clerk/clerk-react": "^5.2.5", "@clerk/themes": "^2.1.10", "@editorjs/editorjs": "^2.19.3", diff --git a/apps/web/src/components/providers/AuthProvider.tsx b/apps/web/src/components/providers/AuthProvider.tsx index 80553064476..d603d945f81 100644 --- a/apps/web/src/components/providers/AuthProvider.tsx +++ b/apps/web/src/components/providers/AuthProvider.tsx @@ -1,5 +1,6 @@ import { useContext } from 'react'; import { IOrganizationEntity, IUserEntity } from '@novu/shared'; +import { type BrowserClerk } from '@clerk/clerk-react'; import { IS_EE_AUTH_ENABLED } from '../../config/index'; import { CommunityAuthContext, @@ -58,6 +59,12 @@ export const useAuth = () => { return value; }; +declare global { + interface Window { + Clerk: BrowserClerk; + } +} + export async function getToken() { if (IS_EE_AUTH_ENABLED) { return (await window?.Clerk?.session?.getToken()) || ''; diff --git a/apps/web/src/ee/clerk/providers/ClerkProvider.tsx b/apps/web/src/ee/clerk/providers/ClerkProvider.tsx index 004ad316898..2c6367593d5 100644 --- a/apps/web/src/ee/clerk/providers/ClerkProvider.tsx +++ b/apps/web/src/ee/clerk/providers/ClerkProvider.tsx @@ -1,10 +1,9 @@ -import { PropsWithChildren, useEffect, useState } from 'react'; +import { PropsWithChildren } from 'react'; import { useNavigate } from 'react-router-dom'; -import { ClerkProp, ClerkProvider as _ClerkProvider } from '@clerk/clerk-react'; +import { ClerkProvider as _ClerkProvider } from '@clerk/clerk-react'; import { useColorScheme } from '@novu/design-system'; import { dark } from '@clerk/themes'; import { Variables } from '@clerk/types'; -import { buildClerk } from './clerk-singleton'; import { CLERK_PUBLISHABLE_KEY, IS_EE_AUTH_ENABLED } from '../../../config/index'; const CLERK_LOCALIZATION = { @@ -271,29 +270,14 @@ const ALLOWED_REDIRECT_ORIGINS = ['http://localhost:*', window.location.origin]; export const ClerkProvider: React.FC> = ({ children }) => { const { colorScheme } = useColorScheme(); - const [clerkInstance, setClerkInstance] = useState(); - const navigate = useNavigate(); - useEffect(() => { - (async () => { - if (IS_EE_AUTH_ENABLED) { - setClerkInstance(await buildClerk({ publishableKey: CLERK_PUBLISHABLE_KEY })); - } - })(); - }, []); - if (!IS_EE_AUTH_ENABLED) { return <>{children}; } - if (IS_EE_AUTH_ENABLED && !clerkInstance) { - return null; - } - return ( <_ClerkProvider - Clerk={clerkInstance} routerPush={(to) => navigate(to)} routerReplace={(to) => navigate(to, { replace: true })} publishableKey={CLERK_PUBLISHABLE_KEY} diff --git a/apps/web/src/ee/clerk/providers/clerk-singleton.ts b/apps/web/src/ee/clerk/providers/clerk-singleton.ts deleted file mode 100644 index 428c3cb1967..00000000000 --- a/apps/web/src/ee/clerk/providers/clerk-singleton.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Clerk } from '@clerk/clerk-js'; -import type { ClerkProp } from '@clerk/clerk-react'; -import { normalizeEmail } from '@novu/shared'; -import { api } from '../../../api/api.client'; - -// eslint-disable-next-line import/no-mutable-exports -export let clerk: Clerk; - -type BuildClerkOptions = { - publishableKey: string; -}; - -export async function buildClerk({ publishableKey }: BuildClerkOptions): Promise { - if (clerk) { - return clerk as ClerkProp; - } - - clerk = new Clerk(publishableKey); - - clerk.__unstable__onBeforeRequest(async (requestInit) => { - const { path, method, body } = requestInit; - const isSignIn = path === '/client/sign_ins' && method === 'POST'; - const isPasswordStrategy = - getParamFromQuery(body as string, 'strategy') === 'password' || !getParamFromQuery(body as string, 'strategy'); - - if (isSignIn && isPasswordStrategy) { - const email = getParamFromQuery(body as string, 'identifier'); - if (email && email !== normalizeEmail(email)) { - await normalizeEmailData(email); - } - } - - return requestInit; - }); - - return clerk as ClerkProp; -} - -function getParamFromQuery(query: string, param: string): string | null { - const params = new URLSearchParams(query); - const value = params.get(param); - - return value ? decodeURIComponent(value) : null; -} - -function normalizeEmailData(email: string) { - return api.post('/v1/clerk/user/normalize', { emailAddress: email }); -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 54020f41c27..9397e6c5b2f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1024,9 +1024,6 @@ importers: '@babel/plugin-transform-runtime': specifier: ^7.23.2 version: 7.23.2(@babel/core@7.22.11) - '@clerk/clerk-js': - specifier: ^5.10.0 - version: 5.10.1(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@clerk/clerk-react': specifier: ^5.2.5 version: 5.2.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -7005,13 +7002,6 @@ packages: resolution: {integrity: sha512-Tiidp1dBs/vBQ82yL+HgRa7GlNjTNjBPNUQj2+Tn176i02wglgTfLWivDzuRwAe/cdf7gu/8OBWTxOF59L4KRQ==} engines: {node: '>=18.17.0'} - '@clerk/clerk-js@5.10.1': - resolution: {integrity: sha512-ViChiKSeY2h79H5dAWlgpN2jukyHUA5vbGAjB6kK1tHjZkPLlQyg8pGBwd7Fcty1XF8e013de+Mez55rw3NXIw==} - engines: {node: '>=18.17.0'} - peerDependencies: - react: '>=18' - react-dom: '>=18' - '@clerk/clerk-react@5.2.7': resolution: {integrity: sha512-8gPS/N0D1ooGg92lrSsAN9nKZEVE1b/nfZGtgEZX9epQ47nD+geThAC1G+mc3hABNkIODvIyecKTLbsk0K+LfA==} engines: {node: '>=18.17.0'} @@ -7023,10 +7013,6 @@ packages: resolution: {integrity: sha512-LnjXgqRGJpBIhkaBQCLixfuGFZNDDpTUv9uuSj3tp5X6DQbmRSPKX0Vm8WwXJmIr67JYoAE+6N3j/P2StVTZ7w==} engines: {node: '>=18.17.0'} - '@clerk/localizations@2.5.1': - resolution: {integrity: sha512-iNv5e6+LDElDnhspHflyRRhg6f5vdWF7MmBrHPPyzN5CQjJVWhDFe6Xl8C4A9yju7V5LLo3E+NxCgkIT5zEkRA==} - engines: {node: '>=18.17.0'} - '@clerk/shared@2.3.2': resolution: {integrity: sha512-uOTYqSmxe41Ye8TnyPtthwLp5rrYK5Ze04bvl1SQzlIibr4qeLU2DXZOYibMnSWvIMwr45pXUHsJh8NfKKIZ2w==} engines: {node: '>=18.17.0'} @@ -7964,15 +7950,6 @@ packages: '@types/react': optional: true - '@emotion/react@11.11.1': - resolution: {integrity: sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA==} - peerDependencies: - '@types/react': '*' - react: '>=16.8.0' - peerDependenciesMeta: - '@types/react': - optional: true - '@emotion/react@11.7.1': resolution: {integrity: sha512-DV2Xe3yhkF1yT4uAUoJcYL1AmrnO5SVsdfvu+fBuS7IbByDeTVx9+wFmvx9Idzv7/78+9Mgx2Hcmr7Fex3tIyw==} peerDependencies: @@ -8857,27 +8834,15 @@ packages: react: '>=16.8.0' react-dom: '>=16.8.0' - '@floating-ui/react@0.25.4': - resolution: {integrity: sha512-lWRQ/UiTvSIBxohn0/2HFHEmnmOVRjl7j6XcRJuLH0ls6f/9AyHMWVzkAJFuwx0n9gaEeCmg9VccCSCJzbEJig==} - peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' - '@floating-ui/react@0.26.13': resolution: {integrity: sha512-kBa9wntpugzrZ8t/4yWelvSmEKZdeTXTJzrxqyrLmcU/n1SM4nvse8yQh2e1b37rJGvtu0EplV9+IkBrCJ1vkw==} peerDependencies: react: '>=16.8.0' react-dom: '>=16.8.0' - '@floating-ui/utils@0.1.6': - resolution: {integrity: sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==} - '@floating-ui/utils@0.2.4': resolution: {integrity: sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==} - '@formkit/auto-animate@0.8.2': - resolution: {integrity: sha512-SwPWfeRa5veb1hOIBMdzI+73te5puUBHmqqaF1Bu7FjvxlYSz/kJcZKSa9Cg60zL0uRNeJL2SbRxV6Jp6Q1nFQ==} - '@fortawesome/fontawesome-common-types@6.4.0': resolution: {integrity: sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ==} engines: {node: '>=6'} @@ -18138,12 +18103,6 @@ packages: engines: {node: '>= 8'} hasBin: true - '@zxcvbn-ts/core@3.0.4': - resolution: {integrity: sha512-aQeiT0F09FuJaAqNrxynlAwZ2mW/1MdXakKWNmGM1Qp/VaY6CnB/GfnMS2T8gB2231Esp1/maCWd8vTG4OuShw==} - - '@zxcvbn-ts/language-common@3.0.4': - resolution: {integrity: sha512-viSNNnRYtc7ULXzxrQIVUNwHAPSXRtoIwy/Tq4XQQdIknBzw4vz36lQLF6mvhMlTIlpjoN/Z1GFu/fwiAlUSsw==} - JSONStream@1.3.5: resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} hasBin: true @@ -19268,9 +19227,6 @@ packages: browser-stdout@1.3.1: resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} - browser-tabs-lock@1.2.15: - resolution: {integrity: sha512-J8K9vdivK0Di+b8SBdE7EZxDr88TnATing7XoLw6+nFkXMQ6sVBh92K3NQvZlZU91AIkFRi0w3sztk5Z+vsswA==} - browserify-zlib@0.1.4: resolution: {integrity: sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==} @@ -20232,9 +20188,6 @@ packages: resolution: {integrity: sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==} deprecated: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js. - core-js@3.26.1: - resolution: {integrity: sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA==} - core-js@3.30.0: resolution: {integrity: sha512-hQotSSARoNh1mYPi9O2YaWeiq/cEB95kOrFb4NCrO4RIFt1qqNpKsaE+vy/L3oiqvND5cThqXzUU3r9F7Efztg==} @@ -29659,11 +29612,6 @@ packages: You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other. (For a CapTP with native promises, see @endo/eventual-send and @endo/captp) - qrcode.react@3.1.0: - resolution: {integrity: sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - qs@6.10.4: resolution: {integrity: sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==} engines: {node: '>=0.6'} @@ -35234,8 +35182,8 @@ snapshots: dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sso-oidc': 3.575.0(@aws-sdk/client-sts@3.575.0) - '@aws-sdk/client-sts': 3.575.0 + '@aws-sdk/client-sso-oidc': 3.575.0 + '@aws-sdk/client-sts': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0) '@aws-sdk/core': 3.575.0 '@aws-sdk/credential-provider-node': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0)(@aws-sdk/client-sts@3.575.0) '@aws-sdk/middleware-host-header': 3.575.0 @@ -35436,8 +35384,8 @@ snapshots: '@aws-crypto/sha1-browser': 3.0.0 '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sso-oidc': 3.575.0(@aws-sdk/client-sts@3.575.0) - '@aws-sdk/client-sts': 3.575.0 + '@aws-sdk/client-sso-oidc': 3.575.0 + '@aws-sdk/client-sts': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0) '@aws-sdk/core': 3.575.0 '@aws-sdk/credential-provider-node': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0)(@aws-sdk/client-sts@3.575.0) '@aws-sdk/middleware-bucket-endpoint': 3.575.0 @@ -35663,11 +35611,11 @@ snapshots: - aws-crt optional: true - '@aws-sdk/client-sso-oidc@3.575.0(@aws-sdk/client-sts@3.575.0)': + '@aws-sdk/client-sso-oidc@3.575.0': dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sts': 3.575.0 + '@aws-sdk/client-sts': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0) '@aws-sdk/core': 3.575.0 '@aws-sdk/credential-provider-node': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0)(@aws-sdk/client-sts@3.575.0) '@aws-sdk/middleware-host-header': 3.575.0 @@ -35706,7 +35654,6 @@ snapshots: '@smithy/util-utf8': 3.0.0 tslib: 2.7.0 transitivePeerDependencies: - - '@aws-sdk/client-sts' - aws-crt '@aws-sdk/client-sso-oidc@3.637.0(@aws-sdk/client-sts@3.637.0)': @@ -36091,11 +36038,11 @@ snapshots: - aws-crt optional: true - '@aws-sdk/client-sts@3.575.0': + '@aws-sdk/client-sts@3.575.0(@aws-sdk/client-sso-oidc@3.575.0)': dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sso-oidc': 3.575.0(@aws-sdk/client-sts@3.575.0) + '@aws-sdk/client-sso-oidc': 3.575.0 '@aws-sdk/core': 3.575.0 '@aws-sdk/credential-provider-node': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0)(@aws-sdk/client-sts@3.575.0) '@aws-sdk/middleware-host-header': 3.575.0 @@ -36134,6 +36081,7 @@ snapshots: '@smithy/util-utf8': 3.0.0 tslib: 2.7.0 transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' - aws-crt '@aws-sdk/client-sts@3.637.0': @@ -36363,7 +36311,7 @@ snapshots: '@aws-sdk/credential-provider-ini@3.575.0(@aws-sdk/client-sso-oidc@3.575.0)(@aws-sdk/client-sts@3.575.0)': dependencies: - '@aws-sdk/client-sts': 3.575.0 + '@aws-sdk/client-sts': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0) '@aws-sdk/credential-provider-env': 3.575.0 '@aws-sdk/credential-provider-process': 3.575.0 '@aws-sdk/credential-provider-sso': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0) @@ -36674,7 +36622,7 @@ snapshots: '@aws-sdk/credential-provider-web-identity@3.575.0(@aws-sdk/client-sts@3.575.0)': dependencies: - '@aws-sdk/client-sts': 3.575.0 + '@aws-sdk/client-sts': 3.575.0(@aws-sdk/client-sso-oidc@3.575.0) '@aws-sdk/types': 3.575.0 '@smithy/property-provider': 3.1.3 '@smithy/types': 3.3.0 @@ -37195,7 +37143,7 @@ snapshots: '@aws-sdk/token-providers@3.575.0(@aws-sdk/client-sso-oidc@3.575.0)': dependencies: - '@aws-sdk/client-sso-oidc': 3.575.0(@aws-sdk/client-sts@3.575.0) + '@aws-sdk/client-sso-oidc': 3.575.0 '@aws-sdk/types': 3.575.0 '@smithy/property-provider': 3.1.3 '@smithy/shared-ini-file-loader': 3.1.4 @@ -37204,7 +37152,7 @@ snapshots: '@aws-sdk/token-providers@3.614.0(@aws-sdk/client-sso-oidc@3.575.0)': dependencies: - '@aws-sdk/client-sso-oidc': 3.575.0(@aws-sdk/client-sts@3.575.0) + '@aws-sdk/client-sso-oidc': 3.575.0 '@aws-sdk/types': 3.609.0 '@smithy/property-provider': 3.1.3 '@smithy/shared-ini-file-loader': 3.1.4 @@ -42405,29 +42353,6 @@ snapshots: - react - react-dom - '@clerk/clerk-js@5.10.1(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@clerk/localizations': 2.5.1 - '@clerk/shared': 2.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@clerk/types': 4.9.0 - '@emotion/cache': 11.11.0 - '@emotion/react': 11.11.1(@types/react@18.3.3)(react@18.3.1) - '@floating-ui/react': 0.25.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@formkit/auto-animate': 0.8.2 - '@zxcvbn-ts/core': 3.0.4 - '@zxcvbn-ts/language-common': 3.0.4 - browser-tabs-lock: 1.2.15 - copy-to-clipboard: 3.3.3 - core-js: 3.26.1 - crypto-js: 4.2.0 - dequal: 2.0.3 - qrcode.react: 3.1.0(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - regenerator-runtime: 0.13.11 - transitivePeerDependencies: - - '@types/react' - '@clerk/clerk-react@5.2.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@clerk/shared': 2.3.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -42446,10 +42371,6 @@ snapshots: - react - react-dom - '@clerk/localizations@2.5.1': - dependencies: - '@clerk/types': 4.9.0 - '@clerk/shared@2.3.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@clerk/types': 4.7.0 @@ -43608,20 +43529,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.3 - '@emotion/react@11.11.1(@types/react@18.3.3)(react@18.3.1)': - dependencies: - '@babel/runtime': 7.25.6 - '@emotion/babel-plugin': 11.11.0 - '@emotion/cache': 11.11.0 - '@emotion/serialize': 1.1.4 - '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.3.1) - '@emotion/utils': 1.2.1 - '@emotion/weak-memoize': 0.3.1 - hoist-non-react-statics: 3.3.2 - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.3 - '@emotion/react@11.7.1(@babel/core@7.25.2)(@types/react@18.3.3)(react@18.3.1)': dependencies: '@babel/runtime': 7.25.6 @@ -43677,19 +43584,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.3 - '@emotion/styled@11.10.6(@emotion/react@11.11.1(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1)': - dependencies: - '@babel/runtime': 7.23.2 - '@emotion/babel-plugin': 11.10.6 - '@emotion/is-prop-valid': 1.2.0 - '@emotion/react': 11.11.1(@types/react@18.3.3)(react@18.3.1) - '@emotion/serialize': 1.1.1 - '@emotion/use-insertion-effect-with-fallbacks': 1.0.0(react@18.3.1) - '@emotion/utils': 1.2.0 - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.3 - '@emotion/unitless@0.7.5': {} '@emotion/unitless@0.8.0': {} @@ -44240,14 +44134,6 @@ snapshots: react-dom: 18.3.1(react@18.3.1) tabbable: 6.1.1 - '@floating-ui/react@0.25.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@floating-ui/react-dom': 2.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@floating-ui/utils': 0.1.6 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - tabbable: 6.1.1 - '@floating-ui/react@0.26.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@floating-ui/react-dom': 2.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -44256,12 +44142,8 @@ snapshots: react-dom: 18.3.1(react@18.3.1) tabbable: 6.1.1 - '@floating-ui/utils@0.1.6': {} - '@floating-ui/utils@0.2.4': {} - '@formkit/auto-animate@0.8.2': {} - '@fortawesome/fontawesome-common-types@6.4.0': {} '@fortawesome/fontawesome-svg-core@6.4.0': @@ -44494,8 +44376,8 @@ snapshots: '@hookform/devtools@4.3.1(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@emotion/react': 11.11.1(@types/react@18.3.3)(react@18.3.1) - '@emotion/styled': 11.10.6(@emotion/react@11.11.1(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) + '@emotion/react': 11.10.6(@types/react@18.3.3)(react@18.3.1) + '@emotion/styled': 11.10.6(@emotion/react@11.10.6(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@types/lodash': 4.14.192 little-state-machine: 4.8.0(react@18.3.1) lodash: 4.17.21 @@ -59093,12 +58975,6 @@ snapshots: dependencies: isexe: 2.0.0 - '@zxcvbn-ts/core@3.0.4': - dependencies: - fastest-levenshtein: 1.0.16 - - '@zxcvbn-ts/language-common@3.0.4': {} - JSONStream@1.3.5: dependencies: jsonparse: 1.3.1 @@ -60929,10 +60805,6 @@ snapshots: browser-stdout@1.3.1: {} - browser-tabs-lock@1.2.15: - dependencies: - lodash: 4.17.21 - browserify-zlib@0.1.4: dependencies: pako: 0.2.9 @@ -62070,8 +61942,6 @@ snapshots: core-js@2.6.12: {} - core-js@3.26.1: {} - core-js@3.30.0: {} core-js@3.35.0: {} @@ -75529,10 +75399,6 @@ snapshots: q@1.5.1: {} - qrcode.react@3.1.0(react@18.3.1): - dependencies: - react: 18.3.1 - qs@6.10.4: dependencies: side-channel: 1.0.6 From f9c09225b9235d9d171aeadf7eb6332e977d46a0 Mon Sep 17 00:00:00 2001 From: Sokratis Vidros Date: Thu, 7 Nov 2024 23:54:36 +0200 Subject: [PATCH 11/29] chore(root): Upgrade NX to latest packages (#6775) --- .cspell.json | 1 + .devcontainer/devcontainer.json | 5 +- .github/ISSUE_TEMPLATE.md | 9 +- .github/ISSUE_TEMPLATE/bug_report.yml | 50 +- .github/ISSUE_TEMPLATE/feature_request.yml | 34 +- .github/PULL_REQUEST_TEMPLATE.md | 4 + .github/actions/docker/build-api/action.yml | 12 +- .../actions/docker/build-worker/action.yml | 12 +- .github/actions/free-space/action.yml | 8 +- .github/actions/run-api/action.yml | 4 +- .github/actions/run-backend/action.yml | 10 +- .github/actions/run-worker/action.yml | 1 - .github/actions/setup-project/action.yml | 2 +- .../actions/setup-redis-cluster/action.yml | 2 +- .../slack-notify-on-failure/action.yml | 8 +- .github/actions/validate-openapi/action.yml | 2 +- .github/actions/validate-swagger/action.yml | 0 .github/workflows/codeql-analysis.yml | 61 +- .github/workflows/community-label.yml | 2 +- .github/workflows/conventional-commit.yml | 3 +- .github/workflows/dev-deploy-api.yml | 9 +- .github/workflows/dev-deploy-dashboard.yml | 5 +- .github/workflows/dev-deploy-embed.yml | 5 +- .github/workflows/dev-deploy-inbound-mail.yml | 12 +- .../workflows/dev-deploy-web-component.yml | 3 + .github/workflows/dev-deploy-web.yml | 5 +- .github/workflows/dev-deploy-webhook.yml | 3 + .github/workflows/dev-deploy-widget.yml | 5 +- .github/workflows/dev-deploy-worker.yml | 8 +- .github/workflows/dev-deploy-ws.yml | 10 +- .github/workflows/issue-label.yml | 2 +- .github/workflows/milestone-assign.yml | 2 +- .github/workflows/on-pr.yml | 7 +- .github/workflows/pr-labeler.yml | 2 +- .github/workflows/pr-manager.yml | 6 +- .github/workflows/prepare-cloud-release.yaml | 7 +- .../workflows/prepare-self-hosted-release.yml | 19 +- .github/workflows/preview-packages.yml | 7 +- .github/workflows/prod-deploy-api.yml | 17 +- .github/workflows/prod-deploy-embed.yml | 23 +- .../workflows/prod-deploy-inbound-mail.yml | 3 + .../workflows/prod-deploy-web-component.yml | 3 + .github/workflows/prod-deploy-web.yml | 5 +- .github/workflows/prod-deploy-webhook.yml | 3 + .github/workflows/prod-deploy-widget.yml | 5 +- .github/workflows/prod-deploy-worker.yml | 11 +- .github/workflows/prod-deploy-ws.yml | 3 + .github/workflows/reusable-api-e2e.yml | 4 +- .../workflows/reusable-dashboard-deploy.yml | 3 + .github/workflows/reusable-dashboard-e2e.yml | 61 +- .github/workflows/reusable-docker.yml | 8 +- .github/workflows/reusable-embed-deploy.yml | 3 + .../workflows/reusable-inbound-mail-e2e.yml | 3 + .../reusable-notification-center.yml | 3 + .github/workflows/reusable-web-deploy.yml | 3 + .github/workflows/reusable-web-e2e.yml | 61 +- .github/workflows/reusable-webhook-e2e.yml | 23 +- .github/workflows/reusable-widget-deploy.yml | 4 +- .github/workflows/reusable-widget-e2e.yml | 4 +- .github/workflows/reusable-worker-e2e.yml | 67 +- .../reusable-workers-service-deploy.yml | 4 +- .github/workflows/reusable-ws-e2e.yml | 3 + .github/workflows/rollback.yml | 11 +- .github/workflows/tag-images.yml | 2 +- .gitpod.yml | 2 +- .markdownlint.jsonc | 18 +- .vscode/launch.json | 145 +- .vscode/tasks.json | 48 +- CODE_OF_CONDUCT.md | 22 +- README.md | 3 + SECURITY.md | 2 +- apps/api/.spectral.yaml | 10 +- apps/api/README.md | 24 +- apps/api/jarvis-api-intro.md | 24 +- apps/dashboard/README.md | 6 +- apps/dashboard/src/index.css | 5 +- apps/web/.storybook/Doc.container.tsx | 3 +- apps/web/.storybook/main.js | 19 +- apps/web/public/index.html | 102 +- apps/web/src/components/docs/DocsButton.tsx | 2 +- apps/web/src/components/docs/Mdx.tsx | 4 +- .../src/components/nav/RootNavMenuFooter.tsx | 2 +- .../templates/components/CustomCodeEditor.css | 5 +- apps/web/src/stories/Introduction.stories.mdx | 21 +- .../components/GetStartedPageV2/index.tsx | 2 +- apps/widget/README.md | 2 +- apps/widget/config-overrides.js | 4 +- .../cypress/test-shell/example/test.html | 18 +- apps/widget/cypress/test-shell/index.html | 429 +- apps/widget/index.html | 52 +- apps/widget/public/index.html | 44 +- apps/worker/README.md | 1 + docker/community/docker-compose.yml | 4 +- docker/local/docker-compose.e2e.yml | 10 +- docker/local/docker-compose.local.yml | 25 +- docker/local/docker-compose.yml | 24 +- enterprise/packages/dal/tsconfig.build.json | 8 +- .../packages/shared-services/tsconfig.json | 2 +- eslint.config.mjs | 11 +- jest.config.js | 4 +- libs/application-generic/README.md | 1 - .../src/utils/deepmerge.ts | 48 +- libs/automation/nx.json | 3 - .../.storybook/Doc.container.tsx | 3 +- libs/design-system/.storybook/NovuTheme.tsx | 4 +- .../.storybook/manager-head.html | 2 +- libs/design-system/src/Colors.stories.mdx | 28 +- .../src/icons/gradient/BellGradient.tsx | 3 +- .../src/icons/gradient/CompassGradient.tsx | 3 +- .../src/icons/gradient/GlobeGradient.tsx | 3 +- libs/embed/src/embed.ts | 5 +- libs/embed/src/shared/helpers.js | 20 +- libs/embed/src/shared/iframeClasses.js | 2 +- libs/embed/test/index.html | 62 +- libs/novui/.storybook/NovuTheme.tsx | 4 +- libs/novui/.storybook/manager-head.html | 2 +- nx.json | 9 +- package.json | 18 +- packages/js/postcss.config.js | 2 +- packages/js/src/ui/index.css | 6 +- packages/node/CHANGELOG.md | 20 - packages/node/README.md | 4 +- .../notification-center-angular/README.md | 1 + .../NotificationCenterComponent.vue | 2 +- .../notification-center/.storybook/main.js | 20 +- .../notification-center/.storybook/preview.js | 4 +- packages/notification-center/jest.config.js | 2 +- .../src/stories/Introduction.stories.mdx | 21 +- .../init/templates/app/ts/app/page.module.css | 232 + packages/stateless/CHANGELOG.md | 20 - playground/nextjs/components.json | 2 +- playground/nextjs/src/components/Header.tsx | 4 +- .../nextjs/src/components/ui/button.tsx | 58 +- .../src/components/ui/dropdown-menu.tsx | 14 +- .../nextjs/src/components/ui/popover.tsx | 22 +- playground/nextjs/src/lib/utils.ts | 6 +- .../pages/hooks/_components/inbox-item.tsx | 38 +- .../_components/more-actions-dropdown.tsx | 2 +- .../pages/hooks/_components/notion-theme.tsx | 34 +- .../pages/hooks/_components/sidebar-item.tsx | 8 +- .../hooks/_components/status-dropdown.tsx | 8 +- playground/nextjs/src/pages/layout.tsx | 4 +- .../nextjs/src/pages/notifications/index.tsx | 10 +- .../nextjs/src/pages/novu-theme/index.tsx | 2 +- .../pages/novu-theme/novu-theme.module.css | 7 +- .../nextjs/src/pages/preferences/index.tsx | 2 +- .../nextjs/src/pages/render-bell/index.tsx | 4 +- .../src/pages/render-notification/index.tsx | 6 +- playground/nextjs/tailwind.config.ts | 104 +- pnpm-lock.yaml | 29078 ++++++++++------ tsconfig.json | 2 +- 151 files changed, 19572 insertions(+), 12191 deletions(-) delete mode 100644 .github/actions/validate-swagger/action.yml create mode 100644 packages/novu/src/commands/init/templates/app/ts/app/page.module.css diff --git a/.cspell.json b/.cspell.json index b8ae9adfc23..e3b2e8a7dec 100644 --- a/.cspell.json +++ b/.cspell.json @@ -594,6 +594,7 @@ "Strobl", "stroeder", "Styleable", + "subfolders", "subjectsthum", "sublist", "subnetmask", diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 9c3e8e3ee11..ac586cbe668 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -12,10 +12,7 @@ // Add the IDs of extensions you want installed when the container is created. "customizations": { "vscode": { - "extensions": [ - "dbaeumer.vscode-eslint", - "mongodb.mongodb-vscode" - ] + "extensions": ["dbaeumer.vscode-eslint", "mongodb.mongodb-vscode"] } }, // Use 'forwardPorts' to make a list of ports inside the container available locally. diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index c5d73961ff2..f5bb4a98071 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,8 +1,9 @@ - **I'm submitting a...** - - [ ] bug report - - [ ] feature request - - [ ] question about the decisions made in the repository - - [ ] question about how to use this project + + - [ ] bug report + - [ ] feature request + - [ ] question about the decisions made in the repository + - [ ] question about how to use this project - **Summary** diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index c0b29ba2813..298cca3eaf3 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,7 +1,7 @@ -name: "🐛 Bug Report" -description: "Submit a bug report to help us improve" -title: "🐛 Bug Report: " -labels: ["type: bug"] +name: '🐛 Bug Report' +description: 'Submit a bug report to help us improve' +title: '🐛 Bug Report: ' +labels: ['type: bug'] body: - type: markdown attributes: @@ -11,36 +11,36 @@ body: validations: required: true attributes: - label: "📜 Description" - description: "A clear and concise description of what the bug is." - placeholder: "It bugs out when ..." + label: '📜 Description' + description: 'A clear and concise description of what the bug is.' + placeholder: 'It bugs out when ...' - type: textarea id: steps-to-reproduce validations: required: true attributes: - label: "👟 Reproduction steps" - description: "How do you trigger this bug? Please walk us through it step by step." + label: '👟 Reproduction steps' + description: 'How do you trigger this bug? Please walk us through it step by step.' placeholder: "1. Go to '...' - 2. Click on '....' - 3. Scroll down to '....' - 4. See the error" + 2. Click on '....' + 3. Scroll down to '....' + 4. See the error" - type: textarea id: expected-behavior validations: required: true attributes: - label: "👍 Expected behavior" - description: "What did you think should happen?" - placeholder: "It should ..." + label: '👍 Expected behavior' + description: 'What did you think should happen?' + placeholder: 'It should ...' - type: textarea id: actual-behavior validations: required: true attributes: - label: "👎 Actual Behavior with Screenshots" - description: "What did actually happen? Add screenshots, if applicable." - placeholder: "It actually ..." + label: '👎 Actual Behavior with Screenshots' + description: 'What did actually happen? Add screenshots, if applicable.' + placeholder: 'It actually ...' - type: input id: novu-version validations: @@ -70,26 +70,26 @@ body: validations: required: false attributes: - label: "📃 Provide any additional context for the Bug." - description: "Add any other context about the problem here." - placeholder: "It actually ..." + label: '📃 Provide any additional context for the Bug.' + description: 'Add any other context about the problem here.' + placeholder: 'It actually ...' - type: checkboxes id: no-duplicate-issues attributes: - label: "👀 Have you spent some time to check if this bug has been raised before?" + label: '👀 Have you spent some time to check if this bug has been raised before?' options: - label: "I checked and didn't find a similar issue" required: true - type: checkboxes id: read-code-of-conduct attributes: - label: "🏢 Have you read the Contributing Guidelines?" + label: '🏢 Have you read the Contributing Guidelines?' options: - - label: "I have read the [Contributing Guidelines](https://github.com/novuhq/novu/blob/main/CONTRIBUTING.md)" + - label: 'I have read the [Contributing Guidelines](https://github.com/novuhq/novu/blob/main/CONTRIBUTING.md)' required: true - type: dropdown attributes: label: Are you willing to submit PR? description: This is absolutely not required, but we are happy to guide you in the contribution process. Find us in help-needed channel on [Discord](https://discord.gg/9wcGSf22PM)! options: - - "Yes I am willing to submit a PR!" + - 'Yes I am willing to submit a PR!' diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index b33d3f7dc26..2d350b2b2bf 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -1,6 +1,6 @@ name: 🚀 Feature -description: "Submit a proposal for a new feature" -title: "🚀 Feature: " +description: 'Submit a proposal for a new feature' +title: '🚀 Feature: ' labels: [feature] body: - type: markdown @@ -12,46 +12,46 @@ body: validations: required: true attributes: - label: "🔖 Feature description" - description: "A clear and concise description of what the feature is." - placeholder: "You should add ..." + label: '🔖 Feature description' + description: 'A clear and concise description of what the feature is.' + placeholder: 'You should add ...' - type: textarea id: pitch validations: required: true attributes: - label: "🎤 Why is this feature needed ?" - description: "Please explain why this feature should be implemented and how it would be used. Add examples, if applicable." - placeholder: "In my use-case, ..." + label: '🎤 Why is this feature needed ?' + description: 'Please explain why this feature should be implemented and how it would be used. Add examples, if applicable.' + placeholder: 'In my use-case, ...' - type: textarea id: solution validations: required: true attributes: - label: "✌️ How do you aim to achieve this?" - description: "A clear and concise description of what you want to happen." - placeholder: "I want this feature to, ..." + label: '✌️ How do you aim to achieve this?' + description: 'A clear and concise description of what you want to happen.' + placeholder: 'I want this feature to, ...' - type: textarea id: alternative validations: required: false attributes: - label: "🔄️ Additional Information" + label: '🔄️ Additional Information' description: "A clear and concise description of any alternative solutions or additional solutions you've considered." - placeholder: "I tried, ..." + placeholder: 'I tried, ...' - type: checkboxes id: no-duplicate-issues attributes: - label: "👀 Have you spent some time to check if this feature request has been raised before?" + label: '👀 Have you spent some time to check if this feature request has been raised before?' options: - label: "I checked and didn't find similar issue" required: true - type: checkboxes id: read-code-of-conduct attributes: - label: "🏢 Have you read the Code of Conduct?" + label: '🏢 Have you read the Code of Conduct?' options: - - label: "I have read the [Contributing Guidelines](https://github.com/novuhq/novu/blob/main/CONTRIBUTING.md)" + - label: 'I have read the [Contributing Guidelines](https://github.com/novuhq/novu/blob/main/CONTRIBUTING.md)' required: true - type: dropdown id: willing-to-submit-pr @@ -59,4 +59,4 @@ body: label: Are you willing to submit PR? description: This is absolutely not required, but we are happy to guide you in the contribution process. Find us in help-needed channel on [Discord](https://discord.gg/9wcGSf22PM)! options: - - "Yes I am willing to submit a PR!" + - 'Yes I am willing to submit a PR!' diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 2cf10e5d3e3..f59b27dde17 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,16 +1,20 @@ ### What changed? Why was the change needed? + ### Screenshots +
Expand for optional sections ### Related enterprise PR + ### Special notes for your reviewer +
diff --git a/.github/actions/docker/build-api/action.yml b/.github/actions/docker/build-api/action.yml index 1014040be21..3a01326e53f 100644 --- a/.github/actions/docker/build-api/action.yml +++ b/.github/actions/docker/build-api/action.yml @@ -52,7 +52,7 @@ runs: aws-access-key-id: ${{ inputs.aws-access-key-id }} aws-secret-access-key: ${{ inputs.aws-secret-access-key }} aws-region: eu-west-2 - + - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v2 @@ -67,7 +67,7 @@ runs: shell: bash env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: novu-dev/api + REPOSITORY: novu-dev/api IMAGE_TAG: ${{ github.sha }} DOCKER_BUILD_ARGUMENTS: > --platform=linux/amd64 --provenance=false @@ -81,7 +81,7 @@ runs: shell: bash env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: novu-dev/api + REPOSITORY: novu-dev/api IMAGE_TAG: ${{ github.sha }} run: | echo "Built image" @@ -97,7 +97,7 @@ runs: shell: bash env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: novu-dev/api + REPOSITORY: novu-dev/api IMAGE_TAG: ${{ github.sha }} run: | docker tag $REGISTRY/$REPOSITORY:$IMAGE_TAG $REGISTRY/$REPOSITORY:${{ inputs.tag }} @@ -107,7 +107,7 @@ runs: shell: bash env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: novu-dev/api + REPOSITORY: novu-dev/api IMAGE_TAG: ${{ github.sha }} run: | docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG @@ -117,6 +117,6 @@ runs: shell: bash env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: novu-dev/api + REPOSITORY: novu-dev/api run: | docker push $REGISTRY/$REPOSITORY:${{ inputs.tag }} diff --git a/.github/actions/docker/build-worker/action.yml b/.github/actions/docker/build-worker/action.yml index 6986429664d..1d94e8f3a02 100644 --- a/.github/actions/docker/build-worker/action.yml +++ b/.github/actions/docker/build-worker/action.yml @@ -52,7 +52,7 @@ runs: aws-access-key-id: ${{ inputs.aws-access-key-id }} aws-secret-access-key: ${{ inputs.aws-secret-access-key }} aws-region: eu-west-2 - + - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v2 @@ -67,7 +67,7 @@ runs: shell: bash env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: novu-dev/worker + REPOSITORY: novu-dev/worker IMAGE_TAG: ${{ github.sha }} DOCKER_BUILD_ARGUMENTS: > --platform=linux/amd64 --provenance=false @@ -81,7 +81,7 @@ runs: shell: bash env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: novu-dev/worker + REPOSITORY: novu-dev/worker IMAGE_TAG: ${{ github.sha }} run: | echo "Built image" @@ -97,7 +97,7 @@ runs: shell: bash env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: novu-dev/worker + REPOSITORY: novu-dev/worker IMAGE_TAG: ${{ github.sha }} run: | docker tag $REGISTRY/$REPOSITORY:$IMAGE_TAG $REGISTRY/$REPOSITORY:${{ inputs.tag }} @@ -107,7 +107,7 @@ runs: shell: bash env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: novu-dev/worker + REPOSITORY: novu-dev/worker IMAGE_TAG: ${{ github.sha }} run: | docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG @@ -117,6 +117,6 @@ runs: shell: bash env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: novu-dev/worker + REPOSITORY: novu-dev/worker run: | docker push $REGISTRY/$REPOSITORY:${{ inputs.tag }} diff --git a/.github/actions/free-space/action.yml b/.github/actions/free-space/action.yml index 45805252eab..b7b4dfa7d3a 100644 --- a/.github/actions/free-space/action.yml +++ b/.github/actions/free-space/action.yml @@ -1,17 +1,17 @@ name: Extend Disk Space -description: This action removes some preinstalled tools in favor of opening space for our docker runs with QEMU +description: This action removes some preinstalled tools in favor of opening space for our docker runs with QEMU runs: using: composite steps: - name: Run script run: | set -eux - + df -h echo "::group::apt clean" sudo apt clean echo "::endgroup::" - + echo "::group::/usr/local/*" du -hsc /usr/local/* echo "::endgroup::" @@ -66,6 +66,6 @@ runs: sudo rm -rf /opt/hostedtoolcache/CodeQL || : # 1.4GB sudo rm -rf /opt/hostedtoolcache/go || : - + df -h shell: bash diff --git a/.github/actions/run-api/action.yml b/.github/actions/run-api/action.yml index e7d027a5a63..93eaedc7a4d 100644 --- a/.github/actions/run-api/action.yml +++ b/.github/actions/run-api/action.yml @@ -21,8 +21,8 @@ runs: shell: bash env: LAUNCH_DARKLY_SDK_KEY: ${{ inputs.launch_darkly_sdk_key }} - NODE_ENV: "test" - PORT: "1336" + NODE_ENV: 'test' + PORT: '1336' run: cd apps/api && pnpm start:prod & - name: Wait on API diff --git a/.github/actions/run-backend/action.yml b/.github/actions/run-backend/action.yml index bec045ebe83..14eb1c91e3a 100644 --- a/.github/actions/run-backend/action.yml +++ b/.github/actions/run-backend/action.yml @@ -27,9 +27,9 @@ runs: env: GITHUB_OAUTH_CLIENT_ID: ${{ inputs.cypress_github_oauth_client_id }} GITHUB_OAUTH_CLIENT_SECRET: ${{ inputs.cypress_github_oauth_client_secret }} - NODE_ENV: "test" - PORT: "1336" - GITHUB_OAUTH_REDIRECT: "http://127.0.0.1:1336/v1/auth/github/callback" + NODE_ENV: 'test' + PORT: '1336' + GITHUB_OAUTH_REDIRECT: 'http://127.0.0.1:1336/v1/auth/github/callback' LAUNCH_DARKLY_SDK_KEY: ${{ inputs.launch_darkly_sdk_key }} CI_EE_TEST: ${{ inputs.ci_ee_test }} run: cd apps/api && pnpm start:prod & @@ -37,8 +37,8 @@ runs: - name: Start Worker shell: bash env: - NODE_ENV: "test" - PORT: "1342" + NODE_ENV: 'test' + PORT: '1342' LAUNCH_DARKLY_SDK_KEY: ${{ inputs.launch_darkly_sdk_key }} CI_EE_TEST: ${{ inputs.ci_ee_test }} run: cd apps/worker && pnpm start:prod & diff --git a/.github/actions/run-worker/action.yml b/.github/actions/run-worker/action.yml index 4d139c010c3..0eeb5c43d5d 100644 --- a/.github/actions/run-worker/action.yml +++ b/.github/actions/run-worker/action.yml @@ -1,4 +1,3 @@ - name: Run Worker description: Sets up a Redis Cluster instance needed to run the tests diff --git a/.github/actions/setup-project/action.yml b/.github/actions/setup-project/action.yml index 01e4c10156d..5526929bae2 100644 --- a/.github/actions/setup-project/action.yml +++ b/.github/actions/setup-project/action.yml @@ -51,7 +51,7 @@ runs: shell: bash if: ${{ inputs.submodules == 'true' }} run: pnpm symlink:submodules - + - name: Install wait-on plugin shell: bash run: pnpm i -g wait-on diff --git a/.github/actions/setup-redis-cluster/action.yml b/.github/actions/setup-redis-cluster/action.yml index 9844a4a5a50..2d23fed6f03 100644 --- a/.github/actions/setup-redis-cluster/action.yml +++ b/.github/actions/setup-redis-cluster/action.yml @@ -1,6 +1,6 @@ name: Setup Novu Redis Cluster -description: Sets up a Redis Cluster instance needed to run the tests +description: Sets up a Redis Cluster instance needed to run the tests runs: using: composite diff --git a/.github/actions/slack-notify-on-failure/action.yml b/.github/actions/slack-notify-on-failure/action.yml index 5a51f187c83..e1f0bff33a8 100644 --- a/.github/actions/slack-notify-on-failure/action.yml +++ b/.github/actions/slack-notify-on-failure/action.yml @@ -6,16 +6,16 @@ inputs: type: string runs: - using: "composite" + using: 'composite' steps: - name: Notify Slack Action if: ${{ github.ref_name == 'next' || github.ref_name == 'main' || github.ref_name == 'prod' }} uses: ravsamhq/notify-slack-action@v2 with: footer: "Run: {run_url}\nCommit: {commit_url}" - message_format: "{emoji} *{workflow}* {status_message} in <{repo_url}|{repo}>" - notification_title: "{workflow} is now failing!" - notify_when: "failure" + message_format: '{emoji} *{workflow}* {status_message} in <{repo_url}|{repo}>' + notification_title: '{workflow} is now failing!' + notify_when: 'failure' status: ${{ job.status }} env: SLACK_WEBHOOK_URL: ${{ inputs.slackWebhookURL }} diff --git a/.github/actions/validate-openapi/action.yml b/.github/actions/validate-openapi/action.yml index 73b3f3444d5..e5726ea88b4 100644 --- a/.github/actions/validate-openapi/action.yml +++ b/.github/actions/validate-openapi/action.yml @@ -12,7 +12,7 @@ runs: with: targets: lint:openapi projects: '@novu/api' - + - name: Kill port for api 1336 for unit tests shell: bash run: sudo kill -9 $(sudo lsof -t -i:1336) diff --git a/.github/actions/validate-swagger/action.yml b/.github/actions/validate-swagger/action.yml deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 29281d9f972..f8837f7372d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -9,17 +9,17 @@ # the `language` matrix defined below to confirm you have the correct set of # supported CodeQL languages. # -name: "CodeQL" +name: 'CodeQL' concurrency: - group: "${{ github.workflow }}-${{ github.ref }}" + group: '${{ github.workflow }}-${{ github.ref }}' cancel-in-progress: true on: push: - branches: [ "main", "next" ] + branches: ['main', 'next'] pull_request: # The branches below must be a subset of the branches above - branches: [ "main", "next" ] + branches: ['main', 'next'] schedule: - cron: '25 2 * * 4' @@ -35,41 +35,40 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'javascript', 'typescript' ] + language: ['javascript', 'typescript'] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support steps: - - name: Checkout repository - uses: actions/checkout@v4 + - name: Checkout repository + uses: actions/checkout@v4 - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. - # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - # ℹ️ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/community-label.yml b/.github/workflows/community-label.yml index b57aea56e3a..3c92433f5b8 100644 --- a/.github/workflows/community-label.yml +++ b/.github/workflows/community-label.yml @@ -7,7 +7,7 @@ on: - '!prod' concurrency: - group: "${{ github.workflow }}-${{ github.ref }}" + group: '${{ github.workflow }}-${{ github.ref }}' cancel-in-progress: true jobs: diff --git a/.github/workflows/conventional-commit.yml b/.github/workflows/conventional-commit.yml index 047aa847d48..73f9703c787 100644 --- a/.github/workflows/conventional-commit.yml +++ b/.github/workflows/conventional-commit.yml @@ -1,4 +1,4 @@ -name: "Lint PR title" +name: 'Lint PR title' on: pull_request_target: @@ -45,7 +45,6 @@ jobs: scopes: | ${{ env.SCOPES }} - - uses: marocchino/sticky-pull-request-comment@v2 # When the previous steps fails, the workflow would stop. By adding this # condition you can continue the execution with the populated error message. diff --git a/.github/workflows/dev-deploy-api.yml b/.github/workflows/dev-deploy-api.yml index bd1a011fd1b..efdd5086659 100644 --- a/.github/workflows/dev-deploy-api.yml +++ b/.github/workflows/dev-deploy-api.yml @@ -17,6 +17,7 @@ on: - 'libs/application-generic/**' env: TF_WORKSPACE: novu-dev + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} jobs: test_api: @@ -130,7 +131,7 @@ jobs: sourcemaps: apps/api/dist ignore_empty: true ignore_missing: true - url_prefix: "~" + url_prefix: '~' newrelic: runs-on: ubuntu-latest @@ -147,6 +148,6 @@ jobs: with: region: EU apiKey: ${{ secrets.NEW_RELIC_API_KEY }} - guid: "MzgxMjQwOHxBUE18QVBQTElDQVRJT058NDk3NjQzODIy" - version: "${{ env.RELEASE_VERSION }}" - user: "${{ github.actor }}" + guid: 'MzgxMjQwOHxBUE18QVBQTElDQVRJT058NDk3NjQzODIy' + version: '${{ env.RELEASE_VERSION }}' + user: '${{ github.actor }}' diff --git a/.github/workflows/dev-deploy-dashboard.yml b/.github/workflows/dev-deploy-dashboard.yml index 3a65f97f4ee..cde607f82e2 100644 --- a/.github/workflows/dev-deploy-dashboard.yml +++ b/.github/workflows/dev-deploy-dashboard.yml @@ -1,5 +1,3 @@ -# This is a basic workflow to help you get started with Actions - name: Deploy DEV DASHBOARD # Controls when the action will run. Triggers the workflow on push or pull request @@ -14,6 +12,9 @@ on: - 'apps/web/**' - 'apps/dashboard/**' +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: test_dashboard: diff --git a/.github/workflows/dev-deploy-embed.yml b/.github/workflows/dev-deploy-embed.yml index a3351de3727..8352f70828a 100644 --- a/.github/workflows/dev-deploy-embed.yml +++ b/.github/workflows/dev-deploy-embed.yml @@ -1,5 +1,3 @@ -# This is a basic workflow to help you get started with Actions - name: Deploy DEV EMBED # Controls when the action will run. Triggers the workflow on push or pull request @@ -13,6 +11,9 @@ on: paths: - 'libs/embed/**' +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: # This workflow contains a single job called "build" diff --git a/.github/workflows/dev-deploy-inbound-mail.yml b/.github/workflows/dev-deploy-inbound-mail.yml index fbe4859bd96..130917b8217 100644 --- a/.github/workflows/dev-deploy-inbound-mail.yml +++ b/.github/workflows/dev-deploy-inbound-mail.yml @@ -1,5 +1,8 @@ name: Deploy DEV Inbound Mail +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # Controls when the action will run. Triggers the workflow on push or pull request # events but only for the master branch on: @@ -79,7 +82,7 @@ jobs: shell: bash env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: novu-dev/inbound-mail + REPOSITORY: novu-dev/inbound-mail IMAGE_TAG: ${{ github.sha }} DOCKER_BUILD_ARGUMENTS: > --platform=linux/amd64 --provenance=false @@ -93,7 +96,7 @@ jobs: shell: bash env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: novu-dev/inbound-mail + REPOSITORY: novu-dev/inbound-mail IMAGE_TAG: ${{ github.sha }} run: | echo "Built image" @@ -106,7 +109,7 @@ jobs: shell: bash env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: novu-dev/inbound-mail + REPOSITORY: novu-dev/inbound-mail IMAGE_TAG: ${{ github.sha }} run: | docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG @@ -118,7 +121,6 @@ jobs: token: ${{ secrets.GH_PACKAGES }} path: cloud-infra - - name: Terraform setup uses: hashicorp/setup-terraform@v3 with: @@ -179,4 +181,4 @@ jobs: sourcemaps: apps/inbound-mail/dist ignore_empty: true ignore_missing: true - url_prefix: "~" + url_prefix: '~' diff --git a/.github/workflows/dev-deploy-web-component.yml b/.github/workflows/dev-deploy-web-component.yml index a691a2a552e..29605c9060d 100644 --- a/.github/workflows/dev-deploy-web-component.yml +++ b/.github/workflows/dev-deploy-web-component.yml @@ -1,5 +1,8 @@ name: Deploy DEV Notification Center Web Component +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + on: workflow_dispatch: push: diff --git a/.github/workflows/dev-deploy-web.yml b/.github/workflows/dev-deploy-web.yml index 092906d424a..5c0edf9dea5 100644 --- a/.github/workflows/dev-deploy-web.yml +++ b/.github/workflows/dev-deploy-web.yml @@ -1,5 +1,3 @@ -# This is a basic workflow to help you get started with Actions - name: Deploy DEV WEB # Controls when the action will run. Triggers the workflow on push or pull request @@ -14,6 +12,9 @@ on: - 'apps/web/**' - 'packages/shared/**' +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: test_web: diff --git a/.github/workflows/dev-deploy-webhook.yml b/.github/workflows/dev-deploy-webhook.yml index 6b4be494f52..42490c14ea3 100644 --- a/.github/workflows/dev-deploy-webhook.yml +++ b/.github/workflows/dev-deploy-webhook.yml @@ -15,6 +15,9 @@ on: - 'libs/dal/**' - 'packages/shared/**' +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + jobs: test_webhook: uses: ./.github/workflows/reusable-webhook-e2e.yml diff --git a/.github/workflows/dev-deploy-widget.yml b/.github/workflows/dev-deploy-widget.yml index 13dc1ae96bf..95fc3284813 100644 --- a/.github/workflows/dev-deploy-widget.yml +++ b/.github/workflows/dev-deploy-widget.yml @@ -1,5 +1,3 @@ -# This is a basic workflow to help you get started with Actions - name: Deploy DEV Widget # Controls when the action will run. Triggers the workflow on push or pull request @@ -15,6 +13,9 @@ on: - 'apps/ws/**' - 'packages/shared/**' +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: test_widget: diff --git a/.github/workflows/dev-deploy-worker.yml b/.github/workflows/dev-deploy-worker.yml index 54c4783d242..e818a148a04 100644 --- a/.github/workflows/dev-deploy-worker.yml +++ b/.github/workflows/dev-deploy-worker.yml @@ -18,8 +18,10 @@ on: - 'libs/application-generic/**' - 'packages/stateless/**' - 'packages/node/**' + env: TF_WORKSPACE: novu-dev + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} jobs: test_worker: @@ -85,6 +87,6 @@ jobs: with: region: EU apiKey: ${{ secrets.NEW_RELIC_API_KEY }} - guid: "MzgxMjQwOHxBUE18QVBQTElDQVRJT058NDk3NjQzODIy" - version: "${{ env.RELEASE_VERSION }}" - user: "${{ github.actor }}" + guid: 'MzgxMjQwOHxBUE18QVBQTElDQVRJT058NDk3NjQzODIy' + version: '${{ env.RELEASE_VERSION }}' + user: '${{ github.actor }}' diff --git a/.github/workflows/dev-deploy-ws.yml b/.github/workflows/dev-deploy-ws.yml index b54bf88aba0..b47739f1db1 100644 --- a/.github/workflows/dev-deploy-ws.yml +++ b/.github/workflows/dev-deploy-ws.yml @@ -12,6 +12,7 @@ on: - 'apps/ws/**' env: TF_WORKSPACE: novu-dev + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} jobs: test_ws: @@ -92,17 +93,16 @@ jobs: aws ecs describe-task-definition --task-definition ${{ env.ws_task_name }} \ --query taskDefinition > task-definition.json - - name: Set Bull MQ Env variable for EE shell: bash run: | echo "BULL_MQ_PRO_NPM_TOKEN=${{ secrets.BULL_MQ_PRO_NPM_TOKEN }}" >> $GITHUB_ENV - + - name: Build with Buildx, tag, and test shell: bash env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: novu-dev/ws + REPOSITORY: novu-dev/ws IMAGE_TAG: ${{ github.sha }} DOCKER_BUILD_ARGUMENTS: > --platform=linux/amd64 --provenance=false @@ -116,7 +116,7 @@ jobs: shell: bash env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: novu-dev/ws + REPOSITORY: novu-dev/ws IMAGE_TAG: ${{ github.sha }} run: | echo "Built image" @@ -130,7 +130,7 @@ jobs: shell: bash env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: novu-dev/ws + REPOSITORY: novu-dev/ws IMAGE_TAG: ${{ github.sha }} run: | docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG diff --git a/.github/workflows/issue-label.yml b/.github/workflows/issue-label.yml index e313538befd..c8539b518f9 100644 --- a/.github/workflows/issue-label.yml +++ b/.github/workflows/issue-label.yml @@ -5,7 +5,7 @@ on: types: [opened] concurrency: - group: "${{ github.workflow }}-${{ github.ref }}" + group: '${{ github.workflow }}-${{ github.ref }}' cancel-in-progress: true jobs: diff --git a/.github/workflows/milestone-assign.yml b/.github/workflows/milestone-assign.yml index c6235cb8bd0..1baa7aeec7e 100644 --- a/.github/workflows/milestone-assign.yml +++ b/.github/workflows/milestone-assign.yml @@ -5,7 +5,7 @@ on: types: [submitted] concurrency: - group: "${{ github.workflow }}-${{ github.ref }}" + group: '${{ github.workflow }}-${{ github.ref }}' cancel-in-progress: true jobs: diff --git a/.github/workflows/on-pr.yml b/.github/workflows/on-pr.yml index 6be684d41e3..13a0bb0a328 100644 --- a/.github/workflows/on-pr.yml +++ b/.github/workflows/on-pr.yml @@ -1,8 +1,11 @@ name: Check pull request concurrency: - group: "${{ github.workflow }}-${{ github.ref }}" + group: '${{ github.workflow }}-${{ github.ref }}' cancel-in-progress: true +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + on: pull_request: workflow_dispatch: @@ -245,7 +248,7 @@ jobs: test-e2e-ee-affected: ${{ contains(fromJson(needs.get-affected.outputs.test-e2e-ee), '@novu/api') || contains(fromJson(needs.get-affected.outputs.test-e2e-ee), '@novu/worker') }} job-name: ${{ matrix.name }} test-unit: false - secrets: inherit + secrets: inherit test_e2e_web: name: E2E test Web app diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml index 6fca208686f..075256d17c6 100644 --- a/.github/workflows/pr-labeler.yml +++ b/.github/workflows/pr-labeler.yml @@ -1,4 +1,4 @@ -name: "Pull Request Labeler" +name: 'Pull Request Labeler' on: - pull_request_target diff --git a/.github/workflows/pr-manager.yml b/.github/workflows/pr-manager.yml index ef3cfd440df..9a229d88154 100644 --- a/.github/workflows/pr-manager.yml +++ b/.github/workflows/pr-manager.yml @@ -1,4 +1,4 @@ -name: "Pull Request Manager" +name: 'Pull Request Manager' on: schedule: - cron: '0 * * * *' @@ -25,6 +25,6 @@ jobs: days-before-pr-close: 31 # Delete the branch when closing PRs. GitHub's "restore branch" function works indefinitely, so no reason not to. delete-branch: true - stale-pr-message: "This PR is being marked as stale due to inactivity." - close-pr-message: "This PR is being closed due to inactivity. Please reopen if work is intended to be continued." + stale-pr-message: 'This PR is being marked as stale due to inactivity.' + close-pr-message: 'This PR is being closed due to inactivity. Please reopen if work is intended to be continued.' operations-per-run: 100 diff --git a/.github/workflows/prepare-cloud-release.yaml b/.github/workflows/prepare-cloud-release.yaml index 7898a1a12ea..8c800b040a2 100644 --- a/.github/workflows/prepare-cloud-release.yaml +++ b/.github/workflows/prepare-cloud-release.yaml @@ -1,11 +1,14 @@ -name: "Prepare Cloud Release" +name: 'Prepare Cloud Release' + +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} on: workflow_dispatch: # Triggers the workflow every work day at 8:00 UTC # The 3 hour offset should change when daylight savings change for GMT +3. schedule: - - cron: "0 8 * * 1,2,3,4,5" + - cron: '0 8 * * 1,2,3,4,5' jobs: prepare-cloud-release: diff --git a/.github/workflows/prepare-self-hosted-release.yml b/.github/workflows/prepare-self-hosted-release.yml index 5fe76966b21..4eed3dbec2b 100644 --- a/.github/workflows/prepare-self-hosted-release.yml +++ b/.github/workflows/prepare-self-hosted-release.yml @@ -1,5 +1,8 @@ name: Prepare Self-hosted Release +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + on: push: tags: @@ -13,16 +16,14 @@ permissions: id-token: write jobs: - build_docker: runs-on: ubuntu-latest timeout-minutes: 90 strategy: fail-fast: false matrix: - name: ['novu/api','novu/worker','novu/web','novu/webhook','novu/ws'] + name: ['novu/api', 'novu/worker', 'novu/web', 'novu/webhook', 'novu/ws'] steps: - - name: Git Checkout uses: actions/checkout@v4 @@ -38,7 +39,7 @@ jobs: echo "SERVICE_COMMON_NAME=$SERVICE_COMMON_NAME" >> $GITHUB_ENV echo "REGISTRY_OWNER=novuhq" >> $GITHUB_ENV echo "This is the service name: $SERVICE_NAME and release version: $LATEST_VERSION" - + - name: Install pnpm uses: pnpm/action-setup@v3 @@ -71,10 +72,10 @@ jobs: uses: docker/setup-buildx-action@v3 with: driver-opts: 'image=moby/buildkit:v0.13.1' - + - uses: ./.github/actions/free-space name: Extend space in Action Container - + - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: @@ -92,16 +93,16 @@ jobs: --output=type=image,name=ghcr.io/${{ env.REGISTRY_OWNER }}/${{ env.SERVICE_NAME }},push-by-digest=true,name-canonical=true run: | cd apps/$SERVICE_COMMON_NAME - + if [ "${{ env.SERVICE_NAME }}" == "worker" ]; then cd src/ && echo -e "\nIS_SELF_HOSTED=true\nOS_TELEMETRY_URL=\"${{ secrets.OS_TELEMETRY_URL }}\"" >> .example.env && cd .. elif [ "${{ env.SERVICE_NAME }}" == "web" ]; then echo -e "\nIS_V2_ENABLED=true" >> .env.sample fi - + pnpm run docker:build docker images - + - name: Check for EE files id: check-ee-files run: | diff --git a/.github/workflows/preview-packages.yml b/.github/workflows/preview-packages.yml index 74428d9e9f1..06a0d6c0a70 100644 --- a/.github/workflows/preview-packages.yml +++ b/.github/workflows/preview-packages.yml @@ -1,5 +1,8 @@ name: Publish NPM Packages Previews +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + on: workflow_dispatch: push: @@ -21,7 +24,7 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 20 - cache: "pnpm" + cache: 'pnpm' - name: Install dependencies run: pnpm install @@ -31,7 +34,7 @@ jobs: - name: Build run: pnpm run preview:pkg:build - + - name: Release package previews to pkg.pr.new run: pnpm run preview:pkg:publish if: ${{ success() }} diff --git a/.github/workflows/prod-deploy-api.yml b/.github/workflows/prod-deploy-api.yml index 93a20d74802..0aca04406d7 100644 --- a/.github/workflows/prod-deploy-api.yml +++ b/.github/workflows/prod-deploy-api.yml @@ -1,5 +1,8 @@ name: Deploy PROD API +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # Controls when the action will run. Triggers the workflow on push or pull request # events but only for the master branch on: @@ -45,23 +48,23 @@ jobs: shell: bash run: | echo "BULL_MQ_PRO_NPM_TOKEN=${{ secrets.BULL_MQ_PRO_NPM_TOKEN }}" >> $GITHUB_ENV - + - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID}} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: us-east-1 - + - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v2 - + - name: Build, tag, and push image to Amazon ECR id: build-image env: REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: novu/api + REPOSITORY: novu/api IMAGE_TAG: ${{ github.sha }} DOCKER_BUILD_ARGUMENTS: > --platform=linux/amd64 @@ -129,6 +132,6 @@ jobs: with: region: EU apiKey: ${{ secrets.NEW_RELIC_API_KEY }} - guid: "MzgxMjQwOHxBUE18QVBQTElDQVRJT058NDk3NzA2ODk2" - version: "${{ env.RELEASE_VERSION }}" - user: "${{ github.actor }}" + guid: 'MzgxMjQwOHxBUE18QVBQTElDQVRJT058NDk3NzA2ODk2' + version: '${{ env.RELEASE_VERSION }}' + user: '${{ github.actor }}' diff --git a/.github/workflows/prod-deploy-embed.yml b/.github/workflows/prod-deploy-embed.yml index d16bd8b3133..ddc7f78a8c1 100644 --- a/.github/workflows/prod-deploy-embed.yml +++ b/.github/workflows/prod-deploy-embed.yml @@ -1,5 +1,3 @@ -# This is a basic workflow to help you get started with Actions - name: Deploy PROD EMBED # Controls when the action will run. Triggers the workflow on push or pull request @@ -7,6 +5,9 @@ name: Deploy PROD EMBED on: workflow_dispatch: +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: deploy_embed_eu: @@ -21,15 +22,15 @@ jobs: secrets: inherit deploy_embed_us: - uses: ./.github/workflows/reusable-embed-deploy.yml - with: - environment: Production - widget_url: https://widget.novu.co - netlify_deploy_message: Production deployment - netlify_alias: prod - netlify_gh_env: Production - netlify_site_id: 0689c015-fca0-4940-a26d-3e33f561bc48 - secrets: inherit + uses: ./.github/workflows/reusable-embed-deploy.yml + with: + environment: Production + widget_url: https://widget.novu.co + netlify_deploy_message: Production deployment + netlify_alias: prod + netlify_gh_env: Production + netlify_site_id: 0689c015-fca0-4940-a26d-3e33f561bc48 + secrets: inherit publish_docker_image_embed: needs: diff --git a/.github/workflows/prod-deploy-inbound-mail.yml b/.github/workflows/prod-deploy-inbound-mail.yml index ca43debae4e..3e59135e0d0 100644 --- a/.github/workflows/prod-deploy-inbound-mail.yml +++ b/.github/workflows/prod-deploy-inbound-mail.yml @@ -5,6 +5,9 @@ name: Deploy PROD Inbound Mail on: workflow_dispatch: +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + jobs: test_inbound_mail: strategy: diff --git a/.github/workflows/prod-deploy-web-component.yml b/.github/workflows/prod-deploy-web-component.yml index 2ed532e3b93..490635dc51a 100644 --- a/.github/workflows/prod-deploy-web-component.yml +++ b/.github/workflows/prod-deploy-web-component.yml @@ -3,6 +3,9 @@ name: Deploy PROD Notification Center Web Component on: workflow_dispatch: +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + jobs: build: uses: ./.github/workflows/reusable-notification-center.yml diff --git a/.github/workflows/prod-deploy-web.yml b/.github/workflows/prod-deploy-web.yml index 7a8f317f4c2..54a5eedb56f 100644 --- a/.github/workflows/prod-deploy-web.yml +++ b/.github/workflows/prod-deploy-web.yml @@ -1,5 +1,3 @@ -# This is a basic workflow to help you get started with Actions - name: Deploy PROD WEB # Controls when the action will run. Triggers the workflow on push or pull request @@ -7,6 +5,9 @@ name: Deploy PROD WEB on: workflow_dispatch: +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: deploy_web_eu: diff --git a/.github/workflows/prod-deploy-webhook.yml b/.github/workflows/prod-deploy-webhook.yml index b9e192724b4..79ca5551847 100644 --- a/.github/workflows/prod-deploy-webhook.yml +++ b/.github/workflows/prod-deploy-webhook.yml @@ -5,6 +5,9 @@ name: Deploy PROD WEBHOOK on: workflow_dispatch: +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + jobs: publish_docker_image_webhook: uses: ./.github/workflows/reusable-docker.yml diff --git a/.github/workflows/prod-deploy-widget.yml b/.github/workflows/prod-deploy-widget.yml index 83a54e3a29a..7be6c05cde0 100644 --- a/.github/workflows/prod-deploy-widget.yml +++ b/.github/workflows/prod-deploy-widget.yml @@ -1,5 +1,3 @@ -# This is a basic workflow to help you get started with Actions - name: Deploy PROD Widget # Controls when the action will run. Triggers the workflow on push or pull request @@ -7,6 +5,9 @@ name: Deploy PROD Widget on: workflow_dispatch: +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + jobs: test_widget: uses: ./.github/workflows/reusable-widget-e2e.yml diff --git a/.github/workflows/prod-deploy-worker.yml b/.github/workflows/prod-deploy-worker.yml index b584bbe0936..31c93529fe0 100644 --- a/.github/workflows/prod-deploy-worker.yml +++ b/.github/workflows/prod-deploy-worker.yml @@ -5,6 +5,9 @@ name: Deploy PROD Worker on: workflow_dispatch: +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + jobs: build_prod_image: # The type of runner that the job will run on @@ -52,7 +55,7 @@ jobs: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID}} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: us-east-1 - + - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v2 @@ -115,6 +118,6 @@ jobs: with: region: EU apiKey: ${{ secrets.NEW_RELIC_API_KEY }} - guid: "MzgxMjQwOHxBUE18QVBQTElDQVRJT058NDk3NzA2ODk2" - version: "${{ env.RELEASE_VERSION }}" - user: "${{ github.actor }}" + guid: 'MzgxMjQwOHxBUE18QVBQTElDQVRJT058NDk3NzA2ODk2' + version: '${{ env.RELEASE_VERSION }}' + user: '${{ github.actor }}' diff --git a/.github/workflows/prod-deploy-ws.yml b/.github/workflows/prod-deploy-ws.yml index ab737bb0b6d..99c8d872ce3 100644 --- a/.github/workflows/prod-deploy-ws.yml +++ b/.github/workflows/prod-deploy-ws.yml @@ -5,6 +5,9 @@ name: Deploy PROD WS on: workflow_dispatch: +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + jobs: # This workflow contains a single job called "build" build_prod_image: diff --git a/.github/workflows/reusable-api-e2e.yml b/.github/workflows/reusable-api-e2e.yml index dda2c7e5a96..8d5b399ec3a 100644 --- a/.github/workflows/reusable-api-e2e.yml +++ b/.github/workflows/reusable-api-e2e.yml @@ -1,5 +1,8 @@ name: E2E API Tests +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # Controls when the action will run. Triggers the workflow on push or pull request on: workflow_call: @@ -83,7 +86,6 @@ jobs: - uses: ./.github/actions/start-localstack name: Start localstack - - uses: ./.github/actions/run-worker name: Run worker with: diff --git a/.github/workflows/reusable-dashboard-deploy.yml b/.github/workflows/reusable-dashboard-deploy.yml index 2cb0eeeb28f..b0cddb617fb 100644 --- a/.github/workflows/reusable-dashboard-deploy.yml +++ b/.github/workflows/reusable-dashboard-deploy.yml @@ -1,5 +1,8 @@ name: Deploy Dashboard to Netlify +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # Controls when the action will run. Triggers the workflow on push or pull request on: workflow_call: diff --git a/.github/workflows/reusable-dashboard-e2e.yml b/.github/workflows/reusable-dashboard-e2e.yml index 01ccd9f0e2f..d0572ecb838 100644 --- a/.github/workflows/reusable-dashboard-e2e.yml +++ b/.github/workflows/reusable-dashboard-e2e.yml @@ -1,7 +1,8 @@ -# This is a basic workflow to help you get started with Actions - name: Test DASHBOARD +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # Controls when the action will run. Triggers the workflow on push or pull request on: workflow_dispatch: @@ -57,7 +58,7 @@ jobs: with: submodules: true token: ${{ secrets.SUBMODULES_TOKEN }} - + - id: checkout-community-code name: Checkout community code uses: actions/checkout@v4 @@ -124,30 +125,30 @@ jobs: needs: [e2e_dashboard] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.8.1 - - - name: Download blob reports from GitHub Actions Artifacts - uses: actions/download-artifact@v4 - with: - path: dashboard-all-blob-reports - pattern: dashboard-blob-report-* - merge-multiple: true - - - name: Merge into HTML Report - run: npx playwright merge-reports --reporter html ./dashboard-all-blob-reports - - - name: Upload HTML report - uses: actions/upload-artifact@v4 - with: - name: dashboard-html-report--attempt-${{ github.run_attempt }} - path: playwright-report - retention-days: 14 - - - name: Send Slack notifications - uses: ./.github/actions/slack-notify-on-failure - if: failure() - with: - slackWebhookURL: ${{ secrets.SLACK_WEBHOOK_URL_ENG_FEED_GITHUB }} + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20.8.1 + + - name: Download blob reports from GitHub Actions Artifacts + uses: actions/download-artifact@v4 + with: + path: dashboard-all-blob-reports + pattern: dashboard-blob-report-* + merge-multiple: true + + - name: Merge into HTML Report + run: npx playwright merge-reports --reporter html ./dashboard-all-blob-reports + + - name: Upload HTML report + uses: actions/upload-artifact@v4 + with: + name: dashboard-html-report--attempt-${{ github.run_attempt }} + path: playwright-report + retention-days: 14 + + - name: Send Slack notifications + uses: ./.github/actions/slack-notify-on-failure + if: failure() + with: + slackWebhookURL: ${{ secrets.SLACK_WEBHOOK_URL_ENG_FEED_GITHUB }} diff --git a/.github/workflows/reusable-docker.yml b/.github/workflows/reusable-docker.yml index 7da9ec7d7d4..0f83e5f773d 100644 --- a/.github/workflows/reusable-docker.yml +++ b/.github/workflows/reusable-docker.yml @@ -1,5 +1,8 @@ name: Build, tag and push docker image to ghcr.io +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # Controls when the action will run. Triggers the workflow on push or pull request on: workflow_call: @@ -64,7 +67,7 @@ jobs: id-token: write strategy: matrix: - name: [ '${{ inputs.package_name }}-ee'] + name: ['${{ inputs.package_name }}-ee'] steps: - uses: actions/checkout@v4 with: @@ -87,14 +90,13 @@ jobs: with: driver-opts: 'image=moby/buildkit:v0.13.1' - - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ${{ inputs.aws-region }} - + - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v2 diff --git a/.github/workflows/reusable-embed-deploy.yml b/.github/workflows/reusable-embed-deploy.yml index a28a2718ef0..5cce978fa92 100644 --- a/.github/workflows/reusable-embed-deploy.yml +++ b/.github/workflows/reusable-embed-deploy.yml @@ -1,5 +1,8 @@ name: Deploy Embed to Netlify +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # Controls when the action will run. Triggers the workflow on push or pull request on: workflow_call: diff --git a/.github/workflows/reusable-inbound-mail-e2e.yml b/.github/workflows/reusable-inbound-mail-e2e.yml index c655735457e..6e10506e09f 100644 --- a/.github/workflows/reusable-inbound-mail-e2e.yml +++ b/.github/workflows/reusable-inbound-mail-e2e.yml @@ -1,5 +1,8 @@ name: E2E Inbound Mail Tests +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # Controls when the action will run. Triggers the workflow on push or pull request on: workflow_call: diff --git a/.github/workflows/reusable-notification-center.yml b/.github/workflows/reusable-notification-center.yml index c67ea65c8e4..d25e0956581 100644 --- a/.github/workflows/reusable-notification-center.yml +++ b/.github/workflows/reusable-notification-center.yml @@ -1,5 +1,8 @@ name: Test and build @novu/notification-center +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + on: workflow_call: diff --git a/.github/workflows/reusable-web-deploy.yml b/.github/workflows/reusable-web-deploy.yml index d3b41e318d3..59ba8aff46a 100644 --- a/.github/workflows/reusable-web-deploy.yml +++ b/.github/workflows/reusable-web-deploy.yml @@ -1,5 +1,8 @@ name: Deploy Web to Netlify +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # Controls when the action will run. Triggers the workflow on push or pull request on: workflow_call: diff --git a/.github/workflows/reusable-web-e2e.yml b/.github/workflows/reusable-web-e2e.yml index 6542f8afd20..b18a7557df2 100644 --- a/.github/workflows/reusable-web-e2e.yml +++ b/.github/workflows/reusable-web-e2e.yml @@ -1,7 +1,8 @@ -# This is a basic workflow to help you get started with Actions - name: Test WEB +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # Controls when the action will run. Triggers the workflow on push or pull request on: workflow_dispatch: @@ -57,7 +58,7 @@ jobs: with: submodules: true token: ${{ secrets.SUBMODULES_TOKEN }} - + - id: checkout-community-code name: Checkout community code uses: actions/checkout@v4 @@ -126,30 +127,30 @@ jobs: needs: [e2e_web] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20.8.1 - - - name: Download blob reports from GitHub Actions Artifacts - uses: actions/download-artifact@v4 - with: - path: all-blob-reports - pattern: blob-report-* - merge-multiple: true - - - name: Merge into HTML Report - run: npx playwright merge-reports --reporter html ./all-blob-reports - - - name: Upload HTML report - uses: actions/upload-artifact@v4 - with: - name: html-report--attempt-${{ github.run_attempt }} - path: playwright-report - retention-days: 14 - - - name: Send Slack notifications - uses: ./.github/actions/slack-notify-on-failure - if: failure() - with: - slackWebhookURL: ${{ secrets.SLACK_WEBHOOK_URL_ENG_FEED_GITHUB }} + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20.8.1 + + - name: Download blob reports from GitHub Actions Artifacts + uses: actions/download-artifact@v4 + with: + path: all-blob-reports + pattern: blob-report-* + merge-multiple: true + + - name: Merge into HTML Report + run: npx playwright merge-reports --reporter html ./all-blob-reports + + - name: Upload HTML report + uses: actions/upload-artifact@v4 + with: + name: html-report--attempt-${{ github.run_attempt }} + path: playwright-report + retention-days: 14 + + - name: Send Slack notifications + uses: ./.github/actions/slack-notify-on-failure + if: failure() + with: + slackWebhookURL: ${{ secrets.SLACK_WEBHOOK_URL_ENG_FEED_GITHUB }} diff --git a/.github/workflows/reusable-webhook-e2e.yml b/.github/workflows/reusable-webhook-e2e.yml index 48d7a123800..24f15aa34e8 100644 --- a/.github/workflows/reusable-webhook-e2e.yml +++ b/.github/workflows/reusable-webhook-e2e.yml @@ -1,5 +1,8 @@ name: E2E WEBHOOK Tests +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # Controls when the action will run. Triggers the workflow on push or pull request on: workflow_call: @@ -14,17 +17,17 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - uses: ./.github/actions/setup-project + - uses: ./.github/actions/setup-project - - uses: ./.github/actions/start-localstack + - uses: ./.github/actions/start-localstack - # Runs a single command using the runners shell - - name: Build Webhook - run: CI='' pnpm build:webhook + # Runs a single command using the runners shell + - name: Build Webhook + run: CI='' pnpm build:webhook - # Runs a set of commands using the runners shell - - name: Run a test - run: | - cd apps/webhook && pnpm test:e2e + # Runs a set of commands using the runners shell + - name: Run a test + run: | + cd apps/webhook && pnpm test:e2e diff --git a/.github/workflows/reusable-widget-deploy.yml b/.github/workflows/reusable-widget-deploy.yml index d4d1b4295b6..f446e10db95 100644 --- a/.github/workflows/reusable-widget-deploy.yml +++ b/.github/workflows/reusable-widget-deploy.yml @@ -1,5 +1,8 @@ name: Deploy Widget to Netlify +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # Controls when the action will run. Triggers the workflow on push or pull request on: workflow_call: @@ -36,7 +39,6 @@ on: required: true type: string - # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: reusable_widget_deploy: diff --git a/.github/workflows/reusable-widget-e2e.yml b/.github/workflows/reusable-widget-e2e.yml index b635bac7def..16e004b2856 100644 --- a/.github/workflows/reusable-widget-e2e.yml +++ b/.github/workflows/reusable-widget-e2e.yml @@ -1,6 +1,8 @@ -# This is a basic workflow to help you get started with Actions name: Test E2E WIDGET +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # Controls when the action will run. Triggers the workflow on push or pull request on: workflow_call: diff --git a/.github/workflows/reusable-worker-e2e.yml b/.github/workflows/reusable-worker-e2e.yml index 5407fc9570c..06546b975a5 100644 --- a/.github/workflows/reusable-worker-e2e.yml +++ b/.github/workflows/reusable-worker-e2e.yml @@ -1,5 +1,8 @@ name: E2E worker Tests +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # Controls when the action will run. Triggers the workflow on push or pull request on: workflow_call: @@ -26,35 +29,35 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: - - id: setup - run: | - if ! [[ -z "${{ secrets.SUBMODULES_TOKEN }}" ]]; then - echo "has_token=true" >> $GITHUB_OUTPUT - else - echo "has_token=false" >> $GITHUB_OUTPUT - fi - # checkout with submodules if token is provided - - uses: actions/checkout@v4 - if: steps.setup.outputs.has_token == 'true' - with: - submodules: ${{ inputs.ee }} - token: ${{ secrets.SUBMODULES_TOKEN }} - # else checkout without submodules if the token is not provided - - uses: actions/checkout@v4 - if: steps.setup.outputs.has_token != 'true' - - - uses: ./.github/actions/setup-project - - - uses: ./.github/actions/setup-redis-cluster - - - uses: ./.github/actions/start-localstack - - # Runs a single command using the runners shell - - name: Build worker - run: CI='' pnpm build:worker - - # Runs a set of commands using the runners shell - - name: Run a test - run: | - cd apps/worker && pnpm test:e2e - pnpm test + - id: setup + run: | + if ! [[ -z "${{ secrets.SUBMODULES_TOKEN }}" ]]; then + echo "has_token=true" >> $GITHUB_OUTPUT + else + echo "has_token=false" >> $GITHUB_OUTPUT + fi + # checkout with submodules if token is provided + - uses: actions/checkout@v4 + if: steps.setup.outputs.has_token == 'true' + with: + submodules: ${{ inputs.ee }} + token: ${{ secrets.SUBMODULES_TOKEN }} + # else checkout without submodules if the token is not provided + - uses: actions/checkout@v4 + if: steps.setup.outputs.has_token != 'true' + + - uses: ./.github/actions/setup-project + + - uses: ./.github/actions/setup-redis-cluster + + - uses: ./.github/actions/start-localstack + + # Runs a single command using the runners shell + - name: Build worker + run: CI='' pnpm build:worker + + # Runs a set of commands using the runners shell + - name: Run a test + run: | + cd apps/worker && pnpm test:e2e + pnpm test diff --git a/.github/workflows/reusable-workers-service-deploy.yml b/.github/workflows/reusable-workers-service-deploy.yml index 15aaa38ef04..afb947952db 100644 --- a/.github/workflows/reusable-workers-service-deploy.yml +++ b/.github/workflows/reusable-workers-service-deploy.yml @@ -1,5 +1,8 @@ name: Deploy Workers Job +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # Controls when the action will run. Triggers the workflow on push or pull request on: workflow_call: @@ -64,7 +67,6 @@ jobs: echo "ecs_cluster=$(terraform output -json worker_ecs_cluster | jq -r .)" >> $GITHUB_OUTPUT echo "aws_region=$(terraform output -json aws_region | jq -r .)" >> $GITHUB_OUTPUT - deploy_worker_queue: needs: infrastructure_data runs-on: ubuntu-latest diff --git a/.github/workflows/reusable-ws-e2e.yml b/.github/workflows/reusable-ws-e2e.yml index ea99d61fb44..f054c2c4906 100644 --- a/.github/workflows/reusable-ws-e2e.yml +++ b/.github/workflows/reusable-ws-e2e.yml @@ -1,5 +1,8 @@ name: E2E WebSocket Tests +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + # Controls when the action will run. Triggers the workflow on push or pull request on: workflow_call: diff --git a/.github/workflows/rollback.yml b/.github/workflows/rollback.yml index a6414c5ef4e..f504ad0b270 100644 --- a/.github/workflows/rollback.yml +++ b/.github/workflows/rollback.yml @@ -1,6 +1,9 @@ name: Rollback run-name: Rollback the ${{ inputs.service }} service in the ${{ inputs.environment }} environment +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + on: workflow_dispatch: inputs: @@ -25,7 +28,7 @@ on: type: choice description: Select the environment region. Required only in production. options: - - [EU,US] + - [EU, US] - [EU] - [US] mode: @@ -121,11 +124,11 @@ jobs: echo "Retrieving current_task_definition_arn..." current_task_definition_arn=$(aws ecs describe-services --cluster ${{ env.ecs_cluster }} --services ${{ env.ecs_service }} --query 'services[0].taskDefinition' --output text) echo "current_task_definition_arn=$current_task_definition_arn" >> $GITHUB_ENV - + echo "Retrieving task_definition_family..." task_definition_family=$(aws ecs describe-task-definition --task-definition ${{ env.task_name }} --query 'taskDefinition.family' --output text) echo "task_definition_family=$task_definition_family" >> $GITHUB_ENV - + echo "Retrieving task_definition_list..." task_definition_list=$(aws ecs list-task-definitions --family-prefix "${task_definition_family}" --output text --sort DESC | grep 'TASKDEFINITIONARNS' | cut -f 2) task_definition_list_formatted=$(echo "$task_definition_list" | tr '\n' '|') # Replace newline with '|' @@ -178,7 +181,6 @@ jobs: echo "previous_task_definition_arn=$needed_arn" >> $GITHUB_ENV echo "Your task definition ARN is $needed_arn" - - name: Rollback a service to the previous task definition id: rollback env: @@ -191,7 +193,6 @@ jobs: echo "The previous task definition: $(echo $CURRENT_TASK | awk -F'task-definition/' '{print $2}')" echo "The current task definition: $(echo $PREVIOUS_TASK | awk -F'task-definition/' '{print $2}')" - netlify: if: contains(fromJson('["web", "widget"]'), github.event.inputs.service) runs-on: ubuntu-latest diff --git a/.github/workflows/tag-images.yml b/.github/workflows/tag-images.yml index daf317f65b8..44fae29177c 100644 --- a/.github/workflows/tag-images.yml +++ b/.github/workflows/tag-images.yml @@ -33,7 +33,7 @@ jobs: GH_ACTOR: ${{ github.actor }} GH_PASSWORD: ${{ secrets.GH_PACKAGES }} run: | - echo $GH_PASSWORD | docker login ghcr.io -u $GH_ACTOR --password-stdin + echo $GH_PASSWORD | docker login ghcr.io -u $GH_ACTOR --password-stdin - name: Tag API env: diff --git a/.gitpod.yml b/.gitpod.yml index bdb9f418eab..5ccafcfc062 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -2,7 +2,7 @@ image: file: .gitpod.dockerfile tasks: - init: npm_config_yes=true pnpm setup:project && gp sync-done setup - command: mkdir -p /workspace/data && mongod --dbpath /workspace/data + command: mkdir -p /workspace/data && mongod --dbpath /workspace/data - init: gp sync-await setup command: redis-server - name: Shared Library diff --git a/.markdownlint.jsonc b/.markdownlint.jsonc index a1d8fea5b69..cd7fe879668 100644 --- a/.markdownlint.jsonc +++ b/.markdownlint.jsonc @@ -4,12 +4,12 @@ // MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content "MD024": { - "siblings_only": true + "siblings_only": true, }, // no-multiple-blanks "MD012": false, - + // MD032/blanks-around-lists - Lists should be surrounded by blank lines "MD032": false, @@ -33,22 +33,14 @@ // MD044/proper-names - Proper names should have the correct capitalization "MD044": { "code_blocks": false, - "names": [ - "Cake.Markdownlint", - "CommonMark", - "JavaScript", - "Markdown", - "markdown-it", - "markdownlint", - "Node.js" - ] + "names": ["Cake.Markdownlint", "CommonMark", "JavaScript", "Markdown", "markdown-it", "markdownlint", "Node.js"], }, // MD-46/code-block-style "MD046": { - "style": "fenced" + "style": "fenced", }, // MD031/blanks-around-fences Fenced code blocks should be surrounded by blank lines - "MD031": false + "MD031": false, } diff --git a/.vscode/launch.json b/.vscode/launch.json index af743d5a772..11075039d70 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,229 +1,148 @@ { "version": "0.2.0", "configurations": [ - { "name": "API - TEST ENV", "request": "launch", - "runtimeArgs": [ - "run-script", - "start:test" - ], + "runtimeArgs": ["run-script", "start:test"], "runtimeExecutable": "npm", "cwd": "${workspaceFolder}/apps/api", - "skipFiles": [ - "/**" - ], + "skipFiles": ["/**"], "type": "node" }, { "name": "API", "request": "launch", - "runtimeArgs": [ - "run-script", - "start" - ], + "runtimeArgs": ["run-script", "start"], "runtimeExecutable": "npm", "cwd": "${workspaceFolder}/apps/api", - "skipFiles": [ - "/**" - ], + "skipFiles": ["/**"], "type": "node" }, { "name": "worker", "request": "launch", - "runtimeArgs": [ - "run-script", - "start" - ], + "runtimeArgs": ["run-script", "start"], "runtimeExecutable": "npm", "cwd": "${workspaceFolder}/apps/worker", - "skipFiles": [ - "/**" - ], + "skipFiles": ["/**"], "type": "node" }, { "name": "WEB", "request": "launch", - "runtimeArgs": [ - "run-script", - "start:dev" - ], + "runtimeArgs": ["run-script", "start:dev"], "runtimeExecutable": "npm", "cwd": "${workspaceFolder}/apps/web", - "skipFiles": [ - "/**" - ], + "skipFiles": ["/**"], "type": "node" }, { "name": "WIDGET", "request": "launch", - "runtimeArgs": [ - "run-script", - "start:dev" - ], + "runtimeArgs": ["run-script", "start:dev"], "runtimeExecutable": "npm", "cwd": "${workspaceFolder}/apps/widget", - "skipFiles": [ - "/**" - ], + "skipFiles": ["/**"], "type": "node" }, { "name": "WIDGET - test", "request": "launch", - "runtimeArgs": [ - "run-script", - "start:test" - ], + "runtimeArgs": ["run-script", "start:test"], "runtimeExecutable": "npm", "cwd": "${workspaceFolder}/apps/widget", - "skipFiles": [ - "/**" - ], + "skipFiles": ["/**"], "type": "node" }, { "name": "WS", "request": "launch", - "runtimeArgs": [ - "run-script", - "start" - ], + "runtimeArgs": ["run-script", "start"], "runtimeExecutable": "npm", "cwd": "${workspaceFolder}/apps/ws", - "skipFiles": [ - "/**" - ], + "skipFiles": ["/**"], "type": "node" }, { "name": "WS - TEST ENV", "request": "launch", - "runtimeArgs": [ - "run-script", - "start:test" - ], + "runtimeArgs": ["run-script", "start:test"], "runtimeExecutable": "npm", "cwd": "${workspaceFolder}/apps/ws", - "skipFiles": [ - "/**" - ], + "skipFiles": ["/**"], "type": "node" }, { "name": "DAL", "request": "launch", - "runtimeArgs": [ - "run-script", - "start:dev" - ], + "runtimeArgs": ["run-script", "start:dev"], "runtimeExecutable": "npm", "cwd": "${workspaceFolder}/libs/dal", - "skipFiles": [ - "/**" - ], + "skipFiles": ["/**"], "type": "node" }, { "name": "TESTING LIB", "request": "launch", - "runtimeArgs": [ - "run-script", - "start:dev" - ], + "runtimeArgs": ["run-script", "start:dev"], "runtimeExecutable": "npm", "cwd": "${workspaceFolder}/libs/testing", - "skipFiles": [ - "/**" - ], + "skipFiles": ["/**"], "type": "node" }, { "name": "EMBED", "request": "launch", - "runtimeArgs": [ - "run-script", - "start:dev" - ], + "runtimeArgs": ["run-script", "start:dev"], "runtimeExecutable": "npm", "cwd": "${workspaceFolder}/libs/embed", - "skipFiles": [ - "/**" - ], + "skipFiles": ["/**"], "type": "node" }, { "name": "SHARED", "request": "launch", - "runtimeArgs": [ - "run-script", - "start:dev" - ], + "runtimeArgs": ["run-script", "start:dev"], "runtimeExecutable": "npm", "cwd": "${workspaceFolder}/packages/shared", - "skipFiles": [ - "/**" - ], + "skipFiles": ["/**"], "type": "node" }, { "name": "STORYBOOK", "request": "launch", - "runtimeArgs": [ - "run-script", - "storybook" - ], + "runtimeArgs": ["run-script", "storybook"], "runtimeExecutable": "npm", "cwd": "${workspaceFolder}/apps/web", - "skipFiles": [ - "/**" - ], + "skipFiles": ["/**"], "type": "node" }, { "name": "CORE", "request": "launch", - "runtimeArgs": [ - "run-script", - "start:dev" - ], + "runtimeArgs": ["run-script", "start:dev"], "runtimeExecutable": "npm", "cwd": "${workspaceFolder}/packages/node", - "skipFiles": [ - "/**" - ], + "skipFiles": ["/**"], "type": "node" }, { "name": "Cypress open - web", "request": "launch", - "runtimeArgs": [ - "run-script", - "cypress:open" - ], + "runtimeArgs": ["run-script", "cypress:open"], "runtimeExecutable": "npm", "cwd": "${workspaceFolder}/apps/web", - "skipFiles": [ - "/**" - ], + "skipFiles": ["/**"], "type": "node" }, { "name": "Cypress open - widget", "request": "launch", - "runtimeArgs": [ - "run-script", - "cypress:open" - ], + "runtimeArgs": ["run-script", "cypress:open"], "runtimeExecutable": "npm", "cwd": "${workspaceFolder}/apps/widget", - "skipFiles": [ - "/**" - ], + "skipFiles": ["/**"], "type": "node" } ], diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 5918193398a..14df9002691 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -21,7 +21,7 @@ "endsPattern": "Started application in NODE_ENV" } } - }, + }, { "type": "npm", "script": "start", @@ -41,14 +41,7 @@ "id": "server", "color": "terminal.ansiGreen" }, - "dependsOn": [ - "SHARED", - "API", - "APPLICATION GENERIC", - "DAL", - "EE - TRANSLATION", - "EE - BILLING" - ] + "dependsOn": ["SHARED", "API", "APPLICATION GENERIC", "DAL", "EE - TRANSLATION", "EE - BILLING"] }, { "type": "npm", @@ -69,7 +62,8 @@ "endsPattern": "webpack compiled successfully" } } - }, { + }, + { "type": "npm", "script": "start", "isBackground": true, @@ -88,12 +82,7 @@ "endsPattern": "webpack compiled successfully" } }, - "dependsOn": [ - "SHARED", - "API", - "DESIGN SYSTEM", - "NOVUI" - ] + "dependsOn": ["SHARED", "API", "DESIGN SYSTEM", "NOVUI"] }, { "type": "npm", @@ -110,11 +99,7 @@ "label": "APPLICATION GENERIC", "path": "/libs/application-generic", "problemMatcher": "$tsc-watch", - "dependsOn": [ - "SHARED", - "TESTING", - "PROVIDERS" - ] + "dependsOn": ["SHARED", "TESTING", "PROVIDERS"] }, { "type": "npm", @@ -123,9 +108,7 @@ "label": "DAL", "path": "/libs/dal", "problemMatcher": "$tsc-watch", - "dependsOn": [ - "SHARED" - ] + "dependsOn": ["SHARED"] }, { "type": "npm", @@ -142,9 +125,7 @@ "label": "PROVIDERS", "path": "/packages/providers", "problemMatcher": "$tsc-watch", - "dependsOn": [ - "SHARED" - ] + "dependsOn": ["SHARED"] }, { "type": "npm", @@ -161,9 +142,7 @@ "label": "TESTING", "path": "/libs/testing", "problemMatcher": "$tsc-watch", - "dependsOn": [ - "SHARED" - ] + "dependsOn": ["SHARED"] }, { "type": "npm", @@ -221,10 +200,7 @@ "label": "NOTIFICATION CENTER", "path": "/packages/notification-center", "problemMatcher": "$tsc", - "dependsOn": [ - "NC CLIENT", - "SHARED" - ] + "dependsOn": ["NC CLIENT", "SHARED"] }, { "type": "npm", @@ -232,9 +208,7 @@ "label": "NC CLIENT", "path": "/packages/client", "problemMatcher": "$tsc", - "dependsOn": [ - "SHARED" - ] + "dependsOn": ["SHARED"] } ] } diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 14352a3718c..4338d6e7904 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -17,23 +17,23 @@ diverse, inclusive, and healthy community. Examples of behavior that contributes to a positive environment for our community includes: -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience -* Focusing on what is best not just for us as individuals, but for the +- Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: -* The use of sexualized language or imagery, and sexual attention or +- The use of sexualized language or imagery, and sexual attention or advances of any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email address, without their explicit permission -* Other conduct that could reasonably be considered inappropriate in a +- Other conduct that could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities @@ -106,7 +106,7 @@ Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an +standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within diff --git a/README.md b/README.md index 7569a559bad..09eca5a66cb 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ There are two ways to get started: ```bash npx novu@latest dev ``` + 2. [Create a free cloud account](https://dashboard.novu.co?utm_campaign=github-readme) ## 📚 Table of contents @@ -135,6 +136,7 @@ Using the Novu API and admin panel, you can easily add a real-time notification notification-center-912bb96e009fb3a69bafec23bcde00b0 Read more about how to add a [notification center Inbox](https://docs.novu.co/inbox/react/get-started?utm_campaign=github-readme) to your app. + ## Providers @@ -217,6 +219,7 @@ We are more than happy to help you. If you are getting any errors or facing prob Novu is a commercial open source company, which means some parts of this open source repository require a commercial license. The concept is called "Open Core," where the core technology is fully open source, licensed under MIT license, and the enterprise code is covered under a commercial license ("/enterprise" Enterprise Edition). Enterprise features are built by the core engineering team of Novu which is hired in full-time. The following modules and folders are licensed under the enterprise license: + - `enterprise` folder at the root of the project and all of their subfolders and modules - `apps/web/src/ee` folder and all of their subfolders and modules - `apps/dashboard/src/ee` folder and all of their subfolders and modules diff --git a/SECURITY.md b/SECURITY.md index 9b94c6ade88..4f7605572fb 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -46,7 +46,7 @@ If you come across a vulnerability, please inform us promptly so we can promptly 6. Please share enough details for us to understand and fix the issue as fast as we can. Typically, providing the IP address or the URL of the affected system along with a description of the problem should be enough, though more intricate issues might need additional clarification. -## What *We* Promise +## What _We_ Promise 1. We'll get back to you within 3 business days with our assessment of the report and an estimated date when we expect to resolve it. diff --git a/apps/api/.spectral.yaml b/apps/api/.spectral.yaml index 31d5ceb4c92..482288d25ed 100644 --- a/apps/api/.spectral.yaml +++ b/apps/api/.spectral.yaml @@ -14,9 +14,9 @@ extends: [[spectral:oas, all]] # https://meta.stoplight.io/docs/spectral/293426e270fac-overrides overrides: - files: - - "**#/paths/~1v1~1subscribers~1%7BsubscriberId%7D~1preferences~1%7BtemplateId%7D" - - "**#/paths/~1v1~1subscribers~1%7BsubscriberId%7D~1preferences~1%7Blevel%7D" - - "**#/paths/~1v1~1workflows~1%7BworkflowIdOrIdentifier%7D" - - "**#/paths/~1v1~1notification-templates~1%7BworkflowIdOrIdentifier%7D" + - '**#/paths/~1v1~1subscribers~1%7BsubscriberId%7D~1preferences~1%7BtemplateId%7D' + - '**#/paths/~1v1~1subscribers~1%7BsubscriberId%7D~1preferences~1%7Blevel%7D' + - '**#/paths/~1v1~1workflows~1%7BworkflowIdOrIdentifier%7D' + - '**#/paths/~1v1~1notification-templates~1%7BworkflowIdOrIdentifier%7D' rules: - path-params: "off" + path-params: 'off' diff --git a/apps/api/README.md b/apps/api/README.md index 477c6f02fd3..bee04293f68 100644 --- a/apps/api/README.md +++ b/apps/api/README.md @@ -11,7 +11,6 @@ A RESTful API for accessing the Novu platform, built using [NestJS](https://nestjs.com/). - ## Running the API See the docs for [Run in Local Machine](https://docs.novu.co/community/run-in-local-machine?utm_campaign=github-api-readme) to get setup. Then run: @@ -24,30 +23,37 @@ $ npm run start:api ## Test ### Unit Tests + ```bash # unit tests $ npm run test ``` ### E2E tests + See the docs for [Running on Local Machine - API Tests](https://docs.novu.co/community/run-in-local-machine#api?utm_campaign=github-api-readme). ## Adding a new Endpoint + ### Choose the right controller / new controller. + - If the endpoint is related to an existing entity, add the endpoint to the existing controller. + ### Add the correct decorators to the controller method. + - Use the `@Get`, `@Post`, `@Put`, `@Delete` decorators to define the HTTP method. - Use the `@Param`, `@Query`, `@Body` decorators to define the parameters. - Use the `@UserAuthentication()` decorator to define the guards as well as make it accessible to novu web app. - Use the @ExternalApiAccessible decorator to define the endpoint as accessible by external API (Users with Api-Key) & The official Novu SDK. -#### Naming conventions - - for the controller methods should be in the format `getEntityName`, `createEntityName`, `updateEntityName`, `deleteEntityName`. - - In Case of a getAll / List use the `list` prefix for the method name and don't forget to add pagination functionality. - - Use the `@SdkUsePagination` decorator to alert the sdk of a paginated endpoint (will improve DX with an async iterator) the pagination parameters. - - In case of a uniuqe usecase outside of the basic REST operations, attempt to use the regular naming conventions just for a sub-resource. - - `@SdkGroupName` - Use this decorator to group the endpoints in the SDK, use `.` separator to create a subresource (Ex' 'Subscribers.Notifications' getSubscriberNotifications), the original resource is defined as an openApi Tag . - - `@SdkMethodName` in case of a unique operation, use this decorator to define the method name in the SDK. +#### Naming conventions + +- for the controller methods should be in the format `getEntityName`, `createEntityName`, `updateEntityName`, `deleteEntityName`. +- In Case of a getAll / List use the `list` prefix for the method name and don't forget to add pagination functionality. + - Use the `@SdkUsePagination` decorator to alert the sdk of a paginated endpoint (will improve DX with an async iterator) the pagination parameters. +- In case of a uniuqe usecase outside of the basic REST operations, attempt to use the regular naming conventions just for a sub-resource. + - `@SdkGroupName` - Use this decorator to group the endpoints in the SDK, use `.` separator to create a subresource (Ex' 'Subscribers.Notifications' getSubscriberNotifications), the original resource is defined as an openApi Tag . + - `@SdkMethodName` in case of a unique operation, use this decorator to define the method name in the SDK. ## OpenAPI (formerly Swagger) @@ -63,8 +69,8 @@ $ npm run lint:openapi The command will return warnings and errors that must be fixed before the Github action will pass. These fixes are created by making changes through the `@nestjs/swagger` decorators. - ## Migrations + Database migrations are included for features that have a hard dependency on specific data being available on database entities. These migrations are run by both Novu Cloud and Novu Self-Hosted users to support new feature releases. ### How to Run diff --git a/apps/api/jarvis-api-intro.md b/apps/api/jarvis-api-intro.md index f5ef84776ef..5ec0272cb3b 100644 --- a/apps/api/jarvis-api-intro.md +++ b/apps/api/jarvis-api-intro.md @@ -1,6 +1,6 @@ Hi, I'm Jarvis 🤖 -I'm a bot built to help you with your contribution to Novu. +I'm a bot built to help you with your contribution to Novu. I will add instructions and guides on how to run the subset of the Novu platform associated to this issue and make your first contribution. This issue was tagged as related to `@novu/api` and the related code is located at the `apps/api` folder, here is how I can help you: @@ -8,19 +8,23 @@ This issue was tagged as related to `@novu/api` and the related code is located
First time contributing to Novu? - If that's the first time you want to contribute to Novu here are a few simple steps to get you started: - 1. Fork the repository and clone your fork to your local machine. - 2. Install the dependencies using `npm run setup:project`. - 3. Create a new branch with the number of the issue, for example: `1454-fix-something-cool` and start contributing based on the [Contributing Guide](https://docs.novu.co/community/run-in-local-machine?utm_campaign=github-jarvis) or the short guide in the section below. - 4. Create a Pull request and follow the template of creation +If that's the first time you want to contribute to Novu here are a few simple steps to get you started: + +1. Fork the repository and clone your fork to your local machine. +2. Install the dependencies using `npm run setup:project`. +3. Create a new branch with the number of the issue, for example: `1454-fix-something-cool` and start contributing based on the [Contributing Guide](https://docs.novu.co/community/run-in-local-machine?utm_campaign=github-jarvis) or the short guide in the section below. +4. Create a Pull request and follow the template of creation
Run and test `@novu/api` locally - ### Run API in watch mode - The easiest way to start the API is to run `npm run start:api` from the root of the repository +### Run API in watch mode + +The easiest way to start the API is to run `npm run start:api` from the root of the repository + +### Run API integration tests + +To validate your changes or simply to run the e2e tests run `npm run start:e2e:api`. All the e2e tests have the `.e2e.ts` suffix and usually are located near the controller files of each module. - ### Run API integration tests - To validate your changes or simply to run the e2e tests run `npm run start:e2e:api`. All the e2e tests have the `.e2e.ts` suffix and usually are located near the controller files of each module.
diff --git a/apps/dashboard/README.md b/apps/dashboard/README.md index 74872fd4af6..1e5a46b4e1c 100644 --- a/apps/dashboard/README.md +++ b/apps/dashboard/README.md @@ -22,7 +22,7 @@ export default tseslint.config({ tsconfigRootDir: import.meta.dirname, }, }, -}) +}); ``` - Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked` @@ -31,7 +31,7 @@ export default tseslint.config({ ```js // eslint.config.js -import react from 'eslint-plugin-react' +import react from 'eslint-plugin-react'; export default tseslint.config({ // Set the react version @@ -46,5 +46,5 @@ export default tseslint.config({ ...react.configs.recommended.rules, ...react.configs['jsx-runtime'].rules, }, -}) +}); ``` diff --git a/apps/dashboard/src/index.css b/apps/dashboard/src/index.css index ecfe13bbf6f..30fa7346b83 100644 --- a/apps/dashboard/src/index.css +++ b/apps/dashboard/src/index.css @@ -87,8 +87,9 @@ @apply bg-background text-foreground-950; } - body, html{ + body, + html { height: 100%; scroll-behavior: smooth; -} + } } diff --git a/apps/web/.storybook/Doc.container.tsx b/apps/web/.storybook/Doc.container.tsx index ae81e24715f..9a13aed2981 100644 --- a/apps/web/.storybook/Doc.container.tsx +++ b/apps/web/.storybook/Doc.container.tsx @@ -22,7 +22,8 @@ export const DocsContainer = ({ children, context }) => { }, }; }, - }}> + }} + > {children} ); diff --git a/apps/web/.storybook/main.js b/apps/web/.storybook/main.js index 8d24b5538aa..a1e2ad206ab 100644 --- a/apps/web/.storybook/main.js +++ b/apps/web/.storybook/main.js @@ -1,12 +1,17 @@ -import { dirname, join } from "path"; +import { dirname, join } from 'path'; module.exports = { stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], - addons: [getAbsolutePath("@storybook/addon-links"), getAbsolutePath("@storybook/addon-essentials"), getAbsolutePath("storybook-dark-mode"), getAbsolutePath("@storybook/addon-mdx-gfm")], + addons: [ + getAbsolutePath('@storybook/addon-links'), + getAbsolutePath('@storybook/addon-essentials'), + getAbsolutePath('storybook-dark-mode'), + getAbsolutePath('@storybook/addon-mdx-gfm'), + ], framework: { - name: getAbsolutePath("@storybook/react-webpack5"), - options: {} + name: getAbsolutePath('@storybook/react-webpack5'), + options: {}, }, features: { @@ -14,10 +19,10 @@ module.exports = { }, docs: { - autodocs: true - } + autodocs: true, + }, }; function getAbsolutePath(value) { - return dirname(require.resolve(join(value, "package.json"))); + return dirname(require.resolve(join(value, 'package.json'))); } diff --git a/apps/web/public/index.html b/apps/web/public/index.html index 0853c4758e6..406aae780ff 100644 --- a/apps/web/public/index.html +++ b/apps/web/public/index.html @@ -1,4 +1,4 @@ - + @@ -46,7 +46,11 @@ /* Critical CSS for the instant loader */ @layer critical { /* Override Mantine injected CSS layers to prevent minor jumps */ - *,::before,::after,::backdrop,::file-selector-button { + *, + ::before, + ::after, + ::backdrop, + ::file-selector-button { margin: 0px; padding: 0px; box-sizing: border-box; @@ -63,12 +67,12 @@ @media (prefers-color-scheme: light) { /* surface.page (light mode) */ - background-color: #EDF0F2; + background-color: #edf0f2; } @media (prefers-color-scheme: dark) { /* surface.page (dark mode) */ - background-color: #13131A ; + background-color: #13131a; } } @@ -104,24 +108,94 @@
- - + + - - + + - - + + - - + + - - + +
diff --git a/apps/web/src/components/docs/DocsButton.tsx b/apps/web/src/components/docs/DocsButton.tsx index 49a1db74787..837a7a5ffeb 100644 --- a/apps/web/src/components/docs/DocsButton.tsx +++ b/apps/web/src/components/docs/DocsButton.tsx @@ -36,7 +36,7 @@ const DefaultButton = ({ onClick }: { onClick: () => void }) => ( } onClick={onClick} diff --git a/apps/web/src/components/docs/Mdx.tsx b/apps/web/src/components/docs/Mdx.tsx index 8810f6f653a..2cec9b51ac5 100644 --- a/apps/web/src/components/docs/Mdx.tsx +++ b/apps/web/src/components/docs/Mdx.tsx @@ -302,7 +302,7 @@ export const Mdx = ({ code = '', mappings = {}, isChildDocs, children, isLoading listStyleType: 'decimal', listStylePosition: 'inside', '& p': { - display: 'inline !important', + display: '!important inline', }, })} {...props} @@ -317,7 +317,7 @@ export const Mdx = ({ code = '', mappings = {}, isChildDocs, children, isLoading listStyleType: 'disc', listStylePosition: 'inside', '& p': { - display: 'inline !important', + display: '!important inline', }, })} {...props} diff --git a/apps/web/src/components/nav/RootNavMenuFooter.tsx b/apps/web/src/components/nav/RootNavMenuFooter.tsx index ef869337fcd..d635525d9c8 100644 --- a/apps/web/src/components/nav/RootNavMenuFooter.tsx +++ b/apps/web/src/components/nav/RootNavMenuFooter.tsx @@ -9,7 +9,7 @@ export const RootNavMenuFooter: React.FC = () => { className={cx( hstack(), css({ - display: 'flex !important', + display: '!important flex', justifyContent: 'space-between', pt: '100', }) diff --git a/apps/web/src/pages/templates/components/CustomCodeEditor.css b/apps/web/src/pages/templates/components/CustomCodeEditor.css index d1d63267e89..e5afb986394 100644 --- a/apps/web/src/pages/templates/components/CustomCodeEditor.css +++ b/apps/web/src/pages/templates/components/CustomCodeEditor.css @@ -41,10 +41,7 @@ color: #fff !important; } - -.custom-code-editor - .monaco-editor - .overflow-guard { +.custom-code-editor .monaco-editor .overflow-guard { border-radius: 10px !important; } diff --git a/apps/web/src/stories/Introduction.stories.mdx b/apps/web/src/stories/Introduction.stories.mdx index a95c3c38220..4363e196737 100644 --- a/apps/web/src/stories/Introduction.stories.mdx +++ b/apps/web/src/stories/Introduction.stories.mdx @@ -128,33 +128,21 @@ We recommend building UIs with a [**component-driven**](https://componentdriven.
Configure
- TipEdit the Markdown in{' '} - src/stories/Introduction.stories.mdx + TipEdit the Markdown in src/stories/Introduction.stories.mdx
diff --git a/apps/web/src/studio/components/GetStartedPageV2/index.tsx b/apps/web/src/studio/components/GetStartedPageV2/index.tsx index 714267accb0..e55d5d99c45 100644 --- a/apps/web/src/studio/components/GetStartedPageV2/index.tsx +++ b/apps/web/src/studio/components/GetStartedPageV2/index.tsx @@ -174,7 +174,7 @@ export const GetStartedPageV2 = ({ location }: { location: 'onboarding' | 'get-s border: 'none !important', padding: '1px', borderRadius: '100', - boxShadow: 'dark !important', + boxShadow: '!important dark', })} onDoubleClick={() => { track('Command copied - [Get Started - V2]'); diff --git a/apps/widget/README.md b/apps/widget/README.md index 9516c111986..c60613a517f 100644 --- a/apps/widget/README.md +++ b/apps/widget/README.md @@ -1,9 +1,9 @@ # Widget - ## How to run e2e test in local? Run `npm run start:test` script in the following apps on separate terminals: + 1. apps/api 2. apps/ws 3. apps/widget diff --git a/apps/widget/config-overrides.js b/apps/widget/config-overrides.js index 404a228034a..1db88e6c840 100644 --- a/apps/widget/config-overrides.js +++ b/apps/widget/config-overrides.js @@ -2,8 +2,8 @@ const { useBabelRc, override } = require('customize-cra'); // const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; function overrideConfig(config, env) { - const plugins = [...config.plugins, /* new BundleAnalyzerPlugin() */]; - + const plugins = [...config.plugins /* new BundleAnalyzerPlugin() */]; + return { ...config, plugins }; } diff --git a/apps/widget/cypress/test-shell/example/test.html b/apps/widget/cypress/test-shell/example/test.html index 8b92cf1b1dc..c49c361a16d 100644 --- a/apps/widget/cypress/test-shell/example/test.html +++ b/apps/widget/cypress/test-shell/example/test.html @@ -1,10 +1,10 @@ - - - - - Title - - -This is a test page - + + + + + Title + + + This is a test page + diff --git a/apps/widget/cypress/test-shell/index.html b/apps/widget/cypress/test-shell/index.html index f21a0ca1126..b58c9ec8726 100644 --- a/apps/widget/cypress/test-shell/index.html +++ b/apps/widget/cypress/test-shell/index.html @@ -1,81 +1,115 @@ - - Getting Started - - - - - - - - -
- - Settings - - Sign - out +
+
+

Dashboard

-
+ +
+
+ +
+
+
+ +
+
- -
-
-

- Dashboard -

-
-
-
-
- -
-
-
- -
-
- - - - - + + diff --git a/apps/widget/index.html b/apps/widget/index.html index 7a617d81528..2f7d9e9f605 100644 --- a/apps/widget/index.html +++ b/apps/widget/index.html @@ -24,8 +24,8 @@
-
+

Dashboard

-
+
-
+
diff --git a/apps/widget/public/index.html b/apps/widget/public/index.html index 910c85e4792..e1d3e55cb13 100644 --- a/apps/widget/public/index.html +++ b/apps/widget/public/index.html @@ -1,19 +1,18 @@ - + - - - - - - - - - - - - React App - - + React App + + - - -
- - - - - \ No newline at end of file + + + diff --git a/apps/worker/README.md b/apps/worker/README.md index 18d4fc94215..04e006db03c 100644 --- a/apps/worker/README.md +++ b/apps/worker/README.md @@ -6,6 +6,7 @@ [travis-url]: https://travis-ci.org/nestjs/nest [linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux [linux-url]: https://travis-ci.org/nestjs/nest +

A progressive Node.js framework for building efficient and scalable server-side applications, heavily inspired by Angular.

NPM Version diff --git a/docker/community/docker-compose.yml b/docker/community/docker-compose.yml index 24377a78043..b15831ec23e 100644 --- a/docker/community/docker-compose.yml +++ b/docker/community/docker-compose.yml @@ -173,9 +173,9 @@ services: REACT_APP_WS_URL: ${REACT_APP_WS_URL} ports: - 4200:4200 - command: ["/bin/sh", "-c", "pnpm run envsetup:docker && pnpm run start:static:build"] + command: ['/bin/sh', '-c', 'pnpm run envsetup:docker && pnpm run start:static:build'] healthcheck: - test: ['CMD-SHELL', 'curl --silent --fail http://localhost:4200 || exit 1'] + test: ['CMD-SHELL', 'curl --silent --fail http://localhost:4200 || exit 1'] interval: 30s timeout: 10s retries: 3 diff --git a/docker/local/docker-compose.e2e.yml b/docker/local/docker-compose.e2e.yml index 5270656dbd9..313d14a0152 100644 --- a/docker/local/docker-compose.e2e.yml +++ b/docker/local/docker-compose.e2e.yml @@ -2,16 +2,16 @@ version: '3.1' services: localstack: - container_name: "${LOCALSTACK_DOCKER_NAME-localstack_main}" - image: "localstack/localstack:0.14.5" + container_name: '${LOCALSTACK_DOCKER_NAME-localstack_main}' + image: 'localstack/localstack:0.14.5' network_mode: bridge environment: - SERVICES=s3 ports: - - "${DOCKER_LOCALSTACK_PORT:-4566}:4566" + - '${DOCKER_LOCALSTACK_PORT:-4566}:4566' volumes: - - "${TMPDIR:-/tmp/localstack}:/tmp/localstack" - - "/var/run/docker.sock:/var/run/docker.sock" + - '${TMPDIR:-/tmp/localstack}:/tmp/localstack' + - '/var/run/docker.sock:/var/run/docker.sock' healthcheck: test: "bash -c 'AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test aws --endpoint-url=http://127.0.0.1:4566 s3 ls'" retries: 5 diff --git a/docker/local/docker-compose.local.yml b/docker/local/docker-compose.local.yml index e2c6aa7667a..cc37db1bb77 100644 --- a/docker/local/docker-compose.local.yml +++ b/docker/local/docker-compose.local.yml @@ -1,26 +1,25 @@ - services: api: build: - dockerfile: "./apps/api/Dockerfile" - context: "../../.." + dockerfile: './apps/api/Dockerfile' + context: '../../..' worker: build: - dockerfile: "./apps/worker/Dockerfile" - context: "../../.." + dockerfile: './apps/worker/Dockerfile' + context: '../../..' web: build: - dockerfile: "./apps/web/Dockerfile" - context: "../../.." + dockerfile: './apps/web/Dockerfile' + context: '../../..' ws: build: - dockerfile: "./apps/ws/Dockerfile" - context: "../../.." + dockerfile: './apps/ws/Dockerfile' + context: '../../..' widget: build: - dockerfile: "./apps/widget/Dockerfile" - context: "../../.." + dockerfile: './apps/widget/Dockerfile' + context: '../../..' embed: build: - dockerfile: "./libs/embed/Dockerfile" - context: "../../.." + dockerfile: './libs/embed/Dockerfile' + context: '../../..' diff --git a/docker/local/docker-compose.yml b/docker/local/docker-compose.yml index 1465a9c1ec5..b8027216012 100644 --- a/docker/local/docker-compose.yml +++ b/docker/local/docker-compose.yml @@ -1,37 +1,37 @@ services: localstack: - container_name: "${LOCALSTACK_DOCKER_NAME-localstack_main}" - image: "localstack/localstack:0.14.5" + container_name: '${LOCALSTACK_DOCKER_NAME-localstack_main}' + image: 'localstack/localstack:0.14.5' network_mode: bridge environment: - SERVICES=s3 ports: - - "${DOCKER_LOCALSTACK_PORT:-4566}:4566" + - '${DOCKER_LOCALSTACK_PORT:-4566}:4566' volumes: - - "${TMPDIR:-/tmp/localstack}:/tmp/localstack" - - "/var/run/docker.sock:/var/run/docker.sock" + - '${TMPDIR:-/tmp/localstack}:/tmp/localstack' + - '/var/run/docker.sock:/var/run/docker.sock' healthcheck: test: "bash -c 'AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test aws --endpoint-url=http://127.0.0.1:4566 s3 ls'" retries: 5 interval: 10s mongo: - container_name: "${MONGO_DOCKER_NAME-mongo_main}" + container_name: '${MONGO_DOCKER_NAME-mongo_main}' image: mongo network_mode: bridge ports: - - "${DOCKER_MONGO_PORT:-27017}:27017" + - '${DOCKER_MONGO_PORT:-27017}:27017' volumes: - - "${TMPDIR:-/tmp/mongo}:/db/data" + - '${TMPDIR:-/tmp/mongo}:/db/data' healthcheck: - test: "bash -c 'mongo --host 127.0.0.1:27017 --eval \"printjson(rs.status())\"'" + test: 'bash -c ''mongo --host 127.0.0.1:27017 --eval "printjson(rs.status())"''' retries: 5 interval: 10s redis: - container_name: "${REDIS_DOCKER_NAME-redis_main}" + container_name: '${REDIS_DOCKER_NAME-redis_main}' image: redis network_mode: bridge ports: - - "${DOCKER_REDIS_SERVICE_PORT:-6379}:6379" + - '${DOCKER_REDIS_SERVICE_PORT:-6379}:6379' healthcheck: test: "bash -c 'redis-cli ping'" retries: 5 @@ -39,6 +39,6 @@ services: pyroscope: image: grafana/pyroscope:latest ports: - - "4040:4040" + - '4040:4040' profiles: - optional diff --git a/enterprise/packages/dal/tsconfig.build.json b/enterprise/packages/dal/tsconfig.build.json index 6ef5124af0b..d4f964ab3ba 100644 --- a/enterprise/packages/dal/tsconfig.build.json +++ b/enterprise/packages/dal/tsconfig.build.json @@ -8,11 +8,7 @@ "esModuleInterop": false, "outDir": "./dist", "rootDir": "./src", - "types": [ - "node" - ] + "types": ["node"] }, - "include": [ - "src/**/*" - ] + "include": ["src/**/*"] } diff --git a/enterprise/packages/shared-services/tsconfig.json b/enterprise/packages/shared-services/tsconfig.json index baba9a9e4c0..1605d2a7119 100644 --- a/enterprise/packages/shared-services/tsconfig.json +++ b/enterprise/packages/shared-services/tsconfig.json @@ -9,7 +9,7 @@ "esModuleInterop": true, "rootDir": "src", "strict": true, - "types": ["node", "jest"], + "types": ["node", "jest"] }, "include": ["src/**/*.ts"], "exclude": ["node_modules/**"] diff --git a/eslint.config.mjs b/eslint.config.mjs index 56a09a4b1ef..6cd21b98a3b 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -46,7 +46,8 @@ const noRestrictedImportsMultiLevelNovuPattern = { // This flatMap logic ignores the path 1 below the root level and prevents deeper imports. ...['framework', 'js', 'novui'].flatMap((pkg) => [`!@novu/${pkg}/**/*`, `@novu/${pkg}/*/**/*`]), ], - message: "Please import only from the root package entry point. For example, use 'import { Client } from '@novu/node';' instead of 'import { Client } from '@novu/node/src';'", + message: + "Please import only from the root package entry point. For example, use 'import { Client } from '@novu/node';' instead of 'import { Client } from '@novu/node/src';'", }; export default tsEslint.config( @@ -116,8 +117,8 @@ export default tsEslint.config( 'unused-imports/no-unused-imports': 'off', '@typescript-eslint/space-before-blocks': 'off', '@typescript-eslint/lines-between-class-members': 'off', - "@typescript-eslint/no-throw-literal": "off", - "@typescript-eslint/only-throw-error": "error", + '@typescript-eslint/no-throw-literal': 'off', + '@typescript-eslint/only-throw-error': 'error', 'react/jsx-wrap-multilines': 'off', 'react/jsx-filename-extension': 'off', 'multiline-comment-style': ['warn', 'starred-block'], @@ -174,9 +175,7 @@ export default tsEslint.config( 'no-restricted-imports': [ 'error', { - patterns: [ - noRestrictedImportsMultiLevelNovuPattern, - ], + patterns: [noRestrictedImportsMultiLevelNovuPattern], }, ], diff --git a/jest.config.js b/jest.config.js index a93551fca25..4a5b465ecb5 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,4 +1,4 @@ module.exports = { - preset: "ts-jest", - testEnvironment: "node", + preset: 'ts-jest', + testEnvironment: 'node', }; diff --git a/libs/application-generic/README.md b/libs/application-generic/README.md index abf86657ed8..3da45db8282 100644 --- a/libs/application-generic/README.md +++ b/libs/application-generic/README.md @@ -1,4 +1,3 @@ # Application generic Generic backend code used inside of Novu's different services - diff --git a/libs/application-generic/src/utils/deepmerge.ts b/libs/application-generic/src/utils/deepmerge.ts index 88c7f03ceea..f6a0ecc7c6f 100644 --- a/libs/application-generic/src/utils/deepmerge.ts +++ b/libs/application-generic/src/utils/deepmerge.ts @@ -24,7 +24,7 @@ function emptyTarget(val: unknown) { function cloneUnlessOtherwiseSpecified( value: Record, - options: IOptions + options: IOptions, ): Record | Record[] { return options.clone !== false && options.isMergeableObject(value) ? deepMergeObjects(emptyTarget(value), value, options) @@ -34,13 +34,13 @@ function cloneUnlessOtherwiseSpecified( function defaultArrayMerge( target: Record[], source: Record[], - options: IOptions + options: IOptions, ): Record[] { return target.concat(source).map(function (element) { - return cloneUnlessOtherwiseSpecified( - element, - options - ) as Record; + return cloneUnlessOtherwiseSpecified(element, options) as Record< + string, + unknown + >; }); } @@ -79,7 +79,7 @@ function propertyIsUnsafe(target: Record, key: string) { function mergeObject( target: Record, source: Record, - options: IOptions + options: IOptions, ): Record { const destination = {}; if (options.isMergeableObject(target)) { @@ -88,7 +88,7 @@ function mergeObject( getKeys(target).forEach((key: string) => { destination[key] = cloneUnlessOtherwiseSpecified( target[key] as Record, - options + options, ); }); } @@ -106,12 +106,12 @@ function mergeObject( destination[key] = getMergeFunction(key as string, options)( target[key] as Record, source[key] as Record, - options + options, ); } else { destination[key] = cloneUnlessOtherwiseSpecified( source[key] as Record, - options + options, ); } }); @@ -121,42 +121,42 @@ function mergeObject( interface IOptions { customMerge: ( - key: string + key: string, ) => ( target: Record, source: Record, - options: IOptions + options: IOptions, ) => Record; arrayMerge: ( target: Record[], source: Record[], - options: IOptions + options: IOptions, ) => Record[]; isMergeableObject: (value: unknown) => boolean; cloneUnlessOtherwiseSpecified: ( value: Record, - options: IOptions + options: IOptions, ) => Record | Record[]; clone?: boolean; } interface IDeepMergeOptions { customMerge?: ( - key: string + key: string, ) => ( target: Record, source: Record, - options: IOptions + options: IOptions, ) => Record; arrayMerge?: ( target: Record[], source: Record[], - options: IOptions + options: IOptions, ) => Record[]; isMergeableObject?: (value: unknown) => boolean; cloneUnlessOtherwiseSpecified?: ( value: Record, - options: IOptions + options: IOptions, ) => Record | Record[]; clone?: boolean; } @@ -170,11 +170,11 @@ interface IDeepMergeOptions { * @returns The merged object or array of objects. */ function deepMergeObjects< - T extends Record | Record[] + T extends Record | Record[], >( target: Record | Record[], source: Record | Record[], - options?: IDeepMergeOptions + options?: IDeepMergeOptions, ): T { options = options || {}; options.arrayMerge = options.arrayMerge || defaultArrayMerge; @@ -192,21 +192,21 @@ function deepMergeObjects< if (!sourceAndTargetTypesMatch) { return cloneUnlessOtherwiseSpecified( source as Record, - options as IOptions + options as IOptions, ) as T; } if (sourceIsArray) { return options.arrayMerge( target as Record[], source as Record[], - options as IOptions + options as IOptions, ) as T; } return mergeObject( target as Record, source, - options as IOptions + options as IOptions, ) as T; } @@ -220,7 +220,7 @@ function deepMergeObjects< */ export function deepMerge>( array: T[], - options?: IDeepMergeOptions + options?: IDeepMergeOptions, ): T { if (!Array.isArray(array)) { throw new Error('first argument should be an array'); diff --git a/libs/automation/nx.json b/libs/automation/nx.json index 832046d4958..a2b00adfb4e 100644 --- a/libs/automation/nx.json +++ b/libs/automation/nx.json @@ -26,12 +26,10 @@ }, "targetDefaults": { "@nx/js:tsc": { - "cache": true, "dependsOn": ["^build"], "inputs": ["production", "^production"] }, "@nx/eslint:lint": { - "cache": true, "inputs": [ "default", "{workspaceRoot}/.eslintrc.json", @@ -40,7 +38,6 @@ ] }, "@nx/jest:jest": { - "cache": true, "inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"], "options": { "passWithNoTests": true diff --git a/libs/design-system/.storybook/Doc.container.tsx b/libs/design-system/.storybook/Doc.container.tsx index ae81e24715f..9a13aed2981 100644 --- a/libs/design-system/.storybook/Doc.container.tsx +++ b/libs/design-system/.storybook/Doc.container.tsx @@ -22,7 +22,8 @@ export const DocsContainer = ({ children, context }) => { }, }; }, - }}> + }} + > {children} ); diff --git a/libs/design-system/.storybook/NovuTheme.tsx b/libs/design-system/.storybook/NovuTheme.tsx index d8f509b6114..86a0b5aa71a 100644 --- a/libs/design-system/.storybook/NovuTheme.tsx +++ b/libs/design-system/.storybook/NovuTheme.tsx @@ -5,10 +5,10 @@ const themeBase: ThemeVarsPartial = { base: 'light', brandTitle: 'Novu Design System', brandTarget: '_self', -} +}; /** * Novu Design System theme for Storybook - * + * * @see https://storybook.js.org/docs/configure/theming */ export const lightTheme = create({ diff --git a/libs/design-system/.storybook/manager-head.html b/libs/design-system/.storybook/manager-head.html index 62499dd0581..fed14ea70bf 100644 --- a/libs/design-system/.storybook/manager-head.html +++ b/libs/design-system/.storybook/manager-head.html @@ -1 +1 @@ - + diff --git a/libs/design-system/src/Colors.stories.mdx b/libs/design-system/src/Colors.stories.mdx index ef039a7dea6..791bde7c5f1 100644 --- a/libs/design-system/src/Colors.stories.mdx +++ b/libs/design-system/src/Colors.stories.mdx @@ -1,4 +1,4 @@ -import { Meta, ColorPalette, ColorItem, } from '@storybook/addon-docs'; +import { Meta, ColorPalette, ColorItem } from '@storybook/addon-docs'; import { colors } from './config'; @@ -8,6 +8,28 @@ import { colors } from './config'; - - + + diff --git a/libs/design-system/src/icons/gradient/BellGradient.tsx b/libs/design-system/src/icons/gradient/BellGradient.tsx index 4d21f74338e..e515417ee30 100644 --- a/libs/design-system/src/icons/gradient/BellGradient.tsx +++ b/libs/design-system/src/icons/gradient/BellGradient.tsx @@ -17,7 +17,8 @@ export function BellGradient(props: React.ComponentPropsWithoutRef<'svg'>) { y1="26.4965" x2="15" y2="4.5" - gradientUnits="userSpaceOnUse"> + gradientUnits="userSpaceOnUse" + > diff --git a/libs/design-system/src/icons/gradient/CompassGradient.tsx b/libs/design-system/src/icons/gradient/CompassGradient.tsx index bc53cc30aad..c3b0708e660 100644 --- a/libs/design-system/src/icons/gradient/CompassGradient.tsx +++ b/libs/design-system/src/icons/gradient/CompassGradient.tsx @@ -28,7 +28,8 @@ export function CompassGradient(props: React.ComponentPropsWithoutRef<'svg'>) { y1="20.7999" x2="15.2502" y2="10.2" - gradientUnits="userSpaceOnUse"> + gradientUnits="userSpaceOnUse" + > diff --git a/libs/design-system/src/icons/gradient/GlobeGradient.tsx b/libs/design-system/src/icons/gradient/GlobeGradient.tsx index 6b24967e615..8cfcbd8498b 100644 --- a/libs/design-system/src/icons/gradient/GlobeGradient.tsx +++ b/libs/design-system/src/icons/gradient/GlobeGradient.tsx @@ -35,7 +35,8 @@ export function GlobeGradient(props: React.ComponentPropsWithoutRef<'svg'>) { y1="16.5" x2="15.75" y2="15.5" - gradientUnits="userSpaceOnUse"> + gradientUnits="userSpaceOnUse" + > diff --git a/libs/embed/src/embed.ts b/libs/embed/src/embed.ts index 789ee484437..da18c90171f 100644 --- a/libs/embed/src/embed.ts +++ b/libs/embed/src/embed.ts @@ -363,9 +363,8 @@ class Novu { wrapper.className = 'wrapper-novu-widget'; wrapper.style.display = 'none'; wrapper.id = WEASL_WRAPPER_ID; - ( - wrapper as any - ).style = `z-index: ${Number.MAX_SAFE_INTEGER}; width: 0; height: 0; position: relative; display: none;`; + (wrapper as any).style = + `z-index: ${Number.MAX_SAFE_INTEGER}; width: 0; height: 0; position: relative; display: none;`; wrapper.appendChild(this.iframe); document.body.appendChild(wrapper); } diff --git a/libs/embed/src/shared/helpers.js b/libs/embed/src/shared/helpers.js index 052670231ba..4810b2b95b5 100644 --- a/libs/embed/src/shared/helpers.js +++ b/libs/embed/src/shared/helpers.js @@ -1,8 +1,7 @@ const COOKIE_NAME = 'WEASL_AUTH'; - export const expireToken = (clientId) => { - document.cookie = `${COOKIE_NAME}-${clientId}=;expires=${(new Date()).toUTCString()};`; + document.cookie = `${COOKIE_NAME}-${clientId}=;expires=${new Date().toUTCString()};`; }; export const isMobile = () => window.innerWidth < 600; @@ -10,14 +9,14 @@ export const isTablet = () => window.innerWidth > 600 && window.innerWidth < 768 export const isDesktop = () => window.innerWidth > 768; export const isPortraitMode = () => window.innerHeight > window.innerWidth; -export const allowedAttrTypes = ['STRING', 'NUMBER', 'BOOLEAN', 'JSON'] +export const allowedAttrTypes = ['STRING', 'NUMBER', 'BOOLEAN', 'JSON']; // TODO: use a library for this export const makeDomainMatcher = (actualDomain) => { - const [ actualHost, actualPort ] = actualDomain.split(':'); + const [actualHost, actualPort] = actualDomain.split(':'); const actualDomainParts = actualHost.split('.'); return (allowedDomain) => { - const [ allowedHost, allowedPort ] = allowedDomain.split(':'); + const [allowedHost, allowedPort] = allowedDomain.split(':'); // check the ports first if both are there if (allowedPort && actualPort && allowedPort !== actualPort) { @@ -25,7 +24,12 @@ export const makeDomainMatcher = (actualDomain) => { } const allowedDomainParts = allowedHost.split('.'); - const matched = allowedDomainParts.length && allowedDomainParts.reduceRight((matchedSoFar, part, index) => matchedSoFar && part === actualDomainParts[index], true); + const matched = + allowedDomainParts.length && + allowedDomainParts.reduceRight( + (matchedSoFar, part, index) => matchedSoFar && part === actualDomainParts[index], + true + ); return matched; - } -} \ No newline at end of file + }; +}; diff --git a/libs/embed/src/shared/iframeClasses.js b/libs/embed/src/shared/iframeClasses.js index 947995719a7..7241787160e 100644 --- a/libs/embed/src/shared/iframeClasses.js +++ b/libs/embed/src/shared/iframeClasses.js @@ -1,2 +1,2 @@ export const TAKEOVER_CLASSNAME = 'weasl-iframe-takeover'; -export const INFO_MSG_CLASSNAME = 'weasl-iframe-info-msg'; \ No newline at end of file +export const INFO_MSG_CLASSNAME = 'weasl-iframe-info-msg'; diff --git a/libs/embed/test/index.html b/libs/embed/test/index.html index c88c4fe9b17..bfc04c67bd1 100644 --- a/libs/embed/test/index.html +++ b/libs/embed/test/index.html @@ -21,12 +21,12 @@ } - +

-
-

- Dashboard -

+
+

Dashboard

-
+
-
+
@@ -272,12 +270,12 @@

`; - client.addWorkflows([ + await client.addWorkflows([ workflow('test-workflow', async ({ step }) => { await step.email('send-email', async () => ({ body: `Start of body. ${script}`, @@ -409,7 +409,7 @@ describe('Novu Client', () => { it('should not sanitize the step result of custom step type', async () => { const script = ``; - client.addWorkflows([ + await client.addWorkflows([ workflow('test-workflow', async ({ step }) => { await step.custom( 'send-email', @@ -468,7 +468,7 @@ describe('Novu Client', () => { controls: {}, }; - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const emailExecutionResult = await client.executeWorkflow(emailEvent); @@ -564,7 +564,7 @@ describe('Novu Client', () => { } ); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const emailEvent: Event = { action: PostActionEnum.EXECUTE, @@ -633,7 +633,7 @@ describe('Novu Client', () => { } ); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.EXECUTE, @@ -699,7 +699,7 @@ describe('Novu Client', () => { } ); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.EXECUTE, @@ -762,7 +762,7 @@ describe('Novu Client', () => { } ); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.EXECUTE, @@ -825,7 +825,7 @@ describe('Novu Client', () => { } ); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.EXECUTE, @@ -888,7 +888,7 @@ describe('Novu Client', () => { } ); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.EXECUTE, @@ -935,7 +935,7 @@ describe('Novu Client', () => { ); }); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.EXECUTE, @@ -981,7 +981,7 @@ describe('Novu Client', () => { ); }); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const emailEvent: Event = { action: PostActionEnum.EXECUTE, @@ -1030,7 +1030,7 @@ describe('Novu Client', () => { ); }); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const emailEvent: Event = { action: PostActionEnum.EXECUTE, @@ -1061,7 +1061,7 @@ describe('Novu Client', () => { await step.email('send-email', async () => ({ body: 'Test Body', subject: 'Subject' })); }); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.EXECUTE, @@ -1100,7 +1100,7 @@ describe('Novu Client', () => { }); }); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.EXECUTE, @@ -1153,7 +1153,7 @@ describe('Novu Client', () => { }); }); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.EXECUTE, @@ -1207,7 +1207,7 @@ describe('Novu Client', () => { }); }); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.EXECUTE, @@ -1249,7 +1249,7 @@ describe('Novu Client', () => { await step.email('inactive-step-id', async () => ({ body: 'Test Body', subject: 'Subject' })); }); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.EXECUTE, @@ -1277,7 +1277,7 @@ describe('Novu Client', () => { }); }); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.EXECUTE, @@ -1306,7 +1306,7 @@ describe('Novu Client', () => { }); }); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.EXECUTE, @@ -1344,7 +1344,7 @@ describe('Novu Client', () => { }); }); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.EXECUTE, @@ -1386,7 +1386,7 @@ describe('Novu Client', () => { } ); - client.addWorkflows([workflowMock]); + await client.addWorkflows([workflowMock]); const event: Event = { action: PostActionEnum.PREVIEW, @@ -1410,7 +1410,7 @@ describe('Novu Client', () => { await step.email('send-email', async () => ({ body: 'Test Body', subject: 'Subject' })); }); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.PREVIEW, @@ -1469,7 +1469,7 @@ describe('Novu Client', () => { await step.inApp('send-in-app', async () => ({ body: 'Test Body', subject: 'Subject' })); }); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.PREVIEW, @@ -1508,7 +1508,7 @@ describe('Novu Client', () => { }); }); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.PREVIEW, @@ -1571,7 +1571,7 @@ describe('Novu Client', () => { } ); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.PREVIEW, @@ -1656,7 +1656,7 @@ describe('Novu Client', () => { } ); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.PREVIEW, @@ -1713,7 +1713,7 @@ describe('Novu Client', () => { await step.email('send-email', async () => ({ body: 'Test Body', subject: 'Subject' })); }); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); // @ts-expect-error - no workflow id const event2: Event = { @@ -1730,7 +1730,7 @@ describe('Novu Client', () => { await step.email('send-email', async () => ({ body: 'Test Body', subject: 'Subject' })); }); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.EXECUTE, @@ -1750,7 +1750,7 @@ describe('Novu Client', () => { await step.email('send-email', async () => ({ body: 'Test Body', subject: 'Subject' })); }); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); // @ts-expect-error - no action const event: Event = { @@ -1771,7 +1771,7 @@ describe('Novu Client', () => { }); }); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.EXECUTE, @@ -1808,7 +1808,7 @@ describe('Novu Client', () => { ); }); - client.addWorkflows([newWorkflow]); + await client.addWorkflows([newWorkflow]); const event: Event = { action: PostActionEnum.EXECUTE, @@ -1828,7 +1828,7 @@ describe('Novu Client', () => { it('should sanitize the step output of all channel step types by default', async () => { const script = ``; - client.addWorkflows([ + await client.addWorkflows([ workflow('test-workflow', async ({ step }) => { await step.email('send-email', async () => ({ body: `Start of body. ${script}`, @@ -1856,7 +1856,7 @@ describe('Novu Client', () => { it('should sanitize the step output of channel step types when `disableOutputSanitization: false`', async () => { const script = ``; - client.addWorkflows([ + await client.addWorkflows([ workflow('test-workflow', async ({ step }) => { await step.email( 'send-email', @@ -1891,7 +1891,7 @@ describe('Novu Client', () => { const link = '/pipeline/Oee4d54-ca52-4d70-86b3-cd10a67b6810/requirements?requirementId=dc25a578-ecf1-4835-9310-2236f8244bd&commentId=e259b16b-68f9-43af-b252-fce68bc7cb2f'; - client.addWorkflows([ + await client.addWorkflows([ workflow('test-workflow', async ({ step }) => { await step.inApp( 'send-inapp', @@ -1927,7 +1927,7 @@ describe('Novu Client', () => { it('should not sanitize the step result of custom step type', async () => { const script = `