@reventlessdev/reventless-local 3.0.0-alpha.211 → 3.0.0-alpha.213

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,24 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # 3.0.0-alpha.213 (2026-08-12)
7
+
8
+ ### Features
9
+
10
+ * **platform:** bake a curated component manifest as a static asset ([4f30265](https://github.com/ReventlessDev/reventless-core/commit/4f30265a51fc2c59e69afd8074cf1b2534c06378))
11
+ * **queries:** narrow owner-bearing reads to the caller ([ba9cc3d](https://github.com/ReventlessDev/reventless-core/commit/ba9cc3d58d7914a9e4827bda90a704a74b1b82dd))
12
+
13
+
14
+ # 3.0.0-alpha.212 (2026-08-11)
15
+
16
+ ### Bug Fixes
17
+
18
+ * **api:** one id contract across the read-side query doors ([c52fac2](https://github.com/ReventlessDev/reventless-core/commit/c52fac2bee87b3dd1fa33b4970a74f3cd3866280))
19
+ ### Features
20
+
21
+ * **api:** infer a queryable's key field and publish its provenance ([c835a42](https://github.com/ReventlessDev/reventless-core/commit/c835a42a0da07cdc4a3f010212e1f340a4a0ca27))
22
+
23
+
6
24
  # 3.0.0-alpha.211 (2026-08-10)
7
25
 
8
26
  **Note:** Version bump only for package @reventlessdev/reventless-local
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reventlessdev/reventless-local",
3
- "version": "3.0.0-alpha.211",
3
+ "version": "3.0.0-alpha.213",
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,19 +34,19 @@
34
34
  "graphql-yoga": "^5.21.0",
35
35
  "sury": "11.0.0-alpha.4",
36
36
  "ws": "^8.18.0",
37
- "@reventlessdev/rescript-effect": "0.1.0-alpha.32",
38
- "@reventlessdev/rescript-graphql-yoga": "1.0.0-alpha.26",
39
37
  "@reventlessdev/rescript-jest": "1.0.0-alpha.10",
40
38
  "@reventlessdev/rescript-mcp-sdk": "1.0.0-alpha.21",
41
- "@reventlessdev/rescript-node": "2.0.0-alpha.3",
39
+ "@reventlessdev/rescript-node": "2.0.0-alpha.4",
40
+ "@reventlessdev/rescript-effect": "0.1.0-alpha.32",
41
+ "@reventlessdev/rescript-graphql-yoga": "1.0.0-alpha.27",
42
42
  "@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.18",
43
- "@reventlessdev/reventless-graphql-server": "1.0.0-alpha.71",
44
- "@reventlessdev/reventless-gwt": "1.0.0-alpha.170",
45
- "@reventlessdev/reventless-core": "3.0.0-alpha.223",
46
- "@reventlessdev/reventless-infra": "3.0.0-alpha.133",
47
- "@reventlessdev/reventless-postgres": "3.0.0-alpha.87",
48
- "@reventlessdev/reventless-spec": "3.0.0-alpha.107",
49
- "@reventlessdev/reventless-seed": "1.0.0-alpha.10"
43
+ "@reventlessdev/reventless-core": "3.0.0-alpha.225",
44
+ "@reventlessdev/reventless-graphql-server": "1.0.0-alpha.73",
45
+ "@reventlessdev/reventless-gwt": "1.0.0-alpha.172",
46
+ "@reventlessdev/reventless-infra": "3.0.0-alpha.135",
47
+ "@reventlessdev/reventless-postgres": "3.0.0-alpha.89",
48
+ "@reventlessdev/reventless-seed": "1.0.0-alpha.11",
49
+ "@reventlessdev/reventless-spec": "3.0.0-alpha.109"
50
50
  },
51
51
  "devDependencies": {
52
52
  "rescript": "12.3.0",
@@ -0,0 +1,72 @@
1
+ // Writes the curated component manifest where the local host shell serves its
2
+ // static assets from, so `manifestUrl` discovery works in dev exactly as it does
3
+ // in a deployment.
4
+ //
5
+ // Locally there is no deploy and no bucket: `reventless-host-shell` serves its
6
+ // own `dist/` (that is where the shipped `config.json` and `ui-hints.json` come
7
+ // from), so that is where the file goes. Rewritten on every boot, which also
8
+ // makes it self-healing — a `pnpm install` that replaces the package directory
9
+ // costs one restart, not a debugging session.
10
+ //
11
+ // The curation itself lives in `ReventlessCore.Platform_BakedManifest`, shared
12
+ // with any other platform that bakes: only the destination is local.
13
+
14
+ let hostShellPackage = "@reventlessdev/reventless-host-shell"
15
+
16
+ let log = ReventlessCore.Logger.fromEnv()
17
+
18
+ // Resolved from the running project rather than from this framework module: the
19
+ // bundle is a deploy input the project names in its own package.json, and a
20
+ // framework-rooted lookup would skip that pin (the same distinction
21
+ // `Util_Bundle.resolvePackageRoot(~fromPulumiProject)` draws on AWS).
22
+ let hostShellDistDir = (): option<string> =>
23
+ try {
24
+ Some(
25
+ NodePath.dirname(
26
+ NodeModule.createRequire(NodeProcess.cwd() ++ "/index.js")->NodeModule.requireResolve(
27
+ hostShellPackage ++ "/package.json",
28
+ ),
29
+ ) ++ "/dist",
30
+ )
31
+ } catch {
32
+ | _ => None
33
+ }
34
+
35
+ let defaultKey = "component-manifest.json"
36
+
37
+ /**
38
+ A declared bake writes the file or fails loudly. Both failure modes it can hit
39
+ are the deployment's own mistake — a name that matches no component, or a shell
40
+ package that is not installed — and both produce the same symptom if swallowed:
41
+ a shop that renders nothing, with no line in the log saying why.
42
+ */
43
+ let emit = (
44
+ ~structures: array<(string, Reventless.Plugin.pluginStructure)>,
45
+ ~config: ReventlessInfra.Platform.bakedManifest,
46
+ ) => {
47
+ let selections =
48
+ config.components->Array.map((
49
+ s
50
+ ): ReventlessCore.Platform_BakedManifest.selection => {
51
+ plugin: s.plugin,
52
+ views: s.views,
53
+ commands: s.commands,
54
+ })
55
+ switch ReventlessCore.Platform_BakedManifest.curate(~structures, ~selections) {
56
+ | Error(e) => JsError.throwWithMessage(ReventlessCore.Platform_BakedManifest.describe(e))
57
+ | Ok(manifest) =>
58
+ switch hostShellDistDir() {
59
+ | None =>
60
+ JsError.throwWithMessage(
61
+ `baked manifest: cannot resolve ${hostShellPackage} from ${NodeProcess.cwd()} — ` ++
62
+ `the local shell serves the file from that package's dist/, so declaring a bake ` ++
63
+ `without the package installed would write nothing and render an empty shell.`,
64
+ )
65
+ | Some(dir) =>
66
+ let key = config.key->Option.getOr(defaultKey)
67
+ let path = NodePath.join([dir, key])
68
+ NodeFs.writeFileSync(path, JSON.stringify(manifest, ~space=2))
69
+ log.info(~comp="BakedManifest", `wrote ${key} for ${selections->Array.length->Int.toString} plugin(s): ${path}`)
70
+ }
71
+ }
72
+ }
@@ -0,0 +1,52 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Nodefs from "node:fs";
4
+ import * as Nodepath from "node:path";
5
+ import * as Nodemodule from "node:module";
6
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
7
+ import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
8
+ import * as Logger$ReventlessCore from "@reventlessdev/reventless-core/src/util/Logger.res.mjs";
9
+ import * as Platform_BakedManifest$ReventlessCore from "@reventlessdev/reventless-core/src/admin/Platform_BakedManifest.res.mjs";
10
+
11
+ let hostShellPackage = "@reventlessdev/reventless-host-shell";
12
+
13
+ let log = Logger$ReventlessCore.fromEnv();
14
+
15
+ function hostShellDistDir() {
16
+ try {
17
+ return Nodepath.dirname(Nodemodule.createRequire(process.cwd() + "/index.js").resolve(hostShellPackage + "/package.json")) + "/dist";
18
+ } catch (exn) {
19
+ return;
20
+ }
21
+ }
22
+
23
+ let defaultKey = "component-manifest.json";
24
+
25
+ function emit(structures, config) {
26
+ let selections = config.components.map(s => ({
27
+ plugin: s.plugin,
28
+ views: s.views,
29
+ commands: s.commands
30
+ }));
31
+ let e = Platform_BakedManifest$ReventlessCore.curate(structures, selections);
32
+ if (e.TAG !== "Ok") {
33
+ return Stdlib_JsError.throwWithMessage(Platform_BakedManifest$ReventlessCore.describe(e._0));
34
+ }
35
+ let dir = hostShellDistDir();
36
+ if (dir === undefined) {
37
+ return Stdlib_JsError.throwWithMessage(`baked manifest: cannot resolve ` + hostShellPackage + ` from ` + process.cwd() + ` — the local shell serves the file from that package's dist/, so declaring a bake without the package installed would write nothing and render an empty shell.`);
38
+ }
39
+ let key = Stdlib_Option.getOr(config.key, defaultKey);
40
+ let path = Nodepath.join(dir, key);
41
+ Nodefs.writeFileSync(path, JSON.stringify(e._0, undefined, 2), "utf8");
42
+ log.info("BakedManifest", undefined, `wrote ` + key + ` for ` + selections.length.toString() + ` plugin(s): ` + path);
43
+ }
44
+
45
+ export {
46
+ hostShellPackage,
47
+ log,
48
+ hostShellDistDir,
49
+ defaultKey,
50
+ emit,
51
+ }
52
+ /* log Not a pure module */
package/src/Platform.res CHANGED
@@ -874,6 +874,35 @@ module MakeWithConfig = (
874
874
  // In-memory store for plugin structures, keyed by plugin ID.
875
875
  let pluginStructuresStore: ref<dict<Reventless.Plugin.pluginStructure>> = ref(Dict.make())
876
876
 
877
+ // Bake the curated manifest from the plugin components directly rather than
878
+ // from `pluginStructuresStore`: a structure only exists once its Output
879
+ // resolves, so a synchronous read of that store at the end of `makePlatform`
880
+ // sees an empty dict. Emitting once the last plugin's structure has landed is
881
+ // both the earliest correct moment and the only one that cannot bake a
882
+ // half-registered platform.
883
+ let bakeManifest = (
884
+ ~pluginComponents: array<ReventlessCore.Plugin.component>,
885
+ ~config: ReventlessInfra.Platform.bakedManifest,
886
+ ) => {
887
+ let resolved: array<(string, Reventless.Plugin.pluginStructure)> = []
888
+ let expected = pluginComponents->Array.length
889
+ pluginComponents->Array.forEach(plugin => {
890
+ let outputs: ReventlessInfra.Plugin.outputs = plugin->ReventlessCore.Component.outputs
891
+ let _ =
892
+ (outputs.id, outputs.pluginStructure)
893
+ ->Pulumi.Output.all2
894
+ ->Pulumi.Output.apply(((id, ps)) => {
895
+ switch ps {
896
+ | Some(def) => resolved->Array.push((id, def))
897
+ | None => ()
898
+ }
899
+ if resolved->Array.length === expected {
900
+ BakedManifest.emit(~structures=resolved, ~config)
901
+ }
902
+ })
903
+ })
904
+ }
905
+
877
906
  // The object stores a plugin's fields declared, as `{plugin}.{store}` keys.
878
907
  let declaredStoresOf = (structure: Reventless.Plugin.pluginStructure) =>
879
908
  structure.requiredStores->Option.getOr([])
@@ -1399,7 +1428,35 @@ module MakeWithConfig = (
1399
1428
  }
1400
1429
  })
1401
1430
 
1402
- let makePlatform = (~version, ~plugins: array<module(PluginMaker)>) => {
1431
+ // In-memory ignores most of `~hostUiBundle` the host shell is served by
1432
+ // `vite dev` against the running in-process GraphQL server, not from a CDN,
1433
+ // including `uiHintsFile` (the AWS deploy writes it as a BucketObject; local
1434
+ // dev serves `public/ui-hints.json` directly). `bakedManifest` is the
1435
+ // exception: it is generated content, so there is no hand-authored file for
1436
+ // local dev to serve instead.
1437
+ type hostUiBundleConfig = {
1438
+ assetsDir?: string,
1439
+ bundleVersion?: string,
1440
+ uiHintsFile?: string,
1441
+ // Honoured here, unlike the rest: `makePlatform` writes the curated manifest
1442
+ // where the local host-shell serves its static assets from.
1443
+ bakedManifest?: ReventlessInfra.Platform.bakedManifest,
1444
+ // AWS host-ui deploy knobs — carried to satisfy the shared Platform.T
1445
+ // signature; the in-memory platform provisions no infrastructure and
1446
+ // ignores them.
1447
+ geocoderPlaceIndex?: ReventlessInfra.Platform.geocoderIndex,
1448
+ uploadBucket?: ReventlessInfra.Platform.objectStore,
1449
+ // Same terms: the AWS deploy writes these into the config.json it hosts, and
1450
+ // local dev has no config.json of its own to write — the host-shell package
1451
+ // serves `public/config.json`, which is where local turns a view mode on.
1452
+ viewModes?: array<ReventlessInfra.Platform.viewMode>,
1453
+ shellConfig?: dict<JSON.t>,
1454
+ }
1455
+ let makePlatform = (
1456
+ ~version,
1457
+ ~plugins: array<module(PluginMaker)>,
1458
+ ~hostUiBundle: option<hostUiBundleConfig>=?,
1459
+ ) => {
1403
1460
  log.info(~comp="Platform", `v${version}`)
1404
1461
  log.info(
1405
1462
  ~comp="Platform",
@@ -1549,6 +1606,14 @@ module MakeWithConfig = (
1549
1606
  connectPlugin(~pluginComponents=plugins)
1550
1607
  seedPluginStructuresStore(~pluginComponents=plugins)
1551
1608
  }
1609
+ // Not inside `seedAdminStores`: the bake describes what this deployment
1610
+ // offers, which is settled at composition and owes nothing to projection
1611
+ // catch-up. Every plugin passed to this call is connected by construction
1612
+ // locally, so there is no status or version dedup to apply.
1613
+ switch hostUiBundle->Option.flatMap(cfg => cfg.bakedManifest) {
1614
+ | None => ()
1615
+ | Some(cfg) => bakeManifest(~pluginComponents=plugins, ~config=cfg)
1616
+ }
1552
1617
  switch (projectionCatchup, pgProjectionCatchup) {
1553
1618
  | (Some((db, upperBound, dcbUpperBound)), _) =>
1554
1619
  let _ =
@@ -2031,25 +2096,6 @@ module MakeWithConfig = (
2031
2096
 
2032
2097
  }
2033
2098
 
2034
- // In-memory ignores `~hostUiBundle` — the host shell is served by `vite dev`
2035
- // against the running in-process GraphQL server, not from a CDN — including
2036
- // `uiHintsFile` (the AWS deploy writes it as a BucketObject; local dev serves
2037
- // `public/ui-hints.json` directly).
2038
- type hostUiBundleConfig = {
2039
- assetsDir?: string,
2040
- bundleVersion?: string,
2041
- uiHintsFile?: string,
2042
- // AWS host-ui deploy knobs — carried to satisfy the shared Platform.T
2043
- // signature; the in-memory platform provisions no infrastructure and
2044
- // ignores them.
2045
- geocoderPlaceIndex?: ReventlessInfra.Platform.geocoderIndex,
2046
- uploadBucket?: ReventlessInfra.Platform.objectStore,
2047
- // Same terms: the AWS deploy writes these into the config.json it hosts, and
2048
- // local dev has no config.json of its own to write — the host-shell package
2049
- // serves `public/config.json`, which is where local turns a view mode on.
2050
- viewModes?: array<ReventlessInfra.Platform.viewMode>,
2051
- shellConfig?: dict<JSON.t>,
2052
- }
2053
2099
  let deployPlatform = (
2054
2100
  ~version,
2055
2101
  ~hostUiBundle as _: option<hostUiBundleConfig>=?,
@@ -31,6 +31,7 @@ import * as BackendState$ReventlessLocal from "./adapter/BackendState.res.mjs";
31
31
  import * as ComponentType$ReventlessCore from "@reventlessdev/reventless-core/src/ComponentType.res.mjs";
32
32
  import * as SqliteDriver$ReventlessLocal from "./adapter/SqliteDriver.res.mjs";
33
33
  import * as Task_Builder$ReventlessLocal from "./components/Task_Builder.res.mjs";
34
+ import * as BakedManifest$ReventlessLocal from "./BakedManifest.res.mjs";
34
35
  import * as Platform_Admin$ReventlessCore from "@reventlessdev/reventless-core/src/admin/Platform_Admin.res.mjs";
35
36
  import * as PluginBehavior$ReventlessCore from "@reventlessdev/reventless-core/src/plugin/lifecycle/PluginBehavior.res.mjs";
36
37
  import * as Plugin_Helpers$ReventlessCore from "@reventlessdev/reventless-core/src/plugin/component/Plugin_Helpers.res.mjs";
@@ -832,6 +833,28 @@ function MakeWithConfig(Config) {
832
833
  let pluginStructuresStore = {
833
834
  contents: {}
834
835
  };
836
+ let bakeManifest = (pluginComponents, config) => {
837
+ let resolved = [];
838
+ let expected = pluginComponents.length;
839
+ pluginComponents.forEach(plugin => {
840
+ let outputs = Component$ReventlessCore.outputs(plugin);
841
+ Pulumi.all([
842
+ outputs.id,
843
+ outputs.pluginStructure
844
+ ]).apply(param => {
845
+ let ps = param[1];
846
+ if (ps !== undefined) {
847
+ resolved.push([
848
+ param[0],
849
+ ps
850
+ ]);
851
+ }
852
+ if (resolved.length === expected) {
853
+ return BakedManifest$ReventlessLocal.emit(resolved, config);
854
+ }
855
+ });
856
+ });
857
+ };
835
858
  let seedPluginStructuresStore = pluginComponents => {
836
859
  pluginComponents.forEach(plugin => {
837
860
  let outputs = Component$ReventlessCore.outputs(plugin);
@@ -1183,7 +1206,7 @@ function MakeWithConfig(Config) {
1183
1206
  }
1184
1207
  });
1185
1208
  };
1186
- let makePlatform = (version, plugins) => {
1209
+ let makePlatform = (version, plugins, hostUiBundle) => {
1187
1210
  log.info("Platform", undefined, `v` + version);
1188
1211
  log.info("Platform", undefined, `silent: ` + Stdlib_Bool.toString(Config.silent) + `, splitApi: ` + Stdlib_Bool.toString(Config.splitApi) + `, cloner: ` + Stdlib_Bool.toString(Config.cloner));
1189
1212
  let match = Config.backend;
@@ -1262,6 +1285,10 @@ function MakeWithConfig(Config) {
1262
1285
  adminResources: []
1263
1286
  });
1264
1287
  subscribeToPluginEvents();
1288
+ let cfg = Stdlib_Option.flatMap(hostUiBundle, cfg => cfg.bakedManifest);
1289
+ if (cfg !== undefined) {
1290
+ bakeManifest(plugins$1, cfg);
1291
+ }
1265
1292
  if (projectionCatchup !== undefined) {
1266
1293
  Stdlib_Promise.$$catch(ProjectionCheckpoint$ReventlessLocal.startupCatchup(projectionCatchup[0], projectionCatchup[1], projectionCatchup[2], () => Bus.projectionCatchupHandlers()), e => {
1267
1294
  console.error("[Platform] projection catch-up failed:", e);
@@ -2529,6 +2556,28 @@ function Make($star) {
2529
2556
  let pluginStructuresStore = {
2530
2557
  contents: {}
2531
2558
  };
2559
+ let bakeManifest = (pluginComponents, config) => {
2560
+ let resolved = [];
2561
+ let expected = pluginComponents.length;
2562
+ pluginComponents.forEach(plugin => {
2563
+ let outputs = Component$ReventlessCore.outputs(plugin);
2564
+ Pulumi.all([
2565
+ outputs.id,
2566
+ outputs.pluginStructure
2567
+ ]).apply(param => {
2568
+ let ps = param[1];
2569
+ if (ps !== undefined) {
2570
+ resolved.push([
2571
+ param[0],
2572
+ ps
2573
+ ]);
2574
+ }
2575
+ if (resolved.length === expected) {
2576
+ return BakedManifest$ReventlessLocal.emit(resolved, config);
2577
+ }
2578
+ });
2579
+ });
2580
+ };
2532
2581
  let seedPluginStructuresStore = pluginComponents => {
2533
2582
  pluginComponents.forEach(plugin => {
2534
2583
  let outputs = Component$ReventlessCore.outputs(plugin);
@@ -2876,7 +2925,7 @@ function Make($star) {
2876
2925
  }
2877
2926
  });
2878
2927
  };
2879
- let makePlatform = (version, plugins) => {
2928
+ let makePlatform = (version, plugins, hostUiBundle) => {
2880
2929
  log.info("Platform", undefined, `v` + version);
2881
2930
  log.info("Platform", undefined, `silent: ` + Stdlib_Bool.toString(false) + `, splitApi: ` + Stdlib_Bool.toString(true) + `, cloner: ` + Stdlib_Bool.toString(false));
2882
2931
  let tmp;
@@ -2954,6 +3003,10 @@ function Make($star) {
2954
3003
  adminResources: []
2955
3004
  });
2956
3005
  subscribeToPluginEvents();
3006
+ let cfg = Stdlib_Option.flatMap(hostUiBundle, cfg => cfg.bakedManifest);
3007
+ if (cfg !== undefined) {
3008
+ bakeManifest(plugins$1, cfg);
3009
+ }
2957
3010
  if (projectionCatchup !== undefined) {
2958
3011
  Stdlib_Promise.$$catch(ProjectionCheckpoint$ReventlessLocal.startupCatchup(projectionCatchup[0], projectionCatchup[1], projectionCatchup[2], () => Bus.projectionCatchupHandlers()), e => {
2959
3012
  console.error("[Platform] projection catch-up failed:", e);
@@ -257,26 +257,14 @@ type resolverFn = YG.resolverFn
257
257
 
258
258
  // -- Relay Global ID encoding/decoding -------------------------------------
259
259
 
260
- @val external btoa: string => string = "btoa"
261
- @val external atob: string => string = "atob"
262
-
260
+ // The encoding itself lives in `ReventlessCore.Api_Ids` — one definition shared
261
+ // with the AWS adapter and with the doors that accept either id form. Kept as
262
+ // named bindings here because the resolver wiring below and the `relay` record
263
+ // passed to QueryDbResolvers_GraphQL both reference them.
263
264
  let encodeGlobalId = (~typeName: string, ~localId: string): string =>
264
- btoa(`${typeName}:${localId}`)
265
+ ReventlessCore.Api_Ids.encode(~typeName, ~localId)
265
266
 
266
- let decodeGlobalId = (globalId: string): option<(string, string)> =>
267
- try {
268
- let decoded = atob(globalId)
269
- let idx = decoded->String.indexOf(":")
270
- if idx > 0 {
271
- let typeName = decoded->String.slice(~start=0, ~end=idx)
272
- let localId = decoded->String.slice(~start=idx + 1, ~end=decoded->String.length)
273
- Some((typeName, localId))
274
- } else {
275
- None
276
- }
277
- } catch {
278
- | _ => None
279
- }
267
+ let decodeGlobalId = ReventlessCore.Api_Ids.decode
280
268
 
281
269
  // -- Scoped registry ---------------------------------------------------------
282
270
  // Mirrors the AWS plugin=source-API, platform=merged-API model: every
@@ -15,6 +15,7 @@ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js
15
15
  import * as Identity$Reventless from "@reventlessdev/reventless-spec/src/types/Identity.res.mjs";
16
16
  import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
17
17
  import * as Logger$ReventlessCore from "@reventlessdev/reventless-core/src/util/Logger.res.mjs";
18
+ import * as Api_Ids$ReventlessCore from "@reventlessdev/reventless-core/src/components/Api/Api_Ids.res.mjs";
18
19
  import * as LocalAuth$ReventlessLocal from "./Auth/LocalAuth.res.mjs";
19
20
  import * as GraphQL_Stitcher$ReventlessCore from "@reventlessdev/reventless-core/src/components/Api/GraphQL_Stitcher.res.mjs";
20
21
  import * as LocalObjectStore$ReventlessLocal from "./ObjectStore/LocalObjectStore.res.mjs";
@@ -193,27 +194,7 @@ function _dispatch(req, res, yoga, getSdl) {
193
194
  });
194
195
  }
195
196
 
196
- function encodeGlobalId(typeName, localId) {
197
- return btoa(typeName + `:` + localId);
198
- }
199
-
200
- function decodeGlobalId(globalId) {
201
- try {
202
- let decoded = atob(globalId);
203
- let idx = decoded.indexOf(":");
204
- if (idx <= 0) {
205
- return;
206
- }
207
- let typeName = decoded.slice(0, idx);
208
- let localId = decoded.slice(idx + 1 | 0, decoded.length);
209
- return [
210
- typeName,
211
- localId
212
- ];
213
- } catch (exn) {
214
- return;
215
- }
216
- }
197
+ let encodeGlobalId = Api_Ids$ReventlessCore.encode;
217
198
 
218
199
  let platformScope = "platform";
219
200
 
@@ -368,7 +349,7 @@ function buildNodeResolver() {
368
349
  }
369
350
  let resolver = async (_root, args, _ctx) => {
370
351
  let id = Stdlib_Option.getOr(Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_JSON.Decode.object(args), d => d["id"]), Stdlib_JSON.Decode.string), "");
371
- let match = decodeGlobalId(id);
352
+ let match = Api_Ids$ReventlessCore.decode(id);
372
353
  if (match === undefined) {
373
354
  return null;
374
355
  }
@@ -738,6 +719,8 @@ let YG;
738
719
 
739
720
  let buildAuthContext = Auth_GraphqlContext$ReventlessLocal.buildAuthContext;
740
721
 
722
+ let decodeGlobalId = Api_Ids$ReventlessCore.decode;
723
+
741
724
  export {
742
725
  YG,
743
726
  log,
@@ -132,6 +132,7 @@ module type T = {
132
132
  ~argsDict: dict<JSON.t>,
133
133
  ~capability: ReventlessCore.GraphQL_FragmentGenerator.serverCapability,
134
134
  ~labelField: string,
135
+ ~ownerScope: (string, string)=?,
135
136
  ) => option<JSON.t>,
136
137
  ) => unit
137
138
  let getQueryDbListPage: string => option<
@@ -139,6 +140,7 @@ module type T = {
139
140
  ~argsDict: dict<JSON.t>,
140
141
  ~capability: ReventlessCore.GraphQL_FragmentGenerator.serverCapability,
141
142
  ~labelField: string,
143
+ ~ownerScope: (string, string)=?,
142
144
  ) => option<JSON.t>,
143
145
  >
144
146
 
@@ -235,6 +237,7 @@ module Impl = (C: BusConfig): T => {
235
237
  ~argsDict: dict<JSON.t>,
236
238
  ~capability: ReventlessCore.GraphQL_FragmentGenerator.serverCapability,
237
239
  ~labelField: string,
240
+ ~ownerScope: (string, string)=?,
238
241
  ) => option<JSON.t>,
239
242
  >,
240
243
  > = ref(Dict.make())