vintasend-prisma 0.3.0 → 0.4.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.js +6 -4
- package/dist/implementations/vintasend-prisma/src/prisma-notification-backend.d.ts +296 -168
- package/dist/implementations/vintasend-prisma/src/prisma-notification-backend.js +389 -382
- package/dist/prisma-notification-backend.d.ts +209 -20
- package/dist/prisma-notification-backend.js +292 -16
- package/dist/services/notification-backends/base-notification-backend.d.ts +85 -26
- package/dist/services/notification-backends/base-notification-backend.js +1 -2
- package/dist/types/identifier.js +1 -2
- package/dist/types/json-values.d.ts +13 -9
- package/dist/types/json-values.js +1 -2
- package/dist/types/notification-context-generators.d.ts +4 -2
- package/dist/types/notification-context-generators.js +1 -2
- package/dist/types/notification-status.js +1 -2
- package/dist/types/notification-type-config.d.ts +5 -5
- package/dist/types/notification-type-config.js +1 -2
- package/dist/types/notification-type.js +1 -2
- package/dist/types/notification.d.ts +75 -41
- package/dist/types/notification.js +1 -2
- package/dist/types/one-off-notification.d.ts +66 -43
- package/dist/types/one-off-notification.js +1 -2
- package/dist/types/uuid.js +1 -2
- package/package.json +27 -29
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PrismaNotificationBackendFactory = exports.PrismaNotificationBackend = exports.NotificationTypeEnum = exports.NotificationStatusEnum = void 0;
|
|
4
|
+
const attachment_1 = require("vintasend/dist/types/attachment");
|
|
4
5
|
exports.NotificationStatusEnum = {
|
|
5
6
|
PENDING_SEND: 'PENDING_SEND',
|
|
6
7
|
SENT: 'SENT',
|
|
@@ -14,6 +15,14 @@ exports.NotificationTypeEnum = {
|
|
|
14
15
|
SMS: 'SMS',
|
|
15
16
|
IN_APP: 'IN_APP',
|
|
16
17
|
};
|
|
18
|
+
// Centralized attachment include shape for DRY
|
|
19
|
+
const notificationWithAttachmentsInclude = {
|
|
20
|
+
attachments: {
|
|
21
|
+
include: {
|
|
22
|
+
attachmentFile: true,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
};
|
|
17
26
|
function convertJsonValueToRecord(jsonValue) {
|
|
18
27
|
if (typeof jsonValue === 'object' && !Array.isArray(jsonValue)) {
|
|
19
28
|
return jsonValue;
|
|
@@ -21,8 +30,15 @@ function convertJsonValueToRecord(jsonValue) {
|
|
|
21
30
|
throw new Error('Invalid JSON value. It should be an object.');
|
|
22
31
|
}
|
|
23
32
|
class PrismaNotificationBackend {
|
|
24
|
-
constructor(prismaClient) {
|
|
33
|
+
constructor(prismaClient, attachmentManager) {
|
|
25
34
|
this.prismaClient = prismaClient;
|
|
35
|
+
this.attachmentManager = attachmentManager;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Inject attachment manager (called by VintaSend when both service and backend exist)
|
|
39
|
+
*/
|
|
40
|
+
injectAttachmentManager(manager) {
|
|
41
|
+
this.attachmentManager = manager;
|
|
26
42
|
}
|
|
27
43
|
/**
|
|
28
44
|
* Build a where clause for status-based updates
|
|
@@ -62,6 +78,10 @@ class PrismaNotificationBackend {
|
|
|
62
78
|
readAt: notification.readAt,
|
|
63
79
|
createdAt: notification.createdAt,
|
|
64
80
|
updatedAt: notification.updatedAt,
|
|
81
|
+
// Serialize attachments if present and attachmentManager is available
|
|
82
|
+
attachments: notification.attachments && this.attachmentManager
|
|
83
|
+
? notification.attachments.map((att) => this.serializeStoredAttachment(att))
|
|
84
|
+
: undefined,
|
|
65
85
|
};
|
|
66
86
|
// Check if this is a one-off notification (has emailOrPhone but no userId)
|
|
67
87
|
// Use explicit null checks to avoid misclassification with empty strings or other falsy values
|
|
@@ -125,21 +145,26 @@ class PrismaNotificationBackend {
|
|
|
125
145
|
sendAfter: notification.sendAfter,
|
|
126
146
|
subjectTemplate: notification.subjectTemplate,
|
|
127
147
|
extraParams: notification.extraParams,
|
|
148
|
+
// Only include one-off fields if this is actually a one-off notification
|
|
149
|
+
...(isOneOff && {
|
|
150
|
+
emailOrPhone: 'emailOrPhone' in notification ? notification.emailOrPhone : null,
|
|
151
|
+
firstName: 'firstName' in notification ? (_a = notification.firstName) !== null && _a !== void 0 ? _a : null : null,
|
|
152
|
+
lastName: 'lastName' in notification ? (_b = notification.lastName) !== null && _b !== void 0 ? _b : null : null,
|
|
153
|
+
}),
|
|
128
154
|
};
|
|
129
155
|
if (isOneOff) {
|
|
130
156
|
return {
|
|
131
157
|
...base,
|
|
132
158
|
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
159
|
status: exports.NotificationStatusEnum.PENDING_SEND,
|
|
160
|
+
user: undefined,
|
|
137
161
|
};
|
|
138
162
|
}
|
|
139
163
|
// At this point we know hasUserId is true, so userId exists and is not null
|
|
140
164
|
const userId = ('userId' in notification ? notification.userId : null);
|
|
141
165
|
return {
|
|
142
166
|
...base,
|
|
167
|
+
userId,
|
|
143
168
|
user: {
|
|
144
169
|
connect: { id: userId },
|
|
145
170
|
},
|
|
@@ -240,6 +265,123 @@ class PrismaNotificationBackend {
|
|
|
240
265
|
}
|
|
241
266
|
return data;
|
|
242
267
|
}
|
|
268
|
+
/**
|
|
269
|
+
* Get or create file record for attachment upload with deduplication (transaction-aware)
|
|
270
|
+
* @private
|
|
271
|
+
*/
|
|
272
|
+
async getOrCreateFileRecordForUploadInTransaction(tx, att) {
|
|
273
|
+
const manager = this.getAttachmentManager();
|
|
274
|
+
const buffer = await manager.fileToBuffer(att.file);
|
|
275
|
+
const checksum = manager.calculateChecksum(buffer);
|
|
276
|
+
let fileRecord = await this.findAttachmentFileByChecksumInTransaction(tx, checksum);
|
|
277
|
+
if (!fileRecord) {
|
|
278
|
+
fileRecord = await manager.uploadFile(att.file, att.filename, att.contentType);
|
|
279
|
+
await tx.attachmentFile.create({
|
|
280
|
+
data: {
|
|
281
|
+
id: fileRecord.id,
|
|
282
|
+
filename: fileRecord.filename,
|
|
283
|
+
contentType: fileRecord.contentType,
|
|
284
|
+
size: fileRecord.size,
|
|
285
|
+
checksum: fileRecord.checksum,
|
|
286
|
+
storageMetadata: fileRecord.storageMetadata,
|
|
287
|
+
},
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
return fileRecord;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Get or create file record for attachment upload with deduplication (non-transactional)
|
|
294
|
+
* @private
|
|
295
|
+
*/
|
|
296
|
+
async getOrCreateFileRecordForUpload(att) {
|
|
297
|
+
return this.getOrCreateFileRecordForUploadInTransaction(this.prismaClient, att);
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Create notification attachment link (transaction-aware)
|
|
301
|
+
* @private
|
|
302
|
+
*/
|
|
303
|
+
async createNotificationAttachmentLinkInTransaction(tx, notificationId, fileId, description) {
|
|
304
|
+
await tx.notificationAttachment.create({
|
|
305
|
+
data: {
|
|
306
|
+
notificationId,
|
|
307
|
+
fileId,
|
|
308
|
+
description: description !== null && description !== void 0 ? description : null,
|
|
309
|
+
},
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Create notification attachment link (non-transactional)
|
|
314
|
+
* @private
|
|
315
|
+
*/
|
|
316
|
+
async createNotificationAttachmentLink(notificationId, fileId, description) {
|
|
317
|
+
return this.createNotificationAttachmentLinkInTransaction(this.prismaClient, notificationId, fileId, description);
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Get attachment file by ID (transaction-aware)
|
|
321
|
+
* @private
|
|
322
|
+
*/
|
|
323
|
+
async getAttachmentFileInTransaction(tx, fileId) {
|
|
324
|
+
const file = await tx.attachmentFile.findUnique({
|
|
325
|
+
where: { id: fileId },
|
|
326
|
+
});
|
|
327
|
+
if (!file)
|
|
328
|
+
return null;
|
|
329
|
+
return this.serializeAttachmentFileRecord(file);
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Find attachment file by checksum (transaction-aware)
|
|
333
|
+
* @private
|
|
334
|
+
*/
|
|
335
|
+
async findAttachmentFileByChecksumInTransaction(tx, checksum) {
|
|
336
|
+
const file = await tx.attachmentFile.findUnique({
|
|
337
|
+
where: { checksum },
|
|
338
|
+
});
|
|
339
|
+
if (!file)
|
|
340
|
+
return null;
|
|
341
|
+
return this.serializeAttachmentFileRecord(file);
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Core helper for creating notifications with attachments (both regular and one-off)
|
|
345
|
+
* Uses transactions to ensure atomicity - if attachment processing fails, the notification won't be created
|
|
346
|
+
* @private
|
|
347
|
+
*/
|
|
348
|
+
async createNotificationWithAttachments(input, buildData, serialize) {
|
|
349
|
+
const { attachments, ...notificationData } = input;
|
|
350
|
+
// If no attachments, skip transaction overhead
|
|
351
|
+
if (!attachments || attachments.length === 0) {
|
|
352
|
+
const created = await this.prismaClient.notification.create({
|
|
353
|
+
data: buildData(notificationData),
|
|
354
|
+
include: notificationWithAttachmentsInclude,
|
|
355
|
+
});
|
|
356
|
+
return serialize(created);
|
|
357
|
+
}
|
|
358
|
+
// Use transaction to ensure atomicity of notification + attachments
|
|
359
|
+
return await this.prismaClient.$transaction(async (tx) => {
|
|
360
|
+
const created = await tx.notification.create({
|
|
361
|
+
data: buildData(notificationData),
|
|
362
|
+
include: notificationWithAttachmentsInclude,
|
|
363
|
+
});
|
|
364
|
+
await this.processAndStoreAttachmentsInTransaction(tx, created.id, attachments);
|
|
365
|
+
const withAttachments = await tx.notification.findUnique({
|
|
366
|
+
where: { id: created.id },
|
|
367
|
+
include: notificationWithAttachmentsInclude,
|
|
368
|
+
});
|
|
369
|
+
if (!withAttachments) {
|
|
370
|
+
throw new Error('Failed to retrieve notification after creating attachments');
|
|
371
|
+
}
|
|
372
|
+
return serialize(withAttachments);
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Get attachment manager with null check
|
|
377
|
+
* @private
|
|
378
|
+
*/
|
|
379
|
+
getAttachmentManager() {
|
|
380
|
+
if (!this.attachmentManager) {
|
|
381
|
+
throw new Error('AttachmentManager is required but not provided');
|
|
382
|
+
}
|
|
383
|
+
return this.attachmentManager;
|
|
384
|
+
}
|
|
243
385
|
deserializeNotification(notification) {
|
|
244
386
|
return this.buildCreateData(notification);
|
|
245
387
|
}
|
|
@@ -342,10 +484,7 @@ class PrismaNotificationBackend {
|
|
|
342
484
|
return notifications.map((n) => this.serializeAnyNotification(n));
|
|
343
485
|
}
|
|
344
486
|
async persistNotification(notification) {
|
|
345
|
-
|
|
346
|
-
data: this.deserializeRegularNotification(notification),
|
|
347
|
-
});
|
|
348
|
-
return this.serializeRegularNotification(created);
|
|
487
|
+
return this.createNotificationWithAttachments(notification, (n) => this.deserializeRegularNotification(n), (db) => this.serializeRegularNotification(db));
|
|
349
488
|
}
|
|
350
489
|
async persistNotificationUpdate(notificationId, notification) {
|
|
351
490
|
const updated = await this.prismaClient.notification.update({
|
|
@@ -358,10 +497,7 @@ class PrismaNotificationBackend {
|
|
|
358
497
|
}
|
|
359
498
|
/* One-off notification persistence and query methods */
|
|
360
499
|
async persistOneOffNotification(notification) {
|
|
361
|
-
|
|
362
|
-
data: this.buildOneOffNotificationData(notification),
|
|
363
|
-
});
|
|
364
|
-
return this.serializeOneOffNotification(created);
|
|
500
|
+
return this.createNotificationWithAttachments(notification, (n) => this.buildOneOffNotificationData(n), (db) => this.serializeOneOffNotification(db));
|
|
365
501
|
}
|
|
366
502
|
async persistOneOffNotificationUpdate(notificationId, notification) {
|
|
367
503
|
const updated = await this.prismaClient.notification.update({
|
|
@@ -460,6 +596,7 @@ class PrismaNotificationBackend {
|
|
|
460
596
|
async getNotification(notificationId, _forUpdate) {
|
|
461
597
|
const notification = await this.prismaClient.notification.findUnique({
|
|
462
598
|
where: { id: notificationId },
|
|
599
|
+
include: notificationWithAttachmentsInclude,
|
|
463
600
|
});
|
|
464
601
|
if (!notification)
|
|
465
602
|
return null;
|
|
@@ -502,19 +639,158 @@ class PrismaNotificationBackend {
|
|
|
502
639
|
async storeContextUsed(notificationId, context) {
|
|
503
640
|
await this.prismaClient.notification.update({
|
|
504
641
|
where: { id: notificationId },
|
|
505
|
-
data: { contextUsed: context }
|
|
642
|
+
data: { contextUsed: context },
|
|
506
643
|
});
|
|
507
644
|
}
|
|
508
645
|
async bulkPersistNotifications(notifications) {
|
|
509
|
-
|
|
646
|
+
const created = await this.prismaClient.notification.createManyAndReturn({
|
|
510
647
|
data: notifications.map((notification) => this.deserializeNotification(notification)),
|
|
511
648
|
});
|
|
649
|
+
return created.map((n) => n.id);
|
|
650
|
+
}
|
|
651
|
+
/* Attachment management methods */
|
|
652
|
+
async getAttachmentFile(fileId) {
|
|
653
|
+
const file = await this.prismaClient.attachmentFile.findUnique({
|
|
654
|
+
where: { id: fileId },
|
|
655
|
+
});
|
|
656
|
+
if (!file)
|
|
657
|
+
return null;
|
|
658
|
+
return this.serializeAttachmentFileRecord(file);
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* Find an attachment file by checksum for deduplication.
|
|
662
|
+
* This allows the backend to check if a file already exists before uploading.
|
|
663
|
+
*/
|
|
664
|
+
async findAttachmentFileByChecksum(checksum) {
|
|
665
|
+
const file = await this.prismaClient.attachmentFile.findUnique({
|
|
666
|
+
where: { checksum },
|
|
667
|
+
});
|
|
668
|
+
if (!file)
|
|
669
|
+
return null;
|
|
670
|
+
return this.serializeAttachmentFileRecord(file);
|
|
671
|
+
}
|
|
672
|
+
async deleteAttachmentFile(fileId) {
|
|
673
|
+
const file = await this.prismaClient.attachmentFile.findUnique({
|
|
674
|
+
where: { id: fileId },
|
|
675
|
+
});
|
|
676
|
+
// If there's no DB record, there's nothing to delete
|
|
677
|
+
if (!file)
|
|
678
|
+
return;
|
|
679
|
+
// First delete the underlying stored file so DB and storage stay in sync
|
|
680
|
+
const manager = this.getAttachmentManager();
|
|
681
|
+
await manager.deleteFile(fileId);
|
|
682
|
+
// Only after successful storage deletion, remove the DB record
|
|
683
|
+
await this.prismaClient.attachmentFile.delete({
|
|
684
|
+
where: { id: fileId },
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
async getOrphanedAttachmentFiles() {
|
|
688
|
+
const orphanedFiles = await this.prismaClient.attachmentFile.findMany({
|
|
689
|
+
where: {
|
|
690
|
+
notificationAttachments: { none: {} },
|
|
691
|
+
},
|
|
692
|
+
});
|
|
693
|
+
return orphanedFiles.map((file) => this.serializeAttachmentFileRecord(file));
|
|
694
|
+
}
|
|
695
|
+
async getAttachments(notificationId) {
|
|
696
|
+
const attachments = await this.prismaClient.notificationAttachment.findMany({
|
|
697
|
+
where: { notificationId },
|
|
698
|
+
include: { attachmentFile: true },
|
|
699
|
+
});
|
|
700
|
+
this.getAttachmentManager(); // Validate attachment manager exists
|
|
701
|
+
return attachments.map((att) => this.serializeStoredAttachment(att));
|
|
702
|
+
}
|
|
703
|
+
async deleteNotificationAttachment(notificationId, attachmentId) {
|
|
704
|
+
const result = await this.prismaClient.notificationAttachment.deleteMany({
|
|
705
|
+
where: {
|
|
706
|
+
id: attachmentId,
|
|
707
|
+
notificationId,
|
|
708
|
+
},
|
|
709
|
+
});
|
|
710
|
+
if (result.count === 0) {
|
|
711
|
+
throw new Error(`Attachment ${attachmentId} not found for notification ${notificationId}`);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
/**
|
|
715
|
+
* Process and store attachments for a notification within a transaction.
|
|
716
|
+
* Handles both new file uploads and references to existing files.
|
|
717
|
+
* Uses attachmentManager for checksum calculation and storage operations.
|
|
718
|
+
* @private
|
|
719
|
+
*/
|
|
720
|
+
async processAndStoreAttachmentsInTransaction(tx, notificationId, attachments) {
|
|
721
|
+
this.getAttachmentManager(); // Validate attachment manager exists
|
|
722
|
+
// Process each attachment
|
|
723
|
+
for (const att of attachments) {
|
|
724
|
+
if ((0, attachment_1.isAttachmentReference)(att)) {
|
|
725
|
+
// Reference existing file - just create the notification link
|
|
726
|
+
const fileRecord = await this.getAttachmentFileInTransaction(tx, att.fileId);
|
|
727
|
+
if (!fileRecord) {
|
|
728
|
+
throw new Error(`Referenced file ${att.fileId} not found`);
|
|
729
|
+
}
|
|
730
|
+
await this.createNotificationAttachmentLinkInTransaction(tx, notificationId, att.fileId, att.description);
|
|
731
|
+
}
|
|
732
|
+
else {
|
|
733
|
+
// Upload new file with deduplication
|
|
734
|
+
const fileRecord = await this.getOrCreateFileRecordForUploadInTransaction(tx, att);
|
|
735
|
+
await this.createNotificationAttachmentLinkInTransaction(tx, notificationId, fileRecord.id, att.description);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Process and store attachments for a notification (non-transactional version).
|
|
741
|
+
* Handles both new file uploads and references to existing files.
|
|
742
|
+
* Uses attachmentManager for checksum calculation and storage operations.
|
|
743
|
+
* @private
|
|
744
|
+
*/
|
|
745
|
+
async processAndStoreAttachments(notificationId, attachments) {
|
|
746
|
+
return this.processAndStoreAttachmentsInTransaction(this.prismaClient, notificationId, attachments);
|
|
747
|
+
}
|
|
748
|
+
/**
|
|
749
|
+
* Serialize a Prisma attachment file model to AttachmentFileRecord
|
|
750
|
+
* @private
|
|
751
|
+
*/
|
|
752
|
+
serializeAttachmentFileRecord(file) {
|
|
753
|
+
return {
|
|
754
|
+
id: file.id,
|
|
755
|
+
filename: file.filename,
|
|
756
|
+
contentType: file.contentType,
|
|
757
|
+
size: file.size,
|
|
758
|
+
checksum: file.checksum,
|
|
759
|
+
storageMetadata: file.storageMetadata,
|
|
760
|
+
createdAt: file.createdAt,
|
|
761
|
+
updatedAt: file.updatedAt,
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
765
|
+
* Serialize a Prisma notification attachment model to StoredAttachment
|
|
766
|
+
* @private
|
|
767
|
+
*/
|
|
768
|
+
serializeStoredAttachment(attachment) {
|
|
769
|
+
var _a;
|
|
770
|
+
const manager = this.getAttachmentManager();
|
|
771
|
+
if (!attachment.attachmentFile) {
|
|
772
|
+
throw new Error('AttachmentFile is required to reconstruct stored attachment');
|
|
773
|
+
}
|
|
774
|
+
const fileRecord = this.serializeAttachmentFileRecord(attachment.attachmentFile);
|
|
775
|
+
const attachmentFile = manager.reconstructAttachmentFile(fileRecord.storageMetadata);
|
|
776
|
+
return {
|
|
777
|
+
id: attachment.id,
|
|
778
|
+
fileId: attachment.fileId,
|
|
779
|
+
filename: fileRecord.filename,
|
|
780
|
+
contentType: fileRecord.contentType,
|
|
781
|
+
size: fileRecord.size,
|
|
782
|
+
checksum: fileRecord.checksum,
|
|
783
|
+
createdAt: attachment.createdAt,
|
|
784
|
+
file: attachmentFile,
|
|
785
|
+
description: (_a = attachment.description) !== null && _a !== void 0 ? _a : undefined,
|
|
786
|
+
storageMetadata: fileRecord.storageMetadata,
|
|
787
|
+
};
|
|
512
788
|
}
|
|
513
789
|
}
|
|
514
790
|
exports.PrismaNotificationBackend = PrismaNotificationBackend;
|
|
515
791
|
class PrismaNotificationBackendFactory {
|
|
516
|
-
create(prismaClient) {
|
|
517
|
-
return new PrismaNotificationBackend(prismaClient);
|
|
792
|
+
create(prismaClient, attachmentManager) {
|
|
793
|
+
return new PrismaNotificationBackend(prismaClient, attachmentManager);
|
|
518
794
|
}
|
|
519
795
|
}
|
|
520
796
|
exports.PrismaNotificationBackendFactory = PrismaNotificationBackendFactory;
|
|
@@ -1,30 +1,89 @@
|
|
|
1
1
|
import type { InputJsonValue } from '../../types/json-values';
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
AnyDatabaseNotification,
|
|
4
|
+
DatabaseNotification,
|
|
5
|
+
DatabaseOneOffNotification,
|
|
6
|
+
Notification,
|
|
7
|
+
OneOffNotificationInput,
|
|
8
|
+
} from '../../types/notification';
|
|
3
9
|
import type { BaseNotificationTypeConfig } from '../../types/notification-type-config';
|
|
4
10
|
export interface BaseNotificationBackend<Config extends BaseNotificationTypeConfig> {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
11
|
+
getAllPendingNotifications(): Promise<AnyDatabaseNotification<Config>[]>;
|
|
12
|
+
getPendingNotifications(
|
|
13
|
+
page: number,
|
|
14
|
+
pageSize: number,
|
|
15
|
+
): Promise<AnyDatabaseNotification<Config>[]>;
|
|
16
|
+
getAllFutureNotifications(): Promise<AnyDatabaseNotification<Config>[]>;
|
|
17
|
+
getFutureNotifications(
|
|
18
|
+
page: number,
|
|
19
|
+
pageSize: number,
|
|
20
|
+
): Promise<AnyDatabaseNotification<Config>[]>;
|
|
21
|
+
getAllFutureNotificationsFromUser(
|
|
22
|
+
userId: Config['UserIdType'],
|
|
23
|
+
): Promise<DatabaseNotification<Config>[]>;
|
|
24
|
+
getFutureNotificationsFromUser(
|
|
25
|
+
userId: Config['UserIdType'],
|
|
26
|
+
page: number,
|
|
27
|
+
pageSize: number,
|
|
28
|
+
): Promise<DatabaseNotification<Config>[]>;
|
|
29
|
+
persistNotification(
|
|
30
|
+
notification: Omit<Notification<Config>, 'id'>,
|
|
31
|
+
): Promise<DatabaseNotification<Config>>;
|
|
32
|
+
getAllNotifications(): Promise<AnyDatabaseNotification<Config>[]>;
|
|
33
|
+
getNotifications(page: number, pageSize: number): Promise<AnyDatabaseNotification<Config>[]>;
|
|
34
|
+
bulkPersistNotifications(
|
|
35
|
+
notifications: Omit<Notification<Config>, 'id'>[],
|
|
36
|
+
): Promise<Config['NotificationIdType'][]>;
|
|
37
|
+
persistNotificationUpdate(
|
|
38
|
+
notificationId: Config['NotificationIdType'],
|
|
39
|
+
notification: Partial<Omit<Notification<Config>, 'id'>>,
|
|
40
|
+
): Promise<DatabaseNotification<Config>>;
|
|
41
|
+
markAsSent(
|
|
42
|
+
notificationId: Config['NotificationIdType'],
|
|
43
|
+
checkIsPending: boolean,
|
|
44
|
+
): Promise<AnyDatabaseNotification<Config>>;
|
|
45
|
+
markAsFailed(
|
|
46
|
+
notificationId: Config['NotificationIdType'],
|
|
47
|
+
checkIsPending: boolean,
|
|
48
|
+
): Promise<AnyDatabaseNotification<Config>>;
|
|
49
|
+
markAsRead(
|
|
50
|
+
notificationId: Config['NotificationIdType'],
|
|
51
|
+
checkIsSent: boolean,
|
|
52
|
+
): Promise<DatabaseNotification<Config>>;
|
|
53
|
+
cancelNotification(notificationId: Config['NotificationIdType']): Promise<void>;
|
|
54
|
+
getNotification(
|
|
55
|
+
notificationId: Config['NotificationIdType'],
|
|
56
|
+
forUpdate: boolean,
|
|
57
|
+
): Promise<AnyDatabaseNotification<Config> | null>;
|
|
58
|
+
filterAllInAppUnreadNotifications(
|
|
59
|
+
userId: Config['UserIdType'],
|
|
60
|
+
): Promise<DatabaseNotification<Config>[]>;
|
|
61
|
+
filterInAppUnreadNotifications(
|
|
62
|
+
userId: Config['UserIdType'],
|
|
63
|
+
page: number,
|
|
64
|
+
pageSize: number,
|
|
65
|
+
): Promise<DatabaseNotification<Config>[]>;
|
|
66
|
+
getUserEmailFromNotification(
|
|
67
|
+
notificationId: Config['NotificationIdType'],
|
|
68
|
+
): Promise<string | undefined>;
|
|
69
|
+
storeContextUsed(
|
|
70
|
+
notificationId: Config['NotificationIdType'],
|
|
71
|
+
context: InputJsonValue,
|
|
72
|
+
): Promise<void>;
|
|
73
|
+
persistOneOffNotification(
|
|
74
|
+
notification: Omit<OneOffNotificationInput<Config>, 'id'>,
|
|
75
|
+
): Promise<DatabaseOneOffNotification<Config>>;
|
|
76
|
+
persistOneOffNotificationUpdate(
|
|
77
|
+
notificationId: Config['NotificationIdType'],
|
|
78
|
+
notification: Partial<Omit<OneOffNotificationInput<Config>, 'id'>>,
|
|
79
|
+
): Promise<DatabaseOneOffNotification<Config>>;
|
|
80
|
+
getOneOffNotification(
|
|
81
|
+
notificationId: Config['NotificationIdType'],
|
|
82
|
+
forUpdate: boolean,
|
|
83
|
+
): Promise<DatabaseOneOffNotification<Config> | null>;
|
|
84
|
+
getAllOneOffNotifications(): Promise<DatabaseOneOffNotification<Config>[]>;
|
|
85
|
+
getOneOffNotifications(
|
|
86
|
+
page: number,
|
|
87
|
+
pageSize: number,
|
|
88
|
+
): Promise<DatabaseOneOffNotification<Config>[]>;
|
|
30
89
|
}
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
package/dist/types/identifier.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
export type JsonPrimitive = string | number | boolean | null;
|
|
2
|
-
export interface JsonArray extends Array<JsonValue> {
|
|
3
|
-
}
|
|
2
|
+
export interface JsonArray extends Array<JsonValue> {}
|
|
4
3
|
export type JsonObject = {
|
|
5
|
-
|
|
4
|
+
[Key in string]?: JsonValue;
|
|
6
5
|
};
|
|
7
6
|
export type JsonValue = string | number | boolean | JsonObject | JsonArray | null;
|
|
8
7
|
export type InputJsonObject = {
|
|
9
|
-
|
|
10
|
-
};
|
|
11
|
-
export interface InputJsonArray extends ReadonlyArray<InputJsonValue | null> {
|
|
12
|
-
}
|
|
13
|
-
export type InputJsonValue = string | number | boolean | InputJsonObject | InputJsonArray | {
|
|
14
|
-
toJSON(): unknown;
|
|
8
|
+
readonly [Key in string]?: InputJsonValue | null;
|
|
15
9
|
};
|
|
10
|
+
export interface InputJsonArray extends ReadonlyArray<InputJsonValue | null> {}
|
|
11
|
+
export type InputJsonValue =
|
|
12
|
+
| string
|
|
13
|
+
| number
|
|
14
|
+
| boolean
|
|
15
|
+
| InputJsonObject
|
|
16
|
+
| InputJsonArray
|
|
17
|
+
| {
|
|
18
|
+
toJSON(): unknown;
|
|
19
|
+
};
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { JsonObject, JsonPrimitive } from './json-values';
|
|
2
|
-
export interface ContextGenerator<
|
|
3
|
-
|
|
2
|
+
export interface ContextGenerator<
|
|
3
|
+
Params extends Record<string, JsonPrimitive> = Record<string, JsonPrimitive>,
|
|
4
|
+
> {
|
|
5
|
+
generate(params: Params): JsonObject | Promise<JsonObject>;
|
|
4
6
|
}
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { Identifier } from './identifier';
|
|
2
|
+
import type { ContextGenerator } from './notification-context-generators';
|
|
3
3
|
export type BaseNotificationTypeConfig = {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
ContextMap: Record<string, ContextGenerator>;
|
|
5
|
+
NotificationIdType: Identifier;
|
|
6
|
+
UserIdType: Identifier;
|
|
7
7
|
};
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|