-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Expand file tree
/
Copy pathlist-topic-subscriptions.usecase.ts
More file actions
103 lines (89 loc) · 3.61 KB
/
list-topic-subscriptions.usecase.ts
File metadata and controls
103 lines (89 loc) · 3.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
import { InstrumentUsecase } from '@novu/application-generic';
import {
SubscriberRepository,
TopicEntity,
TopicRepository,
TopicSubscribersEntity,
TopicSubscribersRepository,
} from '@novu/dal';
import { DirectionEnum, EnvironmentId } from '@novu/shared';
import { ListTopicSubscriptionsResponseDto } from '../../dtos/list-topic-subscriptions-response.dto';
import { TopicSubscriptionResponseDto } from '../../dtos/topic-subscription-response.dto';
import { mapTopicSubscriptionsToDto } from '../list-topics/map-topic-entity-to.dto';
import { ListTopicSubscriptionsCommand } from './list-topic-subscriptions.command';
@Injectable()
export class ListTopicSubscriptionsUseCase {
constructor(
private topicRepository: TopicRepository,
private topicSubscribersRepository: TopicSubscribersRepository,
private subscriberRepository: SubscriberRepository
) {}
@InstrumentUsecase()
async execute(command: ListTopicSubscriptionsCommand): Promise<ListTopicSubscriptionsResponseDto> {
const topic = await this.topicRepository.findTopicByKey(
command.topicKey,
command.organizationId,
command.environmentId
);
if (!topic) {
throw new NotFoundException(`Topic with key ${command.topicKey} not found`);
}
if (command.before && command.after) {
throw new BadRequestException('Cannot specify both "before" and "after" cursors at the same time.');
}
const subscriptionsPagination = await this.topicSubscribersRepository.findTopicSubscriptionsWithPagination({
environmentId: command.environmentId,
organizationId: command.organizationId,
topicKey: command.topicKey,
subscriberId: command.subscriberId,
contextKeys: command.contextKeys,
limit: command.limit || 10,
before: command.before,
after: command.after,
orderDirection: command.orderDirection === 1 ? DirectionEnum.ASC : DirectionEnum.DESC,
includeCursor: command.includeCursor,
});
// Build detailed response with topic and subscriber info
const subscriptionsWithDetails = await this.populateSubscriptionsData(
topic,
subscriptionsPagination.data,
command.environmentId
);
return {
data: subscriptionsWithDetails,
next: subscriptionsPagination.next,
previous: subscriptionsPagination.previous,
totalCount: subscriptionsPagination.totalCount,
totalCountCapped: subscriptionsPagination.totalCountCapped,
};
}
private async populateSubscriptionsData(
topic: TopicEntity,
subscriptions: TopicSubscribersEntity[],
environmentId: EnvironmentId
): Promise<TopicSubscriptionResponseDto[]> {
if (subscriptions.length === 0) {
return [];
}
// Get all subscriber IDs from subscriptions
const subscriberIds = subscriptions.map((subscription) => subscription._subscriberId);
// Fetch all subscribers in a single query
const subscribers = await this.subscriberRepository.find({
_environmentId: environmentId,
_id: { $in: subscriberIds },
});
// Create a map for quick lookup
const subscriberMap = new Map(subscribers.map((subscriber) => [subscriber._id, subscriber]));
// Map subscriptions to response DTOs with topic and subscriber details
return subscriptions
.map((subscription) => {
const subscriber = subscriberMap.get(subscription._subscriberId);
if (!subscriber) {
return null;
}
return mapTopicSubscriptionsToDto(subscription, subscriber, topic);
})
.filter(Boolean) as TopicSubscriptionResponseDto[];
}
}