@reventlessdev/reventless-seed-aws 1.0.0-alpha.5 → 1.0.0-alpha.7
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 +15 -0
- package/lib/bs/.compiler.log +2 -2
- package/lib/bs/.sourcedirs.json +1 -1
- package/lib/bs/compiler-info.json +2 -2
- package/lib/bs/src/ReventlessSeedAws.ast +0 -0
- package/lib/bs/src/ReventlessSeedAws.cmi +0 -0
- package/lib/bs/src/ReventlessSeedAws.cmj +0 -0
- package/lib/bs/src/ReventlessSeedAws.cmt +0 -0
- package/lib/bs/src/ReventlessSeedAws.res +9 -54
- package/lib/bs/src/ReventlessSeedAws.res.mjs +1 -30
- package/lib/bs/src/ReventlessSeedAws_Reset.ast +0 -0
- package/lib/bs/src/ReventlessSeedAws_Reset.cmi +0 -0
- package/lib/bs/src/ReventlessSeedAws_Reset.cmt +0 -0
- package/lib/bs/src/ReventlessSeedAws_Reset.res +8 -15
- package/lib/bs/tests/EndpointResolutionTest.ast +0 -0
- package/lib/bs/tests/EndpointResolutionTest.cmi +0 -0
- package/lib/bs/tests/EndpointResolutionTest.cmj +0 -0
- package/lib/bs/tests/EndpointResolutionTest.cmt +0 -0
- package/lib/bs/tests/EndpointResolutionTest.res +13 -111
- package/lib/bs/tests/EndpointResolutionTest.res.mjs +4 -97
- package/lib/ocaml/.compiler.log +2 -2
- package/lib/ocaml/EndpointResolutionTest.ast +0 -0
- package/lib/ocaml/EndpointResolutionTest.cmi +0 -0
- package/lib/ocaml/EndpointResolutionTest.cmj +0 -0
- package/lib/ocaml/EndpointResolutionTest.cmt +0 -0
- package/lib/ocaml/EndpointResolutionTest.res +13 -111
- package/lib/ocaml/ReventlessSeedAws.ast +0 -0
- package/lib/ocaml/ReventlessSeedAws.cmi +0 -0
- package/lib/ocaml/ReventlessSeedAws.cmj +0 -0
- package/lib/ocaml/ReventlessSeedAws.cmt +0 -0
- package/lib/ocaml/ReventlessSeedAws.res +9 -54
- package/lib/ocaml/ReventlessSeedAws_Reset.ast +0 -0
- package/lib/ocaml/ReventlessSeedAws_Reset.cmi +0 -0
- package/lib/ocaml/ReventlessSeedAws_Reset.cmt +0 -0
- package/lib/ocaml/ReventlessSeedAws_Reset.res +8 -15
- package/package.json +5 -4
- package/rescript.json +1 -0
- package/src/ReventlessSeedAws.res +9 -54
- package/src/ReventlessSeedAws.res.mjs +1 -30
- package/src/ReventlessSeedAws_Reset.res +8 -15
- package/tests/EndpointResolutionTest.res +13 -111
- package/tests/EndpointResolutionTest.res.mjs +4 -97
|
@@ -48,14 +48,7 @@ module Ddb = AwsSdk.DynamoDb
|
|
|
48
48
|
module Rgt = AwsSdk.ResourceGroupsTaggingApi
|
|
49
49
|
module S3 = AwsSdk.S3
|
|
50
50
|
|
|
51
|
-
@scope("process") @val external exit: int => unit = "exit"
|
|
52
|
-
@scope("process") @val external processEnv: dict<string> = "env"
|
|
53
|
-
@module("node:fs") external readFileSync: (string, string) => string = "readFileSync"
|
|
54
51
|
|
|
55
|
-
type stream
|
|
56
|
-
@scope("process") @val external stdin: stream = "stdin"
|
|
57
|
-
// `process.stdin.isTTY` is `true` interactively and `undefined` under a pipe/CI.
|
|
58
|
-
@get external isTTY: stream => option<bool> = "isTTY"
|
|
59
52
|
|
|
60
53
|
// The Pulumi project name, which the framework stamps as `reventless:platform` on
|
|
61
54
|
// every resource (`Plugin.res`: `platformName = getProjectName()`). Discovery
|
|
@@ -66,7 +59,7 @@ type stream
|
|
|
66
59
|
// the target project's Pulumi.yaml — the same dir the pulumi subprocess uses.
|
|
67
60
|
let projectName = (~projectDir: string): string => {
|
|
68
61
|
let path = `${projectDir}/Pulumi.yaml`
|
|
69
|
-
let raw = try readFileSync(path
|
|
62
|
+
let raw = try NodeFs.readFileSync(path) catch {
|
|
70
63
|
| _ => throw(Seed.Failed(`could not read ${path} to scope the wipe to this Pulumi project.`))
|
|
71
64
|
}
|
|
72
65
|
switch raw
|
|
@@ -561,7 +554,7 @@ let run = (~stack=?, ~backend=?, ~targets: array<target>, ()): unit => {
|
|
|
561
554
|
),
|
|
562
555
|
)
|
|
563
556
|
}
|
|
564
|
-
|
|
557
|
+
NodeProcess.env->Dict.set("AWS_REGION", region)
|
|
565
558
|
|
|
566
559
|
// Discover + count each target, scoped to its own project via the platform
|
|
567
560
|
// tag so a same-named stack from another project is never touched.
|
|
@@ -597,7 +590,7 @@ let run = (~stack=?, ~backend=?, ~targets: array<target>, ()): unit => {
|
|
|
597
590
|
Seed.Prompt.close()
|
|
598
591
|
Console.log("")
|
|
599
592
|
Console.log(`Nothing to reset — the selected scope already reads empty in ${region}.`)
|
|
600
|
-
exit(0)
|
|
593
|
+
NodeProcess.exit(0)
|
|
601
594
|
}
|
|
602
595
|
|
|
603
596
|
// Confirmation. Interactively, re-typing the exact stack name IS the
|
|
@@ -606,7 +599,7 @@ let run = (~stack=?, ~backend=?, ~targets: array<target>, ()): unit => {
|
|
|
606
599
|
// TTY (CI/scripts) there is nothing to type into, so
|
|
607
600
|
// REVENTLESS_WIPE_CONFIRM=<stack> is the equivalent opt-in. Dry-run is the
|
|
608
601
|
// default either way.
|
|
609
|
-
let interactive = stdin->isTTY->Option.getOr(false)
|
|
602
|
+
let interactive = NodeProcess.stdin->NodeProcess.isTTY->Option.getOr(false)
|
|
610
603
|
let confirmed = if interactive {
|
|
611
604
|
let typed = await Seed.Prompt.ask(
|
|
612
605
|
`About to permanently empty ${total->Int.toString} item(s)/object(s) across the selected scope of "${stack}". ` ++
|
|
@@ -624,7 +617,7 @@ let run = (~stack=?, ~backend=?, ~targets: array<target>, ()): unit => {
|
|
|
624
617
|
? "Dry run — nothing was deleted."
|
|
625
618
|
: `Dry run — nothing was deleted. Set REVENTLESS_WIPE_CONFIRM=${stack} to empty this scope non-interactively.`,
|
|
626
619
|
)
|
|
627
|
-
exit(0)
|
|
620
|
+
NodeProcess.exit(0)
|
|
628
621
|
}
|
|
629
622
|
|
|
630
623
|
for i in 0 to resolvedList->Array.length - 1 {
|
|
@@ -681,19 +674,19 @@ let run = (~stack=?, ~backend=?, ~targets: array<target>, ()): unit => {
|
|
|
681
674
|
|
|
682
675
|
Console.log("")
|
|
683
676
|
Console.log(`Reset complete — the selected scope of "${stack}" reads empty and is re-seedable.`)
|
|
684
|
-
exit(0)
|
|
677
|
+
NodeProcess.exit(0)
|
|
685
678
|
} catch {
|
|
686
679
|
| Seed.Failed(message) =>
|
|
687
680
|
Seed.Prompt.close()
|
|
688
681
|
Console.error("")
|
|
689
682
|
Console.error(`Reset aborted — ${message}`)
|
|
690
|
-
exit(1)
|
|
683
|
+
NodeProcess.exit(1)
|
|
691
684
|
| exn =>
|
|
692
685
|
Seed.Prompt.close()
|
|
693
686
|
Console.error("")
|
|
694
687
|
Console.error("Reset aborted with an unexpected error:")
|
|
695
688
|
Console.error(exn->JsExn.fromException->Option.flatMap(JsExn.message)->Option.getOr("unknown"))
|
|
696
|
-
exit(1)
|
|
689
|
+
NodeProcess.exit(1)
|
|
697
690
|
}
|
|
698
691
|
}
|
|
699
692
|
go()->ignore
|
|
@@ -1,37 +1,30 @@
|
|
|
1
|
-
// Which document `resolveEndpoints` reads, and
|
|
1
|
+
// Which document `resolveEndpoints` reads, and which GraphQL endpoint each arm takes
|
|
2
|
+
// from it.
|
|
2
3
|
//
|
|
3
4
|
// `endpointsFrom` is the pure half of `resolveEndpoints`; the impure half is a
|
|
4
|
-
// `pulumi stack output` subprocess and a `config.json` fetch, and the decision
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
// shell publishes no `hostShellUrl` by construction, so it takes that arm, and
|
|
10
|
-
// the per-store endpoint is its only way to reach the store.
|
|
5
|
+
// `pulumi stack output` subprocess and a `config.json` fetch, and the decision these
|
|
6
|
+
// tests pin is in neither. Upload endpoints are no longer resolved here — under route B
|
|
7
|
+
// the seed mints through the domain API's `Upload_Presign` mutation on the GraphQL
|
|
8
|
+
// endpoint below — so the only decision left is which GraphQL endpoint each source
|
|
9
|
+
// publishes, and the merged-over-per-plugin precedence within the stack-outputs arm.
|
|
11
10
|
|
|
12
11
|
open JestGlobals
|
|
13
12
|
open ReventlessSeed
|
|
14
13
|
|
|
15
|
-
@val @scope("process") external processEnv: dict<string> = "env"
|
|
16
|
-
|
|
17
14
|
// Every value read here has an env override, and an ambient one in the runner's
|
|
18
|
-
// environment (AWS_REGION is routinely set) would silently stand in for the
|
|
19
|
-
//
|
|
15
|
+
// environment (AWS_REGION is routinely set) would silently stand in for the document
|
|
16
|
+
// under test. An empty string reads as unset.
|
|
20
17
|
let clearOverrides = () =>
|
|
21
18
|
[
|
|
22
19
|
"REVENTLESS_GRAPHQL_ENDPOINT",
|
|
23
|
-
"REVENTLESS_UPLOAD_ENDPOINT",
|
|
24
20
|
"AWS_REGION",
|
|
25
21
|
"COGNITO_CLIENT_ID",
|
|
26
22
|
"SEED_SKIP_UPLOADS",
|
|
27
|
-
]->Array.forEach(k =>
|
|
23
|
+
]->Array.forEach(k => NodeProcess.env->Dict.set(k, ""))
|
|
28
24
|
|
|
29
25
|
let obj = entries => JSON.Encode.object(entries->Dict.fromArray)
|
|
30
26
|
let str = JSON.Encode.string
|
|
31
27
|
|
|
32
|
-
// A host shell's config.json and the stack outputs of a platform that serves no
|
|
33
|
-
// shell — the two documents the two arms read, minus the upload keys each test
|
|
34
|
-
// supplies.
|
|
35
28
|
let config = (~extra: array<(string, JSON.t)>) =>
|
|
36
29
|
obj(
|
|
37
30
|
Array.concat(
|
|
@@ -56,84 +49,18 @@ let outputs = (~extra: array<(string, JSON.t)>) =>
|
|
|
56
49
|
),
|
|
57
50
|
)
|
|
58
51
|
|
|
59
|
-
let storeEndpoints = obj([("Catalog.productImages", str("https://presign.example/"))])
|
|
60
|
-
|
|
61
52
|
describe("endpointsFrom — host shell arm", () => {
|
|
62
53
|
beforeEach(clearOverrides)
|
|
63
54
|
|
|
64
|
-
testSync("reads the
|
|
65
|
-
let eps = ReventlessSeedAws.endpointsFrom(
|
|
66
|
-
|
|
67
|
-
HostShellConfig(
|
|
68
|
-
config(
|
|
69
|
-
~extra=[
|
|
70
|
-
("uploadEndpoint", str("https://legacy.example/")),
|
|
71
|
-
("uploadEndpoints", storeEndpoints),
|
|
72
|
-
],
|
|
73
|
-
),
|
|
74
|
-
),
|
|
75
|
-
)
|
|
76
|
-
expect(eps.uploadEndpoint)->toBe("https://legacy.example/")
|
|
77
|
-
expect(eps.uploadEndpoints)->toEqual(
|
|
78
|
-
Dict.fromArray([("Catalog.productImages", "https://presign.example/")]),
|
|
79
|
-
)
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
// A shell fronting only declared stores writes no singular key. That used to
|
|
83
|
-
// fail the whole run before a command was sent ("deployment is missing
|
|
84
|
-
// uploadEndpoint"), which is a harder failure than the one this plan fixes.
|
|
85
|
-
testSync("a shell publishing only per-store endpoints resolves an empty legacy service", () => {
|
|
86
|
-
let eps = ReventlessSeedAws.endpointsFrom(
|
|
87
|
-
~stack="alpha",
|
|
88
|
-
HostShellConfig(config(~extra=[("uploadEndpoints", storeEndpoints)])),
|
|
89
|
-
)
|
|
90
|
-
expect(eps.uploadEndpoint)->toBe("")
|
|
91
|
-
expect(eps.uploadEndpoints->Dict.keysToArray)->toEqual(["Catalog.productImages"])
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
testSync("REVENTLESS_UPLOAD_ENDPOINT overrides the legacy service and leaves the map alone", () => {
|
|
95
|
-
processEnv->Dict.set("REVENTLESS_UPLOAD_ENDPOINT", "https://override.example/")
|
|
96
|
-
let eps = ReventlessSeedAws.endpointsFrom(
|
|
97
|
-
~stack="alpha",
|
|
98
|
-
HostShellConfig(
|
|
99
|
-
config(
|
|
100
|
-
~extra=[
|
|
101
|
-
("uploadEndpoint", str("https://legacy.example/")),
|
|
102
|
-
("uploadEndpoints", storeEndpoints),
|
|
103
|
-
],
|
|
104
|
-
),
|
|
105
|
-
),
|
|
106
|
-
)
|
|
107
|
-
expect(eps.uploadEndpoint)->toBe("https://override.example/")
|
|
108
|
-
expect(eps.uploadEndpoints->Dict.get("Catalog.productImages"))->toEqual(
|
|
109
|
-
Some("https://presign.example/"),
|
|
110
|
-
)
|
|
55
|
+
testSync("reads the GraphQL endpoint from the shell config", () => {
|
|
56
|
+
let eps = ReventlessSeedAws.endpointsFrom(~stack="alpha", HostShellConfig(config(~extra=[])))
|
|
57
|
+
expect(eps.graphql)->toBe("https://api.example/graphql")
|
|
111
58
|
})
|
|
112
59
|
})
|
|
113
60
|
|
|
114
61
|
describe("endpointsFrom — stack outputs arm", () => {
|
|
115
62
|
beforeEach(clearOverrides)
|
|
116
63
|
|
|
117
|
-
// The lookup that was missing entirely: this arm had no upload source but the
|
|
118
|
-
// env var, so a `PlatformOwned` deployment resolved "" whatever it published.
|
|
119
|
-
testSync("reads the uploadEndpoints stack output", () => {
|
|
120
|
-
let eps = ReventlessSeedAws.endpointsFrom(
|
|
121
|
-
~stack="pr-verify",
|
|
122
|
-
StackOutputs(outputs(~extra=[("uploadEndpoints", storeEndpoints)])),
|
|
123
|
-
)
|
|
124
|
-
expect(eps.uploadEndpoints)->toEqual(
|
|
125
|
-
Dict.fromArray([("Catalog.productImages", "https://presign.example/")]),
|
|
126
|
-
)
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
// Declaring no store is a legitimate deployment, not a broken one — it stays a
|
|
130
|
-
// no-op at the data set rather than failing the run.
|
|
131
|
-
testSync("a deployment declaring no store resolves an empty map without failing", () => {
|
|
132
|
-
let eps = ReventlessSeedAws.endpointsFrom(~stack="pr-verify", StackOutputs(outputs(~extra=[])))
|
|
133
|
-
expect(eps.uploadEndpoint)->toBe("")
|
|
134
|
-
expect(eps.uploadEndpoints->Dict.keysToArray)->toEqual([])
|
|
135
|
-
})
|
|
136
|
-
|
|
137
64
|
testSync("prefers the merged API endpoint over the per-plugin one", () => {
|
|
138
65
|
let eps = ReventlessSeedAws.endpointsFrom(
|
|
139
66
|
~stack="pr-verify",
|
|
@@ -154,28 +81,3 @@ describe("endpointsFrom — stack outputs arm", () => {
|
|
|
154
81
|
}
|
|
155
82
|
)
|
|
156
83
|
})
|
|
157
|
-
|
|
158
|
-
describe("endpointsFrom — malformed uploadEndpoints", () => {
|
|
159
|
-
beforeEach(clearOverrides)
|
|
160
|
-
|
|
161
|
-
// One bad member should not cost the run every endpoint it could have used.
|
|
162
|
-
testSync("drops a non-string member rather than the whole map", () => {
|
|
163
|
-
let eps = ReventlessSeedAws.endpointsFrom(
|
|
164
|
-
~stack="pr-verify",
|
|
165
|
-
StackOutputs(
|
|
166
|
-
outputs(
|
|
167
|
-
~extra=[
|
|
168
|
-
(
|
|
169
|
-
"uploadEndpoints",
|
|
170
|
-
obj([
|
|
171
|
-
("Catalog.productImages", str("https://presign.example/")),
|
|
172
|
-
("Catalog.broken", JSON.Encode.int(7)),
|
|
173
|
-
]),
|
|
174
|
-
),
|
|
175
|
-
],
|
|
176
|
-
),
|
|
177
|
-
),
|
|
178
|
-
)
|
|
179
|
-
expect(eps.uploadEndpoints->Dict.keysToArray)->toEqual(["Catalog.productImages"])
|
|
180
|
-
})
|
|
181
|
-
})
|
|
@@ -8,7 +8,6 @@ import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_excep
|
|
|
8
8
|
function clearOverrides() {
|
|
9
9
|
[
|
|
10
10
|
"REVENTLESS_GRAPHQL_ENDPOINT",
|
|
11
|
-
"REVENTLESS_UPLOAD_ENDPOINT",
|
|
12
11
|
"AWS_REGION",
|
|
13
12
|
"COGNITO_CLIENT_ID",
|
|
14
13
|
"SEED_SKIP_UPLOADS"
|
|
@@ -59,87 +58,19 @@ function outputs(extra) {
|
|
|
59
58
|
].concat(extra));
|
|
60
59
|
}
|
|
61
60
|
|
|
62
|
-
let storeEndpoints = Object.fromEntries([[
|
|
63
|
-
"Catalog.productImages",
|
|
64
|
-
"https://presign.example/"
|
|
65
|
-
]]);
|
|
66
|
-
|
|
67
61
|
globalThis.describe("endpointsFrom — host shell arm", () => {
|
|
68
62
|
globalThis.beforeEach(clearOverrides);
|
|
69
|
-
globalThis.test("reads the
|
|
70
|
-
let eps = ReventlessSeedAws.endpointsFrom("alpha", {
|
|
71
|
-
TAG: "HostShellConfig",
|
|
72
|
-
_0: config([
|
|
73
|
-
[
|
|
74
|
-
"uploadEndpoint",
|
|
75
|
-
"https://legacy.example/"
|
|
76
|
-
],
|
|
77
|
-
[
|
|
78
|
-
"uploadEndpoints",
|
|
79
|
-
storeEndpoints
|
|
80
|
-
]
|
|
81
|
-
])
|
|
82
|
-
});
|
|
83
|
-
globalThis.expect(eps.uploadEndpoint).toBe("https://legacy.example/");
|
|
84
|
-
globalThis.expect(eps.uploadEndpoints).toEqual(Object.fromEntries([[
|
|
85
|
-
"Catalog.productImages",
|
|
86
|
-
"https://presign.example/"
|
|
87
|
-
]]));
|
|
88
|
-
});
|
|
89
|
-
globalThis.test("a shell publishing only per-store endpoints resolves an empty legacy service", () => {
|
|
63
|
+
globalThis.test("reads the GraphQL endpoint from the shell config", () => {
|
|
90
64
|
let eps = ReventlessSeedAws.endpointsFrom("alpha", {
|
|
91
65
|
TAG: "HostShellConfig",
|
|
92
|
-
_0: config([
|
|
93
|
-
"uploadEndpoints",
|
|
94
|
-
storeEndpoints
|
|
95
|
-
]])
|
|
66
|
+
_0: config([])
|
|
96
67
|
});
|
|
97
|
-
globalThis.expect(eps.
|
|
98
|
-
globalThis.expect(Object.keys(eps.uploadEndpoints)).toEqual(["Catalog.productImages"]);
|
|
99
|
-
});
|
|
100
|
-
globalThis.test("REVENTLESS_UPLOAD_ENDPOINT overrides the legacy service and leaves the map alone", () => {
|
|
101
|
-
process.env["REVENTLESS_UPLOAD_ENDPOINT"] = "https://override.example/";
|
|
102
|
-
let eps = ReventlessSeedAws.endpointsFrom("alpha", {
|
|
103
|
-
TAG: "HostShellConfig",
|
|
104
|
-
_0: config([
|
|
105
|
-
[
|
|
106
|
-
"uploadEndpoint",
|
|
107
|
-
"https://legacy.example/"
|
|
108
|
-
],
|
|
109
|
-
[
|
|
110
|
-
"uploadEndpoints",
|
|
111
|
-
storeEndpoints
|
|
112
|
-
]
|
|
113
|
-
])
|
|
114
|
-
});
|
|
115
|
-
globalThis.expect(eps.uploadEndpoint).toBe("https://override.example/");
|
|
116
|
-
globalThis.expect(eps.uploadEndpoints["Catalog.productImages"]).toEqual("https://presign.example/");
|
|
68
|
+
globalThis.expect(eps.graphql).toBe("https://api.example/graphql");
|
|
117
69
|
});
|
|
118
70
|
});
|
|
119
71
|
|
|
120
72
|
globalThis.describe("endpointsFrom — stack outputs arm", () => {
|
|
121
73
|
globalThis.beforeEach(clearOverrides);
|
|
122
|
-
globalThis.test("reads the uploadEndpoints stack output", () => {
|
|
123
|
-
let eps = ReventlessSeedAws.endpointsFrom("pr-verify", {
|
|
124
|
-
TAG: "StackOutputs",
|
|
125
|
-
_0: outputs([[
|
|
126
|
-
"uploadEndpoints",
|
|
127
|
-
storeEndpoints
|
|
128
|
-
]])
|
|
129
|
-
});
|
|
130
|
-
globalThis.expect(eps.uploadEndpoints).toEqual(Object.fromEntries([[
|
|
131
|
-
"Catalog.productImages",
|
|
132
|
-
"https://presign.example/"
|
|
133
|
-
]]));
|
|
134
|
-
});
|
|
135
|
-
globalThis.test("a deployment declaring no store resolves an empty map without failing", () => {
|
|
136
|
-
let eps = ReventlessSeedAws.endpointsFrom("pr-verify", {
|
|
137
|
-
TAG: "StackOutputs",
|
|
138
|
-
_0: outputs([])
|
|
139
|
-
});
|
|
140
|
-
globalThis.expect(eps.uploadEndpoint).toBe("");
|
|
141
|
-
globalThis.expect(Object.keys(eps.uploadEndpoints)).toEqual([]);
|
|
142
|
-
});
|
|
143
74
|
globalThis.test("prefers the merged API endpoint over the per-plugin one", () => {
|
|
144
75
|
let eps = ReventlessSeedAws.endpointsFrom("pr-verify", {
|
|
145
76
|
TAG: "StackOutputs",
|
|
@@ -174,35 +105,11 @@ globalThis.describe("endpointsFrom — stack outputs arm", () => {
|
|
|
174
105
|
});
|
|
175
106
|
});
|
|
176
107
|
|
|
177
|
-
globalThis.describe("endpointsFrom — malformed uploadEndpoints", () => {
|
|
178
|
-
globalThis.beforeEach(clearOverrides);
|
|
179
|
-
globalThis.test("drops a non-string member rather than the whole map", () => {
|
|
180
|
-
let eps = ReventlessSeedAws.endpointsFrom("pr-verify", {
|
|
181
|
-
TAG: "StackOutputs",
|
|
182
|
-
_0: outputs([[
|
|
183
|
-
"uploadEndpoints",
|
|
184
|
-
Object.fromEntries([
|
|
185
|
-
[
|
|
186
|
-
"Catalog.productImages",
|
|
187
|
-
"https://presign.example/"
|
|
188
|
-
],
|
|
189
|
-
[
|
|
190
|
-
"Catalog.broken",
|
|
191
|
-
7
|
|
192
|
-
]
|
|
193
|
-
])
|
|
194
|
-
]])
|
|
195
|
-
});
|
|
196
|
-
globalThis.expect(Object.keys(eps.uploadEndpoints)).toEqual(["Catalog.productImages"]);
|
|
197
|
-
});
|
|
198
|
-
});
|
|
199
|
-
|
|
200
108
|
export {
|
|
201
109
|
clearOverrides,
|
|
202
110
|
obj,
|
|
203
111
|
str,
|
|
204
112
|
config,
|
|
205
113
|
outputs,
|
|
206
|
-
storeEndpoints,
|
|
207
114
|
}
|
|
208
|
-
/*
|
|
115
|
+
/* Not a pure module */
|