@reventlessdev/reventless-infra 3.0.0-alpha.96 → 3.0.0-alpha.97
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +92 -0
- package/package.json +18 -7
- package/rescript.json +7 -1
- package/src/components/DeployBootstrap.res +83 -0
- package/src/components/DeployBootstrap.res.mjs +69 -0
- package/tests/DeployBootstrapTest.res +72 -0
- package/tests/DeployBootstrapTest.res.mjs +100 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# 3.0.0-alpha.97 (2026-07-11)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **infra:** add DeployBootstrap seam for generated deploy programs ([f0dc868](https://github.com/ReventlessDev/reventless-core/commit/f0dc8686396d21e7b39667eb0825b2e57fe4dabf))
|
|
11
|
+
|
|
12
|
+
|
|
6
13
|
# 3.0.0-alpha.96 (2026-07-11)
|
|
7
14
|
|
|
8
15
|
**Note:** Version bump only for package @reventlessdev/reventless-infra
|
package/README.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
[](https://www.npmjs.com/package/@reventlessdev/reventless-infra)
|
|
2
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
3
|
+
[](https://docs.reventless.dev)
|
|
4
|
+
|
|
5
|
+
# @reventlessdev/reventless-infra
|
|
6
|
+
|
|
7
|
+
> ⚠️ **Alpha.** APIs and on-disk formats can change without notice between releases.
|
|
8
|
+
> Pin exact versions and expect breaking changes.
|
|
9
|
+
|
|
10
|
+
The **infrastructure type layer** of [Reventless](https://docs.reventless.dev) — a
|
|
11
|
+
spec-driven, event-sourced CQRS framework written in [ReScript](https://rescript-lang.org).
|
|
12
|
+
This package defines the deploy-time infrastructure types and abstract `Platform` interface
|
|
13
|
+
that are shared across storage/cloud adapters, so plugin-assembly code can be written once
|
|
14
|
+
against provider-agnostic types and satisfied by any concrete adapter. It uses
|
|
15
|
+
[Pulumi](https://www.pulumi.com) types for deploy-time resource references. Modules are
|
|
16
|
+
exposed under the `ReventlessInfra` namespace.
|
|
17
|
+
|
|
18
|
+
## What it provides
|
|
19
|
+
|
|
20
|
+
ReScript modules, consumed by adding the package to your `rescript.json` `dependencies`.
|
|
21
|
+
|
|
22
|
+
**Platform interface & adapters (`types/`, `adapter/`)**
|
|
23
|
+
|
|
24
|
+
- **`Platform`** — the abstract factory interface for platform-agnostic component assembly.
|
|
25
|
+
Plugin code takes a `Platform.T` as a functor argument; a concrete adapter (e.g.
|
|
26
|
+
`reventless-aws`) supplies the implementation at the composition root.
|
|
27
|
+
- **`Adapter`** — deploy-time infrastructure primitives: `resource` (fields wrapped in
|
|
28
|
+
`Pulumi.Output.t`), `resolvedResource` (runtime values), and `resourceInfo` describing a
|
|
29
|
+
resource's structural role (storage keys, stream source, API resolver).
|
|
30
|
+
- **`ResourceNaming`** — provider-agnostic operations for validating and deriving
|
|
31
|
+
URN-safe resource names.
|
|
32
|
+
- **`ExtensionMapping`** / **`ExtensionPointMapping`** — the action types that route commands
|
|
33
|
+
and events between an extension and the extension point it wraps.
|
|
34
|
+
- **`Message`**, **`PluginExtensionPointSpec`**, **`NoEventMappings`** — supporting types for
|
|
35
|
+
message identity and plugin/extension wiring.
|
|
36
|
+
|
|
37
|
+
**Component types (`components/`)**
|
|
38
|
+
|
|
39
|
+
Deploy-time `outputs` (infrastructure references) and runtime `operations` for each Reventless
|
|
40
|
+
component kind — **`Component`** (the typed wrapper around a Pulumi `ComponentResource`),
|
|
41
|
+
**`Plugin`**, **`Aggregate`**, **`ReadModel`**, **`EventLog`** / **`DcbEventLog`**,
|
|
42
|
+
**`CommandTopic`** / **`EventTopic`**, **`CommandGenerator`**, **`EventCollector`**,
|
|
43
|
+
**`EventMapper`**, **`QueryDb`**, **`Api`**, **`Task`**, **`ExtensionPoint`** / **`Extension`**,
|
|
44
|
+
**`Scheduler`**, **`Heartbeat`**, and the DCB slices.
|
|
45
|
+
|
|
46
|
+
## Where it fits
|
|
47
|
+
|
|
48
|
+
`reventless-infra` sits between the specification layer and the concrete adapters:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
reventless-spec (specifications)
|
|
52
|
+
↓
|
|
53
|
+
reventless-infra (shared infrastructure types) ← this package
|
|
54
|
+
↓
|
|
55
|
+
reventless-aws / reventless-postgres / reventless-local (storage & deployment adapters)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
- It builds on
|
|
59
|
+
[`@reventlessdev/reventless-spec`](https://www.npmjs.com/package/@reventlessdev/reventless-spec)
|
|
60
|
+
for the domain contracts.
|
|
61
|
+
- Adapters such as
|
|
62
|
+
[`@reventlessdev/reventless-aws`](https://www.npmjs.com/package/@reventlessdev/reventless-aws)
|
|
63
|
+
provide the concrete `Platform.T` implementation these types describe.
|
|
64
|
+
|
|
65
|
+
You normally obtain `reventless-infra` transitively by scaffolding an app rather than
|
|
66
|
+
installing it on its own.
|
|
67
|
+
|
|
68
|
+
## Install
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pnpm add @reventlessdev/reventless-infra
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Then register it as a ReScript dependency in `rescript.json`:
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"dependencies": ["@reventlessdev/reventless-infra"]
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Requires ReScript `^12.3.0` (peer dependency).
|
|
83
|
+
|
|
84
|
+
## Links
|
|
85
|
+
|
|
86
|
+
- 📚 Documentation — [docs.reventless.dev](https://docs.reventless.dev)
|
|
87
|
+
- 📦 Repository — [ReventlessDev/reventless-core](https://github.com/ReventlessDev/reventless-core)
|
|
88
|
+
- 📋 [Changelog](./CHANGELOG.md)
|
|
89
|
+
|
|
90
|
+
## License
|
|
91
|
+
|
|
92
|
+
[Apache-2.0](https://opensource.org/licenses/Apache-2.0)
|
package/package.json
CHANGED
|
@@ -1,19 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reventlessdev/reventless-infra",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.97",
|
|
4
4
|
"description": "Infrastructure types for Reventless framework",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
|
+
"jest": {
|
|
7
|
+
"testMatch": [
|
|
8
|
+
"<rootDir>/tests/**/*Test.res.mjs"
|
|
9
|
+
],
|
|
10
|
+
"moduleFileExtensions": [
|
|
11
|
+
"js",
|
|
12
|
+
"mjs"
|
|
13
|
+
]
|
|
14
|
+
},
|
|
6
15
|
"dependencies": {
|
|
7
16
|
"sury": "11.0.0-alpha.4",
|
|
8
17
|
"sury-ppx": "11.0.0-alpha.2",
|
|
9
18
|
"uuid": "^13.0.0",
|
|
10
|
-
"@reventlessdev/rescript-effect": "0.1.0-alpha.
|
|
11
|
-
"@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.
|
|
12
|
-
"@reventlessdev/reventless-spec": "3.0.0-alpha.
|
|
13
|
-
"@reventlessdev/rescript-uuid": "1.1.0-alpha.
|
|
19
|
+
"@reventlessdev/rescript-effect": "0.1.0-alpha.27",
|
|
20
|
+
"@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.15",
|
|
21
|
+
"@reventlessdev/reventless-spec": "3.0.0-alpha.75",
|
|
22
|
+
"@reventlessdev/rescript-uuid": "1.1.0-alpha.15"
|
|
14
23
|
},
|
|
15
24
|
"devDependencies": {
|
|
16
|
-
"rescript": "^12.3.0"
|
|
25
|
+
"rescript": "^12.3.0",
|
|
26
|
+
"@reventlessdev/rescript-jest": "1.0.0-alpha.7"
|
|
17
27
|
},
|
|
18
28
|
"peerDependencies": {
|
|
19
29
|
"rescript": "^12.3.0"
|
|
@@ -30,6 +40,7 @@
|
|
|
30
40
|
"build": "rescript build",
|
|
31
41
|
"start": "rescript watch",
|
|
32
42
|
"clean": "rescript clean",
|
|
33
|
-
"rebuild": "pnpm run clean && pnpm run build"
|
|
43
|
+
"rebuild": "pnpm run clean && pnpm run build",
|
|
44
|
+
"test": "NODE_OPTIONS='--experimental-vm-modules' jest"
|
|
34
45
|
}
|
|
35
46
|
}
|
package/rescript.json
CHANGED
|
@@ -15,6 +15,11 @@
|
|
|
15
15
|
{
|
|
16
16
|
"dir": "src",
|
|
17
17
|
"subdirs": true
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"dir": "tests",
|
|
21
|
+
"subdirs": true,
|
|
22
|
+
"type": "dev"
|
|
18
23
|
}
|
|
19
24
|
],
|
|
20
25
|
"dependencies": [
|
|
@@ -22,7 +27,8 @@
|
|
|
22
27
|
"@reventlessdev/rescript-pulumi-pulumi",
|
|
23
28
|
"@reventlessdev/rescript-effect",
|
|
24
29
|
"@reventlessdev/rescript-uuid",
|
|
25
|
-
"@reventlessdev/reventless-spec"
|
|
30
|
+
"@reventlessdev/reventless-spec",
|
|
31
|
+
"@reventlessdev/rescript-jest"
|
|
26
32
|
],
|
|
27
33
|
"suffix": ".res.mjs"
|
|
28
34
|
}
|
|
@@ -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,72 @@
|
|
|
1
|
+
open JestGlobals
|
|
2
|
+
|
|
3
|
+
module DB = DeployBootstrap
|
|
4
|
+
|
|
5
|
+
describe("DeployBootstrap", () => {
|
|
6
|
+
// The seam holds module-level state, so each case resets first for isolation.
|
|
7
|
+
describe("run with no registrations", () => {
|
|
8
|
+
testSync("is a no-op that does not throw", () => {
|
|
9
|
+
DB.reset()
|
|
10
|
+
DB.run(PreDeploy)
|
|
11
|
+
DB.run(PostDeploy)
|
|
12
|
+
expect(true)->toBe(true)
|
|
13
|
+
})
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
describe("registration order within a phase", () => {
|
|
17
|
+
testSync("runs contributions in the order they were registered", () => {
|
|
18
|
+
DB.reset()
|
|
19
|
+
let calls = []
|
|
20
|
+
DB.register(() => calls->Array.push("a"))
|
|
21
|
+
DB.register(() => calls->Array.push("b"))
|
|
22
|
+
DB.register(() => calls->Array.push("c"))
|
|
23
|
+
DB.run(PreDeploy)
|
|
24
|
+
expect(calls)->toEqual(["a", "b", "c"])
|
|
25
|
+
})
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
describe("phase isolation", () => {
|
|
29
|
+
testSync("run(PreDeploy) fires only PreDeploy contributions", () => {
|
|
30
|
+
DB.reset()
|
|
31
|
+
let calls = []
|
|
32
|
+
DB.register(~phase=PreDeploy, () => calls->Array.push("pre"))
|
|
33
|
+
DB.register(~phase=PostDeploy, () => calls->Array.push("post"))
|
|
34
|
+
DB.run(PreDeploy)
|
|
35
|
+
expect(calls)->toEqual(["pre"])
|
|
36
|
+
DB.run(PostDeploy)
|
|
37
|
+
expect(calls)->toEqual(["pre", "post"])
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
testSync("defaults to PreDeploy when no phase is given", () => {
|
|
41
|
+
DB.reset()
|
|
42
|
+
let calls = []
|
|
43
|
+
DB.register(() => calls->Array.push("default"))
|
|
44
|
+
DB.run(PostDeploy)
|
|
45
|
+
expect(calls)->toEqual([])
|
|
46
|
+
DB.run(PreDeploy)
|
|
47
|
+
expect(calls)->toEqual(["default"])
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
describe("idempotent run per phase", () => {
|
|
52
|
+
testSync("running an already-run phase does nothing", () => {
|
|
53
|
+
DB.reset()
|
|
54
|
+
let count = ref(0)
|
|
55
|
+
DB.register(() => count := count.contents + 1)
|
|
56
|
+
DB.run(PreDeploy)
|
|
57
|
+
DB.run(PreDeploy)
|
|
58
|
+
DB.run(PreDeploy)
|
|
59
|
+
expect(count.contents)->toBe(1)
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
testSync("a contribution registered after run does not fire", () => {
|
|
63
|
+
DB.reset()
|
|
64
|
+
let calls = []
|
|
65
|
+
DB.register(() => calls->Array.push("before"))
|
|
66
|
+
DB.run(PreDeploy)
|
|
67
|
+
DB.register(() => calls->Array.push("after"))
|
|
68
|
+
DB.run(PreDeploy)
|
|
69
|
+
expect(calls)->toEqual(["before"])
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
})
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as DeployBootstrap$ReventlessInfra from "../src/components/DeployBootstrap.res.mjs";
|
|
4
|
+
|
|
5
|
+
globalThis.describe("DeployBootstrap", () => {
|
|
6
|
+
globalThis.describe("run with no registrations", () => {
|
|
7
|
+
globalThis.test("is a no-op that does not throw", () => {
|
|
8
|
+
DeployBootstrap$ReventlessInfra.reset();
|
|
9
|
+
DeployBootstrap$ReventlessInfra.run("PreDeploy");
|
|
10
|
+
DeployBootstrap$ReventlessInfra.run("PostDeploy");
|
|
11
|
+
globalThis.expect(true).toBe(true);
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
globalThis.describe("registration order within a phase", () => {
|
|
15
|
+
globalThis.test("runs contributions in the order they were registered", () => {
|
|
16
|
+
DeployBootstrap$ReventlessInfra.reset();
|
|
17
|
+
let calls = [];
|
|
18
|
+
DeployBootstrap$ReventlessInfra.register(undefined, () => {
|
|
19
|
+
calls.push("a");
|
|
20
|
+
});
|
|
21
|
+
DeployBootstrap$ReventlessInfra.register(undefined, () => {
|
|
22
|
+
calls.push("b");
|
|
23
|
+
});
|
|
24
|
+
DeployBootstrap$ReventlessInfra.register(undefined, () => {
|
|
25
|
+
calls.push("c");
|
|
26
|
+
});
|
|
27
|
+
DeployBootstrap$ReventlessInfra.run("PreDeploy");
|
|
28
|
+
globalThis.expect(calls).toEqual([
|
|
29
|
+
"a",
|
|
30
|
+
"b",
|
|
31
|
+
"c"
|
|
32
|
+
]);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
globalThis.describe("phase isolation", () => {
|
|
36
|
+
globalThis.test("run(PreDeploy) fires only PreDeploy contributions", () => {
|
|
37
|
+
DeployBootstrap$ReventlessInfra.reset();
|
|
38
|
+
let calls = [];
|
|
39
|
+
DeployBootstrap$ReventlessInfra.register("PreDeploy", () => {
|
|
40
|
+
calls.push("pre");
|
|
41
|
+
});
|
|
42
|
+
DeployBootstrap$ReventlessInfra.register("PostDeploy", () => {
|
|
43
|
+
calls.push("post");
|
|
44
|
+
});
|
|
45
|
+
DeployBootstrap$ReventlessInfra.run("PreDeploy");
|
|
46
|
+
globalThis.expect(calls).toEqual(["pre"]);
|
|
47
|
+
DeployBootstrap$ReventlessInfra.run("PostDeploy");
|
|
48
|
+
globalThis.expect(calls).toEqual([
|
|
49
|
+
"pre",
|
|
50
|
+
"post"
|
|
51
|
+
]);
|
|
52
|
+
});
|
|
53
|
+
globalThis.test("defaults to PreDeploy when no phase is given", () => {
|
|
54
|
+
DeployBootstrap$ReventlessInfra.reset();
|
|
55
|
+
let calls = [];
|
|
56
|
+
DeployBootstrap$ReventlessInfra.register(undefined, () => {
|
|
57
|
+
calls.push("default");
|
|
58
|
+
});
|
|
59
|
+
DeployBootstrap$ReventlessInfra.run("PostDeploy");
|
|
60
|
+
globalThis.expect(calls).toEqual([]);
|
|
61
|
+
DeployBootstrap$ReventlessInfra.run("PreDeploy");
|
|
62
|
+
globalThis.expect(calls).toEqual(["default"]);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
globalThis.describe("idempotent run per phase", () => {
|
|
66
|
+
globalThis.test("running an already-run phase does nothing", () => {
|
|
67
|
+
DeployBootstrap$ReventlessInfra.reset();
|
|
68
|
+
let count = {
|
|
69
|
+
contents: 0
|
|
70
|
+
};
|
|
71
|
+
DeployBootstrap$ReventlessInfra.register(undefined, () => {
|
|
72
|
+
count.contents = count.contents + 1 | 0;
|
|
73
|
+
});
|
|
74
|
+
DeployBootstrap$ReventlessInfra.run("PreDeploy");
|
|
75
|
+
DeployBootstrap$ReventlessInfra.run("PreDeploy");
|
|
76
|
+
DeployBootstrap$ReventlessInfra.run("PreDeploy");
|
|
77
|
+
globalThis.expect(count.contents).toBe(1);
|
|
78
|
+
});
|
|
79
|
+
globalThis.test("a contribution registered after run does not fire", () => {
|
|
80
|
+
DeployBootstrap$ReventlessInfra.reset();
|
|
81
|
+
let calls = [];
|
|
82
|
+
DeployBootstrap$ReventlessInfra.register(undefined, () => {
|
|
83
|
+
calls.push("before");
|
|
84
|
+
});
|
|
85
|
+
DeployBootstrap$ReventlessInfra.run("PreDeploy");
|
|
86
|
+
DeployBootstrap$ReventlessInfra.register(undefined, () => {
|
|
87
|
+
calls.push("after");
|
|
88
|
+
});
|
|
89
|
+
DeployBootstrap$ReventlessInfra.run("PreDeploy");
|
|
90
|
+
globalThis.expect(calls).toEqual(["before"]);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
let DB;
|
|
96
|
+
|
|
97
|
+
export {
|
|
98
|
+
DB,
|
|
99
|
+
}
|
|
100
|
+
/* Not a pure module */
|