vintasend-prisma 0.1.5 → 0.1.6
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/{index.ts → dist/index.d.ts} +1 -1
- package/dist/index.js +5 -0
- package/dist/prisma-notification-backend.d.ts +159 -0
- package/dist/prisma-notification-backend.js +272 -0
- package/package.json +13 -7
- package/.editorconfig +0 -9
- package/biome.json +0 -34
- package/prisma-notification-backend.ts +0 -516
- package/schema.prisma.example +0 -49
|
@@ -1 +1 @@
|
|
|
1
|
-
export { PrismaNotificationBackend } from './prisma-notification-backend';
|
|
1
|
+
export { PrismaNotificationBackend } from './prisma-notification-backend';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PrismaNotificationBackend = void 0;
|
|
4
|
+
var prisma_notification_backend_1 = require("./prisma-notification-backend");
|
|
5
|
+
Object.defineProperty(exports, "PrismaNotificationBackend", { enumerable: true, get: function () { return prisma_notification_backend_1.PrismaNotificationBackend; } });
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import type { BaseNotificationBackend } from 'vintasend/dist/services/notification-backends/base-notification-backend';
|
|
2
|
+
import type { ContextGenerator } from 'vintasend/dist/services/notification-context-registry';
|
|
3
|
+
import type { InputJsonValue, JsonValue } from 'vintasend/dist/types/json-values';
|
|
4
|
+
import type { Notification, NotificationInput } from 'vintasend/dist/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 { Identifier } from 'vintasend/dist/types/identifier';
|
|
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;
|
|
24
|
+
notificationType: NotificationType;
|
|
25
|
+
title: string | null;
|
|
26
|
+
bodyTemplate: string;
|
|
27
|
+
contextName: string;
|
|
28
|
+
contextParameters: JsonValue;
|
|
29
|
+
sendAfter: Date | null;
|
|
30
|
+
subjectTemplate: string | null;
|
|
31
|
+
status: NotificationStatus;
|
|
32
|
+
contextUsed: JsonValue | null;
|
|
33
|
+
extraParams: JsonValue | null;
|
|
34
|
+
adapterUsed: string | null;
|
|
35
|
+
sentAt: Date | null;
|
|
36
|
+
readAt: Date | null;
|
|
37
|
+
createdAt: Date;
|
|
38
|
+
updatedAt: Date;
|
|
39
|
+
user?: {
|
|
40
|
+
email: string;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export interface NotificationPrismaClientInterface<NotificationIdType, UserIdType> {
|
|
44
|
+
notification: {
|
|
45
|
+
findMany(args: {
|
|
46
|
+
where?: {
|
|
47
|
+
status?: NotificationStatus | {
|
|
48
|
+
not: NotificationStatus;
|
|
49
|
+
};
|
|
50
|
+
sendAfter?: {
|
|
51
|
+
lte: Date;
|
|
52
|
+
} | null;
|
|
53
|
+
userId?: UserIdType;
|
|
54
|
+
readAt?: null;
|
|
55
|
+
};
|
|
56
|
+
skip?: number;
|
|
57
|
+
take?: number;
|
|
58
|
+
include?: {
|
|
59
|
+
user?: boolean;
|
|
60
|
+
};
|
|
61
|
+
}): Promise<PrismaNotificationModel<NotificationIdType, UserIdType>[]>;
|
|
62
|
+
create(args: {
|
|
63
|
+
data: BaseNotificationCreateInput<UserIdType>;
|
|
64
|
+
include?: {
|
|
65
|
+
user?: boolean;
|
|
66
|
+
};
|
|
67
|
+
}): Promise<PrismaNotificationModel<NotificationIdType, UserIdType>>;
|
|
68
|
+
update(args: {
|
|
69
|
+
where: {
|
|
70
|
+
id: NotificationIdType;
|
|
71
|
+
};
|
|
72
|
+
data: Partial<BaseNotificationUpdateInput<UserIdType>>;
|
|
73
|
+
include?: {
|
|
74
|
+
user?: boolean;
|
|
75
|
+
};
|
|
76
|
+
}): Promise<PrismaNotificationModel<NotificationIdType, UserIdType>>;
|
|
77
|
+
findUnique(args: {
|
|
78
|
+
where: {
|
|
79
|
+
id: NotificationIdType;
|
|
80
|
+
};
|
|
81
|
+
include?: {
|
|
82
|
+
user?: boolean;
|
|
83
|
+
};
|
|
84
|
+
}): Promise<PrismaNotificationModel<NotificationIdType, UserIdType> | null>;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
type NoExpand<T> = T extends unknown ? T : never;
|
|
88
|
+
type AtLeast<O extends object, K extends string> = NoExpand<O extends unknown ? (K extends keyof O ? {
|
|
89
|
+
[P in K]: O[P];
|
|
90
|
+
} & O : O) | ({
|
|
91
|
+
[P in keyof O as P extends K ? K : never]-?: O[P];
|
|
92
|
+
} & O) : never>;
|
|
93
|
+
export interface BaseNotificationCreateInput<UserIdType> {
|
|
94
|
+
user: {
|
|
95
|
+
connect?: AtLeast<{
|
|
96
|
+
id?: UserIdType;
|
|
97
|
+
email?: string;
|
|
98
|
+
}, 'id' | 'email'>;
|
|
99
|
+
};
|
|
100
|
+
notificationType: NotificationType;
|
|
101
|
+
title?: string | null;
|
|
102
|
+
bodyTemplate: string;
|
|
103
|
+
contextName: string;
|
|
104
|
+
contextParameters: InputJsonValue;
|
|
105
|
+
sendAfter?: Date | null;
|
|
106
|
+
subjectTemplate?: string | null;
|
|
107
|
+
status?: NotificationStatus;
|
|
108
|
+
contextUsed?: InputJsonValue;
|
|
109
|
+
extraParams?: InputJsonValue;
|
|
110
|
+
adapterUsed?: string | null;
|
|
111
|
+
sentAt?: Date | null;
|
|
112
|
+
readAt?: Date | null;
|
|
113
|
+
}
|
|
114
|
+
export interface BaseNotificationUpdateInput<UserIdType> {
|
|
115
|
+
user: {
|
|
116
|
+
connect?: AtLeast<{
|
|
117
|
+
id?: UserIdType;
|
|
118
|
+
email?: string;
|
|
119
|
+
}, 'id' | 'email'>;
|
|
120
|
+
};
|
|
121
|
+
notificationType?: NotificationType;
|
|
122
|
+
title?: string | null;
|
|
123
|
+
bodyTemplate?: string;
|
|
124
|
+
contextName?: string;
|
|
125
|
+
contextParameters?: InputJsonValue;
|
|
126
|
+
sendAfter?: Date | null;
|
|
127
|
+
subjectTemplate?: string | null;
|
|
128
|
+
status?: NotificationStatus;
|
|
129
|
+
contextUsed?: InputJsonValue;
|
|
130
|
+
extraParams?: InputJsonValue;
|
|
131
|
+
adapterUsed?: string | null;
|
|
132
|
+
sentAt?: Date | null;
|
|
133
|
+
readAt?: Date | null;
|
|
134
|
+
}
|
|
135
|
+
export declare class PrismaNotificationBackend<Client extends NotificationPrismaClientInterface<NotificationIdType, UserIdType>, AvailableContexts extends Record<string, ContextGenerator>, NotificationIdType extends Identifier = Identifier, UserIdType extends Identifier = Identifier> implements BaseNotificationBackend<AvailableContexts, NotificationIdType, UserIdType> {
|
|
136
|
+
private prismaClient;
|
|
137
|
+
constructor(prismaClient: Client);
|
|
138
|
+
serializeNotification(notification: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>): Notification<AvailableContexts, NotificationIdType, UserIdType>;
|
|
139
|
+
deserializeNotification(notification: NotificationInput<AvailableContexts, UserIdType>): BaseNotificationCreateInput<UserIdType>;
|
|
140
|
+
deserializeNotificationForUpdate(notification: Partial<Notification<AvailableContexts, NotificationIdType, UserIdType>>): Partial<Parameters<typeof this.prismaClient.notification.update>[0]['data']>;
|
|
141
|
+
getAllPendingNotifications(): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>[]>;
|
|
142
|
+
getPendingNotifications(): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>[]>;
|
|
143
|
+
getAllFutureNotifications(): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>[]>;
|
|
144
|
+
getFutureNotifications(): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>[]>;
|
|
145
|
+
getAllFutureNotificationsFromUser(userId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['userId']): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>[]>;
|
|
146
|
+
getFutureNotificationsFromUser(userId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['userId']): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>[]>;
|
|
147
|
+
persistNotification(notification: NotificationInput<AvailableContexts, UserIdType>): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>>;
|
|
148
|
+
persistNotificationUpdate(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], notification: Partial<Omit<Notification<AvailableContexts, NotificationIdType, UserIdType>, 'id'>>): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>>;
|
|
149
|
+
markPendingAsSent(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id']): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>>;
|
|
150
|
+
markPendingAsFailed(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id']): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>>;
|
|
151
|
+
markSentAsRead(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id']): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>>;
|
|
152
|
+
cancelNotification(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id']): Promise<void>;
|
|
153
|
+
getNotification(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], _forUpdate: boolean): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType> | null>;
|
|
154
|
+
filterAllInAppUnreadNotifications(userId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['userId']): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>[]>;
|
|
155
|
+
filterInAppUnreadNotifications(userId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['userId'], page: number, pageSize: number): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>[]>;
|
|
156
|
+
getUserEmailFromNotification(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id']): Promise<string | undefined>;
|
|
157
|
+
storeContextUsed(notificationId: NonNullable<Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>>['id'], context: InputJsonValue): Promise<void>;
|
|
158
|
+
}
|
|
159
|
+
export {};
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
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) && jsonValue !== null) {
|
|
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
|
+
serializeNotification(notification) {
|
|
28
|
+
return {
|
|
29
|
+
id: notification.id,
|
|
30
|
+
userId: notification.userId,
|
|
31
|
+
notificationType: notification.notificationType,
|
|
32
|
+
title: notification.title,
|
|
33
|
+
bodyTemplate: notification.bodyTemplate,
|
|
34
|
+
contextName: notification.contextName,
|
|
35
|
+
contextParameters: notification.contextParameters
|
|
36
|
+
? notification.contextParameters
|
|
37
|
+
: {},
|
|
38
|
+
sendAfter: notification.sendAfter,
|
|
39
|
+
subjectTemplate: notification.subjectTemplate,
|
|
40
|
+
status: notification.status,
|
|
41
|
+
contextUsed: notification.contextUsed,
|
|
42
|
+
extraParams: notification.extraParams
|
|
43
|
+
? convertJsonValueToRecord(notification.extraParams)
|
|
44
|
+
: null,
|
|
45
|
+
adapterUsed: notification.adapterUsed,
|
|
46
|
+
sentAt: notification.sentAt,
|
|
47
|
+
readAt: notification.readAt,
|
|
48
|
+
createdAt: notification.createdAt,
|
|
49
|
+
updatedAt: notification.updatedAt,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
deserializeNotification(notification) {
|
|
53
|
+
return {
|
|
54
|
+
user: {
|
|
55
|
+
connect: {
|
|
56
|
+
id: notification.userId,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
notificationType: notification.notificationType,
|
|
60
|
+
title: notification.title,
|
|
61
|
+
bodyTemplate: notification.bodyTemplate,
|
|
62
|
+
contextName: notification.contextName,
|
|
63
|
+
contextParameters: notification.contextParameters,
|
|
64
|
+
sendAfter: notification.sendAfter,
|
|
65
|
+
subjectTemplate: notification.subjectTemplate,
|
|
66
|
+
extraParams: notification.extraParams,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
deserializeNotificationForUpdate(notification) {
|
|
70
|
+
return {
|
|
71
|
+
...(notification.userId ? { user: { connect: { id: notification.userId } } } : {}),
|
|
72
|
+
...(notification.notificationType
|
|
73
|
+
? {
|
|
74
|
+
notificationType: exports.NotificationTypeEnum[notification.notificationType],
|
|
75
|
+
}
|
|
76
|
+
: {}),
|
|
77
|
+
...(notification.title ? { title: notification.title } : {}),
|
|
78
|
+
...(notification.bodyTemplate ? { bodyTemplate: notification.bodyTemplate } : {}),
|
|
79
|
+
...(notification.contextName ? { contextName: notification.contextName } : {}),
|
|
80
|
+
...(notification.contextParameters
|
|
81
|
+
? {
|
|
82
|
+
contextParameters: notification.contextParameters ? notification.contextParameters : {},
|
|
83
|
+
}
|
|
84
|
+
: {}),
|
|
85
|
+
...(notification.sendAfter ? { sendAfter: notification.sendAfter } : {}),
|
|
86
|
+
...(notification.subjectTemplate ? { subjectTemplate: notification.subjectTemplate } : {}),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
async getAllPendingNotifications() {
|
|
90
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
91
|
+
where: {
|
|
92
|
+
status: exports.NotificationStatusEnum.PENDING_SEND,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
return notifications.map(this.serializeNotification);
|
|
96
|
+
}
|
|
97
|
+
async getPendingNotifications() {
|
|
98
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
99
|
+
where: {
|
|
100
|
+
status: exports.NotificationStatusEnum.PENDING_SEND,
|
|
101
|
+
sendAfter: null,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
return notifications.map(this.serializeNotification);
|
|
105
|
+
}
|
|
106
|
+
async getAllFutureNotifications() {
|
|
107
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
108
|
+
where: {
|
|
109
|
+
status: {
|
|
110
|
+
not: exports.NotificationStatusEnum.PENDING_SEND,
|
|
111
|
+
},
|
|
112
|
+
sendAfter: {
|
|
113
|
+
lte: new Date(),
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
return notifications.map(this.serializeNotification);
|
|
118
|
+
}
|
|
119
|
+
async getFutureNotifications() {
|
|
120
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
121
|
+
where: {
|
|
122
|
+
status: {
|
|
123
|
+
not: exports.NotificationStatusEnum.PENDING_SEND,
|
|
124
|
+
},
|
|
125
|
+
sendAfter: {
|
|
126
|
+
lte: new Date(),
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
return notifications.map(this.serializeNotification);
|
|
131
|
+
}
|
|
132
|
+
async getAllFutureNotificationsFromUser(userId) {
|
|
133
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
134
|
+
where: {
|
|
135
|
+
userId,
|
|
136
|
+
status: {
|
|
137
|
+
not: exports.NotificationStatusEnum.PENDING_SEND,
|
|
138
|
+
},
|
|
139
|
+
sendAfter: {
|
|
140
|
+
lte: new Date(),
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
return notifications.map(this.serializeNotification);
|
|
145
|
+
}
|
|
146
|
+
async getFutureNotificationsFromUser(userId) {
|
|
147
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
148
|
+
where: {
|
|
149
|
+
userId,
|
|
150
|
+
status: {
|
|
151
|
+
not: exports.NotificationStatusEnum.PENDING_SEND,
|
|
152
|
+
},
|
|
153
|
+
sendAfter: {
|
|
154
|
+
lte: new Date(),
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
return notifications.map(this.serializeNotification);
|
|
159
|
+
}
|
|
160
|
+
async persistNotification(notification) {
|
|
161
|
+
return this.serializeNotification(await this.prismaClient.notification.create({
|
|
162
|
+
data: this.deserializeNotification(notification),
|
|
163
|
+
}));
|
|
164
|
+
}
|
|
165
|
+
async persistNotificationUpdate(notificationId, notification) {
|
|
166
|
+
return this.serializeNotification(await this.prismaClient.notification.update({
|
|
167
|
+
where: {
|
|
168
|
+
id: notificationId,
|
|
169
|
+
},
|
|
170
|
+
data: this.deserializeNotificationForUpdate(notification),
|
|
171
|
+
}));
|
|
172
|
+
}
|
|
173
|
+
async markPendingAsSent(notificationId) {
|
|
174
|
+
return this.serializeNotification(await this.prismaClient.notification.update({
|
|
175
|
+
where: {
|
|
176
|
+
id: notificationId,
|
|
177
|
+
},
|
|
178
|
+
data: {
|
|
179
|
+
status: exports.NotificationStatusEnum.SENT,
|
|
180
|
+
sentAt: new Date(),
|
|
181
|
+
},
|
|
182
|
+
}));
|
|
183
|
+
}
|
|
184
|
+
async markPendingAsFailed(notificationId) {
|
|
185
|
+
return this.serializeNotification(await this.prismaClient.notification.update({
|
|
186
|
+
where: {
|
|
187
|
+
id: notificationId,
|
|
188
|
+
},
|
|
189
|
+
data: {
|
|
190
|
+
status: exports.NotificationStatusEnum.FAILED,
|
|
191
|
+
sentAt: new Date(),
|
|
192
|
+
},
|
|
193
|
+
}));
|
|
194
|
+
}
|
|
195
|
+
async markSentAsRead(notificationId) {
|
|
196
|
+
return this.serializeNotification(await this.prismaClient.notification.update({
|
|
197
|
+
where: {
|
|
198
|
+
id: notificationId,
|
|
199
|
+
},
|
|
200
|
+
data: {
|
|
201
|
+
status: 'READ',
|
|
202
|
+
readAt: new Date(),
|
|
203
|
+
},
|
|
204
|
+
}));
|
|
205
|
+
}
|
|
206
|
+
async cancelNotification(notificationId) {
|
|
207
|
+
await this.prismaClient.notification.update({
|
|
208
|
+
where: {
|
|
209
|
+
id: notificationId,
|
|
210
|
+
},
|
|
211
|
+
data: {
|
|
212
|
+
status: exports.NotificationStatusEnum.CANCELLED,
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
async getNotification(notificationId, _forUpdate) {
|
|
217
|
+
const notification = await this.prismaClient.notification.findUnique({
|
|
218
|
+
where: {
|
|
219
|
+
id: notificationId,
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
if (!notification) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
return this.serializeNotification(notification);
|
|
226
|
+
}
|
|
227
|
+
async filterAllInAppUnreadNotifications(userId) {
|
|
228
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
229
|
+
where: {
|
|
230
|
+
userId,
|
|
231
|
+
status: 'SENT',
|
|
232
|
+
readAt: null,
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
return notifications.map(this.serializeNotification);
|
|
236
|
+
}
|
|
237
|
+
async filterInAppUnreadNotifications(userId, page, pageSize) {
|
|
238
|
+
const notifications = await this.prismaClient.notification.findMany({
|
|
239
|
+
where: {
|
|
240
|
+
userId,
|
|
241
|
+
status: 'SENT',
|
|
242
|
+
readAt: null,
|
|
243
|
+
},
|
|
244
|
+
skip: page * pageSize,
|
|
245
|
+
take: pageSize,
|
|
246
|
+
});
|
|
247
|
+
return notifications.map(this.serializeNotification);
|
|
248
|
+
}
|
|
249
|
+
async getUserEmailFromNotification(notificationId) {
|
|
250
|
+
var _a;
|
|
251
|
+
const notification = await this.prismaClient.notification.findUnique({
|
|
252
|
+
where: {
|
|
253
|
+
id: notificationId,
|
|
254
|
+
},
|
|
255
|
+
include: {
|
|
256
|
+
user: true,
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
return (_a = notification === null || notification === void 0 ? void 0 : notification.user) === null || _a === void 0 ? void 0 : _a.email;
|
|
260
|
+
}
|
|
261
|
+
async storeContextUsed(notificationId, context) {
|
|
262
|
+
await this.prismaClient.notification.update({
|
|
263
|
+
where: {
|
|
264
|
+
id: notificationId,
|
|
265
|
+
},
|
|
266
|
+
data: {
|
|
267
|
+
contextUsed: context,
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
exports.PrismaNotificationBackend = PrismaNotificationBackend;
|
package/package.json
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vintasend-prisma",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "VintaSend Backend implementation for Prisma",
|
|
5
|
-
"main": "index.js",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"
|
|
8
|
-
"
|
|
7
|
+
"build": "tsc",
|
|
8
|
+
"prepublishOnly": "npm run build"
|
|
9
9
|
},
|
|
10
|
-
"
|
|
11
|
-
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"author": "Hugo Bessa",
|
|
14
|
+
"license": "MIT",
|
|
12
15
|
"dependencies": {
|
|
13
16
|
"@prisma/client": "^6.3.1",
|
|
14
17
|
"prisma": "^6.3.1",
|
|
15
|
-
"vintasend": "^0.1.
|
|
18
|
+
"vintasend": "^0.1.6"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"typescript": "^5.8.2"
|
|
16
22
|
}
|
|
17
23
|
}
|
package/.editorconfig
DELETED
package/biome.json
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
|
|
3
|
-
"vcs": {
|
|
4
|
-
"enabled": false,
|
|
5
|
-
"clientKind": "git",
|
|
6
|
-
"useIgnoreFile": false
|
|
7
|
-
},
|
|
8
|
-
"files": {
|
|
9
|
-
"ignoreUnknown": false,
|
|
10
|
-
"ignore": []
|
|
11
|
-
},
|
|
12
|
-
"formatter": {
|
|
13
|
-
"enabled": true,
|
|
14
|
-
"indentStyle": "space",
|
|
15
|
-
"indentWidth": 2,
|
|
16
|
-
"lineWidth": 100
|
|
17
|
-
},
|
|
18
|
-
"organizeImports": {
|
|
19
|
-
"enabled": true
|
|
20
|
-
},
|
|
21
|
-
"linter": {
|
|
22
|
-
"enabled": true,
|
|
23
|
-
"rules": {
|
|
24
|
-
"recommended": true
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
"javascript": {
|
|
28
|
-
"formatter": {
|
|
29
|
-
"quoteStyle": "single",
|
|
30
|
-
"semicolons": "always",
|
|
31
|
-
"trailingCommas": "all"
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -1,516 +0,0 @@
|
|
|
1
|
-
import type { BaseNotificationBackend } from 'vintasend/src/services/notification-backends/base-notification-backend';
|
|
2
|
-
import type { ContextGenerator } from 'vintasend/src/services/notification-context-registry';
|
|
3
|
-
import type { InputJsonValue, JsonValue } from 'vintasend/src/types/json-values';
|
|
4
|
-
import type { Notification, NotificationInput } from 'vintasend/src/types/notification';
|
|
5
|
-
import type { NotificationStatus } from 'vintasend/src/types/notification-status';
|
|
6
|
-
import type { NotificationType } from 'vintasend/src/types/notification-type';
|
|
7
|
-
import type { Identifier } from 'vintasend/src/types/identifier';
|
|
8
|
-
|
|
9
|
-
export const NotificationStatusEnum = {
|
|
10
|
-
PENDING_SEND: 'PENDING_SEND',
|
|
11
|
-
SENT: 'SENT',
|
|
12
|
-
FAILED: 'FAILED',
|
|
13
|
-
READ: 'READ',
|
|
14
|
-
CANCELLED: 'CANCELLED',
|
|
15
|
-
} as const;
|
|
16
|
-
|
|
17
|
-
export const NotificationTypeEnum = {
|
|
18
|
-
EMAIL: 'EMAIL',
|
|
19
|
-
PUSH: 'PUSH',
|
|
20
|
-
SMS: 'SMS',
|
|
21
|
-
IN_APP: 'IN_APP',
|
|
22
|
-
} as const;
|
|
23
|
-
|
|
24
|
-
export interface PrismaNotificationModel<IdType, UserId> {
|
|
25
|
-
id: IdType;
|
|
26
|
-
userId: UserId;
|
|
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
|
-
|
|
47
|
-
export interface NotificationPrismaClientInterface<NotificationIdType, UserIdType> {
|
|
48
|
-
notification: {
|
|
49
|
-
findMany(args: {
|
|
50
|
-
where?: {
|
|
51
|
-
status?: NotificationStatus | { not: NotificationStatus };
|
|
52
|
-
sendAfter?: { lte: Date } | null;
|
|
53
|
-
userId?: UserIdType;
|
|
54
|
-
readAt?: null;
|
|
55
|
-
};
|
|
56
|
-
skip?: number;
|
|
57
|
-
take?: number;
|
|
58
|
-
include?: { user?: boolean };
|
|
59
|
-
}): Promise<PrismaNotificationModel<NotificationIdType, UserIdType>[]>;
|
|
60
|
-
create(args: {
|
|
61
|
-
data: BaseNotificationCreateInput<UserIdType>;
|
|
62
|
-
include?: { user?: boolean };
|
|
63
|
-
}): Promise<PrismaNotificationModel<NotificationIdType, UserIdType>>;
|
|
64
|
-
update(args: {
|
|
65
|
-
where: { id: NotificationIdType };
|
|
66
|
-
data: Partial<BaseNotificationUpdateInput<UserIdType>>;
|
|
67
|
-
include?: { user?: boolean };
|
|
68
|
-
}): Promise<PrismaNotificationModel<NotificationIdType, UserIdType>>;
|
|
69
|
-
findUnique(args: {
|
|
70
|
-
where: { id: NotificationIdType };
|
|
71
|
-
include?: { user?: boolean };
|
|
72
|
-
}): Promise<PrismaNotificationModel<NotificationIdType, UserIdType> | null>;
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// cause typescript not to expand types and preserve names
|
|
77
|
-
type NoExpand<T> = T extends unknown ? T : never;
|
|
78
|
-
|
|
79
|
-
// this type assumes the passed object is entirely optional
|
|
80
|
-
type AtLeast<O extends object, K extends string> = NoExpand<
|
|
81
|
-
O extends unknown
|
|
82
|
-
?
|
|
83
|
-
| (K extends keyof O ? { [P in K]: O[P] } & O : O)
|
|
84
|
-
| ({ [P in keyof O as P extends K ? K : never]-?: O[P] } & O)
|
|
85
|
-
: never
|
|
86
|
-
>;
|
|
87
|
-
|
|
88
|
-
export interface BaseNotificationCreateInput<UserIdType> {
|
|
89
|
-
user: {
|
|
90
|
-
connect?: AtLeast<
|
|
91
|
-
{
|
|
92
|
-
id?: UserIdType;
|
|
93
|
-
email?: string;
|
|
94
|
-
},
|
|
95
|
-
'id' | 'email'
|
|
96
|
-
>;
|
|
97
|
-
};
|
|
98
|
-
notificationType: NotificationType;
|
|
99
|
-
title?: string | null;
|
|
100
|
-
bodyTemplate: string;
|
|
101
|
-
contextName: string;
|
|
102
|
-
contextParameters: InputJsonValue;
|
|
103
|
-
sendAfter?: Date | null;
|
|
104
|
-
subjectTemplate?: string | null;
|
|
105
|
-
status?: NotificationStatus;
|
|
106
|
-
contextUsed?: InputJsonValue;
|
|
107
|
-
extraParams?: InputJsonValue;
|
|
108
|
-
adapterUsed?: string | null;
|
|
109
|
-
sentAt?: Date | null;
|
|
110
|
-
readAt?: Date | null;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export interface BaseNotificationUpdateInput<UserIdType> {
|
|
114
|
-
user: {
|
|
115
|
-
connect?: AtLeast<
|
|
116
|
-
{
|
|
117
|
-
id?: UserIdType;
|
|
118
|
-
email?: string;
|
|
119
|
-
},
|
|
120
|
-
'id' | 'email'
|
|
121
|
-
>;
|
|
122
|
-
};
|
|
123
|
-
notificationType?: NotificationType;
|
|
124
|
-
title?: string | null;
|
|
125
|
-
bodyTemplate?: string;
|
|
126
|
-
contextName?: string;
|
|
127
|
-
contextParameters?: InputJsonValue;
|
|
128
|
-
sendAfter?: Date | null;
|
|
129
|
-
subjectTemplate?: string | null;
|
|
130
|
-
status?: NotificationStatus;
|
|
131
|
-
contextUsed?: InputJsonValue;
|
|
132
|
-
extraParams?: InputJsonValue;
|
|
133
|
-
adapterUsed?: string | null;
|
|
134
|
-
sentAt?: Date | null;
|
|
135
|
-
readAt?: Date | null;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
function convertJsonValueToRecord(jsonValue: JsonValue): Record<string, string | number | boolean> {
|
|
139
|
-
if (typeof jsonValue === 'object' && !Array.isArray(jsonValue) && jsonValue !== null) {
|
|
140
|
-
return jsonValue as Record<string, string | number | boolean>;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
throw new Error('Invalid JSON value. It should be an object.');
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
export class PrismaNotificationBackend<
|
|
147
|
-
Client extends NotificationPrismaClientInterface<NotificationIdType, UserIdType>,
|
|
148
|
-
AvailableContexts extends Record<string, ContextGenerator>,
|
|
149
|
-
NotificationIdType extends Identifier = Identifier,
|
|
150
|
-
UserIdType extends Identifier = Identifier,
|
|
151
|
-
> implements BaseNotificationBackend<AvailableContexts, NotificationIdType, UserIdType>
|
|
152
|
-
{
|
|
153
|
-
constructor(private prismaClient: Client) {}
|
|
154
|
-
|
|
155
|
-
serializeNotification(
|
|
156
|
-
notification: NonNullable<
|
|
157
|
-
Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>
|
|
158
|
-
>,
|
|
159
|
-
): Notification<AvailableContexts, NotificationIdType, UserIdType> {
|
|
160
|
-
return {
|
|
161
|
-
id: notification.id,
|
|
162
|
-
userId: notification.userId,
|
|
163
|
-
notificationType: notification.notificationType,
|
|
164
|
-
title: notification.title,
|
|
165
|
-
bodyTemplate: notification.bodyTemplate,
|
|
166
|
-
contextName: notification.contextName as keyof AvailableContexts,
|
|
167
|
-
contextParameters: notification.contextParameters
|
|
168
|
-
? (notification.contextParameters as Parameters<
|
|
169
|
-
AvailableContexts[keyof AvailableContexts]['generate']
|
|
170
|
-
>[0])
|
|
171
|
-
: {},
|
|
172
|
-
sendAfter: notification.sendAfter,
|
|
173
|
-
subjectTemplate: notification.subjectTemplate,
|
|
174
|
-
status: notification.status,
|
|
175
|
-
contextUsed: notification.contextUsed as ReturnType<
|
|
176
|
-
AvailableContexts[keyof AvailableContexts]['generate']
|
|
177
|
-
> | null,
|
|
178
|
-
extraParams: notification.extraParams
|
|
179
|
-
? convertJsonValueToRecord(notification.extraParams)
|
|
180
|
-
: null,
|
|
181
|
-
adapterUsed: notification.adapterUsed,
|
|
182
|
-
sentAt: notification.sentAt,
|
|
183
|
-
readAt: notification.readAt,
|
|
184
|
-
createdAt: notification.createdAt,
|
|
185
|
-
updatedAt: notification.updatedAt,
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
deserializeNotification(
|
|
190
|
-
notification: NotificationInput<AvailableContexts, UserIdType>,
|
|
191
|
-
): BaseNotificationCreateInput<UserIdType> {
|
|
192
|
-
return {
|
|
193
|
-
user: {
|
|
194
|
-
connect: {
|
|
195
|
-
id: notification.userId,
|
|
196
|
-
},
|
|
197
|
-
},
|
|
198
|
-
notificationType: notification.notificationType,
|
|
199
|
-
title: notification.title,
|
|
200
|
-
bodyTemplate: notification.bodyTemplate,
|
|
201
|
-
contextName: notification.contextName as string,
|
|
202
|
-
contextParameters: notification.contextParameters as InputJsonValue,
|
|
203
|
-
sendAfter: notification.sendAfter,
|
|
204
|
-
subjectTemplate: notification.subjectTemplate,
|
|
205
|
-
extraParams: notification.extraParams as InputJsonValue,
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
deserializeNotificationForUpdate(
|
|
210
|
-
notification: Partial<Notification<AvailableContexts, NotificationIdType, UserIdType>>,
|
|
211
|
-
): Partial<Parameters<typeof this.prismaClient.notification.update>[0]['data']> {
|
|
212
|
-
return {
|
|
213
|
-
...(notification.userId ? { user: { connect: { id: notification.userId } } } : {}),
|
|
214
|
-
...(notification.notificationType
|
|
215
|
-
? {
|
|
216
|
-
notificationType: NotificationTypeEnum[
|
|
217
|
-
notification.notificationType as keyof typeof NotificationTypeEnum
|
|
218
|
-
] as NotificationType,
|
|
219
|
-
}
|
|
220
|
-
: {}),
|
|
221
|
-
...(notification.title ? { title: notification.title } : {}),
|
|
222
|
-
...(notification.bodyTemplate ? { bodyTemplate: notification.bodyTemplate } : {}),
|
|
223
|
-
...(notification.contextName ? { contextName: notification.contextName } : {}),
|
|
224
|
-
...(notification.contextParameters
|
|
225
|
-
? {
|
|
226
|
-
contextParameters: notification.contextParameters ? notification.contextParameters : {},
|
|
227
|
-
}
|
|
228
|
-
: {}),
|
|
229
|
-
...(notification.sendAfter ? { sendAfter: notification.sendAfter } : {}),
|
|
230
|
-
...(notification.subjectTemplate ? { subjectTemplate: notification.subjectTemplate } : {}),
|
|
231
|
-
} as Partial<Parameters<typeof this.prismaClient.notification.update>[0]['data']>;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
async getAllPendingNotifications(): Promise<
|
|
235
|
-
Notification<AvailableContexts, NotificationIdType, UserIdType>[]
|
|
236
|
-
> {
|
|
237
|
-
const notifications = await this.prismaClient.notification.findMany({
|
|
238
|
-
where: {
|
|
239
|
-
status: NotificationStatusEnum.PENDING_SEND,
|
|
240
|
-
},
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
return notifications.map(this.serializeNotification);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
async getPendingNotifications(): Promise<
|
|
247
|
-
Notification<AvailableContexts, NotificationIdType, UserIdType>[]
|
|
248
|
-
> {
|
|
249
|
-
const notifications = await this.prismaClient.notification.findMany({
|
|
250
|
-
where: {
|
|
251
|
-
status: NotificationStatusEnum.PENDING_SEND,
|
|
252
|
-
sendAfter: null,
|
|
253
|
-
},
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
return notifications.map(this.serializeNotification);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
async getAllFutureNotifications(): Promise<
|
|
260
|
-
Notification<AvailableContexts, NotificationIdType, UserIdType>[]
|
|
261
|
-
> {
|
|
262
|
-
const notifications = await this.prismaClient.notification.findMany({
|
|
263
|
-
where: {
|
|
264
|
-
status: {
|
|
265
|
-
not: NotificationStatusEnum.PENDING_SEND,
|
|
266
|
-
},
|
|
267
|
-
sendAfter: {
|
|
268
|
-
lte: new Date(),
|
|
269
|
-
},
|
|
270
|
-
},
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
return notifications.map(this.serializeNotification);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
async getFutureNotifications(): Promise<
|
|
277
|
-
Notification<AvailableContexts, NotificationIdType, UserIdType>[]
|
|
278
|
-
> {
|
|
279
|
-
const notifications = await this.prismaClient.notification.findMany({
|
|
280
|
-
where: {
|
|
281
|
-
status: {
|
|
282
|
-
not: NotificationStatusEnum.PENDING_SEND,
|
|
283
|
-
},
|
|
284
|
-
sendAfter: {
|
|
285
|
-
lte: new Date(),
|
|
286
|
-
},
|
|
287
|
-
},
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
return notifications.map(this.serializeNotification);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
async getAllFutureNotificationsFromUser(
|
|
294
|
-
userId: NonNullable<
|
|
295
|
-
Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>
|
|
296
|
-
>['userId'],
|
|
297
|
-
): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>[]> {
|
|
298
|
-
const notifications = await this.prismaClient.notification.findMany({
|
|
299
|
-
where: {
|
|
300
|
-
userId,
|
|
301
|
-
status: {
|
|
302
|
-
not: NotificationStatusEnum.PENDING_SEND,
|
|
303
|
-
},
|
|
304
|
-
sendAfter: {
|
|
305
|
-
lte: new Date(),
|
|
306
|
-
},
|
|
307
|
-
},
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
return notifications.map(this.serializeNotification);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
async getFutureNotificationsFromUser(
|
|
314
|
-
userId: NonNullable<
|
|
315
|
-
Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>
|
|
316
|
-
>['userId'],
|
|
317
|
-
): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>[]> {
|
|
318
|
-
const notifications = await this.prismaClient.notification.findMany({
|
|
319
|
-
where: {
|
|
320
|
-
userId,
|
|
321
|
-
status: {
|
|
322
|
-
not: NotificationStatusEnum.PENDING_SEND,
|
|
323
|
-
},
|
|
324
|
-
sendAfter: {
|
|
325
|
-
lte: new Date(),
|
|
326
|
-
},
|
|
327
|
-
},
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
return notifications.map(this.serializeNotification);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
async persistNotification(
|
|
334
|
-
notification: NotificationInput<AvailableContexts, UserIdType>,
|
|
335
|
-
): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>> {
|
|
336
|
-
return this.serializeNotification(
|
|
337
|
-
await this.prismaClient.notification.create({
|
|
338
|
-
data: this.deserializeNotification(notification),
|
|
339
|
-
}),
|
|
340
|
-
);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
async persistNotificationUpdate(
|
|
344
|
-
notificationId: NonNullable<
|
|
345
|
-
Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>
|
|
346
|
-
>['id'],
|
|
347
|
-
notification: Partial<
|
|
348
|
-
Omit<Notification<AvailableContexts, NotificationIdType, UserIdType>, 'id'>
|
|
349
|
-
>,
|
|
350
|
-
): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>> {
|
|
351
|
-
return this.serializeNotification(
|
|
352
|
-
await this.prismaClient.notification.update({
|
|
353
|
-
where: {
|
|
354
|
-
id: notificationId,
|
|
355
|
-
},
|
|
356
|
-
data: this.deserializeNotificationForUpdate(notification),
|
|
357
|
-
}),
|
|
358
|
-
);
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
async markPendingAsSent(
|
|
362
|
-
notificationId: NonNullable<
|
|
363
|
-
Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>
|
|
364
|
-
>['id'],
|
|
365
|
-
): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>> {
|
|
366
|
-
return this.serializeNotification(
|
|
367
|
-
await this.prismaClient.notification.update({
|
|
368
|
-
where: {
|
|
369
|
-
id: notificationId,
|
|
370
|
-
},
|
|
371
|
-
data: {
|
|
372
|
-
status: NotificationStatusEnum.SENT,
|
|
373
|
-
sentAt: new Date(),
|
|
374
|
-
},
|
|
375
|
-
}),
|
|
376
|
-
);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
async markPendingAsFailed(
|
|
380
|
-
notificationId: NonNullable<
|
|
381
|
-
Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>
|
|
382
|
-
>['id'],
|
|
383
|
-
): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>> {
|
|
384
|
-
return this.serializeNotification(
|
|
385
|
-
await this.prismaClient.notification.update({
|
|
386
|
-
where: {
|
|
387
|
-
id: notificationId,
|
|
388
|
-
},
|
|
389
|
-
data: {
|
|
390
|
-
status: NotificationStatusEnum.FAILED,
|
|
391
|
-
sentAt: new Date(),
|
|
392
|
-
},
|
|
393
|
-
}),
|
|
394
|
-
);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
async markSentAsRead(
|
|
398
|
-
notificationId: NonNullable<
|
|
399
|
-
Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>
|
|
400
|
-
>['id'],
|
|
401
|
-
): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>> {
|
|
402
|
-
return this.serializeNotification(
|
|
403
|
-
await this.prismaClient.notification.update({
|
|
404
|
-
where: {
|
|
405
|
-
id: notificationId,
|
|
406
|
-
},
|
|
407
|
-
data: {
|
|
408
|
-
status: 'READ',
|
|
409
|
-
readAt: new Date(),
|
|
410
|
-
},
|
|
411
|
-
}),
|
|
412
|
-
);
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
async cancelNotification(
|
|
416
|
-
notificationId: NonNullable<
|
|
417
|
-
Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>
|
|
418
|
-
>['id'],
|
|
419
|
-
): Promise<void> {
|
|
420
|
-
await this.prismaClient.notification.update({
|
|
421
|
-
where: {
|
|
422
|
-
id: notificationId,
|
|
423
|
-
},
|
|
424
|
-
data: {
|
|
425
|
-
status: NotificationStatusEnum.CANCELLED,
|
|
426
|
-
},
|
|
427
|
-
});
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
async getNotification(
|
|
431
|
-
notificationId: NonNullable<
|
|
432
|
-
Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>
|
|
433
|
-
>['id'],
|
|
434
|
-
_forUpdate: boolean,
|
|
435
|
-
): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType> | null> {
|
|
436
|
-
const notification = await this.prismaClient.notification.findUnique({
|
|
437
|
-
where: {
|
|
438
|
-
id: notificationId,
|
|
439
|
-
},
|
|
440
|
-
});
|
|
441
|
-
if (!notification) {
|
|
442
|
-
return null;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
return this.serializeNotification(notification);
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
async filterAllInAppUnreadNotifications(
|
|
449
|
-
userId: NonNullable<
|
|
450
|
-
Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>
|
|
451
|
-
>['userId'],
|
|
452
|
-
): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>[]> {
|
|
453
|
-
const notifications = await this.prismaClient.notification.findMany({
|
|
454
|
-
where: {
|
|
455
|
-
userId,
|
|
456
|
-
status: 'SENT',
|
|
457
|
-
readAt: null,
|
|
458
|
-
},
|
|
459
|
-
});
|
|
460
|
-
|
|
461
|
-
return notifications.map(this.serializeNotification);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
async filterInAppUnreadNotifications(
|
|
465
|
-
userId: NonNullable<
|
|
466
|
-
Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>
|
|
467
|
-
>['userId'],
|
|
468
|
-
page: number,
|
|
469
|
-
pageSize: number,
|
|
470
|
-
): Promise<Notification<AvailableContexts, NotificationIdType, UserIdType>[]> {
|
|
471
|
-
const notifications = await this.prismaClient.notification.findMany({
|
|
472
|
-
where: {
|
|
473
|
-
userId,
|
|
474
|
-
status: 'SENT',
|
|
475
|
-
readAt: null,
|
|
476
|
-
},
|
|
477
|
-
skip: page * pageSize,
|
|
478
|
-
take: pageSize,
|
|
479
|
-
});
|
|
480
|
-
|
|
481
|
-
return notifications.map(this.serializeNotification);
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
async getUserEmailFromNotification(
|
|
485
|
-
notificationId: NonNullable<
|
|
486
|
-
Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>
|
|
487
|
-
>['id'],
|
|
488
|
-
): Promise<string | undefined> {
|
|
489
|
-
const notification = await this.prismaClient.notification.findUnique({
|
|
490
|
-
where: {
|
|
491
|
-
id: notificationId,
|
|
492
|
-
},
|
|
493
|
-
include: {
|
|
494
|
-
user: true,
|
|
495
|
-
},
|
|
496
|
-
});
|
|
497
|
-
|
|
498
|
-
return notification?.user?.email;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
async storeContextUsed(
|
|
502
|
-
notificationId: NonNullable<
|
|
503
|
-
Awaited<ReturnType<typeof this.prismaClient.notification.findUnique>>
|
|
504
|
-
>['id'],
|
|
505
|
-
context: InputJsonValue,
|
|
506
|
-
): Promise<void> {
|
|
507
|
-
await this.prismaClient.notification.update({
|
|
508
|
-
where: {
|
|
509
|
-
id: notificationId,
|
|
510
|
-
},
|
|
511
|
-
data: {
|
|
512
|
-
contextUsed: context,
|
|
513
|
-
},
|
|
514
|
-
});
|
|
515
|
-
}
|
|
516
|
-
}
|
package/schema.prisma.example
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
datasource db {
|
|
2
|
-
provider = "postgresql"
|
|
3
|
-
url = env("DATABASE_URL")
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
generator client {
|
|
7
|
-
provider = "prisma-client-js"
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
model User {
|
|
11
|
-
id Int @id @default(autoincrement())
|
|
12
|
-
email String @unique
|
|
13
|
-
notifications Notification[]
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
model Notification {
|
|
17
|
-
id Int @id @default(autoincrement())
|
|
18
|
-
user User @relation(fields: [userId], references: [id])
|
|
19
|
-
userId Int
|
|
20
|
-
notificationType NotificationType
|
|
21
|
-
title String?
|
|
22
|
-
bodyTemplate String
|
|
23
|
-
contextName String
|
|
24
|
-
contextParameters Json @default("{}")
|
|
25
|
-
sendAfter DateTime?
|
|
26
|
-
subjectTemplate String?
|
|
27
|
-
status NotificationStatus @default(PENDING_SEND)
|
|
28
|
-
contextUsed Json?
|
|
29
|
-
adapterUsed String?
|
|
30
|
-
sentAt DateTime?
|
|
31
|
-
readAt DateTime?
|
|
32
|
-
createdAt DateTime @default(now())
|
|
33
|
-
updatedAt DateTime @updatedAt
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
enum NotificationType {
|
|
37
|
-
EMAIL
|
|
38
|
-
PUSH
|
|
39
|
-
SMS
|
|
40
|
-
IN_APP
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
enum NotificationStatus {
|
|
44
|
-
PENDING_SEND
|
|
45
|
-
SENT
|
|
46
|
-
FAILED
|
|
47
|
-
READ
|
|
48
|
-
CANCELLED
|
|
49
|
-
}
|