@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.
Files changed (225) hide show
  1. package/LICENSE +382 -0
  2. package/README.md +57 -0
  3. package/dist/lib/BaseDeviceSyncStateRoute.js +90 -0
  4. package/dist/lib/BaseDeviceSyncStateRoute.js.map +1 -0
  5. package/dist/lib/BaseEasRoute.js +213 -0
  6. package/dist/lib/BaseEasRoute.js.map +1 -0
  7. package/dist/lib/CompactDateTime.js +43 -0
  8. package/dist/lib/CompactDateTime.js.map +1 -0
  9. package/dist/lib/EasCommandHandler.js +2 -0
  10. package/dist/lib/EasCommandHandler.js.map +1 -0
  11. package/dist/lib/EasSyncKeyUtils.js +119 -0
  12. package/dist/lib/EasSyncKeyUtils.js.map +1 -0
  13. package/dist/lib/adapters/CalendarSyncAdapter.js +255 -0
  14. package/dist/lib/adapters/CalendarSyncAdapter.js.map +1 -0
  15. package/dist/lib/adapters/ContactsSyncAdapter.js +164 -0
  16. package/dist/lib/adapters/ContactsSyncAdapter.js.map +1 -0
  17. package/dist/lib/adapters/EasCollectionSyncAdapter.js +2 -0
  18. package/dist/lib/adapters/EasCollectionSyncAdapter.js.map +1 -0
  19. package/dist/lib/adapters/EmailSyncAdapter.js +269 -0
  20. package/dist/lib/adapters/EmailSyncAdapter.js.map +1 -0
  21. package/dist/lib/adapters/TasksSyncAdapter.js +100 -0
  22. package/dist/lib/adapters/TasksSyncAdapter.js.map +1 -0
  23. package/dist/lib/adapters/mongo/EmailSyncAdapterMongo.js +16 -0
  24. package/dist/lib/adapters/mongo/EmailSyncAdapterMongo.js.map +1 -0
  25. package/dist/lib/adapters/mongo/index.js +6 -0
  26. package/dist/lib/adapters/mongo/index.js.map +1 -0
  27. package/dist/lib/adapters/sql/EmailSyncAdapterSQL.js +16 -0
  28. package/dist/lib/adapters/sql/EmailSyncAdapterSQL.js.map +1 -0
  29. package/dist/lib/adapters/sql/index.js +6 -0
  30. package/dist/lib/adapters/sql/index.js.map +1 -0
  31. package/dist/lib/codec/WbxmlCodePages.js +706 -0
  32. package/dist/lib/codec/WbxmlCodePages.js.map +1 -0
  33. package/dist/lib/codec/WbxmlDecoder.js +154 -0
  34. package/dist/lib/codec/WbxmlDecoder.js.map +1 -0
  35. package/dist/lib/codec/WbxmlElement.js +31 -0
  36. package/dist/lib/codec/WbxmlElement.js.map +1 -0
  37. package/dist/lib/codec/WbxmlEncoder.js +88 -0
  38. package/dist/lib/codec/WbxmlEncoder.js.map +1 -0
  39. package/dist/lib/commands/ComposeMailCommand.js +187 -0
  40. package/dist/lib/commands/ComposeMailCommand.js.map +1 -0
  41. package/dist/lib/commands/FolderSyncCommand.js +155 -0
  42. package/dist/lib/commands/FolderSyncCommand.js.map +1 -0
  43. package/dist/lib/commands/GetItemEstimateCommand.js +149 -0
  44. package/dist/lib/commands/GetItemEstimateCommand.js.map +1 -0
  45. package/dist/lib/commands/ItemOperationsCommand.js +337 -0
  46. package/dist/lib/commands/ItemOperationsCommand.js.map +1 -0
  47. package/dist/lib/commands/MeetingResponseCommand.js +120 -0
  48. package/dist/lib/commands/MeetingResponseCommand.js.map +1 -0
  49. package/dist/lib/commands/MoveItemsCommand.js +103 -0
  50. package/dist/lib/commands/MoveItemsCommand.js.map +1 -0
  51. package/dist/lib/commands/PingCommand.js +145 -0
  52. package/dist/lib/commands/PingCommand.js.map +1 -0
  53. package/dist/lib/commands/ProvisionCommand.js +164 -0
  54. package/dist/lib/commands/ProvisionCommand.js.map +1 -0
  55. package/dist/lib/commands/ResolveRecipientsCommand.js +123 -0
  56. package/dist/lib/commands/ResolveRecipientsCommand.js.map +1 -0
  57. package/dist/lib/commands/SearchCommand.js +234 -0
  58. package/dist/lib/commands/SearchCommand.js.map +1 -0
  59. package/dist/lib/commands/SendMailCommand.js +18 -0
  60. package/dist/lib/commands/SendMailCommand.js.map +1 -0
  61. package/dist/lib/commands/SettingsCommand.js +138 -0
  62. package/dist/lib/commands/SettingsCommand.js.map +1 -0
  63. package/dist/lib/commands/SmartForwardCommand.js +22 -0
  64. package/dist/lib/commands/SmartForwardCommand.js.map +1 -0
  65. package/dist/lib/commands/SmartReplyCommand.js +22 -0
  66. package/dist/lib/commands/SmartReplyCommand.js.map +1 -0
  67. package/dist/lib/commands/SyncCommand.js +406 -0
  68. package/dist/lib/commands/SyncCommand.js.map +1 -0
  69. package/dist/lib/commands/mongo/FolderSyncCommandMongo.js +16 -0
  70. package/dist/lib/commands/mongo/FolderSyncCommandMongo.js.map +1 -0
  71. package/dist/lib/commands/mongo/GetItemEstimateCommandMongo.js +21 -0
  72. package/dist/lib/commands/mongo/GetItemEstimateCommandMongo.js.map +1 -0
  73. package/dist/lib/commands/mongo/ItemOperationsCommandMongo.js +18 -0
  74. package/dist/lib/commands/mongo/ItemOperationsCommandMongo.js.map +1 -0
  75. package/dist/lib/commands/mongo/MeetingResponseCommandMongo.js +17 -0
  76. package/dist/lib/commands/mongo/MeetingResponseCommandMongo.js.map +1 -0
  77. package/dist/lib/commands/mongo/MoveItemsCommandMongo.js +17 -0
  78. package/dist/lib/commands/mongo/MoveItemsCommandMongo.js.map +1 -0
  79. package/dist/lib/commands/mongo/ResolveRecipientsCommandMongo.js +16 -0
  80. package/dist/lib/commands/mongo/ResolveRecipientsCommandMongo.js.map +1 -0
  81. package/dist/lib/commands/mongo/SearchCommandMongo.js +19 -0
  82. package/dist/lib/commands/mongo/SearchCommandMongo.js.map +1 -0
  83. package/dist/lib/commands/mongo/SendMailCommandMongo.js +17 -0
  84. package/dist/lib/commands/mongo/SendMailCommandMongo.js.map +1 -0
  85. package/dist/lib/commands/mongo/SettingsCommandMongo.js +16 -0
  86. package/dist/lib/commands/mongo/SettingsCommandMongo.js.map +1 -0
  87. package/dist/lib/commands/mongo/SmartForwardCommandMongo.js +17 -0
  88. package/dist/lib/commands/mongo/SmartForwardCommandMongo.js.map +1 -0
  89. package/dist/lib/commands/mongo/SmartReplyCommandMongo.js +17 -0
  90. package/dist/lib/commands/mongo/SmartReplyCommandMongo.js.map +1 -0
  91. package/dist/lib/commands/mongo/SyncCommandMongo.js +26 -0
  92. package/dist/lib/commands/mongo/SyncCommandMongo.js.map +1 -0
  93. package/dist/lib/commands/mongo/index.js +14 -0
  94. package/dist/lib/commands/mongo/index.js.map +1 -0
  95. package/dist/lib/commands/sql/FolderSyncCommandSQL.js +16 -0
  96. package/dist/lib/commands/sql/FolderSyncCommandSQL.js.map +1 -0
  97. package/dist/lib/commands/sql/GetItemEstimateCommandSQL.js +21 -0
  98. package/dist/lib/commands/sql/GetItemEstimateCommandSQL.js.map +1 -0
  99. package/dist/lib/commands/sql/ItemOperationsCommandSQL.js +18 -0
  100. package/dist/lib/commands/sql/ItemOperationsCommandSQL.js.map +1 -0
  101. package/dist/lib/commands/sql/MeetingResponseCommandSQL.js +17 -0
  102. package/dist/lib/commands/sql/MeetingResponseCommandSQL.js.map +1 -0
  103. package/dist/lib/commands/sql/MoveItemsCommandSQL.js +17 -0
  104. package/dist/lib/commands/sql/MoveItemsCommandSQL.js.map +1 -0
  105. package/dist/lib/commands/sql/ResolveRecipientsCommandSQL.js +16 -0
  106. package/dist/lib/commands/sql/ResolveRecipientsCommandSQL.js.map +1 -0
  107. package/dist/lib/commands/sql/SearchCommandSQL.js +19 -0
  108. package/dist/lib/commands/sql/SearchCommandSQL.js.map +1 -0
  109. package/dist/lib/commands/sql/SendMailCommandSQL.js +17 -0
  110. package/dist/lib/commands/sql/SendMailCommandSQL.js.map +1 -0
  111. package/dist/lib/commands/sql/SettingsCommandSQL.js +16 -0
  112. package/dist/lib/commands/sql/SettingsCommandSQL.js.map +1 -0
  113. package/dist/lib/commands/sql/SmartForwardCommandSQL.js +17 -0
  114. package/dist/lib/commands/sql/SmartForwardCommandSQL.js.map +1 -0
  115. package/dist/lib/commands/sql/SmartReplyCommandSQL.js +17 -0
  116. package/dist/lib/commands/sql/SmartReplyCommandSQL.js.map +1 -0
  117. package/dist/lib/commands/sql/SyncCommandSQL.js +26 -0
  118. package/dist/lib/commands/sql/SyncCommandSQL.js.map +1 -0
  119. package/dist/lib/commands/sql/index.js +14 -0
  120. package/dist/lib/commands/sql/index.js.map +1 -0
  121. package/dist/lib/index.js +58 -0
  122. package/dist/lib/index.js.map +1 -0
  123. package/dist/lib/jobs/EasDeviceStateCleanupJob.js +101 -0
  124. package/dist/lib/jobs/EasDeviceStateCleanupJob.js.map +1 -0
  125. package/dist/lib/jobs/mongo/EasDeviceStateCleanupJobMongo.js +13 -0
  126. package/dist/lib/jobs/mongo/EasDeviceStateCleanupJobMongo.js.map +1 -0
  127. package/dist/lib/jobs/sql/EasDeviceStateCleanupJobSQL.js +13 -0
  128. package/dist/lib/jobs/sql/EasDeviceStateCleanupJobSQL.js.map +1 -0
  129. package/dist/lib/models/DeviceSyncState.js +2 -0
  130. package/dist/lib/models/DeviceSyncState.js.map +1 -0
  131. package/dist/lib/models/mongo/DeviceSyncStateMongo.js +130 -0
  132. package/dist/lib/models/mongo/DeviceSyncStateMongo.js.map +1 -0
  133. package/dist/lib/models/sql/DeviceSyncStateSQL.js +130 -0
  134. package/dist/lib/models/sql/DeviceSyncStateSQL.js.map +1 -0
  135. package/dist/lib/mongo/DeviceSyncStateRouteMongo.js +28 -0
  136. package/dist/lib/mongo/DeviceSyncStateRouteMongo.js.map +1 -0
  137. package/dist/lib/mongo/EasRouteMongo.js +63 -0
  138. package/dist/lib/mongo/EasRouteMongo.js.map +1 -0
  139. package/dist/lib/mongo/index.js +9 -0
  140. package/dist/lib/mongo/index.js.map +1 -0
  141. package/dist/lib/mongo.js +15 -0
  142. package/dist/lib/mongo.js.map +1 -0
  143. package/dist/lib/sql/DeviceSyncStateRouteSQL.js +28 -0
  144. package/dist/lib/sql/DeviceSyncStateRouteSQL.js.map +1 -0
  145. package/dist/lib/sql/EasRouteSQL.js +63 -0
  146. package/dist/lib/sql/EasRouteSQL.js.map +1 -0
  147. package/dist/lib/sql/index.js +9 -0
  148. package/dist/lib/sql/index.js.map +1 -0
  149. package/dist/lib/sql.js +15 -0
  150. package/dist/lib/sql.js.map +1 -0
  151. package/dist/types/BaseDeviceSyncStateRoute.d.ts +34 -0
  152. package/dist/types/BaseEasRoute.d.ts +65 -0
  153. package/dist/types/CompactDateTime.d.ts +22 -0
  154. package/dist/types/EasCommandHandler.d.ts +59 -0
  155. package/dist/types/EasSyncKeyUtils.d.ts +89 -0
  156. package/dist/types/adapters/CalendarSyncAdapter.d.ts +52 -0
  157. package/dist/types/adapters/ContactsSyncAdapter.d.ts +33 -0
  158. package/dist/types/adapters/EasCollectionSyncAdapter.d.ts +55 -0
  159. package/dist/types/adapters/EmailSyncAdapter.d.ts +71 -0
  160. package/dist/types/adapters/TasksSyncAdapter.d.ts +32 -0
  161. package/dist/types/adapters/mongo/EmailSyncAdapterMongo.d.ts +7 -0
  162. package/dist/types/adapters/mongo/index.d.ts +1 -0
  163. package/dist/types/adapters/sql/EmailSyncAdapterSQL.d.ts +7 -0
  164. package/dist/types/adapters/sql/index.d.ts +1 -0
  165. package/dist/types/codec/WbxmlCodePages.d.ts +45 -0
  166. package/dist/types/codec/WbxmlDecoder.d.ts +33 -0
  167. package/dist/types/codec/WbxmlElement.d.ts +43 -0
  168. package/dist/types/codec/WbxmlEncoder.d.ts +20 -0
  169. package/dist/types/commands/ComposeMailCommand.d.ts +50 -0
  170. package/dist/types/commands/FolderSyncCommand.d.ts +25 -0
  171. package/dist/types/commands/GetItemEstimateCommand.d.ts +43 -0
  172. package/dist/types/commands/ItemOperationsCommand.d.ts +72 -0
  173. package/dist/types/commands/MeetingResponseCommand.d.ts +32 -0
  174. package/dist/types/commands/MoveItemsCommand.d.ts +29 -0
  175. package/dist/types/commands/PingCommand.d.ts +33 -0
  176. package/dist/types/commands/ProvisionCommand.d.ts +54 -0
  177. package/dist/types/commands/ResolveRecipientsCommand.d.ts +36 -0
  178. package/dist/types/commands/SearchCommand.d.ts +60 -0
  179. package/dist/types/commands/SendMailCommand.d.ts +10 -0
  180. package/dist/types/commands/SettingsCommand.d.ts +37 -0
  181. package/dist/types/commands/SmartForwardCommand.d.ts +17 -0
  182. package/dist/types/commands/SmartReplyCommand.d.ts +17 -0
  183. package/dist/types/commands/SyncCommand.d.ts +100 -0
  184. package/dist/types/commands/mongo/FolderSyncCommandMongo.d.ts +8 -0
  185. package/dist/types/commands/mongo/GetItemEstimateCommandMongo.d.ts +7 -0
  186. package/dist/types/commands/mongo/ItemOperationsCommandMongo.d.ts +9 -0
  187. package/dist/types/commands/mongo/MeetingResponseCommandMongo.d.ts +8 -0
  188. package/dist/types/commands/mongo/MoveItemsCommandMongo.d.ts +8 -0
  189. package/dist/types/commands/mongo/ResolveRecipientsCommandMongo.d.ts +7 -0
  190. package/dist/types/commands/mongo/SearchCommandMongo.d.ts +9 -0
  191. package/dist/types/commands/mongo/SendMailCommandMongo.d.ts +8 -0
  192. package/dist/types/commands/mongo/SettingsCommandMongo.d.ts +7 -0
  193. package/dist/types/commands/mongo/SmartForwardCommandMongo.d.ts +8 -0
  194. package/dist/types/commands/mongo/SmartReplyCommandMongo.d.ts +8 -0
  195. package/dist/types/commands/mongo/SyncCommandMongo.d.ts +8 -0
  196. package/dist/types/commands/mongo/index.d.ts +9 -0
  197. package/dist/types/commands/sql/FolderSyncCommandSQL.d.ts +8 -0
  198. package/dist/types/commands/sql/GetItemEstimateCommandSQL.d.ts +7 -0
  199. package/dist/types/commands/sql/ItemOperationsCommandSQL.d.ts +9 -0
  200. package/dist/types/commands/sql/MeetingResponseCommandSQL.d.ts +8 -0
  201. package/dist/types/commands/sql/MoveItemsCommandSQL.d.ts +8 -0
  202. package/dist/types/commands/sql/ResolveRecipientsCommandSQL.d.ts +7 -0
  203. package/dist/types/commands/sql/SearchCommandSQL.d.ts +9 -0
  204. package/dist/types/commands/sql/SendMailCommandSQL.d.ts +8 -0
  205. package/dist/types/commands/sql/SettingsCommandSQL.d.ts +7 -0
  206. package/dist/types/commands/sql/SmartForwardCommandSQL.d.ts +8 -0
  207. package/dist/types/commands/sql/SmartReplyCommandSQL.d.ts +8 -0
  208. package/dist/types/commands/sql/SyncCommandSQL.d.ts +8 -0
  209. package/dist/types/commands/sql/index.d.ts +9 -0
  210. package/dist/types/index.d.ts +53 -0
  211. package/dist/types/jobs/EasDeviceStateCleanupJob.d.ts +26 -0
  212. package/dist/types/jobs/mongo/EasDeviceStateCleanupJobMongo.d.ts +5 -0
  213. package/dist/types/jobs/sql/EasDeviceStateCleanupJobSQL.d.ts +5 -0
  214. package/dist/types/models/DeviceSyncState.d.ts +30 -0
  215. package/dist/types/models/mongo/DeviceSyncStateMongo.d.ts +22 -0
  216. package/dist/types/models/sql/DeviceSyncStateSQL.d.ts +22 -0
  217. package/dist/types/mongo/DeviceSyncStateRouteMongo.d.ts +8 -0
  218. package/dist/types/mongo/EasRouteMongo.d.ts +14 -0
  219. package/dist/types/mongo/index.d.ts +4 -0
  220. package/dist/types/mongo.d.ts +10 -0
  221. package/dist/types/sql/DeviceSyncStateRouteSQL.d.ts +8 -0
  222. package/dist/types/sql/EasRouteSQL.d.ts +14 -0
  223. package/dist/types/sql/index.d.ts +4 -0
  224. package/dist/types/sql.d.ts +10 -0
  225. 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,8 @@
1
+ import { MoveItemsCommand } from "../MoveItemsCommand.js";
2
+ /**
3
+ * @author Jean-Philippe Steinmetz
4
+ */
5
+ export declare class MoveItemsCommandMongo extends MoveItemsCommand {
6
+ protected messageClass: any;
7
+ protected folderClass: any;
8
+ }
@@ -0,0 +1,7 @@
1
+ import { ResolveRecipientsCommand } from "../ResolveRecipientsCommand.js";
2
+ /**
3
+ * @author Jean-Philippe Steinmetz
4
+ */
5
+ export declare class ResolveRecipientsCommandMongo extends ResolveRecipientsCommand {
6
+ protected contactClass: any;
7
+ }
@@ -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 { SendMailCommand } from "../SendMailCommand.js";
2
+ /**
3
+ * @author Jean-Philippe Steinmetz
4
+ */
5
+ export declare class SendMailCommandMongo extends SendMailCommand {
6
+ protected folderClass: any;
7
+ protected messageClass: any;
8
+ }
@@ -0,0 +1,7 @@
1
+ import { SettingsCommand } from "../SettingsCommand.js";
2
+ /**
3
+ * @author Jean-Philippe Steinmetz
4
+ */
5
+ export declare class SettingsCommandMongo extends SettingsCommand {
6
+ protected mailboxClass: any;
7
+ }
@@ -0,0 +1,8 @@
1
+ import { SmartForwardCommand } from "../SmartForwardCommand.js";
2
+ /**
3
+ * @author Jean-Philippe Steinmetz
4
+ */
5
+ export declare class SmartForwardCommandMongo extends SmartForwardCommand {
6
+ protected folderClass: any;
7
+ protected messageClass: any;
8
+ }
@@ -0,0 +1,8 @@
1
+ import { SmartReplyCommand } from "../SmartReplyCommand.js";
2
+ /**
3
+ * @author Jean-Philippe Steinmetz
4
+ */
5
+ export declare class SmartReplyCommandMongo extends SmartReplyCommand {
6
+ protected folderClass: any;
7
+ protected messageClass: any;
8
+ }
@@ -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,8 @@
1
+ import { MoveItemsCommand } from "../MoveItemsCommand.js";
2
+ /**
3
+ * @author Jean-Philippe Steinmetz
4
+ */
5
+ export declare class MoveItemsCommandSQL extends MoveItemsCommand {
6
+ protected messageClass: any;
7
+ protected folderClass: any;
8
+ }
@@ -0,0 +1,7 @@
1
+ import { ResolveRecipientsCommand } from "../ResolveRecipientsCommand.js";
2
+ /**
3
+ * @author Jean-Philippe Steinmetz
4
+ */
5
+ export declare class ResolveRecipientsCommandSQL extends ResolveRecipientsCommand {
6
+ protected contactClass: any;
7
+ }
@@ -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 { SendMailCommand } from "../SendMailCommand.js";
2
+ /**
3
+ * @author Jean-Philippe Steinmetz
4
+ */
5
+ export declare class SendMailCommandSQL extends SendMailCommand {
6
+ protected folderClass: any;
7
+ protected messageClass: any;
8
+ }
@@ -0,0 +1,7 @@
1
+ import { SettingsCommand } from "../SettingsCommand.js";
2
+ /**
3
+ * @author Jean-Philippe Steinmetz
4
+ */
5
+ export declare class SettingsCommandSQL extends SettingsCommand {
6
+ protected mailboxClass: any;
7
+ }
@@ -0,0 +1,8 @@
1
+ import { SmartForwardCommand } from "../SmartForwardCommand.js";
2
+ /**
3
+ * @author Jean-Philippe Steinmetz
4
+ */
5
+ export declare class SmartForwardCommandSQL extends SmartForwardCommand {
6
+ protected folderClass: any;
7
+ protected messageClass: any;
8
+ }
@@ -0,0 +1,8 @@
1
+ import { SmartReplyCommand } from "../SmartReplyCommand.js";
2
+ /**
3
+ * @author Jean-Philippe Steinmetz
4
+ */
5
+ export declare class SmartReplyCommandSQL extends SmartReplyCommand {
6
+ protected folderClass: any;
7
+ protected messageClass: any;
8
+ }
@@ -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
+ }