Skip to content

Commit

Permalink
Merge branch 'next' into remove-framework-node-builtins
Browse files Browse the repository at this point in the history
  • Loading branch information
rifont authored Nov 8, 2024
2 parents 7407100 + c02e1b2 commit 52cc1ab
Show file tree
Hide file tree
Showing 14 changed files with 128 additions and 129 deletions.
22 changes: 13 additions & 9 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"adresses",
"africas",
"africastalking",
"Aland",
"alanturing",
"alexjoverm",
"alist",
Expand Down Expand Up @@ -68,6 +69,7 @@
"buildscript",
"buildx",
"bullmq",
"Burkina",
"bzrignore",
"cacheable",
"cafebabe",
Expand All @@ -92,6 +94,7 @@
"Clicksend",
"clonedeep",
"clsx",
"cmdk",
"cnamek",
"cnames",
"codecov",
Expand Down Expand Up @@ -188,6 +191,7 @@
"exponentiate",
"externaldb",
"externalredis",
"Faso",
"Fdfdf",
"fieldname",
"fieldtype",
Expand Down Expand Up @@ -274,6 +278,7 @@
"kannel",
"kebabcase",
"keybase",
"Keymap",
"keyrings",
"keysize",
"kitterma",
Expand All @@ -287,6 +292,7 @@
"lastindex",
"Lato",
"Lentczner",
"lezer"
"libarary",
"libauth",
"libspf",
Expand Down Expand Up @@ -342,14 +348,15 @@
"mlen",
"mobishastra",
"Mobishastra",
"Mobishatra",
"moby",
"Modiin",
"modlen",
"Mobishatra",
"mongod",
"mongosh",
"monokai",
"monorepository",
"motionone",
"mpeltonen",
"mpim",
"MPIMs",
Expand Down Expand Up @@ -521,6 +528,7 @@
"RETRYABLE",
"revlookup",
"revlookupall",
"Rica",
"righthand",
"rimraf",
"ringcentral",
Expand Down Expand Up @@ -567,6 +575,8 @@
"softfail",
"softwareupdate",
"sonarjs",
"sonner",
"Sonner",
"sortlist",
"sourcemaps",
"spamassassin",
Expand Down Expand Up @@ -603,6 +613,7 @@
"supernet",
"supertest",
"suported",
"Syncable",
"tabnannied",
"tailwindcss",
"tanstack",
Expand Down Expand Up @@ -685,16 +696,9 @@
"whatsappbusiness",
"xcodebuild",
"xkeysib",
"xyflow",
"zulip",
"zwnj",
"motionone",
"xyflow",
"Sonner",
"sonner",
"cmdk",
"Keymap",
"Syncable",
"lezer"
],
"flagWords": [],
"patterns": [
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/dev-deploy-webhook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ env:
jobs:
test_webhook:
uses: ./.github/workflows/reusable-webhook-e2e.yml
secrets: inherit

publish_docker_image_webhook:
if: "!contains(github.event.head_commit.message, 'ci skip')"
Expand Down
2 changes: 2 additions & 0 deletions apps/api/src/app/events/e2e/bridge-trigger.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1427,6 +1427,8 @@ describe('Novu-Hosted Bridge Trigger', () => {

it('should execute a Novu-managed workflow', async () => {
const createWorkflowDto: CreateWorkflowDto = {
tags: [],
active: true,
name: 'Test Workflow',
description: 'Test Workflow',
__source: WorkflowCreationSourceEnum.DASHBOARD,
Expand Down
14 changes: 2 additions & 12 deletions apps/api/src/app/subscribers/e2e/remove-subscriber.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,8 @@ describe('Delete Subscriber - /subscribers/:subscriberId (DELETE)', function ()
},
});

const isDeleted = !(await subscriberRepository.findBySubscriberId(session.environment._id, '123'));

expect(isDeleted).to.equal(true);

const deletedSubscriber = (
await subscriberRepository.findDeleted({
_environmentId: session.environment._id,
subscriberId: '123',
})
)?.[0];

expect(deletedSubscriber.deleted).to.equal(true);
const subscriber = await subscriberRepository.findBySubscriberId(session.environment._id, '123');
expect(subscriber).to.be.null;
});

it('should dispose subscriber relations to topic once he was removed', async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { Test } from '@nestjs/testing';
import { SubscribersService, UserSession } from '@novu/testing';
import { NotFoundException } from '@nestjs/common';
import { expect } from 'chai';

import { NotFoundException } from '@nestjs/common';
import { SubscribersService, UserSession } from '@novu/testing';
import { Test } from '@nestjs/testing';
import { RemoveSubscriber } from './remove-subscriber.usecase';
import { RemoveSubscriberCommand } from './remove-subscriber.command';

import { SharedModule } from '../../../shared/shared.module';
import { SubscribersModule } from '../../subscribers.module';

Expand Down Expand Up @@ -41,8 +39,6 @@ describe('Remove Subscriber', function () {
});

it('should throw a not found exception if subscriber to remove does not exist', async () => {
const subscriberService = new SubscribersService(session.organization._id, session.environment._id);

try {
await useCase.execute(
RemoveSubscriberCommand.create({
Expand All @@ -51,10 +47,9 @@ describe('Remove Subscriber', function () {
organizationId: session.organization._id,
})
);
throw new Error('Should not reach here');
expect(true, 'Should never reach this statement').to.be.false;
} catch (e) {
expect(e).to.be.instanceOf(NotFoundException);
expect(e.message).to.eql("Subscriber 'invalid-subscriber-id' was not found");
}
});
});
Original file line number Diff line number Diff line change
@@ -1,53 +1,88 @@
import { Injectable } from '@nestjs/common';
import { SubscriberRepository, DalException, TopicSubscribersRepository } from '@novu/dal';
import { buildSubscriberKey, InvalidateCacheService } from '@novu/application-generic';
import { Injectable, NotFoundException } from '@nestjs/common';
import {
SubscriberRepository,
TopicSubscribersRepository,
SubscriberPreferenceRepository,
PreferencesRepository,
} from '@novu/dal';
import {
buildSubscriberKey,
buildFeedKey,
buildMessageCountKey,
InvalidateCacheService,
} from '@novu/application-generic';

import { RemoveSubscriberCommand } from './remove-subscriber.command';
import { GetSubscriber } from '../get-subscriber';
import { ApiException } from '../../../shared/exceptions/api.exception';

@Injectable()
export class RemoveSubscriber {
constructor(
private invalidateCache: InvalidateCacheService,
private subscriberRepository: SubscriberRepository,
private getSubscriber: GetSubscriber,
private topicSubscribersRepository: TopicSubscribersRepository
private topicSubscribersRepository: TopicSubscribersRepository,
private subscriberPreferenceRepository: SubscriberPreferenceRepository,
private preferenceRepository: PreferencesRepository
) {}

async execute(command: RemoveSubscriberCommand) {
try {
const { environmentId: _environmentId, organizationId, subscriberId } = command;
const subscriber = await this.getSubscriber.execute({
environmentId: _environmentId,
organizationId,
subscriberId,
});

await this.invalidateCache.invalidateByKey({
async execute({ environmentId: _environmentId, subscriberId }: RemoveSubscriberCommand) {
await Promise.all([
this.invalidateCache.invalidateByKey({
key: buildSubscriberKey({
subscriberId: command.subscriberId,
_environmentId: command.environmentId,
subscriberId,
_environmentId,
}),
});
}),
this.invalidateCache.invalidateQuery({
key: buildFeedKey().invalidate({
subscriberId,
_environmentId,
}),
}),
this.invalidateCache.invalidateQuery({
key: buildMessageCountKey().invalidate({
subscriberId,
_environmentId,
}),
}),
]);

const subscriberInternalIds = await this.subscriberRepository._model.distinct('_id', {
subscriberId,
_environmentId,
});

if (subscriberInternalIds.length === 0) {
throw new NotFoundException({ message: 'Subscriber was not found', externalSubscriberId: subscriberId });
}

await this.subscriberRepository.withTransaction(async () => {
/*
* Note about parallelism in transactions
*
* Running operations in parallel is not supported during a transaction.
* The use of Promise.all, Promise.allSettled, Promise.race, etc. to parallelize operations
* inside a transaction is undefined behaviour and should be avoided.
*
* Refer to https://mongoosejs.com/docs/transactions.html#note-about-parallelism-in-transactions
*/
await this.subscriberRepository.delete({
_environmentId: subscriber._environmentId,
_organizationId: subscriber._organizationId,
subscriberId: subscriber.subscriberId,
subscriberId,
_environmentId,
});

await this.topicSubscribersRepository.delete({
_environmentId: subscriber._environmentId,
_organizationId: subscriber._organizationId,
externalSubscriberId: subscriber.subscriberId,
_environmentId,
externalSubscriberId: subscriberId,
});
} catch (e) {
if (e instanceof DalException) {
throw new ApiException(e.message);
}
throw e;
}
await this.subscriberPreferenceRepository.delete({
_environmentId,
_subscriberId: { $in: subscriberInternalIds },
});
await this.preferenceRepository.delete({
_environmentId,
_subscriberId: { $in: subscriberInternalIds },
});
});

return {
acknowledged: true,
Expand Down
1 change: 1 addition & 0 deletions apps/api/src/app/workflows-v2/generate-preview.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ describe('Generate Preview', () => {
}
async function createWorkflowWithDigest() {
const createWorkflowDto: CreateWorkflowDto = {
tags: [],
__source: WorkflowCreationSourceEnum.EDITOR,
name: 'John',
workflowId: `john:${randomUUID()}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,18 +161,15 @@ export class UpsertWorkflowUseCase {
);
}

private async upsertUserWorkflowPreferences(
workflow: NotificationTemplateEntity,
command: UpsertWorkflowCommand
): Promise<PreferencesEntity> {
private async upsertUserWorkflowPreferences(workflow: NotificationTemplateEntity, command: UpsertWorkflowCommand) {
let preferences: WorkflowPreferences | null;
if (command.workflowDto.preferences?.user !== undefined) {
preferences = command.workflowDto.preferences.user;
} else {
preferences = DEFAULT_WORKFLOW_PREFERENCES;
}

return await this.upsertPreferencesUsecase.upsertUserWorkflowPreferences(
await this.upsertPreferencesUsecase.upsertUserWorkflowPreferences(
UpsertUserWorkflowPreferencesCommand.create({
environmentId: workflow._environmentId,
organizationId: workflow._organizationId,
Expand All @@ -183,11 +180,8 @@ export class UpsertWorkflowUseCase {
);
}

private async upsertWorkflowPreferences(
workflow: NotificationTemplateEntity,
command: UpsertWorkflowCommand
): Promise<PreferencesEntity> {
return await this.upsertPreferencesUsecase.upsertWorkflowPreferences(
private async upsertWorkflowPreferences(workflow: NotificationTemplateEntity, command: UpsertWorkflowCommand) {
await this.upsertPreferencesUsecase.upsertWorkflowPreferences(
UpsertWorkflowPreferencesCommand.create({
environmentId: workflow._environmentId,
organizationId: workflow._organizationId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ export const INBOX_TOKENS = {
'semantic/color/neutral/80': '#3D3D4D',
'semantic/color/neutral/90': '#292933',
'semantic/margins/buttons/S/S': '1rem',
'Inbox/whiteLable/buttons/accent/normal': '#369EFF',
'Inbox/whiteLable/secondaryButton': '#2E2E32',
'Inbox/whiteLable/devider': '#2E2E32',
'Inbox/whiteLabel/buttons/accent/normal': '#369EFF',
'Inbox/whiteLabel/secondaryButton': '#2E2E32',
'Inbox/whiteLabel/divider': '#2E2E32',
'Inbox/paddings/header/vertical': '1.25rem',
'Inbox/paddings/header/horizontal': '1.5rem',
'Inbox/paddings/message/horizontal': '1.5rem',
Expand Down Expand Up @@ -91,7 +91,7 @@ export function InboxPreviewContent({
<HStack
gap={28}
className={css({
borderColor: INBOX_TOKENS['Inbox/whiteLable/devider'],
borderColor: INBOX_TOKENS['Inbox/whiteLabel/divider'],
borderBottom: 'solid',
borderBottomWidth: '1',
alignSelf: 'stretch',
Expand Down Expand Up @@ -249,10 +249,10 @@ const actionButtonRecipe = cva({
variants: {
type: {
primary: {
bgColor: INBOX_TOKENS['Inbox/whiteLable/buttons/accent/normal'],
bgColor: INBOX_TOKENS['Inbox/whiteLabel/buttons/accent/normal'],
},
secondary: {
bgColor: INBOX_TOKENS['Inbox/whiteLable/secondaryButton'],
bgColor: INBOX_TOKENS['Inbox/whiteLabel/secondaryButton'],
},
},
},
Expand Down
Loading

0 comments on commit 52cc1ab

Please sign in to comment.