Reventless — Framework Developer Guide
This guide is for contributors to the reventless-core package — the cloud-agnostic framework core that application developers build on top of.
If you are building an application with Reventless, see the App Developer Guide. If you are writing a new cloud provider adapter package, see the Infrastructure Guide.
What the Framework Is
The reventless-core package defines:
- Component module types (
Aggregate.T,ReadModel.T,Plugin.T, etc.) — the contracts that all implementations must satisfy - Builder functors (
Aggregate_Builder.Make,ReadModel_Builder.Make, etc.) — generic implementations parameterized over adapter interfaces - Adapter interfaces (
EventLog_Adapter.Storage,CommandTopic_Adapter.Channel, etc.) — the contracts that cloud providers must implement - Spec types (
Aggregate.Spec,ReadModel.Spec, etc.) — the contracts that application developers implement
The framework itself does not depend on any cloud provider. All infrastructure concerns are injected through adapter interfaces.
Repository Structure
The monorepo has four package roots; framework packages live under reventless/. See the
generated Packages page for the full, always-current list.
reventless/
├── reventless-spec/ # Type specs and shared interfaces (no impl)
├── reventless-core/ # Framework core (this package)
│ └── src/
│ ├── components/ # Component definitions and builders
│ │ ├── Aggregate/
│ │ ├── ReadModel/
│ │ ├── Plugin/
│ │ └── ...
│ ├── admin/ # Built-in Platform Admin components
│ └── adapter/ # Adapter interfaces and runtime builders
├── reventless-aws/ # AWS cloud provider implementation
└── reventless-local/ # Local (in-memory / SQLite) provider
Key Abstractions
Component Structure Pattern
Each component follows a consistent file structure — two required files (Component.res,
Component_Builder.res) plus up to three optional ones (_Adapter, _Operations,
_Callback). See Component Structure Pattern
for the full breakdown and a walkthrough using EventLog as an example.
Pulumi.Output.t Wrapping
All infrastructure values are wrapped in Pulumi.Output.t<'a>. This separates deploy-time values (which may not be resolved yet) from runtime values. Adapter interfaces return Pulumi.Output.t-wrapped values; the framework composes them using Pulumi.Output.apply.
Builder Pattern with Module Types
Components use first-class modules and functors for type-safe configuration:
module type T = {
module Spec: Reventless.Aggregate.Spec
let make: (~opts: Pulumi.ComponentResource.options=?) => component
}
module Make = (Spec: Spec, Storage: Storage, Channel: Channel): T => { ... }
Where to Start
- Contributing setup — clone, build, and run tests
- Framework internals — the ordered tour of how the framework fits together
- Component structure pattern — the file pattern used across all components
- Extending the framework — add a component or a provider adapter