Skip to content

Commit

Permalink
feat(js): lazy session initialization and interface fixes (#5665)
Browse files Browse the repository at this point in the history
  • Loading branch information
LetItRock authored Jun 11, 2024
1 parent 92377f7 commit 6b653db
Show file tree
Hide file tree
Showing 32 changed files with 486 additions and 137 deletions.
5 changes: 3 additions & 2 deletions apps/api/src/app/subscribers/subscribers.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ import { ThrottlerCategory, ThrottlerCost } from '../rate-limiting/guards';
import { MessageMarkAsRequestDto } from '../widgets/dtos/mark-as-request.dto';
import { MarkMessageAsByMarkCommand } from '../widgets/usecases/mark-message-as-by-mark/mark-message-as-by-mark.command';
import { MarkMessageAsByMark } from '../widgets/usecases/mark-message-as-by-mark/mark-message-as-by-mark.usecase';
import { FeedResponseDto } from '../widgets/dtos/feeds-response.dto';

@ThrottlerCategory(ApiRateLimitCategoryEnum.CONFIGURATION)
@ApiCommonResponses()
Expand Down Expand Up @@ -476,12 +477,12 @@ export class SubscribersController {
@ApiOperation({
summary: 'Get in-app notification feed for a particular subscriber',
})
@ApiOkPaginatedResponse(MessageResponseDto)
@ApiOkPaginatedResponse(FeedResponseDto)
async getNotificationsFeed(
@UserSession() user: IJwtPayload,
@Param('subscriberId') subscriberId: string,
@Query() query: GetInAppNotificationsFeedForSubscriberDto
): Promise<PaginatedResponseDto<MessageResponseDto>> {
): Promise<FeedResponseDto> {
let feedsQuery: string[] | undefined;
if (query.feedIdentifier) {
feedsQuery = Array.isArray(query.feedIdentifier) ? query.feedIdentifier : [query.feedIdentifier];
Expand Down
131 changes: 131 additions & 0 deletions apps/api/src/app/widgets/dtos/feeds-response.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { ApiExtraModels, ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { ActorTypeEnum, ChannelTypeEnum, IActor, INotificationDto } from '@novu/shared';

import { SubscriberResponseDto } from '../../subscribers/dtos';
import { EmailBlock, MessageCTA } from './message-response.dto';

class Actor implements IActor {
@ApiProperty()
data: string | null;

@ApiProperty({ enum: ActorTypeEnum })
type: ActorTypeEnum;
}

@ApiExtraModels(EmailBlock, MessageCTA)
export class NotificationDto implements INotificationDto {
@ApiPropertyOptional()
_id: string;

@ApiProperty()
_templateId: string;

@ApiProperty()
_environmentId: string;

@ApiProperty()
_messageTemplateId: string;

@ApiProperty()
_organizationId: string;

@ApiProperty()
_notificationId: string;

@ApiProperty()
_subscriberId: string;

@ApiProperty()
_feedId: string;

@ApiProperty()
_jobId: string;

@ApiPropertyOptional()
createdAt: string;

@ApiPropertyOptional()
updatedAt: string;

@ApiPropertyOptional()
expireAt: string;

@ApiPropertyOptional({
type: Actor,
})
actor?: Actor;

@ApiPropertyOptional({
type: SubscriberResponseDto,
})
subscriber?: SubscriberResponseDto;

@ApiProperty()
transactionId: string;

@ApiPropertyOptional()
templateIdentifier: string;

@ApiPropertyOptional()
providerId: string;

@ApiProperty()
content: string;

@ApiProperty()
subject?: string;

@ApiProperty({
enum: ChannelTypeEnum,
})
channel: ChannelTypeEnum;

@ApiProperty()
read: boolean;

@ApiProperty()
seen: boolean;

@ApiProperty()
deleted: boolean;

@ApiPropertyOptional()
deviceTokens?: string[];

@ApiProperty({
type: MessageCTA,
})
cta: MessageCTA;

@ApiProperty({
enum: ['sent', 'error', 'warning'],
})
status: 'sent' | 'error' | 'warning';

@ApiProperty({
description: 'The payload that was used to send the notification trigger',
})
payload: Record<string, unknown>;

@ApiProperty({
description: 'Provider specific overrides used when triggering the notification',
})
overrides: Record<string, unknown>;
}

export class FeedResponseDto {
@ApiPropertyOptional()
totalCount?: number;

@ApiProperty()
hasMore: boolean;

@ApiProperty()
data: NotificationDto[];

@ApiProperty()
pageSize: number;

@ApiProperty()
page: number;
}
38 changes: 24 additions & 14 deletions apps/api/src/app/widgets/dtos/message-response.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import {
EmailBlockTypeEnum,
MessageActionStatusEnum,
TextAlignEnum,
INotificationDto,
IMessage,
IMessageCTA,
IMessageAction,
} from '@novu/shared';
import { SubscriberResponseDto } from '../../subscribers/dtos';
import { WorkflowResponse } from '../../workflows/dto/workflow-response.dto';
Expand All @@ -18,7 +20,7 @@ class EmailBlockStyles {
textAlign?: TextAlignEnum;
}

class EmailBlock {
export class EmailBlock {
@ApiProperty({
enum: ['text', 'button'],
})
Expand Down Expand Up @@ -53,7 +55,7 @@ class MessageButton {
resultContent?: string;
}

class MessageAction {
class MessageAction implements IMessageAction {
@ApiPropertyOptional({
enum: MessageActionStatusEnum,
})
Expand All @@ -68,27 +70,29 @@ class MessageAction {
@ApiPropertyOptional({
type: MessageActionResult,
})
result?: MessageActionResult;
result: MessageActionResult;
}

class MessageCTAData {
@ApiPropertyOptional()
url?: string;
}

class MessageCTA {
export class MessageCTA implements IMessageCTA {
@ApiPropertyOptional()
type?: ChannelCTATypeEnum;
type: ChannelCTATypeEnum;

@ApiProperty()
data: MessageCTAData;

@ApiPropertyOptional()
action?: MessageAction;
}

@ApiExtraModels(EmailBlock, MessageCTA)
export class MessageResponseDto implements INotificationDto {
export class MessageResponseDto implements IMessage {
@ApiPropertyOptional()
_id?: string;
_id: string;

@ApiProperty()
_templateId: string;
Expand Down Expand Up @@ -121,8 +125,14 @@ export class MessageResponseDto implements INotificationDto {
@ApiPropertyOptional()
templateIdentifier?: string;

@ApiProperty()
createdAt: string;

@ApiPropertyOptional()
lastSeenDate?: string;

@ApiPropertyOptional()
createdAt?: string;
lastReadDate?: string;

@ApiProperty({
oneOf: [
Expand All @@ -147,6 +157,9 @@ export class MessageResponseDto implements INotificationDto {
})
channel: ChannelTypeEnum;

@ApiProperty()
read: boolean;

@ApiProperty()
seen: boolean;

Expand All @@ -168,16 +181,13 @@ export class MessageResponseDto implements INotificationDto {
@ApiPropertyOptional()
title?: string;

@ApiProperty()
lastSeenDate: string;

@ApiProperty({
type: MessageCTA,
})
cta: MessageCTA;

@ApiProperty()
_feedId?: string;
@ApiPropertyOptional()
_feedId?: string | null;

@ApiProperty({
enum: ['sent', 'error', 'warning'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import {
import { MessageRepository, SubscriberEntity, SubscriberRepository } from '@novu/dal';

import { GetNotificationsFeedCommand } from './get-notifications-feed.command';
import { MessagesResponseDto } from '../../dtos/message-response.dto';
import { ApiException } from '../../../shared/exceptions/api.exception';
import { FeedResponseDto } from '../../dtos/feeds-response.dto';

@Injectable()
export class GetNotificationsFeed {
Expand Down Expand Up @@ -41,7 +41,7 @@ export class GetNotificationsFeed {
...command,
}),
})
async execute(command: GetNotificationsFeedCommand): Promise<MessagesResponseDto> {
async execute(command: GetNotificationsFeedCommand): Promise<FeedResponseDto> {
const payload = this.getPayloadObject(command.payload);

const subscriber = await this.fetchSubscriber({
Expand Down Expand Up @@ -78,7 +78,7 @@ export class GetNotificationsFeed {

for (const message of feed) {
if (message._actorId && message.actor?.type === ActorTypeEnum.USER) {
message.actor.data = this.processUserAvatar(message.actorSubscriber);
message.actor.data = message.actorSubscriber?.avatar || null;
}
}

Expand All @@ -103,21 +103,17 @@ export class GetNotificationsFeed {
const hasMore = feed.length < totalCount;
totalCount = Math.min(totalCount, command.limit);

const data = feed.map((el) => ({ ...el, content: el.content as string }));

return {
data: feed || [],
data,
totalCount: totalCount,
hasMore: hasMore,
pageSize: command.limit,
page: command.page,
};
}

private getHasMore(page: number, LIMIT: number, feed, totalCount) {
const currentPaginationTotal = page * LIMIT + feed.length;

return currentPaginationTotal < totalCount;
}

@CachedEntity({
builder: (command: { subscriberId: string; _environmentId: string }) =>
buildSubscriberKey({
Expand All @@ -134,8 +130,4 @@ export class GetNotificationsFeed {
}): Promise<SubscriberEntity | null> {
return await this.subscriberRepository.findBySubscriberId(_environmentId, subscriberId);
}

private processUserAvatar(actorSubscriber?: SubscriberEntity): string | null {
return actorSubscriber?.avatar || null;
}
}
13 changes: 9 additions & 4 deletions libs/dal/src/repositories/message/message.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,13 @@ export class MessageEntity {

template?: NotificationTemplateEntity;

templateIdentifier?: string;
templateIdentifier: string;

createdAt?: string;
expireAt?: string;
createdAt: string;

expireAt: string;

updatedAt: string;

content: string | IEmailBlock[];

Expand All @@ -48,6 +51,8 @@ export class MessageEntity {

read: boolean;

deleted: boolean;

email?: string;

phone?: string;
Expand All @@ -56,7 +61,7 @@ export class MessageEntity {

directWebhookUrl?: string;

providerId?: string;
providerId: string;

deviceTokens?: string[];

Expand Down
1 change: 1 addition & 0 deletions libs/shared/src/dto/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from './workflows';
export * from './tenant';
export * from './workflow-override';
export * from './widget';
export * from './session';
1 change: 1 addition & 0 deletions libs/shared/src/dto/session/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './session.dto';
6 changes: 6 additions & 0 deletions libs/shared/src/dto/session/session.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { ISubscriberJwt } from '../../entities/user';

export interface ISessionDto {
token: string;
profile: ISubscriberJwt;
}
Loading

0 comments on commit 6b653db

Please sign in to comment.