Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/next' into preview-usecase
Browse files Browse the repository at this point in the history
# Conflicts:
#	apps/api/package.json
#	apps/api/src/app/environments-v1/usecases/output-renderers/render-email-output.usecase.ts
#	apps/api/src/app/workflows-v2/shared/schemas/email-control.schema.ts
  • Loading branch information
djabarovgeorge committed Dec 16, 2024
2 parents 35e341b + 8f1070a commit 4c8b0e3
Show file tree
Hide file tree
Showing 74 changed files with 672 additions and 588 deletions.
4 changes: 2 additions & 2 deletions .idea/runConfigurations/API.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .source
8 changes: 4 additions & 4 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"dependencies": {
"@godaddy/terminus": "^4.12.1",
"@google-cloud/storage": "^6.2.3",
"@maily-to/render": "^0.0.12",
"@maily-to/render": "^0.0.15",
"@nestjs/axios": "3.0.3",
"@nestjs/common": "10.4.1",
"@nestjs/core": "10.4.1",
Expand All @@ -42,6 +42,7 @@
"@nestjs/swagger": "7.4.0",
"@nestjs/terminus": "10.2.3",
"@nestjs/throttler": "6.2.1",
"@novu/api": "0.0.1-alpha.109",
"@novu/application-generic": "workspace:*",
"@novu/dal": "workspace:*",
"@novu/framework": "workspace:*",
Expand All @@ -58,11 +59,9 @@
"@sentry/tracing": "^7.40.0",
"@types/newrelic": "^9.14.6",
"@upstash/ratelimit": "^0.4.4",
"@novu/api": "0.0.1-alpha.85",
"axios": "^1.6.8",
"ajv": "^8.12.0",
"ajv-formats": "^2.1.1",
"axios": "^1.6.8",
"liquidjs": "^10.14.0",
"bcrypt": "^5.0.0",
"body-parser": "^1.20.0",
"bull": "^4.2.1",
Expand All @@ -79,6 +78,7 @@
"ioredis": "5.3.2",
"json-schema-to-ts": "^3.0.0",
"jsonwebtoken": "9.0.0",
"liquidjs": "^10.14.0",
"lodash": "^4.17.15",
"nanoid": "^3.1.20",
"nest-raven": "10.1.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import {
UseInterceptors,
} from '@nestjs/common';
import { ApiAuthSchemeEnum, MemberRoleEnum, UserSessionData } from '@novu/shared';
import { ApiExcludeEndpoint, ApiOperation, ApiTags } from '@nestjs/swagger';
import { RolesGuard, Roles } from '@novu/application-generic';
import { ApiExcludeController, ApiExcludeEndpoint, ApiOperation, ApiTags } from '@nestjs/swagger';
import { Roles, RolesGuard } from '@novu/application-generic';
import { UserSession } from '../shared/framework/user.decorator';
import { CreateEnvironment } from './usecases/create-environment/create-environment.usecase';
import { CreateEnvironmentCommand } from './usecases/create-environment/create-environment.command';
Expand Down Expand Up @@ -40,6 +40,7 @@ import { SdkGroupName } from '../shared/framework/swagger/sdk.decorators';
@UseInterceptors(ClassSerializerInterceptor)
@UserAuthentication()
@ApiTags('Environments')
@ApiExcludeController()
export class EnvironmentsControllerV1 {
constructor(
private createEnvironmentUsecase: CreateEnvironment,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import { EmailRenderOutput, TipTapNode } from '@novu/shared';
import { Injectable } from '@nestjs/common';
import { render as mailyRender } from '@maily-to/render';
import { Instrument, InstrumentUsecase } from '@novu/application-generic';
import isEmpty from 'lodash/isEmpty';
import { FullPayloadForRender, RenderCommand } from './render-command';
import { ExpandEmailEditorSchemaUsecase } from './expand-email-editor-schema.usecase';
import { EmailStepControlZodSchema } from '../../../workflows-v2/shared';

export class RenderEmailOutputCommand extends RenderCommand {}

Expand All @@ -13,16 +15,16 @@ export class RenderEmailOutputUsecase {

@InstrumentUsecase()
async execute(renderCommand: RenderEmailOutputCommand): Promise<EmailRenderOutput> {
const expandedSchema = this.transformForAndShowLogic(
renderCommand.controlValues.emailEditor as unknown as string,
renderCommand.fullPayloadForRender
);
const { body, subject } = EmailStepControlZodSchema.parse(renderCommand.controlValues);

if (isEmpty(body)) {
return { subject, body: '' };
}

const expandedSchema = this.transformForAndShowLogic(body, renderCommand.fullPayloadForRender);
const htmlRendered = await this.renderEmail(expandedSchema);

return {
subject: renderCommand.controlValues.subject as unknown as string,
body: htmlRendered,
};
return { subject, body: htmlRendered };
}

@Instrument()
Expand Down
69 changes: 37 additions & 32 deletions apps/api/src/app/events/dtos/trigger-event-request.dto.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,8 @@
import {
ArrayMaxSize,
ArrayNotEmpty,
IsArray,
IsDefined,
IsObject,
IsOptional,
IsString,
ValidateIf,
ValidateNested,
} from 'class-validator';
import { IsDefined, IsObject, IsOptional, IsString, ValidateIf, ValidateNested } from 'class-validator';
import { Type } from 'class-transformer';
import { ApiExtraModels, ApiProperty, ApiPropertyOptional, getSchemaPath } from '@nestjs/swagger';
import {
TriggerRecipients,
TriggerRecipientsPayload,
TriggerRecipientsTypeEnum,
TriggerRecipientSubscriber,
TriggerTenantContext,
Expand Down Expand Up @@ -47,7 +37,10 @@ export class TopicPayloadDto {
@ApiProperty()
topicKey: string;

@ApiProperty({ example: 'Topic', enum: TriggerRecipientsTypeEnum, enumName: 'TriggerRecipientsTypeEnum' })
@ApiProperty({
enum: [...Object.values(TriggerRecipientsTypeEnum)],
enumName: 'TriggerRecipientsTypeEnum',
})
type: TriggerRecipientsTypeEnum;
}

Expand Down Expand Up @@ -110,25 +103,40 @@ export class TriggerEventRequestDto {

@ApiProperty({
description: 'The recipients list of people who will receive the notification.',
type: 'array',
items: {
oneOf: [
{
$ref: getSchemaPath(SubscriberPayloadDto),
},
{
$ref: getSchemaPath(TopicPayloadDto),
},
{
type: 'string',
description: 'Unique identifier of a subscriber in your systems',
example: 'SUBSCRIBER_ID',
oneOf: [
{
type: 'array',
items: {
oneOf: [
{
$ref: getSchemaPath(SubscriberPayloadDto),
},
{
$ref: getSchemaPath(TopicPayloadDto),
},
{
type: 'string',
description: 'Unique identifier of a subscriber in your systems',
example: 'SUBSCRIBER_ID',
},
],
},
],
},
},
{
type: 'string',
description: 'Unique identifier of a subscriber in your systems',
example: 'SUBSCRIBER_ID',
},
{
$ref: getSchemaPath(SubscriberPayloadDto),
},
{
$ref: getSchemaPath(TopicPayloadDto),
},
],
})
@IsDefined()
to: TriggerRecipients;
to: TriggerRecipientsPayload;

@ApiPropertyOptional({
description: 'A unique identifier for this transaction, we will generate a UUID if not provided.',
Expand Down Expand Up @@ -177,8 +185,5 @@ export class BulkTriggerEventDto {
isArray: true,
type: TriggerEventRequestDto,
})
@IsArray()
@ArrayNotEmpty()
@ArrayMaxSize(100)
events: TriggerEventRequestDto[];
}
13 changes: 8 additions & 5 deletions apps/api/src/app/events/e2e/bulk-trigger.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import { triggerBulk } from '@novu/api/funcs/triggerBulk';
import { TriggerEventRequestDto } from '@novu/api/models/components';
import { z } from 'zod';
import { NovuCore } from '@novu/api/core';
import { handleSdkError, initNovuClassSdk, initNovuFunctionSdk } from '../../shared/helpers/e2e/sdk/e2e-sdk.helper';
import {
handleValidationErrorDto,
initNovuClassSdk,
initNovuFunctionSdk,
} from '../../shared/helpers/e2e/sdk/e2e-sdk.helper';

describe('Trigger bulk events - /v1/events/trigger/bulk (POST)', function () {
let session: UserSession;
Expand Down Expand Up @@ -214,11 +218,10 @@ describe('Trigger bulk events - /v1/events/trigger/bulk (POST)', function () {
} catch (e) {
error = e;
}
const { error: sdkError, parsedBody } = handleSdkError(error);
const errorDto = handleValidationErrorDto(error);

expect(sdkError.statusCode).to.equal(400);
expect(parsedBody.statusCode).to.equal(400);
expect(parsedBody.message[0]).to.equal('events must contain no more than 100 elements');
expect(errorDto.statusCode).to.equal(422);
expect(errorDto.errors.events.messages[0]).to.equal('events must contain no more than 100 elements');
});

it('should handle bulk if one of the events returns errors', async function () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { IsDefined, IsEnum, IsOptional, IsString, ValidateIf, ValidateNested } f
import {
AddressingTypeEnum,
StatelessControls,
TriggerRecipients,
TriggerRecipientsPayload,
TriggerRecipientSubscriber,
TriggerRequestCategoryEnum,
TriggerTenantContext,
Expand Down Expand Up @@ -54,7 +54,7 @@ export class ParseEventRequestBaseCommand extends EnvironmentWithUserCommand {

export class ParseEventRequestMulticastCommand extends ParseEventRequestBaseCommand {
@IsDefined()
to: TriggerRecipients;
to: TriggerRecipientsPayload;

@IsEnum(AddressingTypeEnum)
addressingType: AddressingTypeEnum.MULTICAST;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { IsArray } from 'class-validator';
import { ArrayMaxSize, ArrayNotEmpty, IsArray } from 'class-validator';
import { EnvironmentWithUserCommand } from '../../../shared/commands/project.command';
import { TriggerEventRequestDto } from '../../dtos';

export class ProcessBulkTriggerCommand extends EnvironmentWithUserCommand {
@IsArray()
@ArrayNotEmpty()
@ArrayMaxSize(100)
events: TriggerEventRequestDto[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,8 @@ export class ProcessBulkTrigger {

async execute(command: ProcessBulkTriggerCommand) {
const results: TriggerEventResponseDto[] = [];
console.log('event.to', JSON.stringify(command));

for (const event of command.events) {
let result: TriggerEventResponseDto;
console.log('event.to', event.to);
console.log('event.to', event.payload);
try {
result = (await this.parseEventRequest.execute(
ParseEventRequestMulticastCommand.create({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ClassSerializerInterceptor, Controller, Get, Query, UseInterceptors } from '@nestjs/common';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiExcludeController, ApiOperation, ApiTags } from '@nestjs/swagger';
import { UserSessionData } from '@novu/shared';
import { ExecutionDetailsResponseDto } from '@novu/application-generic';
import { UserSession } from '../shared/framework/user.decorator';
Expand All @@ -14,6 +14,7 @@ import { UserAuthentication } from '../shared/framework/swagger/api.key.security
@UseInterceptors(ClassSerializerInterceptor)
@UserAuthentication()
@ApiTags('Execution Details')
@ApiExcludeController()
export class ExecutionDetailsController {
constructor(private getExecutionDetails: GetExecutionDetails) {}

Expand Down
4 changes: 2 additions & 2 deletions apps/api/src/app/inbox/e2e/mark-notification-as.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ describe('Mark Notification As - /inbox/notifications/:id/{read,unread,archive,u
it('should throw bad request error when the notification id is not mongo id', async function () {
const id = 'fake';
const { body, status } = await updateNotification({ id, status: 'read' });
expect(body.statusCode).to.equal(400);
expect(body.cause.notificationId.messages[0]).to.equal(`notificationId must be a mongodb id`);
expect(body.statusCode).to.equal(422);
expect(body.errors.notificationId.messages[0]).to.equal(`notificationId must be a mongodb id`);
});

it("should throw not found error when the message doesn't exist", async function () {
Expand Down
6 changes: 3 additions & 3 deletions apps/api/src/app/inbox/e2e/update-notification-action.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ describe('Update Notification Action - /inbox/notifications/:id/{complete/revert
actionType: ButtonTypeEnum.PRIMARY,
});

expect(status).to.equal(400);
expect(body.statusCode).to.equal(400);
expect(body.cause.notificationId.messages[0]).to.equal(`notificationId must be a mongodb id`);
expect(status).to.equal(422);
expect(body.statusCode).to.equal(422);
expect(body.errors.notificationId.messages[0]).to.equal(`notificationId must be a mongodb id`);
});

it("should throw not found error when the message doesn't exist", async function () {
Expand Down
6 changes: 3 additions & 3 deletions apps/api/src/app/inbox/e2e/update-preferences.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,9 @@ describe('Update workflow preferences - /inbox/preferences/:workflowId (PATCH)',
chat: true,
})
.set('Authorization', `Bearer ${session.subscriberToken}`);
expect(response.body.statusCode).to.equal(400);
expect(response.body.cause.workflowId.messages[0]).to.equal(`workflowId must be a mongodb id`);
expect(response.status).to.equal(400);
expect(response.body.statusCode).to.equal(422);
expect(response.body.errors.workflowId.messages[0]).to.equal(`workflowId must be a mongodb id`);
expect(response.status).to.equal(422);
});

it('should throw error when non-existing workflow id is passed', async function () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ describe('Set Integration As Primary - /integrations/:integrationId/set-primary
const fakeIntegrationId = 'fakeIntegrationId';

const { body } = await session.testAgent.post(`/v1/integrations/${fakeIntegrationId}/set-primary`).send({});
expect(body.statusCode).to.equal(400);
expect(body.cause.integrationId.messages[0]).to.equal(`integrationId must be a mongodb id`);
expect(body.statusCode).to.equal(422);
expect(body.errors.integrationId.messages[0]).to.equal(`integrationId must be a mongodb id`);
});

it('when integration does not exist should throw not found exception', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
UseInterceptors,
} from '@nestjs/common';
import { UserSessionData } from '@novu/shared';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiExcludeController, ApiOperation, ApiTags } from '@nestjs/swagger';
import { CreateNotificationGroup } from './usecases/create-notification-group/create-notification-group.usecase';
import { UserSession } from '../shared/framework/user.decorator';
import { CreateNotificationGroupCommand } from './usecases/create-notification-group/create-notification-group.command';
Expand All @@ -34,6 +34,7 @@ import { UserAuthentication } from '../shared/framework/swagger/api.key.security
@UseInterceptors(ClassSerializerInterceptor)
@UserAuthentication()
@ApiTags('Workflow groups')
@ApiExcludeController()
export class NotificationGroupsController {
constructor(
private createNotificationGroupUsecase: CreateNotificationGroup,
Expand Down
1 change: 1 addition & 0 deletions apps/api/src/app/notifications/notification.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export class NotificationsController {
@ApiOperation({
summary: 'Get notifications',
})
@ApiCommonResponses()
@UserAuthentication()
@ExternalApiAccessible()
listNotifications(
Expand Down
3 changes: 2 additions & 1 deletion apps/api/src/app/organization/ee.organization.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
UseInterceptors,
} from '@nestjs/common';
import { UserSessionData } from '@novu/shared';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiExcludeController, ApiOperation, ApiTags } from '@nestjs/swagger';
import { UserSession } from '../shared/framework/user.decorator';
import { UserAuthGuard } from '../auth/framework/user.auth.guard';
import { UpdateBrandingDetailsCommand } from './usecases/update-branding-details/update-branding-details.command';
Expand All @@ -30,6 +30,7 @@ import { OrganizationBrandingResponseDto, OrganizationResponseDto } from './dtos
@UseGuards(UserAuthGuard)
@ApiTags('Organizations')
@ApiCommonResponses()
@ApiExcludeController()
export class EEOrganizationController {
constructor(
private updateBrandingDetailsUsecase: UpdateBrandingDetails,
Expand Down
1 change: 1 addition & 0 deletions apps/api/src/app/shared/dtos/step-filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export class StepFilter {

@ApiProperty({
enum: ['BOOLEAN', 'TEXT', 'DATE', 'NUMBER', 'STATEMENT', 'LIST', 'MULTI_LIST', 'GROUP'],
enumName: 'BuilderFieldType',
})
type?: BuilderFieldType;

Expand Down
Loading

0 comments on commit 4c8b0e3

Please sign in to comment.