@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.
- package/CHANGELOG.md +15 -0
- package/package.json +11 -11
- package/src/Behavior.res +1 -4
- package/src/Message.res +17 -14
- package/src/Projection.res +51 -25
- package/src/RequestContext.res +8 -9
- package/src/ResourceAttribution.res +28 -14
- package/src/adapter/Adapter.res +48 -4
- package/src/adapter/EventLogProvisioning/EventLogProvisioning.res +5 -5
- package/src/adapter/Messaging/Messaging_Log_Backend.res +10 -7
- package/src/adapter/Messaging/Messaging_Log_Backend.res.mjs +2 -4
- package/src/adapter/Monitoring/Monitoring.res +16 -17
- package/src/adapter/QueryInterception/QueryInterception.res +0 -1
- package/src/adapter/Runtime/AggregateRuntime_Builder_Common.res +12 -5
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res +11 -7
- package/src/adapter/Runtime/PluginRuntime_Builder_Micro.res +1 -7
- package/src/adapter/Runtime/PluginRuntime_Builder_Single.res +1 -7
- package/src/adapter/RuntimeExtension/RuntimeExtension.res +0 -1
- package/src/admin/Platform_Admin.res +17 -6
- package/src/admin/Platform_AdminApi.res +14 -9
- package/src/admin/Platform_Admin_Callback.res +1 -1
- package/src/admin/Platform_BakedManifest.res +34 -34
- package/src/admin/Platform_ComponentDefinitionsApi.res +9 -21
- package/src/admin/Platform_PluginStructuresApi.res +15 -12
- package/src/admin/UiFragmentRegistry/StateChange/UiFragmentRegistry.res +1 -1
- package/src/components/Aggregate/Aggregate.res +13 -12
- package/src/components/Aggregate/Aggregate_Builder.res +22 -21
- package/src/components/Aggregate/Aggregate_Callback.res +91 -86
- package/src/components/Api/ApiNoApiHelpers.res +1 -3
- package/src/components/Api/Api_Ids.res +0 -1
- package/src/components/Api/Api_Naming.res +41 -18
- package/src/components/Api/GraphQL_FragmentGenerator.res +42 -52
- package/src/components/Api/GraphQL_FragmentGenerator.res.mjs +11 -4
- package/src/components/Api/GraphQL_SchemaInspector.res +5 -3
- package/src/components/Api/GraphQL_Stitcher.res +9 -10
- package/src/components/Api/MCP_SchemaGenerator.res +8 -12
- package/src/components/Api/OwnerScopeDiagnostics.res +1 -2
- package/src/components/Api/QueryDbListQuery.res +13 -6
- package/src/components/Api/SchemaType.res +40 -20
- package/src/components/Api/SchemaType.res.mjs +16 -0
- package/src/components/Api/SuryToJsonSchema.res +18 -10
- package/src/components/Api/SuryToJsonSchema.res.mjs +135 -121
- package/src/components/AutomationSlice/AutomationSlice.res +4 -4
- package/src/components/AutomationSlice/AutomationSlice_Builder.res +15 -14
- package/src/components/AutomationSlice/AutomationSlice_Callback.res +3 -3
- package/src/components/Builder_Helpers.res +12 -23
- package/src/components/CommandGenerator/CommandGenerator.res +6 -1
- package/src/components/CommandGenerator/CommandGenerator_Builder.res +29 -21
- package/src/components/CommandGenerator/CommandGenerator_Callback.res +17 -21
- package/src/components/CommandTopic/CommandTopic.res +3 -3
- package/src/components/CommandTopic/CommandTopic_Builder.res +10 -10
- package/src/components/CommandTopic/CommandTopic_Callback.res +1 -4
- package/src/components/CommandTopic/CommandTopic_Helpers.res +1 -2
- package/src/components/Counter/Counter_Builder.res +1 -6
- package/src/components/Counter/Counter_Callback.res +3 -3
- package/src/components/Dcb/Dcb_Builder.res +970 -956
- package/src/components/DcbEventLog/DcbEventLog.res +4 -4
- package/src/components/DcbEventLog/DcbEventLog_Builder.res +0 -1
- package/src/components/DcbEventLog/DcbEventLog_Operations.res +17 -18
- package/src/components/EventCollector/EventCollector_Builder.res +2 -1
- package/src/components/EventLog/EventLog.res +5 -1
- package/src/components/EventLog/EventLog_Operations.res +12 -8
- package/src/components/EventMapper/EventMapper.res +8 -10
- package/src/components/EventMapper/EventMapper_Builder.res +4 -1
- package/src/components/EventMapper/EventMapper_Callback.res +46 -31
- package/src/components/EventTopic/EventTopic.res +3 -3
- package/src/components/EventTopic/EventTopic_Builder.res +1 -1
- package/src/components/Extension/Extension.res +4 -1
- package/src/components/Extension/Extension_Operations.res +11 -3
- package/src/components/ExtensionPoint/ExtensionPoint.res +3 -3
- package/src/components/ExtensionPoint/ExtensionPoint_Builder.res +9 -10
- package/src/components/ExtensionPoint/ExtensionPoint_Callback.res +2 -6
- package/src/components/ExtensionPoint/ExtensionPoint_Operations.res +13 -5
- package/src/components/Heartbeat/Heartbeat_Callback.res +3 -3
- package/src/components/InboundTranslationSlice/InboundTranslationSlice.res +4 -4
- package/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res +7 -10
- package/src/components/OutboundTranslationSlice/OutboundTranslationSlice.res +4 -4
- package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res +15 -14
- package/src/components/QueryDb/QueryDb_Adapter.res +1 -3
- package/src/components/QueryDb/QueryDb_Operations.res +10 -10
- package/src/components/ReadModel/ReadModel.res +3 -3
- package/src/components/ReadModel/ReadModel_Builder.res +1 -2
- package/src/components/ReadModel/ReadModel_Callback.res +2 -1
- package/src/components/SideEffectHandler/SideEffectHandler_Callback.res +5 -2
- package/src/components/StateChangeSlice/StateChangeSlice.res +3 -3
- package/src/components/StateChangeSlice/StateChangeSlice_Builder.res +23 -4
- package/src/components/StateChangeSlice/StateChangeSlice_Callback.res +22 -6
- package/src/components/StateTopic.res +1 -3
- package/src/components/StateViewSlice/StateViewSlice.res +4 -4
- package/src/components/StateViewSlice/StateViewSlice_Builder.res +79 -68
- package/src/components/StateViewSlice/StateViewSlice_Callback.res +3 -1
- package/src/components/Task/Task.res +3 -3
- package/src/components/Task/Task_Adapter.res +4 -1
- package/src/components/Task/Task_Builder.res +24 -21
- package/src/plugin/api/PluginBaseFragment.res +9 -3
- package/src/plugin/component/Capability_Inference.res +8 -10
- package/src/plugin/component/Plugin.res +6 -6
- package/src/plugin/component/Plugin_Builder.res +54 -50
- package/src/plugin/component/Plugin_Callback.res +10 -6
- package/src/plugin/component/Plugin_Helpers.res +264 -230
- package/src/plugin/component/Plugin_Structure.res +370 -324
- package/src/plugin/component/Plugin_SubscriptionSchema.res +8 -6
- package/src/plugin/component/SchemaWalker.res +11 -12
- package/src/plugin/connect/PluginConnectExtension_Mapping.res +45 -50
- package/src/plugin/lifecycle/PluginBehavior.res +3 -4
- package/src/plugin/lifecycle/PluginSpec.res +1 -2
- package/src/plugin/lifecycle/PluginsProjection.res +16 -5
- package/src/plugin/lifecycle/PluginsReadModelSpec.res +0 -2
- package/src/util/CommandPublisher.res +9 -2
- package/src/util/CsvStream.res +3 -3
- package/src/util/Interstack.res +7 -15
- package/src/util/Interstack.resi +3 -3
- package/src/util/LogFormat.res +5 -9
- package/src/util/Logger.res +1 -2
- package/src/util/Lru.res +2 -1
- package/src/util/Lru.resi +2 -3
- package/src/util/ScheduleOps.res +24 -27
- package/src/util/StorePrefixCollision.res +6 -9
- package/src/util/Util_Promise.res +4 -1
- package/src/util/Util_Promise.res.mjs +1 -1
- package/tests/IdentityTest.res +166 -113
- package/tests/ResourceAttributionTest.res +28 -25
- package/tests/StorePrefixCollisionTest.res +2 -1
- package/tests/TaskBucketNamingTest.res +3 -2
- package/tests/adapter/EventLogProvisioningTest.res +51 -48
- package/tests/adapter/MonitoringTest.res +81 -38
- package/tests/adapter/QueryInterceptionTest.res +2 -2
- package/tests/adapter/RefusalVocabularyTest.res +31 -23
- package/tests/adapter/RuntimeExtensionHookReachTest.res +9 -8
- package/tests/adapter/RuntimeExtensionTest.res +5 -3
- package/tests/admin/AdminApiSchemaDriftTest.res +22 -16
- package/tests/admin/Platform_Admin_StructureTest.res +10 -11
- package/tests/admin/Platform_BakedManifestTest.res +31 -35
- package/tests/admin/Platform_ComponentDefinitionsApiTest.res +18 -15
- package/tests/admin/Platform_PluginStructuresApiTest.res +5 -3
- package/tests/admin/Platform_UIFragmentsApiTest.res +6 -3
- package/tests/aggregate/AggregateCacheTest.res +10 -12
- package/tests/aggregate/AggregateCallbackTest.res +75 -46
- package/tests/aggregate/AggregateCausationTest.res +19 -20
- package/tests/aggregate/AggregateConflictTest.res +41 -19
- package/tests/aggregate/AggregateFixtures.res +15 -5
- package/tests/aggregate/AggregateRejectionTest.res +97 -80
- package/tests/aggregate/AggregateSnapshotTest.res +44 -16
- package/tests/api/Api_IdsTest.res +10 -4
- package/tests/api/BrandedMarkerCompositionTest.res +48 -36
- package/tests/api/GeolocationSemanticTest.res +3 -3
- package/tests/api/GraphQL_FragmentGeneratorTest.res +66 -54
- package/tests/api/OwnerScopeDiagnosticsTest.res +31 -27
- package/tests/api/StorageRefFieldsTest.res +30 -18
- package/tests/api/SuryToJsonSchemaTest.res +1338 -981
- package/tests/api/SuryToJsonSchemaTest.res.mjs +31 -0
- package/tests/api/TaggedUnionSchemaTest.res +17 -24
- package/tests/commandgenerator/CommandGeneratorCallbackTest.res +235 -179
- package/tests/commandgenerator/CommandGeneratorFixtures.res +8 -13
- package/tests/commandgenerator/OwnerStampingTest.res +91 -76
- package/tests/commandtopic/CommandOutcomeHookTest.res +198 -155
- package/tests/commandtopic/CommandTopicCallbackFixtures.res +5 -4
- package/tests/commandtopic/CommandTopicCallbackTest.res +61 -43
- package/tests/commandtopic/CommandTopicHelpersRejectionTest.res +70 -55
- package/tests/counter/CounterCallbackTest.res +40 -34
- package/tests/counter/CounterFixtures.res +4 -4
- package/tests/dcb/DcbDecodeTest.res +115 -84
- package/tests/dcb/DcbEventLogOperationsTest.res +194 -143
- package/tests/dcb/DcbEventLogSchemaTest.res +13 -13
- package/tests/dcb/DcbFixtures.res +4 -5
- package/tests/dcb/DcbScopeInferenceTest.res +173 -114
- package/tests/dcb/DcbStateChangeSliceTest.res +391 -262
- package/tests/dcb/DcbTagTest.res +22 -11
- package/tests/dcb/DcbValidationTest.res +288 -218
- package/tests/eventlog/EventLogFixtures.res +4 -4
- package/tests/eventlog/EventLogOperationsTest.res +102 -67
- package/tests/eventlog/EventLogRetryTest.res +104 -65
- package/tests/eventmapper/EventMapperCallbackTest.res +118 -83
- package/tests/eventmapper/EventMapperFixtures.res +15 -23
- package/tests/eventmapper/EventMapperTest.res +54 -38
- package/tests/eventtopic/EventTopicFixtures.res +3 -4
- package/tests/eventtopic/EventTopicOperationsTest.res +41 -29
- package/tests/extensionpoint/ExtensionPointCallbackTest.res +58 -45
- package/tests/extensionpoint/ExtensionPointFixtures.res +16 -20
- package/tests/extensionpoint/ExtensionPointOperationsTest.res +70 -49
- package/tests/extensionpoint/PluginDisconnectScheduleTest.res +2 -1
- package/tests/logger/LogFormatTest.res +104 -82
- package/tests/logger/LoggerLazyTest.res +21 -12
- package/tests/message/MessageTest.res +96 -93
- package/tests/message/MetaEnvelopeTest.res +26 -30
- package/tests/plugin/HeartbeatDisconnectGraceTest.res +31 -25
- package/tests/plugin/ManifestVisibilityTest.res +20 -12
- package/tests/plugin/PluginDefinitionScalars.res +1 -2
- package/tests/plugin/PluginLifecycleCorpusTest.res +15 -12
- package/tests/plugin/PluginSpecExperiment.res +0 -1
- package/tests/plugin/PluginStructureTest.res +1533 -1030
- package/tests/plugin/PluginStructureTest.res.mjs +6 -0
- package/tests/plugin/Plugin_EventQuerySchemaTest.res +21 -10
- package/tests/plugin/SchemaWalkerTest.res +116 -70
- package/tests/plugin/StateChange/PsReserveStock.res +4 -4
- package/tests/plugin/StateView/PsAnnotatedView.res +6 -4
- package/tests/plugin/StateView/PsAnnotatedView.res.mjs +7 -3
- package/tests/plugin/StateView/PsCustomersView.res +4 -4
- package/tests/plugin/StateView/PsShipmentsView.res +3 -2
- package/tests/projection/LifecycleTrailTest.res +1 -4
- package/tests/projection/ProjectionOptimizeTest.res +13 -9
- package/tests/querydb/QueryDbFixtures.res +0 -1
- package/tests/querydb/QueryDbOperationsTest.res +99 -64
- package/tests/querydb/TaggedUnionStampTest.res +10 -8
- package/tests/sideeffecthandler/SideEffectHandlerCallbackTest.res +50 -35
- package/tests/sideeffecthandler/SideEffectHandlerFixtures.res +4 -10
- package/tests/util/CommandPublisherTest.res +0 -1
- package/tests/util/CsvStreamTest.res +3 -3
- 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(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
|
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
|
-
|
|
46
|
-
|
|
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
|
-
|
|
129
|
-
|
|
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 =>
|
|
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
|
|
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)
|
|
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)
|
|
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 =>
|
|
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)
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
139
|
-
|
|
140
|
-
|
|
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(
|
|
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
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
)
|
|
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
|
-
|
|
146
|
-
|
|
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(
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
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
|
-
|
|
241
|
-
|
|
242
|
-
"type",
|
|
243
|
-
"null"
|
|
244
|
-
]])
|
|
203
|
+
"format",
|
|
204
|
+
"uuid"
|
|
245
205
|
]
|
|
246
|
-
]
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
[
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
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
|
-
|
|
10
|
-
|
|
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
|
|
18
|
+
resources,
|
|
19
19
|
queryDb: {resources: queryDbResources},
|
|
20
20
|
}
|
|
21
21
|
resolved
|