@reventlessdev/reventless-aws 3.0.0-alpha.418 → 3.0.0-alpha.419
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 +7 -0
- package/package.json +9 -9
- package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res +6 -2
- package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res.mjs +6 -2
- package/src/adapter/Runtime/StateViewSliceEntryPoint_Ops.res +39 -8
- package/src/adapter/Runtime/StateViewSliceEntryPoint_Ops.res.mjs +31 -6
- package/tests/AutomationSliceEntryPoint_OpsTest.res +1 -1
- package/tests/AutomationSliceEntryPoint_OpsTest.res.mjs +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
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.419 (2026-11-01)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **core:** a command's outcome, the flow through automations, and each view change are told ([dcaeed2](https://github.com/ReventlessDev/reventless-core/commit/dcaeed2fabe2047a21797b459f2931618474dec3))
|
|
11
|
+
|
|
12
|
+
|
|
6
13
|
# 3.0.0-alpha.418 (2026-11-01)
|
|
7
14
|
|
|
8
15
|
**Note:** Version bump only for package @reventlessdev/reventless-aws
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reventlessdev/reventless-aws",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.419",
|
|
4
4
|
"description": "AWS adapters for Reventless",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"bin": {
|
|
@@ -22,19 +22,19 @@
|
|
|
22
22
|
"sury": "11.0.0",
|
|
23
23
|
"uuid": "^13.0.0",
|
|
24
24
|
"yaml": "^2.8.3",
|
|
25
|
-
"@reventlessdev/rescript-aws-sdk": "3.0.0-alpha.
|
|
25
|
+
"@reventlessdev/rescript-aws-sdk": "3.0.0-alpha.38",
|
|
26
26
|
"@reventlessdev/rescript-effect": "1.0.0-alpha.1",
|
|
27
27
|
"@reventlessdev/rescript-jest": "1.0.0-alpha.13",
|
|
28
|
-
"@reventlessdev/rescript-node": "2.0.0-alpha.
|
|
29
|
-
"@reventlessdev/rescript-pulumi-aws": "3.0.0-alpha.
|
|
28
|
+
"@reventlessdev/rescript-node": "2.0.0-alpha.25",
|
|
29
|
+
"@reventlessdev/rescript-pulumi-aws": "3.0.0-alpha.38",
|
|
30
30
|
"@reventlessdev/rescript-pulumi-pulumi": "3.0.0-alpha.0",
|
|
31
|
+
"@reventlessdev/rescript-web": "1.0.0-alpha.8",
|
|
31
32
|
"@reventlessdev/rescript-uuid": "2.0.0-alpha.1",
|
|
32
|
-
"@reventlessdev/reventless-core": "3.0.0-alpha.
|
|
33
|
-
"@reventlessdev/reventless-infra": "3.0.0-alpha.220",
|
|
34
|
-
"@reventlessdev/reventless-postgres": "3.0.0-alpha.189",
|
|
33
|
+
"@reventlessdev/reventless-core": "3.0.0-alpha.326",
|
|
35
34
|
"@reventlessdev/reventless-interop": "3.0.0-alpha.42",
|
|
36
|
-
"@reventlessdev/
|
|
37
|
-
"@reventlessdev/reventless-
|
|
35
|
+
"@reventlessdev/reventless-postgres": "3.0.0-alpha.190",
|
|
36
|
+
"@reventlessdev/reventless-infra": "3.0.0-alpha.221",
|
|
37
|
+
"@reventlessdev/reventless-spec": "3.0.0-alpha.192"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"rescript": "12.3.1",
|
|
@@ -539,7 +539,7 @@ let makeOutboundJsonEventsHandler = (
|
|
|
539
539
|
->Option.getOr("")
|
|
540
540
|
let (eventType, dataDict) = rawEvent->ReventlessCore.Message.splitMessage
|
|
541
541
|
switch decoder.decode(~eventType, ~data=dataDict) {
|
|
542
|
-
| Some(event) => [(sourceId, event)]
|
|
542
|
+
| Some(event) => [(sourceId, event, ReventlessCore.Message.metaOfEnvelope(envelope))]
|
|
543
543
|
| None => []
|
|
544
544
|
}
|
|
545
545
|
})
|
|
@@ -549,7 +549,11 @@ let makeOutboundJsonEventsHandler = (
|
|
|
549
549
|
->Effect.flatMap(events =>
|
|
550
550
|
Effect.promise(async () => {
|
|
551
551
|
await loadTodoItems()
|
|
552
|
-
await callback.phase1(
|
|
552
|
+
await callback.phase1(
|
|
553
|
+
events->Array.map(((sourceId, event, _)) => (sourceId, event)),
|
|
554
|
+
~metas=events->Array.map(((_, _, meta)) => meta),
|
|
555
|
+
~capabilities=capabilities(),
|
|
556
|
+
)
|
|
553
557
|
await syncTodoItems()
|
|
554
558
|
await callback.phase2(publishJsons, ~capabilities=capabilities())
|
|
555
559
|
await syncTodoItems()
|
|
@@ -323,14 +323,18 @@ function makeOutboundJsonEventsHandler(consumedEventSchema, callback, publishJso
|
|
|
323
323
|
if (event !== undefined) {
|
|
324
324
|
return [[
|
|
325
325
|
sourceId,
|
|
326
|
-
Primitive_option.valFromOption(event)
|
|
326
|
+
Primitive_option.valFromOption(event),
|
|
327
|
+
Message$ReventlessCore.metaOfEnvelope(envelope)
|
|
327
328
|
]];
|
|
328
329
|
} else {
|
|
329
330
|
return [];
|
|
330
331
|
}
|
|
331
332
|
})), events => Stream$1.fromIterable(events))), events => Effect.promise(async () => {
|
|
332
333
|
await loadTodoItems();
|
|
333
|
-
await callback.phase1(events
|
|
334
|
+
await callback.phase1(events.map(param => [
|
|
335
|
+
param[0],
|
|
336
|
+
param[1]
|
|
337
|
+
]), events.map(param => param[2]), capabilities());
|
|
334
338
|
await syncTodoItems();
|
|
335
339
|
await callback.phase2(publishJsons, capabilities());
|
|
336
340
|
return await syncTodoItems();
|
|
@@ -126,6 +126,20 @@ let decodeEnvelope = (json: JSON.t): envelope<'event> => {
|
|
|
126
126
|
|
|
127
127
|
let exnMessage = StreamRoutedEntryPoint_Ops.exnMessage
|
|
128
128
|
|
|
129
|
+
// The event an envelope carries, as the source of the rows its actions change.
|
|
130
|
+
// Read off the JSON, like `producerTime`: an envelope without a meta yields none.
|
|
131
|
+
let sourcesOf = (json: JSON.t): array<ReventlessCore.Projection.changeSource> => {
|
|
132
|
+
let fields = json->JSON.Decode.object->Option.getOr(Dict.make())
|
|
133
|
+
let meta = fields->Dict.get("meta")->Option.flatMap(JSON.Decode.object)
|
|
134
|
+
let string = (d, k) => d->Option.flatMap(d => d->Dict.get(k))->Option.flatMap(JSON.Decode.string)
|
|
135
|
+
switch string(meta, "msgId") {
|
|
136
|
+
| Some(msgId) =>
|
|
137
|
+
let (entityId, entityType) = ReventlessCore.ViewChange.entityOfEnvelope(fields)
|
|
138
|
+
[{msgId, correlationId: ?string(meta, "correlationId"), ?entityId, ?entityType}]
|
|
139
|
+
| None => []
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
129
143
|
// The typed core of buildJsonEventsHandler: decode each envelope, parse the
|
|
130
144
|
// event against the slice's consumed-event schema, project, and run every
|
|
131
145
|
// resulting action against the view table. A decode failure logs and yields no
|
|
@@ -140,7 +154,13 @@ let makeJsonEventsHandler = (
|
|
|
140
154
|
~queryDbOps: ReventlessCore.QueryDb_Adapter.operations,
|
|
141
155
|
~subIdConfig: option<Reventless.ReadModel.subIdConfig<JSON.t>>,
|
|
142
156
|
~stateSchema: option<S.t<unknown>>,
|
|
143
|
-
): ReventlessCore.EventCollector.jsonEventsHandler =>
|
|
157
|
+
): ReventlessCore.EventCollector.jsonEventsHandler => {
|
|
158
|
+
// Each row the events change is logged; the states are already JSON.
|
|
159
|
+
let onChange = ReventlessCore.ViewChange.reporter(
|
|
160
|
+
~comp=sliceName,
|
|
161
|
+
~view=sliceName,
|
|
162
|
+
~stateToJson=state => state,
|
|
163
|
+
)
|
|
144
164
|
stream =>
|
|
145
165
|
stream
|
|
146
166
|
->Stream.mapEffect(json =>
|
|
@@ -155,11 +175,14 @@ let makeJsonEventsHandler = (
|
|
|
155
175
|
// The deployed slice assembles JSON-level operations rather than going
|
|
156
176
|
// through the typed rewrite, so the trail is appended here — with this
|
|
157
177
|
// envelope's own time, which the apply below no longer has.
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
178
|
+
let sources = sourcesOf(json)
|
|
179
|
+
let actions =
|
|
180
|
+
producerTime === ""
|
|
181
|
+
? actions
|
|
182
|
+
: actions->Array.map(
|
|
183
|
+
ReventlessCore.Projection.rewriteJsonAction(_, ~at=producerTime, ~stateSchema),
|
|
184
|
+
)
|
|
185
|
+
actions->Array.map(action => (action, sources))
|
|
163
186
|
} catch {
|
|
164
187
|
| exn =>
|
|
165
188
|
StreamRoutedEntryPoint_Ops.logError(
|
|
@@ -171,7 +194,7 @@ let makeJsonEventsHandler = (
|
|
|
171
194
|
)
|
|
172
195
|
)
|
|
173
196
|
->Stream.flatMap(actions => Stream.fromIterable(actions))
|
|
174
|
-
->Stream.runForEach(action =>
|
|
197
|
+
->Stream.runForEach(((action, sources)) =>
|
|
175
198
|
// Thread the slice's `subIdConfig` (generated from `@subId`) so
|
|
176
199
|
// sub-id-dependent actions like `UpdateMultiState` can resolve the sort
|
|
177
200
|
// key. Dropping it here made every such action hit the
|
|
@@ -181,9 +204,17 @@ let makeJsonEventsHandler = (
|
|
|
181
204
|
// actions. `~comp` is the slice's spec name — attribution for
|
|
182
205
|
// Projection.handleAction's debug-lazy action log.
|
|
183
206
|
Effect.promise(() =>
|
|
184
|
-
ReventlessCore.Projection.handleAction(
|
|
207
|
+
ReventlessCore.Projection.handleAction(
|
|
208
|
+
~comp=sliceName,
|
|
209
|
+
~sources,
|
|
210
|
+
~onChange,
|
|
211
|
+
action,
|
|
212
|
+
queryDbOps,
|
|
213
|
+
subIdConfig,
|
|
214
|
+
)
|
|
185
215
|
)->Effect.map(_ => ())
|
|
186
216
|
)
|
|
217
|
+
}
|
|
187
218
|
|
|
188
219
|
// ── Handler assembly (called by the shell per HANDLER_CONFIG entry) ─────────
|
|
189
220
|
// `sliceModules` types the shell's reads off the two dynamically imported
|
|
@@ -8,6 +8,7 @@ import * as Stream from "effect/Stream";
|
|
|
8
8
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
9
9
|
import * as Util_Sury$Reventless from "@reventlessdev/reventless-spec/src/util/Util_Sury.res.mjs";
|
|
10
10
|
import * as Projection$ReventlessCore from "@reventlessdev/reventless-core/src/Projection.res.mjs";
|
|
11
|
+
import * as ViewChange$ReventlessCore from "@reventlessdev/reventless-core/src/ViewChange.res.mjs";
|
|
11
12
|
import * as ProjectionEntryPoint_Ops$ReventlessAws from "./ProjectionEntryPoint_Ops.res.mjs";
|
|
12
13
|
import * as StreamRoutedEntryPoint_Ops$ReventlessAws from "./StreamRoutedEntryPoint_Ops.res.mjs";
|
|
13
14
|
|
|
@@ -64,7 +65,25 @@ function decodeEnvelope(json) {
|
|
|
64
65
|
};
|
|
65
66
|
}
|
|
66
67
|
|
|
68
|
+
function sourcesOf(json) {
|
|
69
|
+
let fields = Stdlib_Option.getOr(Stdlib_JSON.Decode.object(json), {});
|
|
70
|
+
let meta = Stdlib_Option.flatMap(fields["meta"], Stdlib_JSON.Decode.object);
|
|
71
|
+
let string = (d, k) => Stdlib_Option.flatMap(Stdlib_Option.flatMap(d, d => d[k]), Stdlib_JSON.Decode.string);
|
|
72
|
+
let msgId = string(meta, "msgId");
|
|
73
|
+
if (msgId === undefined) {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
let match = ViewChange$ReventlessCore.entityOfEnvelope(fields);
|
|
77
|
+
return [{
|
|
78
|
+
msgId: msgId,
|
|
79
|
+
correlationId: string(meta, "correlationId"),
|
|
80
|
+
entityId: match[0],
|
|
81
|
+
entityType: match[1]
|
|
82
|
+
}];
|
|
83
|
+
}
|
|
84
|
+
|
|
67
85
|
function makeJsonEventsHandler(sliceName, eventSchema, project, queryDbOps, subIdConfig, stateSchema) {
|
|
86
|
+
let onChange = ViewChange$ReventlessCore.reporter(sliceName, sliceName, state => state);
|
|
68
87
|
return stream => Stream.runForEach(Stream.flatMap(Stream.mapEffect(stream, json => Effect.sync(() => {
|
|
69
88
|
try {
|
|
70
89
|
let match = decodeEnvelope(json);
|
|
@@ -74,11 +93,12 @@ function makeJsonEventsHandler(sliceName, eventSchema, project, queryDbOps, subI
|
|
|
74
93
|
meta: match.meta,
|
|
75
94
|
recordedAt: match.recordedAt
|
|
76
95
|
});
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
96
|
+
let sources = sourcesOf(json);
|
|
97
|
+
let actions$1 = producerTime === "" ? actions : actions.map(__x => Projection$ReventlessCore.rewriteJsonAction(__x, producerTime, stateSchema));
|
|
98
|
+
return actions$1.map(action => [
|
|
99
|
+
action,
|
|
100
|
+
sources
|
|
101
|
+
]);
|
|
82
102
|
} catch (raw_exn) {
|
|
83
103
|
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
84
104
|
StreamRoutedEntryPoint_Ops$ReventlessAws.logError("failed to decode event", {
|
|
@@ -87,7 +107,11 @@ function makeJsonEventsHandler(sliceName, eventSchema, project, queryDbOps, subI
|
|
|
87
107
|
});
|
|
88
108
|
return [];
|
|
89
109
|
}
|
|
90
|
-
})), actions => Stream.fromIterable(actions)),
|
|
110
|
+
})), actions => Stream.fromIterable(actions)), param => {
|
|
111
|
+
let sources = param[1];
|
|
112
|
+
let action = param[0];
|
|
113
|
+
return Effect.map(Effect.promise(() => Projection$ReventlessCore.handleAction(sliceName, sources, onChange, action, queryDbOps, subIdConfig)), param => {});
|
|
114
|
+
});
|
|
91
115
|
}
|
|
92
116
|
|
|
93
117
|
function makeRegisteredHandler(entry, modules) {
|
|
@@ -106,6 +130,7 @@ export {
|
|
|
106
130
|
parseHandlerConfig,
|
|
107
131
|
decodeEnvelope,
|
|
108
132
|
exnMessage,
|
|
133
|
+
sourcesOf,
|
|
109
134
|
makeJsonEventsHandler,
|
|
110
135
|
makeRegisteredHandler,
|
|
111
136
|
}
|
|
@@ -388,7 +388,7 @@ describe("AutomationSliceEntryPoint_Ops.makeOutboundJsonEventsHandler", () => {
|
|
|
388
388
|
let received = ref([])
|
|
389
389
|
let callback: AutomationSliceEntryPoint_Ops.outboundCallback<outboundEvent> = {
|
|
390
390
|
todoItems: Dict.make(),
|
|
391
|
-
phase1: async (events, ~capabilities as _) => {
|
|
391
|
+
phase1: async (events, ~metas as _=?, ~capabilities as _) => {
|
|
392
392
|
received := events
|
|
393
393
|
steps->Array.push("phase1")
|
|
394
394
|
},
|
|
@@ -581,7 +581,7 @@ globalThis.describe("AutomationSliceEntryPoint_Ops.makeOutboundJsonEventsHandler
|
|
|
581
581
|
contents: []
|
|
582
582
|
};
|
|
583
583
|
let callback_todoItems = {};
|
|
584
|
-
let callback_phase1 = async (events, param) => {
|
|
584
|
+
let callback_phase1 = async (events, param, param$1) => {
|
|
585
585
|
received.contents = events;
|
|
586
586
|
steps.push("phase1");
|
|
587
587
|
};
|