@reventlessdev/reventless-local 3.0.0-alpha.198 → 3.0.0-alpha.199

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 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.199 (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.198 (2026-08-04)
7
14
 
8
15
  ### Bug Fixes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reventlessdev/reventless-local",
3
- "version": "3.0.0-alpha.198",
3
+ "version": "3.0.0-alpha.199",
4
4
  "description": "Local platform for Reventless (in-memory or SQLite backend, for development and testing without AWS)",
5
5
  "license": "Apache-2.0",
6
6
  "bin": {
@@ -34,18 +34,18 @@
34
34
  "graphql-yoga": "^5.21.0",
35
35
  "sury": "11.0.0-alpha.4",
36
36
  "ws": "^8.18.0",
37
- "@reventlessdev/rescript-graphql-yoga": "1.0.0-alpha.26",
38
37
  "@reventlessdev/rescript-effect": "0.1.0-alpha.32",
39
38
  "@reventlessdev/rescript-jest": "1.0.0-alpha.10",
40
39
  "@reventlessdev/rescript-node": "2.0.0-alpha.1",
40
+ "@reventlessdev/rescript-graphql-yoga": "1.0.0-alpha.26",
41
41
  "@reventlessdev/rescript-mcp-sdk": "1.0.0-alpha.21",
42
42
  "@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.18",
43
- "@reventlessdev/reventless-core": "3.0.0-alpha.210",
44
- "@reventlessdev/reventless-graphql-server": "1.0.0-alpha.58",
45
- "@reventlessdev/reventless-gwt": "1.0.0-alpha.157",
46
- "@reventlessdev/reventless-infra": "3.0.0-alpha.125",
43
+ "@reventlessdev/reventless-core": "3.0.0-alpha.211",
44
+ "@reventlessdev/reventless-graphql-server": "1.0.0-alpha.59",
45
+ "@reventlessdev/reventless-infra": "3.0.0-alpha.126",
46
+ "@reventlessdev/reventless-postgres": "3.0.0-alpha.75",
47
47
  "@reventlessdev/reventless-spec": "3.0.0-alpha.100",
48
- "@reventlessdev/reventless-postgres": "3.0.0-alpha.74"
48
+ "@reventlessdev/reventless-gwt": "1.0.0-alpha.158"
49
49
  },
50
50
  "devDependencies": {
51
51
  "rescript": "12.3.0",
package/src/Platform.res CHANGED
@@ -1938,6 +1938,9 @@ module MakeWithConfig = (
1938
1938
  // Upload service (route B) on the domain server — mirrors adding it to
1939
1939
  // `domainBaseFragment` on AWS.
1940
1940
  LocalUploadResolvers.register(DomainGraphQL_Server.asInterface)
1941
+ // Geocoding client door (D9 half 2) on the domain server — same mirror. A dev
1942
+ // stub (no real geocoder locally), so the map picker's search box works offline.
1943
+ LocalGeocodeResolvers.register(DomainGraphQL_Server.asInterface)
1941
1944
  // In split mode, inject Relay base types (Node interface, PageInfo) into the platform
1942
1945
  // server so SDL fragments compile. The node(id) query is Domain-only — the Platform
1943
1946
  // API is consumed by admin tools and agents, not Relay clients.
@@ -61,6 +61,7 @@ import * as EventPublish_Callback$ReventlessCore from "@reventlessdev/reventless
61
61
  import * as LocalUploadResolvers$ReventlessLocal from "./adapter/LocalUploadResolvers.res.mjs";
62
62
  import * as ProjectionCheckpoint$ReventlessLocal from "./adapter/ProjectionCheckpoint.res.mjs";
63
63
  import * as ExtensionPointMapping$ReventlessInfra from "@reventlessdev/reventless-infra/src/types/ExtensionPointMapping.res.mjs";
64
+ import * as LocalGeocodeResolvers$ReventlessLocal from "./adapter/LocalGeocodeResolvers.res.mjs";
64
65
  import * as UiFragments_Projection$ReventlessCore from "@reventlessdev/reventless-core/src/admin/UiFragmentRegistry/StateViewSlice/UiFragments_Projection.res.mjs";
65
66
  import * as EventLogStorage_Sqlite$ReventlessLocal from "./adapter/EventLog/EventLogStorage_Sqlite.res.mjs";
66
67
  import * as ExtensionPoint_Builder$ReventlessLocal from "./components/ExtensionPoint_Builder.res.mjs";
@@ -1559,6 +1560,7 @@ function MakeWithConfig(Config) {
1559
1560
  DomainGraphQL_Server$ReventlessLocal.registerTypes(GraphQL_Stitcher$ReventlessCore.relayBaseTypes);
1560
1561
  DomainGraphQL_Server$ReventlessLocal.registerQueries(GraphQL_Stitcher$ReventlessCore.relayBaseQueries, {});
1561
1562
  LocalUploadResolvers$ReventlessLocal.register(DomainGraphQL_Server$ReventlessLocal.asInterface);
1563
+ LocalGeocodeResolvers$ReventlessLocal.register(DomainGraphQL_Server$ReventlessLocal.asInterface);
1562
1564
  if (Config.splitApi) {
1563
1565
  PlatformGraphQL_Server$ReventlessLocal.registerTypes(GraphQL_Stitcher$ReventlessCore.relayBaseTypes);
1564
1566
  }
@@ -3244,6 +3246,7 @@ function Make($star) {
3244
3246
  DomainGraphQL_Server$ReventlessLocal.registerTypes(GraphQL_Stitcher$ReventlessCore.relayBaseTypes);
3245
3247
  DomainGraphQL_Server$ReventlessLocal.registerQueries(GraphQL_Stitcher$ReventlessCore.relayBaseQueries, {});
3246
3248
  LocalUploadResolvers$ReventlessLocal.register(DomainGraphQL_Server$ReventlessLocal.asInterface);
3249
+ LocalGeocodeResolvers$ReventlessLocal.register(DomainGraphQL_Server$ReventlessLocal.asInterface);
3247
3250
  PlatformGraphQL_Server$ReventlessLocal.registerTypes(GraphQL_Stitcher$ReventlessCore.relayBaseTypes);
3248
3251
  currentDeployTarget.contents = "Domain";
3249
3252
  };
@@ -0,0 +1,63 @@
1
+ // Local geocode resolver — the *client* door of the geocoding capability (D9 half
2
+ // 2) on the dev platform. Registers `Query.geocode` on the domain server the same
3
+ // way `LocalUploadResolvers` registers `Upload_Presign`, which is the local analogue
4
+ // of adding the field to `domainBaseFragment` on AWS.
5
+ //
6
+ // This closes a dev-experience gap: before it, `config.geocoderEndpoint` was unset
7
+ // in local dev, so the map picker's search box did not render at all and the input
8
+ // was click-to-place only. With this door registered, address search works in dev.
9
+ //
10
+ // The dev platform provisions no real geocoder — `LocalCapabilities` keeps the
11
+ // *unattended* slice path at `Capabilities.none`, and the two doors are
12
+ // independent. This browser door is a deterministic stub: a non-empty query
13
+ // resolves to one candidate whose point is a stable function of the query text, so
14
+ // a search places a pin, in the same spot every time, with no network call or API
15
+ // key. The coordinates are placeholders — echoed back beside the query as the label
16
+ // — not a real geocode. An empty query yields no results, matching the AWS door and
17
+ // the browser's cleared-input case.
18
+
19
+ // A stable, in-range `(lat, lng)` derived from the query text: fold the character
20
+ // codes into one number and map it into safe coordinate bands. Deterministic, so a
21
+ // dev search is reproducible across reloads.
22
+ let stubPoint = (text: string): (float, float) => {
23
+ let sum = ref(0)
24
+ for i in 0 to text->String.length - 1 {
25
+ let code = text->String.codePointAt(i)->Option.getOr(0)
26
+ sum := sum.contents + code * (i + 1)
27
+ }
28
+ let n = sum.contents
29
+ let lat = mod(n, 120)->Int.toFloat -. 60.0 // −60 … 59
30
+ let lng = mod(n / 7, 240)->Int.toFloat -. 120.0 // −120 … 119
31
+ (lat, lng)
32
+ }
33
+
34
+ let register = (server: ReventlessGraphqlServer.GraphQL_ServerInstance.t): unit => {
35
+ let resolvers = Dict.make()
36
+ resolvers->Dict.set("geocode", async (_root, args, _ctx): JSON.t => {
37
+ let obj = args->JSON.Decode.object->Option.getOr(Dict.make())
38
+ let text =
39
+ obj
40
+ ->Dict.get("text")
41
+ ->Option.flatMap(JSON.Decode.string)
42
+ ->Option.getOr("")
43
+ ->String.trim
44
+ if text == "" {
45
+ JSON.Encode.array([])
46
+ } else {
47
+ let (lat, lng) = stubPoint(text)
48
+ let candidate =
49
+ Dict.fromArray([
50
+ ("label", JSON.Encode.string(text)),
51
+ ("lat", JSON.Encode.float(lat)),
52
+ ("lng", JSON.Encode.float(lng)),
53
+ ("relevance", JSON.Encode.float(1.0)),
54
+ ])->JSON.Encode.object
55
+ JSON.Encode.array([candidate])
56
+ }
57
+ })
58
+ server.registerTypes(~sdlTypes=ReventlessCore.Platform_AdminApi.geocodeTypes)
59
+ server.registerQueries(
60
+ ~sdlFields=ReventlessCore.Platform_AdminApi.geocodeQueryFields,
61
+ ~resolvers,
62
+ )
63
+ }
@@ -0,0 +1,58 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
4
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
5
+ import * as Platform_AdminApi$ReventlessCore from "@reventlessdev/reventless-core/src/admin/Platform_AdminApi.res.mjs";
6
+
7
+ function stubPoint(text) {
8
+ let sum = 0;
9
+ for (let i = 0, i_finish = text.length; i < i_finish; ++i) {
10
+ let code = Stdlib_Option.getOr(text.codePointAt(i), 0);
11
+ sum = sum + (code * (i + 1 | 0) | 0) | 0;
12
+ }
13
+ let n = sum;
14
+ let lat = n % 120 - 60.0;
15
+ let lng = (n / 7 | 0) % 240 - 120.0;
16
+ return [
17
+ lat,
18
+ lng
19
+ ];
20
+ }
21
+
22
+ function register(server) {
23
+ let resolvers = {};
24
+ resolvers["geocode"] = async (_root, args, _ctx) => {
25
+ let obj = Stdlib_Option.getOr(Stdlib_JSON.Decode.object(args), {});
26
+ let text = Stdlib_Option.getOr(Stdlib_Option.flatMap(obj["text"], Stdlib_JSON.Decode.string), "").trim();
27
+ if (text === "") {
28
+ return [];
29
+ }
30
+ let match = stubPoint(text);
31
+ return [Object.fromEntries([
32
+ [
33
+ "label",
34
+ text
35
+ ],
36
+ [
37
+ "lat",
38
+ match[0]
39
+ ],
40
+ [
41
+ "lng",
42
+ match[1]
43
+ ],
44
+ [
45
+ "relevance",
46
+ 1.0
47
+ ]
48
+ ])];
49
+ };
50
+ server.registerTypes(Platform_AdminApi$ReventlessCore.geocodeTypes);
51
+ server.registerQueries(Platform_AdminApi$ReventlessCore.geocodeQueryFields, resolvers);
52
+ }
53
+
54
+ export {
55
+ stubPoint,
56
+ register,
57
+ }
58
+ /* Platform_AdminApi-ReventlessCore Not a pure module */