vintasend-prisma 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/implementations/vintasend-prisma/src/index.d.ts +2 -0
- package/dist/implementations/vintasend-prisma/src/index.js +5 -0
- package/dist/implementations/vintasend-prisma/src/prisma-notification-backend.d.ts +190 -0
- package/dist/implementations/vintasend-prisma/src/prisma-notification-backend.js +399 -0
- package/dist/prisma-notification-backend.d.ts +74 -17
- package/dist/prisma-notification-backend.js +293 -72
- package/dist/services/notification-backends/base-notification-backend.d.ts +30 -0
- package/dist/services/notification-backends/base-notification-backend.js +2 -0
- package/dist/types/identifier.d.ts +2 -0
- package/dist/types/identifier.js +2 -0
- package/dist/types/json-values.d.ts +15 -0
- package/dist/types/json-values.js +2 -0
- package/dist/types/notification-context-generators.d.ts +4 -0
- package/dist/types/notification-context-generators.js +2 -0
- package/dist/types/notification-status.d.ts +1 -0
- package/dist/types/notification-status.js +2 -0
- package/dist/types/notification-type-config.d.ts +7 -0
- package/dist/types/notification-type-config.js +2 -0
- package/dist/types/notification-type.d.ts +1 -0
- package/dist/types/notification-type.js +2 -0
- package/dist/types/notification.d.ts +63 -0
- package/dist/types/notification.js +2 -0
- package/dist/types/one-off-notification.d.ts +68 -0
- package/dist/types/one-off-notification.js +2 -0
- package/dist/types/uuid.d.ts +1 -0
- package/dist/types/uuid.js +2 -0
- package/package.json +2 -2
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PrismaNotificationBackendFactory = void 0;
|
|
4
|
+
var prisma_notification_backend_1 = require("./prisma-notification-backend");
|
|
5
|
+
Object.defineProperty(exports, "PrismaNotificationBackendFactory", { enumerable: true, get: function () { return prisma_notification_backend_1.PrismaNotificationBackendFactory; } });
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import type { BaseNotificationBackend } from '../../../services/notification-backends/base-notification-backend';
|
|
2
|
+
import type { InputJsonValue, JsonValue } from 'vintasend/dist/types/json-values';
|
|
3
|
+
import type { DatabaseNotification, Notification, NotificationInput } from 'vintasend/dist/types/notification';
|
|
4
|
+
import type { DatabaseOneOffNotification, OneOffNotificationInput, AnyDatabaseNotification } from '../../../types/notification';
|
|
5
|
+
import type { NotificationStatus } from 'vintasend/dist/types/notification-status';
|
|
6
|
+
import type { NotificationType } from 'vintasend/dist/types/notification-type';
|
|
7
|
+
import type { BaseNotificationTypeConfig } from 'vintasend/dist/types/notification-type-config';
|
|
8
|
+
export declare const NotificationStatusEnum: {
|
|
9
|
+
readonly PENDING_SEND: "PENDING_SEND";
|
|
10
|
+
readonly SENT: "SENT";
|
|
11
|
+
readonly FAILED: "FAILED";
|
|
12
|
+
readonly READ: "READ";
|
|
13
|
+
readonly CANCELLED: "CANCELLED";
|
|
14
|
+
};
|
|
15
|
+
export declare const NotificationTypeEnum: {
|
|
16
|
+
readonly EMAIL: "EMAIL";
|
|
17
|
+
readonly PUSH: "PUSH";
|
|
18
|
+
readonly SMS: "SMS";
|
|
19
|
+
readonly IN_APP: "IN_APP";
|
|
20
|
+
};
|
|
21
|
+
export interface PrismaNotificationModel<IdType, UserId> {
|
|
22
|
+
id: IdType;
|
|
23
|
+
userId: UserId | null;
|
|
24
|
+
emailOrPhone: string | null;
|
|
25
|
+
firstName: string | null;
|
|
26
|
+
lastName: string | null;
|
|
27
|
+
notificationType: NotificationType;
|
|
28
|
+
title: string | null;
|
|
29
|
+
bodyTemplate: string;
|
|
30
|
+
contextName: string;
|
|
31
|
+
contextParameters: JsonValue;
|
|
32
|
+
sendAfter: Date | null;
|
|
33
|
+
subjectTemplate: string | null;
|
|
34
|
+
status: NotificationStatus;
|
|
35
|
+
contextUsed: JsonValue | null;
|
|
36
|
+
extraParams: JsonValue | null;
|
|
37
|
+
adapterUsed: string | null;
|
|
38
|
+
sentAt: Date | null;
|
|
39
|
+
readAt: Date | null;
|
|
40
|
+
createdAt: Date;
|
|
41
|
+
updatedAt: Date;
|
|
42
|
+
user?: {
|
|
43
|
+
email: string;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export interface NotificationPrismaClientInterface<NotificationIdType, UserIdType> {
|
|
47
|
+
notification: {
|
|
48
|
+
findMany(args: {
|
|
49
|
+
where?: {
|
|
50
|
+
status?: NotificationStatus | {
|
|
51
|
+
not: NotificationStatus;
|
|
52
|
+
};
|
|
53
|
+
sendAfter?: {
|
|
54
|
+
lte: Date;
|
|
55
|
+
} | null;
|
|
56
|
+
userId?: UserIdType | null;
|
|
57
|
+
readAt?: null;
|
|
58
|
+
emailOrPhone?: string | {
|
|
59
|
+
not: null;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
skip?: number;
|
|
63
|
+
take?: number;
|
|
64
|
+
include?: {
|
|
65
|
+
user?: boolean;
|
|
66
|
+
};
|
|
67
|
+
}): Promise<PrismaNotificationModel<NotificationIdType, UserIdType>[]>;
|
|
68
|
+
create(args: {
|
|
69
|
+
data: BaseNotificationCreateInput<UserIdType>;
|
|
70
|
+
include?: {
|
|
71
|
+
user?: boolean;
|
|
72
|
+
};
|
|
73
|
+
}): Promise<PrismaNotificationModel<NotificationIdType, UserIdType>>;
|
|
74
|
+
createMany(args: {
|
|
75
|
+
data: BaseNotificationCreateInput<UserIdType>[];
|
|
76
|
+
}): Promise<NotificationIdType[]>;
|
|
77
|
+
update(args: {
|
|
78
|
+
where: {
|
|
79
|
+
id: NotificationIdType;
|
|
80
|
+
};
|
|
81
|
+
data: Partial<BaseNotificationUpdateInput<UserIdType>>;
|
|
82
|
+
include?: {
|
|
83
|
+
user?: boolean;
|
|
84
|
+
};
|
|
85
|
+
}): Promise<PrismaNotificationModel<NotificationIdType, UserIdType>>;
|
|
86
|
+
findUnique(args: {
|
|
87
|
+
where: {
|
|
88
|
+
id: NotificationIdType;
|
|
89
|
+
};
|
|
90
|
+
include?: {
|
|
91
|
+
user?: boolean;
|
|
92
|
+
};
|
|
93
|
+
}): Promise<PrismaNotificationModel<NotificationIdType, UserIdType> | null>;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
type NoExpand<T> = T extends unknown ? T : never;
|
|
97
|
+
type AtLeast<O extends object, K extends string> = NoExpand<O extends unknown ? (K extends keyof O ? {
|
|
98
|
+
[P in K]: O[P];
|
|
99
|
+
} & O : O) | ({
|
|
100
|
+
[P in keyof O as P extends K ? K : never]-?: O[P];
|
|
101
|
+
} & O) : never>;
|
|
102
|
+
export interface BaseNotificationCreateInput<UserIdType> {
|
|
103
|
+
user?: {
|
|
104
|
+
connect?: AtLeast<{
|
|
105
|
+
id?: UserIdType;
|
|
106
|
+
email?: string;
|
|
107
|
+
}, 'id' | 'email'>;
|
|
108
|
+
};
|
|
109
|
+
userId?: UserIdType | null;
|
|
110
|
+
emailOrPhone?: string | null;
|
|
111
|
+
firstName?: string | null;
|
|
112
|
+
lastName?: string | null;
|
|
113
|
+
notificationType: NotificationType;
|
|
114
|
+
title?: string | null;
|
|
115
|
+
bodyTemplate: string;
|
|
116
|
+
contextName: string;
|
|
117
|
+
contextParameters: InputJsonValue;
|
|
118
|
+
sendAfter?: Date | null;
|
|
119
|
+
subjectTemplate?: string | null;
|
|
120
|
+
status?: NotificationStatus;
|
|
121
|
+
contextUsed?: InputJsonValue;
|
|
122
|
+
extraParams?: InputJsonValue;
|
|
123
|
+
adapterUsed?: string | null;
|
|
124
|
+
sentAt?: Date | null;
|
|
125
|
+
readAt?: Date | null;
|
|
126
|
+
}
|
|
127
|
+
export interface BaseNotificationUpdateInput<UserIdType> {
|
|
128
|
+
user?: {
|
|
129
|
+
connect?: AtLeast<{
|
|
130
|
+
id?: UserIdType;
|
|
131
|
+
email?: string;
|
|
132
|
+
}, 'id' | 'email'>;
|
|
133
|
+
};
|
|
134
|
+
emailOrPhone?: string | null;
|
|
135
|
+
firstName?: string | null;
|
|
136
|
+
lastName?: string | null;
|
|
137
|
+
notificationType?: NotificationType;
|
|
138
|
+
title?: string | null;
|
|
139
|
+
bodyTemplate?: string;
|
|
140
|
+
contextName?: string;
|
|
141
|
+
contextParameters?: InputJsonValue;
|
|
142
|
+
sendAfter?: Date | null;
|
|
143
|
+
subjectTemplate?: string | null;
|
|
144
|
+
status?: NotificationStatus;
|
|
145
|
+
contextUsed?: InputJsonValue;
|
|
146
|
+
extraParams?: InputJsonValue;
|
|
147
|
+
adapterUsed?: string | null;
|
|
148
|
+
sentAt?: Date | null;
|
|
149
|
+
readAt?: Date | null;
|
|
150
|
+
}
|
|
151
|
+
export declare class PrismaNotificationBackend<Client extends NotificationPrismaClientInterface<Config['NotificationIdType'], Config['UserIdType']>, Config extends BaseNotificationTypeConfig> implements BaseNotificationBackend<Config> {
|
|
152
|
+
private prismaClient;
|
|
153
|
+
constructor(prismaClient: Client);
|
|
154
|
+
/**
|
|
155
|
+
* Serialize a Prisma notification model to either DatabaseNotification or DatabaseOneOffNotification
|
|
156
|
+
* based on whether it has a userId or not
|
|
157
|
+
*/
|
|
158
|
+
serializeNotification(notification: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>): AnyDatabaseNotification<Config>;
|
|
159
|
+
deserializeNotification(notification: NotificationInput<Config>): BaseNotificationCreateInput<Config['UserIdType']>;
|
|
160
|
+
deserializeNotificationForUpdate(notification: Partial<Notification<Config>>): Partial<Parameters<typeof this.prismaClient.notification.update>[0]['data']>;
|
|
161
|
+
getAllPendingNotifications(): Promise<AnyDatabaseNotification<Config>[]>;
|
|
162
|
+
getPendingNotifications(page?: number, pageSize?: number): Promise<AnyDatabaseNotification<Config>[]>;
|
|
163
|
+
getAllFutureNotifications(): Promise<AnyDatabaseNotification<Config>[]>;
|
|
164
|
+
getFutureNotifications(page?: number, pageSize?: number): Promise<AnyDatabaseNotification<Config>[]>;
|
|
165
|
+
getAllFutureNotificationsFromUser(userId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['userId']): Promise<DatabaseNotification<Config>[]>;
|
|
166
|
+
getFutureNotificationsFromUser(userId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['userId'], page: number, pageSize: number): Promise<DatabaseNotification<Config>[]>;
|
|
167
|
+
getAllNotifications(): Promise<AnyDatabaseNotification<Config>[]>;
|
|
168
|
+
getNotifications(page: number, pageSize: number): Promise<AnyDatabaseNotification<Config>[]>;
|
|
169
|
+
persistNotification(notification: NotificationInput<Config>): Promise<DatabaseNotification<Config>>;
|
|
170
|
+
persistNotificationUpdate(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], notification: Partial<Omit<DatabaseNotification<Config>, 'id'>>): Promise<DatabaseNotification<Config>>;
|
|
171
|
+
persistOneOffNotification(notification: OneOffNotificationInput<Config>): Promise<DatabaseOneOffNotification<Config>>;
|
|
172
|
+
persistOneOffNotificationUpdate(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], notification: Partial<Omit<DatabaseOneOffNotification<Config>, 'id'>>): Promise<DatabaseOneOffNotification<Config>>;
|
|
173
|
+
getOneOffNotification(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], _forUpdate: boolean): Promise<DatabaseOneOffNotification<Config> | null>;
|
|
174
|
+
getAllOneOffNotifications(): Promise<DatabaseOneOffNotification<Config>[]>;
|
|
175
|
+
getOneOffNotifications(page: number, pageSize: number): Promise<DatabaseOneOffNotification<Config>[]>;
|
|
176
|
+
markAsSent(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], checkIsPending?: boolean): Promise<AnyDatabaseNotification<Config>>;
|
|
177
|
+
markAsFailed(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], checkIsPending?: boolean): Promise<AnyDatabaseNotification<Config>>;
|
|
178
|
+
markAsRead(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], checkIsSent?: boolean): Promise<DatabaseNotification<Config>>;
|
|
179
|
+
cancelNotification(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id']): Promise<void>;
|
|
180
|
+
getNotification(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], _forUpdate: boolean): Promise<AnyDatabaseNotification<Config> | null>;
|
|
181
|
+
filterAllInAppUnreadNotifications(userId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['userId']): Promise<DatabaseNotification<Config>[]>;
|
|
182
|
+
filterInAppUnreadNotifications(userId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['userId'], page: number, pageSize: number): Promise<DatabaseNotification<Config>[]>;
|
|
183
|
+
getUserEmailFromNotification(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id']): Promise<string | undefined>;
|
|
184
|
+
storeContextUsed(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], context: InputJsonValue): Promise<void>;
|
|
185
|
+
bulkPersistNotifications(notifications: Omit<Notification<Config>, 'id'>[]): Promise<Config['NotificationIdType'][]>;
|
|
186
|
+
}
|
|
187
|
+
export declare class PrismaNotificationBackendFactory<Config extends BaseNotificationTypeConfig> {
|
|
188
|
+
create<Client extends NotificationPrismaClientInterface<Config['NotificationIdType'], Config['UserIdType']>>(prismaClient: Client): PrismaNotificationBackend<Client, Config>;
|
|
189
|
+
}
|
|
190
|
+
export {};
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PrismaNotificationBackendFactory = exports.PrismaNotificationBackend = exports.NotificationTypeEnum = exports.NotificationStatusEnum = void 0;
|
|
4
|
+
exports.NotificationStatusEnum = {
|
|
5
|
+
PENDING_SEND: 'PENDING_SEND',
|
|
6
|
+
SENT: 'SENT',
|
|
7
|
+
FAILED: 'FAILED',
|
|
8
|
+
READ: 'READ',
|
|
9
|
+
CANCELLED: 'CANCELLED',
|
|
10
|
+
};
|
|
11
|
+
exports.NotificationTypeEnum = {
|
|
12
|
+
EMAIL: 'EMAIL',
|
|
13
|
+
PUSH: 'PUSH',
|
|
14
|
+
SMS: 'SMS',
|
|
15
|
+
IN_APP: 'IN_APP',
|
|
16
|
+
};
|
|
17
|
+
function convertJsonValueToRecord(jsonValue) {
|
|
18
|
+
if (typeof jsonValue === 'object' && !Array.isArray(jsonValue)) {
|
|
19
|
+
return jsonValue;
|
|
20
|
+
}
|
|
21
|
+
throw new Error('Invalid JSON value. It should be an object.');
|
|
22
|
+
}
|
|
23
|
+
class PrismaNotificationBackend {
|
|
24
|
+
constructor(prismaClient) {
|
|
25
|
+
this.prismaClient = prismaClient;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Serialize a Prisma notification model to either DatabaseNotification or DatabaseOneOffNotification
|
|
29
|
+
* based on whether it has a userId or not
|
|
30
|
+
*/
|
|
31
|
+
serializeNotification(notification) {
|
|
32
|
+
const baseData = {
|
|
33
|
+
id: notification.id,
|
|
34
|
+
notificationType: notification.notificationType,
|
|
35
|
+
title: notification.title,
|
|
36
|
+
bodyTemplate: notification.bodyTemplate,
|
|
37
|
+
contextName: notification.contextName,
|
|
38
|
+
contextParameters: notification.contextParameters
|
|
39
|
+
? notification.contextParameters
|
|
40
|
+
: {},
|
|
41
|
+
sendAfter: notification.sendAfter,
|
|
42
|
+
subjectTemplate: notification.subjectTemplate,
|
|
43
|
+
status: notification.status,
|
|
44
|
+
contextUsed: notification.contextUsed,
|
|
45
|
+
extraParams: notification.extraParams
|
|
46
|
+
? convertJsonValueToRecord(notification.extraParams)
|
|
47
|
+
: null,
|
|
48
|
+
adapterUsed: notification.adapterUsed,
|
|
49
|
+
sentAt: notification.sentAt,
|
|
50
|
+
readAt: notification.readAt,
|
|
51
|
+
createdAt: notification.createdAt,
|
|
52
|
+
updatedAt: notification.updatedAt,
|
|
53
|
+
};
|
|
54
|
+
// Check if this is a one-off notification (has emailOrPhone but no userId)
|
|
55
|
+
if (notification.emailOrPhone && !notification.userId) {
|
|
56
|
+
return {
|
|
57
|
+
...baseData,
|
|
58
|
+
emailOrPhone: notification.emailOrPhone,
|
|
59
|
+
firstName: notification.firstName || '',
|
|
60
|
+
lastName: notification.lastName || '',
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
// Regular notification with userId
|
|
64
|
+
return {
|
|
65
|
+
...baseData,
|
|
66
|
+
userId: notification.userId,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
deserializeNotification(notification) {
|
|
70
|
+
return {
|
|
71
|
+
user: {
|
|
72
|
+
connect: {
|
|
73
|
+
id: notification.userId,
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
notificationType: notification.notificationType,
|
|
77
|
+
title: notification.title,
|
|
78
|
+
bodyTemplate: notification.bodyTemplate,
|
|
79
|
+
contextName: notification.contextName,
|
|
80
|
+
contextParameters: notification.contextParameters,
|
|
81
|
+
sendAfter: notification.sendAfter,
|
|
82
|
+
subjectTemplate: notification.subjectTemplate,
|
|
83
|
+
extraParams: notification.extraParams,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
deserializeNotificationForUpdate(notification) {
|
|
87
|
+
return {
|
|
88
|
+
...(notification.userId ? { user: { connect: { id: notification.userId } } } : {}),
|
|
89
|
+
...(notification.notificationType
|
|
90
|
+
? {
|
|
91
|
+
notificationType: exports.NotificationTypeEnum[notification.notificationType],
|
|
92
|
+
}
|
|
93
|
+
: {}),
|
|
94
|
+
...(notification.title ? { title: notification.title } : {}),
|
|
95
|
+
...(notification.bodyTemplate ? { bodyTemplate: notification.bodyTemplate } : {}),
|
|
96
|
+
...(notification.contextName ? { contextName: notification.contextName } : {}),
|
|
97
|
+
...(notification.contextParameters
|
|
98
|
+
? {
|
|
99
|
+
contextParameters: notification.contextParameters ? notification.contextParameters : {},
|
|
100
|
+
}
|
|
101
|
+
: {}),
|
|
102
|
+
...(notification.sendAfter ? { sendAfter: notification.sendAfter } : {}),
|
|
103
|
+
...(notification.subjectTemplate ? { subjectTemplate: notification.subjectTemplate } : {}),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
async getAllPendingNotifications() {
|
|
107
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
108
|
+
where: { status: exports.NotificationStatusEnum.PENDING_SEND },
|
|
109
|
+
});
|
|
110
|
+
return notifications.map((n) => this.serializeNotification(n));
|
|
111
|
+
}
|
|
112
|
+
async getPendingNotifications(page = 0, pageSize = 100) {
|
|
113
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
114
|
+
where: {
|
|
115
|
+
status: exports.NotificationStatusEnum.PENDING_SEND,
|
|
116
|
+
sendAfter: null,
|
|
117
|
+
},
|
|
118
|
+
skip: page * pageSize,
|
|
119
|
+
take: pageSize,
|
|
120
|
+
});
|
|
121
|
+
return notifications.map((n) => this.serializeNotification(n));
|
|
122
|
+
}
|
|
123
|
+
async getAllFutureNotifications() {
|
|
124
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
125
|
+
where: {
|
|
126
|
+
status: { not: exports.NotificationStatusEnum.PENDING_SEND },
|
|
127
|
+
sendAfter: { lte: new Date() },
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
return notifications.map((n) => this.serializeNotification(n));
|
|
131
|
+
}
|
|
132
|
+
async getFutureNotifications(page = 0, pageSize = 100) {
|
|
133
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
134
|
+
where: {
|
|
135
|
+
status: { not: exports.NotificationStatusEnum.PENDING_SEND },
|
|
136
|
+
sendAfter: { lte: new Date() },
|
|
137
|
+
},
|
|
138
|
+
skip: page * pageSize,
|
|
139
|
+
take: pageSize,
|
|
140
|
+
});
|
|
141
|
+
return notifications.map((n) => this.serializeNotification(n));
|
|
142
|
+
}
|
|
143
|
+
async getAllFutureNotificationsFromUser(userId) {
|
|
144
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
145
|
+
where: {
|
|
146
|
+
userId,
|
|
147
|
+
status: {
|
|
148
|
+
not: exports.NotificationStatusEnum.PENDING_SEND,
|
|
149
|
+
},
|
|
150
|
+
sendAfter: {
|
|
151
|
+
lte: new Date(),
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
// These are guaranteed to be regular notifications (not one-off) since we're filtering by userId
|
|
156
|
+
return notifications.map((n) => this.serializeNotification(n));
|
|
157
|
+
}
|
|
158
|
+
async getFutureNotificationsFromUser(userId, page, pageSize) {
|
|
159
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
160
|
+
where: {
|
|
161
|
+
userId,
|
|
162
|
+
status: {
|
|
163
|
+
not: exports.NotificationStatusEnum.PENDING_SEND,
|
|
164
|
+
},
|
|
165
|
+
sendAfter: {
|
|
166
|
+
lte: new Date(),
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
skip: page * pageSize,
|
|
170
|
+
take: pageSize,
|
|
171
|
+
});
|
|
172
|
+
// These are guaranteed to be regular notifications (not one-off) since we're filtering by userId
|
|
173
|
+
return notifications.map((n) => this.serializeNotification(n));
|
|
174
|
+
}
|
|
175
|
+
async getAllNotifications() {
|
|
176
|
+
const notifications = await this.prismaClient.notification.findMany({});
|
|
177
|
+
return notifications.map((n) => this.serializeNotification(n));
|
|
178
|
+
}
|
|
179
|
+
async getNotifications(page, pageSize) {
|
|
180
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
181
|
+
skip: page * pageSize,
|
|
182
|
+
take: pageSize,
|
|
183
|
+
});
|
|
184
|
+
return notifications.map((n) => this.serializeNotification(n));
|
|
185
|
+
}
|
|
186
|
+
async persistNotification(notification) {
|
|
187
|
+
const created = await this.prismaClient.notification.create({
|
|
188
|
+
data: this.deserializeNotification(notification),
|
|
189
|
+
});
|
|
190
|
+
// persistNotification takes NotificationInput which always has userId, so this is always a regular notification
|
|
191
|
+
return this.serializeNotification(created);
|
|
192
|
+
}
|
|
193
|
+
async persistNotificationUpdate(notificationId, notification) {
|
|
194
|
+
const updated = await this.prismaClient.notification.update({
|
|
195
|
+
where: {
|
|
196
|
+
id: notificationId,
|
|
197
|
+
},
|
|
198
|
+
data: this.deserializeNotificationForUpdate(notification),
|
|
199
|
+
});
|
|
200
|
+
// persistNotificationUpdate takes Partial<DatabaseNotification> which has userId, so this is always a regular notification
|
|
201
|
+
return this.serializeNotification(updated);
|
|
202
|
+
}
|
|
203
|
+
/* One-off notification persistence and query methods */
|
|
204
|
+
async persistOneOffNotification(notification) {
|
|
205
|
+
const created = await this.prismaClient.notification.create({
|
|
206
|
+
data: {
|
|
207
|
+
userId: null, // One-off notifications don't have a userId
|
|
208
|
+
emailOrPhone: notification.emailOrPhone,
|
|
209
|
+
firstName: notification.firstName,
|
|
210
|
+
lastName: notification.lastName,
|
|
211
|
+
notificationType: notification.notificationType,
|
|
212
|
+
title: notification.title,
|
|
213
|
+
bodyTemplate: notification.bodyTemplate,
|
|
214
|
+
contextName: notification.contextName,
|
|
215
|
+
contextParameters: notification.contextParameters,
|
|
216
|
+
sendAfter: notification.sendAfter,
|
|
217
|
+
subjectTemplate: notification.subjectTemplate,
|
|
218
|
+
extraParams: notification.extraParams,
|
|
219
|
+
status: exports.NotificationStatusEnum.PENDING_SEND,
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
return this.serializeNotification(created);
|
|
223
|
+
}
|
|
224
|
+
async persistOneOffNotificationUpdate(notificationId, notification) {
|
|
225
|
+
const data = {
|
|
226
|
+
...(notification.emailOrPhone !== undefined ? { emailOrPhone: notification.emailOrPhone } : {}),
|
|
227
|
+
...(notification.firstName !== undefined ? { firstName: notification.firstName } : {}),
|
|
228
|
+
...(notification.lastName !== undefined ? { lastName: notification.lastName } : {}),
|
|
229
|
+
...(notification.notificationType ? { notificationType: notification.notificationType } : {}),
|
|
230
|
+
...(notification.title ? { title: notification.title } : {}),
|
|
231
|
+
...(notification.bodyTemplate ? { bodyTemplate: notification.bodyTemplate } : {}),
|
|
232
|
+
...(notification.contextName ? { contextName: notification.contextName } : {}),
|
|
233
|
+
...(notification.contextParameters ? { contextParameters: notification.contextParameters } : {}),
|
|
234
|
+
...(notification.sendAfter ? { sendAfter: notification.sendAfter } : {}),
|
|
235
|
+
...(notification.subjectTemplate ? { subjectTemplate: notification.subjectTemplate } : {}),
|
|
236
|
+
};
|
|
237
|
+
const updated = await this.prismaClient.notification.update({
|
|
238
|
+
where: { id: notificationId },
|
|
239
|
+
data,
|
|
240
|
+
});
|
|
241
|
+
return this.serializeNotification(updated);
|
|
242
|
+
}
|
|
243
|
+
async getOneOffNotification(notificationId, _forUpdate) {
|
|
244
|
+
const notification = await this.prismaClient.notification.findUnique({
|
|
245
|
+
where: {
|
|
246
|
+
id: notificationId,
|
|
247
|
+
},
|
|
248
|
+
});
|
|
249
|
+
if (!notification || !notification.emailOrPhone || notification.userId !== null) {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
return this.serializeNotification(notification);
|
|
253
|
+
}
|
|
254
|
+
async getAllOneOffNotifications() {
|
|
255
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
256
|
+
where: {
|
|
257
|
+
userId: null,
|
|
258
|
+
emailOrPhone: { not: null },
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
return notifications
|
|
262
|
+
.filter((n) => n.emailOrPhone !== null)
|
|
263
|
+
.map((n) => this.serializeNotification(n));
|
|
264
|
+
}
|
|
265
|
+
async getOneOffNotifications(page, pageSize) {
|
|
266
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
267
|
+
where: {
|
|
268
|
+
userId: null,
|
|
269
|
+
emailOrPhone: { not: null },
|
|
270
|
+
},
|
|
271
|
+
skip: page * pageSize,
|
|
272
|
+
take: pageSize,
|
|
273
|
+
});
|
|
274
|
+
return notifications
|
|
275
|
+
.filter((n) => n.emailOrPhone !== null)
|
|
276
|
+
.map((n) => this.serializeNotification(n));
|
|
277
|
+
}
|
|
278
|
+
async markAsSent(notificationId, checkIsPending = true) {
|
|
279
|
+
const whereClause = {
|
|
280
|
+
id: notificationId,
|
|
281
|
+
};
|
|
282
|
+
if (checkIsPending) {
|
|
283
|
+
whereClause.status = exports.NotificationStatusEnum.PENDING_SEND;
|
|
284
|
+
}
|
|
285
|
+
const updated = await this.prismaClient.notification.update({
|
|
286
|
+
where: whereClause,
|
|
287
|
+
data: {
|
|
288
|
+
status: exports.NotificationStatusEnum.SENT,
|
|
289
|
+
sentAt: new Date(),
|
|
290
|
+
},
|
|
291
|
+
});
|
|
292
|
+
return this.serializeNotification(updated);
|
|
293
|
+
}
|
|
294
|
+
async markAsFailed(notificationId, checkIsPending = true) {
|
|
295
|
+
const whereClause = {
|
|
296
|
+
id: notificationId,
|
|
297
|
+
};
|
|
298
|
+
if (checkIsPending) {
|
|
299
|
+
whereClause.status = exports.NotificationStatusEnum.PENDING_SEND;
|
|
300
|
+
}
|
|
301
|
+
const updated = await this.prismaClient.notification.update({
|
|
302
|
+
where: whereClause,
|
|
303
|
+
data: {
|
|
304
|
+
status: exports.NotificationStatusEnum.FAILED,
|
|
305
|
+
sentAt: new Date(),
|
|
306
|
+
},
|
|
307
|
+
});
|
|
308
|
+
return this.serializeNotification(updated);
|
|
309
|
+
}
|
|
310
|
+
async markAsRead(notificationId, checkIsSent = true) {
|
|
311
|
+
const whereClause = {
|
|
312
|
+
id: notificationId,
|
|
313
|
+
};
|
|
314
|
+
if (checkIsSent) {
|
|
315
|
+
whereClause.status = exports.NotificationStatusEnum.SENT;
|
|
316
|
+
}
|
|
317
|
+
const updated = await this.prismaClient.notification.update({
|
|
318
|
+
where: whereClause,
|
|
319
|
+
data: {
|
|
320
|
+
status: 'READ',
|
|
321
|
+
readAt: new Date(),
|
|
322
|
+
},
|
|
323
|
+
});
|
|
324
|
+
// markAsRead is only for in-app notifications (which are always regular notifications with userId)
|
|
325
|
+
return this.serializeNotification(updated);
|
|
326
|
+
}
|
|
327
|
+
async cancelNotification(notificationId) {
|
|
328
|
+
await this.prismaClient.notification.update({
|
|
329
|
+
where: {
|
|
330
|
+
id: notificationId,
|
|
331
|
+
},
|
|
332
|
+
data: {
|
|
333
|
+
status: exports.NotificationStatusEnum.CANCELLED,
|
|
334
|
+
},
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
async getNotification(notificationId, _forUpdate) {
|
|
338
|
+
const notification = await this.prismaClient.notification.findUnique({
|
|
339
|
+
where: { id: notificationId },
|
|
340
|
+
});
|
|
341
|
+
if (!notification)
|
|
342
|
+
return null;
|
|
343
|
+
return this.serializeNotification(notification);
|
|
344
|
+
}
|
|
345
|
+
async filterAllInAppUnreadNotifications(userId) {
|
|
346
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
347
|
+
where: {
|
|
348
|
+
userId,
|
|
349
|
+
status: 'SENT',
|
|
350
|
+
readAt: null,
|
|
351
|
+
},
|
|
352
|
+
});
|
|
353
|
+
// These are guaranteed to be regular notifications (not one-off) since we're filtering by userId
|
|
354
|
+
return notifications.map((n) => this.serializeNotification(n));
|
|
355
|
+
}
|
|
356
|
+
async filterInAppUnreadNotifications(userId, page, pageSize) {
|
|
357
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
358
|
+
where: {
|
|
359
|
+
userId,
|
|
360
|
+
status: 'SENT',
|
|
361
|
+
readAt: null,
|
|
362
|
+
},
|
|
363
|
+
skip: page * pageSize,
|
|
364
|
+
take: pageSize,
|
|
365
|
+
});
|
|
366
|
+
// These are guaranteed to be regular notifications (not one-off) since we're filtering by userId
|
|
367
|
+
return notifications.map((n) => this.serializeNotification(n));
|
|
368
|
+
}
|
|
369
|
+
async getUserEmailFromNotification(notificationId) {
|
|
370
|
+
var _a;
|
|
371
|
+
const notification = await this.prismaClient.notification.findUnique({
|
|
372
|
+
where: {
|
|
373
|
+
id: notificationId,
|
|
374
|
+
},
|
|
375
|
+
include: {
|
|
376
|
+
user: true,
|
|
377
|
+
},
|
|
378
|
+
});
|
|
379
|
+
return (_a = notification === null || notification === void 0 ? void 0 : notification.user) === null || _a === void 0 ? void 0 : _a.email;
|
|
380
|
+
}
|
|
381
|
+
async storeContextUsed(notificationId, context) {
|
|
382
|
+
await this.prismaClient.notification.update({
|
|
383
|
+
where: { id: notificationId },
|
|
384
|
+
data: { contextUsed: context }
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
async bulkPersistNotifications(notifications) {
|
|
388
|
+
return this.prismaClient.notification.createMany({
|
|
389
|
+
data: notifications.map((notification) => this.deserializeNotification(notification)),
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
exports.PrismaNotificationBackend = PrismaNotificationBackend;
|
|
394
|
+
class PrismaNotificationBackendFactory {
|
|
395
|
+
create(prismaClient) {
|
|
396
|
+
return new PrismaNotificationBackend(prismaClient);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
exports.PrismaNotificationBackendFactory = PrismaNotificationBackendFactory;
|