@reventlessdev/reventless-aws 3.0.0-alpha.265 → 3.0.0-alpha.267
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 +14 -0
- package/package.json +6 -6
- package/src/Platform.res +49 -53
- package/src/Platform.res.mjs +17 -36
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res +36 -0
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res.mjs +14 -1
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda_Ops.res +37 -6
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda_Ops.res.mjs +19 -6
- 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,20 @@
|
|
|
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.267 (2026-08-04)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **admin:** serve the complete plugin structure to developer tooling ([e99cda0](https://github.com/ReventlessDev/reventless-core/commit/e99cda02a2f862b36bcfdb018a0fb34bb7426a2b))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# 3.0.0-alpha.266 (2026-08-04)
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* **geocoding:** serve geocoding through the platform GraphQL API (D9 half 2) ([914d3c0](https://github.com/ReventlessDev/reventless-core/commit/914d3c0a99a1b67ffb89e2b8259dd30f67ff9bae))
|
|
18
|
+
|
|
19
|
+
|
|
6
20
|
# 3.0.0-alpha.265 (2026-08-04)
|
|
7
21
|
|
|
8
22
|
### 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.267",
|
|
4
4
|
"description": "AWS adapters for Reventless",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"dependencies": {
|
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
"@reventlessdev/rescript-pulumi-aws": "2.4.0-alpha.65",
|
|
18
18
|
"@reventlessdev/rescript-node": "2.0.0-alpha.1",
|
|
19
19
|
"@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.18",
|
|
20
|
+
"@reventlessdev/reventless-infra": "3.0.0-alpha.126",
|
|
21
|
+
"@reventlessdev/reventless-core": "3.0.0-alpha.212",
|
|
22
|
+
"@reventlessdev/reventless-interop": "3.0.0-alpha.30",
|
|
23
|
+
"@reventlessdev/reventless-postgres": "3.0.0-alpha.76",
|
|
20
24
|
"@reventlessdev/rescript-uuid": "2.0.0-alpha.0",
|
|
21
|
-
"@reventlessdev/reventless-
|
|
22
|
-
"@reventlessdev/reventless-infra": "3.0.0-alpha.125",
|
|
23
|
-
"@reventlessdev/reventless-postgres": "3.0.0-alpha.74",
|
|
24
|
-
"@reventlessdev/reventless-spec": "3.0.0-alpha.100",
|
|
25
|
-
"@reventlessdev/reventless-interop": "3.0.0-alpha.30"
|
|
25
|
+
"@reventlessdev/reventless-spec": "3.0.0-alpha.100"
|
|
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
|
|
@@ -1449,6 +1452,7 @@ module MakeWithConfig = (
|
|
|
1449
1452
|
~api=platformApi,
|
|
1450
1453
|
~pluginReadModelTableName=tableName,
|
|
1451
1454
|
~offloadBucketName,
|
|
1455
|
+
~schemaReady=admin.adminSchemaPushed,
|
|
1452
1456
|
~opts={},
|
|
1453
1457
|
)
|
|
1454
1458
|
| None => ()
|
|
@@ -2066,35 +2070,32 @@ module MakeWithConfig = (
|
|
|
2066
2070
|
| None => Pulumi.Output.make(None)
|
|
2067
2071
|
}
|
|
2068
2072
|
|
|
2069
|
-
//
|
|
2070
|
-
//
|
|
2071
|
-
//
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2073
|
+
// The geocoding capability's client door (D9 half 2): a `Query.geocode`
|
|
2074
|
+
// resolver on the domain API, provisioned only when a place index is
|
|
2075
|
+
// configured. Authenticated by the API's Cognito authorizer, so it replaces
|
|
2076
|
+
// the public unauthenticated Function URL the browser used to call — after
|
|
2077
|
+
// which that endpoint has no callers at all (the unattended slice path reaches
|
|
2078
|
+
// the same index through the SDK, via `geocoderPlaceIndex` below).
|
|
2079
|
+
//
|
|
2080
|
+
// Split-API only, for the same reason the upload resolvers are: `geocode`
|
|
2081
|
+
// lives on the domain base document (`domainBaseFragment`), which a
|
|
2082
|
+
// unified-mode deployment's single API does not carry.
|
|
2083
|
+
switch cfg.geocoderPlaceIndex {
|
|
2084
|
+
| Some(index) if Config.splitApi =>
|
|
2085
|
+
let _geocodeService = Geocoder_AwsLocation_Resolver.make(
|
|
2086
|
+
~api=domainApi,
|
|
2075
2087
|
~placeIndexName=index.indexName,
|
|
2076
|
-
|
|
2077
|
-
|
|
2088
|
+
~opts={},
|
|
2089
|
+
)
|
|
2090
|
+
| _ => ()
|
|
2078
2091
|
}
|
|
2079
2092
|
|
|
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.
|
|
2093
|
+
// The place index itself, exported so the unattended slice path can reach the
|
|
2094
|
+
// capability: a slice's Lambda signs an SDK call directly and needs the index
|
|
2095
|
+
// name, not an endpoint (no proxy hop, no dependence on a public URL). The
|
|
2096
|
+
// browser reaches the same capability through the `Query.geocode` resolver
|
|
2097
|
+
// above. `""` when unset, so a plugin stack reading this output has one shape
|
|
2098
|
+
// to handle rather than two.
|
|
2098
2099
|
let geocoderPlaceIndexFlat = switch cfg.geocoderPlaceIndex {
|
|
2099
2100
|
| Some(index) => index.indexName->Pulumi.Output.fromInput
|
|
2100
2101
|
| None => Pulumi.Output.make("")
|
|
@@ -2116,14 +2117,9 @@ module MakeWithConfig = (
|
|
|
2116
2117
|
cognitoPool.clientId,
|
|
2117
2118
|
)->Pulumi.Output.all4,
|
|
2118
2119
|
domainEventsEndpointOutput,
|
|
2119
|
-
geocoderEndpointOutput,
|
|
2120
2120
|
)
|
|
2121
|
-
->Pulumi.Output.
|
|
2122
|
-
->Pulumi.Output.apply(((
|
|
2123
|
-
(domainEp, platformEp, poolId, clientId),
|
|
2124
|
-
eventsEpOpt,
|
|
2125
|
-
geocoderEpOpt,
|
|
2126
|
-
)) => {
|
|
2121
|
+
->Pulumi.Output.all2
|
|
2122
|
+
->Pulumi.Output.apply((((domainEp, platformEp, poolId, clientId), eventsEpOpt)) => {
|
|
2127
2123
|
let computed = [
|
|
2128
2124
|
("apiEndpoint", JSON.Encode.string(domainEp)),
|
|
2129
2125
|
("platformApiEndpoint", JSON.Encode.string(platformEp)),
|
|
@@ -2151,12 +2147,12 @@ module MakeWithConfig = (
|
|
|
2151
2147
|
)
|
|
2152
2148
|
| None => computed
|
|
2153
2149
|
}
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2150
|
+
// `geocoderEndpoint` is no longer written: the browser reaches geocoding
|
|
2151
|
+
// through the platform API's `Query.geocode` resolver (D9 half 2), the
|
|
2152
|
+
// same way uploads moved off a per-store URL onto `Upload_Presign`. The
|
|
2153
|
+
// public Function URL and its config key are both gone.
|
|
2158
2154
|
Util_ShellConfig.fields(
|
|
2159
|
-
~computed=
|
|
2155
|
+
~computed=withEvents,
|
|
2160
2156
|
~viewModes=?cfg.viewModes,
|
|
2161
2157
|
~shellConfig=?cfg.shellConfig,
|
|
2162
2158
|
)
|
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
|
});
|
|
@@ -865,7 +861,7 @@ function MakeWithConfig(Config) {
|
|
|
865
861
|
Pulumi$Pulumi.$$export("offloadBucket", offloadBucketName);
|
|
866
862
|
if (pluginReadModelTableName !== undefined) {
|
|
867
863
|
AggregateRuntime_Builder_Single$ReventlessAws.setPluginReadModelTable(pluginReadModelTableName);
|
|
868
|
-
Platform_ComponentDefinitions_Lambda$ReventlessAws.make(platformApi, pluginReadModelTableName, offloadBucketName, {});
|
|
864
|
+
Platform_ComponentDefinitions_Lambda$ReventlessAws.make(platformApi, pluginReadModelTableName, offloadBucketName, admin.adminSchemaPushed, {});
|
|
869
865
|
}
|
|
870
866
|
let rm = admin.stateViewSlicesOutputs["UiFragments"];
|
|
871
867
|
if (rm !== undefined) {
|
|
@@ -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
|
});
|
|
@@ -2107,7 +2096,7 @@ function Make($star) {
|
|
|
2107
2096
|
Pulumi$Pulumi.$$export("offloadBucket", offloadBucketName);
|
|
2108
2097
|
if (pluginReadModelTableName !== undefined) {
|
|
2109
2098
|
AggregateRuntime_Builder_Single$ReventlessAws.setPluginReadModelTable(pluginReadModelTableName);
|
|
2110
|
-
Platform_ComponentDefinitions_Lambda$ReventlessAws.make(platformApi, pluginReadModelTableName, offloadBucketName, {});
|
|
2099
|
+
Platform_ComponentDefinitions_Lambda$ReventlessAws.make(platformApi, pluginReadModelTableName, offloadBucketName, admin.adminSchemaPushed, {});
|
|
2111
2100
|
}
|
|
2112
2101
|
let rm = admin.stateViewSlicesOutputs["UiFragments"];
|
|
2113
2102
|
if (rm !== undefined) {
|
|
@@ -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,
|
|
@@ -24,10 +24,29 @@ export function response(ctx) {
|
|
|
24
24
|
}
|
|
25
25
|
`->Pulumi.Input.make
|
|
26
26
|
|
|
27
|
+
// `Platform_PluginStructures` — the same scan, unfiltered. The `complete` flag is
|
|
28
|
+
// the whole difference; see the handler's `toEntryWith`.
|
|
29
|
+
let completeResolverCode = `
|
|
30
|
+
import { util } from '@aws-appsync/utils';
|
|
31
|
+
export function request(ctx) {
|
|
32
|
+
return { operation: 'Invoke', payload: { complete: true } };
|
|
33
|
+
}
|
|
34
|
+
export function response(ctx) {
|
|
35
|
+
if (ctx.error) util.error(ctx.error.message, ctx.error.type);
|
|
36
|
+
return ctx.result;
|
|
37
|
+
}
|
|
38
|
+
`->Pulumi.Input.make
|
|
39
|
+
|
|
27
40
|
let make = (
|
|
28
41
|
~api: Pulumi.Output.t<AppSync.GraphQLApi.t>,
|
|
29
42
|
~pluginReadModelTableName: Pulumi.Output.t<string>,
|
|
30
43
|
~offloadBucketName: Pulumi.Output.t<string>,
|
|
44
|
+
// Resolves once the admin schema push is ACTIVE (Platform_Admin.adminSchemaPushed).
|
|
45
|
+
// Only the `Platform_PluginStructures` resolver is gated on it: that field is new,
|
|
46
|
+
// so CreateResolver would otherwise race StartSchemaCreation on the deploy that
|
|
47
|
+
// first ships it. `Platform_ComponentDefinitions` predates the gate and is left
|
|
48
|
+
// ungated so this change adds no dependency edge to an already-deployed resource.
|
|
49
|
+
~schemaReady: Pulumi.Output.t<unit>,
|
|
31
50
|
~opts: Pulumi.ComponentResource.options,
|
|
32
51
|
) => {
|
|
33
52
|
let opts = opts->ReventlessCore.Util.Pulumi.ComponentResourceOptions.toCustomResourceOptions
|
|
@@ -215,4 +234,21 @@ let make = (
|
|
|
215
234
|
~code=resolverCode,
|
|
216
235
|
~opts,
|
|
217
236
|
)
|
|
237
|
+
|
|
238
|
+
// Second field, same DataSource and same Lambda — the developer-tooling read of
|
|
239
|
+
// the identical scan. Sharing the data source is what keeps the two answers from
|
|
240
|
+
// drifting: there is one place that decides what a deployed plugin's structure is.
|
|
241
|
+
// Created only after the schema carrying `Platform_PluginStructures` is ACTIVE.
|
|
242
|
+
let _structuresResolver =
|
|
243
|
+
schemaReady->Pulumi.Output.apply(() =>
|
|
244
|
+
AppSync_Resolver_Native.makeUnitJsResolver(
|
|
245
|
+
~name=name ++ "StructuresResolver",
|
|
246
|
+
~api,
|
|
247
|
+
~dataSourceName=dataSource.name->Pulumi.Output.asInput,
|
|
248
|
+
~type_="Query"->Pulumi.Input.make,
|
|
249
|
+
~field="Platform_PluginStructures"->Pulumi.Input.make,
|
|
250
|
+
~code=completeResolverCode,
|
|
251
|
+
~opts,
|
|
252
|
+
)
|
|
253
|
+
)
|
|
218
254
|
}
|
|
@@ -27,7 +27,18 @@ export function response(ctx) {
|
|
|
27
27
|
}
|
|
28
28
|
`;
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
let completeResolverCode = `
|
|
31
|
+
import { util } from '@aws-appsync/utils';
|
|
32
|
+
export function request(ctx) {
|
|
33
|
+
return { operation: 'Invoke', payload: { complete: true } };
|
|
34
|
+
}
|
|
35
|
+
export function response(ctx) {
|
|
36
|
+
if (ctx.error) util.error(ctx.error.message, ctx.error.type);
|
|
37
|
+
return ctx.result;
|
|
38
|
+
}
|
|
39
|
+
`;
|
|
40
|
+
|
|
41
|
+
function make(api, pluginReadModelTableName, offloadBucketName, schemaReady, opts) {
|
|
31
42
|
let opts$1 = Util_Pulumi$ReventlessCore.ComponentResourceOptions.toCustomResourceOptions(opts);
|
|
32
43
|
let name = "PlatformUIDefinitions";
|
|
33
44
|
let lambdaRole = IAM$PulumiAws.Role.makeWithDefaultPolicy(name + "Lambda", Pulumi.output(AWS$ReventlessAws.Lambda.principal), AWS_Tags$ReventlessAws.make(name + "Lambda", "Platform", "Identity", "Platform", undefined, undefined, undefined, undefined), opts$1);
|
|
@@ -131,10 +142,12 @@ function make(api, pluginReadModelTableName, offloadBucketName, opts) {
|
|
|
131
142
|
serviceRoleArn: dataSourceRole.arn
|
|
132
143
|
}, opts$1);
|
|
133
144
|
AppSync_Resolver_Native$ReventlessAws.makeUnitJsResolver(name + "Resolver", api, dataSource.name, "Query", "Platform_ComponentDefinitions", resolverCode, opts$1);
|
|
145
|
+
schemaReady.apply(() => AppSync_Resolver_Native$ReventlessAws.makeUnitJsResolver(name + "StructuresResolver", api, dataSource.name, "Query", "Platform_PluginStructures", completeResolverCode, opts$1));
|
|
134
146
|
}
|
|
135
147
|
|
|
136
148
|
export {
|
|
137
149
|
resolverCode,
|
|
150
|
+
completeResolverCode,
|
|
138
151
|
make,
|
|
139
152
|
}
|
|
140
153
|
/* @pulumi/aws Not a pure module */
|
|
@@ -43,11 +43,21 @@ let filterStructure = (structure: JSON.t): option<dict<JSON.t>> =>
|
|
|
43
43
|
Some(out)
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
// `{pluginId: name, ...
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
// `{pluginId: name, ...structure}` — pluginId first so the structure's fields win
|
|
47
|
+
// on the (never-expected) key collision, matching the JS spread. Drops a row with
|
|
48
|
+
// no decodable structure (former `!item.structure`).
|
|
49
|
+
//
|
|
50
|
+
// `~filter` is what separates the two fields this handler serves: AutoUI
|
|
51
|
+
// (`Platform_ComponentDefinitions`) gets the public-queryable subset, developer
|
|
52
|
+
// tooling (`Platform_PluginStructures`) gets the structure exactly as persisted,
|
|
53
|
+
// including Internal components and the producer-side `extensionPoints` that the
|
|
54
|
+
// AutoUI entry type does not declare.
|
|
55
|
+
let toEntryWith = (~filter: bool, item: dict<JSON.t>, ~name: string): option<JSON.t> => {
|
|
56
|
+
let structure =
|
|
57
|
+
item
|
|
58
|
+
->Dict.get("structure")
|
|
59
|
+
->Option.flatMap(s => filter ? filterStructure(s) : s->JSON.Decode.object)
|
|
60
|
+
switch structure {
|
|
51
61
|
| None => None
|
|
52
62
|
| Some(structureObj) =>
|
|
53
63
|
let entry = Dict.make()
|
|
@@ -55,10 +65,17 @@ let toEntry = (item: dict<JSON.t>, ~name: string): option<JSON.t> =>
|
|
|
55
65
|
structureObj->Dict.toArray->Array.forEach(((k, v)) => entry->Dict.set(k, v))
|
|
56
66
|
Some(JSON.Encode.object(entry))
|
|
57
67
|
}
|
|
68
|
+
}
|
|
69
|
+
|
|
58
70
|
|
|
59
71
|
// The built-in Platform_Admin entry, injected at deploy time as the
|
|
60
72
|
// ADMIN_ENTRY_JSON env var (the admin never Connects to itself, so its structure
|
|
61
73
|
// never enters the Plugin read model).
|
|
74
|
+
//
|
|
75
|
+
// Shared by both fields. The admin structure has no Internal components and no
|
|
76
|
+
// extension points, so its filtered and complete encodings carry the same
|
|
77
|
+
// components; the structure-level fields the complete entry adds are absent from
|
|
78
|
+
// this JSON and resolve to null, which is what `extensionPoints: None` means.
|
|
62
79
|
let adminEntry: option<JSON.t> =
|
|
63
80
|
switch NodeProcess.env->Dict.get("ADMIN_ENTRY_JSON") {
|
|
64
81
|
| Some(s) if s != "" => Some(JSON.parseOrThrow(s))
|
|
@@ -94,7 +111,21 @@ let resolveStructure = (
|
|
|
94
111
|
}
|
|
95
112
|
}
|
|
96
113
|
|
|
97
|
-
|
|
114
|
+
// One Lambda serves both fields — the scan, the offload resolution and the
|
|
115
|
+
// latest-version-per-plugin collapse are identical work, and duplicating them into
|
|
116
|
+
// a second function would mean a second cold start and a second chance for the two
|
|
117
|
+
// to disagree about what "the deployed structure" is. The resolver for
|
|
118
|
+
// `Platform_PluginStructures` invokes with `{complete: true}`.
|
|
119
|
+
let isComplete = (event: JSON.t): bool =>
|
|
120
|
+
event
|
|
121
|
+
->JSON.Decode.object
|
|
122
|
+
->Option.flatMap(o => o->Dict.get("complete"))
|
|
123
|
+
->Option.flatMap(JSON.Decode.bool)
|
|
124
|
+
->Option.getOr(false)
|
|
125
|
+
|
|
126
|
+
let handler = async (event: JSON.t): array<JSON.t> => {
|
|
127
|
+
let complete = isComplete(event)
|
|
128
|
+
let toEntry = (item, ~name) => toEntryWith(~filter=!complete, item, ~name)
|
|
98
129
|
let admin = adminEntry->Option.mapOr([], e => [e])
|
|
99
130
|
switch NodeProcess.env->Dict.get("PLUGIN_RM_TABLE") {
|
|
100
131
|
| None | Some("") =>
|
|
@@ -31,14 +31,20 @@ function filterStructure(structure) {
|
|
|
31
31
|
return out;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
function
|
|
35
|
-
let
|
|
36
|
-
|
|
34
|
+
function toEntryWith(filter, item, name) {
|
|
35
|
+
let structure = Stdlib_Option.flatMap(item["structure"], s => {
|
|
36
|
+
if (filter) {
|
|
37
|
+
return filterStructure(s);
|
|
38
|
+
} else {
|
|
39
|
+
return Stdlib_JSON.Decode.object(s);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
if (structure === undefined) {
|
|
37
43
|
return;
|
|
38
44
|
}
|
|
39
45
|
let entry = {};
|
|
40
46
|
entry["pluginId"] = name;
|
|
41
|
-
Object.entries(
|
|
47
|
+
Object.entries(structure).forEach(param => {
|
|
42
48
|
entry[param[0]] = param[1];
|
|
43
49
|
});
|
|
44
50
|
return entry;
|
|
@@ -65,7 +71,13 @@ function resolveStructure(fetch, item) {
|
|
|
65
71
|
}
|
|
66
72
|
}
|
|
67
73
|
|
|
68
|
-
|
|
74
|
+
function isComplete(event) {
|
|
75
|
+
return Stdlib_Option.getOr(Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_JSON.Decode.object(event), o => o["complete"]), Stdlib_JSON.Decode.bool), false);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function handler(event) {
|
|
79
|
+
let complete = isComplete(event);
|
|
80
|
+
let toEntry = (item, name) => toEntryWith(!complete, item, name);
|
|
69
81
|
let admin = Stdlib_Option.mapOr(adminEntry, [], e => [e]);
|
|
70
82
|
let table = process.env["PLUGIN_RM_TABLE"];
|
|
71
83
|
if (table !== undefined) {
|
|
@@ -94,9 +106,10 @@ export {
|
|
|
94
106
|
str,
|
|
95
107
|
isPublicQueryable,
|
|
96
108
|
filterStructure,
|
|
97
|
-
|
|
109
|
+
toEntryWith,
|
|
98
110
|
adminEntry,
|
|
99
111
|
resolveStructure,
|
|
112
|
+
isComplete,
|
|
100
113
|
handler,
|
|
101
114
|
}
|
|
102
115
|
/* s Not a pure module */
|