@reventlessdev/reventless-infra 3.0.0-alpha.81

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 (73) hide show
  1. package/CHANGELOG.md +709 -0
  2. package/LICENSE +202 -0
  3. package/package.json +35 -0
  4. package/rescript.json +28 -0
  5. package/src/adapter/Adapter.res +88 -0
  6. package/src/adapter/Adapter.res.mjs +29 -0
  7. package/src/components/Aggregate.res +73 -0
  8. package/src/components/Aggregate.res.mjs +2 -0
  9. package/src/components/Api.res +124 -0
  10. package/src/components/Api.res.mjs +31 -0
  11. package/src/components/Api_Adapter.res +39 -0
  12. package/src/components/Api_Adapter.res.mjs +2 -0
  13. package/src/components/AutomationSlice.res +48 -0
  14. package/src/components/AutomationSlice.res.mjs +2 -0
  15. package/src/components/CommandGenerator.res +8 -0
  16. package/src/components/CommandGenerator.res.mjs +2 -0
  17. package/src/components/CommandTopic.res +70 -0
  18. package/src/components/CommandTopic.res.mjs +2 -0
  19. package/src/components/Component.js +56 -0
  20. package/src/components/Component.mjs +10 -0
  21. package/src/components/Component.res +90 -0
  22. package/src/components/Component.res.mjs +57 -0
  23. package/src/components/Component.resi +21 -0
  24. package/src/components/Counter.res +81 -0
  25. package/src/components/Counter.res.mjs +2 -0
  26. package/src/components/DcbEventLog.res +115 -0
  27. package/src/components/DcbEventLog.res.mjs +2 -0
  28. package/src/components/EventCollector.res +19 -0
  29. package/src/components/EventCollector.res.mjs +2 -0
  30. package/src/components/EventLog.res +24 -0
  31. package/src/components/EventLog.res.mjs +2 -0
  32. package/src/components/EventMapper.res +37 -0
  33. package/src/components/EventMapper.res.mjs +2 -0
  34. package/src/components/EventTopic.res +51 -0
  35. package/src/components/EventTopic.res.mjs +2 -0
  36. package/src/components/Extension.res +64 -0
  37. package/src/components/Extension.res.mjs +2 -0
  38. package/src/components/ExtensionPoint.res +62 -0
  39. package/src/components/ExtensionPoint.res.mjs +2 -0
  40. package/src/components/Heartbeat.res +7 -0
  41. package/src/components/Heartbeat.res.mjs +2 -0
  42. package/src/components/InboundTranslationSlice.res +41 -0
  43. package/src/components/InboundTranslationSlice.res.mjs +2 -0
  44. package/src/components/OutboundTranslationSlice.res +44 -0
  45. package/src/components/OutboundTranslationSlice.res.mjs +2 -0
  46. package/src/components/Plugin.res +84 -0
  47. package/src/components/Plugin.res.mjs +2 -0
  48. package/src/components/QueryDb.res +48 -0
  49. package/src/components/QueryDb.res.mjs +33 -0
  50. package/src/components/ReadModel.res +50 -0
  51. package/src/components/ReadModel.res.mjs +2 -0
  52. package/src/components/Scheduler.res +32 -0
  53. package/src/components/Scheduler.res.mjs +2 -0
  54. package/src/components/StateChangeSlice.res +45 -0
  55. package/src/components/StateChangeSlice.res.mjs +2 -0
  56. package/src/components/StateViewSlice.res +38 -0
  57. package/src/components/StateViewSlice.res.mjs +2 -0
  58. package/src/components/Task.res +89 -0
  59. package/src/components/Task.res.mjs +2 -0
  60. package/src/types/ExtensionMapping.res +448 -0
  61. package/src/types/ExtensionMapping.res.mjs +252 -0
  62. package/src/types/ExtensionPointMapping.res +303 -0
  63. package/src/types/ExtensionPointMapping.res.mjs +116 -0
  64. package/src/types/Message.res +3 -0
  65. package/src/types/Message.res.mjs +2 -0
  66. package/src/types/NoEventMappings.res +25 -0
  67. package/src/types/NoEventMappings.res.mjs +17 -0
  68. package/src/types/Platform.res +279 -0
  69. package/src/types/Platform.res.mjs +2 -0
  70. package/src/types/PluginExtensionPointSpec.res +43 -0
  71. package/src/types/PluginExtensionPointSpec.res.mjs +204 -0
  72. package/src/types/ResourceNaming.res +12 -0
  73. package/src/types/ResourceNaming.res.mjs +2 -0
@@ -0,0 +1,48 @@
1
+ /**
2
+ Deploy-time outputs produced when an `AutomationSlice` is provisioned.
3
+
4
+ - `resources` — the underlying infrastructure (e.g. SQS subscription)
5
+ - `queryDb` — the DynamoDB table for the TODO list
6
+ */
7
+ type outputs = {
8
+ resources: array<Adapter.resource>,
9
+ queryDb: QueryDb.outputs,
10
+ }
11
+
12
+ /**
13
+ Runtime operations exposed by an `AutomationSlice` component.
14
+
15
+ - `enqueueEvent` — push events into the slice's projection queue
16
+ - `processPending` — manually trigger Phase 2 (useful in tests and for heartbeat)
17
+ */
18
+ type operations = {
19
+ enqueueEvent: EventCollector.enqueueEvent,
20
+ processPending: unit => promise<unit>,
21
+ }
22
+
23
+ /**
24
+ Module type produced by `Platform.AutomationSlice.Make(Spec)`.
25
+
26
+ @example
27
+ ```rescript
28
+ module ShipOrderSlice = Platform.AutomationSlice.Make(ShipOrder)
29
+ let slice = ShipOrderSlice.make(~dcbEventLog=log, ~publishJsons=publishJsonsOutput)
30
+ ```
31
+ */
32
+ type t
33
+
34
+ module type T = {
35
+ module Spec: Reventless.AutomationSlice.Spec
36
+ module Automation: Reventless.AutomationSlice.Automation with module Spec := Spec
37
+ type component = Component.t<t, outputs, operations>
38
+ let queryDbName: string
39
+ /** Names of all sources this slice consumes (deduplicated). Used by
40
+ `Plugin_Builder` for the source-name fail-fast assembly check. */
41
+ let sourceNames: array<string>
42
+ let make: (
43
+ ~allEventTopics: EventTopic.allOutputs,
44
+ ~publishJsons: Pulumi.Output.t<CommandTopic.publishJsons>,
45
+ ~context: Reventless.AutomationSlice.context,
46
+ ~opts: Pulumi.ComponentResource.options=?,
47
+ ) => component
48
+ }
@@ -0,0 +1,2 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Deploy-time outputs produced when a `CommandGenerator` is provisioned.
3
+ *
4
+ * The command generator is an internal component that translates raw JSON
5
+ * command messages from the command topic into typed domain commands and
6
+ * dispatches them to the aggregate handler.
7
+ */
8
+ type outputs = {resources: array<Adapter.resource>}
@@ -0,0 +1,2 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
@@ -0,0 +1,70 @@
1
+ /**
2
+ Module type for an aggregate's command topic specification.
3
+
4
+ `CommandTopic.T` is used by the framework to identify the command channel
5
+ (e.g. an SQS FIFO queue) and validate that published commands match the
6
+ aggregate's command schema.
7
+ */
8
+ module type T = {
9
+ module Id: Reventless.Id.T
10
+
11
+ /** Logical name of the aggregate or component owning this command topic. */
12
+ let name: string
13
+
14
+ /** The command type published to this topic. Must carry `@schema` for serialization. */
15
+ @schema
16
+ type command
17
+ }
18
+
19
+ /**
20
+ Deploy-time outputs produced when a `CommandTopic` is provisioned.
21
+ Contains the underlying queue / messaging infrastructure resources.
22
+ */
23
+ type outputs = {resources: array<Adapter.resource>}
24
+
25
+ /** A dictionary of command topic outputs keyed by aggregate name. */
26
+ type allOutputs = dict<outputs>
27
+
28
+ /**
29
+ Publishes an array of serialized command envelopes to this command topic.
30
+
31
+ Commands are batched for efficiency. Each `Message.commandJson` carries
32
+ the aggregate ID, metadata, raw JSON payload, and optional delivery delay.
33
+
34
+ @example
35
+ ```rescript
36
+ await ops.publishJsons([{id: "cat-1", meta, commandJson: json}])
37
+ ```
38
+ */
39
+ type publishJsons = array<Reventless.Message.commandJson> => promise<unit>
40
+
41
+ /**
42
+ Publishes a stream of serialized command envelopes as an `Effect.t`.
43
+ Use this for high-throughput or streaming command pipelines.
44
+ */
45
+ type publishJsonsStream = Stream.t<Reventless.Message.commandJson, string, unit> => Effect.t<unit, string, unit>
46
+
47
+ /**
48
+ A command together with an idempotency reference string.
49
+
50
+ Used by the extension point runtime to track which commands have already
51
+ been processed and avoid duplicate dispatch.
52
+ */
53
+ type topicItem<'command> = {
54
+ command: 'command,
55
+ reference: string,
56
+ }
57
+
58
+ /**
59
+ A handler that processes a stream of typed topic items and returns an Effect
60
+ producing per-item results.
61
+
62
+ `commandsHandler<JSON.t>` is the JSON-level variant used for routing;
63
+ `commandsHandler<Reventless.Message.command'<Id.t, command>>` is the decoded variant
64
+ used by aggregate and slice callbacks.
65
+ */
66
+ type commandsHandler<'command> = Stream.t<topicItem<'command>, string, unit> => Effect.t<
67
+ array<result<string, string>>,
68
+ string,
69
+ unit,
70
+ >
@@ -0,0 +1,2 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
@@ -0,0 +1,56 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ 'use strict';
3
+
4
+ let ComponentMjs = require("./Component.mjs").default;
5
+
6
+ let _outputsStore = new WeakMap();
7
+
8
+ let _operationsStore = new WeakMap();
9
+
10
+ function outputs(self) {
11
+ return _outputsStore.get(self);
12
+ }
13
+
14
+ function wrappedOutputs(component) {
15
+ return component.apply(outputs);
16
+ }
17
+
18
+ function setOperations(self, ops) {
19
+ _operationsStore.set(self, ops);
20
+ }
21
+
22
+ function operations(self) {
23
+ return _operationsStore.get(self);
24
+ }
25
+
26
+ function make(prim0, prim1, prim2, prim3) {
27
+ return new ComponentMjs(prim0, prim1, prim2, prim3);
28
+ }
29
+
30
+ function registerOutputs(self, outputs) {
31
+ return self.registerOutputs(outputs);
32
+ }
33
+
34
+ function setOutputs(self, outputs) {
35
+ _outputsStore.set(self, outputs);
36
+ return self.registerOutputs({});
37
+ }
38
+
39
+ function toPulumiResource(prim) {
40
+ return prim;
41
+ }
42
+
43
+ function fromPulumiResource(prim) {
44
+ return prim;
45
+ }
46
+
47
+ exports.registerOutputs = registerOutputs;
48
+ exports.setOutputs = setOutputs;
49
+ exports.outputs = outputs;
50
+ exports.wrappedOutputs = wrappedOutputs;
51
+ exports.setOperations = setOperations;
52
+ exports.operations = operations;
53
+ exports.toPulumiResource = toPulumiResource;
54
+ exports.fromPulumiResource = fromPulumiResource;
55
+ exports.make = make;
56
+ /* _outputsStore Not a pure module */
@@ -0,0 +1,10 @@
1
+ import * as pulumi from "@pulumi/pulumi";
2
+
3
+ class Component extends pulumi.ComponentResource {
4
+ constructor(componentType, name, construct, opts, param1, param2, param3) {
5
+ super("reventless:" + componentType, name, {}, opts);
6
+ construct(this, name, param1, param2, param3);
7
+ };
8
+ }
9
+
10
+ export default Component;
@@ -0,0 +1,90 @@
1
+ /**
2
+ A Reventless component — a typed wrapper around a Pulumi `ComponentResource`.
3
+
4
+ Type parameters:
5
+ - `'component` — the concrete component module type (e.g. `Aggregate.T`)
6
+ - `'outputs` — the deploy-time outputs record (infrastructure references)
7
+ - `'operations` — the runtime operations record (async functions for Lambda handlers)
8
+
9
+ Components are created at deploy time by a `Make` functor and carry two payloads:
10
+ - `outputs` — immediately available infrastructure references (queue ARNs, table names…)
11
+ - `operations` — an `Output.t`-wrapped set of async functions injected at runtime
12
+ */
13
+ type t<'component, 'outputs, 'operations>
14
+
15
+ // Side-channel storage for outputs and operations.
16
+ // Using WeakMaps keyed by the component instance prevents Pulumi from
17
+ // serializing internal data (sury schemas, Spec modules) as ComponentResource
18
+ // properties in `pulumi stack output`.
19
+ type weakMap
20
+ @new external _makeWeakMap: unit => weakMap = "WeakMap"
21
+ @send external _get: (weakMap, t<'c, 'o, 'p>) => 'v = "get"
22
+ @send external _set: (weakMap, t<'c, 'o, 'p>, 'v) => unit = "set"
23
+
24
+ let _outputsStore = _makeWeakMap()
25
+ let _operationsStore = _makeWeakMap()
26
+
27
+ /** Access the deploy-time outputs record for this component. */
28
+ let outputs = (self: t<'component, 'outputs, 'operations>): 'outputs =>
29
+ _outputsStore->_get(self)
30
+
31
+ /**
32
+ Access the deploy-time outputs wrapped in an `Output.t` (resolved asynchronously).
33
+ Useful when you need to chain outputs into another `Output.apply`.
34
+ */
35
+ let wrappedOutputs = component => component->Pulumi.Output.apply(component => component->outputs)
36
+
37
+ let setOperations = (
38
+ self: t<'component, 'outputs, 'operations>,
39
+ ops: Pulumi.Output.t<'operations>,
40
+ ): unit => _operationsStore->_set(self, ops)
41
+
42
+ /**
43
+ Access the runtime operations for this component.
44
+
45
+ Returns an `Output.t` that resolves to the runtime operations record once the
46
+ underlying infrastructure values are known. Use `TestRunner.resolve` in tests.
47
+ */
48
+ let operations = (self: t<'component, 'outputs, 'operations>): Pulumi.Output.t<'operations> =>
49
+ _operationsStore->_get(self)
50
+
51
+ /** Cast to a plain Pulumi resource (e.g. to pass to `~opts` as a parent). */
52
+ external toPulumiResource: t<'component, 'outputs, 'operations> => Pulumi.Resource.t = "%identity"
53
+ external fromPulumiResource: Pulumi.Resource.t => t<'component, 'outputs, 'operations> = "%identity"
54
+
55
+ type constructed
56
+
57
+ /**
58
+ Create a new Reventless component backed by a Pulumi `ComponentResource`.
59
+
60
+ - `componentType` — Pulumi type token (e.g. `"reventless:index:Aggregate"`)
61
+ - `name` — unique Pulumi resource name
62
+ - `construct` — a callback that builds child resources; called by the Pulumi runtime
63
+ - `opts` — optional Pulumi resource options (parent, provider, etc.)
64
+ */
65
+ @module("./Component.mjs") @new
66
+ external make: (
67
+ ~componentType: string,
68
+ ~name: string,
69
+ ~construct: 'construct,
70
+ ~opts: option<Pulumi.ComponentResource.options>,
71
+ ) => t<'component, 'outputs, 'operations> = "default"
72
+
73
+ @send
74
+ external _registerOutputs: (t<'component, 'outputs, 'operations>, 'a) => constructed =
75
+ "registerOutputs"
76
+
77
+ /** Register the component's outputs with Pulumi to mark it as constructed. */
78
+ let registerOutputs = (self, outputs) => self->_registerOutputs(outputs)
79
+
80
+ /**
81
+ Set the component's outputs and mark the component as constructed.
82
+
83
+ Outputs are stored in a WeakMap (not on the ComponentResource instance) to prevent
84
+ Pulumi from serializing internal data in `pulumi stack output`. Cross-stack data
85
+ is exported explicitly via `Pulumi.export`.
86
+ */
87
+ let setOutputs = (self, outputs) => {
88
+ _outputsStore->_set(self, outputs)
89
+ self->_registerOutputs(JSON.Encode.object(Dict.make()))
90
+ }
@@ -0,0 +1,57 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import ComponentMjs from "./Component.mjs";
4
+
5
+ let _outputsStore = new WeakMap();
6
+
7
+ let _operationsStore = new WeakMap();
8
+
9
+ function outputs(self) {
10
+ return _outputsStore.get(self);
11
+ }
12
+
13
+ function wrappedOutputs(component) {
14
+ return component.apply(outputs);
15
+ }
16
+
17
+ function setOperations(self, ops) {
18
+ _operationsStore.set(self, ops);
19
+ }
20
+
21
+ function operations(self) {
22
+ return _operationsStore.get(self);
23
+ }
24
+
25
+ function make(prim0, prim1, prim2, prim3) {
26
+ return new ComponentMjs(prim0, prim1, prim2, prim3);
27
+ }
28
+
29
+ function registerOutputs(self, outputs) {
30
+ return self.registerOutputs(outputs);
31
+ }
32
+
33
+ function setOutputs(self, outputs) {
34
+ _outputsStore.set(self, outputs);
35
+ return self.registerOutputs({});
36
+ }
37
+
38
+ function toPulumiResource(prim) {
39
+ return prim;
40
+ }
41
+
42
+ function fromPulumiResource(prim) {
43
+ return prim;
44
+ }
45
+
46
+ export {
47
+ registerOutputs,
48
+ setOutputs,
49
+ outputs,
50
+ wrappedOutputs,
51
+ setOperations,
52
+ operations,
53
+ toPulumiResource,
54
+ fromPulumiResource,
55
+ make,
56
+ }
57
+ /* _outputsStore Not a pure module */
@@ -0,0 +1,21 @@
1
+ type t<'component, 'outputs, 'operations>
2
+
3
+ type constructed
4
+ let registerOutputs: (t<'component, 'outputs, 'operations>, 'outputs) => constructed
5
+ let setOutputs: (t<'component, 'outputs, 'operations>, 'outputs) => constructed
6
+ let outputs: t<'component, 'outputs, 'operations> => 'outputs
7
+ let wrappedOutputs: Pulumi.Output.t<t<'component, 'outputs, 'operations>> => Pulumi.Output.t<
8
+ 'outputs,
9
+ >
10
+ let setOperations: (t<'component, 'outputs, 'operations>, Pulumi.Output.t<'operations>) => unit
11
+ let operations: t<'component, 'outputs, 'operations> => Pulumi.Output.t<'operations>
12
+
13
+ let toPulumiResource: t<'component, 'outputs, 'operations> => Pulumi.Resource.t
14
+ let fromPulumiResource: Pulumi.Resource.t => t<'component, 'outputs, 'operations>
15
+
16
+ let make: (
17
+ ~componentType: string,
18
+ ~name: string,
19
+ ~construct: 'construct,
20
+ ~opts: option<Pulumi.ComponentResource.options>,
21
+ ) => t<'component, 'outputs, 'operations>
@@ -0,0 +1,81 @@
1
+ /**
2
+ A single counter increment item.
3
+
4
+ - `counterId` — which counter to increment
5
+ - `reference` — idempotency key (e.g. the triggering event's message ID)
6
+ - `inc` — how much to increment by (usually 1)
7
+ */
8
+ type countItem = {
9
+ counterId: Reventless.Counter.counterId,
10
+ reference: Reventless.Counter.reference,
11
+ inc: int,
12
+ }
13
+
14
+ /**
15
+ A counter threshold target with an idempotency reference.
16
+
17
+ Used by `addToCounterTarget` to register that a target has been claimed by
18
+ a specific `reference`, preventing duplicate threshold triggers.
19
+ */
20
+ type counterTargetRef = {
21
+ counterId: Reventless.Counter.counterId,
22
+ target: int,
23
+ targetRef: Reventless.Counter.reference,
24
+ }
25
+
26
+ /**
27
+ Deploy-time outputs produced when a `Counter` component is provisioned.
28
+
29
+ - `referencesDb` — tracks which references have already been counted (dedup)
30
+ - `countsDb` — stores the current count per `counterId`
31
+ */
32
+ type outputs = {referencesDb: QueryDb.outputs, countsDb: QueryDb.outputs}
33
+
34
+ /** Increments one or more counters. Each item is applied idempotently via its `reference`. */
35
+ type count = array<countItem> => promise<unit>
36
+
37
+ /**
38
+ Registers a threshold target, claiming it with a `targetRef`.
39
+ When the count reaches `target`, the event mapping's `AddToCounterTarget` action fires.
40
+ */
41
+ type addToCounterTarget = counterTargetRef => promise<unit>
42
+
43
+ /**
44
+ Runtime operations exposed by a `Counter` component.
45
+ Available inside event mapping `map` functions via the injected `operations` record.
46
+ */
47
+ type operations = {count: count, addToCounterTarget: addToCounterTarget}
48
+
49
+ /**
50
+ Processes a stream of raw event JSON values to extract and apply counter increments.
51
+ Used internally by the counter's Lambda handler.
52
+ */
53
+ type jsonEventsHandler = Stream.t<JSON.t, string, unit> => Effect.t<unit, string, unit>
54
+
55
+ /**
56
+ Module type for a `Counter` component.
57
+
58
+ The `Counter` component maintains named reference-counted thresholds.
59
+ When a count crosses a configured threshold, the associated event mapping
60
+ fires a command to the target aggregate.
61
+ */
62
+ module type T = {
63
+ type component
64
+ let make: (
65
+ ~name: string,
66
+ ~jsonEventsHandler: jsonEventsHandler,
67
+ ~ttl: int=?,
68
+ /** ESM specifier of the counter target's spec module. Used by bundling
69
+ adapters that load callbacks via `import()`; other adapters ignore it. */
70
+ ~specModulePath: string=?,
71
+ /** ESM specifier of the counter target's mappings module. Used by bundling
72
+ adapters that load callbacks via `import()`; other adapters ignore it. */
73
+ ~mappingsModulePath: string=?,
74
+ /** Publish-channel address of the aggregate this counter dispatches commands
75
+ to. Used by bundling adapters; other adapters ignore it. */
76
+ ~publishChannelId: Pulumi.Output.t<string>=?,
77
+ ~opts: Pulumi.ComponentResource.options=?,
78
+ ) => component
79
+ let outputs: component => outputs
80
+ let operations: component => Pulumi.Output.t<operations>
81
+ }
@@ -0,0 +1,2 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
@@ -0,0 +1,115 @@
1
+ /**
2
+ Deploy-time outputs produced when a `DcbEventLog` is provisioned.
3
+
4
+ - `resources` — the underlying storage infrastructure (e.g. DynamoDB table)
5
+ - `eventTopic` — the SNS topic for downstream subscribers (state view slices)
6
+ */
7
+ type outputs = {resources: array<Adapter.resource>, eventTopic: EventTopic.outputs}
8
+
9
+ /**
10
+ A raw event ready to be stored in the DCB log.
11
+ Produced by slice callbacks after encoding with their eventSchema.
12
+
13
+ `meta` is the envelope metadata for this event (causation, correlation, tracing).
14
+ Slice callbacks derive it from the triggering message's context.
15
+ */
16
+ type rawEvent = {
17
+ eventType: string,
18
+ data: JSON.t,
19
+ tags: array<Reventless.DcbTag.tag>,
20
+ meta: Reventless.Message.meta,
21
+ }
22
+
23
+ /**
24
+ A raw event read from the DCB log at a known position.
25
+ Consumed by slice callbacks for decoding with their consumedEventSchema.
26
+
27
+ `meta` is the envelope metadata that was written at append time.
28
+ `recordedAt` is the storage timestamp, set by the storage adapter at append.
29
+ */
30
+ type rawSequencedEvent = {
31
+ position: Reventless.DcbTag.sequencePosition,
32
+ eventType: string,
33
+ data: JSON.t,
34
+ tags: array<Reventless.DcbTag.tag>,
35
+ meta: Reventless.Message.meta,
36
+ recordedAt: string,
37
+ }
38
+
39
+ /**
40
+ The result of a DCB `read` operation.
41
+
42
+ - `events` — the matching events in sequence order
43
+ - `headPosition` — the sequence position of the last event read (use as the
44
+ `after` cursor in a subsequent `appendCondition` to detect conflicts)
45
+ */
46
+ type readResult = {
47
+ events: array<rawSequencedEvent>,
48
+ headPosition?: Reventless.DcbTag.sequencePosition,
49
+ }
50
+
51
+ /**
52
+ Reads events from the DCB log matching the given query.
53
+
54
+ - `~query` — content-based filter (event types + tags)
55
+ - `~after` — optional cursor; only events after this position are returned
56
+ */
57
+ type read = (
58
+ ~query: Reventless.DcbTag.query,
59
+ ~after: Reventless.DcbTag.sequencePosition=?,
60
+ ) => promise<readResult>
61
+
62
+ /**
63
+ Appends raw events to the DCB log with optional optimistic-concurrency checking.
64
+
65
+ Returns `Ok(position)` on success or `Error(reason)` if the append condition
66
+ was violated (i.e. the log was modified since `condition.after`).
67
+ */
68
+ type append = (
69
+ array<rawEvent>,
70
+ ~condition: Reventless.DcbTag.appendCondition=?,
71
+ ) => promise<result<Reventless.DcbTag.sequencePosition, string>>
72
+
73
+ /**
74
+ Streams events from the DCB log matching the given query.
75
+ Use for large result sets that should not be loaded into memory at once.
76
+ */
77
+ type readStream = (
78
+ ~query: Reventless.DcbTag.query,
79
+ ~after: Reventless.DcbTag.sequencePosition=?,
80
+ /** Opt into strongly-consistent single-tag reads. Defaults to eventually
81
+ consistent: a stale read can only cause a rejected append (then a retry),
82
+ never a wrong write, because the append fence is always evaluated strongly.
83
+ The slice callback sets this on retries (eventual-first, strong-on-retry). */
84
+ ~strongConsistency: bool=?,
85
+ ) => Stream.t<rawSequencedEvent, string, unit>
86
+
87
+ /**
88
+ Appends a stream of raw events to the DCB log as an `Effect.t`.
89
+ Use for high-throughput batch imports.
90
+ */
91
+ type appendStream = (
92
+ Stream.t<rawEvent, string, unit>,
93
+ ~condition: Reventless.DcbTag.appendCondition=?,
94
+ ) => Effect.t<result<Reventless.DcbTag.sequencePosition, string>, string, unit>
95
+
96
+ /**
97
+ Runtime operations exposed by a `DcbEventLog` component.
98
+ Works with raw events — encode/decode is handled by each slice's callback.
99
+
100
+ Obtained via `Component.operations(dcbEventLog)`. Available inside Lambda handlers.
101
+ */
102
+ type operations = {
103
+ read: read,
104
+ append: append,
105
+ readStream: readStream,
106
+ appendStream: appendStream,
107
+ }
108
+
109
+ type t
110
+ type component = Component.t<t, outputs, operations>
111
+
112
+ module type T = {
113
+ type component = component
114
+ let make: (~name: string, ~indexes: array<string>=?, ~opts: Pulumi.ComponentResource.options=?) => component
115
+ }
@@ -0,0 +1,2 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Enqueues an event for processing by a downstream component (e.g. a read model).
3
+ *
4
+ * - `delay` — delivery delay in seconds (0 for immediate delivery)
5
+ * - `id` — the aggregate ID string the event belongs to
6
+ * - `message` — the serialized event payload (JSON string)
7
+ *
8
+ * This function is exposed by read model `operations` so that the aggregate
9
+ * runtime can push events without knowing the read model's infrastructure details.
10
+ */
11
+ type enqueueEvent = (/* ~delay: */ int, /* ~id: */ string, /* ~message: */ string) => promise<unit>
12
+
13
+ /**
14
+ * Deploy-time outputs produced when an `EventCollector` is provisioned.
15
+ *
16
+ * An `EventCollector` is the inbound queue of a read model — events are collected
17
+ * here and then processed in order by the read model's projection function.
18
+ */
19
+ type outputs = {name: string, resources: array<Adapter.resource>}
@@ -0,0 +1,2 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
@@ -0,0 +1,24 @@
1
+ /**
2
+ Module type for an aggregate's event log specification.
3
+
4
+ `EventLog.T` is used by the framework to configure the event storage backend
5
+ (e.g. a DynamoDB table) and the associated event topic for downstream subscribers.
6
+ */
7
+ module type T = {
8
+ module Id: Reventless.Id.T
9
+
10
+ /** Logical name of the aggregate / event stream (used as a table-name prefix). */
11
+ let name: string
12
+
13
+ /** The event type stored in this log. Must carry `@schema` for serialization. */
14
+ @schema
15
+ type event
16
+ }
17
+
18
+ /**
19
+ Deploy-time outputs produced when an `EventLog` is provisioned.
20
+
21
+ - `resources` — the underlying infrastructure resources (e.g. DynamoDB table)
22
+ - `eventTopic` — the event topic outputs for downstream subscribers
23
+ */
24
+ type outputs = {resources: array<Adapter.resource>, eventTopic: EventTopic.outputs}
@@ -0,0 +1,2 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
@@ -0,0 +1,37 @@
1
+ /**
2
+ Deploy-time outputs produced when an `EventMapper` is provisioned.
3
+
4
+ An `EventMapper` subscribes to an aggregate's event topic and routes events
5
+ to one or more target aggregate command topics, optionally via a `Counter`.
6
+ */
7
+ type outputs = {
8
+ name: string,
9
+ eventCollector: Pulumi.Output.t<EventCollector.outputs>,
10
+ counter?: Counter.outputs,
11
+ }
12
+
13
+ /**
14
+ A collection of `EventMapping.T` modules that route events from one aggregate
15
+ to commands on one or more target aggregates.
16
+
17
+ Pass a `Mappings` module to `Platform.Aggregate.Make` as the third argument.
18
+ Use `NoEventMappings.Make(TargetSpec)` when no routing is needed.
19
+
20
+ @example
21
+ ```rescript
22
+ // CatalogPlugin.res
23
+ module CategoryMappings: Mappings with module Target := CategoriesReadModel = {
24
+ module CategoryMappings = Mappings.Make(CategoriesReadModel)
25
+ module type Mapping = CategoryMappings.Mapping
26
+ let mappings = CategoriesProjections.mappings
27
+ }
28
+ ```
29
+ */
30
+ module type Mappings = {
31
+ module Target: Reventless.EventMapping.Target
32
+ module type Mapping = Reventless.EventMapping.T with module Target := Target
33
+ let moduleUrl: string
34
+ let mappings: array<module(Mapping)>
35
+ /** Optional counter component for threshold-based command triggers. */
36
+ let counter: option<module(Counter.T)>
37
+ }
@@ -0,0 +1,2 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */