@reventlessdev/reventless-core 3.0.0-alpha.181 → 3.0.0-alpha.183
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 +5 -5
- package/src/components/Api/SchemaType.res +3 -1
- package/src/components/Api/SchemaType.res.mjs +12 -2
- package/src/components/Dcb/Dcb_Builder.res +1 -1
- package/src/components/Dcb/Dcb_Builder.res.mjs +1 -2
- package/src/components/InboundTranslationSlice/InboundTranslationSlice.res +0 -23
- package/src/components/InboundTranslationSlice/InboundTranslationSlice.res.mjs +0 -31
- package/src/components/InboundTranslationSlice/InboundTranslationSlice_Callback.res +28 -0
- package/src/components/InboundTranslationSlice/InboundTranslationSlice_Callback.res.mjs +31 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,21 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# 3.0.0-alpha.183 (2026-07-27)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **aws:** keep InboundTranslationSlice runtime path out of the Pulumi graph ([9166cff](https://github.com/ReventlessDev/reventless-core/commit/9166cff85939012d12e44835e2eb79a88fd1b66a))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# 3.0.0-alpha.182 (2026-07-26)
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* **api:** commit regenerated SchemaType output for nullable optional enums ([6d48f53](https://github.com/ReventlessDev/reventless-core/commit/6d48f53c31489b8cb312c4bc63dac3b927145bd4))
|
|
18
|
+
* **api:** preserve nullability for optional enum fields in generated GraphQL ([3110a4a](https://github.com/ReventlessDev/reventless-core/commit/3110a4af032440ba2639519f61f221960ac78fba))
|
|
19
|
+
|
|
20
|
+
|
|
6
21
|
# 3.0.0-alpha.181 (2026-07-26)
|
|
7
22
|
|
|
8
23
|
### Bug Fixes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reventlessdev/reventless-core",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.183",
|
|
4
4
|
"description": "Core package for Reventless framework",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"jest": {
|
|
@@ -28,16 +28,16 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"sury": "11.0.0-alpha.4",
|
|
30
30
|
"uuid": "^13.0.0",
|
|
31
|
+
"@reventlessdev/rescript-effect": "0.1.0-alpha.31",
|
|
31
32
|
"@reventlessdev/rescript-fast-csv": "1.2.0-alpha.14",
|
|
32
|
-
"@reventlessdev/rescript-hash-object": "1.2.0-alpha.13",
|
|
33
33
|
"@reventlessdev/rescript-jest": "1.0.0-alpha.9",
|
|
34
34
|
"@reventlessdev/rescript-node-streams": "1.1.0-alpha.13",
|
|
35
|
-
"@reventlessdev/rescript-
|
|
35
|
+
"@reventlessdev/rescript-hash-object": "1.2.0-alpha.13",
|
|
36
36
|
"@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.17",
|
|
37
|
-
"@reventlessdev/rescript-ssh2": "1.1.0-alpha.14",
|
|
38
37
|
"@reventlessdev/rescript-uuid": "1.1.0-alpha.17",
|
|
39
|
-
"@reventlessdev/reventless-infra": "3.0.0-alpha.105",
|
|
40
38
|
"@reventlessdev/reventless-interop": "3.0.0-alpha.29",
|
|
39
|
+
"@reventlessdev/rescript-ssh2": "1.1.0-alpha.14",
|
|
40
|
+
"@reventlessdev/reventless-infra": "3.0.0-alpha.105",
|
|
41
41
|
"@reventlessdev/reventless-spec": "3.0.0-alpha.81"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
@@ -82,6 +82,7 @@ let rec fromSury = (~parentName: string, ~fieldName: string, schema: S.t<unknown
|
|
|
82
82
|
| _ => true
|
|
83
83
|
}
|
|
84
84
|
)
|
|
85
|
+
let isOptional = nonNullVariants->Array.length < anyOf->Array.length
|
|
85
86
|
if nonNullVariants->Array.length == 1 {
|
|
86
87
|
Nullable(
|
|
87
88
|
fromSury(
|
|
@@ -102,7 +103,8 @@ let rec fromSury = (~parentName: string, ~fieldName: string, schema: S.t<unknown
|
|
|
102
103
|
parentName ++
|
|
103
104
|
fieldName->String.charAt(0)->String.toUpperCase ++
|
|
104
105
|
fieldName->String.slice(~start=1, ~end=fieldName->String.length)
|
|
105
|
-
Enum(enumName, constValues)
|
|
106
|
+
let enum = Enum(enumName, constValues)
|
|
107
|
+
isOptional ? Nullable(enum) : enum
|
|
106
108
|
} else {
|
|
107
109
|
Unknown
|
|
108
110
|
}
|
|
@@ -83,7 +83,8 @@ function fromSury(parentName, fieldName, schema) {
|
|
|
83
83
|
};
|
|
84
84
|
}
|
|
85
85
|
case "union" :
|
|
86
|
-
let
|
|
86
|
+
let anyOf = schema.anyOf;
|
|
87
|
+
let nonNullVariants = anyOf.filter(v => {
|
|
87
88
|
switch (v.type) {
|
|
88
89
|
case "null" :
|
|
89
90
|
case "undefined" :
|
|
@@ -92,6 +93,7 @@ function fromSury(parentName, fieldName, schema) {
|
|
|
92
93
|
return true;
|
|
93
94
|
}
|
|
94
95
|
});
|
|
96
|
+
let isOptional = nonNullVariants.length < anyOf.length;
|
|
95
97
|
if (nonNullVariants.length === 1) {
|
|
96
98
|
return {
|
|
97
99
|
TAG: "Nullable",
|
|
@@ -111,11 +113,19 @@ function fromSury(parentName, fieldName, schema) {
|
|
|
111
113
|
return "Unknown";
|
|
112
114
|
}
|
|
113
115
|
let enumName = parentName + fieldName.charAt(0).toUpperCase() + fieldName.slice(1, fieldName.length);
|
|
114
|
-
|
|
116
|
+
let $$enum = {
|
|
115
117
|
TAG: "Enum",
|
|
116
118
|
_0: enumName,
|
|
117
119
|
_1: constValues
|
|
118
120
|
};
|
|
121
|
+
if (isOptional) {
|
|
122
|
+
return {
|
|
123
|
+
TAG: "Nullable",
|
|
124
|
+
_0: $$enum
|
|
125
|
+
};
|
|
126
|
+
} else {
|
|
127
|
+
return $$enum;
|
|
128
|
+
}
|
|
119
129
|
default:
|
|
120
130
|
return "Unknown";
|
|
121
131
|
}
|
|
@@ -720,7 +720,7 @@ module Make = (
|
|
|
720
720
|
let result = await receiveFn(args)
|
|
721
721
|
let response =
|
|
722
722
|
result
|
|
723
|
-
->
|
|
723
|
+
->InboundTranslationSlice_Callback.receiveResultToOutcome
|
|
724
724
|
->CommandTopic.commandOutcomeToJson
|
|
725
725
|
response->Obj.magic
|
|
726
726
|
})
|
|
@@ -23,7 +23,6 @@ import * as ApiNoApiHelpers$ReventlessCore from "../Api/ApiNoApiHelpers.res.mjs"
|
|
|
23
23
|
import * as Plugin_Structure$ReventlessCore from "../../plugin/component/Plugin_Structure.res.mjs";
|
|
24
24
|
import * as DcbEventLog_Builder$ReventlessCore from "../DcbEventLog/DcbEventLog_Builder.res.mjs";
|
|
25
25
|
import * as CommandTopic_Builder$ReventlessCore from "../CommandTopic/CommandTopic_Builder.res.mjs";
|
|
26
|
-
import * as InboundTranslationSlice$ReventlessCore from "../InboundTranslationSlice/InboundTranslationSlice.res.mjs";
|
|
27
26
|
import * as AutomationSlice_Callback$ReventlessCore from "../AutomationSlice/AutomationSlice_Callback.res.mjs";
|
|
28
27
|
import * as CommandGenerator_Callback$ReventlessCore from "../CommandGenerator/CommandGenerator_Callback.res.mjs";
|
|
29
28
|
import * as InboundTranslationSlice_Callback$ReventlessCore from "../InboundTranslationSlice/InboundTranslationSlice_Callback.res.mjs";
|
|
@@ -384,7 +383,7 @@ function Make(DcbEventLogStorage) {
|
|
|
384
383
|
if (receiveFn !== undefined) {
|
|
385
384
|
return Effect.promise(async () => {
|
|
386
385
|
let result = await receiveFn(args);
|
|
387
|
-
return CommandTopic$ReventlessCore.commandOutcomeToJson(
|
|
386
|
+
return CommandTopic$ReventlessCore.commandOutcomeToJson(InboundTranslationSlice_Callback$ReventlessCore.receiveResultToOutcome(result));
|
|
388
387
|
});
|
|
389
388
|
} else {
|
|
390
389
|
return baseHandler(event, ctx);
|
|
@@ -5,31 +5,8 @@ type outputs = ReventlessInfra.InboundTranslationSlice.outputs
|
|
|
5
5
|
type operations = ReventlessInfra.InboundTranslationSlice.operations
|
|
6
6
|
type acceptedResult = ReventlessInfra.InboundTranslationSlice.acceptedResult
|
|
7
7
|
type rejectedResult = ReventlessInfra.InboundTranslationSlice.rejectedResult
|
|
8
|
-
type receiveResult = ReventlessInfra.InboundTranslationSlice.receiveResult
|
|
9
8
|
type component = Component.t<t, outputs, operations>
|
|
10
9
|
|
|
11
|
-
/**
|
|
12
|
-
Map a `receive` outcome onto the `CommandResult` union the slice's mutation field
|
|
13
|
-
declares, so both surfaces feed `CommandTopic.commandOutcomeToJson` rather than
|
|
14
|
-
hand-rolling a second `__typename` writer.
|
|
15
|
-
|
|
16
|
-
A translation can fan out across several targets; the mutation response reports
|
|
17
|
-
the first target as `entityId` and the fan-out count as `eventCount`. The
|
|
18
|
-
per-target detail stays queryable through the slice's audit read model. When the
|
|
19
|
-
translation legitimately produced no command, `entityId` is omitted (encoding as
|
|
20
|
-
`null`) rather than reporting a target that does not exist.
|
|
21
|
-
*/
|
|
22
|
-
let receiveResultToOutcome = (result: receiveResult): CommandTopic.commandOutcome =>
|
|
23
|
-
switch result {
|
|
24
|
-
| Ok({requestId, targetIds, commandCount}) =>
|
|
25
|
-
switch targetIds->Array.get(0) {
|
|
26
|
-
| Some(entityId) => Accepted({msgId: requestId, entityId, eventCount: commandCount})
|
|
27
|
-
| None => Accepted({msgId: requestId, eventCount: commandCount})
|
|
28
|
-
}
|
|
29
|
-
| Error({requestId, error}) =>
|
|
30
|
-
Rejected({msgId: requestId, errorCode: "TranslationFailed", errorDetail: Some(error)})
|
|
31
|
-
}
|
|
32
|
-
|
|
33
10
|
let toResolvedOutputs = (
|
|
34
11
|
outputs: outputs,
|
|
35
12
|
): Pulumi.Output.t<ReventlessInterop.InboundTranslationSlice.resolvedOutputs> =>
|
|
@@ -3,36 +3,6 @@
|
|
|
3
3
|
import * as Pulumi from "@pulumi/pulumi";
|
|
4
4
|
import * as Adapter$ReventlessCore from "../../adapter/Adapter.res.mjs";
|
|
5
5
|
|
|
6
|
-
function receiveResultToOutcome(result) {
|
|
7
|
-
if (result.TAG === "Ok") {
|
|
8
|
-
let match = result._0;
|
|
9
|
-
let commandCount = match.commandCount;
|
|
10
|
-
let requestId = match.requestId;
|
|
11
|
-
let entityId = match.targetIds[0];
|
|
12
|
-
if (entityId !== undefined) {
|
|
13
|
-
return {
|
|
14
|
-
TAG: "Accepted",
|
|
15
|
-
msgId: requestId,
|
|
16
|
-
entityId: entityId,
|
|
17
|
-
eventCount: commandCount
|
|
18
|
-
};
|
|
19
|
-
} else {
|
|
20
|
-
return {
|
|
21
|
-
TAG: "Accepted",
|
|
22
|
-
msgId: requestId,
|
|
23
|
-
eventCount: commandCount
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
let match$1 = result._0;
|
|
28
|
-
return {
|
|
29
|
-
TAG: "Rejected",
|
|
30
|
-
msgId: match$1.requestId,
|
|
31
|
-
errorCode: "TranslationFailed",
|
|
32
|
-
errorDetail: match$1.error
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
6
|
function toResolvedOutputs(outputs) {
|
|
37
7
|
return Pulumi.all([
|
|
38
8
|
Adapter$ReventlessCore.resourcesToInterop(outputs.resources),
|
|
@@ -49,7 +19,6 @@ let componentType = "InboundTranslationSlice";
|
|
|
49
19
|
|
|
50
20
|
export {
|
|
51
21
|
componentType,
|
|
52
|
-
receiveResultToOutcome,
|
|
53
22
|
toResolvedOutputs,
|
|
54
23
|
}
|
|
55
24
|
/* @pulumi/pulumi Not a pure module */
|
|
@@ -18,6 +18,34 @@ type auditRow = {
|
|
|
18
18
|
receivedAt: string,
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
Map a `receive` outcome onto the `CommandResult` union the slice's mutation field
|
|
23
|
+
declares, so both surfaces feed `CommandTopic.commandOutcomeToJson` rather than
|
|
24
|
+
hand-rolling a second `__typename` writer.
|
|
25
|
+
|
|
26
|
+
A translation can fan out across several targets; the mutation response reports
|
|
27
|
+
the first target as `entityId` and the fan-out count as `eventCount`. The
|
|
28
|
+
per-target detail stays queryable through the slice's audit read model. When the
|
|
29
|
+
translation legitimately produced no command, `entityId` is omitted (encoding as
|
|
30
|
+
`null`) rather than reporting a target that does not exist.
|
|
31
|
+
|
|
32
|
+
Lives here rather than in `InboundTranslationSlice.res` because the deployed DCB
|
|
33
|
+
command Lambda calls it at runtime, and the base module imports `@pulumi/pulumi`
|
|
34
|
+
at deploy time — keeping this runtime-pure keeps Pulumi out of the Lambda graph.
|
|
35
|
+
*/
|
|
36
|
+
let receiveResultToOutcome = (
|
|
37
|
+
result: ReventlessInfra.InboundTranslationSlice.receiveResult,
|
|
38
|
+
): CommandTopic.commandOutcome =>
|
|
39
|
+
switch result {
|
|
40
|
+
| Ok({requestId, targetIds, commandCount}) =>
|
|
41
|
+
switch targetIds->Array.get(0) {
|
|
42
|
+
| Some(entityId) => Accepted({msgId: requestId, entityId, eventCount: commandCount})
|
|
43
|
+
| None => Accepted({msgId: requestId, eventCount: commandCount})
|
|
44
|
+
}
|
|
45
|
+
| Error({requestId, error}) =>
|
|
46
|
+
Rejected({msgId: requestId, errorCode: "TranslationFailed", errorDetail: Some(error)})
|
|
47
|
+
}
|
|
48
|
+
|
|
21
49
|
module type T = {
|
|
22
50
|
module Spec: Reventless.InboundTranslationSlice.Spec
|
|
23
51
|
module Translation: Reventless.InboundTranslationSlice.Translation with module Spec := Spec
|
|
@@ -25,6 +25,36 @@ let auditRowSchema = S.schema(s => ({
|
|
|
25
25
|
receivedAt: s.m(S.string)
|
|
26
26
|
}));
|
|
27
27
|
|
|
28
|
+
function receiveResultToOutcome(result) {
|
|
29
|
+
if (result.TAG === "Ok") {
|
|
30
|
+
let match = result._0;
|
|
31
|
+
let commandCount = match.commandCount;
|
|
32
|
+
let requestId = match.requestId;
|
|
33
|
+
let entityId = match.targetIds[0];
|
|
34
|
+
if (entityId !== undefined) {
|
|
35
|
+
return {
|
|
36
|
+
TAG: "Accepted",
|
|
37
|
+
msgId: requestId,
|
|
38
|
+
entityId: entityId,
|
|
39
|
+
eventCount: commandCount
|
|
40
|
+
};
|
|
41
|
+
} else {
|
|
42
|
+
return {
|
|
43
|
+
TAG: "Accepted",
|
|
44
|
+
msgId: requestId,
|
|
45
|
+
eventCount: commandCount
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
let match$1 = result._0;
|
|
50
|
+
return {
|
|
51
|
+
TAG: "Rejected",
|
|
52
|
+
msgId: match$1.requestId,
|
|
53
|
+
errorCode: "TranslationFailed",
|
|
54
|
+
errorDetail: match$1.error
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
28
58
|
function Make(Spec) {
|
|
29
59
|
return Translation => {
|
|
30
60
|
let auditLog = {};
|
|
@@ -190,6 +220,7 @@ function Make(Spec) {
|
|
|
190
220
|
export {
|
|
191
221
|
auditStatusSchema,
|
|
192
222
|
auditRowSchema,
|
|
223
|
+
receiveResultToOutcome,
|
|
193
224
|
Make,
|
|
194
225
|
}
|
|
195
226
|
/* Not a pure module */
|