@reventlessdev/reventless-aws 3.0.0-alpha.318 → 3.0.0-alpha.319
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,21 @@
|
|
|
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.319 (2026-08-22)
|
|
7
|
+
|
|
8
|
+
* feat(core)!: a slice that has given up says so ([f5559ab](https://github.com/ReventlessDev/reventless-core/commit/f5559abede3a9cf2c9a48aadc69a666c46cc75bf))
|
|
9
|
+
|
|
10
|
+
### BREAKING CHANGES
|
|
11
|
+
|
|
12
|
+
* `onExhausted` is required on the Translation and Automation
|
|
13
|
+
module types. ReScript has no optional module-type fields, so the alternative
|
|
14
|
+
was a PPX-injected default — and defaulting this one to silence is the bug.
|
|
15
|
+
A slice now states what abandonment means for its domain, `None` included.
|
|
16
|
+
GeocodeCustomerAddress answers with MarkAddressUnresolvable; the others say
|
|
17
|
+
nothing, on purpose.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
6
21
|
# 3.0.0-alpha.318 (2026-08-21)
|
|
7
22
|
|
|
8
23
|
### 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.319",
|
|
4
4
|
"description": "AWS adapters for Reventless",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"dependencies": {
|
|
@@ -15,15 +15,15 @@
|
|
|
15
15
|
"@reventlessdev/rescript-aws-sdk": "3.0.0-alpha.12",
|
|
16
16
|
"@reventlessdev/rescript-effect": "0.1.0-alpha.32",
|
|
17
17
|
"@reventlessdev/rescript-jest": "1.0.0-alpha.10",
|
|
18
|
-
"@reventlessdev/rescript-node": "2.0.0-alpha.8",
|
|
19
18
|
"@reventlessdev/rescript-pulumi-aws": "3.0.0-alpha.2",
|
|
19
|
+
"@reventlessdev/rescript-node": "2.0.0-alpha.8",
|
|
20
20
|
"@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.19",
|
|
21
|
-
"@reventlessdev/reventless-core": "3.0.0-alpha.
|
|
22
|
-
"@reventlessdev/reventless-infra": "3.0.0-alpha.149",
|
|
21
|
+
"@reventlessdev/reventless-core": "3.0.0-alpha.247",
|
|
23
22
|
"@reventlessdev/rescript-uuid": "2.0.0-alpha.0",
|
|
23
|
+
"@reventlessdev/reventless-infra": "3.0.0-alpha.150",
|
|
24
24
|
"@reventlessdev/reventless-interop": "3.0.0-alpha.33",
|
|
25
|
-
"@reventlessdev/reventless-spec": "3.0.0-alpha.
|
|
26
|
-
"@reventlessdev/reventless-postgres": "3.0.0-alpha.
|
|
25
|
+
"@reventlessdev/reventless-spec": "3.0.0-alpha.122",
|
|
26
|
+
"@reventlessdev/reventless-postgres": "3.0.0-alpha.111"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"rescript": "12.3.0",
|
|
@@ -148,9 +148,12 @@ let makeSyncTodoItems = (
|
|
|
148
148
|
// by definition no fresher.
|
|
149
149
|
//
|
|
150
150
|
// Only `Pending` and `Failed` are read. `Completed` rows are the bulk of a
|
|
151
|
-
// mature table and are never actionable
|
|
152
|
-
//
|
|
153
|
-
//
|
|
151
|
+
// mature table and are never actionable, and neither are `Abandoned` ones — a
|
|
152
|
+
// row whose retry budget is spent is terminal, so it is left in the table rather
|
|
153
|
+
// than carried into memory. That the status says so is what lets this filter
|
|
154
|
+
// decide it: `maxRetries` is Spec-level and still not known here, and before the
|
|
155
|
+
// status existed an exhausted row had to be loaded and then filtered out by
|
|
156
|
+
// `phase2`.
|
|
154
157
|
let makeLoadTodoItems = (
|
|
155
158
|
~queryDbTableName: string,
|
|
156
159
|
~todoItems: dict<'row>,
|
|
@@ -612,3 +612,169 @@ describe("owner scoping", () => {
|
|
|
612
612
|
expect(r->ids)->toEqual(["p-1", "p-3"])
|
|
613
613
|
})
|
|
614
614
|
})
|
|
615
|
+
|
|
616
|
+
// ── nested union member types ───────────────────────────────────────────────
|
|
617
|
+
//
|
|
618
|
+
// The `__typename` a union member is resolved from is written into the stored
|
|
619
|
+
// row, above the DynamoDB/Postgres branch (`withUnionMemberTypes` wraps the
|
|
620
|
+
// result of `makeQueryDbOps`), and this resolver stamps only the *top level* of
|
|
621
|
+
// a `node` answer. So the Postgres door's whole claim is that it hands a nested
|
|
622
|
+
// union back exactly as stored — which no test made, and which no deploy can
|
|
623
|
+
// make either: nothing runs the Postgres backend, so this door cannot be called
|
|
624
|
+
// against a deployment the way the AppSync ones were.
|
|
625
|
+
//
|
|
626
|
+
// Losing the nested key is not visible as an error: the member resolves to null
|
|
627
|
+
// and the null takes its non-nullable parent, so rows leave the answer.
|
|
628
|
+
|
|
629
|
+
let geoRow = (id, status) => {
|
|
630
|
+
let geo = Dict.make()
|
|
631
|
+
geo->Dict.set("__typename", JSON.Encode.string("GeolocationLocated"))
|
|
632
|
+
geo->Dict.set("lat", JSON.Encode.float(48.2082))
|
|
633
|
+
geo->Dict.set("lng", JSON.Encode.float(16.3738))
|
|
634
|
+
let o = Dict.make()
|
|
635
|
+
o->Dict.set("id", JSON.Encode.string(id))
|
|
636
|
+
o->Dict.set("status", JSON.Encode.string(status))
|
|
637
|
+
o->Dict.set("name", JSON.Encode.string("Geo " ++ id))
|
|
638
|
+
o->Dict.set("owner", JSON.Encode.string("u-a"))
|
|
639
|
+
o->Dict.set("geolocation", JSON.Encode.object(geo))
|
|
640
|
+
JSON.Encode.object(o)
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
let geoStore = Dict.fromArray([("g-1", geoRow("g-1", "active")), ("g-2", geoRow("g-2", "active"))])
|
|
644
|
+
let geoItems = () => geoStore->Dict.valuesToArray
|
|
645
|
+
|
|
646
|
+
let geoConnection = (): JSON.t =>
|
|
647
|
+
JSON.Encode.object(
|
|
648
|
+
Dict.fromArray([
|
|
649
|
+
(
|
|
650
|
+
"edges",
|
|
651
|
+
JSON.Encode.array(
|
|
652
|
+
geoItems()->Array.map(item =>
|
|
653
|
+
JSON.Encode.object(
|
|
654
|
+
Dict.fromArray([("cursor", JSON.Encode.string("c")), ("node", item)]),
|
|
655
|
+
)
|
|
656
|
+
),
|
|
657
|
+
),
|
|
658
|
+
),
|
|
659
|
+
]),
|
|
660
|
+
)
|
|
661
|
+
|
|
662
|
+
let geoBinding = (): PgQueryResolver_Lambda.binding => {
|
|
663
|
+
ops: {
|
|
664
|
+
...ops,
|
|
665
|
+
load: async id => Ok(geoStore->Dict.get(id)->Option.mapOr([], i => [i])),
|
|
666
|
+
},
|
|
667
|
+
pushdowns: {
|
|
668
|
+
indexLookup: async (~readModelName as _, _field, _value) => geoItems(),
|
|
669
|
+
byIds: async (~readModelName as _, ids) => ids->Array.filterMap(id => geoStore->Dict.get(id)),
|
|
670
|
+
listPage: async (
|
|
671
|
+
~readModelName as _,
|
|
672
|
+
~argsDict as _,
|
|
673
|
+
~capability as _,
|
|
674
|
+
~labelField as _,
|
|
675
|
+
~ownerScope as _=?,
|
|
676
|
+
~retiredScope as _=?,
|
|
677
|
+
) => Some(geoConnection()),
|
|
678
|
+
itemsPage: async (
|
|
679
|
+
~readModelName as _,
|
|
680
|
+
~subIdField as _,
|
|
681
|
+
~id as _,
|
|
682
|
+
~argsDict as _,
|
|
683
|
+
~ownerScope as _=?,
|
|
684
|
+
~retiredScope as _=?,
|
|
685
|
+
) => geoConnection(),
|
|
686
|
+
scanAll: async (~readModelName as _) => geoItems(),
|
|
687
|
+
},
|
|
688
|
+
indexes: [
|
|
689
|
+
{index: "byStatus", type_: "S", idField: "status", projectionType: Reventless.ReadModel.ALL},
|
|
690
|
+
],
|
|
691
|
+
subIdField: Some("lineNo"),
|
|
692
|
+
capability,
|
|
693
|
+
labelField: "name",
|
|
694
|
+
includeIdParam: true,
|
|
695
|
+
authorization: Reventless.Authorization.AllowAnonymous,
|
|
696
|
+
ownerField: None,
|
|
697
|
+
retiredField: None,
|
|
698
|
+
retiredValues: None,
|
|
699
|
+
namedWhenRetired: false,
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// The member type of the first row a door answers with, whatever shape it took.
|
|
703
|
+
let memberOf = (r: JSON.t): option<string> => {
|
|
704
|
+
let fromRow = row =>
|
|
705
|
+
row->field("geolocation")->Option.flatMap(g => g->str("__typename"))
|
|
706
|
+
switch r->JSON.Decode.array {
|
|
707
|
+
| Some(rows) => rows->Array.get(0)->Option.flatMap(fromRow)
|
|
708
|
+
| None =>
|
|
709
|
+
switch r->field("edges")->Option.flatMap(JSON.Decode.array) {
|
|
710
|
+
| Some(edges) => edges->Array.get(0)->Option.flatMap(e => e->field("node"))->Option.flatMap(fromRow)
|
|
711
|
+
| None => fromRow(r)
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
describe("PgQueryResolver — a nested union survives every door", () => {
|
|
717
|
+
let doors = [
|
|
718
|
+
("getById", mkPayload(~kind="getById", ~args=objArgs([("id", JSON.Encode.string("g-1"))]), ())),
|
|
719
|
+
(
|
|
720
|
+
"byIds",
|
|
721
|
+
mkPayload(~kind="byIds", ~args=objArgs([("ids", JSON.Encode.array([JSON.Encode.string("g-1")]))]), ()),
|
|
722
|
+
),
|
|
723
|
+
(
|
|
724
|
+
"index",
|
|
725
|
+
mkPayload(~kind="index", ~index="byStatus", ~args=objArgs([("byStatus", JSON.Encode.string("active"))]), ()),
|
|
726
|
+
),
|
|
727
|
+
("list", mkPayload(~kind="list", ())),
|
|
728
|
+
("items", mkPayload(~kind="items", ~args=objArgs([("id", JSON.Encode.string("g-1"))]), ())),
|
|
729
|
+
// The cross-table doors answer with the *target's* rows, so a union on the
|
|
730
|
+
// target travels through a field on some other view's type.
|
|
731
|
+
(
|
|
732
|
+
"resolveOne",
|
|
733
|
+
{
|
|
734
|
+
readModelName: "Geos",
|
|
735
|
+
kind: "resolveOne",
|
|
736
|
+
target: "Geos",
|
|
737
|
+
source: objArgs([("ref", JSON.Encode.string("g-1"))]),
|
|
738
|
+
sourceIdField: "ref",
|
|
739
|
+
multi: false,
|
|
740
|
+
arguments: objArgs([]),
|
|
741
|
+
identity: Reventless.Identity.anonymous,
|
|
742
|
+
},
|
|
743
|
+
),
|
|
744
|
+
(
|
|
745
|
+
"resolveMany",
|
|
746
|
+
{
|
|
747
|
+
readModelName: "Geos",
|
|
748
|
+
kind: "resolveMany",
|
|
749
|
+
target: "Geos",
|
|
750
|
+
source: objArgs([("refs", JSON.Encode.array([JSON.Encode.string("g-1")]))]),
|
|
751
|
+
sourceIdsField: "refs",
|
|
752
|
+
arguments: objArgs([]),
|
|
753
|
+
identity: Reventless.Identity.anonymous,
|
|
754
|
+
},
|
|
755
|
+
),
|
|
756
|
+
]
|
|
757
|
+
|
|
758
|
+
doors->Array.forEach(((label, payload)) =>
|
|
759
|
+
testPromise(label ++ " hands the member type back as stored", async () => {
|
|
760
|
+
let r = await PgQueryResolver_Lambda.dispatch(~binding=geoBinding(), ~payload)
|
|
761
|
+
expect(memberOf(r))->toEqual(Some("GeolocationLocated"))
|
|
762
|
+
})
|
|
763
|
+
)
|
|
764
|
+
|
|
765
|
+
// `node` is the one door that writes a `__typename` of its own, at the top
|
|
766
|
+
// level. It must not reach down and overwrite the member's.
|
|
767
|
+
testPromise("node stamps the top level without disturbing the member", async () => {
|
|
768
|
+
PgQueryResolver_Lambda.register(~readModelName="Geos", geoBinding())
|
|
769
|
+
PgQueryResolver_Lambda.registerNodeType(~typeName="Geo", ~readModelName="Geos")
|
|
770
|
+
let payload: PgQueryResolver_Lambda.payload = {
|
|
771
|
+
readModelName: "",
|
|
772
|
+
kind: "node",
|
|
773
|
+
arguments: objArgs([("id", JSON.Encode.string(btoa("Geo:g-1")))]),
|
|
774
|
+
identity: Reventless.Identity.anonymous,
|
|
775
|
+
}
|
|
776
|
+
let r = await PgQueryResolver_Lambda.handler(payload, Obj.magic(Nullable.null))
|
|
777
|
+
expect(r->str("__typename"))->toEqual(Some("Geo"))
|
|
778
|
+
expect(memberOf(r))->toEqual(Some("GeolocationLocated"))
|
|
779
|
+
})
|
|
780
|
+
})
|
|
@@ -629,6 +629,196 @@ globalThis.describe("owner scoping", () => {
|
|
|
629
629
|
});
|
|
630
630
|
});
|
|
631
631
|
|
|
632
|
+
function geoRow(id, status) {
|
|
633
|
+
let geo = {};
|
|
634
|
+
geo["__typename"] = "GeolocationLocated";
|
|
635
|
+
geo["lat"] = 48.2082;
|
|
636
|
+
geo["lng"] = 16.3738;
|
|
637
|
+
let o = {};
|
|
638
|
+
o["id"] = id;
|
|
639
|
+
o["status"] = status;
|
|
640
|
+
o["name"] = "Geo " + id;
|
|
641
|
+
o["owner"] = "u-a";
|
|
642
|
+
o["geolocation"] = geo;
|
|
643
|
+
return o;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
let geoStore = Object.fromEntries([
|
|
647
|
+
[
|
|
648
|
+
"g-1",
|
|
649
|
+
geoRow("g-1", "active")
|
|
650
|
+
],
|
|
651
|
+
[
|
|
652
|
+
"g-2",
|
|
653
|
+
geoRow("g-2", "active")
|
|
654
|
+
]
|
|
655
|
+
]);
|
|
656
|
+
|
|
657
|
+
function geoItems() {
|
|
658
|
+
return Object.values(geoStore);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
function geoConnection() {
|
|
662
|
+
return Object.fromEntries([[
|
|
663
|
+
"edges",
|
|
664
|
+
Object.values(geoStore).map(item => Object.fromEntries([
|
|
665
|
+
[
|
|
666
|
+
"cursor",
|
|
667
|
+
"c"
|
|
668
|
+
],
|
|
669
|
+
[
|
|
670
|
+
"node",
|
|
671
|
+
item
|
|
672
|
+
]
|
|
673
|
+
]))
|
|
674
|
+
]]);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
function geoBinding() {
|
|
678
|
+
return {
|
|
679
|
+
ops: {
|
|
680
|
+
load: async id => ({
|
|
681
|
+
TAG: "Ok",
|
|
682
|
+
_0: Stdlib_Option.mapOr(geoStore[id], [], i => [i])
|
|
683
|
+
}),
|
|
684
|
+
loadStream: 0,
|
|
685
|
+
save: 0,
|
|
686
|
+
saveBatch: 0,
|
|
687
|
+
count: 0,
|
|
688
|
+
delete: 0,
|
|
689
|
+
deleteBatch: 0
|
|
690
|
+
},
|
|
691
|
+
pushdowns: {
|
|
692
|
+
indexLookup: async (param, _field, _value) => Object.values(geoStore),
|
|
693
|
+
byIds: async (param, ids) => Stdlib_Array.filterMap(ids, id => geoStore[id]),
|
|
694
|
+
listPage: async (param, param$1, param$2, param$3, param$4, param$5) => geoConnection(),
|
|
695
|
+
itemsPage: async (param, param$1, param$2, param$3, param$4, param$5) => geoConnection(),
|
|
696
|
+
scanAll: async param => Object.values(geoStore)
|
|
697
|
+
},
|
|
698
|
+
indexes: [{
|
|
699
|
+
index: "byStatus",
|
|
700
|
+
type_: "S",
|
|
701
|
+
idField: "status",
|
|
702
|
+
projectionType: "ALL"
|
|
703
|
+
}],
|
|
704
|
+
subIdField: "lineNo",
|
|
705
|
+
capability: capability,
|
|
706
|
+
labelField: "name",
|
|
707
|
+
includeIdParam: true,
|
|
708
|
+
authorization: "AllowAnonymous",
|
|
709
|
+
ownerField: undefined,
|
|
710
|
+
retiredField: undefined,
|
|
711
|
+
retiredValues: undefined,
|
|
712
|
+
namedWhenRetired: false
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
function memberOf(r) {
|
|
717
|
+
let fromRow = row => Stdlib_Option.flatMap(field(row, "geolocation"), g => str(g, "__typename"));
|
|
718
|
+
let rows = Stdlib_JSON.Decode.array(r);
|
|
719
|
+
if (rows !== undefined) {
|
|
720
|
+
return Stdlib_Option.flatMap(rows[0], fromRow);
|
|
721
|
+
}
|
|
722
|
+
let edges = Stdlib_Option.flatMap(field(r, "edges"), Stdlib_JSON.Decode.array);
|
|
723
|
+
if (edges !== undefined) {
|
|
724
|
+
return Stdlib_Option.flatMap(Stdlib_Option.flatMap(edges[0], e => field(e, "node")), fromRow);
|
|
725
|
+
} else {
|
|
726
|
+
return fromRow(r);
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
globalThis.describe("PgQueryResolver — a nested union survives every door", () => {
|
|
731
|
+
let doors = [
|
|
732
|
+
[
|
|
733
|
+
"getById",
|
|
734
|
+
mkPayload("getById", undefined, Object.fromEntries([[
|
|
735
|
+
"id",
|
|
736
|
+
"g-1"
|
|
737
|
+
]]), undefined, undefined)
|
|
738
|
+
],
|
|
739
|
+
[
|
|
740
|
+
"byIds",
|
|
741
|
+
mkPayload("byIds", undefined, Object.fromEntries([[
|
|
742
|
+
"ids",
|
|
743
|
+
["g-1"]
|
|
744
|
+
]]), undefined, undefined)
|
|
745
|
+
],
|
|
746
|
+
[
|
|
747
|
+
"index",
|
|
748
|
+
mkPayload("index", "byStatus", Object.fromEntries([[
|
|
749
|
+
"byStatus",
|
|
750
|
+
"active"
|
|
751
|
+
]]), undefined, undefined)
|
|
752
|
+
],
|
|
753
|
+
[
|
|
754
|
+
"list",
|
|
755
|
+
mkPayload("list", undefined, undefined, undefined, undefined)
|
|
756
|
+
],
|
|
757
|
+
[
|
|
758
|
+
"items",
|
|
759
|
+
mkPayload("items", undefined, Object.fromEntries([[
|
|
760
|
+
"id",
|
|
761
|
+
"g-1"
|
|
762
|
+
]]), undefined, undefined)
|
|
763
|
+
],
|
|
764
|
+
[
|
|
765
|
+
"resolveOne",
|
|
766
|
+
{
|
|
767
|
+
readModelName: "Geos",
|
|
768
|
+
kind: "resolveOne",
|
|
769
|
+
target: "Geos",
|
|
770
|
+
source: Object.fromEntries([[
|
|
771
|
+
"ref",
|
|
772
|
+
"g-1"
|
|
773
|
+
]]),
|
|
774
|
+
sourceIdField: "ref",
|
|
775
|
+
multi: false,
|
|
776
|
+
arguments: Object.fromEntries([]),
|
|
777
|
+
identity: Identity$Reventless.anonymous
|
|
778
|
+
}
|
|
779
|
+
],
|
|
780
|
+
[
|
|
781
|
+
"resolveMany",
|
|
782
|
+
{
|
|
783
|
+
readModelName: "Geos",
|
|
784
|
+
kind: "resolveMany",
|
|
785
|
+
target: "Geos",
|
|
786
|
+
source: Object.fromEntries([[
|
|
787
|
+
"refs",
|
|
788
|
+
["g-1"]
|
|
789
|
+
]]),
|
|
790
|
+
sourceIdsField: "refs",
|
|
791
|
+
arguments: Object.fromEntries([]),
|
|
792
|
+
identity: Identity$Reventless.anonymous
|
|
793
|
+
}
|
|
794
|
+
]
|
|
795
|
+
];
|
|
796
|
+
doors.forEach(param => {
|
|
797
|
+
let payload = param[1];
|
|
798
|
+
globalThis.test(param[0] + " hands the member type back as stored", async () => {
|
|
799
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(geoBinding(), undefined, payload);
|
|
800
|
+
globalThis.expect(memberOf(r)).toEqual("GeolocationLocated");
|
|
801
|
+
});
|
|
802
|
+
});
|
|
803
|
+
globalThis.test("node stamps the top level without disturbing the member", async () => {
|
|
804
|
+
PgQueryResolver_Lambda$ReventlessAws.register("Geos", geoBinding());
|
|
805
|
+
PgQueryResolver_Lambda$ReventlessAws.registerNodeType("Geo", "Geos");
|
|
806
|
+
let payload_arguments = Object.fromEntries([[
|
|
807
|
+
"id",
|
|
808
|
+
btoa("Geo:g-1")
|
|
809
|
+
]]);
|
|
810
|
+
let payload = {
|
|
811
|
+
readModelName: "",
|
|
812
|
+
kind: "node",
|
|
813
|
+
arguments: payload_arguments,
|
|
814
|
+
identity: Identity$Reventless.anonymous
|
|
815
|
+
};
|
|
816
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.handler(payload, null);
|
|
817
|
+
globalThis.expect(str(r, "__typename")).toEqual("Geo");
|
|
818
|
+
globalThis.expect(memberOf(r)).toEqual("GeolocationLocated");
|
|
819
|
+
});
|
|
820
|
+
});
|
|
821
|
+
|
|
632
822
|
export {
|
|
633
823
|
mk,
|
|
634
824
|
store,
|
|
@@ -647,5 +837,11 @@ export {
|
|
|
647
837
|
field,
|
|
648
838
|
str,
|
|
649
839
|
ids,
|
|
840
|
+
geoRow,
|
|
841
|
+
geoStore,
|
|
842
|
+
geoItems,
|
|
843
|
+
geoConnection,
|
|
844
|
+
geoBinding,
|
|
845
|
+
memberOf,
|
|
650
846
|
}
|
|
651
847
|
/* store Not a pure module */
|