@reventlessdev/reventless-aws 3.0.0-alpha.250 → 3.0.0-alpha.252
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 +18 -0
- package/package.json +7 -7
- package/src/Platform.res +58 -68
- package/src/Platform.res.mjs +60 -102
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Ops.res +13 -11
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Ops.res.mjs +16 -21
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res +5 -4
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res.mjs +8 -12
- package/src/adapter/Upload/Upload_Presign_S3.res +179 -92
- package/src/adapter/Upload/Upload_Presign_S3.res.mjs +129 -39
- package/src/adapter/Upload/Upload_Presign_S3_Ops.res +227 -104
- package/src/adapter/Upload/Upload_Presign_S3_Ops.res.mjs +195 -75
- package/src/util/Util_DeadLetterQueue.res +26 -0
- package/src/util/Util_DeadLetterQueue.res.mjs +9 -0
- package/tests/Upload_ReleaseRuleTest.res +90 -0
- package/tests/Upload_ReleaseRuleTest.res.mjs +110 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,24 @@
|
|
|
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.252 (2026-08-01)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **aws:** let a dead letter be seen ([e64949b](https://github.com/ReventlessDev/reventless-core/commit/e64949bb3f4965cb8e6fc7a2f04971290ebe43bf))
|
|
11
|
+
* **aws:** let the Function URL own CORS on the upload and geocoder services ([19d4b7f](https://github.com/ReventlessDev/reventless-core/commit/19d4b7f26f0925b7c659a1b37555e952bb7c7f46))
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
* **upload:** add the release half of the upload contract via the domain API ([448f887](https://github.com/ReventlessDev/reventless-core/commit/448f88714a5875be420f794a08d482fcf4ba8404))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# 3.0.0-alpha.251 (2026-08-01)
|
|
18
|
+
|
|
19
|
+
### Bug Fixes
|
|
20
|
+
|
|
21
|
+
* **core:** drain the inbound audit log per request, not wholesale ([e18d4ec](https://github.com/ReventlessDev/reventless-core/commit/e18d4ec4b7ffb38a9e2bd3594d39a07e2ee91851))
|
|
22
|
+
|
|
23
|
+
|
|
6
24
|
# 3.0.0-alpha.250 (2026-08-01)
|
|
7
25
|
|
|
8
26
|
**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.252",
|
|
4
4
|
"description": "AWS adapters for Reventless",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"dependencies": {
|
|
@@ -11,18 +11,18 @@
|
|
|
11
11
|
"@aws-sdk/s3-request-presigner": "3.970.0",
|
|
12
12
|
"sury": "11.0.0-alpha.4",
|
|
13
13
|
"uuid": "^13.0.0",
|
|
14
|
-
"@reventlessdev/rescript-node": "2.0.0-alpha.0",
|
|
15
|
-
"@reventlessdev/rescript-jest": "1.0.0-alpha.10",
|
|
16
14
|
"@reventlessdev/rescript-aws-sdk": "3.0.0-alpha.0",
|
|
17
15
|
"@reventlessdev/rescript-effect": "0.1.0-alpha.32",
|
|
16
|
+
"@reventlessdev/rescript-jest": "1.0.0-alpha.10",
|
|
17
|
+
"@reventlessdev/rescript-node": "2.0.0-alpha.0",
|
|
18
18
|
"@reventlessdev/rescript-pulumi-aws": "2.4.0-alpha.62",
|
|
19
19
|
"@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.18",
|
|
20
20
|
"@reventlessdev/rescript-uuid": "2.0.0-alpha.0",
|
|
21
|
-
"@reventlessdev/reventless-infra": "3.0.0-alpha.
|
|
22
|
-
"@reventlessdev/reventless-core": "3.0.0-alpha.197",
|
|
21
|
+
"@reventlessdev/reventless-infra": "3.0.0-alpha.116",
|
|
23
22
|
"@reventlessdev/reventless-interop": "3.0.0-alpha.30",
|
|
24
|
-
"@reventlessdev/reventless-spec": "3.0.0-alpha.
|
|
25
|
-
"@reventlessdev/reventless-
|
|
23
|
+
"@reventlessdev/reventless-spec": "3.0.0-alpha.91",
|
|
24
|
+
"@reventlessdev/reventless-core": "3.0.0-alpha.199",
|
|
25
|
+
"@reventlessdev/reventless-postgres": "3.0.0-alpha.63"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"rescript": "12.3.0",
|
package/src/Platform.res
CHANGED
|
@@ -67,7 +67,6 @@ type objectStoreEndpoint = {
|
|
|
67
67
|
// only known after the bucket resolves — and a plain string here is exactly
|
|
68
68
|
// how this shipped exporting a bucket name that no ARN matches.
|
|
69
69
|
bucketName: Pulumi.Output.t<string>,
|
|
70
|
-
uploadUrl: Pulumi.Output.t<string>,
|
|
71
70
|
// Public base URL the store is served from, when the platform serves it
|
|
72
71
|
// itself. `None` when a host-UI bundle is deployed — there the shell's own
|
|
73
72
|
// origin serves the store same-origin and a relative `/{prefix}/…` resolves
|
|
@@ -170,9 +169,15 @@ module MakeWithConfig = (
|
|
|
170
169
|
// "Relay node resolution" section of the merged-api plan (never resolved on
|
|
171
170
|
// any deployed AWS platform, zero consumers; the Node interface and global
|
|
172
171
|
// IDs stay).
|
|
172
|
+
// The upload service (route B) lives on the domain base, not the Admin-gated admin
|
|
173
|
+
// base: `Upload_Presign`/`Upload_Release` take the domain API's default
|
|
174
|
+
// `AllowAuthenticated` auth so any authenticated user can mint/release their own
|
|
175
|
+
// uploads. See [docs/plans/upload-release-path.md] § "Which API". (Split mode only —
|
|
176
|
+
// unified mode carries the admin base here instead; it declares no stores in practice,
|
|
177
|
+
// so the upload resolvers below are never created there.)
|
|
173
178
|
let domainBaseFragment = ReventlessCore.GraphQL_Stitcher.encode({
|
|
174
|
-
types:
|
|
175
|
-
mutations:
|
|
179
|
+
types: ReventlessCore.Platform_AdminApi.uploadTypes,
|
|
180
|
+
mutations: ReventlessCore.Platform_AdminApi.uploadMutationFields,
|
|
176
181
|
queries: [" Platform_ping: String"],
|
|
177
182
|
subscriptions: [],
|
|
178
183
|
subscriptionSources: [],
|
|
@@ -1585,17 +1590,14 @@ module MakeWithConfig = (
|
|
|
1585
1590
|
b
|
|
1586
1591
|
}
|
|
1587
1592
|
let storeHandle = bucket->Capability_ObjectStore_S3.underPrefix(~keyPrefix)
|
|
1588
|
-
// One presign service per store, scoped to that store's own prefix.
|
|
1589
|
-
let presign = Upload_Presign_S3.make(
|
|
1590
|
-
~name=`UploadPresign-${plugin}-${store}`,
|
|
1591
|
-
~bucketName=storeHandle.bucketName,
|
|
1592
|
-
~servedPrefix=storeHandle.keyPrefix,
|
|
1593
|
-
)
|
|
1594
1593
|
// `bucketName` is the layout's *logical* name and groups the served view
|
|
1595
1594
|
// below; `storeHandle.bucketName` is the physical one Pulumi resolves, and
|
|
1596
1595
|
// is what a consumer needs to build an ARN. Carrying both is the point —
|
|
1597
1596
|
// they are different strings and only one of them exists in S3.
|
|
1598
|
-
|
|
1597
|
+
//
|
|
1598
|
+
// Presigning is no longer per store: one platform-API Upload service (below)
|
|
1599
|
+
// covers every declared store, keyed by the qualified `{plugin}.{store}` name.
|
|
1600
|
+
(`${plugin}.${store}`, keyPrefix, bucketName, storeHandle.bucketName)
|
|
1599
1601
|
})
|
|
1600
1602
|
|
|
1601
1603
|
// Group the served view by bucket: one origin and one bucket policy per
|
|
@@ -1606,7 +1608,7 @@ module MakeWithConfig = (
|
|
|
1606
1608
|
->Option.map(b => {
|
|
1607
1609
|
ReventlessInfra.Platform.id: bucketName,
|
|
1608
1610
|
prefixes: declaredStoreServices
|
|
1609
|
-
->Array.filterMap(((_, prefix, bn, _
|
|
1611
|
+
->Array.filterMap(((_, prefix, bn, _)) => bn == bucketName ? Some(prefix) : None),
|
|
1610
1612
|
bucketId: b.bucketId,
|
|
1611
1613
|
bucketArn: b.bucketArn,
|
|
1612
1614
|
bucketRegionalDomainName: b.bucketRegionalDomainName,
|
|
@@ -1645,30 +1647,58 @@ module MakeWithConfig = (
|
|
|
1645
1647
|
keyPrefix,
|
|
1646
1648
|
_logicalBucketName,
|
|
1647
1649
|
physicalBucketName,
|
|
1648
|
-
uploadUrl,
|
|
1649
1650
|
)) => {
|
|
1650
1651
|
store,
|
|
1651
1652
|
keyPrefix,
|
|
1652
1653
|
bucketName: physicalBucketName->Pulumi.Output.fromInput,
|
|
1653
|
-
uploadUrl,
|
|
1654
1654
|
baseUrl: storeServingBaseUrl,
|
|
1655
1655
|
})
|
|
1656
1656
|
objectStoreEndpointsRef := declaredStoreEndpoints
|
|
1657
1657
|
|
|
1658
|
+
// One domain-API Upload service (route B1) covers every declared store plus the
|
|
1659
|
+
// legacy `hostUiBundle.uploadBucket`, keyed by the qualified `{plugin}.{store}` name
|
|
1660
|
+
// the caller passes as the `store` argument. On the domain API (not the Admin-gated
|
|
1661
|
+
// platform API — see the plan's "Which API" note) so any authenticated user can
|
|
1662
|
+
// mint/release. Created here in the outer scope — not inside the `hostUiBundle`
|
|
1663
|
+
// branch — because a platform whose UI ships from another stack still has declared
|
|
1664
|
+
// stores that need presigning. `uploads` keys the legacy store, matching the prefix
|
|
1665
|
+
// it has always served under.
|
|
1666
|
+
let uploadServiceStores =
|
|
1667
|
+
declaredStoreServices
|
|
1668
|
+
->Array.map(((qualified, keyPrefix, _logical, physicalBucketName)) => {
|
|
1669
|
+
Upload_Presign_S3.qualified: qualified,
|
|
1670
|
+
bucketName: physicalBucketName,
|
|
1671
|
+
servedPrefix: keyPrefix,
|
|
1672
|
+
})
|
|
1673
|
+
->Array.concat(
|
|
1674
|
+
switch hostUiBundle->Option.flatMap(c => c.uploadBucket) {
|
|
1675
|
+
| Some(store) => [
|
|
1676
|
+
{
|
|
1677
|
+
Upload_Presign_S3.qualified: store.keyPrefix,
|
|
1678
|
+
bucketName: store.bucketName,
|
|
1679
|
+
servedPrefix: store.keyPrefix,
|
|
1680
|
+
},
|
|
1681
|
+
]
|
|
1682
|
+
| None => []
|
|
1683
|
+
},
|
|
1684
|
+
)
|
|
1685
|
+
if uploadServiceStores->Array.length > 0 {
|
|
1686
|
+
let _uploadService = Upload_Presign_S3.make(
|
|
1687
|
+
~api=domainApi,
|
|
1688
|
+
~stores=uploadServiceStores,
|
|
1689
|
+
~opts={},
|
|
1690
|
+
)
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1658
1693
|
// Exported unconditionally — the provisioning above already is. Their only
|
|
1659
1694
|
// consumers used to sit inside `switch hostUiBundle`, which left a platform
|
|
1660
1695
|
// whose UI ships from another stack holding stores it could not name.
|
|
1661
1696
|
//
|
|
1662
1697
|
// Omitted entirely when nothing is declared, so a deployment with no
|
|
1663
|
-
// declared store keeps a byte-identical output set.
|
|
1698
|
+
// declared store keeps a byte-identical output set. The presign endpoint is no
|
|
1699
|
+
// longer exported — under route B the client calls the platform API's
|
|
1700
|
+
// `Upload_Presign` mutation, so there is no per-store URL to publish.
|
|
1664
1701
|
if declaredStoreEndpoints->Array.length > 0 {
|
|
1665
|
-
Pulumi.Pulumi.export(
|
|
1666
|
-
"uploadEndpoints",
|
|
1667
|
-
declaredStoreEndpoints
|
|
1668
|
-
->Array.map(e => e.uploadUrl->Pulumi.Output.apply(u => (e.store, JSON.Encode.string(u))))
|
|
1669
|
-
->Pulumi.Output.all
|
|
1670
|
-
->Pulumi.Output.apply(pairs => pairs->Dict.fromArray->JSON.Encode.object),
|
|
1671
|
-
)
|
|
1672
1702
|
Pulumi.Pulumi.export(
|
|
1673
1703
|
"objectStores",
|
|
1674
1704
|
declaredStoreEndpoints
|
|
@@ -1826,27 +1856,11 @@ module MakeWithConfig = (
|
|
|
1826
1856
|
| None => Pulumi.Output.make(None)
|
|
1827
1857
|
}
|
|
1828
1858
|
|
|
1829
|
-
//
|
|
1830
|
-
//
|
|
1831
|
-
// `
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
Upload_Presign_S3.make(~bucketName=store.bucketName).url->Pulumi.Output.apply(u => Some(u))
|
|
1835
|
-
| None => Pulumi.Output.make(None)
|
|
1836
|
-
}
|
|
1837
|
-
|
|
1838
|
-
// Per-store presign endpoints, keyed by the store's qualified name. This
|
|
1839
|
-
// is what lets an upload input bind to the store its field *declares*
|
|
1840
|
-
// rather than inferring one from the field's name — the endpoint exists
|
|
1841
|
-
// per store, so there is something concrete to bind to.
|
|
1842
|
-
//
|
|
1843
|
-
// `uploadEndpoint` (singular) stays as the legacy service's URL: a shell
|
|
1844
|
-
// built before per-store binding reads it and is unaffected.
|
|
1845
|
-
let storeUploadEndpointsOutput: Pulumi.Output.t<array<(string, string)>> =
|
|
1846
|
-
declaredStoreServices
|
|
1847
|
-
->Array.map(((qualified, _, _, _, url)) => url->Pulumi.Output.apply(u => (qualified, u)))
|
|
1848
|
-
->Pulumi.Output.all
|
|
1849
|
-
|
|
1859
|
+
// Presign endpoints are no longer written to config.json: under route B the
|
|
1860
|
+
// client calls the platform API's `Upload_Presign` mutation (reachable from
|
|
1861
|
+
// `platformApiEndpoint`, already present) with the store it declares, so there
|
|
1862
|
+
// is no per-store URL to publish. The store's *serving* base URL still travels
|
|
1863
|
+
// in the `objectStores` stack output above.
|
|
1850
1864
|
let configJsonContent =
|
|
1851
1865
|
(
|
|
1852
1866
|
(
|
|
@@ -1857,14 +1871,12 @@ module MakeWithConfig = (
|
|
|
1857
1871
|
)->Pulumi.Output.all4,
|
|
1858
1872
|
domainEventsEndpointOutput,
|
|
1859
1873
|
geocoderEndpointOutput,
|
|
1860
|
-
(uploadEndpointOutput, storeUploadEndpointsOutput)->Pulumi.Output.all2,
|
|
1861
1874
|
)
|
|
1862
|
-
->Pulumi.Output.
|
|
1875
|
+
->Pulumi.Output.all3
|
|
1863
1876
|
->Pulumi.Output.apply(((
|
|
1864
1877
|
(domainEp, platformEp, poolId, clientId),
|
|
1865
1878
|
eventsEpOpt,
|
|
1866
1879
|
geocoderEpOpt,
|
|
1867
|
-
(uploadEpOpt, storeUploadEps),
|
|
1868
1880
|
)) => {
|
|
1869
1881
|
let fields = [
|
|
1870
1882
|
("apiEndpoint", JSON.Encode.string(domainEp)),
|
|
@@ -1897,29 +1909,7 @@ module MakeWithConfig = (
|
|
|
1897
1909
|
| Some(ep) => Array.concat(withEvents, [("geocoderEndpoint", JSON.Encode.string(ep))])
|
|
1898
1910
|
| None => withEvents
|
|
1899
1911
|
}
|
|
1900
|
-
|
|
1901
|
-
| Some(ep) => Array.concat(withGeocoder, [("uploadEndpoint", JSON.Encode.string(ep))])
|
|
1902
|
-
| None => withGeocoder
|
|
1903
|
-
}
|
|
1904
|
-
// Omitted entirely when nothing is declared, so a deployment without
|
|
1905
|
-
// declared stores writes a byte-identical config.json.
|
|
1906
|
-
let withStoreUploads = switch storeUploadEps {
|
|
1907
|
-
| [] => withUpload
|
|
1908
|
-
| eps =>
|
|
1909
|
-
Array.concat(
|
|
1910
|
-
withUpload,
|
|
1911
|
-
[
|
|
1912
|
-
(
|
|
1913
|
-
"uploadEndpoints",
|
|
1914
|
-
eps
|
|
1915
|
-
->Array.map(((qualified, url)) => (qualified, JSON.Encode.string(url)))
|
|
1916
|
-
->Dict.fromArray
|
|
1917
|
-
->JSON.Encode.object,
|
|
1918
|
-
),
|
|
1919
|
-
],
|
|
1920
|
-
)
|
|
1921
|
-
}
|
|
1922
|
-
withStoreUploads->Dict.fromArray->JSON.Encode.object->JSON.stringify
|
|
1912
|
+
withGeocoder->Dict.fromArray->JSON.Encode.object->JSON.stringify
|
|
1923
1913
|
})
|
|
1924
1914
|
|
|
1925
1915
|
let _ = PulumiAws.S3.BucketObject.make(
|
package/src/Platform.res.mjs
CHANGED
|
@@ -156,8 +156,8 @@ function MakeWithConfig(Config) {
|
|
|
156
156
|
};
|
|
157
157
|
let platformStackRef = Stdlib_Option.map(new Pulumi.Config("platform").get("stack"), stack => new Pulumi.StackReference(stack));
|
|
158
158
|
let domainBaseFragment = GraphQL_Stitcher$ReventlessCore.encode({
|
|
159
|
-
types:
|
|
160
|
-
mutations:
|
|
159
|
+
types: Platform_AdminApi$ReventlessCore.uploadTypes,
|
|
160
|
+
mutations: Platform_AdminApi$ReventlessCore.uploadMutationFields,
|
|
161
161
|
queries: [" Platform_ping: String"],
|
|
162
162
|
subscriptions: [],
|
|
163
163
|
subscriptionSources: []
|
|
@@ -931,13 +931,11 @@ function MakeWithConfig(Config) {
|
|
|
931
931
|
bucket = b$1;
|
|
932
932
|
}
|
|
933
933
|
let storeHandle = Capability_ObjectStore_S3$ReventlessAws.underPrefix(bucket, keyPrefix);
|
|
934
|
-
let presign = Upload_Presign_S3$ReventlessAws.make(storeHandle.bucketName, undefined, storeHandle.keyPrefix, `UploadPresign-` + plugin + `-` + store, undefined);
|
|
935
934
|
return [
|
|
936
935
|
plugin + `.` + store,
|
|
937
936
|
keyPrefix,
|
|
938
937
|
bucketName,
|
|
939
|
-
storeHandle.bucketName
|
|
940
|
-
presign.url
|
|
938
|
+
storeHandle.bucketName
|
|
941
939
|
];
|
|
942
940
|
});
|
|
943
941
|
let declaredServedBuckets = Stdlib_Array.filterMap(storeBucketOrder, bucketName => Stdlib_Option.map(storeBuckets[bucketName], b => ({
|
|
@@ -966,15 +964,23 @@ function MakeWithConfig(Config) {
|
|
|
966
964
|
store: param[0],
|
|
967
965
|
keyPrefix: param[1],
|
|
968
966
|
bucketName: param[3],
|
|
969
|
-
uploadUrl: param[4],
|
|
970
967
|
baseUrl: storeServingBaseUrl
|
|
971
968
|
}));
|
|
972
969
|
objectStoreEndpointsRef.contents = declaredStoreEndpoints;
|
|
970
|
+
let store = Stdlib_Option.flatMap(hostUiBundle, c => c.uploadBucket);
|
|
971
|
+
let uploadServiceStores = declaredStoreServices.map(param => ({
|
|
972
|
+
qualified: param[0],
|
|
973
|
+
bucketName: param[3],
|
|
974
|
+
servedPrefix: param[1]
|
|
975
|
+
})).concat(store !== undefined ? [{
|
|
976
|
+
qualified: store.keyPrefix,
|
|
977
|
+
bucketName: store.bucketName,
|
|
978
|
+
servedPrefix: store.keyPrefix
|
|
979
|
+
}] : []);
|
|
980
|
+
if (uploadServiceStores.length !== 0) {
|
|
981
|
+
Upload_Presign_S3$ReventlessAws.make(domainApi, uploadServiceStores, undefined, undefined, {});
|
|
982
|
+
}
|
|
973
983
|
if (declaredStoreEndpoints.length !== 0) {
|
|
974
|
-
Pulumi$Pulumi.$$export("uploadEndpoints", Pulumi.all(declaredStoreEndpoints.map(e => e.uploadUrl.apply(u => [
|
|
975
|
-
e.store,
|
|
976
|
-
u
|
|
977
|
-
]))).apply(pairs => Object.fromEntries(pairs)));
|
|
978
984
|
Pulumi$Pulumi.$$export("objectStores", Pulumi.all(declaredStoreEndpoints.map(e => Pulumi.all([
|
|
979
985
|
e.bucketName,
|
|
980
986
|
Output$Pulumi.allOpt(e.baseUrl)
|
|
@@ -1019,14 +1025,14 @@ function MakeWithConfig(Config) {
|
|
|
1019
1025
|
} else {
|
|
1020
1026
|
customDomain = undefined;
|
|
1021
1027
|
}
|
|
1022
|
-
let store = hostUiBundle.uploadBucket;
|
|
1028
|
+
let store$1 = hostUiBundle.uploadBucket;
|
|
1023
1029
|
let servedBuckets = (
|
|
1024
|
-
store !== undefined ? [{
|
|
1025
|
-
id: store.keyPrefix,
|
|
1026
|
-
prefixes: [store.keyPrefix],
|
|
1027
|
-
bucketId: store.bucketId,
|
|
1028
|
-
bucketArn: store.bucketArn,
|
|
1029
|
-
bucketRegionalDomainName: store.bucketRegionalDomainName
|
|
1030
|
+
store$1 !== undefined ? [{
|
|
1031
|
+
id: store$1.keyPrefix,
|
|
1032
|
+
prefixes: [store$1.keyPrefix],
|
|
1033
|
+
bucketId: store$1.bucketId,
|
|
1034
|
+
bucketArn: store$1.bucketArn,
|
|
1035
|
+
bucketRegionalDomainName: store$1.bucketRegionalDomainName
|
|
1030
1036
|
}] : []
|
|
1031
1037
|
).concat(declaredServedBuckets);
|
|
1032
1038
|
let match$4 = Plugin_Stack$ReventlessAws.makeUiBundleDistribution("host-ui", Stdlib_Option.getOr(hostUiBundle.bundleVersion, version), Stdlib_Option.getOr(hostUiBundle.assetsDir, Util_Bundle$ReventlessAws.resolvePackageRoot(true, "@reventlessdev/reventless-host-shell") + "/dist"), true, undefined, true, [
|
|
@@ -1039,15 +1045,6 @@ function MakeWithConfig(Config) {
|
|
|
1039
1045
|
let domainEventsEndpointOutput = domainEventsApiOpt !== undefined ? AppSync_EventsApi$ReventlessAws.httpEndpoint(domainEventsApiOpt).apply(ep => ep + "/event") : Pulumi.output(undefined);
|
|
1040
1046
|
let index = hostUiBundle.geocoderPlaceIndex;
|
|
1041
1047
|
let geocoderEndpointOutput = index !== undefined ? Geocoder_AwsLocation$ReventlessAws.make(index.indexName, undefined, undefined).url.apply(u => u) : Pulumi.output(undefined);
|
|
1042
|
-
let store$1 = hostUiBundle.uploadBucket;
|
|
1043
|
-
let uploadEndpointOutput = store$1 !== undefined ? Upload_Presign_S3$ReventlessAws.make(store$1.bucketName, undefined, undefined, undefined, undefined).url.apply(u => u) : Pulumi.output(undefined);
|
|
1044
|
-
let storeUploadEndpointsOutput = Pulumi.all(declaredStoreServices.map(param => {
|
|
1045
|
-
let qualified = param[0];
|
|
1046
|
-
return param[4].apply(u => [
|
|
1047
|
-
qualified,
|
|
1048
|
-
u
|
|
1049
|
-
]);
|
|
1050
|
-
}));
|
|
1051
1048
|
let configJsonContent = Pulumi.all([
|
|
1052
1049
|
Pulumi.all([
|
|
1053
1050
|
resolvedDomainApiEndpoint,
|
|
@@ -1056,26 +1053,19 @@ function MakeWithConfig(Config) {
|
|
|
1056
1053
|
cognitoPool.clientId
|
|
1057
1054
|
]),
|
|
1058
1055
|
domainEventsEndpointOutput,
|
|
1059
|
-
geocoderEndpointOutput
|
|
1060
|
-
Pulumi.all([
|
|
1061
|
-
uploadEndpointOutput,
|
|
1062
|
-
storeUploadEndpointsOutput
|
|
1063
|
-
])
|
|
1056
|
+
geocoderEndpointOutput
|
|
1064
1057
|
]).apply(param => {
|
|
1065
|
-
let match = param[3];
|
|
1066
|
-
let storeUploadEps = match[1];
|
|
1067
|
-
let uploadEpOpt = match[0];
|
|
1068
1058
|
let geocoderEpOpt = param[2];
|
|
1069
1059
|
let eventsEpOpt = param[1];
|
|
1070
|
-
let match
|
|
1060
|
+
let match = param[0];
|
|
1071
1061
|
let fields = [
|
|
1072
1062
|
[
|
|
1073
1063
|
"apiEndpoint",
|
|
1074
|
-
match
|
|
1064
|
+
match[0]
|
|
1075
1065
|
],
|
|
1076
1066
|
[
|
|
1077
1067
|
"platformApiEndpoint",
|
|
1078
|
-
match
|
|
1068
|
+
match[1]
|
|
1079
1069
|
],
|
|
1080
1070
|
[
|
|
1081
1071
|
"region",
|
|
@@ -1087,11 +1077,11 @@ function MakeWithConfig(Config) {
|
|
|
1087
1077
|
],
|
|
1088
1078
|
[
|
|
1089
1079
|
"cognitoUserPoolId",
|
|
1090
|
-
match
|
|
1080
|
+
match[2]
|
|
1091
1081
|
],
|
|
1092
1082
|
[
|
|
1093
1083
|
"cognitoClientId",
|
|
1094
|
-
match
|
|
1084
|
+
match[3]
|
|
1095
1085
|
],
|
|
1096
1086
|
[
|
|
1097
1087
|
"liveUpdates",
|
|
@@ -1116,18 +1106,7 @@ function MakeWithConfig(Config) {
|
|
|
1116
1106
|
"geocoderEndpoint",
|
|
1117
1107
|
geocoderEpOpt
|
|
1118
1108
|
]]) : withEvents;
|
|
1119
|
-
|
|
1120
|
-
"uploadEndpoint",
|
|
1121
|
-
uploadEpOpt
|
|
1122
|
-
]]) : withGeocoder;
|
|
1123
|
-
let withStoreUploads = storeUploadEps.length !== 0 ? withUpload.concat([[
|
|
1124
|
-
"uploadEndpoints",
|
|
1125
|
-
Object.fromEntries(storeUploadEps.map(param => [
|
|
1126
|
-
param[0],
|
|
1127
|
-
param[1]
|
|
1128
|
-
]))
|
|
1129
|
-
]]) : withUpload;
|
|
1130
|
-
return JSON.stringify(Object.fromEntries(withStoreUploads));
|
|
1109
|
+
return JSON.stringify(Object.fromEntries(withGeocoder));
|
|
1131
1110
|
});
|
|
1132
1111
|
new (Aws.s3.BucketObject)("host-ui-config-json", {
|
|
1133
1112
|
bucket: bucketName,
|
|
@@ -1334,8 +1313,8 @@ function Make($star) {
|
|
|
1334
1313
|
};
|
|
1335
1314
|
let platformStackRef = Stdlib_Option.map(new Pulumi.Config("platform").get("stack"), stack => new Pulumi.StackReference(stack));
|
|
1336
1315
|
let domainBaseFragment = GraphQL_Stitcher$ReventlessCore.encode({
|
|
1337
|
-
types:
|
|
1338
|
-
mutations:
|
|
1316
|
+
types: Platform_AdminApi$ReventlessCore.uploadTypes,
|
|
1317
|
+
mutations: Platform_AdminApi$ReventlessCore.uploadMutationFields,
|
|
1339
1318
|
queries: [" Platform_ping: String"],
|
|
1340
1319
|
subscriptions: [],
|
|
1341
1320
|
subscriptionSources: []
|
|
@@ -2086,13 +2065,11 @@ function Make($star) {
|
|
|
2086
2065
|
bucket = b$1;
|
|
2087
2066
|
}
|
|
2088
2067
|
let storeHandle = Capability_ObjectStore_S3$ReventlessAws.underPrefix(bucket, keyPrefix);
|
|
2089
|
-
let presign = Upload_Presign_S3$ReventlessAws.make(storeHandle.bucketName, undefined, storeHandle.keyPrefix, `UploadPresign-` + plugin + `-` + store, undefined);
|
|
2090
2068
|
return [
|
|
2091
2069
|
plugin + `.` + store,
|
|
2092
2070
|
keyPrefix,
|
|
2093
2071
|
bucketName,
|
|
2094
|
-
storeHandle.bucketName
|
|
2095
|
-
presign.url
|
|
2072
|
+
storeHandle.bucketName
|
|
2096
2073
|
];
|
|
2097
2074
|
});
|
|
2098
2075
|
let declaredServedBuckets = Stdlib_Array.filterMap(storeBucketOrder, bucketName => Stdlib_Option.map(storeBuckets[bucketName], b => ({
|
|
@@ -2121,15 +2098,23 @@ function Make($star) {
|
|
|
2121
2098
|
store: param[0],
|
|
2122
2099
|
keyPrefix: param[1],
|
|
2123
2100
|
bucketName: param[3],
|
|
2124
|
-
uploadUrl: param[4],
|
|
2125
2101
|
baseUrl: storeServingBaseUrl
|
|
2126
2102
|
}));
|
|
2127
2103
|
objectStoreEndpointsRef.contents = declaredStoreEndpoints;
|
|
2104
|
+
let store = Stdlib_Option.flatMap(hostUiBundle, c => c.uploadBucket);
|
|
2105
|
+
let uploadServiceStores = declaredStoreServices.map(param => ({
|
|
2106
|
+
qualified: param[0],
|
|
2107
|
+
bucketName: param[3],
|
|
2108
|
+
servedPrefix: param[1]
|
|
2109
|
+
})).concat(store !== undefined ? [{
|
|
2110
|
+
qualified: store.keyPrefix,
|
|
2111
|
+
bucketName: store.bucketName,
|
|
2112
|
+
servedPrefix: store.keyPrefix
|
|
2113
|
+
}] : []);
|
|
2114
|
+
if (uploadServiceStores.length !== 0) {
|
|
2115
|
+
Upload_Presign_S3$ReventlessAws.make(domainApi, uploadServiceStores, undefined, undefined, {});
|
|
2116
|
+
}
|
|
2128
2117
|
if (declaredStoreEndpoints.length !== 0) {
|
|
2129
|
-
Pulumi$Pulumi.$$export("uploadEndpoints", Pulumi.all(declaredStoreEndpoints.map(e => e.uploadUrl.apply(u => [
|
|
2130
|
-
e.store,
|
|
2131
|
-
u
|
|
2132
|
-
]))).apply(pairs => Object.fromEntries(pairs)));
|
|
2133
2118
|
Pulumi$Pulumi.$$export("objectStores", Pulumi.all(declaredStoreEndpoints.map(e => Pulumi.all([
|
|
2134
2119
|
e.bucketName,
|
|
2135
2120
|
Output$Pulumi.allOpt(e.baseUrl)
|
|
@@ -2174,14 +2159,14 @@ function Make($star) {
|
|
|
2174
2159
|
} else {
|
|
2175
2160
|
customDomain = undefined;
|
|
2176
2161
|
}
|
|
2177
|
-
let store = hostUiBundle.uploadBucket;
|
|
2162
|
+
let store$1 = hostUiBundle.uploadBucket;
|
|
2178
2163
|
let servedBuckets = (
|
|
2179
|
-
store !== undefined ? [{
|
|
2180
|
-
id: store.keyPrefix,
|
|
2181
|
-
prefixes: [store.keyPrefix],
|
|
2182
|
-
bucketId: store.bucketId,
|
|
2183
|
-
bucketArn: store.bucketArn,
|
|
2184
|
-
bucketRegionalDomainName: store.bucketRegionalDomainName
|
|
2164
|
+
store$1 !== undefined ? [{
|
|
2165
|
+
id: store$1.keyPrefix,
|
|
2166
|
+
prefixes: [store$1.keyPrefix],
|
|
2167
|
+
bucketId: store$1.bucketId,
|
|
2168
|
+
bucketArn: store$1.bucketArn,
|
|
2169
|
+
bucketRegionalDomainName: store$1.bucketRegionalDomainName
|
|
2185
2170
|
}] : []
|
|
2186
2171
|
).concat(declaredServedBuckets);
|
|
2187
2172
|
let match$4 = Plugin_Stack$ReventlessAws.makeUiBundleDistribution("host-ui", Stdlib_Option.getOr(hostUiBundle.bundleVersion, version), Stdlib_Option.getOr(hostUiBundle.assetsDir, Util_Bundle$ReventlessAws.resolvePackageRoot(true, "@reventlessdev/reventless-host-shell") + "/dist"), true, undefined, true, [
|
|
@@ -2194,15 +2179,6 @@ function Make($star) {
|
|
|
2194
2179
|
let domainEventsEndpointOutput = domainEventsApiOpt !== undefined ? AppSync_EventsApi$ReventlessAws.httpEndpoint(domainEventsApiOpt).apply(ep => ep + "/event") : Pulumi.output(undefined);
|
|
2195
2180
|
let index = hostUiBundle.geocoderPlaceIndex;
|
|
2196
2181
|
let geocoderEndpointOutput = index !== undefined ? Geocoder_AwsLocation$ReventlessAws.make(index.indexName, undefined, undefined).url.apply(u => u) : Pulumi.output(undefined);
|
|
2197
|
-
let store$1 = hostUiBundle.uploadBucket;
|
|
2198
|
-
let uploadEndpointOutput = store$1 !== undefined ? Upload_Presign_S3$ReventlessAws.make(store$1.bucketName, undefined, undefined, undefined, undefined).url.apply(u => u) : Pulumi.output(undefined);
|
|
2199
|
-
let storeUploadEndpointsOutput = Pulumi.all(declaredStoreServices.map(param => {
|
|
2200
|
-
let qualified = param[0];
|
|
2201
|
-
return param[4].apply(u => [
|
|
2202
|
-
qualified,
|
|
2203
|
-
u
|
|
2204
|
-
]);
|
|
2205
|
-
}));
|
|
2206
2182
|
let configJsonContent = Pulumi.all([
|
|
2207
2183
|
Pulumi.all([
|
|
2208
2184
|
resolvedDomainApiEndpoint,
|
|
@@ -2211,26 +2187,19 @@ function Make($star) {
|
|
|
2211
2187
|
cognitoPool.clientId
|
|
2212
2188
|
]),
|
|
2213
2189
|
domainEventsEndpointOutput,
|
|
2214
|
-
geocoderEndpointOutput
|
|
2215
|
-
Pulumi.all([
|
|
2216
|
-
uploadEndpointOutput,
|
|
2217
|
-
storeUploadEndpointsOutput
|
|
2218
|
-
])
|
|
2190
|
+
geocoderEndpointOutput
|
|
2219
2191
|
]).apply(param => {
|
|
2220
|
-
let match = param[3];
|
|
2221
|
-
let storeUploadEps = match[1];
|
|
2222
|
-
let uploadEpOpt = match[0];
|
|
2223
2192
|
let geocoderEpOpt = param[2];
|
|
2224
2193
|
let eventsEpOpt = param[1];
|
|
2225
|
-
let match
|
|
2194
|
+
let match = param[0];
|
|
2226
2195
|
let fields = [
|
|
2227
2196
|
[
|
|
2228
2197
|
"apiEndpoint",
|
|
2229
|
-
match
|
|
2198
|
+
match[0]
|
|
2230
2199
|
],
|
|
2231
2200
|
[
|
|
2232
2201
|
"platformApiEndpoint",
|
|
2233
|
-
match
|
|
2202
|
+
match[1]
|
|
2234
2203
|
],
|
|
2235
2204
|
[
|
|
2236
2205
|
"region",
|
|
@@ -2242,11 +2211,11 @@ function Make($star) {
|
|
|
2242
2211
|
],
|
|
2243
2212
|
[
|
|
2244
2213
|
"cognitoUserPoolId",
|
|
2245
|
-
match
|
|
2214
|
+
match[2]
|
|
2246
2215
|
],
|
|
2247
2216
|
[
|
|
2248
2217
|
"cognitoClientId",
|
|
2249
|
-
match
|
|
2218
|
+
match[3]
|
|
2250
2219
|
],
|
|
2251
2220
|
[
|
|
2252
2221
|
"liveUpdates",
|
|
@@ -2271,18 +2240,7 @@ function Make($star) {
|
|
|
2271
2240
|
"geocoderEndpoint",
|
|
2272
2241
|
geocoderEpOpt
|
|
2273
2242
|
]]) : withEvents;
|
|
2274
|
-
|
|
2275
|
-
"uploadEndpoint",
|
|
2276
|
-
uploadEpOpt
|
|
2277
|
-
]]) : withGeocoder;
|
|
2278
|
-
let withStoreUploads = storeUploadEps.length !== 0 ? withUpload.concat([[
|
|
2279
|
-
"uploadEndpoints",
|
|
2280
|
-
Object.fromEntries(storeUploadEps.map(param => [
|
|
2281
|
-
param[0],
|
|
2282
|
-
param[1]
|
|
2283
|
-
]))
|
|
2284
|
-
]]) : withUpload;
|
|
2285
|
-
return JSON.stringify(Object.fromEntries(withStoreUploads));
|
|
2243
|
+
return JSON.stringify(Object.fromEntries(withGeocoder));
|
|
2286
2244
|
});
|
|
2287
2245
|
new (Aws.s3.BucketObject)("host-ui-config-json", {
|
|
2288
2246
|
bucket: bucketName,
|
|
@@ -60,14 +60,16 @@ type response = {
|
|
|
60
60
|
body: string,
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
//
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
63
|
+
// CORS belongs to the Function URL's own `cors` configuration and to nothing
|
|
64
|
+
// else. AWS injects the allow-origin header itself whenever the request carries
|
|
65
|
+
// an `Origin`, so a handler that also sets one sends the header *twice* — and a
|
|
66
|
+
// browser rejects `Access-Control-Allow-Origin: *, *` outright, failing every
|
|
67
|
+
// cross-origin call while leaving `curl` (which sends no `Origin`, so AWS adds
|
|
68
|
+
// nothing) working perfectly.
|
|
69
|
+
//
|
|
70
|
+
// It is also the only way `~corsOrigins` can mean anything: a hardcoded `*`
|
|
71
|
+
// here would keep answering `*` for a deployment that narrowed the allow-list.
|
|
72
|
+
let jsonHeaders = () => Dict.fromArray([("content-type", "application/json")])
|
|
71
73
|
|
|
72
74
|
// Pull `q` from the parsed query-string params, falling back to the raw string.
|
|
73
75
|
let readQueryParam = (event: functionUrlEvent): option<string> =>
|
|
@@ -93,7 +95,7 @@ let handler = async (event: functionUrlEvent): response => {
|
|
|
93
95
|
let indexName = getEnv("PLACE_INDEX_NAME")->Option.getOr("")
|
|
94
96
|
let q = readQueryParam(event)->Option.getOr("")
|
|
95
97
|
if indexName == "" || q == "" {
|
|
96
|
-
{statusCode: 200, headers:
|
|
98
|
+
{statusCode: 200, headers: jsonHeaders(), body: "[]"}
|
|
97
99
|
} else {
|
|
98
100
|
let client = makeLocationClient()
|
|
99
101
|
let resp = await client->send(
|
|
@@ -124,13 +126,13 @@ let handler = async (event: functionUrlEvent): response => {
|
|
|
124
126
|
)
|
|
125
127
|
{
|
|
126
128
|
statusCode: 200,
|
|
127
|
-
headers:
|
|
129
|
+
headers: jsonHeaders(),
|
|
128
130
|
body: results->JSON.Encode.array->JSON.stringify,
|
|
129
131
|
}
|
|
130
132
|
}
|
|
131
133
|
} catch {
|
|
132
134
|
| exn =>
|
|
133
135
|
Console.error2("Geocoder: search failed", exn)
|
|
134
|
-
{statusCode: 200, headers:
|
|
136
|
+
{statusCode: 200, headers: jsonHeaders(), body: "[]"}
|
|
135
137
|
}
|
|
136
138
|
}
|