vintasend-prisma 0.2.2 → 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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { BaseNotificationBackend } from 'vintasend/dist/services/notification-backends/base-notification-backend';
|
|
2
2
|
import type { InputJsonValue, JsonValue } from 'vintasend/dist/types/json-values';
|
|
3
|
-
import type { DatabaseNotification, Notification, NotificationInput } from 'vintasend/dist/types/notification';
|
|
3
|
+
import type { AnyNotificationInput, DatabaseNotification, Notification, NotificationInput } from 'vintasend/dist/types/notification';
|
|
4
|
+
import type { DatabaseOneOffNotification, OneOffNotificationInput, AnyNotification, AnyDatabaseNotification } from 'vintasend/dist/types/notification';
|
|
4
5
|
import type { NotificationStatus } from 'vintasend/dist/types/notification-status';
|
|
5
6
|
import type { NotificationType } from 'vintasend/dist/types/notification-type';
|
|
6
7
|
import type { BaseNotificationTypeConfig } from 'vintasend/dist/types/notification-type-config';
|
|
@@ -19,7 +20,10 @@ export declare const NotificationTypeEnum: {
|
|
|
19
20
|
};
|
|
20
21
|
export interface PrismaNotificationModel<IdType, UserId> {
|
|
21
22
|
id: IdType;
|
|
22
|
-
userId: UserId;
|
|
23
|
+
userId: UserId | null;
|
|
24
|
+
emailOrPhone: string | null;
|
|
25
|
+
firstName: string | null;
|
|
26
|
+
lastName: string | null;
|
|
23
27
|
notificationType: NotificationType;
|
|
24
28
|
title: string | null;
|
|
25
29
|
bodyTemplate: string;
|
|
@@ -49,8 +53,11 @@ export interface NotificationPrismaClientInterface<NotificationIdType, UserIdTyp
|
|
|
49
53
|
sendAfter?: {
|
|
50
54
|
lte: Date;
|
|
51
55
|
} | null;
|
|
52
|
-
userId?: UserIdType;
|
|
56
|
+
userId?: UserIdType | null;
|
|
53
57
|
readAt?: null;
|
|
58
|
+
emailOrPhone?: string | {
|
|
59
|
+
not: null;
|
|
60
|
+
};
|
|
54
61
|
};
|
|
55
62
|
skip?: number;
|
|
56
63
|
take?: number;
|
|
@@ -93,12 +100,16 @@ type AtLeast<O extends object, K extends string> = NoExpand<O extends unknown ?
|
|
|
93
100
|
[P in keyof O as P extends K ? K : never]-?: O[P];
|
|
94
101
|
} & O) : never>;
|
|
95
102
|
export interface BaseNotificationCreateInput<UserIdType> {
|
|
96
|
-
user
|
|
103
|
+
user?: {
|
|
97
104
|
connect?: AtLeast<{
|
|
98
105
|
id?: UserIdType;
|
|
99
106
|
email?: string;
|
|
100
107
|
}, 'id' | 'email'>;
|
|
101
108
|
};
|
|
109
|
+
userId?: UserIdType | null;
|
|
110
|
+
emailOrPhone?: string | null;
|
|
111
|
+
firstName?: string | null;
|
|
112
|
+
lastName?: string | null;
|
|
102
113
|
notificationType: NotificationType;
|
|
103
114
|
title?: string | null;
|
|
104
115
|
bodyTemplate: string;
|
|
@@ -114,12 +125,15 @@ export interface BaseNotificationCreateInput<UserIdType> {
|
|
|
114
125
|
readAt?: Date | null;
|
|
115
126
|
}
|
|
116
127
|
export interface BaseNotificationUpdateInput<UserIdType> {
|
|
117
|
-
user
|
|
128
|
+
user?: {
|
|
118
129
|
connect?: AtLeast<{
|
|
119
130
|
id?: UserIdType;
|
|
120
131
|
email?: string;
|
|
121
132
|
}, 'id' | 'email'>;
|
|
122
133
|
};
|
|
134
|
+
emailOrPhone?: string | null;
|
|
135
|
+
firstName?: string | null;
|
|
136
|
+
lastName?: string | null;
|
|
123
137
|
notificationType?: NotificationType;
|
|
124
138
|
title?: string | null;
|
|
125
139
|
bodyTemplate?: string;
|
|
@@ -137,29 +151,72 @@ export interface BaseNotificationUpdateInput<UserIdType> {
|
|
|
137
151
|
export declare class PrismaNotificationBackend<Client extends NotificationPrismaClientInterface<Config['NotificationIdType'], Config['UserIdType']>, Config extends BaseNotificationTypeConfig> implements BaseNotificationBackend<Config> {
|
|
138
152
|
private prismaClient;
|
|
139
153
|
constructor(prismaClient: Client);
|
|
140
|
-
|
|
141
|
-
|
|
154
|
+
/**
|
|
155
|
+
* Build a where clause for status-based updates
|
|
156
|
+
*/
|
|
157
|
+
private buildStatusWhere;
|
|
158
|
+
/**
|
|
159
|
+
* Serialize a Prisma notification model to either DatabaseNotification or DatabaseOneOffNotification
|
|
160
|
+
* based on whether it has a userId or not (internal implementation)
|
|
161
|
+
*/
|
|
162
|
+
private serializeAnyNotification;
|
|
163
|
+
/**
|
|
164
|
+
* Serialize a Prisma notification model to DatabaseNotification
|
|
165
|
+
*/
|
|
166
|
+
private serializeRegularNotification;
|
|
167
|
+
/**
|
|
168
|
+
* Serialize a Prisma notification model to DatabaseOneOffNotification
|
|
169
|
+
*/
|
|
170
|
+
private serializeOneOffNotification;
|
|
171
|
+
/**
|
|
172
|
+
* Public accessor for serialization - primarily for testing
|
|
173
|
+
* @internal
|
|
174
|
+
*/
|
|
175
|
+
serializeNotification(notification: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>): AnyDatabaseNotification<Config>;
|
|
176
|
+
/**
|
|
177
|
+
* Core internal builder for creating notification data
|
|
178
|
+
* Validates that notification has either userId or emailOrPhone (but not neither)
|
|
179
|
+
*/
|
|
180
|
+
private buildCreateData;
|
|
181
|
+
/**
|
|
182
|
+
* Deserialize a regular notification input for creation
|
|
183
|
+
*/
|
|
184
|
+
private deserializeRegularNotification;
|
|
185
|
+
/**
|
|
186
|
+
* Build one-off notification data for creation
|
|
187
|
+
*/
|
|
188
|
+
private buildOneOffNotificationData;
|
|
189
|
+
/**
|
|
190
|
+
* Core internal builder for update data (supports both regular and one-off)
|
|
191
|
+
*/
|
|
192
|
+
private buildUpdateData;
|
|
193
|
+
deserializeNotification(notification: AnyNotificationInput<Config> | Omit<AnyNotificationInput<Config>, 'id'>): BaseNotificationCreateInput<Config['UserIdType']>;
|
|
142
194
|
deserializeNotificationForUpdate(notification: Partial<Notification<Config>>): Partial<Parameters<typeof this.prismaClient.notification.update>[0]['data']>;
|
|
143
|
-
getAllPendingNotifications(): Promise<
|
|
144
|
-
getPendingNotifications(): Promise<
|
|
145
|
-
getAllFutureNotifications(): Promise<
|
|
146
|
-
getFutureNotifications(): Promise<
|
|
195
|
+
getAllPendingNotifications(): Promise<AnyDatabaseNotification<Config>[]>;
|
|
196
|
+
getPendingNotifications(page?: number, pageSize?: number): Promise<AnyDatabaseNotification<Config>[]>;
|
|
197
|
+
getAllFutureNotifications(): Promise<AnyDatabaseNotification<Config>[]>;
|
|
198
|
+
getFutureNotifications(page?: number, pageSize?: number): Promise<AnyDatabaseNotification<Config>[]>;
|
|
147
199
|
getAllFutureNotificationsFromUser(userId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['userId']): Promise<DatabaseNotification<Config>[]>;
|
|
148
200
|
getFutureNotificationsFromUser(userId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['userId'], page: number, pageSize: number): Promise<DatabaseNotification<Config>[]>;
|
|
149
|
-
getAllNotifications(): Promise<
|
|
150
|
-
getNotifications(page: number, pageSize: number): Promise<
|
|
201
|
+
getAllNotifications(): Promise<AnyDatabaseNotification<Config>[]>;
|
|
202
|
+
getNotifications(page: number, pageSize: number): Promise<AnyDatabaseNotification<Config>[]>;
|
|
151
203
|
persistNotification(notification: NotificationInput<Config>): Promise<DatabaseNotification<Config>>;
|
|
152
204
|
persistNotificationUpdate(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], notification: Partial<Omit<DatabaseNotification<Config>, 'id'>>): Promise<DatabaseNotification<Config>>;
|
|
153
|
-
|
|
154
|
-
|
|
205
|
+
persistOneOffNotification(notification: OneOffNotificationInput<Config>): Promise<DatabaseOneOffNotification<Config>>;
|
|
206
|
+
persistOneOffNotificationUpdate(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], notification: Partial<Omit<DatabaseOneOffNotification<Config>, 'id'>>): Promise<DatabaseOneOffNotification<Config>>;
|
|
207
|
+
getOneOffNotification(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], _forUpdate: boolean): Promise<DatabaseOneOffNotification<Config> | null>;
|
|
208
|
+
getAllOneOffNotifications(): Promise<DatabaseOneOffNotification<Config>[]>;
|
|
209
|
+
getOneOffNotifications(page: number, pageSize: number): Promise<DatabaseOneOffNotification<Config>[]>;
|
|
210
|
+
markAsSent(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], checkIsPending?: boolean): Promise<AnyDatabaseNotification<Config>>;
|
|
211
|
+
markAsFailed(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], checkIsPending?: boolean): Promise<AnyDatabaseNotification<Config>>;
|
|
155
212
|
markAsRead(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], checkIsSent?: boolean): Promise<DatabaseNotification<Config>>;
|
|
156
213
|
cancelNotification(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id']): Promise<void>;
|
|
157
|
-
getNotification(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], _forUpdate: boolean): Promise<
|
|
214
|
+
getNotification(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], _forUpdate: boolean): Promise<AnyDatabaseNotification<Config> | null>;
|
|
158
215
|
filterAllInAppUnreadNotifications(userId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['userId']): Promise<DatabaseNotification<Config>[]>;
|
|
159
216
|
filterInAppUnreadNotifications(userId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['userId'], page: number, pageSize: number): Promise<DatabaseNotification<Config>[]>;
|
|
160
217
|
getUserEmailFromNotification(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id']): Promise<string | undefined>;
|
|
161
218
|
storeContextUsed(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], context: InputJsonValue): Promise<void>;
|
|
162
|
-
bulkPersistNotifications(notifications: Omit<
|
|
219
|
+
bulkPersistNotifications(notifications: Omit<AnyNotification<Config>, 'id'>[]): Promise<Config['NotificationIdType'][]>;
|
|
163
220
|
}
|
|
164
221
|
export declare class PrismaNotificationBackendFactory<Config extends BaseNotificationTypeConfig> {
|
|
165
222
|
create<Client extends NotificationPrismaClientInterface<Config['NotificationIdType'], Config['UserIdType']>>(prismaClient: Client): PrismaNotificationBackend<Client, Config>;
|
|
@@ -24,10 +24,25 @@ class PrismaNotificationBackend {
|
|
|
24
24
|
constructor(prismaClient) {
|
|
25
25
|
this.prismaClient = prismaClient;
|
|
26
26
|
}
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Build a where clause for status-based updates
|
|
29
|
+
*/
|
|
30
|
+
buildStatusWhere(id, opts = {}) {
|
|
31
|
+
const where = {
|
|
32
|
+
id: id,
|
|
33
|
+
};
|
|
34
|
+
if (opts.checkStatus) {
|
|
35
|
+
where.status = opts.checkStatus;
|
|
36
|
+
}
|
|
37
|
+
return where;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Serialize a Prisma notification model to either DatabaseNotification or DatabaseOneOffNotification
|
|
41
|
+
* based on whether it has a userId or not (internal implementation)
|
|
42
|
+
*/
|
|
43
|
+
serializeAnyNotification(notification) {
|
|
44
|
+
const baseData = {
|
|
29
45
|
id: notification.id,
|
|
30
|
-
userId: notification.userId,
|
|
31
46
|
notificationType: notification.notificationType,
|
|
32
47
|
title: notification.title,
|
|
33
48
|
bodyTemplate: notification.bodyTemplate,
|
|
@@ -48,14 +63,60 @@ class PrismaNotificationBackend {
|
|
|
48
63
|
createdAt: notification.createdAt,
|
|
49
64
|
updatedAt: notification.updatedAt,
|
|
50
65
|
};
|
|
51
|
-
|
|
52
|
-
|
|
66
|
+
// Check if this is a one-off notification (has emailOrPhone but no userId)
|
|
67
|
+
// Use explicit null checks to avoid misclassification with empty strings or other falsy values
|
|
68
|
+
if (notification.userId == null && notification.emailOrPhone != null) {
|
|
69
|
+
return {
|
|
70
|
+
...baseData,
|
|
71
|
+
emailOrPhone: notification.emailOrPhone,
|
|
72
|
+
firstName: notification.firstName || '',
|
|
73
|
+
lastName: notification.lastName || '',
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
// Regular notification with userId
|
|
77
|
+
if (notification.userId == null) {
|
|
78
|
+
throw new Error('Invalid notification: missing both userId and emailOrPhone');
|
|
79
|
+
}
|
|
53
80
|
return {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
81
|
+
...baseData,
|
|
82
|
+
userId: notification.userId,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Serialize a Prisma notification model to DatabaseNotification
|
|
87
|
+
*/
|
|
88
|
+
serializeRegularNotification(notification) {
|
|
89
|
+
return this.serializeAnyNotification(notification);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Serialize a Prisma notification model to DatabaseOneOffNotification
|
|
93
|
+
*/
|
|
94
|
+
serializeOneOffNotification(notification) {
|
|
95
|
+
return this.serializeAnyNotification(notification);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Public accessor for serialization - primarily for testing
|
|
99
|
+
* @internal
|
|
100
|
+
*/
|
|
101
|
+
serializeNotification(notification) {
|
|
102
|
+
return this.serializeAnyNotification(notification);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Core internal builder for creating notification data
|
|
106
|
+
* Validates that notification has either userId or emailOrPhone (but not neither)
|
|
107
|
+
*/
|
|
108
|
+
buildCreateData(notification) {
|
|
109
|
+
var _a, _b;
|
|
110
|
+
const hasUserId = 'userId' in notification && notification.userId != null;
|
|
111
|
+
const hasEmailOrPhone = 'emailOrPhone' in notification && notification.emailOrPhone != null;
|
|
112
|
+
// Validate: must have either userId or emailOrPhone
|
|
113
|
+
if (!hasUserId && !hasEmailOrPhone) {
|
|
114
|
+
throw new Error('Invalid notification: missing both userId and emailOrPhone');
|
|
115
|
+
}
|
|
116
|
+
// Determine if this is a one-off notification
|
|
117
|
+
// When both are provided, userId takes precedence (regular notification)
|
|
118
|
+
const isOneOff = !hasUserId && hasEmailOrPhone;
|
|
119
|
+
const base = {
|
|
59
120
|
notificationType: notification.notificationType,
|
|
60
121
|
title: notification.title,
|
|
61
122
|
bodyTemplate: notification.bodyTemplate,
|
|
@@ -65,6 +126,122 @@ class PrismaNotificationBackend {
|
|
|
65
126
|
subjectTemplate: notification.subjectTemplate,
|
|
66
127
|
extraParams: notification.extraParams,
|
|
67
128
|
};
|
|
129
|
+
if (isOneOff) {
|
|
130
|
+
return {
|
|
131
|
+
...base,
|
|
132
|
+
userId: null,
|
|
133
|
+
emailOrPhone: 'emailOrPhone' in notification ? notification.emailOrPhone : '',
|
|
134
|
+
firstName: (_a = ('firstName' in notification ? notification.firstName : null)) !== null && _a !== void 0 ? _a : null,
|
|
135
|
+
lastName: (_b = ('lastName' in notification ? notification.lastName : null)) !== null && _b !== void 0 ? _b : null,
|
|
136
|
+
status: exports.NotificationStatusEnum.PENDING_SEND,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
// At this point we know hasUserId is true, so userId exists and is not null
|
|
140
|
+
const userId = ('userId' in notification ? notification.userId : null);
|
|
141
|
+
return {
|
|
142
|
+
...base,
|
|
143
|
+
user: {
|
|
144
|
+
connect: { id: userId },
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Deserialize a regular notification input for creation
|
|
150
|
+
*/
|
|
151
|
+
deserializeRegularNotification(notification) {
|
|
152
|
+
return this.buildCreateData(notification);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Build one-off notification data for creation
|
|
156
|
+
*/
|
|
157
|
+
buildOneOffNotificationData(notification) {
|
|
158
|
+
return this.buildCreateData(notification);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Core internal builder for update data (supports both regular and one-off)
|
|
162
|
+
*/
|
|
163
|
+
buildUpdateData(notification) {
|
|
164
|
+
const data = {};
|
|
165
|
+
// Determine if this is transitioning between regular and one-off notification types
|
|
166
|
+
const hasUserId = 'userId' in notification && notification.userId !== undefined;
|
|
167
|
+
const hasOneOffFields = 'emailOrPhone' in notification && notification.emailOrPhone !== undefined;
|
|
168
|
+
// Handle user / one-off fields with mutual exclusion
|
|
169
|
+
if (hasUserId) {
|
|
170
|
+
// Converting to regular notification: set user and clear one-off fields
|
|
171
|
+
data.user = { connect: { id: notification.userId } };
|
|
172
|
+
// Clear one-off specific fields when transitioning to regular notification
|
|
173
|
+
data.emailOrPhone = null;
|
|
174
|
+
data.firstName = null;
|
|
175
|
+
data.lastName = null;
|
|
176
|
+
}
|
|
177
|
+
else if (hasOneOffFields) {
|
|
178
|
+
// Converting to one-off notification: set one-off fields
|
|
179
|
+
// Note: We cannot explicitly clear the user relationship via update,
|
|
180
|
+
// but setting emailOrPhone indicates this is now a one-off notification
|
|
181
|
+
data.emailOrPhone = notification.emailOrPhone;
|
|
182
|
+
if ('firstName' in notification && notification.firstName !== undefined) {
|
|
183
|
+
data.firstName = notification.firstName;
|
|
184
|
+
}
|
|
185
|
+
if ('lastName' in notification && notification.lastName !== undefined) {
|
|
186
|
+
data.lastName = notification.lastName;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
// No type transition, just update individual fields if provided
|
|
191
|
+
if ('emailOrPhone' in notification && notification.emailOrPhone !== undefined) {
|
|
192
|
+
data.emailOrPhone = notification.emailOrPhone;
|
|
193
|
+
}
|
|
194
|
+
if ('firstName' in notification && notification.firstName !== undefined) {
|
|
195
|
+
data.firstName = notification.firstName;
|
|
196
|
+
}
|
|
197
|
+
if ('lastName' in notification && notification.lastName !== undefined) {
|
|
198
|
+
data.lastName = notification.lastName;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Handle common fields
|
|
202
|
+
if (notification.notificationType !== undefined) {
|
|
203
|
+
data.notificationType = notification.notificationType;
|
|
204
|
+
}
|
|
205
|
+
if (notification.title !== undefined) {
|
|
206
|
+
data.title = notification.title;
|
|
207
|
+
}
|
|
208
|
+
if (notification.bodyTemplate !== undefined) {
|
|
209
|
+
data.bodyTemplate = notification.bodyTemplate;
|
|
210
|
+
}
|
|
211
|
+
if (notification.contextName !== undefined) {
|
|
212
|
+
data.contextName = notification.contextName;
|
|
213
|
+
}
|
|
214
|
+
if (notification.contextParameters !== undefined) {
|
|
215
|
+
data.contextParameters = notification.contextParameters;
|
|
216
|
+
}
|
|
217
|
+
if (notification.sendAfter !== undefined) {
|
|
218
|
+
data.sendAfter = notification.sendAfter;
|
|
219
|
+
}
|
|
220
|
+
if (notification.subjectTemplate !== undefined) {
|
|
221
|
+
data.subjectTemplate = notification.subjectTemplate;
|
|
222
|
+
}
|
|
223
|
+
if (notification.status !== undefined) {
|
|
224
|
+
data.status = notification.status;
|
|
225
|
+
}
|
|
226
|
+
if (notification.contextUsed !== undefined) {
|
|
227
|
+
data.contextUsed = notification.contextUsed;
|
|
228
|
+
}
|
|
229
|
+
if (notification.extraParams !== undefined) {
|
|
230
|
+
data.extraParams = notification.extraParams;
|
|
231
|
+
}
|
|
232
|
+
if (notification.adapterUsed !== undefined) {
|
|
233
|
+
data.adapterUsed = notification.adapterUsed;
|
|
234
|
+
}
|
|
235
|
+
if (notification.sentAt !== undefined) {
|
|
236
|
+
data.sentAt = notification.sentAt;
|
|
237
|
+
}
|
|
238
|
+
if (notification.readAt !== undefined) {
|
|
239
|
+
data.readAt = notification.readAt;
|
|
240
|
+
}
|
|
241
|
+
return data;
|
|
242
|
+
}
|
|
243
|
+
deserializeNotification(notification) {
|
|
244
|
+
return this.buildCreateData(notification);
|
|
68
245
|
}
|
|
69
246
|
deserializeNotificationForUpdate(notification) {
|
|
70
247
|
return {
|
|
@@ -88,46 +265,40 @@ class PrismaNotificationBackend {
|
|
|
88
265
|
}
|
|
89
266
|
async getAllPendingNotifications() {
|
|
90
267
|
const notifications = await this.prismaClient.notification.findMany({
|
|
91
|
-
where: {
|
|
92
|
-
status: exports.NotificationStatusEnum.PENDING_SEND,
|
|
93
|
-
},
|
|
268
|
+
where: { status: exports.NotificationStatusEnum.PENDING_SEND },
|
|
94
269
|
});
|
|
95
|
-
return notifications.map(this.
|
|
270
|
+
return notifications.map((n) => this.serializeAnyNotification(n));
|
|
96
271
|
}
|
|
97
|
-
async getPendingNotifications() {
|
|
272
|
+
async getPendingNotifications(page = 0, pageSize = 100) {
|
|
98
273
|
const notifications = await this.prismaClient.notification.findMany({
|
|
99
274
|
where: {
|
|
100
275
|
status: exports.NotificationStatusEnum.PENDING_SEND,
|
|
101
276
|
sendAfter: null,
|
|
102
277
|
},
|
|
278
|
+
skip: page * pageSize,
|
|
279
|
+
take: pageSize,
|
|
103
280
|
});
|
|
104
|
-
return notifications.map(this.
|
|
281
|
+
return notifications.map((n) => this.serializeAnyNotification(n));
|
|
105
282
|
}
|
|
106
283
|
async getAllFutureNotifications() {
|
|
107
284
|
const notifications = await this.prismaClient.notification.findMany({
|
|
108
285
|
where: {
|
|
109
|
-
status: {
|
|
110
|
-
|
|
111
|
-
},
|
|
112
|
-
sendAfter: {
|
|
113
|
-
lte: new Date(),
|
|
114
|
-
},
|
|
286
|
+
status: { not: exports.NotificationStatusEnum.PENDING_SEND },
|
|
287
|
+
sendAfter: { lte: new Date() },
|
|
115
288
|
},
|
|
116
289
|
});
|
|
117
|
-
return notifications.map(this.
|
|
290
|
+
return notifications.map((n) => this.serializeAnyNotification(n));
|
|
118
291
|
}
|
|
119
|
-
async getFutureNotifications() {
|
|
292
|
+
async getFutureNotifications(page = 0, pageSize = 100) {
|
|
120
293
|
const notifications = await this.prismaClient.notification.findMany({
|
|
121
294
|
where: {
|
|
122
|
-
status: {
|
|
123
|
-
|
|
124
|
-
},
|
|
125
|
-
sendAfter: {
|
|
126
|
-
lte: new Date(),
|
|
127
|
-
},
|
|
295
|
+
status: { not: exports.NotificationStatusEnum.PENDING_SEND },
|
|
296
|
+
sendAfter: { lte: new Date() },
|
|
128
297
|
},
|
|
298
|
+
skip: page * pageSize,
|
|
299
|
+
take: pageSize,
|
|
129
300
|
});
|
|
130
|
-
return notifications.map(this.
|
|
301
|
+
return notifications.map((n) => this.serializeAnyNotification(n));
|
|
131
302
|
}
|
|
132
303
|
async getAllFutureNotificationsFromUser(userId) {
|
|
133
304
|
const notifications = await this.prismaClient.notification.findMany({
|
|
@@ -141,7 +312,7 @@ class PrismaNotificationBackend {
|
|
|
141
312
|
},
|
|
142
313
|
},
|
|
143
314
|
});
|
|
144
|
-
return notifications.map(this.
|
|
315
|
+
return notifications.map((n) => this.serializeRegularNotification(n));
|
|
145
316
|
}
|
|
146
317
|
async getFutureNotificationsFromUser(userId, page, pageSize) {
|
|
147
318
|
const notifications = await this.prismaClient.notification.findMany({
|
|
@@ -157,67 +328,124 @@ class PrismaNotificationBackend {
|
|
|
157
328
|
skip: page * pageSize,
|
|
158
329
|
take: pageSize,
|
|
159
330
|
});
|
|
160
|
-
return notifications.map(this.
|
|
331
|
+
return notifications.map((n) => this.serializeRegularNotification(n));
|
|
161
332
|
}
|
|
162
333
|
async getAllNotifications() {
|
|
163
334
|
const notifications = await this.prismaClient.notification.findMany({});
|
|
164
|
-
return notifications.map(this.
|
|
335
|
+
return notifications.map((n) => this.serializeAnyNotification(n));
|
|
165
336
|
}
|
|
166
337
|
async getNotifications(page, pageSize) {
|
|
167
338
|
const notifications = await this.prismaClient.notification.findMany({
|
|
168
339
|
skip: page * pageSize,
|
|
169
340
|
take: pageSize,
|
|
170
341
|
});
|
|
171
|
-
return notifications.map(this.
|
|
342
|
+
return notifications.map((n) => this.serializeAnyNotification(n));
|
|
172
343
|
}
|
|
173
344
|
async persistNotification(notification) {
|
|
174
|
-
|
|
175
|
-
data: this.
|
|
176
|
-
})
|
|
345
|
+
const created = await this.prismaClient.notification.create({
|
|
346
|
+
data: this.deserializeRegularNotification(notification),
|
|
347
|
+
});
|
|
348
|
+
return this.serializeRegularNotification(created);
|
|
177
349
|
}
|
|
178
350
|
async persistNotificationUpdate(notificationId, notification) {
|
|
179
|
-
|
|
351
|
+
const updated = await this.prismaClient.notification.update({
|
|
180
352
|
where: {
|
|
181
353
|
id: notificationId,
|
|
182
354
|
},
|
|
183
|
-
data: this.
|
|
184
|
-
})
|
|
355
|
+
data: this.buildUpdateData(notification),
|
|
356
|
+
});
|
|
357
|
+
return this.serializeRegularNotification(updated);
|
|
185
358
|
}
|
|
186
|
-
|
|
187
|
-
|
|
359
|
+
/* One-off notification persistence and query methods */
|
|
360
|
+
async persistOneOffNotification(notification) {
|
|
361
|
+
const created = await this.prismaClient.notification.create({
|
|
362
|
+
data: this.buildOneOffNotificationData(notification),
|
|
363
|
+
});
|
|
364
|
+
return this.serializeOneOffNotification(created);
|
|
365
|
+
}
|
|
366
|
+
async persistOneOffNotificationUpdate(notificationId, notification) {
|
|
367
|
+
const updated = await this.prismaClient.notification.update({
|
|
368
|
+
where: { id: notificationId },
|
|
369
|
+
data: this.buildUpdateData(notification),
|
|
370
|
+
});
|
|
371
|
+
return this.serializeOneOffNotification(updated);
|
|
372
|
+
}
|
|
373
|
+
async getOneOffNotification(notificationId, _forUpdate) {
|
|
374
|
+
const notification = await this.prismaClient.notification.findUnique({
|
|
188
375
|
where: {
|
|
189
376
|
id: notificationId,
|
|
190
|
-
...(checkIsPending ? { status: exports.NotificationStatusEnum.PENDING_SEND } : {}),
|
|
191
377
|
},
|
|
378
|
+
});
|
|
379
|
+
if (!notification || notification.emailOrPhone == null || notification.userId !== null) {
|
|
380
|
+
return null;
|
|
381
|
+
}
|
|
382
|
+
return this.serializeOneOffNotification(notification);
|
|
383
|
+
}
|
|
384
|
+
async getAllOneOffNotifications() {
|
|
385
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
386
|
+
where: {
|
|
387
|
+
userId: null,
|
|
388
|
+
emailOrPhone: { not: null },
|
|
389
|
+
},
|
|
390
|
+
});
|
|
391
|
+
return notifications.map((n) => this.serializeOneOffNotification(n));
|
|
392
|
+
}
|
|
393
|
+
async getOneOffNotifications(page, pageSize) {
|
|
394
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
395
|
+
where: {
|
|
396
|
+
userId: null,
|
|
397
|
+
emailOrPhone: { not: null },
|
|
398
|
+
},
|
|
399
|
+
skip: page * pageSize,
|
|
400
|
+
take: pageSize,
|
|
401
|
+
});
|
|
402
|
+
return notifications.map((n) => this.serializeOneOffNotification(n));
|
|
403
|
+
}
|
|
404
|
+
async markAsSent(notificationId, checkIsPending = true) {
|
|
405
|
+
const updated = await this.prismaClient.notification.update({
|
|
406
|
+
where: this.buildStatusWhere(notificationId, {
|
|
407
|
+
checkStatus: checkIsPending ? exports.NotificationStatusEnum.PENDING_SEND : undefined,
|
|
408
|
+
}),
|
|
192
409
|
data: {
|
|
193
410
|
status: exports.NotificationStatusEnum.SENT,
|
|
194
411
|
sentAt: new Date(),
|
|
195
412
|
},
|
|
196
|
-
})
|
|
413
|
+
});
|
|
414
|
+
return this.serializeAnyNotification(updated);
|
|
197
415
|
}
|
|
198
416
|
async markAsFailed(notificationId, checkIsPending = true) {
|
|
199
|
-
|
|
200
|
-
where: {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
},
|
|
417
|
+
const updated = await this.prismaClient.notification.update({
|
|
418
|
+
where: this.buildStatusWhere(notificationId, {
|
|
419
|
+
checkStatus: checkIsPending ? exports.NotificationStatusEnum.PENDING_SEND : undefined,
|
|
420
|
+
}),
|
|
204
421
|
data: {
|
|
205
422
|
status: exports.NotificationStatusEnum.FAILED,
|
|
206
423
|
sentAt: new Date(),
|
|
207
424
|
},
|
|
208
|
-
})
|
|
425
|
+
});
|
|
426
|
+
return this.serializeAnyNotification(updated);
|
|
209
427
|
}
|
|
210
428
|
async markAsRead(notificationId, checkIsSent = true) {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
429
|
+
// First fetch to validate it's a regular notification
|
|
430
|
+
const notification = await this.prismaClient.notification.findUnique({
|
|
431
|
+
where: { id: notificationId },
|
|
432
|
+
});
|
|
433
|
+
if (!notification) {
|
|
434
|
+
throw new Error('Notification not found');
|
|
435
|
+
}
|
|
436
|
+
if (notification.userId == null) {
|
|
437
|
+
throw new Error('Cannot mark one-off notification as read');
|
|
438
|
+
}
|
|
439
|
+
const updated = await this.prismaClient.notification.update({
|
|
440
|
+
where: this.buildStatusWhere(notificationId, {
|
|
441
|
+
checkStatus: checkIsSent ? exports.NotificationStatusEnum.SENT : undefined,
|
|
442
|
+
}),
|
|
216
443
|
data: {
|
|
217
|
-
status:
|
|
444
|
+
status: exports.NotificationStatusEnum.READ,
|
|
218
445
|
readAt: new Date(),
|
|
219
446
|
},
|
|
220
|
-
})
|
|
447
|
+
});
|
|
448
|
+
return this.serializeRegularNotification(updated);
|
|
221
449
|
}
|
|
222
450
|
async cancelNotification(notificationId) {
|
|
223
451
|
await this.prismaClient.notification.update({
|
|
@@ -231,14 +459,11 @@ class PrismaNotificationBackend {
|
|
|
231
459
|
}
|
|
232
460
|
async getNotification(notificationId, _forUpdate) {
|
|
233
461
|
const notification = await this.prismaClient.notification.findUnique({
|
|
234
|
-
where: {
|
|
235
|
-
id: notificationId,
|
|
236
|
-
},
|
|
462
|
+
where: { id: notificationId },
|
|
237
463
|
});
|
|
238
|
-
if (!notification)
|
|
464
|
+
if (!notification)
|
|
239
465
|
return null;
|
|
240
|
-
|
|
241
|
-
return this.serializeNotification(notification);
|
|
466
|
+
return this.serializeAnyNotification(notification);
|
|
242
467
|
}
|
|
243
468
|
async filterAllInAppUnreadNotifications(userId) {
|
|
244
469
|
const notifications = await this.prismaClient.notification.findMany({
|
|
@@ -248,7 +473,7 @@ class PrismaNotificationBackend {
|
|
|
248
473
|
readAt: null,
|
|
249
474
|
},
|
|
250
475
|
});
|
|
251
|
-
return notifications.map(this.
|
|
476
|
+
return notifications.map((n) => this.serializeRegularNotification(n));
|
|
252
477
|
}
|
|
253
478
|
async filterInAppUnreadNotifications(userId, page, pageSize) {
|
|
254
479
|
const notifications = await this.prismaClient.notification.findMany({
|
|
@@ -260,7 +485,7 @@ class PrismaNotificationBackend {
|
|
|
260
485
|
skip: page * pageSize,
|
|
261
486
|
take: pageSize,
|
|
262
487
|
});
|
|
263
|
-
return notifications.map(this.
|
|
488
|
+
return notifications.map((n) => this.serializeRegularNotification(n));
|
|
264
489
|
}
|
|
265
490
|
async getUserEmailFromNotification(notificationId) {
|
|
266
491
|
var _a;
|
|
@@ -276,12 +501,8 @@ class PrismaNotificationBackend {
|
|
|
276
501
|
}
|
|
277
502
|
async storeContextUsed(notificationId, context) {
|
|
278
503
|
await this.prismaClient.notification.update({
|
|
279
|
-
where: {
|
|
280
|
-
|
|
281
|
-
},
|
|
282
|
-
data: {
|
|
283
|
-
contextUsed: context,
|
|
284
|
-
},
|
|
504
|
+
where: { id: notificationId },
|
|
505
|
+
data: { contextUsed: context }
|
|
285
506
|
});
|
|
286
507
|
}
|
|
287
508
|
async bulkPersistNotifications(notifications) {
|