@reventlessdev/reventless-aws 3.0.0-alpha.264 → 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 +17 -0
- package/package.json +7 -7
- package/src/Platform.res +66 -45
- package/src/Platform.res.mjs +31 -35
- 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/src/adapter/Runtime/AutomationSliceEntryPoint.mjs +21 -3
- package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res +219 -27
- package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res.mjs +121 -7
- package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res +118 -0
- package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res.mjs +61 -0
- package/src/components/OutboundTranslationSlice_Builder.res +15 -0
- package/src/components/OutboundTranslationSlice_Builder.res.mjs +11 -1
- package/src/plugin/runtime/PluginRuntime_Builder.res +26 -0
- package/src/plugin/runtime/PluginRuntime_Builder.res.mjs +26 -0
- package/tests/AutomationSliceEntryPoint_OpsTest.res +44 -3
- package/tests/AutomationSliceEntryPoint_OpsTest.res.mjs +65 -1
- 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,23 @@
|
|
|
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
|
+
|
|
13
|
+
# 3.0.0-alpha.265 (2026-08-04)
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* **aws:** make a slice's TODO backlog survive, and actually sweep it ([f35dcbd](https://github.com/ReventlessDev/reventless-core/commit/f35dcbd86374124106c2d1e48d29c6f41fdbec2c))
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* **outbound:** hand translate its geocoder instead of making it fetch one ([fb18312](https://github.com/ReventlessDev/reventless-core/commit/fb1831216b37c9562868c46e1a09054e69418c67))
|
|
21
|
+
|
|
22
|
+
|
|
6
23
|
# 3.0.0-alpha.264 (2026-08-03)
|
|
7
24
|
|
|
8
25
|
### 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-spec": "3.0.0-alpha.
|
|
24
|
-
"@reventlessdev/reventless-
|
|
25
|
-
"@reventlessdev/reventless-
|
|
21
|
+
"@reventlessdev/reventless-core": "3.0.0-alpha.211",
|
|
22
|
+
"@reventlessdev/reventless-infra": "3.0.0-alpha.126",
|
|
23
|
+
"@reventlessdev/reventless-spec": "3.0.0-alpha.100",
|
|
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,19 +82,22 @@ 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
|
|
100
|
+
let geocoderPlaceIndexRef: ref<Pulumi.Output.t<string>> = ref(Pulumi.Output.make(""))
|
|
98
101
|
|
|
99
102
|
module MakeWithConfig = (
|
|
100
103
|
Config: {
|
|
@@ -242,9 +245,15 @@ module MakeWithConfig = (
|
|
|
242
245
|
// unified mode carries the admin base here instead; it declares no stores in practice,
|
|
243
246
|
// so the upload resolvers below are never created there.)
|
|
244
247
|
let domainBaseFragment = ReventlessCore.GraphQL_Stitcher.encode({
|
|
245
|
-
types:
|
|
248
|
+
types: Array.concat(
|
|
249
|
+
ReventlessCore.Platform_AdminApi.uploadTypes,
|
|
250
|
+
ReventlessCore.Platform_AdminApi.geocodeTypes,
|
|
251
|
+
),
|
|
246
252
|
mutations: ReventlessCore.Platform_AdminApi.uploadMutationFields,
|
|
247
|
-
queries:
|
|
253
|
+
queries: Array.concat(
|
|
254
|
+
[" Platform_ping: String"],
|
|
255
|
+
ReventlessCore.Platform_AdminApi.geocodeQueryFields,
|
|
256
|
+
),
|
|
248
257
|
subscriptions: [],
|
|
249
258
|
subscriptionSources: [],
|
|
250
259
|
})
|
|
@@ -1146,10 +1155,10 @@ module MakeWithConfig = (
|
|
|
1146
1155
|
// unchanged. Single-mode shape: one origin-relative file per deployment.
|
|
1147
1156
|
uiHintsFile?: string,
|
|
1148
1157
|
// Optional geocoding place index, as returned by
|
|
1149
|
-
// `Capability_Geocoding_AwsLocation.make`. When set, the deploy provisions
|
|
1150
|
-
//
|
|
1151
|
-
//
|
|
1152
|
-
//
|
|
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.
|
|
1153
1162
|
geocoderPlaceIndex?: ReventlessInfra.Platform.geocoderIndex,
|
|
1154
1163
|
// Optional object store for direct-to-S3 uploads, as returned by
|
|
1155
1164
|
// `Capability_ObjectStore_S3.make`. When set, the deploy registers it with
|
|
@@ -2060,28 +2069,38 @@ module MakeWithConfig = (
|
|
|
2060
2069
|
| None => Pulumi.Output.make(None)
|
|
2061
2070
|
}
|
|
2062
2071
|
|
|
2063
|
-
//
|
|
2064
|
-
//
|
|
2065
|
-
//
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
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,
|
|
2069
2086
|
~placeIndexName=index.indexName,
|
|
2070
|
-
|
|
2071
|
-
|
|
2087
|
+
~opts={},
|
|
2088
|
+
)
|
|
2089
|
+
| _ => ()
|
|
2072
2090
|
}
|
|
2073
2091
|
|
|
2074
|
-
//
|
|
2075
|
-
//
|
|
2076
|
-
//
|
|
2077
|
-
//
|
|
2078
|
-
// `""` when unset
|
|
2079
|
-
//
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
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
|
+
let geocoderPlaceIndexFlat = switch cfg.geocoderPlaceIndex {
|
|
2099
|
+
| Some(index) => index.indexName->Pulumi.Output.fromInput
|
|
2100
|
+
| None => Pulumi.Output.make("")
|
|
2101
|
+
}
|
|
2102
|
+
Pulumi.Pulumi.export("geocoderPlaceIndex", geocoderPlaceIndexFlat)
|
|
2103
|
+
geocoderPlaceIndexRef := geocoderPlaceIndexFlat
|
|
2085
2104
|
|
|
2086
2105
|
// Presign endpoints are no longer written to config.json: under route B the
|
|
2087
2106
|
// client calls the platform API's `Upload_Presign` mutation (reachable from
|
|
@@ -2097,14 +2116,9 @@ module MakeWithConfig = (
|
|
|
2097
2116
|
cognitoPool.clientId,
|
|
2098
2117
|
)->Pulumi.Output.all4,
|
|
2099
2118
|
domainEventsEndpointOutput,
|
|
2100
|
-
geocoderEndpointOutput,
|
|
2101
2119
|
)
|
|
2102
|
-
->Pulumi.Output.
|
|
2103
|
-
->Pulumi.Output.apply(((
|
|
2104
|
-
(domainEp, platformEp, poolId, clientId),
|
|
2105
|
-
eventsEpOpt,
|
|
2106
|
-
geocoderEpOpt,
|
|
2107
|
-
)) => {
|
|
2120
|
+
->Pulumi.Output.all2
|
|
2121
|
+
->Pulumi.Output.apply((((domainEp, platformEp, poolId, clientId), eventsEpOpt)) => {
|
|
2108
2122
|
let computed = [
|
|
2109
2123
|
("apiEndpoint", JSON.Encode.string(domainEp)),
|
|
2110
2124
|
("platformApiEndpoint", JSON.Encode.string(platformEp)),
|
|
@@ -2132,12 +2146,12 @@ module MakeWithConfig = (
|
|
|
2132
2146
|
)
|
|
2133
2147
|
| None => computed
|
|
2134
2148
|
}
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
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.
|
|
2139
2153
|
Util_ShellConfig.fields(
|
|
2140
|
-
~computed=
|
|
2154
|
+
~computed=withEvents,
|
|
2141
2155
|
~viewModes=?cfg.viewModes,
|
|
2142
2156
|
~shellConfig=?cfg.shellConfig,
|
|
2143
2157
|
)
|
|
@@ -2251,15 +2265,22 @@ module MakeWithConfig = (
|
|
|
2251
2265
|
// is a modelled outcome, which is the point of the empty string: a plugin
|
|
2252
2266
|
// deployed against a platform without the capability degrades rather than
|
|
2253
2267
|
// failing to deploy.
|
|
2254
|
-
|
|
2268
|
+
// The place index, not the Function URL. A slice's Lambda reaches Amazon
|
|
2269
|
+
// Location through the SDK now, so what it needs is the index's name — and
|
|
2270
|
+
// the grant that goes with it, which is why this is also handed to
|
|
2271
|
+
// `registerGeocoderPlaceIndex` rather than only to the environment. The
|
|
2272
|
+
// browser keeps using the Function URL until the platform API carries a
|
|
2273
|
+
// geocode field; the two doors are independent.
|
|
2274
|
+
let geocoderPlaceIndex: Pulumi.Output.t<string> = switch platformStackRef {
|
|
2255
2275
|
| Some(stackRef) =>
|
|
2256
2276
|
(
|
|
2257
|
-
stackRef->Pulumi.StackReference.getOutput("
|
|
2277
|
+
stackRef->Pulumi.StackReference.getOutput("geocoderPlaceIndex"):
|
|
2258
2278
|
Pulumi.Output.t<option<string>>
|
|
2259
2279
|
)->Pulumi.Output.apply(o => o->Option.getOr(""))
|
|
2260
|
-
| None =>
|
|
2280
|
+
| None => geocoderPlaceIndexRef.contents
|
|
2261
2281
|
}
|
|
2262
|
-
PluginRuntime_Builder.registerCapabilityEnv("
|
|
2282
|
+
PluginRuntime_Builder.registerCapabilityEnv("PLACE_INDEX_NAME", geocoderPlaceIndex)
|
|
2283
|
+
PluginRuntime_Builder.registerGeocoderPlaceIndex(geocoderPlaceIndex)
|
|
2263
2284
|
|
|
2264
2285
|
module P = unpack(plugin)
|
|
2265
2286
|
let pluginComponent = P.make()
|
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,7 +130,7 @@ function getObjectStoreEndpoints() {
|
|
|
130
130
|
return objectStoreEndpointsRef.contents;
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
let
|
|
133
|
+
let geocoderPlaceIndexRef = {
|
|
134
134
|
contents: Pulumi.output("")
|
|
135
135
|
};
|
|
136
136
|
|
|
@@ -189,9 +189,9 @@ function MakeWithConfig(Config) {
|
|
|
189
189
|
}
|
|
190
190
|
};
|
|
191
191
|
let domainBaseFragment = GraphQL_Stitcher$ReventlessCore.encode({
|
|
192
|
-
types: Platform_AdminApi$ReventlessCore.uploadTypes,
|
|
192
|
+
types: Platform_AdminApi$ReventlessCore.uploadTypes.concat(Platform_AdminApi$ReventlessCore.geocodeTypes),
|
|
193
193
|
mutations: Platform_AdminApi$ReventlessCore.uploadMutationFields,
|
|
194
|
-
queries: [" Platform_ping: String"],
|
|
194
|
+
queries: [" Platform_ping: String"].concat(Platform_AdminApi$ReventlessCore.geocodeQueryFields),
|
|
195
195
|
subscriptions: [],
|
|
196
196
|
subscriptionSources: []
|
|
197
197
|
});
|
|
@@ -1127,10 +1127,13 @@ function MakeWithConfig(Config) {
|
|
|
1127
1127
|
let cognitoPool = Platform_Stack$ReventlessAws.resolveCognitoUserPool();
|
|
1128
1128
|
let domainEventsEndpointOutput = domainEventsApiOpt !== undefined ? AppSync_EventsApi$ReventlessAws.httpEndpoint(domainEventsApiOpt).apply(ep => ep + "/event") : Pulumi.output(undefined);
|
|
1129
1129
|
let index = hostUiBundle.geocoderPlaceIndex;
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1130
|
+
if (index !== undefined && Config.splitApi) {
|
|
1131
|
+
Geocoder_AwsLocation_Resolver$ReventlessAws.make(domainApi, index.indexName, undefined, {});
|
|
1132
|
+
}
|
|
1133
|
+
let index$1 = hostUiBundle.geocoderPlaceIndex;
|
|
1134
|
+
let geocoderPlaceIndexFlat = index$1 !== undefined ? index$1.indexName : Pulumi.output("");
|
|
1135
|
+
Pulumi$Pulumi.$$export("geocoderPlaceIndex", geocoderPlaceIndexFlat);
|
|
1136
|
+
geocoderPlaceIndexRef.contents = geocoderPlaceIndexFlat;
|
|
1134
1137
|
let configJsonContent = Pulumi.all([
|
|
1135
1138
|
Pulumi.all([
|
|
1136
1139
|
resolvedDomainApiEndpoint,
|
|
@@ -1138,10 +1141,8 @@ function MakeWithConfig(Config) {
|
|
|
1138
1141
|
cognitoPool.poolId,
|
|
1139
1142
|
cognitoPool.clientId
|
|
1140
1143
|
]),
|
|
1141
|
-
domainEventsEndpointOutput
|
|
1142
|
-
geocoderEndpointOutput
|
|
1144
|
+
domainEventsEndpointOutput
|
|
1143
1145
|
]).apply(param => {
|
|
1144
|
-
let geocoderEpOpt = param[2];
|
|
1145
1146
|
let eventsEpOpt = param[1];
|
|
1146
1147
|
let match = param[0];
|
|
1147
1148
|
let computed = [
|
|
@@ -1188,11 +1189,7 @@ function MakeWithConfig(Config) {
|
|
|
1188
1189
|
AppSync_EventsApi$ReventlessAws.clientNamespaceName
|
|
1189
1190
|
]
|
|
1190
1191
|
]) : computed;
|
|
1191
|
-
|
|
1192
|
-
"geocoderEndpoint",
|
|
1193
|
-
geocoderEpOpt
|
|
1194
|
-
]]) : withEvents;
|
|
1195
|
-
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));
|
|
1196
1193
|
});
|
|
1197
1194
|
new (Aws.s3.BucketObject)("host-ui-config-json", {
|
|
1198
1195
|
bucket: bucketName,
|
|
@@ -1247,8 +1244,9 @@ function MakeWithConfig(Config) {
|
|
|
1247
1244
|
bytes: bytes.length
|
|
1248
1245
|
};
|
|
1249
1246
|
});
|
|
1250
|
-
let
|
|
1251
|
-
PluginRuntime_Builder$ReventlessAws.registerCapabilityEnv("
|
|
1247
|
+
let geocoderPlaceIndex = platformStackRef !== undefined ? Primitive_option.valFromOption(platformStackRef).getOutput("geocoderPlaceIndex").apply(o => Stdlib_Option.getOr(o, "")) : geocoderPlaceIndexRef.contents;
|
|
1248
|
+
PluginRuntime_Builder$ReventlessAws.registerCapabilityEnv("PLACE_INDEX_NAME", geocoderPlaceIndex);
|
|
1249
|
+
PluginRuntime_Builder$ReventlessAws.registerGeocoderPlaceIndex(geocoderPlaceIndex);
|
|
1252
1250
|
let pluginComponent = plugin.make();
|
|
1253
1251
|
Plugin_Helpers$ReventlessCore.clearOffload();
|
|
1254
1252
|
currentDeployTarget.contents = "Domain";
|
|
@@ -1443,9 +1441,9 @@ function Make($star) {
|
|
|
1443
1441
|
}
|
|
1444
1442
|
};
|
|
1445
1443
|
let domainBaseFragment = GraphQL_Stitcher$ReventlessCore.encode({
|
|
1446
|
-
types: Platform_AdminApi$ReventlessCore.uploadTypes,
|
|
1444
|
+
types: Platform_AdminApi$ReventlessCore.uploadTypes.concat(Platform_AdminApi$ReventlessCore.geocodeTypes),
|
|
1447
1445
|
mutations: Platform_AdminApi$ReventlessCore.uploadMutationFields,
|
|
1448
|
-
queries: [" Platform_ping: String"],
|
|
1446
|
+
queries: [" Platform_ping: String"].concat(Platform_AdminApi$ReventlessCore.geocodeQueryFields),
|
|
1449
1447
|
subscriptions: [],
|
|
1450
1448
|
subscriptionSources: []
|
|
1451
1449
|
});
|
|
@@ -2358,10 +2356,13 @@ function Make($star) {
|
|
|
2358
2356
|
let cognitoPool = Platform_Stack$ReventlessAws.resolveCognitoUserPool();
|
|
2359
2357
|
let domainEventsEndpointOutput = domainEventsApiOpt !== undefined ? AppSync_EventsApi$ReventlessAws.httpEndpoint(domainEventsApiOpt).apply(ep => ep + "/event") : Pulumi.output(undefined);
|
|
2360
2358
|
let index = hostUiBundle.geocoderPlaceIndex;
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2359
|
+
if (index !== undefined) {
|
|
2360
|
+
Geocoder_AwsLocation_Resolver$ReventlessAws.make(domainApi, index.indexName, undefined, {});
|
|
2361
|
+
}
|
|
2362
|
+
let index$1 = hostUiBundle.geocoderPlaceIndex;
|
|
2363
|
+
let geocoderPlaceIndexFlat = index$1 !== undefined ? index$1.indexName : Pulumi.output("");
|
|
2364
|
+
Pulumi$Pulumi.$$export("geocoderPlaceIndex", geocoderPlaceIndexFlat);
|
|
2365
|
+
geocoderPlaceIndexRef.contents = geocoderPlaceIndexFlat;
|
|
2365
2366
|
let configJsonContent = Pulumi.all([
|
|
2366
2367
|
Pulumi.all([
|
|
2367
2368
|
resolvedDomainApiEndpoint,
|
|
@@ -2369,10 +2370,8 @@ function Make($star) {
|
|
|
2369
2370
|
cognitoPool.poolId,
|
|
2370
2371
|
cognitoPool.clientId
|
|
2371
2372
|
]),
|
|
2372
|
-
domainEventsEndpointOutput
|
|
2373
|
-
geocoderEndpointOutput
|
|
2373
|
+
domainEventsEndpointOutput
|
|
2374
2374
|
]).apply(param => {
|
|
2375
|
-
let geocoderEpOpt = param[2];
|
|
2376
2375
|
let eventsEpOpt = param[1];
|
|
2377
2376
|
let match = param[0];
|
|
2378
2377
|
let computed = [
|
|
@@ -2419,11 +2418,7 @@ function Make($star) {
|
|
|
2419
2418
|
AppSync_EventsApi$ReventlessAws.clientNamespaceName
|
|
2420
2419
|
]
|
|
2421
2420
|
]) : computed;
|
|
2422
|
-
|
|
2423
|
-
"geocoderEndpoint",
|
|
2424
|
-
geocoderEpOpt
|
|
2425
|
-
]]) : withEvents;
|
|
2426
|
-
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));
|
|
2427
2422
|
});
|
|
2428
2423
|
new (Aws.s3.BucketObject)("host-ui-config-json", {
|
|
2429
2424
|
bucket: bucketName,
|
|
@@ -2478,8 +2473,9 @@ function Make($star) {
|
|
|
2478
2473
|
bytes: bytes.length
|
|
2479
2474
|
};
|
|
2480
2475
|
});
|
|
2481
|
-
let
|
|
2482
|
-
PluginRuntime_Builder$ReventlessAws.registerCapabilityEnv("
|
|
2476
|
+
let geocoderPlaceIndex = platformStackRef !== undefined ? Primitive_option.valFromOption(platformStackRef).getOutput("geocoderPlaceIndex").apply(o => Stdlib_Option.getOr(o, "")) : geocoderPlaceIndexRef.contents;
|
|
2477
|
+
PluginRuntime_Builder$ReventlessAws.registerCapabilityEnv("PLACE_INDEX_NAME", geocoderPlaceIndex);
|
|
2478
|
+
PluginRuntime_Builder$ReventlessAws.registerGeocoderPlaceIndex(geocoderPlaceIndex);
|
|
2483
2479
|
let pluginComponent = plugin.make();
|
|
2484
2480
|
Plugin_Helpers$ReventlessCore.clearOffload();
|
|
2485
2481
|
currentDeployTarget.contents = "Domain";
|
|
@@ -2631,7 +2627,7 @@ export {
|
|
|
2631
2627
|
getSplitApiOutputs,
|
|
2632
2628
|
objectStoreEndpointsRef,
|
|
2633
2629
|
getObjectStoreEndpoints,
|
|
2634
|
-
|
|
2630
|
+
geocoderPlaceIndexRef,
|
|
2635
2631
|
MakeWithConfig,
|
|
2636
2632
|
Make,
|
|
2637
2633
|
}
|
|
@@ -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
|
+
}
|