@_linked/core 1.2.1 → 2.0.0-next.20260310082533
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 +117 -6
- package/README.md +209 -14
- package/lib/cjs/index.d.ts +10 -2
- package/lib/cjs/index.js +33 -8
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/interfaces/IQuadStore.d.ts +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/queryDispatch.d.ts +20 -0
- package/lib/cjs/queries/queryDispatch.js +15 -0
- package/lib/cjs/queries/queryDispatch.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 -50
- 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-capture-store.d.ts +8 -2
- package/lib/cjs/test-helpers/query-capture-store.js +80 -34
- package/lib/cjs/test-helpers/query-capture-store.js.map +1 -1
- package/lib/cjs/test-helpers/query-fixtures.d.ts +564 -3045
- 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/LinkedStorage.d.ts +3 -4
- package/lib/cjs/utils/LinkedStorage.js +12 -6
- package/lib/cjs/utils/LinkedStorage.js.map +1 -1
- 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 +25 -4
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/interfaces/IQuadStore.d.ts +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/queryDispatch.d.ts +20 -0
- package/lib/esm/queries/queryDispatch.js +11 -0
- package/lib/esm/queries/queryDispatch.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 -47
- 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-capture-store.d.ts +8 -2
- package/lib/esm/test-helpers/query-capture-store.js +45 -33
- package/lib/esm/test-helpers/query-capture-store.js.map +1 -1
- package/lib/esm/test-helpers/query-fixtures.d.ts +564 -3045
- 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/LinkedStorage.d.ts +3 -4
- package/lib/esm/utils/LinkedStorage.js +12 -6
- package/lib/esm/utils/LinkedStorage.js.map +1 -1
- 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
- package/lib/cjs/queries/QueryParser.d.ts +0 -17
- package/lib/cjs/queries/QueryParser.js +0 -55
- package/lib/cjs/queries/QueryParser.js.map +0 -1
- package/lib/esm/queries/QueryParser.d.ts +0 -17
- package/lib/esm/queries/QueryParser.js +0 -51
- package/lib/esm/queries/QueryParser.js.map +0 -1
|
@@ -3,10 +3,10 @@ import { ShapeSet } from '../collections/ShapeSet.js';
|
|
|
3
3
|
import { shacl } from '../ontologies/shacl.js';
|
|
4
4
|
import { CoreSet } from '../collections/CoreSet.js';
|
|
5
5
|
import { getPropertyShapeByLabel, getShapeClass } from '../utils/ShapeClass.js';
|
|
6
|
-
import { QueryFactory } from './QueryFactory.js';
|
|
7
6
|
import { xsd } from '../ontologies/xsd.js';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { createProxiedPathBuilder } from './ProxiedPathBuilder.js';
|
|
8
|
+
import { FieldSet } from './FieldSet.js';
|
|
9
|
+
import { PropertyPath } from './PropertyPath.js';
|
|
10
10
|
const isSameRef = (a, b) => !!a && !!b && a.id === b.id;
|
|
11
11
|
export var WhereMethods;
|
|
12
12
|
(function (WhereMethods) {
|
|
@@ -43,16 +43,16 @@ export class QueryBuilderObject {
|
|
|
43
43
|
return QueryShapeSet.create(originalValue, property, subject);
|
|
44
44
|
}
|
|
45
45
|
else if (typeof originalValue === 'string') {
|
|
46
|
-
return new
|
|
46
|
+
return new QueryPrimitive(originalValue, property, subject);
|
|
47
47
|
}
|
|
48
48
|
else if (typeof originalValue === 'number') {
|
|
49
|
-
return new
|
|
49
|
+
return new QueryPrimitive(originalValue, property, subject);
|
|
50
50
|
}
|
|
51
51
|
else if (typeof originalValue === 'boolean') {
|
|
52
|
-
return new
|
|
52
|
+
return new QueryPrimitive(originalValue, property, subject);
|
|
53
53
|
}
|
|
54
54
|
else if (originalValue instanceof Date) {
|
|
55
|
-
return new
|
|
55
|
+
return new QueryPrimitive(originalValue, property, subject);
|
|
56
56
|
}
|
|
57
57
|
else if (Array.isArray(originalValue)) {
|
|
58
58
|
return new QueryPrimitiveSet(originalValue, property, subject);
|
|
@@ -91,23 +91,23 @@ export class QueryBuilderObject {
|
|
|
91
91
|
if (datatype) {
|
|
92
92
|
if (singleValue) {
|
|
93
93
|
if (isSameRef(datatype, xsd.integer)) {
|
|
94
|
-
return new
|
|
94
|
+
return new QueryPrimitive(0, property, subject);
|
|
95
95
|
}
|
|
96
96
|
else if (isSameRef(datatype, xsd.boolean)) {
|
|
97
|
-
return new
|
|
97
|
+
return new QueryPrimitive(false, property, subject);
|
|
98
98
|
}
|
|
99
99
|
else if (isSameRef(datatype, xsd.dateTime) ||
|
|
100
100
|
isSameRef(datatype, xsd.date)) {
|
|
101
|
-
return new
|
|
101
|
+
return new QueryPrimitive(new Date(), property, subject);
|
|
102
102
|
}
|
|
103
103
|
else if (isSameRef(datatype, xsd.string)) {
|
|
104
|
-
return new
|
|
104
|
+
return new QueryPrimitive('', property, subject);
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
else {
|
|
108
108
|
//TODO review this, do we need property & subject in both of these? currently yes, but why
|
|
109
109
|
return new QueryPrimitiveSet([''], property, subject, [
|
|
110
|
-
new
|
|
110
|
+
new QueryPrimitive('', property, subject),
|
|
111
111
|
]);
|
|
112
112
|
}
|
|
113
113
|
}
|
|
@@ -134,30 +134,17 @@ export class QueryBuilderObject {
|
|
|
134
134
|
isSameRef(property.nodeKind, shacl.BlankNodeOrLiteral)) {
|
|
135
135
|
if (singleValue) {
|
|
136
136
|
//default to string if no datatype is set
|
|
137
|
-
return new
|
|
137
|
+
return new QueryPrimitive('', property, subject);
|
|
138
138
|
}
|
|
139
139
|
else {
|
|
140
140
|
//TODO review this, do we need property & subject in both of these? currently yes, but why
|
|
141
141
|
return new QueryPrimitiveSet([''], property, subject, [
|
|
142
|
-
new
|
|
142
|
+
new QueryPrimitive('', property, subject),
|
|
143
143
|
]);
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
//if an object is expected and no value shape is set, then warn
|
|
147
147
|
throw Error(`No shape set for objectProperty ${property.parentNodeShape.label}.${property.label}`);
|
|
148
|
-
// //and use a generic shape
|
|
149
|
-
// const shapeValue = new (Shape as any)(new TestNode(path));
|
|
150
|
-
// if (singleValue) {
|
|
151
|
-
// return QueryShape.create(shapeValue, property, subject);
|
|
152
|
-
// } else {
|
|
153
|
-
// //check if shapeValue is iterable
|
|
154
|
-
// if (!(Symbol.iterator in Object(shapeValue))) {
|
|
155
|
-
// throw new Error(
|
|
156
|
-
// `Property ${property.parentNodeShape.label}.${property.label} is not marked as single value (maxCount:1), but the value is not iterable`,
|
|
157
|
-
// );
|
|
158
|
-
// }
|
|
159
|
-
// return QueryShapeSet.create(new ShapeSet(shapeValue), property, subject);
|
|
160
|
-
// }
|
|
161
148
|
}
|
|
162
149
|
static getOriginalSource(endValue) {
|
|
163
150
|
if (typeof endValue === 'undefined')
|
|
@@ -165,7 +152,7 @@ export class QueryBuilderObject {
|
|
|
165
152
|
if (endValue instanceof QueryPrimitiveSet) {
|
|
166
153
|
return new ShapeSet(endValue.contents.map((endValue) => this.getOriginalSource(endValue)));
|
|
167
154
|
}
|
|
168
|
-
if (endValue instanceof
|
|
155
|
+
if (endValue instanceof QueryPrimitive) {
|
|
169
156
|
return endValue.subject
|
|
170
157
|
? this.getOriginalSource(endValue.subject)
|
|
171
158
|
: endValue.originalValue;
|
|
@@ -199,7 +186,6 @@ export class QueryBuilderObject {
|
|
|
199
186
|
return new BoundComponent(component, this);
|
|
200
187
|
}
|
|
201
188
|
limit(lim) {
|
|
202
|
-
console.log(lim);
|
|
203
189
|
}
|
|
204
190
|
/**
|
|
205
191
|
* Returns the path of properties that were requested to reach this value
|
|
@@ -227,45 +213,6 @@ export class BoundComponent extends QueryBuilderObject {
|
|
|
227
213
|
this.originalValue = originalValue;
|
|
228
214
|
this.source = source;
|
|
229
215
|
}
|
|
230
|
-
getParentQueryFactory() {
|
|
231
|
-
let parentQuery = this.originalValue.query;
|
|
232
|
-
if (parentQuery instanceof SelectQueryFactory) {
|
|
233
|
-
return parentQuery;
|
|
234
|
-
}
|
|
235
|
-
if (typeof parentQuery === 'object') {
|
|
236
|
-
if (Object.keys(parentQuery).length > 1) {
|
|
237
|
-
throw new Error('Only one key is allowed to map a query to a property for linkedSetComponents');
|
|
238
|
-
}
|
|
239
|
-
for (let key in parentQuery) {
|
|
240
|
-
if (parentQuery[key] instanceof SelectQueryFactory) {
|
|
241
|
-
return parentQuery[key];
|
|
242
|
-
}
|
|
243
|
-
throw new Error('Unknown value type for query object. Keep to this format: {propName: Shape.query(s => ...)}');
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
throw new Error('Unknown data query type. Expected a SelectQueryFactory (from Shape.query()) or an object with 1 key whose value is a SelectQueryFactory');
|
|
247
|
-
}
|
|
248
|
-
getPropertyPath() {
|
|
249
|
-
let sourcePath = this.source.getPropertyPath();
|
|
250
|
-
let requestQuery = this.getParentQueryFactory();
|
|
251
|
-
let compSelectQuery = requestQuery.getQueryPaths();
|
|
252
|
-
if (Array.isArray(sourcePath)) {
|
|
253
|
-
if (Array.isArray(compSelectQuery)) {
|
|
254
|
-
// QueryPath[] — unwrap single-element arrays for compact representation
|
|
255
|
-
const unwrapped = compSelectQuery.length === 1
|
|
256
|
-
? Array.isArray(compSelectQuery[0]) && compSelectQuery[0].length === 1
|
|
257
|
-
? compSelectQuery[0][0]
|
|
258
|
-
: compSelectQuery[0]
|
|
259
|
-
: compSelectQuery;
|
|
260
|
-
sourcePath.push(unwrapped);
|
|
261
|
-
}
|
|
262
|
-
else {
|
|
263
|
-
// CustomQueryObject
|
|
264
|
-
sourcePath.push(compSelectQuery);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
return sourcePath;
|
|
268
|
-
}
|
|
269
216
|
}
|
|
270
217
|
/**
|
|
271
218
|
* Converts query context to a ShapeReferenceValue
|
|
@@ -278,17 +225,40 @@ const convertQueryContext = (shape) => {
|
|
|
278
225
|
},
|
|
279
226
|
};
|
|
280
227
|
};
|
|
281
|
-
const processWhereClause = (validation, shape) => {
|
|
228
|
+
export const processWhereClause = (validation, shape) => {
|
|
282
229
|
if (validation instanceof Function) {
|
|
283
230
|
if (!shape) {
|
|
284
231
|
throw new Error('Cannot process where clause without shape');
|
|
285
232
|
}
|
|
286
|
-
|
|
233
|
+
const proxy = createProxiedPathBuilder(shape);
|
|
234
|
+
const evaluation = validation(proxy);
|
|
235
|
+
return evaluation.getWherePath();
|
|
287
236
|
}
|
|
288
237
|
else {
|
|
289
238
|
return validation.getWherePath();
|
|
290
239
|
}
|
|
291
240
|
};
|
|
241
|
+
/**
|
|
242
|
+
* Evaluate a sort callback through the proxy and extract a SortByPath.
|
|
243
|
+
* This is a standalone helper that replaces the need for the former SelectQueryFactory.sortBy().
|
|
244
|
+
*/
|
|
245
|
+
export const evaluateSortCallback = (shape, sortFn, direction = 'ASC') => {
|
|
246
|
+
const proxy = createProxiedPathBuilder(shape);
|
|
247
|
+
const response = sortFn(proxy);
|
|
248
|
+
const nodeShape = shape.shape;
|
|
249
|
+
const paths = [];
|
|
250
|
+
if (response instanceof QueryBuilderObject || response instanceof QueryPrimitiveSet) {
|
|
251
|
+
paths.push(new PropertyPath(nodeShape, FieldSet.collectPropertySegments(response)));
|
|
252
|
+
}
|
|
253
|
+
else if (Array.isArray(response)) {
|
|
254
|
+
for (const item of response) {
|
|
255
|
+
if (item instanceof QueryBuilderObject) {
|
|
256
|
+
paths.push(new PropertyPath(nodeShape, FieldSet.collectPropertySegments(item)));
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return { paths, direction };
|
|
261
|
+
};
|
|
292
262
|
export class QueryShapeSet extends QueryBuilderObject {
|
|
293
263
|
constructor(_originalValue, property, subject) {
|
|
294
264
|
super(property, subject);
|
|
@@ -344,8 +314,6 @@ export class QueryShapeSet extends QueryBuilderObject {
|
|
|
344
314
|
return originalShapeSet[key].bind(originalShapeSet);
|
|
345
315
|
}
|
|
346
316
|
else if (key !== 'then' && key !== '$$typeof') {
|
|
347
|
-
//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
|
|
348
|
-
//hiding the warning for now in that case as it doesn't seem to affect the results
|
|
349
317
|
console.warn('Could not find property shape for key ' +
|
|
350
318
|
key +
|
|
351
319
|
' on shape ' +
|
|
@@ -452,10 +420,10 @@ export class QueryShapeSet extends QueryBuilderObject {
|
|
|
452
420
|
return this.proxy;
|
|
453
421
|
}
|
|
454
422
|
select(subQueryFn) {
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
return
|
|
423
|
+
const leastSpecificShape = this.getOriginalValue().getLeastSpecificShape();
|
|
424
|
+
const parentSegments = FieldSet.collectPropertySegments(this);
|
|
425
|
+
const fs = FieldSet.forSubSelect(leastSpecificShape, subQueryFn, parentSegments);
|
|
426
|
+
return fs;
|
|
459
427
|
}
|
|
460
428
|
selectAll() {
|
|
461
429
|
let leastSpecificShape = this.getOriginalValue().getLeastSpecificShape();
|
|
@@ -487,12 +455,6 @@ export class QueryShape extends QueryBuilderObject {
|
|
|
487
455
|
return (this.originalValue.__queryContextId ||
|
|
488
456
|
this.originalValue['id']);
|
|
489
457
|
}
|
|
490
|
-
// where(validation: WhereClause<S>): this {
|
|
491
|
-
// let nodeShape = this.originalValue.nodeShape;
|
|
492
|
-
// this.wherePath = processWhereClause(validation, nodeShape);
|
|
493
|
-
// //return this because after Shape.friends.where() we can call other methods of Shape.friends
|
|
494
|
-
// return this.proxy;
|
|
495
|
-
// }
|
|
496
458
|
static create(original, property, subject) {
|
|
497
459
|
let instance = new QueryShape(original, property, subject);
|
|
498
460
|
let proxy = this.proxifyQueryShape(instance);
|
|
@@ -517,27 +479,9 @@ export class QueryShape extends QueryBuilderObject {
|
|
|
517
479
|
//if not, then a method/accessor of the original shape was called
|
|
518
480
|
//then check if we have indexed any property shapes with that name for this shapes NodeShape
|
|
519
481
|
//NOTE: this will only work with a @linkedProperty decorator
|
|
520
|
-
// let propertyShape = originalShape.nodeShape
|
|
521
|
-
// .getPropertyShapes()
|
|
522
|
-
// .find((propertyShape) => propertyShape.label === key);
|
|
523
482
|
let propertyShape = getPropertyShapeByLabel(originalShape.constructor, key);
|
|
524
483
|
if (propertyShape) {
|
|
525
|
-
//generate the query shape based on the property shape
|
|
526
|
-
// let nodeValue;
|
|
527
|
-
// if(propertyShape.maxCount <= 1) {
|
|
528
|
-
// nodeValue = new TestNode(propertyShape.path);
|
|
529
|
-
// } else {
|
|
530
|
-
// nodeValue = new NodeSet(new TestNode(propertyShape.path));
|
|
531
|
-
// }
|
|
532
484
|
return QueryBuilderObject.generatePathValue(propertyShape, target);
|
|
533
|
-
//get the value of the property from the original shape
|
|
534
|
-
// let value = originalShape[key];
|
|
535
|
-
// //convert the value into a query value
|
|
536
|
-
// return QueryBuilderObject.convertOriginal(
|
|
537
|
-
// value,
|
|
538
|
-
// propertyShape,
|
|
539
|
-
// queryShape,
|
|
540
|
-
// );
|
|
541
485
|
}
|
|
542
486
|
}
|
|
543
487
|
if (key !== 'then' && key !== '$$typeof') {
|
|
@@ -547,8 +491,6 @@ export class QueryShape extends QueryBuilderObject {
|
|
|
547
491
|
//https://stackoverflow.com/a/49725198/977206
|
|
548
492
|
const stackLines = stack.split('\n').slice(1); //remove the "Error" line
|
|
549
493
|
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')}`);
|
|
550
|
-
// } else {
|
|
551
|
-
// console.error('Proxy is accessed like a promise');
|
|
552
494
|
}
|
|
553
495
|
return originalShape[key];
|
|
554
496
|
},
|
|
@@ -564,18 +506,16 @@ export class QueryShape extends QueryBuilderObject {
|
|
|
564
506
|
}
|
|
565
507
|
return QueryShape.create(newOriginal, this.property, this.subject);
|
|
566
508
|
}
|
|
567
|
-
// else return this
|
|
568
509
|
return this;
|
|
569
|
-
// return this.proxy;
|
|
570
510
|
}
|
|
571
511
|
equals(otherValue) {
|
|
572
512
|
return new Evaluation(this, WhereMethods.EQUALS, [otherValue]);
|
|
573
513
|
}
|
|
574
514
|
select(subQueryFn) {
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
return
|
|
515
|
+
const leastSpecificShape = getShapeClass(this.getOriginalValue().nodeShape.id);
|
|
516
|
+
const parentSegments = FieldSet.collectPropertySegments(this);
|
|
517
|
+
const fs = FieldSet.forSubSelect(leastSpecificShape, subQueryFn, parentSegments);
|
|
518
|
+
return fs;
|
|
579
519
|
}
|
|
580
520
|
selectAll() {
|
|
581
521
|
let leastSpecificShape = getShapeClass(this.getOriginalValue().nodeShape.id);
|
|
@@ -651,8 +591,11 @@ export class Evaluation {
|
|
|
651
591
|
class SetEvaluation extends Evaluation {
|
|
652
592
|
}
|
|
653
593
|
/**
|
|
654
|
-
*
|
|
655
|
-
*
|
|
594
|
+
* Concrete query wrapper for JS primitive values (string, number, boolean, Date).
|
|
595
|
+
*
|
|
596
|
+
* Replaces the former abstract class + subclasses (QueryString, QueryNumber,
|
|
597
|
+
* QueryBoolean, QueryDate) — the type parameter T carries the primitive type,
|
|
598
|
+
* so separate subclasses are unnecessary.
|
|
656
599
|
*/
|
|
657
600
|
export class QueryPrimitive extends QueryBuilderObject {
|
|
658
601
|
constructor(originalValue, property, subject) {
|
|
@@ -667,21 +610,11 @@ export class QueryPrimitive extends QueryBuilderObject {
|
|
|
667
610
|
}
|
|
668
611
|
where(validation) {
|
|
669
612
|
// let nodeShape = this.subject.getOriginalValue().nodeShape;
|
|
670
|
-
this.wherePath = processWhereClause(validation, new
|
|
613
|
+
this.wherePath = processWhereClause(validation, new QueryPrimitive(''));
|
|
671
614
|
//return this because after Shape.friends.where() we can call other methods of Shape.friends
|
|
672
615
|
return this;
|
|
673
616
|
}
|
|
674
617
|
}
|
|
675
|
-
//@TODO: QueryString, QueryNumber, QueryBoolean, QueryDate can all be replaced with QueryPrimitive, and we can infer the original type, no need for these extra classes
|
|
676
|
-
//UPDATE some of this has started. Query response to result conversion is using QueryPrimitive only
|
|
677
|
-
export class QueryString extends QueryPrimitive {
|
|
678
|
-
}
|
|
679
|
-
export class QueryDate extends QueryPrimitive {
|
|
680
|
-
}
|
|
681
|
-
export class QueryNumber extends QueryPrimitive {
|
|
682
|
-
}
|
|
683
|
-
export class QueryBoolean extends QueryPrimitive {
|
|
684
|
-
}
|
|
685
618
|
export class QueryPrimitiveSet extends QueryBuilderObject {
|
|
686
619
|
constructor(originalValue, property, subject, items) {
|
|
687
620
|
super(property, subject);
|
|
@@ -700,7 +633,7 @@ export class QueryPrimitiveSet extends QueryBuilderObject {
|
|
|
700
633
|
createNew(...args) {
|
|
701
634
|
return new this.constructor(this.property, this.subject, ...args);
|
|
702
635
|
}
|
|
703
|
-
//TODO: see if we can merge these methods of
|
|
636
|
+
//TODO: see if we can merge these methods of QueryPrimitive and QueryPrimitiveSet
|
|
704
637
|
// so that they're only defined once
|
|
705
638
|
equals(other) {
|
|
706
639
|
return new Evaluation(this, WhereMethods.EQUALS, [other]);
|
|
@@ -735,358 +668,7 @@ export class QueryPrimitiveSet extends QueryBuilderObject {
|
|
|
735
668
|
//countable, resultKey
|
|
736
669
|
}
|
|
737
670
|
}
|
|
738
|
-
|
|
739
|
-
let callbackStack = [];
|
|
740
|
-
const docReady = () => {
|
|
741
|
-
documentLoaded = true;
|
|
742
|
-
callbackStack.forEach((callback) => callback());
|
|
743
|
-
callbackStack = [];
|
|
744
|
-
};
|
|
745
|
-
if (typeof document === 'undefined' || document.readyState !== 'loading') {
|
|
746
|
-
docReady();
|
|
747
|
-
}
|
|
748
|
-
else {
|
|
749
|
-
documentLoaded = false;
|
|
750
|
-
document.addEventListener('DOMContentLoaded', () => () => {
|
|
751
|
-
docReady();
|
|
752
|
-
});
|
|
753
|
-
setTimeout(() => {
|
|
754
|
-
if (!documentLoaded) {
|
|
755
|
-
console.warn('⚠️ Forcing init after timeout');
|
|
756
|
-
docReady();
|
|
757
|
-
}
|
|
758
|
-
}, 3500);
|
|
759
|
-
}
|
|
760
|
-
//only continue to parse the query if the document is ready, and all shapes from initial bundles are loaded
|
|
761
|
-
export var onQueriesReady = (callback) => {
|
|
762
|
-
if (!documentLoaded) {
|
|
763
|
-
callbackStack.push(callback);
|
|
764
|
-
}
|
|
765
|
-
else {
|
|
766
|
-
callback();
|
|
767
|
-
}
|
|
768
|
-
};
|
|
769
|
-
export class SelectQueryFactory extends QueryFactory {
|
|
770
|
-
constructor(shape, queryBuildFn, subject) {
|
|
771
|
-
super();
|
|
772
|
-
this.shape = shape;
|
|
773
|
-
this.queryBuildFn = queryBuildFn;
|
|
774
|
-
this.subject = subject;
|
|
775
|
-
let promise, resolve, reject;
|
|
776
|
-
promise = new Promise((res, rej) => {
|
|
777
|
-
resolve = res;
|
|
778
|
-
reject = rej;
|
|
779
|
-
});
|
|
780
|
-
this.initPromise = { promise, resolve, reject, complete: false };
|
|
781
|
-
//only continue to parse the query if the document is ready, and all shapes from initial bundles are loaded
|
|
782
|
-
if (typeof document === 'undefined' || document.readyState !== 'loading') {
|
|
783
|
-
this.init();
|
|
784
|
-
}
|
|
785
|
-
else {
|
|
786
|
-
document.addEventListener('DOMContentLoaded', () => this.init());
|
|
787
|
-
setTimeout(() => {
|
|
788
|
-
if (!this.initPromise.complete) {
|
|
789
|
-
console.warn('⚠️ Forcing init after timeout');
|
|
790
|
-
this.init();
|
|
791
|
-
}
|
|
792
|
-
}, 3500);
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
setLimit(limit) {
|
|
796
|
-
this.limit = limit;
|
|
797
|
-
}
|
|
798
|
-
getLimit() {
|
|
799
|
-
return this.limit;
|
|
800
|
-
}
|
|
801
|
-
setOffset(offset) {
|
|
802
|
-
this.offset = offset;
|
|
803
|
-
}
|
|
804
|
-
getOffset() {
|
|
805
|
-
return this.offset;
|
|
806
|
-
}
|
|
807
|
-
setSubject(subject) {
|
|
808
|
-
this.subject = subject;
|
|
809
|
-
return this;
|
|
810
|
-
}
|
|
811
|
-
where(validation) {
|
|
812
|
-
this.wherePath = processWhereClause(validation, this.shape);
|
|
813
|
-
return this;
|
|
814
|
-
}
|
|
815
|
-
exec() {
|
|
816
|
-
return QueryParser.selectQuery(this);
|
|
817
|
-
}
|
|
818
|
-
/**
|
|
819
|
-
* Returns the raw pipeline input for this query.
|
|
820
|
-
* Used internally by build() and by test helpers that need
|
|
821
|
-
* to feed factory state into individual pipeline stages.
|
|
822
|
-
*/
|
|
823
|
-
toRawInput() {
|
|
824
|
-
const input = {
|
|
825
|
-
select: this.getQueryPaths(),
|
|
826
|
-
subject: this.getSubject(),
|
|
827
|
-
limit: this.limit,
|
|
828
|
-
offset: this.offset,
|
|
829
|
-
shape: this.shape,
|
|
830
|
-
sortBy: this.getSortByPath(),
|
|
831
|
-
singleResult: this.singleResult ||
|
|
832
|
-
!!(this.subject &&
|
|
833
|
-
('id' in this.subject || 'id' in this.subject)),
|
|
834
|
-
};
|
|
835
|
-
if (this.wherePath) {
|
|
836
|
-
input.where = this.wherePath;
|
|
837
|
-
}
|
|
838
|
-
return input;
|
|
839
|
-
}
|
|
840
|
-
build() {
|
|
841
|
-
return buildSelectQuery(this.toRawInput());
|
|
842
|
-
}
|
|
843
|
-
getSubject() {
|
|
844
|
-
var _a, _b;
|
|
845
|
-
//if the subject is a QueryShape which comes from query context
|
|
846
|
-
//then it will carry a query context id and we convert it to a node reference
|
|
847
|
-
//NOTE: its important to access originalValue instead of .node directly because QueryShape.node may be undefined
|
|
848
|
-
if ((_b = (_a = this.subject) === null || _a === void 0 ? void 0 : _a.originalValue) === null || _b === void 0 ? void 0 : _b.__queryContextId) {
|
|
849
|
-
return convertQueryContext(this.subject);
|
|
850
|
-
}
|
|
851
|
-
// }
|
|
852
|
-
return this.subject;
|
|
853
|
-
}
|
|
854
|
-
/**
|
|
855
|
-
* Returns an array of query paths
|
|
856
|
-
* 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]))
|
|
857
|
-
* Each query path is returned as array of the property paths requested, with potential where clauses (together called a QueryStep)
|
|
858
|
-
*/
|
|
859
|
-
getQueryPaths(response = this.traceResponse) {
|
|
860
|
-
let queryPaths = [];
|
|
861
|
-
let queryObject;
|
|
862
|
-
//if the trace response is an array, then multiple paths were requested
|
|
863
|
-
if (response instanceof QueryBuilderObject ||
|
|
864
|
-
response instanceof QueryPrimitiveSet) {
|
|
865
|
-
//if it's a single value, then only one path was requested, and we can add it directly
|
|
866
|
-
queryPaths.push(response.getPropertyPath());
|
|
867
|
-
}
|
|
868
|
-
else if (Array.isArray(response) || response instanceof Set) {
|
|
869
|
-
response.forEach((endValue) => {
|
|
870
|
-
if (endValue instanceof QueryBuilderObject) {
|
|
871
|
-
queryPaths.push(endValue.getPropertyPath());
|
|
872
|
-
}
|
|
873
|
-
else if (endValue instanceof SelectQueryFactory) {
|
|
874
|
-
queryPaths.push(endValue.getQueryPaths());
|
|
875
|
-
}
|
|
876
|
-
});
|
|
877
|
-
}
|
|
878
|
-
else if (response instanceof Evaluation) {
|
|
879
|
-
queryPaths.push(response.getWherePath());
|
|
880
|
-
}
|
|
881
|
-
else if (response instanceof SelectQueryFactory) {
|
|
882
|
-
queryPaths.push(response.getQueryPaths());
|
|
883
|
-
}
|
|
884
|
-
else if (!response) {
|
|
885
|
-
//that's totally fine. For example Person.select().where(p => p.name.equals('John'))
|
|
886
|
-
//will return all persons with the name John, but no properties are selected for these persons
|
|
887
|
-
}
|
|
888
|
-
//if it's an object
|
|
889
|
-
else if (typeof response === 'object') {
|
|
890
|
-
queryObject = {};
|
|
891
|
-
//then loop over all the keys
|
|
892
|
-
Object.getOwnPropertyNames(response).forEach((key) => {
|
|
893
|
-
//and add the property paths for each key
|
|
894
|
-
const value = response[key];
|
|
895
|
-
//TODO: we could potentially make Evaluation extend QueryValue, and rename getPropertyPath to something more generic,
|
|
896
|
-
//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?)
|
|
897
|
-
if (value instanceof QueryBuilderObject ||
|
|
898
|
-
value instanceof QueryPrimitiveSet) {
|
|
899
|
-
queryObject[key] = value.getPropertyPath();
|
|
900
|
-
}
|
|
901
|
-
else if (value instanceof Evaluation) {
|
|
902
|
-
queryObject[key] = value.getWherePath();
|
|
903
|
-
}
|
|
904
|
-
else {
|
|
905
|
-
throw Error('Unknown trace response type for key ' + key);
|
|
906
|
-
}
|
|
907
|
-
});
|
|
908
|
-
}
|
|
909
|
-
else {
|
|
910
|
-
throw Error('Unknown trace response type');
|
|
911
|
-
}
|
|
912
|
-
if (this.parentQueryPath) {
|
|
913
|
-
queryPaths = this.parentQueryPath.concat([
|
|
914
|
-
queryObject || queryPaths,
|
|
915
|
-
]);
|
|
916
|
-
//reset the variable so it doesn't get used again below
|
|
917
|
-
queryObject = null;
|
|
918
|
-
}
|
|
919
|
-
return queryObject || queryPaths;
|
|
920
|
-
}
|
|
921
|
-
isValidSetResult(qResults) {
|
|
922
|
-
return qResults.every((qResult) => {
|
|
923
|
-
return this.isValidResult(qResult);
|
|
924
|
-
});
|
|
925
|
-
}
|
|
926
|
-
isValidResult(qResult) {
|
|
927
|
-
let select = this.getQueryPaths();
|
|
928
|
-
if (Array.isArray(select)) {
|
|
929
|
-
return this.isValidQueryPathsResult(qResult, select);
|
|
930
|
-
}
|
|
931
|
-
else if (typeof select === 'object') {
|
|
932
|
-
return this.isValidCustomObjectResult(qResult, select);
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
clone() {
|
|
936
|
-
return new SelectQueryFactory(this.shape, this.queryBuildFn, this.subject);
|
|
937
|
-
}
|
|
938
|
-
/**
|
|
939
|
-
* Makes a clone of the query template, sets the subject and executes the query
|
|
940
|
-
* @param subject
|
|
941
|
-
*/
|
|
942
|
-
execFor(subject) {
|
|
943
|
-
//TODO: Differentiate between the result of Shape.query and the internal query in Shape.select?
|
|
944
|
-
// so that Shape.query can never be executed. Its just a template
|
|
945
|
-
return this.clone().setSubject(subject).exec();
|
|
946
|
-
}
|
|
947
|
-
patchResultPromise(p) {
|
|
948
|
-
let pAdjusted = p;
|
|
949
|
-
p['where'] = (validation) => {
|
|
950
|
-
// preventExec();
|
|
951
|
-
this.where(validation);
|
|
952
|
-
return pAdjusted;
|
|
953
|
-
};
|
|
954
|
-
p['limit'] = (lim) => {
|
|
955
|
-
this.setLimit(lim);
|
|
956
|
-
return pAdjusted;
|
|
957
|
-
};
|
|
958
|
-
p['sortBy'] = (sortFn, direction = 'ASC') => {
|
|
959
|
-
this.sortBy(sortFn, direction);
|
|
960
|
-
return pAdjusted;
|
|
961
|
-
};
|
|
962
|
-
p['one'] = () => {
|
|
963
|
-
this.setLimit(1);
|
|
964
|
-
this.singleResult = true;
|
|
965
|
-
return pAdjusted;
|
|
966
|
-
};
|
|
967
|
-
return p;
|
|
968
|
-
}
|
|
969
|
-
sortBy(sortFn, direction) {
|
|
970
|
-
let queryShape = this.getQueryShape();
|
|
971
|
-
if (sortFn) {
|
|
972
|
-
this.sortResponse = sortFn(queryShape, this);
|
|
973
|
-
this.sortDirection = direction;
|
|
974
|
-
}
|
|
975
|
-
return this;
|
|
976
|
-
}
|
|
977
|
-
init() {
|
|
978
|
-
let queryShape = this.getQueryShape();
|
|
979
|
-
if (this.queryBuildFn) {
|
|
980
|
-
let queryResponse = this.queryBuildFn(queryShape, this);
|
|
981
|
-
this.traceResponse = queryResponse;
|
|
982
|
-
}
|
|
983
|
-
this.initPromise.resolve(this.traceResponse);
|
|
984
|
-
this.initPromise.complete = true;
|
|
985
|
-
}
|
|
986
|
-
initialized() {
|
|
987
|
-
return this.initPromise.promise;
|
|
988
|
-
}
|
|
989
|
-
/**
|
|
990
|
-
* Returns the dummy shape instance who's properties can be accessed freely inside a queryBuildFn
|
|
991
|
-
* It is used to trace the properties that are accessed in the queryBuildFn
|
|
992
|
-
* @private
|
|
993
|
-
*/
|
|
994
|
-
getQueryShape() {
|
|
995
|
-
let queryShape;
|
|
996
|
-
//if the given class already extends QueryValue
|
|
997
|
-
if (this.shape instanceof QueryBuilderObject) {
|
|
998
|
-
//then we're likely dealing with QueryPrimitives (end values like strings)
|
|
999
|
-
//and we can use the given query value directly for the query evaluation
|
|
1000
|
-
queryShape = this.shape;
|
|
1001
|
-
}
|
|
1002
|
-
else {
|
|
1003
|
-
//else a shape class is given, and we need to create a dummy node to apply and trace the query
|
|
1004
|
-
let dummyShape = new this.shape();
|
|
1005
|
-
queryShape = QueryShape.create(dummyShape);
|
|
1006
|
-
}
|
|
1007
|
-
return queryShape;
|
|
1008
|
-
}
|
|
1009
|
-
getSortByPath() {
|
|
1010
|
-
if (!this.sortResponse)
|
|
1011
|
-
return null;
|
|
1012
|
-
//TODO: we should put more restrictions on sortBy and getting query paths from the response
|
|
1013
|
-
// currently it reuses much of the select logic, but for example using .where() should probably not be allowed in a sortBy function?
|
|
1014
|
-
return {
|
|
1015
|
-
paths: this.getQueryPaths(this.sortResponse),
|
|
1016
|
-
direction: this.sortDirection,
|
|
1017
|
-
};
|
|
1018
|
-
}
|
|
1019
|
-
isValidQueryPathsResult(qResult, select) {
|
|
1020
|
-
return select.every((path) => {
|
|
1021
|
-
return this.isValidQueryPathResult(qResult, path);
|
|
1022
|
-
});
|
|
1023
|
-
}
|
|
1024
|
-
isValidQueryPathResult(qResult, path, nameOverwrite) {
|
|
1025
|
-
if (Array.isArray(path)) {
|
|
1026
|
-
return this.isValidQueryStepResult(qResult, path[0], path.splice(1), nameOverwrite);
|
|
1027
|
-
}
|
|
1028
|
-
else {
|
|
1029
|
-
if (path.firstPath) {
|
|
1030
|
-
return this.isValidQueryPathResult(qResult, path.firstPath);
|
|
1031
|
-
}
|
|
1032
|
-
else if (path.path) {
|
|
1033
|
-
return this.isValidQueryPathResult(qResult, path.path);
|
|
1034
|
-
}
|
|
1035
|
-
}
|
|
1036
|
-
}
|
|
1037
|
-
isValidQueryStepResult(qResult, step, restPath = [], nameOverwrite) {
|
|
1038
|
-
if (!qResult) {
|
|
1039
|
-
return false;
|
|
1040
|
-
}
|
|
1041
|
-
if (step.property) {
|
|
1042
|
-
//if a name overwrite is given we check if that key exists instead of the property label
|
|
1043
|
-
//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.
|
|
1044
|
-
//e.g. {title:item.name} in a query will result in a "title" key in the result, not "name"
|
|
1045
|
-
const accessKey = nameOverwrite || step.property.label;
|
|
1046
|
-
//also check if this property needs to have a value (minCount > 0), if not it can be empty and undefined
|
|
1047
|
-
// if (!qResult.hasOwnProperty(accessKey) && (step as PropertyQueryStep).property.minCount > 0) {
|
|
1048
|
-
//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)
|
|
1049
|
-
if (!qResult.hasOwnProperty(accessKey)) {
|
|
1050
|
-
return false;
|
|
1051
|
-
}
|
|
1052
|
-
if (restPath.length > 0) {
|
|
1053
|
-
return this.isValidQueryStepResult(qResult[accessKey], restPath[0], restPath.splice(1));
|
|
1054
|
-
}
|
|
1055
|
-
return true;
|
|
1056
|
-
}
|
|
1057
|
-
else if (step.count) {
|
|
1058
|
-
return this.isValidQueryStepResult(qResult, step.count[0]);
|
|
1059
|
-
}
|
|
1060
|
-
else if (Array.isArray(step)) {
|
|
1061
|
-
return step.every((subStep) => {
|
|
1062
|
-
return this.isValidQueryPathResult(qResult, subStep);
|
|
1063
|
-
});
|
|
1064
|
-
}
|
|
1065
|
-
else if (typeof step === 'object') {
|
|
1066
|
-
if (Array.isArray(qResult)) {
|
|
1067
|
-
return qResult.every((singleResult) => {
|
|
1068
|
-
return this.isValidQueryStepResult(singleResult, step);
|
|
1069
|
-
});
|
|
1070
|
-
}
|
|
1071
|
-
return this.isValidCustomObjectResult(qResult, step);
|
|
1072
|
-
}
|
|
1073
|
-
}
|
|
1074
|
-
isValidCustomObjectResult(qResult, step) {
|
|
1075
|
-
//for custom objects, all keys need to be defined, even if the value is undefined
|
|
1076
|
-
for (let key in step) {
|
|
1077
|
-
if (!qResult.hasOwnProperty(key)) {
|
|
1078
|
-
return false;
|
|
1079
|
-
}
|
|
1080
|
-
let path = step[key];
|
|
1081
|
-
if (!this.isValidQueryPathResult(qResult, path, key)) {
|
|
1082
|
-
return false;
|
|
1083
|
-
}
|
|
1084
|
-
// return this.isValidQueryPathResult(qResult[key], path);
|
|
1085
|
-
}
|
|
1086
|
-
return true;
|
|
1087
|
-
}
|
|
1088
|
-
}
|
|
1089
|
-
export class SetSize extends QueryNumber {
|
|
671
|
+
export class SetSize extends QueryPrimitive {
|
|
1090
672
|
constructor(subject, countable, label) {
|
|
1091
673
|
super();
|
|
1092
674
|
this.subject = subject;
|
|
@@ -1098,57 +680,21 @@ export class SetSize extends QueryNumber {
|
|
|
1098
680
|
return this;
|
|
1099
681
|
}
|
|
1100
682
|
getPropertyPath() {
|
|
1101
|
-
//
|
|
1102
|
-
//
|
|
1103
|
-
//then creating the count step is straightforward
|
|
1104
|
-
// let countablePath = this.countable.getPropertyPath();
|
|
1105
|
-
// if (countablePath.some((step) => Array.isArray(step))) {
|
|
1106
|
-
// throw new Error(
|
|
1107
|
-
// 'Cannot count a diverging path. Provide one path of properties to count',
|
|
1108
|
-
// );
|
|
1109
|
-
// }
|
|
1110
|
-
// let self: CountStep = {
|
|
1111
|
-
// count: this.countable?.getPropertyPath(),
|
|
1112
|
-
// label: this.label,
|
|
1113
|
-
// };
|
|
1114
|
-
// //and we can add the count step to the path of the subject
|
|
1115
|
-
// let parent = this.subject.getPropertyPath();
|
|
1116
|
-
// parent.push(self);
|
|
1117
|
-
// return parent;
|
|
1118
|
-
// } else {
|
|
1119
|
-
//if nothing to count was given as an argument,
|
|
1120
|
-
//then we just count the last property in the path
|
|
1121
|
-
//also, we use the label of the last property as the label of the count step
|
|
683
|
+
//count the last property in the path
|
|
684
|
+
//use the label of the last property as the label of the count step
|
|
1122
685
|
let countable = this.subject.getPropertyStep();
|
|
1123
686
|
let self = {
|
|
1124
687
|
count: [countable],
|
|
1125
|
-
label: this.label || this.subject.property.label,
|
|
1126
|
-
//numFriends
|
|
1127
|
-
// 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
|
|
688
|
+
label: this.label || this.subject.property.label,
|
|
1128
689
|
};
|
|
1129
|
-
//
|
|
1130
|
-
//and add the
|
|
1131
|
-
//since we already used the subject as the thing that's counted.
|
|
690
|
+
//request the path of the subject's subject (the parent of the parent)
|
|
691
|
+
//and add the SizeStep to that path, since we already used the subject as the thing that's counted
|
|
1132
692
|
if (this.subject.subject) {
|
|
1133
693
|
let path = this.subject.subject.getPropertyPath();
|
|
1134
694
|
path.push(self);
|
|
1135
695
|
return path;
|
|
1136
696
|
}
|
|
1137
|
-
//if there is no parent of a parent, then we just return the count step as the whole path
|
|
1138
697
|
return [self];
|
|
1139
|
-
// }
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
/**
|
|
1143
|
-
* A sub query that is used to filter results
|
|
1144
|
-
* i.e p.friends.where(f => //LinkedWhereQuery here)
|
|
1145
|
-
*/
|
|
1146
|
-
export class LinkedWhereQuery extends SelectQueryFactory {
|
|
1147
|
-
getResponse() {
|
|
1148
|
-
return this.traceResponse;
|
|
1149
|
-
}
|
|
1150
|
-
getWherePath() {
|
|
1151
|
-
return this.traceResponse.getWherePath();
|
|
1152
698
|
}
|
|
1153
699
|
}
|
|
1154
700
|
//# sourceMappingURL=SelectQuery.js.map
|