@fibery/expression-utils 1.1.11 → 1.1.12
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/paramsPlaceholders.d.ts +99 -0
- package/lib/paramsPlaceholders.js +4 -21
- package/package.json +7 -7
- package/lib/contextVariables.js +0 -20
- package/lib/expression-utils.js +0 -745
- package/lib/utils.js +0 -193
- package/lib/visitors.js +0 -463
package/lib/utils.js
DELETED
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
var trace = require('@fibery/helpers/utils/trace');
|
|
2
|
-
var _ = require('lodash');
|
|
3
|
-
|
|
4
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
5
|
-
|
|
6
|
-
var ___default = /*#__PURE__*/_interopDefaultLegacy(_);
|
|
7
|
-
|
|
8
|
-
function _extends() {
|
|
9
|
-
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
10
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
11
|
-
var source = arguments[i];
|
|
12
|
-
for (var key in source) {
|
|
13
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
14
|
-
target[key] = source[key];
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
return target;
|
|
19
|
-
};
|
|
20
|
-
return _extends.apply(this, arguments);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const stringify = x => {
|
|
24
|
-
if (x === undefined) {
|
|
25
|
-
return "undefined";
|
|
26
|
-
}
|
|
27
|
-
return JSON.stringify(x);
|
|
28
|
-
};
|
|
29
|
-
class NotImplementedError extends Error {
|
|
30
|
-
constructor(value, itemType = undefined) {
|
|
31
|
-
super([`"${stringify(value)}"`, itemType, "is not implemented"].filter(x => x !== undefined).join(" "));
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const assertIsValidExpression = expression => {
|
|
36
|
-
trace.assert(Array.isArray(expression), "expression must be array", {
|
|
37
|
-
expression
|
|
38
|
-
});
|
|
39
|
-
trace.assert(expression.length > 0, "empty expression does not make any sense");
|
|
40
|
-
};
|
|
41
|
-
const dateRangeFunctions = new Set(["q/start", "q/end"]);
|
|
42
|
-
const firstLastFunctions = new Set(["q/first", "q/last"]);
|
|
43
|
-
const collectionOps = new Set(["q/count", "q/count-distinct", "q/sum", "q/min", "q/max", "q/avg", "q/join", "q/first", "q/last"]);
|
|
44
|
-
// [op, left, right]
|
|
45
|
-
// [=, $true, $false]
|
|
46
|
-
// [=, $my-id, ["fibery/id"]]
|
|
47
|
-
const binaryOperations = new Set(["=", "!=", "<", ">", "<=", ">=", "in",
|
|
48
|
-
//asc: obsolete,use q/in
|
|
49
|
-
"q/contains", "q/not-contains", "+", "-", "q/+", "q/-", "*", "/", "and", "or",
|
|
50
|
-
//asc: obsolete. use q/and, q/or
|
|
51
|
-
"q/and", "q/or", "q/in", "q/not-in"]);
|
|
52
|
-
|
|
53
|
-
// TODO: get rid of this. Use visitors everywhere
|
|
54
|
-
const naryOperations = new Set(["and", "or", "q/and", "q/or"]);
|
|
55
|
-
const logicalOperators = new Set(["and", "or", "q/and", "q/or"]);
|
|
56
|
-
const relationalOperators = new Set(["=", "!=", "<", ">", "<=", ">="]);
|
|
57
|
-
const mathOperators = new Set(["+", "-", "*", "/", "q/+", "q/-", "q/concat"]);
|
|
58
|
-
const isFunctionCallExpression = expression => expression.length > 1 && ___default["default"].isString(expression[0]) && (expression[0].startsWith("q/") || ["=", "!=", "<", ">", "<=", ">=", "+", "-", "*", "/", "in", "and", "or", "not-in"].includes(expression[0]));
|
|
59
|
-
const fromRootKeyword = "q/from-root";
|
|
60
|
-
const isFromRootFieldExpression = expression => ___default["default"].isArray(expression) && expression[0] === fromRootKeyword;
|
|
61
|
-
const isDateRangeFunctionExpression = expression => (expression.length === 2 || expression.length === 3) && dateRangeFunctions.has(expression[0]) && isFieldExpression(expression[1]);
|
|
62
|
-
const isCollectionFunctionExpression = expression =>
|
|
63
|
-
//expression has length 3 in case of q/join
|
|
64
|
-
(expression.length === 2 || expression.length === 3) && collectionOps.has(expression[0]);
|
|
65
|
-
const isAccessFunctionExpression = expresion => expresion.length === 2 && expresion[0] === "q/access?" && isFieldExpression(expresion[1]);
|
|
66
|
-
const isBinaryExpression = expression => expression.length === 3 && binaryOperations.has(expression[0]);
|
|
67
|
-
const isNaryExpression = expression => expression.length > 1 && naryOperations.has(expression[0]);
|
|
68
|
-
const isVariableExpression = expression => ___default["default"].isString(expression) && expression.startsWith("$");
|
|
69
|
-
const isFieldExpression = expression => Array.isArray(expression) && expression.every(x => !isVariableExpression(x) && !binaryOperations.has(x) && ___default["default"].isString(x));
|
|
70
|
-
const isQueryExpression = expression => {
|
|
71
|
-
if (___default["default"].isObject(expression) && "q/from" in expression) {
|
|
72
|
-
const fromExpression = expression["q/from"];
|
|
73
|
-
//asc: fromExpression === null for denormalizeSelect for reference collection case
|
|
74
|
-
return fromExpression === null || isFieldExpression(fromExpression);
|
|
75
|
-
}
|
|
76
|
-
return false;
|
|
77
|
-
};
|
|
78
|
-
// [q/count, [..., collection]]
|
|
79
|
-
// [q/start, [..., range]]
|
|
80
|
-
// [q/end, [..., range]]
|
|
81
|
-
// [q/access?, [..., field-expr]]
|
|
82
|
-
const isFunctionExpression = expression => {
|
|
83
|
-
if (!Array.isArray(expression)) {
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
if (isFieldExpression(expression)) {
|
|
87
|
-
return false;
|
|
88
|
-
} else if (isDateRangeFunctionExpression(expression) || isCollectionFunctionExpression(expression) || isAccessFunctionExpression(expression)) {
|
|
89
|
-
return true;
|
|
90
|
-
}
|
|
91
|
-
throw new Error("invalid expression:" + JSON.stringify(expression));
|
|
92
|
-
};
|
|
93
|
-
const collectFieldExpressions = (memo, expression) => {
|
|
94
|
-
if (isVariableExpression(expression)) ; else if (isFunctionCallExpression(expression)) {
|
|
95
|
-
for (const part of expression.slice(1)) {
|
|
96
|
-
if (isVariableExpression(part) || part === null) ; else {
|
|
97
|
-
if (___default["default"].isString(part)) {
|
|
98
|
-
// field path shortcut
|
|
99
|
-
memo.push([part]);
|
|
100
|
-
} else {
|
|
101
|
-
collectFieldExpressions(memo, part);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
} else if (isFieldExpression(expression)) {
|
|
106
|
-
memo.push(expression);
|
|
107
|
-
} else if (expression["q/from"] && isFieldExpression(expression["q/from"])) {
|
|
108
|
-
const innerMemo = [];
|
|
109
|
-
expression["q/select"] && collectFieldExpressions(innerMemo, expression["q/select"]);
|
|
110
|
-
expression["q/where"] && collectFieldExpressions(innerMemo, expression["q/where"]);
|
|
111
|
-
for (const fieldExpression of innerMemo) {
|
|
112
|
-
memo.push([...expression["q/from"], ...fieldExpression]);
|
|
113
|
-
}
|
|
114
|
-
} else {
|
|
115
|
-
throw new NotImplementedError(expression, "expression");
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
const extractFieldExpressions = expression => {
|
|
119
|
-
const memo = [];
|
|
120
|
-
collectFieldExpressions(memo, expression);
|
|
121
|
-
return ___default["default"].uniqBy(memo, x => x.join(","));
|
|
122
|
-
};
|
|
123
|
-
const createExpressionVisitor = visitor => {
|
|
124
|
-
let visitorWithDefault = null;
|
|
125
|
-
const visitorDefault = {
|
|
126
|
-
visitVariableExpression: expression => expression,
|
|
127
|
-
visitFunctionCallExpression: ([fnName, ...args]) => [fnName, ...args.map(x => visitorWithDefault.visitExpression(x))],
|
|
128
|
-
visitFromRootFieldExpression: ([fromRootKeyword, ...rest]) => [fromRootKeyword, ...rest.map(x => visitorWithDefault.visitExpression(x))],
|
|
129
|
-
visitFieldExpression: expression => expression,
|
|
130
|
-
visitOrderByExpression: orderByExpression => orderByExpression.map(x => {
|
|
131
|
-
const [fieldExpression, orderDir] = x;
|
|
132
|
-
const fieldExpressionNew = visitorWithDefault.visitExpression(fieldExpression);
|
|
133
|
-
return [fieldExpressionNew, orderDir];
|
|
134
|
-
}),
|
|
135
|
-
visitQueryExpression: subQueryExpression => {
|
|
136
|
-
const {
|
|
137
|
-
"q/from": fromExpression,
|
|
138
|
-
"q/select": selectExpression,
|
|
139
|
-
"q/where": whereExpression,
|
|
140
|
-
"q/order-by": orderByExpression
|
|
141
|
-
} = subQueryExpression;
|
|
142
|
-
return _extends({}, subQueryExpression, fromExpression ? {
|
|
143
|
-
"q/from": visitorWithDefault.visitFieldExpression(fromExpression)
|
|
144
|
-
} : null, selectExpression ? {
|
|
145
|
-
"q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => visitorWithDefault.visitExpression(val)) : visitorWithDefault.visitExpression(selectExpression)
|
|
146
|
-
} : null, whereExpression ? {
|
|
147
|
-
"q/where": visitorWithDefault.visitExpression(whereExpression)
|
|
148
|
-
} : null, orderByExpression ? {
|
|
149
|
-
"q/order-by": visitorWithDefault.visitOrderByExpression(orderByExpression)
|
|
150
|
-
} : null);
|
|
151
|
-
},
|
|
152
|
-
visitExpression: expression => {
|
|
153
|
-
if (expression === null) {
|
|
154
|
-
throw new NotImplementedError(expression, "expression");
|
|
155
|
-
} else if (isVariableExpression(expression)) {
|
|
156
|
-
return visitorWithDefault.visitVariableExpression(expression, visitorDefault);
|
|
157
|
-
} else if (isFromRootFieldExpression(expression)) {
|
|
158
|
-
return visitorWithDefault.visitFromRootFieldExpression(expression, visitorDefault);
|
|
159
|
-
} else if (isFunctionCallExpression(expression)) {
|
|
160
|
-
return visitorWithDefault.visitFunctionCallExpression(expression, visitorDefault);
|
|
161
|
-
} else if (isFieldExpression(expression)) {
|
|
162
|
-
return visitorWithDefault.visitFieldExpression(expression, visitorDefault);
|
|
163
|
-
} else if (isQueryExpression(expression)) {
|
|
164
|
-
return visitorWithDefault.visitQueryExpression(expression, visitorDefault);
|
|
165
|
-
} else {
|
|
166
|
-
throw new NotImplementedError(expression, "expression");
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
visitorWithDefault = _extends({}, visitorDefault, visitor);
|
|
171
|
-
return visitorWithDefault;
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
exports.assertIsValidExpression = assertIsValidExpression;
|
|
175
|
-
exports.createExpressionVisitor = createExpressionVisitor;
|
|
176
|
-
exports.dateRangeFunctions = dateRangeFunctions;
|
|
177
|
-
exports.extractFieldExpressions = extractFieldExpressions;
|
|
178
|
-
exports.firstLastFunctions = firstLastFunctions;
|
|
179
|
-
exports.fromRootKeyword = fromRootKeyword;
|
|
180
|
-
exports.isAccessFunctionExpression = isAccessFunctionExpression;
|
|
181
|
-
exports.isBinaryExpression = isBinaryExpression;
|
|
182
|
-
exports.isCollectionFunctionExpression = isCollectionFunctionExpression;
|
|
183
|
-
exports.isDateRangeFunctionExpression = isDateRangeFunctionExpression;
|
|
184
|
-
exports.isFieldExpression = isFieldExpression;
|
|
185
|
-
exports.isFromRootFieldExpression = isFromRootFieldExpression;
|
|
186
|
-
exports.isFunctionCallExpression = isFunctionCallExpression;
|
|
187
|
-
exports.isFunctionExpression = isFunctionExpression;
|
|
188
|
-
exports.isNaryExpression = isNaryExpression;
|
|
189
|
-
exports.isQueryExpression = isQueryExpression;
|
|
190
|
-
exports.isVariableExpression = isVariableExpression;
|
|
191
|
-
exports.logicalOperators = logicalOperators;
|
|
192
|
-
exports.mathOperators = mathOperators;
|
|
193
|
-
exports.relationalOperators = relationalOperators;
|
package/lib/visitors.js
DELETED
|
@@ -1,463 +0,0 @@
|
|
|
1
|
-
var _ = require('lodash');
|
|
2
|
-
require('@fibery/helpers/utils/trace');
|
|
3
|
-
|
|
4
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
5
|
-
|
|
6
|
-
var ___default = /*#__PURE__*/_interopDefaultLegacy(_);
|
|
7
|
-
|
|
8
|
-
function _extends() {
|
|
9
|
-
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
10
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
11
|
-
var source = arguments[i];
|
|
12
|
-
for (var key in source) {
|
|
13
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
14
|
-
target[key] = source[key];
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
return target;
|
|
19
|
-
};
|
|
20
|
-
return _extends.apply(this, arguments);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const stringify = x => {
|
|
24
|
-
if (x === undefined) {
|
|
25
|
-
return "undefined";
|
|
26
|
-
}
|
|
27
|
-
return JSON.stringify(x);
|
|
28
|
-
};
|
|
29
|
-
class NotImplementedError extends Error {
|
|
30
|
-
constructor(value, itemType = undefined) {
|
|
31
|
-
super([`"${stringify(value)}"`, itemType, "is not implemented"].filter(x => x !== undefined).join(" "));
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const firstLastFunctions = new Set(["q/first", "q/last"]);
|
|
36
|
-
const collectionOps = new Set(["q/count", "q/count-distinct", "q/sum", "q/min", "q/max", "q/avg", "q/join", "q/first", "q/last"]);
|
|
37
|
-
// [op, left, right]
|
|
38
|
-
// [=, $true, $false]
|
|
39
|
-
// [=, $my-id, ["fibery/id"]]
|
|
40
|
-
const binaryOperations = new Set(["=", "!=", "<", ">", "<=", ">=", "in",
|
|
41
|
-
//asc: obsolete,use q/in
|
|
42
|
-
"q/contains", "q/not-contains", "+", "-", "q/+", "q/-", "*", "/", "and", "or",
|
|
43
|
-
//asc: obsolete. use q/and, q/or
|
|
44
|
-
"q/and", "q/or", "q/in", "q/not-in"]);
|
|
45
|
-
const logicalOperators = new Set(["and", "or", "q/and", "q/or"]);
|
|
46
|
-
const isFunctionCallExpression = expression => expression.length > 1 && ___default["default"].isString(expression[0]) && (expression[0].startsWith("q/") || ["=", "!=", "<", ">", "<=", ">=", "+", "-", "*", "/", "in", "and", "or", "not-in"].includes(expression[0]));
|
|
47
|
-
const fromRootKeyword = "q/from-root";
|
|
48
|
-
const isFromRootFieldExpression = expression => ___default["default"].isArray(expression) && expression[0] === fromRootKeyword;
|
|
49
|
-
const isCollectionFunctionExpression = expression =>
|
|
50
|
-
//expression has length 3 in case of q/join
|
|
51
|
-
(expression.length === 2 || expression.length === 3) && collectionOps.has(expression[0]);
|
|
52
|
-
const isVariableExpression = expression => ___default["default"].isString(expression) && expression.startsWith("$");
|
|
53
|
-
const isFieldExpression = expression => Array.isArray(expression) && expression.every(x => !isVariableExpression(x) && !binaryOperations.has(x) && ___default["default"].isString(x));
|
|
54
|
-
const isQueryExpression = expression => {
|
|
55
|
-
if (___default["default"].isObject(expression) && "q/from" in expression) {
|
|
56
|
-
const fromExpression = expression["q/from"];
|
|
57
|
-
//asc: fromExpression === null for denormalizeSelect for reference collection case
|
|
58
|
-
return fromExpression === null || isFieldExpression(fromExpression);
|
|
59
|
-
}
|
|
60
|
-
return false;
|
|
61
|
-
};
|
|
62
|
-
const createExpressionVisitor = visitor => {
|
|
63
|
-
let visitorWithDefault = null;
|
|
64
|
-
const visitorDefault = {
|
|
65
|
-
visitVariableExpression: expression => expression,
|
|
66
|
-
visitFunctionCallExpression: ([fnName, ...args]) => [fnName, ...args.map(x => visitorWithDefault.visitExpression(x))],
|
|
67
|
-
visitFromRootFieldExpression: ([fromRootKeyword, ...rest]) => [fromRootKeyword, ...rest.map(x => visitorWithDefault.visitExpression(x))],
|
|
68
|
-
visitFieldExpression: expression => expression,
|
|
69
|
-
visitOrderByExpression: orderByExpression => orderByExpression.map(x => {
|
|
70
|
-
const [fieldExpression, orderDir] = x;
|
|
71
|
-
const fieldExpressionNew = visitorWithDefault.visitExpression(fieldExpression);
|
|
72
|
-
return [fieldExpressionNew, orderDir];
|
|
73
|
-
}),
|
|
74
|
-
visitQueryExpression: subQueryExpression => {
|
|
75
|
-
const {
|
|
76
|
-
"q/from": fromExpression,
|
|
77
|
-
"q/select": selectExpression,
|
|
78
|
-
"q/where": whereExpression,
|
|
79
|
-
"q/order-by": orderByExpression
|
|
80
|
-
} = subQueryExpression;
|
|
81
|
-
return _extends({}, subQueryExpression, fromExpression ? {
|
|
82
|
-
"q/from": visitorWithDefault.visitFieldExpression(fromExpression)
|
|
83
|
-
} : null, selectExpression ? {
|
|
84
|
-
"q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => visitorWithDefault.visitExpression(val)) : visitorWithDefault.visitExpression(selectExpression)
|
|
85
|
-
} : null, whereExpression ? {
|
|
86
|
-
"q/where": visitorWithDefault.visitExpression(whereExpression)
|
|
87
|
-
} : null, orderByExpression ? {
|
|
88
|
-
"q/order-by": visitorWithDefault.visitOrderByExpression(orderByExpression)
|
|
89
|
-
} : null);
|
|
90
|
-
},
|
|
91
|
-
visitExpression: expression => {
|
|
92
|
-
if (expression === null) {
|
|
93
|
-
throw new NotImplementedError(expression, "expression");
|
|
94
|
-
} else if (isVariableExpression(expression)) {
|
|
95
|
-
return visitorWithDefault.visitVariableExpression(expression, visitorDefault);
|
|
96
|
-
} else if (isFromRootFieldExpression(expression)) {
|
|
97
|
-
return visitorWithDefault.visitFromRootFieldExpression(expression, visitorDefault);
|
|
98
|
-
} else if (isFunctionCallExpression(expression)) {
|
|
99
|
-
return visitorWithDefault.visitFunctionCallExpression(expression, visitorDefault);
|
|
100
|
-
} else if (isFieldExpression(expression)) {
|
|
101
|
-
return visitorWithDefault.visitFieldExpression(expression, visitorDefault);
|
|
102
|
-
} else if (isQueryExpression(expression)) {
|
|
103
|
-
return visitorWithDefault.visitQueryExpression(expression, visitorDefault);
|
|
104
|
-
} else {
|
|
105
|
-
throw new NotImplementedError(expression, "expression");
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
visitorWithDefault = _extends({}, visitorDefault, visitor);
|
|
110
|
-
return visitorWithDefault;
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
const defaultIdsWithNamesOnFieldNotFound = ({
|
|
114
|
-
fieldExpressionInNamesTerms,
|
|
115
|
-
fieldId
|
|
116
|
-
}) => {
|
|
117
|
-
return {
|
|
118
|
-
currentTypeObject: null,
|
|
119
|
-
fieldExpressionInNamesTerms: [...fieldExpressionInNamesTerms, fieldId]
|
|
120
|
-
};
|
|
121
|
-
};
|
|
122
|
-
const visitFieldExpressionForReplaceIdsWithNamesVisitor = ({
|
|
123
|
-
expression,
|
|
124
|
-
typeObject,
|
|
125
|
-
onFieldNotFound
|
|
126
|
-
}) => expression.reduce(({
|
|
127
|
-
currentTypeObject,
|
|
128
|
-
fieldExpressionInNamesTerms
|
|
129
|
-
}, fieldId) => {
|
|
130
|
-
if (currentTypeObject && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId)) {
|
|
131
|
-
const fieldObject = currentTypeObject.fieldObjectsById[fieldId];
|
|
132
|
-
return {
|
|
133
|
-
currentTypeObject: fieldObject.typeObject,
|
|
134
|
-
fieldExpressionInNamesTerms: [...fieldExpressionInNamesTerms, fieldObject.name]
|
|
135
|
-
};
|
|
136
|
-
} else {
|
|
137
|
-
return onFieldNotFound({
|
|
138
|
-
currentTypeObject,
|
|
139
|
-
fieldExpressionInNamesTerms,
|
|
140
|
-
fieldId,
|
|
141
|
-
expression
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
}, {
|
|
145
|
-
currentTypeObject: typeObject,
|
|
146
|
-
fieldExpressionInNamesTerms: []
|
|
147
|
-
});
|
|
148
|
-
const replaceIdsWithNamesVisitor = (typeObject, onFieldNotFound = defaultIdsWithNamesOnFieldNotFound) => {
|
|
149
|
-
const visitor = createExpressionVisitor({
|
|
150
|
-
visitFieldExpression: expression => visitFieldExpressionForReplaceIdsWithNamesVisitor({
|
|
151
|
-
expression,
|
|
152
|
-
typeObject,
|
|
153
|
-
onFieldNotFound
|
|
154
|
-
}).fieldExpressionInNamesTerms,
|
|
155
|
-
visitQueryExpression: subQueryExpression => {
|
|
156
|
-
const {
|
|
157
|
-
"q/from": fromExpression,
|
|
158
|
-
"q/select": selectExpression,
|
|
159
|
-
"q/where": whereExpression,
|
|
160
|
-
"q/order-by": orderByExpression
|
|
161
|
-
} = subQueryExpression;
|
|
162
|
-
const subQueryTypeObject = visitFieldExpressionForReplaceIdsWithNamesVisitor({
|
|
163
|
-
expression: fromExpression,
|
|
164
|
-
onFieldNotFound,
|
|
165
|
-
typeObject
|
|
166
|
-
}).currentTypeObject;
|
|
167
|
-
if (subQueryTypeObject) {
|
|
168
|
-
const subQueryVisitor = replaceIdsWithNamesVisitor(subQueryTypeObject, onFieldNotFound);
|
|
169
|
-
return _extends({}, subQueryExpression, {
|
|
170
|
-
"q/from": visitor.visitFieldExpression(fromExpression),
|
|
171
|
-
"q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => subQueryVisitor.visitExpression(val)) : subQueryVisitor.visitExpression(selectExpression)
|
|
172
|
-
}, whereExpression ? {
|
|
173
|
-
"q/where": subQueryVisitor.visitExpression(whereExpression)
|
|
174
|
-
} : null, orderByExpression ? {
|
|
175
|
-
"q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
|
|
176
|
-
} : null);
|
|
177
|
-
}
|
|
178
|
-
return subQueryExpression;
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
return visitor;
|
|
182
|
-
};
|
|
183
|
-
const defaultNamesWithIdsOnFieldNotFound = ({
|
|
184
|
-
fieldExpressionInIdsTerms,
|
|
185
|
-
field
|
|
186
|
-
}) => {
|
|
187
|
-
return {
|
|
188
|
-
currentTypeObject: null,
|
|
189
|
-
fieldExpressionInIdsTerms: [...fieldExpressionInIdsTerms, field]
|
|
190
|
-
};
|
|
191
|
-
};
|
|
192
|
-
const visitFieldExpressionForReplaceNamesWithIdsVisitor = ({
|
|
193
|
-
expression,
|
|
194
|
-
onFieldNotFound,
|
|
195
|
-
typeObject
|
|
196
|
-
}) => expression.reduce(({
|
|
197
|
-
currentTypeObject,
|
|
198
|
-
fieldExpressionInIdsTerms
|
|
199
|
-
}, field) => {
|
|
200
|
-
if (currentTypeObject && currentTypeObject.fieldObjectsByName.hasOwnProperty(field)) {
|
|
201
|
-
const fieldObject = currentTypeObject.fieldObjectsByName[field];
|
|
202
|
-
return {
|
|
203
|
-
currentTypeObject: fieldObject.typeObject,
|
|
204
|
-
fieldExpressionInIdsTerms: [...fieldExpressionInIdsTerms, fieldObject.id]
|
|
205
|
-
};
|
|
206
|
-
} else {
|
|
207
|
-
return onFieldNotFound({
|
|
208
|
-
currentTypeObject,
|
|
209
|
-
fieldExpressionInIdsTerms,
|
|
210
|
-
field,
|
|
211
|
-
expression
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
}, {
|
|
215
|
-
currentTypeObject: typeObject,
|
|
216
|
-
fieldExpressionInIdsTerms: []
|
|
217
|
-
});
|
|
218
|
-
const replaceNamesWithIdsVisitor = (typeObject, onFieldNotFound = defaultNamesWithIdsOnFieldNotFound) => {
|
|
219
|
-
const visitor = createExpressionVisitor({
|
|
220
|
-
visitFieldExpression: expression => visitFieldExpressionForReplaceNamesWithIdsVisitor({
|
|
221
|
-
expression,
|
|
222
|
-
onFieldNotFound,
|
|
223
|
-
typeObject
|
|
224
|
-
}).fieldExpressionInIdsTerms,
|
|
225
|
-
visitQueryExpression: subQueryExpression => {
|
|
226
|
-
const {
|
|
227
|
-
"q/from": fromExpression,
|
|
228
|
-
"q/select": selectExpression,
|
|
229
|
-
"q/where": whereExpression,
|
|
230
|
-
"q/order-by": orderByExpression
|
|
231
|
-
} = subQueryExpression;
|
|
232
|
-
const subQueryTypeObject = visitFieldExpressionForReplaceNamesWithIdsVisitor({
|
|
233
|
-
expression: fromExpression,
|
|
234
|
-
onFieldNotFound,
|
|
235
|
-
typeObject
|
|
236
|
-
}).currentTypeObject;
|
|
237
|
-
if (subQueryTypeObject) {
|
|
238
|
-
const subQueryVisitor = replaceNamesWithIdsVisitor(subQueryTypeObject, onFieldNotFound);
|
|
239
|
-
return _extends({}, subQueryExpression, {
|
|
240
|
-
"q/from": visitor.visitFieldExpression(fromExpression),
|
|
241
|
-
"q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => subQueryVisitor.visitExpression(val)) : subQueryVisitor.visitExpression(selectExpression)
|
|
242
|
-
}, whereExpression ? {
|
|
243
|
-
"q/where": subQueryVisitor.visitExpression(whereExpression)
|
|
244
|
-
} : null, orderByExpression ? {
|
|
245
|
-
"q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
|
|
246
|
-
} : null);
|
|
247
|
-
}
|
|
248
|
-
return subQueryExpression;
|
|
249
|
-
}
|
|
250
|
-
});
|
|
251
|
-
return visitor;
|
|
252
|
-
};
|
|
253
|
-
const deleteExpressionsWithNotFoundFieldsVisitor = typeObject => {
|
|
254
|
-
const visitor = createExpressionVisitor({
|
|
255
|
-
visitFunctionCallExpression: ([fnName, ...args]) => {
|
|
256
|
-
const argsNew = args.map(x => visitor.visitExpression(x)).filter(Boolean);
|
|
257
|
-
if (logicalOperators.has(fnName)) {
|
|
258
|
-
if (argsNew.length > 0) {
|
|
259
|
-
return argsNew.length === 1 ? argsNew[0] : [fnName, ...argsNew];
|
|
260
|
-
}
|
|
261
|
-
return null;
|
|
262
|
-
} else {
|
|
263
|
-
return argsNew.length === args.length ? [fnName, ...argsNew] : null;
|
|
264
|
-
}
|
|
265
|
-
},
|
|
266
|
-
visitFieldExpression: expression => {
|
|
267
|
-
const fieldTypeObject = expression.reduce((holderTypeObject, field) => holderTypeObject && holderTypeObject.fieldObjectsByName.hasOwnProperty(field) ? holderTypeObject.fieldObjectsByName[field].typeObject : null, typeObject);
|
|
268
|
-
return fieldTypeObject && expression;
|
|
269
|
-
},
|
|
270
|
-
visitOrderByExpression: orderByExpression => {
|
|
271
|
-
return orderByExpression.map(x => {
|
|
272
|
-
const [fieldExpression, orderDir] = x;
|
|
273
|
-
const fieldExpressionNew = visitor.visitExpression(fieldExpression);
|
|
274
|
-
return fieldExpressionNew && [fieldExpressionNew, orderDir];
|
|
275
|
-
}).filter(Boolean);
|
|
276
|
-
},
|
|
277
|
-
visitQueryExpression: subQueryExpression => {
|
|
278
|
-
const {
|
|
279
|
-
"q/from": fromExpression,
|
|
280
|
-
"q/select": selectExpression,
|
|
281
|
-
"q/where": whereExpression,
|
|
282
|
-
"q/order-by": orderByExpression
|
|
283
|
-
} = subQueryExpression;
|
|
284
|
-
const subQueryTypeObject = fromExpression.reduce((typeObject, field) => typeObject && typeObject.fieldObjectsByName.hasOwnProperty(field) ? typeObject.fieldObjectsByName[field].typeObject : null, typeObject);
|
|
285
|
-
if (subQueryTypeObject) {
|
|
286
|
-
const subQueryVisitor = deleteExpressionsWithNotFoundFieldsVisitor(subQueryTypeObject);
|
|
287
|
-
const subQueryExpressionNew = ___default["default"].pickBy(_extends({}, subQueryExpression, {
|
|
288
|
-
"q/from": visitor.visitFieldExpression(fromExpression),
|
|
289
|
-
"q/select": subQueryVisitor.visitExpression(selectExpression)
|
|
290
|
-
}, whereExpression ? {
|
|
291
|
-
"q/where": subQueryVisitor.visitExpression(whereExpression)
|
|
292
|
-
} : null, orderByExpression ? {
|
|
293
|
-
"q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
|
|
294
|
-
} : null));
|
|
295
|
-
const {
|
|
296
|
-
"q/select": selectExpressionNew
|
|
297
|
-
} = subQueryExpressionNew;
|
|
298
|
-
return selectExpressionNew ? subQueryExpressionNew : null;
|
|
299
|
-
} else {
|
|
300
|
-
return null;
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
return visitor;
|
|
305
|
-
};
|
|
306
|
-
const expressionContainsAggregation = expression => {
|
|
307
|
-
let result = false;
|
|
308
|
-
const visitor = createExpressionVisitor({
|
|
309
|
-
visitQueryExpression: queryExpression => {
|
|
310
|
-
const {
|
|
311
|
-
"q/select": selectExpression
|
|
312
|
-
} = queryExpression;
|
|
313
|
-
if (isCollectionFunctionExpression(selectExpression)) {
|
|
314
|
-
result = true;
|
|
315
|
-
}
|
|
316
|
-
},
|
|
317
|
-
visitFunctionCallExpression: (expression, visitorDefault) => {
|
|
318
|
-
if (firstLastFunctions.has(expression[0])) {
|
|
319
|
-
result = true;
|
|
320
|
-
} else {
|
|
321
|
-
visitorDefault.visitFunctionCallExpression(expression);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
});
|
|
325
|
-
visitor.visitExpression(expression);
|
|
326
|
-
return result;
|
|
327
|
-
};
|
|
328
|
-
const defaultGetExpressionTypeOnFieldNotFound = () => {
|
|
329
|
-
return {
|
|
330
|
-
currentTypeObject: null
|
|
331
|
-
};
|
|
332
|
-
};
|
|
333
|
-
const getFieldAccessExpressionTypeObject = ({
|
|
334
|
-
expression,
|
|
335
|
-
typeObject,
|
|
336
|
-
onFieldNotFound,
|
|
337
|
-
returnRefTypeInsteadOfId
|
|
338
|
-
}) => {
|
|
339
|
-
const reduced = expression.reduce(({
|
|
340
|
-
currentTypeObject
|
|
341
|
-
}, fieldId, index) => {
|
|
342
|
-
const fieldObject = currentTypeObject && currentTypeObject.fieldObjects.find(f => f.id === fieldId);
|
|
343
|
-
if (fieldObject) {
|
|
344
|
-
if (returnRefTypeInsteadOfId && index === expression.length - 1 && fieldObject.isId) {
|
|
345
|
-
return {
|
|
346
|
-
currentTypeObject
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
return {
|
|
350
|
-
currentTypeObject: fieldObject.typeObject
|
|
351
|
-
};
|
|
352
|
-
} else {
|
|
353
|
-
return onFieldNotFound({
|
|
354
|
-
currentTypeObject,
|
|
355
|
-
fieldId
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
}, {
|
|
359
|
-
currentTypeObject: typeObject
|
|
360
|
-
});
|
|
361
|
-
return reduced.currentTypeObject;
|
|
362
|
-
};
|
|
363
|
-
const UNKNOWN_EXPRESSION_TYPE = "unknown";
|
|
364
|
-
const getExpressionTypeInternal = ({
|
|
365
|
-
expression,
|
|
366
|
-
typeObject,
|
|
367
|
-
functionsMeta,
|
|
368
|
-
onFieldNotFound,
|
|
369
|
-
returnRefTypeInsteadOfId
|
|
370
|
-
}) => {
|
|
371
|
-
let result = null;
|
|
372
|
-
const visitor = createExpressionVisitor({
|
|
373
|
-
visitVariableExpression: function () {
|
|
374
|
-
result = UNKNOWN_EXPRESSION_TYPE;
|
|
375
|
-
},
|
|
376
|
-
visitFunctionCallExpression: function ([fnName, ...args]) {
|
|
377
|
-
const fnMeta = functionsMeta[fnName];
|
|
378
|
-
if (!fnMeta) {
|
|
379
|
-
throw new Error(`Function meta for "${fnName}" was not provided`);
|
|
380
|
-
}
|
|
381
|
-
const argTypes = args.map(arg => getExpressionTypeInternal({
|
|
382
|
-
expression: arg,
|
|
383
|
-
typeObject,
|
|
384
|
-
functionsMeta,
|
|
385
|
-
onFieldNotFound,
|
|
386
|
-
returnRefTypeInsteadOfId: false
|
|
387
|
-
}));
|
|
388
|
-
const overload = fnMeta.overloads.find(o => o["arg-types"].every((argType, index) => argTypes[index] === UNKNOWN_EXPRESSION_TYPE || argTypes[index] === argType));
|
|
389
|
-
if (!overload) {
|
|
390
|
-
throw new Error(`No overload with args ${argTypes.join(",")} found for "${fnName}" in meta`);
|
|
391
|
-
}
|
|
392
|
-
result = overload["result-type"];
|
|
393
|
-
},
|
|
394
|
-
visitQueryExpression: expression => {
|
|
395
|
-
const {
|
|
396
|
-
"q/from": fromExpression,
|
|
397
|
-
"q/select": selectExpression
|
|
398
|
-
} = expression;
|
|
399
|
-
const fromTypeObject = getFieldAccessExpressionTypeObject({
|
|
400
|
-
expression: fromExpression,
|
|
401
|
-
typeObject,
|
|
402
|
-
onFieldNotFound,
|
|
403
|
-
returnRefTypeInsteadOfId
|
|
404
|
-
});
|
|
405
|
-
if (!fromTypeObject) {
|
|
406
|
-
result = null;
|
|
407
|
-
}
|
|
408
|
-
if (___default["default"].isPlainObject(selectExpression)) {
|
|
409
|
-
if (Object.values(selectExpression).length !== 1) {
|
|
410
|
-
throw new Error(`Cannot determine type of query expression ${JSON.stringify(expression)}`);
|
|
411
|
-
}
|
|
412
|
-
result = getExpressionTypeInternal({
|
|
413
|
-
expression: Object.values(selectExpression)[0],
|
|
414
|
-
typeObject: fromTypeObject,
|
|
415
|
-
functionsMeta,
|
|
416
|
-
onFieldNotFound,
|
|
417
|
-
returnRefTypeInsteadOfId
|
|
418
|
-
});
|
|
419
|
-
} else {
|
|
420
|
-
result = getExpressionTypeInternal({
|
|
421
|
-
expression: selectExpression,
|
|
422
|
-
typeObject: fromTypeObject,
|
|
423
|
-
functionsMeta,
|
|
424
|
-
onFieldNotFound,
|
|
425
|
-
returnRefTypeInsteadOfId
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
},
|
|
429
|
-
visitFieldExpression(expression) {
|
|
430
|
-
const fieldAccessExpressionTypeObject = getFieldAccessExpressionTypeObject({
|
|
431
|
-
expression,
|
|
432
|
-
typeObject,
|
|
433
|
-
onFieldNotFound,
|
|
434
|
-
returnRefTypeInsteadOfId
|
|
435
|
-
});
|
|
436
|
-
result = fieldAccessExpressionTypeObject && fieldAccessExpressionTypeObject.name;
|
|
437
|
-
}
|
|
438
|
-
});
|
|
439
|
-
visitor.visitExpression(expression);
|
|
440
|
-
return result;
|
|
441
|
-
};
|
|
442
|
-
const getExpressionType = ({
|
|
443
|
-
expression,
|
|
444
|
-
typeObject,
|
|
445
|
-
functionsMeta,
|
|
446
|
-
onFieldNotFound = defaultGetExpressionTypeOnFieldNotFound,
|
|
447
|
-
returnRefTypeInsteadOfId = true
|
|
448
|
-
}) => {
|
|
449
|
-
return getExpressionTypeInternal({
|
|
450
|
-
expression,
|
|
451
|
-
typeObject,
|
|
452
|
-
functionsMeta,
|
|
453
|
-
onFieldNotFound,
|
|
454
|
-
returnRefTypeInsteadOfId
|
|
455
|
-
});
|
|
456
|
-
};
|
|
457
|
-
|
|
458
|
-
exports.UNKNOWN_EXPRESSION_TYPE = UNKNOWN_EXPRESSION_TYPE;
|
|
459
|
-
exports.deleteExpressionsWithNotFoundFieldsVisitor = deleteExpressionsWithNotFoundFieldsVisitor;
|
|
460
|
-
exports.expressionContainsAggregation = expressionContainsAggregation;
|
|
461
|
-
exports.getExpressionType = getExpressionType;
|
|
462
|
-
exports.replaceIdsWithNamesVisitor = replaceIdsWithNamesVisitor;
|
|
463
|
-
exports.replaceNamesWithIdsVisitor = replaceNamesWithIdsVisitor;
|