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