@_linked/core 1.3.0 → 2.0.0-next.20260310085832
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +113 -10
- package/README.md +209 -14
- package/lib/cjs/index.d.ts +10 -2
- package/lib/cjs/index.js +31 -6
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/package.d.ts +1 -1
- package/lib/cjs/queries/CreateBuilder.d.ts +38 -0
- package/lib/cjs/queries/CreateBuilder.js +100 -0
- package/lib/cjs/queries/CreateBuilder.js.map +1 -0
- package/lib/cjs/queries/CreateQuery.d.ts +3 -3
- package/lib/cjs/queries/CreateQuery.js.map +1 -1
- package/lib/cjs/queries/DeleteBuilder.d.ts +39 -0
- package/lib/cjs/queries/DeleteBuilder.js +85 -0
- package/lib/cjs/queries/DeleteBuilder.js.map +1 -0
- package/lib/cjs/queries/DeleteQuery.d.ts +3 -3
- package/lib/cjs/queries/DeleteQuery.js.map +1 -1
- package/lib/cjs/queries/FieldSet.d.ts +203 -0
- package/lib/cjs/queries/FieldSet.js +533 -0
- package/lib/cjs/queries/FieldSet.js.map +1 -0
- package/lib/cjs/queries/IRDesugar.d.ts +13 -8
- package/lib/cjs/queries/IRDesugar.js +143 -132
- package/lib/cjs/queries/IRDesugar.js.map +1 -1
- package/lib/cjs/queries/IRLower.js +1 -0
- package/lib/cjs/queries/IRLower.js.map +1 -1
- package/lib/cjs/queries/IntermediateRepresentation.d.ts +1 -0
- package/lib/cjs/queries/MutationQuery.d.ts +1 -1
- package/lib/cjs/queries/MutationQuery.js +1 -6
- package/lib/cjs/queries/MutationQuery.js.map +1 -1
- package/lib/cjs/queries/PropertyPath.d.ts +38 -0
- package/lib/cjs/queries/PropertyPath.js +82 -0
- package/lib/cjs/queries/PropertyPath.js.map +1 -0
- package/lib/cjs/queries/ProxiedPathBuilder.d.ts +14 -0
- package/lib/cjs/queries/ProxiedPathBuilder.js +29 -0
- package/lib/cjs/queries/ProxiedPathBuilder.js.map +1 -0
- package/lib/cjs/queries/QueryBuilder.d.ts +141 -0
- package/lib/cjs/queries/QueryBuilder.js +334 -0
- package/lib/cjs/queries/QueryBuilder.js.map +1 -0
- package/lib/cjs/queries/SelectQuery.d.ts +60 -134
- package/lib/cjs/queries/SelectQuery.js +67 -526
- package/lib/cjs/queries/SelectQuery.js.map +1 -1
- package/lib/cjs/queries/UpdateBuilder.d.ts +37 -0
- package/lib/cjs/queries/UpdateBuilder.js +84 -0
- package/lib/cjs/queries/UpdateBuilder.js.map +1 -0
- package/lib/cjs/queries/UpdateQuery.d.ts +3 -3
- package/lib/cjs/queries/UpdateQuery.js.map +1 -1
- package/lib/cjs/queries/WhereCondition.d.ts +18 -0
- package/lib/cjs/queries/WhereCondition.js +3 -0
- package/lib/cjs/queries/WhereCondition.js.map +1 -0
- package/lib/cjs/queries/resolveShape.d.ts +10 -0
- package/lib/cjs/queries/resolveShape.js +23 -0
- package/lib/cjs/queries/resolveShape.js.map +1 -0
- package/lib/cjs/shapes/SHACL.js +7 -5
- package/lib/cjs/shapes/SHACL.js.map +1 -1
- package/lib/cjs/shapes/Shape.d.ts +33 -52
- package/lib/cjs/shapes/Shape.js +36 -56
- package/lib/cjs/shapes/Shape.js.map +1 -1
- package/lib/cjs/sparql/SparqlAlgebra.d.ts +6 -1
- package/lib/cjs/sparql/algebraToString.js +10 -0
- package/lib/cjs/sparql/algebraToString.js.map +1 -1
- package/lib/cjs/sparql/irToAlgebra.js +6 -2
- package/lib/cjs/sparql/irToAlgebra.js.map +1 -1
- package/lib/cjs/test-helpers/query-fixtures.d.ts +568 -3049
- package/lib/cjs/test-helpers/query-fixtures.js +59 -18
- package/lib/cjs/test-helpers/query-fixtures.js.map +1 -1
- package/lib/cjs/test-helpers/test-utils.d.ts +18 -0
- package/lib/cjs/test-helpers/test-utils.js +47 -0
- package/lib/cjs/test-helpers/test-utils.js.map +1 -0
- package/lib/cjs/utils/Package.d.ts +8 -8
- package/lib/cjs/utils/Package.js.map +1 -1
- package/lib/cjs/utils/ShapeClass.d.ts +2 -2
- package/lib/cjs/utils/ShapeClass.js +4 -22
- package/lib/cjs/utils/ShapeClass.js.map +1 -1
- package/lib/esm/index.d.ts +10 -2
- package/lib/esm/index.js +23 -2
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/package.d.ts +1 -1
- package/lib/esm/queries/CreateBuilder.d.ts +38 -0
- package/lib/esm/queries/CreateBuilder.js +96 -0
- package/lib/esm/queries/CreateBuilder.js.map +1 -0
- package/lib/esm/queries/CreateQuery.d.ts +3 -3
- package/lib/esm/queries/CreateQuery.js.map +1 -1
- package/lib/esm/queries/DeleteBuilder.d.ts +39 -0
- package/lib/esm/queries/DeleteBuilder.js +81 -0
- package/lib/esm/queries/DeleteBuilder.js.map +1 -0
- package/lib/esm/queries/DeleteQuery.d.ts +3 -3
- package/lib/esm/queries/DeleteQuery.js.map +1 -1
- package/lib/esm/queries/FieldSet.d.ts +203 -0
- package/lib/esm/queries/FieldSet.js +529 -0
- package/lib/esm/queries/FieldSet.js.map +1 -0
- package/lib/esm/queries/IRDesugar.d.ts +13 -8
- package/lib/esm/queries/IRDesugar.js +143 -132
- package/lib/esm/queries/IRDesugar.js.map +1 -1
- package/lib/esm/queries/IRLower.js +1 -0
- package/lib/esm/queries/IRLower.js.map +1 -1
- package/lib/esm/queries/IntermediateRepresentation.d.ts +1 -0
- package/lib/esm/queries/MutationQuery.d.ts +1 -1
- package/lib/esm/queries/MutationQuery.js +1 -6
- package/lib/esm/queries/MutationQuery.js.map +1 -1
- package/lib/esm/queries/PropertyPath.d.ts +38 -0
- package/lib/esm/queries/PropertyPath.js +77 -0
- package/lib/esm/queries/PropertyPath.js.map +1 -0
- package/lib/esm/queries/ProxiedPathBuilder.d.ts +14 -0
- package/lib/esm/queries/ProxiedPathBuilder.js +26 -0
- package/lib/esm/queries/ProxiedPathBuilder.js.map +1 -0
- package/lib/esm/queries/QueryBuilder.d.ts +141 -0
- package/lib/esm/queries/QueryBuilder.js +330 -0
- package/lib/esm/queries/QueryBuilder.js.map +1 -0
- package/lib/esm/queries/SelectQuery.d.ts +60 -134
- package/lib/esm/queries/SelectQuery.js +61 -515
- package/lib/esm/queries/SelectQuery.js.map +1 -1
- package/lib/esm/queries/UpdateBuilder.d.ts +37 -0
- package/lib/esm/queries/UpdateBuilder.js +80 -0
- package/lib/esm/queries/UpdateBuilder.js.map +1 -0
- package/lib/esm/queries/UpdateQuery.d.ts +3 -3
- package/lib/esm/queries/UpdateQuery.js.map +1 -1
- package/lib/esm/queries/WhereCondition.d.ts +18 -0
- package/lib/esm/queries/WhereCondition.js +2 -0
- package/lib/esm/queries/WhereCondition.js.map +1 -0
- package/lib/esm/queries/resolveShape.d.ts +10 -0
- package/lib/esm/queries/resolveShape.js +20 -0
- package/lib/esm/queries/resolveShape.js.map +1 -0
- package/lib/esm/shapes/SHACL.js +7 -5
- package/lib/esm/shapes/SHACL.js.map +1 -1
- package/lib/esm/shapes/Shape.d.ts +33 -52
- package/lib/esm/shapes/Shape.js +36 -53
- package/lib/esm/shapes/Shape.js.map +1 -1
- package/lib/esm/sparql/SparqlAlgebra.d.ts +6 -1
- package/lib/esm/sparql/algebraToString.js +10 -0
- package/lib/esm/sparql/algebraToString.js.map +1 -1
- package/lib/esm/sparql/irToAlgebra.js +6 -2
- package/lib/esm/sparql/irToAlgebra.js.map +1 -1
- package/lib/esm/test-helpers/query-fixtures.d.ts +568 -3049
- package/lib/esm/test-helpers/query-fixtures.js +59 -18
- package/lib/esm/test-helpers/query-fixtures.js.map +1 -1
- package/lib/esm/test-helpers/test-utils.d.ts +18 -0
- package/lib/esm/test-helpers/test-utils.js +41 -0
- package/lib/esm/test-helpers/test-utils.js.map +1 -0
- package/lib/esm/utils/Package.d.ts +8 -8
- package/lib/esm/utils/Package.js.map +1 -1
- package/lib/esm/utils/ShapeClass.d.ts +2 -2
- package/lib/esm/utils/ShapeClass.js +4 -22
- package/lib/esm/utils/ShapeClass.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.SetSize = exports.QueryPrimitiveSet = exports.QueryPrimitive = exports.Evaluation = exports.QueryShape = exports.QueryShapeSet = exports.evaluateSortCallback = exports.processWhereClause = exports.BoundComponent = exports.QueryBuilderObject = exports.isWhereEvaluationPath = exports.WhereMethods = void 0;
|
|
4
4
|
const Shape_js_1 = require("../shapes/Shape.js");
|
|
5
5
|
const ShapeSet_js_1 = require("../collections/ShapeSet.js");
|
|
6
6
|
const shacl_js_1 = require("../ontologies/shacl.js");
|
|
7
7
|
const CoreSet_js_1 = require("../collections/CoreSet.js");
|
|
8
8
|
const ShapeClass_js_1 = require("../utils/ShapeClass.js");
|
|
9
|
-
const QueryFactory_js_1 = require("./QueryFactory.js");
|
|
10
9
|
const xsd_js_1 = require("../ontologies/xsd.js");
|
|
11
|
-
const
|
|
12
|
-
const
|
|
10
|
+
const ProxiedPathBuilder_js_1 = require("./ProxiedPathBuilder.js");
|
|
11
|
+
const FieldSet_js_1 = require("./FieldSet.js");
|
|
12
|
+
const PropertyPath_js_1 = require("./PropertyPath.js");
|
|
13
13
|
const isSameRef = (a, b) => !!a && !!b && a.id === b.id;
|
|
14
14
|
var WhereMethods;
|
|
15
15
|
(function (WhereMethods) {
|
|
@@ -47,16 +47,16 @@ class QueryBuilderObject {
|
|
|
47
47
|
return QueryShapeSet.create(originalValue, property, subject);
|
|
48
48
|
}
|
|
49
49
|
else if (typeof originalValue === 'string') {
|
|
50
|
-
return new
|
|
50
|
+
return new QueryPrimitive(originalValue, property, subject);
|
|
51
51
|
}
|
|
52
52
|
else if (typeof originalValue === 'number') {
|
|
53
|
-
return new
|
|
53
|
+
return new QueryPrimitive(originalValue, property, subject);
|
|
54
54
|
}
|
|
55
55
|
else if (typeof originalValue === 'boolean') {
|
|
56
|
-
return new
|
|
56
|
+
return new QueryPrimitive(originalValue, property, subject);
|
|
57
57
|
}
|
|
58
58
|
else if (originalValue instanceof Date) {
|
|
59
|
-
return new
|
|
59
|
+
return new QueryPrimitive(originalValue, property, subject);
|
|
60
60
|
}
|
|
61
61
|
else if (Array.isArray(originalValue)) {
|
|
62
62
|
return new QueryPrimitiveSet(originalValue, property, subject);
|
|
@@ -95,23 +95,23 @@ class QueryBuilderObject {
|
|
|
95
95
|
if (datatype) {
|
|
96
96
|
if (singleValue) {
|
|
97
97
|
if (isSameRef(datatype, xsd_js_1.xsd.integer)) {
|
|
98
|
-
return new
|
|
98
|
+
return new QueryPrimitive(0, property, subject);
|
|
99
99
|
}
|
|
100
100
|
else if (isSameRef(datatype, xsd_js_1.xsd.boolean)) {
|
|
101
|
-
return new
|
|
101
|
+
return new QueryPrimitive(false, property, subject);
|
|
102
102
|
}
|
|
103
103
|
else if (isSameRef(datatype, xsd_js_1.xsd.dateTime) ||
|
|
104
104
|
isSameRef(datatype, xsd_js_1.xsd.date)) {
|
|
105
|
-
return new
|
|
105
|
+
return new QueryPrimitive(new Date(), property, subject);
|
|
106
106
|
}
|
|
107
107
|
else if (isSameRef(datatype, xsd_js_1.xsd.string)) {
|
|
108
|
-
return new
|
|
108
|
+
return new QueryPrimitive('', property, subject);
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
else {
|
|
112
112
|
//TODO review this, do we need property & subject in both of these? currently yes, but why
|
|
113
113
|
return new QueryPrimitiveSet([''], property, subject, [
|
|
114
|
-
new
|
|
114
|
+
new QueryPrimitive('', property, subject),
|
|
115
115
|
]);
|
|
116
116
|
}
|
|
117
117
|
}
|
|
@@ -138,30 +138,17 @@ class QueryBuilderObject {
|
|
|
138
138
|
isSameRef(property.nodeKind, shacl_js_1.shacl.BlankNodeOrLiteral)) {
|
|
139
139
|
if (singleValue) {
|
|
140
140
|
//default to string if no datatype is set
|
|
141
|
-
return new
|
|
141
|
+
return new QueryPrimitive('', property, subject);
|
|
142
142
|
}
|
|
143
143
|
else {
|
|
144
144
|
//TODO review this, do we need property & subject in both of these? currently yes, but why
|
|
145
145
|
return new QueryPrimitiveSet([''], property, subject, [
|
|
146
|
-
new
|
|
146
|
+
new QueryPrimitive('', property, subject),
|
|
147
147
|
]);
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
//if an object is expected and no value shape is set, then warn
|
|
151
151
|
throw Error(`No shape set for objectProperty ${property.parentNodeShape.label}.${property.label}`);
|
|
152
|
-
// //and use a generic shape
|
|
153
|
-
// const shapeValue = new (Shape as any)(new TestNode(path));
|
|
154
|
-
// if (singleValue) {
|
|
155
|
-
// return QueryShape.create(shapeValue, property, subject);
|
|
156
|
-
// } else {
|
|
157
|
-
// //check if shapeValue is iterable
|
|
158
|
-
// if (!(Symbol.iterator in Object(shapeValue))) {
|
|
159
|
-
// throw new Error(
|
|
160
|
-
// `Property ${property.parentNodeShape.label}.${property.label} is not marked as single value (maxCount:1), but the value is not iterable`,
|
|
161
|
-
// );
|
|
162
|
-
// }
|
|
163
|
-
// return QueryShapeSet.create(new ShapeSet(shapeValue), property, subject);
|
|
164
|
-
// }
|
|
165
152
|
}
|
|
166
153
|
static getOriginalSource(endValue) {
|
|
167
154
|
if (typeof endValue === 'undefined')
|
|
@@ -169,7 +156,7 @@ class QueryBuilderObject {
|
|
|
169
156
|
if (endValue instanceof QueryPrimitiveSet) {
|
|
170
157
|
return new ShapeSet_js_1.ShapeSet(endValue.contents.map((endValue) => this.getOriginalSource(endValue)));
|
|
171
158
|
}
|
|
172
|
-
if (endValue instanceof
|
|
159
|
+
if (endValue instanceof QueryPrimitive) {
|
|
173
160
|
return endValue.subject
|
|
174
161
|
? this.getOriginalSource(endValue.subject)
|
|
175
162
|
: endValue.originalValue;
|
|
@@ -203,7 +190,6 @@ class QueryBuilderObject {
|
|
|
203
190
|
return new BoundComponent(component, this);
|
|
204
191
|
}
|
|
205
192
|
limit(lim) {
|
|
206
|
-
console.log(lim);
|
|
207
193
|
}
|
|
208
194
|
/**
|
|
209
195
|
* Returns the path of properties that were requested to reach this value
|
|
@@ -232,45 +218,6 @@ class BoundComponent extends QueryBuilderObject {
|
|
|
232
218
|
this.originalValue = originalValue;
|
|
233
219
|
this.source = source;
|
|
234
220
|
}
|
|
235
|
-
getParentQueryFactory() {
|
|
236
|
-
let parentQuery = this.originalValue.query;
|
|
237
|
-
if (parentQuery instanceof SelectQueryFactory) {
|
|
238
|
-
return parentQuery;
|
|
239
|
-
}
|
|
240
|
-
if (typeof parentQuery === 'object') {
|
|
241
|
-
if (Object.keys(parentQuery).length > 1) {
|
|
242
|
-
throw new Error('Only one key is allowed to map a query to a property for linkedSetComponents');
|
|
243
|
-
}
|
|
244
|
-
for (let key in parentQuery) {
|
|
245
|
-
if (parentQuery[key] instanceof SelectQueryFactory) {
|
|
246
|
-
return parentQuery[key];
|
|
247
|
-
}
|
|
248
|
-
throw new Error('Unknown value type for query object. Keep to this format: {propName: Shape.query(s => ...)}');
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
throw new Error('Unknown data query type. Expected a SelectQueryFactory (from Shape.query()) or an object with 1 key whose value is a SelectQueryFactory');
|
|
252
|
-
}
|
|
253
|
-
getPropertyPath() {
|
|
254
|
-
let sourcePath = this.source.getPropertyPath();
|
|
255
|
-
let requestQuery = this.getParentQueryFactory();
|
|
256
|
-
let compSelectQuery = requestQuery.getQueryPaths();
|
|
257
|
-
if (Array.isArray(sourcePath)) {
|
|
258
|
-
if (Array.isArray(compSelectQuery)) {
|
|
259
|
-
// QueryPath[] — unwrap single-element arrays for compact representation
|
|
260
|
-
const unwrapped = compSelectQuery.length === 1
|
|
261
|
-
? Array.isArray(compSelectQuery[0]) && compSelectQuery[0].length === 1
|
|
262
|
-
? compSelectQuery[0][0]
|
|
263
|
-
: compSelectQuery[0]
|
|
264
|
-
: compSelectQuery;
|
|
265
|
-
sourcePath.push(unwrapped);
|
|
266
|
-
}
|
|
267
|
-
else {
|
|
268
|
-
// CustomQueryObject
|
|
269
|
-
sourcePath.push(compSelectQuery);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
return sourcePath;
|
|
273
|
-
}
|
|
274
221
|
}
|
|
275
222
|
exports.BoundComponent = BoundComponent;
|
|
276
223
|
/**
|
|
@@ -289,12 +236,37 @@ const processWhereClause = (validation, shape) => {
|
|
|
289
236
|
if (!shape) {
|
|
290
237
|
throw new Error('Cannot process where clause without shape');
|
|
291
238
|
}
|
|
292
|
-
|
|
239
|
+
const proxy = (0, ProxiedPathBuilder_js_1.createProxiedPathBuilder)(shape);
|
|
240
|
+
const evaluation = validation(proxy);
|
|
241
|
+
return evaluation.getWherePath();
|
|
293
242
|
}
|
|
294
243
|
else {
|
|
295
244
|
return validation.getWherePath();
|
|
296
245
|
}
|
|
297
246
|
};
|
|
247
|
+
exports.processWhereClause = processWhereClause;
|
|
248
|
+
/**
|
|
249
|
+
* Evaluate a sort callback through the proxy and extract a SortByPath.
|
|
250
|
+
* This is a standalone helper that replaces the need for the former SelectQueryFactory.sortBy().
|
|
251
|
+
*/
|
|
252
|
+
const evaluateSortCallback = (shape, sortFn, direction = 'ASC') => {
|
|
253
|
+
const proxy = (0, ProxiedPathBuilder_js_1.createProxiedPathBuilder)(shape);
|
|
254
|
+
const response = sortFn(proxy);
|
|
255
|
+
const nodeShape = shape.shape;
|
|
256
|
+
const paths = [];
|
|
257
|
+
if (response instanceof QueryBuilderObject || response instanceof QueryPrimitiveSet) {
|
|
258
|
+
paths.push(new PropertyPath_js_1.PropertyPath(nodeShape, FieldSet_js_1.FieldSet.collectPropertySegments(response)));
|
|
259
|
+
}
|
|
260
|
+
else if (Array.isArray(response)) {
|
|
261
|
+
for (const item of response) {
|
|
262
|
+
if (item instanceof QueryBuilderObject) {
|
|
263
|
+
paths.push(new PropertyPath_js_1.PropertyPath(nodeShape, FieldSet_js_1.FieldSet.collectPropertySegments(item)));
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return { paths, direction };
|
|
268
|
+
};
|
|
269
|
+
exports.evaluateSortCallback = evaluateSortCallback;
|
|
298
270
|
class QueryShapeSet extends QueryBuilderObject {
|
|
299
271
|
constructor(_originalValue, property, subject) {
|
|
300
272
|
super(property, subject);
|
|
@@ -350,8 +322,6 @@ class QueryShapeSet extends QueryBuilderObject {
|
|
|
350
322
|
return originalShapeSet[key].bind(originalShapeSet);
|
|
351
323
|
}
|
|
352
324
|
else if (key !== 'then' && key !== '$$typeof') {
|
|
353
|
-
//TODO: there is a strange bug with "then" being called, only for queries that access ShapeSets (multi value props), but I'm not sure where it comes from
|
|
354
|
-
//hiding the warning for now in that case as it doesn't seem to affect the results
|
|
355
325
|
console.warn('Could not find property shape for key ' +
|
|
356
326
|
key +
|
|
357
327
|
' on shape ' +
|
|
@@ -452,16 +422,16 @@ class QueryShapeSet extends QueryBuilderObject {
|
|
|
452
422
|
throw new Error('You cannot call where() from within a where() clause. Consider using some() or every() instead');
|
|
453
423
|
}
|
|
454
424
|
let leastSpecificShape = this.getOriginalValue().getLeastSpecificShape();
|
|
455
|
-
this.wherePath = processWhereClause(validation, leastSpecificShape);
|
|
425
|
+
this.wherePath = (0, exports.processWhereClause)(validation, leastSpecificShape);
|
|
456
426
|
//return this.proxy because after Shape.friends.where() we can call other methods of Shape.friends
|
|
457
427
|
//and for that we need the proxy
|
|
458
428
|
return this.proxy;
|
|
459
429
|
}
|
|
460
430
|
select(subQueryFn) {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
return
|
|
431
|
+
const leastSpecificShape = this.getOriginalValue().getLeastSpecificShape();
|
|
432
|
+
const parentSegments = FieldSet_js_1.FieldSet.collectPropertySegments(this);
|
|
433
|
+
const fs = FieldSet_js_1.FieldSet.forSubSelect(leastSpecificShape, subQueryFn, parentSegments);
|
|
434
|
+
return fs;
|
|
465
435
|
}
|
|
466
436
|
selectAll() {
|
|
467
437
|
let leastSpecificShape = this.getOriginalValue().getLeastSpecificShape();
|
|
@@ -480,7 +450,7 @@ class QueryShapeSet extends QueryBuilderObject {
|
|
|
480
450
|
let leastSpecificShape = this.getOriginalValue().getLeastSpecificShape();
|
|
481
451
|
//do we need to store this here? or are we accessing the evaluation and then going backwards?
|
|
482
452
|
//in that case just pass it to the evaluation and don't use this.wherePath
|
|
483
|
-
let wherePath = processWhereClause(validation, leastSpecificShape);
|
|
453
|
+
let wherePath = (0, exports.processWhereClause)(validation, leastSpecificShape);
|
|
484
454
|
return new SetEvaluation(this, method, [wherePath]);
|
|
485
455
|
}
|
|
486
456
|
}
|
|
@@ -494,12 +464,6 @@ class QueryShape extends QueryBuilderObject {
|
|
|
494
464
|
return (this.originalValue.__queryContextId ||
|
|
495
465
|
this.originalValue['id']);
|
|
496
466
|
}
|
|
497
|
-
// where(validation: WhereClause<S>): this {
|
|
498
|
-
// let nodeShape = this.originalValue.nodeShape;
|
|
499
|
-
// this.wherePath = processWhereClause(validation, nodeShape);
|
|
500
|
-
// //return this because after Shape.friends.where() we can call other methods of Shape.friends
|
|
501
|
-
// return this.proxy;
|
|
502
|
-
// }
|
|
503
467
|
static create(original, property, subject) {
|
|
504
468
|
let instance = new QueryShape(original, property, subject);
|
|
505
469
|
let proxy = this.proxifyQueryShape(instance);
|
|
@@ -524,27 +488,9 @@ class QueryShape extends QueryBuilderObject {
|
|
|
524
488
|
//if not, then a method/accessor of the original shape was called
|
|
525
489
|
//then check if we have indexed any property shapes with that name for this shapes NodeShape
|
|
526
490
|
//NOTE: this will only work with a @linkedProperty decorator
|
|
527
|
-
// let propertyShape = originalShape.nodeShape
|
|
528
|
-
// .getPropertyShapes()
|
|
529
|
-
// .find((propertyShape) => propertyShape.label === key);
|
|
530
491
|
let propertyShape = (0, ShapeClass_js_1.getPropertyShapeByLabel)(originalShape.constructor, key);
|
|
531
492
|
if (propertyShape) {
|
|
532
|
-
//generate the query shape based on the property shape
|
|
533
|
-
// let nodeValue;
|
|
534
|
-
// if(propertyShape.maxCount <= 1) {
|
|
535
|
-
// nodeValue = new TestNode(propertyShape.path);
|
|
536
|
-
// } else {
|
|
537
|
-
// nodeValue = new NodeSet(new TestNode(propertyShape.path));
|
|
538
|
-
// }
|
|
539
493
|
return QueryBuilderObject.generatePathValue(propertyShape, target);
|
|
540
|
-
//get the value of the property from the original shape
|
|
541
|
-
// let value = originalShape[key];
|
|
542
|
-
// //convert the value into a query value
|
|
543
|
-
// return QueryBuilderObject.convertOriginal(
|
|
544
|
-
// value,
|
|
545
|
-
// propertyShape,
|
|
546
|
-
// queryShape,
|
|
547
|
-
// );
|
|
548
494
|
}
|
|
549
495
|
}
|
|
550
496
|
if (key !== 'then' && key !== '$$typeof') {
|
|
@@ -554,8 +500,6 @@ class QueryShape extends QueryBuilderObject {
|
|
|
554
500
|
//https://stackoverflow.com/a/49725198/977206
|
|
555
501
|
const stackLines = stack.split('\n').slice(1); //remove the "Error" line
|
|
556
502
|
console.warn(`${originalShape.constructor.name}.${key.toString()} is accessed in a query, but it does not have a @linkedProperty decorator. Queries can only access decorated get/set methods. ${stackLines.join('\n')}`);
|
|
557
|
-
// } else {
|
|
558
|
-
// console.error('Proxy is accessed like a promise');
|
|
559
503
|
}
|
|
560
504
|
return originalShape[key];
|
|
561
505
|
},
|
|
@@ -571,18 +515,16 @@ class QueryShape extends QueryBuilderObject {
|
|
|
571
515
|
}
|
|
572
516
|
return QueryShape.create(newOriginal, this.property, this.subject);
|
|
573
517
|
}
|
|
574
|
-
// else return this
|
|
575
518
|
return this;
|
|
576
|
-
// return this.proxy;
|
|
577
519
|
}
|
|
578
520
|
equals(otherValue) {
|
|
579
521
|
return new Evaluation(this, WhereMethods.EQUALS, [otherValue]);
|
|
580
522
|
}
|
|
581
523
|
select(subQueryFn) {
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
return
|
|
524
|
+
const leastSpecificShape = (0, ShapeClass_js_1.getShapeClass)(this.getOriginalValue().nodeShape.id);
|
|
525
|
+
const parentSegments = FieldSet_js_1.FieldSet.collectPropertySegments(this);
|
|
526
|
+
const fs = FieldSet_js_1.FieldSet.forSubSelect(leastSpecificShape, subQueryFn, parentSegments);
|
|
527
|
+
return fs;
|
|
586
528
|
}
|
|
587
529
|
selectAll() {
|
|
588
530
|
let leastSpecificShape = (0, ShapeClass_js_1.getShapeClass)(this.getOriginalValue().nodeShape.id);
|
|
@@ -645,13 +587,13 @@ class Evaluation {
|
|
|
645
587
|
}
|
|
646
588
|
and(subQuery) {
|
|
647
589
|
this._andOr.push({
|
|
648
|
-
and: processWhereClause(subQuery),
|
|
590
|
+
and: (0, exports.processWhereClause)(subQuery),
|
|
649
591
|
});
|
|
650
592
|
return this;
|
|
651
593
|
}
|
|
652
594
|
or(subQuery) {
|
|
653
595
|
this._andOr.push({
|
|
654
|
-
or: processWhereClause(subQuery),
|
|
596
|
+
or: (0, exports.processWhereClause)(subQuery),
|
|
655
597
|
});
|
|
656
598
|
return this;
|
|
657
599
|
}
|
|
@@ -660,8 +602,11 @@ exports.Evaluation = Evaluation;
|
|
|
660
602
|
class SetEvaluation extends Evaluation {
|
|
661
603
|
}
|
|
662
604
|
/**
|
|
663
|
-
*
|
|
664
|
-
*
|
|
605
|
+
* Concrete query wrapper for JS primitive values (string, number, boolean, Date).
|
|
606
|
+
*
|
|
607
|
+
* Replaces the former abstract class + subclasses (QueryString, QueryNumber,
|
|
608
|
+
* QueryBoolean, QueryDate) — the type parameter T carries the primitive type,
|
|
609
|
+
* so separate subclasses are unnecessary.
|
|
665
610
|
*/
|
|
666
611
|
class QueryPrimitive extends QueryBuilderObject {
|
|
667
612
|
constructor(originalValue, property, subject) {
|
|
@@ -676,26 +621,12 @@ class QueryPrimitive extends QueryBuilderObject {
|
|
|
676
621
|
}
|
|
677
622
|
where(validation) {
|
|
678
623
|
// let nodeShape = this.subject.getOriginalValue().nodeShape;
|
|
679
|
-
this.wherePath = processWhereClause(validation, new
|
|
624
|
+
this.wherePath = (0, exports.processWhereClause)(validation, new QueryPrimitive(''));
|
|
680
625
|
//return this because after Shape.friends.where() we can call other methods of Shape.friends
|
|
681
626
|
return this;
|
|
682
627
|
}
|
|
683
628
|
}
|
|
684
629
|
exports.QueryPrimitive = QueryPrimitive;
|
|
685
|
-
//@TODO: QueryString, QueryNumber, QueryBoolean, QueryDate can all be replaced with QueryPrimitive, and we can infer the original type, no need for these extra classes
|
|
686
|
-
//UPDATE some of this has started. Query response to result conversion is using QueryPrimitive only
|
|
687
|
-
class QueryString extends QueryPrimitive {
|
|
688
|
-
}
|
|
689
|
-
exports.QueryString = QueryString;
|
|
690
|
-
class QueryDate extends QueryPrimitive {
|
|
691
|
-
}
|
|
692
|
-
exports.QueryDate = QueryDate;
|
|
693
|
-
class QueryNumber extends QueryPrimitive {
|
|
694
|
-
}
|
|
695
|
-
exports.QueryNumber = QueryNumber;
|
|
696
|
-
class QueryBoolean extends QueryPrimitive {
|
|
697
|
-
}
|
|
698
|
-
exports.QueryBoolean = QueryBoolean;
|
|
699
630
|
class QueryPrimitiveSet extends QueryBuilderObject {
|
|
700
631
|
constructor(originalValue, property, subject, items) {
|
|
701
632
|
super(property, subject);
|
|
@@ -714,7 +645,7 @@ class QueryPrimitiveSet extends QueryBuilderObject {
|
|
|
714
645
|
createNew(...args) {
|
|
715
646
|
return new this.constructor(this.property, this.subject, ...args);
|
|
716
647
|
}
|
|
717
|
-
//TODO: see if we can merge these methods of
|
|
648
|
+
//TODO: see if we can merge these methods of QueryPrimitive and QueryPrimitiveSet
|
|
718
649
|
// so that they're only defined once
|
|
719
650
|
equals(other) {
|
|
720
651
|
return new Evaluation(this, WhereMethods.EQUALS, [other]);
|
|
@@ -750,360 +681,7 @@ class QueryPrimitiveSet extends QueryBuilderObject {
|
|
|
750
681
|
}
|
|
751
682
|
}
|
|
752
683
|
exports.QueryPrimitiveSet = QueryPrimitiveSet;
|
|
753
|
-
|
|
754
|
-
let callbackStack = [];
|
|
755
|
-
const docReady = () => {
|
|
756
|
-
documentLoaded = true;
|
|
757
|
-
callbackStack.forEach((callback) => callback());
|
|
758
|
-
callbackStack = [];
|
|
759
|
-
};
|
|
760
|
-
if (typeof document === 'undefined' || document.readyState !== 'loading') {
|
|
761
|
-
docReady();
|
|
762
|
-
}
|
|
763
|
-
else {
|
|
764
|
-
documentLoaded = false;
|
|
765
|
-
document.addEventListener('DOMContentLoaded', () => () => {
|
|
766
|
-
docReady();
|
|
767
|
-
});
|
|
768
|
-
setTimeout(() => {
|
|
769
|
-
if (!documentLoaded) {
|
|
770
|
-
console.warn('⚠️ Forcing init after timeout');
|
|
771
|
-
docReady();
|
|
772
|
-
}
|
|
773
|
-
}, 3500);
|
|
774
|
-
}
|
|
775
|
-
//only continue to parse the query if the document is ready, and all shapes from initial bundles are loaded
|
|
776
|
-
var onQueriesReady = (callback) => {
|
|
777
|
-
if (!documentLoaded) {
|
|
778
|
-
callbackStack.push(callback);
|
|
779
|
-
}
|
|
780
|
-
else {
|
|
781
|
-
callback();
|
|
782
|
-
}
|
|
783
|
-
};
|
|
784
|
-
exports.onQueriesReady = onQueriesReady;
|
|
785
|
-
class SelectQueryFactory extends QueryFactory_js_1.QueryFactory {
|
|
786
|
-
constructor(shape, queryBuildFn, subject) {
|
|
787
|
-
super();
|
|
788
|
-
this.shape = shape;
|
|
789
|
-
this.queryBuildFn = queryBuildFn;
|
|
790
|
-
this.subject = subject;
|
|
791
|
-
let promise, resolve, reject;
|
|
792
|
-
promise = new Promise((res, rej) => {
|
|
793
|
-
resolve = res;
|
|
794
|
-
reject = rej;
|
|
795
|
-
});
|
|
796
|
-
this.initPromise = { promise, resolve, reject, complete: false };
|
|
797
|
-
//only continue to parse the query if the document is ready, and all shapes from initial bundles are loaded
|
|
798
|
-
if (typeof document === 'undefined' || document.readyState !== 'loading') {
|
|
799
|
-
this.init();
|
|
800
|
-
}
|
|
801
|
-
else {
|
|
802
|
-
document.addEventListener('DOMContentLoaded', () => this.init());
|
|
803
|
-
setTimeout(() => {
|
|
804
|
-
if (!this.initPromise.complete) {
|
|
805
|
-
console.warn('⚠️ Forcing init after timeout');
|
|
806
|
-
this.init();
|
|
807
|
-
}
|
|
808
|
-
}, 3500);
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
setLimit(limit) {
|
|
812
|
-
this.limit = limit;
|
|
813
|
-
}
|
|
814
|
-
getLimit() {
|
|
815
|
-
return this.limit;
|
|
816
|
-
}
|
|
817
|
-
setOffset(offset) {
|
|
818
|
-
this.offset = offset;
|
|
819
|
-
}
|
|
820
|
-
getOffset() {
|
|
821
|
-
return this.offset;
|
|
822
|
-
}
|
|
823
|
-
setSubject(subject) {
|
|
824
|
-
this.subject = subject;
|
|
825
|
-
return this;
|
|
826
|
-
}
|
|
827
|
-
where(validation) {
|
|
828
|
-
this.wherePath = processWhereClause(validation, this.shape);
|
|
829
|
-
return this;
|
|
830
|
-
}
|
|
831
|
-
exec() {
|
|
832
|
-
return (0, queryDispatch_js_1.getQueryDispatch)().selectQuery(this.build());
|
|
833
|
-
}
|
|
834
|
-
/**
|
|
835
|
-
* Returns the raw pipeline input for this query.
|
|
836
|
-
* Used internally by build() and by test helpers that need
|
|
837
|
-
* to feed factory state into individual pipeline stages.
|
|
838
|
-
*/
|
|
839
|
-
toRawInput() {
|
|
840
|
-
const input = {
|
|
841
|
-
select: this.getQueryPaths(),
|
|
842
|
-
subject: this.getSubject(),
|
|
843
|
-
limit: this.limit,
|
|
844
|
-
offset: this.offset,
|
|
845
|
-
shape: this.shape,
|
|
846
|
-
sortBy: this.getSortByPath(),
|
|
847
|
-
singleResult: this.singleResult ||
|
|
848
|
-
!!(this.subject &&
|
|
849
|
-
('id' in this.subject || 'id' in this.subject)),
|
|
850
|
-
};
|
|
851
|
-
if (this.wherePath) {
|
|
852
|
-
input.where = this.wherePath;
|
|
853
|
-
}
|
|
854
|
-
return input;
|
|
855
|
-
}
|
|
856
|
-
build() {
|
|
857
|
-
return (0, IRPipeline_js_1.buildSelectQuery)(this.toRawInput());
|
|
858
|
-
}
|
|
859
|
-
getSubject() {
|
|
860
|
-
var _a, _b;
|
|
861
|
-
//if the subject is a QueryShape which comes from query context
|
|
862
|
-
//then it will carry a query context id and we convert it to a node reference
|
|
863
|
-
//NOTE: its important to access originalValue instead of .node directly because QueryShape.node may be undefined
|
|
864
|
-
if ((_b = (_a = this.subject) === null || _a === void 0 ? void 0 : _a.originalValue) === null || _b === void 0 ? void 0 : _b.__queryContextId) {
|
|
865
|
-
return convertQueryContext(this.subject);
|
|
866
|
-
}
|
|
867
|
-
// }
|
|
868
|
-
return this.subject;
|
|
869
|
-
}
|
|
870
|
-
/**
|
|
871
|
-
* Returns an array of query paths
|
|
872
|
-
* A single query can request multiple things in multiple "query paths" (For example this is using 2 paths: Shape.select(p => [p.name, p.friends.name]))
|
|
873
|
-
* Each query path is returned as array of the property paths requested, with potential where clauses (together called a QueryStep)
|
|
874
|
-
*/
|
|
875
|
-
getQueryPaths(response = this.traceResponse) {
|
|
876
|
-
let queryPaths = [];
|
|
877
|
-
let queryObject;
|
|
878
|
-
//if the trace response is an array, then multiple paths were requested
|
|
879
|
-
if (response instanceof QueryBuilderObject ||
|
|
880
|
-
response instanceof QueryPrimitiveSet) {
|
|
881
|
-
//if it's a single value, then only one path was requested, and we can add it directly
|
|
882
|
-
queryPaths.push(response.getPropertyPath());
|
|
883
|
-
}
|
|
884
|
-
else if (Array.isArray(response) || response instanceof Set) {
|
|
885
|
-
response.forEach((endValue) => {
|
|
886
|
-
if (endValue instanceof QueryBuilderObject) {
|
|
887
|
-
queryPaths.push(endValue.getPropertyPath());
|
|
888
|
-
}
|
|
889
|
-
else if (endValue instanceof SelectQueryFactory) {
|
|
890
|
-
queryPaths.push(endValue.getQueryPaths());
|
|
891
|
-
}
|
|
892
|
-
});
|
|
893
|
-
}
|
|
894
|
-
else if (response instanceof Evaluation) {
|
|
895
|
-
queryPaths.push(response.getWherePath());
|
|
896
|
-
}
|
|
897
|
-
else if (response instanceof SelectQueryFactory) {
|
|
898
|
-
queryPaths.push(response.getQueryPaths());
|
|
899
|
-
}
|
|
900
|
-
else if (!response) {
|
|
901
|
-
//that's totally fine. For example Person.select().where(p => p.name.equals('John'))
|
|
902
|
-
//will return all persons with the name John, but no properties are selected for these persons
|
|
903
|
-
}
|
|
904
|
-
//if it's an object
|
|
905
|
-
else if (typeof response === 'object') {
|
|
906
|
-
queryObject = {};
|
|
907
|
-
//then loop over all the keys
|
|
908
|
-
Object.getOwnPropertyNames(response).forEach((key) => {
|
|
909
|
-
//and add the property paths for each key
|
|
910
|
-
const value = response[key];
|
|
911
|
-
//TODO: we could potentially make Evaluation extend QueryValue, and rename getPropertyPath to something more generic,
|
|
912
|
-
//that way we can simplify the code perhaps? Or would we loose type clarity? (QueryStep is the generic one for QueryValue, and Evaluation can just return WherePath right?)
|
|
913
|
-
if (value instanceof QueryBuilderObject ||
|
|
914
|
-
value instanceof QueryPrimitiveSet) {
|
|
915
|
-
queryObject[key] = value.getPropertyPath();
|
|
916
|
-
}
|
|
917
|
-
else if (value instanceof Evaluation) {
|
|
918
|
-
queryObject[key] = value.getWherePath();
|
|
919
|
-
}
|
|
920
|
-
else {
|
|
921
|
-
throw Error('Unknown trace response type for key ' + key);
|
|
922
|
-
}
|
|
923
|
-
});
|
|
924
|
-
}
|
|
925
|
-
else {
|
|
926
|
-
throw Error('Unknown trace response type');
|
|
927
|
-
}
|
|
928
|
-
if (this.parentQueryPath) {
|
|
929
|
-
queryPaths = this.parentQueryPath.concat([
|
|
930
|
-
queryObject || queryPaths,
|
|
931
|
-
]);
|
|
932
|
-
//reset the variable so it doesn't get used again below
|
|
933
|
-
queryObject = null;
|
|
934
|
-
}
|
|
935
|
-
return queryObject || queryPaths;
|
|
936
|
-
}
|
|
937
|
-
isValidSetResult(qResults) {
|
|
938
|
-
return qResults.every((qResult) => {
|
|
939
|
-
return this.isValidResult(qResult);
|
|
940
|
-
});
|
|
941
|
-
}
|
|
942
|
-
isValidResult(qResult) {
|
|
943
|
-
let select = this.getQueryPaths();
|
|
944
|
-
if (Array.isArray(select)) {
|
|
945
|
-
return this.isValidQueryPathsResult(qResult, select);
|
|
946
|
-
}
|
|
947
|
-
else if (typeof select === 'object') {
|
|
948
|
-
return this.isValidCustomObjectResult(qResult, select);
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
clone() {
|
|
952
|
-
return new SelectQueryFactory(this.shape, this.queryBuildFn, this.subject);
|
|
953
|
-
}
|
|
954
|
-
/**
|
|
955
|
-
* Makes a clone of the query template, sets the subject and executes the query
|
|
956
|
-
* @param subject
|
|
957
|
-
*/
|
|
958
|
-
execFor(subject) {
|
|
959
|
-
//TODO: Differentiate between the result of Shape.query and the internal query in Shape.select?
|
|
960
|
-
// so that Shape.query can never be executed. Its just a template
|
|
961
|
-
return this.clone().setSubject(subject).exec();
|
|
962
|
-
}
|
|
963
|
-
patchResultPromise(p) {
|
|
964
|
-
let pAdjusted = p;
|
|
965
|
-
p['where'] = (validation) => {
|
|
966
|
-
// preventExec();
|
|
967
|
-
this.where(validation);
|
|
968
|
-
return pAdjusted;
|
|
969
|
-
};
|
|
970
|
-
p['limit'] = (lim) => {
|
|
971
|
-
this.setLimit(lim);
|
|
972
|
-
return pAdjusted;
|
|
973
|
-
};
|
|
974
|
-
p['sortBy'] = (sortFn, direction = 'ASC') => {
|
|
975
|
-
this.sortBy(sortFn, direction);
|
|
976
|
-
return pAdjusted;
|
|
977
|
-
};
|
|
978
|
-
p['one'] = () => {
|
|
979
|
-
this.setLimit(1);
|
|
980
|
-
this.singleResult = true;
|
|
981
|
-
return pAdjusted;
|
|
982
|
-
};
|
|
983
|
-
return p;
|
|
984
|
-
}
|
|
985
|
-
sortBy(sortFn, direction) {
|
|
986
|
-
let queryShape = this.getQueryShape();
|
|
987
|
-
if (sortFn) {
|
|
988
|
-
this.sortResponse = sortFn(queryShape, this);
|
|
989
|
-
this.sortDirection = direction;
|
|
990
|
-
}
|
|
991
|
-
return this;
|
|
992
|
-
}
|
|
993
|
-
init() {
|
|
994
|
-
let queryShape = this.getQueryShape();
|
|
995
|
-
if (this.queryBuildFn) {
|
|
996
|
-
let queryResponse = this.queryBuildFn(queryShape, this);
|
|
997
|
-
this.traceResponse = queryResponse;
|
|
998
|
-
}
|
|
999
|
-
this.initPromise.resolve(this.traceResponse);
|
|
1000
|
-
this.initPromise.complete = true;
|
|
1001
|
-
}
|
|
1002
|
-
initialized() {
|
|
1003
|
-
return this.initPromise.promise;
|
|
1004
|
-
}
|
|
1005
|
-
/**
|
|
1006
|
-
* Returns the dummy shape instance who's properties can be accessed freely inside a queryBuildFn
|
|
1007
|
-
* It is used to trace the properties that are accessed in the queryBuildFn
|
|
1008
|
-
* @private
|
|
1009
|
-
*/
|
|
1010
|
-
getQueryShape() {
|
|
1011
|
-
let queryShape;
|
|
1012
|
-
//if the given class already extends QueryValue
|
|
1013
|
-
if (this.shape instanceof QueryBuilderObject) {
|
|
1014
|
-
//then we're likely dealing with QueryPrimitives (end values like strings)
|
|
1015
|
-
//and we can use the given query value directly for the query evaluation
|
|
1016
|
-
queryShape = this.shape;
|
|
1017
|
-
}
|
|
1018
|
-
else {
|
|
1019
|
-
//else a shape class is given, and we need to create a dummy node to apply and trace the query
|
|
1020
|
-
let dummyShape = new this.shape();
|
|
1021
|
-
queryShape = QueryShape.create(dummyShape);
|
|
1022
|
-
}
|
|
1023
|
-
return queryShape;
|
|
1024
|
-
}
|
|
1025
|
-
getSortByPath() {
|
|
1026
|
-
if (!this.sortResponse)
|
|
1027
|
-
return null;
|
|
1028
|
-
//TODO: we should put more restrictions on sortBy and getting query paths from the response
|
|
1029
|
-
// currently it reuses much of the select logic, but for example using .where() should probably not be allowed in a sortBy function?
|
|
1030
|
-
return {
|
|
1031
|
-
paths: this.getQueryPaths(this.sortResponse),
|
|
1032
|
-
direction: this.sortDirection,
|
|
1033
|
-
};
|
|
1034
|
-
}
|
|
1035
|
-
isValidQueryPathsResult(qResult, select) {
|
|
1036
|
-
return select.every((path) => {
|
|
1037
|
-
return this.isValidQueryPathResult(qResult, path);
|
|
1038
|
-
});
|
|
1039
|
-
}
|
|
1040
|
-
isValidQueryPathResult(qResult, path, nameOverwrite) {
|
|
1041
|
-
if (Array.isArray(path)) {
|
|
1042
|
-
return this.isValidQueryStepResult(qResult, path[0], path.splice(1), nameOverwrite);
|
|
1043
|
-
}
|
|
1044
|
-
else {
|
|
1045
|
-
if (path.firstPath) {
|
|
1046
|
-
return this.isValidQueryPathResult(qResult, path.firstPath);
|
|
1047
|
-
}
|
|
1048
|
-
else if (path.path) {
|
|
1049
|
-
return this.isValidQueryPathResult(qResult, path.path);
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
isValidQueryStepResult(qResult, step, restPath = [], nameOverwrite) {
|
|
1054
|
-
if (!qResult) {
|
|
1055
|
-
return false;
|
|
1056
|
-
}
|
|
1057
|
-
if (step.property) {
|
|
1058
|
-
//if a name overwrite is given we check if that key exists instead of the property label
|
|
1059
|
-
//this happens with custom objects: for the first property step, the named key will be the accessKey used in the result instead of the first property label.
|
|
1060
|
-
//e.g. {title:item.name} in a query will result in a "title" key in the result, not "name"
|
|
1061
|
-
const accessKey = nameOverwrite || step.property.label;
|
|
1062
|
-
//also check if this property needs to have a value (minCount > 0), if not it can be empty and undefined
|
|
1063
|
-
// if (!qResult.hasOwnProperty(accessKey) && (step as PropertyQueryStep).property.minCount > 0) {
|
|
1064
|
-
//the key must be in the object. If there is no value then it should be null (or undefined, but null works better with JSON.stringify, as it keeps the key. Whilst undefined keys get removed)
|
|
1065
|
-
if (!qResult.hasOwnProperty(accessKey)) {
|
|
1066
|
-
return false;
|
|
1067
|
-
}
|
|
1068
|
-
if (restPath.length > 0) {
|
|
1069
|
-
return this.isValidQueryStepResult(qResult[accessKey], restPath[0], restPath.splice(1));
|
|
1070
|
-
}
|
|
1071
|
-
return true;
|
|
1072
|
-
}
|
|
1073
|
-
else if (step.count) {
|
|
1074
|
-
return this.isValidQueryStepResult(qResult, step.count[0]);
|
|
1075
|
-
}
|
|
1076
|
-
else if (Array.isArray(step)) {
|
|
1077
|
-
return step.every((subStep) => {
|
|
1078
|
-
return this.isValidQueryPathResult(qResult, subStep);
|
|
1079
|
-
});
|
|
1080
|
-
}
|
|
1081
|
-
else if (typeof step === 'object') {
|
|
1082
|
-
if (Array.isArray(qResult)) {
|
|
1083
|
-
return qResult.every((singleResult) => {
|
|
1084
|
-
return this.isValidQueryStepResult(singleResult, step);
|
|
1085
|
-
});
|
|
1086
|
-
}
|
|
1087
|
-
return this.isValidCustomObjectResult(qResult, step);
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
isValidCustomObjectResult(qResult, step) {
|
|
1091
|
-
//for custom objects, all keys need to be defined, even if the value is undefined
|
|
1092
|
-
for (let key in step) {
|
|
1093
|
-
if (!qResult.hasOwnProperty(key)) {
|
|
1094
|
-
return false;
|
|
1095
|
-
}
|
|
1096
|
-
let path = step[key];
|
|
1097
|
-
if (!this.isValidQueryPathResult(qResult, path, key)) {
|
|
1098
|
-
return false;
|
|
1099
|
-
}
|
|
1100
|
-
// return this.isValidQueryPathResult(qResult[key], path);
|
|
1101
|
-
}
|
|
1102
|
-
return true;
|
|
1103
|
-
}
|
|
1104
|
-
}
|
|
1105
|
-
exports.SelectQueryFactory = SelectQueryFactory;
|
|
1106
|
-
class SetSize extends QueryNumber {
|
|
684
|
+
class SetSize extends QueryPrimitive {
|
|
1107
685
|
constructor(subject, countable, label) {
|
|
1108
686
|
super();
|
|
1109
687
|
this.subject = subject;
|
|
@@ -1115,59 +693,22 @@ class SetSize extends QueryNumber {
|
|
|
1115
693
|
return this;
|
|
1116
694
|
}
|
|
1117
695
|
getPropertyPath() {
|
|
1118
|
-
//
|
|
1119
|
-
//
|
|
1120
|
-
//then creating the count step is straightforward
|
|
1121
|
-
// let countablePath = this.countable.getPropertyPath();
|
|
1122
|
-
// if (countablePath.some((step) => Array.isArray(step))) {
|
|
1123
|
-
// throw new Error(
|
|
1124
|
-
// 'Cannot count a diverging path. Provide one path of properties to count',
|
|
1125
|
-
// );
|
|
1126
|
-
// }
|
|
1127
|
-
// let self: CountStep = {
|
|
1128
|
-
// count: this.countable?.getPropertyPath(),
|
|
1129
|
-
// label: this.label,
|
|
1130
|
-
// };
|
|
1131
|
-
// //and we can add the count step to the path of the subject
|
|
1132
|
-
// let parent = this.subject.getPropertyPath();
|
|
1133
|
-
// parent.push(self);
|
|
1134
|
-
// return parent;
|
|
1135
|
-
// } else {
|
|
1136
|
-
//if nothing to count was given as an argument,
|
|
1137
|
-
//then we just count the last property in the path
|
|
1138
|
-
//also, we use the label of the last property as the label of the count step
|
|
696
|
+
//count the last property in the path
|
|
697
|
+
//use the label of the last property as the label of the count step
|
|
1139
698
|
let countable = this.subject.getPropertyStep();
|
|
1140
699
|
let self = {
|
|
1141
700
|
count: [countable],
|
|
1142
|
-
label: this.label || this.subject.property.label,
|
|
1143
|
-
//numFriends
|
|
1144
|
-
// label: this.label || 'num'+this.subject.property.label[0].toUpperCase()+this.subject.property.label.slice(1),//the default is property name + 'Size', i.e., friendsSize
|
|
701
|
+
label: this.label || this.subject.property.label,
|
|
1145
702
|
};
|
|
1146
|
-
//
|
|
1147
|
-
//and add the
|
|
1148
|
-
//since we already used the subject as the thing that's counted.
|
|
703
|
+
//request the path of the subject's subject (the parent of the parent)
|
|
704
|
+
//and add the SizeStep to that path, since we already used the subject as the thing that's counted
|
|
1149
705
|
if (this.subject.subject) {
|
|
1150
706
|
let path = this.subject.subject.getPropertyPath();
|
|
1151
707
|
path.push(self);
|
|
1152
708
|
return path;
|
|
1153
709
|
}
|
|
1154
|
-
//if there is no parent of a parent, then we just return the count step as the whole path
|
|
1155
710
|
return [self];
|
|
1156
|
-
// }
|
|
1157
711
|
}
|
|
1158
712
|
}
|
|
1159
713
|
exports.SetSize = SetSize;
|
|
1160
|
-
/**
|
|
1161
|
-
* A sub query that is used to filter results
|
|
1162
|
-
* i.e p.friends.where(f => //LinkedWhereQuery here)
|
|
1163
|
-
*/
|
|
1164
|
-
class LinkedWhereQuery extends SelectQueryFactory {
|
|
1165
|
-
getResponse() {
|
|
1166
|
-
return this.traceResponse;
|
|
1167
|
-
}
|
|
1168
|
-
getWherePath() {
|
|
1169
|
-
return this.traceResponse.getWherePath();
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
1172
|
-
exports.LinkedWhereQuery = LinkedWhereQuery;
|
|
1173
714
|
//# sourceMappingURL=SelectQuery.js.map
|