@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.
- package/CHANGELOG.md +709 -0
- package/LICENSE +202 -0
- package/package.json +35 -0
- package/rescript.json +28 -0
- package/src/adapter/Adapter.res +88 -0
- package/src/adapter/Adapter.res.mjs +29 -0
- package/src/components/Aggregate.res +73 -0
- package/src/components/Aggregate.res.mjs +2 -0
- package/src/components/Api.res +124 -0
- package/src/components/Api.res.mjs +31 -0
- package/src/components/Api_Adapter.res +39 -0
- package/src/components/Api_Adapter.res.mjs +2 -0
- package/src/components/AutomationSlice.res +48 -0
- package/src/components/AutomationSlice.res.mjs +2 -0
- package/src/components/CommandGenerator.res +8 -0
- package/src/components/CommandGenerator.res.mjs +2 -0
- package/src/components/CommandTopic.res +70 -0
- package/src/components/CommandTopic.res.mjs +2 -0
- package/src/components/Component.js +56 -0
- package/src/components/Component.mjs +10 -0
- package/src/components/Component.res +90 -0
- package/src/components/Component.res.mjs +57 -0
- package/src/components/Component.resi +21 -0
- package/src/components/Counter.res +81 -0
- package/src/components/Counter.res.mjs +2 -0
- package/src/components/DcbEventLog.res +115 -0
- package/src/components/DcbEventLog.res.mjs +2 -0
- package/src/components/EventCollector.res +19 -0
- package/src/components/EventCollector.res.mjs +2 -0
- package/src/components/EventLog.res +24 -0
- package/src/components/EventLog.res.mjs +2 -0
- package/src/components/EventMapper.res +37 -0
- package/src/components/EventMapper.res.mjs +2 -0
- package/src/components/EventTopic.res +51 -0
- package/src/components/EventTopic.res.mjs +2 -0
- package/src/components/Extension.res +64 -0
- package/src/components/Extension.res.mjs +2 -0
- package/src/components/ExtensionPoint.res +62 -0
- package/src/components/ExtensionPoint.res.mjs +2 -0
- package/src/components/Heartbeat.res +7 -0
- package/src/components/Heartbeat.res.mjs +2 -0
- package/src/components/InboundTranslationSlice.res +41 -0
- package/src/components/InboundTranslationSlice.res.mjs +2 -0
- package/src/components/OutboundTranslationSlice.res +44 -0
- package/src/components/OutboundTranslationSlice.res.mjs +2 -0
- package/src/components/Plugin.res +84 -0
- package/src/components/Plugin.res.mjs +2 -0
- package/src/components/QueryDb.res +48 -0
- package/src/components/QueryDb.res.mjs +33 -0
- package/src/components/ReadModel.res +50 -0
- package/src/components/ReadModel.res.mjs +2 -0
- package/src/components/Scheduler.res +32 -0
- package/src/components/Scheduler.res.mjs +2 -0
- package/src/components/StateChangeSlice.res +45 -0
- package/src/components/StateChangeSlice.res.mjs +2 -0
- package/src/components/StateViewSlice.res +38 -0
- package/src/components/StateViewSlice.res.mjs +2 -0
- package/src/components/Task.res +89 -0
- package/src/components/Task.res.mjs +2 -0
- package/src/types/ExtensionMapping.res +448 -0
- package/src/types/ExtensionMapping.res.mjs +252 -0
- package/src/types/ExtensionPointMapping.res +303 -0
- package/src/types/ExtensionPointMapping.res.mjs +116 -0
- package/src/types/Message.res +3 -0
- package/src/types/Message.res.mjs +2 -0
- package/src/types/NoEventMappings.res +25 -0
- package/src/types/NoEventMappings.res.mjs +17 -0
- package/src/types/Platform.res +279 -0
- package/src/types/Platform.res.mjs +2 -0
- package/src/types/PluginExtensionPointSpec.res +43 -0
- package/src/types/PluginExtensionPointSpec.res.mjs +204 -0
- package/src/types/ResourceNaming.res +12 -0
- package/src/types/ResourceNaming.res.mjs +2 -0
|
@@ -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,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,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,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,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,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,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Deploy-time outputs produced by the `Plugin.T.make` function.
|
|
3
|
+
|
|
4
|
+
All fields are `Pulumi.Output.t`-wrapped because they reference resources
|
|
5
|
+
provisioned during the Pulumi stack update.
|
|
6
|
+
*/
|
|
7
|
+
type outputs = {
|
|
8
|
+
id: Pulumi.Output.t<string>,
|
|
9
|
+
version: Pulumi.Output.t<string>,
|
|
10
|
+
heartbeatInterval: Pulumi.Output.t<int>,
|
|
11
|
+
eventCollector: Pulumi.Output.t<EventCollector.outputs>,
|
|
12
|
+
extensionPoints: Pulumi.Output.t<dict<ExtensionPoint.outputs>>,
|
|
13
|
+
extensions: Pulumi.Output.t<dict<Extension.outputs>>,
|
|
14
|
+
aggregates: Pulumi.Output.t<dict<Aggregate.outputs>>,
|
|
15
|
+
readModels: Pulumi.Output.t<dict<ReadModel.outputs>>,
|
|
16
|
+
tasks: Pulumi.Output.t<dict<Task.outputs>>,
|
|
17
|
+
/** AppSync / GraphQL resolver resources. */
|
|
18
|
+
resolvers: Pulumi.Output.t<array<Adapter.resource>>,
|
|
19
|
+
heartbeat: Pulumi.Output.t<Heartbeat.outputs>,
|
|
20
|
+
apiSchemaFragment: Pulumi.Output.t<option<Reventless.Plugin.apiSchemaFragment>>,
|
|
21
|
+
/** UI fragment manifest for runtime micro-frontend registration (None for pure backend plugins). */
|
|
22
|
+
uiFragments: Pulumi.Output.t<option<Reventless.Plugin.uiFragmentManifest>>,
|
|
23
|
+
/** Plugin structure carrying queryable and writable component metadata (None for pure backend plugins). */
|
|
24
|
+
pluginStructure: Pulumi.Output.t<option<Reventless.Plugin.pluginStructure>>,
|
|
25
|
+
/** Present when the plugin uses a `DcbEventLog`. */
|
|
26
|
+
dcbEventLog: Pulumi.Output.t<option<DcbEventLog.outputs>>,
|
|
27
|
+
stateChangeSlices: Pulumi.Output.t<dict<StateChangeSlice.outputs>>,
|
|
28
|
+
stateViewSlices: Pulumi.Output.t<dict<StateViewSlice.outputs>>,
|
|
29
|
+
automationSlices: Pulumi.Output.t<dict<AutomationSlice.outputs>>,
|
|
30
|
+
outboundTranslationSlices: Pulumi.Output.t<dict<OutboundTranslationSlice.outputs>>,
|
|
31
|
+
inboundTranslationSlices: Pulumi.Output.t<dict<InboundTranslationSlice.outputs>>,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
Module type for the top-level plugin factory.
|
|
36
|
+
|
|
37
|
+
Call `Plugin.T.make` to provision all plugin components (aggregates, read models,
|
|
38
|
+
tasks, extension points, extensions, heartbeat, DCB log) in a single Pulumi stack update.
|
|
39
|
+
|
|
40
|
+
DCB slices are passed directly as optional labeled arrays. When any slice array
|
|
41
|
+
is non-empty, a shared DCB EventLog is provisioned automatically.
|
|
42
|
+
*/
|
|
43
|
+
module type T = {
|
|
44
|
+
type api
|
|
45
|
+
type role
|
|
46
|
+
type component
|
|
47
|
+
let make: (
|
|
48
|
+
~name: string,
|
|
49
|
+
/** How often (in seconds) the heartbeat Lambda fires. */
|
|
50
|
+
~heartbeatInterval: int,
|
|
51
|
+
~extensionPoints: array<module(ExtensionPoint.T)>=?,
|
|
52
|
+
~extensions: array<module(Extension.Blueprint)>=?,
|
|
53
|
+
~aggregates: array<module(Aggregate.T with type api = api)>=?,
|
|
54
|
+
~readModels: array<module(ReadModel.T with type api = api and type role = role)>=?,
|
|
55
|
+
~tasks: array<module(Task.T)>=?,
|
|
56
|
+
~stateChangeSlices: array<module(StateChangeSlice.T)>=?,
|
|
57
|
+
~stateViewSlices: array<module(StateViewSlice.T)>=?,
|
|
58
|
+
~automationSlices: array<module(AutomationSlice.T)>=?,
|
|
59
|
+
~outboundTranslationSlices: array<module(OutboundTranslationSlice.T)>=?,
|
|
60
|
+
~inboundTranslationSlices: array<module(InboundTranslationSlice.T)>=?,
|
|
61
|
+
~uiFragments: Reventless.Plugin.uiFragmentManifest=?,
|
|
62
|
+
~pluginStructure: Reventless.Plugin.pluginStructure=?,
|
|
63
|
+
~opts: Pulumi.ComponentResource.options=?,
|
|
64
|
+
) => component
|
|
65
|
+
let makeAutoUIManifest: (
|
|
66
|
+
~remoteEntryUrl: string,
|
|
67
|
+
~name: string,
|
|
68
|
+
~pluginStructure: Reventless.Plugin.pluginStructure,
|
|
69
|
+
~readModelPositions: array<string>=?,
|
|
70
|
+
~aggregatePositions: array<string>=?,
|
|
71
|
+
) => Reventless.Plugin.uiFragmentManifest
|
|
72
|
+
let makePluginDefinition: (
|
|
73
|
+
~name: string,
|
|
74
|
+
~aggregates: array<module(Aggregate.T with type api = api)>=?,
|
|
75
|
+
~readModels: array<module(ReadModel.T with type api = api and type role = role)>=?,
|
|
76
|
+
~stateViewSlices: array<module(StateViewSlice.T)>=?,
|
|
77
|
+
~stateChangeSlices: array<module(StateChangeSlice.T)>=?,
|
|
78
|
+
~automationSlices: array<module(AutomationSlice.T)>=?,
|
|
79
|
+
~outboundTranslationSlices: array<module(OutboundTranslationSlice.T)>=?,
|
|
80
|
+
~inboundTranslationSlices: array<module(InboundTranslationSlice.T)>=?,
|
|
81
|
+
~extensions: array<module(Extension.Blueprint)>=?,
|
|
82
|
+
~extensionPoints: array<module(ExtensionPointMapping.Mapping)>=?,
|
|
83
|
+
) => Reventless.Plugin.pluginStructure
|
|
84
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Errors that can occur during read model storage operations.
|
|
3
|
+
|
|
4
|
+
Returned as the error variant in `Result.t` by read model operations that
|
|
5
|
+
interact with the underlying query database (e.g. DynamoDB).
|
|
6
|
+
*/
|
|
7
|
+
@schema
|
|
8
|
+
type storageError =
|
|
9
|
+
/** A write operation failed to persist the state. */
|
|
10
|
+
| NotSavedToStorage(string)
|
|
11
|
+
/** A read operation failed to retrieve the state. */
|
|
12
|
+
| NotLoadedFromStorage(string)
|
|
13
|
+
/** A count operation failed. */
|
|
14
|
+
| NotCountedOnStorage(string)
|
|
15
|
+
/** A delete operation failed. */
|
|
16
|
+
| NotDeletedFromStorage(string)
|
|
17
|
+
/** A batch write did not fully succeed (some items may not have been written). */
|
|
18
|
+
| BatchNotFullyWrittenToStorage(string)
|
|
19
|
+
/** A conditional write failed because the state was modified concurrently. */
|
|
20
|
+
| StaleState
|
|
21
|
+
/** A composite-key (sub-ID) operation was attempted but no sub-ID config was provided. */
|
|
22
|
+
| MissingSubIdConfig
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
A function that derives the infrastructure resources needed to back GraphQL resolvers,
|
|
26
|
+
given the set of all query database outputs in the plugin.
|
|
27
|
+
*/
|
|
28
|
+
type rec resolversResourcesMaker = dict<outputs> => array<Adapter.resource>
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
Deploy-time outputs produced when a `QueryDb` is provisioned.
|
|
32
|
+
|
|
33
|
+
- `resources` — the underlying database infrastructure resources
|
|
34
|
+
- `resolversMaker` — callback used by the plugin to assemble resolver resources
|
|
35
|
+
- `dataSourceName` — name of the AppSync DataSource that fronts this query DB.
|
|
36
|
+
Surfaced separately from `resources` so admin-side schema-push barriers can
|
|
37
|
+
wait for the DataSource to settle before invoking StartSchemaCreation —
|
|
38
|
+
AppSync rejects concurrent CreateDataSource / StartSchemaCreation calls
|
|
39
|
+
with `ConcurrentModificationException`.
|
|
40
|
+
*/
|
|
41
|
+
and outputs = {
|
|
42
|
+
resources: array<Adapter.resource>,
|
|
43
|
+
resolversMaker: resolversResourcesMaker,
|
|
44
|
+
dataSourceName: Pulumi.Output.t<string>,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** A dictionary of query database outputs keyed by read model name. */
|
|
48
|
+
type allOutputs = dict<outputs>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as S from "sury/src/S.res.mjs";
|
|
4
|
+
|
|
5
|
+
let storageErrorSchema = S.union([
|
|
6
|
+
S.schema(s => ({
|
|
7
|
+
TAG: "NotSavedToStorage",
|
|
8
|
+
_0: s.m(S.string)
|
|
9
|
+
})),
|
|
10
|
+
S.schema(s => ({
|
|
11
|
+
TAG: "NotLoadedFromStorage",
|
|
12
|
+
_0: s.m(S.string)
|
|
13
|
+
})),
|
|
14
|
+
S.schema(s => ({
|
|
15
|
+
TAG: "NotCountedOnStorage",
|
|
16
|
+
_0: s.m(S.string)
|
|
17
|
+
})),
|
|
18
|
+
S.schema(s => ({
|
|
19
|
+
TAG: "NotDeletedFromStorage",
|
|
20
|
+
_0: s.m(S.string)
|
|
21
|
+
})),
|
|
22
|
+
S.schema(s => ({
|
|
23
|
+
TAG: "BatchNotFullyWrittenToStorage",
|
|
24
|
+
_0: s.m(S.string)
|
|
25
|
+
})),
|
|
26
|
+
S.literal("StaleState"),
|
|
27
|
+
S.literal("MissingSubIdConfig")
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
export {
|
|
31
|
+
storageErrorSchema,
|
|
32
|
+
}
|
|
33
|
+
/* storageErrorSchema Not a pure module */
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Deploy-time outputs produced when a `ReadModel` is provisioned.
|
|
3
|
+
|
|
4
|
+
- `name` — the read model's logical name
|
|
5
|
+
- `queryDb` — the underlying query database outputs (DynamoDB table)
|
|
6
|
+
- `eventCollector` — the inbound event queue
|
|
7
|
+
- `sourceNames` — names of all aggregates whose events feed this read model
|
|
8
|
+
*/
|
|
9
|
+
type outputs = {
|
|
10
|
+
name: string,
|
|
11
|
+
queryDb: QueryDb.outputs,
|
|
12
|
+
eventCollector: Pulumi.Output.t<EventCollector.outputs>,
|
|
13
|
+
sourceNames: array<string>,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
Runtime operations exposed by a `ReadModel` component.
|
|
18
|
+
Used by the aggregate runtime to push events into the read model's event queue.
|
|
19
|
+
*/
|
|
20
|
+
type operations = {enqueueEvent: EventCollector.enqueueEvent}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
Module type produced by `Platform.ReadModel.Make(Spec, Mappings)`.
|
|
24
|
+
|
|
25
|
+
@example
|
|
26
|
+
```rescript
|
|
27
|
+
// CatalogPlugin.res
|
|
28
|
+
module CategoryReadModel = Platform.ReadModel.Make(CategoriesReadModel, CategoryMappings)
|
|
29
|
+
|
|
30
|
+
let rm = CategoryReadModel.make(~api, ~apiRole, ~allEventTopics, ~opts=?)
|
|
31
|
+
```
|
|
32
|
+
*/
|
|
33
|
+
module type T = {
|
|
34
|
+
module Spec: Reventless.ReadModel.Spec
|
|
35
|
+
type api
|
|
36
|
+
type role
|
|
37
|
+
type component
|
|
38
|
+
/** Names of aggregates whose events feed this read model (from Projection.Mapping.sourceName). */
|
|
39
|
+
let sourceNames: array<string>
|
|
40
|
+
let make: (
|
|
41
|
+
~api: api,
|
|
42
|
+
~apiRole: role,
|
|
43
|
+
~allEventTopics: EventTopic.allOutputs,
|
|
44
|
+
~opts: Pulumi.ComponentResource.options=?,
|
|
45
|
+
) => component
|
|
46
|
+
let outputs: component => outputs
|
|
47
|
+
let operations: component => Pulumi.Output.t<operations>
|
|
48
|
+
/** Signal that all sources have been registered; finalises the read model. */
|
|
49
|
+
let finish: unit => unit
|
|
50
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Deploy-time outputs produced when a `Scheduler` component is provisioned.
|
|
3
|
+
Contains the single infrastructure resource backing the scheduler (e.g. EventBridge Scheduler).
|
|
4
|
+
*/
|
|
5
|
+
type outputs = {resource: Adapter.resource}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
Creates a schedule in the underlying scheduling service (e.g. EventBridge Scheduler).
|
|
9
|
+
|
|
10
|
+
- `array<Adapter.resolvedResource>` — resolved scheduler resources (ARNs, etc.)
|
|
11
|
+
- `Reventless.Schedule.schedule` — the schedule definition to create
|
|
12
|
+
*/
|
|
13
|
+
type createSchedule = (array<Adapter.resolvedResource>, Reventless.Schedule.schedule) => promise<unit>
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
Deletes a schedule by name from the underlying scheduling service.
|
|
17
|
+
|
|
18
|
+
- `array<Adapter.resolvedResource>` — resolved scheduler resources
|
|
19
|
+
- `string` — the name of the schedule to delete
|
|
20
|
+
*/
|
|
21
|
+
type deleteSchedule = (array<Adapter.resolvedResource>, string) => promise<unit>
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
Runtime operations exposed by a `Scheduler` component.
|
|
25
|
+
|
|
26
|
+
Injected into extension points, tasks, and the plugin to create or delete
|
|
27
|
+
schedules dynamically at runtime.
|
|
28
|
+
*/
|
|
29
|
+
type operations = {
|
|
30
|
+
createSchedule: createSchedule,
|
|
31
|
+
deleteSchedule: deleteSchedule,
|
|
32
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Deploy-time outputs produced when a `StateChangeSlice` is provisioned.
|
|
3
|
+
Contains the underlying command queue infrastructure resources.
|
|
4
|
+
*/
|
|
5
|
+
type outputs = {
|
|
6
|
+
resources: array<Adapter.resource>,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
Runtime operations exposed by a `StateChangeSlice` component.
|
|
11
|
+
Used to publish commands to this slice's command topic.
|
|
12
|
+
*/
|
|
13
|
+
type operations = {publishJsons: CommandTopic.publishJsons}
|
|
14
|
+
|
|
15
|
+
type t
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
Module type produced by `Platform.StateChangeSlice.Make(Spec, Behavior)`.
|
|
19
|
+
|
|
20
|
+
@example
|
|
21
|
+
```rescript
|
|
22
|
+
// CatalogPlugin.res
|
|
23
|
+
module AddCategorySlice = Platform.StateChangeSlice.Make(AddCategory, AddCategory_Behavior)
|
|
24
|
+
let slice = AddCategorySlice.make(~dcbEventLog=log, ~publishJsons=publishJsonsOutput)
|
|
25
|
+
```
|
|
26
|
+
*/
|
|
27
|
+
module type T = {
|
|
28
|
+
module Spec: Reventless.StateChangeSlice.Spec
|
|
29
|
+
module Behavior: Reventless.StateChangeSlice.Behavior with module Spec := Spec
|
|
30
|
+
/** `true` when built with `Platform.StateChangeSlice.MakeAsync` — uses FIFO channel, returns `CommandPending`. */
|
|
31
|
+
let isAsync: bool
|
|
32
|
+
type component = Component.t<t, outputs, operations>
|
|
33
|
+
let make: (
|
|
34
|
+
~dcbEventLog: DcbEventLog.component,
|
|
35
|
+
~publishJsons: Pulumi.Output.t<CommandTopic.publishJsons>,
|
|
36
|
+
/** Produced event-log type→tag-key map, used to drop vacuous (type, tag)
|
|
37
|
+
clause combinations when building the decision-model query. */
|
|
38
|
+
~tagKeysByEventType: Dict.t<array<string>>=?,
|
|
39
|
+
/** Tag keys declared `@crossPartition` across the produced event schemas —
|
|
40
|
+
a cross-partition scalar command tag fans out into its own single-tag
|
|
41
|
+
decision-read clause. */
|
|
42
|
+
~crossPartitionTagKeys: array<string>=?,
|
|
43
|
+
~opts: Pulumi.ComponentResource.options=?,
|
|
44
|
+
) => component
|
|
45
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Deploy-time outputs produced when a `StateViewSlice` is provisioned.
|
|
3
|
+
|
|
4
|
+
- `resources` — the underlying infrastructure (e.g. SQS subscription)
|
|
5
|
+
- `queryDb` — the DynamoDB table for querying projected state
|
|
6
|
+
*/
|
|
7
|
+
type outputs = {
|
|
8
|
+
resources: array<Adapter.resource>,
|
|
9
|
+
queryDb: QueryDb.outputs,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
Runtime operations exposed by a `StateViewSlice` component.
|
|
14
|
+
Used to push events into the slice's projection queue.
|
|
15
|
+
*/
|
|
16
|
+
type operations = {enqueueEvent: EventCollector.enqueueEvent}
|
|
17
|
+
|
|
18
|
+
type t
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
Module type produced by `Platform.StateViewSlice.Make(Spec, Projection)`.
|
|
22
|
+
|
|
23
|
+
@example
|
|
24
|
+
```rescript
|
|
25
|
+
// CatalogPlugin.res
|
|
26
|
+
module CategoriesViewSlice = Platform.StateViewSlice.Make(CategoriesView, CategoriesView_Projection)
|
|
27
|
+
let slice = CategoriesViewSlice.make(~dcbEventLog=log)
|
|
28
|
+
```
|
|
29
|
+
*/
|
|
30
|
+
module type T = {
|
|
31
|
+
module Spec: Reventless.StateViewSlice.Spec
|
|
32
|
+
module Projection: Reventless.StateViewSlice.Projection with module Spec := Spec
|
|
33
|
+
type component = Component.t<t, outputs, operations>
|
|
34
|
+
let make: (
|
|
35
|
+
~dcbEventLog: DcbEventLog.component,
|
|
36
|
+
~opts: Pulumi.ComponentResource.options=?,
|
|
37
|
+
) => component
|
|
38
|
+
}
|