@reventlessdev/reventless-aws 3.0.0-alpha.386 → 3.0.0-alpha.387
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/package.json +8 -8
- package/src/Platform.res +7 -0
- package/src/Platform.res.mjs +6 -2
- package/src/util/Util_ShellConfig.res +7 -1
- package/src/util/Util_ShellConfig.res.mjs +8 -2
- package/tests/Util_ShellConfigTest.res +40 -0
- package/tests/Util_ShellConfigTest.res.mjs +76 -21
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.387 (2026-10-19)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **spec,aws,local:** tell the host shell which environment it runs in, and write local host UI files into a chosen assetsDir ([4f896d1](https://github.com/ReventlessDev/reventless-core/commit/4f896d13ae9ec0d211c33dbd9271e7197cfebc41))
|
|
11
|
+
|
|
12
|
+
|
|
6
13
|
# 3.0.0-alpha.386 (2026-10-17)
|
|
7
14
|
|
|
8
15
|
**Note:** Version bump only for package @reventlessdev/reventless-aws
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reventlessdev/reventless-aws",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.387",
|
|
4
4
|
"description": "AWS adapters for Reventless",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"bin": {
|
|
@@ -23,18 +23,18 @@
|
|
|
23
23
|
"uuid": "^13.0.0",
|
|
24
24
|
"yaml": "^2.8.3",
|
|
25
25
|
"@reventlessdev/rescript-aws-sdk": "3.0.0-alpha.32",
|
|
26
|
-
"@reventlessdev/rescript-
|
|
26
|
+
"@reventlessdev/rescript-pulumi-aws": "3.0.0-alpha.30",
|
|
27
27
|
"@reventlessdev/rescript-jest": "1.0.0-alpha.12",
|
|
28
|
+
"@reventlessdev/rescript-effect": "1.0.0-alpha.0",
|
|
28
29
|
"@reventlessdev/rescript-node": "2.0.0-alpha.22",
|
|
29
|
-
"@reventlessdev/rescript-pulumi-aws": "3.0.0-alpha.30",
|
|
30
30
|
"@reventlessdev/rescript-pulumi-pulumi": "3.0.0-alpha.0",
|
|
31
|
-
"@reventlessdev/rescript-uuid": "2.0.0-alpha.1",
|
|
32
31
|
"@reventlessdev/rescript-web": "1.0.0-alpha.7",
|
|
33
|
-
"@reventlessdev/reventless-core": "3.0.0-alpha.
|
|
34
|
-
"@reventlessdev/
|
|
32
|
+
"@reventlessdev/reventless-core": "3.0.0-alpha.300",
|
|
33
|
+
"@reventlessdev/rescript-uuid": "2.0.0-alpha.1",
|
|
34
|
+
"@reventlessdev/reventless-infra": "3.0.0-alpha.197",
|
|
35
|
+
"@reventlessdev/reventless-postgres": "3.0.0-alpha.164",
|
|
35
36
|
"@reventlessdev/reventless-interop": "3.0.0-alpha.41",
|
|
36
|
-
"@reventlessdev/reventless-
|
|
37
|
-
"@reventlessdev/reventless-spec": "3.0.0-alpha.168"
|
|
37
|
+
"@reventlessdev/reventless-spec": "3.0.0-alpha.169"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"rescript": "12.3.1",
|
package/src/Platform.res
CHANGED
|
@@ -2355,6 +2355,12 @@ module MakeWithConfig = (
|
|
|
2355
2355
|
// `platformApiEndpoint`, already present) with the store it declares, so there
|
|
2356
2356
|
// is no per-store URL to publish. The store's *serving* base URL still travels
|
|
2357
2357
|
// in the `objectStores` stack output above.
|
|
2358
|
+
// Outside the apply; the same name the deployment record carries.
|
|
2359
|
+
let shellEnvironment = Reventless.ShellEnvironment.resolve(
|
|
2360
|
+
~provenance=Reventless.DeploymentProvenance.current(),
|
|
2361
|
+
~stack=stackName,
|
|
2362
|
+
~prodStacks=Util_HostUiDomain.resolveProdStacks(),
|
|
2363
|
+
)
|
|
2358
2364
|
let configJsonContent =
|
|
2359
2365
|
(
|
|
2360
2366
|
(
|
|
@@ -2407,6 +2413,7 @@ module MakeWithConfig = (
|
|
|
2407
2413
|
// public Function URL and its config key are both gone.
|
|
2408
2414
|
Util_ShellConfig.fields(
|
|
2409
2415
|
~computed=withEvents,
|
|
2416
|
+
~environment=shellEnvironment,
|
|
2410
2417
|
~viewModes=?cfg.viewModes,
|
|
2411
2418
|
~bakedManifest=?cfg.bakedManifest,
|
|
2412
2419
|
~uiSlotsFile=?cfg.uiSlotsFile,
|
package/src/Platform.res.mjs
CHANGED
|
@@ -35,6 +35,7 @@ import * as Plugin_Stack$ReventlessAws from "./plugin/stack/Plugin_Stack.res.mjs
|
|
|
35
35
|
import * as UiFragments$ReventlessCore from "@reventlessdev/reventless-core/src/admin/UiFragmentRegistry/StateView/UiFragments.res.mjs";
|
|
36
36
|
import * as Util_Pulumi$ReventlessCore from "@reventlessdev/reventless-core/src/util/Util_Pulumi.res.mjs";
|
|
37
37
|
import * as AccountsManifest$Reventless from "@reventlessdev/reventless-spec/src/types/AccountsManifest.res.mjs";
|
|
38
|
+
import * as ShellEnvironment$Reventless from "@reventlessdev/reventless-spec/src/types/ShellEnvironment.res.mjs";
|
|
38
39
|
import * as Platform_Casts$ReventlessAws from "./Platform_Casts.res.mjs";
|
|
39
40
|
import * as Platform_Stack$ReventlessAws from "./Platform_Stack.res.mjs";
|
|
40
41
|
import * as QueryDbBackend$ReventlessAws from "./adapter/QueryDb/QueryDbBackend.res.mjs";
|
|
@@ -52,6 +53,7 @@ import * as Util_StoreLayout$ReventlessAws from "./util/Util_StoreLayout.res.mjs
|
|
|
52
53
|
import * as IndexJs from "@pulumi/pulumi/runtime/index.js";
|
|
53
54
|
import * as AppSync_EventsApi$ReventlessAws from "./adapter/Api/AppSync_EventsApi.res.mjs";
|
|
54
55
|
import * as AppSync_MergedApi$ReventlessAws from "./components/Api/AppSync_MergedApi.res.mjs";
|
|
56
|
+
import * as DeploymentProvenance$Reventless from "@reventlessdev/reventless-spec/src/types/DeploymentProvenance.res.mjs";
|
|
55
57
|
import * as GraphQL_Stitcher$ReventlessCore from "@reventlessdev/reventless-core/src/components/Api/GraphQL_Stitcher.res.mjs";
|
|
56
58
|
import * as NoEventMappings$ReventlessInfra from "@reventlessdev/reventless-infra/src/types/NoEventMappings.res.mjs";
|
|
57
59
|
import * as Platform_UiSlots$ReventlessCore from "@reventlessdev/reventless-core/src/admin/Platform_UiSlots.res.mjs";
|
|
@@ -1235,6 +1237,7 @@ function MakeWithConfig(Config) {
|
|
|
1235
1237
|
if (capabilities.includes("Messaging") && !emailSenderProvisioned) {
|
|
1236
1238
|
Stdlib_JsError.throwWithMessage(`A plugin of this deployment declares the Messaging capability, but this platform provisions no email sender.\n The sender is configuration and has no default: set \`platform:messagingEmailSender\` in Pulumi.<stack>.yaml (or the env var REVENTLESS_MESSAGING_EMAIL_SENDER), then verify the address with SES.\n A stack that should not mail anybody sets \`platform:messagingEmailProvider: log\` instead — every message is logged and none is sent, and the address is optional.\n The root must also pass \`~messagingSender\` in \`~hostUiBundle\`, from \`ReventlessAws.Capability_Messaging.make(~name=…)\`.\n The declaration is generated from the plugins' capabilities.json — regenerate with \`pnpm run generate:platform\` if it is stale.`);
|
|
1237
1239
|
}
|
|
1240
|
+
let shellEnvironment = ShellEnvironment$Reventless.resolve(DeploymentProvenance$Reventless.current(), stackName, Util_HostUiDomain$ReventlessAws.resolveProdStacks());
|
|
1238
1241
|
let configJsonContent = Pulumi.all([
|
|
1239
1242
|
Pulumi.all([
|
|
1240
1243
|
resolvedDomainApiEndpoint,
|
|
@@ -1286,7 +1289,7 @@ function MakeWithConfig(Config) {
|
|
|
1286
1289
|
AppSync_EventsApi$ReventlessAws.clientNamespaceName
|
|
1287
1290
|
]
|
|
1288
1291
|
]) : computed;
|
|
1289
|
-
return JSON.stringify(Util_ShellConfig$ReventlessAws.fields(withEvents, hostUiBundle.viewModes, hostUiBundle.bakedManifest, hostUiBundle.uiSlotsFile, hostUiBundle.shellConfig));
|
|
1292
|
+
return JSON.stringify(Util_ShellConfig$ReventlessAws.fields(withEvents, shellEnvironment, hostUiBundle.viewModes, hostUiBundle.bakedManifest, hostUiBundle.uiSlotsFile, hostUiBundle.shellConfig));
|
|
1290
1293
|
});
|
|
1291
1294
|
let bootFileCacheControl = "no-cache";
|
|
1292
1295
|
new (Aws.s3.BucketObject)("host-ui-config-json", {
|
|
@@ -2628,6 +2631,7 @@ function Make($star) {
|
|
|
2628
2631
|
if (capabilities.includes("Messaging") && !emailSenderProvisioned) {
|
|
2629
2632
|
Stdlib_JsError.throwWithMessage(`A plugin of this deployment declares the Messaging capability, but this platform provisions no email sender.\n The sender is configuration and has no default: set \`platform:messagingEmailSender\` in Pulumi.<stack>.yaml (or the env var REVENTLESS_MESSAGING_EMAIL_SENDER), then verify the address with SES.\n A stack that should not mail anybody sets \`platform:messagingEmailProvider: log\` instead — every message is logged and none is sent, and the address is optional.\n The root must also pass \`~messagingSender\` in \`~hostUiBundle\`, from \`ReventlessAws.Capability_Messaging.make(~name=…)\`.\n The declaration is generated from the plugins' capabilities.json — regenerate with \`pnpm run generate:platform\` if it is stale.`);
|
|
2630
2633
|
}
|
|
2634
|
+
let shellEnvironment = ShellEnvironment$Reventless.resolve(DeploymentProvenance$Reventless.current(), stackName, Util_HostUiDomain$ReventlessAws.resolveProdStacks());
|
|
2631
2635
|
let configJsonContent = Pulumi.all([
|
|
2632
2636
|
Pulumi.all([
|
|
2633
2637
|
resolvedDomainApiEndpoint,
|
|
@@ -2679,7 +2683,7 @@ function Make($star) {
|
|
|
2679
2683
|
AppSync_EventsApi$ReventlessAws.clientNamespaceName
|
|
2680
2684
|
]
|
|
2681
2685
|
]) : computed;
|
|
2682
|
-
return JSON.stringify(Util_ShellConfig$ReventlessAws.fields(withEvents, hostUiBundle.viewModes, hostUiBundle.bakedManifest, hostUiBundle.uiSlotsFile, hostUiBundle.shellConfig));
|
|
2686
|
+
return JSON.stringify(Util_ShellConfig$ReventlessAws.fields(withEvents, shellEnvironment, hostUiBundle.viewModes, hostUiBundle.bakedManifest, hostUiBundle.uiSlotsFile, hostUiBundle.shellConfig));
|
|
2683
2687
|
});
|
|
2684
2688
|
let bootFileCacheControl = "no-cache";
|
|
2685
2689
|
new (Aws.s3.BucketObject)("host-ui-config-json", {
|
|
@@ -81,7 +81,8 @@ let subscriptionEndpoint = (httpsEndpoint: string): string =>
|
|
|
81
81
|
/**
|
|
82
82
|
The config.json field set.
|
|
83
83
|
|
|
84
|
-
`computed` arrives in wire order and keeps it
|
|
84
|
+
`computed` arrives in wire order and keeps it; `environment` follows it, its
|
|
85
|
+
purpose key only when the purpose is known. `viewModes` unset ⇒ no
|
|
85
86
|
`viewModes` key and no per-mode key, so a deployment that wants no optional mode
|
|
86
87
|
gets byte-identical output to before this input existed. `bakedManifest` unset ⇒
|
|
87
88
|
no `manifestUrl`, and every caller keeps the admin discovery path. `shellConfig`
|
|
@@ -91,6 +92,7 @@ somewhere unintended with nothing in the diff to say so.
|
|
|
91
92
|
*/
|
|
92
93
|
let fields = (
|
|
93
94
|
~computed: array<(string, JSON.t)>,
|
|
95
|
+
~environment: option<Reventless.ShellEnvironment.t>=?,
|
|
94
96
|
~viewModes: option<array<Platform.viewMode>>=?,
|
|
95
97
|
~bakedManifest: option<Platform.bakedManifest>=?,
|
|
96
98
|
~uiSlotsFile: option<string>=?,
|
|
@@ -98,6 +100,10 @@ let fields = (
|
|
|
98
100
|
): dict<JSON.t> => {
|
|
99
101
|
let out = computed->Dict.fromArray
|
|
100
102
|
|
|
103
|
+
environment->Option.forEach(env =>
|
|
104
|
+
env->Reventless.ShellEnvironment.configFields->Array.forEach(((k, v)) => out->Dict.set(k, v))
|
|
105
|
+
)
|
|
106
|
+
|
|
101
107
|
// Computed, like the endpoints: the group the admin API is gated on, from the
|
|
102
108
|
// deploy's own role mapping.
|
|
103
109
|
ReventlessCore.Platform_AdminGroup.configEntry()->Option.forEach(((k, v)) => out->Dict.set(k, v))
|
|
@@ -4,6 +4,7 @@ import * as Pervasives from "@rescript/runtime/lib/es6/Pervasives.js";
|
|
|
4
4
|
import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
|
|
5
5
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
6
6
|
import * as Platform$ReventlessInfra from "@reventlessdev/reventless-infra/src/types/Platform.res.mjs";
|
|
7
|
+
import * as ShellEnvironment$Reventless from "@reventlessdev/reventless-spec/src/types/ShellEnvironment.res.mjs";
|
|
7
8
|
import * as Platform_UiSlots$ReventlessCore from "@reventlessdev/reventless-core/src/admin/Platform_UiSlots.res.mjs";
|
|
8
9
|
import * as Platform_AdminGroup$ReventlessCore from "@reventlessdev/reventless-core/src/admin/Platform_AdminGroup.res.mjs";
|
|
9
10
|
import * as Platform_BakedManifest$ReventlessCore from "@reventlessdev/reventless-core/src/admin/Platform_BakedManifest.res.mjs";
|
|
@@ -58,8 +59,13 @@ function subscriptionEndpoint(httpsEndpoint) {
|
|
|
58
59
|
return httpsEndpoint.replace("https://", "wss://").replace(".appsync-api.", ".appsync-realtime-api.");
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
function fields(computed, viewModes, bakedManifest, uiSlotsFile, shellConfig) {
|
|
62
|
+
function fields(computed, environment, viewModes, bakedManifest, uiSlotsFile, shellConfig) {
|
|
62
63
|
let out = Object.fromEntries(computed);
|
|
64
|
+
Stdlib_Option.forEach(environment, env => {
|
|
65
|
+
ShellEnvironment$Reventless.configFields(env).forEach(param => {
|
|
66
|
+
out[param[0]] = param[1];
|
|
67
|
+
});
|
|
68
|
+
});
|
|
63
69
|
Stdlib_Option.forEach(Platform_AdminGroup$ReventlessCore.configEntry(), param => {
|
|
64
70
|
out[param[0]] = param[1];
|
|
65
71
|
});
|
|
@@ -107,4 +113,4 @@ export {
|
|
|
107
113
|
subscriptionEndpoint,
|
|
108
114
|
fields,
|
|
109
115
|
}
|
|
110
|
-
/*
|
|
116
|
+
/* ShellEnvironment-Reventless Not a pure module */
|
|
@@ -226,6 +226,46 @@ describe("Util_ShellConfig.fields — journeys", () => {
|
|
|
226
226
|
})
|
|
227
227
|
})
|
|
228
228
|
|
|
229
|
+
// The shell badges every environment that is not production, so a purpose that
|
|
230
|
+
// went missing shows as a badge rather than as nothing.
|
|
231
|
+
describe("Util_ShellConfig.fields — environment", () => {
|
|
232
|
+
testSync("the name and the purpose follow the computed keys", () => {
|
|
233
|
+
let out = Util_ShellConfig.fields(~computed, ~environment={name: "test", purpose: Some("test")})
|
|
234
|
+
expect(out->Dict.keysToArray)->toEqual([
|
|
235
|
+
"apiEndpoint",
|
|
236
|
+
"region",
|
|
237
|
+
"environment",
|
|
238
|
+
"environmentPurpose",
|
|
239
|
+
])
|
|
240
|
+
expect((out->get("environment"), out->get("environmentPurpose")))->toEqual((
|
|
241
|
+
JSON.Encode.string("test"),
|
|
242
|
+
JSON.Encode.string("test"),
|
|
243
|
+
))
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
testSync("an unknown purpose leaves its key out", () => {
|
|
247
|
+
let out = Util_ShellConfig.fields(~computed, ~environment={name: "alpha", purpose: None})
|
|
248
|
+
expect(out->Dict.get("environmentPurpose")->Option.isNone)->toBe(true)
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
testSync("a shellConfig environment fails the deploy rather than renaming it", () => {
|
|
252
|
+
let failure = try {
|
|
253
|
+
let _ = Util_ShellConfig.fields(
|
|
254
|
+
~computed,
|
|
255
|
+
~environment={name: "prod", purpose: Some("production")},
|
|
256
|
+
~shellConfig=Dict.fromArray([("environment", JSON.Encode.string("staging"))]),
|
|
257
|
+
)
|
|
258
|
+
None
|
|
259
|
+
} catch {
|
|
260
|
+
| Failure(message) => Some(message)
|
|
261
|
+
}
|
|
262
|
+
switch failure {
|
|
263
|
+
| Some(message) => expect(message->String.includes("environment"))->toBe(true)
|
|
264
|
+
| None => fail("a shellConfig key renaming the computed environment must fail the deploy")
|
|
265
|
+
}
|
|
266
|
+
})
|
|
267
|
+
})
|
|
268
|
+
|
|
229
269
|
describe("Util_ShellConfig.fields — shellConfig passthrough", () => {
|
|
230
270
|
testSync("shell-owned keys land verbatim, under the computed ones", () => {
|
|
231
271
|
let out = Util_ShellConfig.fields(
|
|
@@ -28,7 +28,7 @@ function get(out, key) {
|
|
|
28
28
|
|
|
29
29
|
globalThis.describe("Util_ShellConfig.fields — viewModes", () => {
|
|
30
30
|
globalThis.test("unset ⇒ no viewModes key and the computed set is untouched", () => {
|
|
31
|
-
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, undefined, undefined);
|
|
31
|
+
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, undefined, undefined, undefined);
|
|
32
32
|
globalThis.expect(Object.keys(out)).toEqual([
|
|
33
33
|
"apiEndpoint",
|
|
34
34
|
"region"
|
|
@@ -36,7 +36,7 @@ globalThis.describe("Util_ShellConfig.fields — viewModes", () => {
|
|
|
36
36
|
globalThis.expect(Stdlib_Option.isNone(out["viewModes"])).toBe(true);
|
|
37
37
|
});
|
|
38
38
|
globalThis.test("Map with defaults ⇒ the mode, and no mapStyle key", () => {
|
|
39
|
-
let out = Util_ShellConfig$ReventlessAws.fields(computed, [{
|
|
39
|
+
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, [{
|
|
40
40
|
TAG: "Map",
|
|
41
41
|
_0: {}
|
|
42
42
|
}], undefined, undefined, undefined);
|
|
@@ -44,7 +44,7 @@ globalThis.describe("Util_ShellConfig.fields — viewModes", () => {
|
|
|
44
44
|
globalThis.expect(Stdlib_Option.isNone(out["mapStyle"])).toBe(true);
|
|
45
45
|
});
|
|
46
46
|
globalThis.test("per-mode options flatten beside the mode", () => {
|
|
47
|
-
let out = Util_ShellConfig$ReventlessAws.fields(computed, [
|
|
47
|
+
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, [
|
|
48
48
|
{
|
|
49
49
|
TAG: "Map",
|
|
50
50
|
_0: {
|
|
@@ -77,21 +77,21 @@ globalThis.describe("Util_ShellConfig.fields — bakedManifest", () => {
|
|
|
77
77
|
key: key
|
|
78
78
|
});
|
|
79
79
|
globalThis.test("unset ⇒ no manifestUrl, so every caller keeps the admin path", () => {
|
|
80
|
-
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, undefined, undefined);
|
|
80
|
+
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, undefined, undefined, undefined);
|
|
81
81
|
globalThis.expect(Stdlib_Option.isNone(out["manifestUrl"])).toBe(true);
|
|
82
82
|
});
|
|
83
83
|
globalThis.test("declared ⇒ the URL the deploy writes the file to", () => {
|
|
84
|
-
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, bake(undefined), undefined, undefined);
|
|
84
|
+
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, bake(undefined), undefined, undefined);
|
|
85
85
|
globalThis.expect(get(out, "manifestUrl")).toEqual("/component-manifest.json");
|
|
86
86
|
});
|
|
87
87
|
globalThis.test("follows a renamed bake", () => {
|
|
88
|
-
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, bake("storefront.json"), undefined, undefined);
|
|
88
|
+
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, bake("storefront.json"), undefined, undefined);
|
|
89
89
|
globalThis.expect(get(out, "manifestUrl")).toEqual("/storefront.json");
|
|
90
90
|
});
|
|
91
91
|
globalThis.test("a shellConfig manifestUrl fails the deploy rather than redirecting it", () => {
|
|
92
92
|
let failure;
|
|
93
93
|
try {
|
|
94
|
-
Util_ShellConfig$ReventlessAws.fields(computed, undefined, bake(undefined), undefined, Object.fromEntries([[
|
|
94
|
+
Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, bake(undefined), undefined, Object.fromEntries([[
|
|
95
95
|
"manifestUrl",
|
|
96
96
|
"/elsewhere.json"
|
|
97
97
|
]]));
|
|
@@ -115,21 +115,21 @@ globalThis.describe("Util_ShellConfig.fields — bakedManifest", () => {
|
|
|
115
115
|
|
|
116
116
|
globalThis.describe("Util_ShellConfig.fields — uiSlotsFile", () => {
|
|
117
117
|
globalThis.test("unset ⇒ no uiSlotsUrl, and the shell imports nothing", () => {
|
|
118
|
-
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, undefined, undefined);
|
|
118
|
+
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, undefined, undefined, undefined);
|
|
119
119
|
globalThis.expect(Stdlib_Option.isNone(out["uiSlotsUrl"])).toBe(true);
|
|
120
120
|
});
|
|
121
121
|
globalThis.test("declared ⇒ the URL the deploy writes the module to", () => {
|
|
122
|
-
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, "/src/storefront-slots.js", undefined);
|
|
122
|
+
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, undefined, "/src/storefront-slots.js", undefined);
|
|
123
123
|
globalThis.expect(get(out, "uiSlotsUrl")).toEqual("/ui-slots.js");
|
|
124
124
|
});
|
|
125
125
|
globalThis.test("names where the file is served, never where it was authored", () => {
|
|
126
|
-
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, "/home/me/prj/slots.js", undefined);
|
|
126
|
+
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, undefined, "/home/me/prj/slots.js", undefined);
|
|
127
127
|
globalThis.expect(get(out, "uiSlotsUrl")).toEqual("/ui-slots.js");
|
|
128
128
|
});
|
|
129
129
|
globalThis.test("a shellConfig uiSlotsUrl fails the deploy rather than redirecting it", () => {
|
|
130
130
|
let failure;
|
|
131
131
|
try {
|
|
132
|
-
Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, "/src/storefront-slots.js", Object.fromEntries([[
|
|
132
|
+
Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, undefined, "/src/storefront-slots.js", Object.fromEntries([[
|
|
133
133
|
"uiSlotsUrl",
|
|
134
134
|
"/elsewhere.js"
|
|
135
135
|
]]));
|
|
@@ -181,7 +181,7 @@ globalThis.describe("Util_ShellConfig.fields — journeys", () => {
|
|
|
181
181
|
key: fulfilment_key
|
|
182
182
|
};
|
|
183
183
|
globalThis.test("a bake declaring no journeys writes no map", () => {
|
|
184
|
-
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, {
|
|
184
|
+
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, {
|
|
185
185
|
components: [{
|
|
186
186
|
plugin: "Catalog",
|
|
187
187
|
views: ["Products"],
|
|
@@ -191,15 +191,15 @@ globalThis.describe("Util_ShellConfig.fields — journeys", () => {
|
|
|
191
191
|
globalThis.expect(Stdlib_Option.isNone(out["journeyManifestUrls"])).toBe(true);
|
|
192
192
|
});
|
|
193
193
|
globalThis.test("an empty journeys array is the same as none", () => {
|
|
194
|
-
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, withJourneys([]), undefined, undefined);
|
|
194
|
+
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, withJourneys([]), undefined, undefined);
|
|
195
195
|
globalThis.expect(Stdlib_Option.isNone(out["journeyManifestUrls"])).toBe(true);
|
|
196
196
|
});
|
|
197
197
|
globalThis.test("keeps manifestUrl as the default journey", () => {
|
|
198
|
-
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, withJourneys([shopper]), undefined, undefined);
|
|
198
|
+
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, withJourneys([shopper]), undefined, undefined);
|
|
199
199
|
globalThis.expect(get(out, "manifestUrl")).toEqual("/component-manifest.json");
|
|
200
200
|
});
|
|
201
201
|
globalThis.test("maps each declared group to its own file", () => {
|
|
202
|
-
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, withJourneys([
|
|
202
|
+
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, withJourneys([
|
|
203
203
|
shopper,
|
|
204
204
|
fulfilment
|
|
205
205
|
]), undefined, undefined);
|
|
@@ -219,14 +219,14 @@ globalThis.describe("Util_ShellConfig.fields — journeys", () => {
|
|
|
219
219
|
shopper,
|
|
220
220
|
fulfilment
|
|
221
221
|
]);
|
|
222
|
-
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, bake, undefined, undefined);
|
|
222
|
+
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, bake, undefined, undefined);
|
|
223
223
|
let published = Stdlib_Option.mapOr(Stdlib_JSON.Decode.string(get(out, "manifestUrl")), [], url => [url]).concat(Stdlib_Array.filterMap(Object.values(Stdlib_Option.getOr(Stdlib_JSON.Decode.object(get(out, "journeyManifestUrls")), {})), Stdlib_JSON.Decode.string));
|
|
224
224
|
globalThis.expect(published).toEqual(Platform_BakedManifest$ReventlessCore.files(bake).map(param => "/" + param[0]));
|
|
225
225
|
});
|
|
226
226
|
globalThis.test("a shellConfig journey map fails the deploy rather than redirecting it", () => {
|
|
227
227
|
let failure;
|
|
228
228
|
try {
|
|
229
|
-
Util_ShellConfig$ReventlessAws.fields(computed, undefined, withJourneys([shopper]), undefined, Object.fromEntries([[
|
|
229
|
+
Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, withJourneys([shopper]), undefined, Object.fromEntries([[
|
|
230
230
|
"journeyManifestUrls",
|
|
231
231
|
{}
|
|
232
232
|
]]));
|
|
@@ -248,9 +248,64 @@ globalThis.describe("Util_ShellConfig.fields — journeys", () => {
|
|
|
248
248
|
});
|
|
249
249
|
});
|
|
250
250
|
|
|
251
|
+
globalThis.describe("Util_ShellConfig.fields — environment", () => {
|
|
252
|
+
globalThis.test("the name and the purpose follow the computed keys", () => {
|
|
253
|
+
let out = Util_ShellConfig$ReventlessAws.fields(computed, {
|
|
254
|
+
name: "test",
|
|
255
|
+
purpose: "test"
|
|
256
|
+
}, undefined, undefined, undefined, undefined);
|
|
257
|
+
globalThis.expect(Object.keys(out)).toEqual([
|
|
258
|
+
"apiEndpoint",
|
|
259
|
+
"region",
|
|
260
|
+
"environment",
|
|
261
|
+
"environmentPurpose"
|
|
262
|
+
]);
|
|
263
|
+
globalThis.expect([
|
|
264
|
+
get(out, "environment"),
|
|
265
|
+
get(out, "environmentPurpose")
|
|
266
|
+
]).toEqual([
|
|
267
|
+
"test",
|
|
268
|
+
"test"
|
|
269
|
+
]);
|
|
270
|
+
});
|
|
271
|
+
globalThis.test("an unknown purpose leaves its key out", () => {
|
|
272
|
+
let out = Util_ShellConfig$ReventlessAws.fields(computed, {
|
|
273
|
+
name: "alpha",
|
|
274
|
+
purpose: undefined
|
|
275
|
+
}, undefined, undefined, undefined, undefined);
|
|
276
|
+
globalThis.expect(Stdlib_Option.isNone(out["environmentPurpose"])).toBe(true);
|
|
277
|
+
});
|
|
278
|
+
globalThis.test("a shellConfig environment fails the deploy rather than renaming it", () => {
|
|
279
|
+
let failure;
|
|
280
|
+
try {
|
|
281
|
+
Util_ShellConfig$ReventlessAws.fields(computed, {
|
|
282
|
+
name: "prod",
|
|
283
|
+
purpose: "production"
|
|
284
|
+
}, undefined, undefined, undefined, Object.fromEntries([[
|
|
285
|
+
"environment",
|
|
286
|
+
"staging"
|
|
287
|
+
]]));
|
|
288
|
+
failure = undefined;
|
|
289
|
+
} catch (raw_message) {
|
|
290
|
+
let message = Primitive_exceptions.internalToException(raw_message);
|
|
291
|
+
if (message.RE_EXN_ID === "Failure") {
|
|
292
|
+
failure = message._1;
|
|
293
|
+
} else {
|
|
294
|
+
throw message;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (failure !== undefined) {
|
|
298
|
+
globalThis.expect(failure.includes("environment")).toBe(true);
|
|
299
|
+
return;
|
|
300
|
+
} else {
|
|
301
|
+
return JestGlobals.fail("a shellConfig key renaming the computed environment must fail the deploy");
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
|
|
251
306
|
globalThis.describe("Util_ShellConfig.fields — shellConfig passthrough", () => {
|
|
252
307
|
globalThis.test("shell-owned keys land verbatim, under the computed ones", () => {
|
|
253
|
-
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, undefined, Object.fromEntries([
|
|
308
|
+
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, undefined, undefined, Object.fromEntries([
|
|
254
309
|
[
|
|
255
310
|
"platformName",
|
|
256
311
|
"Online Shop"
|
|
@@ -271,7 +326,7 @@ globalThis.describe("Util_ShellConfig.fields — shellConfig passthrough", () =>
|
|
|
271
326
|
globalThis.test("a key the deploy computes fails the deploy, naming it", () => {
|
|
272
327
|
let failure;
|
|
273
328
|
try {
|
|
274
|
-
Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, undefined, Object.fromEntries([[
|
|
329
|
+
Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, undefined, undefined, Object.fromEntries([[
|
|
275
330
|
"apiEndpoint",
|
|
276
331
|
"https://wrong.example/graphql"
|
|
277
332
|
]]));
|
|
@@ -345,7 +400,7 @@ globalThis.describe("the subscription endpoint", () => {
|
|
|
345
400
|
globalThis.describe("Util_ShellConfig.fields — adminGroup", () => {
|
|
346
401
|
globalThis.test("is absent while the administrator role keeps its own name", () => {
|
|
347
402
|
Role$Reventless.clearGroups();
|
|
348
|
-
globalThis.expect(Stdlib_Option.isNone(Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, undefined, undefined)["adminGroup"])).toBe(true);
|
|
403
|
+
globalThis.expect(Stdlib_Option.isNone(Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, undefined, undefined, undefined)["adminGroup"])).toBe(true);
|
|
349
404
|
});
|
|
350
405
|
globalThis.test("carries the group a renamed administrator role maps to", () => {
|
|
351
406
|
Role$Reventless.clearGroups();
|
|
@@ -353,7 +408,7 @@ globalThis.describe("Util_ShellConfig.fields — adminGroup", () => {
|
|
|
353
408
|
Role$Reventless.admin,
|
|
354
409
|
"shop-admins"
|
|
355
410
|
]]);
|
|
356
|
-
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, undefined, undefined);
|
|
411
|
+
let out = Util_ShellConfig$ReventlessAws.fields(computed, undefined, undefined, undefined, undefined, undefined);
|
|
357
412
|
Role$Reventless.clearGroups();
|
|
358
413
|
globalThis.expect(get(out, "adminGroup")).toEqual("shop-admins");
|
|
359
414
|
});
|