@reventlessdev/reventless-core 3.0.0-alpha.134

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 (502) hide show
  1. package/CHANGELOG.md +1355 -0
  2. package/LICENSE +202 -0
  3. package/README.md +173 -0
  4. package/__mocks__/emptyModule.js +2 -0
  5. package/jest.setup.cjs +5 -0
  6. package/package.json +73 -0
  7. package/rescript.json +41 -0
  8. package/scripts/deploy.sh +6 -0
  9. package/scripts/post-deploy.sh +5 -0
  10. package/scripts/pre-deploy.sh +18 -0
  11. package/scripts/pulumi-up.sh +30 -0
  12. package/src/Behavior.res +18 -0
  13. package/src/Behavior.res.mjs +2 -0
  14. package/src/ComponentType.res +125 -0
  15. package/src/ComponentType.res.mjs +199 -0
  16. package/src/Env.res +5 -0
  17. package/src/Env.res.mjs +2 -0
  18. package/src/Mapper.res +36 -0
  19. package/src/Mapper.res.mjs +18 -0
  20. package/src/Mapper1toN.res +107 -0
  21. package/src/Mapper1toN.res.mjs +2 -0
  22. package/src/MapperNto1.res +78 -0
  23. package/src/MapperNto1.res.mjs +35 -0
  24. package/src/Message.res +353 -0
  25. package/src/Message.res.mjs +418 -0
  26. package/src/PluginRuntimeOperations.res +15 -0
  27. package/src/PluginRuntimeOperations.res.mjs +2 -0
  28. package/src/Projection.res +447 -0
  29. package/src/Projection.res.mjs +712 -0
  30. package/src/ProjectionMapper.res +44 -0
  31. package/src/ProjectionMapper.res.mjs +51 -0
  32. package/src/RequestContext.res +42 -0
  33. package/src/RequestContext.res.mjs +39 -0
  34. package/src/adapter/Adapter.res +178 -0
  35. package/src/adapter/Adapter.res.mjs +201 -0
  36. package/src/adapter/AdapterDeploytime.res +56 -0
  37. package/src/adapter/AdapterDeploytime.res.mjs +42 -0
  38. package/src/adapter/Auth/Auth_Adapter.res +42 -0
  39. package/src/adapter/Auth/Auth_Adapter.res.mjs +2 -0
  40. package/src/adapter/Runtime/AggregateRuntime_Builder.res +22 -0
  41. package/src/adapter/Runtime/AggregateRuntime_Builder.res.mjs +2 -0
  42. package/src/adapter/Runtime/AggregateRuntime_Builder_Common.res +259 -0
  43. package/src/adapter/Runtime/AggregateRuntime_Builder_Common.res.mjs +190 -0
  44. package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res +92 -0
  45. package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res.mjs +59 -0
  46. package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate.res +52 -0
  47. package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate.res.mjs +49 -0
  48. package/src/adapter/Runtime/AggregateRuntime_Builder_Single.res +64 -0
  49. package/src/adapter/Runtime/AggregateRuntime_Builder_Single.res.mjs +59 -0
  50. package/src/adapter/Runtime/EventCollectorRuntime_Builder.res +11 -0
  51. package/src/adapter/Runtime/EventCollectorRuntime_Builder.res.mjs +2 -0
  52. package/src/adapter/Runtime/EventCollectorRuntime_Builder_PerEventCollector.res +46 -0
  53. package/src/adapter/Runtime/EventCollectorRuntime_Builder_PerEventCollector.res.mjs +40 -0
  54. package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res +204 -0
  55. package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res.mjs +150 -0
  56. package/src/adapter/Runtime/ExtensionPointRuntime_Builder.res +18 -0
  57. package/src/adapter/Runtime/ExtensionPointRuntime_Builder.res.mjs +2 -0
  58. package/src/adapter/Runtime/ExtensionPointRuntime_Builder_PerExtensionPoint.res +36 -0
  59. package/src/adapter/Runtime/ExtensionPointRuntime_Builder_PerExtensionPoint.res.mjs +28 -0
  60. package/src/adapter/Runtime/PluginRuntime_Builder.res +23 -0
  61. package/src/adapter/Runtime/PluginRuntime_Builder.res.mjs +2 -0
  62. package/src/adapter/Runtime/PluginRuntime_Builder_Micro.res +97 -0
  63. package/src/adapter/Runtime/PluginRuntime_Builder_Micro.res.mjs +62 -0
  64. package/src/adapter/Runtime/PluginRuntime_Builder_Single.res +89 -0
  65. package/src/adapter/Runtime/PluginRuntime_Builder_Single.res.mjs +62 -0
  66. package/src/adapter/Runtime/Runtime.res +106 -0
  67. package/src/adapter/Runtime/Runtime.res.mjs +22 -0
  68. package/src/adapter/Runtime/TaskRuntime_Builder.res +32 -0
  69. package/src/adapter/Runtime/TaskRuntime_Builder.res.mjs +2 -0
  70. package/src/adapter/Runtime/TaskRuntime_Builder_PerBucket.res +42 -0
  71. package/src/adapter/Runtime/TaskRuntime_Builder_PerBucket.res.mjs +29 -0
  72. package/src/admin/AdminApi.res +88 -0
  73. package/src/admin/AdminApi.res.mjs +89 -0
  74. package/src/admin/Admin_Callback.res +27 -0
  75. package/src/admin/Admin_Callback.res.mjs +20 -0
  76. package/src/admin/Platform_Admin.res +402 -0
  77. package/src/admin/Platform_Admin.res.mjs +250 -0
  78. package/src/admin/Platform_Admin_Structure.res +125 -0
  79. package/src/admin/Platform_Admin_Structure.res.mjs +182 -0
  80. package/src/admin/Platform_ComponentDefinitionsApi.res +160 -0
  81. package/src/admin/Platform_ComponentDefinitionsApi.res.mjs +299 -0
  82. package/src/admin/Platform_UIFragmentsApi.res +55 -0
  83. package/src/admin/Platform_UIFragmentsApi.res.mjs +124 -0
  84. package/src/admin/UIFragmentRegistryProjection.res +43 -0
  85. package/src/admin/UIFragmentRegistryProjection.res.mjs +81 -0
  86. package/src/admin/UIFragmentRegistryReadModelSpec.res +13 -0
  87. package/src/admin/UIFragmentRegistryReadModelSpec.res.mjs +40 -0
  88. package/src/components/Aggregate/Aggregate.res +96 -0
  89. package/src/components/Aggregate/Aggregate.res.mjs +82 -0
  90. package/src/components/Aggregate/Aggregate_Builder.res +175 -0
  91. package/src/components/Aggregate/Aggregate_Builder.res.mjs +119 -0
  92. package/src/components/Aggregate/Aggregate_Callback.res +273 -0
  93. package/src/components/Aggregate/Aggregate_Callback.res.mjs +208 -0
  94. package/src/components/Api/ApiAllowedStatesHelpers.res +19 -0
  95. package/src/components/Api/ApiAllowedStatesHelpers.res.mjs +16 -0
  96. package/src/components/Api/ApiNoApiHelpers.res +13 -0
  97. package/src/components/Api/ApiNoApiHelpers.res.mjs +29 -0
  98. package/src/components/Api/Api_Builder.res +40 -0
  99. package/src/components/Api/Api_Builder.res.mjs +33 -0
  100. package/src/components/Api/Api_Naming.res +92 -0
  101. package/src/components/Api/Api_Naming.res.mjs +103 -0
  102. package/src/components/Api/Api_Operations.res +13 -0
  103. package/src/components/Api/Api_Operations.res.mjs +12 -0
  104. package/src/components/Api/GraphQL_FragmentGenerator.res +612 -0
  105. package/src/components/Api/GraphQL_FragmentGenerator.res.mjs +503 -0
  106. package/src/components/Api/GraphQL_SchemaInspector.res +156 -0
  107. package/src/components/Api/GraphQL_SchemaInspector.res.mjs +123 -0
  108. package/src/components/Api/GraphQL_Stitcher.res +271 -0
  109. package/src/components/Api/GraphQL_Stitcher.res.mjs +229 -0
  110. package/src/components/Api/MCP_SchemaGenerator.res +185 -0
  111. package/src/components/Api/MCP_SchemaGenerator.res.mjs +146 -0
  112. package/src/components/Api/SchemaType.res +126 -0
  113. package/src/components/Api/SchemaType.res.mjs +143 -0
  114. package/src/components/Api/SuryToJsonSchema.res +142 -0
  115. package/src/components/Api/SuryToJsonSchema.res.mjs +210 -0
  116. package/src/components/AutomationSlice/AutomationSlice.res +39 -0
  117. package/src/components/AutomationSlice/AutomationSlice.res.mjs +24 -0
  118. package/src/components/AutomationSlice/AutomationSlice_Builder.res +207 -0
  119. package/src/components/AutomationSlice/AutomationSlice_Builder.res.mjs +123 -0
  120. package/src/components/AutomationSlice/AutomationSlice_Callback.res +212 -0
  121. package/src/components/AutomationSlice/AutomationSlice_Callback.res.mjs +189 -0
  122. package/src/components/Builder_Helpers.res +196 -0
  123. package/src/components/Builder_Helpers.res.mjs +142 -0
  124. package/src/components/Cloner.res +84 -0
  125. package/src/components/Cloner.res.mjs +88 -0
  126. package/src/components/CommandGenerator/CommandGenerator.res +54 -0
  127. package/src/components/CommandGenerator/CommandGenerator.res.mjs +15 -0
  128. package/src/components/CommandGenerator/CommandGenerator_Adapter.res +22 -0
  129. package/src/components/CommandGenerator/CommandGenerator_Adapter.res.mjs +2 -0
  130. package/src/components/CommandGenerator/CommandGenerator_Builder.res +70 -0
  131. package/src/components/CommandGenerator/CommandGenerator_Builder.res.mjs +68 -0
  132. package/src/components/CommandGenerator/CommandGenerator_Callback.res +191 -0
  133. package/src/components/CommandGenerator/CommandGenerator_Callback.res.mjs +161 -0
  134. package/src/components/CommandTopic/CommandTopic.res +79 -0
  135. package/src/components/CommandTopic/CommandTopic.res.mjs +68 -0
  136. package/src/components/CommandTopic/CommandTopic_Adapter.res +53 -0
  137. package/src/components/CommandTopic/CommandTopic_Adapter.res.mjs +2 -0
  138. package/src/components/CommandTopic/CommandTopic_Builder.res +146 -0
  139. package/src/components/CommandTopic/CommandTopic_Builder.res.mjs +127 -0
  140. package/src/components/CommandTopic/CommandTopic_Callback.res +38 -0
  141. package/src/components/CommandTopic/CommandTopic_Callback.res.mjs +49 -0
  142. package/src/components/CommandTopic/CommandTopic_Helpers.res +176 -0
  143. package/src/components/CommandTopic/CommandTopic_Helpers.res.mjs +195 -0
  144. package/src/components/CommandTopic/CommandTopic_Operations.res +40 -0
  145. package/src/components/CommandTopic/CommandTopic_Operations.res.mjs +49 -0
  146. package/src/components/Component.res +1 -0
  147. package/src/components/Component.res.mjs +34 -0
  148. package/src/components/Component.resi +1 -0
  149. package/src/components/Counter/Counter.res +47 -0
  150. package/src/components/Counter/Counter.res.mjs +55 -0
  151. package/src/components/Counter/Counter_Adapter.res +18 -0
  152. package/src/components/Counter/Counter_Adapter.res.mjs +2 -0
  153. package/src/components/Counter/Counter_Builder.res +142 -0
  154. package/src/components/Counter/Counter_Builder.res.mjs +112 -0
  155. package/src/components/Counter/Counter_Callback.res +94 -0
  156. package/src/components/Counter/Counter_Callback.res.mjs +70 -0
  157. package/src/components/Counter/Counter_Operations.res +70 -0
  158. package/src/components/Counter/Counter_Operations.res.mjs +91 -0
  159. package/src/components/Dcb/Dcb_Builder.res +971 -0
  160. package/src/components/Dcb/Dcb_Builder.res.mjs +572 -0
  161. package/src/components/DcbEventLog/DcbEventLog.res +43 -0
  162. package/src/components/DcbEventLog/DcbEventLog.res.mjs +24 -0
  163. package/src/components/DcbEventLog/DcbEventLog_Adapter.res +57 -0
  164. package/src/components/DcbEventLog/DcbEventLog_Adapter.res.mjs +2 -0
  165. package/src/components/DcbEventLog/DcbEventLog_Builder.res +72 -0
  166. package/src/components/DcbEventLog/DcbEventLog_Builder.res.mjs +67 -0
  167. package/src/components/DcbEventLog/DcbEventLog_Operations.res +160 -0
  168. package/src/components/DcbEventLog/DcbEventLog_Operations.res.mjs +121 -0
  169. package/src/components/EventCollector/EventCollector.res +34 -0
  170. package/src/components/EventCollector/EventCollector.res.mjs +9 -0
  171. package/src/components/EventCollector/EventCollector_Adapter.res +45 -0
  172. package/src/components/EventCollector/EventCollector_Adapter.res.mjs +2 -0
  173. package/src/components/EventCollector/EventCollector_Builder.res +91 -0
  174. package/src/components/EventCollector/EventCollector_Builder.res.mjs +64 -0
  175. package/src/components/EventLog/EventLog.res +27 -0
  176. package/src/components/EventLog/EventLog.res.mjs +13 -0
  177. package/src/components/EventLog/EventLog_Adapter.res +15 -0
  178. package/src/components/EventLog/EventLog_Adapter.res.mjs +2 -0
  179. package/src/components/EventLog/EventLog_Builder.res +65 -0
  180. package/src/components/EventLog/EventLog_Builder.res.mjs +57 -0
  181. package/src/components/EventLog/EventLog_Operations.res +209 -0
  182. package/src/components/EventLog/EventLog_Operations.res.mjs +202 -0
  183. package/src/components/EventLog/EventPublish_Callback.res +29 -0
  184. package/src/components/EventLog/EventPublish_Callback.res.mjs +32 -0
  185. package/src/components/EventMapper/EventMapper.res +72 -0
  186. package/src/components/EventMapper/EventMapper.res.mjs +54 -0
  187. package/src/components/EventMapper/EventMapper_Builder.res +128 -0
  188. package/src/components/EventMapper/EventMapper_Builder.res.mjs +81 -0
  189. package/src/components/EventMapper/EventMapper_Callback.res +323 -0
  190. package/src/components/EventMapper/EventMapper_Callback.res.mjs +231 -0
  191. package/src/components/EventTopic/EventTopic.res +69 -0
  192. package/src/components/EventTopic/EventTopic.res.mjs +50 -0
  193. package/src/components/EventTopic/EventTopic_Adapter.res +15 -0
  194. package/src/components/EventTopic/EventTopic_Adapter.res.mjs +2 -0
  195. package/src/components/EventTopic/EventTopic_Builder.res +53 -0
  196. package/src/components/EventTopic/EventTopic_Builder.res.mjs +46 -0
  197. package/src/components/EventTopic/EventTopic_Operations.res +37 -0
  198. package/src/components/EventTopic/EventTopic_Operations.res.mjs +39 -0
  199. package/src/components/Extension/Extension.res +32 -0
  200. package/src/components/Extension/Extension.res.mjs +9 -0
  201. package/src/components/Extension/Extension_Builder.res +82 -0
  202. package/src/components/Extension/Extension_Builder.res.mjs +57 -0
  203. package/src/components/Extension/Extension_Operations.res +203 -0
  204. package/src/components/Extension/Extension_Operations.res.mjs +154 -0
  205. package/src/components/ExtensionPoint/ExtensionPoint.res +49 -0
  206. package/src/components/ExtensionPoint/ExtensionPoint.res.mjs +25 -0
  207. package/src/components/ExtensionPoint/ExtensionPoint_Builder.res +163 -0
  208. package/src/components/ExtensionPoint/ExtensionPoint_Builder.res.mjs +113 -0
  209. package/src/components/ExtensionPoint/ExtensionPoint_Callback.res +110 -0
  210. package/src/components/ExtensionPoint/ExtensionPoint_Callback.res.mjs +76 -0
  211. package/src/components/ExtensionPoint/ExtensionPoint_Operations.res +146 -0
  212. package/src/components/ExtensionPoint/ExtensionPoint_Operations.res.mjs +122 -0
  213. package/src/components/Heartbeat/Heartbeat.res +25 -0
  214. package/src/components/Heartbeat/Heartbeat.res.mjs +9 -0
  215. package/src/components/Heartbeat/Heartbeat_Adapter.res +14 -0
  216. package/src/components/Heartbeat/Heartbeat_Adapter.res.mjs +2 -0
  217. package/src/components/Heartbeat/Heartbeat_Builder.res +43 -0
  218. package/src/components/Heartbeat/Heartbeat_Builder.res.mjs +47 -0
  219. package/src/components/Heartbeat/Heartbeat_Callback.res +32 -0
  220. package/src/components/Heartbeat/Heartbeat_Callback.res.mjs +40 -0
  221. package/src/components/InboundTranslationSlice/InboundTranslationSlice.res +34 -0
  222. package/src/components/InboundTranslationSlice/InboundTranslationSlice.res.mjs +24 -0
  223. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res +98 -0
  224. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res.mjs +87 -0
  225. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Callback.res +191 -0
  226. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Callback.res.mjs +175 -0
  227. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice.res +35 -0
  228. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice.res.mjs +24 -0
  229. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res +181 -0
  230. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res.mjs +137 -0
  231. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Callback.res +173 -0
  232. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Callback.res.mjs +173 -0
  233. package/src/components/QueryDb/QueryDb.res +74 -0
  234. package/src/components/QueryDb/QueryDb.res.mjs +37 -0
  235. package/src/components/QueryDb/QueryDb_Adapter.res +78 -0
  236. package/src/components/QueryDb/QueryDb_Adapter.res.mjs +17 -0
  237. package/src/components/QueryDb/QueryDb_Builder.res +76 -0
  238. package/src/components/QueryDb/QueryDb_Builder.res.mjs +53 -0
  239. package/src/components/QueryDb/QueryDb_Callback.res +18 -0
  240. package/src/components/QueryDb/QueryDb_Callback.res.mjs +21 -0
  241. package/src/components/QueryDb/QueryDb_Operations.res +116 -0
  242. package/src/components/QueryDb/QueryDb_Operations.res.mjs +165 -0
  243. package/src/components/ReadModel/ReadModel.res +42 -0
  244. package/src/components/ReadModel/ReadModel.res.mjs +27 -0
  245. package/src/components/ReadModel/ReadModel_Builder.res +155 -0
  246. package/src/components/ReadModel/ReadModel_Builder.res.mjs +101 -0
  247. package/src/components/ReadModel/ReadModel_Callback.res +48 -0
  248. package/src/components/ReadModel/ReadModel_Callback.res.mjs +48 -0
  249. package/src/components/Scheduler/Scheduler.res +13 -0
  250. package/src/components/Scheduler/Scheduler.res.mjs +9 -0
  251. package/src/components/Scheduler/Scheduler_Adapter.res +13 -0
  252. package/src/components/Scheduler/Scheduler_Adapter.res.mjs +2 -0
  253. package/src/components/Scheduler/Scheduler_Builder.res +19 -0
  254. package/src/components/Scheduler/Scheduler_Builder.res.mjs +29 -0
  255. package/src/components/SideEffectHandler/SideEffectHandler.res +30 -0
  256. package/src/components/SideEffectHandler/SideEffectHandler.res.mjs +12 -0
  257. package/src/components/SideEffectHandler/SideEffectHandler_Builder.res +117 -0
  258. package/src/components/SideEffectHandler/SideEffectHandler_Builder.res.mjs +64 -0
  259. package/src/components/SideEffectHandler/SideEffectHandler_Callback.res +116 -0
  260. package/src/components/SideEffectHandler/SideEffectHandler_Callback.res.mjs +95 -0
  261. package/src/components/StateChangeSlice/StateChangeSlice.res +38 -0
  262. package/src/components/StateChangeSlice/StateChangeSlice.res.mjs +17 -0
  263. package/src/components/StateChangeSlice/StateChangeSlice_Builder.res +91 -0
  264. package/src/components/StateChangeSlice/StateChangeSlice_Builder.res.mjs +81 -0
  265. package/src/components/StateChangeSlice/StateChangeSlice_Callback.res +412 -0
  266. package/src/components/StateChangeSlice/StateChangeSlice_Callback.res.mjs +299 -0
  267. package/src/components/StateTopic.res +91 -0
  268. package/src/components/StateTopic.res.mjs +41 -0
  269. package/src/components/StateViewSlice/StateViewSlice.res +33 -0
  270. package/src/components/StateViewSlice/StateViewSlice.res.mjs +24 -0
  271. package/src/components/StateViewSlice/StateViewSlice_Builder.res +176 -0
  272. package/src/components/StateViewSlice/StateViewSlice_Builder.res.mjs +134 -0
  273. package/src/components/StateViewSlice/StateViewSlice_Callback.res +64 -0
  274. package/src/components/StateViewSlice/StateViewSlice_Callback.res.mjs +56 -0
  275. package/src/components/Task/Task.res +81 -0
  276. package/src/components/Task/Task.res.mjs +51 -0
  277. package/src/components/Task/Task_Adapter.res +31 -0
  278. package/src/components/Task/Task_Adapter.res.mjs +2 -0
  279. package/src/components/Task/Task_Builder.res +223 -0
  280. package/src/components/Task/Task_Builder.res.mjs +115 -0
  281. package/src/plugin/api/PluginBaseFragment.res +104 -0
  282. package/src/plugin/api/PluginBaseFragment.res.mjs +64 -0
  283. package/src/plugin/component/Plugin.res +100 -0
  284. package/src/plugin/component/Plugin.res.mjs +61 -0
  285. package/src/plugin/component/Plugin_Builder.res +1017 -0
  286. package/src/plugin/component/Plugin_Builder.res.mjs +608 -0
  287. package/src/plugin/component/Plugin_BuiltHook.res +141 -0
  288. package/src/plugin/component/Plugin_BuiltHook.res.mjs +39 -0
  289. package/src/plugin/component/Plugin_Callback.res +98 -0
  290. package/src/plugin/component/Plugin_Callback.res.mjs +55 -0
  291. package/src/plugin/component/Plugin_Helpers.res +1730 -0
  292. package/src/plugin/component/Plugin_Helpers.res.mjs +1010 -0
  293. package/src/plugin/component/Plugin_ResolverError.res +27 -0
  294. package/src/plugin/component/Plugin_ResolverError.res.mjs +21 -0
  295. package/src/plugin/component/Plugin_Structure.res +570 -0
  296. package/src/plugin/component/Plugin_Structure.res.mjs +458 -0
  297. package/src/plugin/component/Plugin_SubscriptionSchema.res +103 -0
  298. package/src/plugin/component/Plugin_SubscriptionSchema.res.mjs +71 -0
  299. package/src/plugin/component/SchemaWalker.res +164 -0
  300. package/src/plugin/component/SchemaWalker.res.mjs +183 -0
  301. package/src/plugin/connect/PluginConnectExtension_Builder.res +14 -0
  302. package/src/plugin/connect/PluginConnectExtension_Builder.res.mjs +36 -0
  303. package/src/plugin/connect/PluginConnectExtension_Mapping.res +76 -0
  304. package/src/plugin/connect/PluginConnectExtension_Mapping.res.mjs +89 -0
  305. package/src/plugin/connect/PluginExtensionPoint_Builder.res +39 -0
  306. package/src/plugin/connect/PluginExtensionPoint_Builder.res.mjs +33 -0
  307. package/src/plugin/connect/PluginExtensionPoint_Plugin.res +231 -0
  308. package/src/plugin/connect/PluginExtensionPoint_Plugin.res.mjs +353 -0
  309. package/src/plugin/lifecycle/PluginBehavior.res +250 -0
  310. package/src/plugin/lifecycle/PluginBehavior.res.mjs +391 -0
  311. package/src/plugin/lifecycle/PluginSpec.res +84 -0
  312. package/src/plugin/lifecycle/PluginSpec.res.mjs +148 -0
  313. package/src/plugin/lifecycle/PluginsProjection.res +154 -0
  314. package/src/plugin/lifecycle/PluginsProjection.res.mjs +230 -0
  315. package/src/plugin/lifecycle/PluginsReadModelSpec.res +66 -0
  316. package/src/plugin/lifecycle/PluginsReadModelSpec.res.mjs +58 -0
  317. package/src/util/AWS.res +7 -0
  318. package/src/util/AWS.res.mjs +20 -0
  319. package/src/util/CSV.res +27 -0
  320. package/src/util/CSV.res.mjs +56 -0
  321. package/src/util/CommandPublisher.res +133 -0
  322. package/src/util/CommandPublisher.res.mjs +161 -0
  323. package/src/util/CsvStream.res +39 -0
  324. package/src/util/CsvStream.res.mjs +42 -0
  325. package/src/util/EffectLogger.res +178 -0
  326. package/src/util/EffectLogger.res.mjs +171 -0
  327. package/src/util/FTP.res +69 -0
  328. package/src/util/FTP.res.mjs +101 -0
  329. package/src/util/FTPHandler.res +142 -0
  330. package/src/util/FTPHandler.res.mjs +136 -0
  331. package/src/util/Hash.res +1 -0
  332. package/src/util/Hash.res.mjs +10 -0
  333. package/src/util/Interstack.res +74 -0
  334. package/src/util/Interstack.res.mjs +126 -0
  335. package/src/util/Interstack.resi +25 -0
  336. package/src/util/LogFormat.res +222 -0
  337. package/src/util/LogFormat.res.mjs +257 -0
  338. package/src/util/Logger.res +196 -0
  339. package/src/util/Logger.res.mjs +238 -0
  340. package/src/util/Lru.res +51 -0
  341. package/src/util/Lru.res.mjs +59 -0
  342. package/src/util/Lru.resi +32 -0
  343. package/src/util/Metrics.res +32 -0
  344. package/src/util/Metrics.res.mjs +42 -0
  345. package/src/util/OutputFailsafeDeploytime.res +16 -0
  346. package/src/util/OutputFailsafeDeploytime.res.mjs +20 -0
  347. package/src/util/OutputFailsafeRuntime.res +6 -0
  348. package/src/util/OutputFailsafeRuntime.res.mjs +15 -0
  349. package/src/util/OutputLogger.res +9 -0
  350. package/src/util/OutputLogger.res.mjs +19 -0
  351. package/src/util/ResourceQuery.res +14 -0
  352. package/src/util/ResourceQuery.res.mjs +17 -0
  353. package/src/util/ResourceQueryRuntime.res +17 -0
  354. package/src/util/ResourceQueryRuntime.res.mjs +18 -0
  355. package/src/util/ScheduleOps.res +124 -0
  356. package/src/util/ScheduleOps.res.mjs +132 -0
  357. package/src/util/Util.res +12 -0
  358. package/src/util/Util.res.mjs +42 -0
  359. package/src/util/Util_Adapter.res +97 -0
  360. package/src/util/Util_Adapter.res.mjs +82 -0
  361. package/src/util/Util_AdapterRuntime.res +39 -0
  362. package/src/util/Util_AdapterRuntime.res.mjs +42 -0
  363. package/src/util/Util_Array.res +2 -0
  364. package/src/util/Util_Array.res.mjs +12 -0
  365. package/src/util/Util_Error.res +16 -0
  366. package/src/util/Util_Error.res.mjs +19 -0
  367. package/src/util/Util_Promise.res +67 -0
  368. package/src/util/Util_Promise.res.mjs +105 -0
  369. package/src/util/Util_Pulumi.res +35 -0
  370. package/src/util/Util_Pulumi.res.mjs +55 -0
  371. package/src/util/Util_Pulumi.resi +21 -0
  372. package/src/util/Util_QueryDb.res +14 -0
  373. package/src/util/Util_QueryDb.res.mjs +21 -0
  374. package/src/util/Util_QueryDbRuntime.res +11 -0
  375. package/src/util/Util_QueryDbRuntime.res.mjs +19 -0
  376. package/src/util/Util_ReadModel.res +2 -0
  377. package/src/util/Util_ReadModel.res.mjs +10 -0
  378. package/src/util/Util_StackRefs.res +24 -0
  379. package/src/util/Util_StackRefs.res.mjs +39 -0
  380. package/src/util/Validation.res +75 -0
  381. package/src/util/Validation.res.mjs +181 -0
  382. package/tests/.gitkeep +0 -0
  383. package/tests/IdentityTest.res +155 -0
  384. package/tests/IdentityTest.res.mjs +174 -0
  385. package/tests/admin/Platform_ComponentDefinitionsApiTest.res +237 -0
  386. package/tests/admin/Platform_ComponentDefinitionsApiTest.res.mjs +298 -0
  387. package/tests/admin/Platform_UIFragmentsApiTest.res +96 -0
  388. package/tests/admin/Platform_UIFragmentsApiTest.res.mjs +101 -0
  389. package/tests/aggregate/AggregateCallbackTest.res +81 -0
  390. package/tests/aggregate/AggregateCallbackTest.res.mjs +140 -0
  391. package/tests/aggregate/AggregateCausationTest.res +49 -0
  392. package/tests/aggregate/AggregateCausationTest.res.mjs +44 -0
  393. package/tests/aggregate/AggregateConflictTest.res +212 -0
  394. package/tests/aggregate/AggregateConflictTest.res.mjs +363 -0
  395. package/tests/aggregate/AggregateFixtures.res +177 -0
  396. package/tests/aggregate/AggregateFixtures.res.mjs +285 -0
  397. package/tests/aggregate/AggregateRejectionTest.res +139 -0
  398. package/tests/aggregate/AggregateRejectionTest.res.mjs +163 -0
  399. package/tests/api/ApiNoApiTest.res +62 -0
  400. package/tests/api/ApiNoApiTest.res.mjs +90 -0
  401. package/tests/api/GraphQL_StitcherTest.res +107 -0
  402. package/tests/api/GraphQL_StitcherTest.res.mjs +99 -0
  403. package/tests/api/SimpleTest.res +7 -0
  404. package/tests/api/SimpleTest.res.mjs +10 -0
  405. package/tests/api/SuryToJsonSchemaTest.res +405 -0
  406. package/tests/api/SuryToJsonSchemaTest.res.mjs +623 -0
  407. package/tests/commandgenerator/CommandGeneratorCallbackTest.res +128 -0
  408. package/tests/commandgenerator/CommandGeneratorCallbackTest.res.mjs +160 -0
  409. package/tests/commandgenerator/CommandGeneratorFixtures.res +139 -0
  410. package/tests/commandgenerator/CommandGeneratorFixtures.res.mjs +197 -0
  411. package/tests/commandtopic/CommandTopicCallbackFixtures.res +87 -0
  412. package/tests/commandtopic/CommandTopicCallbackFixtures.res.mjs +152 -0
  413. package/tests/commandtopic/CommandTopicCallbackTest.res +66 -0
  414. package/tests/commandtopic/CommandTopicCallbackTest.res.mjs +106 -0
  415. package/tests/commandtopic/CommandTopicHelpersRejectionTest.res +83 -0
  416. package/tests/commandtopic/CommandTopicHelpersRejectionTest.res.mjs +109 -0
  417. package/tests/counter/CounterCallbackTest.res +83 -0
  418. package/tests/counter/CounterCallbackTest.res.mjs +140 -0
  419. package/tests/counter/CounterFixtures.res +57 -0
  420. package/tests/counter/CounterFixtures.res.mjs +67 -0
  421. package/tests/dcb/DcbDecodeTest.res +122 -0
  422. package/tests/dcb/DcbDecodeTest.res.mjs +194 -0
  423. package/tests/dcb/DcbEventLogOperationsTest.res +195 -0
  424. package/tests/dcb/DcbEventLogOperationsTest.res.mjs +268 -0
  425. package/tests/dcb/DcbFixtures.res +422 -0
  426. package/tests/dcb/DcbFixtures.res.mjs +534 -0
  427. package/tests/dcb/DcbScopeInferenceTest.res +242 -0
  428. package/tests/dcb/DcbScopeInferenceTest.res.mjs +480 -0
  429. package/tests/dcb/DcbStateChangeSliceTest.res +362 -0
  430. package/tests/dcb/DcbStateChangeSliceTest.res.mjs +546 -0
  431. package/tests/dcb/DcbTagTest.res +978 -0
  432. package/tests/dcb/DcbTagTest.res.mjs +867 -0
  433. package/tests/dcb/DcbValidationTest.res +349 -0
  434. package/tests/dcb/DcbValidationTest.res.mjs +476 -0
  435. package/tests/eventlog/EventLogFixtures.res +113 -0
  436. package/tests/eventlog/EventLogFixtures.res.mjs +166 -0
  437. package/tests/eventlog/EventLogOperationsTest.res +96 -0
  438. package/tests/eventlog/EventLogOperationsTest.res.mjs +192 -0
  439. package/tests/eventlog/EventLogRetryTest.res +121 -0
  440. package/tests/eventlog/EventLogRetryTest.res.mjs +171 -0
  441. package/tests/eventmapper/EventMapperCallbackTest.res +134 -0
  442. package/tests/eventmapper/EventMapperCallbackTest.res.mjs +141 -0
  443. package/tests/eventmapper/EventMapperFixtures.res +255 -0
  444. package/tests/eventmapper/EventMapperFixtures.res.mjs +440 -0
  445. package/tests/eventmapper/EventMapperTest.res +53 -0
  446. package/tests/eventmapper/EventMapperTest.res.mjs +83 -0
  447. package/tests/eventtopic/EventTopicFixtures.res +36 -0
  448. package/tests/eventtopic/EventTopicFixtures.res.mjs +65 -0
  449. package/tests/eventtopic/EventTopicOperationsTest.res +48 -0
  450. package/tests/eventtopic/EventTopicOperationsTest.res.mjs +71 -0
  451. package/tests/extensionpoint/ExtensionPointCallbackTest.res +84 -0
  452. package/tests/extensionpoint/ExtensionPointCallbackTest.res.mjs +94 -0
  453. package/tests/extensionpoint/ExtensionPointFixtures.res +173 -0
  454. package/tests/extensionpoint/ExtensionPointFixtures.res.mjs +205 -0
  455. package/tests/extensionpoint/ExtensionPointOperationsTest.res +261 -0
  456. package/tests/extensionpoint/ExtensionPointOperationsTest.res.mjs +304 -0
  457. package/tests/ftp/FTPTest.res +64 -0
  458. package/tests/ftp/FTPTest.res.mjs +88 -0
  459. package/tests/logger/LogFormatTest.res +348 -0
  460. package/tests/logger/LogFormatTest.res.mjs +309 -0
  461. package/tests/message/MessageTest.res +95 -0
  462. package/tests/message/MessageTest.res.mjs +93 -0
  463. package/tests/message/MetaEnvelopeTest.res +200 -0
  464. package/tests/message/MetaEnvelopeTest.res.mjs +188 -0
  465. package/tests/plugin/ManifestVisibilityTest.res +137 -0
  466. package/tests/plugin/ManifestVisibilityTest.res.mjs +205 -0
  467. package/tests/plugin/PluginSpecExperiment.res +13 -0
  468. package/tests/plugin/PluginSpecExperiment.res.mjs +31 -0
  469. package/tests/plugin/PluginStructureTest.res +298 -0
  470. package/tests/plugin/PluginStructureTest.res.mjs +388 -0
  471. package/tests/plugin/PluginVersionTest.res +34 -0
  472. package/tests/plugin/PluginVersionTest.res.mjs +30 -0
  473. package/tests/plugin/SchemaWalkerTest.res +115 -0
  474. package/tests/plugin/SchemaWalkerTest.res.mjs +160 -0
  475. package/tests/plugin/StateChangeSlice/PsPlaceOrder.res +24 -0
  476. package/tests/plugin/StateChangeSlice/PsPlaceOrder.res.mjs +62 -0
  477. package/tests/plugin/StateChangeSlice/PsShipOrder.res +29 -0
  478. package/tests/plugin/StateChangeSlice/PsShipOrder.res.mjs +69 -0
  479. package/tests/plugin/StateViewSlice/PsAnnotatedView.res +24 -0
  480. package/tests/plugin/StateViewSlice/PsAnnotatedView.res.mjs +94 -0
  481. package/tests/plugin/StateViewSlice/PsAvailableProductsView.res +18 -0
  482. package/tests/plugin/StateViewSlice/PsAvailableProductsView.res.mjs +69 -0
  483. package/tests/plugin/StateViewSlice/PsCustomersView.res +22 -0
  484. package/tests/plugin/StateViewSlice/PsCustomersView.res.mjs +69 -0
  485. package/tests/plugin/StateViewSlice/PsOrdersView.res +20 -0
  486. package/tests/plugin/StateViewSlice/PsOrdersView.res.mjs +81 -0
  487. package/tests/poc/StructuralSubtypingPoc.res +211 -0
  488. package/tests/poc/StructuralSubtypingPoc.res.mjs +61 -0
  489. package/tests/querydb/QueryDbFixtures.res +65 -0
  490. package/tests/querydb/QueryDbFixtures.res.mjs +135 -0
  491. package/tests/querydb/QueryDbOperationsTest.res +94 -0
  492. package/tests/querydb/QueryDbOperationsTest.res.mjs +168 -0
  493. package/tests/sideeffecthandler/SideEffectHandlerCallbackTest.res +56 -0
  494. package/tests/sideeffecthandler/SideEffectHandlerCallbackTest.res.mjs +77 -0
  495. package/tests/sideeffecthandler/SideEffectHandlerFixtures.res +96 -0
  496. package/tests/sideeffecthandler/SideEffectHandlerFixtures.res.mjs +139 -0
  497. package/tests/util/CsvStreamTest.res +54 -0
  498. package/tests/util/CsvStreamTest.res.mjs +51 -0
  499. package/tests/util/LruTest.res +73 -0
  500. package/tests/util/LruTest.res.mjs +105 -0
  501. package/tests/util/MetricsTest.res +36 -0
  502. package/tests/util/MetricsTest.res.mjs +53 -0
@@ -0,0 +1,1017 @@
1
+ open Plugin_Helpers
2
+
3
+ module PluginExtensionPointSpec = ReventlessInfra.PluginExtensionPointSpec
4
+
5
+ // (No type aliases needed — adminExtensionPoints is accessed as a ref field
6
+ // on Spec.hooks, so no optional-parameter parsing issues arise.)
7
+
8
+ module type Spec = {
9
+ let runtimeOps: PluginRuntimeOperations.operations
10
+ let resourceNaming: ReventlessInfra.ResourceNaming.operations
11
+ let environment: string
12
+ /** Deployment-level identity (Pulumi project name in AWS, "local" in
13
+ the local platform). Threaded into `AutomationSlice.context` so
14
+ mappings can populate partition tags from deployment metadata. */
15
+ let platformName: string
16
+ let hooks: Plugin_Helpers.platformHooks
17
+ }
18
+
19
+ module Make = (
20
+ Spec: Spec,
21
+ ApiSpec: {
22
+ type api
23
+ type role
24
+ },
25
+ FragmentProvider: ReventlessInfra.Api_Adapter.Provider,
26
+ RuntimeEnvironment: Runtime.Environment,
27
+ EventCollectorChannel: EventCollector_Adapter.Channel
28
+ with type runtimeParts = RuntimeEnvironment.parts,
29
+ QueryEngineAdapter: QueryDb_Adapter.QueryEngineAdapter,
30
+ PluginExtensionPointRemoteChannel: CommandTopic_Adapter.RemoteChannel,
31
+ HeartbeatRunner: Heartbeat_Adapter.Runner with type runtimeParts = RuntimeEnvironment.parts,
32
+ PluginRuntimeBuilder: PluginRuntime_Builder.T
33
+ with module EventCollectorChannel = EventCollectorChannel
34
+ and type runtimeParts = RuntimeEnvironment.parts,
35
+ DcbEventLogStorage: DcbEventLog_Adapter.Storage,
36
+ DcbEventTopicPublisher: EventTopic_Adapter.Publisher,
37
+ DcbCommandTopicChannel: CommandTopic_Adapter.Channel,
38
+ DcbCommandTopicChannelAsync: CommandTopic_Adapter.Channel,
39
+ ): (Plugin.T with type api = ApiSpec.api and type role = ApiSpec.role) => {
40
+ type api = ApiSpec.api
41
+ type role = ApiSpec.role
42
+
43
+ let construct = (
44
+ ~version: string,
45
+ ~heartbeatInterval: int,
46
+ ~extensionPoints: array<module(ReventlessInfra.ExtensionPoint.T)>,
47
+ ~extensions: array<module(ReventlessInfra.Extension.Blueprint)>,
48
+ ~aggregates: array<module(ReventlessInfra.Aggregate.T with type api = api)>,
49
+ ~readModels: array<
50
+ module(ReventlessInfra.ReadModel.T with type api = api and type role = role),
51
+ >,
52
+ ~tasks: array<module(ReventlessInfra.Task.T)>,
53
+ ~stateChangeSlices: array<module(ReventlessInfra.StateChangeSlice.T)>,
54
+ ~stateViewSlices: array<module(ReventlessInfra.StateViewSlice.T)>,
55
+ ~automationSlices: array<module(ReventlessInfra.AutomationSlice.T)>,
56
+ ~outboundTranslationSlices: array<module(ReventlessInfra.OutboundTranslationSlice.T)>,
57
+ ~inboundTranslationSlices: array<module(ReventlessInfra.InboundTranslationSlice.T)>,
58
+ ~uiFragments: option<Reventless.Plugin.uiFragmentManifest>,
59
+ ~pluginStructure: option<Reventless.Plugin.pluginStructure>,
60
+ self,
61
+ name,
62
+ ) => {
63
+ // Tag all logs emitted during this plugin's construction with `[name]`.
64
+ // Restored at the end of construct; nested constructs (none today) would stack.
65
+ let _prevPluginName = Logger.currentPluginName.contents
66
+ Logger.currentPluginName := Some(name)
67
+
68
+ // Register every component → plugin so runtime logs (fired after construct
69
+ // returns) can resolve a comp like `StateChangeSlice(AddProduct)` to its
70
+ // owning plugin via `Logger.componentPluginRegistry`. Also register the
71
+ // plugin's own name so dotted EP / Plugin / CommandTopic log comps resolve.
72
+ let registerComp = compName =>
73
+ Logger.registerComponentPlugin(~componentName=compName, ~pluginName=name)
74
+ registerComp(name)
75
+ aggregates->Array.forEach((module(M: ReventlessInfra.Aggregate.T with type api = api)) =>
76
+ registerComp(M.Spec.name)
77
+ )
78
+ readModels->Array.forEach((
79
+ module(R: ReventlessInfra.ReadModel.T with type api = api and type role = role),
80
+ ) => registerComp(R.Spec.name))
81
+ stateChangeSlices->Array.forEach((module(Sc: ReventlessInfra.StateChangeSlice.T)) =>
82
+ registerComp(Sc.Spec.name)
83
+ )
84
+ stateViewSlices->Array.forEach((module(Sv: ReventlessInfra.StateViewSlice.T)) =>
85
+ registerComp(Sv.Spec.name)
86
+ )
87
+ automationSlices->Array.forEach((module(As: ReventlessInfra.AutomationSlice.T)) =>
88
+ registerComp(As.Spec.name)
89
+ )
90
+ outboundTranslationSlices->Array.forEach((
91
+ module(Ots: ReventlessInfra.OutboundTranslationSlice.T),
92
+ ) => registerComp(Ots.Spec.name))
93
+ inboundTranslationSlices->Array.forEach((
94
+ module(Its: ReventlessInfra.InboundTranslationSlice.T),
95
+ ) => registerComp(Its.Spec.name))
96
+ tasks->Array.forEach((module(T: ReventlessInfra.Task.T)) => registerComp(T.Spec.name))
97
+ // Extensions deliberately not registered: their Spec.name is the filename stem
98
+ // (e.g. "Products") and would collide with same-named SVS/ReadModels in other
99
+ // plugins. Extension log comps already use the fully-qualified EP form
100
+ // `Extension(Catalog.Products.Ordering)`; the lastDot transformation resolves
101
+ // them to the consumer plugin via its self-registration.
102
+
103
+ // Read platform context from hooks refs (populated by makePlatform/deployPlugin).
104
+ let scheduler = switch Spec.hooks.scheduler.contents {
105
+ | Some(s) => s
106
+ | None =>
107
+ JsError.throwWithMessage(
108
+ "Plugin_Builder: scheduler not set — call makePlatform/deployPlugin first",
109
+ )
110
+ }
111
+ let schedulerRoleUrn = Spec.hooks.schedulerRoleUrn.contents
112
+ let api: api = switch Spec.hooks.api.contents {
113
+ | Some({val}) => Obj.magic(val)
114
+ | None =>
115
+ JsError.throwWithMessage(
116
+ "Plugin_Builder: api not set — call makePlatform/deployPlugin first",
117
+ )
118
+ }
119
+ let apiRole: role = switch Spec.hooks.apiRole.contents {
120
+ | Some({val}) => Obj.magic(val)
121
+ | None =>
122
+ JsError.throwWithMessage(
123
+ "Plugin_Builder: apiRole not set — call makePlatform/deployPlugin first",
124
+ )
125
+ }
126
+
127
+ let id = Plugin.makeId(name, version)
128
+ let opts = {Pulumi.ComponentResource.parent: self->Component.toPulumiResource}
129
+ let childName = name->ComponentType.name(Plugin.componentType)
130
+
131
+ // Aggregates are constructed early so their EventTopics can feed multi-source
132
+ // AutomationSlices created inside DcbBuilder. The same `aggregateEventTopics`
133
+ // dict (after merging in the DCB EventLog topic) is reused later as
134
+ // `allEventTopics` for ReadModels.
135
+ let aggregatesWithoutEventMappers = aggregates->createAggregatesWithoutEventMappers(~api, opts)
136
+ let aggregateEventTopics = Aggregate.allEventTopics(aggregatesWithoutEventMappers)
137
+
138
+ // Construct DCB components and derive DCB-specific API schema entries
139
+ module DcbBuilder = Dcb_Builder.Make(
140
+ DcbEventLogStorage,
141
+ DcbEventTopicPublisher,
142
+ DcbCommandTopicChannel,
143
+ DcbCommandTopicChannelAsync,
144
+ PluginRuntimeBuilder,
145
+ Spec,
146
+ )
147
+ let dcbResult = DcbBuilder.construct(
148
+ ~name,
149
+ ~childName,
150
+ ~environment=Spec.environment,
151
+ ~platformName=Spec.platformName,
152
+ ~aggregateEventTopics,
153
+ ~stateChangeSlices,
154
+ ~stateViewSlices,
155
+ ~automationSlices,
156
+ ~outboundTranslationSlices,
157
+ ~inboundTranslationSlices,
158
+ ~pluginStructure?,
159
+ ~opts,
160
+ )
161
+
162
+ // Derive GraphQL schema fragment for this plugin
163
+ let mutationEntriesFromAggregates =
164
+ aggregates->Array.flatMap((module(M: ReventlessInfra.Aggregate.T with type api = api)) => {
165
+ let commandSchema = M.Spec.commandSchema->S.castToUnknown
166
+ if ApiNoApiHelpers.isNoApi(commandSchema) {
167
+ []
168
+ } else {
169
+ let constructorNames = Reventless.DcbTag.extractAllVariantNames(M.Spec.commandSchema)
170
+ let filteredConstructorNames = ApiNoApiHelpers.filterNoApiVariants(constructorNames, commandSchema)
171
+ let fieldNames =
172
+ filteredConstructorNames->Array.map(cname =>
173
+ Api_Naming.aggregateMutationField(~plugin=name, ~aggregate=M.Spec.name, ~command=cname)
174
+ )
175
+ // Register plugin-prefixed field names for CommandGenerator_Builder.
176
+ Plugin_Helpers.aggregateMutationFieldsRegistry->Dict.set(M.Spec.name, fieldNames)
177
+ if fieldNames->Array.length === 0 {
178
+ []
179
+ } else {
180
+ // Register aggregate mutation SDL + resolver stubs synchronously via hook
181
+ // (before Output.apply chains fire).
182
+ Spec.hooks.mutationResolverHook->Option.forEach(registerResolver =>
183
+ registerResolver(
184
+ ~kind=Aggregate,
185
+ ~fields=fieldNames,
186
+ ~commandSchema,
187
+ ~commandAuthorization=M.Spec.commandAuthorization->Obj.magic,
188
+ )
189
+ )
190
+ let aggDef =
191
+ pluginStructure->Option.flatMap(s =>
192
+ s.aggregates->Array.find(d => d.name == M.Spec.name)
193
+ )
194
+ // Stage E2 (host-ui-login-core): derive per-field permissions by
195
+ // evaluating the PPX-generated `commandAuthorization` against a
196
+ // synthetic command value per constructor. Mirrors the resolver-time
197
+ // shape from `CommandGeneratorResolvers_GraphQL.syntheticCommand` —
198
+ // payload-bearing variants compile to `{TAG, ...}`, payload-less to
199
+ // bare strings.
200
+ let fieldPermissions = Dict.make()
201
+ filteredConstructorNames->Array.forEachWithIndex((cname, idx) => {
202
+ let fieldName = fieldNames->Array.getUnsafe(idx)
203
+ let hasPayload =
204
+ Reventless.DcbTag.isVariantPayloadBearing(M.Spec.commandSchema->Obj.magic, cname)
205
+ let syntheticCmd: unknown =
206
+ hasPayload ? {"TAG": cname}->Obj.magic : cname->Obj.magic
207
+ let rule = M.Spec.commandAuthorization(syntheticCmd->Obj.magic)
208
+ fieldPermissions->Dict.set(fieldName, rule)
209
+ })
210
+ [{
211
+ ReventlessInfra.Api.fieldNames,
212
+ commandSchema,
213
+ fieldPermissions,
214
+ linkedViews: ?aggDef->Option.map(d => d.linkedViews),
215
+ consistencyRead: ?aggDef->Option.flatMap(d => d.consistencyRead),
216
+ }]
217
+ }
218
+ }
219
+ })
220
+
221
+ let mutationEntries = Array.concat(mutationEntriesFromAggregates, dcbResult.mutationEntries)
222
+
223
+ let queryEntriesFromReadModels =
224
+ readModels->Array.map((
225
+ module(R: ReventlessInfra.ReadModel.T with type api = api and type role = role),
226
+ ) => {
227
+ let qn = Api_Naming.queryFieldNamesForReadModel(~plugin=name, ~name=R.Spec.name)
228
+ let subIdField = R.Spec.subIdConfig->Option.map(c => c.subIdField)
229
+ {
230
+ ReventlessInfra.Api.singleFieldName: qn.singleFieldName,
231
+ listFieldName: qn.listFieldName,
232
+ returnTypeName: qn.returnTypeName,
233
+ stateSchema: R.Spec.stateSchema->S.castToUnknown,
234
+ authorization: None,
235
+ permission: R.Spec.authorization,
236
+ connectionSpec: true,
237
+ subIdField: ?subIdField,
238
+ }
239
+ })
240
+
241
+ let queryEntries = Array.concat(queryEntriesFromReadModels, dcbResult.queryEntries)
242
+
243
+ let eventLogEntriesFromAggregates =
244
+ aggregates->Array.map((module(M: ReventlessInfra.Aggregate.T with type api = api)) => {
245
+ ReventlessInfra.Api.busKey: M.Spec.name ++ "Aggr" ++ "EventLog",
246
+ displayName: M.Spec.name,
247
+ eventSchema: M.Spec.eventSchema->S.castToUnknown,
248
+ })
249
+
250
+ let eventLogEntries = Array.concat(eventLogEntriesFromAggregates, dcbResult.eventLogEntries)
251
+
252
+ // Populate query field names registry so resolvers align with fragment SDL.
253
+ // Keyed by the Spec.name that each component uses for its QueryDb.
254
+ // (StateViewSlice registry is populated earlier, inside the DCB builder,
255
+ // before StateViewSlice.make calls — see above.)
256
+ readModels->Array.forEach((
257
+ module(R: ReventlessInfra.ReadModel.T with type api = api and type role = role),
258
+ ) => {
259
+ let qn = Api_Naming.queryFieldNamesForReadModel(~plugin=name, ~name=R.Spec.name)
260
+ let (labelField, _searchableFields) = Plugin_Structure.labelFieldsFromStateSchema(
261
+ ~entityName=R.Spec.name,
262
+ R.Spec.stateSchema->S.castToUnknown,
263
+ )
264
+ let qn = {
265
+ ...qn,
266
+ labelField,
267
+ connectionFilterTypeName: qn.returnTypeName ++ "Filter",
268
+ }
269
+ let qn = switch R.Spec.subIdConfig {
270
+ | Some(_) =>
271
+ {
272
+ ...qn,
273
+ itemsFieldName: qn.singleFieldName ++ "Items",
274
+ itemsFilterTypeName: qn.returnTypeName ++ "ItemsFilter",
275
+ }
276
+ | None => qn
277
+ }
278
+ Plugin_Helpers.queryFieldNamesRegistry->Dict.set(R.Spec.name, qn)
279
+ Plugin_Helpers.stateSchemaRegistry->Dict.set(
280
+ R.Spec.name,
281
+ R.Spec.stateSchema->S.castToUnknown,
282
+ )
283
+ })
284
+
285
+ let apiSchemaFragment = {
286
+ let baseFragment = FragmentProvider.generateFragment(~mutationEntries, ~queryEntries)
287
+ let subResult = Plugin_SubscriptionSchema.generate(
288
+ ~mutationEntries,
289
+ ~eventLogEntries,
290
+ )
291
+ let parts = GraphQL_Stitcher.decode(baseFragment)
292
+ GraphQL_Stitcher.encode({
293
+ ...parts,
294
+ types: Array.concat(parts.types, subResult.extraTypes),
295
+ subscriptions: subResult.subscriptionFields,
296
+ })
297
+ }
298
+
299
+ // Register type definitions via platform hook (e.g. GraphQL in-memory)
300
+ Spec.hooks.schemaTypeRegistrationHook->Option.forEach(registerTypes => {
301
+ let parts = GraphQL_Stitcher.decode(apiSchemaFragment)
302
+ registerTypes(parts.types)
303
+ })
304
+
305
+ // Register MCP tools and resources via platform hook (e.g. MCP in-memory)
306
+ Spec.hooks.mcpSchemaRegistrationHook->Option.forEach(registerMcp =>
307
+ registerMcp({
308
+ pluginName: name,
309
+ mutationEntries,
310
+ queryEntries,
311
+ eventLogEntries,
312
+ subscriptionFields: GraphQL_Stitcher.decode(apiSchemaFragment).subscriptions,
313
+ })
314
+ )
315
+
316
+ // Register DCB StateChangeSlice publish functions in publishToAggregates so that
317
+ // extensions whose Delegate is a DCB slice can dispatch commands to them.
318
+ // All slices in a plugin share the same DCB command topic (same publishJsons).
319
+ switch dcbResult.dcbPublishJsons {
320
+ | Some(slicePublishJsons) =>
321
+ stateChangeSlices->Array.forEach((module(Sc: StateChangeSlice.T)) =>
322
+ publishToAggregates->Dict.set(Sc.Spec.name, slicePublishJsons)
323
+ )
324
+ | None => ()
325
+ }
326
+ // Reuse the aggregateEventTopics dict computed before DcbBuilder.construct;
327
+ // merge in the DCB EventLog topic for ReadModels (already merged inside
328
+ // DcbBuilder for AutomationSlice subscription).
329
+ let allEventTopics = aggregateEventTopics
330
+ switch dcbResult.dcbEventLogOutputs {
331
+ | Some(dcbOutputs) => allEventTopics->Dict.set(name ++ "DcbEventLog", dcbOutputs.eventTopic)
332
+ | None => ()
333
+ }
334
+
335
+ let readModelsOutputs = readModels->createReadModels(~api, ~apiRole, allEventTopics, opts)
336
+ let allQueryDbs = readModelsOutputs->ReadModel.allQueryDbs
337
+ // Merge DCB StateViewSlice, InboundTranslation, AutomationSlice, and
338
+ // OutboundTranslation QueryDbs into allQueryDbs so createResolvers builds
339
+ // AppSync resolvers for them too.
340
+ //
341
+ // Key must match `name` passed to QueryDbResolvers_AppSync.make (the
342
+ // QueryDb's own queryDbName, used by storageResource lookups for ByIds
343
+ // and idResolver paths). Slice output dicts are keyed by Spec.name; the
344
+ // queryDb name appends a suffix per slice kind:
345
+ // StateViewSlice — no suffix
346
+ // AutomationSlice — "Todo"
347
+ // OutboundTranslationSlice — "Todo"
348
+ // InboundTranslationSlice — "Audit"
349
+ dcbResult.stateViewSlicesOutputs
350
+ ->Dict.toArray
351
+ ->Array.forEach(((k, v)) => allQueryDbs->Dict.set(k, v.queryDb))
352
+ dcbResult.inboundTranslationSlicesOutputs
353
+ ->Dict.toArray
354
+ ->Array.forEach(((k, v)) => allQueryDbs->Dict.set(k ++ "Audit", v.queryDb))
355
+ dcbResult.automationSlicesOutputs
356
+ ->Dict.toArray
357
+ ->Array.forEach(((k, v)) => allQueryDbs->Dict.set(k ++ "Todo", v.queryDb))
358
+ dcbResult.outboundTranslationSlicesOutputs
359
+ ->Dict.toArray
360
+ ->Array.forEach(((k, v)) => allQueryDbs->Dict.set(k ++ "Todo", v.queryDb))
361
+ let queryEngine = QueryEngineAdapter.make(allQueryDbs)
362
+
363
+ {
364
+ // Fire onPluginBuiltHook synchronously with a plain-data summary.
365
+ // ExtensionPoint/Extension names are not accessible from their T module type,
366
+ // so only aggregates, read models, and DCB slice names are included.
367
+
368
+ let extractTypes = schema => Reventless.DcbTag.extractAllVariantNames(schema)
369
+ // Build per-component schema data and register it for the deployed hook.
370
+ let aggregateComponents = aggregates->Array.map((
371
+ module(M: ReventlessInfra.Aggregate.T with type api = api),
372
+ ) => {
373
+ let schema: Plugin_Helpers.pluginDeployedSchema = {
374
+ commandTypes: extractTypes(M.Spec.commandSchema),
375
+ eventTypes: extractTypes(M.Spec.eventSchema),
376
+ errorTypes: extractTypes(M.Spec.errorSchema),
377
+ commandSchemas: [
378
+ SchemaWalker.walk(M.Spec.name ++ ".command", M.Spec.commandSchema),
379
+ ],
380
+ eventSchemas: [
381
+ SchemaWalker.walk(M.Spec.name ++ ".event", M.Spec.eventSchema),
382
+ ],
383
+ }
384
+ Plugin_Helpers.componentSchemaRegistry->Dict.set(M.Spec.name, schema)
385
+ ({name: M.Spec.name, kind: "Aggregate", schema}: Plugin_Helpers.pluginBuiltComponent)
386
+ })
387
+
388
+ let readModelComponents = readModels->Array.map((
389
+ module(R: ReventlessInfra.ReadModel.T with type api = api and type role = role),
390
+ ) => {
391
+ let qn = Api_Naming.queryFieldNamesForReadModel(~plugin=name, ~name=R.Spec.name)
392
+ let schema: Plugin_Helpers.pluginDeployedSchema = {
393
+ queryFields: [qn.singleFieldName, qn.listFieldName],
394
+ }
395
+ Plugin_Helpers.componentSchemaRegistry->Dict.set(R.Spec.name, schema)
396
+ ({name: R.Spec.name, kind: "ReadModel", schema}: Plugin_Helpers.pluginBuiltComponent)
397
+ })
398
+
399
+ let mapNames = (d: dict<_>, kind: string) =>
400
+ d
401
+ ->Dict.keysToArray
402
+ ->Array.map(name => {
403
+ let schema: Plugin_Helpers.pluginDeployedSchema = {}
404
+ ({Plugin_Helpers.name, kind, schema}: Plugin_Helpers.pluginBuiltComponent)
405
+ })
406
+
407
+ // Routing slices (automation / inbound + outbound translation) expose their
408
+ // command/event wiring and routing target on the hook surface, at parity
409
+ // with aggregates and read models — mirroring the metadata Plugin_Structure
410
+ // records on the static plugin def. Type strings stay unqualified to match
411
+ // the aggregate/read-model entries already on this same hook surface
412
+ // (Plugin_Structure additionally prefixes them with the plugin name).
413
+ let extractEventTypes = schema => Reventless.DcbTag.extractVariantNames(schema)
414
+ let routingSchemas: Dict.t<Plugin_Helpers.pluginDeployedSchema> = Dict.make()
415
+ automationSlices->Array.forEach((module(As: ReventlessInfra.AutomationSlice.T)) => {
416
+ // Union of source-event variants across every per-source mapping.
417
+ let consumedEventTypes =
418
+ As.Automation.mappings
419
+ ->Array.flatMap((module(M: As.Automation.Mapping)) =>
420
+ extractEventTypes(M.sourceEventSchema->S.castToUnknown)
421
+ )
422
+ ->Belt.Set.String.fromArray
423
+ ->Belt.Set.String.toArray
424
+ routingSchemas->Dict.set(
425
+ As.Spec.name,
426
+ {
427
+ consumedEventTypes,
428
+ producedCommandTypes: extractTypes(As.Spec.commandSchema),
429
+ targetName: As.Spec.targetName,
430
+ },
431
+ )
432
+ })
433
+ outboundTranslationSlices->Array.forEach((
434
+ module(Ots: ReventlessInfra.OutboundTranslationSlice.T),
435
+ ) =>
436
+ routingSchemas->Dict.set(
437
+ Ots.Spec.name,
438
+ {
439
+ consumedEventTypes: extractEventTypes(Ots.Spec.consumedEventSchema),
440
+ commandTypes: extractTypes(Ots.Spec.inboundCommandSchema),
441
+ // Outbound slices may have no target (option); pass it through.
442
+ targetName: ?Ots.Spec.targetName,
443
+ },
444
+ )
445
+ )
446
+ inboundTranslationSlices->Array.forEach((
447
+ module(Its: ReventlessInfra.InboundTranslationSlice.T),
448
+ ) =>
449
+ routingSchemas->Dict.set(
450
+ Its.Spec.name,
451
+ {
452
+ commandTypes: extractTypes(Its.Spec.commandSchema),
453
+ targetName: Its.Spec.targetName,
454
+ },
455
+ )
456
+ )
457
+
458
+ // Component set still derives from the DCB outputs dict (unchanged
459
+ // membership); enrich + register the schema where a matching spec module
460
+ // was found above, so the deployed hook surfaces it too (the built-hook
461
+ // components carry it inline).
462
+ let routingComponents = (d: dict<_>, kind: string) =>
463
+ d
464
+ ->Dict.keysToArray
465
+ ->Array.map(name => {
466
+ let schema = routingSchemas->Dict.get(name)->Option.getOr({})
467
+ Plugin_Helpers.componentSchemaRegistry->Dict.set(name, schema)
468
+ ({Plugin_Helpers.name, kind, schema}: Plugin_Helpers.pluginBuiltComponent)
469
+ })
470
+
471
+ let components = Array.flat([
472
+ aggregateComponents,
473
+ readModelComponents,
474
+ mapNames(dcbResult.stateChangeSlicesOutputs, "StateChangeSlice"),
475
+ mapNames(dcbResult.stateViewSlicesOutputs, "StateViewSlice"),
476
+ routingComponents(dcbResult.automationSlicesOutputs, "AutomationSlice"),
477
+ routingComponents(dcbResult.outboundTranslationSlicesOutputs, "OutboundTranslationSlice"),
478
+ routingComponents(dcbResult.inboundTranslationSlicesOutputs, "InboundTranslationSlice"),
479
+ ])
480
+
481
+ switch Plugin_Helpers.onPluginBuiltHook.contents {
482
+ | Some(hook) =>
483
+ let meta = Plugin_Helpers.pluginMetadataRegistry.contents
484
+ hook({
485
+ name,
486
+ version,
487
+ kind: ?meta->Option.flatMap(m => m.kind),
488
+ displayName: ?meta->Option.flatMap(m => m.displayName),
489
+ vendor: ?meta->Option.flatMap(m => m.vendor),
490
+ architectureType: ?meta->Option.flatMap(m => m.architectureType),
491
+ components,
492
+ })
493
+ | None => ()
494
+ }
495
+ }
496
+
497
+ let builderOutputs = {
498
+ // Resolve admin extension point data — from Interstack (AWS cross-stack reference).
499
+ let interstackAdminExtensionPoints =
500
+ Interstack.coreStackReference->Option.mapOr(Pulumi.Output.make(None), coreStack =>
501
+ coreStack->Pulumi.StackReference.getOutput("extensionPoints")
502
+ )
503
+
504
+ // Derive local admin extension point resolved data (passed from makePlatform).
505
+ let localAdminResolvedEP =
506
+ Spec.hooks.adminExtensionPoints.contents->Pulumi.Output.flatMap(eps =>
507
+ switch eps->Dict.get(PluginExtensionPointSpec.name) {
508
+ | Some(ep) => ep->ExtensionPoint.toResolvedOutputs->Pulumi.Output.apply(r => Some(r))
509
+ | None => Pulumi.Output.make(None)
510
+ }
511
+ )
512
+
513
+ // Push schema fragment to the API before resolvers are created (AWS only).
514
+ // The returned Output chains into the dependency tuple so Pulumi waits
515
+ // for the schema update to complete before creating resolver resources.
516
+ let schemaPushed = switch Spec.hooks.preResolversSchemaHook {
517
+ | Some(pushSchema) => pushSchema(~name, ~version, apiSchemaFragment)
518
+ | None => Pulumi.Output.make()
519
+ }
520
+
521
+ (
522
+ (interstackAdminExtensionPoints, localAdminResolvedEP, schemaPushed)->Pulumi.Output.all3,
523
+ aggregateResources->Pulumi.Output.allDict,
524
+ publishToAggregates->Pulumi.Output.allDict,
525
+ publishToReadModels->Pulumi.Output.allDict,
526
+ scheduler,
527
+ queryEngine,
528
+ )
529
+ ->Pulumi.Output.all6
530
+ ->Pulumi.Output.apply(((
531
+ (interstackAdminExtensionPoints, localAdminResolvedEP, _),
532
+ aggregateResources,
533
+ publishToAggregates,
534
+ publishToReadModels,
535
+ scheduler,
536
+ queryEngine,
537
+ )) => {
538
+ let aggregatesOutputs = addEventMappers(allEventTopics, queryEngine)
539
+
540
+ let (extensionPointsOutputs, extensionPointsHandlers, extensionPointRegistryInfos) =
541
+ extensionPoints->createExtensionPoints(
542
+ ~aggregateResources,
543
+ ~publishToAggregates,
544
+ ~scheduler,
545
+ ~queryEngine,
546
+ ~resourceNaming=Spec.resourceNaming,
547
+ ~opts,
548
+ )
549
+
550
+ // Resolve admin connection — from Interstack (AWS), local admin (in-memory), or None
551
+ let coreSetup = switch interstackAdminExtensionPoints {
552
+ | Some(interstackAdminExtensionPoints) => {
553
+ let pluginExtensionPointUnwrapped: ReventlessInterop.ExtensionPoint.resolvedOutputs = (
554
+ interstackAdminExtensionPoints
555
+ ->Pulumi.StackReference.get(PluginExtensionPointSpec.name)
556
+ ->Obj.magic: JSON.t
557
+ )->S.parseOrThrow(ReventlessInterop.ExtensionPoint.resolvedOutputsSchema)
558
+ let pluginExtensionPointCommandTopicRemoteChannel = PluginExtensionPointRemoteChannel.make(
559
+ pluginExtensionPointUnwrapped.commandTopic.resources->Array.map(
560
+ Adapter.fromInteropResolved,
561
+ ),
562
+ )
563
+ Some((pluginExtensionPointUnwrapped, pluginExtensionPointCommandTopicRemoteChannel))
564
+ }
565
+ | None =>
566
+ // Fallback: use local admin extension point data (e.g. in-memory platform)
567
+ switch localAdminResolvedEP {
568
+ | Some(resolvedEP) =>
569
+ let remoteChannel = PluginExtensionPointRemoteChannel.make(
570
+ resolvedEP.commandTopic.resources->Array.map(Adapter.fromInteropResolved),
571
+ )
572
+ Some((resolvedEP, remoteChannel))
573
+ | None => None
574
+ }
575
+ }
576
+
577
+ let publishToPluginExtensionPoint: ReventlessInfra.CommandTopic.publishJsons = switch coreSetup {
578
+ | Some((_, remoteChannel)) => remoteChannel.remotePublish
579
+ | None => async _ => ()
580
+ }
581
+
582
+ let (extensionsOutputs, extensionsHandlers, extensionRegistryInfos) =
583
+ extensions->createExtensions(
584
+ ~pluginName=name,
585
+ ~publishToPluginExtensionPoint,
586
+ ~publishToAggregates,
587
+ ~publishToReadModels,
588
+ ~queryEngine,
589
+ ~opts,
590
+ )
591
+
592
+ let extensionPointsDefinitions = extensionPointsOutputs->extractExtensionPointDefinitions
593
+ let extensionsDefinitions = extensionsOutputs->extractExtensionDefinitions
594
+
595
+ module Set = Belt.Set.String
596
+
597
+ let collectAggregateNames = ex =>
598
+ ex
599
+ ->Set.fromArray
600
+ ->Set.remove(ReventlessInfra.ExtensionMapping.NoDelegate.name)
601
+
602
+ let extensionPointAggregateNames =
603
+ extensionPointsOutputs
604
+ ->Array.flatMap(ex => ex.aggregateNames)
605
+ ->collectAggregateNames
606
+
607
+ let extensionAggregateNames =
608
+ extensionsOutputs
609
+ ->Array.flatMap(ex => ex.aggregateNames)
610
+ ->collectAggregateNames
611
+
612
+ let eventTopics =
613
+ aggregatesOutputs->Aggregate.filterEventTopics(
614
+ extensionPointAggregateNames->Set.union(extensionAggregateNames),
615
+ )
616
+ // Include DCB EventTopic so the EventCollector subscribes to DynamoDB Stream events
617
+ switch dcbResult.dcbEventLogOutputs {
618
+ | Some(dcbOutputs) => eventTopics->Dict.set(name ++ "DcbEventLog", dcbOutputs.eventTopic)
619
+ | None => ()
620
+ }
621
+ switch coreSetup {
622
+ | Some((pluginExtensionPointUnwrapped, _)) =>
623
+ eventTopics->Dict.set(
624
+ PluginExtensionPointSpec.name,
625
+ {
626
+ resources: pluginExtensionPointUnwrapped.eventTopic.resources->Array.map(
627
+ AdapterDeploytime.fromInteropResource,
628
+ ),
629
+ },
630
+ )
631
+ | None => ()
632
+ }
633
+
634
+ let childName = name->ComponentType.name(Plugin.componentType)
635
+
636
+ module EventCollectorHelper = MakeEventCollectorHelper(
637
+ RuntimeEnvironment,
638
+ EventCollectorChannel,
639
+ PluginRuntimeBuilder,
640
+ )
641
+ let (eventCollector, eventCollectorOutputs, eventCollectorUrn) = EventCollectorHelper.make(
642
+ ~name=childName,
643
+ ~eventTopics,
644
+ ~opts,
645
+ )
646
+
647
+ // Capture deployTarget synchronously before the Pulumi.Output.apply callback.
648
+ // deployPlugin resets hooks.deployTarget to "Domain" after P.make() returns,
649
+ // so reading it inside the async callback would always yield "Domain".
650
+ let capturedDeployTarget = Spec.hooks.deployTarget.contents
651
+
652
+ // DCB EventLog definition — Some when this plugin has a DcbEventLog
653
+ // component, None otherwise. Admin's manageSubscriptions reads this to
654
+ // provision cross-plugin SNS subscriptions from peer plugins' DCB
655
+ // topics → this plugin's EventCollector, and vice-versa. The eventTopic
656
+ // resource's `id` is the SNS topic ARN (same convention as
657
+ // extensionPointDefinition.eventTopic).
658
+ let dcbEventLogDef: Pulumi.Output.t<option<Reventless.Plugin.dcbEventLogDefinition>> =
659
+ switch dcbResult.dcbEventLogOutputs {
660
+ | None => Pulumi.Output.make(None)
661
+ | Some(dcbOutputs) =>
662
+ switch dcbOutputs.eventTopic.resources->Array.get(0) {
663
+ | Some(r) =>
664
+ r.id->Pulumi.Output.apply(arn => Some({
665
+ Reventless.Plugin.name: name ++ "DcbEventLog",
666
+ eventTopicArn: arn,
667
+ }))
668
+ | None => Pulumi.Output.make(None)
669
+ }
670
+ }
671
+
672
+ let pluginDefinition =
673
+ (extensionPointsDefinitions, eventCollectorUrn, dcbEventLogDef)
674
+ ->Pulumi.Output.all3
675
+ ->Pulumi.Output.apply(((extensionPointsDefinitions, eventCollectorUrn, dcbEventLogDef)) => {
676
+ Reventless.Plugin.id,
677
+ name,
678
+ version,
679
+ extensionPoints: extensionPointsDefinitions,
680
+ extensions: extensionsDefinitions,
681
+ eventCollector: eventCollectorUrn,
682
+ extensionProtocols: [],
683
+ apiSchemaFragment: Some(apiSchemaFragment),
684
+ apiTarget: Some(capturedDeployTarget),
685
+ uiFragments,
686
+ structure: pluginStructure,
687
+ dcbEventLog: dcbEventLogDef,
688
+ })
689
+
690
+ // Bundled Plugin EventCollector reconstructs Extension_Operations at
691
+ // cold start from HANDLER_CONFIG, which needs concrete cmd-topic SQS
692
+ // URLs for every aggregate/slice a user extension may publish to.
693
+ let aggregateQueueUrls: dict<Pulumi.Output.t<string>> = Dict.make()
694
+ aggregateResources
695
+ ->Dict.toArray
696
+ ->Array.forEach(((aggName, resources)) =>
697
+ switch resources->Array.get(0) {
698
+ | Some(r) => aggregateQueueUrls->Dict.set(aggName, r.id)
699
+ | None => ()
700
+ }
701
+ )
702
+ // All DCB StateChangeSlices share the same dcb command topic — map
703
+ // every slice name to that single URL so PublishStateChangeSliceCommand
704
+ // routes correctly regardless of which slice the extension targets.
705
+ switch dcbResult.dcbCommandTopicQueueUrl {
706
+ | Some(url) =>
707
+ stateChangeSlices->Array.forEach((module(Sc: StateChangeSlice.T)) =>
708
+ aggregateQueueUrls->Dict.set(Sc.Spec.name, url)
709
+ )
710
+ | None => ()
711
+ }
712
+
713
+ // Per-RM EventCollector SQS URL — populated only for plugins that
714
+ // expose RMs the bundled handler may enqueue events into directly.
715
+ let readModelQueueUrls: dict<Pulumi.Output.t<string>> = Dict.make()
716
+ readModelsOutputs
717
+ ->Dict.toArray
718
+ ->Array.forEach(((rmName, rmOut)) => {
719
+ let urlOutput =
720
+ rmOut.eventCollector->Pulumi.Output.flatMap(ecOutputs =>
721
+ switch ecOutputs.resources->Array.get(0) {
722
+ | Some(r) => r.id
723
+ | None => Pulumi.Output.make("")
724
+ }
725
+ )
726
+ readModelQueueUrls->Dict.set(rmName, urlOutput)
727
+ })
728
+
729
+ switch coreSetup {
730
+ | Some((pluginExtensionPointUnwrapped, _)) => {
731
+ let (
732
+ connectPluginExtensionOutputs,
733
+ connectPluginExtensionIncomingEventHandler,
734
+ ) = createConnectPluginExtension(
735
+ ~pluginDefinition,
736
+ ~publishToPluginExtensionPoint,
737
+ ~publishToAggregates,
738
+ ~readModelNamesForSourceName,
739
+ ~publishToReadModels,
740
+ ~queryEngine,
741
+ ~opts,
742
+ )
743
+ let _ = EventCollectorHelper.connect(
744
+ ~eventCollector,
745
+ ~eventTopics,
746
+ ~extensionPointsOutputs,
747
+ ~extensionsOutputs,
748
+ ~pluginExtensionPointUnwrapped,
749
+ ~pluginDefinition,
750
+ ~connectPluginExtensionIncomingEventHandler,
751
+ ~extensionsHandlers,
752
+ ~extensionPointsHandlers,
753
+ ~connectPluginExtensionOutputs,
754
+ ~extensionRegistryInfos,
755
+ ~extensionPointRegistryInfos,
756
+ ~aggregateQueueUrls,
757
+ ~readModelQueueUrls,
758
+ ~readModelNamesForSourceName,
759
+ )
760
+ }
761
+ | None =>
762
+ // No admin connection — connect EventCollector without ConnectPluginExtension
763
+ let _ = EventCollectorHelper.connect(
764
+ ~eventCollector,
765
+ ~eventTopics,
766
+ ~extensionPointsOutputs,
767
+ ~extensionsOutputs,
768
+ ~pluginDefinition,
769
+ ~extensionsHandlers,
770
+ ~extensionPointsHandlers,
771
+ ~extensionRegistryInfos,
772
+ ~aggregateQueueUrls,
773
+ ~readModelQueueUrls,
774
+ ~readModelNamesForSourceName,
775
+ )
776
+ }
777
+
778
+ let tasksOutputs = createTasks(
779
+ tasks,
780
+ ~aggregatesOutputs,
781
+ ~scheduler,
782
+ ~schedulerRoleUrn,
783
+ ~publishToAggregates,
784
+ ~queryEngine,
785
+ ~resourceNaming=Spec.resourceNaming,
786
+ ~opts,
787
+ )
788
+
789
+ let resolvers = allQueryDbs->createResolvers
790
+
791
+ // Wire subscription infrastructure (StateTopic, EventLogSubscription) after resolvers.
792
+ // Gives the AWS platform access to allQueryDbs, allEventTopics, and eventLogEntries
793
+ // without coupling reventless-core to reventless-aws.
794
+ Spec.hooks.subscriptionInfraHook->Option.forEach(hook =>
795
+ hook({allQueryDbs, allEventTopics, eventLogEntries, opts})
796
+ )
797
+
798
+ module SpecificHeartbeat = Heartbeat_Builder.Make(HeartbeatRunner)
799
+ let heartbeat = SpecificHeartbeat.make(~name=childName, ~opts)
800
+ let handler = SpecificHeartbeat.makeHandler(
801
+ ~id,
802
+ ~timeout=heartbeatInterval,
803
+ ~publishToPluginExtensionPoint,
804
+ )
805
+ switch coreSetup {
806
+ | Some((_, pluginExtensionPointCommandTopicRemoteChannel)) =>
807
+ // Notify platform hook that the EP channel is available (AWS extracts SQS URL for bundled heartbeat)
808
+ Spec.hooks.onHeartbeatEpChannelAvailable->Option.forEach(hook =>
809
+ hook(pluginExtensionPointCommandTopicRemoteChannel->Obj.magic, ~pluginId=id)
810
+ )
811
+ heartbeat->PluginRuntimeBuilder.forPluginHeartbeat(
812
+ ~handler,
813
+ ~connect=SpecificHeartbeat.connect(
814
+ heartbeat,
815
+ ~remoteChannel=pluginExtensionPointCommandTopicRemoteChannel,
816
+ ~timeout=heartbeatInterval,
817
+ ...
818
+ ),
819
+ )
820
+ | None =>
821
+ heartbeat->PluginRuntimeBuilder.forPluginHeartbeat(~handler, ~connect=(~runtime as _) =>
822
+ ()
823
+ )
824
+ }
825
+
826
+ // Connect DCB command topic to its Lambda runtime (if DCB is configured)
827
+ dcbResult.dcbRuntimeSetup->Option.forEach(dcbRuntimeSetup => dcbRuntimeSetup())
828
+
829
+ {
830
+ id,
831
+ version,
832
+ heartbeatInterval,
833
+ eventCollector: eventCollectorOutputs,
834
+ extensionPoints: extensionPointsOutputs->Array.map(el => (el.name, el))->Dict.fromArray,
835
+ extensions: extensionsOutputs->Array.map(el => (el.name, el))->Dict.fromArray,
836
+ aggregates: aggregatesOutputs,
837
+ stateChangeSlices: dcbResult.stateChangeSlicesOutputs,
838
+ stateViewSlices: dcbResult.stateViewSlicesOutputs,
839
+ automationSlices: dcbResult.automationSlicesOutputs,
840
+ outboundTranslationSlices: dcbResult.outboundTranslationSlicesOutputs,
841
+ inboundTranslationSlices: dcbResult.inboundTranslationSlicesOutputs,
842
+ readModels: readModelsOutputs,
843
+ tasks: tasksOutputs->Array.map(el => (el.name, el))->Dict.fromArray,
844
+ resolvers,
845
+ heartbeat: heartbeat->Component.outputs,
846
+ dcbEventLog: dcbResult.dcbEventLogOutputs,
847
+ uiFragments: (uiFragments: option<Reventless.Plugin.uiFragmentManifest>),
848
+ }
849
+ })
850
+ }
851
+
852
+ let pluginOutputs: Plugin.outputs = {
853
+ id: builderOutputs->Pulumi.Output.apply(outputs => outputs.id),
854
+ version: builderOutputs->Pulumi.Output.apply(outputs => outputs.version),
855
+ heartbeatInterval: builderOutputs->Pulumi.Output.apply(outputs => outputs.heartbeatInterval),
856
+ eventCollector: builderOutputs->Pulumi.Output.apply(outputs => outputs.eventCollector),
857
+ extensionPoints: builderOutputs->Pulumi.Output.apply(outputs => outputs.extensionPoints),
858
+ extensions: builderOutputs->Pulumi.Output.apply(outputs => outputs.extensions),
859
+ aggregates: builderOutputs->Pulumi.Output.apply(outputs => outputs.aggregates),
860
+ stateChangeSlices: builderOutputs->Pulumi.Output.apply(outputs => outputs.stateChangeSlices),
861
+ stateViewSlices: builderOutputs->Pulumi.Output.apply(outputs => outputs.stateViewSlices),
862
+ automationSlices: builderOutputs->Pulumi.Output.apply(outputs => outputs.automationSlices),
863
+ outboundTranslationSlices: builderOutputs->Pulumi.Output.apply(outputs =>
864
+ outputs.outboundTranslationSlices
865
+ ),
866
+ inboundTranslationSlices: builderOutputs->Pulumi.Output.apply(outputs =>
867
+ outputs.inboundTranslationSlices
868
+ ),
869
+ readModels: builderOutputs->Pulumi.Output.apply(outputs => outputs.readModels),
870
+ tasks: builderOutputs->Pulumi.Output.apply(outputs => outputs.tasks),
871
+ resolvers: builderOutputs->Pulumi.Output.apply(outputs => outputs.resolvers),
872
+ heartbeat: builderOutputs->Pulumi.Output.apply(outputs => outputs.heartbeat),
873
+ dcbEventLog: builderOutputs->Pulumi.Output.apply(outputs => outputs.dcbEventLog),
874
+ apiSchemaFragment: Pulumi.Output.make(Some(apiSchemaFragment)),
875
+ uiFragments: builderOutputs->Pulumi.Output.apply(outputs => outputs.uiFragments),
876
+ pluginStructure: Pulumi.Output.make(pluginStructure),
877
+ }
878
+ let _ = self->Component.setOutputs(pluginOutputs)
879
+
880
+ // Compute and store the _interopMeta stack export value. User entry-point
881
+ // code retrieves it via Plugin_Helpers.getInteropMeta() and exports it
882
+ // alongside "tasks", "plugin", and "eventMappers".
883
+ // Assign directly — do NOT wrap in Some(). Pulumi.Output.t is a JS Proxy;
884
+ // wrapping a Proxy in Caml_option.some() triggers the BS_PRIVATE sentinel bug.
885
+ interopMetaOutput :=
886
+ builderOutputs->Pulumi.Output.apply(outputs =>
887
+ outputs
888
+ ->toInteropMeta
889
+ ->S.reverseConvertToJsonOrThrow(ReventlessInterop.ExportMeta.schema)
890
+ )
891
+
892
+ Logger.currentPluginName := _prevPluginName
893
+ }
894
+
895
+ let makeAutoUIManifest = (
896
+ ~remoteEntryUrl: string,
897
+ ~name: string,
898
+ ~pluginStructure: Reventless.Plugin.pluginStructure,
899
+ ~readModelPositions: array<string>=[],
900
+ ~aggregatePositions: array<string>=[],
901
+ ): Reventless.Plugin.uiFragmentManifest => {
902
+ // Internal queryable components are hidden from the AutoUI manifest. They
903
+ // remain fully wired (resolvers, GraphQL schema, queryable defs,
904
+ // authorization) — visibility is a UX hint, not a security boundary. See
905
+ // docs/plans/done/component-visibility-annotations.md
906
+ let isVisibleQueryable = (q: Reventless.Plugin.queryableDef) =>
907
+ switch q.visibility {
908
+ | Some("Internal") => false
909
+ | _ => true
910
+ }
911
+ let visibleReadModels = pluginStructure.readModels->Array.filter(isVisibleQueryable)
912
+ let visibleStateViewSlices = pluginStructure.stateViewSlices->Array.filter(isVisibleQueryable)
913
+ let listPanel = (q: Reventless.Plugin.queryableDef): Reventless.Plugin.panelManifestEntry => {
914
+ fragmentId: name ++ "." ++ q.name ++ ".list",
915
+ title: q.name,
916
+ description: "",
917
+ positions: readModelPositions,
918
+ requiredAccess: None,
919
+ }
920
+ let detailPanel = (w: Reventless.Plugin.writableDef): Reventless.Plugin.panelManifestEntry => {
921
+ fragmentId: name ++ "." ++ w.name ++ ".detail",
922
+ title: w.name,
923
+ description: "",
924
+ positions: aggregatePositions,
925
+ requiredAccess: None,
926
+ }
927
+ let listPage = (q: Reventless.Plugin.queryableDef): Reventless.Plugin.pageManifestEntry => {
928
+ fragmentId: name ++ "." ++ q.name ++ ".list",
929
+ title: q.name,
930
+ menuEntry: {label: q.name, icon: None, group: None, sortOrder: 0},
931
+ requiredAccess: None,
932
+ }
933
+ let panels = Array.flat([
934
+ visibleReadModels->Array.map(listPanel),
935
+ visibleStateViewSlices->Array.map(listPanel),
936
+ pluginStructure.aggregates->Array.map(detailPanel),
937
+ pluginStructure.stateChangeSlices->Array.map(detailPanel),
938
+ ])
939
+ let pages = Array.flat([
940
+ visibleReadModels->Array.map(listPage),
941
+ visibleStateViewSlices->Array.map(listPage),
942
+ ])
943
+ {remoteEntryUrl, panels, pages}
944
+ }
945
+
946
+ let makePluginDefinition = (
947
+ ~name: string,
948
+ ~aggregates: array<module(ReventlessInfra.Aggregate.T with type api = api)>=[],
949
+ ~readModels: array<
950
+ module(ReventlessInfra.ReadModel.T with type api = api and type role = role),
951
+ >=[],
952
+ ~stateViewSlices: array<module(ReventlessInfra.StateViewSlice.T)>=[],
953
+ ~stateChangeSlices: array<module(ReventlessInfra.StateChangeSlice.T)>=[],
954
+ ~automationSlices: array<module(ReventlessInfra.AutomationSlice.T)>=[],
955
+ ~outboundTranslationSlices: array<module(ReventlessInfra.OutboundTranslationSlice.T)>=[],
956
+ ~inboundTranslationSlices: array<module(ReventlessInfra.InboundTranslationSlice.T)>=[],
957
+ ~extensions: array<module(ReventlessInfra.Extension.Blueprint)>=[],
958
+ ~extensionPoints: array<module(ReventlessInfra.ExtensionPointMapping.Mapping)>=[],
959
+ ): Reventless.Plugin.pluginStructure =>
960
+ Plugin_Structure.make(
961
+ ~name,
962
+ ~aggregates,
963
+ ~readModels,
964
+ ~stateViewSlices,
965
+ ~stateChangeSlices,
966
+ ~automationSlices,
967
+ ~outboundTranslationSlices,
968
+ ~inboundTranslationSlices,
969
+ ~extensions,
970
+ ~extensionPoints,
971
+ )
972
+
973
+ let make = (
974
+ ~name,
975
+ ~heartbeatInterval,
976
+ ~extensionPoints=[],
977
+ ~extensions=[],
978
+ ~aggregates: array<module(ReventlessInfra.Aggregate.T with type api = api)>=[],
979
+ ~readModels: array<
980
+ module(ReventlessInfra.ReadModel.T with type api = api and type role = role),
981
+ >=[],
982
+ ~tasks=[],
983
+ ~stateChangeSlices=[],
984
+ ~stateViewSlices=[],
985
+ ~automationSlices=[],
986
+ ~outboundTranslationSlices=[],
987
+ ~inboundTranslationSlices=[],
988
+ ~uiFragments: option<Reventless.Plugin.uiFragmentManifest>=?,
989
+ ~pluginStructure: option<Reventless.Plugin.pluginStructure>=?,
990
+ ~opts=?,
991
+ ) => {
992
+ PluginRuntimeBuilder.registerPluginName(name)
993
+ let version = Reventless.PackageVersion.fromCaller()
994
+ Component.make(
995
+ ~componentType=Plugin.componentType->ComponentType.toString,
996
+ ~name,
997
+ ~construct=construct(
998
+ ~version,
999
+ ~heartbeatInterval,
1000
+ ~extensionPoints,
1001
+ ~extensions,
1002
+ ~aggregates,
1003
+ ~readModels,
1004
+ ~tasks,
1005
+ ~stateChangeSlices,
1006
+ ~stateViewSlices,
1007
+ ~automationSlices,
1008
+ ~outboundTranslationSlices,
1009
+ ~inboundTranslationSlices,
1010
+ ~uiFragments,
1011
+ ~pluginStructure,
1012
+ ...
1013
+ ),
1014
+ ~opts,
1015
+ )
1016
+ }
1017
+ }