@reventlessdev/reventless-aws 3.0.0-alpha.345 → 3.0.0-alpha.347
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 +54 -0
- package/package.json +19 -12
- package/rescript.json +2 -1
- package/run-bake-manifest.mjs +3 -0
- package/run-deploy-app.mjs +3 -0
- package/run-provision-accounts.mjs +3 -0
- package/run-provision-admin.mjs +3 -0
- package/scripts/BakeManifest.res +395 -0
- package/scripts/BakeManifest.res.mjs +487 -0
- package/scripts/DeployApp.res +708 -0
- package/scripts/DeployApp.res.mjs +1015 -0
- package/scripts/DeployManifest.res +84 -0
- package/scripts/DeployManifest.res.mjs +112 -0
- package/scripts/ProvisionAccounts.res +339 -0
- package/scripts/ProvisionAccounts.res.mjs +351 -0
- package/scripts/ProvisionAdmin.res +275 -0
- package/scripts/ProvisionAdmin.res.mjs +289 -0
- package/scripts/ProvisionCognito.res +149 -0
- package/scripts/ProvisionCognito.res.mjs +98 -0
- package/scripts/ProvisionIdentity.res +76 -11
- package/scripts/ProvisionIdentity.res.mjs +72 -7
- package/scripts/ProvisionProvider.res +104 -0
- package/scripts/ProvisionProvider.res.mjs +123 -0
- package/scripts/PulumiCli.res +43 -0
- package/scripts/PulumiCli.res.mjs +106 -0
- package/src/Platform.res +51 -4
- package/src/Platform.res.mjs +32 -14
- package/src/Platform_Stack.res +119 -9
- package/src/Platform_Stack.res.mjs +42 -4
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res +1 -5
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res.mjs +1 -1
- package/src/adapter/Api/Platform_UIFragments_Lambda.res +1 -5
- package/src/adapter/Api/Platform_UIFragments_Lambda.res.mjs +1 -2
- package/src/adapter/Auth/Auth_ActiveRoleStore.res +1 -5
- package/src/adapter/Auth/Auth_ActiveRoleStore.res.mjs +1 -2
- package/src/adapter/Auth/Auth_ActiveRoleTrigger.res +1 -5
- package/src/adapter/Auth/Auth_ActiveRoleTrigger.res.mjs +1 -2
- package/src/adapter/Auth/Auth_LoginIdentifier.res +66 -0
- package/src/adapter/Auth/Auth_LoginIdentifier.res.mjs +70 -0
- package/src/adapter/Auth/Auth_SignUpMode.res +78 -0
- package/src/adapter/Auth/Auth_SignUpMode.res.mjs +56 -0
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res +52 -31
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res.mjs +75 -44
- package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res +1 -5
- package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res.mjs +1 -2
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver.res +1 -5
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver.res.mjs +1 -2
- package/src/adapter/Postgres/PgChangeFeedRelay_Runtime.res +5 -4
- package/src/adapter/Postgres/PgChangeFeedRelay_Runtime.res.mjs +1 -1
- package/src/adapter/Postgres/PgMigration_Builder.res +1 -1
- package/src/adapter/Postgres/PgMigration_Builder.res.mjs +1 -2
- package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res +5 -0
- package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res.mjs +5 -1
- package/src/adapter/Runtime/CommandGeneratorEntryPoint_Ops.res +2 -0
- package/src/adapter/Runtime/CommandGeneratorEntryPoint_Ops.res.mjs +2 -2
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint.mjs +15 -6
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res +51 -30
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res.mjs +31 -14
- package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +1 -5
- package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res.mjs +1 -1
- package/src/adapter/StateTopic/StateTopic_AppSync.res +1 -5
- package/src/adapter/StateTopic/StateTopic_AppSync.res.mjs +1 -1
- package/src/adapter/Task/TaskBucket_S3.res +1 -3
- package/src/adapter/Task/TaskBucket_S3.res.mjs +1 -1
- package/src/adapter/Upload/Upload_Claim_S3.res +1 -5
- package/src/adapter/Upload/Upload_Claim_S3.res.mjs +1 -1
- package/src/adapter/Upload/Upload_Presign_S3.res +1 -5
- package/src/adapter/Upload/Upload_Presign_S3.res.mjs +1 -2
- package/src/capability/Capability_Geocoding_AwsLocation.res +5 -1
- package/src/capability/Capability_Geocoding_AwsLocation.res.mjs +7 -1
- package/src/components/Api/AppSync_Adapter.res +56 -72
- package/src/components/Api/AppSync_Adapter.res.mjs +26 -60
- package/src/components/Api/AppSync_SdlDecorate.res +82 -1
- package/src/components/Api/AppSync_SdlDecorate.res.mjs +45 -0
- package/src/plugin/cloner/ClonerRunner_Fargate.res +1 -5
- package/src/plugin/cloner/ClonerRunner_Fargate.res.mjs +1 -1
- package/src/plugin/stack/Plugin_Stack.res +4 -0
- package/src/plugin/stack/Plugin_Stack.res.mjs +2 -0
- package/src/util/Util_DeadLetterQueue.res +1 -5
- package/src/util/Util_DeadLetterQueue.res.mjs +1 -2
- package/src/util/Util_StoreLayout.res +15 -2
- package/src/util/Util_StoreLayout.res.mjs +11 -3
- package/tests/AppSync_AdapterTest.res +83 -0
- package/tests/AppSync_AdapterTest.res.mjs +69 -0
- package/tests/Auth_LoginIdentifierTest.res +51 -0
- package/tests/Auth_LoginIdentifierTest.res.mjs +51 -0
- package/tests/Auth_SignUpModeTest.res +56 -0
- package/tests/Auth_SignUpModeTest.res.mjs +53 -0
- package/tests/BakeManifestTest.res +204 -0
- package/tests/BakeManifestTest.res.mjs +259 -0
- package/tests/DcbColdStartPartitionTest.res +32 -0
- package/tests/DcbColdStartPartitionTest.res.mjs +33 -0
- package/tests/DcbEventLogStorage_DynamoDb_RuntimeTest.res +88 -0
- package/tests/DcbEventLogStorage_DynamoDb_RuntimeTest.res.mjs +112 -0
- package/tests/DcbUnresolvedPartitionSlice.res +28 -0
- package/tests/DcbUnresolvedPartitionSlice.res.mjs +38 -0
- package/tests/DeployAppTest.res +90 -0
- package/tests/DeployAppTest.res.mjs +133 -0
- package/tests/LambdaLayerLookupTest.res +104 -0
- package/tests/LambdaLayerLookupTest.res.mjs +117 -0
- package/tests/ProvisionAccountsTest.res +168 -0
- package/tests/ProvisionAccountsTest.res.mjs +184 -0
- package/tests/ProvisionAdminTest.res +55 -0
- package/tests/ProvisionAdminTest.res.mjs +66 -0
- package/tests/ProvisionIdentityTest.res +89 -3
- package/tests/ProvisionIdentityTest.res.mjs +66 -1
- package/tests/Util_OwnerScopeEnvTest.res +25 -0
- package/tests/Util_OwnerScopeEnvTest.res.mjs +13 -0
- package/tests/Util_StoreLayoutTest.res +6 -0
- package/tests/Util_StoreLayoutTest.res.mjs +7 -4
- package/tests/dcbColdStartPartition.mjs +66 -0
- package/tests/setup/layerArn.cjs +5 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Nodefs from "node:fs";
|
|
4
|
+
import * as Nodeos from "node:os";
|
|
5
|
+
import * as Nodepath from "node:path";
|
|
6
|
+
import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
|
|
7
|
+
import * as Stdlib_Result from "@rescript/runtime/lib/es6/Stdlib_Result.js";
|
|
8
|
+
import * as ProvisionAccounts$ReventlessAws from "../scripts/ProvisionAccounts.res.mjs";
|
|
9
|
+
import * as ProvisionProvider$ReventlessAws from "../scripts/ProvisionProvider.res.mjs";
|
|
10
|
+
|
|
11
|
+
globalThis.describe("ProvisionAccounts.parseArgs", () => {
|
|
12
|
+
globalThis.test("no arguments leaves every choice unanswered", () => {
|
|
13
|
+
globalThis.expect(ProvisionAccounts$ReventlessAws.parseArgs([])).toEqual({
|
|
14
|
+
TAG: "Ok",
|
|
15
|
+
_0: {
|
|
16
|
+
providerId: undefined,
|
|
17
|
+
stack: undefined,
|
|
18
|
+
file: undefined,
|
|
19
|
+
help: false
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
globalThis.test("a pool and a manifest parse", () => {
|
|
24
|
+
globalThis.expect(ProvisionAccounts$ReventlessAws.parseArgs([
|
|
25
|
+
"--provider-id",
|
|
26
|
+
"eu-west-1_AbCdEfGhI",
|
|
27
|
+
"--file",
|
|
28
|
+
"cast.yaml"
|
|
29
|
+
])).toEqual({
|
|
30
|
+
TAG: "Ok",
|
|
31
|
+
_0: {
|
|
32
|
+
providerId: "eu-west-1_AbCdEfGhI",
|
|
33
|
+
stack: undefined,
|
|
34
|
+
file: "cast.yaml",
|
|
35
|
+
help: false
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
globalThis.test("--stack picks the deployment to read the pool id from", () => {
|
|
40
|
+
globalThis.expect(ProvisionAccounts$ReventlessAws.parseArgs([
|
|
41
|
+
"--stack",
|
|
42
|
+
"beta"
|
|
43
|
+
])).toEqual({
|
|
44
|
+
TAG: "Ok",
|
|
45
|
+
_0: {
|
|
46
|
+
providerId: undefined,
|
|
47
|
+
stack: "beta",
|
|
48
|
+
file: undefined,
|
|
49
|
+
help: false
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
globalThis.test("an unknown flag refuses rather than being ignored", () => {
|
|
54
|
+
globalThis.expect(ProvisionAccounts$ReventlessAws.parseArgs([
|
|
55
|
+
"--pool",
|
|
56
|
+
"eu-west-1_AbCdEfGhI"
|
|
57
|
+
])).toEqual({
|
|
58
|
+
TAG: "Error",
|
|
59
|
+
_0: `unknown argument "--pool"`
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
globalThis.test("a flag with no value refuses", () => {
|
|
63
|
+
globalThis.expect(ProvisionAccounts$ReventlessAws.parseArgs(["--provider-id"])).toEqual({
|
|
64
|
+
TAG: "Error",
|
|
65
|
+
_0: "--provider-id needs a value"
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
globalThis.test("-h asks for the usage", () => {
|
|
69
|
+
globalThis.expect(ProvisionAccounts$ReventlessAws.parseArgs(["-h"])).toEqual({
|
|
70
|
+
TAG: "Ok",
|
|
71
|
+
_0: {
|
|
72
|
+
providerId: undefined,
|
|
73
|
+
stack: undefined,
|
|
74
|
+
file: undefined,
|
|
75
|
+
help: true
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
globalThis.describe("ProvisionProvider.resolve", () => {
|
|
82
|
+
let withoutEnv = fn => {
|
|
83
|
+
let saved = process.env[ProvisionProvider$ReventlessAws.envKey];
|
|
84
|
+
Stdlib_Dict.$$delete(process.env, ProvisionProvider$ReventlessAws.envKey);
|
|
85
|
+
let outcome = fn();
|
|
86
|
+
if (saved !== undefined) {
|
|
87
|
+
process.env[ProvisionProvider$ReventlessAws.envKey] = saved;
|
|
88
|
+
}
|
|
89
|
+
return outcome;
|
|
90
|
+
};
|
|
91
|
+
globalThis.test("an explicit id wins, and says so", () => {
|
|
92
|
+
globalThis.expect(withoutEnv(() => ProvisionProvider$ReventlessAws.resolve("eu-west-1_Explicit", "alpha"))).toEqual({
|
|
93
|
+
TAG: "Ok",
|
|
94
|
+
_0: [
|
|
95
|
+
"eu-west-1_Explicit",
|
|
96
|
+
"Flag"
|
|
97
|
+
]
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
globalThis.test("an explicit id beats the environment", () => {
|
|
101
|
+
process.env[ProvisionProvider$ReventlessAws.envKey] = "eu-west-1_FromEnv";
|
|
102
|
+
let resolved = ProvisionProvider$ReventlessAws.resolve("eu-west-1_Explicit", undefined);
|
|
103
|
+
Stdlib_Dict.$$delete(process.env, ProvisionProvider$ReventlessAws.envKey);
|
|
104
|
+
globalThis.expect(resolved).toEqual({
|
|
105
|
+
TAG: "Ok",
|
|
106
|
+
_0: [
|
|
107
|
+
"eu-west-1_Explicit",
|
|
108
|
+
"Flag"
|
|
109
|
+
]
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
globalThis.test("the environment answers when no flag does", () => {
|
|
113
|
+
process.env[ProvisionProvider$ReventlessAws.envKey] = "eu-west-1_FromEnv";
|
|
114
|
+
let resolved = ProvisionProvider$ReventlessAws.resolve(undefined, undefined);
|
|
115
|
+
Stdlib_Dict.$$delete(process.env, ProvisionProvider$ReventlessAws.envKey);
|
|
116
|
+
globalThis.expect(resolved).toEqual({
|
|
117
|
+
TAG: "Ok",
|
|
118
|
+
_0: [
|
|
119
|
+
"eu-west-1_FromEnv",
|
|
120
|
+
"Environment"
|
|
121
|
+
]
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
globalThis.test("an empty environment variable is not an answer", () => {
|
|
125
|
+
process.env[ProvisionProvider$ReventlessAws.envKey] = " ";
|
|
126
|
+
let resolved = ProvisionProvider$ReventlessAws.resolve(undefined, "no-such-stack-here");
|
|
127
|
+
globalThis.expect((Stdlib_Dict.$$delete(process.env, ProvisionProvider$ReventlessAws.envKey), Stdlib_Result.isError(resolved))).toBe(true);
|
|
128
|
+
});
|
|
129
|
+
globalThis.test("each source describes itself", () => {
|
|
130
|
+
globalThis.expect(ProvisionProvider$ReventlessAws.describe("Flag")).toBe("--provider-id");
|
|
131
|
+
globalThis.expect(ProvisionProvider$ReventlessAws.describe("Environment")).toBe("REVENTLESS_IDENTITY_PROVIDER_ID");
|
|
132
|
+
globalThis.expect(ProvisionProvider$ReventlessAws.describe({
|
|
133
|
+
TAG: "Stack",
|
|
134
|
+
_0: "beta"
|
|
135
|
+
})).toBe("stack beta");
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
globalThis.describe("ProvisionAccounts.looksLikeEmail", () => {
|
|
140
|
+
globalThis.test("an address is one", () => {
|
|
141
|
+
globalThis.expect(ProvisionAccounts$ReventlessAws.looksLikeEmail("me@example.com")).toBe(true);
|
|
142
|
+
});
|
|
143
|
+
globalThis.test("a demo username is not", () => {
|
|
144
|
+
globalThis.expect(ProvisionAccounts$ReventlessAws.looksLikeEmail("shopper")).toBe(false);
|
|
145
|
+
});
|
|
146
|
+
globalThis.test("an @ with no domain dot is not", () => {
|
|
147
|
+
globalThis.expect(ProvisionAccounts$ReventlessAws.looksLikeEmail("admin@localhost")).toBe(false);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
globalThis.describe("ProvisionAccounts.provision", () => {
|
|
152
|
+
let manifest = `# the cast
|
|
153
|
+
- username: shopper
|
|
154
|
+
password: ""
|
|
155
|
+
groups: [Shopper]
|
|
156
|
+
`;
|
|
157
|
+
globalThis.test("a refused pool leaves the manifest untouched", async () => {
|
|
158
|
+
let dir = Nodefs.mkdtempSync(Nodepath.join(Nodeos.tmpdir(), "provision-accounts-"));
|
|
159
|
+
let file = Nodepath.join(dir, "users.yaml");
|
|
160
|
+
Nodefs.writeFileSync(file, manifest, "utf8");
|
|
161
|
+
let refuse = async (param, param$1) => ({
|
|
162
|
+
TAG: "Error",
|
|
163
|
+
_0: "pool signs in on email"
|
|
164
|
+
});
|
|
165
|
+
let outcome = await ProvisionAccounts$ReventlessAws.provision(file, "eu-west-1_Refuses", refuse);
|
|
166
|
+
let after = Nodefs.readFileSync(file, "utf8");
|
|
167
|
+
Nodefs.rmSync(dir, {
|
|
168
|
+
recursive: true,
|
|
169
|
+
force: true
|
|
170
|
+
});
|
|
171
|
+
globalThis.expect(outcome).toEqual({
|
|
172
|
+
TAG: "Error",
|
|
173
|
+
_0: "pool signs in on email"
|
|
174
|
+
});
|
|
175
|
+
globalThis.expect(after).toBe(manifest);
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
let Provision;
|
|
180
|
+
|
|
181
|
+
export {
|
|
182
|
+
Provision,
|
|
183
|
+
}
|
|
184
|
+
/* Not a pure module */
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
open JestGlobals
|
|
2
|
+
|
|
3
|
+
// The bootstrap script's decidable part: which pool and which person the run is
|
|
4
|
+
// about. Reachable at all only because the module defines `main` without calling
|
|
5
|
+
// it — `run-provision-admin.mjs` does that — which is the same reason its sibling
|
|
6
|
+
// is testable.
|
|
7
|
+
//
|
|
8
|
+
// The AWS calls themselves are not covered here; what is covered is everything
|
|
9
|
+
// that can be wrong *before* one is made. The credential this script hands out is
|
|
10
|
+
// no longer its own — the generator moved to `spec` so the manifest's
|
|
11
|
+
// platform-neutral half could reach it, and `Util_PasswordTest` holds the policy
|
|
12
|
+
// it has to satisfy.
|
|
13
|
+
|
|
14
|
+
module Provision = ProvisionAdmin
|
|
15
|
+
|
|
16
|
+
describe("ProvisionAdmin.parseArgs", () => {
|
|
17
|
+
testSync("both arguments parse", () =>
|
|
18
|
+
expect(
|
|
19
|
+
Provision.parseArgs(["--provider-id", "eu-west-1_AbCdEfGhI", "--email", "me@example.com"]),
|
|
20
|
+
)->toEqual(
|
|
21
|
+
Ok({
|
|
22
|
+
Provision.providerId: Some("eu-west-1_AbCdEfGhI"),
|
|
23
|
+
stack: None,
|
|
24
|
+
email: Some("me@example.com"),
|
|
25
|
+
help: false,
|
|
26
|
+
}),
|
|
27
|
+
)
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
testSync("no arguments leaves both unanswered", () =>
|
|
31
|
+
expect(Provision.parseArgs([]))->toEqual(
|
|
32
|
+
Ok({Provision.providerId: None, stack: None, email: None, help: false}),
|
|
33
|
+
)
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
// The reason unknown flags refuse rather than being skipped: a typo'd
|
|
37
|
+
// `--provider-id` would fall through to the environment and make the
|
|
38
|
+
// administrator in a different pool than the operator named — a successful run
|
|
39
|
+
// against the wrong deployment, which is worse than a failed one.
|
|
40
|
+
testSync("an unknown flag refuses rather than being ignored", () =>
|
|
41
|
+
expect(Provision.parseArgs(["--provider", "eu-west-1_AbCdEfGhI"]))->toEqual(
|
|
42
|
+
Error(`unknown argument "--provider"`),
|
|
43
|
+
)
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
testSync("a flag with no value refuses", () =>
|
|
47
|
+
expect(Provision.parseArgs(["--email"]))->toEqual(Error("--email needs a value"))
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
testSync("-h asks for the usage", () =>
|
|
51
|
+
expect(Provision.parseArgs(["-h"]))->toEqual(
|
|
52
|
+
Ok({Provision.providerId: None, stack: None, email: None, help: true}),
|
|
53
|
+
)
|
|
54
|
+
)
|
|
55
|
+
})
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as ProvisionAdmin$ReventlessAws from "../scripts/ProvisionAdmin.res.mjs";
|
|
4
|
+
|
|
5
|
+
globalThis.describe("ProvisionAdmin.parseArgs", () => {
|
|
6
|
+
globalThis.test("both arguments parse", () => {
|
|
7
|
+
globalThis.expect(ProvisionAdmin$ReventlessAws.parseArgs([
|
|
8
|
+
"--provider-id",
|
|
9
|
+
"eu-west-1_AbCdEfGhI",
|
|
10
|
+
"--email",
|
|
11
|
+
"me@example.com"
|
|
12
|
+
])).toEqual({
|
|
13
|
+
TAG: "Ok",
|
|
14
|
+
_0: {
|
|
15
|
+
providerId: "eu-west-1_AbCdEfGhI",
|
|
16
|
+
stack: undefined,
|
|
17
|
+
email: "me@example.com",
|
|
18
|
+
help: false
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
globalThis.test("no arguments leaves both unanswered", () => {
|
|
23
|
+
globalThis.expect(ProvisionAdmin$ReventlessAws.parseArgs([])).toEqual({
|
|
24
|
+
TAG: "Ok",
|
|
25
|
+
_0: {
|
|
26
|
+
providerId: undefined,
|
|
27
|
+
stack: undefined,
|
|
28
|
+
email: undefined,
|
|
29
|
+
help: false
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
globalThis.test("an unknown flag refuses rather than being ignored", () => {
|
|
34
|
+
globalThis.expect(ProvisionAdmin$ReventlessAws.parseArgs([
|
|
35
|
+
"--provider",
|
|
36
|
+
"eu-west-1_AbCdEfGhI"
|
|
37
|
+
])).toEqual({
|
|
38
|
+
TAG: "Error",
|
|
39
|
+
_0: `unknown argument "--provider"`
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
globalThis.test("a flag with no value refuses", () => {
|
|
43
|
+
globalThis.expect(ProvisionAdmin$ReventlessAws.parseArgs(["--email"])).toEqual({
|
|
44
|
+
TAG: "Error",
|
|
45
|
+
_0: "--email needs a value"
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
globalThis.test("-h asks for the usage", () => {
|
|
49
|
+
globalThis.expect(ProvisionAdmin$ReventlessAws.parseArgs(["-h"])).toEqual({
|
|
50
|
+
TAG: "Ok",
|
|
51
|
+
_0: {
|
|
52
|
+
providerId: undefined,
|
|
53
|
+
stack: undefined,
|
|
54
|
+
email: undefined,
|
|
55
|
+
help: true
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
let Provision;
|
|
62
|
+
|
|
63
|
+
export {
|
|
64
|
+
Provision,
|
|
65
|
+
}
|
|
66
|
+
/* Not a pure module */
|
|
@@ -16,6 +16,8 @@ describe("ProvisionIdentity.parseArgs", () => {
|
|
|
16
16
|
Ok({
|
|
17
17
|
Provision.poolName: Provision.defaultPoolName,
|
|
18
18
|
providerId: None,
|
|
19
|
+
loginIdentifier: Auth_LoginIdentifier.Email,
|
|
20
|
+
signUpMode: Auth_SignUpMode.AdminOnly,
|
|
19
21
|
help: false,
|
|
20
22
|
}),
|
|
21
23
|
)
|
|
@@ -26,6 +28,8 @@ describe("ProvisionIdentity.parseArgs", () => {
|
|
|
26
28
|
Ok({
|
|
27
29
|
Provision.poolName: Provision.defaultPoolName,
|
|
28
30
|
providerId: Some("eu-west-1_AbCdEfGhI"),
|
|
31
|
+
loginIdentifier: Auth_LoginIdentifier.Email,
|
|
32
|
+
signUpMode: Auth_SignUpMode.AdminOnly,
|
|
29
33
|
help: false,
|
|
30
34
|
}),
|
|
31
35
|
)
|
|
@@ -33,13 +37,60 @@ describe("ProvisionIdentity.parseArgs", () => {
|
|
|
33
37
|
|
|
34
38
|
testSync("--name selects which pool to adopt by name", () =>
|
|
35
39
|
expect(Provision.parseArgs(["--name", "examples-dev"]))->toEqual(
|
|
36
|
-
Ok({
|
|
40
|
+
Ok({
|
|
41
|
+
Provision.poolName: "examples-dev",
|
|
42
|
+
providerId: None,
|
|
43
|
+
loginIdentifier: Auth_LoginIdentifier.Email,
|
|
44
|
+
signUpMode: Auth_SignUpMode.AdminOnly,
|
|
45
|
+
help: false,
|
|
46
|
+
}),
|
|
37
47
|
)
|
|
38
48
|
)
|
|
39
49
|
|
|
40
50
|
testSync("both together are accepted, and the id wins at resolve time", () =>
|
|
41
51
|
expect(Provision.parseArgs(["--name", "ignored", "--provider-id", "eu-west-1_x"]))->toEqual(
|
|
42
|
-
Ok({
|
|
52
|
+
Ok({
|
|
53
|
+
Provision.poolName: "ignored",
|
|
54
|
+
providerId: Some("eu-west-1_x"),
|
|
55
|
+
loginIdentifier: Auth_LoginIdentifier.Email,
|
|
56
|
+
signUpMode: Auth_SignUpMode.AdminOnly,
|
|
57
|
+
help: false,
|
|
58
|
+
}),
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
testSync("--login-identifier picks the sign-in attribute", () =>
|
|
63
|
+
expect(
|
|
64
|
+
Provision.parseArgs(["--login-identifier", "emailOrPhone"])->Result.map(
|
|
65
|
+
a => a.loginIdentifier,
|
|
66
|
+
),
|
|
67
|
+
)->toEqual(Ok(Auth_LoginIdentifier.EmailOrPhone))
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
// 🚨 The sign-in attribute cannot be changed once the pool exists, so a typo
|
|
71
|
+
// that fell back to the default would create a pool the operator has to
|
|
72
|
+
// rebuild — and re-register every account in — to correct.
|
|
73
|
+
testSync("an unrecognised sign-in attribute is refused, never defaulted", () =>
|
|
74
|
+
expect(Provision.parseArgs(["--login-identifier", "e-mail"])->Result.isError)->toBe(true)
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
testSync("--sign-up-mode opens the pool to self-registration", () =>
|
|
78
|
+
expect(
|
|
79
|
+
Provision.parseArgs(["--sign-up-mode", "selfService"])->Result.map(a => a.signUpMode),
|
|
80
|
+
)->toEqual(Ok(Auth_SignUpMode.SelfService))
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
// This one IS correctable later, unlike the sign-in attribute — it is refused
|
|
84
|
+
// because the mistake is silent, not because it is permanent. Defaulting past
|
|
85
|
+
// a typo leaves a pool that refuses every registration while the command line
|
|
86
|
+
// reads as though it allows them.
|
|
87
|
+
testSync("an unrecognised sign-up mode is refused, never defaulted", () =>
|
|
88
|
+
expect(Provision.parseArgs(["--sign-up-mode", "self-service"])->Result.isError)->toBe(true)
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
testSync("sign-up mode defaults to admin-only, so an existing pool is unchanged", () =>
|
|
92
|
+
expect(Provision.parseArgs([])->Result.map(a => a.signUpMode))->toEqual(
|
|
93
|
+
Ok(Auth_SignUpMode.AdminOnly),
|
|
43
94
|
)
|
|
44
95
|
)
|
|
45
96
|
|
|
@@ -62,6 +113,12 @@ describe("ProvisionIdentity.parseArgs", () => {
|
|
|
62
113
|
expect(Provision.parseArgs(["--name"]))->toEqual(Error("--name needs a value"))
|
|
63
114
|
)
|
|
64
115
|
|
|
116
|
+
testSync("--login-identifier with no value is refused too", () =>
|
|
117
|
+
expect(Provision.parseArgs(["--login-identifier"]))->toEqual(
|
|
118
|
+
Error("--login-identifier needs a value"),
|
|
119
|
+
)
|
|
120
|
+
)
|
|
121
|
+
|
|
65
122
|
testSync("--help and -h both ask for the usage text", () =>
|
|
66
123
|
expect((
|
|
67
124
|
Provision.parseArgs(["--help"])->Result.map(a => a.help),
|
|
@@ -83,7 +140,11 @@ describe("ProvisionIdentity.parseArgs", () => {
|
|
|
83
140
|
// touches it — so its settings are not a detail an operator can revise cheaply
|
|
84
141
|
// once accounts exist in it.
|
|
85
142
|
describe("ProvisionIdentity.poolSettings", () => {
|
|
86
|
-
let settings = Provision.poolSettings(
|
|
143
|
+
let settings = Provision.poolSettings(
|
|
144
|
+
~poolName="MyIdentity",
|
|
145
|
+
~loginIdentifier=Auth_LoginIdentifier.default,
|
|
146
|
+
~signUpMode=Auth_SignUpMode.default,
|
|
147
|
+
)
|
|
87
148
|
|
|
88
149
|
testSync("carries the name it was asked for", () => expect(settings.poolName)->toBe("MyIdentity"))
|
|
89
150
|
|
|
@@ -95,6 +156,31 @@ describe("ProvisionIdentity.poolSettings", () => {
|
|
|
95
156
|
))->toEqual((Some(["email"]), Some("OFF"), Some(true)))
|
|
96
157
|
)
|
|
97
158
|
|
|
159
|
+
testSync("a phone pool is created signing in on phone_number", () =>
|
|
160
|
+
expect(
|
|
161
|
+
Provision.poolSettings(
|
|
162
|
+
~poolName="MyIdentity",
|
|
163
|
+
~loginIdentifier=Auth_LoginIdentifier.Phone,
|
|
164
|
+
~signUpMode=Auth_SignUpMode.default,
|
|
165
|
+
).usernameAttributes,
|
|
166
|
+
)->toEqual(Some(["phone_number"]))
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
// The negation is the part worth pinning: this type asks who may sign up, and
|
|
170
|
+
// Cognito's field asks the opposite question. Reading it backwards would open a
|
|
171
|
+
// pool that was meant to stay closed.
|
|
172
|
+
testSync("selfService clears allowAdminCreateUserOnly, adminOnly sets it", () => {
|
|
173
|
+
let openPool = Provision.poolSettings(
|
|
174
|
+
~poolName="MyIdentity",
|
|
175
|
+
~loginIdentifier=Auth_LoginIdentifier.default,
|
|
176
|
+
~signUpMode=Auth_SignUpMode.SelfService,
|
|
177
|
+
)
|
|
178
|
+
expect((
|
|
179
|
+
openPool.adminCreateUserConfig->Option.flatMap(c => c.allowAdminCreateUserOnly),
|
|
180
|
+
settings.adminCreateUserConfig->Option.flatMap(c => c.allowAdminCreateUserOnly),
|
|
181
|
+
))->toEqual((Some(false), Some(true)))
|
|
182
|
+
})
|
|
183
|
+
|
|
98
184
|
testSync("keeps the 12-character password policy", () =>
|
|
99
185
|
expect(
|
|
100
186
|
settings.policies
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
4
4
|
import * as Stdlib_Result from "@rescript/runtime/lib/es6/Stdlib_Result.js";
|
|
5
|
+
import * as Auth_SignUpMode$ReventlessAws from "../src/adapter/Auth/Auth_SignUpMode.res.mjs";
|
|
5
6
|
import * as ProvisionIdentity$ReventlessAws from "../scripts/ProvisionIdentity.res.mjs";
|
|
7
|
+
import * as Auth_LoginIdentifier$ReventlessAws from "../src/adapter/Auth/Auth_LoginIdentifier.res.mjs";
|
|
6
8
|
|
|
7
9
|
globalThis.describe("ProvisionIdentity.parseArgs", () => {
|
|
8
10
|
globalThis.test("no arguments means adopt-or-create the default name", () => {
|
|
@@ -11,6 +13,8 @@ globalThis.describe("ProvisionIdentity.parseArgs", () => {
|
|
|
11
13
|
_0: {
|
|
12
14
|
poolName: ProvisionIdentity$ReventlessAws.defaultPoolName,
|
|
13
15
|
providerId: undefined,
|
|
16
|
+
loginIdentifier: "Email",
|
|
17
|
+
signUpMode: "AdminOnly",
|
|
14
18
|
help: false
|
|
15
19
|
}
|
|
16
20
|
});
|
|
@@ -24,6 +28,8 @@ globalThis.describe("ProvisionIdentity.parseArgs", () => {
|
|
|
24
28
|
_0: {
|
|
25
29
|
poolName: ProvisionIdentity$ReventlessAws.defaultPoolName,
|
|
26
30
|
providerId: "eu-west-1_AbCdEfGhI",
|
|
31
|
+
loginIdentifier: "Email",
|
|
32
|
+
signUpMode: "AdminOnly",
|
|
27
33
|
help: false
|
|
28
34
|
}
|
|
29
35
|
});
|
|
@@ -37,6 +43,8 @@ globalThis.describe("ProvisionIdentity.parseArgs", () => {
|
|
|
37
43
|
_0: {
|
|
38
44
|
poolName: "examples-dev",
|
|
39
45
|
providerId: undefined,
|
|
46
|
+
loginIdentifier: "Email",
|
|
47
|
+
signUpMode: "AdminOnly",
|
|
40
48
|
help: false
|
|
41
49
|
}
|
|
42
50
|
});
|
|
@@ -52,10 +60,48 @@ globalThis.describe("ProvisionIdentity.parseArgs", () => {
|
|
|
52
60
|
_0: {
|
|
53
61
|
poolName: "ignored",
|
|
54
62
|
providerId: "eu-west-1_x",
|
|
63
|
+
loginIdentifier: "Email",
|
|
64
|
+
signUpMode: "AdminOnly",
|
|
55
65
|
help: false
|
|
56
66
|
}
|
|
57
67
|
});
|
|
58
68
|
});
|
|
69
|
+
globalThis.test("--login-identifier picks the sign-in attribute", () => {
|
|
70
|
+
globalThis.expect(Stdlib_Result.map(ProvisionIdentity$ReventlessAws.parseArgs([
|
|
71
|
+
"--login-identifier",
|
|
72
|
+
"emailOrPhone"
|
|
73
|
+
]), a => a.loginIdentifier)).toEqual({
|
|
74
|
+
TAG: "Ok",
|
|
75
|
+
_0: "EmailOrPhone"
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
globalThis.test("an unrecognised sign-in attribute is refused, never defaulted", () => {
|
|
79
|
+
globalThis.expect(Stdlib_Result.isError(ProvisionIdentity$ReventlessAws.parseArgs([
|
|
80
|
+
"--login-identifier",
|
|
81
|
+
"e-mail"
|
|
82
|
+
]))).toBe(true);
|
|
83
|
+
});
|
|
84
|
+
globalThis.test("--sign-up-mode opens the pool to self-registration", () => {
|
|
85
|
+
globalThis.expect(Stdlib_Result.map(ProvisionIdentity$ReventlessAws.parseArgs([
|
|
86
|
+
"--sign-up-mode",
|
|
87
|
+
"selfService"
|
|
88
|
+
]), a => a.signUpMode)).toEqual({
|
|
89
|
+
TAG: "Ok",
|
|
90
|
+
_0: "SelfService"
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
globalThis.test("an unrecognised sign-up mode is refused, never defaulted", () => {
|
|
94
|
+
globalThis.expect(Stdlib_Result.isError(ProvisionIdentity$ReventlessAws.parseArgs([
|
|
95
|
+
"--sign-up-mode",
|
|
96
|
+
"self-service"
|
|
97
|
+
]))).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
globalThis.test("sign-up mode defaults to admin-only, so an existing pool is unchanged", () => {
|
|
100
|
+
globalThis.expect(Stdlib_Result.map(ProvisionIdentity$ReventlessAws.parseArgs([]), a => a.signUpMode)).toEqual({
|
|
101
|
+
TAG: "Ok",
|
|
102
|
+
_0: "AdminOnly"
|
|
103
|
+
});
|
|
104
|
+
});
|
|
59
105
|
globalThis.test("a misspelled flag is refused, not ignored", () => {
|
|
60
106
|
globalThis.expect(ProvisionIdentity$ReventlessAws.parseArgs([
|
|
61
107
|
"--provider_id",
|
|
@@ -77,6 +123,12 @@ globalThis.describe("ProvisionIdentity.parseArgs", () => {
|
|
|
77
123
|
_0: "--name needs a value"
|
|
78
124
|
});
|
|
79
125
|
});
|
|
126
|
+
globalThis.test("--login-identifier with no value is refused too", () => {
|
|
127
|
+
globalThis.expect(ProvisionIdentity$ReventlessAws.parseArgs(["--login-identifier"])).toEqual({
|
|
128
|
+
TAG: "Error",
|
|
129
|
+
_0: "--login-identifier needs a value"
|
|
130
|
+
});
|
|
131
|
+
});
|
|
80
132
|
globalThis.test("--help and -h both ask for the usage text", () => {
|
|
81
133
|
globalThis.expect([
|
|
82
134
|
Stdlib_Result.map(ProvisionIdentity$ReventlessAws.parseArgs(["--help"]), a => a.help),
|
|
@@ -104,7 +156,7 @@ globalThis.describe("ProvisionIdentity.parseArgs", () => {
|
|
|
104
156
|
});
|
|
105
157
|
|
|
106
158
|
globalThis.describe("ProvisionIdentity.poolSettings", () => {
|
|
107
|
-
let settings = ProvisionIdentity$ReventlessAws.poolSettings("MyIdentity");
|
|
159
|
+
let settings = ProvisionIdentity$ReventlessAws.poolSettings("MyIdentity", Auth_LoginIdentifier$ReventlessAws.default, Auth_SignUpMode$ReventlessAws.default);
|
|
108
160
|
globalThis.test("carries the name it was asked for", () => {
|
|
109
161
|
globalThis.expect(settings.PoolName).toBe("MyIdentity");
|
|
110
162
|
});
|
|
@@ -119,6 +171,19 @@ globalThis.describe("ProvisionIdentity.poolSettings", () => {
|
|
|
119
171
|
true
|
|
120
172
|
]);
|
|
121
173
|
});
|
|
174
|
+
globalThis.test("a phone pool is created signing in on phone_number", () => {
|
|
175
|
+
globalThis.expect(ProvisionIdentity$ReventlessAws.poolSettings("MyIdentity", "Phone", Auth_SignUpMode$ReventlessAws.default).UsernameAttributes).toEqual(["phone_number"]);
|
|
176
|
+
});
|
|
177
|
+
globalThis.test("selfService clears allowAdminCreateUserOnly, adminOnly sets it", () => {
|
|
178
|
+
let openPool = ProvisionIdentity$ReventlessAws.poolSettings("MyIdentity", Auth_LoginIdentifier$ReventlessAws.default, "SelfService");
|
|
179
|
+
globalThis.expect([
|
|
180
|
+
Stdlib_Option.flatMap(openPool.AdminCreateUserConfig, c => c.AllowAdminCreateUserOnly),
|
|
181
|
+
Stdlib_Option.flatMap(settings.AdminCreateUserConfig, c => c.AllowAdminCreateUserOnly)
|
|
182
|
+
]).toEqual([
|
|
183
|
+
false,
|
|
184
|
+
true
|
|
185
|
+
]);
|
|
186
|
+
});
|
|
122
187
|
globalThis.test("keeps the 12-character password policy", () => {
|
|
123
188
|
globalThis.expect(Stdlib_Option.flatMap(Stdlib_Option.flatMap(settings.Policies, p => p.PasswordPolicy), p => p.MinimumLength)).toEqual(12);
|
|
124
189
|
});
|
|
@@ -59,4 +59,29 @@ describe("Util_OwnerScopeEnv — the elevated-groups carrier", () => {
|
|
|
59
59
|
withElevated([], () => Util_OwnerScopeEnv.applyElevatedGroupsDefault(variables))
|
|
60
60
|
expect(variables->Dict.get(Util_OwnerScopeEnv.key)->Option.isNone)->toBe(true)
|
|
61
61
|
})
|
|
62
|
+
|
|
63
|
+
// The whole path the "administrator sees empty screens" trap ran through: the
|
|
64
|
+
// platform entry point defaults the list, and this composes it into a Lambda's
|
|
65
|
+
// environment. Asserted end to end rather than at either half, because both
|
|
66
|
+
// halves were already correct while the trap was open — the pipe was laid and
|
|
67
|
+
// nothing ever put a value in.
|
|
68
|
+
testSync("the platform's administrator default reaches a composed environment", () => {
|
|
69
|
+
Reventless.OwnerScope.clearElevatedGroups()
|
|
70
|
+
NodeProcess.env->Dict.delete(Util_OwnerScopeEnv.key)
|
|
71
|
+
Reventless.OwnerScope.defaultElevatedGroups([Reventless.AdminGroup.name])
|
|
72
|
+
|
|
73
|
+
let variables = Dict.make()
|
|
74
|
+
Util_OwnerScopeEnv.applyElevatedGroupsDefault(variables)
|
|
75
|
+
let encoded = switch variables->Dict.get(Util_OwnerScopeEnv.key) {
|
|
76
|
+
| Some(value) => value->Obj.magic
|
|
77
|
+
| None => ""
|
|
78
|
+
}
|
|
79
|
+
Reventless.OwnerScope.clearElevatedGroups()
|
|
80
|
+
|
|
81
|
+
// Round-tripped, like the first case above: the runtime reads this back with
|
|
82
|
+
// `parseElevatedGroups`, so the encoding is asserted rather than the spelling.
|
|
83
|
+
expect(Reventless.OwnerScope.parseElevatedGroups(encoded))->toEqual([
|
|
84
|
+
Reventless.AdminGroup.name,
|
|
85
|
+
])
|
|
86
|
+
})
|
|
62
87
|
})
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
+
import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
|
|
3
4
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
5
|
+
import * as AdminGroup$Reventless from "@reventlessdev/reventless-spec/src/types/AdminGroup.res.mjs";
|
|
4
6
|
import * as OwnerScope$Reventless from "@reventlessdev/reventless-spec/src/types/OwnerScope.res.mjs";
|
|
5
7
|
import * as Util_OwnerScopeEnv$ReventlessAws from "../src/util/Util_OwnerScopeEnv.res.mjs";
|
|
6
8
|
|
|
@@ -54,6 +56,17 @@ globalThis.describe("Util_OwnerScopeEnv — the elevated-groups carrier", () =>
|
|
|
54
56
|
withElevated([], () => Util_OwnerScopeEnv$ReventlessAws.applyElevatedGroupsDefault(variables));
|
|
55
57
|
globalThis.expect(Stdlib_Option.isNone(variables[Util_OwnerScopeEnv$ReventlessAws.key])).toBe(true);
|
|
56
58
|
});
|
|
59
|
+
globalThis.test("the platform's administrator default reaches a composed environment", () => {
|
|
60
|
+
OwnerScope$Reventless.clearElevatedGroups();
|
|
61
|
+
Stdlib_Dict.$$delete(process.env, Util_OwnerScopeEnv$ReventlessAws.key);
|
|
62
|
+
OwnerScope$Reventless.defaultElevatedGroups([AdminGroup$Reventless.name]);
|
|
63
|
+
let variables = {};
|
|
64
|
+
Util_OwnerScopeEnv$ReventlessAws.applyElevatedGroupsDefault(variables);
|
|
65
|
+
let value = variables[Util_OwnerScopeEnv$ReventlessAws.key];
|
|
66
|
+
let encoded = value !== undefined ? value : "";
|
|
67
|
+
OwnerScope$Reventless.clearElevatedGroups();
|
|
68
|
+
globalThis.expect(OwnerScope$Reventless.parseElevatedGroups(encoded)).toEqual([AdminGroup$Reventless.name]);
|
|
69
|
+
});
|
|
57
70
|
});
|
|
58
71
|
|
|
59
72
|
export {
|
|
@@ -179,6 +179,12 @@ describe("Util_StoreLayout.protectionFor", () => {
|
|
|
179
179
|
testSync("'prepare' is not a PR stack — the prefix is 'pr-', not 'pr'", () =>
|
|
180
180
|
expect(Util_StoreLayout.protectionFor(~stack="prepare"))->toEqual(Util_StoreLayout.Protected)
|
|
181
181
|
)
|
|
182
|
+
|
|
183
|
+
testSync("a stack declared disposable is unprotected whatever its name", () =>
|
|
184
|
+
expect(Util_StoreLayout.protectionFor(~stack="dev", ~disposable=true))->toEqual(
|
|
185
|
+
Util_StoreLayout.Unprotected,
|
|
186
|
+
)
|
|
187
|
+
)
|
|
182
188
|
})
|
|
183
189
|
|
|
184
190
|
describe("Util_StoreLayout.bucketNameFor", () => {
|
|
@@ -87,16 +87,19 @@ globalThis.describe("Util_StoreLayout.coverageFor", () => {
|
|
|
87
87
|
globalThis.describe("Util_StoreLayout.protectionFor", () => {
|
|
88
88
|
globalThis.test("alpha shares a bucket and is still protected", () => {
|
|
89
89
|
globalThis.expect(Util_StoreLayout$ReventlessAws.layoutFor("alpha", Util_HostUiDomain$ReventlessAws.defaultProdStacks)).toEqual("SharedBucket");
|
|
90
|
-
globalThis.expect(Util_StoreLayout$ReventlessAws.protectionFor("alpha", undefined)).toEqual("Protected");
|
|
90
|
+
globalThis.expect(Util_StoreLayout$ReventlessAws.protectionFor("alpha", undefined, undefined)).toEqual("Protected");
|
|
91
91
|
});
|
|
92
92
|
globalThis.test("prod is protected", () => {
|
|
93
|
-
globalThis.expect(Util_StoreLayout$ReventlessAws.protectionFor("prod", undefined)).toEqual("Protected");
|
|
93
|
+
globalThis.expect(Util_StoreLayout$ReventlessAws.protectionFor("prod", undefined, undefined)).toEqual("Protected");
|
|
94
94
|
});
|
|
95
95
|
globalThis.test("a PR stack is unprotected so teardown does not leak buckets", () => {
|
|
96
|
-
globalThis.expect(Util_StoreLayout$ReventlessAws.protectionFor("pr-42", undefined)).toEqual("Unprotected");
|
|
96
|
+
globalThis.expect(Util_StoreLayout$ReventlessAws.protectionFor("pr-42", undefined, undefined)).toEqual("Unprotected");
|
|
97
97
|
});
|
|
98
98
|
globalThis.test("'prepare' is not a PR stack — the prefix is 'pr-', not 'pr'", () => {
|
|
99
|
-
globalThis.expect(Util_StoreLayout$ReventlessAws.protectionFor("prepare", undefined)).toEqual("Protected");
|
|
99
|
+
globalThis.expect(Util_StoreLayout$ReventlessAws.protectionFor("prepare", undefined, undefined)).toEqual("Protected");
|
|
100
|
+
});
|
|
101
|
+
globalThis.test("a stack declared disposable is unprotected whatever its name", () => {
|
|
102
|
+
globalThis.expect(Util_StoreLayout$ReventlessAws.protectionFor("dev", true, undefined)).toEqual("Unprotected");
|
|
100
103
|
});
|
|
101
104
|
});
|
|
102
105
|
|