@memberjunction/server 6.1.0-edge.6 → 6.1.0-edge.7

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 (177) hide show
  1. package/README.md +24 -9
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/config.d.ts +36 -0
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +9 -0
  6. package/dist/config.js.map +1 -1
  7. package/dist/entitySubclasses/MJEntityPermissionEntityServer.server.d.ts +30 -0
  8. package/dist/entitySubclasses/MJEntityPermissionEntityServer.server.d.ts.map +1 -1
  9. package/dist/entitySubclasses/MJEntityPermissionEntityServer.server.js +58 -5
  10. package/dist/entitySubclasses/MJEntityPermissionEntityServer.server.js.map +1 -1
  11. package/dist/generated/graphql-schemas/__mj.d.ts +2842 -2144
  12. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  13. package/dist/generated/graphql-schemas/__mj.js +5334 -2143
  14. package/dist/generated/graphql-schemas/__mj.js.map +1 -1
  15. package/dist/generic/ResolverBase.d.ts +119 -4
  16. package/dist/generic/ResolverBase.d.ts.map +1 -1
  17. package/dist/generic/ResolverBase.js +264 -11
  18. package/dist/generic/ResolverBase.js.map +1 -1
  19. package/dist/generic/RunViewResolver.d.ts.map +1 -1
  20. package/dist/generic/RunViewResolver.js +26 -2
  21. package/dist/generic/RunViewResolver.js.map +1 -1
  22. package/dist/generic/refusalExtensions.d.ts +52 -0
  23. package/dist/generic/refusalExtensions.d.ts.map +1 -0
  24. package/dist/generic/refusalExtensions.js +16 -0
  25. package/dist/generic/refusalExtensions.js.map +1 -0
  26. package/dist/index.d.ts +9 -3
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +115 -91
  29. package/dist/index.js.map +1 -1
  30. package/dist/resolvers/EntityRecordNameResolver.d.ts +34 -5
  31. package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
  32. package/dist/resolvers/EntityRecordNameResolver.js +64 -7
  33. package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
  34. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +10 -2
  35. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  36. package/dist/resolvers/RealtimeClientSessionResolver.js +80 -4
  37. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  38. package/dist/rest/RealtimeSdpBrokerHandler.d.ts +23 -0
  39. package/dist/rest/RealtimeSdpBrokerHandler.d.ts.map +1 -0
  40. package/dist/rest/RealtimeSdpBrokerHandler.js +78 -0
  41. package/dist/rest/RealtimeSdpBrokerHandler.js.map +1 -0
  42. package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
  43. package/dist/serverExtensionReservedRoots.js +2 -3
  44. package/dist/serverExtensionReservedRoots.js.map +1 -1
  45. package/package.json +92 -92
  46. package/src/__tests__/EntityRecordNameResolver.fieldSecurity.test.ts +118 -0
  47. package/src/__tests__/RealtimeClientSessionResolver.test.ts +20 -0
  48. package/src/__tests__/RealtimeSdpBrokerHandler.test.ts +191 -0
  49. package/src/__tests__/ResolverBase.filterEscaping.test.ts +63 -0
  50. package/src/__tests__/ResolverBase.readableFieldsTransport.test.ts +106 -0
  51. package/src/__tests__/generatedGraphQLSchema.structural.test.ts +46 -0
  52. package/src/__tests__/resolverBase.fls.test.ts +483 -0
  53. package/src/__tests__/resolverBase.recordChangesFls.test.ts +358 -0
  54. package/src/__tests__/resolverBase.refusalExtensions.test.ts +101 -0
  55. package/src/__tests__/serverExtensionReservedRoots.test.ts +79 -11
  56. package/src/config.ts +12 -0
  57. package/src/entitySubclasses/MJEntityPermissionEntityServer.server.ts +65 -6
  58. package/src/generated/graphql-schemas/__mj.ts +6590 -4287
  59. package/src/generic/ResolverBase.ts +313 -10
  60. package/src/generic/RunViewResolver.ts +28 -2
  61. package/src/generic/refusalExtensions.ts +59 -0
  62. package/src/index.ts +137 -100
  63. package/src/resolvers/EntityRecordNameResolver.ts +74 -8
  64. package/src/resolvers/RealtimeClientSessionResolver.ts +128 -2
  65. package/src/rest/RealtimeSdpBrokerHandler.ts +101 -0
  66. package/src/serverExtensionReservedRoots.ts +2 -3
  67. package/dist/resolvers/RingCentralTelephonyResolver.d.ts +0 -27
  68. package/dist/resolvers/RingCentralTelephonyResolver.d.ts.map +0 -1
  69. package/dist/resolvers/RingCentralTelephonyResolver.js +0 -87
  70. package/dist/resolvers/RingCentralTelephonyResolver.js.map +0 -1
  71. package/dist/resolvers/TeamsMeetingsResolver.d.ts +0 -28
  72. package/dist/resolvers/TeamsMeetingsResolver.d.ts.map +0 -1
  73. package/dist/resolvers/TeamsMeetingsResolver.js +0 -91
  74. package/dist/resolvers/TeamsMeetingsResolver.js.map +0 -1
  75. package/dist/resolvers/TelephonyResolver.d.ts +0 -26
  76. package/dist/resolvers/TelephonyResolver.d.ts.map +0 -1
  77. package/dist/resolvers/TelephonyResolver.js +0 -86
  78. package/dist/resolvers/TelephonyResolver.js.map +0 -1
  79. package/dist/resolvers/VonageTelephonyResolver.d.ts +0 -26
  80. package/dist/resolvers/VonageTelephonyResolver.d.ts.map +0 -1
  81. package/dist/resolvers/VonageTelephonyResolver.js +0 -86
  82. package/dist/resolvers/VonageTelephonyResolver.js.map +0 -1
  83. package/dist/telephony/RingCentralTelephonyService.d.ts +0 -115
  84. package/dist/telephony/RingCentralTelephonyService.d.ts.map +0 -1
  85. package/dist/telephony/RingCentralTelephonyService.js +0 -262
  86. package/dist/telephony/RingCentralTelephonyService.js.map +0 -1
  87. package/dist/telephony/TeamsMeetingsRouter.d.ts +0 -40
  88. package/dist/telephony/TeamsMeetingsRouter.d.ts.map +0 -1
  89. package/dist/telephony/TeamsMeetingsRouter.js +0 -112
  90. package/dist/telephony/TeamsMeetingsRouter.js.map +0 -1
  91. package/dist/telephony/TeamsMeetingsService.d.ts +0 -113
  92. package/dist/telephony/TeamsMeetingsService.d.ts.map +0 -1
  93. package/dist/telephony/TeamsMeetingsService.js +0 -196
  94. package/dist/telephony/TeamsMeetingsService.js.map +0 -1
  95. package/dist/telephony/TwilioTelephonyRouter.d.ts +0 -36
  96. package/dist/telephony/TwilioTelephonyRouter.d.ts.map +0 -1
  97. package/dist/telephony/TwilioTelephonyRouter.js +0 -143
  98. package/dist/telephony/TwilioTelephonyRouter.js.map +0 -1
  99. package/dist/telephony/TwilioTelephonyService.d.ts +0 -95
  100. package/dist/telephony/TwilioTelephonyService.d.ts.map +0 -1
  101. package/dist/telephony/TwilioTelephonyService.js +0 -193
  102. package/dist/telephony/TwilioTelephonyService.js.map +0 -1
  103. package/dist/telephony/VonageTelephonyRouter.d.ts +0 -41
  104. package/dist/telephony/VonageTelephonyRouter.d.ts.map +0 -1
  105. package/dist/telephony/VonageTelephonyRouter.js +0 -201
  106. package/dist/telephony/VonageTelephonyRouter.js.map +0 -1
  107. package/dist/telephony/VonageTelephonyService.d.ts +0 -90
  108. package/dist/telephony/VonageTelephonyService.d.ts.map +0 -1
  109. package/dist/telephony/VonageTelephonyService.js +0 -191
  110. package/dist/telephony/VonageTelephonyService.js.map +0 -1
  111. package/dist/telephony/calendar-scheduler.d.ts +0 -67
  112. package/dist/telephony/calendar-scheduler.d.ts.map +0 -1
  113. package/dist/telephony/calendar-scheduler.js +0 -133
  114. package/dist/telephony/calendar-scheduler.js.map +0 -1
  115. package/dist/telephony/index.d.ts +0 -29
  116. package/dist/telephony/index.d.ts.map +0 -1
  117. package/dist/telephony/index.js +0 -38
  118. package/dist/telephony/index.js.map +0 -1
  119. package/dist/telephony/media-upgrade-router.d.ts +0 -47
  120. package/dist/telephony/media-upgrade-router.d.ts.map +0 -1
  121. package/dist/telephony/media-upgrade-router.js +0 -72
  122. package/dist/telephony/media-upgrade-router.js.map +0 -1
  123. package/dist/telephony/ringcentral-runtime.d.ts +0 -14
  124. package/dist/telephony/ringcentral-runtime.d.ts.map +0 -1
  125. package/dist/telephony/ringcentral-runtime.js +0 -18
  126. package/dist/telephony/ringcentral-runtime.js.map +0 -1
  127. package/dist/telephony/teams-meetings-runtime.d.ts +0 -16
  128. package/dist/telephony/teams-meetings-runtime.d.ts.map +0 -1
  129. package/dist/telephony/teams-meetings-runtime.js +0 -20
  130. package/dist/telephony/teams-meetings-runtime.js.map +0 -1
  131. package/dist/telephony/teamsAcsMediaRegistry.d.ts +0 -69
  132. package/dist/telephony/teamsAcsMediaRegistry.d.ts.map +0 -1
  133. package/dist/telephony/teamsAcsMediaRegistry.js +0 -118
  134. package/dist/telephony/teamsAcsMediaRegistry.js.map +0 -1
  135. package/dist/telephony/telephony-runtime.d.ts +0 -14
  136. package/dist/telephony/telephony-runtime.d.ts.map +0 -1
  137. package/dist/telephony/telephony-runtime.js +0 -18
  138. package/dist/telephony/telephony-runtime.js.map +0 -1
  139. package/dist/telephony/twilioMediaRegistry.d.ts +0 -60
  140. package/dist/telephony/twilioMediaRegistry.d.ts.map +0 -1
  141. package/dist/telephony/twilioMediaRegistry.js +0 -106
  142. package/dist/telephony/twilioMediaRegistry.js.map +0 -1
  143. package/dist/telephony/vonage-runtime.d.ts +0 -14
  144. package/dist/telephony/vonage-runtime.d.ts.map +0 -1
  145. package/dist/telephony/vonage-runtime.js +0 -18
  146. package/dist/telephony/vonage-runtime.js.map +0 -1
  147. package/dist/telephony/vonageMediaRegistry.d.ts +0 -78
  148. package/dist/telephony/vonageMediaRegistry.d.ts.map +0 -1
  149. package/dist/telephony/vonageMediaRegistry.js +0 -158
  150. package/dist/telephony/vonageMediaRegistry.js.map +0 -1
  151. package/src/__tests__/media-upgrade-router.test.ts +0 -43
  152. package/src/__tests__/teams-meetings-service.test.ts +0 -65
  153. package/src/__tests__/teamsAcsMediaRegistry.test.ts +0 -82
  154. package/src/__tests__/twilio-telephony-service.test.ts +0 -23
  155. package/src/__tests__/twilioMediaRegistry.test.ts +0 -103
  156. package/src/__tests__/vonageMediaRegistry.test.ts +0 -180
  157. package/src/resolvers/RingCentralTelephonyResolver.ts +0 -64
  158. package/src/resolvers/TeamsMeetingsResolver.ts +0 -68
  159. package/src/resolvers/TelephonyResolver.ts +0 -63
  160. package/src/resolvers/VonageTelephonyResolver.ts +0 -63
  161. package/src/telephony/RingCentralTelephonyService.ts +0 -342
  162. package/src/telephony/TeamsMeetingsRouter.ts +0 -143
  163. package/src/telephony/TeamsMeetingsService.ts +0 -268
  164. package/src/telephony/TwilioTelephonyRouter.ts +0 -184
  165. package/src/telephony/TwilioTelephonyService.ts +0 -261
  166. package/src/telephony/VonageTelephonyRouter.ts +0 -239
  167. package/src/telephony/VonageTelephonyService.ts +0 -259
  168. package/src/telephony/calendar-scheduler.ts +0 -176
  169. package/src/telephony/index.ts +0 -43
  170. package/src/telephony/media-upgrade-router.ts +0 -79
  171. package/src/telephony/ringcentral-runtime.ts +0 -22
  172. package/src/telephony/teams-meetings-runtime.ts +0 -24
  173. package/src/telephony/teamsAcsMediaRegistry.ts +0 -152
  174. package/src/telephony/telephony-runtime.ts +0 -22
  175. package/src/telephony/twilioMediaRegistry.ts +0 -137
  176. package/src/telephony/vonage-runtime.ts +0 -22
  177. package/src/telephony/vonageMediaRegistry.ts +0 -200
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import { DatabasePlatform } from '@memberjunction/core';
2
2
  import { Application } from 'express';
3
3
  import 'reflect-metadata';
4
4
  import { RESTApiOptions } from './config.js';
5
- import { ServerExtensionConfig } from '@memberjunction/server-extensions-core';
5
+ import { ServerExtensionLoader, ServerExtensionConfig } from '@memberjunction/server-extensions-core';
6
6
  export { MetadataCacheRefreshIntervalSeconds } from './providerConfigUnits.js';
7
7
  /**
8
8
  * Returns the configured database platform from the `DB_PLATFORM` environment
@@ -22,8 +22,8 @@ export * from 'type-graphql';
22
22
  export { Int, Float, ID } from 'type-graphql';
23
23
  export { NewUserBase } from './auth/newUsers.js';
24
24
  export { configInfo, DEFAULT_SERVER_CONFIG } from './config.js';
25
- export { ServerExtensionLoader, BaseServerExtension } from '@memberjunction/server-extensions-core';
26
- export type { ServerExtensionConfig, ExtensionInitResult, ExtensionHealthResult } from '@memberjunction/server-extensions-core';
25
+ export { ServerExtensionLoader, BaseServerExtension, DefaultServerExtensionServiceRegistry } from '@memberjunction/server-extensions-core';
26
+ export type { ServerExtensionConfig, ServerExtensionPhase, ServerExtensionServiceRegistry, ServerExtensionInitContext, ExtensionInitResult, ExtensionHealthResult, LoadExtensionsOptions, } from '@memberjunction/server-extensions-core';
27
27
  export * from './directives/index.js';
28
28
  export { NoLog, hasNoLogParameter, getNoLogFields } from './logging/NoLog.js';
29
29
  export * from './entitySubclasses/MJEntityPermissionEntityServer.server.js';
@@ -34,10 +34,16 @@ export * from './auth/actingContextResolver.js';
34
34
  export { ResolveConfiguredPrincipal, resolvePrincipalFrom } from './auth/principals.js';
35
35
  export type { ResolvablePrincipal, PrincipalResolution, PrincipalResolutionReason } from './auth/principals.js';
36
36
  export { CloneUserForSessionContext } from './auth/sessionUserClone.js';
37
+ /**
38
+ * Returns the active ServerExtensionLoader instance for the running server.
39
+ * Returns null if the server has not been started yet.
40
+ */
41
+ export declare function GetServerExtensionLoader(): ServerExtensionLoader | null;
37
42
  export * from './generic/PushStatusResolver.js';
38
43
  export * from './generic/PubSubManager.js';
39
44
  export * from './generic/CacheInvalidationResolver.js';
40
45
  export * from './generic/ResolverBase.js';
46
+ export * from './generic/refusalExtensions.js';
41
47
  export * from './generic/RunViewResolver.js';
42
48
  export * from './resolvers/RunTemplateResolver.js';
43
49
  export * from './resolvers/RunAIPromptResolver.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAY,gBAAgB,EAAuI,MAAM,sBAAsB,CAAC;AAUvM,OAAgB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAQ/C,OAAO,kBAAkB,CAAC;AAQ1B,OAAO,EAA2I,cAAc,EAAE,MAAM,aAAa,CAAC;AAmDtL,OAAO,EAAyB,qBAAqB,EAA4F,MAAM,wCAAwC,CAAC;AAMhM,OAAO,EAAE,mCAAmC,EAAE,MAAM,0BAA0B,CAAC;AAE/E;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,IAAI,gBAAgB,CAE5C;AAED,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,cAAc,cAAc,CAAC;AAI7B,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AACpG,YAAY,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAChI,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC9E,cAAc,6DAA6D,CAAC;AAC5E,cAAc,YAAY,CAAC;AAC3B,OAAO,EACH,aAAa,EACb,cAAc,EACd,0BAA0B,EAC1B,gBAAgB,GACnB,MAAM,iBAAiB,CAAC;AACzB,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC;AAOhD,OAAO,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACxF,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AAChH,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAExE,cAAc,iCAAiC,CAAC;AAChD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wCAAwC,CAAC;AACvD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,oCAAoC,CAAC;AACnD,cAAc,oCAAoC,CAAC;AACnD,cAAc,mCAAmC,CAAC;AAClD,cAAc,wCAAwC,CAAC;AACvD,cAAc,wCAAwC,CAAC;AACvD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,iDAAiD,CAAC;AAChE,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,6CAA6C,CAAC;AAC5D,cAAc,yCAAyC,CAAC;AACxD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,gDAAgD,CAAC;AAC/D,cAAc,0CAA0C,CAAC;AACzD,cAAc,wCAAwC,CAAC;AACvD,cAAc,sCAAsC,CAAC;AACrD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,kCAAkC,CAAC;AAGjD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,0CAA0C,CAAC;AACzD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,yCAAyC,CAAC;AACxD,cAAc,qCAAqC,CAAC;AACpD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wCAAwC,CAAC;AACvD,cAAc,oCAAoC,CAAC;AACnD,cAAc,wCAAwC,CAAC;AACvD,cAAc,qCAAqC,CAAC;AACpD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,uCAAuC,CAAC;AACtD,cAAc,qCAAqC,CAAC;AACpD,cAAc,yCAAyC,CAAC;AACxD,cAAc,uCAAuC,CAAC;AACtD,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2CAA2C,CAAC;AAC1D,cAAc,yCAAyC,CAAC;AACxD,cAAc,wCAAwC,CAAC;AACvD,cAAc,kCAAkC,CAAC;AACjD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kCAAkC,CAAC;AACjD,cAAc,qCAAqC,CAAC;AACpD,cAAc,qCAAqC,CAAC;AACpD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iDAAiD,CAAC;AAChE,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uCAAuC,CAAC;AACtD,cAAc,qCAAqC,CAAC;AACpD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,uCAAuC,CAAC;AACtD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qCAAqC,CAAC;AACpD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,4CAA4C,CAAC;AAC3D,cAAc,0BAA0B,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAErH,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AAStC,MAAM,MAAM,eAAe,GAAG;IAC5B,aAAa,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,cAAc,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACzC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,qBAAqB,EAAE,CAAC;CAC5C,CAAC;AAUF,eAAO,MAAM,SAAS,QAAO,WAAwB,CAAC;AAoBtD,eAAO,MAAM,KAAK,GAAU,eAAe,KAAK,CAAC,MAAM,CAAC,EAAE,MAAK,WAAyB,EAAE,UAAU,eAAe,KAAG,OAAO,CAAC,IAAI,CA+0CjI,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -41,13 +41,10 @@ import { setupRESTEndpoints } from './rest/setupRESTEndpoints.js';
41
41
  import { createOAuthCallbackHandler } from './rest/OAuthCallbackHandler.js';
42
42
  import { createSignatureWebhookHandler } from './rest/SignatureWebhookHandler.js';
43
43
  import { createMediaStreamRouter } from './rest/MediaStreamHandler.js';
44
+ import { createRealtimeSdpBrokerRouter } from './rest/RealtimeSdpBrokerHandler.js';
45
+ import { REALTIME_SDP_EXCHANGE_PATH } from '@memberjunction/ai';
44
46
  import { createMagicLinkHandler, createMagicLinkJwksRouter, registerMagicLinkAuthProvider, MAGIC_LINK_MOUNT_PATH } from './auth/magicLink/index.js';
45
47
  import { createWidgetHandler, WIDGET_MOUNT_PATH } from './realtimeWidget/index.js';
46
- import { createTwilioTelephonyHandler, TWILIO_TELEPHONY_MOUNT_PATH, SetTwilioTelephonyService } from './telephony/index.js';
47
- import { createVonageTelephonyHandler, VONAGE_TELEPHONY_MOUNT_PATH, SetVonageTelephonyService } from './telephony/index.js';
48
- import { RingCentralTelephonyService, SetRingCentralTelephonyService } from './telephony/index.js';
49
- import { createTeamsMeetingsHandler, TEAMS_MEETINGS_MOUNT_PATH, SetTeamsMeetingsService, GetTeamsMeetingsService, StartCalendarScheduler } from './telephony/index.js';
50
- import { InstallMediaUpgradeDispatcher, IsGraphQLWsPath } from './telephony/index.js';
51
48
  import { resolve } from 'node:path';
52
49
  import { DataSourceInfo, raiseEvent } from './types.js';
53
50
  import { ScheduledJobsService } from './services/ScheduledJobsService.js';
@@ -67,7 +64,7 @@ import { StartTaskGraphDispatcher } from './services/StartTaskGraphDispatcher.js
67
64
  import { CACHE_INVALIDATION_TOPIC } from './generic/CacheInvalidationResolver.js';
68
65
  import { ConnectorFactory, IntegrationEngine } from '@memberjunction/integration-engine';
69
66
  import { CronExpressionHelper } from '@memberjunction/scheduling-engine';
70
- import { ServerExtensionLoader, mergeServerExtensionConfigs, prepareServerExtensionConfigs, describeServerExtensionMount } from '@memberjunction/server-extensions-core';
67
+ import { ServerExtensionLoader, mergeServerExtensionConfigs, prepareServerExtensionConfigs, describeServerExtensionMount, InstallMediaUpgradeDispatcher, IsGraphQLWsPath } from '@memberjunction/server-extensions-core';
71
68
  import { coreReservedServerExtensionRoots } from './serverExtensionReservedRoots.js';
72
69
  import { MetadataCacheRefreshIntervalSeconds } from './providerConfigUnits.js';
73
70
  const cacheRefreshInterval = configInfo.databaseSettings.metadataCacheRefreshInterval;
@@ -95,7 +92,7 @@ export * from 'type-graphql';
95
92
  export { Int, Float, ID } from 'type-graphql';
96
93
  export { NewUserBase } from './auth/newUsers.js';
97
94
  export { configInfo, DEFAULT_SERVER_CONFIG } from './config.js';
98
- export { ServerExtensionLoader, BaseServerExtension } from '@memberjunction/server-extensions-core';
95
+ export { ServerExtensionLoader, BaseServerExtension, DefaultServerExtensionServiceRegistry } from '@memberjunction/server-extensions-core';
99
96
  export * from './directives/index.js';
100
97
  export { NoLog, hasNoLogParameter, getNoLogFields } from './logging/NoLog.js';
101
98
  export * from './entitySubclasses/MJEntityPermissionEntityServer.server.js';
@@ -111,10 +108,19 @@ export * from './auth/actingContextResolver.js';
111
108
  // a published export is a maintenance commitment no caller asked for.
112
109
  export { ResolveConfiguredPrincipal, resolvePrincipalFrom } from './auth/principals.js';
113
110
  export { CloneUserForSessionContext } from './auth/sessionUserClone.js';
111
+ let _currentExtensionLoader = null;
112
+ /**
113
+ * Returns the active ServerExtensionLoader instance for the running server.
114
+ * Returns null if the server has not been started yet.
115
+ */
116
+ export function GetServerExtensionLoader() {
117
+ return _currentExtensionLoader;
118
+ }
114
119
  export * from './generic/PushStatusResolver.js';
115
120
  export * from './generic/PubSubManager.js';
116
121
  export * from './generic/CacheInvalidationResolver.js';
117
122
  export * from './generic/ResolverBase.js';
123
+ export * from './generic/refusalExtensions.js';
118
124
  export * from './generic/RunViewResolver.js';
119
125
  export * from './resolvers/RunTemplateResolver.js';
120
126
  export * from './resolvers/RunAIPromptResolver.js';
@@ -996,6 +1002,14 @@ export const serve = async (resolverPaths, app = createApp(), options) => {
996
1002
  app.use('/oauth', oauthCors, callbackRouter);
997
1003
  startupLog.LogIf('verbose', '[OAuth] Callback route registered at /oauth/callback');
998
1004
  }
1005
+ // ─── Core HTTP Routes (Static Core Infrastructure) ─────────────────────────
1006
+ // IMPORTANT ARCHITECTURAL NOTE:
1007
+ // The route mounts below are strictly reserved for core framework infrastructure (OAuth, eSignature,
1008
+ // media streaming, realtime WebRTC broker, magic-link, widgets).
1009
+ // ALL new custom routes, external webhooks, vendor adapters, and application integrations MUST be
1010
+ // implemented as Server Extensions (subclasses of BaseServerExtension in @memberjunction/server-extensions-core)
1011
+ // mounted via ServerExtensionLoader — NEVER hardcoded as ad-hoc app.use() in serve().
1012
+ // See guides/SERVER_EXTENSIONS_GUIDE.md for complete patterns and best practices.
999
1013
  // ─── eSignature webhook (unauthenticated, registered BEFORE auth) ─────
1000
1014
  // Called by external signature providers (DocuSign Connect, etc.) without an MJ bearer token.
1001
1015
  // The provider DRIVER verifies the payload signature/HMAC; MJ auth does not apply here.
@@ -1007,6 +1021,11 @@ export const serve = async (resolverPaths, app = createApp(), options) => {
1007
1021
  // auth middleware (an <audio>/<video> element can't send Authorization headers).
1008
1022
  app.use('/media', cors(), createMediaStreamRouter());
1009
1023
  startupLog.LogIf('verbose', '[Media] Streaming route registered at /media/:fileId');
1024
+ // ─── Realtime WebRTC SDP broker (ticket-gated, registered BEFORE auth) ───────
1025
+ if (configInfo.realtime?.enabled) {
1026
+ app.use(REALTIME_SDP_EXCHANGE_PATH, cors(), createRealtimeSdpBrokerRouter());
1027
+ startupLog.LogIf('verbose', `[Realtime] WebRTC SDP broker registered at ${REALTIME_SDP_EXCHANGE_PATH}`);
1028
+ }
1010
1029
  // ─── Magic-link routes (MJ-issued, app-scoped external access) ───────────
1011
1030
  // Public router (JWKS + redeem) mounts BEFORE the auth middleware; the
1012
1031
  // authenticated invite-creation router mounts AFTER it (see below).
@@ -1038,57 +1057,65 @@ export const serve = async (resolverPaths, app = createApp(), options) => {
1038
1057
  }
1039
1058
  startupLog.LogIf('verbose', `[Widget] Public routes registered at ${WIDGET_MOUNT_PATH}/session and ${WIDGET_MOUNT_PATH}/session/refresh`);
1040
1059
  }
1041
- // ─── Telephony (Twilio) ingress: inbound voice webhook + Media-Streams WSS (PUBLIC) ──
1042
- // Carriers cannot present an MJ JWT — the X-Twilio-Signature HMAC is the gate. The
1043
- // public webhook router mounts BEFORE the auth middleware; the Media-Streams WSS attaches
1044
- // to the shared HTTP server. The outbound PlaceTwilioCall mutation reuses the same service.
1045
- if (configInfo.telephony?.enabled && configInfo.telephony.twilio) {
1046
- const twilioHandler = createTwilioTelephonyHandler(oauthPublicUrl, configInfo.telephony.twilio);
1047
- app.use(TWILIO_TELEPHONY_MOUNT_PATH, cors(), twilioHandler.publicRouter);
1048
- twilioHandler.attachMediaStreamServer();
1049
- SetTwilioTelephonyService(twilioHandler.service);
1050
- startupLog.LogIf('verbose', `[Telephony] Twilio routes registered at ${TWILIO_TELEPHONY_MOUNT_PATH}/voice + Media-Streams WSS`);
1051
- }
1052
- // ─── Telephony (Vonage) ingress: inbound answer/event webhooks + media WSS (PUBLIC) ──
1053
- // Carriers cannot present an MJ JWT — the Vonage signed-request HMAC / webhook JWT is the gate.
1054
- // The public router mounts BEFORE the auth middleware; the media WSS attaches to the shared
1055
- // HTTP server. The outbound PlaceVonageCall mutation reuses the same service.
1056
- if (configInfo.telephony?.enabled && configInfo.telephony.vonage) {
1057
- const vonageHandler = createVonageTelephonyHandler(oauthPublicUrl, configInfo.telephony.vonage);
1058
- app.use(VONAGE_TELEPHONY_MOUNT_PATH, cors(), vonageHandler.publicRouter);
1059
- vonageHandler.attachMediaStreamServer();
1060
- SetVonageTelephonyService(vonageHandler.service);
1061
- startupLog.LogIf('verbose', `[Telephony] Vonage routes registered at ${VONAGE_TELEPHONY_MOUNT_PATH}/answer + /event + media WSS`);
1062
- }
1063
- // ─── Telephony (RingCentral) ingress: SIP softphone registration (no HTTP webhook / media WSS) ──
1064
- // RingCentral's only bidirectional-audio transport is a registered SIP softphone — inbound calls arrive
1065
- // as SIP INVITEs on its own SIP/TLS connection, so there is no public webhook or media WSS to mount.
1066
- // start() registers the softphone fire-and-forget so SIP registration never blocks boot; the outbound
1067
- // PlaceRingCentralCall mutation reuses the same service via the runtime holder.
1068
- if (configInfo.telephony?.enabled && configInfo.telephony.ringcentral) {
1069
- const ringCentralService = new RingCentralTelephonyService(configInfo.telephony.ringcentral);
1070
- SetRingCentralTelephonyService(ringCentralService);
1071
- void ringCentralService.start();
1072
- startupLog.LogIf('verbose', `[Telephony] RingCentral SIP softphone starting (codec ${configInfo.telephony.ringcentral.codec ?? 'OPUS/16000'})`);
1060
+ // ─── Server extensions loader & shared service registry ───────────────────
1061
+ const extensionLoader = new ServerExtensionLoader();
1062
+ _currentExtensionLoader = extensionLoader;
1063
+ // Open App packages publish their extensions; host mj.config.cjs overlays by DriverClass
1064
+ // Backwards-compatibility shim: synthesize ServerExtensionConfig entries from legacy configInfo.telephony
1065
+ const telephonyExtensionConfigs = [];
1066
+ if (configInfo.telephony?.enabled) {
1067
+ if (configInfo.telephony.twilio) {
1068
+ telephonyExtensionConfigs.push({
1069
+ Enabled: true,
1070
+ DriverClass: 'TwilioTelephonyExtension',
1071
+ RootPath: '/telephony/twilio',
1072
+ Phase: 'pre-auth',
1073
+ Settings: configInfo.telephony.twilio,
1074
+ });
1075
+ }
1076
+ if (configInfo.telephony.vonage) {
1077
+ telephonyExtensionConfigs.push({
1078
+ Enabled: true,
1079
+ DriverClass: 'VonageTelephonyExtension',
1080
+ RootPath: '/telephony/vonage',
1081
+ Phase: 'pre-auth',
1082
+ Settings: configInfo.telephony.vonage,
1083
+ });
1084
+ }
1085
+ if (configInfo.telephony.ringcentral) {
1086
+ telephonyExtensionConfigs.push({
1087
+ Enabled: true,
1088
+ DriverClass: 'RingCentralTelephonyExtension',
1089
+ RootPath: '/telephony/ringcentral',
1090
+ Phase: 'pre-auth',
1091
+ Settings: configInfo.telephony.ringcentral,
1092
+ });
1093
+ }
1094
+ if (configInfo.telephony.teams?.enabled) {
1095
+ telephonyExtensionConfigs.push({
1096
+ Enabled: true,
1097
+ DriverClass: 'TeamsMeetingsExtension',
1098
+ RootPath: '/meetings/teams',
1099
+ Phase: 'pre-auth',
1100
+ Settings: configInfo.telephony.teams,
1101
+ });
1102
+ }
1073
1103
  }
1074
- // ─── Teams meetings ingress: Graph change-notification webhook (PUBLIC) ──────────────
1075
- // Graph cannot present an MJ JWT — the subscription validationToken handshake + the per-
1076
- // notification clientState shared secret are the gate. The public webhook router mounts
1077
- // BEFORE the auth middleware. The ACS application-hosted-media audio plane is owned by the
1078
- // server's native ACS media adapter, which attaches transports to the shared registry
1079
- // (a media WSS is not needed here). The StartTeamsMeetingSession mutation reuses the same
1080
- // service via the runtime holder.
1081
- if (configInfo.telephony?.enabled && configInfo.telephony.teams?.enabled) {
1082
- const teamsHandler = createTeamsMeetingsHandler(configInfo.telephony.teams);
1083
- app.use(TEAMS_MEETINGS_MOUNT_PATH, cors(), teamsHandler.publicRouter);
1084
- SetTeamsMeetingsService(teamsHandler.service);
1085
- startupLog.LogIf('verbose', `[Meetings] Teams routes registered at ${TEAMS_MEETINGS_MOUNT_PATH}/notifications`);
1104
+ const rawHostExtensions = (configInfo.serverExtensions ?? []);
1105
+ const mergedHostExtensions = mergeServerExtensionConfigs(telephonyExtensionConfigs, rawHostExtensions);
1106
+ // Open App packages publish their extensions; host mj.config.cjs overlays by DriverClass
1107
+ // (and remains the only source for host-only extensions such as Slack/Teams).
1108
+ // extraReservedRoots is derived from the mounts registered above plus graphqlRootPath
1109
+ // so a new pre-auth app.use(...) in serve() must also be added to
1110
+ // coreReservedServerExtensionRoots() — otherwise an Open App can claim it.
1111
+ const extensionConfigs = prepareServerExtensionConfigs(mergeServerExtensionConfigs(options?.serverExtensions ?? [], mergedHostExtensions), {
1112
+ onInvalid: (message) => LogError(message),
1113
+ onOverlap: (message) => LogStatus(message),
1114
+ extraReservedRoots: coreReservedServerExtensionRoots(graphqlRootPath),
1115
+ });
1116
+ for (const cfg of extensionConfigs) {
1117
+ LogStatus(`Server extension ${describeServerExtensionMount(cfg)}`);
1086
1118
  }
1087
- // Install the single path-routing WebSocket-upgrade dispatcher AFTER all media WSS routes have
1088
- // registered. ws 8.x has each {server}-bound WebSocketServer 400 paths it doesn't own, so the GraphQL
1089
- // socket and the telephony media sockets cannot coexist as separate {server} servers — this strips the
1090
- // auto-listeners and routes upgrades by path. No-op when no media routes registered (telephony off).
1091
- InstallMediaUpgradeDispatcher(httpServer, webSocketServer, graphqlRootPath);
1092
1119
  // ─── Global CORS (before auth so 401 responses include CORS headers) ─────
1093
1120
  // Without this, the browser blocks 401 responses from the auth middleware
1094
1121
  // because they lack Access-Control-Allow-Origin headers, preventing the
@@ -1115,29 +1142,16 @@ export const serve = async (resolverPaths, app = createApp(), options) => {
1115
1142
  credentials: corsWildcard ? false : (configInfo.cors?.allowCredentials ?? true),
1116
1143
  maxAge: configInfo.cors?.maxAge ?? 86400,
1117
1144
  }));
1118
- // ─── Server extensions (before auth — extensions handle their own auth) ─────
1145
+ // ─── Pre-auth server extensions (before auth — extensions handle their own auth) ─────
1119
1146
  // Slack uses HMAC signature verification, Teams uses Bot Framework JWT validation.
1120
1147
  // These must be registered before the unified auth middleware so webhook
1121
1148
  // requests aren't rejected for lacking an MJ bearer token.
1122
- const extensionLoader = new ServerExtensionLoader();
1123
- // Open App packages publish their extensions; host mj.config.cjs overlays by DriverClass
1124
- // (and remains the only source for host-only extensions such as Slack/Teams).
1125
- // extraReservedRoots is derived from the mounts registered above plus graphqlRootPath
1126
- // so a new pre-auth app.use(...) in serve() must also be added to
1127
- // coreReservedServerExtensionRoots() — otherwise an Open App can claim it.
1128
- const extensionConfigs = prepareServerExtensionConfigs(mergeServerExtensionConfigs(options?.serverExtensions ?? [], (configInfo.serverExtensions ?? [])), {
1129
- onInvalid: (message) => LogError(message),
1130
- onOverlap: (message) => LogStatus(message),
1131
- extraReservedRoots: coreReservedServerExtensionRoots(graphqlRootPath),
1132
- });
1133
- // These routes mount BEFORE createUnifiedAuthMiddleware. Name every one so an
1134
- // operator who installed an Open App for its entities can see the pre-auth HTTP
1135
- // surface and suppress it with host serverExtensions[].Enabled = false.
1136
- for (const cfg of extensionConfigs) {
1137
- LogStatus(`Server extension ${describeServerExtensionMount(cfg)}`);
1138
- }
1139
1149
  if (extensionConfigs.length > 0) {
1140
- await extensionLoader.LoadExtensions(app, extensionConfigs);
1150
+ await extensionLoader.LoadExtensions(app, extensionConfigs, {
1151
+ phase: 'pre-auth',
1152
+ httpServer,
1153
+ publicUrl: oauthPublicUrl,
1154
+ });
1141
1155
  }
1142
1156
  // Extension health endpoint (always available, returns empty array if no extensions)
1143
1157
  app.get('/health/extensions', async (_req, res) => {
@@ -1179,6 +1193,31 @@ export const serve = async (resolverPaths, app = createApp(), options) => {
1179
1193
  app.use(WIDGET_MOUNT_PATH, cors(), widgetAuthenticatedRouter);
1180
1194
  startupLog.LogIf('verbose', `[Widget] Authenticated route registered at ${WIDGET_MOUNT_PATH}/resolve-identity`);
1181
1195
  }
1196
+ // ─── Post-auth server extensions ──────────────────────────────────────────
1197
+ // Extensions declaring Phase: 'post-auth' mount after the unified auth middleware
1198
+ // and are protected by JWT authentication by default.
1199
+ if (extensionConfigs.length > 0) {
1200
+ await extensionLoader.LoadExtensions(app, extensionConfigs, {
1201
+ phase: 'post-auth',
1202
+ httpServer,
1203
+ publicUrl: oauthPublicUrl,
1204
+ });
1205
+ }
1206
+ // ─── Cross-extension lifecycle hook: OnAllExtensionsMounted ───────────────
1207
+ // Called after all extensions across both pre-auth and post-auth phases are mounted.
1208
+ // Extensions can wire themselves to services registered by other extensions or core.
1209
+ await extensionLoader.NotifyAllExtensionsMounted({
1210
+ httpServer,
1211
+ publicUrl: oauthPublicUrl,
1212
+ });
1213
+ // Install the single path-routing WebSocket-upgrade dispatcher AFTER all extensions across both
1214
+ // pre-auth and post-auth phases have mounted and registered their media WSS routes. ws 8.x has each
1215
+ // {server}-bound WebSocketServer 400 paths it doesn't own, so the GraphQL socket and the telephony
1216
+ // media sockets cannot coexist as separate {server} servers — this strips the auto-listeners and
1217
+ // routes upgrades by path. No-op when no media routes registered (telephony off).
1218
+ InstallMediaUpgradeDispatcher(httpServer, webSocketServer, graphqlRootPath, (req, socket, head) => {
1219
+ return RealtimeProxyServer.Instance.TryHandleUpgrade(req, socket, head);
1220
+ });
1182
1221
  // ─── REST API endpoints (auth already handled by unified middleware) ─────
1183
1222
  const restApiConfig = {
1184
1223
  enabled: configInfo.restApiOptions?.enabled ?? false,
@@ -1324,22 +1363,6 @@ export const serve = async (resolverPaths, app = createApp(), options) => {
1324
1363
  StartTaskGraphDispatcher(taskGraphPool, resumeUser)
1325
1364
  .catch(err => console.warn(`[TaskGraphDispatcher] Startup failed: ${err}`));
1326
1365
  }
1327
- // Launch the calendar / scheduled-bridge loop (M2): poll agent calendars for meeting invites and
1328
- // start due meeting bridges. Mirrors the SessionJanitor lifecycle (run-once + interval, timer
1329
- // unref'd). Gated on Teams meetings being enabled (the provider whose scheduled-join is wired) and
1330
- // reuses the SAME meetings service as the ingress; identities without configured calendar creds are
1331
- // skipped, so this is a harmless no-op until a Graph-backed identity + token are configured.
1332
- if (resumeUser && configInfo.telephony?.teams?.enabled) { // global-provider-ok: server-owned background poller under the server's provider + system user
1333
- const teamsMeetingsService = GetTeamsMeetingsService();
1334
- if (teamsMeetingsService) {
1335
- StartCalendarScheduler({
1336
- Provider: Metadata.Provider, // global-provider-ok: server-owned background poller under the server's single default provider + system user
1337
- ContextUser: resumeUser,
1338
- TeamsService: teamsMeetingsService,
1339
- TeamsConfig: configInfo.telephony.teams,
1340
- });
1341
- }
1342
- }
1343
1366
  // Set up graceful shutdown handlers
1344
1367
  const gracefulShutdown = async (signal) => {
1345
1368
  console.log(`\n${signal} received, shutting down gracefully...`);
@@ -1347,6 +1370,7 @@ export const serve = async (resolverPaths, app = createApp(), options) => {
1347
1370
  if (extensionLoader.ExtensionCount > 0) {
1348
1371
  try {
1349
1372
  await extensionLoader.ShutdownAll();
1373
+ _currentExtensionLoader = null;
1350
1374
  console.log('✅ Server extensions shut down');
1351
1375
  }
1352
1376
  catch (error) {