@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
@@ -19,8 +19,14 @@ describe("Monitoring", () => {
19
19
  testSync("an announcement made before any backend is registered reaches the first one", () => {
20
20
  let recorded: array<(Monitoring.unitKind, string, option<string>)> = []
21
21
  module Late: Monitoring.Backend = {
22
- let onProvisioned = (~kind, ~name, ~component as _, ~plugin, ~platform as _, ~logLocator as _) =>
23
- recorded->Array.push((kind, name, plugin))
22
+ let onProvisioned = (
23
+ ~kind,
24
+ ~name,
25
+ ~component as _,
26
+ ~plugin,
27
+ ~platform as _,
28
+ ~logLocator as _,
29
+ ) => recorded->Array.push((kind, name, plugin))
24
30
  }
25
31
 
26
32
  // Provisioned at import time, inside a construct scope that is long gone by the time
@@ -42,8 +48,14 @@ describe("Monitoring", () => {
42
48
  // Drained: a second registration does not receive them again.
43
49
  let second: array<string> = []
44
50
  module Other: Monitoring.Backend = {
45
- let onProvisioned = (~kind as _, ~name, ~component as _, ~plugin as _, ~platform as _, ~logLocator as _) =>
46
- second->Array.push(name)
51
+ let onProvisioned = (
52
+ ~kind as _,
53
+ ~name,
54
+ ~component as _,
55
+ ~plugin as _,
56
+ ~platform as _,
57
+ ~logLocator as _,
58
+ ) => second->Array.push(name)
47
59
  }
48
60
  Monitoring.use(module(Other: Monitoring.Backend))
49
61
  expect(second)->toEqual([])
@@ -54,12 +66,22 @@ describe("Monitoring", () => {
54
66
  testSync("use registers a backend that receives every notify, role and name", () => {
55
67
  let recorded: array<(Monitoring.unitKind, string)> = []
56
68
  module Recorder: Monitoring.Backend = {
57
- let onProvisioned = (~kind, ~name, ~component as _, ~plugin as _, ~platform as _, ~logLocator as _) =>
58
- recorded->Array.push((kind, name))
69
+ let onProvisioned = (
70
+ ~kind,
71
+ ~name,
72
+ ~component as _,
73
+ ~plugin as _,
74
+ ~platform as _,
75
+ ~logLocator as _,
76
+ ) => recorded->Array.push((kind, name))
59
77
  }
60
78
  Monitoring.use(module(Recorder: Monitoring.Backend))
61
79
 
62
- Monitoring.notify(~kind=CommandHandler, ~name="AllAggregatesCmdHandler", ~component=stubResource)
80
+ Monitoring.notify(
81
+ ~kind=CommandHandler,
82
+ ~name="AllAggregatesCmdHandler",
83
+ ~component=stubResource,
84
+ )
63
85
  Monitoring.notify(~kind=Projection, ~name="AllStateViewSlices", ~component=stubResource)
64
86
  Monitoring.notify(~kind=DeadLetterSink, ~name="DeadLetterQueue", ~component=stubResource)
65
87
  Monitoring.notify(~kind=Other("Counter"), ~name="ProductCounter", ~component=stubResource)
@@ -78,8 +100,14 @@ describe("Monitoring", () => {
78
100
  testSync("notify forwards the static name and component resource to the backend", () => {
79
101
  let seen: ref<option<(string, ReventlessInfra.Adapter.resource)>> = ref(None)
80
102
  module Capture: Monitoring.Backend = {
81
- let onProvisioned = (~kind as _, ~name, ~component, ~plugin as _, ~platform as _, ~logLocator as _) =>
82
- seen := Some((name, component))
103
+ let onProvisioned = (
104
+ ~kind as _,
105
+ ~name,
106
+ ~component,
107
+ ~plugin as _,
108
+ ~platform as _,
109
+ ~logLocator as _,
110
+ ) => seen := Some((name, component))
83
111
  }
84
112
  Monitoring.use(module(Capture: Monitoring.Backend))
85
113
 
@@ -92,33 +120,42 @@ describe("Monitoring", () => {
92
120
  Monitoring.reset()
93
121
  })
94
122
 
95
- testSync("notify delivers the ambient plugin/platform inside a construct scope, None outside", () => {
96
- let seen: array<(option<string>, option<string>)> = []
97
- module OwnerCapture: Monitoring.Backend = {
98
- let onProvisioned = (~kind as _, ~name as _, ~component as _, ~plugin, ~platform, ~logLocator as _) =>
99
- seen->Array.push((plugin, platform))
100
- }
101
- Monitoring.use(module(OwnerCapture: Monitoring.Backend))
102
-
103
- // Outside any plugin construct: platform substrate → both None.
104
- Monitoring.notify(~kind=CommandHandler, ~name="ApiRouter", ~component=stubResource)
105
-
106
- // Inside a construct scope (what Plugin_Builder.construct establishes): both delivered.
107
- let prev = ResourceAttribution.enter(~platform="online-shop", ~plugin="Ordering")
108
- Monitoring.notify(~kind=CommandHandler, ~name="AllAggregatesCmdHandler", ~component=stubResource)
109
- ResourceAttribution.restore(prev)
110
-
111
- // After restore: back to None.
112
- Monitoring.notify(~kind=Projection, ~name="AllStateViewSlices", ~component=stubResource)
113
-
114
- expect(seen)->toEqual([
115
- (None, None),
116
- (Some("Ordering"), Some("online-shop")),
117
- (None, None),
118
- ])
119
-
120
- Monitoring.reset()
121
- })
123
+ testSync(
124
+ "notify delivers the ambient plugin/platform inside a construct scope, None outside",
125
+ () => {
126
+ let seen: array<(option<string>, option<string>)> = []
127
+ module OwnerCapture: Monitoring.Backend = {
128
+ let onProvisioned = (
129
+ ~kind as _,
130
+ ~name as _,
131
+ ~component as _,
132
+ ~plugin,
133
+ ~platform,
134
+ ~logLocator as _,
135
+ ) => seen->Array.push((plugin, platform))
136
+ }
137
+ Monitoring.use(module(OwnerCapture: Monitoring.Backend))
138
+
139
+ // Outside any plugin construct: platform substrate → both None.
140
+ Monitoring.notify(~kind=CommandHandler, ~name="ApiRouter", ~component=stubResource)
141
+
142
+ // Inside a construct scope (what Plugin_Builder.construct establishes): both delivered.
143
+ let prev = ResourceAttribution.enter(~platform="online-shop", ~plugin="Ordering")
144
+ Monitoring.notify(
145
+ ~kind=CommandHandler,
146
+ ~name="AllAggregatesCmdHandler",
147
+ ~component=stubResource,
148
+ )
149
+ ResourceAttribution.restore(prev)
150
+
151
+ // After restore: back to None.
152
+ Monitoring.notify(~kind=Projection, ~name="AllStateViewSlices", ~component=stubResource)
153
+
154
+ expect(seen)->toEqual([(None, None), (Some("Ordering"), Some("online-shop")), (None, None)])
155
+
156
+ Monitoring.reset()
157
+ },
158
+ )
122
159
 
123
160
  // Unlike the owner, the locator is not ambient — the seam only forwards what the provisioning
124
161
  // site passed. A site with nothing to say omits it, and the backend must see that as "this unit
@@ -129,8 +166,14 @@ describe("Monitoring", () => {
129
166
  let stubLocator: Pulumi.Output.t<string> = %raw(`{}`)
130
167
  let seen: array<bool> = []
131
168
  module LocatorCapture: Monitoring.Backend = {
132
- let onProvisioned = (~kind as _, ~name as _, ~component as _, ~plugin as _, ~platform as _, ~logLocator) =>
133
- seen->Array.push(logLocator->Option.isSome)
169
+ let onProvisioned = (
170
+ ~kind as _,
171
+ ~name as _,
172
+ ~component as _,
173
+ ~plugin as _,
174
+ ~platform as _,
175
+ ~logLocator,
176
+ ) => seen->Array.push(logLocator->Option.isSome)
134
177
  }
135
178
  Monitoring.use(module(LocatorCapture: Monitoring.Backend))
136
179
 
@@ -46,8 +46,8 @@ describe("QueryInterception", () => {
46
46
 
47
47
  testSync("and registering a runtime interceptor does not switch provisioning on", () => {
48
48
  Interception.reset()
49
- QueryDb_Callback.registerQueryInterceptor((~identity as _, ~readModelName as _, ~args as _) =>
50
- Promise.resolve(QueryDb_Callback.Allow)
49
+ QueryDb_Callback.registerQueryInterceptor(
50
+ (~identity as _, ~readModelName as _, ~args as _) => Promise.resolve(QueryDb_Callback.Allow),
51
51
  )
52
52
  expect(Interception.isEnabled())->toBe(false)
53
53
  QueryDb_Callback.clearQueryInterceptor()
@@ -17,39 +17,47 @@ describe("Auth_RefusalVocabulary — the table", () => {
17
17
  })
18
18
 
19
19
  testSync("each adapter can express both refusals", () => {
20
- [Local, AppSync]->Array.forEach(adapter => {
21
- let kinds = signalsFor(adapter)->Array.map(s => s.kind)
22
- expect(kinds->Array.includes(Entitlement))->toBe(true)
23
- expect(kinds->Array.includes(Identity))->toBe(true)
24
- })
20
+ [Local, AppSync]->Array.forEach(
21
+ adapter => {
22
+ let kinds = signalsFor(adapter)->Array.map(s => s.kind)
23
+ expect(kinds->Array.includes(Entitlement))->toBe(true)
24
+ expect(kinds->Array.includes(Identity))->toBe(true)
25
+ },
26
+ )
25
27
  })
26
28
 
27
29
  testSync("within an adapter the two refusals are actually distinguishable", () => {
28
30
  // A mapping whose two rows look identical to a client would be worthless —
29
31
  // it has to differ in the status, the place to look, or the value found.
30
- [Local, AppSync]->Array.forEach(adapter => {
31
- let signals = signalsFor(adapter)
32
- let entitlement = signals->Array.find(s => s.kind == Entitlement)
33
- let identity = signals->Array.find(s => s.kind == Identity)
34
- switch (entitlement, identity) {
35
- | (Some(e), Some(i)) =>
36
- let differs =
37
- e.httpStatus != i.httpStatus || e.discriminator != i.discriminator || e.value != i.value
38
- expect(differs)->toBe(true)
39
- | _ => JsError.throwWithMessage("adapter is missing one of the two refusals")
40
- }
41
- })
32
+ [Local, AppSync]->Array.forEach(
33
+ adapter => {
34
+ let signals = signalsFor(adapter)
35
+ let entitlement = signals->Array.find(s => s.kind == Entitlement)
36
+ let identity = signals->Array.find(s => s.kind == Identity)
37
+ switch (entitlement, identity) {
38
+ | (Some(e), Some(i)) =>
39
+ let differs =
40
+ e.httpStatus != i.httpStatus || e.discriminator != i.discriminator || e.value != i.value
41
+ expect(differs)->toBe(true)
42
+ | _ => JsError.throwWithMessage("adapter is missing one of the two refusals")
43
+ }
44
+ },
45
+ )
42
46
  })
43
47
  })
44
48
 
45
49
  describe("Auth_RefusalVocabulary.classify", () => {
46
50
  testSync("classifies every row of the table as that row's kind", () => {
47
- signals->Array.forEach(s => {
48
- let errorType = s.discriminator->String.includes("errorType") ? Some(s.value) : None
49
- let extensionsCode = s.discriminator == "extensions.code" ? Some(s.value) : None
50
- // The 401 row's discriminator is a response header; status alone carries it.
51
- expect(classify(~httpStatus=s.httpStatus, ~errorType?, ~extensionsCode?))->toEqual(Some(s.kind))
52
- })
51
+ signals->Array.forEach(
52
+ s => {
53
+ let errorType = s.discriminator->String.includes("errorType") ? Some(s.value) : None
54
+ let extensionsCode = s.discriminator == "extensions.code" ? Some(s.value) : None
55
+ // The 401 row's discriminator is a response header; status alone carries it.
56
+ expect(classify(~httpStatus=s.httpStatus, ~errorType?, ~extensionsCode?))->toEqual(
57
+ Some(s.kind),
58
+ )
59
+ },
60
+ )
53
61
  })
54
62
 
55
63
  // The trap the table exists to defuse: on AppSync the entitlement value is a
@@ -1,6 +1,5 @@
1
1
  open JestGlobals
2
2
 
3
-
4
3
  // The point of the seam, end to end at the hook level: an extension that only
5
4
  // ever gets `onColdStart` can reach the framework's runtime callback hooks from
6
5
  // there, and they take effect on the requests that follow.
@@ -49,13 +48,15 @@ describe("RuntimeExtension reaches the runtime callback hooks", () => {
49
48
  let companionModuleUrls = []
50
49
  let onColdStart = (~runtimeKind as _, ~component, ~plugin as _, ~platform as _) => {
51
50
  seenAtColdStart->Array.push(component)
52
- CommandGenerator_Callback.registerCommandInterceptor(async (
53
- ~identity as _,
54
- ~componentName,
55
- ~componentKind as _,
56
- ~tag,
57
- ~args as _,
58
- ) => CommandGenerator_Callback.Deny(`${componentName}.${tag} refused`))
51
+ CommandGenerator_Callback.registerCommandInterceptor(
52
+ async (
53
+ ~identity as _,
54
+ ~componentName,
55
+ ~componentKind as _,
56
+ ~tag,
57
+ ~args as _,
58
+ ) => CommandGenerator_Callback.Deny(`${componentName}.${tag} refused`),
59
+ )
59
60
  }
60
61
  }
61
62
  RuntimeExtension.use(module(Gatekeeper: RuntimeExtension.Extension))
@@ -7,9 +7,11 @@ type call = {
7
7
  platform: option<string>,
8
8
  }
9
9
 
10
- let recorderNamed = (~companions: array<string>=[], label: string, into: array<(string, call)>): module(
11
- RuntimeExtension.Extension
12
- ) => {
10
+ let recorderNamed = (
11
+ ~companions: array<string>=[],
12
+ label: string,
13
+ into: array<(string, call)>,
14
+ ): module(RuntimeExtension.Extension) => {
13
15
  module R = {
14
16
  let moduleUrl = `file:///pkg/${label}.res.mjs`
15
17
  let companionModuleUrls = companions
@@ -442,25 +442,32 @@ guards->Array.forEach(g => {
442
442
  describe(g.gqlType, () => {
443
443
  // Without this, a renamed GraphQL type or an unreadable schema would make
444
444
  // every assertion below pass over two empty lists.
445
- testSync("the SDL block and the record schema are both readable", () => {
446
- expect(sdlFields->Array.length > 0)->toEqual(true)
447
- expect(g.recordFields->Array.length > 0)->toEqual(true)
448
- })
445
+ testSync(
446
+ "the SDL block and the record schema are both readable",
447
+ () => {
448
+ expect(sdlFields->Array.length > 0)->toEqual(true)
449
+ expect(g.recordFields->Array.length > 0)->toEqual(true)
450
+ },
451
+ )
449
452
 
450
- testSync("every encoded field is selectable", () =>
451
- expect(missing(g.wireFields, sdlFields))->toEqual([])
453
+ testSync(
454
+ "every encoded field is selectable",
455
+ () => expect(missing(g.wireFields, sdlFields))->toEqual([]),
452
456
  )
453
457
 
454
- testSync("every declared field is encoded", () =>
455
- expect(missing(sdlFields, g.wireFields))->toEqual([])
458
+ testSync(
459
+ "every declared field is encoded",
460
+ () => expect(missing(sdlFields, g.wireFields))->toEqual([]),
456
461
  )
457
462
 
458
- testSync("every record field reaches the wire", () =>
459
- expect(missing(g.recordFields, Array.concat(sdlFields, g.recordOnly)))->toEqual([])
463
+ testSync(
464
+ "every record field reaches the wire",
465
+ () => expect(missing(g.recordFields, Array.concat(sdlFields, g.recordOnly)))->toEqual([]),
460
466
  )
461
467
 
462
- testSync("the wire carries nothing the record and the divergences do not name", () =>
463
- expect(missing(sdlFields, Array.concat(g.recordFields, g.wireOnly)))->toEqual([])
468
+ testSync(
469
+ "the wire carries nothing the record and the divergences do not name",
470
+ () => expect(missing(sdlFields, Array.concat(g.recordFields, g.wireOnly)))->toEqual([]),
464
471
  )
465
472
  })
466
473
  })
@@ -479,10 +486,9 @@ describe("derivedPages", () => {
479
486
  )
480
487
  expect(jsonKeys(baked)->Array.includes("derivedPages"))->toEqual(true)
481
488
  expect(
482
- sdlFieldNames(
483
- ~typeName="Platform_ComponentDefinitionEntry",
484
- componentSdl,
485
- )->Array.includes("derivedPages"),
489
+ sdlFieldNames(~typeName="Platform_ComponentDefinitionEntry", componentSdl)->Array.includes(
490
+ "derivedPages",
491
+ ),
486
492
  )->toEqual(false)
487
493
  })
488
494
  })
@@ -44,8 +44,7 @@ describe("the Plugins read model declares its lifecycle", () => {
44
44
  })
45
45
 
46
46
  testSync("is served on the encoded def under the new key", () => {
47
- let json =
48
- rm->Platform_ComponentDefinitionsApi.encodeQueryableDef->JSON.stringify
47
+ let json = rm->Platform_ComponentDefinitionsApi.encodeQueryableDef->JSON.stringify
49
48
  expect(json->String.includes(`"lifecycleField":"status"`))->toEqual(true)
50
49
  })
51
50
 
@@ -137,11 +136,7 @@ describe("the Plugin command defs carry every argument the SDL requires", () =>
137
136
  Platform_Admin_Structure.pluginCommands
138
137
  ->Array.filter(c => c.apiExposed != Some(false))
139
138
  ->Array.map(c => c.mutationField),
140
- )->toEqual([
141
- "Platform_Plugin_Activate",
142
- "Platform_Plugin_Deactivate",
143
- "Platform_Plugin_Retire",
144
- ])
139
+ )->toEqual(["Platform_Plugin_Activate", "Platform_Plugin_Deactivate", "Platform_Plugin_Retire"])
145
140
  )
146
141
 
147
142
  // The `@noApi` protocol variants come back from the same walk. They belong on
@@ -179,16 +174,20 @@ describe("the internal commands declare the edges they move rows along", () => {
179
174
  }
180
175
 
181
176
  testSync("the only edge into Disconnected is declared", () =>
182
- expect((commandNamed("Disconnect").allowedStates, commandNamed("Disconnect").targetState))
183
- ->toEqual((Some(["Connected"]), Some("Disconnected")))
177
+ expect((
178
+ commandNamed("Disconnect").allowedStates,
179
+ commandNamed("Disconnect").targetState,
180
+ ))->toEqual((Some(["Connected"]), Some("Disconnected")))
184
181
  )
185
182
 
186
183
  // The creating form's claim: a target and no from-set. `Connect` brings the
187
184
  // version's row into being, so there is no state it runs from — and an empty
188
185
  // `allowedStates` would say the opposite, that it is legal in none.
189
186
  testSync("the handshake declares a target and no from-set", () =>
190
- expect((commandNamed("Connect").allowedStates, commandNamed("Connect").targetState))
191
- ->toEqual((None, Some("Connected")))
187
+ expect((commandNamed("Connect").allowedStates, commandNamed("Connect").targetState))->toEqual((
188
+ None,
189
+ Some("Connected"),
190
+ ))
192
191
  )
193
192
 
194
193
  testSync("and no state is left unreachable", () =>
@@ -91,8 +91,7 @@ let structure: pluginStructure = {
91
91
 
92
92
  let structures = [("Ordering@1.0.0", structure)]
93
93
 
94
- let bake = selections =>
95
- Platform_BakedManifest.curate(~structures, ~selections)
94
+ let bake = selections => Platform_BakedManifest.curate(~structures, ~selections)
96
95
 
97
96
  // Every case below varies one include-list and means "everything" by the rest,
98
97
  // which is exactly what an omitted labelled argument says.
@@ -112,7 +111,10 @@ let names = (entry: JSON.t, field: string) =>
112
111
  ->Option.flatMap(JSON.Decode.array)
113
112
  ->Option.getOr([])
114
113
  ->Array.filterMap(v =>
115
- v->JSON.Decode.object->Option.flatMap(d => d->Dict.get("name"))->Option.flatMap(JSON.Decode.string)
114
+ v
115
+ ->JSON.Decode.object
116
+ ->Option.flatMap(d => d->Dict.get("name"))
117
+ ->Option.flatMap(JSON.Decode.string)
116
118
  )
117
119
 
118
120
  let firstEntry = (r: result<JSON.t, Platform_BakedManifest.error>) =>
@@ -146,15 +148,13 @@ describe("curate", () => {
146
148
  // from, so an Internal view a kept command points at has to survive the bake.
147
149
  testSync("carries an Internal view referenced by an included command", () => {
148
150
  let entry =
149
- bake([sel(~plugin="Ordering", ~views=["Orders"], ~commands=["PlaceOrder"])])
150
- ->firstEntry
151
+ bake([sel(~plugin="Ordering", ~views=["Orders"], ~commands=["PlaceOrder"])])->firstEntry
151
152
  expect(entry->names("internalQueryables"))->toEqual(["AvailableProducts"])
152
153
  })
153
154
 
154
155
  testSync("omits an Internal view no included command references", () => {
155
156
  let entry =
156
- bake([sel(~plugin="Ordering", ~views=["Orders"], ~commands=["ImportOrders"])])
157
- ->firstEntry
157
+ bake([sel(~plugin="Ordering", ~views=["Orders"], ~commands=["ImportOrders"])])->firstEntry
158
158
  expect(entry->names("internalQueryables"))->toEqual([])
159
159
  })
160
160
 
@@ -193,9 +193,9 @@ describe("curate", () => {
193
193
  )
194
194
 
195
195
  testSync("accepts a kind this plugin generates no page for", () =>
196
- expect(
197
- bake([sel(~plugin="Ordering", ~derived=["scheduler"])])->firstEntry->derivedOf,
198
- )->toEqual(Some(["scheduler"]))
196
+ expect(bake([sel(~plugin="Ordering", ~derived=["scheduler"])])->firstEntry->derivedOf)->toEqual(
197
+ Some(["scheduler"]),
198
+ )
199
199
  )
200
200
 
201
201
  testSync("an Internal view is never selectable as a view", () =>
@@ -228,27 +228,26 @@ describe("curate", () => {
228
228
  })
229
229
 
230
230
  testSync("one entry per selection, in declaration order", () => {
231
- let json =
232
- Platform_BakedManifest.curate(
233
- ~structures=[("Ordering@1.0.0", structure), ("Catalog@1.0.0", structure)],
234
- ~selections=[
235
- sel(~plugin="Catalog", ~views=[], ~commands=[]),
236
- sel(~plugin="Ordering", ~views=[], ~commands=[]),
237
- ],
238
- )
239
- let ids =
240
- switch json {
241
- | Ok(j) =>
242
- j
243
- ->entries
244
- ->Array.filterMap(e =>
231
+ let json = Platform_BakedManifest.curate(
232
+ ~structures=[("Ordering@1.0.0", structure), ("Catalog@1.0.0", structure)],
233
+ ~selections=[
234
+ sel(~plugin="Catalog", ~views=[], ~commands=[]),
235
+ sel(~plugin="Ordering", ~views=[], ~commands=[]),
236
+ ],
237
+ )
238
+ let ids = switch json {
239
+ | Ok(j) =>
240
+ j
241
+ ->entries
242
+ ->Array.filterMap(
243
+ e =>
245
244
  e
246
245
  ->JSON.Decode.object
247
246
  ->Option.flatMap(d => d->Dict.get("pluginId"))
248
- ->Option.flatMap(JSON.Decode.string)
249
- )
250
- | Error(_) => []
251
- }
247
+ ->Option.flatMap(JSON.Decode.string),
248
+ )
249
+ | Error(_) => []
250
+ }
252
251
  expect(ids)->toEqual(["Catalog", "Ordering"])
253
252
  })
254
253
 
@@ -258,8 +257,7 @@ describe("curate", () => {
258
257
  // makes this hold — the assertion guards that property, not a second code path.
259
258
  testSync("a curated entry carries the owner field the served entry carries", () => {
260
259
  let entry =
261
- bake([sel(~plugin="Ordering", ~views=["Orders"], ~commands=["PlaceOrder"])])
262
- ->firstEntry
260
+ bake([sel(~plugin="Ordering", ~views=["Orders"], ~commands=["PlaceOrder"])])->firstEntry
263
261
  let ownerOf = (key, name) =>
264
262
  entry
265
263
  ->JSON.Decode.object
@@ -267,9 +265,7 @@ describe("curate", () => {
267
265
  ->Option.flatMap(JSON.Decode.array)
268
266
  ->Option.getOr([])
269
267
  ->Array.filterMap(JSON.Decode.object)
270
- ->Array.find(d =>
271
- d->Dict.get("name")->Option.flatMap(JSON.Decode.string) == Some(name)
272
- )
268
+ ->Array.find(d => d->Dict.get("name")->Option.flatMap(JSON.Decode.string) == Some(name))
273
269
  ->Option.flatMap(d => d->Dict.get("ownerField"))
274
270
  ->Option.flatMap(JSON.Decode.string)
275
271
  let commandOwner =
@@ -279,8 +275,8 @@ describe("curate", () => {
279
275
  ->Option.flatMap(JSON.Decode.array)
280
276
  ->Option.getOr([])
281
277
  ->Array.filterMap(JSON.Decode.object)
282
- ->Array.flatMap(w =>
283
- w->Dict.get("commands")->Option.flatMap(JSON.Decode.array)->Option.getOr([])
278
+ ->Array.flatMap(
279
+ w => w->Dict.get("commands")->Option.flatMap(JSON.Decode.array)->Option.getOr([]),
284
280
  )
285
281
  ->Array.filterMap(JSON.Decode.object)
286
282
  ->Array.get(0)
@@ -11,9 +11,7 @@ let cmd: commandDef = {
11
11
  level: Collection,
12
12
  aggregateIdField: None,
13
13
  mutationField: "AddProduct",
14
- references: [
15
- {fieldName: "categoryId", entity: "Category", plugin: Some("Catalog")},
16
- ],
14
+ references: [{fieldName: "categoryId", entity: "Category", plugin: Some("Catalog")}],
17
15
  allowedStates: None,
18
16
  targetState: None,
19
17
  apiExposed: Some(true),
@@ -276,10 +274,10 @@ describe("visibility filtering (deployed AutoUI hides Internal)", () => {
276
274
  idField: Some("productId"),
277
275
  idFieldSource: Some("sole"),
278
276
  requiredAccess: None,
279
- ownerField: None,
280
- retiredField: None,
281
- retiredValues: None,
282
- namedWhenRetired: None,
277
+ ownerField: None,
278
+ retiredField: None,
279
+ retiredValues: None,
280
+ namedWhenRetired: None,
283
281
  }
284
282
  // A distinct name per source array: the complement has to be fed by both, and
285
283
  // reusing one def would hide a version that only walks `readModels`.
@@ -293,8 +291,10 @@ describe("visibility filtering (deployed AutoUI hides Internal)", () => {
293
291
  readModels: [qbl, internalQbl],
294
292
  stateViewSlices: [internalSlice],
295
293
  }
296
- let mixedEntry =
297
- Platform_ComponentDefinitionsApi.encodePluginStructureEntry(~pluginId="Ordering", mixed)
294
+ let mixedEntry = Platform_ComponentDefinitionsApi.encodePluginStructureEntry(
295
+ ~pluginId="Ordering",
296
+ mixed,
297
+ )
298
298
 
299
299
  // Names under one key of the encoded entry. `String.includes` over the whole
300
300
  // JSON can no longer answer this: an Internal view is legitimately present
@@ -308,7 +308,10 @@ describe("visibility filtering (deployed AutoUI hides Internal)", () => {
308
308
  ->Option.flatMap(JSON.Decode.array)
309
309
  ->Option.getOr([])
310
310
  ->Array.filterMap(c =>
311
- c->JSON.Decode.object->Option.flatMap(o => o->Dict.get("name"))->Option.flatMap(JSON.Decode.string)
311
+ c
312
+ ->JSON.Decode.object
313
+ ->Option.flatMap(o => o->Dict.get("name"))
314
+ ->Option.flatMap(JSON.Decode.string)
312
315
  )
313
316
 
314
317
  testSync("excludes an Internal queryableDef from the encoded read-side", () => {
@@ -358,7 +361,7 @@ describe("allowedStates + lifecycleField populated", () => {
358
361
  allowedStatesSource: "declared",
359
362
  apiExposed: Some(true),
360
363
  requiredAccess: None,
361
- ownerField: None,
364
+ ownerField: None,
362
365
  }
363
366
 
364
367
  let qblWithStatus: queryableDef = {
@@ -377,10 +380,10 @@ describe("allowedStates + lifecycleField populated", () => {
377
380
  idField: None,
378
381
  idFieldSource: None,
379
382
  requiredAccess: None,
380
- ownerField: None,
381
- retiredField: None,
382
- retiredValues: None,
383
- namedWhenRetired: None,
383
+ ownerField: None,
384
+ retiredField: None,
385
+ retiredValues: None,
386
+ namedWhenRetired: None,
384
387
  }
385
388
 
386
389
  let wblWithStates: writableDef = {
@@ -84,7 +84,10 @@ let namesOf = (key): array<string> =>
84
84
  ->Option.flatMap(JSON.Decode.array)
85
85
  ->Option.getOr([])
86
86
  ->Array.filterMap(v =>
87
- v->JSON.Decode.object->Option.flatMap(o => o->Dict.get("name"))->Option.flatMap(JSON.Decode.string)
87
+ v
88
+ ->JSON.Decode.object
89
+ ->Option.flatMap(o => o->Dict.get("name"))
90
+ ->Option.flatMap(JSON.Decode.string)
88
91
  )
89
92
 
90
93
  describe("Platform_PluginStructures entry", () => {
@@ -130,8 +133,7 @@ describe("Platform_PluginStructures entry", () => {
130
133
  expect(
131
134
  json->String.includes(
132
135
  "\"extensionPoints\":[{\"name\":\"Catalog.Products\",\"delegateNames\":[\"onAdded\"],\"sourceEventTypes\":[\"Catalog.ProductAdded\"],\"commandTypes\":null," ++
133
- "\"publishedEvents\":[{\"name\":\"Catalog.Products.ProductBecameAvailable\",\"fromEventTypes\":[\"Catalog.ProductAdded\"]}]," ++
134
- "\"acceptedCommands\":[{\"name\":\"Catalog.Products.Reserve\",\"toCommandTypes\":[\"Catalog.ReserveStock\"]}]}]",
136
+ "\"publishedEvents\":[{\"name\":\"Catalog.Products.ProductBecameAvailable\",\"fromEventTypes\":[\"Catalog.ProductAdded\"]}]," ++ "\"acceptedCommands\":[{\"name\":\"Catalog.Products.Reserve\",\"toCommandTypes\":[\"Catalog.ReserveStock\"]}]}]",
135
137
  ),
136
138
  )->toEqual(true)
137
139
  )
@@ -57,7 +57,9 @@ describe("encodeUIFragmentEntry", () => {
57
57
 
58
58
  testSync("encodes remoteEntryUrl", () =>
59
59
  expect(
60
- json->String.includes("\"remoteEntryUrl\":\"https://cdn.example.com/catalog@1.0/remoteEntry.js\""),
60
+ json->String.includes(
61
+ "\"remoteEntryUrl\":\"https://cdn.example.com/catalog@1.0/remoteEntry.js\"",
62
+ ),
61
63
  )->toEqual(true)
62
64
  )
63
65
 
@@ -80,8 +82,9 @@ describe("encodeUIFragmentEntry", () => {
80
82
 
81
83
  describe("Platform_UIFragmentsApi.sdl", () => {
82
84
  testSync("query field declares the list type", () =>
83
- expect(Platform_UIFragmentsApi.sdlQueryField->String.includes("[Platform_UIFragmentEntry!]!"))
84
- ->toEqual(true)
85
+ expect(
86
+ Platform_UIFragmentsApi.sdlQueryField->String.includes("[Platform_UIFragmentEntry!]!"),
87
+ )->toEqual(true)
85
88
  )
86
89
 
87
90
  testSync("sdlTypes includes Platform_UIFragmentEntry", () => {