@rapidmx/activesync-plugin 1.0.0-beta.2
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 +57 -0
- package/dist/lib/BaseDeviceSyncStateRoute.js +90 -0
- package/dist/lib/BaseDeviceSyncStateRoute.js.map +1 -0
- package/dist/lib/BaseEasRoute.js +213 -0
- package/dist/lib/BaseEasRoute.js.map +1 -0
- package/dist/lib/CompactDateTime.js +43 -0
- package/dist/lib/CompactDateTime.js.map +1 -0
- package/dist/lib/EasCommandHandler.js +2 -0
- package/dist/lib/EasCommandHandler.js.map +1 -0
- package/dist/lib/EasSyncKeyUtils.js +119 -0
- package/dist/lib/EasSyncKeyUtils.js.map +1 -0
- package/dist/lib/adapters/CalendarSyncAdapter.js +255 -0
- package/dist/lib/adapters/CalendarSyncAdapter.js.map +1 -0
- package/dist/lib/adapters/ContactsSyncAdapter.js +164 -0
- package/dist/lib/adapters/ContactsSyncAdapter.js.map +1 -0
- package/dist/lib/adapters/EasCollectionSyncAdapter.js +2 -0
- package/dist/lib/adapters/EasCollectionSyncAdapter.js.map +1 -0
- package/dist/lib/adapters/EmailSyncAdapter.js +269 -0
- package/dist/lib/adapters/EmailSyncAdapter.js.map +1 -0
- package/dist/lib/adapters/TasksSyncAdapter.js +100 -0
- package/dist/lib/adapters/TasksSyncAdapter.js.map +1 -0
- package/dist/lib/adapters/mongo/EmailSyncAdapterMongo.js +16 -0
- package/dist/lib/adapters/mongo/EmailSyncAdapterMongo.js.map +1 -0
- package/dist/lib/adapters/mongo/index.js +6 -0
- package/dist/lib/adapters/mongo/index.js.map +1 -0
- package/dist/lib/adapters/sql/EmailSyncAdapterSQL.js +16 -0
- package/dist/lib/adapters/sql/EmailSyncAdapterSQL.js.map +1 -0
- package/dist/lib/adapters/sql/index.js +6 -0
- package/dist/lib/adapters/sql/index.js.map +1 -0
- package/dist/lib/codec/WbxmlCodePages.js +706 -0
- package/dist/lib/codec/WbxmlCodePages.js.map +1 -0
- package/dist/lib/codec/WbxmlDecoder.js +154 -0
- package/dist/lib/codec/WbxmlDecoder.js.map +1 -0
- package/dist/lib/codec/WbxmlElement.js +31 -0
- package/dist/lib/codec/WbxmlElement.js.map +1 -0
- package/dist/lib/codec/WbxmlEncoder.js +88 -0
- package/dist/lib/codec/WbxmlEncoder.js.map +1 -0
- package/dist/lib/commands/ComposeMailCommand.js +187 -0
- package/dist/lib/commands/ComposeMailCommand.js.map +1 -0
- package/dist/lib/commands/FolderSyncCommand.js +155 -0
- package/dist/lib/commands/FolderSyncCommand.js.map +1 -0
- package/dist/lib/commands/GetItemEstimateCommand.js +149 -0
- package/dist/lib/commands/GetItemEstimateCommand.js.map +1 -0
- package/dist/lib/commands/ItemOperationsCommand.js +337 -0
- package/dist/lib/commands/ItemOperationsCommand.js.map +1 -0
- package/dist/lib/commands/MeetingResponseCommand.js +120 -0
- package/dist/lib/commands/MeetingResponseCommand.js.map +1 -0
- package/dist/lib/commands/MoveItemsCommand.js +103 -0
- package/dist/lib/commands/MoveItemsCommand.js.map +1 -0
- package/dist/lib/commands/PingCommand.js +145 -0
- package/dist/lib/commands/PingCommand.js.map +1 -0
- package/dist/lib/commands/ProvisionCommand.js +164 -0
- package/dist/lib/commands/ProvisionCommand.js.map +1 -0
- package/dist/lib/commands/ResolveRecipientsCommand.js +123 -0
- package/dist/lib/commands/ResolveRecipientsCommand.js.map +1 -0
- package/dist/lib/commands/SearchCommand.js +234 -0
- package/dist/lib/commands/SearchCommand.js.map +1 -0
- package/dist/lib/commands/SendMailCommand.js +18 -0
- package/dist/lib/commands/SendMailCommand.js.map +1 -0
- package/dist/lib/commands/SettingsCommand.js +138 -0
- package/dist/lib/commands/SettingsCommand.js.map +1 -0
- package/dist/lib/commands/SmartForwardCommand.js +22 -0
- package/dist/lib/commands/SmartForwardCommand.js.map +1 -0
- package/dist/lib/commands/SmartReplyCommand.js +22 -0
- package/dist/lib/commands/SmartReplyCommand.js.map +1 -0
- package/dist/lib/commands/SyncCommand.js +406 -0
- package/dist/lib/commands/SyncCommand.js.map +1 -0
- package/dist/lib/commands/mongo/FolderSyncCommandMongo.js +16 -0
- package/dist/lib/commands/mongo/FolderSyncCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/GetItemEstimateCommandMongo.js +21 -0
- package/dist/lib/commands/mongo/GetItemEstimateCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/ItemOperationsCommandMongo.js +18 -0
- package/dist/lib/commands/mongo/ItemOperationsCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/MeetingResponseCommandMongo.js +17 -0
- package/dist/lib/commands/mongo/MeetingResponseCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/MoveItemsCommandMongo.js +17 -0
- package/dist/lib/commands/mongo/MoveItemsCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/ResolveRecipientsCommandMongo.js +16 -0
- package/dist/lib/commands/mongo/ResolveRecipientsCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/SearchCommandMongo.js +19 -0
- package/dist/lib/commands/mongo/SearchCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/SendMailCommandMongo.js +17 -0
- package/dist/lib/commands/mongo/SendMailCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/SettingsCommandMongo.js +16 -0
- package/dist/lib/commands/mongo/SettingsCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/SmartForwardCommandMongo.js +17 -0
- package/dist/lib/commands/mongo/SmartForwardCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/SmartReplyCommandMongo.js +17 -0
- package/dist/lib/commands/mongo/SmartReplyCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/SyncCommandMongo.js +26 -0
- package/dist/lib/commands/mongo/SyncCommandMongo.js.map +1 -0
- package/dist/lib/commands/mongo/index.js +14 -0
- package/dist/lib/commands/mongo/index.js.map +1 -0
- package/dist/lib/commands/sql/FolderSyncCommandSQL.js +16 -0
- package/dist/lib/commands/sql/FolderSyncCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/GetItemEstimateCommandSQL.js +21 -0
- package/dist/lib/commands/sql/GetItemEstimateCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/ItemOperationsCommandSQL.js +18 -0
- package/dist/lib/commands/sql/ItemOperationsCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/MeetingResponseCommandSQL.js +17 -0
- package/dist/lib/commands/sql/MeetingResponseCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/MoveItemsCommandSQL.js +17 -0
- package/dist/lib/commands/sql/MoveItemsCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/ResolveRecipientsCommandSQL.js +16 -0
- package/dist/lib/commands/sql/ResolveRecipientsCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/SearchCommandSQL.js +19 -0
- package/dist/lib/commands/sql/SearchCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/SendMailCommandSQL.js +17 -0
- package/dist/lib/commands/sql/SendMailCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/SettingsCommandSQL.js +16 -0
- package/dist/lib/commands/sql/SettingsCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/SmartForwardCommandSQL.js +17 -0
- package/dist/lib/commands/sql/SmartForwardCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/SmartReplyCommandSQL.js +17 -0
- package/dist/lib/commands/sql/SmartReplyCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/SyncCommandSQL.js +26 -0
- package/dist/lib/commands/sql/SyncCommandSQL.js.map +1 -0
- package/dist/lib/commands/sql/index.js +14 -0
- package/dist/lib/commands/sql/index.js.map +1 -0
- package/dist/lib/index.js +58 -0
- package/dist/lib/index.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/mongo/EasDeviceStateCleanupJobMongo.js +13 -0
- package/dist/lib/jobs/mongo/EasDeviceStateCleanupJobMongo.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/models/DeviceSyncState.js +2 -0
- package/dist/lib/models/DeviceSyncState.js.map +1 -0
- package/dist/lib/models/mongo/DeviceSyncStateMongo.js +130 -0
- package/dist/lib/models/mongo/DeviceSyncStateMongo.js.map +1 -0
- package/dist/lib/models/sql/DeviceSyncStateSQL.js +130 -0
- package/dist/lib/models/sql/DeviceSyncStateSQL.js.map +1 -0
- package/dist/lib/mongo/DeviceSyncStateRouteMongo.js +28 -0
- package/dist/lib/mongo/DeviceSyncStateRouteMongo.js.map +1 -0
- package/dist/lib/mongo/EasRouteMongo.js +63 -0
- package/dist/lib/mongo/EasRouteMongo.js.map +1 -0
- package/dist/lib/mongo/index.js +9 -0
- package/dist/lib/mongo/index.js.map +1 -0
- package/dist/lib/mongo.js +15 -0
- package/dist/lib/mongo.js.map +1 -0
- package/dist/lib/sql/DeviceSyncStateRouteSQL.js +28 -0
- package/dist/lib/sql/DeviceSyncStateRouteSQL.js.map +1 -0
- package/dist/lib/sql/EasRouteSQL.js +63 -0
- package/dist/lib/sql/EasRouteSQL.js.map +1 -0
- package/dist/lib/sql/index.js +9 -0
- package/dist/lib/sql/index.js.map +1 -0
- package/dist/lib/sql.js +15 -0
- package/dist/lib/sql.js.map +1 -0
- package/dist/types/BaseDeviceSyncStateRoute.d.ts +34 -0
- package/dist/types/BaseEasRoute.d.ts +65 -0
- package/dist/types/CompactDateTime.d.ts +22 -0
- package/dist/types/EasCommandHandler.d.ts +59 -0
- package/dist/types/EasSyncKeyUtils.d.ts +89 -0
- package/dist/types/adapters/CalendarSyncAdapter.d.ts +52 -0
- package/dist/types/adapters/ContactsSyncAdapter.d.ts +33 -0
- package/dist/types/adapters/EasCollectionSyncAdapter.d.ts +55 -0
- package/dist/types/adapters/EmailSyncAdapter.d.ts +71 -0
- package/dist/types/adapters/TasksSyncAdapter.d.ts +32 -0
- package/dist/types/adapters/mongo/EmailSyncAdapterMongo.d.ts +7 -0
- package/dist/types/adapters/mongo/index.d.ts +1 -0
- package/dist/types/adapters/sql/EmailSyncAdapterSQL.d.ts +7 -0
- package/dist/types/adapters/sql/index.d.ts +1 -0
- package/dist/types/codec/WbxmlCodePages.d.ts +45 -0
- package/dist/types/codec/WbxmlDecoder.d.ts +33 -0
- package/dist/types/codec/WbxmlElement.d.ts +43 -0
- package/dist/types/codec/WbxmlEncoder.d.ts +20 -0
- package/dist/types/commands/ComposeMailCommand.d.ts +50 -0
- package/dist/types/commands/FolderSyncCommand.d.ts +25 -0
- package/dist/types/commands/GetItemEstimateCommand.d.ts +43 -0
- package/dist/types/commands/ItemOperationsCommand.d.ts +72 -0
- package/dist/types/commands/MeetingResponseCommand.d.ts +32 -0
- package/dist/types/commands/MoveItemsCommand.d.ts +29 -0
- package/dist/types/commands/PingCommand.d.ts +33 -0
- package/dist/types/commands/ProvisionCommand.d.ts +54 -0
- package/dist/types/commands/ResolveRecipientsCommand.d.ts +36 -0
- package/dist/types/commands/SearchCommand.d.ts +60 -0
- package/dist/types/commands/SendMailCommand.d.ts +10 -0
- package/dist/types/commands/SettingsCommand.d.ts +37 -0
- package/dist/types/commands/SmartForwardCommand.d.ts +17 -0
- package/dist/types/commands/SmartReplyCommand.d.ts +17 -0
- package/dist/types/commands/SyncCommand.d.ts +100 -0
- package/dist/types/commands/mongo/FolderSyncCommandMongo.d.ts +8 -0
- package/dist/types/commands/mongo/GetItemEstimateCommandMongo.d.ts +7 -0
- package/dist/types/commands/mongo/ItemOperationsCommandMongo.d.ts +9 -0
- package/dist/types/commands/mongo/MeetingResponseCommandMongo.d.ts +8 -0
- package/dist/types/commands/mongo/MoveItemsCommandMongo.d.ts +8 -0
- package/dist/types/commands/mongo/ResolveRecipientsCommandMongo.d.ts +7 -0
- package/dist/types/commands/mongo/SearchCommandMongo.d.ts +9 -0
- package/dist/types/commands/mongo/SendMailCommandMongo.d.ts +8 -0
- package/dist/types/commands/mongo/SettingsCommandMongo.d.ts +7 -0
- package/dist/types/commands/mongo/SmartForwardCommandMongo.d.ts +8 -0
- package/dist/types/commands/mongo/SmartReplyCommandMongo.d.ts +8 -0
- package/dist/types/commands/mongo/SyncCommandMongo.d.ts +8 -0
- package/dist/types/commands/mongo/index.d.ts +9 -0
- package/dist/types/commands/sql/FolderSyncCommandSQL.d.ts +8 -0
- package/dist/types/commands/sql/GetItemEstimateCommandSQL.d.ts +7 -0
- package/dist/types/commands/sql/ItemOperationsCommandSQL.d.ts +9 -0
- package/dist/types/commands/sql/MeetingResponseCommandSQL.d.ts +8 -0
- package/dist/types/commands/sql/MoveItemsCommandSQL.d.ts +8 -0
- package/dist/types/commands/sql/ResolveRecipientsCommandSQL.d.ts +7 -0
- package/dist/types/commands/sql/SearchCommandSQL.d.ts +9 -0
- package/dist/types/commands/sql/SendMailCommandSQL.d.ts +8 -0
- package/dist/types/commands/sql/SettingsCommandSQL.d.ts +7 -0
- package/dist/types/commands/sql/SmartForwardCommandSQL.d.ts +8 -0
- package/dist/types/commands/sql/SmartReplyCommandSQL.d.ts +8 -0
- package/dist/types/commands/sql/SyncCommandSQL.d.ts +8 -0
- package/dist/types/commands/sql/index.d.ts +9 -0
- package/dist/types/index.d.ts +53 -0
- package/dist/types/jobs/EasDeviceStateCleanupJob.d.ts +26 -0
- package/dist/types/jobs/mongo/EasDeviceStateCleanupJobMongo.d.ts +5 -0
- package/dist/types/jobs/sql/EasDeviceStateCleanupJobSQL.d.ts +5 -0
- package/dist/types/models/DeviceSyncState.d.ts +30 -0
- package/dist/types/models/mongo/DeviceSyncStateMongo.d.ts +22 -0
- package/dist/types/models/sql/DeviceSyncStateSQL.d.ts +22 -0
- package/dist/types/mongo/DeviceSyncStateRouteMongo.d.ts +8 -0
- package/dist/types/mongo/EasRouteMongo.d.ts +14 -0
- package/dist/types/mongo/index.d.ts +4 -0
- package/dist/types/mongo.d.ts +10 -0
- package/dist/types/sql/DeviceSyncStateRouteSQL.d.ts +8 -0
- package/dist/types/sql/EasRouteSQL.d.ts +14 -0
- package/dist/types/sql/index.d.ts +4 -0
- package/dist/types/sql.d.ts +10 -0
- package/package.json +238 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type WbxmlElement } from "../codec/WbxmlElement.js";
|
|
2
|
+
import type { EasCommandContext, EasCommandHandler } from "../EasCommandHandler.js";
|
|
3
|
+
/**
|
|
4
|
+
* Handles EAS `Search` for the `GAL` and `Mailbox` stores - `DocumentLibrary` (the real spec's third store type)
|
|
5
|
+
* remains out of scope, matching `ItemOperationsCommand`'s identical scope decision; this library has no
|
|
6
|
+
* document-library model.
|
|
7
|
+
*
|
|
8
|
+
* **`GAL`**: this library's `Contact` records are also the source of truth for GAL lookups against a mailbox's
|
|
9
|
+
* own address book (see the architecture note on `Contact` itself). A simple case-insensitive substring match
|
|
10
|
+
* via `RepoUtils.find()` directly, not the heavier `SearchProvider` full-text index - GAL lookups are
|
|
11
|
+
* small-scale exact/prefix matching against a personal address book, not relevance-ranked full text over large
|
|
12
|
+
* content. Only `displayName`/`givenName`/`surname`/`company` are matched - `Contact.emails`/`phones` are
|
|
13
|
+
* embedded arrays of objects, which a plain per-field regex query can't reach into on either backend (confirmed:
|
|
14
|
+
* MongoDB's `$regex` against an array-of-objects field matches nothing useful, and this library's own
|
|
15
|
+
* query-injection guard rejects dot-notation field paths like `"emails.address"` outright) - a documented gap,
|
|
16
|
+
* not an oversight.
|
|
17
|
+
*
|
|
18
|
+
* **`Mailbox`**: real full-text search over the caller's own `Email` messages, backed by `restapi`'s
|
|
19
|
+
* `SearchProvider` (its own full-text index, kept eventually-consistent with the primary datastore via
|
|
20
|
+
* `SearchIndexJob` - a just-sent/just-received message may briefly not be findable yet). **Pragmatic subset**:
|
|
21
|
+
* only `Class` `Email` is supported (a `Query` naming any other class is rejected, matching the `GAL`-only
|
|
22
|
+
* precedent this file already established for search generally); only the common real-world `Query` shape -
|
|
23
|
+
* `Class`/`CollectionId`/`FreeText`, optionally grouped under one `And` - is parsed, not the full recursive
|
|
24
|
+
* `And`/`Or`/`EqualTo`/`GreaterThan`/`LessThan` boolean-tree grammar MS-ASCMD's schema allows for, so a
|
|
25
|
+
* multi-level nested query silently only sees the first `And` group's own direct children. Each match is
|
|
26
|
+
* re-verified for `READ` on its own current `folderUid` before being included - `SearchProvider`'s index is
|
|
27
|
+
* scoped by `mailboxUid` alone, not per-folder ACL, so this is the one place that check still has to happen
|
|
28
|
+
* per-result rather than once up front. `SearchResultPage` carries no total count (the underlying providers
|
|
29
|
+
* don't compute one cheaply over a relevance-ranked query), so `Total` here means "how many matches this
|
|
30
|
+
* request's own capped fetch actually returned" - a client requesting a `Range` past that cap sees fewer
|
|
31
|
+
* results than may really exist, a documented approximation rather than exact server-side paging.
|
|
32
|
+
*
|
|
33
|
+
* `contactClass`/`messageClass`/`emailAdapterClass` are supplied by the Mongo/SQL concrete subclasses.
|
|
34
|
+
*
|
|
35
|
+
* @author Jean-Philippe Steinmetz
|
|
36
|
+
*/
|
|
37
|
+
export declare abstract class SearchCommand implements EasCommandHandler {
|
|
38
|
+
readonly command = "Search";
|
|
39
|
+
protected abstract contactClass: any;
|
|
40
|
+
protected abstract messageClass: any;
|
|
41
|
+
protected abstract emailAdapterClass: any;
|
|
42
|
+
private _objectFactory?;
|
|
43
|
+
private contactRepo?;
|
|
44
|
+
private messageRepo?;
|
|
45
|
+
private emailAdapter?;
|
|
46
|
+
private searchProvider?;
|
|
47
|
+
private aclUtils?;
|
|
48
|
+
private defaultRangeEnd;
|
|
49
|
+
private maxRangeEnd;
|
|
50
|
+
init(): Promise<void>;
|
|
51
|
+
handle(ctx: EasCommandContext): Promise<WbxmlElement | undefined>;
|
|
52
|
+
private handleGal;
|
|
53
|
+
private handleMailbox;
|
|
54
|
+
private contactToResult;
|
|
55
|
+
/** Reuses `EmailSyncAdapter.toApplicationData()`'s own field mapping (Subject/From/To/Cc/Bcc/DateReceived/
|
|
56
|
+
* Importance/Read/Flag/Body/ConversationId) for a Mailbox-store search hit's `Properties` - the same
|
|
57
|
+
* per-field shape `Sync` already renders for this message, rather than a second, parallel mapping that
|
|
58
|
+
* could drift out of sync with it. */
|
|
59
|
+
private messageToResult;
|
|
60
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ComposeMailCommand } from "./ComposeMailCommand.js";
|
|
2
|
+
/**
|
|
3
|
+
* Handles EAS `SendMail`: relays a freshly composed message with no referenced original - see
|
|
4
|
+
* `ComposeMailCommand`'s own doc comment for the full shared implementation.
|
|
5
|
+
*
|
|
6
|
+
* @author Jean-Philippe Steinmetz
|
|
7
|
+
*/
|
|
8
|
+
export declare abstract class SendMailCommand extends ComposeMailCommand {
|
|
9
|
+
readonly command = "SendMail";
|
|
10
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type WbxmlElement } from "../codec/WbxmlElement.js";
|
|
2
|
+
import type { EasCommandContext, EasCommandHandler } from "../EasCommandHandler.js";
|
|
3
|
+
/**
|
|
4
|
+
* Handles EAS `Settings`: the first-run/general-purpose device<->server settings exchange. This pragmatic
|
|
5
|
+
* subset supports the sub-elements every real client actually depends on:
|
|
6
|
+
*
|
|
7
|
+
* - `UserInformation`/`Get`: returns the mailbox's `primarySmtpAddress`/`aliasAddresses` as `EmailAddresses`.
|
|
8
|
+
* - `DeviceInformation`/`Set`: acknowledged with `Status 1` but not persisted anywhere - `DeviceSyncState` has
|
|
9
|
+
* no fields for a device's model/IMEI/OS/friendly name, and nothing else in this library currently consumes
|
|
10
|
+
* them. A real client only requires the acknowledgement to proceed past first-run setup, not that the values
|
|
11
|
+
* are retrievable later.
|
|
12
|
+
* - `Oof`/`Get` and `Oof`/`Set`: reads/writes `Mailbox.oofEnabled`/`oofMessage`/`oofStartTime`/`oofEndTime`.
|
|
13
|
+
* `StartTime`/`EndTime` use MS-ASDTYPE's plain `dateTime` type (`Date.prototype.toISOString()`), not Compact
|
|
14
|
+
* DateTime - confirmed against MS-ASSETTINGS directly, unlike `Calendar`/`Tasks`' timestamp fields (see
|
|
15
|
+
* `CompactDateTime.ts`'s own doc comment on that exact distinction). A single combined reply message is stored
|
|
16
|
+
* rather than the spec's three audience-specific `OofMessage` variants (internal/external-known/
|
|
17
|
+
* external-unknown) - matches this codebase's existing "one thing, not three" simplification precedent (e.g.
|
|
18
|
+
* `ContactsSyncAdapter`'s single-slot phone/email handling).
|
|
19
|
+
* - `RightsManagementInformation` is not implemented - deferred, matching this library's "pragmatic subset"
|
|
20
|
+
* precedent elsewhere (e.g. `ComposeMailCommand`'s own documented gaps).
|
|
21
|
+
*
|
|
22
|
+
* `mailboxClass` is supplied by the Mongo/SQL concrete subclasses.
|
|
23
|
+
*
|
|
24
|
+
* @author Jean-Philippe Steinmetz
|
|
25
|
+
*/
|
|
26
|
+
export declare abstract class SettingsCommand implements EasCommandHandler {
|
|
27
|
+
readonly command = "Settings";
|
|
28
|
+
protected abstract mailboxClass: any;
|
|
29
|
+
private _objectFactory?;
|
|
30
|
+
private mailboxRepo?;
|
|
31
|
+
init(): Promise<void>;
|
|
32
|
+
handle(ctx: EasCommandContext): Promise<WbxmlElement | undefined>;
|
|
33
|
+
/** `OofState`: `0`=disabled, `1`=enabled indefinitely, `2`=time-based (only while now is within
|
|
34
|
+
* `StartTime`/`EndTime`). */
|
|
35
|
+
private getOof;
|
|
36
|
+
private setOof;
|
|
37
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ComposeMailCommand } from "./ComposeMailCommand.js";
|
|
2
|
+
import type { EasCommandContext } from "../EasCommandHandler.js";
|
|
3
|
+
import type { Message } from "@rapidmx/restapi";
|
|
4
|
+
/**
|
|
5
|
+
* Handles EAS `SmartForward`: relays a freshly composed message threaded to (and referencing) the original via
|
|
6
|
+
* `<Source>`, then flips the original's `Forwarded` flag - see `ComposeMailCommand`'s own doc comment for the
|
|
7
|
+
* full shared implementation and this pragmatic subset's scope.
|
|
8
|
+
*
|
|
9
|
+
* @author Jean-Philippe Steinmetz
|
|
10
|
+
*/
|
|
11
|
+
export declare abstract class SmartForwardCommand extends ComposeMailCommand {
|
|
12
|
+
readonly command = "SmartForward";
|
|
13
|
+
protected markOriginal(ctx: EasCommandContext, original: Message & {
|
|
14
|
+
uid: string;
|
|
15
|
+
version: number;
|
|
16
|
+
}): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ComposeMailCommand } from "./ComposeMailCommand.js";
|
|
2
|
+
import type { EasCommandContext } from "../EasCommandHandler.js";
|
|
3
|
+
import type { Message } from "@rapidmx/restapi";
|
|
4
|
+
/**
|
|
5
|
+
* Handles EAS `SmartReply`: relays a freshly composed message threaded to (and referencing) the original via
|
|
6
|
+
* `<Source>`, then flips the original's `Answered` flag - see `ComposeMailCommand`'s own doc comment for the
|
|
7
|
+
* full shared implementation and this pragmatic subset's scope.
|
|
8
|
+
*
|
|
9
|
+
* @author Jean-Philippe Steinmetz
|
|
10
|
+
*/
|
|
11
|
+
export declare abstract class SmartReplyCommand extends ComposeMailCommand {
|
|
12
|
+
readonly command = "SmartReply";
|
|
13
|
+
protected markOriginal(ctx: EasCommandContext, original: Message & {
|
|
14
|
+
uid: string;
|
|
15
|
+
version: number;
|
|
16
|
+
}): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { type RecoverableBaseEntity } from "@rapidrest/service-core";
|
|
2
|
+
import { type WbxmlElement } from "../codec/WbxmlElement.js";
|
|
3
|
+
import type { EasCommandContext, EasCommandHandler } from "../EasCommandHandler.js";
|
|
4
|
+
/** Binds one MS-ASCMD `Class` value (`"Email"`, `"Contacts"`, ...) to the concrete entity class `SyncCommand`
|
|
5
|
+
* should build a `RepoUtils` for, and the adapter class that maps that entity to/from `ApplicationData`.
|
|
6
|
+
* Supplied by the Mongo/SQL concrete subclasses, one map entry per supported collection type.
|
|
7
|
+
*
|
|
8
|
+
* `adapterClass`, not a pre-built `adapter` instance: `SyncCommand.init()` instantiates each one itself via
|
|
9
|
+
* `ObjectFactory`, so an adapter can `@Inject` its own dependencies (`EmailSyncAdapter` needs `BlobStore` for a
|
|
10
|
+
* Draft's body) exactly like any other DI-managed class in this library - a bare `new EmailSyncAdapter()` has
|
|
11
|
+
* no way to satisfy that. */
|
|
12
|
+
export interface SyncCollectionBinding<T extends RecoverableBaseEntity> {
|
|
13
|
+
entityClass: any;
|
|
14
|
+
adapterClass: any;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Handles EAS `Sync`: enumerates `Add`/`Change`/`Delete`s for a single folder's contents since the device's last
|
|
18
|
+
* `Sync` of that folder, using the same watermark-based cursor mechanism `FolderSyncCommand` uses (via
|
|
19
|
+
* `EasSyncKeyUtils`), scoped by `folderUid` instead of `mailboxUid`, and keyed per-folder in
|
|
20
|
+
* `DeviceSyncState.folderSyncKeys` (the `CollectionId` a client sends *is* the `folderUid` - this library never
|
|
21
|
+
* invents a separate collection identifier).
|
|
22
|
+
*
|
|
23
|
+
* **Multi-collection requests**: every `<Collection>` in a request's `<Collections>` is processed and gets its
|
|
24
|
+
* own `<Collection>` entry in the response, each with its own independent `SyncKey`/`Status` - a client
|
|
25
|
+
* syncing several folders in one round trip (the common case once the initial per-folder backlog is done)
|
|
26
|
+
* gets one response covering all of them. All per-collection `SyncKey`/remembered-`Class` writes for the whole
|
|
27
|
+
* request are batched into a single `persistDeviceSyncState` call after every collection has been processed
|
|
28
|
+
* (never one call per collection) - see `EasSyncKeyUtils.persistDeviceSyncState`'s own doc comment for why a
|
|
29
|
+
* second write to the same `DeviceSyncState` within one request must never be built off a stale copy.
|
|
30
|
+
*
|
|
31
|
+
* **`Class` is only required on a collection's first (`SyncKey "0"`) request**, per `[MS-ASCMD]` - once seen,
|
|
32
|
+
* it's remembered in `DeviceSyncState.folderCollectionClasses` (keyed by `folderUid`) so a later request may
|
|
33
|
+
* omit it; omitting it for a folder never previously synced still gets `Status 4` (nothing to fall back to).
|
|
34
|
+
*
|
|
35
|
+
* **Every `CollectionId` is ACL-checked against the caller before it's touched**: `processCollection()` requires
|
|
36
|
+
* `ACLAction.READ` on the folder before enumerating or accepting any Commands for it at all (a folder the caller
|
|
37
|
+
* can't read is reported the same as an unrecognized collection - Status `4` - rather than leaking whether it
|
|
38
|
+
* exists); `applyAdd`/`applyChange`/`applyDelete` additionally require `CREATE`/`UPDATE`/`DELETE` respectively,
|
|
39
|
+
* and `applyChange`/`applyDelete` re-verify the resolved item's own `folderUid` actually matches the collection
|
|
40
|
+
* being synced (treating a mismatch identically to "not found" - Status `8` - never revealing that the
|
|
41
|
+
* `ServerId` resolves to something real elsewhere). Without this, a client could supply any other mailbox's
|
|
42
|
+
* folder/item uid as its own `CollectionId`/`ServerId` and read or mutate that mailbox's data directly - the
|
|
43
|
+
* same ownership-verification-after-an-`ignoreACL`-lookup pattern `ItemOperationsCommand`/`MoveItemsCommand`
|
|
44
|
+
* already use, applied consistently here too.
|
|
45
|
+
*
|
|
46
|
+
* **Pragmatic subset, deliberately not the full MS-ASCMD `Sync` surface**:
|
|
47
|
+
* - **Client-originated `Add`/`Change`/`Delete` commands are accepted for every collection type**, including
|
|
48
|
+
* `Email` (a device creating/editing a Draft, or deleting a message locally - see `applyAdd`/`applyChange`/
|
|
49
|
+
* `applyDelete`). `[MS-ASCMD]` itself disallows `Add`/`Change` for any *non-draft* `Email` item - this library
|
|
50
|
+
* doesn't verify a Sync `Email` Add/Change actually targets the caller's own Drafts folder *specifically*
|
|
51
|
+
* (only that it's a folder the caller actually owns/can write to - see above), matching how Contacts/Calendar/
|
|
52
|
+
* Tasks folder targeting is equally unchecked beyond ownership elsewhere. A collection whose adapter has no
|
|
53
|
+
* `fromApplicationData` at all would get Status `6` for `Add`/`Change` instead, but every adapter today
|
|
54
|
+
* implements it. Per `[MS-ASCMD]`'s own "Add (Sync)"/"Status (Sync)" pages: `Add` always gets a `Responses`
|
|
55
|
+
* entry (it must report the assigned `ServerId`); `Change`/`Delete` only get one on **failure** - a silent
|
|
56
|
+
* success means "assume it worked."
|
|
57
|
+
* - Only a body preview is returned per item (see `EmailSyncAdapter`'s own doc comment) - full body content is
|
|
58
|
+
* fetched separately via `ItemOperationsCommand`. A Draft's `Email` Add/Change is plain-text-only, with no
|
|
59
|
+
* attachment support (mirrors `ComposeMailCommand`'s own already-documented attachment gap).
|
|
60
|
+
*
|
|
61
|
+
* @author Jean-Philippe Steinmetz
|
|
62
|
+
*/
|
|
63
|
+
export declare abstract class SyncCommand implements EasCommandHandler {
|
|
64
|
+
readonly command = "Sync";
|
|
65
|
+
protected abstract collectionBindings: Record<string, SyncCollectionBinding<any>>;
|
|
66
|
+
/** Supplied by the Mongo/SQL concrete subclasses so a client-originated `Add`'s `newEntityDefaults()` can
|
|
67
|
+
* be given the caller's own `Mailbox` (`EmailSyncAdapter` needs it for a new Draft's `from`) - same
|
|
68
|
+
* one-line-per-backend pattern `MeetingResponseCommand`/`SettingsCommand` already use. */
|
|
69
|
+
protected abstract mailboxClass: any;
|
|
70
|
+
private windowSize;
|
|
71
|
+
private _objectFactory?;
|
|
72
|
+
private aclUtils?;
|
|
73
|
+
private repos;
|
|
74
|
+
private adapters;
|
|
75
|
+
private mailboxRepo?;
|
|
76
|
+
init(): Promise<void>;
|
|
77
|
+
/** Resolves the caller's own `Mailbox` at most once per request, and only if actually needed - most `Sync`
|
|
78
|
+
* requests contain no client-originated `Add` at all, so most requests never pay this extra round trip. */
|
|
79
|
+
private mailboxLoader;
|
|
80
|
+
handle(ctx: EasCommandContext): Promise<WbxmlElement | undefined>;
|
|
81
|
+
/** Processes one `<Collection>` from the request into its own `<Collection>` response element, plus (when
|
|
82
|
+
* this round advanced anything) the `folderUid`/new `SyncKey`/remembered `Class` for `handle()` to fold
|
|
83
|
+
* into its single end-of-request `persistDeviceSyncState` call - this method itself never persists
|
|
84
|
+
* anything, so it's safe to call once per collection in a request without the write-batching hazard
|
|
85
|
+
* `EasSyncKeyUtils.persistDeviceSyncState`'s doc comment describes. */
|
|
86
|
+
private processCollection;
|
|
87
|
+
private itemToCommandElement;
|
|
88
|
+
/** One client-originated command's outcome: `response` is a `Responses/{Add,Change,Delete}` entry to
|
|
89
|
+
* include (per MS-ASCMD, always present for `Add`, only present on failure for `Change`/`Delete`);
|
|
90
|
+
* `writtenAt` is the resulting `dateModified` of whatever was actually written, used to advance the
|
|
91
|
+
* persisted watermark past this round's own writes (see `handle()`'s own comment on why). */
|
|
92
|
+
private addResponseElement;
|
|
93
|
+
private statusResponseElement;
|
|
94
|
+
private applyAdd;
|
|
95
|
+
private applyChange;
|
|
96
|
+
private applyDelete;
|
|
97
|
+
/** Builds one `<Collection>` response element - `handle()` collects one of these per request `<Collection>`
|
|
98
|
+
* and wraps the whole set in a single `<Sync><Collections>`. */
|
|
99
|
+
private collectionResponse;
|
|
100
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { FolderMongo } from "@rapidmx/restapi/mongo";
|
|
2
|
+
import { FolderSyncCommand } from "../FolderSyncCommand.js";
|
|
3
|
+
/**
|
|
4
|
+
* @author Jean-Philippe Steinmetz
|
|
5
|
+
*/
|
|
6
|
+
export declare class FolderSyncCommandMongo extends FolderSyncCommand<FolderMongo> {
|
|
7
|
+
protected folderClass: any;
|
|
8
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { GetItemEstimateCommand, type EstimateCollectionBinding } from "../GetItemEstimateCommand.js";
|
|
2
|
+
/**
|
|
3
|
+
* @author Jean-Philippe Steinmetz
|
|
4
|
+
*/
|
|
5
|
+
export declare class GetItemEstimateCommandMongo extends GetItemEstimateCommand {
|
|
6
|
+
protected collectionBindings: Record<string, EstimateCollectionBinding>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ItemOperationsCommand } from "../ItemOperationsCommand.js";
|
|
2
|
+
/**
|
|
3
|
+
* @author Jean-Philippe Steinmetz
|
|
4
|
+
*/
|
|
5
|
+
export declare class ItemOperationsCommandMongo extends ItemOperationsCommand {
|
|
6
|
+
protected folderClass: any;
|
|
7
|
+
protected messageClass: any;
|
|
8
|
+
protected attachmentClass: any;
|
|
9
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { MeetingResponseCommand } from "../MeetingResponseCommand.js";
|
|
2
|
+
/**
|
|
3
|
+
* @author Jean-Philippe Steinmetz
|
|
4
|
+
*/
|
|
5
|
+
export declare class MeetingResponseCommandMongo extends MeetingResponseCommand {
|
|
6
|
+
protected calendarEventClass: any;
|
|
7
|
+
protected mailboxClass: any;
|
|
8
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SearchCommand } from "../SearchCommand.js";
|
|
2
|
+
/**
|
|
3
|
+
* @author Jean-Philippe Steinmetz
|
|
4
|
+
*/
|
|
5
|
+
export declare class SearchCommandMongo extends SearchCommand {
|
|
6
|
+
protected contactClass: any;
|
|
7
|
+
protected messageClass: any;
|
|
8
|
+
protected emailAdapterClass: any;
|
|
9
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { SyncCommand, type SyncCollectionBinding } from "../SyncCommand.js";
|
|
2
|
+
/**
|
|
3
|
+
* @author Jean-Philippe Steinmetz
|
|
4
|
+
*/
|
|
5
|
+
export declare class SyncCommandMongo extends SyncCommand {
|
|
6
|
+
protected mailboxClass: any;
|
|
7
|
+
protected collectionBindings: Record<string, SyncCollectionBinding<any>>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./FolderSyncCommandMongo.js";
|
|
2
|
+
export * from "./SyncCommandMongo.js";
|
|
3
|
+
export * from "./SendMailCommandMongo.js";
|
|
4
|
+
export * from "./SmartForwardCommandMongo.js";
|
|
5
|
+
export * from "./SmartReplyCommandMongo.js";
|
|
6
|
+
export * from "./ItemOperationsCommandMongo.js";
|
|
7
|
+
export * from "./SearchCommandMongo.js";
|
|
8
|
+
export * from "./MeetingResponseCommandMongo.js";
|
|
9
|
+
export * from "./SettingsCommandMongo.js";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { FolderSQL } from "@rapidmx/restapi/sql";
|
|
2
|
+
import { FolderSyncCommand } from "../FolderSyncCommand.js";
|
|
3
|
+
/**
|
|
4
|
+
* @author Jean-Philippe Steinmetz
|
|
5
|
+
*/
|
|
6
|
+
export declare class FolderSyncCommandSQL extends FolderSyncCommand<FolderSQL> {
|
|
7
|
+
protected folderClass: any;
|
|
8
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { GetItemEstimateCommand, type EstimateCollectionBinding } from "../GetItemEstimateCommand.js";
|
|
2
|
+
/**
|
|
3
|
+
* @author Jean-Philippe Steinmetz
|
|
4
|
+
*/
|
|
5
|
+
export declare class GetItemEstimateCommandSQL extends GetItemEstimateCommand {
|
|
6
|
+
protected collectionBindings: Record<string, EstimateCollectionBinding>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ItemOperationsCommand } from "../ItemOperationsCommand.js";
|
|
2
|
+
/**
|
|
3
|
+
* @author Jean-Philippe Steinmetz
|
|
4
|
+
*/
|
|
5
|
+
export declare class ItemOperationsCommandSQL extends ItemOperationsCommand {
|
|
6
|
+
protected folderClass: any;
|
|
7
|
+
protected messageClass: any;
|
|
8
|
+
protected attachmentClass: any;
|
|
9
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { MeetingResponseCommand } from "../MeetingResponseCommand.js";
|
|
2
|
+
/**
|
|
3
|
+
* @author Jean-Philippe Steinmetz
|
|
4
|
+
*/
|
|
5
|
+
export declare class MeetingResponseCommandSQL extends MeetingResponseCommand {
|
|
6
|
+
protected calendarEventClass: any;
|
|
7
|
+
protected mailboxClass: any;
|
|
8
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SearchCommand } from "../SearchCommand.js";
|
|
2
|
+
/**
|
|
3
|
+
* @author Jean-Philippe Steinmetz
|
|
4
|
+
*/
|
|
5
|
+
export declare class SearchCommandSQL extends SearchCommand {
|
|
6
|
+
protected contactClass: any;
|
|
7
|
+
protected messageClass: any;
|
|
8
|
+
protected emailAdapterClass: any;
|
|
9
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { SyncCommand, type SyncCollectionBinding } from "../SyncCommand.js";
|
|
2
|
+
/**
|
|
3
|
+
* @author Jean-Philippe Steinmetz
|
|
4
|
+
*/
|
|
5
|
+
export declare class SyncCommandSQL extends SyncCommand {
|
|
6
|
+
protected mailboxClass: any;
|
|
7
|
+
protected collectionBindings: Record<string, SyncCollectionBinding<any>>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./FolderSyncCommandSQL.js";
|
|
2
|
+
export * from "./SyncCommandSQL.js";
|
|
3
|
+
export * from "./SendMailCommandSQL.js";
|
|
4
|
+
export * from "./SmartForwardCommandSQL.js";
|
|
5
|
+
export * from "./SmartReplyCommandSQL.js";
|
|
6
|
+
export * from "./ItemOperationsCommandSQL.js";
|
|
7
|
+
export * from "./SearchCommandSQL.js";
|
|
8
|
+
export * from "./MeetingResponseCommandSQL.js";
|
|
9
|
+
export * from "./SettingsCommandSQL.js";
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exchange ActiveSync protocol compatibility (Phase 2 of this library's roadmap): a WBXML codec, JWT-secured
|
|
3
|
+
* transport (`BaseEasRoute`, reusing the framework's existing `@Auth(["jwt"])` strategy - no EAS-specific auth
|
|
4
|
+
* code of its own), and the pragmatic command subset agreed in the architecture plan - `Provision`,
|
|
5
|
+
* `FolderSync`, `Sync` (`Email`/`Contacts`/`Calendar`/`Tasks`), `SendMail`/`SmartForward`/`SmartReply`,
|
|
6
|
+
* `ItemOperations`, `Ping`, `Search` (GAL), `MeetingResponse`, and `Settings`.
|
|
7
|
+
*
|
|
8
|
+
* This module exports only the backend-agnostic surface: the codec, the abstract route/command base classes,
|
|
9
|
+
* the shared sync-cursor/date-format utilities, and the `Sync` collection adapters. The concrete Mongo/SQL
|
|
10
|
+
* classes a deployment actually instantiates (`EasRouteMongo`/`EasRouteSQL` and each command's Mongo/SQL
|
|
11
|
+
* variant) are exported from this package's `./mongo`/`./sql` subpaths instead, alongside every other
|
|
12
|
+
* entity/route/job this library defines - see `MongoConnection`/`ConnectionManager` usage elsewhere in this
|
|
13
|
+
* library's own README for that convention.
|
|
14
|
+
*
|
|
15
|
+
* A deployment mounts EAS at the protocol's well-known path with a trivial one-line subclass, the same pattern
|
|
16
|
+
* `push/MailPushRoute.ts`'s doc comment describes for `BasePushRoute`:
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { EasRouteMongo } from "@rapidrest/mail/mongo";
|
|
19
|
+
* import { RouteDecorators } from "@rapidrest/service-core";
|
|
20
|
+
* const { Route } = RouteDecorators;
|
|
21
|
+
*
|
|
22
|
+
* @Route("/Microsoft-Server-ActiveSync")
|
|
23
|
+
* export class MyEasRoute extends EasRouteMongo {}
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export * from "./codec/WbxmlCodePages.js";
|
|
27
|
+
export * from "./codec/WbxmlElement.js";
|
|
28
|
+
export * from "./codec/WbxmlEncoder.js";
|
|
29
|
+
export * from "./codec/WbxmlDecoder.js";
|
|
30
|
+
export * from "./BaseEasRoute.js";
|
|
31
|
+
export * from "./BaseDeviceSyncStateRoute.js";
|
|
32
|
+
export * from "./models/DeviceSyncState.js";
|
|
33
|
+
export * from "./jobs/EasDeviceStateCleanupJob.js";
|
|
34
|
+
export * from "./EasCommandHandler.js";
|
|
35
|
+
export * from "./EasSyncKeyUtils.js";
|
|
36
|
+
export * from "./CompactDateTime.js";
|
|
37
|
+
export * from "./commands/ProvisionCommand.js";
|
|
38
|
+
export * from "./commands/FolderSyncCommand.js";
|
|
39
|
+
export * from "./commands/SyncCommand.js";
|
|
40
|
+
export * from "./commands/ComposeMailCommand.js";
|
|
41
|
+
export * from "./commands/SendMailCommand.js";
|
|
42
|
+
export * from "./commands/SmartForwardCommand.js";
|
|
43
|
+
export * from "./commands/SmartReplyCommand.js";
|
|
44
|
+
export * from "./commands/PingCommand.js";
|
|
45
|
+
export * from "./commands/ItemOperationsCommand.js";
|
|
46
|
+
export * from "./commands/SearchCommand.js";
|
|
47
|
+
export * from "./commands/MeetingResponseCommand.js";
|
|
48
|
+
export * from "./commands/SettingsCommand.js";
|
|
49
|
+
export * from "./adapters/EasCollectionSyncAdapter.js";
|
|
50
|
+
export * from "./adapters/EmailSyncAdapter.js";
|
|
51
|
+
export * from "./adapters/ContactsSyncAdapter.js";
|
|
52
|
+
export * from "./adapters/CalendarSyncAdapter.js";
|
|
53
|
+
export * from "./adapters/TasksSyncAdapter.js";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { BackgroundService } from "@rapidrest/service-core";
|
|
2
|
+
import { DeviceSyncState } from "../models/DeviceSyncState.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,5 @@
|
|
|
1
|
+
import { EasDeviceStateCleanupJob } from "../EasDeviceStateCleanupJob.js";
|
|
2
|
+
import { DeviceSyncStateMongo } from "../../models/mongo/DeviceSyncStateMongo.js";
|
|
3
|
+
export declare class EasDeviceStateCleanupJobMongo extends EasDeviceStateCleanupJob<DeviceSyncStateMongo> {
|
|
4
|
+
protected deviceSyncStateClass: any;
|
|
5
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { EasDeviceStateCleanupJob } from "../EasDeviceStateCleanupJob.js";
|
|
2
|
+
import { DeviceSyncStateSQL } from "../../models/sql/DeviceSyncStateSQL.js";
|
|
3
|
+
export declare class EasDeviceStateCleanupJobSQL extends EasDeviceStateCleanupJob<DeviceSyncStateSQL> {
|
|
4
|
+
protected deviceSyncStateClass: any;
|
|
5
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { BaseEntity } from "@rapidrest/service-core";
|
|
2
|
+
/**
|
|
3
|
+
* Tracks the EAS sync state of a single paired mobile device against a `Mailbox`.
|
|
4
|
+
*
|
|
5
|
+
* @author Jean-Philippe Steinmetz
|
|
6
|
+
*/
|
|
7
|
+
export interface DeviceSyncState extends BaseEntity {
|
|
8
|
+
mailboxUid: string;
|
|
9
|
+
deviceId: string;
|
|
10
|
+
deviceType: string;
|
|
11
|
+
/** The EAS provisioning policy key most recently acknowledged by the device. */
|
|
12
|
+
policyKey?: string;
|
|
13
|
+
/** The per-folder EAS `SyncKey` cursor, keyed by `Folder.uid`. */
|
|
14
|
+
folderSyncKeys: Record<string, string>;
|
|
15
|
+
/** The EAS `Class` (`"Email"`, `"Contacts"`, ...) most recently synced for a folder, keyed by `Folder.uid` -
|
|
16
|
+
* lets a `Sync` request omit `Class` after its first request for a collection, per [MS-ASCMD], without the
|
|
17
|
+
* server losing track of which entity type that collection holds. */
|
|
18
|
+
folderCollectionClasses: Record<string, string>;
|
|
19
|
+
lastSyncAt?: Date;
|
|
20
|
+
provisioned: boolean;
|
|
21
|
+
/** `true` once an administrator has requested this device be remotely wiped (MS-ASPROV `RemoteWipe`). Set
|
|
22
|
+
* back to `false` once the device acknowledges the wipe. */
|
|
23
|
+
remoteWipeRequested?: boolean;
|
|
24
|
+
/** `true` if the pending/most recent remote wipe request was scoped to this account only (vs. a full device
|
|
25
|
+
* wipe) - recorded for administrative record-keeping; the wire directive sent to the device is the same
|
|
26
|
+
* either way in this library's pragmatic subset. */
|
|
27
|
+
remoteWipeAccountOnly?: boolean;
|
|
28
|
+
/** When the device most recently acknowledged a remote wipe request. */
|
|
29
|
+
remoteWipeAcknowledgedAt?: Date;
|
|
30
|
+
}
|