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

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 (208) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/package.json +10 -10
  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/adapter/Secrets/Secrets_Node_Backend.res +60 -0
  20. package/src/adapter/Secrets/Secrets_Node_Backend.res.mjs +69 -0
  21. package/src/admin/Platform_Admin.res +17 -6
  22. package/src/admin/Platform_AdminApi.res +14 -9
  23. package/src/admin/Platform_Admin_Callback.res +1 -1
  24. package/src/admin/Platform_BakedManifest.res +34 -34
  25. package/src/admin/Platform_ComponentDefinitionsApi.res +9 -21
  26. package/src/admin/Platform_PluginStructuresApi.res +15 -12
  27. package/src/admin/UiFragmentRegistry/StateChange/UiFragmentRegistry.res +1 -1
  28. package/src/components/Aggregate/Aggregate.res +13 -12
  29. package/src/components/Aggregate/Aggregate_Builder.res +22 -21
  30. package/src/components/Aggregate/Aggregate_Callback.res +91 -86
  31. package/src/components/Api/ApiNoApiHelpers.res +1 -3
  32. package/src/components/Api/Api_Ids.res +0 -1
  33. package/src/components/Api/Api_Naming.res +41 -18
  34. package/src/components/Api/GraphQL_FragmentGenerator.res +38 -51
  35. package/src/components/Api/GraphQL_SchemaInspector.res +5 -3
  36. package/src/components/Api/GraphQL_Stitcher.res +9 -10
  37. package/src/components/Api/MCP_SchemaGenerator.res +8 -12
  38. package/src/components/Api/OwnerScopeDiagnostics.res +1 -2
  39. package/src/components/Api/QueryDbListQuery.res +13 -6
  40. package/src/components/Api/SchemaType.res +28 -23
  41. package/src/components/Api/SuryToJsonSchema.res +9 -10
  42. package/src/components/AutomationSlice/AutomationSlice.res +4 -4
  43. package/src/components/AutomationSlice/AutomationSlice_Builder.res +15 -14
  44. package/src/components/AutomationSlice/AutomationSlice_Callback.res +3 -3
  45. package/src/components/Builder_Helpers.res +12 -23
  46. package/src/components/CommandGenerator/CommandGenerator.res +6 -1
  47. package/src/components/CommandGenerator/CommandGenerator_Builder.res +29 -21
  48. package/src/components/CommandGenerator/CommandGenerator_Callback.res +17 -21
  49. package/src/components/CommandTopic/CommandTopic.res +3 -3
  50. package/src/components/CommandTopic/CommandTopic_Builder.res +10 -10
  51. package/src/components/CommandTopic/CommandTopic_Callback.res +1 -4
  52. package/src/components/CommandTopic/CommandTopic_Helpers.res +1 -2
  53. package/src/components/Counter/Counter_Builder.res +1 -6
  54. package/src/components/Counter/Counter_Callback.res +3 -3
  55. package/src/components/Dcb/Dcb_Builder.res +970 -956
  56. package/src/components/DcbEventLog/DcbEventLog.res +4 -4
  57. package/src/components/DcbEventLog/DcbEventLog_Builder.res +0 -1
  58. package/src/components/DcbEventLog/DcbEventLog_Operations.res +17 -18
  59. package/src/components/EventCollector/EventCollector_Builder.res +2 -1
  60. package/src/components/EventLog/EventLog.res +5 -1
  61. package/src/components/EventLog/EventLog_Operations.res +12 -8
  62. package/src/components/EventMapper/EventMapper.res +8 -10
  63. package/src/components/EventMapper/EventMapper_Builder.res +4 -1
  64. package/src/components/EventMapper/EventMapper_Callback.res +46 -31
  65. package/src/components/EventTopic/EventTopic.res +3 -3
  66. package/src/components/EventTopic/EventTopic_Builder.res +1 -1
  67. package/src/components/Extension/Extension.res +4 -1
  68. package/src/components/Extension/Extension_Operations.res +11 -3
  69. package/src/components/ExtensionPoint/ExtensionPoint.res +3 -3
  70. package/src/components/ExtensionPoint/ExtensionPoint_Builder.res +9 -10
  71. package/src/components/ExtensionPoint/ExtensionPoint_Callback.res +2 -6
  72. package/src/components/ExtensionPoint/ExtensionPoint_Operations.res +13 -5
  73. package/src/components/Heartbeat/Heartbeat_Callback.res +3 -3
  74. package/src/components/InboundTranslationSlice/InboundTranslationSlice.res +4 -4
  75. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res +7 -10
  76. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice.res +4 -4
  77. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res +15 -14
  78. package/src/components/QueryDb/QueryDb_Adapter.res +1 -3
  79. package/src/components/QueryDb/QueryDb_Operations.res +10 -10
  80. package/src/components/ReadModel/ReadModel.res +3 -3
  81. package/src/components/ReadModel/ReadModel_Builder.res +1 -2
  82. package/src/components/ReadModel/ReadModel_Callback.res +2 -1
  83. package/src/components/SideEffectHandler/SideEffectHandler_Callback.res +5 -2
  84. package/src/components/StateChangeSlice/StateChangeSlice.res +3 -3
  85. package/src/components/StateChangeSlice/StateChangeSlice_Builder.res +23 -4
  86. package/src/components/StateChangeSlice/StateChangeSlice_Callback.res +22 -6
  87. package/src/components/StateTopic.res +1 -3
  88. package/src/components/StateViewSlice/StateViewSlice.res +4 -4
  89. package/src/components/StateViewSlice/StateViewSlice_Builder.res +79 -68
  90. package/src/components/StateViewSlice/StateViewSlice_Callback.res +3 -1
  91. package/src/components/Task/Task.res +3 -3
  92. package/src/components/Task/Task_Adapter.res +4 -1
  93. package/src/components/Task/Task_Builder.res +24 -21
  94. package/src/plugin/api/PluginBaseFragment.res +9 -3
  95. package/src/plugin/component/Capability_Inference.res +8 -10
  96. package/src/plugin/component/Plugin.res +6 -6
  97. package/src/plugin/component/Plugin_Builder.res +54 -50
  98. package/src/plugin/component/Plugin_Callback.res +10 -6
  99. package/src/plugin/component/Plugin_Helpers.res +264 -230
  100. package/src/plugin/component/Plugin_Structure.res +370 -324
  101. package/src/plugin/component/Plugin_SubscriptionSchema.res +8 -6
  102. package/src/plugin/component/SchemaWalker.res +11 -12
  103. package/src/plugin/connect/PluginConnectExtension_Mapping.res +45 -50
  104. package/src/plugin/lifecycle/PluginBehavior.res +3 -4
  105. package/src/plugin/lifecycle/PluginSpec.res +1 -2
  106. package/src/plugin/lifecycle/PluginsProjection.res +16 -5
  107. package/src/plugin/lifecycle/PluginsReadModelSpec.res +0 -2
  108. package/src/util/CommandPublisher.res +9 -2
  109. package/src/util/CsvStream.res +3 -3
  110. package/src/util/Interstack.res +7 -15
  111. package/src/util/Interstack.resi +3 -3
  112. package/src/util/LogFormat.res +5 -9
  113. package/src/util/Logger.res +1 -2
  114. package/src/util/Lru.res +2 -1
  115. package/src/util/Lru.resi +2 -3
  116. package/src/util/ScheduleOps.res +24 -27
  117. package/src/util/StorePrefixCollision.res +6 -9
  118. package/src/util/Util_Promise.res +4 -1
  119. package/src/util/Util_Promise.res.mjs +1 -1
  120. package/tests/IdentityTest.res +166 -113
  121. package/tests/ResourceAttributionTest.res +28 -25
  122. package/tests/Secrets_Node_BackendTest.res +141 -0
  123. package/tests/Secrets_Node_BackendTest.res.mjs +152 -0
  124. package/tests/StorePrefixCollisionTest.res +2 -1
  125. package/tests/TaskBucketNamingTest.res +3 -2
  126. package/tests/adapter/EventLogProvisioningTest.res +51 -48
  127. package/tests/adapter/MonitoringTest.res +81 -38
  128. package/tests/adapter/QueryInterceptionTest.res +2 -2
  129. package/tests/adapter/RefusalVocabularyTest.res +31 -23
  130. package/tests/adapter/RuntimeExtensionHookReachTest.res +9 -8
  131. package/tests/adapter/RuntimeExtensionTest.res +5 -3
  132. package/tests/admin/AdminApiSchemaDriftTest.res +22 -16
  133. package/tests/admin/Platform_Admin_StructureTest.res +22 -14
  134. package/tests/admin/Platform_Admin_StructureTest.res.mjs +4 -3
  135. package/tests/admin/Platform_BakedManifestTest.res +31 -35
  136. package/tests/admin/Platform_ComponentDefinitionsApiTest.res +18 -15
  137. package/tests/admin/Platform_PluginStructuresApiTest.res +5 -3
  138. package/tests/admin/Platform_UIFragmentsApiTest.res +6 -3
  139. package/tests/aggregate/AggregateCacheTest.res +10 -12
  140. package/tests/aggregate/AggregateCallbackTest.res +75 -46
  141. package/tests/aggregate/AggregateCausationTest.res +19 -20
  142. package/tests/aggregate/AggregateConflictTest.res +41 -19
  143. package/tests/aggregate/AggregateFixtures.res +15 -5
  144. package/tests/aggregate/AggregateRejectionTest.res +97 -80
  145. package/tests/aggregate/AggregateSnapshotTest.res +44 -16
  146. package/tests/api/Api_IdsTest.res +10 -4
  147. package/tests/api/BrandedMarkerCompositionTest.res +48 -36
  148. package/tests/api/GeolocationSemanticTest.res +3 -3
  149. package/tests/api/GraphQL_FragmentGeneratorTest.res +66 -54
  150. package/tests/api/OwnerScopeDiagnosticsTest.res +31 -27
  151. package/tests/api/StorageRefFieldsTest.res +30 -18
  152. package/tests/api/SuryToJsonSchemaTest.res +1315 -1014
  153. package/tests/api/TaggedUnionSchemaTest.res +17 -24
  154. package/tests/commandgenerator/CommandGeneratorCallbackTest.res +235 -179
  155. package/tests/commandgenerator/CommandGeneratorFixtures.res +8 -13
  156. package/tests/commandgenerator/OwnerStampingTest.res +91 -76
  157. package/tests/commandtopic/CommandOutcomeHookTest.res +198 -155
  158. package/tests/commandtopic/CommandTopicCallbackFixtures.res +5 -4
  159. package/tests/commandtopic/CommandTopicCallbackTest.res +61 -43
  160. package/tests/commandtopic/CommandTopicHelpersRejectionTest.res +70 -55
  161. package/tests/counter/CounterCallbackTest.res +40 -34
  162. package/tests/counter/CounterFixtures.res +4 -4
  163. package/tests/dcb/DcbDecodeTest.res +115 -84
  164. package/tests/dcb/DcbEventLogOperationsTest.res +194 -143
  165. package/tests/dcb/DcbEventLogSchemaTest.res +13 -13
  166. package/tests/dcb/DcbFixtures.res +4 -5
  167. package/tests/dcb/DcbScopeInferenceTest.res +173 -114
  168. package/tests/dcb/DcbStateChangeSliceTest.res +391 -262
  169. package/tests/dcb/DcbTagTest.res +22 -11
  170. package/tests/dcb/DcbValidationTest.res +288 -218
  171. package/tests/eventlog/EventLogFixtures.res +4 -4
  172. package/tests/eventlog/EventLogOperationsTest.res +102 -67
  173. package/tests/eventlog/EventLogRetryTest.res +104 -65
  174. package/tests/eventmapper/EventMapperCallbackTest.res +118 -83
  175. package/tests/eventmapper/EventMapperFixtures.res +15 -23
  176. package/tests/eventmapper/EventMapperTest.res +54 -38
  177. package/tests/eventtopic/EventTopicFixtures.res +3 -4
  178. package/tests/eventtopic/EventTopicOperationsTest.res +41 -29
  179. package/tests/extensionpoint/ExtensionPointCallbackTest.res +58 -45
  180. package/tests/extensionpoint/ExtensionPointFixtures.res +16 -20
  181. package/tests/extensionpoint/ExtensionPointOperationsTest.res +70 -49
  182. package/tests/extensionpoint/PluginDisconnectScheduleTest.res +2 -1
  183. package/tests/logger/LogFormatTest.res +104 -82
  184. package/tests/logger/LoggerLazyTest.res +21 -12
  185. package/tests/message/MessageTest.res +96 -93
  186. package/tests/message/MetaEnvelopeTest.res +26 -30
  187. package/tests/plugin/HeartbeatDisconnectGraceTest.res +31 -25
  188. package/tests/plugin/ManifestVisibilityTest.res +20 -12
  189. package/tests/plugin/PluginDefinitionScalars.res +1 -2
  190. package/tests/plugin/PluginLifecycleCorpusTest.res +15 -12
  191. package/tests/plugin/PluginSpecExperiment.res +0 -1
  192. package/tests/plugin/PluginStructureTest.res +1529 -1045
  193. package/tests/plugin/Plugin_EventQuerySchemaTest.res +21 -10
  194. package/tests/plugin/SchemaWalkerTest.res +116 -70
  195. package/tests/plugin/StateChange/PsReserveStock.res +4 -4
  196. package/tests/plugin/StateView/PsAnnotatedView.res +4 -4
  197. package/tests/plugin/StateView/PsCustomersView.res +4 -4
  198. package/tests/plugin/StateView/PsShipmentsView.res +3 -2
  199. package/tests/projection/LifecycleTrailTest.res +1 -4
  200. package/tests/projection/ProjectionOptimizeTest.res +13 -9
  201. package/tests/querydb/QueryDbFixtures.res +0 -1
  202. package/tests/querydb/QueryDbOperationsTest.res +99 -64
  203. package/tests/querydb/TaggedUnionStampTest.res +10 -8
  204. package/tests/sideeffecthandler/SideEffectHandlerCallbackTest.res +50 -35
  205. package/tests/sideeffecthandler/SideEffectHandlerFixtures.res +4 -10
  206. package/tests/util/CommandPublisherTest.res +0 -1
  207. package/tests/util/CsvStreamTest.res +3 -3
  208. package/tests/util/LruTest.res +84 -56
@@ -0,0 +1,152 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
4
+ import * as Primitive_int from "@rescript/runtime/lib/es6/Primitive_int.js";
5
+ import * as Stdlib_Result from "@rescript/runtime/lib/es6/Stdlib_Result.js";
6
+ import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
7
+ import * as Secrets$Reventless from "@reventlessdev/reventless-spec/src/semantic/Secrets.res.mjs";
8
+ import * as Capabilities$Reventless from "@reventlessdev/reventless-spec/src/semantic/Capabilities.res.mjs";
9
+ import * as Secrets_Node_Backend$ReventlessCore from "../src/adapter/Secrets/Secrets_Node_Backend.res.mjs";
10
+
11
+ function token(length, alphabet) {
12
+ return Stdlib_Result.getOr(Secrets_Node_Backend$ReventlessCore.provider.randomToken(length, alphabet), "");
13
+ }
14
+
15
+ globalThis.describe("randomToken", () => {
16
+ globalThis.test("draws the requested length", () => {
17
+ globalThis.expect([
18
+ 1,
19
+ 6,
20
+ 32,
21
+ 64
22
+ ].map(length => token(length, "Digits").length)).toEqual([
23
+ 1,
24
+ 6,
25
+ 32,
26
+ 64
27
+ ]);
28
+ });
29
+ globalThis.test("draws only from the alphabet it was given", () => {
30
+ let allowed = Secrets$Reventless.characters("UrlSafe");
31
+ globalThis.expect(token(512, "UrlSafe").split("").every(c => allowed.includes(c))).toBe(true);
32
+ });
33
+ globalThis.test("digits are digits", () => {
34
+ globalThis.expect(token(512, "Digits").split("").every(c => "0123456789".includes(c))).toBe(true);
35
+ });
36
+ globalThis.test("two draws differ", () => {
37
+ globalThis.expect(token(32, "UrlSafe") === token(32, "UrlSafe")).toBe(false);
38
+ });
39
+ globalThis.test("a non-positive length is refused, not clamped", () => {
40
+ globalThis.expect([
41
+ 0,
42
+ -1
43
+ ].map(length => Stdlib_Result.isError(Secrets_Node_Backend$ReventlessCore.provider.randomToken(length, "Digits")))).toEqual([
44
+ true,
45
+ true
46
+ ]);
47
+ });
48
+ });
49
+
50
+ globalThis.describe("accepts — the rejection rule", () => {
51
+ let rejected = size => Stdlib_Array.fromInitializer(256, i => i).filter(byte => !Secrets_Node_Backend$ReventlessCore.accepts(byte, size));
52
+ globalThis.test("rejects exactly the bytes that would skew a 10-character alphabet", () => {
53
+ globalThis.expect(rejected(10)).toEqual([
54
+ 250,
55
+ 251,
56
+ 252,
57
+ 253,
58
+ 254,
59
+ 255
60
+ ]);
61
+ });
62
+ globalThis.test("rejects nothing when the alphabet divides evenly", () => {
63
+ globalThis.expect(rejected(64)).toEqual([]);
64
+ });
65
+ globalThis.test("what it accepts is a whole multiple of the alphabet", () => {
66
+ globalThis.expect([
67
+ 2,
68
+ 3,
69
+ 7,
70
+ 10,
71
+ 16,
72
+ 26,
73
+ 62,
74
+ 64
75
+ ].map(size => Primitive_int.mod_(256 - rejected(size).length | 0, size))).toEqual([
76
+ 0,
77
+ 0,
78
+ 0,
79
+ 0,
80
+ 0,
81
+ 0,
82
+ 0,
83
+ 0
84
+ ]);
85
+ });
86
+ globalThis.test("never discards more than one cycle's worth", () => {
87
+ globalThis.expect([
88
+ 3,
89
+ 7,
90
+ 10,
91
+ 26,
92
+ 62
93
+ ].map(size => rejected(size).length < size)).toEqual([
94
+ true,
95
+ true,
96
+ true,
97
+ true,
98
+ true
99
+ ]);
100
+ });
101
+ });
102
+
103
+ globalThis.describe("hash", () => {
104
+ globalThis.test("is deterministic, which is what lets a proof be compared", () => {
105
+ globalThis.expect(Primitive_object.equal(Secrets_Node_Backend$ReventlessCore.provider.hash("a-secret"), Secrets_Node_Backend$ReventlessCore.provider.hash("a-secret"))).toBe(true);
106
+ });
107
+ globalThis.test("separates different inputs", () => {
108
+ globalThis.expect(Primitive_object.equal(Secrets_Node_Backend$ReventlessCore.provider.hash("a-secret"), Secrets_Node_Backend$ReventlessCore.provider.hash("a-secret "))).toBe(false);
109
+ });
110
+ globalThis.test("does not contain its input", () => {
111
+ globalThis.expect(Stdlib_Result.getOr(Secrets_Node_Backend$ReventlessCore.provider.hash("a-secret"), "").includes("a-secret")).toBe(false);
112
+ });
113
+ });
114
+
115
+ globalThis.describe("Capabilities.none.secrets", () => {
116
+ globalThis.test("refuses both operations", () => {
117
+ globalThis.expect([
118
+ Stdlib_Result.isError(Capabilities$Reventless.none.secrets.randomToken(32, "UrlSafe")),
119
+ Stdlib_Result.isError(Capabilities$Reventless.none.secrets.hash("x"))
120
+ ]).toEqual([
121
+ true,
122
+ true
123
+ ]);
124
+ });
125
+ });
126
+
127
+ globalThis.describe("Secrets.fixed", () => {
128
+ let provider = Secrets$Reventless.fixed("known", input => `hashed:` + input);
129
+ globalThis.test("hands back the token it was built with", () => {
130
+ globalThis.expect(provider.randomToken(32, "UrlSafe")).toEqual({
131
+ TAG: "Ok",
132
+ _0: "known"
133
+ });
134
+ });
135
+ globalThis.test("hashes through the function it was given", () => {
136
+ globalThis.expect(provider.hash("known")).toEqual({
137
+ TAG: "Ok",
138
+ _0: "hashed:known"
139
+ });
140
+ });
141
+ });
142
+
143
+ let Secrets;
144
+
145
+ let Backend;
146
+
147
+ export {
148
+ Secrets,
149
+ Backend,
150
+ token,
151
+ }
152
+ /* Not a pure module */
@@ -33,7 +33,8 @@ describe("collisionsFor", () => {
33
33
  store(~qualified="Ordering.productImages", ~prefix="productImages"),
34
34
  ],
35
35
  ) {
36
- | [c] => expect((c.first.qualified, c.second.qualified, c.nested))->toEqual((
36
+ | [c] =>
37
+ expect((c.first.qualified, c.second.qualified, c.nested))->toEqual((
37
38
  "Catalog.productImages",
38
39
  "Ordering.productImages",
39
40
  false,
@@ -36,8 +36,9 @@ describe("kebabCase", () => {
36
36
 
37
37
  describe("bucketResourceName", () => {
38
38
  testSync("qualifies a task's default bucket with its plugin", () =>
39
- expect(Naming.bucketResourceName(~plugin=Some("Catalog"), ~task="ImportProducts", ~bucketId=None))
40
- ->toBe("catalog-import-products")
39
+ expect(
40
+ Naming.bucketResourceName(~plugin=Some("Catalog"), ~task="ImportProducts", ~bucketId=None),
41
+ )->toBe("catalog-import-products")
41
42
  )
42
43
 
43
44
  testSync("appends a declared bucket id", () =>
@@ -128,54 +128,57 @@ describe("EventLogProvisioning", () => {
128
128
  EventLogProvisioning.reset()
129
129
  })
130
130
 
131
- testSync("notify delivers the ambient plugin/platform inside a construct scope, None outside", () => {
132
- let seen: array<(option<string>, option<string>)> = []
133
- module OwnerCapture: EventLogProvisioning.Backend = {
134
- let onProvisioned = (
135
- ~logStyle as _,
136
- ~name as _,
137
- ~owner as _,
138
- ~plugin,
139
- ~platform,
140
- ~resources as _,
141
- ~opts as _,
142
- ) => seen->Array.push((plugin, platform))
143
- }
144
- EventLogProvisioning.use(module(OwnerCapture: EventLogProvisioning.Backend))
145
-
146
- // Outside any plugin construct: both None.
147
- EventLogProvisioning.notify(
148
- ~logStyle=Classic,
149
- ~name="ProductEventLog",
150
- ~owner=Some(classicOwner),
151
- ~resources=[],
152
- ~opts=noOpts,
153
- )
154
-
155
- // Inside a construct scope (what Plugin_Builder.construct establishes): both delivered.
156
- let prev = ResourceAttribution.enter(~platform="online-shop", ~plugin="Catalog")
157
- EventLogProvisioning.notify(
158
- ~logStyle=Dcb,
159
- ~name="CatalogDcbEventLog",
160
- ~owner=Some(dcbOwner),
161
- ~resources=[],
162
- ~opts=noOpts,
163
- )
164
- ResourceAttribution.restore(prev)
165
-
166
- // After restore: back to None.
167
- EventLogProvisioning.notify(
168
- ~logStyle=Classic,
169
- ~name="OrderEventLog",
170
- ~owner=None,
171
- ~resources=[],
172
- ~opts=noOpts,
173
- )
174
-
175
- expect(seen)->toEqual([(None, None), (Some("Catalog"), Some("online-shop")), (None, None)])
176
-
177
- EventLogProvisioning.reset()
178
- })
131
+ testSync(
132
+ "notify delivers the ambient plugin/platform inside a construct scope, None outside",
133
+ () => {
134
+ let seen: array<(option<string>, option<string>)> = []
135
+ module OwnerCapture: EventLogProvisioning.Backend = {
136
+ let onProvisioned = (
137
+ ~logStyle as _,
138
+ ~name as _,
139
+ ~owner as _,
140
+ ~plugin,
141
+ ~platform,
142
+ ~resources as _,
143
+ ~opts as _,
144
+ ) => seen->Array.push((plugin, platform))
145
+ }
146
+ EventLogProvisioning.use(module(OwnerCapture: EventLogProvisioning.Backend))
147
+
148
+ // Outside any plugin construct: both None.
149
+ EventLogProvisioning.notify(
150
+ ~logStyle=Classic,
151
+ ~name="ProductEventLog",
152
+ ~owner=Some(classicOwner),
153
+ ~resources=[],
154
+ ~opts=noOpts,
155
+ )
156
+
157
+ // Inside a construct scope (what Plugin_Builder.construct establishes): both delivered.
158
+ let prev = ResourceAttribution.enter(~platform="online-shop", ~plugin="Catalog")
159
+ EventLogProvisioning.notify(
160
+ ~logStyle=Dcb,
161
+ ~name="CatalogDcbEventLog",
162
+ ~owner=Some(dcbOwner),
163
+ ~resources=[],
164
+ ~opts=noOpts,
165
+ )
166
+ ResourceAttribution.restore(prev)
167
+
168
+ // After restore: back to None.
169
+ EventLogProvisioning.notify(
170
+ ~logStyle=Classic,
171
+ ~name="OrderEventLog",
172
+ ~owner=None,
173
+ ~resources=[],
174
+ ~opts=noOpts,
175
+ )
176
+
177
+ expect(seen)->toEqual([(None, None), (Some("Catalog"), Some("online-shop")), (None, None)])
178
+
179
+ EventLogProvisioning.reset()
180
+ },
181
+ )
179
182
 
180
183
  testSync("use is single-slot: a second registration throws rather than silently winning", () => {
181
184
  module First: EventLogProvisioning.Backend = {
@@ -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
  })