@reventlessdev/reventless-aws 3.0.0-alpha.265 → 3.0.0-alpha.266
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 +6 -6
- package/src/Platform.res +48 -53
- package/src/Platform.res.mjs +15 -34
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver.res +227 -0
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver.res.mjs +127 -0
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver_Ops.res +55 -0
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver_Ops.res.mjs +48 -0
- package/tests/Geocoder_AwsLocation_Resolver_OpsTest.res +53 -0
- package/tests/Geocoder_AwsLocation_Resolver_OpsTest.res.mjs +55 -0
- package/src/adapter/Geocoder/Geocoder_AwsLocation.res +0 -166
- package/src/adapter/Geocoder/Geocoder_AwsLocation.res.mjs +0 -105
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Ops.res +0 -144
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Ops.res.mjs +0 -137
- package/tests/Geocoder_AwsLocation_OpsTest.res +0 -78
- package/tests/Geocoder_AwsLocation_OpsTest.res.mjs +0 -71
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.266 (2026-08-04)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **geocoding:** serve geocoding through the platform GraphQL API (D9 half 2) ([914d3c0](https://github.com/ReventlessDev/reventless-core/commit/914d3c0a99a1b67ffb89e2b8259dd30f67ff9bae))
|
|
11
|
+
|
|
12
|
+
|
|
6
13
|
# 3.0.0-alpha.265 (2026-08-04)
|
|
7
14
|
|
|
8
15
|
### Bug Fixes
|
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.266",
|
|
4
4
|
"description": "AWS adapters for Reventless",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"dependencies": {
|
|
@@ -13,16 +13,16 @@
|
|
|
13
13
|
"uuid": "^13.0.0",
|
|
14
14
|
"@reventlessdev/rescript-aws-sdk": "3.0.0-alpha.3",
|
|
15
15
|
"@reventlessdev/rescript-effect": "0.1.0-alpha.32",
|
|
16
|
+
"@reventlessdev/rescript-node": "2.0.0-alpha.1",
|
|
16
17
|
"@reventlessdev/rescript-jest": "1.0.0-alpha.10",
|
|
17
18
|
"@reventlessdev/rescript-pulumi-aws": "2.4.0-alpha.65",
|
|
18
|
-
"@reventlessdev/rescript-node": "2.0.0-alpha.1",
|
|
19
19
|
"@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.18",
|
|
20
20
|
"@reventlessdev/rescript-uuid": "2.0.0-alpha.0",
|
|
21
|
-
"@reventlessdev/reventless-core": "3.0.0-alpha.
|
|
22
|
-
"@reventlessdev/reventless-infra": "3.0.0-alpha.
|
|
23
|
-
"@reventlessdev/reventless-postgres": "3.0.0-alpha.74",
|
|
21
|
+
"@reventlessdev/reventless-core": "3.0.0-alpha.211",
|
|
22
|
+
"@reventlessdev/reventless-infra": "3.0.0-alpha.126",
|
|
24
23
|
"@reventlessdev/reventless-spec": "3.0.0-alpha.100",
|
|
25
|
-
"@reventlessdev/reventless-interop": "3.0.0-alpha.30"
|
|
24
|
+
"@reventlessdev/reventless-interop": "3.0.0-alpha.30",
|
|
25
|
+
"@reventlessdev/reventless-postgres": "3.0.0-alpha.75"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"rescript": "12.3.0",
|
package/src/Platform.res
CHANGED
|
@@ -82,24 +82,21 @@ let objectStoreEndpointsRef: ref<array<objectStoreEndpoint>> = ref([])
|
|
|
82
82
|
`getApiConfig` does. */
|
|
83
83
|
let getObjectStoreEndpoints = () => objectStoreEndpointsRef.contents
|
|
84
84
|
|
|
85
|
-
/** The
|
|
85
|
+
/** The geocoding place index this platform provisioned, for the monolithic case.
|
|
86
86
|
|
|
87
|
-
In plugin mode the value crosses to the plugin stack as the `
|
|
87
|
+
In plugin mode the value crosses to the plugin stack as the `geocoderPlaceIndex`
|
|
88
88
|
export; when platform and plugin are one program there is no stack to read, so
|
|
89
89
|
`deployPlatform` records it here and `deployPlugin` picks it up — the same two
|
|
90
|
-
halves `objectStoreEndpointsRef` exists for.
|
|
90
|
+
halves `objectStoreEndpointsRef` exists for. Slice Lambdas call Amazon Location
|
|
91
|
+
directly with this index name; the browser reaches the same capability through
|
|
92
|
+
the platform API's `Query.geocode` resolver (D9 half 2), so there is no endpoint
|
|
93
|
+
to carry beside it.
|
|
91
94
|
|
|
92
95
|
A plain Output with `""` as the "no geocoder" sentinel, never
|
|
93
96
|
`option<Pulumi.Output.t<_>>`: any generic `Option.*` over an Output runs
|
|
94
97
|
`valFromOption`, whose nested-option probe hits the Output proxy — where every
|
|
95
98
|
property access returns a truthy Output — and corrupts it. Same reasoning, and
|
|
96
99
|
the same sentinel, as `PluginRuntime_Builder.inboundSliceReg.auditTableName`. */
|
|
97
|
-
let geocoderEndpointRef: ref<Pulumi.Output.t<string>> = ref(Pulumi.Output.make(""))
|
|
98
|
-
|
|
99
|
-
/** The geocoding place index, for the monolithic case — the SDK-side half of the
|
|
100
|
-
same capability, carried for exactly the reasons above and with the same `""`
|
|
101
|
-
sentinel. Slice Lambdas call Amazon Location directly with this; only the
|
|
102
|
-
browser needs the Function URL. */
|
|
103
100
|
let geocoderPlaceIndexRef: ref<Pulumi.Output.t<string>> = ref(Pulumi.Output.make(""))
|
|
104
101
|
|
|
105
102
|
module MakeWithConfig = (
|
|
@@ -248,9 +245,15 @@ module MakeWithConfig = (
|
|
|
248
245
|
// unified mode carries the admin base here instead; it declares no stores in practice,
|
|
249
246
|
// so the upload resolvers below are never created there.)
|
|
250
247
|
let domainBaseFragment = ReventlessCore.GraphQL_Stitcher.encode({
|
|
251
|
-
types:
|
|
248
|
+
types: Array.concat(
|
|
249
|
+
ReventlessCore.Platform_AdminApi.uploadTypes,
|
|
250
|
+
ReventlessCore.Platform_AdminApi.geocodeTypes,
|
|
251
|
+
),
|
|
252
252
|
mutations: ReventlessCore.Platform_AdminApi.uploadMutationFields,
|
|
253
|
-
queries:
|
|
253
|
+
queries: Array.concat(
|
|
254
|
+
[" Platform_ping: String"],
|
|
255
|
+
ReventlessCore.Platform_AdminApi.geocodeQueryFields,
|
|
256
|
+
),
|
|
254
257
|
subscriptions: [],
|
|
255
258
|
subscriptionSources: [],
|
|
256
259
|
})
|
|
@@ -1152,10 +1155,10 @@ module MakeWithConfig = (
|
|
|
1152
1155
|
// unchanged. Single-mode shape: one origin-relative file per deployment.
|
|
1153
1156
|
uiHintsFile?: string,
|
|
1154
1157
|
// Optional geocoding place index, as returned by
|
|
1155
|
-
// `Capability_Geocoding_AwsLocation.make`. When set, the deploy provisions
|
|
1156
|
-
//
|
|
1157
|
-
//
|
|
1158
|
-
//
|
|
1158
|
+
// `Capability_Geocoding_AwsLocation.make`. When set, the deploy provisions the
|
|
1159
|
+
// capability's client door — a Cognito-authenticated `Query.geocode` resolver
|
|
1160
|
+
// on the domain API (`Geocoder_AwsLocation_Resolver`, split mode) — and exports
|
|
1161
|
+
// the index name for the unattended slice path. Unset ⇒ no resolver, no export.
|
|
1159
1162
|
geocoderPlaceIndex?: ReventlessInfra.Platform.geocoderIndex,
|
|
1160
1163
|
// Optional object store for direct-to-S3 uploads, as returned by
|
|
1161
1164
|
// `Capability_ObjectStore_S3.make`. When set, the deploy registers it with
|
|
@@ -2066,35 +2069,32 @@ module MakeWithConfig = (
|
|
|
2066
2069
|
| None => Pulumi.Output.make(None)
|
|
2067
2070
|
}
|
|
2068
2071
|
|
|
2069
|
-
//
|
|
2070
|
-
//
|
|
2071
|
-
//
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2072
|
+
// The geocoding capability's client door (D9 half 2): a `Query.geocode`
|
|
2073
|
+
// resolver on the domain API, provisioned only when a place index is
|
|
2074
|
+
// configured. Authenticated by the API's Cognito authorizer, so it replaces
|
|
2075
|
+
// the public unauthenticated Function URL the browser used to call — after
|
|
2076
|
+
// which that endpoint has no callers at all (the unattended slice path reaches
|
|
2077
|
+
// the same index through the SDK, via `geocoderPlaceIndex` below).
|
|
2078
|
+
//
|
|
2079
|
+
// Split-API only, for the same reason the upload resolvers are: `geocode`
|
|
2080
|
+
// lives on the domain base document (`domainBaseFragment`), which a
|
|
2081
|
+
// unified-mode deployment's single API does not carry.
|
|
2082
|
+
switch cfg.geocoderPlaceIndex {
|
|
2083
|
+
| Some(index) if Config.splitApi =>
|
|
2084
|
+
let _geocodeService = Geocoder_AwsLocation_Resolver.make(
|
|
2085
|
+
~api=domainApi,
|
|
2075
2086
|
~placeIndexName=index.indexName,
|
|
2076
|
-
|
|
2077
|
-
|
|
2087
|
+
~opts={},
|
|
2088
|
+
)
|
|
2089
|
+
| _ => ()
|
|
2078
2090
|
}
|
|
2079
2091
|
|
|
2080
|
-
//
|
|
2081
|
-
//
|
|
2082
|
-
//
|
|
2083
|
-
//
|
|
2084
|
-
// `""` when unset
|
|
2085
|
-
//
|
|
2086
|
-
// "no geocoder configured".
|
|
2087
|
-
let geocoderEndpointFlat =
|
|
2088
|
-
geocoderEndpointOutput->Pulumi.Output.apply(o => o->Option.getOr(""))
|
|
2089
|
-
Pulumi.Pulumi.export("geocoderEndpoint", geocoderEndpointFlat)
|
|
2090
|
-
geocoderEndpointRef := geocoderEndpointFlat
|
|
2091
|
-
|
|
2092
|
-
// The place index itself, exported beside the Function URL because the two
|
|
2093
|
-
// callers need different things from the same capability. A browser cannot
|
|
2094
|
-
// sign an SDK call and gets the URL; a slice's Lambda can, and gets the
|
|
2095
|
-
// index name — no proxy hop, and no dependence on a public unauthenticated
|
|
2096
|
-
// endpoint for an unattended path. `""` when unset, for the same
|
|
2097
|
-
// one-shape-to-handle reason as the endpoint above.
|
|
2092
|
+
// The place index itself, exported so the unattended slice path can reach the
|
|
2093
|
+
// capability: a slice's Lambda signs an SDK call directly and needs the index
|
|
2094
|
+
// name, not an endpoint (no proxy hop, no dependence on a public URL). The
|
|
2095
|
+
// browser reaches the same capability through the `Query.geocode` resolver
|
|
2096
|
+
// above. `""` when unset, so a plugin stack reading this output has one shape
|
|
2097
|
+
// to handle rather than two.
|
|
2098
2098
|
let geocoderPlaceIndexFlat = switch cfg.geocoderPlaceIndex {
|
|
2099
2099
|
| Some(index) => index.indexName->Pulumi.Output.fromInput
|
|
2100
2100
|
| None => Pulumi.Output.make("")
|
|
@@ -2116,14 +2116,9 @@ module MakeWithConfig = (
|
|
|
2116
2116
|
cognitoPool.clientId,
|
|
2117
2117
|
)->Pulumi.Output.all4,
|
|
2118
2118
|
domainEventsEndpointOutput,
|
|
2119
|
-
geocoderEndpointOutput,
|
|
2120
2119
|
)
|
|
2121
|
-
->Pulumi.Output.
|
|
2122
|
-
->Pulumi.Output.apply(((
|
|
2123
|
-
(domainEp, platformEp, poolId, clientId),
|
|
2124
|
-
eventsEpOpt,
|
|
2125
|
-
geocoderEpOpt,
|
|
2126
|
-
)) => {
|
|
2120
|
+
->Pulumi.Output.all2
|
|
2121
|
+
->Pulumi.Output.apply((((domainEp, platformEp, poolId, clientId), eventsEpOpt)) => {
|
|
2127
2122
|
let computed = [
|
|
2128
2123
|
("apiEndpoint", JSON.Encode.string(domainEp)),
|
|
2129
2124
|
("platformApiEndpoint", JSON.Encode.string(platformEp)),
|
|
@@ -2151,12 +2146,12 @@ module MakeWithConfig = (
|
|
|
2151
2146
|
)
|
|
2152
2147
|
| None => computed
|
|
2153
2148
|
}
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2149
|
+
// `geocoderEndpoint` is no longer written: the browser reaches geocoding
|
|
2150
|
+
// through the platform API's `Query.geocode` resolver (D9 half 2), the
|
|
2151
|
+
// same way uploads moved off a per-store URL onto `Upload_Presign`. The
|
|
2152
|
+
// public Function URL and its config key are both gone.
|
|
2158
2153
|
Util_ShellConfig.fields(
|
|
2159
|
-
~computed=
|
|
2154
|
+
~computed=withEvents,
|
|
2160
2155
|
~viewModes=?cfg.viewModes,
|
|
2161
2156
|
~shellConfig=?cfg.shellConfig,
|
|
2162
2157
|
)
|
package/src/Platform.res.mjs
CHANGED
|
@@ -59,7 +59,6 @@ import * as AppSync_SdlDecorate$ReventlessAws from "./components/Api/AppSync_Sdl
|
|
|
59
59
|
import * as UiFragmentRegistry$ReventlessCore from "@reventlessdev/reventless-core/src/admin/UiFragmentRegistry/StateChangeSlice/UiFragmentRegistry.res.mjs";
|
|
60
60
|
import * as Util_ResourceNaming$ReventlessAws from "./util/Util_ResourceNaming.res.mjs";
|
|
61
61
|
import * as ClonerRunner_Fargate$ReventlessAws from "./plugin/cloner/ClonerRunner_Fargate.res.mjs";
|
|
62
|
-
import * as Geocoder_AwsLocation$ReventlessAws from "./adapter/Geocoder/Geocoder_AwsLocation.res.mjs";
|
|
63
62
|
import * as QueryEngine_DynamoDb$ReventlessAws from "./adapter/QueryEngine/QueryEngine_DynamoDb.res.mjs";
|
|
64
63
|
import * as PluginRuntime_Builder$ReventlessAws from "./plugin/runtime/PluginRuntime_Builder.res.mjs";
|
|
65
64
|
import * as PluginsReadModelSpec$ReventlessCore from "@reventlessdev/reventless-core/src/plugin/lifecycle/PluginsReadModelSpec.res.mjs";
|
|
@@ -85,6 +84,7 @@ import * as CommandTopicChannel_SQS_Sync$ReventlessAws from "./adapter/CommandTo
|
|
|
85
84
|
import * as EventLogSubscription_AppSync$ReventlessAws from "./adapter/EventLogSubscription/EventLogSubscription_AppSync.res.mjs";
|
|
86
85
|
import * as UiFragmentRegistry_Behavior$ReventlessCore from "@reventlessdev/reventless-core/src/admin/UiFragmentRegistry/StateChangeSlice/UiFragmentRegistry_Behavior.res.mjs";
|
|
87
86
|
import * as CommandTopicChannel_SQS_Async$ReventlessAws from "./adapter/CommandTopic/CommandTopicChannel_SQS_Async.res.mjs";
|
|
87
|
+
import * as Geocoder_AwsLocation_Resolver$ReventlessAws from "./adapter/Geocoder/Geocoder_AwsLocation_Resolver.res.mjs";
|
|
88
88
|
import * as Plugin_ExtensionPoint_Builder$ReventlessAws from "./plugin/stack/Plugin_ExtensionPoint_Builder.res.mjs";
|
|
89
89
|
import * as QueryDbStorage_DynamoDbStream$ReventlessAws from "./adapter/QueryDb/QueryDbStorage_DynamoDbStream.res.mjs";
|
|
90
90
|
import * as StateViewSlice_Builder_Stream$ReventlessAws from "./components/StateViewSlice_Builder_Stream.res.mjs";
|
|
@@ -130,10 +130,6 @@ function getObjectStoreEndpoints() {
|
|
|
130
130
|
return objectStoreEndpointsRef.contents;
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
let geocoderEndpointRef = {
|
|
134
|
-
contents: Pulumi.output("")
|
|
135
|
-
};
|
|
136
|
-
|
|
137
133
|
let geocoderPlaceIndexRef = {
|
|
138
134
|
contents: Pulumi.output("")
|
|
139
135
|
};
|
|
@@ -193,9 +189,9 @@ function MakeWithConfig(Config) {
|
|
|
193
189
|
}
|
|
194
190
|
};
|
|
195
191
|
let domainBaseFragment = GraphQL_Stitcher$ReventlessCore.encode({
|
|
196
|
-
types: Platform_AdminApi$ReventlessCore.uploadTypes,
|
|
192
|
+
types: Platform_AdminApi$ReventlessCore.uploadTypes.concat(Platform_AdminApi$ReventlessCore.geocodeTypes),
|
|
197
193
|
mutations: Platform_AdminApi$ReventlessCore.uploadMutationFields,
|
|
198
|
-
queries: [" Platform_ping: String"],
|
|
194
|
+
queries: [" Platform_ping: String"].concat(Platform_AdminApi$ReventlessCore.geocodeQueryFields),
|
|
199
195
|
subscriptions: [],
|
|
200
196
|
subscriptionSources: []
|
|
201
197
|
});
|
|
@@ -1131,10 +1127,9 @@ function MakeWithConfig(Config) {
|
|
|
1131
1127
|
let cognitoPool = Platform_Stack$ReventlessAws.resolveCognitoUserPool();
|
|
1132
1128
|
let domainEventsEndpointOutput = domainEventsApiOpt !== undefined ? AppSync_EventsApi$ReventlessAws.httpEndpoint(domainEventsApiOpt).apply(ep => ep + "/event") : Pulumi.output(undefined);
|
|
1133
1129
|
let index = hostUiBundle.geocoderPlaceIndex;
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
geocoderEndpointRef.contents = geocoderEndpointFlat;
|
|
1130
|
+
if (index !== undefined && Config.splitApi) {
|
|
1131
|
+
Geocoder_AwsLocation_Resolver$ReventlessAws.make(domainApi, index.indexName, undefined, {});
|
|
1132
|
+
}
|
|
1138
1133
|
let index$1 = hostUiBundle.geocoderPlaceIndex;
|
|
1139
1134
|
let geocoderPlaceIndexFlat = index$1 !== undefined ? index$1.indexName : Pulumi.output("");
|
|
1140
1135
|
Pulumi$Pulumi.$$export("geocoderPlaceIndex", geocoderPlaceIndexFlat);
|
|
@@ -1146,10 +1141,8 @@ function MakeWithConfig(Config) {
|
|
|
1146
1141
|
cognitoPool.poolId,
|
|
1147
1142
|
cognitoPool.clientId
|
|
1148
1143
|
]),
|
|
1149
|
-
domainEventsEndpointOutput
|
|
1150
|
-
geocoderEndpointOutput
|
|
1144
|
+
domainEventsEndpointOutput
|
|
1151
1145
|
]).apply(param => {
|
|
1152
|
-
let geocoderEpOpt = param[2];
|
|
1153
1146
|
let eventsEpOpt = param[1];
|
|
1154
1147
|
let match = param[0];
|
|
1155
1148
|
let computed = [
|
|
@@ -1196,11 +1189,7 @@ function MakeWithConfig(Config) {
|
|
|
1196
1189
|
AppSync_EventsApi$ReventlessAws.clientNamespaceName
|
|
1197
1190
|
]
|
|
1198
1191
|
]) : computed;
|
|
1199
|
-
|
|
1200
|
-
"geocoderEndpoint",
|
|
1201
|
-
geocoderEpOpt
|
|
1202
|
-
]]) : withEvents;
|
|
1203
|
-
return JSON.stringify(Util_ShellConfig$ReventlessAws.fields(withGeocoder, hostUiBundle.viewModes, hostUiBundle.shellConfig));
|
|
1192
|
+
return JSON.stringify(Util_ShellConfig$ReventlessAws.fields(withEvents, hostUiBundle.viewModes, hostUiBundle.shellConfig));
|
|
1204
1193
|
});
|
|
1205
1194
|
new (Aws.s3.BucketObject)("host-ui-config-json", {
|
|
1206
1195
|
bucket: bucketName,
|
|
@@ -1452,9 +1441,9 @@ function Make($star) {
|
|
|
1452
1441
|
}
|
|
1453
1442
|
};
|
|
1454
1443
|
let domainBaseFragment = GraphQL_Stitcher$ReventlessCore.encode({
|
|
1455
|
-
types: Platform_AdminApi$ReventlessCore.uploadTypes,
|
|
1444
|
+
types: Platform_AdminApi$ReventlessCore.uploadTypes.concat(Platform_AdminApi$ReventlessCore.geocodeTypes),
|
|
1456
1445
|
mutations: Platform_AdminApi$ReventlessCore.uploadMutationFields,
|
|
1457
|
-
queries: [" Platform_ping: String"],
|
|
1446
|
+
queries: [" Platform_ping: String"].concat(Platform_AdminApi$ReventlessCore.geocodeQueryFields),
|
|
1458
1447
|
subscriptions: [],
|
|
1459
1448
|
subscriptionSources: []
|
|
1460
1449
|
});
|
|
@@ -2367,10 +2356,9 @@ function Make($star) {
|
|
|
2367
2356
|
let cognitoPool = Platform_Stack$ReventlessAws.resolveCognitoUserPool();
|
|
2368
2357
|
let domainEventsEndpointOutput = domainEventsApiOpt !== undefined ? AppSync_EventsApi$ReventlessAws.httpEndpoint(domainEventsApiOpt).apply(ep => ep + "/event") : Pulumi.output(undefined);
|
|
2369
2358
|
let index = hostUiBundle.geocoderPlaceIndex;
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
geocoderEndpointRef.contents = geocoderEndpointFlat;
|
|
2359
|
+
if (index !== undefined) {
|
|
2360
|
+
Geocoder_AwsLocation_Resolver$ReventlessAws.make(domainApi, index.indexName, undefined, {});
|
|
2361
|
+
}
|
|
2374
2362
|
let index$1 = hostUiBundle.geocoderPlaceIndex;
|
|
2375
2363
|
let geocoderPlaceIndexFlat = index$1 !== undefined ? index$1.indexName : Pulumi.output("");
|
|
2376
2364
|
Pulumi$Pulumi.$$export("geocoderPlaceIndex", geocoderPlaceIndexFlat);
|
|
@@ -2382,10 +2370,8 @@ function Make($star) {
|
|
|
2382
2370
|
cognitoPool.poolId,
|
|
2383
2371
|
cognitoPool.clientId
|
|
2384
2372
|
]),
|
|
2385
|
-
domainEventsEndpointOutput
|
|
2386
|
-
geocoderEndpointOutput
|
|
2373
|
+
domainEventsEndpointOutput
|
|
2387
2374
|
]).apply(param => {
|
|
2388
|
-
let geocoderEpOpt = param[2];
|
|
2389
2375
|
let eventsEpOpt = param[1];
|
|
2390
2376
|
let match = param[0];
|
|
2391
2377
|
let computed = [
|
|
@@ -2432,11 +2418,7 @@ function Make($star) {
|
|
|
2432
2418
|
AppSync_EventsApi$ReventlessAws.clientNamespaceName
|
|
2433
2419
|
]
|
|
2434
2420
|
]) : computed;
|
|
2435
|
-
|
|
2436
|
-
"geocoderEndpoint",
|
|
2437
|
-
geocoderEpOpt
|
|
2438
|
-
]]) : withEvents;
|
|
2439
|
-
return JSON.stringify(Util_ShellConfig$ReventlessAws.fields(withGeocoder, hostUiBundle.viewModes, hostUiBundle.shellConfig));
|
|
2421
|
+
return JSON.stringify(Util_ShellConfig$ReventlessAws.fields(withEvents, hostUiBundle.viewModes, hostUiBundle.shellConfig));
|
|
2440
2422
|
});
|
|
2441
2423
|
new (Aws.s3.BucketObject)("host-ui-config-json", {
|
|
2442
2424
|
bucket: bucketName,
|
|
@@ -2645,7 +2627,6 @@ export {
|
|
|
2645
2627
|
getSplitApiOutputs,
|
|
2646
2628
|
objectStoreEndpointsRef,
|
|
2647
2629
|
getObjectStoreEndpoints,
|
|
2648
|
-
geocoderEndpointRef,
|
|
2649
2630
|
geocoderPlaceIndexRef,
|
|
2650
2631
|
MakeWithConfig,
|
|
2651
2632
|
Make,
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
// AWS Location Service geocoder, mounted on the platform GraphQL API.
|
|
2
|
+
//
|
|
3
|
+
// Deploy-time only: `make` provisions one compiled-EntryPoint Lambda (a plain
|
|
4
|
+
// `Lambda.Function` whose code archive re-exports `handler` from the compiled,
|
|
5
|
+
// type-checked runtime module `Geocoder_AwsLocation_Resolver_Ops` and ships the
|
|
6
|
+
// shared ESM resolve-hook loader), an IAM execution role scoped to CloudWatch Logs
|
|
7
|
+
// + `geo:SearchPlaceIndexForText` on the target place index, an AppSync Lambda data
|
|
8
|
+
// source, and one resolver — `Query.geocode` — on the platform API.
|
|
9
|
+
//
|
|
10
|
+
// There is no Function URL and no anonymous surface: authentication is the platform
|
|
11
|
+
// API's Cognito authorizer. This is the *client* door of the geocoding capability
|
|
12
|
+
// (D9 half 2), replacing the public Function URL the browser used to call. The
|
|
13
|
+
// unattended slice path reaches the same place index through the SDK directly
|
|
14
|
+
// (`Geocoder_AwsLocation_Backend`), so one capability, two doors — the same shape
|
|
15
|
+
// the object store already has with `Upload_Presign` and `Offload.resolve`.
|
|
16
|
+
//
|
|
17
|
+
// Why an EntryPoint and not a Pulumi `CallbackFunction`: same SDK-skew reason as the
|
|
18
|
+
// upload service — a serialized closure bakes the deploy machine's version-specific
|
|
19
|
+
// AWS SDK internals into the archive but then resolves `@smithy/*`/`@aws-sdk/*`
|
|
20
|
+
// transitives from independently-versioned layer/runtime sources that disagree at
|
|
21
|
+
// cold start. Shipping the compiled `_Ops` module with bare `@aws-sdk/*` imports,
|
|
22
|
+
// resolved through the resolve-hook, loads one internally consistent SDK. The
|
|
23
|
+
// runtime logic lives in [Geocoder_AwsLocation_Resolver_Ops.res].
|
|
24
|
+
|
|
25
|
+
open PulumiAws
|
|
26
|
+
|
|
27
|
+
type serviceOutputs = {resources: array<Pulumi.Output.t<string>>}
|
|
28
|
+
|
|
29
|
+
// JS resolver code (APPSYNC_JS runtime): forward the caller's arguments to the
|
|
30
|
+
// Lambda. CORS and auth belong to the API, not to this code. No identity is
|
|
31
|
+
// forwarded — geocoding is not scoped per caller (any authenticated user may
|
|
32
|
+
// resolve any address), unlike the upload service which namespaces objects by the
|
|
33
|
+
// verified `sub`.
|
|
34
|
+
let invokeCode: Pulumi.Input.t<string> =
|
|
35
|
+
`import { util } from '@aws-appsync/utils';
|
|
36
|
+
export function request(ctx) {
|
|
37
|
+
return { operation: 'Invoke', payload: { arguments: ctx.args } };
|
|
38
|
+
}
|
|
39
|
+
export function response(ctx) {
|
|
40
|
+
if (ctx.error) util.error(ctx.error.message, ctx.error.type);
|
|
41
|
+
return ctx.result;
|
|
42
|
+
}
|
|
43
|
+
`->Pulumi.Input.make
|
|
44
|
+
|
|
45
|
+
let make = (
|
|
46
|
+
~api: Pulumi.Output.t<AppSync.GraphQLApi.t>,
|
|
47
|
+
~placeIndexName: Pulumi.Input.t<string>,
|
|
48
|
+
~name: string="GeocodeService",
|
|
49
|
+
~opts: Pulumi.ComponentResource.options,
|
|
50
|
+
): serviceOutputs => {
|
|
51
|
+
let opts = opts->ReventlessCore.Util.Pulumi.ComponentResourceOptions.toCustomResourceOptions
|
|
52
|
+
|
|
53
|
+
let lambdaRole = IAM.Role.makeWithDefaultPolicy(
|
|
54
|
+
~name=name ++ "Lambda",
|
|
55
|
+
~servicePrincipal=AWS.Lambda.principal->Pulumi.Output.make,
|
|
56
|
+
~tags=AWS.Tags.make(
|
|
57
|
+
~name=name ++ "Lambda",
|
|
58
|
+
~kind=ReventlessCore.ComponentType.Platform,
|
|
59
|
+
~role=Identity,
|
|
60
|
+
~scope=Platform,
|
|
61
|
+
),
|
|
62
|
+
~opts,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
// CloudWatch Logs (so failures are observable) plus least-privilege
|
|
66
|
+
// `geo:SearchPlaceIndexForText` on the one place index — the same grant the
|
|
67
|
+
// Function URL flavour carried, now on a resolver-invoked Lambda.
|
|
68
|
+
let _policy =
|
|
69
|
+
placeIndexName
|
|
70
|
+
->Pulumi.Output.fromInput
|
|
71
|
+
->Pulumi.Output.apply(idx => {
|
|
72
|
+
let arn = `arn:aws:geo:*:*:place-index/${idx}`
|
|
73
|
+
let _ = IAM.RolePolicy.make(
|
|
74
|
+
~name=name ++ "LambdaPolicy",
|
|
75
|
+
~args={
|
|
76
|
+
policy: PolicyDocument.make(
|
|
77
|
+
~id=name ++ "LambdaPolicy",
|
|
78
|
+
~statements=[
|
|
79
|
+
{
|
|
80
|
+
sid: "AllowLambdaLogging",
|
|
81
|
+
effect: Allow,
|
|
82
|
+
actions: Actions(["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"]),
|
|
83
|
+
resources: Resource("arn:aws:logs:*:*:*"),
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
sid: "AllowGeocode",
|
|
87
|
+
effect: Allow,
|
|
88
|
+
actions: Action("geo:SearchPlaceIndexForText"),
|
|
89
|
+
resources: Resource(arn),
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
)
|
|
93
|
+
->PolicyDocument.toJsonString
|
|
94
|
+
->Pulumi.Input.make,
|
|
95
|
+
role: lambdaRole.id->Pulumi.Output.asInput,
|
|
96
|
+
},
|
|
97
|
+
~opts,
|
|
98
|
+
)
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
// Bundle reventless-aws (the compiled `_Ops` handler lives inside it) and
|
|
102
|
+
// re-export its `handler`; buildCodeArchive also ships the ESM resolve-hook.
|
|
103
|
+
let packageDirs = Dict.fromArray([
|
|
104
|
+
(
|
|
105
|
+
"@reventlessdev/reventless-aws",
|
|
106
|
+
Util_Bundle.resolvePackageRoot("@reventlessdev/reventless-aws"),
|
|
107
|
+
),
|
|
108
|
+
])
|
|
109
|
+
let {code, sourceCodeHash} = Util_Bundle.buildCodeArchive(
|
|
110
|
+
~entryPointModule="@reventlessdev/reventless-aws/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver_Ops.res.mjs",
|
|
111
|
+
~packageDirs,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
let layers =
|
|
115
|
+
Lambda.reventlessLayerArn
|
|
116
|
+
->Option.map(arn => [arn->Pulumi.Input.make])
|
|
117
|
+
->Option.getOr([])
|
|
118
|
+
->Pulumi.Input.make
|
|
119
|
+
|
|
120
|
+
let lambda = Lambda.Function.make(
|
|
121
|
+
~name=name ++ "Lambda",
|
|
122
|
+
~args={
|
|
123
|
+
handler: "index.handler"->Pulumi.Input.make,
|
|
124
|
+
runtime: "nodejs22.x"->Pulumi.Input.make,
|
|
125
|
+
code: code->Pulumi.Input.make,
|
|
126
|
+
sourceCodeHash: sourceCodeHash->Pulumi.Input.make,
|
|
127
|
+
role: lambdaRole.arn->Pulumi.Output.asInput,
|
|
128
|
+
memorySize: 256->Pulumi.Input.make,
|
|
129
|
+
timeout: 30->Pulumi.Input.make,
|
|
130
|
+
layers,
|
|
131
|
+
tags: AWS.Tags.make(
|
|
132
|
+
~name=name ++ "Lambda",
|
|
133
|
+
~kind=ReventlessCore.ComponentType.Platform,
|
|
134
|
+
~role=Runtime,
|
|
135
|
+
~scope=Platform,
|
|
136
|
+
),
|
|
137
|
+
environment: (
|
|
138
|
+
{
|
|
139
|
+
Lambda.Function.variables: Dict.fromArray([
|
|
140
|
+
("Environment", Pulumi.Pulumi.getStackName()->Pulumi.Input.make),
|
|
141
|
+
("PLACE_INDEX_NAME", placeIndexName),
|
|
142
|
+
("NODE_OPTIONS", Util_Bundle.esmLoaderNodeOptions->Pulumi.Input.make),
|
|
143
|
+
("ESM_FALLBACK_DIRS", Util_Bundle.esmFallbackDirs->Pulumi.Input.make),
|
|
144
|
+
Util_LambdaLogging.logLevelEntry(),
|
|
145
|
+
]),
|
|
146
|
+
}: Lambda.Function.functionEnvironment
|
|
147
|
+
)->Pulumi.Input.make,
|
|
148
|
+
},
|
|
149
|
+
~opts,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
Util_LambdaLogging.makeManagedLogGroup(
|
|
153
|
+
~name=name ++ "Lambda",
|
|
154
|
+
~lambdaName=lambda.name,
|
|
155
|
+
~tags=AWS.Tags.make(
|
|
156
|
+
~name=name ++ "LambdaLogGroup",
|
|
157
|
+
~kind=ReventlessCore.ComponentType.Platform,
|
|
158
|
+
~role=Logs,
|
|
159
|
+
~scope=Platform,
|
|
160
|
+
),
|
|
161
|
+
~opts,
|
|
162
|
+
(),
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
let dataSourceRole = IAM.Role.makeWithDefaultPolicy(
|
|
166
|
+
~name=name ++ "DataSource",
|
|
167
|
+
~servicePrincipal=AWS.AppSync.principal->Pulumi.Output.make,
|
|
168
|
+
~tags=AWS.Tags.make(
|
|
169
|
+
~name=name ++ "DataSource",
|
|
170
|
+
~kind=ReventlessCore.ComponentType.Platform,
|
|
171
|
+
~role=Identity,
|
|
172
|
+
~scope=Platform,
|
|
173
|
+
),
|
|
174
|
+
~opts,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
let _ =
|
|
178
|
+
(lambda.arn, dataSourceRole.id)
|
|
179
|
+
->Pulumi.Output.all2
|
|
180
|
+
->Pulumi.Output.apply(((lambdaArn, dataSourceRoleId)) => {
|
|
181
|
+
let _attach = IAM.RolePolicy.make(
|
|
182
|
+
~name=name ++ "DataSource",
|
|
183
|
+
~args={
|
|
184
|
+
policy: PolicyDocument.make(
|
|
185
|
+
~id=name ++ "DataSourcePolicy",
|
|
186
|
+
~statements=[
|
|
187
|
+
{
|
|
188
|
+
sid: "AllowDataSourceInvokeLambda",
|
|
189
|
+
effect: Allow,
|
|
190
|
+
actions: Action("lambda:InvokeFunction"),
|
|
191
|
+
resources: Resource(lambdaArn),
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
)
|
|
195
|
+
->PolicyDocument.toJsonString
|
|
196
|
+
->Pulumi.Input.make,
|
|
197
|
+
role: dataSourceRoleId->Pulumi.Input.make,
|
|
198
|
+
},
|
|
199
|
+
~opts,
|
|
200
|
+
)
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
let dataSource = AppSync.DataSource.make(
|
|
204
|
+
~name=name ++ "DataSource",
|
|
205
|
+
~args={
|
|
206
|
+
type_: AWS_LAMBDA,
|
|
207
|
+
apiId: api->Pulumi.Output.flatMap(api => api.id)->Pulumi.Output.asInput,
|
|
208
|
+
lambdaConfig: {
|
|
209
|
+
AppSync.DataSource.functionArn: lambda.arn->Pulumi.Output.asInput,
|
|
210
|
+
}->Pulumi.Input.make,
|
|
211
|
+
serviceRoleArn: dataSourceRole.arn->Pulumi.Output.asInput,
|
|
212
|
+
},
|
|
213
|
+
~opts=Some(opts),
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
let _geocodeResolver = AppSync_Resolver_Native.makeUnitJsResolver(
|
|
217
|
+
~name=name ++ "Geocode",
|
|
218
|
+
~api,
|
|
219
|
+
~dataSourceName=dataSource.name->Pulumi.Output.asInput,
|
|
220
|
+
~type_="Query"->Pulumi.Input.make,
|
|
221
|
+
~field="geocode"->Pulumi.Input.make,
|
|
222
|
+
~code=invokeCode,
|
|
223
|
+
~opts,
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
{resources: [lambda.arn]}
|
|
227
|
+
}
|