@rapidmx/restapi 0.1.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/LICENSE +382 -0
- package/README.md +50 -0
- package/dist/lib/blob/BlobStore.js +6 -0
- package/dist/lib/blob/BlobStore.js.map +1 -0
- package/dist/lib/blob/LocalFsBlobStore.js +101 -0
- package/dist/lib/blob/LocalFsBlobStore.js.map +1 -0
- package/dist/lib/blob/index.js +7 -0
- package/dist/lib/blob/index.js.map +1 -0
- package/dist/lib/index.js +12 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/jobs/AttachmentExtractionJob.js +124 -0
- package/dist/lib/jobs/AttachmentExtractionJob.js.map +1 -0
- package/dist/lib/jobs/CalendarReminderJob.js +132 -0
- package/dist/lib/jobs/CalendarReminderJob.js.map +1 -0
- package/dist/lib/jobs/EasDeviceStateCleanupJob.js +101 -0
- package/dist/lib/jobs/EasDeviceStateCleanupJob.js.map +1 -0
- package/dist/lib/jobs/ExternalShareExpirationJob.js +117 -0
- package/dist/lib/jobs/ExternalShareExpirationJob.js.map +1 -0
- package/dist/lib/jobs/MailboxQuotaRecalcJob.js +163 -0
- package/dist/lib/jobs/MailboxQuotaRecalcJob.js.map +1 -0
- package/dist/lib/jobs/MeetingSchedulingJob.js +106 -0
- package/dist/lib/jobs/MeetingSchedulingJob.js.map +1 -0
- package/dist/lib/jobs/QuarantineRetentionJob.js +97 -0
- package/dist/lib/jobs/QuarantineRetentionJob.js.map +1 -0
- package/dist/lib/jobs/ScanQueueJob.js +223 -0
- package/dist/lib/jobs/ScanQueueJob.js.map +1 -0
- package/dist/lib/jobs/SearchIndexJob.js +146 -0
- package/dist/lib/jobs/SearchIndexJob.js.map +1 -0
- package/dist/lib/jobs/index.js +10 -0
- package/dist/lib/jobs/index.js.map +1 -0
- package/dist/lib/jobs/mongo/AttachmentExtractionJobMongo.js +14 -0
- package/dist/lib/jobs/mongo/AttachmentExtractionJobMongo.js.map +1 -0
- package/dist/lib/jobs/mongo/CalendarReminderJobMongo.js +13 -0
- package/dist/lib/jobs/mongo/CalendarReminderJobMongo.js.map +1 -0
- package/dist/lib/jobs/mongo/EasDeviceStateCleanupJobMongo.js +13 -0
- package/dist/lib/jobs/mongo/EasDeviceStateCleanupJobMongo.js.map +1 -0
- package/dist/lib/jobs/mongo/ExternalShareExpirationJobMongo.js +13 -0
- package/dist/lib/jobs/mongo/ExternalShareExpirationJobMongo.js.map +1 -0
- package/dist/lib/jobs/mongo/MailboxQuotaRecalcJobMongo.js +15 -0
- package/dist/lib/jobs/mongo/MailboxQuotaRecalcJobMongo.js.map +1 -0
- package/dist/lib/jobs/mongo/MeetingSchedulingJobMongo.js +13 -0
- package/dist/lib/jobs/mongo/MeetingSchedulingJobMongo.js.map +1 -0
- package/dist/lib/jobs/mongo/QuarantineRetentionJobMongo.js +13 -0
- package/dist/lib/jobs/mongo/QuarantineRetentionJobMongo.js.map +1 -0
- package/dist/lib/jobs/mongo/ScanQueueJobMongo.js +18 -0
- package/dist/lib/jobs/mongo/ScanQueueJobMongo.js.map +1 -0
- package/dist/lib/jobs/mongo/SearchIndexJobMongo.js +14 -0
- package/dist/lib/jobs/mongo/SearchIndexJobMongo.js.map +1 -0
- package/dist/lib/jobs/mongo/index.js +10 -0
- package/dist/lib/jobs/mongo/index.js.map +1 -0
- package/dist/lib/jobs/mongo.js +2 -0
- package/dist/lib/jobs/mongo.js.map +1 -0
- package/dist/lib/jobs/sql/AttachmentExtractionJobSQL.js +14 -0
- package/dist/lib/jobs/sql/AttachmentExtractionJobSQL.js.map +1 -0
- package/dist/lib/jobs/sql/CalendarReminderJobSQL.js +13 -0
- package/dist/lib/jobs/sql/CalendarReminderJobSQL.js.map +1 -0
- package/dist/lib/jobs/sql/EasDeviceStateCleanupJobSQL.js +13 -0
- package/dist/lib/jobs/sql/EasDeviceStateCleanupJobSQL.js.map +1 -0
- package/dist/lib/jobs/sql/ExternalShareExpirationJobSQL.js +13 -0
- package/dist/lib/jobs/sql/ExternalShareExpirationJobSQL.js.map +1 -0
- package/dist/lib/jobs/sql/MailboxQuotaRecalcJobSQL.js +15 -0
- package/dist/lib/jobs/sql/MailboxQuotaRecalcJobSQL.js.map +1 -0
- package/dist/lib/jobs/sql/MeetingSchedulingJobSQL.js +13 -0
- package/dist/lib/jobs/sql/MeetingSchedulingJobSQL.js.map +1 -0
- package/dist/lib/jobs/sql/QuarantineRetentionJobSQL.js +13 -0
- package/dist/lib/jobs/sql/QuarantineRetentionJobSQL.js.map +1 -0
- package/dist/lib/jobs/sql/ScanQueueJobSQL.js +18 -0
- package/dist/lib/jobs/sql/ScanQueueJobSQL.js.map +1 -0
- package/dist/lib/jobs/sql/SearchIndexJobSQL.js +14 -0
- package/dist/lib/jobs/sql/SearchIndexJobSQL.js.map +1 -0
- package/dist/lib/jobs/sql/index.js +10 -0
- package/dist/lib/jobs/sql/index.js.map +1 -0
- package/dist/lib/jobs/sql.js +2 -0
- package/dist/lib/jobs/sql.js.map +1 -0
- package/dist/lib/models/index.js +2 -0
- package/dist/lib/models/index.js.map +1 -0
- package/dist/lib/models/mongo/AttachmentMongo.js +129 -0
- package/dist/lib/models/mongo/AttachmentMongo.js.map +1 -0
- package/dist/lib/models/mongo/CalendarEventMongo.js +172 -0
- package/dist/lib/models/mongo/CalendarEventMongo.js.map +1 -0
- package/dist/lib/models/mongo/CalendarShareLinkMongo.js +85 -0
- package/dist/lib/models/mongo/CalendarShareLinkMongo.js.map +1 -0
- package/dist/lib/models/mongo/ContactListMongo.js +60 -0
- package/dist/lib/models/mongo/ContactListMongo.js.map +1 -0
- package/dist/lib/models/mongo/ContactMongo.js +148 -0
- package/dist/lib/models/mongo/ContactMongo.js.map +1 -0
- package/dist/lib/models/mongo/DeviceSyncStateMongo.js +97 -0
- package/dist/lib/models/mongo/DeviceSyncStateMongo.js.map +1 -0
- package/dist/lib/models/mongo/FolderMongo.js +102 -0
- package/dist/lib/models/mongo/FolderMongo.js.map +1 -0
- package/dist/lib/models/mongo/IngestQueueEntryMongo.js +93 -0
- package/dist/lib/models/mongo/IngestQueueEntryMongo.js.map +1 -0
- package/dist/lib/models/mongo/MailboxMongo.js +105 -0
- package/dist/lib/models/mongo/MailboxMongo.js.map +1 -0
- package/dist/lib/models/mongo/MessageMongo.js +180 -0
- package/dist/lib/models/mongo/MessageMongo.js.map +1 -0
- package/dist/lib/models/mongo/NoteMongo.js +83 -0
- package/dist/lib/models/mongo/NoteMongo.js.map +1 -0
- package/dist/lib/models/mongo/QuarantineEntryMongo.js +99 -0
- package/dist/lib/models/mongo/QuarantineEntryMongo.js.map +1 -0
- package/dist/lib/models/mongo/ScanResultMongo.js +112 -0
- package/dist/lib/models/mongo/ScanResultMongo.js.map +1 -0
- package/dist/lib/models/mongo/SearchIndexStateMongo.js +83 -0
- package/dist/lib/models/mongo/SearchIndexStateMongo.js.map +1 -0
- package/dist/lib/models/mongo/TaskMongo.js +105 -0
- package/dist/lib/models/mongo/TaskMongo.js.map +1 -0
- package/dist/lib/models/mongo/index.js +16 -0
- package/dist/lib/models/mongo/index.js.map +1 -0
- package/dist/lib/models/mongo.js +2 -0
- package/dist/lib/models/mongo.js.map +1 -0
- package/dist/lib/models/sql/AttachmentSQL.js +129 -0
- package/dist/lib/models/sql/AttachmentSQL.js.map +1 -0
- package/dist/lib/models/sql/CalendarEventSQL.js +176 -0
- package/dist/lib/models/sql/CalendarEventSQL.js.map +1 -0
- package/dist/lib/models/sql/CalendarShareLinkSQL.js +85 -0
- package/dist/lib/models/sql/CalendarShareLinkSQL.js.map +1 -0
- package/dist/lib/models/sql/ContactListSQL.js +60 -0
- package/dist/lib/models/sql/ContactListSQL.js.map +1 -0
- package/dist/lib/models/sql/ContactSQL.js +148 -0
- package/dist/lib/models/sql/ContactSQL.js.map +1 -0
- package/dist/lib/models/sql/DeviceSyncStateSQL.js +97 -0
- package/dist/lib/models/sql/DeviceSyncStateSQL.js.map +1 -0
- package/dist/lib/models/sql/FolderSQL.js +106 -0
- package/dist/lib/models/sql/FolderSQL.js.map +1 -0
- package/dist/lib/models/sql/IngestQueueEntrySQL.js +97 -0
- package/dist/lib/models/sql/IngestQueueEntrySQL.js.map +1 -0
- package/dist/lib/models/sql/MailboxSQL.js +105 -0
- package/dist/lib/models/sql/MailboxSQL.js.map +1 -0
- package/dist/lib/models/sql/MessageSQL.js +184 -0
- package/dist/lib/models/sql/MessageSQL.js.map +1 -0
- package/dist/lib/models/sql/NoteSQL.js +83 -0
- package/dist/lib/models/sql/NoteSQL.js.map +1 -0
- package/dist/lib/models/sql/QuarantineEntrySQL.js +103 -0
- package/dist/lib/models/sql/QuarantineEntrySQL.js.map +1 -0
- package/dist/lib/models/sql/ScanResultSQL.js +116 -0
- package/dist/lib/models/sql/ScanResultSQL.js.map +1 -0
- package/dist/lib/models/sql/SearchIndexStateSQL.js +83 -0
- package/dist/lib/models/sql/SearchIndexStateSQL.js.map +1 -0
- package/dist/lib/models/sql/TaskSQL.js +109 -0
- package/dist/lib/models/sql/TaskSQL.js.map +1 -0
- package/dist/lib/models/sql/index.js +16 -0
- package/dist/lib/models/sql/index.js.map +1 -0
- package/dist/lib/models/sql.js +2 -0
- package/dist/lib/models/sql.js.map +1 -0
- package/dist/lib/models/types.js +108 -0
- package/dist/lib/models/types.js.map +1 -0
- package/dist/lib/mongo.js +8 -0
- package/dist/lib/mongo.js.map +1 -0
- package/dist/lib/push/MailPushRoute.js +42 -0
- package/dist/lib/push/MailPushRoute.js.map +1 -0
- package/dist/lib/push/index.js +6 -0
- package/dist/lib/push/index.js.map +1 -0
- package/dist/lib/routes/BaseAttachmentRoute.js +142 -0
- package/dist/lib/routes/BaseAttachmentRoute.js.map +1 -0
- package/dist/lib/routes/BaseCalendarShareLinkRoute.js +123 -0
- package/dist/lib/routes/BaseCalendarShareLinkRoute.js.map +1 -0
- package/dist/lib/routes/BaseFolderRoute.js +192 -0
- package/dist/lib/routes/BaseFolderRoute.js.map +1 -0
- package/dist/lib/routes/BaseMailIngestRoute.js +179 -0
- package/dist/lib/routes/BaseMailIngestRoute.js.map +1 -0
- package/dist/lib/routes/BaseMailboxRoute.js +187 -0
- package/dist/lib/routes/BaseMailboxRoute.js.map +1 -0
- package/dist/lib/routes/BaseMessageRoute.js +142 -0
- package/dist/lib/routes/BaseMessageRoute.js.map +1 -0
- package/dist/lib/routes/BaseScopedChildRoute.js +348 -0
- package/dist/lib/routes/BaseScopedChildRoute.js.map +1 -0
- package/dist/lib/routes/BaseSearchRoute.js +91 -0
- package/dist/lib/routes/BaseSearchRoute.js.map +1 -0
- package/dist/lib/routes/index.js +13 -0
- package/dist/lib/routes/index.js.map +1 -0
- package/dist/lib/routes/mongo/AttachmentRouteMongo.js +26 -0
- package/dist/lib/routes/mongo/AttachmentRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/CalendarEventRouteMongo.js +27 -0
- package/dist/lib/routes/mongo/CalendarEventRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/CalendarShareLinkRouteMongo.js +26 -0
- package/dist/lib/routes/mongo/CalendarShareLinkRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/ContactListRouteMongo.js +26 -0
- package/dist/lib/routes/mongo/ContactListRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/ContactRouteMongo.js +27 -0
- package/dist/lib/routes/mongo/ContactRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/FolderRouteMongo.js +26 -0
- package/dist/lib/routes/mongo/FolderRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/IngestQueueRouteMongo.js +33 -0
- package/dist/lib/routes/mongo/IngestQueueRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/MailIngestRouteMongo.js +14 -0
- package/dist/lib/routes/mongo/MailIngestRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/MailboxRouteMongo.js +39 -0
- package/dist/lib/routes/mongo/MailboxRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/MessageRouteMongo.js +27 -0
- package/dist/lib/routes/mongo/MessageRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/NoteRouteMongo.js +26 -0
- package/dist/lib/routes/mongo/NoteRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/QuarantineRouteMongo.js +35 -0
- package/dist/lib/routes/mongo/QuarantineRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/SearchRouteMongo.js +13 -0
- package/dist/lib/routes/mongo/SearchRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/TaskRouteMongo.js +27 -0
- package/dist/lib/routes/mongo/TaskRouteMongo.js.map +1 -0
- package/dist/lib/routes/mongo/index.js +15 -0
- package/dist/lib/routes/mongo/index.js.map +1 -0
- package/dist/lib/routes/mongo.js +2 -0
- package/dist/lib/routes/mongo.js.map +1 -0
- package/dist/lib/routes/sql/AttachmentRouteSQL.js +26 -0
- package/dist/lib/routes/sql/AttachmentRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/CalendarEventRouteSQL.js +27 -0
- package/dist/lib/routes/sql/CalendarEventRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/CalendarShareLinkRouteSQL.js +26 -0
- package/dist/lib/routes/sql/CalendarShareLinkRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/ContactListRouteSQL.js +26 -0
- package/dist/lib/routes/sql/ContactListRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/ContactRouteSQL.js +27 -0
- package/dist/lib/routes/sql/ContactRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/FolderRouteSQL.js +26 -0
- package/dist/lib/routes/sql/FolderRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/IngestQueueRouteSQL.js +29 -0
- package/dist/lib/routes/sql/IngestQueueRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/MailIngestRouteSQL.js +35 -0
- package/dist/lib/routes/sql/MailIngestRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/MailboxRouteSQL.js +64 -0
- package/dist/lib/routes/sql/MailboxRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/MessageRouteSQL.js +27 -0
- package/dist/lib/routes/sql/MessageRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/NoteRouteSQL.js +26 -0
- package/dist/lib/routes/sql/NoteRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/QuarantineRouteSQL.js +29 -0
- package/dist/lib/routes/sql/QuarantineRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/SearchRouteSQL.js +13 -0
- package/dist/lib/routes/sql/SearchRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/TaskRouteSQL.js +27 -0
- package/dist/lib/routes/sql/TaskRouteSQL.js.map +1 -0
- package/dist/lib/routes/sql/index.js +15 -0
- package/dist/lib/routes/sql/index.js.map +1 -0
- package/dist/lib/routes/sql.js +2 -0
- package/dist/lib/routes/sql.js.map +1 -0
- package/dist/lib/scan/AvScanProvider.js +2 -0
- package/dist/lib/scan/AvScanProvider.js.map +1 -0
- package/dist/lib/scan/ClamAvScanProvider.js +112 -0
- package/dist/lib/scan/ClamAvScanProvider.js.map +1 -0
- package/dist/lib/scan/RspamdSpamScanProvider.js +100 -0
- package/dist/lib/scan/RspamdSpamScanProvider.js.map +1 -0
- package/dist/lib/scan/ScanPipeline.js +118 -0
- package/dist/lib/scan/ScanPipeline.js.map +1 -0
- package/dist/lib/scan/SpamScanProvider.js +2 -0
- package/dist/lib/scan/SpamScanProvider.js.map +1 -0
- package/dist/lib/scan/index.js +10 -0
- package/dist/lib/scan/index.js.map +1 -0
- package/dist/lib/search/MongoTextSearchProvider.js +116 -0
- package/dist/lib/search/MongoTextSearchProvider.js.map +1 -0
- package/dist/lib/search/OpenSearchProvider.js +156 -0
- package/dist/lib/search/OpenSearchProvider.js.map +1 -0
- package/dist/lib/search/PostgresFullTextSearchProvider.js +139 -0
- package/dist/lib/search/PostgresFullTextSearchProvider.js.map +1 -0
- package/dist/lib/search/SearchProvider.js +6 -0
- package/dist/lib/search/SearchProvider.js.map +1 -0
- package/dist/lib/search/extraction/DocxTextExtractor.js +27 -0
- package/dist/lib/search/extraction/DocxTextExtractor.js.map +1 -0
- package/dist/lib/search/extraction/ExtractorRegistry.js +82 -0
- package/dist/lib/search/extraction/ExtractorRegistry.js.map +1 -0
- package/dist/lib/search/extraction/HtmlTextExtractor.js +20 -0
- package/dist/lib/search/extraction/HtmlTextExtractor.js.map +1 -0
- package/dist/lib/search/extraction/PdfTextExtractor.js +22 -0
- package/dist/lib/search/extraction/PdfTextExtractor.js.map +1 -0
- package/dist/lib/search/extraction/PlainTextExtractor.js +14 -0
- package/dist/lib/search/extraction/PlainTextExtractor.js.map +1 -0
- package/dist/lib/search/extraction/TextExtractor.js +6 -0
- package/dist/lib/search/extraction/TextExtractor.js.map +1 -0
- package/dist/lib/search/index.js +15 -0
- package/dist/lib/search/index.js.map +1 -0
- package/dist/lib/sql.js +8 -0
- package/dist/lib/sql.js.map +1 -0
- package/dist/lib/transport/MTAIngestAdapter.js +30 -0
- package/dist/lib/transport/MTAIngestAdapter.js.map +1 -0
- package/dist/lib/transport/MailTransport.js +6 -0
- package/dist/lib/transport/MailTransport.js.map +1 -0
- package/dist/lib/transport/PostfixSendmailTransport.js +61 -0
- package/dist/lib/transport/PostfixSendmailTransport.js.map +1 -0
- package/dist/lib/transport/index.js +8 -0
- package/dist/lib/transport/index.js.map +1 -0
- package/dist/lib/util/FolderUtils.js +50 -0
- package/dist/lib/util/FolderUtils.js.map +1 -0
- package/dist/lib/util/MailSendUtils.js +36 -0
- package/dist/lib/util/MailSendUtils.js.map +1 -0
- package/dist/lib/util/MailboxScopeUtils.js +23 -0
- package/dist/lib/util/MailboxScopeUtils.js.map +1 -0
- package/dist/lib/util/OptionalDeps.js +23 -0
- package/dist/lib/util/OptionalDeps.js.map +1 -0
- package/dist/lib/util/RecoverableRepoUtils.js +42 -0
- package/dist/lib/util/RecoverableRepoUtils.js.map +1 -0
- package/dist/lib/util/index.js +17 -0
- package/dist/lib/util/index.js.map +1 -0
- package/dist/types/blob/BlobStore.d.ts +54 -0
- package/dist/types/blob/LocalFsBlobStore.d.ts +23 -0
- package/dist/types/blob/index.d.ts +2 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/jobs/AttachmentExtractionJob.d.ts +34 -0
- package/dist/types/jobs/CalendarReminderJob.d.ts +37 -0
- package/dist/types/jobs/EasDeviceStateCleanupJob.d.ts +26 -0
- package/dist/types/jobs/ExternalShareExpirationJob.d.ts +34 -0
- package/dist/types/jobs/MailboxQuotaRecalcJob.d.ts +44 -0
- package/dist/types/jobs/MeetingSchedulingJob.d.ts +32 -0
- package/dist/types/jobs/QuarantineRetentionJob.d.ts +27 -0
- package/dist/types/jobs/ScanQueueJob.d.ts +41 -0
- package/dist/types/jobs/SearchIndexJob.d.ts +37 -0
- package/dist/types/jobs/index.d.ts +9 -0
- package/dist/types/jobs/mongo/AttachmentExtractionJobMongo.d.ts +6 -0
- package/dist/types/jobs/mongo/CalendarReminderJobMongo.d.ts +5 -0
- package/dist/types/jobs/mongo/EasDeviceStateCleanupJobMongo.d.ts +5 -0
- package/dist/types/jobs/mongo/ExternalShareExpirationJobMongo.d.ts +5 -0
- package/dist/types/jobs/mongo/MailboxQuotaRecalcJobMongo.d.ts +7 -0
- package/dist/types/jobs/mongo/MeetingSchedulingJobMongo.d.ts +5 -0
- package/dist/types/jobs/mongo/QuarantineRetentionJobMongo.d.ts +5 -0
- package/dist/types/jobs/mongo/ScanQueueJobMongo.d.ts +10 -0
- package/dist/types/jobs/mongo/SearchIndexJobMongo.d.ts +6 -0
- package/dist/types/jobs/mongo/index.d.ts +9 -0
- package/dist/types/jobs/mongo.d.ts +1 -0
- package/dist/types/jobs/sql/AttachmentExtractionJobSQL.d.ts +6 -0
- package/dist/types/jobs/sql/CalendarReminderJobSQL.d.ts +5 -0
- package/dist/types/jobs/sql/EasDeviceStateCleanupJobSQL.d.ts +5 -0
- package/dist/types/jobs/sql/ExternalShareExpirationJobSQL.d.ts +5 -0
- package/dist/types/jobs/sql/MailboxQuotaRecalcJobSQL.d.ts +7 -0
- package/dist/types/jobs/sql/MeetingSchedulingJobSQL.d.ts +5 -0
- package/dist/types/jobs/sql/QuarantineRetentionJobSQL.d.ts +5 -0
- package/dist/types/jobs/sql/ScanQueueJobSQL.d.ts +10 -0
- package/dist/types/jobs/sql/SearchIndexJobSQL.d.ts +6 -0
- package/dist/types/jobs/sql/index.d.ts +9 -0
- package/dist/types/jobs/sql.d.ts +1 -0
- package/dist/types/models/index.d.ts +1 -0
- package/dist/types/models/mongo/AttachmentMongo.d.ts +22 -0
- package/dist/types/models/mongo/CalendarEventMongo.d.ts +28 -0
- package/dist/types/models/mongo/CalendarShareLinkMongo.d.ts +16 -0
- package/dist/types/models/mongo/ContactListMongo.d.ts +13 -0
- package/dist/types/models/mongo/ContactMongo.d.ts +25 -0
- package/dist/types/models/mongo/DeviceSyncStateMongo.d.ts +18 -0
- package/dist/types/models/mongo/FolderMongo.d.ts +18 -0
- package/dist/types/models/mongo/IngestQueueEntryMongo.d.ts +17 -0
- package/dist/types/models/mongo/MailboxMongo.d.ts +18 -0
- package/dist/types/models/mongo/MessageMongo.d.ts +29 -0
- package/dist/types/models/mongo/NoteMongo.d.ts +16 -0
- package/dist/types/models/mongo/QuarantineEntryMongo.d.ts +18 -0
- package/dist/types/models/mongo/ScanResultMongo.d.ts +23 -0
- package/dist/types/models/mongo/SearchIndexStateMongo.d.ts +16 -0
- package/dist/types/models/mongo/TaskMongo.d.ts +19 -0
- package/dist/types/models/mongo/index.d.ts +15 -0
- package/dist/types/models/mongo.d.ts +1 -0
- package/dist/types/models/sql/AttachmentSQL.d.ts +22 -0
- package/dist/types/models/sql/CalendarEventSQL.d.ts +28 -0
- package/dist/types/models/sql/CalendarShareLinkSQL.d.ts +16 -0
- package/dist/types/models/sql/ContactListSQL.d.ts +13 -0
- package/dist/types/models/sql/ContactSQL.d.ts +25 -0
- package/dist/types/models/sql/DeviceSyncStateSQL.d.ts +18 -0
- package/dist/types/models/sql/FolderSQL.d.ts +18 -0
- package/dist/types/models/sql/IngestQueueEntrySQL.d.ts +17 -0
- package/dist/types/models/sql/MailboxSQL.d.ts +18 -0
- package/dist/types/models/sql/MessageSQL.d.ts +29 -0
- package/dist/types/models/sql/NoteSQL.d.ts +16 -0
- package/dist/types/models/sql/QuarantineEntrySQL.d.ts +18 -0
- package/dist/types/models/sql/ScanResultSQL.d.ts +23 -0
- package/dist/types/models/sql/SearchIndexStateSQL.d.ts +16 -0
- package/dist/types/models/sql/TaskSQL.d.ts +19 -0
- package/dist/types/models/sql/index.d.ts +15 -0
- package/dist/types/models/sql.d.ts +1 -0
- package/dist/types/models/types.d.ts +541 -0
- package/dist/types/mongo.d.ts +3 -0
- package/dist/types/push/MailPushRoute.d.ts +37 -0
- package/dist/types/push/index.d.ts +1 -0
- package/dist/types/routes/BaseAttachmentRoute.d.ts +24 -0
- package/dist/types/routes/BaseCalendarShareLinkRoute.d.ts +35 -0
- package/dist/types/routes/BaseFolderRoute.d.ts +58 -0
- package/dist/types/routes/BaseMailIngestRoute.d.ts +47 -0
- package/dist/types/routes/BaseMailboxRoute.d.ts +60 -0
- package/dist/types/routes/BaseMessageRoute.d.ts +27 -0
- package/dist/types/routes/BaseScopedChildRoute.d.ts +61 -0
- package/dist/types/routes/BaseSearchRoute.d.ts +23 -0
- package/dist/types/routes/index.d.ts +8 -0
- package/dist/types/routes/mongo/AttachmentRouteMongo.d.ts +6 -0
- package/dist/types/routes/mongo/CalendarEventRouteMongo.d.ts +6 -0
- package/dist/types/routes/mongo/CalendarShareLinkRouteMongo.d.ts +6 -0
- package/dist/types/routes/mongo/ContactListRouteMongo.d.ts +6 -0
- package/dist/types/routes/mongo/ContactRouteMongo.d.ts +6 -0
- package/dist/types/routes/mongo/FolderRouteMongo.d.ts +5 -0
- package/dist/types/routes/mongo/IngestQueueRouteMongo.d.ts +13 -0
- package/dist/types/routes/mongo/MailIngestRouteMongo.d.ts +6 -0
- package/dist/types/routes/mongo/MailboxRouteMongo.d.ts +8 -0
- package/dist/types/routes/mongo/MessageRouteMongo.d.ts +6 -0
- package/dist/types/routes/mongo/NoteRouteMongo.d.ts +6 -0
- package/dist/types/routes/mongo/QuarantineRouteMongo.d.ts +15 -0
- package/dist/types/routes/mongo/SearchRouteMongo.d.ts +5 -0
- package/dist/types/routes/mongo/TaskRouteMongo.d.ts +6 -0
- package/dist/types/routes/mongo/index.d.ts +14 -0
- package/dist/types/routes/mongo.d.ts +1 -0
- package/dist/types/routes/sql/AttachmentRouteSQL.d.ts +6 -0
- package/dist/types/routes/sql/CalendarEventRouteSQL.d.ts +6 -0
- package/dist/types/routes/sql/CalendarShareLinkRouteSQL.d.ts +6 -0
- package/dist/types/routes/sql/ContactListRouteSQL.d.ts +6 -0
- package/dist/types/routes/sql/ContactRouteSQL.d.ts +6 -0
- package/dist/types/routes/sql/FolderRouteSQL.d.ts +5 -0
- package/dist/types/routes/sql/IngestQueueRouteSQL.d.ts +9 -0
- package/dist/types/routes/sql/MailIngestRouteSQL.d.ts +23 -0
- package/dist/types/routes/sql/MailboxRouteSQL.d.ts +22 -0
- package/dist/types/routes/sql/MessageRouteSQL.d.ts +6 -0
- package/dist/types/routes/sql/NoteRouteSQL.d.ts +6 -0
- package/dist/types/routes/sql/QuarantineRouteSQL.d.ts +9 -0
- package/dist/types/routes/sql/SearchRouteSQL.d.ts +5 -0
- package/dist/types/routes/sql/TaskRouteSQL.d.ts +6 -0
- package/dist/types/routes/sql/index.d.ts +14 -0
- package/dist/types/routes/sql.d.ts +1 -0
- package/dist/types/scan/AvScanProvider.d.ts +22 -0
- package/dist/types/scan/ClamAvScanProvider.d.ts +17 -0
- package/dist/types/scan/RspamdSpamScanProvider.d.ts +16 -0
- package/dist/types/scan/ScanPipeline.d.ts +53 -0
- package/dist/types/scan/SpamScanProvider.d.ts +29 -0
- package/dist/types/scan/index.d.ts +5 -0
- package/dist/types/search/MongoTextSearchProvider.d.ts +22 -0
- package/dist/types/search/OpenSearchProvider.d.ts +24 -0
- package/dist/types/search/PostgresFullTextSearchProvider.d.ts +21 -0
- package/dist/types/search/SearchProvider.d.ts +62 -0
- package/dist/types/search/extraction/DocxTextExtractor.d.ts +14 -0
- package/dist/types/search/extraction/ExtractorRegistry.d.ts +19 -0
- package/dist/types/search/extraction/HtmlTextExtractor.d.ts +11 -0
- package/dist/types/search/extraction/PdfTextExtractor.d.ts +10 -0
- package/dist/types/search/extraction/PlainTextExtractor.d.ts +10 -0
- package/dist/types/search/extraction/TextExtractor.d.ts +17 -0
- package/dist/types/search/index.d.ts +10 -0
- package/dist/types/sql.d.ts +3 -0
- package/dist/types/transport/MTAIngestAdapter.d.ts +25 -0
- package/dist/types/transport/MailTransport.d.ts +29 -0
- package/dist/types/transport/PostfixSendmailTransport.d.ts +15 -0
- package/dist/types/transport/index.d.ts +3 -0
- package/dist/types/util/FolderUtils.d.ts +15 -0
- package/dist/types/util/MailSendUtils.d.ts +19 -0
- package/dist/types/util/MailboxScopeUtils.d.ts +19 -0
- package/dist/types/util/OptionalDeps.d.ts +9 -0
- package/dist/types/util/RecoverableRepoUtils.d.ts +24 -0
- package/dist/types/util/index.d.ts +12 -0
- package/package.json +122 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
import * as crypto from "crypto";
|
|
6
|
+
import { ApiError } from "@rapidrest/core";
|
|
7
|
+
import { ApiErrors } from "@rapidrest/service-core";
|
|
8
|
+
import { resolveDeliveryVerdict } from "../scan/ScanPipeline.js";
|
|
9
|
+
/**
|
|
10
|
+
* Runs `raw` through `ScanPipeline` and, if it passes, relays it via `mailTransport` - the scan-then-relay core
|
|
11
|
+
* shared by every "send a composed message" entry point in this library (`BaseMessageRoute.send()`'s REST
|
|
12
|
+
* endpoint and the EAS `SendMail`/`SmartForward`/`SmartReply` commands via `sendComposedMime()` below), so this
|
|
13
|
+
* gate is defined exactly once rather than duplicated per protocol.
|
|
14
|
+
*
|
|
15
|
+
* Throws `ApiError` (422) if the scan pipeline's verdict is anything other than "deliver", or (502) if the
|
|
16
|
+
* transport itself rejects the message outright - both cases callers should let propagate as the request's
|
|
17
|
+
* own failure, not attempt to recover from.
|
|
18
|
+
*/
|
|
19
|
+
export async function scanAndRelay(raw, envelopeFrom, envelopeTo, scanPipeline, mailTransport, blobStore) {
|
|
20
|
+
const scanResult = await scanPipeline.run(raw, { from: envelopeFrom, to: envelopeTo });
|
|
21
|
+
const verdict = resolveDeliveryVerdict(scanResult);
|
|
22
|
+
if (verdict !== "deliver") {
|
|
23
|
+
throw new ApiError(ApiErrors.INVALID_REQUEST, 422, "This message could not be sent because it failed spam/malware scanning.");
|
|
24
|
+
}
|
|
25
|
+
const transportResult = await mailTransport.send({ raw, envelopeFrom, envelopeTo });
|
|
26
|
+
if (transportResult.accepted.length === 0) {
|
|
27
|
+
throw new ApiError(ApiErrors.INTERNAL_ERROR, 502, "The mail transport rejected this message.");
|
|
28
|
+
}
|
|
29
|
+
let sanitizedHtmlBlobKey;
|
|
30
|
+
if (scanResult.sanitizedHtml !== undefined) {
|
|
31
|
+
sanitizedHtmlBlobKey = `sanitized/${crypto.randomUUID()}`;
|
|
32
|
+
await blobStore.put(sanitizedHtmlBlobKey, Buffer.from(scanResult.sanitizedHtml, "utf-8"), { contentType: "text/html" });
|
|
33
|
+
}
|
|
34
|
+
return { sanitizedHtmlBlobKey };
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=MailSendUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MailSendUtils.js","sourceRoot":"","sources":["../../../src/util/MailSendUtils.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E;AAC/E,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpD,OAAO,EAAE,sBAAsB,EAAgB,MAAM,yBAAyB,CAAC;AAS/E;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAC9B,GAAW,EACX,YAAoB,EACpB,UAAoB,EACpB,YAA0B,EAC1B,aAAkB,EAClB,SAAoB;IAEpB,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;IACvF,MAAM,OAAO,GAAG,sBAAsB,CAAC,UAAU,CAAC,CAAC;IACnD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,eAAe,EAAE,GAAG,EAAE,yEAAyE,CAAC,CAAC;IAClI,CAAC;IAED,MAAM,eAAe,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,CAAC;IACpF,IAAI,eAAe,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,GAAG,EAAE,2CAA2C,CAAC,CAAC;IACnG,CAAC;IAED,IAAI,oBAAwC,CAAC;IAC7C,IAAI,UAAU,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QACzC,oBAAoB,GAAG,aAAa,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC;QAC1D,MAAM,SAAS,CAAC,GAAG,CAAC,oBAAoB,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,OAAO,CAAC,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;IAC5H,CAAC;IAED,OAAO,EAAE,oBAAoB,EAAE,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves the `Mailbox` owned by `user` (a mailbox's `ownerUserUid` field, not an ACL lookup — this runs with
|
|
3
|
+
* `ignoreACL: true` deliberately, since it's used to derive the *scope* of what a query is allowed to touch,
|
|
4
|
+
* not to check permission on an already-identified record). Returns `undefined` if `user` is unauthenticated
|
|
5
|
+
* or owns no mailbox.
|
|
6
|
+
*
|
|
7
|
+
* See the doc comment on `findOrCreateWellKnownFolder`'s callers / `BaseMailboxScopedRoute` for why this
|
|
8
|
+
* exists: per-record ACLs in this platform inherit from their class-level ACL whenever no record-specific
|
|
9
|
+
* grant matches the caller, so a class-level grant broad enough to let any authenticated user list/read *some*
|
|
10
|
+
* records of a type also lets them list/read records they don't personally own, once class-level `LIST`/`READ`
|
|
11
|
+
* are opened up at all. The class-level ACL for every mailbox-owned entity in this library therefore denies
|
|
12
|
+
* `LIST`/`READ`/`COUNT`/`EXISTS` to `.*` entirely (see each entity's `@Protect` policy), and routes that need
|
|
13
|
+
* to list/count a caller's own records do so by explicitly scoping the query to their own mailbox and passing
|
|
14
|
+
* `ignoreACL: true` for that specific, safely-bounded query — the same pattern this function supports.
|
|
15
|
+
*/
|
|
16
|
+
export async function resolveCallerMailboxUid(mailboxRepo, user) {
|
|
17
|
+
if (!user) {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
const mailboxes = await mailboxRepo.find({ ownerUserUid: user.uid }, { ignoreACL: true, limit: 1 });
|
|
21
|
+
return mailboxes[0]?.uid;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=MailboxScopeUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MailboxScopeUtils.js","sourceRoot":"","sources":["../../../src/util/MailboxScopeUtils.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CACzC,WAAyB,EACzB,IAAc;IAEd,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,MAAM,SAAS,GAAQ,MAAM,WAAW,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IACzG,OAAO,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
import { ApiError } from "@rapidrest/core";
|
|
6
|
+
import { ApiErrors } from "@rapidrest/service-core";
|
|
7
|
+
/**
|
|
8
|
+
* Dynamically imports an optional peer dependency, throwing a helpful `ApiError` naming the package and its
|
|
9
|
+
* install command if it is not installed. Mirrors `@rapidrest/auth`'s `importArgon2()`/`importOTPLib()`
|
|
10
|
+
* convention so every optional adapter in this library (PDF/DOCX text extraction, OpenSearch) fails the same,
|
|
11
|
+
* actionable way rather than with a raw `MODULE_NOT_FOUND` error.
|
|
12
|
+
*
|
|
13
|
+
* @param packageName The npm package name to import.
|
|
14
|
+
*/
|
|
15
|
+
export async function importOptional(packageName) {
|
|
16
|
+
try {
|
|
17
|
+
return (await import(packageName));
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
throw new ApiError(ApiErrors.INTERNAL_ERROR, 500, `This feature requires the optional peer dependency '${packageName}'. Install it with: yarn add ${packageName}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=OptionalDeps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OptionalDeps.js","sourceRoot":"","sources":["../../../src/util/OptionalDeps.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E;AAC/E,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAU,WAAmB;IAC7D,IAAI,CAAC;QACD,OAAO,CAAC,MAAM,MAAM,CAAC,WAAW,CAAC,CAAM,CAAC;IAC5C,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAChB,MAAM,IAAI,QAAQ,CACd,SAAS,CAAC,cAAc,EACxB,GAAG,EACH,uDAAuD,WAAW,gCAAgC,WAAW,EAAE,CAClH,CAAC;IACN,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
import { MongoRepository, RepoUtils } from "@rapidrest/service-core";
|
|
6
|
+
/**
|
|
7
|
+
* Extends `RepoUtils` to close a gap in service-core's own soft-delete path: `RepoUtils.delete()`'s
|
|
8
|
+
* soft-delete branch (for a `RecoverableBaseEntity` subclass, when `purge` isn't requested) sets only
|
|
9
|
+
* `deleted: true` — unlike `update()`, it does not bump `dateModified`/`version` (confirmed by reading its
|
|
10
|
+
* source). EAS `Sync`'s per-folder watermark query (`find({dateModified: gt(lastSyncWatermark)})`, see
|
|
11
|
+
* `eas/EasSyncKeyUtils.ts`) needs a soft-deleted row to surface exactly the way an ordinary field change
|
|
12
|
+
* would, or a deletion would never be reported to a device that already synced the item.
|
|
13
|
+
*
|
|
14
|
+
* Stays entirely local to `@rapidrest/mail` (no service-core change): calls `super.delete()` unchanged for
|
|
15
|
+
* everything else (permission checks, ACL cleanup, cache invalidation, notifications, rollback hooks) and
|
|
16
|
+
* only adds one small follow-up write for the two fields service-core's own branch leaves alone. Wired in via
|
|
17
|
+
* the `repoUtilsClass` extension point every concrete Mongo/SQL route already declares (`ModelRoute.ts`'s
|
|
18
|
+
* `this._objectFactory.newInstance(this.repoUtilsClass || RepoUtils, ...)`), and by any job that builds a
|
|
19
|
+
* `RepoUtils` directly for one of the same entity classes.
|
|
20
|
+
*
|
|
21
|
+
* `RepoUtils.truncate()` has no soft-delete branch at all (it always hard-deletes, recoverable or not) — a
|
|
22
|
+
* bulk folder-empty is a documented, out-of-scope-for-this-override gap, not something this class fixes.
|
|
23
|
+
*
|
|
24
|
+
* @author Jean-Philippe Steinmetz
|
|
25
|
+
*/
|
|
26
|
+
export class RecoverableRepoUtils extends RepoUtils {
|
|
27
|
+
async delete(uid, options) {
|
|
28
|
+
await super.delete(uid, options);
|
|
29
|
+
if (options.purge || !this.repo) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const dateModified = new Date();
|
|
33
|
+
if (this.repo instanceof MongoRepository) {
|
|
34
|
+
await this.repo.updateMany({ uid }, { $set: { dateModified }, $inc: { version: 1 } });
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
await this.repo.update({ uid }, { dateModified });
|
|
38
|
+
await this.repo.increment({ uid }, "version", 1);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=RecoverableRepoUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RecoverableRepoUtils.js","sourceRoot":"","sources":["../../../src/util/RecoverableRepoUtils.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E;AAC/E,OAAO,EAAE,eAAe,EAAiD,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,oBAAsD,SAAQ,SAAY;IAC5E,KAAK,CAAC,MAAM,CAAC,GAAW,EAAE,OAA0B;QACvD,MAAM,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAEjC,IAAI,OAAO,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAC9B,OAAO;QACX,CAAC;QAED,MAAM,YAAY,GAAS,IAAI,IAAI,EAAE,CAAC;QACtC,IAAI,IAAI,CAAC,IAAI,YAAY,eAAe,EAAE,CAAC;YACvC,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,GAAG,EAAS,EAAE,EAAE,IAAI,EAAE,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,EAAS,CAAC,CAAC;QACxG,CAAC;aAAM,CAAC;YACJ,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,EAAS,EAAE,EAAE,YAAY,EAAS,CAAC,CAAC;YAChE,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAS,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;QAC5D,CAAC;IACL,CAAC;CACJ"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
/**
|
|
6
|
+
* Public, backend-agnostic REST-layer helpers shared across this library's own routes and useful to any
|
|
7
|
+
* downstream protocol package (`@rapidmx/activesync`, `@rapidmx/mapi`, `@rapidmx/autodiscover`) that needs to
|
|
8
|
+
* resolve a caller's mailbox, walk a folder tree, send a composed message through the scan/relay pipeline, or
|
|
9
|
+
* soft-delete a `RecoverableBaseEntity` with a correctly bumped watermark. `OptionalDeps.ts`'s
|
|
10
|
+
* `importOptional()` is deliberately not re-exported here - it's an internal helper for this library's own
|
|
11
|
+
* optional peer dependencies (PDF/DOCX extraction, OpenSearch), not something a protocol package needs.
|
|
12
|
+
*/
|
|
13
|
+
export * from "./FolderUtils.js";
|
|
14
|
+
export * from "./MailSendUtils.js";
|
|
15
|
+
export * from "./MailboxScopeUtils.js";
|
|
16
|
+
export * from "./RecoverableRepoUtils.js";
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/util/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E;AAE/E;;;;;;;GAOG;AACH,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The options available when storing a new blob via `BlobStore.put()`.
|
|
3
|
+
*/
|
|
4
|
+
export interface BlobPutOptions {
|
|
5
|
+
/** The MIME content type of the data being stored, if known. */
|
|
6
|
+
contentType?: string;
|
|
7
|
+
}
|
|
8
|
+
/** A byte range to retrieve via `BlobStore.getStream()`. `end` is inclusive; omit for "to end of blob". */
|
|
9
|
+
export interface BlobRange {
|
|
10
|
+
start: number;
|
|
11
|
+
end?: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Provides storage for binary content too large or unstructured to live inline on an entity record — raw MIME
|
|
15
|
+
* message sources, rendered message bodies, attachment content, extracted attachment text, and contact photos
|
|
16
|
+
* are all stored here, referenced from the owning entity by a `blobKey`. No entity in this library ever stores
|
|
17
|
+
* binary content directly in a Mongo/SQL column.
|
|
18
|
+
*
|
|
19
|
+
* @author Jean-Philippe Steinmetz
|
|
20
|
+
*/
|
|
21
|
+
export interface BlobStore {
|
|
22
|
+
/**
|
|
23
|
+
* Stores `data` under `key`, replacing any existing blob at that key.
|
|
24
|
+
*/
|
|
25
|
+
put(key: string, data: Buffer | NodeJS.ReadableStream, options?: BlobPutOptions): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Retrieves the full content stored under `key`.
|
|
28
|
+
*
|
|
29
|
+
* @throws if no blob exists at `key`.
|
|
30
|
+
*/
|
|
31
|
+
get(key: string): Promise<Buffer>;
|
|
32
|
+
/**
|
|
33
|
+
* Retrieves a readable stream of the content stored under `key`, optionally limited to `range`. Used to
|
|
34
|
+
* serve large attachments (e.g. MAPI/EAS `ItemOperations` fetch, webmail download) without buffering the
|
|
35
|
+
* entire blob into memory.
|
|
36
|
+
*
|
|
37
|
+
* @throws if no blob exists at `key`.
|
|
38
|
+
*/
|
|
39
|
+
getStream(key: string, range?: BlobRange): Promise<NodeJS.ReadableStream>;
|
|
40
|
+
/**
|
|
41
|
+
* Removes the blob stored under `key`. A no-op if no blob exists at `key`.
|
|
42
|
+
*/
|
|
43
|
+
delete(key: string): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Determines whether a blob exists at `key`.
|
|
46
|
+
*/
|
|
47
|
+
exists(key: string): Promise<boolean>;
|
|
48
|
+
/**
|
|
49
|
+
* Returns the size, in bytes, of the blob stored under `key`.
|
|
50
|
+
*
|
|
51
|
+
* @throws if no blob exists at `key`.
|
|
52
|
+
*/
|
|
53
|
+
size(key: string): Promise<number>;
|
|
54
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { BlobPutOptions, BlobRange, BlobStore } from "./BlobStore.js";
|
|
2
|
+
/**
|
|
3
|
+
* A `BlobStore` implementation backed by the local filesystem. Suitable for single-instance deployments or
|
|
4
|
+
* where `key`'s underlying directory is itself a shared/replicated mount (e.g. NFS). Larger deployments should
|
|
5
|
+
* prefer `S3BlobStore` instead.
|
|
6
|
+
*
|
|
7
|
+
* Keys are sharded two levels deep by the first four characters of their MD5 hash (e.g. key `abc123` is stored
|
|
8
|
+
* at `<root>/ab/c1/abc123`) to avoid placing an unbounded number of files in a single directory.
|
|
9
|
+
*
|
|
10
|
+
* @author Jean-Philippe Steinmetz
|
|
11
|
+
*/
|
|
12
|
+
export declare class LocalFsBlobStore implements BlobStore {
|
|
13
|
+
private root;
|
|
14
|
+
private resolvePath;
|
|
15
|
+
put(key: string, data: Buffer | NodeJS.ReadableStream, _options?: BlobPutOptions): Promise<void>;
|
|
16
|
+
get(key: string): Promise<Buffer>;
|
|
17
|
+
getStream(key: string, range?: BlobRange): Promise<NodeJS.ReadableStream>;
|
|
18
|
+
delete(key: string): Promise<void>;
|
|
19
|
+
exists(key: string): Promise<boolean>;
|
|
20
|
+
size(key: string): Promise<number>;
|
|
21
|
+
}
|
|
22
|
+
/** Coerces a `Buffer | NodeJS.ReadableStream` into a `Buffer`, for adapters that only accept whole buffers. */
|
|
23
|
+
export declare function toBuffer(data: Buffer | NodeJS.ReadableStream): Promise<Buffer>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { BackgroundService } from "@rapidrest/service-core";
|
|
2
|
+
import { Attachment, Message } from "../models/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Runs `ExtractorRegistry` (PDF/DOCX/plain-text/HTML text extraction) over `Attachment` records that haven't
|
|
5
|
+
* been processed yet (`extractedTextBlobKey` unset), as a background job — never inline on ingestion, since
|
|
6
|
+
* extraction can be slow and must not block SMTP-ACK or webmail send/save-draft latency (see the architecture
|
|
7
|
+
* plan's rationale for this).
|
|
8
|
+
*
|
|
9
|
+
* Every eligible attachment gets `extractedTextBlobKey` set exactly once, even when nothing extractable was
|
|
10
|
+
* found (an empty-content blob) — this is what marks an attachment as "already attempted" so an unsupported
|
|
11
|
+
* MIME type (e.g. an image) isn't re-selected by this job forever. When extraction *does* produce non-empty
|
|
12
|
+
* text for an attachment whose parent `Message` was already search-indexed, this job clears that message's
|
|
13
|
+
* `searchIndexedAt` back to `undefined` so `SearchIndexJob` re-indexes it with the newly available text.
|
|
14
|
+
*
|
|
15
|
+
* @author Jean-Philippe Steinmetz
|
|
16
|
+
*/
|
|
17
|
+
export declare abstract class AttachmentExtractionJob<A extends Attachment, M extends Message> extends BackgroundService {
|
|
18
|
+
protected abstract attachmentClass: any;
|
|
19
|
+
protected abstract messageClass: any;
|
|
20
|
+
private _objectFactory?;
|
|
21
|
+
private attachmentRepo?;
|
|
22
|
+
private messageRepo?;
|
|
23
|
+
private blobStore?;
|
|
24
|
+
private extractorRegistry;
|
|
25
|
+
private scheduleExpr;
|
|
26
|
+
private batchSize;
|
|
27
|
+
private logger;
|
|
28
|
+
get schedule(): string | undefined;
|
|
29
|
+
init(): Promise<void>;
|
|
30
|
+
start(): Promise<void>;
|
|
31
|
+
stop(): Promise<void> | void;
|
|
32
|
+
run(): Promise<void>;
|
|
33
|
+
private processAttachment;
|
|
34
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { BackgroundService } from "@rapidrest/service-core";
|
|
2
|
+
import { CalendarEvent } from "../models/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Polls upcoming `CalendarEvent` records and dispatches a `"reminder"` push notification once each event's
|
|
5
|
+
* configured `reminderMinutesBeforeStart` fire time falls within this job's own polling window.
|
|
6
|
+
*
|
|
7
|
+
* `CalendarEvent` has no persisted "reminder already sent" flag, and adding one is out of scope here, so this
|
|
8
|
+
* job takes the simplest correct-enough approach: the query only prunes past events (`startDate` lower-bounded
|
|
9
|
+
* at `now`, via `ModelUtils.buildSearchQuery`'s single-sided `gte(...)` operator, which - unlike its two-sided
|
|
10
|
+
* `range(...)` operator - has confirmed correct Date coercion on both backends), and everything else (the
|
|
11
|
+
* upper lookahead bound, and the actual reminder-fire-time arithmetic) is computed/filtered in-process.
|
|
12
|
+
*
|
|
13
|
+
* KNOWN LIMITATION: without a persisted "reminder already sent" flag (e.g. a future `CalendarEvent.
|
|
14
|
+
* reminderSentAt`), a reminder could in principle fire more than once if this job's own polling window ever
|
|
15
|
+
* overlaps across runs (e.g. after a restart, or a run that took longer than `windowSeconds`). This is a
|
|
16
|
+
* deliberate simplification, not an oversight - flagged here for a future follow-up.
|
|
17
|
+
*
|
|
18
|
+
* Concrete entity classes are supplied by the Mongo/SQL subclasses (`CalendarReminderJobMongo`/
|
|
19
|
+
* `CalendarReminderJobSQL`), following the same generic pattern `ScanQueueJob` uses.
|
|
20
|
+
*
|
|
21
|
+
* @author Jean-Philippe Steinmetz
|
|
22
|
+
*/
|
|
23
|
+
export declare abstract class CalendarReminderJob<CE extends CalendarEvent> extends BackgroundService {
|
|
24
|
+
protected abstract calendarEventClass: any;
|
|
25
|
+
private _objectFactory?;
|
|
26
|
+
private calendarEventRepo?;
|
|
27
|
+
private notificationUtils?;
|
|
28
|
+
private scheduleExpr;
|
|
29
|
+
private batchSize;
|
|
30
|
+
private windowSeconds;
|
|
31
|
+
private logger;
|
|
32
|
+
get schedule(): string | undefined;
|
|
33
|
+
init(): Promise<void>;
|
|
34
|
+
start(): Promise<void>;
|
|
35
|
+
stop(): Promise<void> | void;
|
|
36
|
+
run(): Promise<void>;
|
|
37
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { BackgroundService } from "@rapidrest/service-core";
|
|
2
|
+
import { DeviceSyncState } from "../models/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Prunes `DeviceSyncState` rows for EAS devices that haven't synced in more than `device_ttl_days` days (or
|
|
5
|
+
* that have never successfully synced at all), keeping the collection from growing unbounded with abandoned
|
|
6
|
+
* device pairings.
|
|
7
|
+
*
|
|
8
|
+
* Concrete entity classes are supplied by the Mongo/SQL subclasses (`EasDeviceStateCleanupJobMongo`/
|
|
9
|
+
* `EasDeviceStateCleanupJobSQL`), following the same generic pattern `ScanQueueJob` uses.
|
|
10
|
+
*
|
|
11
|
+
* @author Jean-Philippe Steinmetz
|
|
12
|
+
*/
|
|
13
|
+
export declare abstract class EasDeviceStateCleanupJob<D extends DeviceSyncState> extends BackgroundService {
|
|
14
|
+
protected abstract deviceSyncStateClass: any;
|
|
15
|
+
private _objectFactory?;
|
|
16
|
+
private deviceSyncStateRepo?;
|
|
17
|
+
private scheduleExpr;
|
|
18
|
+
private batchSize;
|
|
19
|
+
private deviceTtlDays;
|
|
20
|
+
private logger;
|
|
21
|
+
get schedule(): string | undefined;
|
|
22
|
+
init(): Promise<void>;
|
|
23
|
+
start(): Promise<void>;
|
|
24
|
+
stop(): Promise<void> | void;
|
|
25
|
+
run(): Promise<void>;
|
|
26
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { BackgroundService } from "@rapidrest/service-core";
|
|
2
|
+
import { CalendarShareLink } from "../models/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Garbage-collects expired `CalendarShareLink` rows (anonymous external calendar-sharing links whose
|
|
5
|
+
* `expiresAt` has passed), also revoking the `ACLRecord` each link's `token` was granted on its shared
|
|
6
|
+
* folder's `AccessControlList` (see `BaseCalendarShareLinkRoute`, which grants/upserts that same record on
|
|
7
|
+
* create/update — this job is the other half of keeping it in sync, for links that expire rather than being
|
|
8
|
+
* explicitly deleted via the API).
|
|
9
|
+
*
|
|
10
|
+
* Concrete entity classes are supplied by the Mongo/SQL subclasses (`ExternalShareExpirationJobMongo`/
|
|
11
|
+
* `ExternalShareExpirationJobSQL`), following the same generic pattern `ScanQueueJob` uses.
|
|
12
|
+
*
|
|
13
|
+
* @author Jean-Philippe Steinmetz
|
|
14
|
+
*/
|
|
15
|
+
export declare abstract class ExternalShareExpirationJob<S extends CalendarShareLink> extends BackgroundService {
|
|
16
|
+
protected abstract calendarShareLinkClass: any;
|
|
17
|
+
private _objectFactory?;
|
|
18
|
+
private calendarShareLinkRepo?;
|
|
19
|
+
private aclUtils?;
|
|
20
|
+
private scheduleExpr;
|
|
21
|
+
private batchSize;
|
|
22
|
+
private logger;
|
|
23
|
+
get schedule(): string | undefined;
|
|
24
|
+
init(): Promise<void>;
|
|
25
|
+
start(): Promise<void>;
|
|
26
|
+
stop(): Promise<void> | void;
|
|
27
|
+
run(): Promise<void>;
|
|
28
|
+
/** Removes any ACL record for `token` from `folderUid`'s ACL - see `BaseCalendarShareLinkRoute`'s identical
|
|
29
|
+
* helper for the full rationale (kept as a separate copy here rather than a shared import, since this job
|
|
30
|
+
* has no other dependency on the routes layer and the logic is a few lines). A no-op if the folder has no
|
|
31
|
+
* ACL document or no matching record - failing open here keeps a missing/corrupt folder ACL from turning a
|
|
32
|
+
* routine expiration sweep into a failed job run for every OTHER link in the same batch. */
|
|
33
|
+
private revokeShareTokenAccess;
|
|
34
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { BackgroundService } from "@rapidrest/service-core";
|
|
2
|
+
import { Attachment, Mailbox, Message } from "../models/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Periodically recomputes `Mailbox.usedBytes` from the mailbox's actual stored content (message body blobs plus
|
|
5
|
+
* attachment content) and corrects any drift from the incremental updates other code paths (ingest, delete,
|
|
6
|
+
* etc.) are expected to apply on their own. This job is a safety net against drift, not the primary mechanism
|
|
7
|
+
* for keeping `usedBytes` accurate — it runs cheaply and idempotently, and only writes when the recomputed value
|
|
8
|
+
* actually differs from what's stored.
|
|
9
|
+
*
|
|
10
|
+
* Concrete entity classes are supplied by the Mongo/SQL subclasses (`MailboxQuotaRecalcJobMongo`/
|
|
11
|
+
* `MailboxQuotaRecalcJobSQL`), following the same multi-entity-type generic pattern `ScanQueueJob` uses.
|
|
12
|
+
*
|
|
13
|
+
* @author Jean-Philippe Steinmetz
|
|
14
|
+
*/
|
|
15
|
+
export declare abstract class MailboxQuotaRecalcJob<MB extends Mailbox, M extends Message, A extends Attachment> extends BackgroundService {
|
|
16
|
+
protected abstract mailboxClass: any;
|
|
17
|
+
protected abstract messageClass: any;
|
|
18
|
+
protected abstract attachmentClass: any;
|
|
19
|
+
private _objectFactory?;
|
|
20
|
+
private mailboxRepo?;
|
|
21
|
+
private messageRepo?;
|
|
22
|
+
private attachmentRepo?;
|
|
23
|
+
private blobStore?;
|
|
24
|
+
private scheduleExpr;
|
|
25
|
+
private batchSize;
|
|
26
|
+
private logger;
|
|
27
|
+
get schedule(): string | undefined;
|
|
28
|
+
init(): Promise<void>;
|
|
29
|
+
start(): Promise<void>;
|
|
30
|
+
stop(): Promise<void> | void;
|
|
31
|
+
run(): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Fetches every page of `repo.find(criteria, ...)` results, not just the first. `RepoUtils.find()` caps at
|
|
34
|
+
* 100 rows per call by default (and SQL ignores `options.limit`/`options.page` entirely unless `limit`/
|
|
35
|
+
* `page` are *also* baked into the criteria object itself - see the comments on `run()`'s own `find()` call
|
|
36
|
+
* above for the full explanation) - a bare, unpaginated `find()` call here would silently recompute
|
|
37
|
+
* `usedBytes` from only the first ~100 messages/attachments, permanently understating usage for any mailbox
|
|
38
|
+
* larger than that. Confirmed as a real bug (not just a SQL-only quirk) by real-database testing: the
|
|
39
|
+
* previous unpaginated call truncated identically on both backends, since 100 is `RepoUtils.find()`'s own
|
|
40
|
+
* unconditional default, independent of which backend is in use.
|
|
41
|
+
*/
|
|
42
|
+
private findAllPages;
|
|
43
|
+
private recalcMailbox;
|
|
44
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { BackgroundService } from "@rapidrest/service-core";
|
|
2
|
+
import { CalendarEvent } from "../models/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Scheduled placeholder for outbound iTIP meeting-request processing: an organizer creates/updates a
|
|
5
|
+
* `CalendarEvent` with attendees, and an iTIP `REQUEST` email needs to go out to each attendee.
|
|
6
|
+
*
|
|
7
|
+
* TODO: Full iTIP send/response processing is deferred pending (1) an `IcsUtils` helper for composing RFC 5546
|
|
8
|
+
* iTIP messages/ICS payloads, which does not exist in this codebase yet, and (2) a persisted `CalendarEvent`
|
|
9
|
+
* invite-tracking field (there is currently no way to tell "attendees were already invited" apart from
|
|
10
|
+
* "attendees were just added and haven't been invited yet"). Inventing either of those here would just have to
|
|
11
|
+
* be redone once the real implementations land. This job currently exists purely as a scheduled placeholder so
|
|
12
|
+
* the surrounding plumbing (config, DI, `jobs/index.ts` registration) is already in place when that follow-up
|
|
13
|
+
* work is ready - `run()` only finds and logs candidate events, it does not compose or send anything.
|
|
14
|
+
*
|
|
15
|
+
* Concrete entity classes are supplied by the Mongo/SQL subclasses (`MeetingSchedulingJobMongo`/
|
|
16
|
+
* `MeetingSchedulingJobSQL`), following the same generic pattern `ScanQueueJob` uses.
|
|
17
|
+
*
|
|
18
|
+
* @author Jean-Philippe Steinmetz
|
|
19
|
+
*/
|
|
20
|
+
export declare abstract class MeetingSchedulingJob<CE extends CalendarEvent> extends BackgroundService {
|
|
21
|
+
protected abstract calendarEventClass: any;
|
|
22
|
+
private _objectFactory?;
|
|
23
|
+
private calendarEventRepo?;
|
|
24
|
+
private scheduleExpr;
|
|
25
|
+
private batchSize;
|
|
26
|
+
private logger;
|
|
27
|
+
get schedule(): string | undefined;
|
|
28
|
+
init(): Promise<void>;
|
|
29
|
+
start(): Promise<void>;
|
|
30
|
+
stop(): Promise<void> | void;
|
|
31
|
+
run(): Promise<void>;
|
|
32
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { BackgroundService } from "@rapidrest/service-core";
|
|
2
|
+
import { QuarantineEntry } from "../models/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Purges `QuarantineEntry` rows (and, once `BlobStore` deletion is wired in here, their `rawBlobKey` payload)
|
|
5
|
+
* once they've sat in quarantine longer than `retention_days`, whether or not they were ever released. A
|
|
6
|
+
* released entry is retained for the same window as an unreleased one — this job doesn't distinguish between
|
|
7
|
+
* them, since both represent quarantine history an operator may want to review for that same window.
|
|
8
|
+
*
|
|
9
|
+
* Concrete entity classes are supplied by the Mongo/SQL subclasses (`QuarantineRetentionJobMongo`/
|
|
10
|
+
* `QuarantineRetentionJobSQL`), following the same generic pattern `ScanQueueJob` uses.
|
|
11
|
+
*
|
|
12
|
+
* @author Jean-Philippe Steinmetz
|
|
13
|
+
*/
|
|
14
|
+
export declare abstract class QuarantineRetentionJob<Q extends QuarantineEntry> extends BackgroundService {
|
|
15
|
+
protected abstract quarantineEntryClass: any;
|
|
16
|
+
private _objectFactory?;
|
|
17
|
+
private quarantineEntryRepo?;
|
|
18
|
+
private scheduleExpr;
|
|
19
|
+
private batchSize;
|
|
20
|
+
private retentionDays;
|
|
21
|
+
private logger;
|
|
22
|
+
get schedule(): string | undefined;
|
|
23
|
+
init(): Promise<void>;
|
|
24
|
+
start(): Promise<void>;
|
|
25
|
+
stop(): Promise<void> | void;
|
|
26
|
+
run(): Promise<void>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { BackgroundService } from "@rapidrest/service-core";
|
|
2
|
+
import { Attachment, Folder, IngestQueueEntry, Message, QuarantineEntry, ScanResult } from "../models/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Drains `IngestQueueEntry` rows staged by `BaseMailIngestRoute`: runs the `ScanPipeline` against each one's
|
|
5
|
+
* raw message, then either delivers it to the mailbox's Inbox, files it in Junk, or holds it in
|
|
6
|
+
* `QuarantineEntry` — depending on `resolveDeliveryVerdict()`. No client protocol (webmail/EAS/MAPI) ever sees
|
|
7
|
+
* a message before this job has processed it.
|
|
8
|
+
*
|
|
9
|
+
* Concrete entity classes are supplied by the Mongo/SQL subclasses (`ScanQueueJobMongo`/`ScanQueueJobSQL`),
|
|
10
|
+
* following the same multi-entity-type generic pattern `DefaultAccounts` uses.
|
|
11
|
+
*
|
|
12
|
+
* @author Jean-Philippe Steinmetz
|
|
13
|
+
*/
|
|
14
|
+
export declare abstract class ScanQueueJob<Q extends IngestQueueEntry, F extends Folder, M extends Message, A extends Attachment, QE extends QuarantineEntry, SR extends ScanResult> extends BackgroundService {
|
|
15
|
+
protected abstract ingestQueueClass: any;
|
|
16
|
+
protected abstract folderClass: any;
|
|
17
|
+
protected abstract messageClass: any;
|
|
18
|
+
protected abstract attachmentClass: any;
|
|
19
|
+
protected abstract quarantineEntryClass: any;
|
|
20
|
+
protected abstract scanResultClass: any;
|
|
21
|
+
private _objectFactory?;
|
|
22
|
+
private ingestQueueRepo?;
|
|
23
|
+
private folderRepo?;
|
|
24
|
+
private messageRepo?;
|
|
25
|
+
private attachmentRepo?;
|
|
26
|
+
private quarantineEntryRepo?;
|
|
27
|
+
private scanResultRepo?;
|
|
28
|
+
private blobStore?;
|
|
29
|
+
private scanPipeline?;
|
|
30
|
+
/** Publishes a live-update notification (see `push/MailPushRoute.ts`) once a message is delivered. */
|
|
31
|
+
private notificationUtils?;
|
|
32
|
+
private scheduleExpr;
|
|
33
|
+
private batchSize;
|
|
34
|
+
private logger;
|
|
35
|
+
get schedule(): string | undefined;
|
|
36
|
+
init(): Promise<void>;
|
|
37
|
+
start(): Promise<void>;
|
|
38
|
+
stop(): Promise<void> | void;
|
|
39
|
+
run(): Promise<void>;
|
|
40
|
+
private processEntry;
|
|
41
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { BackgroundService } from "@rapidrest/service-core";
|
|
2
|
+
import { Attachment, Message } from "../models/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Reconciles `SearchProvider`'s index against `Message` records that haven't been indexed yet
|
|
5
|
+
* (`Message.searchIndexedAt` is unset). This is what decouples "committed to the primary datastore" from
|
|
6
|
+
* "visible in search" (see `SearchProvider`'s doc comment) — a just-ingested or just-sent message is readable
|
|
7
|
+
* via the standard REST API immediately, and becomes findable via search within one run of this job.
|
|
8
|
+
*
|
|
9
|
+
* Scoped to `Message` search for the initial pragmatic subset, since full-text search over subject/body/
|
|
10
|
+
* attachments was the explicit requirement driving this subsystem; indexing Contacts/CalendarEvents/Notes/
|
|
11
|
+
* Tasks is a natural extension (the `SearchProvider`/`SearchDocument` interfaces already support it) but is
|
|
12
|
+
* deliberately left for a later pass rather than built speculatively here.
|
|
13
|
+
*
|
|
14
|
+
* `AttachmentExtractionJob` clears `searchIndexedAt` back to `undefined` on a message whose attachment text
|
|
15
|
+
* extraction completes *after* this job already indexed it once, so it gets picked up again with the newly
|
|
16
|
+
* available attachment text.
|
|
17
|
+
*
|
|
18
|
+
* @author Jean-Philippe Steinmetz
|
|
19
|
+
*/
|
|
20
|
+
export declare abstract class SearchIndexJob<M extends Message, A extends Attachment> extends BackgroundService {
|
|
21
|
+
protected abstract messageClass: any;
|
|
22
|
+
protected abstract attachmentClass: any;
|
|
23
|
+
private _objectFactory?;
|
|
24
|
+
private messageRepo?;
|
|
25
|
+
private attachmentRepo?;
|
|
26
|
+
private blobStore?;
|
|
27
|
+
private searchProvider?;
|
|
28
|
+
private scheduleExpr;
|
|
29
|
+
private batchSize;
|
|
30
|
+
private logger;
|
|
31
|
+
get schedule(): string | undefined;
|
|
32
|
+
init(): Promise<void>;
|
|
33
|
+
start(): Promise<void>;
|
|
34
|
+
stop(): Promise<void> | void;
|
|
35
|
+
run(): Promise<void>;
|
|
36
|
+
private buildDocument;
|
|
37
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./AttachmentExtractionJob.js";
|
|
2
|
+
export * from "./CalendarReminderJob.js";
|
|
3
|
+
export * from "./EasDeviceStateCleanupJob.js";
|
|
4
|
+
export * from "./ExternalShareExpirationJob.js";
|
|
5
|
+
export * from "./MailboxQuotaRecalcJob.js";
|
|
6
|
+
export * from "./MeetingSchedulingJob.js";
|
|
7
|
+
export * from "./QuarantineRetentionJob.js";
|
|
8
|
+
export * from "./ScanQueueJob.js";
|
|
9
|
+
export * from "./SearchIndexJob.js";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { AttachmentExtractionJob } from "../AttachmentExtractionJob.js";
|
|
2
|
+
import { AttachmentMongo, MessageMongo } from "../../mongo.js";
|
|
3
|
+
export declare class AttachmentExtractionJobMongo extends AttachmentExtractionJob<AttachmentMongo, MessageMongo> {
|
|
4
|
+
protected attachmentClass: any;
|
|
5
|
+
protected messageClass: any;
|
|
6
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { EasDeviceStateCleanupJob } from "../EasDeviceStateCleanupJob.js";
|
|
2
|
+
import { DeviceSyncStateMongo } from "../../mongo.js";
|
|
3
|
+
export declare class EasDeviceStateCleanupJobMongo extends EasDeviceStateCleanupJob<DeviceSyncStateMongo> {
|
|
4
|
+
protected deviceSyncStateClass: any;
|
|
5
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ExternalShareExpirationJob } from "../ExternalShareExpirationJob.js";
|
|
2
|
+
import { CalendarShareLinkMongo } from "../../mongo.js";
|
|
3
|
+
export declare class ExternalShareExpirationJobMongo extends ExternalShareExpirationJob<CalendarShareLinkMongo> {
|
|
4
|
+
protected calendarShareLinkClass: any;
|
|
5
|
+
}
|