@reventlessdev/reventless-core 3.0.0-alpha.260 → 3.0.0-alpha.261

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 (203) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/package.json +9 -9
  3. package/src/Behavior.res +1 -4
  4. package/src/Message.res +17 -14
  5. package/src/Projection.res +51 -25
  6. package/src/RequestContext.res +8 -9
  7. package/src/ResourceAttribution.res +28 -14
  8. package/src/adapter/Adapter.res +48 -4
  9. package/src/adapter/EventLogProvisioning/EventLogProvisioning.res +5 -5
  10. package/src/adapter/Messaging/Messaging_Log_Backend.res +10 -7
  11. package/src/adapter/Messaging/Messaging_Log_Backend.res.mjs +2 -4
  12. package/src/adapter/Monitoring/Monitoring.res +16 -17
  13. package/src/adapter/QueryInterception/QueryInterception.res +0 -1
  14. package/src/adapter/Runtime/AggregateRuntime_Builder_Common.res +12 -5
  15. package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res +11 -7
  16. package/src/adapter/Runtime/PluginRuntime_Builder_Micro.res +1 -7
  17. package/src/adapter/Runtime/PluginRuntime_Builder_Single.res +1 -7
  18. package/src/adapter/RuntimeExtension/RuntimeExtension.res +0 -1
  19. package/src/admin/Platform_Admin.res +17 -6
  20. package/src/admin/Platform_AdminApi.res +14 -9
  21. package/src/admin/Platform_Admin_Callback.res +1 -1
  22. package/src/admin/Platform_BakedManifest.res +34 -34
  23. package/src/admin/Platform_ComponentDefinitionsApi.res +9 -21
  24. package/src/admin/Platform_PluginStructuresApi.res +15 -12
  25. package/src/admin/UiFragmentRegistry/StateChange/UiFragmentRegistry.res +1 -1
  26. package/src/components/Aggregate/Aggregate.res +13 -12
  27. package/src/components/Aggregate/Aggregate_Builder.res +22 -21
  28. package/src/components/Aggregate/Aggregate_Callback.res +91 -86
  29. package/src/components/Api/ApiNoApiHelpers.res +1 -3
  30. package/src/components/Api/Api_Ids.res +0 -1
  31. package/src/components/Api/Api_Naming.res +41 -18
  32. package/src/components/Api/GraphQL_FragmentGenerator.res +38 -51
  33. package/src/components/Api/GraphQL_SchemaInspector.res +5 -3
  34. package/src/components/Api/GraphQL_Stitcher.res +9 -10
  35. package/src/components/Api/MCP_SchemaGenerator.res +8 -12
  36. package/src/components/Api/OwnerScopeDiagnostics.res +1 -2
  37. package/src/components/Api/QueryDbListQuery.res +13 -6
  38. package/src/components/Api/SchemaType.res +28 -23
  39. package/src/components/Api/SuryToJsonSchema.res +9 -10
  40. package/src/components/AutomationSlice/AutomationSlice.res +4 -4
  41. package/src/components/AutomationSlice/AutomationSlice_Builder.res +15 -14
  42. package/src/components/AutomationSlice/AutomationSlice_Callback.res +3 -3
  43. package/src/components/Builder_Helpers.res +12 -23
  44. package/src/components/CommandGenerator/CommandGenerator.res +6 -1
  45. package/src/components/CommandGenerator/CommandGenerator_Builder.res +29 -21
  46. package/src/components/CommandGenerator/CommandGenerator_Callback.res +17 -21
  47. package/src/components/CommandTopic/CommandTopic.res +3 -3
  48. package/src/components/CommandTopic/CommandTopic_Builder.res +10 -10
  49. package/src/components/CommandTopic/CommandTopic_Callback.res +1 -4
  50. package/src/components/CommandTopic/CommandTopic_Helpers.res +1 -2
  51. package/src/components/Counter/Counter_Builder.res +1 -6
  52. package/src/components/Counter/Counter_Callback.res +3 -3
  53. package/src/components/Dcb/Dcb_Builder.res +970 -956
  54. package/src/components/DcbEventLog/DcbEventLog.res +4 -4
  55. package/src/components/DcbEventLog/DcbEventLog_Builder.res +0 -1
  56. package/src/components/DcbEventLog/DcbEventLog_Operations.res +17 -18
  57. package/src/components/EventCollector/EventCollector_Builder.res +2 -1
  58. package/src/components/EventLog/EventLog.res +5 -1
  59. package/src/components/EventLog/EventLog_Operations.res +12 -8
  60. package/src/components/EventMapper/EventMapper.res +8 -10
  61. package/src/components/EventMapper/EventMapper_Builder.res +4 -1
  62. package/src/components/EventMapper/EventMapper_Callback.res +46 -31
  63. package/src/components/EventTopic/EventTopic.res +3 -3
  64. package/src/components/EventTopic/EventTopic_Builder.res +1 -1
  65. package/src/components/Extension/Extension.res +4 -1
  66. package/src/components/Extension/Extension_Operations.res +11 -3
  67. package/src/components/ExtensionPoint/ExtensionPoint.res +3 -3
  68. package/src/components/ExtensionPoint/ExtensionPoint_Builder.res +9 -10
  69. package/src/components/ExtensionPoint/ExtensionPoint_Callback.res +2 -6
  70. package/src/components/ExtensionPoint/ExtensionPoint_Operations.res +13 -5
  71. package/src/components/Heartbeat/Heartbeat_Callback.res +3 -3
  72. package/src/components/InboundTranslationSlice/InboundTranslationSlice.res +4 -4
  73. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res +7 -10
  74. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice.res +4 -4
  75. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res +15 -14
  76. package/src/components/QueryDb/QueryDb_Adapter.res +1 -3
  77. package/src/components/QueryDb/QueryDb_Operations.res +10 -10
  78. package/src/components/ReadModel/ReadModel.res +3 -3
  79. package/src/components/ReadModel/ReadModel_Builder.res +1 -2
  80. package/src/components/ReadModel/ReadModel_Callback.res +2 -1
  81. package/src/components/SideEffectHandler/SideEffectHandler_Callback.res +5 -2
  82. package/src/components/StateChangeSlice/StateChangeSlice.res +3 -3
  83. package/src/components/StateChangeSlice/StateChangeSlice_Builder.res +23 -4
  84. package/src/components/StateChangeSlice/StateChangeSlice_Callback.res +22 -6
  85. package/src/components/StateTopic.res +1 -3
  86. package/src/components/StateViewSlice/StateViewSlice.res +4 -4
  87. package/src/components/StateViewSlice/StateViewSlice_Builder.res +79 -68
  88. package/src/components/StateViewSlice/StateViewSlice_Callback.res +3 -1
  89. package/src/components/Task/Task.res +3 -3
  90. package/src/components/Task/Task_Adapter.res +4 -1
  91. package/src/components/Task/Task_Builder.res +24 -21
  92. package/src/plugin/api/PluginBaseFragment.res +9 -3
  93. package/src/plugin/component/Capability_Inference.res +8 -10
  94. package/src/plugin/component/Plugin.res +6 -6
  95. package/src/plugin/component/Plugin_Builder.res +54 -50
  96. package/src/plugin/component/Plugin_Callback.res +10 -6
  97. package/src/plugin/component/Plugin_Helpers.res +264 -230
  98. package/src/plugin/component/Plugin_Structure.res +370 -324
  99. package/src/plugin/component/Plugin_SubscriptionSchema.res +8 -6
  100. package/src/plugin/component/SchemaWalker.res +11 -12
  101. package/src/plugin/connect/PluginConnectExtension_Mapping.res +45 -50
  102. package/src/plugin/lifecycle/PluginBehavior.res +3 -4
  103. package/src/plugin/lifecycle/PluginSpec.res +1 -2
  104. package/src/plugin/lifecycle/PluginsProjection.res +16 -5
  105. package/src/plugin/lifecycle/PluginsReadModelSpec.res +0 -2
  106. package/src/util/CommandPublisher.res +9 -2
  107. package/src/util/CsvStream.res +3 -3
  108. package/src/util/Interstack.res +7 -15
  109. package/src/util/Interstack.resi +3 -3
  110. package/src/util/LogFormat.res +5 -9
  111. package/src/util/Logger.res +1 -2
  112. package/src/util/Lru.res +2 -1
  113. package/src/util/Lru.resi +2 -3
  114. package/src/util/ScheduleOps.res +24 -27
  115. package/src/util/StorePrefixCollision.res +6 -9
  116. package/src/util/Util_Promise.res +4 -1
  117. package/src/util/Util_Promise.res.mjs +1 -1
  118. package/tests/IdentityTest.res +166 -113
  119. package/tests/ResourceAttributionTest.res +28 -25
  120. package/tests/StorePrefixCollisionTest.res +2 -1
  121. package/tests/TaskBucketNamingTest.res +3 -2
  122. package/tests/adapter/EventLogProvisioningTest.res +51 -48
  123. package/tests/adapter/MonitoringTest.res +81 -38
  124. package/tests/adapter/QueryInterceptionTest.res +2 -2
  125. package/tests/adapter/RefusalVocabularyTest.res +31 -23
  126. package/tests/adapter/RuntimeExtensionHookReachTest.res +9 -8
  127. package/tests/adapter/RuntimeExtensionTest.res +5 -3
  128. package/tests/admin/AdminApiSchemaDriftTest.res +22 -16
  129. package/tests/admin/Platform_Admin_StructureTest.res +10 -11
  130. package/tests/admin/Platform_BakedManifestTest.res +31 -35
  131. package/tests/admin/Platform_ComponentDefinitionsApiTest.res +18 -15
  132. package/tests/admin/Platform_PluginStructuresApiTest.res +5 -3
  133. package/tests/admin/Platform_UIFragmentsApiTest.res +6 -3
  134. package/tests/aggregate/AggregateCacheTest.res +10 -12
  135. package/tests/aggregate/AggregateCallbackTest.res +75 -46
  136. package/tests/aggregate/AggregateCausationTest.res +19 -20
  137. package/tests/aggregate/AggregateConflictTest.res +41 -19
  138. package/tests/aggregate/AggregateFixtures.res +15 -5
  139. package/tests/aggregate/AggregateRejectionTest.res +97 -80
  140. package/tests/aggregate/AggregateSnapshotTest.res +44 -16
  141. package/tests/api/Api_IdsTest.res +10 -4
  142. package/tests/api/BrandedMarkerCompositionTest.res +48 -36
  143. package/tests/api/GeolocationSemanticTest.res +3 -3
  144. package/tests/api/GraphQL_FragmentGeneratorTest.res +66 -54
  145. package/tests/api/OwnerScopeDiagnosticsTest.res +31 -27
  146. package/tests/api/StorageRefFieldsTest.res +30 -18
  147. package/tests/api/SuryToJsonSchemaTest.res +1315 -1014
  148. package/tests/api/TaggedUnionSchemaTest.res +17 -24
  149. package/tests/commandgenerator/CommandGeneratorCallbackTest.res +235 -179
  150. package/tests/commandgenerator/CommandGeneratorFixtures.res +8 -13
  151. package/tests/commandgenerator/OwnerStampingTest.res +91 -76
  152. package/tests/commandtopic/CommandOutcomeHookTest.res +198 -155
  153. package/tests/commandtopic/CommandTopicCallbackFixtures.res +5 -4
  154. package/tests/commandtopic/CommandTopicCallbackTest.res +61 -43
  155. package/tests/commandtopic/CommandTopicHelpersRejectionTest.res +70 -55
  156. package/tests/counter/CounterCallbackTest.res +40 -34
  157. package/tests/counter/CounterFixtures.res +4 -4
  158. package/tests/dcb/DcbDecodeTest.res +115 -84
  159. package/tests/dcb/DcbEventLogOperationsTest.res +194 -143
  160. package/tests/dcb/DcbEventLogSchemaTest.res +13 -13
  161. package/tests/dcb/DcbFixtures.res +4 -5
  162. package/tests/dcb/DcbScopeInferenceTest.res +173 -114
  163. package/tests/dcb/DcbStateChangeSliceTest.res +391 -262
  164. package/tests/dcb/DcbTagTest.res +22 -11
  165. package/tests/dcb/DcbValidationTest.res +288 -218
  166. package/tests/eventlog/EventLogFixtures.res +4 -4
  167. package/tests/eventlog/EventLogOperationsTest.res +102 -67
  168. package/tests/eventlog/EventLogRetryTest.res +104 -65
  169. package/tests/eventmapper/EventMapperCallbackTest.res +118 -83
  170. package/tests/eventmapper/EventMapperFixtures.res +15 -23
  171. package/tests/eventmapper/EventMapperTest.res +54 -38
  172. package/tests/eventtopic/EventTopicFixtures.res +3 -4
  173. package/tests/eventtopic/EventTopicOperationsTest.res +41 -29
  174. package/tests/extensionpoint/ExtensionPointCallbackTest.res +58 -45
  175. package/tests/extensionpoint/ExtensionPointFixtures.res +16 -20
  176. package/tests/extensionpoint/ExtensionPointOperationsTest.res +70 -49
  177. package/tests/extensionpoint/PluginDisconnectScheduleTest.res +2 -1
  178. package/tests/logger/LogFormatTest.res +104 -82
  179. package/tests/logger/LoggerLazyTest.res +21 -12
  180. package/tests/message/MessageTest.res +96 -93
  181. package/tests/message/MetaEnvelopeTest.res +26 -30
  182. package/tests/plugin/HeartbeatDisconnectGraceTest.res +31 -25
  183. package/tests/plugin/ManifestVisibilityTest.res +20 -12
  184. package/tests/plugin/PluginDefinitionScalars.res +1 -2
  185. package/tests/plugin/PluginLifecycleCorpusTest.res +15 -12
  186. package/tests/plugin/PluginSpecExperiment.res +0 -1
  187. package/tests/plugin/PluginStructureTest.res +1529 -1045
  188. package/tests/plugin/Plugin_EventQuerySchemaTest.res +21 -10
  189. package/tests/plugin/SchemaWalkerTest.res +116 -70
  190. package/tests/plugin/StateChange/PsReserveStock.res +4 -4
  191. package/tests/plugin/StateView/PsAnnotatedView.res +4 -4
  192. package/tests/plugin/StateView/PsCustomersView.res +4 -4
  193. package/tests/plugin/StateView/PsShipmentsView.res +3 -2
  194. package/tests/projection/LifecycleTrailTest.res +1 -4
  195. package/tests/projection/ProjectionOptimizeTest.res +13 -9
  196. package/tests/querydb/QueryDbFixtures.res +0 -1
  197. package/tests/querydb/QueryDbOperationsTest.res +99 -64
  198. package/tests/querydb/TaggedUnionStampTest.res +10 -8
  199. package/tests/sideeffecthandler/SideEffectHandlerCallbackTest.res +50 -35
  200. package/tests/sideeffecthandler/SideEffectHandlerFixtures.res +4 -10
  201. package/tests/util/CommandPublisherTest.res +0 -1
  202. package/tests/util/CsvStreamTest.res +3 -3
  203. package/tests/util/LruTest.res +84 -56
@@ -28,8 +28,7 @@ let buildDescriptionSuffix = (
28
28
  ~entry: ReventlessInfra.Api.mutationSchemaEntry,
29
29
  ): string => {
30
30
  let viewsSuffix = switch entry.linkedViews {
31
- | Some(views) if views->Array.length > 0 =>
32
- ` Affects views: ${views->Array.join(", ")}.`
31
+ | Some(views) if views->Array.length > 0 => ` Affects views: ${views->Array.join(", ")}.`
33
32
  | _ => ""
34
33
  }
35
34
  let consistencySuffix = switch entry.consistencyRead {
@@ -41,10 +40,9 @@ let buildDescriptionSuffix = (
41
40
 
42
41
  /** Generate MCP tool definitions from mutation entries.
43
42
  Each command variant becomes a separate tool. */
44
- let generateTools = (
45
- ~pluginName: string,
46
- ~mutationEntries: array<mutationSchemaEntry>,
47
- ): array<mcpToolDefinition> => {
43
+ let generateTools = (~pluginName: string, ~mutationEntries: array<mutationSchemaEntry>): array<
44
+ mcpToolDefinition,
45
+ > => {
48
46
  let tools: array<mcpToolDefinition> = []
49
47
 
50
48
  mutationEntries->Array.forEach(entry => {
@@ -87,8 +85,7 @@ let generateTools = (
87
85
  obj->Dict.set("required", JSON.Encode.array(arr))
88
86
  | None => ()
89
87
  }
90
- | None =>
91
- obj->Dict.set("required", JSON.Encode.array([JSON.Encode.string("id")]))
88
+ | None => obj->Dict.set("required", JSON.Encode.array([JSON.Encode.string("id")]))
92
89
  }
93
90
  JSON.Encode.object(obj)
94
91
  | None => inputSchema
@@ -124,10 +121,9 @@ let generateTools = (
124
121
 
125
122
  /** Generate MCP resource definitions from query entries.
126
123
  Each query entry becomes one or two resources (single + list). */
127
- let generateResources = (
128
- ~pluginName: string,
129
- ~queryEntries: array<querySchemaEntry>,
130
- ): array<mcpResourceDefinition> => {
124
+ let generateResources = (~pluginName: string, ~queryEntries: array<querySchemaEntry>): array<
125
+ mcpResourceDefinition,
126
+ > => {
131
127
  let resources: array<mcpResourceDefinition> = []
132
128
 
133
129
  queryEntries->Array.forEach(entry => {
@@ -43,8 +43,7 @@ let warnIfNoElevatedGroups = (~comp: string, ~view: string, ~ownerField: option<
43
43
  `${view}: "${field}" is declared @owner, but no elevated groups are configured. ` ++
44
44
  "Every caller — administrators included — will see only their own rows. " ++
45
45
  "Call OwnerScope.setElevatedGroups([...]) before components are built, or set " ++
46
- "REVENTLESS_ELEVATED_GROUPS — the environment is what reaches a deployment's " ++
47
- "separate function runtimes, which a call in the deploy program does not.",
46
+ "REVENTLESS_ELEVATED_GROUPS — the environment is what reaches a deployment's " ++ "separate function runtimes, which a call in the deploy program does not.",
48
47
  )
49
48
  }
50
49
  | _ => ()
@@ -66,10 +66,14 @@ let buildConnection = (
66
66
  ~cursorValueOf: JSON.t => string,
67
67
  ): JSON.t => {
68
68
  let edges =
69
- pageItems->Array.map(item => Obj.magic({"node": item, "cursor": encodeCursor(cursorValueOf(item))}))
69
+ pageItems->Array.map(item =>
70
+ Obj.magic({"node": item, "cursor": encodeCursor(cursorValueOf(item))})
71
+ )
70
72
  let startCursor = pageItems->Array.get(0)->Option.map(item => encodeCursor(cursorValueOf(item)))
71
73
  let endCursor =
72
- pageItems->Array.get(pageItems->Array.length - 1)->Option.map(item => encodeCursor(cursorValueOf(item)))
74
+ pageItems
75
+ ->Array.get(pageItems->Array.length - 1)
76
+ ->Option.map(item => encodeCursor(cursorValueOf(item)))
73
77
  Obj.magic({
74
78
  "edges": edges,
75
79
  "pageInfo": {
@@ -130,7 +134,7 @@ let run = (
130
134
  let perFieldChecks: array<JSON.t => bool> = capability.filterFields->Array.flatMap(f => {
131
135
  let checks: array<JSON.t => bool> = []
132
136
  switch filterDict->Dict.get(f.name ++ "Eq") {
133
- | Some(v) when v != JSON.Encode.null =>
137
+ | Some(v) if v != JSON.Encode.null =>
134
138
  let expected = switch v->JSON.Decode.string {
135
139
  | Some(s) => s
136
140
  | None => v->JSON.Decode.float->Option.map(f => Float.toString(f))->Option.getOr("")
@@ -142,16 +146,18 @@ let run = (
142
146
  }
143
147
  if f.range {
144
148
  switch filterDict->Dict.get(f.name ++ "From") {
145
- | Some(v) when v != JSON.Encode.null =>
149
+ | Some(v) if v != JSON.Encode.null =>
146
150
  let from =
147
151
  v
148
152
  ->JSON.Decode.string
149
153
  ->Option.getOr(v->JSON.Decode.float->Option.map(f => Float.toString(f))->Option.getOr(""))
150
- checks->Array.push(item => getFieldString(item, f.name)->Option.mapOr(false, v => v >= from))
154
+ checks->Array.push(item =>
155
+ getFieldString(item, f.name)->Option.mapOr(false, v => v >= from)
156
+ )
151
157
  | _ => ()
152
158
  }
153
159
  switch filterDict->Dict.get(f.name ++ "To") {
154
- | Some(v) when v != JSON.Encode.null =>
160
+ | Some(v) if v != JSON.Encode.null =>
155
161
  let to_ =
156
162
  v
157
163
  ->JSON.Decode.string
@@ -207,6 +213,7 @@ let run = (
207
213
  item->JSON.Decode.object->Option.flatMap(d => d->Dict.get(scope.field)),
208
214
  )
209
215
  )
216
+
210
217
  | None => true
211
218
  }
212
219
  passSearch && passPrefix && passIds && passPerField && passOwner && passRetired
@@ -1,44 +1,44 @@
1
1
  type rec schemaType =
2
2
  | ScalarString
3
3
  | ScalarNumber
4
- | /** A number the schema says is whole. sury carries the fact on the number's
4
+ /** A number the schema says is whole. sury carries the fact on the number's
5
5
  `format`, and it was being dropped here — so every `int` in the domain
6
6
  reached the SDL as `Float` and JSON Schema as `"number"`, and a quantity
7
7
  was a field a client could legally send `2.5` in. */
8
- ScalarInt
8
+ | ScalarInt
9
9
  | ScalarBoolean
10
10
  | ScalarBigInt
11
11
  | EntityId
12
12
  | DateTime
13
- | /** A calendar day, with no instant in it. A shape of its own rather than a
13
+ /** A calendar day, with no instant in it. A shape of its own rather than a
14
14
  plain string so `format: "date"` reaches the JSON Schema — but, unlike
15
15
  `DateTime`, it is not excluded from the generic semantic wrapper below,
16
16
  so it carries `x-reventless-semantic` as well. `DateTime`'s exclusion
17
17
  exists because its bare-`format` output predates the marker and is a
18
18
  published contract; a new semantic has no such history. */
19
- CalendarDate
19
+ | CalendarDate
20
20
  | Nullable(schemaType)
21
21
  | ArrayOf(schemaType)
22
22
  | ObjectRef(string, dict<schemaType>)
23
23
  | Enum(string, array<string>)
24
- | /** A field whose type carries a semantic the IR has no dedicated shape for.
24
+ /** A field whose type carries a semantic the IR has no dedicated shape for.
25
25
  Wraps the shape the value actually has, so every consumer that only cares
26
26
  about shape unwraps and is otherwise unaffected. `DateTime` and `EntityId`
27
27
  are *not* expressed this way: they long predate the generic marker and
28
28
  their JSON Schema `format` output is a published contract. */
29
- Semantic(Reventless.Semantic.t, schemaType)
30
- | /** A field whose type declares the value it opens with. Wraps the shape the
29
+ | Semantic(Reventless.Semantic.t, schemaType)
30
+ /** A field whose type declares the value it opens with. Wraps the shape the
31
31
  value has, as `Semantic` does, so a consumer that cares only about shape
32
32
  unwraps: a default changes where a form starts, never what the field is. */
33
- Defaulted(JSON.t, schemaType)
34
- | /** A variant used as a field: the union's name, and one arm per constructor
33
+ | Defaulted(JSON.t, schemaType)
34
+ /** A variant used as a field: the union's name, and one arm per constructor
35
35
  keyed by the `TAG` sury discriminates on. Each arm is the `ObjectRef` its
36
36
  member type is emitted from, so the arm's own name travels with it and
37
37
  every consumer that can already render an object renders an arm.
38
38
 
39
39
  Only a *named* union reaches this case — see `Reventless.TaggedUnion`,
40
40
  which owns the name and the arm rules both. */
41
- TaggedUnion(string, array<(string, schemaType)>)
41
+ | TaggedUnion(string, array<(string, schemaType)>)
42
42
  | Unknown
43
43
 
44
44
  let isTagged = Reventless.DcbTag.isTagged
@@ -96,7 +96,11 @@ let rec fromSury = (~parentName: string, ~fieldName: string, schema: S.t<unknown
96
96
  }
97
97
  }
98
98
 
99
- and withoutDefault = (~parentName: string, ~fieldName: string, schema: S.t<unknown>): schemaType => {
99
+ and withoutDefault = (
100
+ ~parentName: string,
101
+ ~fieldName: string,
102
+ schema: S.t<unknown>,
103
+ ): schemaType => {
100
104
  // Semantics the IR already has a dedicated shape for keep it: `dateTime` and
101
105
  // `reference` are read below via `isDateTime` / `getTarget`, both of which now
102
106
  // consult the generic marker, and their `format` output is a published
@@ -150,9 +154,10 @@ and shapeOf = (~parentName: string, ~fieldName: string, schema: S.t<unknown>): s
150
154
  | _ => ScalarString
151
155
  }
152
156
  }
153
- let itemType = (isIdsFieldName(fieldName) || isIdFieldName(fieldName)) && itemType == ScalarString
154
- ? EntityId
155
- : itemType
157
+ let itemType =
158
+ (isIdsFieldName(fieldName) || isIdFieldName(fieldName)) && itemType == ScalarString
159
+ ? EntityId
160
+ : itemType
156
161
  ArrayOf(itemType)
157
162
  | Object({properties}) =>
158
163
  let nestedName =
@@ -164,7 +169,10 @@ and shapeOf = (~parentName: string, ~fieldName: string, schema: S.t<unknown>): s
164
169
  ->Dict.toArray
165
170
  ->Array.forEach(((propName, propSchema)) => {
166
171
  if propName !== "TAG" {
167
- fields->Dict.set(propName, fromSury(~parentName=nestedName, ~fieldName=propName, propSchema))
172
+ fields->Dict.set(
173
+ propName,
174
+ fromSury(~parentName=nestedName, ~fieldName=propName, propSchema),
175
+ )
168
176
  }
169
177
  })
170
178
  if fields->Dict.keysToArray->Array.length == 0 {
@@ -181,13 +189,7 @@ and shapeOf = (~parentName: string, ~fieldName: string, schema: S.t<unknown>): s
181
189
  )
182
190
  let isOptional = nonNullVariants->Array.length < anyOf->Array.length
183
191
  if nonNullVariants->Array.length == 1 {
184
- Nullable(
185
- fromSury(
186
- ~parentName,
187
- ~fieldName,
188
- nonNullVariants->Array.getUnsafe(0),
189
- ),
190
- )
192
+ Nullable(fromSury(~parentName, ~fieldName, nonNullVariants->Array.getUnsafe(0)))
191
193
  } else {
192
194
  let constValues = nonNullVariants->Array.filterMap(v =>
193
195
  switch v {
@@ -195,7 +197,10 @@ and shapeOf = (~parentName: string, ~fieldName: string, schema: S.t<unknown>): s
195
197
  | _ => None
196
198
  }
197
199
  )
198
- if constValues->Array.length == nonNullVariants->Array.length && constValues->Array.length > 0 {
200
+ if (
201
+ constValues->Array.length == nonNullVariants->Array.length &&
202
+ constValues->Array.length > 0
203
+ ) {
199
204
  let enumName =
200
205
  parentName ++
201
206
  fieldName->String.charAt(0)->String.toUpperCase ++
@@ -13,10 +13,10 @@ let jsonObject = (entries: array<(string, JSON.t)>): JSON.t =>
13
13
  // An absent plugin means "the declaring plugin's own", which the key's absence
14
14
  // says exactly. Writing an empty string instead would make "mine" and "unnamed"
15
15
  // indistinguishable to every reader.
16
- let withOptionalPlugin = (
17
- entries: array<(string, JSON.t)>,
18
- plugin: option<string>,
19
- ): array<(string, JSON.t)> =>
16
+ let withOptionalPlugin = (entries: array<(string, JSON.t)>, plugin: option<string>): array<(
17
+ string,
18
+ JSON.t,
19
+ )> =>
20
20
  switch plugin {
21
21
  | Some(p) => entries->Array.concat([("plugin", JSON.Encode.string(p))])
22
22
  | None => entries
@@ -47,8 +47,7 @@ let mergeAnnotations = (
47
47
  }
48
48
  switch spec.indexes->Array.find(((field, _)) => field === fieldName) {
49
49
  | Some((_, indexName)) =>
50
- let value =
51
- indexName === "" ? JSON.Encode.bool(true) : JSON.Encode.string(indexName)
50
+ let value = indexName === "" ? JSON.Encode.bool(true) : JSON.Encode.string(indexName)
52
51
  obj->Dict.set("x-reventless-index", value)
53
52
  | None => ()
54
53
  }
@@ -141,10 +140,9 @@ let mergeAnnotations = (
141
140
  // the keys above follow: false is what every record said before the opt-in
142
141
  // existed, and writing it would put a key on every retirement to say
143
142
  // nothing changed.
144
- let entries =
145
- r.namedWhenRetired
146
- ? Array.concat(entries, [("namedWhenRetired", JSON.Encode.bool(true))])
147
- : entries
143
+ let entries = r.namedWhenRetired
144
+ ? Array.concat(entries, [("namedWhenRetired", JSON.Encode.bool(true))])
145
+ : entries
148
146
  obj->Dict.set("x-reventless-retired", JSON.Encode.object(Dict.fromArray(entries)))
149
147
  | _ => ()
150
148
  }
@@ -428,6 +426,7 @@ and objectRefToJsonSchema = (
428
426
  | None => withAnnotations
429
427
  }
430
428
  props->Dict.set(fieldName, withAnnotations)
429
+
431
430
  // Optional two ways, because neither source answers alone. `optional` is
432
431
  // read off the sury schema and is the only thing that can speak for a
433
432
  // reference or a tagged field, which classify as `EntityId` before their
@@ -5,9 +5,9 @@ type outputs = ReventlessInfra.AutomationSlice.outputs
5
5
  type operations = ReventlessInfra.AutomationSlice.operations
6
6
  type component = Component.t<t, outputs, operations>
7
7
 
8
- let toResolvedOutputs = (
9
- outputs: outputs,
10
- ): Pulumi.Output.t<ReventlessInterop.AutomationSlice.resolvedOutputs> =>
8
+ let toResolvedOutputs = (outputs: outputs): Pulumi.Output.t<
9
+ ReventlessInterop.AutomationSlice.resolvedOutputs,
10
+ > =>
11
11
  (
12
12
  outputs.resources->Adapter.resourcesToInterop,
13
13
  outputs.queryDb.resources->Adapter.resourcesToInterop,
@@ -15,7 +15,7 @@ let toResolvedOutputs = (
15
15
  ->Pulumi.Output.all2
16
16
  ->Pulumi.Output.apply(((resources, queryDbResources)) => {
17
17
  let resolved: ReventlessInterop.AutomationSlice.resolvedOutputs = {
18
- resources: resources,
18
+ resources,
19
19
  queryDb: {resources: queryDbResources},
20
20
  }
21
21
  resolved
@@ -110,8 +110,7 @@ module Make = (
110
110
  `AutomationSlice "${Spec.name}" has a Mapping with sourceName "${sourceName}", ` ++
111
111
  `but no EventTopic with that key exists in allEventTopics. ` ++
112
112
  `Available source names: [${availableNames}]. ` ++
113
- `Check Mapping.Make's first arg matches an Aggregate Spec.name or a DCB ` ++
114
- `source name (typically "<pluginName>DcbEventLog").`,
113
+ `Check Mapping.Make's first arg matches an Aggregate Spec.name or a DCB ` ++ `source name (typically "<pluginName>DcbEventLog").`,
115
114
  )
116
115
  }
117
116
  )
@@ -159,18 +158,20 @@ module Make = (
159
158
  let _ =
160
159
  Callback.phase2(publishJsonsFn)
161
160
  ->Promise.then(() => syncToQueryDb(queryDbOps))
162
- ->Promise.catch(exn => {
163
- let errMsg =
164
- exn
165
- ->JsExn.fromException
166
- ->Option.flatMap(JsExn.message)
167
- ->Option.getOr("unknown")
168
- EffectLogger.logError(
169
- ~comp=`AutomationSlice(${Spec.name})`,
170
- `detached phase 2 error: ${errMsg}`,
171
- )->Effect.runSync
172
- Promise.resolve()
173
- })
161
+ ->Promise.catch(
162
+ exn => {
163
+ let errMsg =
164
+ exn
165
+ ->JsExn.fromException
166
+ ->Option.flatMap(JsExn.message)
167
+ ->Option.getOr("unknown")
168
+ EffectLogger.logError(
169
+ ~comp=`AutomationSlice(${Spec.name})`,
170
+ `detached phase 2 error: ${errMsg}`,
171
+ )->Effect.runSync
172
+ Promise.resolve()
173
+ },
174
+ )
174
175
  },
175
176
  )
176
177
  )
@@ -172,9 +172,9 @@ module Make = (
172
172
  handle: (JSON.t, ~sourceId: string, Reventless.AutomationSlice.context) => unit,
173
173
  }
174
174
 
175
- let dispatches: array<dispatch> = Automation.mappings->Array.map((
176
- module(M: Automation.Mapping),
177
- ) => {
175
+ let dispatches: array<
176
+ dispatch,
177
+ > = Automation.mappings->Array.map((module(M: Automation.Mapping)) => {
178
178
  let decoder = Reventless.DcbDecode.makeDecoder(M.sourceEventSchema)
179
179
  let handle = (json: JSON.t, ~sourceId: string, ctx: Reventless.AutomationSlice.context) => {
180
180
  let (eventType, dataDict) = json->Message.splitMessage
@@ -30,14 +30,9 @@ let createAggregatesWithoutEventMappers = (
30
30
  ~opts,
31
31
  )
32
32
  let aggOutputs = SpecificAggregate.outputs(aggregate)
33
- addEventMapperFns->Dict.set(
34
- SpecificAggregate.Spec.name,
35
- aggOutputs.addEventMapper,
36
- )
33
+ addEventMapperFns->Dict.set(SpecificAggregate.Spec.name, aggOutputs.addEventMapper)
37
34
  let resources =
38
- aggOutputs.commandTopic->Pulumi.Output.apply(commandTopic =>
39
- commandTopic.resources
40
- )
35
+ aggOutputs.commandTopic->Pulumi.Output.apply(commandTopic => commandTopic.resources)
41
36
  aggregateResources->Dict.set(SpecificAggregate.Spec.name, resources)
42
37
  let publishJsons =
43
38
  SpecificAggregate.operations(aggregate)->Pulumi.Output.apply(({publishJsons}) => publishJsons)
@@ -54,10 +49,7 @@ let createAggregatesWithoutEventMappers = (
54
49
  ->Array.map(aggregate => {(aggregate.name, aggregate)})
55
50
  ->Dict.fromArray
56
51
 
57
-
58
- let finishAggregates = (
59
- aggregatesOutputs: dict<Aggregate.outputs>,
60
- ) => {
52
+ let finishAggregates = (aggregatesOutputs: dict<Aggregate.outputs>) => {
61
53
  let allOutputs = aggregatesOutputs->Dict.valuesToArray
62
54
 
63
55
  // Wait for ALL commandTopicOutputs (not just those with event mappers)
@@ -89,10 +81,7 @@ let finishAggregates = (
89
81
  )
90
82
  }
91
83
 
92
- let addEventMappers = (
93
- allEventTopics,
94
- queryEngine,
95
- ) => {
84
+ let addEventMappers = (allEventTopics, queryEngine) => {
96
85
  let aggregatesOutputs =
97
86
  addEventMapperFns->Dict.mapValues(addEventMapperFn =>
98
87
  addEventMapperFn(allEventTopics, queryEngine)
@@ -126,9 +115,7 @@ let finishTasks = () =>
126
115
  let _ =
127
116
  taskSideEffectGates
128
117
  ->Pulumi.Output.all
129
- ->Pulumi.Output.apply(_ =>
130
- taskSideEffectFinishFns->Array.forEach(finishFn => finishFn())
131
- )
118
+ ->Pulumi.Output.apply(_ => taskSideEffectFinishFns->Array.forEach(finishFn => finishFn()))
132
119
  }
133
120
 
134
121
  let readModelNamesForSourceName = Dict.make()
@@ -154,8 +141,7 @@ let extractReadModelsOutputs = readModels =>
154
141
  ->Dict.fromArray
155
142
 
156
143
  let createReadModels = (
157
- type a,
158
- type r,
144
+ type a r,
159
145
  readModels: array<module(ReventlessInfra.ReadModel.T with type api = a and type role = r)>,
160
146
  ~api: a,
161
147
  ~apiRole: r,
@@ -163,7 +149,9 @@ let createReadModels = (
163
149
  allEventTopics,
164
150
  opts,
165
151
  ) => {
166
- let readModels = readModels->Array.map((module(SpecificReadModel: ReventlessInfra.ReadModel.T with type api = a and type role = r)) => {
152
+ let readModels = readModels->Array.map((
153
+ module(SpecificReadModel: ReventlessInfra.ReadModel.T with type api = a and type role = r),
154
+ ) => {
167
155
  let readModel = SpecificReadModel.make(
168
156
  ~api,
169
157
  ~apiRole,
@@ -222,8 +210,9 @@ let createExtensionPoints = (
222
210
  ~opts,
223
211
  ) => {
224
212
  let triples =
225
- extensionPoints
226
- ->Array.map((module(SpecificExtensionPoint: ReventlessInfra.ExtensionPoint.T)) => {
213
+ extensionPoints->Array.map((
214
+ module(SpecificExtensionPoint: ReventlessInfra.ExtensionPoint.T),
215
+ ) => {
227
216
  let extensionPoint = SpecificExtensionPoint.make(
228
217
  ~aggregateResources,
229
218
  ~publishToAggregates,
@@ -27,7 +27,12 @@ external asEvent: 'a => event = "%identity"
27
27
  let metaInfo = event => (event->asEvent).meta->Option.map(({info}) => info)
28
28
 
29
29
  type commandGenerator = payload => Effect.t<CommandTopic.commandOutcome, unit, unit>
30
- type effectEventHandler<'context> = Runtime.effectHandler<payload, 'context, CommandTopic.commandOutcome, unit>
30
+ type effectEventHandler<'context> = Runtime.effectHandler<
31
+ payload,
32
+ 'context,
33
+ CommandTopic.commandOutcome,
34
+ unit,
35
+ >
31
36
 
32
37
  type publishJsons = CommandTopic.publishJsons
33
38
 
@@ -1,25 +1,29 @@
1
- module Make = (
2
- Spec: Reventless.Aggregate.Spec,
3
- Resolvers: CommandGenerator_Adapter.Resolvers,
4
- ): (
1
+ module Make = (Spec: Reventless.Aggregate.Spec, Resolvers: CommandGenerator_Adapter.Resolvers): (
5
2
  CommandGenerator.T with type runtimeParts := Resolvers.runtimeParts and type api := Resolvers.api
6
3
  ) => {
7
4
  let construct = (self, _name) => {
8
- let resources = Plugin_Helpers.aggregateMutationFieldsRegistry->Dict.get(Spec.name)->Option.getOr([])->Array.map(field => {
9
- let r: ReventlessInfra.Adapter.resource = {
10
- id: ""->Pulumi.Output.make,
11
- resourceInfo: ReventlessInfra.Adapter.ApiResolver({typeName: "Mutation", fieldName: field})->Pulumi.Output.make,
12
- name: ""->Pulumi.Output.make,
13
- urn: ""->Pulumi.Output.make,
14
- service: ""->Pulumi.Output.make,
15
- role: "commandGenerator"->Pulumi.Output.make,
16
- region: ""->Pulumi.Output.make,
17
- resourceType: ""->Pulumi.Output.make,
18
- configuration: Dict.make()->Pulumi.Output.make,
19
- tags: Dict.make()->Pulumi.Output.make,
20
- }
21
- r
22
- })
5
+ let resources =
6
+ Plugin_Helpers.aggregateMutationFieldsRegistry
7
+ ->Dict.get(Spec.name)
8
+ ->Option.getOr([])
9
+ ->Array.map(field => {
10
+ let r: ReventlessInfra.Adapter.resource = {
11
+ id: ""->Pulumi.Output.make,
12
+ resourceInfo: ReventlessInfra.Adapter.ApiResolver({
13
+ typeName: "Mutation",
14
+ fieldName: field,
15
+ })->Pulumi.Output.make,
16
+ name: ""->Pulumi.Output.make,
17
+ urn: ""->Pulumi.Output.make,
18
+ service: ""->Pulumi.Output.make,
19
+ role: "commandGenerator"->Pulumi.Output.make,
20
+ region: ""->Pulumi.Output.make,
21
+ resourceType: ""->Pulumi.Output.make,
22
+ configuration: Dict.make()->Pulumi.Output.make,
23
+ tags: Dict.make()->Pulumi.Output.make,
24
+ }
25
+ r
26
+ })
23
27
  let outputs: CommandGenerator.outputs = {resources: resources}
24
28
  let _ = self->Component.setOutputs(outputs)
25
29
  }
@@ -32,7 +36,8 @@ module Make = (
32
36
  ->ComponentType.name(CommandGenerator.componentType)
33
37
  let opts = {Pulumi.ComponentResource.parent: commandGeneratorResource}
34
38
 
35
- let fields = Plugin_Helpers.aggregateMutationFieldsRegistry->Dict.get(Spec.name)->Option.getOr([])
39
+ let fields =
40
+ Plugin_Helpers.aggregateMutationFieldsRegistry->Dict.get(Spec.name)->Option.getOr([])
36
41
 
37
42
  let resolvers = Resolvers.make(
38
43
  ~name,
@@ -48,7 +53,10 @@ module Make = (
48
53
  let _ = commandGenerator->Component.setOutputs(cgOutputs)
49
54
  }
50
55
 
51
- let makeHandler = (~publishJsons, ~publishJsonsAndWait: option<CommandTopic.publishJsonsAndWait>) => {
56
+ let makeHandler = (
57
+ ~publishJsons,
58
+ ~publishJsonsAndWait: option<CommandTopic.publishJsonsAndWait>,
59
+ ) => {
52
60
  module Callback = CommandGenerator_Callback.Make(
53
61
  {
54
62
  let publishJsons = publishJsons
@@ -168,9 +168,7 @@ let makeGenerateCommand = (
168
168
  | Some(idValue) => idValue
169
169
  | None =>
170
170
  try {
171
- let derived = Reventless.DcbTag.derivePartitionTag([
172
- (serviceName, "", commandSchema),
173
- ])
171
+ let derived = Reventless.DcbTag.derivePartitionTag([(serviceName, "", commandSchema)])
174
172
  switch derived {
175
173
  | Simple(pt) =>
176
174
  let tags = Reventless.DcbTag.extractTagsFromJson(commandSchema, commandJson)
@@ -221,22 +219,23 @@ let makeGenerateCommand = (
221
219
  | Allow =>
222
220
  switch publishJsonsAndWait {
223
221
  | Some(publishAndWait) =>
224
- Effect.promise(() => publishAndWait([{id, meta, commandJson}]))
225
- ->Effect.map(outcomes => {
226
- // For aggregates, entityId comes from the envelope id.
227
- // DCB slices populate entityId via the side-channel; don't override it.
228
- switch outcomes->Array.getUnsafe(0) {
229
- | CommandTopic.Accepted(payload) when payload.entityId->Option.isNone =>
230
- CommandTopic.Accepted({...payload, entityId: id})
231
- | outcome => outcome
232
- }
233
- })
222
+ Effect.promise(() => publishAndWait([{id, meta, commandJson}]))->Effect.map(
223
+ outcomes => {
224
+ // For aggregates, entityId comes from the envelope id.
225
+ // DCB slices populate entityId via the side-channel; don't override it.
226
+ switch outcomes->Array.getUnsafe(0) {
227
+ | CommandTopic.Accepted(payload) if payload.entityId->Option.isNone =>
228
+ CommandTopic.Accepted({...payload, entityId: id})
229
+ | outcome => outcome
230
+ }
231
+ },
232
+ )
234
233
  | None =>
235
- Effect.promise(() => publishJsons([{id, meta, commandJson}]))
236
- ->Effect.map(_ => CommandTopic.Pending({msgId: meta.msgId}))
234
+ Effect.promise(() => publishJsons([{id, meta, commandJson}]))->Effect.map(
235
+ _ => CommandTopic.Pending({msgId: meta.msgId}),
236
+ )
237
237
  }
238
- | Deny(msg) =>
239
- JsError.throwWithMessage(msg)
238
+ | Deny(msg) => JsError.throwWithMessage(msg)
240
239
  }
241
240
  )
242
241
  | exception err =>
@@ -265,10 +264,7 @@ let makeGenerateCommand = (
265
264
  })
266
265
  }
267
266
 
268
- module Make = (
269
- Spec: Spec,
270
- AggregateSpec: Reventless.Aggregate.Spec,
271
- ): T => {
267
+ module Make = (Spec: Spec, AggregateSpec: Reventless.Aggregate.Spec): T => {
272
268
  let generateCommand = makeGenerateCommand(
273
269
  ~publishJsons=Spec.publishJsons,
274
270
  ~publishJsonsAndWait=?Spec.publishJsonsAndWait,
@@ -63,9 +63,9 @@ module type T = {
63
63
  ) => component
64
64
  }
65
65
 
66
- let toResolvedOutputs = (
67
- outputs: outputs,
68
- ): Pulumi.Output.t<ReventlessInterop.CommandTopic.resolvedOutputs> =>
66
+ let toResolvedOutputs = (outputs: outputs): Pulumi.Output.t<
67
+ ReventlessInterop.CommandTopic.resolvedOutputs,
68
+ > =>
69
69
  outputs.resources
70
70
  ->Adapter.resourcesToInterop
71
71
  ->Pulumi.Output.apply(resources => {
@@ -49,21 +49,21 @@ module Make = (Spec: ReventlessInfra.CommandTopic.T, Channel: CommandTopic_Adapt
49
49
  let handlers = CommandTopic.getHandlers(typeName)
50
50
  Effect.promise(async () => {
51
51
  let allResults: array<result<string, string>> = []
52
- let _ =
53
- await handlers
54
- ->Array.map(async handlerEntry => {
52
+ let _ = await handlers
53
+ ->Array.map(
54
+ async handlerEntry => {
55
55
  let {CommandTopic.handler: handler} = handlerEntry
56
56
  try {
57
- let results =
58
- await handler(
59
- Stream.fromIterable([{ReventlessInfra.CommandTopic.reference, command: json}]),
60
- )->Effect.runPromise
57
+ let results = await handler(
58
+ Stream.fromIterable([{ReventlessInfra.CommandTopic.reference, command: json}]),
59
+ )->Effect.runPromise
61
60
  allResults->Array.pushMany(results)
62
61
  } catch {
63
62
  | _ => () // Skip if handler fails
64
63
  }
65
- })
66
- ->Promise.all
64
+ },
65
+ )
66
+ ->Promise.all
67
67
  allResults
68
68
  })
69
69
  })
@@ -89,7 +89,7 @@ module Make = (Spec: ReventlessInfra.CommandTopic.T, Channel: CommandTopic_Adapt
89
89
  {
90
90
  publish: Operations.publish,
91
91
  publishJsons: Operations.publishJsons,
92
- publishJsonsStream: publishJsonsStream,
92
+ publishJsonsStream,
93
93
  publishJsonsAndWait,
94
94
  }
95
95
  }),
@@ -19,10 +19,7 @@ module Make = (Spec: ReventlessInfra.CommandTopic.T, Ops: Ops with module Spec =
19
19
  | exception err =>
20
20
  let commandStr = json->JSON.stringify
21
21
  let errMsg = err->Reventless.Util_Sury.exnMessage
22
- EffectLogger.logError(
23
- ~comp,
24
- `decode failed: ${commandStr} err=${errMsg}`,
25
- )->Effect.runSync
22
+ EffectLogger.logError(~comp, `decode failed: ${commandStr} err=${errMsg}`)->Effect.runSync
26
23
  None
27
24
  }
28
25
  )