@aws-amplify/datastore 5.0.1-api-v6-models.c1977f8.0 → 5.0.1-api-v6-models.891fe0d.0
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/lib/authModeStrategies/defaultAuthStrategy.js +1 -1
- package/lib/authModeStrategies/multiAuthStrategy.js +29 -105
- package/lib/datastore/datastore.js +887 -1370
- package/lib/index.js +1 -1
- package/lib/predicates/index.js +53 -102
- package/lib/predicates/next.js +310 -557
- package/lib/predicates/sort.js +24 -27
- package/lib/ssr/index.js +1 -1
- package/lib/storage/adapter/AsyncStorageAdapter.js +115 -449
- package/lib/storage/adapter/AsyncStorageDatabase.js +215 -480
- package/lib/storage/adapter/InMemoryStore.js +27 -101
- package/lib/storage/adapter/InMemoryStore.native.js +1 -1
- package/lib/storage/adapter/IndexedDBAdapter.js +441 -1002
- package/lib/storage/adapter/StorageAdapterBase.js +177 -396
- package/lib/storage/adapter/getDefaultAdapter/index.js +5 -6
- package/lib/storage/adapter/getDefaultAdapter/index.native.js +2 -2
- package/lib/storage/relationship.js +174 -260
- package/lib/storage/storage.js +244 -507
- package/lib/sync/datastoreConnectivity.js +29 -84
- package/lib/sync/datastoreReachability/index.js +1 -1
- package/lib/sync/datastoreReachability/index.native.js +2 -2
- package/lib/sync/index.js +512 -885
- package/lib/sync/merger.js +30 -133
- package/lib/sync/outbox.js +147 -302
- package/lib/sync/processors/errorMaps.js +30 -80
- package/lib/sync/processors/mutation.js +331 -579
- package/lib/sync/processors/subscription.js +268 -428
- package/lib/sync/processors/sync.js +276 -464
- package/lib/sync/utils.js +248 -393
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types.js +16 -58
- package/lib/util.js +335 -575
- package/lib-esm/authModeStrategies/defaultAuthStrategy.js +1 -1
- package/lib-esm/authModeStrategies/multiAuthStrategy.js +27 -103
- package/lib-esm/datastore/datastore.js +874 -1359
- package/lib-esm/index.js +6 -6
- package/lib-esm/predicates/index.js +54 -104
- package/lib-esm/predicates/next.js +306 -555
- package/lib-esm/predicates/sort.js +24 -27
- package/lib-esm/ssr/index.js +1 -1
- package/lib-esm/storage/adapter/AsyncStorageAdapter.js +111 -446
- package/lib-esm/storage/adapter/AsyncStorageDatabase.js +212 -477
- package/lib-esm/storage/adapter/InMemoryStore.js +27 -102
- package/lib-esm/storage/adapter/IndexedDBAdapter.js +436 -997
- package/lib-esm/storage/adapter/StorageAdapterBase.js +172 -392
- package/lib-esm/storage/adapter/getDefaultAdapter/index.js +2 -3
- package/lib-esm/storage/adapter/getDefaultAdapter/index.native.js +1 -1
- package/lib-esm/storage/relationship.js +173 -260
- package/lib-esm/storage/storage.js +236 -499
- package/lib-esm/sync/datastoreConnectivity.js +26 -82
- package/lib-esm/sync/datastoreReachability/index.js +1 -1
- package/lib-esm/sync/datastoreReachability/index.native.js +1 -1
- package/lib-esm/sync/index.js +498 -872
- package/lib-esm/sync/merger.js +28 -131
- package/lib-esm/sync/outbox.js +143 -298
- package/lib-esm/sync/processors/errorMaps.js +32 -82
- package/lib-esm/sync/processors/mutation.js +324 -572
- package/lib-esm/sync/processors/subscription.js +258 -418
- package/lib-esm/sync/processors/sync.js +269 -457
- package/lib-esm/sync/utils.js +245 -390
- package/lib-esm/tsconfig.tsbuildinfo +1 -1
- package/lib-esm/types.js +16 -59
- package/lib-esm/util.js +335 -577
- package/package.json +12 -12
- package/src/datastore/datastore.ts +4 -3
- package/src/storage/adapter/getDefaultAdapter/index.ts +1 -3
- package/src/sync/processors/mutation.ts +1 -1
- package/src/sync/processors/sync.ts +1 -1
- package/src/sync/utils.ts +1 -1
- package/src/util.ts +44 -6
package/lib/predicates/next.js
CHANGED
|
@@ -1,108 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __assign = (this && this.__assign) || function () {
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
-
});
|
|
21
|
-
};
|
|
22
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
24
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
-
function step(op) {
|
|
27
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
-
switch (op[0]) {
|
|
32
|
-
case 0: case 1: t = op; break;
|
|
33
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
-
default:
|
|
37
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
-
if (t[2]) _.ops.pop();
|
|
42
|
-
_.trys.pop(); continue;
|
|
43
|
-
}
|
|
44
|
-
op = body.call(thisArg, _);
|
|
45
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
50
|
-
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
51
|
-
var m = o[Symbol.asyncIterator], i;
|
|
52
|
-
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
53
|
-
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
54
|
-
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
55
|
-
};
|
|
56
|
-
var __read = (this && this.__read) || function (o, n) {
|
|
57
|
-
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
58
|
-
if (!m) return o;
|
|
59
|
-
var i = m.call(o), r, ar = [], e;
|
|
60
|
-
try {
|
|
61
|
-
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
62
|
-
}
|
|
63
|
-
catch (error) { e = { error: error }; }
|
|
64
|
-
finally {
|
|
65
|
-
try {
|
|
66
|
-
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
67
|
-
}
|
|
68
|
-
finally { if (e) throw e.error; }
|
|
69
|
-
}
|
|
70
|
-
return ar;
|
|
71
|
-
};
|
|
72
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
73
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
74
|
-
if (ar || !(i in from)) {
|
|
75
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
76
|
-
ar[i] = from[i];
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
80
|
-
};
|
|
81
|
-
var __values = (this && this.__values) || function(o) {
|
|
82
|
-
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
83
|
-
if (m) return m.call(o);
|
|
84
|
-
if (o && typeof o.length === "number") return {
|
|
85
|
-
next: function () {
|
|
86
|
-
if (o && i >= o.length) o = void 0;
|
|
87
|
-
return { value: o && o[i++], done: !o };
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
91
|
-
};
|
|
92
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
93
3
|
exports.predicateFor = exports.recursivePredicateFor = exports.GroupCondition = exports.FieldCondition = exports.internals = void 0;
|
|
94
4
|
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
95
5
|
// SPDX-License-Identifier: Apache-2.0
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
6
|
+
const types_1 = require("../types");
|
|
7
|
+
const index_1 = require("./index");
|
|
8
|
+
const relationship_1 = require("../storage/relationship");
|
|
9
|
+
const util_1 = require("../util");
|
|
10
|
+
const ops = [...index_1.comparisonKeys];
|
|
101
11
|
/**
|
|
102
12
|
* A map from keys (exposed to customers) to the internal predicate data
|
|
103
13
|
* structures invoking code should not muck with.
|
|
104
14
|
*/
|
|
105
|
-
|
|
15
|
+
const predicateInternalsMap = new Map();
|
|
106
16
|
/**
|
|
107
17
|
* Creates a link between a key (and generates a key if needed) and an internal
|
|
108
18
|
* `GroupCondition`, which allows us to return a key object instead of the gory
|
|
@@ -112,8 +22,8 @@ var predicateInternalsMap = new Map();
|
|
|
112
22
|
* @param key The object DataStore will use to find the internal condition.
|
|
113
23
|
* If no key is given, an empty one is created.
|
|
114
24
|
*/
|
|
115
|
-
|
|
116
|
-
|
|
25
|
+
const registerPredicateInternals = (condition, key) => {
|
|
26
|
+
const finalKey = key || new types_1.PredicateInternalsKey();
|
|
117
27
|
predicateInternalsMap.set(finalKey, condition);
|
|
118
28
|
return finalKey;
|
|
119
29
|
};
|
|
@@ -128,7 +38,7 @@ var registerPredicateInternals = function (condition, key) {
|
|
|
128
38
|
*
|
|
129
39
|
* @param key A key object previously returned by `registerPredicateInternals()`
|
|
130
40
|
*/
|
|
131
|
-
|
|
41
|
+
const internals = (key) => {
|
|
132
42
|
if (!predicateInternalsMap.has(key)) {
|
|
133
43
|
throw new Error("Invalid predicate. Terminate your predicate with a valid condition (e.g., `p => p.field.eq('value')`) or pass `Predicates.ALL`.");
|
|
134
44
|
}
|
|
@@ -139,7 +49,7 @@ exports.internals = internals;
|
|
|
139
49
|
* Maps operators to negated operators.
|
|
140
50
|
* Used to facilitate propagation of negation down a tree of conditions.
|
|
141
51
|
*/
|
|
142
|
-
|
|
52
|
+
const negations = {
|
|
143
53
|
and: 'or',
|
|
144
54
|
or: 'and',
|
|
145
55
|
not: 'and',
|
|
@@ -158,8 +68,8 @@ var negations = {
|
|
|
158
68
|
* @member operator The equality or comparison operator to use.
|
|
159
69
|
* @member operands The operands for the equality/comparison check.
|
|
160
70
|
*/
|
|
161
|
-
|
|
162
|
-
|
|
71
|
+
class FieldCondition {
|
|
72
|
+
constructor(field, operator, operands) {
|
|
163
73
|
this.field = field;
|
|
164
74
|
this.operator = operator;
|
|
165
75
|
this.operands = operands;
|
|
@@ -170,12 +80,12 @@ var FieldCondition = /** @class */ (function () {
|
|
|
170
80
|
* @param extract Not used. Present only to fulfill the `UntypedCondition` interface.
|
|
171
81
|
* @returns A new, identitical `FieldCondition`.
|
|
172
82
|
*/
|
|
173
|
-
|
|
83
|
+
copy(extract) {
|
|
174
84
|
return [
|
|
175
|
-
new FieldCondition(this.field, this.operator,
|
|
85
|
+
new FieldCondition(this.field, this.operator, [...this.operands]),
|
|
176
86
|
undefined,
|
|
177
87
|
];
|
|
178
|
-
}
|
|
88
|
+
}
|
|
179
89
|
/**
|
|
180
90
|
* Produces a tree structure similar to a graphql condition. The returned
|
|
181
91
|
* structure is "dumb" and is intended for another query/condition
|
|
@@ -192,16 +102,15 @@ var FieldCondition = /** @class */ (function () {
|
|
|
192
102
|
* }
|
|
193
103
|
* ```
|
|
194
104
|
*/
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
_b[this.operator] = this.operator === 'between'
|
|
105
|
+
toAST() {
|
|
106
|
+
return {
|
|
107
|
+
[this.field]: {
|
|
108
|
+
[this.operator]: this.operator === 'between'
|
|
200
109
|
? [this.operands[0], this.operands[1]]
|
|
201
110
|
: this.operands[0],
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
205
114
|
/**
|
|
206
115
|
* Produces a new condition (`FieldCondition` or `GroupCondition`) that
|
|
207
116
|
* matches the opposite of this condition.
|
|
@@ -218,7 +127,7 @@ var FieldCondition = /** @class */ (function () {
|
|
|
218
127
|
* @param model The model meta to use when construction a new `GroupCondition`
|
|
219
128
|
* for cases where the negation requires multiple `FieldCondition`'s.
|
|
220
129
|
*/
|
|
221
|
-
|
|
130
|
+
negated(model) {
|
|
222
131
|
if (this.operator === 'between') {
|
|
223
132
|
return new GroupCondition(model, undefined, undefined, 'or', [
|
|
224
133
|
new FieldCondition(this.field, 'lt', [this.operands[0]]),
|
|
@@ -236,77 +145,65 @@ var FieldCondition = /** @class */ (function () {
|
|
|
236
145
|
else {
|
|
237
146
|
return new FieldCondition(this.field, negations[this.operator], this.operands);
|
|
238
147
|
}
|
|
239
|
-
}
|
|
148
|
+
}
|
|
240
149
|
/**
|
|
241
150
|
* Not implemented. Not needed. GroupCondition instead consumes FieldConditions and
|
|
242
151
|
* transforms them into legacy predicates. (*For now.*)
|
|
243
152
|
* @param storage N/A. If ever implemented, the storage adapter to query.
|
|
244
153
|
* @returns N/A. If ever implemented, return items from `storage` that match.
|
|
245
154
|
*/
|
|
246
|
-
|
|
247
|
-
return
|
|
248
|
-
|
|
249
|
-
return [2 /*return*/, Promise.reject('No implementation needed [yet].')];
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
};
|
|
155
|
+
async fetch(storage) {
|
|
156
|
+
return Promise.reject('No implementation needed [yet].');
|
|
157
|
+
}
|
|
253
158
|
/**
|
|
254
159
|
* Determins whether a given item matches the expressed condition.
|
|
255
160
|
* @param item The item to test.
|
|
256
161
|
* @returns `Promise<boolean>`, `true` if matches; `false` otherwise.
|
|
257
162
|
*/
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
else {
|
|
282
|
-
throw new Error("Invalid operator given: ".concat(this.operator));
|
|
283
|
-
}
|
|
284
|
-
return [2 /*return*/];
|
|
285
|
-
});
|
|
286
|
-
});
|
|
287
|
-
};
|
|
163
|
+
async matches(item) {
|
|
164
|
+
const v = item[this.field];
|
|
165
|
+
const operations = {
|
|
166
|
+
eq: () => v === this.operands[0],
|
|
167
|
+
ne: () => v !== this.operands[0],
|
|
168
|
+
gt: () => v > this.operands[0],
|
|
169
|
+
ge: () => v >= this.operands[0],
|
|
170
|
+
lt: () => v < this.operands[0],
|
|
171
|
+
le: () => v <= this.operands[0],
|
|
172
|
+
contains: () => v?.indexOf(this.operands[0]) > -1,
|
|
173
|
+
notContains: () => (!v ? true : v.indexOf(this.operands[0]) === -1),
|
|
174
|
+
beginsWith: () => v?.startsWith(this.operands[0]),
|
|
175
|
+
between: () => v >= this.operands[0] && v <= this.operands[1],
|
|
176
|
+
};
|
|
177
|
+
const operation = operations[this.operator];
|
|
178
|
+
if (operation) {
|
|
179
|
+
const result = operation();
|
|
180
|
+
return result;
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
throw new Error(`Invalid operator given: ${this.operator}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
288
186
|
/**
|
|
289
187
|
* Checks `this.operands` for compatibility with `this.operator`.
|
|
290
188
|
*/
|
|
291
|
-
|
|
292
|
-
var _this = this;
|
|
189
|
+
validate() {
|
|
293
190
|
/**
|
|
294
191
|
* Creates a validator that checks for a particular `operands` count.
|
|
295
192
|
* Throws an exception if the `count` disagrees with `operands.length`.
|
|
296
193
|
* @param count The number of `operands` expected.
|
|
297
194
|
*/
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
return
|
|
301
|
-
if (
|
|
302
|
-
return
|
|
195
|
+
const argumentCount = count => {
|
|
196
|
+
const argsClause = count === 1 ? 'argument is' : 'arguments are';
|
|
197
|
+
return () => {
|
|
198
|
+
if (this.operands.length !== count) {
|
|
199
|
+
return `Exactly ${count} ${argsClause} required.`;
|
|
303
200
|
}
|
|
304
201
|
};
|
|
305
202
|
};
|
|
306
203
|
// NOTE: validations should return a message on failure.
|
|
307
204
|
// hence, they should be "joined" together with logical OR's
|
|
308
205
|
// as seen in the `between:` entry.
|
|
309
|
-
|
|
206
|
+
const validations = {
|
|
310
207
|
eq: argumentCount(1),
|
|
311
208
|
ne: argumentCount(1),
|
|
312
209
|
gt: argumentCount(1),
|
|
@@ -316,34 +213,31 @@ var FieldCondition = /** @class */ (function () {
|
|
|
316
213
|
contains: argumentCount(1),
|
|
317
214
|
notContains: argumentCount(1),
|
|
318
215
|
beginsWith: argumentCount(1),
|
|
319
|
-
between:
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
: null);
|
|
324
|
-
},
|
|
216
|
+
between: () => argumentCount(2)() ||
|
|
217
|
+
(this.operands[0] > this.operands[1]
|
|
218
|
+
? 'The first argument must be less than or equal to the second argument.'
|
|
219
|
+
: null),
|
|
325
220
|
};
|
|
326
|
-
|
|
221
|
+
const validate = validations[this.operator];
|
|
327
222
|
if (validate) {
|
|
328
|
-
|
|
223
|
+
const e = validate();
|
|
329
224
|
if (typeof e === 'string')
|
|
330
|
-
throw new Error(
|
|
225
|
+
throw new Error(`Incorrect usage of \`${this.operator}()\`: ${e}`);
|
|
331
226
|
}
|
|
332
227
|
else {
|
|
333
|
-
throw new Error(
|
|
228
|
+
throw new Error(`Non-existent operator: \`${this.operator}()\``);
|
|
334
229
|
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
}());
|
|
230
|
+
}
|
|
231
|
+
}
|
|
338
232
|
exports.FieldCondition = FieldCondition;
|
|
339
233
|
/**
|
|
340
234
|
* Small utility function to generate a monotonically increasing ID.
|
|
341
235
|
* Used by GroupCondition to help keep track of which group is doing what,
|
|
342
236
|
* when, and where during troubleshooting.
|
|
343
237
|
*/
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
return
|
|
238
|
+
const getGroupId = (() => {
|
|
239
|
+
let seed = 1;
|
|
240
|
+
return () => `group_${seed++}`;
|
|
347
241
|
})();
|
|
348
242
|
/**
|
|
349
243
|
* A set of sub-conditions to operate against a model, optionally scoped to
|
|
@@ -355,8 +249,8 @@ var getGroupId = (function () {
|
|
|
355
249
|
* @member operator How to group child conditions together.
|
|
356
250
|
* @member operands The child conditions.
|
|
357
251
|
*/
|
|
358
|
-
|
|
359
|
-
|
|
252
|
+
class GroupCondition {
|
|
253
|
+
constructor(
|
|
360
254
|
/**
|
|
361
255
|
* The `ModelMeta` of the model to query and/or filter against.
|
|
362
256
|
* Expected to contain:
|
|
@@ -400,8 +294,7 @@ var GroupCondition = /** @class */ (function () {
|
|
|
400
294
|
* This is used to guard against infinitely fetch -> optimize -> fetch
|
|
401
295
|
* recursion.
|
|
402
296
|
*/
|
|
403
|
-
isOptimized) {
|
|
404
|
-
if (isOptimized === void 0) { isOptimized = false; }
|
|
297
|
+
isOptimized = false) {
|
|
405
298
|
this.model = model;
|
|
406
299
|
this.field = field;
|
|
407
300
|
this.relationshipType = relationshipType;
|
|
@@ -418,16 +311,16 @@ var GroupCondition = /** @class */ (function () {
|
|
|
418
311
|
* @param extract A node of interest. Its copy will *also* be returned if the node exists.
|
|
419
312
|
* @returns [The full copy, the copy of `extract` | undefined]
|
|
420
313
|
*/
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
this.operands.forEach(
|
|
425
|
-
|
|
314
|
+
copy(extract) {
|
|
315
|
+
const copied = new GroupCondition(this.model, this.field, this.relationshipType, this.operator, []);
|
|
316
|
+
let extractedCopy = extract === this ? copied : undefined;
|
|
317
|
+
this.operands.forEach(o => {
|
|
318
|
+
const [operandCopy, extractedFromOperand] = o.copy(extract);
|
|
426
319
|
copied.operands.push(operandCopy);
|
|
427
320
|
extractedCopy = extractedCopy || extractedFromOperand;
|
|
428
321
|
});
|
|
429
322
|
return [copied, extractedCopy];
|
|
430
|
-
}
|
|
323
|
+
}
|
|
431
324
|
/**
|
|
432
325
|
* Creates a new `GroupCondition` that contains only the local field conditions,
|
|
433
326
|
* omitting related model conditions. That resulting `GroupCondition` can be
|
|
@@ -437,15 +330,12 @@ var GroupCondition = /** @class */ (function () {
|
|
|
437
330
|
* @param negate Whether the condition tree should be negated according
|
|
438
331
|
* to De Morgan's law.
|
|
439
332
|
*/
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
var negateChildren = negate !== (this.operator === 'not');
|
|
333
|
+
withFieldConditionsOnly(negate) {
|
|
334
|
+
const negateChildren = negate !== (this.operator === 'not');
|
|
443
335
|
return new GroupCondition(this.model, undefined, undefined, (negate ? negations[this.operator] : this.operator), this.operands
|
|
444
|
-
.filter(
|
|
445
|
-
.map(
|
|
446
|
-
|
|
447
|
-
}));
|
|
448
|
-
};
|
|
336
|
+
.filter(o => o instanceof FieldCondition)
|
|
337
|
+
.map(o => negateChildren ? o.negated(this.model) : o));
|
|
338
|
+
}
|
|
449
339
|
/**
|
|
450
340
|
* Returns a version of the predicate tree with unnecessary logical groups
|
|
451
341
|
* condensed and merged together. This is intended to create a dense tree
|
|
@@ -482,12 +372,8 @@ var GroupCondition = /** @class */ (function () {
|
|
|
482
372
|
* `not` groups. `not` groups will always have a single child, so there's nothing to
|
|
483
373
|
* optimize below a `not` (for now), and it makes the query logic simpler later.
|
|
484
374
|
*/
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
if (preserveNode === void 0) { preserveNode = true; }
|
|
488
|
-
var operands = this.operands.map(function (o) {
|
|
489
|
-
return o instanceof GroupCondition ? o.optimized(_this.operator === 'not') : o;
|
|
490
|
-
});
|
|
375
|
+
optimized(preserveNode = true) {
|
|
376
|
+
const operands = this.operands.map(o => o instanceof GroupCondition ? o.optimized(this.operator === 'not') : o);
|
|
491
377
|
// we're only collapsing and/or groups that contains a single child for now,
|
|
492
378
|
// because they're much more common and much more trivial to collapse. basically,
|
|
493
379
|
// an `and`/`or` that contains a single child doesn't require the layer of
|
|
@@ -496,7 +382,7 @@ var GroupCondition = /** @class */ (function () {
|
|
|
496
382
|
['and', 'or'].includes(this.operator) &&
|
|
497
383
|
!this.field &&
|
|
498
384
|
operands.length === 1) {
|
|
499
|
-
|
|
385
|
+
const operand = operands[0];
|
|
500
386
|
if (operand instanceof FieldCondition) {
|
|
501
387
|
// between conditions should NOT be passed up the chain. if they
|
|
502
388
|
// need to be *negated* later, it is important that they be properly
|
|
@@ -512,7 +398,7 @@ var GroupCondition = /** @class */ (function () {
|
|
|
512
398
|
}
|
|
513
399
|
}
|
|
514
400
|
return new GroupCondition(this.model, this.field, this.relationshipType, this.operator, operands, true);
|
|
515
|
-
}
|
|
401
|
+
}
|
|
516
402
|
/**
|
|
517
403
|
* Fetches matching records from a given storage adapter using legacy predicates (for now).
|
|
518
404
|
* @param storage The storage adapter this predicate will query against.
|
|
@@ -521,211 +407,134 @@ var GroupCondition = /** @class */ (function () {
|
|
|
521
407
|
* @param negate Whether to match on the `NOT` of `this`.
|
|
522
408
|
* @returns An `Promise` of `any[]` from `storage` matching the child conditions.
|
|
523
409
|
*/
|
|
524
|
-
|
|
525
|
-
if (
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
relative = relatives_1_1.value;
|
|
587
|
-
relativeConditions = [];
|
|
588
|
-
for (i = 0; i < relationship.localJoinFields.length; i++) {
|
|
589
|
-
relativeConditions.push((_l = {},
|
|
590
|
-
_l[relationship.localJoinFields[i]] = {
|
|
591
|
-
eq: relative[relationship.remoteJoinFields[i]],
|
|
592
|
-
},
|
|
593
|
-
_l));
|
|
594
|
-
}
|
|
595
|
-
allJoinConditions.push({ and: relativeConditions });
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
599
|
-
finally {
|
|
600
|
-
try {
|
|
601
|
-
if (relatives_1_1 && !relatives_1_1.done && (_k = relatives_1.return)) _k.call(relatives_1);
|
|
602
|
-
}
|
|
603
|
-
finally { if (e_2) throw e_2.error; }
|
|
604
|
-
}
|
|
605
|
-
predicate = index_1.ModelPredicateCreator.createFromAST(this.model.schema, {
|
|
606
|
-
or: allJoinConditions,
|
|
607
|
-
});
|
|
608
|
-
_b = (_a = resultGroups).push;
|
|
609
|
-
return [4 /*yield*/, storage.query(this.model.builder, predicate)];
|
|
610
|
-
case 4:
|
|
611
|
-
_b.apply(_a, [_r.sent()]);
|
|
612
|
-
return [3 /*break*/, 6];
|
|
613
|
-
case 5: throw new Error('Missing field metadata.');
|
|
614
|
-
case 6: return [3 /*break*/, 8];
|
|
615
|
-
case 7:
|
|
616
|
-
// relatives are not actually relatives. they're candidate results.
|
|
617
|
-
resultGroups.push(relatives);
|
|
618
|
-
_r.label = 8;
|
|
619
|
-
case 8:
|
|
620
|
-
groups_1_1 = groups_1.next();
|
|
621
|
-
return [3 /*break*/, 2];
|
|
622
|
-
case 9: return [3 /*break*/, 12];
|
|
623
|
-
case 10:
|
|
624
|
-
e_1_1 = _r.sent();
|
|
625
|
-
e_1 = { error: e_1_1 };
|
|
626
|
-
return [3 /*break*/, 12];
|
|
627
|
-
case 11:
|
|
628
|
-
try {
|
|
629
|
-
if (groups_1_1 && !groups_1_1.done && (_j = groups_1.return)) _j.call(groups_1);
|
|
630
|
-
}
|
|
631
|
-
finally { if (e_1) throw e_1.error; }
|
|
632
|
-
return [7 /*endfinally*/];
|
|
633
|
-
case 12:
|
|
634
|
-
if (!(conditions.length > 0)) return [3 /*break*/, 14];
|
|
635
|
-
predicate = this.withFieldConditionsOnly(negateChildren).toStoragePredicate();
|
|
636
|
-
_d = (_c = resultGroups).push;
|
|
637
|
-
return [4 /*yield*/, storage.query(this.model.builder, predicate)];
|
|
638
|
-
case 13:
|
|
639
|
-
_d.apply(_c, [_r.sent()]);
|
|
640
|
-
return [3 /*break*/, 16];
|
|
641
|
-
case 14:
|
|
642
|
-
if (!(conditions.length === 0 && resultGroups.length === 0)) return [3 /*break*/, 16];
|
|
643
|
-
_f = (_e = resultGroups).push;
|
|
644
|
-
return [4 /*yield*/, storage.query(this.model.builder)];
|
|
645
|
-
case 15:
|
|
646
|
-
_f.apply(_e, [_r.sent()]);
|
|
647
|
-
_r.label = 16;
|
|
648
|
-
case 16:
|
|
649
|
-
getPKValue = function (item) {
|
|
650
|
-
return JSON.stringify(_this.model.pkField.map(function (name) { return item[name]; }));
|
|
651
|
-
};
|
|
652
|
-
if (operator === 'and') {
|
|
653
|
-
if (resultGroups.length === 0) {
|
|
654
|
-
return [2 /*return*/, []];
|
|
655
|
-
}
|
|
656
|
-
try {
|
|
657
|
-
// for each group, we intersect, removing items from the result index
|
|
658
|
-
// that aren't present in each subsequent group.
|
|
659
|
-
for (resultGroups_1 = __values(resultGroups), resultGroups_1_1 = resultGroups_1.next(); !resultGroups_1_1.done; resultGroups_1_1 = resultGroups_1.next()) {
|
|
660
|
-
group = resultGroups_1_1.value;
|
|
661
|
-
if (resultIndex === undefined) {
|
|
662
|
-
resultIndex = new Map(group.map(function (item) { return [getPKValue(item), item]; }));
|
|
663
|
-
}
|
|
664
|
-
else {
|
|
665
|
-
intersectWith = new Map(group.map(function (item) { return [getPKValue(item), item]; }));
|
|
666
|
-
try {
|
|
667
|
-
for (_g = (e_4 = void 0, __values(resultIndex.keys())), _h = _g.next(); !_h.done; _h = _g.next()) {
|
|
668
|
-
k = _h.value;
|
|
669
|
-
if (!intersectWith.has(k)) {
|
|
670
|
-
resultIndex.delete(k);
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
675
|
-
finally {
|
|
676
|
-
try {
|
|
677
|
-
if (_h && !_h.done && (_o = _g.return)) _o.call(_g);
|
|
678
|
-
}
|
|
679
|
-
finally { if (e_4) throw e_4.error; }
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
685
|
-
finally {
|
|
686
|
-
try {
|
|
687
|
-
if (resultGroups_1_1 && !resultGroups_1_1.done && (_m = resultGroups_1.return)) _m.call(resultGroups_1);
|
|
688
|
-
}
|
|
689
|
-
finally { if (e_3) throw e_3.error; }
|
|
690
|
-
}
|
|
410
|
+
async fetch(storage, breadcrumb = [], negate = false) {
|
|
411
|
+
if (!this.isOptimized) {
|
|
412
|
+
return this.optimized().fetch(storage);
|
|
413
|
+
}
|
|
414
|
+
const resultGroups = [];
|
|
415
|
+
const operator = (negate ? negations[this.operator] : this.operator);
|
|
416
|
+
const negateChildren = negate !== (this.operator === 'not');
|
|
417
|
+
/**
|
|
418
|
+
* Conditions that must be branched out and used to generate a base, "candidate"
|
|
419
|
+
* result set.
|
|
420
|
+
*
|
|
421
|
+
* If `field` is populated, these groups select *related* records, and the base,
|
|
422
|
+
* candidate results are selected to match those.
|
|
423
|
+
*/
|
|
424
|
+
const groups = this.operands.filter(op => op instanceof GroupCondition);
|
|
425
|
+
/**
|
|
426
|
+
* Simple conditions that must match the target model of `this`.
|
|
427
|
+
*/
|
|
428
|
+
const conditions = this.operands.filter(op => op instanceof FieldCondition);
|
|
429
|
+
for (const g of groups) {
|
|
430
|
+
const relatives = await g.fetch(storage, [...breadcrumb, this.groupId], negateChildren);
|
|
431
|
+
// no relatives -> no need to attempt to perform a "join" query for
|
|
432
|
+
// candidate results:
|
|
433
|
+
//
|
|
434
|
+
// select a.* from a,b where b.id in EMPTY_SET ==> EMPTY_SET
|
|
435
|
+
//
|
|
436
|
+
// Additionally, the entire (sub)-query can be short-circuited if
|
|
437
|
+
// the operator is `AND`. Illustrated in SQL:
|
|
438
|
+
//
|
|
439
|
+
// select a.* from a where
|
|
440
|
+
// id in [a,b,c]
|
|
441
|
+
// AND <
|
|
442
|
+
// id in EMTPY_SET <<< Look!
|
|
443
|
+
// AND <
|
|
444
|
+
// id in [x,y,z]
|
|
445
|
+
//
|
|
446
|
+
// YIELDS: EMPTY_SET // <-- Easy peasy. Lemon squeezy.
|
|
447
|
+
//
|
|
448
|
+
if (relatives.length === 0) {
|
|
449
|
+
// aggressively short-circuit as soon as we know the group condition will fail
|
|
450
|
+
if (operator === 'and') {
|
|
451
|
+
return [];
|
|
452
|
+
}
|
|
453
|
+
// less aggressive short-circuit if we know the relatives will produce no
|
|
454
|
+
// candidate results; but aren't sure yet how this affects the group condition.
|
|
455
|
+
resultGroups.push([]);
|
|
456
|
+
continue;
|
|
457
|
+
}
|
|
458
|
+
if (g.field) {
|
|
459
|
+
// `relatives` are actual relatives. We'll skim them for FK query values.
|
|
460
|
+
// Use the relatives to add candidate result sets (`resultGroups`)
|
|
461
|
+
const relationship = relationship_1.ModelRelationship.from(this.model, g.field);
|
|
462
|
+
if (relationship) {
|
|
463
|
+
const allJoinConditions = [];
|
|
464
|
+
for (const relative of relatives) {
|
|
465
|
+
const relativeConditions = [];
|
|
466
|
+
for (let i = 0; i < relationship.localJoinFields.length; i++) {
|
|
467
|
+
relativeConditions.push({
|
|
468
|
+
[relationship.localJoinFields[i]]: {
|
|
469
|
+
eq: relative[relationship.remoteJoinFields[i]],
|
|
470
|
+
},
|
|
471
|
+
});
|
|
691
472
|
}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
473
|
+
allJoinConditions.push({ and: relativeConditions });
|
|
474
|
+
}
|
|
475
|
+
const predicate = index_1.ModelPredicateCreator.createFromAST(this.model.schema, {
|
|
476
|
+
or: allJoinConditions,
|
|
477
|
+
});
|
|
478
|
+
resultGroups.push(await storage.query(this.model.builder, predicate));
|
|
479
|
+
}
|
|
480
|
+
else {
|
|
481
|
+
throw new Error('Missing field metadata.');
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
else {
|
|
485
|
+
// relatives are not actually relatives. they're candidate results.
|
|
486
|
+
resultGroups.push(relatives);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
// if conditions is empty at this point, child predicates found no matches.
|
|
490
|
+
// i.e., we can stop looking and return empty.
|
|
491
|
+
if (conditions.length > 0) {
|
|
492
|
+
const predicate = this.withFieldConditionsOnly(negateChildren).toStoragePredicate();
|
|
493
|
+
resultGroups.push(await storage.query(this.model.builder, predicate));
|
|
494
|
+
}
|
|
495
|
+
else if (conditions.length === 0 && resultGroups.length === 0) {
|
|
496
|
+
resultGroups.push(await storage.query(this.model.builder));
|
|
497
|
+
}
|
|
498
|
+
// PK might be a single field, like `id`, or it might be several fields.
|
|
499
|
+
// so, we'll need to extract the list of PK fields from an object
|
|
500
|
+
// and stringify the list for easy comparison / merging.
|
|
501
|
+
const getPKValue = item => JSON.stringify(this.model.pkField.map(name => item[name]));
|
|
502
|
+
// will be used for intersecting or unioning results
|
|
503
|
+
let resultIndex;
|
|
504
|
+
if (operator === 'and') {
|
|
505
|
+
if (resultGroups.length === 0) {
|
|
506
|
+
return [];
|
|
507
|
+
}
|
|
508
|
+
// for each group, we intersect, removing items from the result index
|
|
509
|
+
// that aren't present in each subsequent group.
|
|
510
|
+
for (const group of resultGroups) {
|
|
511
|
+
if (resultIndex === undefined) {
|
|
512
|
+
resultIndex = new Map(group.map(item => [getPKValue(item), item]));
|
|
513
|
+
}
|
|
514
|
+
else {
|
|
515
|
+
const intersectWith = new Map(group.map(item => [getPKValue(item), item]));
|
|
516
|
+
for (const k of resultIndex.keys()) {
|
|
517
|
+
if (!intersectWith.has(k)) {
|
|
518
|
+
resultIndex.delete(k);
|
|
723
519
|
}
|
|
724
|
-
|
|
520
|
+
}
|
|
725
521
|
}
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
else if (operator === 'or' || operator === 'not') {
|
|
525
|
+
// it's OK to handle NOT here, because NOT must always only negate
|
|
526
|
+
// a single child predicate. NOT logic will have been distributed down
|
|
527
|
+
// to the leaf conditions already.
|
|
528
|
+
resultIndex = new Map();
|
|
529
|
+
// just merge the groups, performing DISTINCT-ification by ID.
|
|
530
|
+
for (const group of resultGroups) {
|
|
531
|
+
for (const item of group) {
|
|
532
|
+
resultIndex.set(getPKValue(item), item);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
return Array.from(resultIndex?.values() || []);
|
|
537
|
+
}
|
|
729
538
|
/**
|
|
730
539
|
* Determines whether a single item matches the conditions of `this`.
|
|
731
540
|
* When checking the target `item`'s properties, each property will be `await`'d
|
|
@@ -735,119 +544,67 @@ var GroupCondition = /** @class */ (function () {
|
|
|
735
544
|
* (Used for iterating over children on HAS_MANY checks.)
|
|
736
545
|
* @returns A boolean (promise): `true` if matched, `false` otherwise.
|
|
737
546
|
*/
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
if
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
case 2:
|
|
752
|
-
_d = item;
|
|
753
|
-
_f.label = 3;
|
|
754
|
-
case 3:
|
|
755
|
-
itemToCheck = _d;
|
|
756
|
-
// if there is no item to check, we can stop recursing immediately.
|
|
757
|
-
// a condition cannot match against an item that does not exist. this
|
|
758
|
-
// can occur when `item.field` is optional in the schema.
|
|
759
|
-
if (!itemToCheck) {
|
|
760
|
-
return [2 /*return*/, false];
|
|
761
|
-
}
|
|
762
|
-
if (!(this.relationshipType === 'HAS_MANY' &&
|
|
763
|
-
typeof itemToCheck[Symbol.asyncIterator] === 'function')) return [3 /*break*/, 19];
|
|
764
|
-
_f.label = 4;
|
|
765
|
-
case 4:
|
|
766
|
-
_f.trys.push([4, 12, 13, 18]);
|
|
767
|
-
_e = true, itemToCheck_1 = __asyncValues(itemToCheck);
|
|
768
|
-
_f.label = 5;
|
|
769
|
-
case 5: return [4 /*yield*/, itemToCheck_1.next()];
|
|
770
|
-
case 6:
|
|
771
|
-
if (!(itemToCheck_1_1 = _f.sent(), _a = itemToCheck_1_1.done, !_a)) return [3 /*break*/, 11];
|
|
772
|
-
_c = itemToCheck_1_1.value;
|
|
773
|
-
_e = false;
|
|
774
|
-
_f.label = 7;
|
|
775
|
-
case 7:
|
|
776
|
-
_f.trys.push([7, , 9, 10]);
|
|
777
|
-
singleItem = _c;
|
|
778
|
-
return [4 /*yield*/, this.matches(singleItem, true)];
|
|
779
|
-
case 8:
|
|
780
|
-
if (_f.sent()) {
|
|
781
|
-
return [2 /*return*/, true];
|
|
782
|
-
}
|
|
783
|
-
return [3 /*break*/, 10];
|
|
784
|
-
case 9:
|
|
785
|
-
_e = true;
|
|
786
|
-
return [7 /*endfinally*/];
|
|
787
|
-
case 10: return [3 /*break*/, 5];
|
|
788
|
-
case 11: return [3 /*break*/, 18];
|
|
789
|
-
case 12:
|
|
790
|
-
e_7_1 = _f.sent();
|
|
791
|
-
e_7 = { error: e_7_1 };
|
|
792
|
-
return [3 /*break*/, 18];
|
|
793
|
-
case 13:
|
|
794
|
-
_f.trys.push([13, , 16, 17]);
|
|
795
|
-
if (!(!_e && !_a && (_b = itemToCheck_1.return))) return [3 /*break*/, 15];
|
|
796
|
-
return [4 /*yield*/, _b.call(itemToCheck_1)];
|
|
797
|
-
case 14:
|
|
798
|
-
_f.sent();
|
|
799
|
-
_f.label = 15;
|
|
800
|
-
case 15: return [3 /*break*/, 17];
|
|
801
|
-
case 16:
|
|
802
|
-
if (e_7) throw e_7.error;
|
|
803
|
-
return [7 /*endfinally*/];
|
|
804
|
-
case 17: return [7 /*endfinally*/];
|
|
805
|
-
case 18: return [2 /*return*/, false];
|
|
806
|
-
case 19:
|
|
807
|
-
if (!(this.operator === 'or')) return [3 /*break*/, 20];
|
|
808
|
-
return [2 /*return*/, (0, util_1.asyncSome)(this.operands, function (c) { return c.matches(itemToCheck); })];
|
|
809
|
-
case 20:
|
|
810
|
-
if (!(this.operator === 'and')) return [3 /*break*/, 21];
|
|
811
|
-
return [2 /*return*/, (0, util_1.asyncEvery)(this.operands, function (c) { return c.matches(itemToCheck); })];
|
|
812
|
-
case 21:
|
|
813
|
-
if (!(this.operator === 'not')) return [3 /*break*/, 23];
|
|
814
|
-
if (this.operands.length !== 1) {
|
|
815
|
-
throw new Error('Invalid arguments! `not()` accepts exactly one predicate expression.');
|
|
816
|
-
}
|
|
817
|
-
return [4 /*yield*/, this.operands[0].matches(itemToCheck)];
|
|
818
|
-
case 22: return [2 /*return*/, !(_f.sent())];
|
|
819
|
-
case 23: throw new Error('Invalid group operator!');
|
|
547
|
+
async matches(item, ignoreFieldName = false) {
|
|
548
|
+
const itemToCheck = this.field && !ignoreFieldName ? await item[this.field] : item;
|
|
549
|
+
// if there is no item to check, we can stop recursing immediately.
|
|
550
|
+
// a condition cannot match against an item that does not exist. this
|
|
551
|
+
// can occur when `item.field` is optional in the schema.
|
|
552
|
+
if (!itemToCheck) {
|
|
553
|
+
return false;
|
|
554
|
+
}
|
|
555
|
+
if (this.relationshipType === 'HAS_MANY' &&
|
|
556
|
+
typeof itemToCheck[Symbol.asyncIterator] === 'function') {
|
|
557
|
+
for await (const singleItem of itemToCheck) {
|
|
558
|
+
if (await this.matches(singleItem, true)) {
|
|
559
|
+
return true;
|
|
820
560
|
}
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
|
|
561
|
+
}
|
|
562
|
+
return false;
|
|
563
|
+
}
|
|
564
|
+
if (this.operator === 'or') {
|
|
565
|
+
return (0, util_1.asyncSome)(this.operands, c => c.matches(itemToCheck));
|
|
566
|
+
}
|
|
567
|
+
else if (this.operator === 'and') {
|
|
568
|
+
return (0, util_1.asyncEvery)(this.operands, c => c.matches(itemToCheck));
|
|
569
|
+
}
|
|
570
|
+
else if (this.operator === 'not') {
|
|
571
|
+
if (this.operands.length !== 1) {
|
|
572
|
+
throw new Error('Invalid arguments! `not()` accepts exactly one predicate expression.');
|
|
573
|
+
}
|
|
574
|
+
return !(await this.operands[0].matches(itemToCheck));
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
throw new Error('Invalid group operator!');
|
|
578
|
+
}
|
|
579
|
+
}
|
|
824
580
|
/**
|
|
825
581
|
* Tranfsorm to a AppSync GraphQL compatible AST.
|
|
826
582
|
* (Does not support filtering in nested types.)
|
|
827
583
|
*/
|
|
828
|
-
|
|
829
|
-
var _a;
|
|
584
|
+
toAST() {
|
|
830
585
|
if (this.field)
|
|
831
586
|
throw new Error('Nested type conditions are not supported!');
|
|
832
|
-
return
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
}
|
|
587
|
+
return {
|
|
588
|
+
[this.operator]: this.operands.map(operand => operand.toAST()),
|
|
589
|
+
};
|
|
590
|
+
}
|
|
836
591
|
/**
|
|
837
592
|
* Turn this predicate group into something a storage adapter
|
|
838
593
|
* understands how to use.
|
|
839
594
|
*/
|
|
840
|
-
|
|
595
|
+
toStoragePredicate() {
|
|
841
596
|
return index_1.ModelPredicateCreator.createFromAST(this.model.schema, this.toAST());
|
|
842
|
-
}
|
|
597
|
+
}
|
|
843
598
|
/**
|
|
844
599
|
* A JSON representation that's good for debugging.
|
|
845
600
|
*/
|
|
846
|
-
|
|
847
|
-
return
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
}
|
|
601
|
+
toJSON() {
|
|
602
|
+
return {
|
|
603
|
+
...this,
|
|
604
|
+
model: this.model.schema.name,
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
}
|
|
851
608
|
exports.GroupCondition = GroupCondition;
|
|
852
609
|
/**
|
|
853
610
|
* Creates a "seed" predicate that can be used to build an executable condition.
|
|
@@ -876,49 +633,48 @@ exports.GroupCondition = GroupCondition;
|
|
|
876
633
|
* @returns A ModelPredicate (builder) that customers can create queries with.
|
|
877
634
|
* (As shown in function description.)
|
|
878
635
|
*/
|
|
879
|
-
function recursivePredicateFor(ModelType, allowRecursion, field, query, tail) {
|
|
880
|
-
if (allowRecursion === void 0) { allowRecursion = true; }
|
|
636
|
+
function recursivePredicateFor(ModelType, allowRecursion = true, field, query, tail) {
|
|
881
637
|
// to be used if we don't have a base query or tail to build onto
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
638
|
+
const starter = new GroupCondition(ModelType, field, undefined, 'and', []);
|
|
639
|
+
const baseCondition = query && tail ? query : starter;
|
|
640
|
+
const tailCondition = query && tail ? tail : starter;
|
|
885
641
|
// our eventual return object, which can be built upon.
|
|
886
642
|
// next steps will be to add or(), and(), not(), and field.op() methods.
|
|
887
|
-
|
|
643
|
+
const link = {};
|
|
888
644
|
// so it can be looked up later with in the internals when processing conditions.
|
|
889
645
|
registerPredicateInternals(baseCondition, link);
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
return { query
|
|
646
|
+
const copyLink = () => {
|
|
647
|
+
const [query, newTail] = baseCondition.copy(tailCondition);
|
|
648
|
+
const newLink = recursivePredicateFor(ModelType, allowRecursion, undefined, query, newTail);
|
|
649
|
+
return { query, newTail, newLink };
|
|
894
650
|
};
|
|
895
651
|
// Adds .or() and .and() methods to the link.
|
|
896
652
|
// TODO: If revisiting this code, consider writing a Proxy instead.
|
|
897
|
-
['and', 'or'].forEach(
|
|
898
|
-
link[op] =
|
|
653
|
+
['and', 'or'].forEach(op => {
|
|
654
|
+
link[op] = (builder) => {
|
|
899
655
|
// or() and and() will return a copy of the original link
|
|
900
656
|
// to head off mutability concerns.
|
|
901
|
-
|
|
902
|
-
|
|
657
|
+
const { query, newTail } = copyLink();
|
|
658
|
+
const childConditions = builder(recursivePredicateFor(ModelType, allowRecursion));
|
|
903
659
|
if (!Array.isArray(childConditions)) {
|
|
904
|
-
throw new Error(
|
|
660
|
+
throw new Error(`Invalid predicate. \`${op}\` groups must return an array of child conditions.`);
|
|
905
661
|
}
|
|
906
662
|
// the customer will supply a child predicate, which apply to the `model.field`
|
|
907
663
|
// of the tail GroupCondition.
|
|
908
|
-
newTail
|
|
664
|
+
newTail?.operands.push(new GroupCondition(ModelType, field, undefined, op, childConditions.map(c => (0, exports.internals)(c))));
|
|
909
665
|
// FinalPredicate
|
|
910
666
|
return registerPredicateInternals(query);
|
|
911
667
|
};
|
|
912
668
|
});
|
|
913
669
|
// TODO: If revisiting this code, consider proxy.
|
|
914
|
-
link.not =
|
|
670
|
+
link.not = (builder) => {
|
|
915
671
|
// not() will return a copy of the original link
|
|
916
672
|
// to head off mutability concerns.
|
|
917
|
-
|
|
673
|
+
const { query, newTail } = copyLink();
|
|
918
674
|
// unlike and() and or(), the customer will supply a "singular" child predicate.
|
|
919
675
|
// the difference being: not() does not accept an array of predicate-like objects.
|
|
920
676
|
// it negates only a *single* predicate subtree.
|
|
921
|
-
newTail
|
|
677
|
+
newTail?.operands.push(new GroupCondition(ModelType, field, undefined, 'not', [
|
|
922
678
|
(0, exports.internals)(builder(recursivePredicateFor(ModelType, allowRecursion))),
|
|
923
679
|
]));
|
|
924
680
|
// A `FinalModelPredicate`.
|
|
@@ -926,39 +682,42 @@ function recursivePredicateFor(ModelType, allowRecursion, field, query, tail) {
|
|
|
926
682
|
// or query storage: `.__query.fetch(storage)`.
|
|
927
683
|
return registerPredicateInternals(query);
|
|
928
684
|
};
|
|
929
|
-
|
|
685
|
+
// For each field on the model schema, we want to add a getter
|
|
686
|
+
// that creates the appropriate new `link` in the query chain.
|
|
687
|
+
// TODO: If revisiting, consider a proxy.
|
|
688
|
+
for (const fieldName in ModelType.schema.allFields) {
|
|
930
689
|
Object.defineProperty(link, fieldName, {
|
|
931
690
|
enumerable: true,
|
|
932
|
-
get:
|
|
933
|
-
|
|
691
|
+
get: () => {
|
|
692
|
+
const def = ModelType.schema.allFields[fieldName];
|
|
934
693
|
if (!def.association) {
|
|
935
694
|
// we're looking at a value field. we need to return a
|
|
936
695
|
// "field matcher object", which contains all of the comparison
|
|
937
696
|
// functions ('eq', 'ne', 'gt', etc.), scoped to operate
|
|
938
697
|
// against the target field (fieldName).
|
|
939
|
-
return ops.reduce(
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
}
|
|
698
|
+
return ops.reduce((fieldMatcher, operator) => {
|
|
699
|
+
return {
|
|
700
|
+
...fieldMatcher,
|
|
701
|
+
// each operator on the fieldMatcher objcect is a function.
|
|
702
|
+
// when the customer calls the function, it returns a new link
|
|
703
|
+
// in the chain -- for now -- this is the "leaf" link that
|
|
704
|
+
// cannot be further extended.
|
|
705
|
+
[operator]: (...operands) => {
|
|
706
|
+
// build off a fresh copy of the existing `link`, just in case
|
|
707
|
+
// the same link is being used elsewhere by the customer.
|
|
708
|
+
const { query, newTail } = copyLink();
|
|
709
|
+
// normalize operands. if any of the values are `undefiend`, use
|
|
710
|
+
// `null` instead, because that's what will be stored cross-platform.
|
|
711
|
+
const normalizedOperands = operands.map(o => o === undefined ? null : o);
|
|
712
|
+
// add the given condition to the link's TAIL node.
|
|
713
|
+
// remember: the base link might go N nodes deep! e.g.,
|
|
714
|
+
newTail?.operands.push(new FieldCondition(fieldName, operator, normalizedOperands));
|
|
715
|
+
// A `FinalModelPredicate`.
|
|
716
|
+
// Return a thing that can no longer be extended, but instead used to `async filter(items)`
|
|
717
|
+
// or query storage: `.__query.fetch(storage)`.
|
|
718
|
+
return registerPredicateInternals(query);
|
|
719
|
+
},
|
|
720
|
+
};
|
|
962
721
|
}, {});
|
|
963
722
|
}
|
|
964
723
|
else {
|
|
@@ -970,20 +729,20 @@ function recursivePredicateFor(ModelType, allowRecursion, field, query, tail) {
|
|
|
970
729
|
def.association.connectionType === 'HAS_MANY') {
|
|
971
730
|
// the use has just typed '.someRelatedModel'. we need to given them
|
|
972
731
|
// back a predicate chain.
|
|
973
|
-
|
|
732
|
+
const relatedMeta = def.type.modelConstructor;
|
|
974
733
|
if (!relatedMeta) {
|
|
975
734
|
throw new Error('Related model metadata is missing. This is a bug! Please report it.');
|
|
976
735
|
}
|
|
977
736
|
// `Model.reletedModelField` returns a copy of the original link,
|
|
978
737
|
// and will contains copies of internal GroupConditions
|
|
979
738
|
// to head off mutability concerns.
|
|
980
|
-
|
|
981
|
-
|
|
739
|
+
const [newquery, oldtail] = baseCondition.copy(tailCondition);
|
|
740
|
+
const newtail = new GroupCondition(relatedMeta, fieldName, def.association.connectionType, 'and', []);
|
|
982
741
|
// `oldtail` here refers to the *copy* of the old tail.
|
|
983
742
|
// so, it's safe to modify at this point. and we need to modify
|
|
984
743
|
// it to push the *new* tail onto the end of it.
|
|
985
744
|
oldtail.operands.push(newtail);
|
|
986
|
-
|
|
745
|
+
const newlink = recursivePredicateFor(relatedMeta, allowRecursion, undefined, newquery, newtail);
|
|
987
746
|
return newlink;
|
|
988
747
|
}
|
|
989
748
|
else {
|
|
@@ -992,12 +751,6 @@ function recursivePredicateFor(ModelType, allowRecursion, field, query, tail) {
|
|
|
992
751
|
}
|
|
993
752
|
},
|
|
994
753
|
});
|
|
995
|
-
};
|
|
996
|
-
// For each field on the model schema, we want to add a getter
|
|
997
|
-
// that creates the appropriate new `link` in the query chain.
|
|
998
|
-
// TODO: If revisiting, consider a proxy.
|
|
999
|
-
for (var fieldName in ModelType.schema.allFields) {
|
|
1000
|
-
_loop_1(fieldName);
|
|
1001
754
|
}
|
|
1002
755
|
return link;
|
|
1003
756
|
}
|