@fibery/expression-utils 9.1.4 → 9.2.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.
@@ -127,7 +127,11 @@ const parseRelativeDatePlaceholder = placeholder => {
127
127
  let unit = relativeDatePlaceholderMatch[2];
128
128
  return {
129
129
  isStartOfInterval,
130
- unitForStart: fullMatch.startsWith("$start-of-day") || fullMatch.startsWith("$end-of-day") ? "day" : isStartOfInterval !== undefined ? unit : undefined,
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,
131
135
  amount: Number.parseInt(relativeDatePlaceholderMatch[1]),
132
136
  unit,
133
137
  isBeforeNow: relativeDatePlaceholderMatch[3] === "before-now",
@@ -249,6 +253,11 @@ const assertIsValidExpression = expression => {
249
253
  });
250
254
  trace.assert(expression.length > 0, "empty expression does not make any sense");
251
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"];
252
261
  const dateRangeFunctions = new Set(["q/start", "q/end"]);
253
262
  const firstLastFunctions = new Set(["q/first", "q/last"]);
254
263
  const collectionOps = new Set(["q/count", "q/count-distinct", "q/sum", "q/min", "q/max", "q/avg", "q/join", "q/first", "q/last"]);
@@ -313,6 +322,38 @@ const collectFieldExpressions = (memo, expression) => {
313
322
  throw new NotImplementedError(expression, "expression");
314
323
  }
315
324
  };
325
+ const getFieldObjectsByFieldExpression = ({
326
+ typeObject,
327
+ expression
328
+ }) => {
329
+ assertIsValidExpression(expression);
330
+ const fieldObjects = [];
331
+ let currentTypeObject = typeObject;
332
+ for (const fieldOrMultiFieldAccess of expression) {
333
+ if (isMultiFieldAccess(fieldOrMultiFieldAccess)) {
334
+ const [multiField, type] = fieldOrMultiFieldAccess;
335
+ const fieldObject = currentTypeObject.fieldObjectsByName[multiField];
336
+ fieldObjects.push(fieldObject);
337
+ const foundField = fieldObject.multiRelatedFieldObjects.find(f => f.holderType === type);
338
+ trace.assert(foundField, "incorrect expression for multi-field");
339
+ currentTypeObject = foundField.holderTypeObject;
340
+ } else {
341
+ const fieldObject = currentTypeObject.fieldObjectsByName[fieldOrMultiFieldAccess];
342
+ fieldObjects.push(fieldObject);
343
+ currentTypeObject = fieldObject.typeObject;
344
+ }
345
+ }
346
+ return fieldObjects;
347
+ };
348
+ const getFieldObjectByFieldExpression = (x // TODO: review types. using type assertion now to avoid rewriting half of app
349
+ ) => ___default["default"].last(getFieldObjectsByFieldExpression(x));
350
+ const getFieldObjects = (expression, typeObject) => {
351
+ const fieldExpression = extractFieldExpressions(expression)[0];
352
+ return getFieldObjectsByFieldExpression({
353
+ typeObject,
354
+ expression: fieldExpression
355
+ });
356
+ };
316
357
 
317
358
  /** @deprecated
318
359
  * This method checks few expression forms, that we do not generate on frontend anymore(field-access shortcut, direct value as parameter).
@@ -387,6 +428,11 @@ const createExpressionVisitor = visitor => {
387
428
  var utils = {
388
429
  __proto__: null,
389
430
  assertIsValidExpression: assertIsValidExpression,
431
+ textTypes: textTypes,
432
+ dateTypes: dateTypes,
433
+ dateRangeTypes: dateRangeTypes,
434
+ convertableDateTypes: convertableDateTypes,
435
+ numberTypes: numberTypes,
390
436
  dateRangeFunctions: dateRangeFunctions,
391
437
  firstLastFunctions: firstLastFunctions,
392
438
  logicalOperators: logicalOperators,
@@ -405,6 +451,9 @@ var utils = {
405
451
  isMultiFieldExpression: isMultiFieldExpression,
406
452
  isFieldExpression: isFieldExpression,
407
453
  isQueryExpression: isQueryExpression,
454
+ getFieldObjectsByFieldExpression: getFieldObjectsByFieldExpression,
455
+ getFieldObjectByFieldExpression: getFieldObjectByFieldExpression,
456
+ getFieldObjects: getFieldObjects,
408
457
  extractFieldExpressions: extractFieldExpressions,
409
458
  createExpressionVisitor: createExpressionVisitor
410
459
  };
@@ -126,7 +126,11 @@ const parseRelativeDatePlaceholder = placeholder => {
126
126
  let unit = relativeDatePlaceholderMatch[2];
127
127
  return {
128
128
  isStartOfInterval,
129
- unitForStart: fullMatch.startsWith("$start-of-day") || fullMatch.startsWith("$end-of-day") ? "day" : isStartOfInterval !== undefined ? unit : undefined,
129
+ unitForStart:
130
+ // Usually the "start" unit is the same as the unit for relative date calculation.
131
+ // e.g. when we calculate the date "1 week ago", we want the beginning of the previous week.
132
+ // But sometimes they are different. We have hardcoded "day" for now, but this can be extended to any unit.
133
+ fullMatch.startsWith("$start-of-day") || fullMatch.startsWith("$end-of-day") ? "day" : isStartOfInterval !== undefined ? unit : undefined,
130
134
  amount: Number.parseInt(relativeDatePlaceholderMatch[1]),
131
135
  unit,
132
136
  isBeforeNow: relativeDatePlaceholderMatch[3] === "before-now",
package/lib/utils.js CHANGED
@@ -23,6 +23,11 @@ const assertIsValidExpression = expression => {
23
23
  });
24
24
  trace.assert(expression.length > 0, "empty expression does not make any sense");
25
25
  };
26
+ const textTypes = ["fibery/text", "fibery/email", "fibery/url", "fibery/emoji"];
27
+ const dateTypes = ["fibery/date", "fibery/date-time"];
28
+ const dateRangeTypes = ["fibery/date-range", "fibery/date-time-range"];
29
+ const convertableDateTypes = ["fibery/date", "fibery/date-range"];
30
+ const numberTypes = ["fibery/int", "fibery/decimal"];
26
31
  const dateRangeFunctions = new Set(["q/start", "q/end"]);
27
32
  const firstLastFunctions = new Set(["q/first", "q/last"]);
28
33
  const collectionOps = new Set(["q/count", "q/count-distinct", "q/sum", "q/min", "q/max", "q/avg", "q/join", "q/first", "q/last"]);
@@ -87,6 +92,38 @@ const collectFieldExpressions = (memo, expression) => {
87
92
  throw new NotImplementedError(expression, "expression");
88
93
  }
89
94
  };
95
+ const getFieldObjectsByFieldExpression = ({
96
+ typeObject,
97
+ expression
98
+ }) => {
99
+ assertIsValidExpression(expression);
100
+ const fieldObjects = [];
101
+ let currentTypeObject = typeObject;
102
+ for (const fieldOrMultiFieldAccess of expression) {
103
+ if (isMultiFieldAccess(fieldOrMultiFieldAccess)) {
104
+ const [multiField, type] = fieldOrMultiFieldAccess;
105
+ const fieldObject = currentTypeObject.fieldObjectsByName[multiField];
106
+ fieldObjects.push(fieldObject);
107
+ const foundField = fieldObject.multiRelatedFieldObjects.find(f => f.holderType === type);
108
+ trace.assert(foundField, "incorrect expression for multi-field");
109
+ currentTypeObject = foundField.holderTypeObject;
110
+ } else {
111
+ const fieldObject = currentTypeObject.fieldObjectsByName[fieldOrMultiFieldAccess];
112
+ fieldObjects.push(fieldObject);
113
+ currentTypeObject = fieldObject.typeObject;
114
+ }
115
+ }
116
+ return fieldObjects;
117
+ };
118
+ const getFieldObjectByFieldExpression = (x // TODO: review types. using type assertion now to avoid rewriting half of app
119
+ ) => ___default["default"].last(getFieldObjectsByFieldExpression(x));
120
+ const getFieldObjects = (expression, typeObject) => {
121
+ const fieldExpression = extractFieldExpressions(expression)[0];
122
+ return getFieldObjectsByFieldExpression({
123
+ typeObject,
124
+ expression: fieldExpression
125
+ });
126
+ };
90
127
 
91
128
  /** @deprecated
92
129
  * This method checks few expression forms, that we do not generate on frontend anymore(field-access shortcut, direct value as parameter).
@@ -159,11 +196,17 @@ const createExpressionVisitor = visitor => {
159
196
  };
160
197
 
161
198
  exports.assertIsValidExpression = assertIsValidExpression;
199
+ exports.convertableDateTypes = convertableDateTypes;
162
200
  exports.createExpressionVisitor = createExpressionVisitor;
163
201
  exports.dateRangeFunctions = dateRangeFunctions;
202
+ exports.dateRangeTypes = dateRangeTypes;
203
+ exports.dateTypes = dateTypes;
164
204
  exports.extractFieldExpressions = extractFieldExpressions;
165
205
  exports.firstLastFunctions = firstLastFunctions;
166
206
  exports.fromRootKeyword = fromRootKeyword;
207
+ exports.getFieldObjectByFieldExpression = getFieldObjectByFieldExpression;
208
+ exports.getFieldObjects = getFieldObjects;
209
+ exports.getFieldObjectsByFieldExpression = getFieldObjectsByFieldExpression;
167
210
  exports.isAccessFunctionExpression = isAccessFunctionExpression;
168
211
  exports.isBinaryExpression = isBinaryExpression;
169
212
  exports.isCollectionFunctionExpression = isCollectionFunctionExpression;
@@ -178,4 +221,6 @@ exports.isQueryExpression = isQueryExpression;
178
221
  exports.isVariableExpression = isVariableExpression;
179
222
  exports.logicalOperators = logicalOperators;
180
223
  exports.mathOperators = mathOperators;
224
+ exports.numberTypes = numberTypes;
181
225
  exports.relationalOperators = relationalOperators;
226
+ exports.textTypes = textTypes;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fibery/expression-utils",
3
- "version": "9.1.4",
3
+ "version": "9.2.0",
4
4
  "description": "utils for working with fibery api expressions",
5
5
  "exports": {
6
6
  ".": "./lib/expression-utils.js",
@@ -26,7 +26,7 @@
26
26
  "dependencies": {
27
27
  "lodash": "4.17.21",
28
28
  "moment": "2.29.4",
29
- "@fibery/helpers": "1.3.0"
29
+ "@fibery/helpers": "1.3.2"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@babel/core": "7.23.9",
@@ -34,11 +34,11 @@
34
34
  "jest": "27.5.1",
35
35
  "jest-junit": "13.0.0",
36
36
  "microbundle": "0.15.1",
37
- "@fibery/eslint-config": "8.6.0",
38
- "@fibery/babel-preset": "7.4.0"
37
+ "@fibery/babel-preset": "7.4.0",
38
+ "@fibery/eslint-config": "8.6.1"
39
39
  },
40
40
  "peerDependencies": {
41
- "@fibery/schema": "10.2.5"
41
+ "@fibery/schema": "10.2.7"
42
42
  },
43
43
  "jest": {
44
44
  "testEnvironment": "node",
package/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  // eslint-disable-next-line import/no-extraneous-dependencies
2
- import {Schema, TypeObject, FieldObject} from "@fibery/schema";
2
+ import {FieldObject, Schema, TypeObject} from "@fibery/schema";
3
3
 
4
4
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
5
  export type $TSFixMe = any;
@@ -61,6 +61,14 @@ declare module "@fibery/expression-utils" {
61
61
  firstLastFunctions: Set<string>;
62
62
  isQueryExpression: (expression: $TSFixMe) => boolean;
63
63
  isVariableExpression: (expression: $TSFixMe) => boolean;
64
+ isFunctionCallExpression: (expression: $TSFixMe) => boolean;
65
+ getFieldObjectByFieldExpression: (x: {typeObject: TypeObject; expression: Expression}) => FieldObject | undefined;
66
+ isFieldExpression: (expression: $TSFixMe) => boolean;
67
+ isBinaryExpression: (expression: $TSFixMe) => boolean;
68
+ isMultiFieldAccess: (expression: $TSFixMe) => boolean;
69
+ logicalOperators: Set<string>;
70
+ relationalOperators: Set<string>;
71
+ mathOperators: Set<string>;
64
72
  };
65
73
  export const contextVariables: {
66
74
  getEntityQueryVariables: (
@@ -69,6 +77,7 @@ declare module "@fibery/expression-utils" {
69
77
  };
70
78
  export const paramsPlaceholders: {
71
79
  formulaTodayDateParamPlaceholder: string;
80
+ formulaNowDateTimeParamPlaceholder: string;
72
81
  dynamicFilterParamPrefix: string;
73
82
 
74
83
  isDynamicFilterParam(paramValue: string): boolean;