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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/package.json +11 -11
  3. package/src/Behavior.res +1 -4
  4. package/src/Message.res +17 -14
  5. package/src/Projection.res +51 -25
  6. package/src/RequestContext.res +8 -9
  7. package/src/ResourceAttribution.res +28 -14
  8. package/src/adapter/Adapter.res +48 -4
  9. package/src/adapter/EventLogProvisioning/EventLogProvisioning.res +5 -5
  10. package/src/adapter/Messaging/Messaging_Log_Backend.res +10 -7
  11. package/src/adapter/Messaging/Messaging_Log_Backend.res.mjs +2 -4
  12. package/src/adapter/Monitoring/Monitoring.res +16 -17
  13. package/src/adapter/QueryInterception/QueryInterception.res +0 -1
  14. package/src/adapter/Runtime/AggregateRuntime_Builder_Common.res +12 -5
  15. package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res +11 -7
  16. package/src/adapter/Runtime/PluginRuntime_Builder_Micro.res +1 -7
  17. package/src/adapter/Runtime/PluginRuntime_Builder_Single.res +1 -7
  18. package/src/adapter/RuntimeExtension/RuntimeExtension.res +0 -1
  19. package/src/admin/Platform_Admin.res +17 -6
  20. package/src/admin/Platform_AdminApi.res +14 -9
  21. package/src/admin/Platform_Admin_Callback.res +1 -1
  22. package/src/admin/Platform_BakedManifest.res +34 -34
  23. package/src/admin/Platform_ComponentDefinitionsApi.res +9 -21
  24. package/src/admin/Platform_PluginStructuresApi.res +15 -12
  25. package/src/admin/UiFragmentRegistry/StateChange/UiFragmentRegistry.res +1 -1
  26. package/src/components/Aggregate/Aggregate.res +13 -12
  27. package/src/components/Aggregate/Aggregate_Builder.res +22 -21
  28. package/src/components/Aggregate/Aggregate_Callback.res +91 -86
  29. package/src/components/Api/ApiNoApiHelpers.res +1 -3
  30. package/src/components/Api/Api_Ids.res +0 -1
  31. package/src/components/Api/Api_Naming.res +41 -18
  32. package/src/components/Api/GraphQL_FragmentGenerator.res +42 -52
  33. package/src/components/Api/GraphQL_FragmentGenerator.res.mjs +11 -4
  34. package/src/components/Api/GraphQL_SchemaInspector.res +5 -3
  35. package/src/components/Api/GraphQL_Stitcher.res +9 -10
  36. package/src/components/Api/MCP_SchemaGenerator.res +8 -12
  37. package/src/components/Api/OwnerScopeDiagnostics.res +1 -2
  38. package/src/components/Api/QueryDbListQuery.res +13 -6
  39. package/src/components/Api/SchemaType.res +40 -20
  40. package/src/components/Api/SchemaType.res.mjs +16 -0
  41. package/src/components/Api/SuryToJsonSchema.res +18 -10
  42. package/src/components/Api/SuryToJsonSchema.res.mjs +135 -121
  43. package/src/components/AutomationSlice/AutomationSlice.res +4 -4
  44. package/src/components/AutomationSlice/AutomationSlice_Builder.res +15 -14
  45. package/src/components/AutomationSlice/AutomationSlice_Callback.res +3 -3
  46. package/src/components/Builder_Helpers.res +12 -23
  47. package/src/components/CommandGenerator/CommandGenerator.res +6 -1
  48. package/src/components/CommandGenerator/CommandGenerator_Builder.res +29 -21
  49. package/src/components/CommandGenerator/CommandGenerator_Callback.res +17 -21
  50. package/src/components/CommandTopic/CommandTopic.res +3 -3
  51. package/src/components/CommandTopic/CommandTopic_Builder.res +10 -10
  52. package/src/components/CommandTopic/CommandTopic_Callback.res +1 -4
  53. package/src/components/CommandTopic/CommandTopic_Helpers.res +1 -2
  54. package/src/components/Counter/Counter_Builder.res +1 -6
  55. package/src/components/Counter/Counter_Callback.res +3 -3
  56. package/src/components/Dcb/Dcb_Builder.res +970 -956
  57. package/src/components/DcbEventLog/DcbEventLog.res +4 -4
  58. package/src/components/DcbEventLog/DcbEventLog_Builder.res +0 -1
  59. package/src/components/DcbEventLog/DcbEventLog_Operations.res +17 -18
  60. package/src/components/EventCollector/EventCollector_Builder.res +2 -1
  61. package/src/components/EventLog/EventLog.res +5 -1
  62. package/src/components/EventLog/EventLog_Operations.res +12 -8
  63. package/src/components/EventMapper/EventMapper.res +8 -10
  64. package/src/components/EventMapper/EventMapper_Builder.res +4 -1
  65. package/src/components/EventMapper/EventMapper_Callback.res +46 -31
  66. package/src/components/EventTopic/EventTopic.res +3 -3
  67. package/src/components/EventTopic/EventTopic_Builder.res +1 -1
  68. package/src/components/Extension/Extension.res +4 -1
  69. package/src/components/Extension/Extension_Operations.res +11 -3
  70. package/src/components/ExtensionPoint/ExtensionPoint.res +3 -3
  71. package/src/components/ExtensionPoint/ExtensionPoint_Builder.res +9 -10
  72. package/src/components/ExtensionPoint/ExtensionPoint_Callback.res +2 -6
  73. package/src/components/ExtensionPoint/ExtensionPoint_Operations.res +13 -5
  74. package/src/components/Heartbeat/Heartbeat_Callback.res +3 -3
  75. package/src/components/InboundTranslationSlice/InboundTranslationSlice.res +4 -4
  76. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res +7 -10
  77. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice.res +4 -4
  78. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res +15 -14
  79. package/src/components/QueryDb/QueryDb_Adapter.res +1 -3
  80. package/src/components/QueryDb/QueryDb_Operations.res +10 -10
  81. package/src/components/ReadModel/ReadModel.res +3 -3
  82. package/src/components/ReadModel/ReadModel_Builder.res +1 -2
  83. package/src/components/ReadModel/ReadModel_Callback.res +2 -1
  84. package/src/components/SideEffectHandler/SideEffectHandler_Callback.res +5 -2
  85. package/src/components/StateChangeSlice/StateChangeSlice.res +3 -3
  86. package/src/components/StateChangeSlice/StateChangeSlice_Builder.res +23 -4
  87. package/src/components/StateChangeSlice/StateChangeSlice_Callback.res +22 -6
  88. package/src/components/StateTopic.res +1 -3
  89. package/src/components/StateViewSlice/StateViewSlice.res +4 -4
  90. package/src/components/StateViewSlice/StateViewSlice_Builder.res +79 -68
  91. package/src/components/StateViewSlice/StateViewSlice_Callback.res +3 -1
  92. package/src/components/Task/Task.res +3 -3
  93. package/src/components/Task/Task_Adapter.res +4 -1
  94. package/src/components/Task/Task_Builder.res +24 -21
  95. package/src/plugin/api/PluginBaseFragment.res +9 -3
  96. package/src/plugin/component/Capability_Inference.res +8 -10
  97. package/src/plugin/component/Plugin.res +6 -6
  98. package/src/plugin/component/Plugin_Builder.res +54 -50
  99. package/src/plugin/component/Plugin_Callback.res +10 -6
  100. package/src/plugin/component/Plugin_Helpers.res +264 -230
  101. package/src/plugin/component/Plugin_Structure.res +370 -324
  102. package/src/plugin/component/Plugin_SubscriptionSchema.res +8 -6
  103. package/src/plugin/component/SchemaWalker.res +11 -12
  104. package/src/plugin/connect/PluginConnectExtension_Mapping.res +45 -50
  105. package/src/plugin/lifecycle/PluginBehavior.res +3 -4
  106. package/src/plugin/lifecycle/PluginSpec.res +1 -2
  107. package/src/plugin/lifecycle/PluginsProjection.res +16 -5
  108. package/src/plugin/lifecycle/PluginsReadModelSpec.res +0 -2
  109. package/src/util/CommandPublisher.res +9 -2
  110. package/src/util/CsvStream.res +3 -3
  111. package/src/util/Interstack.res +7 -15
  112. package/src/util/Interstack.resi +3 -3
  113. package/src/util/LogFormat.res +5 -9
  114. package/src/util/Logger.res +1 -2
  115. package/src/util/Lru.res +2 -1
  116. package/src/util/Lru.resi +2 -3
  117. package/src/util/ScheduleOps.res +24 -27
  118. package/src/util/StorePrefixCollision.res +6 -9
  119. package/src/util/Util_Promise.res +4 -1
  120. package/src/util/Util_Promise.res.mjs +1 -1
  121. package/tests/IdentityTest.res +166 -113
  122. package/tests/ResourceAttributionTest.res +28 -25
  123. package/tests/StorePrefixCollisionTest.res +2 -1
  124. package/tests/TaskBucketNamingTest.res +3 -2
  125. package/tests/adapter/EventLogProvisioningTest.res +51 -48
  126. package/tests/adapter/MonitoringTest.res +81 -38
  127. package/tests/adapter/QueryInterceptionTest.res +2 -2
  128. package/tests/adapter/RefusalVocabularyTest.res +31 -23
  129. package/tests/adapter/RuntimeExtensionHookReachTest.res +9 -8
  130. package/tests/adapter/RuntimeExtensionTest.res +5 -3
  131. package/tests/admin/AdminApiSchemaDriftTest.res +22 -16
  132. package/tests/admin/Platform_Admin_StructureTest.res +10 -11
  133. package/tests/admin/Platform_BakedManifestTest.res +31 -35
  134. package/tests/admin/Platform_ComponentDefinitionsApiTest.res +18 -15
  135. package/tests/admin/Platform_PluginStructuresApiTest.res +5 -3
  136. package/tests/admin/Platform_UIFragmentsApiTest.res +6 -3
  137. package/tests/aggregate/AggregateCacheTest.res +10 -12
  138. package/tests/aggregate/AggregateCallbackTest.res +75 -46
  139. package/tests/aggregate/AggregateCausationTest.res +19 -20
  140. package/tests/aggregate/AggregateConflictTest.res +41 -19
  141. package/tests/aggregate/AggregateFixtures.res +15 -5
  142. package/tests/aggregate/AggregateRejectionTest.res +97 -80
  143. package/tests/aggregate/AggregateSnapshotTest.res +44 -16
  144. package/tests/api/Api_IdsTest.res +10 -4
  145. package/tests/api/BrandedMarkerCompositionTest.res +48 -36
  146. package/tests/api/GeolocationSemanticTest.res +3 -3
  147. package/tests/api/GraphQL_FragmentGeneratorTest.res +66 -54
  148. package/tests/api/OwnerScopeDiagnosticsTest.res +31 -27
  149. package/tests/api/StorageRefFieldsTest.res +30 -18
  150. package/tests/api/SuryToJsonSchemaTest.res +1338 -981
  151. package/tests/api/SuryToJsonSchemaTest.res.mjs +31 -0
  152. package/tests/api/TaggedUnionSchemaTest.res +17 -24
  153. package/tests/commandgenerator/CommandGeneratorCallbackTest.res +235 -179
  154. package/tests/commandgenerator/CommandGeneratorFixtures.res +8 -13
  155. package/tests/commandgenerator/OwnerStampingTest.res +91 -76
  156. package/tests/commandtopic/CommandOutcomeHookTest.res +198 -155
  157. package/tests/commandtopic/CommandTopicCallbackFixtures.res +5 -4
  158. package/tests/commandtopic/CommandTopicCallbackTest.res +61 -43
  159. package/tests/commandtopic/CommandTopicHelpersRejectionTest.res +70 -55
  160. package/tests/counter/CounterCallbackTest.res +40 -34
  161. package/tests/counter/CounterFixtures.res +4 -4
  162. package/tests/dcb/DcbDecodeTest.res +115 -84
  163. package/tests/dcb/DcbEventLogOperationsTest.res +194 -143
  164. package/tests/dcb/DcbEventLogSchemaTest.res +13 -13
  165. package/tests/dcb/DcbFixtures.res +4 -5
  166. package/tests/dcb/DcbScopeInferenceTest.res +173 -114
  167. package/tests/dcb/DcbStateChangeSliceTest.res +391 -262
  168. package/tests/dcb/DcbTagTest.res +22 -11
  169. package/tests/dcb/DcbValidationTest.res +288 -218
  170. package/tests/eventlog/EventLogFixtures.res +4 -4
  171. package/tests/eventlog/EventLogOperationsTest.res +102 -67
  172. package/tests/eventlog/EventLogRetryTest.res +104 -65
  173. package/tests/eventmapper/EventMapperCallbackTest.res +118 -83
  174. package/tests/eventmapper/EventMapperFixtures.res +15 -23
  175. package/tests/eventmapper/EventMapperTest.res +54 -38
  176. package/tests/eventtopic/EventTopicFixtures.res +3 -4
  177. package/tests/eventtopic/EventTopicOperationsTest.res +41 -29
  178. package/tests/extensionpoint/ExtensionPointCallbackTest.res +58 -45
  179. package/tests/extensionpoint/ExtensionPointFixtures.res +16 -20
  180. package/tests/extensionpoint/ExtensionPointOperationsTest.res +70 -49
  181. package/tests/extensionpoint/PluginDisconnectScheduleTest.res +2 -1
  182. package/tests/logger/LogFormatTest.res +104 -82
  183. package/tests/logger/LoggerLazyTest.res +21 -12
  184. package/tests/message/MessageTest.res +96 -93
  185. package/tests/message/MetaEnvelopeTest.res +26 -30
  186. package/tests/plugin/HeartbeatDisconnectGraceTest.res +31 -25
  187. package/tests/plugin/ManifestVisibilityTest.res +20 -12
  188. package/tests/plugin/PluginDefinitionScalars.res +1 -2
  189. package/tests/plugin/PluginLifecycleCorpusTest.res +15 -12
  190. package/tests/plugin/PluginSpecExperiment.res +0 -1
  191. package/tests/plugin/PluginStructureTest.res +1533 -1030
  192. package/tests/plugin/PluginStructureTest.res.mjs +6 -0
  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 +6 -4
  197. package/tests/plugin/StateView/PsAnnotatedView.res.mjs +7 -3
  198. package/tests/plugin/StateView/PsCustomersView.res +4 -4
  199. package/tests/plugin/StateView/PsShipmentsView.res +3 -2
  200. package/tests/projection/LifecycleTrailTest.res +1 -4
  201. package/tests/projection/ProjectionOptimizeTest.res +13 -9
  202. package/tests/querydb/QueryDbFixtures.res +0 -1
  203. package/tests/querydb/QueryDbOperationsTest.res +99 -64
  204. package/tests/querydb/TaggedUnionStampTest.res +10 -8
  205. package/tests/sideeffecthandler/SideEffectHandlerCallbackTest.res +50 -35
  206. package/tests/sideeffecthandler/SideEffectHandlerFixtures.res +4 -10
  207. package/tests/util/CommandPublisherTest.res +0 -1
  208. package/tests/util/CsvStreamTest.res +3 -3
  209. package/tests/util/LruTest.res +84 -56
@@ -73,11 +73,12 @@ let decode = (fragment: Reventless.Plugin.apiSchemaFragment): fragmentParts => {
73
73
  let field = obj->Dict.get("field")->Option.flatMap(JSON.Decode.string)
74
74
  let mutations = switch obj->Dict.get("mutations") {
75
75
  | Some(JSON.Array(ms)) =>
76
- ms->Array.filterMap(m =>
77
- switch m {
78
- | JSON.String(s) => Some(s)
79
- | _ => None
80
- }
76
+ ms->Array.filterMap(
77
+ m =>
78
+ switch m {
79
+ | JSON.String(s) => Some(s)
80
+ | _ => None
81
+ },
81
82
  )
82
83
  | _ => []
83
84
  }
@@ -169,9 +170,7 @@ let relayBaseTypes = [
169
170
  `enum SortOrder {\n ASC\n DESC\n}`,
170
171
  ]
171
172
 
172
- let relayBaseQueries = [
173
- ` node(id: ID!): Node`,
174
- ]
173
+ let relayBaseQueries = [` node(id: ID!): Node`]
175
174
 
176
175
  /**
177
176
  Assemble fragments into a complete GraphQL SDL string.
@@ -293,8 +292,8 @@ let assembleSdl = (
293
292
  : None
294
293
 
295
294
  let sdlParts =
296
- [Some(typesSdl), Some(queriesSdl), Some(mutationsSdl), subscriptionsSdl]->Array.filterMap(
297
- x => x,
295
+ [Some(typesSdl), Some(queriesSdl), Some(mutationsSdl), subscriptionsSdl]->Array.filterMap(x =>
296
+ x
298
297
  )
299
298
  sdlParts->Array.join("\n\n")
300
299
  }
@@ -28,8 +28,7 @@ let buildDescriptionSuffix = (
28
28
  ~entry: ReventlessInfra.Api.mutationSchemaEntry,
29
29
  ): string => {
30
30
  let viewsSuffix = switch entry.linkedViews {
31
- | Some(views) if views->Array.length > 0 =>
32
- ` Affects views: ${views->Array.join(", ")}.`
31
+ | Some(views) if views->Array.length > 0 => ` Affects views: ${views->Array.join(", ")}.`
33
32
  | _ => ""
34
33
  }
35
34
  let consistencySuffix = switch entry.consistencyRead {
@@ -41,10 +40,9 @@ let buildDescriptionSuffix = (
41
40
 
42
41
  /** Generate MCP tool definitions from mutation entries.
43
42
  Each command variant becomes a separate tool. */
44
- let generateTools = (
45
- ~pluginName: string,
46
- ~mutationEntries: array<mutationSchemaEntry>,
47
- ): array<mcpToolDefinition> => {
43
+ let generateTools = (~pluginName: string, ~mutationEntries: array<mutationSchemaEntry>): array<
44
+ mcpToolDefinition,
45
+ > => {
48
46
  let tools: array<mcpToolDefinition> = []
49
47
 
50
48
  mutationEntries->Array.forEach(entry => {
@@ -87,8 +85,7 @@ let generateTools = (
87
85
  obj->Dict.set("required", JSON.Encode.array(arr))
88
86
  | None => ()
89
87
  }
90
- | None =>
91
- obj->Dict.set("required", JSON.Encode.array([JSON.Encode.string("id")]))
88
+ | None => obj->Dict.set("required", JSON.Encode.array([JSON.Encode.string("id")]))
92
89
  }
93
90
  JSON.Encode.object(obj)
94
91
  | None => inputSchema
@@ -124,10 +121,9 @@ let generateTools = (
124
121
 
125
122
  /** Generate MCP resource definitions from query entries.
126
123
  Each query entry becomes one or two resources (single + list). */
127
- let generateResources = (
128
- ~pluginName: string,
129
- ~queryEntries: array<querySchemaEntry>,
130
- ): array<mcpResourceDefinition> => {
124
+ let generateResources = (~pluginName: string, ~queryEntries: array<querySchemaEntry>): array<
125
+ mcpResourceDefinition,
126
+ > => {
131
127
  let resources: array<mcpResourceDefinition> = []
132
128
 
133
129
  queryEntries->Array.forEach(entry => {
@@ -43,8 +43,7 @@ let warnIfNoElevatedGroups = (~comp: string, ~view: string, ~ownerField: option<
43
43
  `${view}: "${field}" is declared @owner, but no elevated groups are configured. ` ++
44
44
  "Every caller — administrators included — will see only their own rows. " ++
45
45
  "Call OwnerScope.setElevatedGroups([...]) before components are built, or set " ++
46
- "REVENTLESS_ELEVATED_GROUPS — the environment is what reaches a deployment's " ++
47
- "separate function runtimes, which a call in the deploy program does not.",
46
+ "REVENTLESS_ELEVATED_GROUPS — the environment is what reaches a deployment's " ++ "separate function runtimes, which a call in the deploy program does not.",
48
47
  )
49
48
  }
50
49
  | _ => ()
@@ -66,10 +66,14 @@ let buildConnection = (
66
66
  ~cursorValueOf: JSON.t => string,
67
67
  ): JSON.t => {
68
68
  let edges =
69
- pageItems->Array.map(item => Obj.magic({"node": item, "cursor": encodeCursor(cursorValueOf(item))}))
69
+ pageItems->Array.map(item =>
70
+ Obj.magic({"node": item, "cursor": encodeCursor(cursorValueOf(item))})
71
+ )
70
72
  let startCursor = pageItems->Array.get(0)->Option.map(item => encodeCursor(cursorValueOf(item)))
71
73
  let endCursor =
72
- pageItems->Array.get(pageItems->Array.length - 1)->Option.map(item => encodeCursor(cursorValueOf(item)))
74
+ pageItems
75
+ ->Array.get(pageItems->Array.length - 1)
76
+ ->Option.map(item => encodeCursor(cursorValueOf(item)))
73
77
  Obj.magic({
74
78
  "edges": edges,
75
79
  "pageInfo": {
@@ -130,7 +134,7 @@ let run = (
130
134
  let perFieldChecks: array<JSON.t => bool> = capability.filterFields->Array.flatMap(f => {
131
135
  let checks: array<JSON.t => bool> = []
132
136
  switch filterDict->Dict.get(f.name ++ "Eq") {
133
- | Some(v) when v != JSON.Encode.null =>
137
+ | Some(v) if v != JSON.Encode.null =>
134
138
  let expected = switch v->JSON.Decode.string {
135
139
  | Some(s) => s
136
140
  | None => v->JSON.Decode.float->Option.map(f => Float.toString(f))->Option.getOr("")
@@ -142,16 +146,18 @@ let run = (
142
146
  }
143
147
  if f.range {
144
148
  switch filterDict->Dict.get(f.name ++ "From") {
145
- | Some(v) when v != JSON.Encode.null =>
149
+ | Some(v) if v != JSON.Encode.null =>
146
150
  let from =
147
151
  v
148
152
  ->JSON.Decode.string
149
153
  ->Option.getOr(v->JSON.Decode.float->Option.map(f => Float.toString(f))->Option.getOr(""))
150
- checks->Array.push(item => getFieldString(item, f.name)->Option.mapOr(false, v => v >= from))
154
+ checks->Array.push(item =>
155
+ getFieldString(item, f.name)->Option.mapOr(false, v => v >= from)
156
+ )
151
157
  | _ => ()
152
158
  }
153
159
  switch filterDict->Dict.get(f.name ++ "To") {
154
- | Some(v) when v != JSON.Encode.null =>
160
+ | Some(v) if v != JSON.Encode.null =>
155
161
  let to_ =
156
162
  v
157
163
  ->JSON.Decode.string
@@ -207,6 +213,7 @@ let run = (
207
213
  item->JSON.Decode.object->Option.flatMap(d => d->Dict.get(scope.field)),
208
214
  )
209
215
  )
216
+
210
217
  | None => true
211
218
  }
212
219
  passSearch && passPrefix && passIds && passPerField && passOwner && passRetired
@@ -1,40 +1,44 @@
1
1
  type rec schemaType =
2
2
  | ScalarString
3
3
  | ScalarNumber
4
- | /** A number the schema says is whole. sury carries the fact on the number's
4
+ /** A number the schema says is whole. sury carries the fact on the number's
5
5
  `format`, and it was being dropped here — so every `int` in the domain
6
6
  reached the SDL as `Float` and JSON Schema as `"number"`, and a quantity
7
7
  was a field a client could legally send `2.5` in. */
8
- ScalarInt
8
+ | ScalarInt
9
9
  | ScalarBoolean
10
10
  | ScalarBigInt
11
11
  | EntityId
12
12
  | DateTime
13
- | /** A calendar day, with no instant in it. A shape of its own rather than a
13
+ /** A calendar day, with no instant in it. A shape of its own rather than a
14
14
  plain string so `format: "date"` reaches the JSON Schema — but, unlike
15
15
  `DateTime`, it is not excluded from the generic semantic wrapper below,
16
16
  so it carries `x-reventless-semantic` as well. `DateTime`'s exclusion
17
17
  exists because its bare-`format` output predates the marker and is a
18
18
  published contract; a new semantic has no such history. */
19
- CalendarDate
19
+ | CalendarDate
20
20
  | Nullable(schemaType)
21
21
  | ArrayOf(schemaType)
22
22
  | ObjectRef(string, dict<schemaType>)
23
23
  | Enum(string, array<string>)
24
- | /** A field whose type carries a semantic the IR has no dedicated shape for.
24
+ /** A field whose type carries a semantic the IR has no dedicated shape for.
25
25
  Wraps the shape the value actually has, so every consumer that only cares
26
26
  about shape unwraps and is otherwise unaffected. `DateTime` and `EntityId`
27
27
  are *not* expressed this way: they long predate the generic marker and
28
28
  their JSON Schema `format` output is a published contract. */
29
- Semantic(Reventless.Semantic.t, schemaType)
30
- | /** A variant used as a field: the union's name, and one arm per constructor
29
+ | Semantic(Reventless.Semantic.t, schemaType)
30
+ /** A field whose type declares the value it opens with. Wraps the shape the
31
+ value has, as `Semantic` does, so a consumer that cares only about shape
32
+ unwraps: a default changes where a form starts, never what the field is. */
33
+ | Defaulted(JSON.t, schemaType)
34
+ /** A variant used as a field: the union's name, and one arm per constructor
31
35
  keyed by the `TAG` sury discriminates on. Each arm is the `ObjectRef` its
32
36
  member type is emitted from, so the arm's own name travels with it and
33
37
  every consumer that can already render an object renders an arm.
34
38
 
35
39
  Only a *named* union reaches this case — see `Reventless.TaggedUnion`,
36
40
  which owns the name and the arm rules both. */
37
- TaggedUnion(string, array<(string, schemaType)>)
41
+ | TaggedUnion(string, array<(string, schemaType)>)
38
42
  | Unknown
39
43
 
40
44
  let isTagged = Reventless.DcbTag.isTagged
@@ -82,6 +86,21 @@ let canonicalName = (id: string): option<string> =>
82
86
  ->Option.map(((_, name)) => name)
83
87
 
84
88
  let rec fromSury = (~parentName: string, ~fieldName: string, schema: S.t<unknown>): schemaType => {
89
+ // Outermost, so it wraps whatever the field turns out to be, a semantic
90
+ // composite included — the other order buries the marker under a shape whose
91
+ // consumers unwrap it.
92
+ let shape = withoutDefault(~parentName, ~fieldName, schema)
93
+ switch Reventless.FieldDefault.getFrom(schema) {
94
+ | Some(value) => Defaulted(value, shape)
95
+ | None => shape
96
+ }
97
+ }
98
+
99
+ and withoutDefault = (
100
+ ~parentName: string,
101
+ ~fieldName: string,
102
+ schema: S.t<unknown>,
103
+ ): schemaType => {
85
104
  // Semantics the IR already has a dedicated shape for keep it: `dateTime` and
86
105
  // `reference` are read below via `isDateTime` / `getTarget`, both of which now
87
106
  // consult the generic marker, and their `format` output is a published
@@ -135,9 +154,10 @@ and shapeOf = (~parentName: string, ~fieldName: string, schema: S.t<unknown>): s
135
154
  | _ => ScalarString
136
155
  }
137
156
  }
138
- let itemType = (isIdsFieldName(fieldName) || isIdFieldName(fieldName)) && itemType == ScalarString
139
- ? EntityId
140
- : itemType
157
+ let itemType =
158
+ (isIdsFieldName(fieldName) || isIdFieldName(fieldName)) && itemType == ScalarString
159
+ ? EntityId
160
+ : itemType
141
161
  ArrayOf(itemType)
142
162
  | Object({properties}) =>
143
163
  let nestedName =
@@ -149,7 +169,10 @@ and shapeOf = (~parentName: string, ~fieldName: string, schema: S.t<unknown>): s
149
169
  ->Dict.toArray
150
170
  ->Array.forEach(((propName, propSchema)) => {
151
171
  if propName !== "TAG" {
152
- fields->Dict.set(propName, fromSury(~parentName=nestedName, ~fieldName=propName, propSchema))
172
+ fields->Dict.set(
173
+ propName,
174
+ fromSury(~parentName=nestedName, ~fieldName=propName, propSchema),
175
+ )
153
176
  }
154
177
  })
155
178
  if fields->Dict.keysToArray->Array.length == 0 {
@@ -166,13 +189,7 @@ and shapeOf = (~parentName: string, ~fieldName: string, schema: S.t<unknown>): s
166
189
  )
167
190
  let isOptional = nonNullVariants->Array.length < anyOf->Array.length
168
191
  if nonNullVariants->Array.length == 1 {
169
- Nullable(
170
- fromSury(
171
- ~parentName,
172
- ~fieldName,
173
- nonNullVariants->Array.getUnsafe(0),
174
- ),
175
- )
192
+ Nullable(fromSury(~parentName, ~fieldName, nonNullVariants->Array.getUnsafe(0)))
176
193
  } else {
177
194
  let constValues = nonNullVariants->Array.filterMap(v =>
178
195
  switch v {
@@ -180,7 +197,10 @@ and shapeOf = (~parentName: string, ~fieldName: string, schema: S.t<unknown>): s
180
197
  | _ => None
181
198
  }
182
199
  )
183
- if constValues->Array.length == nonNullVariants->Array.length && constValues->Array.length > 0 {
200
+ if (
201
+ constValues->Array.length == nonNullVariants->Array.length &&
202
+ constValues->Array.length > 0
203
+ ) {
184
204
  let enumName =
185
205
  parentName ++
186
206
  fieldName->String.charAt(0)->String.toUpperCase ++
@@ -9,6 +9,7 @@ import * as Lifecycle$Reventless from "@reventlessdev/reventless-spec/src/types/
9
9
  import * as Reference$Reventless from "@reventlessdev/reventless-spec/src/components/Reference.res.mjs";
10
10
  import * as TaggedUnion$Reventless from "@reventlessdev/reventless-spec/src/components/TaggedUnion.res.mjs";
11
11
  import * as CalendarDate$Reventless from "@reventlessdev/reventless-spec/src/semantic/CalendarDate.res.mjs";
12
+ import * as FieldDefault$Reventless from "@reventlessdev/reventless-spec/src/components/FieldDefault.res.mjs";
12
13
 
13
14
  function isIdFieldName(name) {
14
15
  let lower = name.toLowerCase();
@@ -54,6 +55,20 @@ function canonicalName(id) {
54
55
  }
55
56
 
56
57
  function fromSury(parentName, fieldName, schema) {
58
+ let shape = withoutDefault(parentName, fieldName, schema);
59
+ let value = FieldDefault$Reventless.getFrom(schema);
60
+ if (value !== undefined) {
61
+ return {
62
+ TAG: "Defaulted",
63
+ _0: value,
64
+ _1: shape
65
+ };
66
+ } else {
67
+ return shape;
68
+ }
69
+ }
70
+
71
+ function withoutDefault(parentName, fieldName, schema) {
57
72
  let sem = Semantic$Reventless.get(schema);
58
73
  if (sem === undefined) {
59
74
  return shapeOf(parentName, fieldName, schema);
@@ -415,6 +430,7 @@ export {
415
430
  semanticCompositeNames,
416
431
  canonicalName,
417
432
  fromSury,
433
+ withoutDefault,
418
434
  shapeOf,
419
435
  maxReportDepth,
420
436
  collectUnclassifiedUnions,
@@ -13,10 +13,10 @@ let jsonObject = (entries: array<(string, JSON.t)>): JSON.t =>
13
13
  // An absent plugin means "the declaring plugin's own", which the key's absence
14
14
  // says exactly. Writing an empty string instead would make "mine" and "unnamed"
15
15
  // indistinguishable to every reader.
16
- let withOptionalPlugin = (
17
- entries: array<(string, JSON.t)>,
18
- plugin: option<string>,
19
- ): array<(string, JSON.t)> =>
16
+ let withOptionalPlugin = (entries: array<(string, JSON.t)>, plugin: option<string>): array<(
17
+ string,
18
+ JSON.t,
19
+ )> =>
20
20
  switch plugin {
21
21
  | Some(p) => entries->Array.concat([("plugin", JSON.Encode.string(p))])
22
22
  | None => entries
@@ -47,8 +47,7 @@ let mergeAnnotations = (
47
47
  }
48
48
  switch spec.indexes->Array.find(((field, _)) => field === fieldName) {
49
49
  | Some((_, indexName)) =>
50
- let value =
51
- indexName === "" ? JSON.Encode.bool(true) : JSON.Encode.string(indexName)
50
+ let value = indexName === "" ? JSON.Encode.bool(true) : JSON.Encode.string(indexName)
52
51
  obj->Dict.set("x-reventless-index", value)
53
52
  | None => ()
54
53
  }
@@ -141,10 +140,9 @@ let mergeAnnotations = (
141
140
  // the keys above follow: false is what every record said before the opt-in
142
141
  // existed, and writing it would put a key on every retirement to say
143
142
  // nothing changed.
144
- let entries =
145
- r.namedWhenRetired
146
- ? Array.concat(entries, [("namedWhenRetired", JSON.Encode.bool(true))])
147
- : entries
143
+ let entries = r.namedWhenRetired
144
+ ? Array.concat(entries, [("namedWhenRetired", JSON.Encode.bool(true))])
145
+ : entries
148
146
  obj->Dict.set("x-reventless-retired", JSON.Encode.object(Dict.fromArray(entries)))
149
147
  | _ => ()
150
148
  }
@@ -234,6 +232,15 @@ let rec fromSchemaType = (~inputNames: bool=false, st: SchemaType.schemaType): J
234
232
  | _ => base
235
233
  }
236
234
  base->withSemantic(sem)
235
+ // JSON Schema's own keyword, not an `x-reventless-` extension: the vocabulary
236
+ // already has a word for this one, so any client reads it.
237
+ | Defaulted(value, inner) =>
238
+ switch fromSchemaType(~inputNames, inner)->JSON.Decode.object {
239
+ | Some(obj) =>
240
+ obj->Dict.set("default", value)
241
+ JSON.Encode.object(obj)
242
+ | None => fromSchemaType(~inputNames, inner)
243
+ }
237
244
  // A union has no input form — see the fragment generator, which emits `String`
238
245
  // and says so — hence no name to publish on either arm.
239
246
  // A union is `oneOf` its arms, each an object carrying the `TAG` const it is
@@ -419,6 +426,7 @@ and objectRefToJsonSchema = (
419
426
  | None => withAnnotations
420
427
  }
421
428
  props->Dict.set(fieldName, withAnnotations)
429
+
422
430
  // Optional two ways, because neither source answers alone. `optional` is
423
431
  // read off the sury schema and is the only thing that can speak for a
424
432
  // reference or a tagged field, which classify as `EntityId` before their
@@ -170,130 +170,144 @@ function withGraphqlInput(schema, name) {
170
170
  }
171
171
  }
172
172
 
173
- function fromSchemaType(inputNamesOpt, st) {
174
- let inputNames = inputNamesOpt !== undefined ? inputNamesOpt : false;
175
- if (typeof st !== "object") {
176
- switch (st) {
177
- case "ScalarNumber" :
178
- return Object.fromEntries([[
179
- "type",
180
- "number"
181
- ]]);
182
- case "ScalarBoolean" :
183
- return Object.fromEntries([[
184
- "type",
185
- "boolean"
186
- ]]);
187
- case "ScalarInt" :
188
- case "ScalarBigInt" :
189
- return Object.fromEntries([[
190
- "type",
191
- "integer"
192
- ]]);
193
- case "EntityId" :
194
- return Object.fromEntries([
195
- [
196
- "type",
197
- "string"
198
- ],
199
- [
200
- "format",
201
- "uuid"
202
- ]
203
- ]);
204
- case "DateTime" :
205
- return Object.fromEntries([
206
- [
207
- "type",
208
- "string"
209
- ],
210
- [
211
- "format",
212
- "date-time"
213
- ]
214
- ]);
215
- case "CalendarDate" :
216
- return Object.fromEntries([
217
- [
218
- "type",
219
- "string"
220
- ],
221
- [
222
- "format",
223
- "date"
224
- ]
225
- ]);
226
- case "ScalarString" :
227
- case "Unknown" :
228
- return Object.fromEntries([[
229
- "type",
230
- "string"
231
- ]]);
232
- }
233
- } else {
234
- switch (st.TAG) {
235
- case "Nullable" :
236
- let innerSchema = fromSchemaType(inputNames, st._0);
237
- return Object.fromEntries([[
238
- "oneOf",
173
+ function fromSchemaType(_inputNamesOpt, _st) {
174
+ while (true) {
175
+ let inputNamesOpt = _inputNamesOpt;
176
+ let st = _st;
177
+ let inputNames = inputNamesOpt !== undefined ? inputNamesOpt : false;
178
+ if (typeof st !== "object") {
179
+ switch (st) {
180
+ case "ScalarNumber" :
181
+ return Object.fromEntries([[
182
+ "type",
183
+ "number"
184
+ ]]);
185
+ case "ScalarBoolean" :
186
+ return Object.fromEntries([[
187
+ "type",
188
+ "boolean"
189
+ ]]);
190
+ case "ScalarInt" :
191
+ case "ScalarBigInt" :
192
+ return Object.fromEntries([[
193
+ "type",
194
+ "integer"
195
+ ]]);
196
+ case "EntityId" :
197
+ return Object.fromEntries([
198
+ [
199
+ "type",
200
+ "string"
201
+ ],
239
202
  [
240
- innerSchema,
241
- Object.fromEntries([[
242
- "type",
243
- "null"
244
- ]])
203
+ "format",
204
+ "uuid"
245
205
  ]
246
- ]]);
247
- case "ArrayOf" :
248
- return Object.fromEntries([
249
- [
250
- "type",
251
- "array"
252
- ],
253
- [
254
- "items",
255
- fromSchemaType(inputNames, st._0)
256
- ]
257
- ]);
258
- case "ObjectRef" :
259
- let base = objectRefToJsonSchema(undefined, undefined, undefined, undefined, inputNames, st._1);
260
- if (inputNames) {
261
- return withGraphqlInput(base, st._0);
262
- } else {
263
- return base;
264
- }
265
- case "Enum" :
266
- return Object.fromEntries([
267
- [
268
- "type",
269
- "string"
270
- ],
271
- [
272
- "enum",
273
- st._1.map(prim => prim)
274
- ]
275
- ]);
276
- case "Semantic" :
277
- let inner = st._1;
278
- let sem = st._0;
279
- let base$1 = fromSchemaType(inputNames, inner);
280
- let match = SchemaType$ReventlessCore.canonicalName(sem.id);
281
- let base$2 = inputNames && match !== undefined && typeof inner === "object" && inner.TAG === "ObjectRef" ? withGraphqlInput(base$1, match + "Input") : base$1;
282
- return withSemantic(base$2, sem);
283
- case "TaggedUnion" :
284
- let members = st._1.map(param => armToJsonSchema(inputNames, param[0], param[1]));
285
- return Object.fromEntries([
286
- [
287
- "oneOf",
288
- members
289
- ],
290
- [
291
- "x-reventless-union",
292
- st._0
293
- ]
294
- ]);
206
+ ]);
207
+ case "DateTime" :
208
+ return Object.fromEntries([
209
+ [
210
+ "type",
211
+ "string"
212
+ ],
213
+ [
214
+ "format",
215
+ "date-time"
216
+ ]
217
+ ]);
218
+ case "CalendarDate" :
219
+ return Object.fromEntries([
220
+ [
221
+ "type",
222
+ "string"
223
+ ],
224
+ [
225
+ "format",
226
+ "date"
227
+ ]
228
+ ]);
229
+ case "ScalarString" :
230
+ case "Unknown" :
231
+ return Object.fromEntries([[
232
+ "type",
233
+ "string"
234
+ ]]);
235
+ }
236
+ } else {
237
+ switch (st.TAG) {
238
+ case "Nullable" :
239
+ let innerSchema = fromSchemaType(inputNames, st._0);
240
+ return Object.fromEntries([[
241
+ "oneOf",
242
+ [
243
+ innerSchema,
244
+ Object.fromEntries([[
245
+ "type",
246
+ "null"
247
+ ]])
248
+ ]
249
+ ]]);
250
+ case "ArrayOf" :
251
+ return Object.fromEntries([
252
+ [
253
+ "type",
254
+ "array"
255
+ ],
256
+ [
257
+ "items",
258
+ fromSchemaType(inputNames, st._0)
259
+ ]
260
+ ]);
261
+ case "ObjectRef" :
262
+ let base = objectRefToJsonSchema(undefined, undefined, undefined, undefined, inputNames, st._1);
263
+ if (inputNames) {
264
+ return withGraphqlInput(base, st._0);
265
+ } else {
266
+ return base;
267
+ }
268
+ case "Enum" :
269
+ return Object.fromEntries([
270
+ [
271
+ "type",
272
+ "string"
273
+ ],
274
+ [
275
+ "enum",
276
+ st._1.map(prim => prim)
277
+ ]
278
+ ]);
279
+ case "Semantic" :
280
+ let inner = st._1;
281
+ let sem = st._0;
282
+ let base$1 = fromSchemaType(inputNames, inner);
283
+ let match = SchemaType$ReventlessCore.canonicalName(sem.id);
284
+ let base$2 = inputNames && match !== undefined && typeof inner === "object" && inner.TAG === "ObjectRef" ? withGraphqlInput(base$1, match + "Input") : base$1;
285
+ return withSemantic(base$2, sem);
286
+ case "Defaulted" :
287
+ let inner$1 = st._1;
288
+ let obj = Stdlib_JSON.Decode.object(fromSchemaType(inputNames, inner$1));
289
+ if (obj !== undefined) {
290
+ obj["default"] = st._0;
291
+ return obj;
292
+ }
293
+ _st = inner$1;
294
+ _inputNamesOpt = inputNames;
295
+ continue;
296
+ case "TaggedUnion" :
297
+ let members = st._1.map(param => armToJsonSchema(inputNames, param[0], param[1]));
298
+ return Object.fromEntries([
299
+ [
300
+ "oneOf",
301
+ members
302
+ ],
303
+ [
304
+ "x-reventless-union",
305
+ st._0
306
+ ]
307
+ ]);
308
+ }
295
309
  }
296
- }
310
+ };
297
311
  }
298
312
 
299
313
  function armToJsonSchema(inputNamesOpt, tag, armType) {
@@ -5,9 +5,9 @@ type outputs = ReventlessInfra.AutomationSlice.outputs
5
5
  type operations = ReventlessInfra.AutomationSlice.operations
6
6
  type component = Component.t<t, outputs, operations>
7
7
 
8
- let toResolvedOutputs = (
9
- outputs: outputs,
10
- ): Pulumi.Output.t<ReventlessInterop.AutomationSlice.resolvedOutputs> =>
8
+ let toResolvedOutputs = (outputs: outputs): Pulumi.Output.t<
9
+ ReventlessInterop.AutomationSlice.resolvedOutputs,
10
+ > =>
11
11
  (
12
12
  outputs.resources->Adapter.resourcesToInterop,
13
13
  outputs.queryDb.resources->Adapter.resourcesToInterop,
@@ -15,7 +15,7 @@ let toResolvedOutputs = (
15
15
  ->Pulumi.Output.all2
16
16
  ->Pulumi.Output.apply(((resources, queryDbResources)) => {
17
17
  let resolved: ReventlessInterop.AutomationSlice.resolvedOutputs = {
18
- resources: resources,
18
+ resources,
19
19
  queryDb: {resources: queryDbResources},
20
20
  }
21
21
  resolved