@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,6 +1,5 @@
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 Stream from "@reventlessdev/rescript-effect/src/Stream.res.mjs";
5
4
  import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
6
5
  import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
@@ -12,6 +11,7 @@ import * as Effect from "effect/Effect";
12
11
  import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
13
12
  import * as DcbDecode$Reventless from "@reventlessdev/reventless-spec/src/components/DcbDecode.res.mjs";
14
13
  import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
14
+ import * as Util_Sury$Reventless from "@reventlessdev/reventless-spec/src/util/Util_Sury.res.mjs";
15
15
  import * as Message$ReventlessCore from "../../Message.res.mjs";
16
16
  import * as Component$ReventlessCore from "../Component.res.mjs";
17
17
  import * as LogFormat$ReventlessCore from "../../util/LogFormat.res.mjs";
@@ -87,7 +87,7 @@ function Make(RuntimeEnvironment) {
87
87
  let meta;
88
88
  if (m !== undefined) {
89
89
  try {
90
- meta = S.parseJsonOrThrow(m, Message$ReventlessCore.metaSchema);
90
+ meta = Util_Sury$Reventless.fromJson(m, Message$ReventlessCore.metaSchema);
91
91
  } catch (exn) {
92
92
  meta = Message$ReventlessCore.generateMeta(Spec.name, undefined, undefined, undefined, undefined, undefined, undefined, undefined);
93
93
  }
@@ -158,4 +158,4 @@ export {
158
158
  FrameworkProjection,
159
159
  Make,
160
160
  }
161
- /* S Not a pure module */
161
+ /* Stream Not a pure module */
@@ -1,32 +1,5 @@
1
1
  open ReventlessInfra.Api
2
2
 
3
- let adminAuth: Reventless.ReadModel.authorization = {
4
- tableName: "Plugin",
5
- group: "Admin",
6
- }
7
-
8
- // Fields present on `PluginsReadModelSpec.state` for projection/storage purposes
9
- // but intentionally absent from the public GraphQL surface. Shared with
10
- // `Platform_Admin_Structure` so the schema announced via `Platform_ComponentDefinitions`
11
- // stays aligned with the SDL — otherwise AutoUI generates list-view queries
12
- // for fields the server doesn't expose and every Plugin row fails to load.
13
- let pluginExcludeFields: array<string> = [
14
- "eventCollector",
15
- "extensionPointNames",
16
- "extensionNames",
17
- ]
18
-
19
- // Additional fields the SDL exposes but the Plugin list view should NOT
20
- // surface — they're option-of-nested-object types (e.g. apiSchemaFragment,
21
- // structure) which AutoUI currently renders as scalar columns
22
- // and queries without a sub-selection, failing schema validation. Other
23
- // callers (host-shell's Platform_ComponentDefinitions) keep querying them via
24
- // dedicated fields and resolver paths.
25
- let pluginUIOnlyExcludeFields: array<string> = pluginExcludeFields->Array.concat([
26
- "apiSchemaFragment",
27
- "structure",
28
- ])
29
-
30
3
  // Admin read-model query entries are generated from each spec the same way
31
4
  // ordinary read models are (Plugin_Builder.res): `subIdField` flows from the
32
5
  // spec's `subIdConfig` and `indexQueries` from `config.indexes`, so
@@ -57,8 +30,18 @@ let queryEntries: array<querySchemaEntry> = [
57
30
  listFieldName: Api_Naming.adminField(~name="Plugins"),
58
31
  returnTypeName: Api_Naming.adminField(~name="Plugin"),
59
32
  stateSchema: PluginsReadModelSpec.stateSchema->S.castToUnknown,
60
- authorization: Some(adminAuth),
61
- excludeFields: pluginExcludeFields,
33
+ // Read off the spec rather than restated. The hand-written
34
+ // `{tableName: "Plugin", group: "Admin"}` that used to sit here said the same
35
+ // thing as `Spec.authorization` in a different type, and the spec's default
36
+ // (`AllowAuthenticated`) disagreed with it — so the view's rule depended on
37
+ // which of the two a reader happened to find. The `tableName` half was never
38
+ // read: the entry path uses only the group, and the per-`@index` auth-table
39
+ // pipeline params come from `indexConfig.authorization`, which is untouched.
40
+ authorization: None,
41
+ permission: PluginsReadModelSpec.authorization,
42
+ // No `excludeFields`: the three fields this entry used to name are declared
43
+ // `@internal` on the spec, and `deriveObjectTypeWithNested` reads that off the
44
+ // schema itself.
62
45
  subIdField: ?PluginsReadModelSpec.subIdConfig->Option.map((c: Reventless.ReadModel.subIdConfig<_>) => c.subIdField),
63
46
  indexQueries: ?indexQueriesOfConfig(PluginsReadModelSpec.config),
64
47
  },
@@ -7,22 +7,6 @@ import * as PluginSpec$ReventlessCore from "../lifecycle/PluginSpec.res.mjs";
7
7
  import * as ApiNoApiHelpers$ReventlessCore from "../../components/Api/ApiNoApiHelpers.res.mjs";
8
8
  import * as PluginsReadModelSpec$ReventlessCore from "../lifecycle/PluginsReadModelSpec.res.mjs";
9
9
 
10
- let adminAuth = {
11
- tableName: "Plugin",
12
- group: "Admin"
13
- };
14
-
15
- let pluginExcludeFields = [
16
- "eventCollector",
17
- "extensionPointNames",
18
- "extensionNames"
19
- ];
20
-
21
- let pluginUIOnlyExcludeFields = pluginExcludeFields.concat([
22
- "apiSchemaFragment",
23
- "structure"
24
- ]);
25
-
26
10
  function indexQueriesOfConfig(config) {
27
11
  if (config.indexes.length !== 0) {
28
12
  return config.indexes;
@@ -35,8 +19,8 @@ let queryEntries = [{
35
19
  returnTypeName: Api_Naming$ReventlessCore.adminField("Plugin"),
36
20
  stateSchema: PluginsReadModelSpec$ReventlessCore.stateSchema,
37
21
  specName: PluginsReadModelSpec$ReventlessCore.name,
38
- authorization: adminAuth,
39
- excludeFields: pluginExcludeFields,
22
+ authorization: undefined,
23
+ permission: PluginsReadModelSpec$ReventlessCore.authorization,
40
24
  subIdField: Stdlib_Option.map(undefined, c => c.subIdField),
41
25
  indexQueries: indexQueriesOfConfig(PluginsReadModelSpec$ReventlessCore.config)
42
26
  }];
@@ -53,11 +37,8 @@ let pluginAggregateMutationEntries = fieldNames.length === 0 ? [] : [{
53
37
  }];
54
38
 
55
39
  export {
56
- adminAuth,
57
- pluginExcludeFields,
58
- pluginUIOnlyExcludeFields,
59
40
  indexQueriesOfConfig,
60
41
  queryEntries,
61
42
  pluginAggregateMutationEntries,
62
43
  }
63
- /* pluginUIOnlyExcludeFields Not a pure module */
44
+ /* queryEntries Not a pure module */
@@ -55,7 +55,7 @@ let scanSchema = (~component: string, schema: S.t<unknown>): array<warning> => {
55
55
  | _ => []
56
56
  }
57
57
  switch schema {
58
- | Union({anyOf}) => anyOf->Array.flatMap(fromVariant)
58
+ | AnyOf({anyOf}) => anyOf->Array.flatMap(fromVariant)
59
59
  | other => fromVariant(other)
60
60
  }
61
61
  }
@@ -66,3 +66,120 @@ let message = (w: warning): string =>
66
66
  `${w.component}.${w.field} looks like a stored-object reference but declares no store — ` ++
67
67
  `annotate it \`@storageRef("<store>")\` so the deployment provisions the store it needs, ` ++
68
68
  `or rename the field if it holds an external URL. Heuristic matches are never provisioned.`
69
+
70
+ // ── Near-duplicate stores ──────────────────────────────────────────────────
71
+ //
72
+ // Under name-derived stores a typo does not fail, it *provisions*: `productImage`
73
+ // and `productImgae` both compile, both deploy, and objects split silently
74
+ // across two buckets. Nothing else in the pipeline can see the mistake — both
75
+ // are well-formed declarations — so the check has to live where every store a
76
+ // plugin declares is visible at once.
77
+ //
78
+ // Unlike the heuristic lint above this is a hard failure, and it is meant to be:
79
+ // a warning about infrastructure that was already created is a warning nobody
80
+ // can act on cheaply. A pair that is genuinely two stores settles it by naming
81
+ // one explicitly with `@storageRef("<store>")`.
82
+
83
+ /** Two store declarations close enough that one is likely a typo for the other. */
84
+ type collision = {
85
+ a: Reventless.Plugin.requiredStoreDeclaration,
86
+ b: Reventless.Plugin.requiredStoreDeclaration,
87
+ }
88
+
89
+ // Exactly the optimal-string-alignment distance ≤ 1: one insert, one delete, one
90
+ // substitution, or one transposition. Written directly rather than as a general
91
+ // distance because a transposition is the shape the motivating typo has
92
+ // (`Images` → `Imgaes`), and a plain Levenshtein scores that 2 and misses it.
93
+ let withinOneEdit = (a: string, b: string): bool => {
94
+ let (la, lb) = (String.length(a), String.length(b))
95
+ let charAt = (s, i) => String.charAt(s, i)
96
+ if la == lb {
97
+ let diffs = []
98
+ for i in 0 to la - 1 {
99
+ if charAt(a, i) != charAt(b, i) {
100
+ diffs->Array.push(i)
101
+ }
102
+ }
103
+ switch diffs {
104
+ | [] => true
105
+ | [_] => true
106
+ | [i, j] if j == i + 1 =>
107
+ charAt(a, i) == charAt(b, j) && charAt(a, j) == charAt(b, i)
108
+ | _ => false
109
+ }
110
+ } else if la - lb == 1 || lb - la == 1 {
111
+ // The longer string with one character removed must equal the shorter one.
112
+ let (long, short) = la > lb ? (a, b) : (b, a)
113
+ let rec scan = (~li, ~si, ~skipped) =>
114
+ if si >= String.length(short) {
115
+ true
116
+ } else if charAt(long, li) == charAt(short, si) {
117
+ scan(~li=li + 1, ~si=si + 1, ~skipped)
118
+ } else if skipped {
119
+ false
120
+ } else {
121
+ scan(~li=li + 1, ~si, ~skipped=true)
122
+ }
123
+ scan(~li=0, ~si=0, ~skipped=false)
124
+ } else {
125
+ false
126
+ }
127
+ }
128
+
129
+ /** Whether two store names are the same word in different number. Reached only
130
+ through an explicit `@storageRef` override — a derived name is already
131
+ pluralised through its singular stem, so two *derived* names cannot differ
132
+ this way. */
133
+ let sameStem = (a: string, b: string): bool =>
134
+ Api_Naming.singularize(a) == Api_Naming.singularize(b)
135
+
136
+ // The unqualified store name and its owning plugin, split off the qualified key
137
+ // the declarations carry.
138
+ let splitKey = (key: string): (string, string) =>
139
+ switch key->String.split(".") {
140
+ | [plugin, store] => (plugin, store)
141
+ | _ => ("", key)
142
+ }
143
+
144
+ /**
145
+ Pairs of declared stores that are probably one store misspelled twice.
146
+
147
+ Compared within an owning plugin only: two plugins may legitimately hold stores
148
+ whose names are one edit apart, and neither can be a typo for the other.
149
+ */
150
+ let collisions = (
151
+ declarations: array<Reventless.Plugin.requiredStoreDeclaration>,
152
+ ): array<collision> => {
153
+ // One entry per store, keeping the first declaration site as the one the
154
+ // message names — several fields naming one store is ordinary, not a clash.
155
+ let byStore: dict<Reventless.Plugin.requiredStoreDeclaration> = Dict.make()
156
+ declarations->Array.forEach(d =>
157
+ switch byStore->Dict.get(d.store) {
158
+ | Some(_) => ()
159
+ | None => byStore->Dict.set(d.store, d)
160
+ }
161
+ )
162
+ let unique = byStore->Dict.valuesToArray
163
+ let found = []
164
+ for i in 0 to Array.length(unique) - 1 {
165
+ for j in i + 1 to Array.length(unique) - 1 {
166
+ let a = unique->Array.getUnsafe(i)
167
+ let b = unique->Array.getUnsafe(j)
168
+ let (pluginA, storeA) = splitKey(a.store)
169
+ let (pluginB, storeB) = splitKey(b.store)
170
+ if pluginA == pluginB && (withinOneEdit(storeA, storeB) || sameStem(storeA, storeB)) {
171
+ found->Array.push({a, b})->ignore
172
+ }
173
+ }
174
+ }
175
+ found
176
+ }
177
+
178
+ /** The failure text: name both stores and both declaration sites, so a pair that
179
+ is genuinely two stores is diagnosed in one reading. */
180
+ let collisionMessage = (c: collision): string =>
181
+ `${c.a.store} (${c.a.component}.${c.a.field}) and ${c.b.store} ` ++
182
+ `(${c.b.component}.${c.b.field}) differ by one edit — one is probably a typo for ` ++
183
+ `the other, and both would be provisioned, splitting objects across two stores. ` ++
184
+ `Fix the field name, or name the store explicitly with \`@storageRef("<store>")\` ` ++
185
+ `if the two really are separate stores.`
@@ -3,6 +3,7 @@
3
3
  import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
4
4
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
5
5
  import * as StorageRef$Reventless from "@reventlessdev/reventless-spec/src/semantic/StorageRef.res.mjs";
6
+ import * as Api_Naming$ReventlessCore from "../../components/Api/Api_Naming.res.mjs";
6
7
 
7
8
  let refLikeNames = [
8
9
  "file",
@@ -56,7 +57,7 @@ function scanSchema(component, schema) {
56
57
  return [];
57
58
  }
58
59
  };
59
- if (schema.type === "union") {
60
+ if (schema.type === "anyOf") {
60
61
  return schema.anyOf.flatMap(fromVariant);
61
62
  } else {
62
63
  return fromVariant(schema);
@@ -67,6 +68,127 @@ function message(w) {
67
68
  return w.component + `.` + w.field + ` looks like a stored-object reference but declares no store — annotate it \`@storageRef("<store>")\` so the deployment provisions the store it needs, or rename the field if it holds an external URL. Heuristic matches are never provisioned.`;
68
69
  }
69
70
 
71
+ function withinOneEdit(a, b) {
72
+ let la = a.length;
73
+ let lb = b.length;
74
+ if (la === lb) {
75
+ let diffs = [];
76
+ for (let i = 0; i < la; ++i) {
77
+ if (a.charAt(i) !== b.charAt(i)) {
78
+ diffs.push(i);
79
+ }
80
+ }
81
+ let len = diffs.length;
82
+ if (len >= 3) {
83
+ return false;
84
+ }
85
+ switch (len) {
86
+ case 0 :
87
+ case 1 :
88
+ return true;
89
+ case 2 :
90
+ let i$1 = diffs[0];
91
+ let j = diffs[1];
92
+ if (j === (i$1 + 1 | 0) && a.charAt(i$1) === b.charAt(j)) {
93
+ return a.charAt(j) === b.charAt(i$1);
94
+ } else {
95
+ return false;
96
+ }
97
+ }
98
+ } else {
99
+ if ((la - lb | 0) !== 1 && (lb - la | 0) !== 1) {
100
+ return false;
101
+ }
102
+ let match = la > lb ? [
103
+ a,
104
+ b
105
+ ] : [
106
+ b,
107
+ a
108
+ ];
109
+ let short = match[1];
110
+ let long = match[0];
111
+ let _li = 0;
112
+ let _si = 0;
113
+ let _skipped = false;
114
+ while (true) {
115
+ let skipped = _skipped;
116
+ let si = _si;
117
+ let li = _li;
118
+ if (si >= short.length) {
119
+ return true;
120
+ }
121
+ if (long.charAt(li) === short.charAt(si)) {
122
+ _si = si + 1 | 0;
123
+ _li = li + 1 | 0;
124
+ continue;
125
+ }
126
+ if (skipped) {
127
+ return false;
128
+ }
129
+ _skipped = true;
130
+ _li = li + 1 | 0;
131
+ continue;
132
+ };
133
+ }
134
+ }
135
+
136
+ function sameStem(a, b) {
137
+ return Api_Naming$ReventlessCore.singularize(a) === Api_Naming$ReventlessCore.singularize(b);
138
+ }
139
+
140
+ function splitKey(key) {
141
+ let match = key.split(".");
142
+ if (match.length !== 2) {
143
+ return [
144
+ "",
145
+ key
146
+ ];
147
+ }
148
+ let plugin = match[0];
149
+ let store = match[1];
150
+ return [
151
+ plugin,
152
+ store
153
+ ];
154
+ }
155
+
156
+ function collisions(declarations) {
157
+ let byStore = {};
158
+ declarations.forEach(d => {
159
+ let match = byStore[d.store];
160
+ if (match !== undefined) {
161
+ return;
162
+ } else {
163
+ byStore[d.store] = d;
164
+ return;
165
+ }
166
+ });
167
+ let unique = Object.values(byStore);
168
+ let found = [];
169
+ for (let i = 0, i_finish = unique.length; i < i_finish; ++i) {
170
+ for (let j = i + 1 | 0, j_finish = unique.length; j < j_finish; ++j) {
171
+ let a = unique[i];
172
+ let b = unique[j];
173
+ let match = splitKey(a.store);
174
+ let storeA = match[1];
175
+ let match$1 = splitKey(b.store);
176
+ let storeB = match$1[1];
177
+ if (match[0] === match$1[0] && (withinOneEdit(storeA, storeB) || sameStem(storeA, storeB))) {
178
+ found.push({
179
+ a: a,
180
+ b: b
181
+ });
182
+ }
183
+ }
184
+ }
185
+ return found;
186
+ }
187
+
188
+ function collisionMessage(c) {
189
+ return c.a.store + ` (` + c.a.component + `.` + c.a.field + `) and ` + c.b.store + ` ` + (`(` + c.b.component + `.` + c.b.field + `) differ by one edit — one is probably a typo for `) + `the other, and both would be provisioned, splitting objects across two stores. Fix the field name, or name the store explicitly with \`@storageRef("<store>")\` if the two really are separate stores.`;
190
+ }
191
+
70
192
  export {
71
193
  refLikeNames,
72
194
  refLikeSuffixes,
@@ -75,5 +197,10 @@ export {
75
197
  warningsFromProperties,
76
198
  scanSchema,
77
199
  message,
200
+ withinOneEdit,
201
+ sameStem,
202
+ splitKey,
203
+ collisions,
204
+ collisionMessage,
78
205
  }
79
206
  /* StorageRef-Reventless Not a pure module */
@@ -249,6 +249,12 @@ module Make = (
249
249
  ) => {
250
250
  let qn = Api_Naming.queryFieldNamesForReadModel(~plugin=name, ~name=R.Spec.name)
251
251
  let subIdField = R.Spec.subIdConfig->Option.map(c => c.subIdField)
252
+ // An ordinary read model's `@index` reached the resolver layer
253
+ // (`QueryDbResolvers_{AppSync,Lambda}` build one per `config.indexes`)
254
+ // and never reached the schema, so AWS carried a resolver for a field
255
+ // its SDL did not declare. The DCB and admin entries have populated this
256
+ // all along; the omission here was the asymmetry, not the rule.
257
+ let indexes = R.Spec.config.indexes
252
258
  {
253
259
  ReventlessInfra.Api.singleFieldName: qn.singleFieldName,
254
260
  listFieldName: qn.listFieldName,
@@ -258,6 +264,7 @@ module Make = (
258
264
  permission: R.Spec.authorization,
259
265
  connectionSpec: true,
260
266
  subIdField: ?subIdField,
267
+ indexQueries: ?(indexes->Array.length > 0 ? Some(indexes) : None),
261
268
  }
262
269
  })
263
270
 
@@ -680,7 +687,7 @@ module Make = (
680
687
  interstackAdminExtensionPoints
681
688
  ->Pulumi.StackReference.get(PluginExtensionPointSpec.name)
682
689
  ->Obj.magic: JSON.t
683
- )->S.parseOrThrow(ReventlessInterop.ExtensionPoint.resolvedOutputsSchema)
690
+ )->S.parseOrThrow(~to=ReventlessInterop.ExtensionPoint.resolvedOutputsSchema)
684
691
  let pluginExtensionPointCommandTopicRemoteChannel = PluginExtensionPointRemoteChannel.make(
685
692
  pluginExtensionPointUnwrapped.commandTopic.resources->Array.map(
686
693
  Adapter.fromInteropResolved,
@@ -1023,7 +1030,7 @@ module Make = (
1023
1030
  builderOutputs->Pulumi.Output.apply(outputs =>
1024
1031
  outputs
1025
1032
  ->toInteropMeta
1026
- ->S.reverseConvertToJsonOrThrow(ReventlessInterop.ExportMeta.schema)
1033
+ ->Reventless.Util_Sury.toJson(ReventlessInterop.ExportMeta.schema)
1027
1034
  )
1028
1035
 
1029
1036
  Logger.currentPluginName := _prevPluginName
@@ -9,6 +9,7 @@ import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
9
9
  import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
10
10
  import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
11
11
  import * as Plugin$Reventless from "@reventlessdev/reventless-spec/src/components/Plugin.res.mjs";
12
+ import * as Util_Sury$Reventless from "@reventlessdev/reventless-spec/src/util/Util_Sury.res.mjs";
12
13
  import * as Logger$ReventlessCore from "../../util/Logger.res.mjs";
13
14
  import * as Plugin$ReventlessCore from "./Plugin.res.mjs";
14
15
  import * as StackReference$Pulumi from "@reventlessdev/rescript-pulumi-pulumi/src/StackReference.res.mjs";
@@ -194,6 +195,7 @@ function Make(Spec) {
194
195
  let queryEntriesFromReadModels = readModels.map(R => {
195
196
  let qn = Api_Naming$ReventlessCore.queryFieldNamesForReadModel(extra$1, R.Spec.name, undefined);
196
197
  let subIdField = Stdlib_Option.map(R.Spec.subIdConfig, c => c.subIdField);
198
+ let indexes = R.Spec.config.indexes;
197
199
  return {
198
200
  singleFieldName: qn.singleFieldName,
199
201
  listFieldName: qn.listFieldName,
@@ -202,7 +204,8 @@ function Make(Spec) {
202
204
  authorization: undefined,
203
205
  permission: R.Spec.authorization,
204
206
  connectionSpec: true,
205
- subIdField: subIdField
207
+ subIdField: subIdField,
208
+ indexQueries: indexes.length !== 0 ? indexes : undefined
206
209
  };
207
210
  });
208
211
  let queryEntries = queryEntriesFromReadModels.concat(dcbResult.queryEntries);
@@ -646,7 +649,7 @@ function Make(Spec) {
646
649
  inboundTranslationSlices: pluginOutputs_inboundTranslationSlices
647
650
  };
648
651
  Component$ReventlessCore.setOutputs(extra, pluginOutputs);
649
- Plugin_Helpers$ReventlessCore.interopMetaOutput.contents = builderOutputs.apply(outputs => S.reverseConvertToJsonOrThrow(Plugin_Helpers$ReventlessCore.toInteropMeta(outputs), ExportMeta$ReventlessInterop.schema));
652
+ Plugin_Helpers$ReventlessCore.interopMetaOutput.contents = builderOutputs.apply(outputs => Util_Sury$Reventless.toJson(Plugin_Helpers$ReventlessCore.toInteropMeta(outputs), ExportMeta$ReventlessInterop.schema));
650
653
  Logger$ReventlessCore.currentPluginName.contents = _prevPluginName;
651
654
  return ResourceAttribution$ReventlessCore.restore(_prevAttribution);
652
655
  }, opts);
@@ -46,7 +46,7 @@ let getRemoteStorageResources = (pluginName, queryDbName) =>
46
46
  | Some(rawReadModel) =>
47
47
  try {
48
48
  let readModel =
49
- rawReadModel->S.parseOrThrow(ReventlessInterop.ReadModel.resolvedOutputsSchema)
49
+ rawReadModel->S.parseOrThrow(~to=ReventlessInterop.ReadModel.resolvedOutputsSchema)
50
50
  readModel.queryDb.resources->Adapter.fromInteropResources
51
51
  } catch {
52
52
  | exn =>
@@ -607,12 +607,12 @@ module MakeEventCollectorHelper = (
607
607
  ecResource.name->ComponentType.nameOpt(EventCollector.componentType)
608
608
  let pluginDefinitionJson =
609
609
  pluginDefinition
610
- ->S.reverseConvertToJsonOrThrow(Reventless.Plugin.pluginDefinitionSchema)
610
+ ->Reventless.Util_Sury.toJson(Reventless.Plugin.pluginDefinitionSchema)
611
611
  ->JSON.stringify
612
612
  ->Pulumi.Output.make
613
613
  let uiFragmentsJson =
614
614
  uiFragments
615
- ->S.reverseConvertToJsonOrThrow(Reventless.Plugin.uiFragmentManifestOptionSchema)
615
+ ->Reventless.Util_Sury.toJson(Reventless.Plugin.uiFragmentManifestOptionSchema)
616
616
  ->JSON.stringify
617
617
  ->Pulumi.Output.make
618
618
  let pluginExtensionPointCmdTopicUrl = switch pluginExtensionPointUnwrapped {
@@ -824,7 +824,7 @@ let offloadPayload = (value: 'a, ~schema: S.t<'a>, ~store: string): Reventless.O
824
824
  switch offloadHook.contents {
825
825
  | Some(hook) =>
826
826
  Reventless.Offload.Offloaded(
827
- hook(~store, ~bytes=value->S.reverseConvertToJsonStringOrThrow(schema)),
827
+ hook(~store, ~bytes=value->Reventless.Util_Sury.toJsonString(schema)),
828
828
  )
829
829
  | None => Reventless.Offload.Inline(value)
830
830
  }
@@ -1250,7 +1250,7 @@ let serializePlainDictExport = (
1250
1250
  ->toResolved
1251
1251
  ->Pulumi.Output.apply(resolved => (
1252
1252
  name,
1253
- resolved->S.reverseConvertToJsonOrThrow(schema),
1253
+ resolved->Reventless.Util_Sury.toJson(schema),
1254
1254
  ))
1255
1255
  )
1256
1256
  ->Pulumi.Output.all
@@ -1269,7 +1269,7 @@ let serializeDictExport = (
1269
1269
  ->toResolved
1270
1270
  ->Pulumi.Output.apply(resolved => (
1271
1271
  name,
1272
- resolved->S.reverseConvertToJsonOrThrow(schema),
1272
+ resolved->Reventless.Util_Sury.toJson(schema),
1273
1273
  ))
1274
1274
  )
1275
1275
  ->Pulumi.Output.all
@@ -1285,7 +1285,7 @@ let serializeTasksOutputs = (pluginOutputs: Plugin.outputs): Pulumi.Output.t<JSO
1285
1285
  task
1286
1286
  ->Task.toResolvedOutputs
1287
1287
  ->Pulumi.Output.apply(resolved =>
1288
- resolved->S.reverseConvertToJsonOrThrow(ReventlessInterop.Task.resolvedOutputsSchema)
1288
+ resolved->Reventless.Util_Sury.toJson(ReventlessInterop.Task.resolvedOutputsSchema)
1289
1289
  )
1290
1290
  )
1291
1291
  ->Pulumi.Output.all
@@ -1310,7 +1310,7 @@ let serializeEventMappersOutputs = (pluginOutputs: Plugin.outputs): Pulumi.Outpu
1310
1310
  ->EventMapper.toResolvedOutputs
1311
1311
  ->Pulumi.Output.apply(resolved =>
1312
1312
  Some(
1313
- resolved->S.reverseConvertToJsonOrThrow(
1313
+ resolved->Reventless.Util_Sury.toJson(
1314
1314
  ReventlessInterop.EventMapper.resolvedOutputsSchema,
1315
1315
  ),
1316
1316
  )
@@ -1350,7 +1350,7 @@ let exportPlatformOutputs = (
1350
1350
  ->ExtensionPoint.toResolvedOutputs
1351
1351
  ->Pulumi.Output.apply(resolved => (
1352
1352
  ep.name,
1353
- resolved->S.reverseConvertToJsonOrThrow(
1353
+ resolved->Reventless.Util_Sury.toJson(
1354
1354
  ReventlessInterop.ExtensionPoint.resolvedOutputsSchema,
1355
1355
  ),
1356
1356
  ))
@@ -1392,7 +1392,7 @@ let exportPlatformOutputs = (
1392
1392
  dcbOutputs
1393
1393
  ->DcbEventLog.toResolvedOutputs
1394
1394
  ->Pulumi.Output.apply(resolved =>
1395
- resolved->S.reverseConvertToJsonOrThrow(
1395
+ resolved->Reventless.Util_Sury.toJson(
1396
1396
  ReventlessInterop.DcbEventLog.resolvedOutputsSchema,
1397
1397
  )
1398
1398
  ),
@@ -1545,7 +1545,7 @@ let exportPluginOutputs = (pluginOutputs: Plugin.outputs) => {
1545
1545
  dcbOutputs
1546
1546
  ->DcbEventLog.toResolvedOutputs
1547
1547
  ->Pulumi.Output.apply(resolved =>
1548
- resolved->S.reverseConvertToJsonOrThrow(
1548
+ resolved->Reventless.Util_Sury.toJson(
1549
1549
  ReventlessInterop.DcbEventLog.resolvedOutputsSchema,
1550
1550
  )
1551
1551
  )
@@ -16,6 +16,7 @@ import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/component
16
16
  import * as Plugin$Reventless from "@reventlessdev/reventless-spec/src/components/Plugin.res.mjs";
17
17
  import * as Task$ReventlessCore from "../../components/Task/Task.res.mjs";
18
18
  import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
19
+ import * as Util_Sury$Reventless from "@reventlessdev/reventless-spec/src/util/Util_Sury.res.mjs";
19
20
  import * as Logger$ReventlessCore from "../../util/Logger.res.mjs";
20
21
  import * as Adapter$ReventlessCore from "../../adapter/Adapter.res.mjs";
21
22
  import * as Task$ReventlessInterop from "@reventlessdev/reventless-interop/src/components/Task.res.mjs";
@@ -321,8 +322,8 @@ function MakeEventCollectorHelper(RuntimeEnvironment) {
321
322
  let handler = PluginEventCollector.makeHandler(eventCollector, Callback.handleJsonEvents);
322
323
  let ecResource = Component$ReventlessCore.toPulumiResource(eventCollector);
323
324
  let ecName = ComponentType$ReventlessCore.nameOpt(ecResource.__name, EventCollector$ReventlessCore.componentType);
324
- let pluginDefinitionJson = Pulumi.output(JSON.stringify(S.reverseConvertToJsonOrThrow(pluginDefinition, Plugin$Reventless.pluginDefinitionSchema)));
325
- let uiFragmentsJson = Pulumi.output(JSON.stringify(S.reverseConvertToJsonOrThrow(uiFragments, Plugin$Reventless.uiFragmentManifestOptionSchema)));
325
+ let pluginDefinitionJson = Pulumi.output(JSON.stringify(Util_Sury$Reventless.toJson(pluginDefinition, Plugin$Reventless.pluginDefinitionSchema)));
326
+ let uiFragmentsJson = Pulumi.output(JSON.stringify(Util_Sury$Reventless.toJson(uiFragments, Plugin$Reventless.uiFragmentManifestOptionSchema)));
326
327
  let pluginExtensionPointCmdTopicUrl;
327
328
  if (pluginExtensionPointUnwrapped !== undefined) {
328
329
  let r = pluginExtensionPointUnwrapped.commandTopic.resources[0];
@@ -436,7 +437,7 @@ function offloadPayload(value, schema, store) {
436
437
  if (hook !== undefined) {
437
438
  return {
438
439
  TAG: "Offloaded",
439
- _0: hook(store, S.reverseConvertToJsonStringOrThrow(value, schema, undefined))
440
+ _0: hook(store, Util_Sury$Reventless.toJsonString(value, schema, undefined))
440
441
  };
441
442
  } else {
442
443
  return {
@@ -636,7 +637,7 @@ function serializePlainDictExport(dict, toResolved, schema) {
636
637
  let name = param[0];
637
638
  return toResolved(param[1]).apply(resolved => [
638
639
  name,
639
- S.reverseConvertToJsonOrThrow(resolved, schema)
640
+ Util_Sury$Reventless.toJson(resolved, schema)
640
641
  ]);
641
642
  })).apply(pairs => Object.fromEntries(pairs));
642
643
  }
@@ -646,19 +647,19 @@ function serializeDictExport(dictOutput, toResolved, schema) {
646
647
  let name = param[0];
647
648
  return toResolved(param[1]).apply(resolved => [
648
649
  name,
649
- S.reverseConvertToJsonOrThrow(resolved, schema)
650
+ Util_Sury$Reventless.toJson(resolved, schema)
650
651
  ]);
651
652
  })).apply(pairs => Object.fromEntries(pairs)));
652
653
  }
653
654
 
654
655
  function serializeTasksOutputs(pluginOutputs) {
655
- return Output$Pulumi.flatMap(pluginOutputs.tasks, tasks => Pulumi.all(Object.values(tasks).map(task => Task$ReventlessCore.toResolvedOutputs(task).apply(resolved => S.reverseConvertToJsonOrThrow(resolved, Task$ReventlessInterop.resolvedOutputsSchema)))).apply(arr => arr));
656
+ return Output$Pulumi.flatMap(pluginOutputs.tasks, tasks => Pulumi.all(Object.values(tasks).map(task => Task$ReventlessCore.toResolvedOutputs(task).apply(resolved => Util_Sury$Reventless.toJson(resolved, Task$ReventlessInterop.resolvedOutputsSchema)))).apply(arr => arr));
656
657
  }
657
658
 
658
659
  function serializeEventMappersOutputs(pluginOutputs) {
659
660
  return Output$Pulumi.flatMap(pluginOutputs.aggregates, aggregates => Pulumi.all(Object.values(aggregates).map(agg => Output$Pulumi.flatMap(agg.eventMapper, em => {
660
661
  if (em !== undefined) {
661
- return EventMapper$ReventlessCore.toResolvedOutputs(em).apply(resolved => S.reverseConvertToJsonOrThrow(resolved, EventMapper$ReventlessInterop.resolvedOutputsSchema));
662
+ return EventMapper$ReventlessCore.toResolvedOutputs(em).apply(resolved => Util_Sury$Reventless.toJson(resolved, EventMapper$ReventlessInterop.resolvedOutputsSchema));
662
663
  } else {
663
664
  return Pulumi.output(undefined);
664
665
  }
@@ -669,7 +670,7 @@ function exportPlatformOutputs(extensionPointsOutputs, aggregatesOutputs, readMo
669
670
  exportDeploymentMetadata();
670
671
  Pulumi$Pulumi.$$export("extensionPoints", Output$Pulumi.flatMap(extensionPointsOutputs, eps => Pulumi.all(eps.map(ep => ExtensionPoint$ReventlessCore.toResolvedOutputs(ep).apply(resolved => [
671
672
  ep.name,
672
- S.reverseConvertToJsonOrThrow(resolved, ExtensionPoint$ReventlessInterop.resolvedOutputsSchema)
673
+ Util_Sury$Reventless.toJson(resolved, ExtensionPoint$ReventlessInterop.resolvedOutputsSchema)
673
674
  ]))).apply(pairs => Object.fromEntries(pairs))));
674
675
  if (Object.keys(aggregatesOutputs).length !== 0) {
675
676
  Pulumi$Pulumi.$$export("aggregates", serializePlainDictExport(aggregatesOutputs, Aggregate$ReventlessCore.toResolvedOutputs, Aggregate$ReventlessInterop.resolvedOutputsSchema));
@@ -678,7 +679,7 @@ function exportPlatformOutputs(extensionPointsOutputs, aggregatesOutputs, readMo
678
679
  Pulumi$Pulumi.$$export("readModels", serializePlainDictExport(readModelsOutputs, ReadModel$ReventlessCore.toResolvedOutputs, ReadModel$ReventlessInterop.resolvedOutputsSchema));
679
680
  }
680
681
  if (dcbEventLogOutputs !== undefined) {
681
- Pulumi$Pulumi.$$export("dcbEventLog", DcbEventLog$ReventlessCore.toResolvedOutputs(dcbEventLogOutputs).apply(resolved => S.reverseConvertToJsonOrThrow(resolved, DcbEventLog$ReventlessInterop.resolvedOutputsSchema)));
682
+ Pulumi$Pulumi.$$export("dcbEventLog", DcbEventLog$ReventlessCore.toResolvedOutputs(dcbEventLogOutputs).apply(resolved => Util_Sury$Reventless.toJson(resolved, DcbEventLog$ReventlessInterop.resolvedOutputsSchema)));
682
683
  }
683
684
  if (Object.keys(stateChangeSlicesOutputs).length !== 0) {
684
685
  Pulumi$Pulumi.$$export("stateChangeSlices", serializePlainDictExport(stateChangeSlicesOutputs, StateChangeSlice$ReventlessCore.toResolvedOutputs, StateChangeSlice$ReventlessInterop.resolvedOutputsSchema));
@@ -711,7 +712,7 @@ function exportPluginOutputs(pluginOutputs) {
711
712
  Pulumi$Pulumi.$$export("inboundTranslationSlices", serializeDictExport(pluginOutputs.inboundTranslationSlices, InboundTranslationSlice$ReventlessCore.toResolvedOutputs, InboundTranslationSlice$ReventlessInterop.resolvedOutputsSchema));
712
713
  Pulumi$Pulumi.$$export("dcbEventLog", Output$Pulumi.flatMap(pluginOutputs.dcbEventLog, opt => {
713
714
  if (opt !== undefined) {
714
- return DcbEventLog$ReventlessCore.toResolvedOutputs(opt).apply(resolved => S.reverseConvertToJsonOrThrow(resolved, DcbEventLog$ReventlessInterop.resolvedOutputsSchema));
715
+ return DcbEventLog$ReventlessCore.toResolvedOutputs(opt).apply(resolved => Util_Sury$Reventless.toJson(resolved, DcbEventLog$ReventlessInterop.resolvedOutputsSchema));
715
716
  } else {
716
717
  return Pulumi.output(null);
717
718
  }