@fibery/expression-utils 9.2.1 → 9.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +6 -0
- package/lib/index.js +44 -0
- package/lib/src/context-variables.d.ts +22 -0
- package/lib/src/context-variables.js +122 -0
- package/lib/src/errors.d.ts +4 -0
- package/lib/src/errors.js +15 -0
- package/lib/src/fieldExpressionVisitorTypeAware.d.ts +5 -0
- package/lib/src/fieldExpressionVisitorTypeAware.js +133 -0
- package/lib/src/params-placeholders.d.ts +55 -0
- package/lib/src/params-placeholders.js +204 -0
- package/lib/src/tsfixme.d.ts +1 -0
- package/lib/src/tsfixme.js +2 -0
- package/lib/src/types.d.ts +35 -0
- package/lib/src/types.js +2 -0
- package/lib/src/utils.d.ts +42 -0
- package/lib/src/utils.js +260 -0
- package/lib/src/visitors.d.ts +44 -0
- package/lib/src/visitors.js +382 -0
- package/lib/testData/schemaMock.d.ts +502 -0
- package/lib/testData/schemaMock.js +138 -0
- package/package.json +22 -22
- package/lib/contextVariables.js +0 -20
- package/lib/expression-utils.js +0 -1035
- package/lib/paramsPlaceholders.js +0 -232
- package/lib/utils.js +0 -223
- package/lib/visitors.js +0 -660
- package/types.d.ts +0 -119
package/lib/expression-utils.js
DELETED
|
@@ -1,1035 +0,0 @@
|
|
|
1
|
-
var _ = require('lodash');
|
|
2
|
-
var moment = require('moment');
|
|
3
|
-
var trace = require('@fibery/helpers/utils/trace');
|
|
4
|
-
|
|
5
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
6
|
-
|
|
7
|
-
var ___default = /*#__PURE__*/_interopDefaultLegacy(_);
|
|
8
|
-
var moment__default = /*#__PURE__*/_interopDefaultLegacy(moment);
|
|
9
|
-
|
|
10
|
-
const serializeDate = momentDate => {
|
|
11
|
-
return momentDate.format("YYYY-MM-DD");
|
|
12
|
-
};
|
|
13
|
-
const serializeDateTime = momentDate => {
|
|
14
|
-
return momentDate.toISOString();
|
|
15
|
-
};
|
|
16
|
-
const formulaTodayDateParamPlaceholder = "$formula-today-date-placeholder";
|
|
17
|
-
const formulaNowDateTimeParamPlaceholder = "$formula-now-date-time-placeholder";
|
|
18
|
-
const todayDateParamPlaceholder = "$today-date";
|
|
19
|
-
const tomorrowDateParamPlaceholder = "$tomorrow-date";
|
|
20
|
-
const yesterdayDateParamPlaceholder = "$yesterday-date";
|
|
21
|
-
const weekAgoDateParamPlaceholder = "$week-ago-date";
|
|
22
|
-
const weekFromNowDateParamPlaceholder = "$week-from-now-date";
|
|
23
|
-
const monthAgoDateParamPlaceholder = "$month-ago-date";
|
|
24
|
-
const monthFromNowDateParamPlaceholder = "$month-from-now-date";
|
|
25
|
-
const yearAgoDateParamPlaceholder = "$year-ago-date";
|
|
26
|
-
const yearFromNowDateParamPlaceholder = "$year-from-now-date";
|
|
27
|
-
const todayStartDateTimeParamPlaceholder = "$today-date-time-start";
|
|
28
|
-
const todayEndDateTimeParamPlaceholder = "$today-date-time-end";
|
|
29
|
-
const tomorrowStartDateTimeParamPlaceholder = "$tomorrow-date-time-start";
|
|
30
|
-
const tomorrowEndDateTimeParamPlaceholder = "$tomorrow-date-time-end";
|
|
31
|
-
const yesterdayStartDateTimeParamPlaceholder = "$yesterday-date-time-start";
|
|
32
|
-
const yesterdayEndDateTimeParamPlaceholder = "$yesterday-date-time-end";
|
|
33
|
-
const weekAgoStartDateTimeParamPlaceholder = "$week-ago-date-time-start";
|
|
34
|
-
const weekAgoEndDateTimeParamPlaceholder = "$week-ago-date-time-end";
|
|
35
|
-
const weekFromNowStartDateTimeParamPlaceholder = "$week-from-now-date-time-start";
|
|
36
|
-
const weekFromNowEndDateTimeParamPlaceholder = "$week-from-now-date-time-end";
|
|
37
|
-
const monthAgoStartDateTimeParamPlaceholder = "$month-ago-date-time-start";
|
|
38
|
-
const monthAgoEndDateTimeParamPlaceholder = "$month-ago-date-time-end";
|
|
39
|
-
const monthFromNowStartDateTimeParamPlaceholder = "$month-from-now-date-time-start";
|
|
40
|
-
const monthFromNowEndDateTimeParamPlaceholder = "$month-from-now-date-time-end";
|
|
41
|
-
const yearAgoStartDateTimeParamPlaceholder = "$year-ago-date-time-start";
|
|
42
|
-
const yearAgoEndDateTimeParamPlaceholder = "$year-ago-date-time-end";
|
|
43
|
-
const yearFromNowStartDateTimeParamPlaceholder = "$year-from-now-date-time-start";
|
|
44
|
-
const yearFromNowEndDateTimeParamPlaceholder = "$year-from-now-date-time-end";
|
|
45
|
-
const paramsPlaceholdersLookup = {
|
|
46
|
-
[todayDateParamPlaceholder]: () => serializeDate(moment__default["default"]()),
|
|
47
|
-
[formulaTodayDateParamPlaceholder]: () => serializeDate(moment__default["default"]()),
|
|
48
|
-
[formulaNowDateTimeParamPlaceholder]: () => serializeDateTime(moment__default["default"]()),
|
|
49
|
-
[tomorrowDateParamPlaceholder]: () => serializeDate(moment__default["default"]().add(1, "days")),
|
|
50
|
-
[yesterdayDateParamPlaceholder]: () => serializeDate(moment__default["default"]().subtract(1, "days")),
|
|
51
|
-
[weekAgoDateParamPlaceholder]: () => serializeDate(moment__default["default"]().subtract(7, "days")),
|
|
52
|
-
[weekFromNowDateParamPlaceholder]: () => serializeDate(moment__default["default"]().add(7, "days")),
|
|
53
|
-
[monthAgoDateParamPlaceholder]: () => serializeDate(moment__default["default"]().subtract(1, "months")),
|
|
54
|
-
[monthFromNowDateParamPlaceholder]: () => serializeDate(moment__default["default"]().add(1, "months")),
|
|
55
|
-
[yearAgoDateParamPlaceholder]: () => serializeDate(moment__default["default"]().subtract(1, "year")),
|
|
56
|
-
[yearFromNowDateParamPlaceholder]: () => serializeDate(moment__default["default"]().add(1, "year")),
|
|
57
|
-
[todayStartDateTimeParamPlaceholder]: () => serializeDateTime(moment__default["default"]().startOf("day")),
|
|
58
|
-
[todayEndDateTimeParamPlaceholder]: () => serializeDateTime(moment__default["default"]().endOf("day")),
|
|
59
|
-
[tomorrowStartDateTimeParamPlaceholder]: () => serializeDateTime(moment__default["default"]().add(1, "days").startOf("day")),
|
|
60
|
-
[tomorrowEndDateTimeParamPlaceholder]: () => serializeDateTime(moment__default["default"]().add(1, "days").endOf("day")),
|
|
61
|
-
[yesterdayStartDateTimeParamPlaceholder]: () => serializeDateTime(moment__default["default"]().subtract(1, "days").startOf("day")),
|
|
62
|
-
[yesterdayEndDateTimeParamPlaceholder]: () => serializeDateTime(moment__default["default"]().subtract(1, "days").endOf("day")),
|
|
63
|
-
[weekAgoStartDateTimeParamPlaceholder]: () => serializeDateTime(moment__default["default"]().subtract(7, "days").startOf("day")),
|
|
64
|
-
[weekAgoEndDateTimeParamPlaceholder]: () => serializeDateTime(moment__default["default"]().subtract(7, "days").endOf("day")),
|
|
65
|
-
[weekFromNowStartDateTimeParamPlaceholder]: () => serializeDateTime(moment__default["default"]().add(7, "days").startOf("day")),
|
|
66
|
-
[weekFromNowEndDateTimeParamPlaceholder]: () => serializeDateTime(moment__default["default"]().add(7, "days").endOf("day")),
|
|
67
|
-
[monthAgoStartDateTimeParamPlaceholder]: () => serializeDateTime(moment__default["default"]().subtract(1, "months").startOf("day")),
|
|
68
|
-
[monthAgoEndDateTimeParamPlaceholder]: () => serializeDateTime(moment__default["default"]().subtract(1, "months").endOf("day")),
|
|
69
|
-
[monthFromNowStartDateTimeParamPlaceholder]: () => serializeDateTime(moment__default["default"]().add(1, "months").startOf("day")),
|
|
70
|
-
[monthFromNowEndDateTimeParamPlaceholder]: () => serializeDateTime(moment__default["default"]().add(1, "months").endOf("day")),
|
|
71
|
-
[yearAgoStartDateTimeParamPlaceholder]: () => serializeDateTime(moment__default["default"]().subtract(1, "year").startOf("day")),
|
|
72
|
-
[yearAgoEndDateTimeParamPlaceholder]: () => serializeDateTime(moment__default["default"]().subtract(1, "year").endOf("day")),
|
|
73
|
-
[yearFromNowStartDateTimeParamPlaceholder]: () => serializeDateTime(moment__default["default"]().add(1, "year").startOf("day")),
|
|
74
|
-
[yearFromNowEndDateTimeParamPlaceholder]: () => serializeDateTime(moment__default["default"]().add(1, "year").endOf("day"))
|
|
75
|
-
};
|
|
76
|
-
const dynamicFilterParamPrefix = `$dynamic_`;
|
|
77
|
-
const isDynamicFilterParam = paramValue => paramValue.startsWith(dynamicFilterParamPrefix);
|
|
78
|
-
const getFieldIdFromDynamicParam = paramValue => paramValue.substring(dynamicFilterParamPrefix.length);
|
|
79
|
-
const whereParamPrefix = "$where";
|
|
80
|
-
const mapDynamicParams = (params, onDynamicParam) => {
|
|
81
|
-
if (!params) {
|
|
82
|
-
return params;
|
|
83
|
-
}
|
|
84
|
-
return Object.fromEntries(Object.entries(params).map(([key, value]) => {
|
|
85
|
-
if (___default["default"].isArray(value)) {
|
|
86
|
-
return [key, value.map(v => {
|
|
87
|
-
return ___default["default"].isString(v) && isDynamicFilterParam(v) ? onDynamicParam(v) : v;
|
|
88
|
-
})];
|
|
89
|
-
} else {
|
|
90
|
-
return [key, ___default["default"].isString(value) && isDynamicFilterParam(value) ? onDynamicParam(value) : value];
|
|
91
|
-
}
|
|
92
|
-
}));
|
|
93
|
-
};
|
|
94
|
-
const relativeDatePlaceholderRegex = /\$(?:start-|end-|start-of-day-|end-of-day-)?(\d+)-(second|minute|hour|day|week|month|quarter|year)-(before-now|after-now)-(date-time|date)/;
|
|
95
|
-
const getRelativeDateValue = ({
|
|
96
|
-
isStartOfInterval,
|
|
97
|
-
unitForStart,
|
|
98
|
-
amount,
|
|
99
|
-
unit,
|
|
100
|
-
isBeforeNow,
|
|
101
|
-
isDateTime
|
|
102
|
-
}) => {
|
|
103
|
-
const result = isBeforeNow ? moment__default["default"]().subtract(amount, unit) : moment__default["default"]().add(amount, unit);
|
|
104
|
-
if (isStartOfInterval === undefined) {
|
|
105
|
-
return isDateTime ? serializeDateTime(result) : serializeDate(result);
|
|
106
|
-
} else {
|
|
107
|
-
const resultByStartEnd = isStartOfInterval ? result.startOf(unitForStart) : result.endOf(unitForStart);
|
|
108
|
-
return isDateTime ? serializeDateTime(resultByStartEnd) : serializeDate(resultByStartEnd);
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
const toRelativeDatePlaceholder = ({
|
|
112
|
-
isStartOfInterval,
|
|
113
|
-
unitForStart,
|
|
114
|
-
amount,
|
|
115
|
-
unit,
|
|
116
|
-
isBeforeNow,
|
|
117
|
-
isDateTime
|
|
118
|
-
}) => {
|
|
119
|
-
return `$${isStartOfInterval === undefined ? "" : isStartOfInterval ? `start-of-${unitForStart}-` : `end-of-${unitForStart}-`}${amount}-${unit}-${isBeforeNow ? "before-now" : "after-now"}-${isDateTime ? "date-time" : "date"}`;
|
|
120
|
-
};
|
|
121
|
-
const parseRelativeDatePlaceholder = placeholder => {
|
|
122
|
-
if (typeof placeholder === "string") {
|
|
123
|
-
const relativeDatePlaceholderMatch = placeholder.match(relativeDatePlaceholderRegex);
|
|
124
|
-
if (relativeDatePlaceholderMatch) {
|
|
125
|
-
const fullMatch = relativeDatePlaceholderMatch[0];
|
|
126
|
-
const isStartOfInterval = fullMatch.startsWith("$start") ? true : fullMatch.startsWith("$end") ? false : undefined;
|
|
127
|
-
let unit = relativeDatePlaceholderMatch[2];
|
|
128
|
-
return {
|
|
129
|
-
isStartOfInterval,
|
|
130
|
-
unitForStart:
|
|
131
|
-
// Usually the "start" unit is the same as the unit for relative date calculation.
|
|
132
|
-
// e.g. when we calculate the date "1 week ago", we want the beginning of the previous week.
|
|
133
|
-
// But sometimes they are different. We have hardcoded "day" for now, but this can be extended to any unit.
|
|
134
|
-
fullMatch.startsWith("$start-of-day") || fullMatch.startsWith("$end-of-day") ? "day" : isStartOfInterval !== undefined ? unit : undefined,
|
|
135
|
-
amount: Number.parseInt(relativeDatePlaceholderMatch[1]),
|
|
136
|
-
unit,
|
|
137
|
-
isBeforeNow: relativeDatePlaceholderMatch[3] === "before-now",
|
|
138
|
-
isDateTime: relativeDatePlaceholderMatch[4] === "date-time"
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return null;
|
|
143
|
-
};
|
|
144
|
-
const replacePlaceholdersInParams = params => params && ___default["default"].mapValues(params, (value, key) => {
|
|
145
|
-
const replaceFn = paramsPlaceholdersLookup[key];
|
|
146
|
-
if (replaceFn) {
|
|
147
|
-
return replaceFn();
|
|
148
|
-
}
|
|
149
|
-
const relativeDateInfo = parseRelativeDatePlaceholder(key);
|
|
150
|
-
if (relativeDateInfo) {
|
|
151
|
-
return getRelativeDateValue(relativeDateInfo);
|
|
152
|
-
}
|
|
153
|
-
return value;
|
|
154
|
-
});
|
|
155
|
-
const dateToDateTimeIntervalLookup = {
|
|
156
|
-
[todayDateParamPlaceholder]: {
|
|
157
|
-
start: todayStartDateTimeParamPlaceholder,
|
|
158
|
-
end: todayEndDateTimeParamPlaceholder
|
|
159
|
-
},
|
|
160
|
-
[tomorrowDateParamPlaceholder]: {
|
|
161
|
-
start: tomorrowStartDateTimeParamPlaceholder,
|
|
162
|
-
end: tomorrowEndDateTimeParamPlaceholder
|
|
163
|
-
},
|
|
164
|
-
[yesterdayDateParamPlaceholder]: {
|
|
165
|
-
start: yesterdayStartDateTimeParamPlaceholder,
|
|
166
|
-
end: yesterdayEndDateTimeParamPlaceholder
|
|
167
|
-
},
|
|
168
|
-
[weekAgoDateParamPlaceholder]: {
|
|
169
|
-
start: weekAgoStartDateTimeParamPlaceholder,
|
|
170
|
-
end: weekAgoEndDateTimeParamPlaceholder
|
|
171
|
-
},
|
|
172
|
-
[weekFromNowDateParamPlaceholder]: {
|
|
173
|
-
start: weekFromNowStartDateTimeParamPlaceholder,
|
|
174
|
-
end: weekFromNowEndDateTimeParamPlaceholder
|
|
175
|
-
},
|
|
176
|
-
[monthAgoDateParamPlaceholder]: {
|
|
177
|
-
start: monthAgoStartDateTimeParamPlaceholder,
|
|
178
|
-
end: monthAgoEndDateTimeParamPlaceholder
|
|
179
|
-
},
|
|
180
|
-
[monthFromNowDateParamPlaceholder]: {
|
|
181
|
-
start: monthFromNowStartDateTimeParamPlaceholder,
|
|
182
|
-
end: monthFromNowEndDateTimeParamPlaceholder
|
|
183
|
-
},
|
|
184
|
-
[yearAgoDateParamPlaceholder]: {
|
|
185
|
-
start: yearAgoStartDateTimeParamPlaceholder,
|
|
186
|
-
end: yearAgoEndDateTimeParamPlaceholder
|
|
187
|
-
},
|
|
188
|
-
[yearFromNowDateParamPlaceholder]: {
|
|
189
|
-
start: yearFromNowStartDateTimeParamPlaceholder,
|
|
190
|
-
end: yearFromNowEndDateTimeParamPlaceholder
|
|
191
|
-
}
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
var paramsPlaceholders = {
|
|
195
|
-
__proto__: null,
|
|
196
|
-
formulaTodayDateParamPlaceholder: formulaTodayDateParamPlaceholder,
|
|
197
|
-
formulaNowDateTimeParamPlaceholder: formulaNowDateTimeParamPlaceholder,
|
|
198
|
-
todayDateParamPlaceholder: todayDateParamPlaceholder,
|
|
199
|
-
tomorrowDateParamPlaceholder: tomorrowDateParamPlaceholder,
|
|
200
|
-
yesterdayDateParamPlaceholder: yesterdayDateParamPlaceholder,
|
|
201
|
-
weekAgoDateParamPlaceholder: weekAgoDateParamPlaceholder,
|
|
202
|
-
weekFromNowDateParamPlaceholder: weekFromNowDateParamPlaceholder,
|
|
203
|
-
monthAgoDateParamPlaceholder: monthAgoDateParamPlaceholder,
|
|
204
|
-
monthFromNowDateParamPlaceholder: monthFromNowDateParamPlaceholder,
|
|
205
|
-
yearAgoDateParamPlaceholder: yearAgoDateParamPlaceholder,
|
|
206
|
-
yearFromNowDateParamPlaceholder: yearFromNowDateParamPlaceholder,
|
|
207
|
-
todayStartDateTimeParamPlaceholder: todayStartDateTimeParamPlaceholder,
|
|
208
|
-
todayEndDateTimeParamPlaceholder: todayEndDateTimeParamPlaceholder,
|
|
209
|
-
tomorrowStartDateTimeParamPlaceholder: tomorrowStartDateTimeParamPlaceholder,
|
|
210
|
-
tomorrowEndDateTimeParamPlaceholder: tomorrowEndDateTimeParamPlaceholder,
|
|
211
|
-
yesterdayStartDateTimeParamPlaceholder: yesterdayStartDateTimeParamPlaceholder,
|
|
212
|
-
yesterdayEndDateTimeParamPlaceholder: yesterdayEndDateTimeParamPlaceholder,
|
|
213
|
-
weekAgoStartDateTimeParamPlaceholder: weekAgoStartDateTimeParamPlaceholder,
|
|
214
|
-
weekAgoEndDateTimeParamPlaceholder: weekAgoEndDateTimeParamPlaceholder,
|
|
215
|
-
weekFromNowStartDateTimeParamPlaceholder: weekFromNowStartDateTimeParamPlaceholder,
|
|
216
|
-
weekFromNowEndDateTimeParamPlaceholder: weekFromNowEndDateTimeParamPlaceholder,
|
|
217
|
-
monthAgoStartDateTimeParamPlaceholder: monthAgoStartDateTimeParamPlaceholder,
|
|
218
|
-
monthAgoEndDateTimeParamPlaceholder: monthAgoEndDateTimeParamPlaceholder,
|
|
219
|
-
monthFromNowStartDateTimeParamPlaceholder: monthFromNowStartDateTimeParamPlaceholder,
|
|
220
|
-
monthFromNowEndDateTimeParamPlaceholder: monthFromNowEndDateTimeParamPlaceholder,
|
|
221
|
-
yearAgoStartDateTimeParamPlaceholder: yearAgoStartDateTimeParamPlaceholder,
|
|
222
|
-
yearAgoEndDateTimeParamPlaceholder: yearAgoEndDateTimeParamPlaceholder,
|
|
223
|
-
yearFromNowStartDateTimeParamPlaceholder: yearFromNowStartDateTimeParamPlaceholder,
|
|
224
|
-
yearFromNowEndDateTimeParamPlaceholder: yearFromNowEndDateTimeParamPlaceholder,
|
|
225
|
-
paramsPlaceholdersLookup: paramsPlaceholdersLookup,
|
|
226
|
-
dynamicFilterParamPrefix: dynamicFilterParamPrefix,
|
|
227
|
-
isDynamicFilterParam: isDynamicFilterParam,
|
|
228
|
-
getFieldIdFromDynamicParam: getFieldIdFromDynamicParam,
|
|
229
|
-
whereParamPrefix: whereParamPrefix,
|
|
230
|
-
mapDynamicParams: mapDynamicParams,
|
|
231
|
-
getRelativeDateValue: getRelativeDateValue,
|
|
232
|
-
toRelativeDatePlaceholder: toRelativeDatePlaceholder,
|
|
233
|
-
parseRelativeDatePlaceholder: parseRelativeDatePlaceholder,
|
|
234
|
-
replacePlaceholdersInParams: replacePlaceholdersInParams,
|
|
235
|
-
dateToDateTimeIntervalLookup: dateToDateTimeIntervalLookup
|
|
236
|
-
};
|
|
237
|
-
|
|
238
|
-
const stringify = x => {
|
|
239
|
-
if (x === undefined) {
|
|
240
|
-
return "undefined";
|
|
241
|
-
}
|
|
242
|
-
return JSON.stringify(x);
|
|
243
|
-
};
|
|
244
|
-
class NotImplementedError extends Error {
|
|
245
|
-
constructor(value, itemType = undefined) {
|
|
246
|
-
super([`"${stringify(value)}"`, itemType, "is not implemented"].filter(x => x !== undefined).join(" "));
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
const assertIsValidExpression = expression => {
|
|
251
|
-
trace.assert(Array.isArray(expression), "expression must be array", {
|
|
252
|
-
expression
|
|
253
|
-
});
|
|
254
|
-
trace.assert(expression.length > 0, "empty expression does not make any sense");
|
|
255
|
-
};
|
|
256
|
-
const textTypes = ["fibery/text", "fibery/email", "fibery/url", "fibery/emoji"];
|
|
257
|
-
const dateTypes = ["fibery/date", "fibery/date-time"];
|
|
258
|
-
const dateRangeTypes = ["fibery/date-range", "fibery/date-time-range"];
|
|
259
|
-
const convertableDateTypes = ["fibery/date", "fibery/date-range"];
|
|
260
|
-
const numberTypes = ["fibery/int", "fibery/decimal"];
|
|
261
|
-
const dateRangeFunctions = new Set(["q/start", "q/end"]);
|
|
262
|
-
const firstLastFunctions = new Set(["q/first", "q/last"]);
|
|
263
|
-
const collectionOps = new Set(["q/count", "q/count-distinct", "q/sum", "q/min", "q/max", "q/avg", "q/join", "q/first", "q/last"]);
|
|
264
|
-
// [op, left, right]
|
|
265
|
-
// [=, $true, $false]
|
|
266
|
-
// [=, $my-id, ["fibery/id"]]
|
|
267
|
-
const binaryOperations = new Set(["=", "!=", "<", ">", "<=", ">=", "in",
|
|
268
|
-
//asc: obsolete,use q/in
|
|
269
|
-
"q/contains", "q/not-contains", "+", "-", "q/+", "q/-", "*", "/", "and", "or",
|
|
270
|
-
//asc: obsolete. use q/and, q/or
|
|
271
|
-
"q/and", "q/or", "q/in", "q/not-in"]);
|
|
272
|
-
const logicalOperators = new Set(["and", "or", "q/and", "q/or"]);
|
|
273
|
-
const relationalOperators = new Set(["=", "!=", "<", ">", "<=", ">="]);
|
|
274
|
-
const mathOperators = new Set(["+", "-", "*", "/", "q/+", "q/-", "q/concat"]);
|
|
275
|
-
const isFunctionCallExpression = expression => expression.length > 1 && ___default["default"].isString(expression[0]) && (expression[0].startsWith("q/") || ["=", "!=", "<", ">", "<=", ">=", "+", "-", "*", "/", "in", "and", "or", "not-in"].includes(expression[0]));
|
|
276
|
-
const fromRootKeyword = "q/from-root";
|
|
277
|
-
const isFromRootFieldExpression = expression => ___default["default"].isArray(expression) && expression[0] === fromRootKeyword;
|
|
278
|
-
const isDateRangeFunctionExpression = expression => (expression.length === 2 || expression.length === 3) && dateRangeFunctions.has(expression[0]) && isFieldExpression(expression[1]);
|
|
279
|
-
const isCollectionFunctionExpression = expression =>
|
|
280
|
-
//expression has length 3 in case of q/join
|
|
281
|
-
(expression.length === 2 || expression.length === 3) && collectionOps.has(expression[0]);
|
|
282
|
-
const isAccessFunctionExpression = expresion => expresion.length === 2 && expresion[0] === "q/access?" && isFieldExpression(expresion[1]);
|
|
283
|
-
const isBinaryExpression = expression => expression.length === 3 && binaryOperations.has(expression[0]);
|
|
284
|
-
const isNaryExpression = expression => expression.length > 1 && logicalOperators.has(expression[0]);
|
|
285
|
-
const isVariableExpression = expression => ___default["default"].isString(expression) && expression.startsWith("$");
|
|
286
|
-
const isMultiFieldAccess = expression => ___default["default"].isArray(expression) && expression.length === 2 && !isFunctionCallExpression(expression) && expression.every(x => ___default["default"].isString(x));
|
|
287
|
-
const isMultiFieldExpression = expression => Array.isArray(expression) && !isFunctionCallExpression(expression) && expression.some(x => isMultiFieldAccess(x)) && expression.every(x => !isVariableExpression(x) && !binaryOperations.has(x) && (___default["default"].isString(x) || isMultiFieldAccess(x)));
|
|
288
|
-
const isFieldExpression = expression => Array.isArray(expression) && !isFunctionCallExpression(expression) && expression.every(x => !isVariableExpression(x) && ___default["default"].isString(x));
|
|
289
|
-
const isQueryExpression = expression => {
|
|
290
|
-
if (___default["default"].isObject(expression) && "q/from" in expression) {
|
|
291
|
-
const fromExpression = expression["q/from"];
|
|
292
|
-
//asc: fromExpression === null for denormalizeSelect for reference collection case
|
|
293
|
-
return fromExpression === null || isFieldExpression(fromExpression) || isFromRootFieldExpression(fromExpression) || isMultiFieldExpression(fromExpression);
|
|
294
|
-
}
|
|
295
|
-
return false;
|
|
296
|
-
};
|
|
297
|
-
const collectFieldExpressions = (memo, expression) => {
|
|
298
|
-
if (isVariableExpression(expression)) ; else if (isFunctionCallExpression(expression)) {
|
|
299
|
-
for (const part of expression.slice(1)) {
|
|
300
|
-
if (isVariableExpression(part) || part === null) ; else {
|
|
301
|
-
if (___default["default"].isString(part)) {
|
|
302
|
-
// field path shortcut
|
|
303
|
-
memo.push([part]);
|
|
304
|
-
} else {
|
|
305
|
-
collectFieldExpressions(memo, part);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
} else if (isFieldExpression(expression) || isMultiFieldExpression(expression)) {
|
|
310
|
-
memo.push(expression);
|
|
311
|
-
} else if (expression["q/from"] && isFieldExpression(expression["q/from"])) {
|
|
312
|
-
const innerMemo = [];
|
|
313
|
-
expression["q/select"] && collectFieldExpressions(innerMemo, expression["q/select"]);
|
|
314
|
-
expression["q/where"] && collectFieldExpressions(innerMemo, expression["q/where"]);
|
|
315
|
-
for (const fieldExpression of innerMemo) {
|
|
316
|
-
memo.push([...expression["q/from"], ...fieldExpression]);
|
|
317
|
-
}
|
|
318
|
-
} else {
|
|
319
|
-
throw new NotImplementedError(expression, "expression");
|
|
320
|
-
}
|
|
321
|
-
};
|
|
322
|
-
const getFieldObjectsByFieldExpression = ({
|
|
323
|
-
typeObject,
|
|
324
|
-
expression
|
|
325
|
-
}) => {
|
|
326
|
-
assertIsValidExpression(expression);
|
|
327
|
-
const fieldObjects = [];
|
|
328
|
-
let currentTypeObject = typeObject;
|
|
329
|
-
for (const fieldOrMultiFieldAccess of expression) {
|
|
330
|
-
if (isMultiFieldAccess(fieldOrMultiFieldAccess)) {
|
|
331
|
-
const [multiField, type] = fieldOrMultiFieldAccess;
|
|
332
|
-
const fieldObject = currentTypeObject.fieldObjectsByName[multiField];
|
|
333
|
-
fieldObjects.push(fieldObject);
|
|
334
|
-
const foundField = fieldObject.multiRelatedFieldObjects.find(f => f.holderType === type);
|
|
335
|
-
trace.assert(foundField, "incorrect expression for multi-field");
|
|
336
|
-
currentTypeObject = foundField.holderTypeObject;
|
|
337
|
-
} else {
|
|
338
|
-
const fieldObject = currentTypeObject.fieldObjectsByName[fieldOrMultiFieldAccess];
|
|
339
|
-
fieldObjects.push(fieldObject);
|
|
340
|
-
currentTypeObject = fieldObject.typeObject;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
return fieldObjects;
|
|
344
|
-
};
|
|
345
|
-
const getFieldObjectByFieldExpression = (x // TODO: review types. using type assertion now to avoid rewriting half of app
|
|
346
|
-
) => ___default["default"].last(getFieldObjectsByFieldExpression(x));
|
|
347
|
-
const getFieldObjects = (expression, typeObject) => {
|
|
348
|
-
const fieldExpression = extractFieldExpressions(expression)[0];
|
|
349
|
-
return getFieldObjectsByFieldExpression({
|
|
350
|
-
typeObject,
|
|
351
|
-
expression: fieldExpression
|
|
352
|
-
});
|
|
353
|
-
};
|
|
354
|
-
|
|
355
|
-
/** @deprecated
|
|
356
|
-
* This method checks few expression forms, that we do not generate on frontend anymore(field-access shortcut, direct value as parameter).
|
|
357
|
-
* I'm afraid to replace it with implementation based on visitor everywhere, as visitors don't allow such expression forms and I don't want to extend visitor with those forms.
|
|
358
|
-
* If you need this method in new places, consider implementing same logic on visitors and use it.
|
|
359
|
-
**/
|
|
360
|
-
const extractFieldExpressions = expression => {
|
|
361
|
-
const memo = [];
|
|
362
|
-
collectFieldExpressions(memo, expression);
|
|
363
|
-
return ___default["default"].uniqBy(memo, x => x.join(","));
|
|
364
|
-
};
|
|
365
|
-
const createExpressionVisitor = visitor => {
|
|
366
|
-
let visitorWithDefault = null;
|
|
367
|
-
const visitorDefault = {
|
|
368
|
-
visitVariableExpression: expression => expression,
|
|
369
|
-
visitFunctionCallExpression: ([fnName, ...args]) => [fnName, ...args.map(x => visitorWithDefault.visitExpression(x))],
|
|
370
|
-
visitFromRootFieldExpression: ([fromRootKeyword, ...rest]) => [fromRootKeyword, ...rest.map(x => visitorWithDefault.visitExpression(x))],
|
|
371
|
-
visitFieldExpression: expression => expression,
|
|
372
|
-
visitOrderByExpression: orderByExpression => orderByExpression.map(x => {
|
|
373
|
-
const [fieldExpression, orderDir] = x;
|
|
374
|
-
const fieldExpressionNew = visitorWithDefault.visitExpression(fieldExpression);
|
|
375
|
-
return [fieldExpressionNew, orderDir];
|
|
376
|
-
}),
|
|
377
|
-
visitQueryExpression: subQueryExpression => {
|
|
378
|
-
const {
|
|
379
|
-
"q/from": fromExpression,
|
|
380
|
-
"q/select": selectExpression,
|
|
381
|
-
"q/where": whereExpression,
|
|
382
|
-
"q/order-by": orderByExpression
|
|
383
|
-
} = subQueryExpression;
|
|
384
|
-
return {
|
|
385
|
-
...subQueryExpression,
|
|
386
|
-
...(fromExpression ? {
|
|
387
|
-
"q/from": visitorWithDefault.visitFieldExpression(fromExpression)
|
|
388
|
-
} : null),
|
|
389
|
-
...(selectExpression ? {
|
|
390
|
-
"q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => visitorWithDefault.visitExpression(val)) : visitorWithDefault.visitExpression(selectExpression)
|
|
391
|
-
} : null),
|
|
392
|
-
...(whereExpression ? {
|
|
393
|
-
"q/where": visitorWithDefault.visitExpression(whereExpression)
|
|
394
|
-
} : null),
|
|
395
|
-
...(orderByExpression ? {
|
|
396
|
-
"q/order-by": visitorWithDefault.visitOrderByExpression(orderByExpression)
|
|
397
|
-
} : null)
|
|
398
|
-
};
|
|
399
|
-
},
|
|
400
|
-
visitExpression: expression => {
|
|
401
|
-
if (expression === null) {
|
|
402
|
-
throw new NotImplementedError(expression, "expression");
|
|
403
|
-
} else if (isVariableExpression(expression)) {
|
|
404
|
-
return visitorWithDefault.visitVariableExpression(expression, visitorDefault);
|
|
405
|
-
} else if (isFromRootFieldExpression(expression)) {
|
|
406
|
-
return visitorWithDefault.visitFromRootFieldExpression(expression, visitorDefault);
|
|
407
|
-
} else if (isFunctionCallExpression(expression)) {
|
|
408
|
-
return visitorWithDefault.visitFunctionCallExpression(expression, visitorDefault);
|
|
409
|
-
} else if (isFieldExpression(expression) || isMultiFieldExpression(expression)) {
|
|
410
|
-
return visitorWithDefault.visitFieldExpression(expression, visitorDefault);
|
|
411
|
-
} else if (isQueryExpression(expression)) {
|
|
412
|
-
return visitorWithDefault.visitQueryExpression(expression, visitorDefault);
|
|
413
|
-
} else {
|
|
414
|
-
throw new NotImplementedError(expression, "expression");
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
};
|
|
418
|
-
visitorWithDefault = {
|
|
419
|
-
...visitorDefault,
|
|
420
|
-
...visitor
|
|
421
|
-
};
|
|
422
|
-
return visitorWithDefault;
|
|
423
|
-
};
|
|
424
|
-
|
|
425
|
-
var utils = {
|
|
426
|
-
__proto__: null,
|
|
427
|
-
assertIsValidExpression: assertIsValidExpression,
|
|
428
|
-
textTypes: textTypes,
|
|
429
|
-
dateTypes: dateTypes,
|
|
430
|
-
dateRangeTypes: dateRangeTypes,
|
|
431
|
-
convertableDateTypes: convertableDateTypes,
|
|
432
|
-
numberTypes: numberTypes,
|
|
433
|
-
dateRangeFunctions: dateRangeFunctions,
|
|
434
|
-
firstLastFunctions: firstLastFunctions,
|
|
435
|
-
logicalOperators: logicalOperators,
|
|
436
|
-
relationalOperators: relationalOperators,
|
|
437
|
-
mathOperators: mathOperators,
|
|
438
|
-
isFunctionCallExpression: isFunctionCallExpression,
|
|
439
|
-
fromRootKeyword: fromRootKeyword,
|
|
440
|
-
isFromRootFieldExpression: isFromRootFieldExpression,
|
|
441
|
-
isDateRangeFunctionExpression: isDateRangeFunctionExpression,
|
|
442
|
-
isCollectionFunctionExpression: isCollectionFunctionExpression,
|
|
443
|
-
isAccessFunctionExpression: isAccessFunctionExpression,
|
|
444
|
-
isBinaryExpression: isBinaryExpression,
|
|
445
|
-
isNaryExpression: isNaryExpression,
|
|
446
|
-
isVariableExpression: isVariableExpression,
|
|
447
|
-
isMultiFieldAccess: isMultiFieldAccess,
|
|
448
|
-
isMultiFieldExpression: isMultiFieldExpression,
|
|
449
|
-
isFieldExpression: isFieldExpression,
|
|
450
|
-
isQueryExpression: isQueryExpression,
|
|
451
|
-
getFieldObjectsByFieldExpression: getFieldObjectsByFieldExpression,
|
|
452
|
-
getFieldObjectByFieldExpression: getFieldObjectByFieldExpression,
|
|
453
|
-
getFieldObjects: getFieldObjects,
|
|
454
|
-
extractFieldExpressions: extractFieldExpressions,
|
|
455
|
-
createExpressionVisitor: createExpressionVisitor
|
|
456
|
-
};
|
|
457
|
-
|
|
458
|
-
const visitFieldExpression = ({
|
|
459
|
-
expression: fieldExpression,
|
|
460
|
-
typeObject: initialTypeObject,
|
|
461
|
-
onField,
|
|
462
|
-
onFieldNotFound
|
|
463
|
-
}) => fieldExpression.reduce(({
|
|
464
|
-
typeObject,
|
|
465
|
-
expression
|
|
466
|
-
}, fieldAccess) => {
|
|
467
|
-
if (typeObject && isMultiFieldAccess(fieldAccess) && typeObject.fieldObjectsById.hasOwnProperty(fieldAccess[0])) {
|
|
468
|
-
var _fieldObject$multiRel;
|
|
469
|
-
const typeId = fieldAccess[1];
|
|
470
|
-
const fieldObject = typeObject.fieldObjectsById[fieldAccess[0]];
|
|
471
|
-
const nextTypeObject = (_fieldObject$multiRel = fieldObject.multiRelatedFieldObjects.find(f => f.holderTypeObject.id === typeId)) == null ? void 0 : _fieldObject$multiRel.holderTypeObject;
|
|
472
|
-
if (!nextTypeObject) {
|
|
473
|
-
const notFoundResult = onFieldNotFound({
|
|
474
|
-
currentTypeObject: typeObject,
|
|
475
|
-
expression: fieldExpression,
|
|
476
|
-
fieldAccess
|
|
477
|
-
});
|
|
478
|
-
return notFoundResult ? {
|
|
479
|
-
typeObject: notFoundResult.typeObject,
|
|
480
|
-
expression: [...expression, notFoundResult.fieldAccess]
|
|
481
|
-
} : {
|
|
482
|
-
typeObject,
|
|
483
|
-
expression
|
|
484
|
-
};
|
|
485
|
-
}
|
|
486
|
-
const onFieldResult = onField({
|
|
487
|
-
fieldAccess,
|
|
488
|
-
fieldObject,
|
|
489
|
-
typeObject: nextTypeObject
|
|
490
|
-
});
|
|
491
|
-
return onFieldResult ? {
|
|
492
|
-
typeObject: onFieldResult.typeObject,
|
|
493
|
-
expression: [...expression, onFieldResult.fieldAccess]
|
|
494
|
-
} : {
|
|
495
|
-
typeObject,
|
|
496
|
-
expression
|
|
497
|
-
};
|
|
498
|
-
} else if (typeObject && typeObject.fieldObjectsById.hasOwnProperty(fieldAccess)) {
|
|
499
|
-
const fieldObject = typeObject.fieldObjectsById[fieldAccess];
|
|
500
|
-
const onFieldResult = onField({
|
|
501
|
-
fieldAccess,
|
|
502
|
-
fieldObject,
|
|
503
|
-
typeObject: fieldObject.typeObject
|
|
504
|
-
});
|
|
505
|
-
return onFieldResult ? {
|
|
506
|
-
typeObject: onFieldResult.typeObject,
|
|
507
|
-
expression: [...expression, onFieldResult.fieldAccess]
|
|
508
|
-
} : {
|
|
509
|
-
typeObject,
|
|
510
|
-
expression
|
|
511
|
-
};
|
|
512
|
-
} else {
|
|
513
|
-
const notFoundResult = onFieldNotFound({
|
|
514
|
-
currentTypeObject: typeObject,
|
|
515
|
-
expression: fieldExpression,
|
|
516
|
-
fieldAccess
|
|
517
|
-
});
|
|
518
|
-
return notFoundResult ? {
|
|
519
|
-
typeObject: notFoundResult.typeObject,
|
|
520
|
-
expression: [...expression, notFoundResult.fieldAccess]
|
|
521
|
-
} : {
|
|
522
|
-
typeObject,
|
|
523
|
-
expression
|
|
524
|
-
};
|
|
525
|
-
}
|
|
526
|
-
}, {
|
|
527
|
-
typeObject: initialTypeObject,
|
|
528
|
-
expression: []
|
|
529
|
-
});
|
|
530
|
-
const defaultOnFieldNotFound = () => undefined;
|
|
531
|
-
const defaultOnField = () => undefined;
|
|
532
|
-
const fieldAccessVisitorTypeAwareInternal = ({
|
|
533
|
-
typeObject,
|
|
534
|
-
rootTypeObject,
|
|
535
|
-
onField = defaultOnField,
|
|
536
|
-
onFieldNotFound = defaultOnFieldNotFound
|
|
537
|
-
}) => {
|
|
538
|
-
return createExpressionVisitor({
|
|
539
|
-
visitFieldExpression: expression => visitFieldExpression({
|
|
540
|
-
typeObject,
|
|
541
|
-
expression,
|
|
542
|
-
onField,
|
|
543
|
-
onFieldNotFound
|
|
544
|
-
}).expression,
|
|
545
|
-
visitFromRootFieldExpression: ([fromRootKeyword, ...rest]) => [fromRootKeyword, ...rest.map(x => fieldAccessVisitorTypeAwareInternal({
|
|
546
|
-
typeObject: rootTypeObject,
|
|
547
|
-
rootTypeObject,
|
|
548
|
-
onField,
|
|
549
|
-
onFieldNotFound
|
|
550
|
-
}).visitExpression(x))],
|
|
551
|
-
visitQueryExpression: subQueryExpression => {
|
|
552
|
-
const {
|
|
553
|
-
"q/from": fromExpression,
|
|
554
|
-
"q/select": selectExpression,
|
|
555
|
-
"q/where": whereExpression,
|
|
556
|
-
"q/order-by": orderByExpression
|
|
557
|
-
} = subQueryExpression;
|
|
558
|
-
const fromVisitResult = visitFieldExpression({
|
|
559
|
-
typeObject,
|
|
560
|
-
expression: fromExpression,
|
|
561
|
-
onField,
|
|
562
|
-
onFieldNotFound
|
|
563
|
-
});
|
|
564
|
-
if (fromVisitResult != null && fromVisitResult.typeObject) {
|
|
565
|
-
const subQueryVisitor = fieldAccessVisitorTypeAwareInternal({
|
|
566
|
-
typeObject: fromVisitResult == null ? void 0 : fromVisitResult.typeObject,
|
|
567
|
-
rootTypeObject,
|
|
568
|
-
onField,
|
|
569
|
-
onFieldNotFound
|
|
570
|
-
});
|
|
571
|
-
return {
|
|
572
|
-
...subQueryExpression,
|
|
573
|
-
...{
|
|
574
|
-
"q/from": fromVisitResult.expression,
|
|
575
|
-
"q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => subQueryVisitor.visitExpression(val)) : subQueryVisitor.visitExpression(selectExpression)
|
|
576
|
-
},
|
|
577
|
-
...(whereExpression ? {
|
|
578
|
-
"q/where": subQueryVisitor.visitExpression(whereExpression)
|
|
579
|
-
} : null),
|
|
580
|
-
...(orderByExpression ? {
|
|
581
|
-
"q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
|
|
582
|
-
} : null)
|
|
583
|
-
};
|
|
584
|
-
}
|
|
585
|
-
return subQueryExpression;
|
|
586
|
-
}
|
|
587
|
-
});
|
|
588
|
-
};
|
|
589
|
-
const fieldAccessVisitorTypeAware = ({
|
|
590
|
-
typeObject,
|
|
591
|
-
onField = defaultOnField,
|
|
592
|
-
onFieldNotFound = defaultOnFieldNotFound
|
|
593
|
-
}) => {
|
|
594
|
-
return fieldAccessVisitorTypeAwareInternal({
|
|
595
|
-
typeObject,
|
|
596
|
-
rootTypeObject: typeObject,
|
|
597
|
-
onField,
|
|
598
|
-
onFieldNotFound
|
|
599
|
-
});
|
|
600
|
-
};
|
|
601
|
-
|
|
602
|
-
const defaultIdsWithNamesOnFieldNotFound = ({
|
|
603
|
-
fieldExpressionInNamesTerms,
|
|
604
|
-
fieldId
|
|
605
|
-
}) => {
|
|
606
|
-
return {
|
|
607
|
-
currentTypeObject: null,
|
|
608
|
-
fieldExpressionInNamesTerms: [...fieldExpressionInNamesTerms, fieldId]
|
|
609
|
-
};
|
|
610
|
-
};
|
|
611
|
-
const visitFieldExpressionForReplaceIdsWithNamesVisitor = ({
|
|
612
|
-
expression,
|
|
613
|
-
typeObject,
|
|
614
|
-
onFieldNotFound
|
|
615
|
-
}) => expression.reduce(({
|
|
616
|
-
currentTypeObject,
|
|
617
|
-
fieldExpressionInNamesTerms
|
|
618
|
-
}, fieldId) => {
|
|
619
|
-
if (currentTypeObject && isMultiFieldAccess(fieldId) && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId[0])) {
|
|
620
|
-
var _fieldObject$multiRel;
|
|
621
|
-
const typeId = fieldId[1];
|
|
622
|
-
const fieldObject = currentTypeObject.fieldObjectsById[fieldId[0]];
|
|
623
|
-
const nextTypeObject = (_fieldObject$multiRel = fieldObject.multiRelatedFieldObjects.find(f => f.holderTypeObject.id === typeId)) == null ? void 0 : _fieldObject$multiRel.holderTypeObject;
|
|
624
|
-
if (!nextTypeObject) {
|
|
625
|
-
return onFieldNotFound({
|
|
626
|
-
currentTypeObject,
|
|
627
|
-
fieldExpressionInNamesTerms,
|
|
628
|
-
fieldId: fieldId,
|
|
629
|
-
expression
|
|
630
|
-
});
|
|
631
|
-
}
|
|
632
|
-
return {
|
|
633
|
-
currentTypeObject: nextTypeObject,
|
|
634
|
-
fieldExpressionInNamesTerms: [...fieldExpressionInNamesTerms, [fieldObject.name, nextTypeObject.name]]
|
|
635
|
-
};
|
|
636
|
-
} else if (currentTypeObject && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId)) {
|
|
637
|
-
const fieldObject = currentTypeObject.fieldObjectsById[fieldId];
|
|
638
|
-
return {
|
|
639
|
-
currentTypeObject: fieldObject.typeObject,
|
|
640
|
-
fieldExpressionInNamesTerms: [...fieldExpressionInNamesTerms, fieldObject.name]
|
|
641
|
-
};
|
|
642
|
-
} else {
|
|
643
|
-
return onFieldNotFound({
|
|
644
|
-
currentTypeObject,
|
|
645
|
-
fieldExpressionInNamesTerms,
|
|
646
|
-
fieldId,
|
|
647
|
-
expression
|
|
648
|
-
});
|
|
649
|
-
}
|
|
650
|
-
}, {
|
|
651
|
-
currentTypeObject: typeObject,
|
|
652
|
-
fieldExpressionInNamesTerms: []
|
|
653
|
-
});
|
|
654
|
-
const fieldExpressionVisitor = (typeObject, visitFieldExpression, replacedExpressionKey = "replacedExpression") => {
|
|
655
|
-
const visitor = createExpressionVisitor({
|
|
656
|
-
visitFieldExpression: expression => visitFieldExpression(typeObject, expression)[replacedExpressionKey],
|
|
657
|
-
visitQueryExpression: subQueryExpression => {
|
|
658
|
-
const {
|
|
659
|
-
"q/from": fromExpression,
|
|
660
|
-
"q/select": selectExpression,
|
|
661
|
-
"q/where": whereExpression,
|
|
662
|
-
"q/order-by": orderByExpression
|
|
663
|
-
} = subQueryExpression;
|
|
664
|
-
const subQueryTypeObject = visitFieldExpression(typeObject, fromExpression).currentTypeObject;
|
|
665
|
-
if (subQueryTypeObject) {
|
|
666
|
-
const subQueryVisitor = fieldExpressionVisitor(subQueryTypeObject, visitFieldExpression, replacedExpressionKey);
|
|
667
|
-
return {
|
|
668
|
-
...subQueryExpression,
|
|
669
|
-
...{
|
|
670
|
-
"q/from": visitor.visitFieldExpression(fromExpression),
|
|
671
|
-
"q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => subQueryVisitor.visitExpression(val)) : subQueryVisitor.visitExpression(selectExpression)
|
|
672
|
-
},
|
|
673
|
-
...(whereExpression ? {
|
|
674
|
-
"q/where": subQueryVisitor.visitExpression(whereExpression)
|
|
675
|
-
} : null),
|
|
676
|
-
...(orderByExpression ? {
|
|
677
|
-
"q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
|
|
678
|
-
} : null)
|
|
679
|
-
};
|
|
680
|
-
}
|
|
681
|
-
return subQueryExpression;
|
|
682
|
-
}
|
|
683
|
-
});
|
|
684
|
-
return visitor;
|
|
685
|
-
};
|
|
686
|
-
const replaceIdsWithNamesVisitor = (typeObject, onFieldNotFound = defaultIdsWithNamesOnFieldNotFound) => {
|
|
687
|
-
return fieldExpressionVisitor(typeObject, (typeObject, expression) => visitFieldExpressionForReplaceIdsWithNamesVisitor({
|
|
688
|
-
expression,
|
|
689
|
-
typeObject,
|
|
690
|
-
onFieldNotFound
|
|
691
|
-
}), "fieldExpressionInNamesTerms");
|
|
692
|
-
};
|
|
693
|
-
const defaultNamesWithIdsOnFieldNotFound = ({
|
|
694
|
-
fieldExpressionInIdsTerms,
|
|
695
|
-
field
|
|
696
|
-
}) => {
|
|
697
|
-
return {
|
|
698
|
-
currentTypeObject: null,
|
|
699
|
-
fieldExpressionInIdsTerms: [...fieldExpressionInIdsTerms, field]
|
|
700
|
-
};
|
|
701
|
-
};
|
|
702
|
-
const visitFieldExpressionForReplaceNamesWithIdsVisitor = ({
|
|
703
|
-
expression,
|
|
704
|
-
typeObject,
|
|
705
|
-
onFieldNotFound
|
|
706
|
-
}) => expression.reduce(({
|
|
707
|
-
currentTypeObject,
|
|
708
|
-
fieldExpressionInIdsTerms
|
|
709
|
-
}, field) => {
|
|
710
|
-
if (currentTypeObject && isMultiFieldAccess(field) && currentTypeObject.fieldObjectsByName.hasOwnProperty(field[0])) {
|
|
711
|
-
var _fieldObject$multiRel2;
|
|
712
|
-
const type = field[1];
|
|
713
|
-
const fieldObject = currentTypeObject.fieldObjectsByName[field[0]];
|
|
714
|
-
const nextTypeObject = (_fieldObject$multiRel2 = fieldObject.multiRelatedFieldObjects.find(f => f.holderType === type)) == null ? void 0 : _fieldObject$multiRel2.holderTypeObject;
|
|
715
|
-
if (!nextTypeObject) {
|
|
716
|
-
return onFieldNotFound({
|
|
717
|
-
currentTypeObject,
|
|
718
|
-
fieldExpressionInIdsTerms,
|
|
719
|
-
field,
|
|
720
|
-
expression
|
|
721
|
-
});
|
|
722
|
-
}
|
|
723
|
-
return {
|
|
724
|
-
currentTypeObject: nextTypeObject,
|
|
725
|
-
fieldExpressionInIdsTerms: [...fieldExpressionInIdsTerms, [fieldObject.id, nextTypeObject.id]]
|
|
726
|
-
};
|
|
727
|
-
} else if (currentTypeObject && currentTypeObject.fieldObjectsByName.hasOwnProperty(field)) {
|
|
728
|
-
const fieldObject = currentTypeObject.fieldObjectsByName[field];
|
|
729
|
-
return {
|
|
730
|
-
currentTypeObject: fieldObject.typeObject,
|
|
731
|
-
fieldExpressionInIdsTerms: [...fieldExpressionInIdsTerms, fieldObject.id]
|
|
732
|
-
};
|
|
733
|
-
} else {
|
|
734
|
-
return onFieldNotFound({
|
|
735
|
-
currentTypeObject,
|
|
736
|
-
fieldExpressionInIdsTerms,
|
|
737
|
-
field,
|
|
738
|
-
expression
|
|
739
|
-
});
|
|
740
|
-
}
|
|
741
|
-
}, {
|
|
742
|
-
currentTypeObject: typeObject,
|
|
743
|
-
fieldExpressionInIdsTerms: []
|
|
744
|
-
});
|
|
745
|
-
const replaceNamesWithIdsVisitor = (typeObject, onFieldNotFound = defaultNamesWithIdsOnFieldNotFound) => {
|
|
746
|
-
return fieldExpressionVisitor(typeObject, (typeObject, expression) => visitFieldExpressionForReplaceNamesWithIdsVisitor({
|
|
747
|
-
expression,
|
|
748
|
-
typeObject,
|
|
749
|
-
onFieldNotFound
|
|
750
|
-
}), "fieldExpressionInIdsTerms");
|
|
751
|
-
};
|
|
752
|
-
const deleteExpressionsWithNotFoundFieldsVisitor = typeObject => {
|
|
753
|
-
const visitor = createExpressionVisitor({
|
|
754
|
-
visitFunctionCallExpression: ([fnName, ...args]) => {
|
|
755
|
-
const argsNew = args.map(x => visitor.visitExpression(x)).filter(Boolean);
|
|
756
|
-
if (logicalOperators.has(fnName)) {
|
|
757
|
-
if (argsNew.length > 0) {
|
|
758
|
-
return argsNew.length === 1 ? argsNew[0] : [fnName, ...argsNew];
|
|
759
|
-
}
|
|
760
|
-
return null;
|
|
761
|
-
} else {
|
|
762
|
-
return argsNew.length === args.length ? [fnName, ...argsNew] : null;
|
|
763
|
-
}
|
|
764
|
-
},
|
|
765
|
-
visitFieldExpression: expression => {
|
|
766
|
-
const fieldTypeObject = expression.reduce((holderTypeObject, field) => {
|
|
767
|
-
if (holderTypeObject && isMultiFieldAccess(field) && holderTypeObject.fieldObjectsByName.hasOwnProperty(field[0])) {
|
|
768
|
-
var _fieldObject$multiRel3;
|
|
769
|
-
const type = field[1];
|
|
770
|
-
const fieldObject = holderTypeObject.fieldObjectsByName[field[0]];
|
|
771
|
-
const nextTypeObject = (_fieldObject$multiRel3 = fieldObject.multiRelatedFieldObjects.find(f => f.holderType === type)) == null ? void 0 : _fieldObject$multiRel3.holderTypeObject;
|
|
772
|
-
if (!nextTypeObject) {
|
|
773
|
-
return null;
|
|
774
|
-
}
|
|
775
|
-
return nextTypeObject;
|
|
776
|
-
} else if (holderTypeObject && holderTypeObject.fieldObjectsByName.hasOwnProperty(field)) {
|
|
777
|
-
return holderTypeObject.fieldObjectsByName[field].typeObject;
|
|
778
|
-
} else {
|
|
779
|
-
return null;
|
|
780
|
-
}
|
|
781
|
-
}, typeObject);
|
|
782
|
-
return fieldTypeObject && expression;
|
|
783
|
-
},
|
|
784
|
-
visitOrderByExpression: orderByExpression => {
|
|
785
|
-
return orderByExpression.map(x => {
|
|
786
|
-
const [fieldExpression, orderDir] = x;
|
|
787
|
-
const fieldExpressionNew = visitor.visitExpression(fieldExpression);
|
|
788
|
-
return fieldExpressionNew && [fieldExpressionNew, orderDir];
|
|
789
|
-
}).filter(Boolean);
|
|
790
|
-
},
|
|
791
|
-
visitQueryExpression: subQueryExpression => {
|
|
792
|
-
const {
|
|
793
|
-
"q/from": fromExpression,
|
|
794
|
-
"q/select": selectExpression,
|
|
795
|
-
"q/where": whereExpression,
|
|
796
|
-
"q/order-by": orderByExpression
|
|
797
|
-
} = subQueryExpression;
|
|
798
|
-
const subQueryTypeObject = fromExpression.reduce((typeObject, field) => typeObject && typeObject.fieldObjectsByName.hasOwnProperty(field) ? typeObject.fieldObjectsByName[field].typeObject : null, typeObject);
|
|
799
|
-
if (subQueryTypeObject) {
|
|
800
|
-
const subQueryVisitor = deleteExpressionsWithNotFoundFieldsVisitor(subQueryTypeObject);
|
|
801
|
-
const subQueryExpressionNew = ___default["default"].pickBy({
|
|
802
|
-
...subQueryExpression,
|
|
803
|
-
...{
|
|
804
|
-
"q/from": visitor.visitFieldExpression(fromExpression),
|
|
805
|
-
"q/select": subQueryVisitor.visitExpression(selectExpression)
|
|
806
|
-
},
|
|
807
|
-
...(whereExpression ? {
|
|
808
|
-
"q/where": subQueryVisitor.visitExpression(whereExpression)
|
|
809
|
-
} : null),
|
|
810
|
-
...(orderByExpression ? {
|
|
811
|
-
"q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
|
|
812
|
-
} : null)
|
|
813
|
-
});
|
|
814
|
-
const {
|
|
815
|
-
"q/select": selectExpressionNew
|
|
816
|
-
} = subQueryExpressionNew;
|
|
817
|
-
return selectExpressionNew ? subQueryExpressionNew : null;
|
|
818
|
-
} else {
|
|
819
|
-
return null;
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
});
|
|
823
|
-
return visitor;
|
|
824
|
-
};
|
|
825
|
-
const expressionContainsAggregation = expression => {
|
|
826
|
-
let result = false;
|
|
827
|
-
const visitor = createExpressionVisitor({
|
|
828
|
-
visitQueryExpression: queryExpression => {
|
|
829
|
-
const {
|
|
830
|
-
"q/select": selectExpression
|
|
831
|
-
} = queryExpression;
|
|
832
|
-
if (isCollectionFunctionExpression(selectExpression)) {
|
|
833
|
-
result = true;
|
|
834
|
-
}
|
|
835
|
-
},
|
|
836
|
-
visitFunctionCallExpression: (expression, visitorDefault) => {
|
|
837
|
-
if (firstLastFunctions.has(expression[0])) {
|
|
838
|
-
result = true;
|
|
839
|
-
} else {
|
|
840
|
-
visitorDefault.visitFunctionCallExpression(expression);
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
});
|
|
844
|
-
visitor.visitExpression(expression);
|
|
845
|
-
return result;
|
|
846
|
-
};
|
|
847
|
-
const defaultGetExpressionTypeOnFieldNotFound = () => {
|
|
848
|
-
return {
|
|
849
|
-
currentTypeObject: null
|
|
850
|
-
};
|
|
851
|
-
};
|
|
852
|
-
const getFieldAccessExpressionTypeObject = ({
|
|
853
|
-
expression,
|
|
854
|
-
typeObject,
|
|
855
|
-
onFieldNotFound,
|
|
856
|
-
returnRefTypeInsteadOfId
|
|
857
|
-
}) => {
|
|
858
|
-
const reduced = expression.reduce(({
|
|
859
|
-
currentTypeObject
|
|
860
|
-
}, fieldId, index) => {
|
|
861
|
-
if (currentTypeObject && isMultiFieldAccess(fieldId) && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId[0])) {
|
|
862
|
-
var _fieldObject$multiRel4;
|
|
863
|
-
const typeId = fieldId[1];
|
|
864
|
-
const fieldObject = currentTypeObject.fieldObjectsById[fieldId[0]];
|
|
865
|
-
const nextTypeObject = (_fieldObject$multiRel4 = fieldObject.multiRelatedFieldObjects.find(f => f.holderTypeObject.id === typeId)) == null ? void 0 : _fieldObject$multiRel4.holderTypeObject;
|
|
866
|
-
if (!nextTypeObject) {
|
|
867
|
-
return onFieldNotFound({
|
|
868
|
-
currentTypeObject,
|
|
869
|
-
fieldId
|
|
870
|
-
});
|
|
871
|
-
}
|
|
872
|
-
return {
|
|
873
|
-
currentTypeObject: nextTypeObject
|
|
874
|
-
};
|
|
875
|
-
} else if (currentTypeObject && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId)) {
|
|
876
|
-
const fieldObject = currentTypeObject.fieldObjectsById[fieldId];
|
|
877
|
-
if (returnRefTypeInsteadOfId && index === expression.length - 1 && fieldObject.isId) {
|
|
878
|
-
return {
|
|
879
|
-
currentTypeObject
|
|
880
|
-
};
|
|
881
|
-
}
|
|
882
|
-
return {
|
|
883
|
-
currentTypeObject: fieldObject.typeObject
|
|
884
|
-
};
|
|
885
|
-
} else {
|
|
886
|
-
return onFieldNotFound({
|
|
887
|
-
currentTypeObject,
|
|
888
|
-
fieldId
|
|
889
|
-
});
|
|
890
|
-
}
|
|
891
|
-
}, {
|
|
892
|
-
currentTypeObject: typeObject
|
|
893
|
-
});
|
|
894
|
-
return reduced.currentTypeObject;
|
|
895
|
-
};
|
|
896
|
-
const UNKNOWN_EXPRESSION_TYPE = "unknown";
|
|
897
|
-
const getExpressionTypeInternal = ({
|
|
898
|
-
expression,
|
|
899
|
-
typeObject,
|
|
900
|
-
functionsMeta,
|
|
901
|
-
onFieldNotFound,
|
|
902
|
-
returnRefTypeInsteadOfId
|
|
903
|
-
}) => {
|
|
904
|
-
let result = null;
|
|
905
|
-
const visitor = createExpressionVisitor({
|
|
906
|
-
visitVariableExpression: function () {
|
|
907
|
-
result = UNKNOWN_EXPRESSION_TYPE;
|
|
908
|
-
},
|
|
909
|
-
visitFunctionCallExpression: function ([fnName, ...args]) {
|
|
910
|
-
const fnMeta = functionsMeta[fnName];
|
|
911
|
-
if (!fnMeta) {
|
|
912
|
-
throw new Error(`Function meta for "${fnName}" was not provided`);
|
|
913
|
-
}
|
|
914
|
-
const argTypes = args.map(arg => getExpressionTypeInternal({
|
|
915
|
-
expression: arg,
|
|
916
|
-
typeObject,
|
|
917
|
-
functionsMeta,
|
|
918
|
-
onFieldNotFound,
|
|
919
|
-
returnRefTypeInsteadOfId: firstLastFunctions.has(fnName) || fnName === "q/if" || fnName === "q/if-null" ? returnRefTypeInsteadOfId : false
|
|
920
|
-
}));
|
|
921
|
-
if (firstLastFunctions.has(fnName)) {
|
|
922
|
-
//assuming q/first has one argument and result type equals arg type.
|
|
923
|
-
//we need this trick to support 'returnRefTypeInsteadOfId' behavior for q/first and q/last.
|
|
924
|
-
result = argTypes[0];
|
|
925
|
-
} else if (fnName === "q/if") {
|
|
926
|
-
//we need this trick to support 'returnRefTypeInsteadOfId' behavior for q/if.
|
|
927
|
-
result = argTypes[1];
|
|
928
|
-
} else if (fnName === "q/if-null" && argTypes.some(x => !x.isPrimitive)) {
|
|
929
|
-
//we need this trick to support 'returnRefTypeInsteadOfId' behavior for q/if.
|
|
930
|
-
result = argTypes[0];
|
|
931
|
-
} else {
|
|
932
|
-
const overload = fnMeta.overloads.find(o => o["arg-types"].every((argType, index) => argTypes[index] === UNKNOWN_EXPRESSION_TYPE || argTypes[index] === argType || ["fibery/email", "fibery/url", "fibery/emoji", "fibery/color"].includes(argTypes[index]) && argType === "fibery/text"));
|
|
933
|
-
if (!overload) {
|
|
934
|
-
throw new Error(`No overload with args ${argTypes.join(",")} found for "${fnName}" in meta`);
|
|
935
|
-
}
|
|
936
|
-
result = overload["result-type"];
|
|
937
|
-
}
|
|
938
|
-
},
|
|
939
|
-
visitQueryExpression: expression => {
|
|
940
|
-
const {
|
|
941
|
-
"q/from": fromExpression,
|
|
942
|
-
"q/select": selectExpression
|
|
943
|
-
} = expression;
|
|
944
|
-
const fromTypeObject = getFieldAccessExpressionTypeObject({
|
|
945
|
-
expression: fromExpression,
|
|
946
|
-
typeObject,
|
|
947
|
-
onFieldNotFound,
|
|
948
|
-
returnRefTypeInsteadOfId
|
|
949
|
-
});
|
|
950
|
-
if (!fromTypeObject) {
|
|
951
|
-
result = null;
|
|
952
|
-
}
|
|
953
|
-
if (___default["default"].isPlainObject(selectExpression)) {
|
|
954
|
-
if (Object.values(selectExpression).length !== 1) {
|
|
955
|
-
throw new Error(`Can't determine type of query expression ${JSON.stringify(expression)}`);
|
|
956
|
-
}
|
|
957
|
-
result = getExpressionTypeInternal({
|
|
958
|
-
expression: Object.values(selectExpression)[0],
|
|
959
|
-
typeObject: fromTypeObject,
|
|
960
|
-
functionsMeta,
|
|
961
|
-
onFieldNotFound,
|
|
962
|
-
returnRefTypeInsteadOfId
|
|
963
|
-
});
|
|
964
|
-
} else {
|
|
965
|
-
result = getExpressionTypeInternal({
|
|
966
|
-
expression: selectExpression,
|
|
967
|
-
typeObject: fromTypeObject,
|
|
968
|
-
functionsMeta,
|
|
969
|
-
onFieldNotFound,
|
|
970
|
-
returnRefTypeInsteadOfId
|
|
971
|
-
});
|
|
972
|
-
}
|
|
973
|
-
},
|
|
974
|
-
visitFieldExpression(expression) {
|
|
975
|
-
const fieldAccessExpressionTypeObject = getFieldAccessExpressionTypeObject({
|
|
976
|
-
expression,
|
|
977
|
-
typeObject,
|
|
978
|
-
onFieldNotFound,
|
|
979
|
-
returnRefTypeInsteadOfId
|
|
980
|
-
});
|
|
981
|
-
result = fieldAccessExpressionTypeObject && fieldAccessExpressionTypeObject.name;
|
|
982
|
-
}
|
|
983
|
-
});
|
|
984
|
-
visitor.visitExpression(expression);
|
|
985
|
-
return result;
|
|
986
|
-
};
|
|
987
|
-
const getExpressionType = ({
|
|
988
|
-
expression,
|
|
989
|
-
typeObject,
|
|
990
|
-
functionsMeta,
|
|
991
|
-
onFieldNotFound = defaultGetExpressionTypeOnFieldNotFound,
|
|
992
|
-
returnRefTypeInsteadOfId = true
|
|
993
|
-
}) => {
|
|
994
|
-
return getExpressionTypeInternal({
|
|
995
|
-
expression,
|
|
996
|
-
typeObject,
|
|
997
|
-
functionsMeta,
|
|
998
|
-
onFieldNotFound,
|
|
999
|
-
returnRefTypeInsteadOfId
|
|
1000
|
-
});
|
|
1001
|
-
};
|
|
1002
|
-
|
|
1003
|
-
var visitors = {
|
|
1004
|
-
__proto__: null,
|
|
1005
|
-
replaceIdsWithNamesVisitor: replaceIdsWithNamesVisitor,
|
|
1006
|
-
replaceNamesWithIdsVisitor: replaceNamesWithIdsVisitor,
|
|
1007
|
-
deleteExpressionsWithNotFoundFieldsVisitor: deleteExpressionsWithNotFoundFieldsVisitor,
|
|
1008
|
-
expressionContainsAggregation: expressionContainsAggregation,
|
|
1009
|
-
UNKNOWN_EXPRESSION_TYPE: UNKNOWN_EXPRESSION_TYPE,
|
|
1010
|
-
getExpressionType: getExpressionType,
|
|
1011
|
-
fieldAccessVisitorTypeAware: fieldAccessVisitorTypeAware
|
|
1012
|
-
};
|
|
1013
|
-
|
|
1014
|
-
const getEntityQueryVariables = schema => {
|
|
1015
|
-
const grouped = ___default["default"].groupBy(schema.typeObjects.filter(x => x.isDomain), typeObject => typeObject.pluralTitle);
|
|
1016
|
-
return ___default["default"].flatten(Object.values(grouped).map(group => {
|
|
1017
|
-
return group.map(typeObject => ({
|
|
1018
|
-
typeObject,
|
|
1019
|
-
id: `entityQuery_${typeObject.id}`,
|
|
1020
|
-
title: group.length > 1 ? `${typeObject.pluralTitle} (${typeObject.nameParts.namespace})` : typeObject.pluralTitle,
|
|
1021
|
-
isCollection: true,
|
|
1022
|
-
description: `All Entities from "${typeObject.title}" Database`
|
|
1023
|
-
}));
|
|
1024
|
-
}));
|
|
1025
|
-
};
|
|
1026
|
-
|
|
1027
|
-
var contextVariables = {
|
|
1028
|
-
__proto__: null,
|
|
1029
|
-
getEntityQueryVariables: getEntityQueryVariables
|
|
1030
|
-
};
|
|
1031
|
-
|
|
1032
|
-
exports.contextVariables = contextVariables;
|
|
1033
|
-
exports.paramsPlaceholders = paramsPlaceholders;
|
|
1034
|
-
exports.utils = utils;
|
|
1035
|
-
exports.visitors = visitors;
|