@reventlessdev/reventless-core 3.0.0-alpha.238 → 3.0.0-alpha.240

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 (178) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/package.json +12 -12
  3. package/src/Message.res +11 -11
  4. package/src/Message.res.mjs +15 -14
  5. package/src/Projection.res +2 -2
  6. package/src/Projection.res.mjs +5 -4
  7. package/src/adapter/Monitoring/Monitoring.res +24 -2
  8. package/src/adapter/Monitoring/Monitoring.res.mjs +3 -3
  9. package/src/admin/Platform_AdminApi.res.mjs +3 -3
  10. package/src/admin/Platform_Admin_Structure.res +33 -112
  11. package/src/admin/Platform_Admin_Structure.res.mjs +8 -138
  12. package/src/admin/Platform_ComponentDefinitionsApi.res +2 -1
  13. package/src/admin/Platform_ComponentDefinitionsApi.res.mjs +5 -1
  14. package/src/admin/UiFragmentRegistry/StateChangeSlice/UiFragmentRegistry.res.mjs +12 -12
  15. package/src/admin/UiFragmentRegistry/StateViewSlice/UiFragments.res.mjs +14 -14
  16. package/src/components/Aggregate/Aggregate_Callback.res +2 -2
  17. package/src/components/Aggregate/Aggregate_Callback.res.mjs +4 -4
  18. package/src/components/Api/ApiAllowedStatesHelpers.res.mjs +3 -3
  19. package/src/components/Api/ApiNoApiHelpers.res.mjs +5 -5
  20. package/src/components/Api/ApiTargetStateHelpers.res.mjs +3 -3
  21. package/src/components/Api/GraphQL_FragmentGenerator.res +140 -24
  22. package/src/components/Api/GraphQL_FragmentGenerator.res.mjs +48 -21
  23. package/src/components/Api/GraphQL_SchemaInspector.res +1 -1
  24. package/src/components/Api/GraphQL_SchemaInspector.res.mjs +1 -1
  25. package/src/components/Api/MCP_SchemaGenerator.res +1 -1
  26. package/src/components/Api/MCP_SchemaGenerator.res.mjs +1 -1
  27. package/src/components/Api/SchemaType.res +6 -10
  28. package/src/components/Api/SchemaType.res.mjs +4 -4
  29. package/src/components/Api/StorageRefFields.res +1 -1
  30. package/src/components/Api/StorageRefFields.res.mjs +1 -1
  31. package/src/components/Api/SuryToJsonSchema.res +19 -0
  32. package/src/components/Api/SuryToJsonSchema.res.mjs +10 -5
  33. package/src/components/AutomationSlice/AutomationSlice_Callback.res +3 -4
  34. package/src/components/AutomationSlice/AutomationSlice_Callback.res.mjs +22 -23
  35. package/src/components/CommandTopic/CommandTopic_Callback.res +1 -2
  36. package/src/components/CommandTopic/CommandTopic_Callback.res.mjs +3 -4
  37. package/src/components/CommandTopic/CommandTopic_Helpers.res +1 -1
  38. package/src/components/CommandTopic/CommandTopic_Helpers.res.mjs +3 -3
  39. package/src/components/Counter/Counter.res.mjs +2 -2
  40. package/src/components/Counter/Counter_Callback.res.mjs +4 -4
  41. package/src/components/Counter/Counter_Operations.res.mjs +4 -4
  42. package/src/components/Dcb/Dcb_Builder.res +1 -1
  43. package/src/components/Dcb/Dcb_Builder.res.mjs +8 -6
  44. package/src/components/DcbEventLog/DcbEventLog_Builder.res.mjs +4 -3
  45. package/src/components/EventCollector/EventCollector_Builder.res +1 -1
  46. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Callback.res +1 -2
  47. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Callback.res.mjs +11 -12
  48. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Callback.res +3 -4
  49. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Callback.res.mjs +24 -25
  50. package/src/components/SideEffectHandler/SideEffectHandler_Callback.res +1 -1
  51. package/src/components/SideEffectHandler/SideEffectHandler_Callback.res.mjs +3 -3
  52. package/src/components/StateChangeSlice/StateChangeSlice_Callback.res +2 -2
  53. package/src/components/StateChangeSlice/StateChangeSlice_Callback.res.mjs +4 -4
  54. package/src/components/StateViewSlice/StateViewSlice_Builder.res +1 -1
  55. package/src/components/StateViewSlice/StateViewSlice_Builder.res.mjs +3 -3
  56. package/src/plugin/api/PluginBaseFragment.res +12 -29
  57. package/src/plugin/api/PluginBaseFragment.res.mjs +3 -22
  58. package/src/plugin/component/Capability_Inference.res +118 -1
  59. package/src/plugin/component/Capability_Inference.res.mjs +128 -1
  60. package/src/plugin/component/Plugin_Builder.res +9 -2
  61. package/src/plugin/component/Plugin_Builder.res.mjs +5 -2
  62. package/src/plugin/component/Plugin_Helpers.res +11 -11
  63. package/src/plugin/component/Plugin_Helpers.res.mjs +11 -10
  64. package/src/plugin/component/Plugin_Structure.res +458 -296
  65. package/src/plugin/component/Plugin_Structure.res.mjs +259 -182
  66. package/src/plugin/component/Plugin_SubscriptionSchema.res +1 -1
  67. package/src/plugin/component/Plugin_SubscriptionSchema.res.mjs +1 -1
  68. package/src/plugin/component/SchemaWalker.res +11 -11
  69. package/src/plugin/component/SchemaWalker.res.mjs +8 -9
  70. package/src/plugin/connect/PluginExtensionPoint_Plugin.res.mjs +15 -15
  71. package/src/plugin/lifecycle/PluginBehavior.res.mjs +55 -55
  72. package/src/plugin/lifecycle/PluginSpec.res +22 -7
  73. package/src/plugin/lifecycle/PluginSpec.res.mjs +91 -36
  74. package/src/plugin/lifecycle/PluginsReadModelSpec.res +36 -9
  75. package/src/plugin/lifecycle/PluginsReadModelSpec.res.mjs +33 -22
  76. package/src/util/Interstack.res +3 -3
  77. package/src/util/LogFormat.res +1 -2
  78. package/src/util/LogFormat.res.mjs +2 -2
  79. package/tests/IdentityTest.res +6 -7
  80. package/tests/IdentityTest.res.mjs +7 -9
  81. package/tests/adapter/MonitoringTest.res +30 -3
  82. package/tests/adapter/MonitoringTest.res.mjs +31 -12
  83. package/tests/adapter/RuntimeExtensionHookReachTest.res +0 -1
  84. package/tests/adapter/RuntimeExtensionHookReachTest.res.mjs +5 -7
  85. package/tests/admin/Platform_Admin_StructureTest.res +254 -0
  86. package/tests/admin/Platform_Admin_StructureTest.res.mjs +219 -0
  87. package/tests/admin/Platform_BakedManifestTest.res +1 -0
  88. package/tests/admin/Platform_BakedManifestTest.res.mjs +1 -0
  89. package/tests/admin/Platform_ComponentDefinitionsApiTest.res +3 -0
  90. package/tests/admin/Platform_ComponentDefinitionsApiTest.res.mjs +6 -0
  91. package/tests/admin/Platform_PluginStructuresApiTest.res +1 -0
  92. package/tests/admin/Platform_PluginStructuresApiTest.res.mjs +2 -0
  93. package/tests/aggregate/AggregateCacheTest.res +0 -1
  94. package/tests/aggregate/AggregateCacheTest.res.mjs +13 -15
  95. package/tests/aggregate/AggregateConflictTest.res +0 -1
  96. package/tests/aggregate/AggregateConflictTest.res.mjs +7 -9
  97. package/tests/aggregate/AggregateFixtures.res +0 -1
  98. package/tests/aggregate/AggregateFixtures.res.mjs +19 -21
  99. package/tests/aggregate/AggregateSnapshotTest.res +1 -2
  100. package/tests/aggregate/AggregateSnapshotTest.res.mjs +15 -16
  101. package/tests/api/ApiNoApiTest.res.mjs +17 -9
  102. package/tests/api/GraphQL_FragmentGeneratorTest.res +232 -0
  103. package/tests/api/GraphQL_FragmentGeneratorTest.res.mjs +207 -55
  104. package/tests/api/PsInternalFieldsReadModel.res +21 -0
  105. package/tests/api/PsInternalFieldsReadModel.res.mjs +74 -0
  106. package/tests/api/StorageRefFieldsTest.res.mjs +13 -13
  107. package/tests/api/SuryToJsonSchemaTest.res +73 -3
  108. package/tests/api/SuryToJsonSchemaTest.res.mjs +364 -816
  109. package/tests/commandgenerator/CommandGeneratorFixtures.res +0 -1
  110. package/tests/commandgenerator/CommandGeneratorFixtures.res.mjs +19 -21
  111. package/tests/commandgenerator/OwnerStampingTest.res +0 -1
  112. package/tests/commandgenerator/OwnerStampingTest.res.mjs +9 -11
  113. package/tests/commandtopic/CommandTopicCallbackFixtures.res +0 -1
  114. package/tests/commandtopic/CommandTopicCallbackFixtures.res.mjs +7 -9
  115. package/tests/counter/CounterFixtures.res +0 -1
  116. package/tests/counter/CounterFixtures.res.mjs +1 -4
  117. package/tests/dcb/DcbDecodeTest.res.mjs +24 -24
  118. package/tests/dcb/DcbEventLogOperationsTest.res +2 -2
  119. package/tests/dcb/DcbEventLogOperationsTest.res.mjs +3 -3
  120. package/tests/dcb/DcbEventLogSchemaTest.res.mjs +7 -7
  121. package/tests/dcb/DcbFixtures.res +0 -1
  122. package/tests/dcb/DcbFixtures.res.mjs +87 -89
  123. package/tests/dcb/DcbTagTest.res.mjs +6 -6
  124. package/tests/dcb/DcbValidationTest.res.mjs +52 -52
  125. package/tests/eventlog/EventLogFixtures.res +0 -1
  126. package/tests/eventlog/EventLogFixtures.res.mjs +7 -9
  127. package/tests/eventmapper/EventMapperFixtures.res +0 -1
  128. package/tests/eventmapper/EventMapperFixtures.res.mjs +24 -26
  129. package/tests/eventtopic/EventTopicFixtures.res +0 -1
  130. package/tests/eventtopic/EventTopicFixtures.res.mjs +7 -9
  131. package/tests/extensionpoint/ExtensionPointFixtures.res +0 -1
  132. package/tests/extensionpoint/ExtensionPointFixtures.res.mjs +10 -12
  133. package/tests/extensionpoint/ExtensionPointOperationsTest.res +1 -2
  134. package/tests/extensionpoint/ExtensionPointOperationsTest.res.mjs +9 -10
  135. package/tests/logger/LogFormatTest.res +3 -2
  136. package/tests/logger/LogFormatTest.res.mjs +7 -9
  137. package/tests/message/MessageTest.res +2 -2
  138. package/tests/message/MessageTest.res.mjs +8 -7
  139. package/tests/message/MetaEnvelopeTest.res +5 -5
  140. package/tests/message/MetaEnvelopeTest.res.mjs +12 -11
  141. package/tests/plugin/ManifestVisibilityTest.res.mjs +7 -7
  142. package/tests/plugin/PluginDefinitionScalars.res +5 -3
  143. package/tests/plugin/PluginDefinitionScalars.res.mjs +2 -2
  144. package/tests/plugin/PluginLifecycleCorpusTest.res +4 -3
  145. package/tests/plugin/PluginLifecycleCorpusTest.res.mjs +3 -6
  146. package/tests/plugin/PluginSpecExperiment.res +0 -1
  147. package/tests/plugin/PluginSpecExperiment.res.mjs +12 -14
  148. package/tests/plugin/PluginStructureTest.res +292 -2
  149. package/tests/plugin/PluginStructureTest.res.mjs +391 -88
  150. package/tests/plugin/Plugin_EventQuerySchemaTest.res.mjs +3 -3
  151. package/tests/plugin/SchemaWalkerTest.res +0 -1
  152. package/tests/plugin/SchemaWalkerTest.res.mjs +17 -19
  153. package/tests/plugin/StateChangeSlice/PsAttachInvoice.res.mjs +5 -5
  154. package/tests/plugin/StateChangeSlice/PsChangePhoto.res.mjs +8 -8
  155. package/tests/plugin/StateChangeSlice/PsDispatchShipment.res.mjs +5 -5
  156. package/tests/plugin/StateChangeSlice/PsGatedCommands.res.mjs +9 -9
  157. package/tests/plugin/StateChangeSlice/PsPlaceOrder.res.mjs +5 -5
  158. package/tests/plugin/StateChangeSlice/PsReserveStock.res.mjs +8 -8
  159. package/tests/plugin/StateChangeSlice/PsShipOrder.res.mjs +15 -15
  160. package/tests/plugin/StateChangeSlice/PsTypoStore.res +31 -0
  161. package/tests/plugin/StateChangeSlice/PsTypoStore.res.mjs +62 -0
  162. package/tests/plugin/StateChangeSlice/PsUploadAvatar.res.mjs +8 -8
  163. package/tests/plugin/StateChangeSlice/PsUploadImages.res +40 -0
  164. package/tests/plugin/StateChangeSlice/PsUploadImages.res.mjs +66 -0
  165. package/tests/plugin/StateViewSlice/PsAnnotatedView.res.mjs +13 -12
  166. package/tests/plugin/StateViewSlice/PsAvailableProductsView.res.mjs +8 -8
  167. package/tests/plugin/StateViewSlice/PsCategoriesView.res.mjs +6 -6
  168. package/tests/plugin/StateViewSlice/PsCustomersView.res.mjs +10 -10
  169. package/tests/plugin/StateViewSlice/PsGatedView.res.mjs +6 -6
  170. package/tests/plugin/StateViewSlice/PsOrdersView.res.mjs +9 -9
  171. package/tests/plugin/StateViewSlice/PsShipmentsView.res.mjs +11 -10
  172. package/tests/plugin/pluginDefinitionRequiredScalars.txt +15 -0
  173. package/tests/querydb/QueryDbFixtures.res +0 -1
  174. package/tests/querydb/QueryDbFixtures.res.mjs +5 -7
  175. package/tests/sideeffecthandler/SideEffectHandlerFixtures.res +0 -1
  176. package/tests/sideeffecthandler/SideEffectHandlerFixtures.res.mjs +4 -6
  177. package/tests/util/CommandPublisherTest.res +0 -1
  178. package/tests/util/CommandPublisherTest.res.mjs +4 -6
@@ -1,5 +1,17 @@
1
1
  @@reventless.spec("Plugins")
2
2
 
3
+ // Who may read this view. Declared rather than left to default, because the
4
+ // default was `AllowAuthenticated` and it was not true: `PluginBaseFragment`
5
+ // hand-wrote an `Admin` Cognito gate beside it, and the local platform serves
6
+ // every `Platform_*` field behind an `Admin` wrapper. Three statements of one
7
+ // rule, one of which disagreed with the other two.
8
+ //
9
+ // Stating it here makes the spec the source. The AppSync directive comes from
10
+ // this (spec-level `permission` outranks the legacy `{tableName, group}` pair),
11
+ // and so does the `requiredAccess` the platform publishes — so a shell can gate
12
+ // the Plugins view up front instead of offering it and meeting a refusal.
13
+ @@reventless.authorize(Reventless.Authorization.AllowGroups(["Admin"]))
14
+
3
15
  // Current view — one row per plugin **name**, holding the currently-active
4
16
  // version's definition. Keyed by the aggregate id (= plugin name). The status
5
17
  // here is the *current* version's status; "Superseded" is not represented (a
@@ -17,21 +29,33 @@ type status =
17
29
  type state = {
18
30
  name: Reventless.Plugin.name,
19
31
  version: Reventless.Plugin.version,
20
- eventCollector: string,
32
+ // Projection/storage only — never on the GraphQL surface. `@internal` says so
33
+ // on the field, where the next person to edit the record will see it; the same
34
+ // three names used to live in a hand-written exclude list in `PluginBaseFragment`
35
+ // that nothing kept in step with this declaration.
36
+ @internal eventCollector: string,
21
37
  extensionPoints: array<Reventless.Plugin.extensionPointDefinition>,
22
- extensionPointNames: array<string>,
23
- extensionNames: array<string>,
38
+ @internal extensionPointNames: array<string>,
39
+ @internal extensionNames: array<string>,
24
40
  extensions: array<Reventless.Plugin.extensionDefinition>,
25
- status: status,
41
+ // Annotated rather than renamed to `lifecycle` to meet the convention: `status`
42
+ // is published in the SDL, in stored rows and in the UI's hand-written plugin
43
+ // views. Without this the transition check has no states to compare and passes
44
+ // while verifying nothing.
45
+ @lifecycle status: status,
26
46
  statusChange: Message.statusChange,
27
47
  // Stored as the **untagged** offload wire JSON (a bare fragment, or an
28
48
  // `{$offload: {...}}` reference) — NOT the `Offload.payload` variant. The QueryDb
29
49
  // write path marshals the raw ReScript value straight to DynamoDB without
30
50
  // sury-encoding through this field's schema, so a variant would persist as its
31
- // runtime `{TAG, _0}` shape and no reader could parse it. UI-excluded
32
- // (PluginBaseFragment.pluginUIOnlyExcludeFields), so JSON.t typing costs no
33
- // GraphQL consumer. PluginsProjection.displayState writes it via Offload.toJson.
34
- apiSchemaFragment: option<JSON.t>,
51
+ // runtime `{TAG, _0}` shape and no reader could parse it.
52
+ // PluginsProjection.displayState writes it via Offload.toJson.
53
+ //
54
+ // `@hidden`, not `@internal`: the field IS on the API and the host shell fetches
55
+ // it through a dedicated resolver path. What it must not be is a column in a
56
+ // generated list view — it is a multi-kilobyte JSON blob, and a query that names
57
+ // it drags one per row over the wire to render a cell nobody reads.
58
+ @hidden apiSchemaFragment: option<JSON.t>,
35
59
  // API target for split-API schema routing. Absent/None means "Domain" (backward compat).
36
60
  // "Platform" → excluded from DomainApi runtime schema stitching in updateApiSchema.
37
61
  apiTarget?: string,
@@ -39,7 +63,10 @@ type state = {
39
63
  // None for older plugins whose protocol version did not carry the field. Same
40
64
  // untagged-JSON storage as apiSchemaFragment above; the ComponentDefinitions
41
65
  // Lambda detects the `$offload` sentinel and resolves it from S3.
42
- structure: option<JSON.t>,
66
+ //
67
+ // `@hidden` for the same reason, and more so: this is the larger of the two
68
+ // blobs.
69
+ @hidden structure: option<JSON.t>,
43
70
  // DCB EventLog definition for plugins that bundle a DcbEventLog component.
44
71
  // Admin's manageSubscriptions uses this to wire cross-plugin SNS subscriptions
45
72
  // from this plugin's DCB topic → peer EventCollectors (and vice-versa). None
@@ -1,46 +1,54 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
- import * as S from "sury/src/S.res.mjs";
3
+ import * as Sury from "sury";
4
4
  import * as Plugin$Reventless from "@reventlessdev/reventless-spec/src/components/Plugin.res.mjs";
5
5
  import * as ReadModel$Reventless from "@reventlessdev/reventless-spec/src/components/ReadModel.res.mjs";
6
6
  import * as Message$ReventlessCore from "../../Message.res.mjs";
7
7
  import * as StateAnnotations$Reventless from "@reventlessdev/reventless-spec/src/components/StateAnnotations.res.mjs";
8
8
 
9
- let statusSchema = S.union([
10
- S.literal("Connected"),
11
- S.literal("Disconnected"),
12
- S.literal("Inactive"),
13
- S.literal("Retired")
9
+ let statusSchema = Sury.union([
10
+ Sury.literal("Connected"),
11
+ Sury.literal("Disconnected"),
12
+ Sury.literal("Inactive"),
13
+ Sury.literal("Retired")
14
14
  ]);
15
15
 
16
- let stateSchema = S.schema(s => ({
16
+ let stateSchema = Sury.$schema(s => ({
17
17
  name: s.m(Plugin$Reventless.nameSchema),
18
18
  version: s.m(Plugin$Reventless.versionSchema),
19
- eventCollector: s.m(S.string),
20
- extensionPoints: s.m(S.array(Plugin$Reventless.extensionPointDefinitionSchema)),
21
- extensionPointNames: s.m(S.array(S.string)),
22
- extensionNames: s.m(S.array(S.string)),
23
- extensions: s.m(S.array(Plugin$Reventless.extensionDefinitionSchema)),
19
+ eventCollector: s.m(Sury.string),
20
+ extensionPoints: s.m(Sury.array(Plugin$Reventless.extensionPointDefinitionSchema)),
21
+ extensionPointNames: s.m(Sury.array(Sury.string)),
22
+ extensionNames: s.m(Sury.array(Sury.string)),
23
+ extensions: s.m(Sury.array(Plugin$Reventless.extensionDefinitionSchema)),
24
24
  status: s.m(statusSchema),
25
25
  statusChange: s.m(Message$ReventlessCore.statusChangeSchema),
26
- apiSchemaFragment: s.m(S.option(S.json)),
27
- apiTarget: s.m(S.option(S.string)),
28
- structure: s.m(S.option(S.json)),
26
+ apiSchemaFragment: s.m(Sury.$option(Sury.json)),
27
+ apiTarget: s.m(Sury.$option(Sury.string)),
28
+ structure: s.m(Sury.$option(Sury.json)),
29
29
  dcbEventLog: s.m(Plugin$Reventless.dcbEventLogOptionSchema),
30
- kind: s.m(S.option(Plugin$Reventless.pluginKindSchema)),
31
- otherConnectedVersions: s.m(S.array(Plugin$Reventless.versionSchema))
30
+ kind: s.m(Sury.$option(Plugin$Reventless.pluginKindSchema)),
31
+ otherConnectedVersions: s.m(Sury.array(Plugin$Reventless.versionSchema))
32
32
  }));
33
33
 
34
34
  let config = ReadModel$Reventless.config(undefined, undefined, undefined);
35
35
 
36
- let stateSchema$1 = S.Metadata.set(stateSchema, StateAnnotations$Reventless.stateAnnotationsId, {
36
+ let stateSchema$1 = Sury.$Metadata_set(stateSchema, StateAnnotations$Reventless.stateAnnotationsId, {
37
37
  ids: [],
38
38
  compositeIds: [],
39
39
  subIds: [],
40
40
  compositeSubIds: [],
41
41
  indexes: [],
42
- hidden: [],
42
+ hidden: [
43
+ "apiSchemaFragment",
44
+ "structure"
45
+ ],
43
46
  summary: [],
47
+ internal: [
48
+ "eventCollector",
49
+ "extensionPointNames",
50
+ "extensionNames"
51
+ ],
44
52
  drillTargets: [],
45
53
  drillTargetKeys: [],
46
54
  collapsed: [],
@@ -48,13 +56,18 @@ let stateSchema$1 = S.Metadata.set(stateSchema, StateAnnotations$Reventless.stat
48
56
  scanSort: [],
49
57
  semantic: [],
50
58
  metric: [],
51
- lifecycle: undefined,
59
+ lifecycle: "status",
52
60
  groupBy: "kind",
53
61
  visibility: undefined,
54
62
  live: undefined,
55
63
  retired: undefined
56
64
  });
57
65
 
66
+ let authorization = {
67
+ TAG: "AllowGroups",
68
+ _0: ["Admin"]
69
+ };
70
+
58
71
  let name = "Plugins";
59
72
 
60
73
  let Id;
@@ -63,8 +76,6 @@ let subIdConfig;
63
76
 
64
77
  let moduleUrl = "@reventlessdev/reventless-core/src/plugin/lifecycle/PluginsReadModelSpec.res.mjs";
65
78
 
66
- let authorization = "AllowAuthenticated";
67
-
68
79
  let visibility = "Public";
69
80
 
70
81
  export {
@@ -21,7 +21,7 @@ module DefaultTaskQuery = ReventlessInterop.Query.Task.Make({
21
21
  let requiredFields = ["name"]
22
22
  let optionalFields = ["bucketNames", "sideEffectSources"]
23
23
  let fromJson = (json: JSON.t) =>
24
- try Ok(json->S.parseOrThrow(ReventlessInterop.Task.resolvedOutputsSchema))
24
+ try Ok(json->S.parseOrThrow(~to=ReventlessInterop.Task.resolvedOutputsSchema))
25
25
  catch {
26
26
  | exn =>
27
27
  let msg =
@@ -35,7 +35,7 @@ module DefaultEventMapperQuery = ReventlessInterop.Query.EventMapper.Make({
35
35
  let requiredFields = ["name", "eventCollector"]
36
36
  let optionalFields = ["counter"]
37
37
  let fromJson = (json: JSON.t) =>
38
- try Ok(json->S.parseOrThrow(ReventlessInterop.EventMapper.resolvedOutputsSchema))
38
+ try Ok(json->S.parseOrThrow(~to=ReventlessInterop.EventMapper.resolvedOutputsSchema))
39
39
  catch {
40
40
  | exn =>
41
41
  let msg =
@@ -54,7 +54,7 @@ module DefaultExtensionPointQuery = ReventlessInterop.Query.ExtensionPoint.Make(
54
54
  let requiredFields = ["name", "commandTopic", "eventTopic"]
55
55
  let optionalFields = []
56
56
  let fromJson = (json: JSON.t) =>
57
- try Ok(json->S.parseOrThrow(ReventlessInterop.ExtensionPoint.resolvedOutputsSchema))
57
+ try Ok(json->S.parseOrThrow(~to=ReventlessInterop.ExtensionPoint.resolvedOutputsSchema))
58
58
  catch {
59
59
  | exn =>
60
60
  let msg =
@@ -248,8 +248,7 @@ let fmtState = (~name: string, ~id: string, ~seq: int): string =>
248
248
  `state=${name}(${id}) seq=${seq->Int.toString}`
249
249
 
250
250
  // "err=<message>"
251
- let fmtExn = (e: exn): string =>
252
- `err=${e->JsExn.fromException->Option.flatMap(JsExn.message)->Option.getOr("unknown")}`
251
+ let fmtExn = (e: exn): string => `err=${e->Reventless.Util_Sury.exnMessage}`
253
252
 
254
253
  // ─── Legacy aliases (kept for existing callers) ──────────────────────────────
255
254
 
@@ -3,10 +3,10 @@
3
3
  import * as Stdlib_Int from "@rescript/runtime/lib/es6/Stdlib_Int.js";
4
4
  import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
5
5
  import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
6
- import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
7
6
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
8
7
  import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
9
8
  import * as AnsiStyle$Reventless from "@reventlessdev/reventless-spec/src/AnsiStyle.res.mjs";
9
+ import * as Util_Sury$Reventless from "@reventlessdev/reventless-spec/src/util/Util_Sury.res.mjs";
10
10
  import * as Message$ReventlessCore from "../Message.res.mjs";
11
11
 
12
12
  let maxValueChars = Stdlib_Option.getOr(Stdlib_Option.flatMap(process.env["REVENTLESS_LOG_MAX_VALUE"], v => Stdlib_Int.fromString(v, undefined)), 512);
@@ -204,7 +204,7 @@ function fmtState(name, id, seq) {
204
204
  }
205
205
 
206
206
  function fmtExn(e) {
207
- return `err=` + Stdlib_Option.getOr(Stdlib_Option.flatMap(Stdlib_JsExn.fromException(e), Stdlib_JsExn.message), "unknown");
207
+ return `err=` + Util_Sury$Reventless.exnMessage(e, undefined);
208
208
  }
209
209
 
210
210
  function commandJsonsToLogMessages(cmdJsons) {
@@ -1,6 +1,5 @@
1
1
  open JestGlobals
2
2
 
3
- S.enableJson()
4
3
 
5
4
  describe("Identity", () => {
6
5
  describe("anonymous", () => {
@@ -71,8 +70,8 @@ describe("Identity", () => {
71
70
  claims: Dict.fromArray([("tenant", "acme")]),
72
71
  provider: Cognito,
73
72
  }
74
- let json = identity->S.reverseConvertToJsonOrThrow(Reventless.Identity.schema)
75
- let decoded = json->S.parseJsonOrThrow(Reventless.Identity.schema)
73
+ let json = identity->Reventless.Util_Sury.toJson(Reventless.Identity.schema)
74
+ let decoded = json->Reventless.Util_Sury.fromJson(Reventless.Identity.schema)
76
75
  expect(decoded)->toEqual(identity)
77
76
  })
78
77
 
@@ -83,8 +82,8 @@ describe("Identity", () => {
83
82
  groups: [],
84
83
  provider: Custom("oauth2"),
85
84
  }
86
- let json = identity->S.reverseConvertToJsonOrThrow(Reventless.Identity.schema)
87
- let decoded = json->S.parseJsonOrThrow(Reventless.Identity.schema)
85
+ let json = identity->Reventless.Util_Sury.toJson(Reventless.Identity.schema)
86
+ let decoded = json->Reventless.Util_Sury.fromJson(Reventless.Identity.schema)
88
87
  expect(decoded)->toEqual(identity)
89
88
  })
90
89
 
@@ -95,8 +94,8 @@ describe("Identity", () => {
95
94
  groups: [],
96
95
  provider: InMemory,
97
96
  }
98
- let json = identity->S.reverseConvertToJsonOrThrow(Reventless.Identity.schema)
99
- let decoded = json->S.parseJsonOrThrow(Reventless.Identity.schema)
97
+ let json = identity->Reventless.Util_Sury.toJson(Reventless.Identity.schema)
98
+ let decoded = json->Reventless.Util_Sury.fromJson(Reventless.Identity.schema)
100
99
  expect(decoded.userId)->toBe("user-3")->ignore
101
100
  expect(decoded.provider)->toEqual(Reventless.Identity.InMemory)
102
101
  })
@@ -1,11 +1,9 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
- import * as S from "sury/src/S.res.mjs";
4
3
  import * as Identity$Reventless from "@reventlessdev/reventless-spec/src/types/Identity.res.mjs";
4
+ import * as Util_Sury$Reventless from "@reventlessdev/reventless-spec/src/util/Util_Sury.res.mjs";
5
5
  import * as RequestContext$ReventlessCore from "../src/RequestContext.res.mjs";
6
6
 
7
- S.enableJson();
8
-
9
7
  globalThis.describe("Identity", () => {
10
8
  globalThis.describe("anonymous", () => {
11
9
  globalThis.test("has userId 'anonymous'", () => {
@@ -86,8 +84,8 @@ globalThis.describe("Identity", () => {
86
84
  claims: identity_claims,
87
85
  provider: "Cognito"
88
86
  };
89
- let json = S.reverseConvertToJsonOrThrow(identity, Identity$Reventless.schema);
90
- let decoded = S.parseJsonOrThrow(json, Identity$Reventless.schema);
87
+ let json = Util_Sury$Reventless.toJson(identity, Identity$Reventless.schema);
88
+ let decoded = Util_Sury$Reventless.fromJson(json, Identity$Reventless.schema);
91
89
  globalThis.expect(decoded).toEqual(identity);
92
90
  });
93
91
  globalThis.test("roundtrip with Custom provider", () => {
@@ -102,8 +100,8 @@ globalThis.describe("Identity", () => {
102
100
  groups: identity_groups,
103
101
  provider: identity_provider
104
102
  };
105
- let json = S.reverseConvertToJsonOrThrow(identity, Identity$Reventless.schema);
106
- let decoded = S.parseJsonOrThrow(json, Identity$Reventless.schema);
103
+ let json = Util_Sury$Reventless.toJson(identity, Identity$Reventless.schema);
104
+ let decoded = Util_Sury$Reventless.fromJson(json, Identity$Reventless.schema);
107
105
  globalThis.expect(decoded).toEqual(identity);
108
106
  });
109
107
  globalThis.test("roundtrip without optional claims", () => {
@@ -114,8 +112,8 @@ globalThis.describe("Identity", () => {
114
112
  groups: identity_groups,
115
113
  provider: "InMemory"
116
114
  };
117
- let json = S.reverseConvertToJsonOrThrow(identity, Identity$Reventless.schema);
118
- let decoded = S.parseJsonOrThrow(json, Identity$Reventless.schema);
115
+ let json = Util_Sury$Reventless.toJson(identity, Identity$Reventless.schema);
116
+ let decoded = Util_Sury$Reventless.fromJson(json, Identity$Reventless.schema);
119
117
  globalThis.expect(decoded.userId).toBe("user-3");
120
118
  globalThis.expect(decoded.provider).toEqual("InMemory");
121
119
  });
@@ -15,7 +15,7 @@ describe("Monitoring", () => {
15
15
  testSync("use registers a backend that receives every notify, role and name", () => {
16
16
  let recorded: array<(Monitoring.unitKind, string)> = []
17
17
  module Recorder: Monitoring.Backend = {
18
- let onProvisioned = (~kind, ~name, ~component as _, ~plugin as _, ~platform as _) =>
18
+ let onProvisioned = (~kind, ~name, ~component as _, ~plugin as _, ~platform as _, ~logLocator as _) =>
19
19
  recorded->Array.push((kind, name))
20
20
  }
21
21
  Monitoring.use(module(Recorder: Monitoring.Backend))
@@ -39,7 +39,7 @@ describe("Monitoring", () => {
39
39
  testSync("notify forwards the static name and component resource to the backend", () => {
40
40
  let seen: ref<option<(string, ReventlessInfra.Adapter.resource)>> = ref(None)
41
41
  module Capture: Monitoring.Backend = {
42
- let onProvisioned = (~kind as _, ~name, ~component, ~plugin as _, ~platform as _) =>
42
+ let onProvisioned = (~kind as _, ~name, ~component, ~plugin as _, ~platform as _, ~logLocator as _) =>
43
43
  seen := Some((name, component))
44
44
  }
45
45
  Monitoring.use(module(Capture: Monitoring.Backend))
@@ -56,7 +56,7 @@ describe("Monitoring", () => {
56
56
  testSync("notify delivers the ambient plugin/platform inside a construct scope, None outside", () => {
57
57
  let seen: array<(option<string>, option<string>)> = []
58
58
  module OwnerCapture: Monitoring.Backend = {
59
- let onProvisioned = (~kind as _, ~name as _, ~component as _, ~plugin, ~platform) =>
59
+ let onProvisioned = (~kind as _, ~name as _, ~component as _, ~plugin, ~platform, ~logLocator as _) =>
60
60
  seen->Array.push((plugin, platform))
61
61
  }
62
62
  Monitoring.use(module(OwnerCapture: Monitoring.Backend))
@@ -80,4 +80,31 @@ describe("Monitoring", () => {
80
80
 
81
81
  Monitoring.use(module(Monitoring.Noop))
82
82
  })
83
+
84
+ // Unlike the owner, the locator is not ambient — the seam only forwards what the provisioning
85
+ // site passed. A site with nothing to say omits it, and the backend must see that as "this unit
86
+ // has no logs of its own" rather than receiving a fabricated address.
87
+ testSync("notify forwards the log locator when given one, None when omitted", () => {
88
+ // The registry only forwards the locator; it never resolves it. A structural stand-in keeps
89
+ // @pulumi/pulumi out of the Jest run, exactly as `stubResource` does.
90
+ let stubLocator: Pulumi.Output.t<string> = %raw(`{}`)
91
+ let seen: array<bool> = []
92
+ module LocatorCapture: Monitoring.Backend = {
93
+ let onProvisioned = (~kind as _, ~name as _, ~component as _, ~plugin as _, ~platform as _, ~logLocator) =>
94
+ seen->Array.push(logLocator->Option.isSome)
95
+ }
96
+ Monitoring.use(module(LocatorCapture: Monitoring.Backend))
97
+
98
+ Monitoring.notify(
99
+ ~kind=CommandHandler,
100
+ ~name="AllAggregatesCmdHandler",
101
+ ~component=stubResource,
102
+ ~logLocator=stubLocator,
103
+ )
104
+ Monitoring.notify(~kind=DeadLetterSink, ~name="DeadLetterQueue", ~component=stubResource)
105
+
106
+ expect(seen)->toEqual([true, false])
107
+
108
+ Monitoring.use(module(Monitoring.Noop))
109
+ })
83
110
  })
@@ -1,5 +1,6 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
3
4
  import * as Monitoring$ReventlessCore from "../../src/adapter/Monitoring/Monitoring.res.mjs";
4
5
  import * as ResourceAttribution$ReventlessCore from "../../src/ResourceAttribution.res.mjs";
5
6
 
@@ -7,12 +8,12 @@ let stubResource = {};
7
8
 
8
9
  globalThis.describe("Monitoring", () => {
9
10
  globalThis.test("Noop default: notify is silent and does not throw", () => {
10
- Monitoring$ReventlessCore.notify("CommandHandler", "before", stubResource);
11
+ Monitoring$ReventlessCore.notify("CommandHandler", "before", stubResource, undefined);
11
12
  globalThis.expect(true).toBe(true);
12
13
  });
13
14
  globalThis.test("use registers a backend that receives every notify, role and name", () => {
14
15
  let recorded = [];
15
- let onProvisioned = (kind, name, param, param$1, param$2) => {
16
+ let onProvisioned = (kind, name, param, param$1, param$2, param$3) => {
16
17
  recorded.push([
17
18
  kind,
18
19
  name
@@ -22,13 +23,13 @@ globalThis.describe("Monitoring", () => {
22
23
  onProvisioned: onProvisioned
23
24
  };
24
25
  Monitoring$ReventlessCore.use(Recorder);
25
- Monitoring$ReventlessCore.notify("CommandHandler", "AllAggregatesCmdHandler", stubResource);
26
- Monitoring$ReventlessCore.notify("Projection", "AllStateViewSlices", stubResource);
27
- Monitoring$ReventlessCore.notify("DeadLetterSink", "DeadLetterQueue", stubResource);
26
+ Monitoring$ReventlessCore.notify("CommandHandler", "AllAggregatesCmdHandler", stubResource, undefined);
27
+ Monitoring$ReventlessCore.notify("Projection", "AllStateViewSlices", stubResource, undefined);
28
+ Monitoring$ReventlessCore.notify("DeadLetterSink", "DeadLetterQueue", stubResource, undefined);
28
29
  Monitoring$ReventlessCore.notify({
29
30
  TAG: "Other",
30
31
  _0: "Counter"
31
- }, "ProductCounter", stubResource);
32
+ }, "ProductCounter", stubResource, undefined);
32
33
  globalThis.expect(recorded).toEqual([
33
34
  [
34
35
  "CommandHandler",
@@ -56,7 +57,7 @@ globalThis.describe("Monitoring", () => {
56
57
  let seen = {
57
58
  contents: undefined
58
59
  };
59
- let onProvisioned = (param, name, component, param$1, param$2) => {
60
+ let onProvisioned = (param, name, component, param$1, param$2, param$3) => {
60
61
  seen.contents = [
61
62
  name,
62
63
  component
@@ -66,7 +67,7 @@ globalThis.describe("Monitoring", () => {
66
67
  onProvisioned: onProvisioned
67
68
  };
68
69
  Monitoring$ReventlessCore.use(Capture);
69
- Monitoring$ReventlessCore.notify("Scheduler", "HeartbeatUnit", stubResource);
70
+ Monitoring$ReventlessCore.notify("Scheduler", "HeartbeatUnit", stubResource, undefined);
70
71
  let match = seen.contents;
71
72
  if (match !== undefined) {
72
73
  globalThis.expect(match[0]).toBe("HeartbeatUnit");
@@ -77,7 +78,7 @@ globalThis.describe("Monitoring", () => {
77
78
  });
78
79
  globalThis.test("notify delivers the ambient plugin/platform inside a construct scope, None outside", () => {
79
80
  let seen = [];
80
- let onProvisioned = (param, param$1, param$2, plugin, platform) => {
81
+ let onProvisioned = (param, param$1, param$2, plugin, platform, param$3) => {
81
82
  seen.push([
82
83
  plugin,
83
84
  platform
@@ -87,11 +88,11 @@ globalThis.describe("Monitoring", () => {
87
88
  onProvisioned: onProvisioned
88
89
  };
89
90
  Monitoring$ReventlessCore.use(OwnerCapture);
90
- Monitoring$ReventlessCore.notify("CommandHandler", "ApiRouter", stubResource);
91
+ Monitoring$ReventlessCore.notify("CommandHandler", "ApiRouter", stubResource, undefined);
91
92
  let prev = ResourceAttribution$ReventlessCore.enter("online-shop", "Ordering");
92
- Monitoring$ReventlessCore.notify("CommandHandler", "AllAggregatesCmdHandler", stubResource);
93
+ Monitoring$ReventlessCore.notify("CommandHandler", "AllAggregatesCmdHandler", stubResource, undefined);
93
94
  ResourceAttribution$ReventlessCore.restore(prev);
94
- Monitoring$ReventlessCore.notify("Projection", "AllStateViewSlices", stubResource);
95
+ Monitoring$ReventlessCore.notify("Projection", "AllStateViewSlices", stubResource, undefined);
95
96
  globalThis.expect(seen).toEqual([
96
97
  [
97
98
  undefined,
@@ -108,6 +109,24 @@ globalThis.describe("Monitoring", () => {
108
109
  ]);
109
110
  Monitoring$ReventlessCore.use(Monitoring$ReventlessCore.Noop);
110
111
  });
112
+ globalThis.test("notify forwards the log locator when given one, None when omitted", () => {
113
+ let stubLocator = {};
114
+ let seen = [];
115
+ let onProvisioned = (param, param$1, param$2, param$3, param$4, logLocator) => {
116
+ seen.push(Stdlib_Option.isSome(logLocator));
117
+ };
118
+ let LocatorCapture = {
119
+ onProvisioned: onProvisioned
120
+ };
121
+ Monitoring$ReventlessCore.use(LocatorCapture);
122
+ Monitoring$ReventlessCore.notify("CommandHandler", "AllAggregatesCmdHandler", stubResource, stubLocator);
123
+ Monitoring$ReventlessCore.notify("DeadLetterSink", "DeadLetterQueue", stubResource, undefined);
124
+ globalThis.expect(seen).toEqual([
125
+ true,
126
+ false
127
+ ]);
128
+ Monitoring$ReventlessCore.use(Monitoring$ReventlessCore.Noop);
129
+ });
111
130
  });
112
131
 
113
132
  export {
@@ -1,6 +1,5 @@
1
1
  open JestGlobals
2
2
 
3
- S.enableJson()
4
3
 
5
4
  // The point of the seam, end to end at the hook level: an extension that only
6
5
  // ever gets `onColdStart` can reach the framework's runtime callback hooks from
@@ -1,6 +1,6 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
- import * as S from "sury/src/S.res.mjs";
3
+ import * as Sury from "sury";
4
4
  import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
5
5
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
6
6
  import * as Effect from "effect/Effect";
@@ -8,12 +8,10 @@ import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_excep
8
8
  import * as RuntimeExtension$ReventlessCore from "../../src/adapter/RuntimeExtension/RuntimeExtension.res.mjs";
9
9
  import * as CommandGenerator_Callback$ReventlessCore from "../../src/components/CommandGenerator/CommandGenerator_Callback.res.mjs";
10
10
 
11
- S.enableJson();
12
-
13
- let commandSchema = S.schema(s => ({
11
+ let commandSchema = Sury.$schema(s => ({
14
12
  TAG: "Add",
15
- productId: s.m(S.string),
16
- name: s.m(S.string)
13
+ productId: s.m(Sury.string),
14
+ name: s.m(Sury.string)
17
15
  }));
18
16
 
19
17
  let published = {
@@ -94,4 +92,4 @@ export {
94
92
  addChair,
95
93
  runAdd,
96
94
  }
97
- /* Not a pure module */
95
+ /* commandSchema Not a pure module */