@reventlessdev/reventless-infra 3.0.0-alpha.100

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 (78) hide show
  1. package/CHANGELOG.md +853 -0
  2. package/LICENSE +202 -0
  3. package/README.md +92 -0
  4. package/package.json +46 -0
  5. package/rescript.json +34 -0
  6. package/src/adapter/Adapter.res +88 -0
  7. package/src/adapter/Adapter.res.mjs +29 -0
  8. package/src/components/Aggregate.res +73 -0
  9. package/src/components/Aggregate.res.mjs +2 -0
  10. package/src/components/Api.res +120 -0
  11. package/src/components/Api.res.mjs +31 -0
  12. package/src/components/Api_Adapter.res +29 -0
  13. package/src/components/Api_Adapter.res.mjs +2 -0
  14. package/src/components/AutomationSlice.res +48 -0
  15. package/src/components/AutomationSlice.res.mjs +2 -0
  16. package/src/components/CommandGenerator.res +8 -0
  17. package/src/components/CommandGenerator.res.mjs +2 -0
  18. package/src/components/CommandTopic.res +70 -0
  19. package/src/components/CommandTopic.res.mjs +2 -0
  20. package/src/components/Component.js +56 -0
  21. package/src/components/Component.mjs +10 -0
  22. package/src/components/Component.res +90 -0
  23. package/src/components/Component.res.mjs +57 -0
  24. package/src/components/Component.resi +21 -0
  25. package/src/components/Counter.res +81 -0
  26. package/src/components/Counter.res.mjs +2 -0
  27. package/src/components/DcbEventLog.res +130 -0
  28. package/src/components/DcbEventLog.res.mjs +2 -0
  29. package/src/components/DeployBootstrap.res +83 -0
  30. package/src/components/DeployBootstrap.res.mjs +69 -0
  31. package/src/components/EventCollector.res +19 -0
  32. package/src/components/EventCollector.res.mjs +2 -0
  33. package/src/components/EventLog.res +24 -0
  34. package/src/components/EventLog.res.mjs +2 -0
  35. package/src/components/EventMapper.res +37 -0
  36. package/src/components/EventMapper.res.mjs +2 -0
  37. package/src/components/EventTopic.res +51 -0
  38. package/src/components/EventTopic.res.mjs +2 -0
  39. package/src/components/Extension.res +64 -0
  40. package/src/components/Extension.res.mjs +2 -0
  41. package/src/components/ExtensionPoint.res +62 -0
  42. package/src/components/ExtensionPoint.res.mjs +2 -0
  43. package/src/components/Heartbeat.res +7 -0
  44. package/src/components/Heartbeat.res.mjs +2 -0
  45. package/src/components/InboundTranslationSlice.res +41 -0
  46. package/src/components/InboundTranslationSlice.res.mjs +2 -0
  47. package/src/components/OutboundTranslationSlice.res +44 -0
  48. package/src/components/OutboundTranslationSlice.res.mjs +2 -0
  49. package/src/components/Plugin.res +93 -0
  50. package/src/components/Plugin.res.mjs +2 -0
  51. package/src/components/QueryDb.res +48 -0
  52. package/src/components/QueryDb.res.mjs +33 -0
  53. package/src/components/ReadModel.res +56 -0
  54. package/src/components/ReadModel.res.mjs +2 -0
  55. package/src/components/Scheduler.res +32 -0
  56. package/src/components/Scheduler.res.mjs +2 -0
  57. package/src/components/StateChangeSlice.res +45 -0
  58. package/src/components/StateChangeSlice.res.mjs +2 -0
  59. package/src/components/StateViewSlice.res +38 -0
  60. package/src/components/StateViewSlice.res.mjs +2 -0
  61. package/src/components/Task.res +89 -0
  62. package/src/components/Task.res.mjs +2 -0
  63. package/src/types/ExtensionMapping.res +448 -0
  64. package/src/types/ExtensionMapping.res.mjs +252 -0
  65. package/src/types/ExtensionPointMapping.res +303 -0
  66. package/src/types/ExtensionPointMapping.res.mjs +116 -0
  67. package/src/types/Message.res +3 -0
  68. package/src/types/Message.res.mjs +2 -0
  69. package/src/types/NoEventMappings.res +25 -0
  70. package/src/types/NoEventMappings.res.mjs +17 -0
  71. package/src/types/Platform.res +269 -0
  72. package/src/types/Platform.res.mjs +2 -0
  73. package/src/types/PluginExtensionPointSpec.res +55 -0
  74. package/src/types/PluginExtensionPointSpec.res.mjs +209 -0
  75. package/src/types/ResourceNaming.res +12 -0
  76. package/src/types/ResourceNaming.res.mjs +2 -0
  77. package/tests/DeployBootstrapTest.res +72 -0
  78. package/tests/DeployBootstrapTest.res.mjs +100 -0
@@ -0,0 +1,130 @@
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
+ Typed DCB append outcome — mirrors `EventLog.appendError`. `Conflict` is the
64
+ optimistic-concurrency sentinel (the append-condition failed: a matching event
65
+ was written since `condition.after`), which the slice callback retries by
66
+ re-reading and re-deciding. Every other failure is a `StorageFailure` carrying
67
+ its message. Replaces the former string sentinel that conflated the two — a
68
+ storage error whose text happened to contain "conflict" would have been retried
69
+ forever, and backends disagreed on the sentinel's casing so conflict metrics were
70
+ misclassified across backends.
71
+ */
72
+ type appendError =
73
+ | Conflict
74
+ | StorageFailure(string)
75
+
76
+ /**
77
+ Appends raw events to the DCB log with optional optimistic-concurrency checking.
78
+
79
+ Returns `Ok(position)` on success or `Error(Conflict)` if the append condition
80
+ was violated (i.e. the log was modified since `condition.after`), or
81
+ `Error(StorageFailure(_))` on any other failure.
82
+ */
83
+ type append = (
84
+ array<rawEvent>,
85
+ ~condition: Reventless.DcbTag.appendCondition=?,
86
+ ) => promise<result<Reventless.DcbTag.sequencePosition, appendError>>
87
+
88
+ /**
89
+ Streams events from the DCB log matching the given query.
90
+ Use for large result sets that should not be loaded into memory at once.
91
+ */
92
+ type readStream = (
93
+ ~query: Reventless.DcbTag.query,
94
+ ~after: Reventless.DcbTag.sequencePosition=?,
95
+ /** Opt into strongly-consistent single-tag reads. Defaults to eventually
96
+ consistent: a stale read can only cause a rejected append (then a retry),
97
+ never a wrong write, because the append fence is always evaluated strongly.
98
+ The slice callback sets this on retries (eventual-first, strong-on-retry). */
99
+ ~strongConsistency: bool=?,
100
+ ) => Stream.t<rawSequencedEvent, string, unit>
101
+
102
+ /**
103
+ Appends a stream of raw events to the DCB log as an `Effect.t`.
104
+ Use for high-throughput batch imports.
105
+ */
106
+ type appendStream = (
107
+ Stream.t<rawEvent, string, unit>,
108
+ ~condition: Reventless.DcbTag.appendCondition=?,
109
+ ) => Effect.t<result<Reventless.DcbTag.sequencePosition, appendError>, string, unit>
110
+
111
+ /**
112
+ Runtime operations exposed by a `DcbEventLog` component.
113
+ Works with raw events — encode/decode is handled by each slice's callback.
114
+
115
+ Obtained via `Component.operations(dcbEventLog)`. Available inside Lambda handlers.
116
+ */
117
+ type operations = {
118
+ read: read,
119
+ append: append,
120
+ readStream: readStream,
121
+ appendStream: appendStream,
122
+ }
123
+
124
+ type t
125
+ type component = Component.t<t, outputs, operations>
126
+
127
+ module type T = {
128
+ type component = component
129
+ let make: (~name: string, ~indexes: array<string>=?, ~opts: Pulumi.ComponentResource.options=?) => component
130
+ }
@@ -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,83 @@
1
+ /**
2
+ Deploy-time bootstrap seam: a named choke point through which a deploy program
3
+ runs cross-cutting activations at fixed phases, without hand-editing the
4
+ generated `Main.res`.
5
+
6
+ No-op by default. Zero registrations ⇒ `run` does nothing ⇒ existing generated
7
+ and hand-written deploy programs are byte-identical and preview with no resource
8
+ diff. An extension (a backend, an operational package) registers a contribution
9
+ via `register` — at module-load time as an import side effect, or explicitly —
10
+ and the generated program's `run(PreDeploy)` / `run(PostDeploy)` calls fire it in
11
+ registration order.
12
+
13
+ Same shape as `ReventlessCore.Monitoring.use`: a module-level registry consulted
14
+ by an emitted call, so deploy-time extension becomes *registration*, not *file
15
+ editing*. See `docs/plans/deploy-bootstrap-seam.md`.
16
+ */
17
+
18
+ /**
19
+ Ordered phases at which bootstrap contributions run during a deploy program.
20
+ */
21
+ type phase =
22
+ | /** before `deployPlatform` / `deployPlugin` — seam registration and other
23
+ ordering-sensitive activations that must precede the platform/plugin
24
+ graph build */
25
+ PreDeploy
26
+ | /** after the platform/plugin graph is registered — exports, cross-stack
27
+ output emission */
28
+ PostDeploy
29
+
30
+ type contribution = unit => unit
31
+
32
+ let preContributions: ref<array<contribution>> = ref([])
33
+ let postContributions: ref<array<contribution>> = ref([])
34
+ let preRan = ref(false)
35
+ let postRan = ref(false)
36
+
37
+ let registryFor = phase =>
38
+ switch phase {
39
+ | PreDeploy => preContributions
40
+ | PostDeploy => postContributions
41
+ }
42
+
43
+ let ranFor = phase =>
44
+ switch phase {
45
+ | PreDeploy => preRan
46
+ | PostDeploy => postRan
47
+ }
48
+
49
+ /**
50
+ Register a contribution. Contributions run in registration order within a phase.
51
+ Safe to call at module-load time (as an import side effect) or explicitly.
52
+ Defaults to `PreDeploy`.
53
+ */
54
+ let register = (~phase=PreDeploy, contribution: contribution) => {
55
+ let registry = registryFor(phase)
56
+ registry := registry.contents->Array.concat([contribution])
57
+ }
58
+
59
+ /**
60
+ Run all contributions registered for a phase, in registration order. Emitted by
61
+ generated deploy programs around the platform/plugin build. Idempotent per phase:
62
+ running an already-run phase is a no-op, and running a phase with no
63
+ registrations does nothing.
64
+ */
65
+ let run = (phase: phase) => {
66
+ let ran = ranFor(phase)
67
+ if !ran.contents {
68
+ ran := true
69
+ registryFor(phase).contents->Array.forEach(contribution => contribution())
70
+ }
71
+ }
72
+
73
+ /**
74
+ Reset all registries and run-flags. Test-support only — deploy programs never
75
+ call this. Lets a test exercise registration order, phase isolation, and
76
+ idempotency from a clean slate.
77
+ */
78
+ let reset = () => {
79
+ preContributions := []
80
+ postContributions := []
81
+ preRan := false
82
+ postRan := false
83
+ }
@@ -0,0 +1,69 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+
4
+ let preContributions = {
5
+ contents: []
6
+ };
7
+
8
+ let postContributions = {
9
+ contents: []
10
+ };
11
+
12
+ let preRan = {
13
+ contents: false
14
+ };
15
+
16
+ let postRan = {
17
+ contents: false
18
+ };
19
+
20
+ function registryFor(phase) {
21
+ if (phase === "PreDeploy") {
22
+ return preContributions;
23
+ } else {
24
+ return postContributions;
25
+ }
26
+ }
27
+
28
+ function ranFor(phase) {
29
+ if (phase === "PreDeploy") {
30
+ return preRan;
31
+ } else {
32
+ return postRan;
33
+ }
34
+ }
35
+
36
+ function register(phaseOpt, contribution) {
37
+ let phase = phaseOpt !== undefined ? phaseOpt : "PreDeploy";
38
+ let registry = registryFor(phase);
39
+ registry.contents = registry.contents.concat([contribution]);
40
+ }
41
+
42
+ function run(phase) {
43
+ let ran = ranFor(phase);
44
+ if (!ran.contents) {
45
+ ran.contents = true;
46
+ registryFor(phase).contents.forEach(contribution => contribution());
47
+ return;
48
+ }
49
+ }
50
+
51
+ function reset() {
52
+ preContributions.contents = [];
53
+ postContributions.contents = [];
54
+ preRan.contents = false;
55
+ postRan.contents = false;
56
+ }
57
+
58
+ export {
59
+ preContributions,
60
+ postContributions,
61
+ preRan,
62
+ postRan,
63
+ registryFor,
64
+ ranFor,
65
+ register,
66
+ run,
67
+ reset,
68
+ }
69
+ /* No side effect */
@@ -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. */
@@ -0,0 +1,51 @@
1
+ /**
2
+ Module type for an aggregate's event topic specification.
3
+
4
+ `EventTopic.T` is used by the framework to identify the event channel
5
+ (e.g. an SNS topic) and validate that published events match the
6
+ aggregate's event schema.
7
+ */
8
+ module type T = {
9
+ module Id: Reventless.Id.T
10
+
11
+ /** Logical name of the aggregate or component owning this event topic. */
12
+ let name: string
13
+
14
+ /** The event type published to this topic. Must carry `@schema` for serialization. */
15
+ @schema
16
+ type event
17
+ }
18
+
19
+ /**
20
+ Deploy-time outputs produced when an `EventTopic` is provisioned.
21
+ Contains the underlying messaging infrastructure resources.
22
+ */
23
+ type outputs = {resources: array<Adapter.resource>}
24
+
25
+ /** A dictionary of event topic outputs keyed by aggregate name. */
26
+ type allOutputs = dict<outputs>
27
+
28
+ /**
29
+ Publishes a single event as raw JSON to the event topic.
30
+
31
+ - `string` — the aggregate ID (as a plain string)
32
+ - `Message.meta` — the event envelope metadata
33
+ - `JSON.t` — the serialized event payload
34
+ */
35
+ type publishJson = (string, Reventless.Message.meta, JSON.t) => promise<unit>
36
+
37
+ /**
38
+ An item in a streaming event publication batch.
39
+ Passed to `publishJsonStream` for high-throughput event pipelines.
40
+ */
41
+ type publishJsonStreamItem = {
42
+ service: string,
43
+ meta: Reventless.Message.meta,
44
+ json: JSON.t,
45
+ }
46
+
47
+ /**
48
+ Publishes a stream of event items as an `Effect.t`.
49
+ Use this for high-throughput or streaming event pipelines.
50
+ */
51
+ type publishJsonStream = Stream.t<publishJsonStreamItem, string, unit> => Effect.t<unit, string, unit>
@@ -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,64 @@
1
+ /**
2
+ Deploy-time outputs produced when an `Extension` is provisioned.
3
+
4
+ - `name` — the extension's logical name
5
+ - `extensionPointName` — the extension point this extension connects to
6
+ - `aggregateNames` — names of aggregates wired through this extension
7
+ */
8
+ type outputs = {
9
+ name: string,
10
+ extensionPointName: string,
11
+ aggregateNames: array<string>,
12
+ }
13
+
14
+ // eventHandler type is defined in reventless (references Plugin.pluginDefinition which
15
+ // would create a circular dependency: Extension → Plugin → Extension).
16
+ // The spec-level T uses abstract `type operations` to avoid the cycle.
17
+
18
+ /**
19
+ Module type for a provisioned extension component.
20
+
21
+ An `Extension` connects a host plugin's extension point to one or more aggregates,
22
+ translating commands and events in both directions via `ExtensionMapping.Mapping`.
23
+
24
+ `operations` is left abstract at the spec level to avoid a circular dependency.
25
+ The concrete type is defined in the `reventless` package.
26
+ */
27
+ module type T = {
28
+ type operations
29
+ type component
30
+ let make: (
31
+ ~publishToPluginExtensionPoint: CommandTopic.publishJsons,
32
+ ~publishToAggregates: dict<CommandTopic.publishJsons>,
33
+ ~readModelNamesForSourceName: dict<array<string>>,
34
+ ~publishToReadModels: dict<EventCollector.enqueueEvent>,
35
+ ~queryEngine: Reventless.QueryEngine.operations,
36
+ ~opts: option<Pulumi.ComponentResource.options>,
37
+ ) => component
38
+ let outputs: component => outputs
39
+ let operations: component => Pulumi.Output.t<operations>
40
+ }
41
+
42
+ /**
43
+ Pre-build blueprint for an extension — compiled mappings that have not yet been
44
+ instantiated as a Pulumi component.
45
+
46
+ `Plugin.make` receives blueprints, groups them by extension point name,
47
+ auto-merges mappings for the same EP, sets the component name to the plugin
48
+ name, and builds the actual `Extension` component.
49
+ */
50
+ module type Blueprint = {
51
+ module Spec: ExtensionMapping.Spec
52
+ module type Mapping = ExtensionMapping.T with module ExtensionPoint := Spec
53
+ let name: string
54
+ // npm-style specifier of the user extension file (the one declaring the
55
+ // `module Mapping`). Threaded from the user-facing Mapping.moduleUrl by
56
+ // Platform.Extension.Make so deploy-side helpers can emit HANDLER_CONFIG
57
+ // entries that let the runtime dynamic-import the user mapping at cold
58
+ // start.
59
+ let moduleUrl: string
60
+ // npm-style specifier of the Delegate (aggregate / slice) the extension
61
+ // delegates to. Threaded from Mapping.delegateModuleUrl by Platform.Extension.Make.
62
+ let delegateModuleUrl: string
63
+ let mappings: array<module(Mapping)>
64
+ }
@@ -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,62 @@
1
+ /**
2
+ Deploy-time outputs produced when an `ExtensionPoint` is provisioned.
3
+
4
+ - `name` — the extension point's logical name
5
+ - `aggregateNames` — names of aggregates connected via `ExtensionPointMapping`
6
+ - `commandTopic` — the inbound command queue for extensions to publish to
7
+ - `eventTopic` — the outbound event topic extensions subscribe to
8
+ */
9
+ type outputs = {
10
+ name: string,
11
+ aggregateNames: array<string>,
12
+ commandTopic: Pulumi.Output.t<CommandTopic.outputs>,
13
+ eventTopic: Pulumi.Output.t<EventTopic.outputs>,
14
+ // Module URLs preserved from the Spec and Mappings packed into Make. The
15
+ // EventCollector runtime needs them at HANDLER_CONFIG-build time to wire
16
+ // outgoing event publication for this extension point — see
17
+ // `Plugin_Helpers.registerEventCollectorContext` and the `extensionPointEntry`
18
+ // type that's serialised into the Lambda's HANDLER_CONFIG.
19
+ specModule: string,
20
+ mappingsModule: string,
21
+ }
22
+
23
+ // eventHandler type is defined in reventless (references Plugin.pluginDefinition which
24
+ // would create a circular dependency: ExtensionPoint → Plugin → ExtensionPoint).
25
+ // The infra-level T uses abstract `type operations` to avoid the cycle.
26
+
27
+ /**
28
+ A collection of `ExtensionPointMapping.T` modules connecting aggregates to
29
+ this extension point.
30
+
31
+ Pass a `Mappings` module to `Platform.ExtensionPoint.Make` to register all
32
+ aggregate-to-extension-point connections.
33
+ */
34
+ module type Mappings = {
35
+ module Spec: ExtensionPointMapping.Spec
36
+ module type Mapping = ExtensionPointMapping.T with module ExtensionPoint := Spec
37
+ let name: string
38
+ let moduleUrl: string
39
+ let mappings: array<module(Mapping)>
40
+ }
41
+
42
+ /**
43
+ Module type for a provisioned extension point component.
44
+
45
+ `operations` is left abstract to avoid a circular dependency between
46
+ `ExtensionPoint`, `Plugin`, and back. The concrete type is defined in
47
+ the `reventless` package.
48
+ */
49
+ module type T = {
50
+ type operations
51
+ type component
52
+ let make: (
53
+ ~aggregateResources: dict<array<Adapter.resource>>,
54
+ ~publishToAggregates: dict<CommandTopic.publishJsons>,
55
+ ~scheduler: Scheduler.operations,
56
+ ~queryEngine: Reventless.QueryEngine.operations,
57
+ ~resourceNaming: ResourceNaming.operations,
58
+ ~opts: option<Pulumi.ComponentResource.options>,
59
+ ) => component
60
+ let outputs: component => outputs
61
+ let operations: component => Pulumi.Output.t<operations>
62
+ }
@@ -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,7 @@
1
+ /**
2
+ * Deploy-time outputs produced when a `Heartbeat` component is provisioned.
3
+ *
4
+ * The heartbeat is an internal health-check component that periodically fires
5
+ * to verify that the plugin's Lambda handlers are reachable and warm.
6
+ */
7
+ 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,41 @@
1
+ /**
2
+ Deploy-time outputs produced when an `InboundTranslationSlice` is provisioned.
3
+
4
+ - `resources` -- the underlying infrastructure
5
+ - `queryDb` -- the DynamoDB table for the audit log
6
+ */
7
+ type outputs = {
8
+ resources: array<Adapter.resource>,
9
+ queryDb: QueryDb.outputs,
10
+ }
11
+
12
+ /**
13
+ Runtime operations exposed by an `InboundTranslationSlice` component.
14
+
15
+ - `receive` -- accept external input, translate it, and publish a command
16
+ */
17
+ type operations = {
18
+ receive: JSON.t => promise<result<array<string>, string>>,
19
+ }
20
+
21
+ /**
22
+ Module type produced by `Platform.InboundTranslationSlice.Make(Spec)`.
23
+
24
+ @example
25
+ ```rescript
26
+ module PaymentWebhookSlice = Platform.InboundTranslationSlice.Make(PaymentWebhook)
27
+ let slice = PaymentWebhookSlice.make(~publishJsons=publishJsonsOutput)
28
+ ```
29
+ */
30
+ type t
31
+
32
+ module type T = {
33
+ module Spec: Reventless.InboundTranslationSlice.Spec
34
+ module Translation: Reventless.InboundTranslationSlice.Translation with module Spec := Spec
35
+ type component = Component.t<t, outputs, operations>
36
+ let queryDbName: string
37
+ let make: (
38
+ ~publishJsons: Pulumi.Output.t<CommandTopic.publishJsons>,
39
+ ~opts: Pulumi.ComponentResource.options=?,
40
+ ) => component
41
+ }
@@ -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,44 @@
1
+ /**
2
+ Deploy-time outputs produced when an `OutboundTranslationSlice` 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 `OutboundTranslationSlice` component.
14
+
15
+ - `enqueueEvent` -- push events into the slice's projection queue
16
+ - `translatePending` -- manually trigger Phase 2 (useful in tests and for heartbeat)
17
+ */
18
+ type operations = {
19
+ enqueueEvent: EventCollector.enqueueEvent,
20
+ translatePending: unit => promise<unit>,
21
+ }
22
+
23
+ /**
24
+ Module type produced by `Platform.OutboundTranslationSlice.Make(Spec)`.
25
+
26
+ @example
27
+ ```rescript
28
+ module SendTrackingEmailSlice = Platform.OutboundTranslationSlice.Make(SendTrackingEmail)
29
+ let slice = SendTrackingEmailSlice.make(~dcbEventLog=log, ~publishJsons=publishJsonsOutput)
30
+ ```
31
+ */
32
+ type t
33
+
34
+ module type T = {
35
+ module Spec: Reventless.OutboundTranslationSlice.Spec
36
+ module Translation: Reventless.OutboundTranslationSlice.Translation with module Spec := Spec
37
+ type component = Component.t<t, outputs, operations>
38
+ let queryDbName: string
39
+ let make: (
40
+ ~dcbEventLog: DcbEventLog.component,
41
+ ~publishJsons: Pulumi.Output.t<CommandTopic.publishJsons>,
42
+ ~opts: Pulumi.ComponentResource.options=?,
43
+ ) => component
44
+ }
@@ -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. */