@rapidmx/mapi-plugin 1.0.0-beta.10

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 (204) hide show
  1. package/LICENSE +382 -0
  2. package/README.md +60 -0
  3. package/dist/lib/BaseMapiEmsmdbRoute.js +489 -0
  4. package/dist/lib/BaseMapiEmsmdbRoute.js.map +1 -0
  5. package/dist/lib/BaseMapiNspiRoute.js +114 -0
  6. package/dist/lib/BaseMapiNspiRoute.js.map +1 -0
  7. package/dist/lib/MapiSessionManager.js +475 -0
  8. package/dist/lib/MapiSessionManager.js.map +1 -0
  9. package/dist/lib/RegexPatternUtils.js +30 -0
  10. package/dist/lib/RegexPatternUtils.js.map +1 -0
  11. package/dist/lib/RopDispatcher.js +145 -0
  12. package/dist/lib/RopDispatcher.js.map +1 -0
  13. package/dist/lib/codec/AppointmentRecurrence.js +315 -0
  14. package/dist/lib/codec/AppointmentRecurrence.js.map +1 -0
  15. package/dist/lib/codec/BufferCursor.js +242 -0
  16. package/dist/lib/codec/BufferCursor.js.map +1 -0
  17. package/dist/lib/codec/GlobalObjectId.js +98 -0
  18. package/dist/lib/codec/GlobalObjectId.js.map +1 -0
  19. package/dist/lib/codec/MapiGuid.js +41 -0
  20. package/dist/lib/codec/MapiGuid.js.map +1 -0
  21. package/dist/lib/codec/MapiTimeZone.js +126 -0
  22. package/dist/lib/codec/MapiTimeZone.js.map +1 -0
  23. package/dist/lib/codec/PropertyValue.js +240 -0
  24. package/dist/lib/codec/PropertyValue.js.map +1 -0
  25. package/dist/lib/codec/RopBuffer.js +38 -0
  26. package/dist/lib/codec/RopBuffer.js.map +1 -0
  27. package/dist/lib/codec/TypedString.js +54 -0
  28. package/dist/lib/codec/TypedString.js.map +1 -0
  29. package/dist/lib/index.js +99 -0
  30. package/dist/lib/index.js.map +1 -0
  31. package/dist/lib/mongo/MapiEmsmdbRouteMongo.js +85 -0
  32. package/dist/lib/mongo/MapiEmsmdbRouteMongo.js.map +1 -0
  33. package/dist/lib/mongo/MapiNspiRouteMongo.js +33 -0
  34. package/dist/lib/mongo/MapiNspiRouteMongo.js.map +1 -0
  35. package/dist/lib/mongo/index.js +7 -0
  36. package/dist/lib/mongo/index.js.map +1 -0
  37. package/dist/lib/mongo.js +6 -0
  38. package/dist/lib/mongo.js.map +1 -0
  39. package/dist/lib/nspi/NspiBindHandler.js +54 -0
  40. package/dist/lib/nspi/NspiBindHandler.js.map +1 -0
  41. package/dist/lib/nspi/NspiCodec.js +106 -0
  42. package/dist/lib/nspi/NspiCodec.js.map +1 -0
  43. package/dist/lib/nspi/NspiGetMatchesHandler.js +142 -0
  44. package/dist/lib/nspi/NspiGetMatchesHandler.js.map +1 -0
  45. package/dist/lib/rop/AddressList.js +114 -0
  46. package/dist/lib/rop/AddressList.js.map +1 -0
  47. package/dist/lib/rop/CalendarEventTarget.js +30 -0
  48. package/dist/lib/rop/CalendarEventTarget.js.map +1 -0
  49. package/dist/lib/rop/CalendarNamedProperties.js +57 -0
  50. package/dist/lib/rop/CalendarNamedProperties.js.map +1 -0
  51. package/dist/lib/rop/ContactTarget.js +19 -0
  52. package/dist/lib/rop/ContactTarget.js.map +1 -0
  53. package/dist/lib/rop/ContentsTable.js +60 -0
  54. package/dist/lib/rop/ContentsTable.js.map +1 -0
  55. package/dist/lib/rop/ExecuteBudget.js +82 -0
  56. package/dist/lib/rop/ExecuteBudget.js.map +1 -0
  57. package/dist/lib/rop/FastTransferStream.js +195 -0
  58. package/dist/lib/rop/FastTransferStream.js.map +1 -0
  59. package/dist/lib/rop/FolderTarget.js +118 -0
  60. package/dist/lib/rop/FolderTarget.js.map +1 -0
  61. package/dist/lib/rop/HandleDataCache.js +412 -0
  62. package/dist/lib/rop/HandleDataCache.js.map +1 -0
  63. package/dist/lib/rop/MeetingMessageClassHandler.js +241 -0
  64. package/dist/lib/rop/MeetingMessageClassHandler.js.map +1 -0
  65. package/dist/lib/rop/MessageBodyStream.js +68 -0
  66. package/dist/lib/rop/MessageBodyStream.js.map +1 -0
  67. package/dist/lib/rop/MessageTarget.js +57 -0
  68. package/dist/lib/rop/MessageTarget.js.map +1 -0
  69. package/dist/lib/rop/NamedPropertyRegistry.js +69 -0
  70. package/dist/lib/rop/NamedPropertyRegistry.js.map +1 -0
  71. package/dist/lib/rop/PropertyResolvers.js +353 -0
  72. package/dist/lib/rop/PropertyResolvers.js.map +1 -0
  73. package/dist/lib/rop/RepoPaging.js +54 -0
  74. package/dist/lib/rop/RepoPaging.js.map +1 -0
  75. package/dist/lib/rop/RestapiRules.js +52 -0
  76. package/dist/lib/rop/RestapiRules.js.map +1 -0
  77. package/dist/lib/rop/RopCreateMessageHandler.js +55 -0
  78. package/dist/lib/rop/RopCreateMessageHandler.js.map +1 -0
  79. package/dist/lib/rop/RopDeleteFolderHandler.js +174 -0
  80. package/dist/lib/rop/RopDeleteFolderHandler.js.map +1 -0
  81. package/dist/lib/rop/RopDeleteMessagesHandler.js +110 -0
  82. package/dist/lib/rop/RopDeleteMessagesHandler.js.map +1 -0
  83. package/dist/lib/rop/RopFastTransferSourceCopyPropertiesHandler.js +61 -0
  84. package/dist/lib/rop/RopFastTransferSourceCopyPropertiesHandler.js.map +1 -0
  85. package/dist/lib/rop/RopFastTransferSourceCopyToHandler.js +60 -0
  86. package/dist/lib/rop/RopFastTransferSourceCopyToHandler.js.map +1 -0
  87. package/dist/lib/rop/RopFastTransferSourceGetBufferHandler.js +76 -0
  88. package/dist/lib/rop/RopFastTransferSourceGetBufferHandler.js.map +1 -0
  89. package/dist/lib/rop/RopGetContentsTableHandler.js +55 -0
  90. package/dist/lib/rop/RopGetContentsTableHandler.js.map +1 -0
  91. package/dist/lib/rop/RopGetHierarchyTableHandler.js +42 -0
  92. package/dist/lib/rop/RopGetHierarchyTableHandler.js.map +1 -0
  93. package/dist/lib/rop/RopGetPropertiesSpecificHandler.js +56 -0
  94. package/dist/lib/rop/RopGetPropertiesSpecificHandler.js.map +1 -0
  95. package/dist/lib/rop/RopGetPropertyIdsFromNamesHandler.js +92 -0
  96. package/dist/lib/rop/RopGetPropertyIdsFromNamesHandler.js.map +1 -0
  97. package/dist/lib/rop/RopHandler.js +6 -0
  98. package/dist/lib/rop/RopHandler.js.map +1 -0
  99. package/dist/lib/rop/RopLogonHandler.js +135 -0
  100. package/dist/lib/rop/RopLogonHandler.js.map +1 -0
  101. package/dist/lib/rop/RopOpenFolderHandler.js +48 -0
  102. package/dist/lib/rop/RopOpenFolderHandler.js.map +1 -0
  103. package/dist/lib/rop/RopOpenMessageHandler.js +83 -0
  104. package/dist/lib/rop/RopOpenMessageHandler.js.map +1 -0
  105. package/dist/lib/rop/RopOpenStreamHandler.js +84 -0
  106. package/dist/lib/rop/RopOpenStreamHandler.js.map +1 -0
  107. package/dist/lib/rop/RopQueryRowsHandler.js +120 -0
  108. package/dist/lib/rop/RopQueryRowsHandler.js.map +1 -0
  109. package/dist/lib/rop/RopReadStreamHandler.js +73 -0
  110. package/dist/lib/rop/RopReadStreamHandler.js.map +1 -0
  111. package/dist/lib/rop/RopReleaseHandler.js +23 -0
  112. package/dist/lib/rop/RopReleaseHandler.js.map +1 -0
  113. package/dist/lib/rop/RopSaveChangesMessageHandler.js +269 -0
  114. package/dist/lib/rop/RopSaveChangesMessageHandler.js.map +1 -0
  115. package/dist/lib/rop/RopSetColumnsHandler.js +50 -0
  116. package/dist/lib/rop/RopSetColumnsHandler.js.map +1 -0
  117. package/dist/lib/rop/RopSetPropertiesHandler.js +173 -0
  118. package/dist/lib/rop/RopSetPropertiesHandler.js.map +1 -0
  119. package/dist/lib/rop/RopSubmitMessageHandler.js +342 -0
  120. package/dist/lib/rop/RopSubmitMessageHandler.js.map +1 -0
  121. package/dist/lib/rop/RopWriteStreamHandler.js +72 -0
  122. package/dist/lib/rop/RopWriteStreamHandler.js.map +1 -0
  123. package/dist/lib/rop/TaskNamedProperties.js +29 -0
  124. package/dist/lib/rop/TaskNamedProperties.js.map +1 -0
  125. package/dist/lib/rop/TaskTarget.js +15 -0
  126. package/dist/lib/rop/TaskTarget.js.map +1 -0
  127. package/dist/lib/rop/TransportSend.js +16 -0
  128. package/dist/lib/rop/TransportSend.js.map +1 -0
  129. package/dist/lib/sql/MapiEmsmdbRouteSQL.js +85 -0
  130. package/dist/lib/sql/MapiEmsmdbRouteSQL.js.map +1 -0
  131. package/dist/lib/sql/MapiNspiRouteSQL.js +33 -0
  132. package/dist/lib/sql/MapiNspiRouteSQL.js.map +1 -0
  133. package/dist/lib/sql/index.js +7 -0
  134. package/dist/lib/sql/index.js.map +1 -0
  135. package/dist/lib/sql.js +6 -0
  136. package/dist/lib/sql.js.map +1 -0
  137. package/dist/types/BaseMapiEmsmdbRoute.d.ts +139 -0
  138. package/dist/types/BaseMapiNspiRoute.d.ts +38 -0
  139. package/dist/types/MapiSessionManager.d.ts +285 -0
  140. package/dist/types/RegexPatternUtils.d.ts +14 -0
  141. package/dist/types/RopDispatcher.d.ts +53 -0
  142. package/dist/types/codec/AppointmentRecurrence.d.ts +14 -0
  143. package/dist/types/codec/BufferCursor.d.ts +92 -0
  144. package/dist/types/codec/GlobalObjectId.d.ts +15 -0
  145. package/dist/types/codec/MapiGuid.d.ts +6 -0
  146. package/dist/types/codec/MapiTimeZone.d.ts +7 -0
  147. package/dist/types/codec/PropertyValue.d.ts +87 -0
  148. package/dist/types/codec/RopBuffer.d.ts +32 -0
  149. package/dist/types/codec/TypedString.d.ts +17 -0
  150. package/dist/types/index.d.ts +94 -0
  151. package/dist/types/mongo/MapiEmsmdbRouteMongo.d.ts +20 -0
  152. package/dist/types/mongo/MapiNspiRouteMongo.d.ts +13 -0
  153. package/dist/types/mongo/index.d.ts +2 -0
  154. package/dist/types/mongo.d.ts +1 -0
  155. package/dist/types/nspi/NspiBindHandler.d.ts +22 -0
  156. package/dist/types/nspi/NspiCodec.d.ts +59 -0
  157. package/dist/types/nspi/NspiGetMatchesHandler.d.ts +26 -0
  158. package/dist/types/rop/AddressList.d.ts +48 -0
  159. package/dist/types/rop/CalendarEventTarget.d.ts +33 -0
  160. package/dist/types/rop/CalendarNamedProperties.d.ts +37 -0
  161. package/dist/types/rop/ContactTarget.d.ts +29 -0
  162. package/dist/types/rop/ContentsTable.d.ts +16 -0
  163. package/dist/types/rop/ExecuteBudget.d.ts +48 -0
  164. package/dist/types/rop/FastTransferStream.d.ts +57 -0
  165. package/dist/types/rop/FolderTarget.d.ts +64 -0
  166. package/dist/types/rop/HandleDataCache.d.ts +145 -0
  167. package/dist/types/rop/MeetingMessageClassHandler.d.ts +30 -0
  168. package/dist/types/rop/MessageBodyStream.d.ts +35 -0
  169. package/dist/types/rop/MessageTarget.d.ts +45 -0
  170. package/dist/types/rop/NamedPropertyRegistry.d.ts +50 -0
  171. package/dist/types/rop/PropertyResolvers.d.ts +86 -0
  172. package/dist/types/rop/RepoPaging.d.ts +30 -0
  173. package/dist/types/rop/RestapiRules.d.ts +32 -0
  174. package/dist/types/rop/RopCreateMessageHandler.d.ts +24 -0
  175. package/dist/types/rop/RopDeleteFolderHandler.d.ts +53 -0
  176. package/dist/types/rop/RopDeleteMessagesHandler.d.ts +43 -0
  177. package/dist/types/rop/RopFastTransferSourceCopyPropertiesHandler.d.ts +25 -0
  178. package/dist/types/rop/RopFastTransferSourceCopyToHandler.d.ts +25 -0
  179. package/dist/types/rop/RopFastTransferSourceGetBufferHandler.d.ts +22 -0
  180. package/dist/types/rop/RopGetContentsTableHandler.d.ts +25 -0
  181. package/dist/types/rop/RopGetHierarchyTableHandler.d.ts +18 -0
  182. package/dist/types/rop/RopGetPropertiesSpecificHandler.d.ts +26 -0
  183. package/dist/types/rop/RopGetPropertyIdsFromNamesHandler.d.ts +23 -0
  184. package/dist/types/rop/RopHandler.d.ts +106 -0
  185. package/dist/types/rop/RopLogonHandler.d.ts +31 -0
  186. package/dist/types/rop/RopOpenFolderHandler.d.ts +20 -0
  187. package/dist/types/rop/RopOpenMessageHandler.d.ts +28 -0
  188. package/dist/types/rop/RopOpenStreamHandler.d.ts +28 -0
  189. package/dist/types/rop/RopQueryRowsHandler.d.ts +43 -0
  190. package/dist/types/rop/RopReadStreamHandler.d.ts +20 -0
  191. package/dist/types/rop/RopReleaseHandler.d.ts +15 -0
  192. package/dist/types/rop/RopSaveChangesMessageHandler.d.ts +59 -0
  193. package/dist/types/rop/RopSetColumnsHandler.d.ts +21 -0
  194. package/dist/types/rop/RopSetPropertiesHandler.d.ts +38 -0
  195. package/dist/types/rop/RopSubmitMessageHandler.d.ts +80 -0
  196. package/dist/types/rop/RopWriteStreamHandler.d.ts +31 -0
  197. package/dist/types/rop/TaskNamedProperties.d.ts +24 -0
  198. package/dist/types/rop/TaskTarget.d.ts +24 -0
  199. package/dist/types/rop/TransportSend.d.ts +10 -0
  200. package/dist/types/sql/MapiEmsmdbRouteSQL.d.ts +20 -0
  201. package/dist/types/sql/MapiNspiRouteSQL.d.ts +13 -0
  202. package/dist/types/sql/index.d.ts +2 -0
  203. package/dist/types/sql.d.ts +1 -0
  204. package/package.json +104 -0
@@ -0,0 +1,29 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ /**
6
+ * The Task named-property identity table (`(PropertySet GUID, LID)` pairs) this pragmatic subset supports, per
7
+ * `[MS-OXPROPS]`/`[MS-OXOTASK]` - the exact `CalendarNamedProperties.ts` precedent, adapted for `PSETID_Task`,
8
+ * shared by `PropertyResolvers.ts` (the read side: `taskValueFor`). Read-only in this pass - see
9
+ * `TaskTarget.ts`'s own doc comment for why there's no write-side (`RopSetProperties`/`RopSaveChangesMessage`)
10
+ * counterpart yet.
11
+ */
12
+ export const PSETID_TASK = "00062003-0000-0000-c000-000000000046";
13
+ /** `PidLidTaskStatus` (`PT_LONG`) - `[MS-OXOTASK]` §2.2.2.1.5's own `olTaskNotStarted`(0)/`olTaskInProgress`(1)/
14
+ * `olTaskComplete`(2)/`olTaskWaiting`(3)/`olTaskDeferred`(4) values. This data model's `Task.completed` is a
15
+ * plain boolean with no in-progress/waiting/deferred distinction, so only `olTaskNotStarted`/`olTaskComplete`
16
+ * are ever produced - a documented, harmless approximation, the same category as `CalendarNamedProperties.ts`'s
17
+ * own `olWorkingElsewhere` gap. */
18
+ export const LID_TASK_STATUS = 0x8101;
19
+ export const TASK_STATUS_NOT_STARTED = 0;
20
+ export const TASK_STATUS_COMPLETE = 2;
21
+ /** `PidLidPercentComplete` (`PT_R8`, `[MS-OXOTASK]` §2.2.2.1.6) - `0.0`-`1.0`. No partial-progress tracking in
22
+ * this data model either, so this is always `1.0` (complete) or `0.0` (not started), mirroring
23
+ * `LID_TASK_STATUS`'s own two-value approximation. */
24
+ export const LID_PERCENT_COMPLETE = 0x8102;
25
+ /** `PidLidTaskDueDate` (`PT_SYSTIME`, `[MS-OXOTASK]` §2.2.2.2.4). */
26
+ export const LID_TASK_DUE_DATE = 0x8105;
27
+ /** `PidLidTaskComplete` (`PT_BOOLEAN`, `[MS-OXOTASK]` §2.2.2.1.9) - maps directly to `Task.completed`. */
28
+ export const LID_TASK_COMPLETE = 0x811c;
29
+ //# sourceMappingURL=TaskNamedProperties.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskNamedProperties.js","sourceRoot":"","sources":["../../../src/rop/TaskNamedProperties.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E;AAE/E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,sCAAsC,CAAC;AAElE;;;;mCAImC;AACnC,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC;AACtC,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAEtC;;sDAEsD;AACtD,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAE3C,qEAAqE;AACrE,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC;AAExC,0GAA0G;AAC1G,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC"}
@@ -0,0 +1,15 @@
1
+ /** Degrades to empty-looking values for a `"task:<uid>"` target whose real `Task` has since vanished
2
+ * (soft-deleted or otherwise) - the same "don't fail the whole ROP over one stale row" principle
3
+ * `MessageTarget.resolveMessageInfo`/`ContactTarget.resolveContactInfo` already apply. */
4
+ export async function resolveTaskInfo(target, taskRepo) {
5
+ const uid = target.slice("task:".length);
6
+ const task = await taskRepo.findOne(uid, { ignoreACL: true });
7
+ return {
8
+ title: task?.title ?? "",
9
+ completed: task?.completed ?? false,
10
+ dueDate: task?.dueDate,
11
+ };
12
+ }
13
+ /** The order a `TASKS` folder's contents table lists tasks in (see `ContentsTable.ts`). */
14
+ export const TASK_SORT = { title: "ASC", uid: "ASC" };
15
+ //# sourceMappingURL=TaskTarget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskTarget.js","sourceRoot":"","sources":["../../../src/rop/TaskTarget.ts"],"names":[],"mappings":"AAyBA;;0FAE0F;AAC1F,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAc,EAAE,QAAwB;IAC1E,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,IAAI,GAAqB,MAAM,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChF,OAAO;QACH,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE;QACxB,SAAS,EAAE,IAAI,EAAE,SAAS,IAAI,KAAK;QACnC,OAAO,EAAE,IAAI,EAAE,OAAO;KACzB,CAAC;AACN,CAAC;AAED,2FAA2F;AAC3F,MAAM,CAAC,MAAM,SAAS,GAAa,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Sends `message` and throws unless the transport accepted it for at least one recipient and rejected none.
3
+ *
4
+ * The same rule as restapi's own `sendOrThrow()` (`transport/TransportResultUtils.ts`), which isn't exported from
5
+ * the `@rapidmx/restapi` package root, so it can't be imported here; keep the two in sync. Every bundled transport
6
+ * reports a failed relay through `TransportResult.rejected` rather than throwing, so a bare `send()` would treat a
7
+ * rejected message as sent.
8
+ */
9
+ export async function sendOrThrow(transport, message) {
10
+ const result = await transport.send(message);
11
+ if (!result || (result.accepted ?? []).length === 0 || (result.rejected ?? []).length > 0) {
12
+ throw new Error(`The mail transport did not accept the message (rejected: ${(result?.rejected ?? []).length}).`);
13
+ }
14
+ return result;
15
+ }
16
+ //# sourceMappingURL=TransportSend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TransportSend.js","sourceRoot":"","sources":["../../../src/rop/TransportSend.ts"],"names":[],"mappings":"AAMA;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,SAAwB,EAAE,OAAwB;IAChF,MAAM,MAAM,GAAgC,MAAM,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1E,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxF,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,MAAM,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;IACrH,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC"}
@@ -0,0 +1,85 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ ///////////////////////////////////////////////////////////////////////////////
8
+ // Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
9
+ // SPDX-License-Identifier: MPL-2.0
10
+ ///////////////////////////////////////////////////////////////////////////////
11
+ import { AuditLogEntrySQL, CalendarEventSQL, ContactSQL, FolderSQL, LabelSQL, MailboxSQL, MessageSQL, TaskSQL } from "@rapidmx/restapi/sql";
12
+ import { BaseMapiEmsmdbRoute } from "../BaseMapiEmsmdbRoute.js";
13
+ import { RopLogonHandler } from "../rop/RopLogonHandler.js";
14
+ import { RopReleaseHandler } from "../rop/RopReleaseHandler.js";
15
+ import { RopOpenFolderHandler } from "../rop/RopOpenFolderHandler.js";
16
+ import { RopGetHierarchyTableHandler } from "../rop/RopGetHierarchyTableHandler.js";
17
+ import { RopGetContentsTableHandler } from "../rop/RopGetContentsTableHandler.js";
18
+ import { RopSetColumnsHandler } from "../rop/RopSetColumnsHandler.js";
19
+ import { RopQueryRowsHandler } from "../rop/RopQueryRowsHandler.js";
20
+ import { RopOpenMessageHandler } from "../rop/RopOpenMessageHandler.js";
21
+ import { RopGetPropertiesSpecificHandler } from "../rop/RopGetPropertiesSpecificHandler.js";
22
+ import { RopOpenStreamHandler } from "../rop/RopOpenStreamHandler.js";
23
+ import { RopReadStreamHandler } from "../rop/RopReadStreamHandler.js";
24
+ import { RopCreateMessageHandler } from "../rop/RopCreateMessageHandler.js";
25
+ import { RopSetPropertiesHandler } from "../rop/RopSetPropertiesHandler.js";
26
+ import { RopWriteStreamHandler } from "../rop/RopWriteStreamHandler.js";
27
+ import { RopSaveChangesMessageHandler } from "../rop/RopSaveChangesMessageHandler.js";
28
+ import { RopSubmitMessageHandler } from "../rop/RopSubmitMessageHandler.js";
29
+ import { RopGetPropertyIdsFromNamesHandler } from "../rop/RopGetPropertyIdsFromNamesHandler.js";
30
+ import { RopDeleteMessagesHandler } from "../rop/RopDeleteMessagesHandler.js";
31
+ import { RopDeleteFolderHandler } from "../rop/RopDeleteFolderHandler.js";
32
+ import { RopFastTransferSourceCopyToHandler } from "../rop/RopFastTransferSourceCopyToHandler.js";
33
+ import { RopFastTransferSourceCopyPropertiesHandler } from "../rop/RopFastTransferSourceCopyPropertiesHandler.js";
34
+ import { RopFastTransferSourceGetBufferHandler } from "../rop/RopFastTransferSourceGetBufferHandler.js";
35
+ import { RouteDecorators } from "@rapidrest/service-core";
36
+ const { Route } = RouteDecorators;
37
+ /**
38
+ * SQL-backed concrete `BaseMapiEmsmdbRoute`, mounted at `/mapi/emsmdb`. Exported from this plugin's
39
+ * `./sql` entry point, so the server host mounts it without a wrapper class of its
40
+ * own.
41
+ *
42
+ * @author Jean-Philippe Steinmetz
43
+ */
44
+ let MapiEmsmdbRouteSQL = class MapiEmsmdbRouteSQL extends BaseMapiEmsmdbRoute {
45
+ constructor() {
46
+ super(...arguments);
47
+ this.mailboxClass = MailboxSQL;
48
+ this.folderClass = FolderSQL;
49
+ this.messageClass = MessageSQL;
50
+ this.calendarEventClass = CalendarEventSQL;
51
+ this.contactClass = ContactSQL;
52
+ this.taskClass = TaskSQL;
53
+ this.labelClass = LabelSQL;
54
+ this.auditLogClass = AuditLogEntrySQL;
55
+ this.ropHandlerClasses = [
56
+ RopLogonHandler,
57
+ RopReleaseHandler,
58
+ RopOpenFolderHandler,
59
+ RopGetHierarchyTableHandler,
60
+ RopGetContentsTableHandler,
61
+ RopSetColumnsHandler,
62
+ RopQueryRowsHandler,
63
+ RopOpenMessageHandler,
64
+ RopGetPropertiesSpecificHandler,
65
+ RopOpenStreamHandler,
66
+ RopReadStreamHandler,
67
+ RopCreateMessageHandler,
68
+ RopSetPropertiesHandler,
69
+ RopWriteStreamHandler,
70
+ RopSaveChangesMessageHandler,
71
+ RopSubmitMessageHandler,
72
+ RopGetPropertyIdsFromNamesHandler,
73
+ RopDeleteMessagesHandler,
74
+ RopDeleteFolderHandler,
75
+ RopFastTransferSourceCopyToHandler,
76
+ RopFastTransferSourceCopyPropertiesHandler,
77
+ RopFastTransferSourceGetBufferHandler,
78
+ ];
79
+ }
80
+ };
81
+ MapiEmsmdbRouteSQL = __decorate([
82
+ Route("/mapi/emsmdb")
83
+ ], MapiEmsmdbRouteSQL);
84
+ export { MapiEmsmdbRouteSQL };
85
+ //# sourceMappingURL=MapiEmsmdbRouteSQL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MapiEmsmdbRouteSQL.js","sourceRoot":"","sources":["../../../src/sql/MapiEmsmdbRouteSQL.ts"],"names":[],"mappings":";;;;;;AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E;AAC/E,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC5I,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,2BAA2B,EAAE,MAAM,uCAAuC,CAAC;AACpF,OAAO,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AAClF,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,+BAA+B,EAAE,MAAM,2CAA2C,CAAC;AAC5F,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,4BAA4B,EAAE,MAAM,wCAAwC,CAAC;AACtF,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EAAE,iCAAiC,EAAE,MAAM,6CAA6C,CAAC;AAChG,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,kCAAkC,EAAE,MAAM,8CAA8C,CAAC;AAClG,OAAO,EAAE,0CAA0C,EAAE,MAAM,sDAAsD,CAAC;AAClH,OAAO,EAAE,qCAAqC,EAAE,MAAM,iDAAiD,CAAC;AACxG,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,MAAM,EAAE,KAAK,EAAE,GAAG,eAAe,CAAC;AAElC;;;;;;GAMG;AAEI,IAAM,kBAAkB,GAAxB,MAAM,kBAAmB,SAAQ,mBAA+B;IAAhE;;QACO,iBAAY,GAAQ,UAAU,CAAC;QAC/B,gBAAW,GAAQ,SAAS,CAAC;QAC7B,iBAAY,GAAQ,UAAU,CAAC;QAC/B,uBAAkB,GAAQ,gBAAgB,CAAC;QAC3C,iBAAY,GAAQ,UAAU,CAAC;QAC/B,cAAS,GAAQ,OAAO,CAAC;QACzB,eAAU,GAAQ,QAAQ,CAAC;QAC3B,kBAAa,GAAQ,gBAAgB,CAAC;QACtC,sBAAiB,GAAU;YACjC,eAAe;YACf,iBAAiB;YACjB,oBAAoB;YACpB,2BAA2B;YAC3B,0BAA0B;YAC1B,oBAAoB;YACpB,mBAAmB;YACnB,qBAAqB;YACrB,+BAA+B;YAC/B,oBAAoB;YACpB,oBAAoB;YACpB,uBAAuB;YACvB,uBAAuB;YACvB,qBAAqB;YACrB,4BAA4B;YAC5B,uBAAuB;YACvB,iCAAiC;YACjC,wBAAwB;YACxB,sBAAsB;YACtB,kCAAkC;YAClC,0CAA0C;YAC1C,qCAAqC;SACxC,CAAC;IACN,CAAC;CAAA,CAAA;AAjCY,kBAAkB;IAD9B,KAAK,CAAC,cAAc,CAAC;GACT,kBAAkB,CAiC9B"}
@@ -0,0 +1,33 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ ///////////////////////////////////////////////////////////////////////////////
8
+ // Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
9
+ // SPDX-License-Identifier: MPL-2.0
10
+ ///////////////////////////////////////////////////////////////////////////////
11
+ import { ContactSQL, MailboxSQL } from "@rapidmx/restapi/sql";
12
+ import { BaseMapiNspiRoute } from "../BaseMapiNspiRoute.js";
13
+ import { RouteDecorators } from "@rapidrest/service-core";
14
+ const { Route } = RouteDecorators;
15
+ /**
16
+ * SQL-backed concrete `BaseMapiNspiRoute`, mounted at `/mapi/nspi`. Exported from this plugin's
17
+ * `./sql` entry point, so the server host mounts it without a wrapper class of its
18
+ * own.
19
+ *
20
+ * @author Jean-Philippe Steinmetz
21
+ */
22
+ let MapiNspiRouteSQL = class MapiNspiRouteSQL extends BaseMapiNspiRoute {
23
+ constructor() {
24
+ super(...arguments);
25
+ this.mailboxClass = MailboxSQL;
26
+ this.contactClass = ContactSQL;
27
+ }
28
+ };
29
+ MapiNspiRouteSQL = __decorate([
30
+ Route("/mapi/nspi")
31
+ ], MapiNspiRouteSQL);
32
+ export { MapiNspiRouteSQL };
33
+ //# sourceMappingURL=MapiNspiRouteSQL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MapiNspiRouteSQL.js","sourceRoot":"","sources":["../../../src/sql/MapiNspiRouteSQL.ts"],"names":[],"mappings":";;;;;;AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E;AAC/E,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,MAAM,EAAE,KAAK,EAAE,GAAG,eAAe,CAAC;AAElC;;;;;;GAMG;AAEI,IAAM,gBAAgB,GAAtB,MAAM,gBAAiB,SAAQ,iBAA6B;IAA5D;;QACO,iBAAY,GAAQ,UAAU,CAAC;QAC/B,iBAAY,GAAQ,UAAU,CAAC;IAC7C,CAAC;CAAA,CAAA;AAHY,gBAAgB;IAD5B,KAAK,CAAC,YAAY,CAAC;GACP,gBAAgB,CAG5B"}
@@ -0,0 +1,7 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ export * from "./MapiEmsmdbRouteSQL.js";
6
+ export * from "./MapiNspiRouteSQL.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/sql/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E;AAC/E,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1,6 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz. All rights reserved.
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ export * from "./sql/index.js";
6
+ //# sourceMappingURL=sql.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql.js","sourceRoot":"","sources":["../../src/sql.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mEAAmE;AACnE,mCAAmC;AACnC,+EAA+E;AAC/E,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,139 @@
1
+ import { type JWTUser } from "@rapidrest/core";
2
+ import { HttpRequest, HttpResponse } from "@rapidrest/service-core";
3
+ import { type RopBuffer } from "./codec/RopBuffer.js";
4
+ import { Mailbox } from "@rapidmx/restapi";
5
+ /** The largest `RopBufferSize` accepted - the `[MS-OXCRPC]` ROP input buffer limit. */
6
+ export declare const MAX_ROP_BUFFER_SIZE = 32767;
7
+ /** A decoded `Execute` request: the ROP buffer framing plus the client's `MaxRopOut`. */
8
+ export interface ExecuteRequest extends RopBuffer {
9
+ /** The most bytes the client accepts in the response's `RopBuffer`. */
10
+ maxRopOut: number;
11
+ }
12
+ /**
13
+ * Decodes an `Execute` request body's `Flags`/`RopBufferSize`/`RopBuffer`/`MaxRopOut` and the ROP buffer framing
14
+ * inside it. Throws a 400 `ApiError` for a malformed body - a `RopBufferSize` over `MAX_ROP_BUFFER_SIZE` or past the
15
+ * end of the body, or a ROP buffer `decodeRopBuffer` rejects - instead of letting a bare `RangeError` surface as a
16
+ * 500. A body that ends before `MaxRopOut` gets the largest response a `RopBuffer` can carry.
17
+ * `AuxiliaryBufferSize`/`AuxiliaryBuffer` are left unread - no auxiliary-payload support in this pragmatic subset.
18
+ */
19
+ export declare function decodeExecuteRequest(rawBody: Buffer): ExecuteRequest;
20
+ /**
21
+ * Abstract base for the single fixed EMSMDB endpoint (`POST /mapi/emsmdb` by `[MS-OXCMAPIHTTP]` convention,
22
+ * though the concrete path is left to the consuming application to mount via `@Route(...)` - see
23
+ * `BaseEasRoute.ts` for the identical undecorated-base-class pattern this follows). Like EAS, MAPI/HTTP
24
+ * multiplexes several request types against one URL - here via the `X-RequestType` **header**
25
+ * (`Connect`/`Execute`/`Disconnect`/`NotificationWait`) rather than a query parameter - so there is exactly
26
+ * one `@Post()` method, not one per request type.
27
+ *
28
+ * **Auth**: `@Auth(["jwt"])` - unchanged from every other route in this app. Real, modern Exchange Server's
29
+ * own MAPI virtual directory genuinely supports `OAuth` as a configured `IISAuthenticationMethods` value
30
+ * alongside `NTLM`/`Negotiate`, so Bearer-token auth on this exact endpoint is real current Exchange
31
+ * behavior, not a deviation this library invents - see the architecture plan's "Auth" section.
32
+ *
33
+ * **Connect/Disconnect are complete**: `Connect` establishes a real `MapiSessionContext` (via
34
+ * `MapiSessionManager`) and sets the two spec-fixed session cookies (`MapiContext`/`MapiSequence`);
35
+ * `Disconnect` releases the session. **`Execute` dispatches real ROPs** (starting with `RopLogon`/`RopRelease`
36
+ * - build-order step 4) via `RopDispatcher`, using whichever `RopHandler`s `ropHandlerClasses` registers;
37
+ * an unrecognized `RopId` simply stops processing (see `RopDispatcher`'s own doc comment for why), the same
38
+ * "real, functional, no commands implemented yet" stance `BaseEasRoute`'s own skeleton step took for its
39
+ * empty `commandHandlerClasses` before `ProvisionCommand` landed - here scoped per-ROP instead of per-request.
40
+ *
41
+ * **Always non-chunked**: every response here uses `Content-Length` (via `res.status(200).send(buffer)`),
42
+ * never `Transfer-Encoding: chunked` - both are equally spec-valid per `[MS-OXCMAPIHTTP]`'s own "Common
43
+ * Response Format", and skipping the `PROCESSING`/`PENDING`/`DONE` keep-alive meta-tag streaming matches
44
+ * every other route in this library's own response idiom. See the architecture plan's "Protocol facts"
45
+ * section for the full reasoning and its documented limitation.
46
+ *
47
+ * `mailboxClass`/`folderClass` are supplied by the Mongo/SQL concrete subclasses, following the exact
48
+ * one-line-per-backend pattern used throughout this library's other routes/jobs. `folderRepo` is built once
49
+ * here (not per-handler, unlike EAS's per-command repo pattern) and threaded through `RopContext` to every
50
+ * `RopHandler` - see `RopHandler.ts`'s own doc comment for why.
51
+ *
52
+ * @author Jean-Philippe Steinmetz
53
+ */
54
+ export declare abstract class BaseMapiEmsmdbRoute<M extends Mailbox> {
55
+ protected abstract mailboxClass: any;
56
+ protected abstract folderClass: any;
57
+ protected abstract messageClass: any;
58
+ protected abstract calendarEventClass: any;
59
+ protected abstract contactClass: any;
60
+ protected abstract taskClass: any;
61
+ protected abstract labelClass: any;
62
+ /** The backend's `AuditLogEntry` class. When set, messages deleted through MAPI are audited like REST deletes. */
63
+ protected auditLogClass?: any;
64
+ /** ROP handler classes to instantiate (one each) in `@Init`, keyed by their own `ropId`. Empty until a
65
+ * concrete `RopHandler` lands - every ROP is then simply left unprocessed (see `RopDispatcher`'s own doc
66
+ * comment), the correct, honest behavior for a transport skeleton with no ROPs implemented yet. */
67
+ protected ropHandlerClasses: any[];
68
+ private _objectFactory?;
69
+ private mailboxRepo?;
70
+ private folderRepo?;
71
+ private messageRepo?;
72
+ private calendarEventRepo?;
73
+ private contactRepo?;
74
+ private taskRepo?;
75
+ private labelRepo?;
76
+ private sessionManager?;
77
+ private readonly ropHandlers;
78
+ private blobStore?;
79
+ private scanPipeline?;
80
+ private mailTransport?;
81
+ /** Publishes the live `Folder` counts-update event `refreshFolderCounts()` sends after a ROP handler changes what
82
+ * a folder holds through `context.messageRepo` directly - see `folderCountsContext()`/`RopContext.notifyFolderCounts`. */
83
+ private notificationUtils?;
84
+ private logger;
85
+ private config?;
86
+ init(): Promise<void>;
87
+ dispatch(req: HttpRequest, res: HttpResponse, user?: JWTUser): Promise<void>;
88
+ /**
89
+ * `Connect` establishes a new Session Context - never trusts the request body's own `UserDn` field for
90
+ * mailbox identity (the same "never a client-supplied mailbox, always resolved from the authenticated
91
+ * JWT" principle `BaseEasRoute`/`BaseSearchRoute` already apply via `resolveCallerMailboxUid`) - so the
92
+ * request body is never decoded at all here.
93
+ */
94
+ private handleConnect;
95
+ /**
96
+ * `Execute` decodes the outer envelope (`Flags`/`RopBufferSize`/`RopBuffer`/`MaxRopOut`/...) and the inner ROP
97
+ * buffer framing (`RopBuffer.ts`), dispatches every contained ROP via `RopDispatcher`, and re-encodes the
98
+ * collected responses - preserving the incoming `handleTable` unchanged (this pragmatic subset never
99
+ * allocates/frees table-wide handle slots at the framing level; individual `RopHandler`s manage their own
100
+ * entries within `session.handles` instead).
101
+ *
102
+ * - **One request at a time per session.** Only the caller's own session (whose mailbox is still the caller's) is
103
+ * locked. The lock is taken before any ROP runs and renewed every `SESSION_LOCK_RENEW_MS` while the request runs,
104
+ * so a slow request keeps it; an overlapping request gets `X-ResponseCode` 15 (Invalid Sequence) without any side
105
+ * effects. The save stays compare-and-set. Each `Execute` also refreshes the session's place in the per-user cap.
106
+ * - **Retries.** While a request with an `X-RequestId` runs, an in-progress marker for that id is kept (renewed with
107
+ * the lock); a retry of it is answered with code 15 instead of running again. Its response then replaces the
108
+ * marker, and a request repeating the last id (a client retrying after a lost response) gets that response again
109
+ * instead of running its ROPs twice. A request that ends without a stored response drops its marker.
110
+ * `MapiSequence` isn't validated - the lock and the replay cache cover what it guards against here.
111
+ * - **Output size.** ROP responses are held to the client's `MaxRopOut`, less the `RopSize` field and handle
112
+ * table, and to what a 16-bit `RopSize` can describe (see `dispatchRops`). Room for a `RopBufferTooSmall` covering
113
+ * the rest of the request is kept free as ROPs run, so a response that doesn't fit is always answered that way (a
114
+ * normal, stored response). Only a `MaxRopOut` too small for a `RopBufferTooSmall` of the whole request answers
115
+ * `ecBufferTooSmall` in the body `ErrorCode`, before any ROP runs, so nothing is stored and a retry changes nothing.
116
+ * - **Released handles.** Once the session is saved, the FastTransfer streams and write-stream chunks of handles
117
+ * the request released are deleted from the shared store; `Disconnect` and session eviction delete a session's
118
+ * whole set.
119
+ * - **Malformed ROPs.** A ROP that can't be decoded answers 400; the ROPs before it already ran, so the session is
120
+ * still saved first.
121
+ */
122
+ private handleExecute;
123
+ /** Runs an `Execute` under its session's lock. `running.requestId` is set while this request's in-progress marker is
124
+ * stored, and cleared once its response is stored instead. */
125
+ private executeLocked;
126
+ /** What `refreshFolderCounts()` (`@rapidmx/restapi`) needs to recompute, re-cache and publish a folder's counts -
127
+ * see `RopContext.notifyFolderCounts`'s own doc comment for why a ROP handler must call it after adding, deleting
128
+ * or moving a `Message` row through `context.messageRepo` itself. */
129
+ private folderCountsContext;
130
+ /** Writes an `Execute` failure body (no ROP buffer) with the given `X-ResponseCode` and `ErrorCode`. */
131
+ private sendExecuteFailure;
132
+ /**
133
+ * Loads the session named by the `MapiContext` cookie, but only if the authenticated caller is the user who
134
+ * `Connect`ed it. The cookie value alone is a bearer token for someone else's mailbox otherwise, so a session
135
+ * belonging to another user is treated exactly like one that doesn't exist.
136
+ */
137
+ private loadOwnSession;
138
+ private handleDisconnect;
139
+ }
@@ -0,0 +1,38 @@
1
+ import { type JWTUser } from "@rapidrest/core";
2
+ import { HttpRequest, HttpResponse } from "@rapidrest/service-core";
3
+ import { Mailbox } from "@rapidmx/restapi";
4
+ /**
5
+ * Abstract base for the single fixed NSPI endpoint (`POST /mapi/nspi` by `[MS-OXCMAPIHTTP]` convention, though
6
+ * the concrete path is left to the consuming application to mount via `@Route(...)`, the identical
7
+ * undecorated-base-class pattern `BaseMapiEmsmdbRoute`/`BaseEasRoute` already establish). Dispatches on the
8
+ * `X-RequestType` header, the same multiplexing mechanism EMSMDB uses - but unlike EMSMDB, there is no ROP
9
+ * buffer framing here: each `X-RequestType` value (`Bind`/`Unbind`/`GetMatches`) is its own flat, self-
10
+ * contained request/response body (`[MS-OXCMAPIHTTP]` §2.2.5), so this route dispatches directly to a small
11
+ * handler function per operation instead of decoding a multiplexed stream.
12
+ *
13
+ * **Pragmatic subset scope**: only `Bind`/`Unbind`/`GetMatches` are implemented - real NSPI's other dozen-plus
14
+ * request types (`QueryRows`, `ResolveNames`, `GetProps`, `ModProps`, ...) are genuine full address-book/
15
+ * directory-replication operations this deployment's own minimal GAL-lookup use case doesn't need; an
16
+ * unrecognized `X-RequestType` gets a `501`, the same "recognized-but-deferred vs malformed" distinction
17
+ * `BaseMapiEmsmdbRoute`'s own `NotificationWait` case already draws. See `NspiBindHandler.ts`'s own doc comment
18
+ * for why no real NSPI session state is created or tracked between calls.
19
+ *
20
+ * **Auth**: `@Auth(["jwt"])`, unchanged from every other route in this app - the same reasoning
21
+ * `BaseMapiEmsmdbRoute`'s own doc comment already gives for why Bearer-token auth on an address-book endpoint
22
+ * is real, current Exchange behavior, not a deviation this library invents.
23
+ *
24
+ * `mailboxClass`/`contactClass` are supplied by the Mongo/SQL concrete subclasses. GAL search itself (see
25
+ * `NspiGetMatchesHandler.ts`) uses `RepoUtils`'s `regex(...)` operator, which compiles identically on both
26
+ * backends - no per-backend hook needed here.
27
+ *
28
+ * @author Jean-Philippe Steinmetz
29
+ */
30
+ export declare abstract class BaseMapiNspiRoute<M extends Mailbox> {
31
+ protected abstract mailboxClass: any;
32
+ protected abstract contactClass: any;
33
+ private _objectFactory?;
34
+ private mailboxRepo?;
35
+ private contactRepo?;
36
+ init(): Promise<void>;
37
+ dispatch(req: HttpRequest, res: HttpResponse, user?: JWTUser): Promise<void>;
38
+ }