@reventlessdev/reventless-aws 3.0.0-alpha.302 → 3.0.0-alpha.303
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 +10 -0
- package/package.json +9 -9
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda_Ops.res +21 -0
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda_Ops.res.mjs +20 -0
- package/src/adapter/QueryDb/PgQueryResolver_Lambda.res +41 -3
- package/src/adapter/QueryDb/PgQueryResolver_Lambda.res.mjs +27 -6
- package/src/adapter/QueryDb/QueryDbResolvers_AppSync.res +34 -4
- package/src/adapter/QueryDb/QueryDbResolvers_AppSync.res.mjs +16 -5
- package/src/adapter/Runtime/PgQueryResolverEntryPoint_Ops.res +10 -0
- package/src/adapter/Runtime/PgQueryResolverEntryPoint_Ops.res.mjs +4 -1
- package/src/adapter/Runtime/StateTopicPublish.mjs +38 -5
- package/src/adapter/StateTopic/StateTopic_AppSync.res +49 -1
- package/src/adapter/StateTopic/StateTopic_AppSync.res.mjs +28 -3
- package/src/adapter/StateTopic/StateTopic_AppSync_Ops.res +73 -2
- package/src/adapter/StateTopic/StateTopic_AppSync_Ops.res.mjs +39 -4
- package/tests/PgQueryResolver_LambdaTest.res +16 -1
- package/tests/PgQueryResolver_LambdaTest.res.mjs +46 -32
- package/tests/Platform_ComponentDefinitions_Lambda_OpsTest.res +65 -0
- package/tests/Platform_ComponentDefinitions_Lambda_OpsTest.res.mjs +36 -0
- package/tests/QueryDbResolvers_AppSyncTest.res.mjs +3 -3
- package/tests/StateChangeDescriptorParityTest.res +82 -1
- package/tests/StateChangeDescriptorParityTest.res.mjs +97 -1
- package/tests/stateChangeDescriptorParity.mjs +72 -3
|
@@ -10,6 +10,8 @@ import * as AWS_Tags$ReventlessAws from "../AWS_Tags.res.mjs";
|
|
|
10
10
|
import * as QueryDb$ReventlessCore from "@reventlessdev/reventless-core/src/components/QueryDb/QueryDb.res.mjs";
|
|
11
11
|
import * as PolicyDocument$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/IAM/PolicyDocument.res.mjs";
|
|
12
12
|
import * as Util_Bundle$ReventlessAws from "../../util/Util_Bundle.res.mjs";
|
|
13
|
+
import * as StateAnnotations$Reventless from "@reventlessdev/reventless-spec/src/components/StateAnnotations.res.mjs";
|
|
14
|
+
import * as Plugin_Helpers$ReventlessCore from "@reventlessdev/reventless-core/src/plugin/component/Plugin_Helpers.res.mjs";
|
|
13
15
|
import * as Util_ReadModel$ReventlessCore from "@reventlessdev/reventless-core/src/util/Util_ReadModel.res.mjs";
|
|
14
16
|
import * as AppSync_EventsApi$ReventlessAws from "../Api/AppSync_EventsApi.res.mjs";
|
|
15
17
|
import * as Util_LambdaLogging$ReventlessAws from "../../util/Util_LambdaLogging.res.mjs";
|
|
@@ -18,7 +20,7 @@ import * as StateTopic_AppSync_Helpers$ReventlessAws from "./StateTopic_AppSync_
|
|
|
18
20
|
|
|
19
21
|
let registry = {};
|
|
20
22
|
|
|
21
|
-
function makeForTable(tableName, streamArn, partitionKeyName, topicName, eventsApi, param) {
|
|
23
|
+
function makeForTable(tableName, streamArn, partitionKeyName, topicName, retiredField, retiredValues, eventsApi, param) {
|
|
22
24
|
let checkedTableName = Pulumi.all([
|
|
23
25
|
tableName,
|
|
24
26
|
partitionKeyName
|
|
@@ -32,13 +34,15 @@ function makeForTable(tableName, streamArn, partitionKeyName, topicName, eventsA
|
|
|
32
34
|
registry[key] = entries.concat([{
|
|
33
35
|
tableName: checkedTableName,
|
|
34
36
|
streamArn: streamArn,
|
|
35
|
-
topicName: topicName
|
|
37
|
+
topicName: topicName,
|
|
38
|
+
retiredField: retiredField,
|
|
39
|
+
retiredValues: retiredValues
|
|
36
40
|
}]);
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
function make(readModelName, topicName, allQueryDbs, eventsApi, opts) {
|
|
40
44
|
let streamResource = Util_DynamoDbStream$ReventlessAws.findResource(Util_ReadModel$ReventlessCore.queryDbStorageResources(allQueryDbs, readModelName));
|
|
41
|
-
makeForTable(streamResource.name, Util_DynamoDbStream$ReventlessAws.streamArnFromDynamoDbTableResource(streamResource), Pulumi.output(StateTopic_AppSync_Helpers$ReventlessAws.entityKeyPartitionAttribute), topicName, eventsApi, opts);
|
|
45
|
+
makeForTable(streamResource.name, Util_DynamoDbStream$ReventlessAws.streamArnFromDynamoDbTableResource(streamResource), Pulumi.output(StateTopic_AppSync_Helpers$ReventlessAws.entityKeyPartitionAttribute), topicName, Stdlib_Option.map(Stdlib_Option.flatMap(Stdlib_Option.flatMap(Plugin_Helpers$ReventlessCore.stateSchemaRegistry[readModelName], StateAnnotations$Reventless.getSpec), spec => spec.retired), r => r.field), Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_Option.flatMap(Plugin_Helpers$ReventlessCore.stateSchemaRegistry[readModelName], StateAnnotations$Reventless.getSpec), spec => spec.retired), r => r.values), eventsApi, opts);
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
function finish(eventsApi, opts) {
|
|
@@ -94,6 +98,23 @@ function finish(eventsApi, opts) {
|
|
|
94
98
|
});
|
|
95
99
|
return JSON.stringify(dict);
|
|
96
100
|
});
|
|
101
|
+
let retiredMapJson = Pulumi.all(entries.map(e => e.tableName)).apply(tableNames => {
|
|
102
|
+
let dict = {};
|
|
103
|
+
tableNames.forEach((tableName, i) => {
|
|
104
|
+
let entry = entries[i];
|
|
105
|
+
Stdlib_Option.forEach(entry.retiredField, f => {
|
|
106
|
+
let obj = Object.fromEntries([[
|
|
107
|
+
"field",
|
|
108
|
+
f
|
|
109
|
+
]]);
|
|
110
|
+
Stdlib_Option.forEach(entry.retiredValues, vs => {
|
|
111
|
+
obj["values"] = vs.map(prim => prim);
|
|
112
|
+
});
|
|
113
|
+
dict[tableName] = obj;
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
return JSON.stringify(dict);
|
|
117
|
+
});
|
|
97
118
|
let packageDirs = Object.fromEntries([[
|
|
98
119
|
"@reventlessdev/reventless-aws",
|
|
99
120
|
Util_Bundle$ReventlessAws.resolvePackageRoot(undefined, "@reventlessdev/reventless-aws")
|
|
@@ -125,6 +146,10 @@ function finish(eventsApi, opts) {
|
|
|
125
146
|
"STATE_TOPIC_MAP",
|
|
126
147
|
topicMapJson
|
|
127
148
|
],
|
|
149
|
+
[
|
|
150
|
+
"STATE_RETIRED_MAP",
|
|
151
|
+
retiredMapJson
|
|
152
|
+
],
|
|
128
153
|
[
|
|
129
154
|
"NODE_OPTIONS",
|
|
130
155
|
Util_Bundle$ReventlessAws.esmLoaderNodeOptions
|
|
@@ -53,6 +53,55 @@ type event = {@as("Records") records: array<record>}
|
|
|
53
53
|
|
|
54
54
|
// ── Per-record derivations (ports of the former inline JS helpers) ───────────
|
|
55
55
|
|
|
56
|
+
// STATE_RETIRED_MAP: `{ <tableName>: {field, values?} }`, injected at deploy time
|
|
57
|
+
// beside STATE_TOPIC_MAP. This handler runs with no plugin registry in process —
|
|
58
|
+
// there is nothing here that could read a state schema — so the whole predicate
|
|
59
|
+
// has to arrive the same way the topic routing does. A table absent from the map
|
|
60
|
+
// declares no retirement, which is every table until one does.
|
|
61
|
+
//
|
|
62
|
+
// `values` absent is the boolean form. Carried as an object rather than as an
|
|
63
|
+
// encoded string because a `field=Value` convention is a parser this side and a
|
|
64
|
+
// writer the other, and the two drift the first time a state name contains the
|
|
65
|
+
// separator — an argument that only gets stronger now that a lifecycle can name
|
|
66
|
+
// several states.
|
|
67
|
+
let retiredMap: dict<Reventless.OwnerScope.retiredScope> =
|
|
68
|
+
switch NodeProcess.env
|
|
69
|
+
->Dict.get("STATE_RETIRED_MAP")
|
|
70
|
+
->Option.getOr("{}")
|
|
71
|
+
->JSON.parseOrThrow
|
|
72
|
+
->JSON.Decode.object {
|
|
73
|
+
| Some(d) =>
|
|
74
|
+
let out = Dict.make()
|
|
75
|
+
d->Dict.forEachWithKey((v, k) =>
|
|
76
|
+
v
|
|
77
|
+
->JSON.Decode.object
|
|
78
|
+
->Option.flatMap(o =>
|
|
79
|
+
o
|
|
80
|
+
->Dict.get("field")
|
|
81
|
+
->Option.flatMap(JSON.Decode.string)
|
|
82
|
+
->Option.map(field => {
|
|
83
|
+
Reventless.OwnerScope.field,
|
|
84
|
+
values: o
|
|
85
|
+
->Dict.get("values")
|
|
86
|
+
->Option.flatMap(JSON.Decode.array)
|
|
87
|
+
->Option.map(vs => vs->Array.filterMap(JSON.Decode.string)),
|
|
88
|
+
})
|
|
89
|
+
)
|
|
90
|
+
->Option.forEach(scope => out->Dict.set(k, scope))
|
|
91
|
+
)
|
|
92
|
+
out
|
|
93
|
+
| None => Dict.make()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let tableNameFromEventSourceArn = (arn: string): option<string> => {
|
|
97
|
+
let parts = arn->String.split("/")
|
|
98
|
+
switch (parts->Array.get(0), parts->Array.get(1), parts->Array.get(2)) {
|
|
99
|
+
| (Some(prefix), Some(tableName), Some("stream")) if prefix->String.endsWith(":table") =>
|
|
100
|
+
Some(tableName)
|
|
101
|
+
| _ => None
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
56
105
|
// Map record.eventSourceARN → topicRoot via STATE_TOPIC_MAP. Stream ARNs look
|
|
57
106
|
// like arn:aws:dynamodb:<region>:<acct>:table/<TableName>/stream/<ts>; split on
|
|
58
107
|
// "/" gives [ "...:table", "<TableName>", "stream", "<ts>" ].
|
|
@@ -131,18 +180,34 @@ let makeDescriptor = (
|
|
|
131
180
|
~entityKey: string,
|
|
132
181
|
~image: dict<JSON.t>,
|
|
133
182
|
~seq: option<string>,
|
|
183
|
+
~retiredField: option<string>=?,
|
|
184
|
+
~retiredValues: option<array<string>>=?,
|
|
134
185
|
): JSON.t => {
|
|
135
186
|
let removed = changeKind == "Removed"
|
|
187
|
+
// A retired row publishes as metadata only, for the reason the other two
|
|
188
|
+
// implementations do it: this channel reaches every subscriber of the view,
|
|
189
|
+
// and a payload would deliver the row to the callers the resolvers refuse it
|
|
190
|
+
// to. `Updated` with no state is the shape an oversized row already takes.
|
|
191
|
+
// Both forms are the one question `isRetiredValue` answers, so nothing here
|
|
192
|
+
// branches on which the view declared.
|
|
193
|
+
let retired = switch retiredField {
|
|
194
|
+
| Some(field) =>
|
|
195
|
+
!removed &&
|
|
196
|
+
{Reventless.OwnerScope.field, values: retiredValues}->Reventless.OwnerScope.isRetiredValue(
|
|
197
|
+
image->Dict.get(field),
|
|
198
|
+
)
|
|
199
|
+
| None => false
|
|
200
|
+
}
|
|
136
201
|
let descriptor = Dict.make()
|
|
137
202
|
descriptor->Dict.set("changeKind", JSON.Encode.string(changeKind))
|
|
138
203
|
descriptor->Dict.set("id", JSON.Encode.string(entityKey))
|
|
139
|
-
if !removed {
|
|
204
|
+
if !removed && !retired {
|
|
140
205
|
pickSortKeyValue(image)->Option.forEach(v =>
|
|
141
206
|
descriptor->Dict.set("sortKeyValue", JSON.Encode.string(v))
|
|
142
207
|
)
|
|
143
208
|
}
|
|
144
209
|
seq->Option.forEach(s => descriptor->Dict.set("seq", JSON.Encode.string(s)))
|
|
145
|
-
if !removed {
|
|
210
|
+
if !removed && !retired {
|
|
146
211
|
let state = image->JSON.Encode.object
|
|
147
212
|
let encoded = state->JSON.stringify
|
|
148
213
|
if encoded->String.length <= maxStateChars {
|
|
@@ -191,6 +256,12 @@ let processRecord = async (
|
|
|
191
256
|
~entityKey,
|
|
192
257
|
~image=unmarshalled,
|
|
193
258
|
~seq=dynamodb.sequenceNumber,
|
|
259
|
+
~retiredField=?tableNameFromEventSourceArn(record.eventSourceARN)
|
|
260
|
+
->Option.flatMap(t => retiredMap->Dict.get(t))
|
|
261
|
+
->Option.map(scope => scope.Reventless.OwnerScope.field),
|
|
262
|
+
~retiredValues=?tableNameFromEventSourceArn(record.eventSourceARN)
|
|
263
|
+
->Option.flatMap(t => retiredMap->Dict.get(t))
|
|
264
|
+
->Option.flatMap(scope => scope.Reventless.OwnerScope.values),
|
|
194
265
|
)
|
|
195
266
|
let body =
|
|
196
267
|
Dict.fromArray([
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
+
import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
|
|
3
4
|
import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
|
|
4
5
|
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
5
6
|
import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
|
|
@@ -7,6 +8,7 @@ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
|
7
8
|
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
8
9
|
import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
|
|
9
10
|
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
11
|
+
import * as OwnerScope$Reventless from "@reventlessdev/reventless-spec/src/types/OwnerScope.res.mjs";
|
|
10
12
|
import * as DynamoDb_Util_Helpers$AwsSdk from "@reventlessdev/rescript-aws-sdk/src/DynamoDb_Util_Helpers.res.mjs";
|
|
11
13
|
import * as AppSyncEventsSigner_Ops$ReventlessAws from "../Api/AppSyncEventsSigner_Ops.res.mjs";
|
|
12
14
|
|
|
@@ -22,6 +24,33 @@ let topicMap = obj !== undefined ? Object.fromEntries(Stdlib_Array.filterMap(Obj
|
|
|
22
24
|
]);
|
|
23
25
|
})) : ({});
|
|
24
26
|
|
|
27
|
+
let d = Stdlib_JSON.Decode.object(JSON.parse(Stdlib_Option.getOr(process.env["STATE_RETIRED_MAP"], "{}")));
|
|
28
|
+
|
|
29
|
+
let retiredMap;
|
|
30
|
+
|
|
31
|
+
if (d !== undefined) {
|
|
32
|
+
let out = {};
|
|
33
|
+
Stdlib_Dict.forEachWithKey(d, (v, k) => Stdlib_Option.forEach(Stdlib_Option.flatMap(Stdlib_JSON.Decode.object(v), o => Stdlib_Option.map(Stdlib_Option.flatMap(o["field"], Stdlib_JSON.Decode.string), field => ({
|
|
34
|
+
field: field,
|
|
35
|
+
values: Stdlib_Option.map(Stdlib_Option.flatMap(o["values"], Stdlib_JSON.Decode.array), vs => Stdlib_Array.filterMap(vs, Stdlib_JSON.Decode.string))
|
|
36
|
+
}))), scope => {
|
|
37
|
+
out[k] = scope;
|
|
38
|
+
}));
|
|
39
|
+
retiredMap = out;
|
|
40
|
+
} else {
|
|
41
|
+
retiredMap = {};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function tableNameFromEventSourceArn(arn) {
|
|
45
|
+
let parts = arn.split("/");
|
|
46
|
+
let match = parts[0];
|
|
47
|
+
let match$1 = parts[1];
|
|
48
|
+
let match$2 = parts[2];
|
|
49
|
+
if (match !== undefined && match$1 !== undefined && match$2 !== undefined && match$2 === "stream" && match.endsWith(":table")) {
|
|
50
|
+
return match$1;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
25
54
|
function topicRootFromEventSourceArn(arn) {
|
|
26
55
|
let parts = arn.split("/");
|
|
27
56
|
let match = parts[0];
|
|
@@ -89,12 +118,16 @@ function pickSortKeyValue(image) {
|
|
|
89
118
|
}
|
|
90
119
|
}
|
|
91
120
|
|
|
92
|
-
function makeDescriptor(changeKind, entityKey, image, seq) {
|
|
121
|
+
function makeDescriptor(changeKind, entityKey, image, seq, retiredField, retiredValues) {
|
|
93
122
|
let removed = changeKind === "Removed";
|
|
123
|
+
let retired = retiredField !== undefined ? !removed && OwnerScope$Reventless.isRetiredValue({
|
|
124
|
+
field: retiredField,
|
|
125
|
+
values: retiredValues
|
|
126
|
+
}, image[retiredField]) : false;
|
|
94
127
|
let descriptor = {};
|
|
95
128
|
descriptor["changeKind"] = changeKind;
|
|
96
129
|
descriptor["id"] = entityKey;
|
|
97
|
-
if (!removed) {
|
|
130
|
+
if (!removed && !retired) {
|
|
98
131
|
Stdlib_Option.forEach(pickSortKeyValue(image), v => {
|
|
99
132
|
descriptor["sortKeyValue"] = v;
|
|
100
133
|
});
|
|
@@ -102,7 +135,7 @@ function makeDescriptor(changeKind, entityKey, image, seq) {
|
|
|
102
135
|
Stdlib_Option.forEach(seq, s => {
|
|
103
136
|
descriptor["seq"] = s;
|
|
104
137
|
});
|
|
105
|
-
if (!removed) {
|
|
138
|
+
if (!removed && !retired) {
|
|
106
139
|
let encoded = JSON.stringify(image);
|
|
107
140
|
if (encoded.length <= 61440) {
|
|
108
141
|
descriptor["state"] = image;
|
|
@@ -127,7 +160,7 @@ async function processRecord(record, region, creds) {
|
|
|
127
160
|
let entityKey = entityKeyFromRecord(dynamodb);
|
|
128
161
|
let channel = `/default/` + topicRoot + `/` + AppSyncEventsSigner_Ops$ReventlessAws.pathSegment(entityKey);
|
|
129
162
|
let unmarshalled = DynamoDb_Util_Helpers$AwsSdk.unmarshallDict(undefined, image);
|
|
130
|
-
let descriptor = makeDescriptor(changeKindFor(record.eventName), entityKey, unmarshalled, dynamodb.SequenceNumber);
|
|
163
|
+
let descriptor = makeDescriptor(changeKindFor(record.eventName), entityKey, unmarshalled, dynamodb.SequenceNumber, Stdlib_Option.map(Stdlib_Option.flatMap(tableNameFromEventSourceArn(record.eventSourceARN), t => retiredMap[t]), scope => scope.field), Stdlib_Option.flatMap(Stdlib_Option.flatMap(tableNameFromEventSourceArn(record.eventSourceARN), t => retiredMap[t]), scope => scope.values));
|
|
131
164
|
let body = JSON.stringify(Object.fromEntries([
|
|
132
165
|
[
|
|
133
166
|
"id",
|
|
@@ -193,6 +226,8 @@ let maxStateChars = 61440;
|
|
|
193
226
|
export {
|
|
194
227
|
endpoint,
|
|
195
228
|
topicMap,
|
|
229
|
+
retiredMap,
|
|
230
|
+
tableNameFromEventSourceArn,
|
|
196
231
|
topicRootFromEventSourceArn,
|
|
197
232
|
jsonToString,
|
|
198
233
|
entityKeyFromRecord,
|
|
@@ -52,6 +52,8 @@ let ops: QueryDb_Adapter.operations = {
|
|
|
52
52
|
deleteBatch: Obj.magic(0),
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
let lastRetiredScope: ref<option<Reventless.OwnerScope.retiredScope>> = ref(None)
|
|
56
|
+
|
|
55
57
|
let pushdowns: PgQueryResolver_Lambda.pushdowns = {
|
|
56
58
|
indexLookup: async (~readModelName as _, field, value) =>
|
|
57
59
|
allItems()->Array.filter(i => fieldEq(i, field, value)),
|
|
@@ -63,11 +65,20 @@ let pushdowns: PgQueryResolver_Lambda.pushdowns = {
|
|
|
63
65
|
~capability as _,
|
|
64
66
|
~labelField as _,
|
|
65
67
|
~ownerScope: option<(string, string)>=?,
|
|
68
|
+
~retiredScope: option<Reventless.OwnerScope.retiredScope>=?,
|
|
66
69
|
) => {
|
|
67
70
|
lastOwnerScope := ownerScope
|
|
71
|
+
lastRetiredScope := retiredScope
|
|
68
72
|
listPageReturn.contents
|
|
69
73
|
},
|
|
70
|
-
itemsPage: async (
|
|
74
|
+
itemsPage: async (
|
|
75
|
+
~readModelName as _,
|
|
76
|
+
~subIdField as _,
|
|
77
|
+
~id,
|
|
78
|
+
~argsDict as _,
|
|
79
|
+
~ownerScope as _=?,
|
|
80
|
+
~retiredScope as _=?,
|
|
81
|
+
) =>
|
|
71
82
|
// Sentinel echoing the requested id, so the dispatch routing is observable.
|
|
72
83
|
JSON.Encode.object(Dict.fromArray([("itemsFor", JSON.Encode.string(id))])),
|
|
73
84
|
scanAll: async (~readModelName as _) => allItems(),
|
|
@@ -82,6 +93,8 @@ let makeBinding = (
|
|
|
82
93
|
~authorization=Reventless.Authorization.AllowAnonymous,
|
|
83
94
|
~subIdField=None,
|
|
84
95
|
~ownerField=None,
|
|
96
|
+
~retiredField=None,
|
|
97
|
+
~retiredValues=None,
|
|
85
98
|
(),
|
|
86
99
|
): PgQueryResolver_Lambda.binding => {
|
|
87
100
|
ops,
|
|
@@ -96,6 +109,8 @@ let makeBinding = (
|
|
|
96
109
|
includeIdParam: true,
|
|
97
110
|
authorization,
|
|
98
111
|
ownerField,
|
|
112
|
+
retiredField,
|
|
113
|
+
retiredValues,
|
|
99
114
|
}
|
|
100
115
|
|
|
101
116
|
let mkPayload = (
|
|
@@ -68,6 +68,10 @@ let ops = {
|
|
|
68
68
|
deleteBatch: 0
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
+
let lastRetiredScope = {
|
|
72
|
+
contents: undefined
|
|
73
|
+
};
|
|
74
|
+
|
|
71
75
|
async function pushdowns_indexLookup(param, field, value) {
|
|
72
76
|
return Object.values(store).filter(i => fieldEq(i, field, value));
|
|
73
77
|
}
|
|
@@ -76,12 +80,13 @@ async function pushdowns_byIds(param, ids) {
|
|
|
76
80
|
return Stdlib_Array.filterMap(ids, id => store[id]);
|
|
77
81
|
}
|
|
78
82
|
|
|
79
|
-
async function pushdowns_listPage(param, param$1, param$2, param$3, ownerScope) {
|
|
83
|
+
async function pushdowns_listPage(param, param$1, param$2, param$3, ownerScope, retiredScope) {
|
|
80
84
|
lastOwnerScope.contents = ownerScope;
|
|
85
|
+
lastRetiredScope.contents = retiredScope;
|
|
81
86
|
return listPageReturn.contents;
|
|
82
87
|
}
|
|
83
88
|
|
|
84
|
-
async function pushdowns_itemsPage(param, param$1, id, param$2, param$3) {
|
|
89
|
+
async function pushdowns_itemsPage(param, param$1, id, param$2, param$3, param$4) {
|
|
85
90
|
return Object.fromEntries([[
|
|
86
91
|
"itemsFor",
|
|
87
92
|
id
|
|
@@ -116,10 +121,12 @@ let capability = {
|
|
|
116
121
|
sortFields: capability_sortFields
|
|
117
122
|
};
|
|
118
123
|
|
|
119
|
-
function makeBinding(authorizationOpt, subIdFieldOpt, ownerFieldOpt, param) {
|
|
124
|
+
function makeBinding(authorizationOpt, subIdFieldOpt, ownerFieldOpt, retiredFieldOpt, retiredValuesOpt, param) {
|
|
120
125
|
let authorization = authorizationOpt !== undefined ? authorizationOpt : "AllowAnonymous";
|
|
121
126
|
let subIdField = subIdFieldOpt !== undefined ? Primitive_option.valFromOption(subIdFieldOpt) : undefined;
|
|
122
127
|
let ownerField = ownerFieldOpt !== undefined ? Primitive_option.valFromOption(ownerFieldOpt) : undefined;
|
|
128
|
+
let retiredField = retiredFieldOpt !== undefined ? Primitive_option.valFromOption(retiredFieldOpt) : undefined;
|
|
129
|
+
let retiredValues = retiredValuesOpt !== undefined ? Primitive_option.valFromOption(retiredValuesOpt) : undefined;
|
|
123
130
|
return {
|
|
124
131
|
ops: ops,
|
|
125
132
|
pushdowns: pushdowns,
|
|
@@ -134,7 +141,9 @@ function makeBinding(authorizationOpt, subIdFieldOpt, ownerFieldOpt, param) {
|
|
|
134
141
|
labelField: "name",
|
|
135
142
|
includeIdParam: true,
|
|
136
143
|
authorization: authorization,
|
|
137
|
-
ownerField: ownerField
|
|
144
|
+
ownerField: ownerField,
|
|
145
|
+
retiredField: retiredField,
|
|
146
|
+
retiredValues: retiredValues
|
|
138
147
|
};
|
|
139
148
|
}
|
|
140
149
|
|
|
@@ -177,7 +186,7 @@ function ids(arr) {
|
|
|
177
186
|
|
|
178
187
|
globalThis.describe("PgQueryResolver_Lambda.dispatch", () => {
|
|
179
188
|
globalThis.test("getById returns the item (id-carrying)", async () => {
|
|
180
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), undefined, mkPayload("getById", undefined, Object.fromEntries([[
|
|
189
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), undefined, mkPayload("getById", undefined, Object.fromEntries([[
|
|
181
190
|
"id",
|
|
182
191
|
"p-2"
|
|
183
192
|
]]), undefined, undefined));
|
|
@@ -185,14 +194,14 @@ globalThis.describe("PgQueryResolver_Lambda.dispatch", () => {
|
|
|
185
194
|
globalThis.expect(str(r, "name")).toEqual("Bravo");
|
|
186
195
|
});
|
|
187
196
|
globalThis.test("getById miss → null", async () => {
|
|
188
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), undefined, mkPayload("getById", undefined, Object.fromEntries([[
|
|
197
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), undefined, mkPayload("getById", undefined, Object.fromEntries([[
|
|
189
198
|
"id",
|
|
190
199
|
"absent"
|
|
191
200
|
]]), undefined, undefined));
|
|
192
201
|
globalThis.expect(r).toBe(null);
|
|
193
202
|
});
|
|
194
203
|
globalThis.test("byIds returns matches, drops missing", async () => {
|
|
195
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), undefined, mkPayload("byIds", undefined, Object.fromEntries([[
|
|
204
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), undefined, mkPayload("byIds", undefined, Object.fromEntries([[
|
|
196
205
|
"ids",
|
|
197
206
|
[
|
|
198
207
|
"p-1",
|
|
@@ -206,7 +215,7 @@ globalThis.describe("PgQueryResolver_Lambda.dispatch", () => {
|
|
|
206
215
|
]);
|
|
207
216
|
});
|
|
208
217
|
globalThis.test("index routes to indexLookup on the idField", async () => {
|
|
209
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), undefined, mkPayload("index", "byStatus", Object.fromEntries([[
|
|
218
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), undefined, mkPayload("index", "byStatus", Object.fromEntries([[
|
|
210
219
|
"byStatus",
|
|
211
220
|
"active"
|
|
212
221
|
]]), undefined, undefined));
|
|
@@ -217,13 +226,13 @@ globalThis.describe("PgQueryResolver_Lambda.dispatch", () => {
|
|
|
217
226
|
});
|
|
218
227
|
globalThis.test("list with push-down → returns the connection listPage gives", async () => {
|
|
219
228
|
listPageReturn.contents = "PUSHED";
|
|
220
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), undefined, mkPayload("list", undefined, undefined, undefined, undefined));
|
|
229
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), undefined, mkPayload("list", undefined, undefined, undefined, undefined));
|
|
221
230
|
listPageReturn.contents = undefined;
|
|
222
231
|
globalThis.expect(r).toEqual("PUSHED");
|
|
223
232
|
});
|
|
224
233
|
globalThis.test("list without push-down → falls back to the shared spec", async () => {
|
|
225
234
|
listPageReturn.contents = undefined;
|
|
226
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), undefined, mkPayload("list", undefined, undefined, undefined, undefined));
|
|
235
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), undefined, mkPayload("list", undefined, undefined, undefined, undefined));
|
|
227
236
|
let edgeIds = Stdlib_Array.filterMap(Stdlib_Option.getOr(Stdlib_Option.flatMap(field(r, "edges"), Stdlib_JSON.Decode.array), []), e => Stdlib_Option.flatMap(field(e, "node"), n => str(n, "id")));
|
|
228
237
|
globalThis.expect(edgeIds).toEqual([
|
|
229
238
|
"p-1",
|
|
@@ -232,21 +241,21 @@ globalThis.describe("PgQueryResolver_Lambda.dispatch", () => {
|
|
|
232
241
|
]);
|
|
233
242
|
});
|
|
234
243
|
globalThis.test("items with subId routes to itemsPage (id echoed)", async () => {
|
|
235
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, "seq", undefined, undefined), undefined, mkPayload("items", undefined, Object.fromEntries([[
|
|
244
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, "seq", undefined, undefined, undefined, undefined), undefined, mkPayload("items", undefined, Object.fromEntries([[
|
|
236
245
|
"id",
|
|
237
246
|
"p-2"
|
|
238
247
|
]]), undefined, undefined));
|
|
239
248
|
globalThis.expect(str(r, "itemsFor")).toEqual("p-2");
|
|
240
249
|
});
|
|
241
250
|
globalThis.test("items without subId → empty connection", async () => {
|
|
242
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), undefined, mkPayload("items", undefined, Object.fromEntries([[
|
|
251
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), undefined, mkPayload("items", undefined, Object.fromEntries([[
|
|
243
252
|
"id",
|
|
244
253
|
"p-2"
|
|
245
254
|
]]), undefined, undefined));
|
|
246
255
|
globalThis.expect(Stdlib_Option.getOr(Stdlib_Option.flatMap(field(r, "edges"), Stdlib_JSON.Decode.array), []).length).toBe(0);
|
|
247
256
|
});
|
|
248
257
|
globalThis.test("authorization DenyAll → empty shape per kind", async () => {
|
|
249
|
-
let b = makeBinding("DenyAll", undefined, undefined, undefined);
|
|
258
|
+
let b = makeBinding("DenyAll", undefined, undefined, undefined, undefined, undefined);
|
|
250
259
|
let single = await PgQueryResolver_Lambda$ReventlessAws.dispatch(b, undefined, mkPayload("getById", undefined, Object.fromEntries([[
|
|
251
260
|
"id",
|
|
252
261
|
"p-1"
|
|
@@ -265,7 +274,7 @@ globalThis.describe("PgQueryResolver_Lambda.dispatch", () => {
|
|
|
265
274
|
TAG: "Deny",
|
|
266
275
|
_0: "nope"
|
|
267
276
|
}));
|
|
268
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), undefined, mkPayload("getById", undefined, Object.fromEntries([[
|
|
277
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), undefined, mkPayload("getById", undefined, Object.fromEntries([[
|
|
269
278
|
"id",
|
|
270
279
|
"p-1"
|
|
271
280
|
]]), undefined, undefined));
|
|
@@ -291,7 +300,7 @@ globalThis.describe("PgQueryResolver_Lambda.dispatch", () => {
|
|
|
291
300
|
arguments: payload_arguments,
|
|
292
301
|
identity: Identity$Reventless.anonymous
|
|
293
302
|
};
|
|
294
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), undefined, payload);
|
|
303
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), undefined, payload);
|
|
295
304
|
globalThis.expect(str(r, "id")).toEqual("p-2");
|
|
296
305
|
});
|
|
297
306
|
globalThis.test("resolveOne multi via target index → array", async () => {
|
|
@@ -317,7 +326,7 @@ globalThis.describe("PgQueryResolver_Lambda.dispatch", () => {
|
|
|
317
326
|
arguments: payload_arguments,
|
|
318
327
|
identity: Identity$Reventless.anonymous
|
|
319
328
|
};
|
|
320
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), undefined, payload);
|
|
329
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), undefined, payload);
|
|
321
330
|
globalThis.expect(ids(r)).toEqual([
|
|
322
331
|
"p-1",
|
|
323
332
|
"p-3"
|
|
@@ -344,14 +353,14 @@ globalThis.describe("PgQueryResolver_Lambda.dispatch", () => {
|
|
|
344
353
|
arguments: payload_arguments,
|
|
345
354
|
identity: Identity$Reventless.anonymous
|
|
346
355
|
};
|
|
347
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), undefined, payload);
|
|
356
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), undefined, payload);
|
|
348
357
|
globalThis.expect(ids(r)).toEqual([
|
|
349
358
|
"p-1",
|
|
350
359
|
"p-3"
|
|
351
360
|
]);
|
|
352
361
|
});
|
|
353
362
|
globalThis.test("node decodes global id → __typename + item", async () => {
|
|
354
|
-
PgQueryResolver_Lambda$ReventlessAws.register("Things", makeBinding(undefined, undefined, undefined, undefined));
|
|
363
|
+
PgQueryResolver_Lambda$ReventlessAws.register("Things", makeBinding(undefined, undefined, undefined, undefined, undefined, undefined));
|
|
355
364
|
PgQueryResolver_Lambda$ReventlessAws.registerNodeType("Thing", "Things");
|
|
356
365
|
let payload_arguments = Object.fromEntries([[
|
|
357
366
|
"id",
|
|
@@ -401,7 +410,7 @@ globalThis.describe("PgQueryResolver_Lambda.dispatch", () => {
|
|
|
401
410
|
delete: 0,
|
|
402
411
|
deleteBatch: 0
|
|
403
412
|
};
|
|
404
|
-
let init = makeBinding(undefined, undefined, undefined, undefined);
|
|
413
|
+
let init = makeBinding(undefined, undefined, undefined, undefined, undefined, undefined);
|
|
405
414
|
let authBinding_pushdowns = init.pushdowns;
|
|
406
415
|
let authBinding_indexes = init.indexes;
|
|
407
416
|
let authBinding_subIdField = init.subIdField;
|
|
@@ -410,6 +419,8 @@ globalThis.describe("PgQueryResolver_Lambda.dispatch", () => {
|
|
|
410
419
|
let authBinding_includeIdParam = init.includeIdParam;
|
|
411
420
|
let authBinding_authorization = init.authorization;
|
|
412
421
|
let authBinding_ownerField = init.ownerField;
|
|
422
|
+
let authBinding_retiredField = init.retiredField;
|
|
423
|
+
let authBinding_retiredValues = init.retiredValues;
|
|
413
424
|
let authBinding = {
|
|
414
425
|
ops: authOps,
|
|
415
426
|
pushdowns: authBinding_pushdowns,
|
|
@@ -419,7 +430,9 @@ globalThis.describe("PgQueryResolver_Lambda.dispatch", () => {
|
|
|
419
430
|
labelField: authBinding_labelField,
|
|
420
431
|
includeIdParam: authBinding_includeIdParam,
|
|
421
432
|
authorization: authBinding_authorization,
|
|
422
|
-
ownerField: authBinding_ownerField
|
|
433
|
+
ownerField: authBinding_ownerField,
|
|
434
|
+
retiredField: authBinding_retiredField,
|
|
435
|
+
retiredValues: authBinding_retiredValues
|
|
423
436
|
};
|
|
424
437
|
let lookupAuth = name => {
|
|
425
438
|
if (name === "AuthTable") {
|
|
@@ -445,18 +458,18 @@ globalThis.describe("PgQueryResolver_Lambda.dispatch", () => {
|
|
|
445
458
|
identity: ident(username, groups)
|
|
446
459
|
});
|
|
447
460
|
globalThis.test("auth index: group member who owns → results", async () => {
|
|
448
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), lookupAuth, authIndexPayload("alice", ["Owner"]));
|
|
461
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), lookupAuth, authIndexPayload("alice", ["Owner"]));
|
|
449
462
|
globalThis.expect(ids(r)).toEqual([
|
|
450
463
|
"p-1",
|
|
451
464
|
"p-3"
|
|
452
465
|
]);
|
|
453
466
|
});
|
|
454
467
|
globalThis.test("auth index: group member who does NOT own → empty", async () => {
|
|
455
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), lookupAuth, authIndexPayload("bob", ["Owner"]));
|
|
468
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), lookupAuth, authIndexPayload("bob", ["Owner"]));
|
|
456
469
|
globalThis.expect(Stdlib_Option.getOr(Stdlib_JSON.Decode.array(r), []).length).toBe(0);
|
|
457
470
|
});
|
|
458
471
|
globalThis.test("auth index: non-member passes through → results", async () => {
|
|
459
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), lookupAuth, authIndexPayload("bob", []));
|
|
472
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), lookupAuth, authIndexPayload("bob", []));
|
|
460
473
|
globalThis.expect(ids(r)).toEqual([
|
|
461
474
|
"p-1",
|
|
462
475
|
"p-3"
|
|
@@ -465,7 +478,7 @@ globalThis.describe("PgQueryResolver_Lambda.dispatch", () => {
|
|
|
465
478
|
globalThis.test("unmapped kind throws", async () => {
|
|
466
479
|
let threw;
|
|
467
480
|
try {
|
|
468
|
-
await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), undefined, mkPayload("frobnicate", undefined, undefined, undefined, undefined));
|
|
481
|
+
await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), undefined, mkPayload("frobnicate", undefined, undefined, undefined, undefined));
|
|
469
482
|
threw = false;
|
|
470
483
|
} catch (exn) {
|
|
471
484
|
threw = true;
|
|
@@ -476,35 +489,35 @@ globalThis.describe("PgQueryResolver_Lambda.dispatch", () => {
|
|
|
476
489
|
|
|
477
490
|
globalThis.describe("id form — the typed doors take either", () => {
|
|
478
491
|
globalThis.test("getById resolves a Relay global id", async () => {
|
|
479
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), undefined, mkPayload("getById", undefined, Object.fromEntries([[
|
|
492
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), undefined, mkPayload("getById", undefined, Object.fromEntries([[
|
|
480
493
|
"id",
|
|
481
494
|
Api_Ids$ReventlessCore.encode("Thing", "p-2")
|
|
482
495
|
]]), undefined, undefined));
|
|
483
496
|
globalThis.expect(str(r, "name")).toEqual("Bravo");
|
|
484
497
|
});
|
|
485
498
|
globalThis.test("getById reports the storage key it resolved to", async () => {
|
|
486
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), undefined, mkPayload("getById", undefined, Object.fromEntries([[
|
|
499
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), undefined, mkPayload("getById", undefined, Object.fromEntries([[
|
|
487
500
|
"id",
|
|
488
501
|
Api_Ids$ReventlessCore.encode("Thing", "p-2")
|
|
489
502
|
]]), undefined, undefined));
|
|
490
503
|
globalThis.expect(str(r, "id")).toEqual("p-2");
|
|
491
504
|
});
|
|
492
505
|
globalThis.test("getById still resolves a plain storage key", async () => {
|
|
493
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), undefined, mkPayload("getById", undefined, Object.fromEntries([[
|
|
506
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), undefined, mkPayload("getById", undefined, Object.fromEntries([[
|
|
494
507
|
"id",
|
|
495
508
|
"p-2"
|
|
496
509
|
]]), undefined, undefined));
|
|
497
510
|
globalThis.expect(str(r, "name")).toEqual("Bravo");
|
|
498
511
|
});
|
|
499
512
|
globalThis.test("getById on a global id for a row that does not exist is still null", async () => {
|
|
500
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), undefined, mkPayload("getById", undefined, Object.fromEntries([[
|
|
513
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), undefined, mkPayload("getById", undefined, Object.fromEntries([[
|
|
501
514
|
"id",
|
|
502
515
|
Api_Ids$ReventlessCore.encode("Thing", "absent")
|
|
503
516
|
]]), undefined, undefined));
|
|
504
517
|
globalThis.expect(r).toBe(null);
|
|
505
518
|
});
|
|
506
519
|
globalThis.test("byIds accepts the two forms mixed in one call", async () => {
|
|
507
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), undefined, mkPayload("byIds", undefined, Object.fromEntries([[
|
|
520
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), undefined, mkPayload("byIds", undefined, Object.fromEntries([[
|
|
508
521
|
"ids",
|
|
509
522
|
[
|
|
510
523
|
"p-1",
|
|
@@ -517,7 +530,7 @@ globalThis.describe("id form — the typed doors take either", () => {
|
|
|
517
530
|
]);
|
|
518
531
|
});
|
|
519
532
|
globalThis.test("byIds with every id found does not double-count", async () => {
|
|
520
|
-
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined), undefined, mkPayload("byIds", undefined, Object.fromEntries([[
|
|
533
|
+
let r = await PgQueryResolver_Lambda$ReventlessAws.dispatch(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), undefined, mkPayload("byIds", undefined, Object.fromEntries([[
|
|
521
534
|
"ids",
|
|
522
535
|
[
|
|
523
536
|
"p-1",
|
|
@@ -532,7 +545,7 @@ globalThis.describe("id form — the typed doors take either", () => {
|
|
|
532
545
|
});
|
|
533
546
|
|
|
534
547
|
globalThis.describe("owner scoping", () => {
|
|
535
|
-
let ownedBinding = () => makeBinding(undefined, undefined, "owner", undefined);
|
|
548
|
+
let ownedBinding = () => makeBinding(undefined, undefined, "owner", undefined, undefined, undefined);
|
|
536
549
|
let shopper = cognito("u-a", ["User"]);
|
|
537
550
|
let listWith = async (binding, identity) => {
|
|
538
551
|
lastOwnerScope.contents = undefined;
|
|
@@ -557,7 +570,7 @@ globalThis.describe("owner scoping", () => {
|
|
|
557
570
|
globalThis.expect(match[1]).toBe(undefined);
|
|
558
571
|
});
|
|
559
572
|
globalThis.test("a view with no owner field is never scoped", async () => {
|
|
560
|
-
let match = await listWith(makeBinding(undefined, undefined, undefined, undefined), shopper);
|
|
573
|
+
let match = await listWith(makeBinding(undefined, undefined, undefined, undefined, undefined, undefined), shopper);
|
|
561
574
|
globalThis.expect(match[1]).toBe(undefined);
|
|
562
575
|
});
|
|
563
576
|
globalThis.test("an unidentified caller is refused before the push-down runs", async () => {
|
|
@@ -620,6 +633,7 @@ export {
|
|
|
620
633
|
listPageReturn,
|
|
621
634
|
lastOwnerScope,
|
|
622
635
|
ops,
|
|
636
|
+
lastRetiredScope,
|
|
623
637
|
pushdowns,
|
|
624
638
|
capability,
|
|
625
639
|
makeBinding,
|