@fibery/expression-utils 9.4.1 → 9.5.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.
@@ -0,0 +1,17 @@
1
+ import { $TSFixMe } from "../tsfixme";
2
+ import { TypeObject } from "@fibery/schema";
3
+ import { Expression, Select, SubQuery } from "../types";
4
+ type ExpressionToMatch = SubQuery | Select | Expression | string | undefined;
5
+ export type PatternMatches = {
6
+ matchType: ":expression-match-type/param";
7
+ value: $TSFixMe;
8
+ } | {
9
+ matchType: ":expression-match-type/expression";
10
+ value: Expression;
11
+ };
12
+ export type PatternMatchResult = {
13
+ matchSuccess: boolean;
14
+ matches: Array<PatternMatches>;
15
+ };
16
+ export declare const doPatternMatch: (expression: ExpressionToMatch, params: $TSFixMe, pattern: $TSFixMe, typeObject: TypeObject) => PatternMatchResult;
17
+ export {};
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.doPatternMatch = void 0;
7
+ const utils_1 = require("../utils");
8
+ const lodash_1 = __importDefault(require("lodash"));
9
+ const matchSelectClause = (selectExpression, params, selectPattern, typeObject) => {
10
+ if (selectExpression && lodash_1.default.isPlainObject(selectExpression) && lodash_1.default.isPlainObject(selectPattern)) {
11
+ if (Object.keys(selectExpression).length !== Object.keys(selectPattern).length) {
12
+ return { matchSuccess: false, matches: [] };
13
+ }
14
+ return Object.entries(selectExpression).reduce((acc, [key, value]) => {
15
+ const { matchSuccess, matches } = (0, exports.doPatternMatch)(value, params, selectPattern[key], typeObject);
16
+ return {
17
+ matchSuccess: acc.matchSuccess && matchSuccess,
18
+ matches: acc.matches.concat(matches),
19
+ };
20
+ }, { matchSuccess: true, matches: [] });
21
+ }
22
+ else {
23
+ return (0, exports.doPatternMatch)(selectExpression, params, selectPattern, typeObject);
24
+ }
25
+ };
26
+ const matchQuery = (expression, params, pattern, typeObject) => {
27
+ const fromExpression = expression["q/from"];
28
+ if (!(0, utils_1.isFieldExpressionValid)({ typeObject, expression: fromExpression })) {
29
+ return {
30
+ matchSuccess: false,
31
+ matches: [],
32
+ };
33
+ }
34
+ const fromTypeObject = (0, utils_1.getFieldObjectByFieldExpression)({
35
+ typeObject,
36
+ expression: fromExpression,
37
+ }).typeObject;
38
+ const { matchSuccess: fromMatchSuccess, matches: fromMatches } = (0, exports.doPatternMatch)(fromExpression, params, pattern["q/from"], typeObject);
39
+ const { matchSuccess: selectMatchSuccess, matches: selectMatches } = matchSelectClause(expression["q/select"], params, pattern["q/select"], fromTypeObject);
40
+ const limitMatchSuccess = pattern["q/limit"] === expression["q/limit"];
41
+ const { matchSuccess: whereMatchSuccess, matches: whereMatches } = (0, exports.doPatternMatch)(expression["q/where"], params, pattern["q/where"], fromTypeObject);
42
+ return {
43
+ matchSuccess: fromMatchSuccess && selectMatchSuccess && limitMatchSuccess && whereMatchSuccess,
44
+ matches: [...fromMatches, ...whereMatches, ...selectMatches],
45
+ };
46
+ };
47
+ const matchExpression = (expressionPlaceholder, expression, typeObject) => {
48
+ if (!lodash_1.default.isString(expression) && !lodash_1.default.isArray(expression)) {
49
+ return { matchSuccess: false, matches: [] };
50
+ }
51
+ return {
52
+ matchSuccess: Boolean(expressionPlaceholder.matchFn(expression, typeObject)),
53
+ matches: [
54
+ {
55
+ matchType: ":expression-match-type/expression",
56
+ value: lodash_1.default.isString(expression) ? [expression] : expression,
57
+ },
58
+ ],
59
+ };
60
+ };
61
+ const doPatternMatch = (expression, params, pattern, typeObject) => {
62
+ if (expression === pattern) {
63
+ return { matchSuccess: true, matches: [] };
64
+ }
65
+ if (pattern.id === ":expression-pattern/expression-placeholder") {
66
+ return matchExpression(pattern, expression, typeObject);
67
+ }
68
+ if (expression && !lodash_1.default.isString(expression) && Object.hasOwn(expression, "q/from") && pattern["q/from"]) {
69
+ return matchQuery(expression, params, pattern, typeObject);
70
+ }
71
+ if (!(lodash_1.default.isArray(expression) && lodash_1.default.isArray(pattern))) {
72
+ return { matchSuccess: false, matches: [] };
73
+ }
74
+ const zipped = lodash_1.default.zipWith(expression, pattern, (expressionNode, patternNode) => {
75
+ if (!patternNode) {
76
+ return { matchSuccess: false, matches: [] };
77
+ }
78
+ else if (lodash_1.default.isString(patternNode)) {
79
+ return { matchSuccess: expressionNode === patternNode, matches: [] };
80
+ }
81
+ else if (lodash_1.default.isArray(patternNode)) {
82
+ return (0, exports.doPatternMatch)(expressionNode, params, patternNode, typeObject);
83
+ }
84
+ else if (patternNode.id === ":expression-pattern/expression-placeholder") {
85
+ return matchExpression(patternNode, expressionNode, typeObject);
86
+ }
87
+ else if (patternNode.id === ":expression-pattern/param-placeholder" ||
88
+ patternNode.id === ":expression-pattern/constant-placeholder") {
89
+ const shouldReturnValue = patternNode.id === ":expression-pattern/param-placeholder";
90
+ if (lodash_1.default.isString(expressionNode) && (0, utils_1.isVariableExpression)(expressionNode)) {
91
+ return {
92
+ matchSuccess: patternNode.matchFn(params[expressionNode]),
93
+ matches: shouldReturnValue
94
+ ? [
95
+ {
96
+ matchType: ":expression-match-type/param",
97
+ value: params[expressionNode],
98
+ },
99
+ ]
100
+ : [],
101
+ };
102
+ }
103
+ else {
104
+ return {
105
+ matchSuccess: patternNode.matchFn(expressionNode),
106
+ matches: shouldReturnValue
107
+ ? [
108
+ {
109
+ matchType: ":expression-match-type/param",
110
+ value: expressionNode,
111
+ },
112
+ ]
113
+ : [],
114
+ };
115
+ }
116
+ }
117
+ else if (patternNode["q/from"] && lodash_1.default.isObject(expressionNode) && "q/from" in expressionNode) {
118
+ return matchQuery(expressionNode, params, patternNode, typeObject);
119
+ }
120
+ else {
121
+ return { matchSuccess: false, matches: [] };
122
+ }
123
+ });
124
+ return zipped.reduce(({ matchSuccess: accMatchSuccess, matches: accMatches }, { matchSuccess, matches }) => {
125
+ if (!matchSuccess || !accMatchSuccess) {
126
+ return { matchSuccess: false, matches: [] };
127
+ }
128
+ return {
129
+ matchSuccess: true,
130
+ matches: matches ? [...accMatches, ...matches] : accMatches,
131
+ };
132
+ }, { matchSuccess: true, matches: [] });
133
+ };
134
+ exports.doPatternMatch = doPatternMatch;
@@ -0,0 +1,59 @@
1
+ export namespace anyExpressionPlaceholder {
2
+ let id: string;
3
+ function matchFn(): boolean;
4
+ }
5
+ export namespace idFieldPlaceholder {
6
+ let id_1: string;
7
+ export { id_1 as id };
8
+ export { matchFn };
9
+ }
10
+ export namespace basicFieldPlaceholder { }
11
+ export namespace textFieldPlaceholder {
12
+ let id_2: string;
13
+ export { id_2 as id };
14
+ export function matchFn_2(expression: any, typeObject: any): any;
15
+ export { matchFn_2 as matchFn };
16
+ }
17
+ export namespace numberFieldPlaceholder { }
18
+ export namespace dateFieldPlaceholder { }
19
+ export namespace dateTimeFieldPlaceholder { }
20
+ export namespace boolFieldPlaceholder { }
21
+ export namespace locationFieldPlaceholder { }
22
+ export namespace referenceCollectionFieldPlaceholder { }
23
+ export namespace referenceExpressionPlaceholder {
24
+ let id_3: string;
25
+ export { id_3 as id };
26
+ export { matchFn };
27
+ }
28
+ export namespace referenceCollectionExpressionPlaceholder { }
29
+ export namespace dateOrDateRangeExpressionPlaceholder {
30
+ let id_4: string;
31
+ export { id_4 as id };
32
+ export function matchFn_4(expression: any, typeObject: any): any;
33
+ export { matchFn_4 as matchFn };
34
+ }
35
+ export namespace dateTimeOrDateTimeRangeExpressionPlaceholder { }
36
+ export namespace anyDateExpressionPlaceholder {
37
+ let id_5: string;
38
+ export { id_5 as id };
39
+ export function matchFn_5(expression: any, typeObject: any): any;
40
+ export { matchFn_5 as matchFn };
41
+ }
42
+ export function getParamPlaceholder(matchFn?: (_x: any) => boolean): {
43
+ id: string;
44
+ matchFn: (_x: any) => boolean;
45
+ };
46
+ export function getConstantPlaceholder(value: any): {
47
+ id: string;
48
+ value: any;
49
+ matchFn: (x: any) => boolean;
50
+ };
51
+ export namespace referenceTitleOrRankExpressionPlaceholder {
52
+ let id_6: string;
53
+ export { id_6 as id };
54
+ export function matchFn_6(expression: any, typeObject: any): boolean;
55
+ export { matchFn_6 as matchFn };
56
+ }
57
+ declare function matchFn_1(expression: any, typeObject: any): any;
58
+ declare function matchFn_3(expression: any, typeObject: any): boolean;
59
+ export {};
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.referenceTitleOrRankExpressionPlaceholder = exports.getConstantPlaceholder = exports.getParamPlaceholder = exports.anyDateExpressionPlaceholder = exports.dateTimeOrDateTimeRangeExpressionPlaceholder = exports.dateOrDateRangeExpressionPlaceholder = exports.referenceCollectionExpressionPlaceholder = exports.referenceExpressionPlaceholder = exports.referenceCollectionFieldPlaceholder = exports.locationFieldPlaceholder = exports.boolFieldPlaceholder = exports.dateTimeFieldPlaceholder = exports.dateFieldPlaceholder = exports.numberFieldPlaceholder = exports.textFieldPlaceholder = exports.basicFieldPlaceholder = exports.idFieldPlaceholder = exports.anyExpressionPlaceholder = void 0;
7
+ const lodash_1 = __importDefault(require("lodash"));
8
+ const utils_1 = require("../utils");
9
+ const getFieldPlaceholder = (fieldObjectMatchFn) => {
10
+ const matchFn = (expression, typeObject) => {
11
+ if (lodash_1.default.isString(expression)) {
12
+ return typeObject.fieldObjectsByName.hasOwnProperty(expression)
13
+ ? fieldObjectMatchFn(typeObject.fieldObjectsByName[expression], [typeObject.fieldObjectsByName[expression]])
14
+ : false;
15
+ }
16
+ if (!(0, utils_1.isFieldExpression)(expression)) {
17
+ return false;
18
+ }
19
+ if (!(0, utils_1.isFieldExpressionValid)({ typeObject, expression })) {
20
+ return false;
21
+ }
22
+ if (expression.length === 0) {
23
+ return false;
24
+ }
25
+ const fieldObjects = (0, utils_1.getFieldObjectsByFieldExpression)({
26
+ typeObject,
27
+ expression,
28
+ });
29
+ if (fieldObjects.length > 1 && fieldObjects[fieldObjects.length - 2].type === "Collaboration~Documents/Document") {
30
+ return fieldObjectMatchFn(fieldObjects[fieldObjects.length - 1], fieldObjects);
31
+ }
32
+ return fieldObjectMatchFn(fieldObjects[fieldObjects.length - 1], fieldObjects);
33
+ };
34
+ return { id: ":expression-pattern/expression-placeholder", matchFn };
35
+ };
36
+ const getReferenceExpressionPlaceholder = (isReferenceCollection) => {
37
+ const matchFn = (expression, typeObject) => {
38
+ if (!(0, utils_1.isFieldExpression)(expression)) {
39
+ return false;
40
+ }
41
+ if (!(0, utils_1.isFieldExpressionValid)({ typeObject, expression })) {
42
+ return false;
43
+ }
44
+ if (expression.length < 2) {
45
+ return false;
46
+ }
47
+ const fieldObjects = (0, utils_1.getFieldObjectsByFieldExpression)({
48
+ typeObject,
49
+ expression,
50
+ });
51
+ if (fieldObjects.length < 2) {
52
+ return false;
53
+ }
54
+ const matchesReferenceKind = isReferenceCollection
55
+ ? fieldObjects[fieldObjects.length - 2].isCollection
56
+ : !fieldObjects[fieldObjects.length - 2].isCollection;
57
+ return (!fieldObjects[fieldObjects.length - 2].typeObject.isPrimitive &&
58
+ matchesReferenceKind &&
59
+ fieldObjects[fieldObjects.length - 1].isId);
60
+ };
61
+ return { id: ":expression-pattern/expression-placeholder", matchFn };
62
+ };
63
+ const getDateExpressionPlaceholder = (dateFieldMatchFn) => ({
64
+ id: ":expression-pattern/expression-placeholder",
65
+ matchFn: (expression, typeObject) => {
66
+ return (0, utils_1.isDateRangeFunctionExpression)(expression)
67
+ ? dateFieldMatchFn(expression[1], typeObject)
68
+ : dateFieldMatchFn(expression, typeObject);
69
+ },
70
+ });
71
+ exports.anyExpressionPlaceholder = {
72
+ id: ":expression-pattern/expression-placeholder",
73
+ matchFn: () => true,
74
+ };
75
+ exports.idFieldPlaceholder = getFieldPlaceholder((fieldObject, fieldObjects) => fieldObjects.length === 1 && fieldObject.isId);
76
+ exports.basicFieldPlaceholder = getFieldPlaceholder((fieldObject) => {
77
+ return fieldObject.typeObject.isPrimitive === true;
78
+ });
79
+ exports.textFieldPlaceholder = {
80
+ id: ":expression-pattern/expression-placeholder",
81
+ matchFn: (expression, typeObject) => {
82
+ const isTextFieldObjectExpression = getFieldPlaceholder((fieldObject) => fieldObject.type === "fibery/text" || fieldObject.type === "fibery/email" || fieldObject.type === "fibery/url").matchFn(expression, typeObject);
83
+ const isSnippetExpression = lodash_1.default.last(expression) === "Collaboration~Documents/Snippet";
84
+ return isTextFieldObjectExpression || isSnippetExpression;
85
+ },
86
+ };
87
+ exports.numberFieldPlaceholder = getFieldPlaceholder((fieldObject) => fieldObject.type === "fibery/int" || fieldObject.type === "fibery/decimal");
88
+ exports.dateFieldPlaceholder = getFieldPlaceholder((fieldObject) => {
89
+ return (0, utils_1.isDateType)(fieldObject.type);
90
+ });
91
+ exports.dateTimeFieldPlaceholder = getFieldPlaceholder((fieldObject) => {
92
+ return (0, utils_1.isDateTimeType)(fieldObject.type);
93
+ });
94
+ exports.boolFieldPlaceholder = getFieldPlaceholder((fieldObject) => fieldObject.type === "fibery/bool");
95
+ exports.locationFieldPlaceholder = getFieldPlaceholder((fieldObject) => fieldObject.type === "fibery/location");
96
+ exports.referenceCollectionFieldPlaceholder = getFieldPlaceholder((fieldObject) => {
97
+ return !fieldObject.typeObject.isPrimitive && fieldObject.isCollection;
98
+ });
99
+ exports.referenceExpressionPlaceholder = getReferenceExpressionPlaceholder(false);
100
+ exports.referenceCollectionExpressionPlaceholder = getReferenceExpressionPlaceholder(true);
101
+ exports.dateOrDateRangeExpressionPlaceholder = getDateExpressionPlaceholder(exports.dateFieldPlaceholder.matchFn);
102
+ exports.dateTimeOrDateTimeRangeExpressionPlaceholder = getDateExpressionPlaceholder(exports.dateTimeFieldPlaceholder.matchFn);
103
+ exports.anyDateExpressionPlaceholder = {
104
+ id: ":expression-pattern/expression-placeholder",
105
+ matchFn: (expression, typeObject) => exports.dateOrDateRangeExpressionPlaceholder.matchFn(expression, typeObject) ||
106
+ exports.dateTimeOrDateTimeRangeExpressionPlaceholder.matchFn(expression, typeObject),
107
+ };
108
+ const getParamPlaceholder = (matchFn = (_x) => true) => ({
109
+ id: ":expression-pattern/param-placeholder",
110
+ matchFn,
111
+ });
112
+ exports.getParamPlaceholder = getParamPlaceholder;
113
+ const getConstantPlaceholder = (value) => ({
114
+ id: ":expression-pattern/constant-placeholder",
115
+ value,
116
+ matchFn: (x) => x === value,
117
+ });
118
+ exports.getConstantPlaceholder = getConstantPlaceholder;
119
+ // Infinite relation path not supported for Sorts right now.
120
+ exports.referenceTitleOrRankExpressionPlaceholder = {
121
+ id: ":expression-pattern/expression-placeholder",
122
+ matchFn: (expression, typeObject) => {
123
+ if (!(0, utils_1.isFieldExpression)(expression)) {
124
+ return false;
125
+ }
126
+ if (!(0, utils_1.isFieldExpressionValid)({ typeObject, expression })) {
127
+ return false;
128
+ }
129
+ if (expression.length !== 2) {
130
+ return false;
131
+ }
132
+ const fieldObjects = (0, utils_1.getFieldObjectsByFieldExpression)({
133
+ typeObject,
134
+ expression,
135
+ });
136
+ if (fieldObjects.length !== 2) {
137
+ return false;
138
+ }
139
+ return (!fieldObjects[0].typeObject.isPrimitive &&
140
+ !fieldObjects[0].isCollection &&
141
+ (fieldObjects[1].isTitle || fieldObjects[1] === fieldObjects[1].holderTypeObject.rankFieldObject));
142
+ },
143
+ };
@@ -0,0 +1,4 @@
1
+ export function convertToExpression(pattern: any, filterExpression: any, value: any, getNextParamName: any): {
2
+ expression: any;
3
+ params: {};
4
+ };
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.convertToExpression = void 0;
7
+ const lodash_1 = __importDefault(require("lodash"));
8
+ const params_placeholders_1 = require("../params-placeholders");
9
+ const convertToExpression = (pattern, filterExpression, value, getNextParamName) => {
10
+ let params = {};
11
+ const expression = pattern.map((patternNode) => {
12
+ if (patternNode.id === ":expression-pattern/expression-placeholder") {
13
+ return filterExpression;
14
+ }
15
+ else if (patternNode.id === ":expression-pattern/param-placeholder") {
16
+ const isPlaceholder = params_placeholders_1.paramsPlaceholdersLookup[value] || (0, params_placeholders_1.parseRelativeDatePlaceholder)(value) !== null;
17
+ const paramName = isPlaceholder ? value : getNextParamName();
18
+ params[paramName] = value;
19
+ return paramName;
20
+ }
21
+ else if (patternNode.id === ":expression-pattern/constant-placeholder") {
22
+ const paramName = getNextParamName();
23
+ params[paramName] = patternNode.value;
24
+ return paramName;
25
+ }
26
+ else if (lodash_1.default.isArray(patternNode)) {
27
+ const { expression, params: innerParams } = (0, exports.convertToExpression)(patternNode, filterExpression, value, getNextParamName);
28
+ params = { ...params, ...innerParams };
29
+ return expression;
30
+ }
31
+ else if (patternNode["q/from"]) {
32
+ // Note: very naive implementation here
33
+ const { expression: selectExpression, params: selectParams } = (0, exports.convertToExpression)(patternNode["q/select"], filterExpression, value, getNextParamName);
34
+ const { expression: whereExpression, params: whereParams } = (0, exports.convertToExpression)(patternNode["q/where"], filterExpression, value, getNextParamName);
35
+ params = { ...params, ...selectParams, ...whereParams };
36
+ return {
37
+ "q/from": filterExpression,
38
+ "q/select": selectExpression,
39
+ "q/where": whereExpression,
40
+ "q/limit": patternNode["q/limit"],
41
+ };
42
+ }
43
+ else {
44
+ return patternNode;
45
+ }
46
+ });
47
+ return { expression, params };
48
+ };
49
+ exports.convertToExpression = convertToExpression;
@@ -0,0 +1,24 @@
1
+ import { $TSFixMe } from "../tsfixme";
2
+ import { TypeObject } from "@fibery/schema";
3
+ import { Expression } from "../types";
4
+ export type Operator = {
5
+ id: string;
6
+ type: string;
7
+ title: string;
8
+ pattern?: $TSFixMe;
9
+ customMatch?: (where: Expression, params: $TSFixMe, typeObject: TypeObject) => {
10
+ matchSuccess: boolean;
11
+ value?: $TSFixMe;
12
+ expression?: Expression;
13
+ };
14
+ customConvertToWhereExpression?: (expression: $TSFixMe, value: $TSFixMe, getNextParamName: $TSFixMe) => $TSFixMe;
15
+ };
16
+ export type ExpressionToFilterBy = {
17
+ title?: string;
18
+ icon?: string;
19
+ itemExpressions: Array<{
20
+ expression: Expression;
21
+ type: string;
22
+ }>;
23
+ calculateRelationFieldExpressions?: () => ExpressionToFilterBy[];
24
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -11,6 +11,8 @@ export declare const firstLastFunctions: Set<string>;
11
11
  export declare const logicalOperators: Set<string>;
12
12
  export declare const relationalOperators: Set<string>;
13
13
  export declare const mathOperators: Set<string>;
14
+ export declare const isDateType: (type: string) => type is "fibery/date" | "fibery/date-range";
15
+ export declare const isDateTimeType: (type: string) => type is "fibery/date-time" | "fibery/date-time-range";
14
16
  export declare const isFunctionCallExpression: (expression: Expression | SubQuery | OrderBy | string) => boolean;
15
17
  export declare const fromRootKeyword = "q/from-root";
16
18
  export declare const isFromRootFieldExpression: (expression: Expression | SubQuery | OrderBy | string) => boolean;
@@ -28,6 +30,10 @@ export declare const getFieldObjectsByFieldExpression: ({ typeObject, expression
28
30
  typeObject: TypeObject;
29
31
  expression: Expression;
30
32
  }) => FieldObject[];
33
+ export declare const isFieldExpressionValid: ({ typeObject, expression }: {
34
+ typeObject: TypeObject;
35
+ expression: Expression;
36
+ }) => boolean;
31
37
  export declare const getFieldObjectByFieldExpression: (x: {
32
38
  typeObject: TypeObject;
33
39
  expression: Expression;
package/lib/src/utils.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.createExpressionVisitor = exports.extractFieldExpressions = exports.getFieldObjects = exports.getFieldObjectByFieldExpression = exports.getFieldObjectsByFieldExpression = exports.isQueryExpression = exports.isFieldExpression = exports.isMultiFieldExpression = exports.isMultiFieldAccess = exports.isVariableExpression = exports.isNaryExpression = exports.isBinaryExpression = exports.isAccessFunctionExpression = exports.isCollectionFunctionExpression = exports.isDateRangeFunctionExpression = exports.isFromRootFieldExpression = exports.fromRootKeyword = exports.isFunctionCallExpression = exports.mathOperators = exports.relationalOperators = exports.logicalOperators = exports.firstLastFunctions = exports.dateRangeFunctions = exports.numberTypes = exports.convertableDateTypes = exports.dateRangeTypes = exports.dateTypes = exports.textTypes = exports.assertIsValidExpression = void 0;
6
+ exports.createExpressionVisitor = exports.extractFieldExpressions = exports.getFieldObjects = exports.getFieldObjectByFieldExpression = exports.isFieldExpressionValid = exports.getFieldObjectsByFieldExpression = exports.isQueryExpression = exports.isFieldExpression = exports.isMultiFieldExpression = exports.isMultiFieldAccess = exports.isVariableExpression = exports.isNaryExpression = exports.isBinaryExpression = exports.isAccessFunctionExpression = exports.isCollectionFunctionExpression = exports.isDateRangeFunctionExpression = exports.isFromRootFieldExpression = exports.fromRootKeyword = exports.isFunctionCallExpression = exports.isDateTimeType = exports.isDateType = exports.mathOperators = exports.relationalOperators = exports.logicalOperators = exports.firstLastFunctions = exports.dateRangeFunctions = exports.numberTypes = exports.convertableDateTypes = exports.dateRangeTypes = exports.dateTypes = exports.textTypes = exports.assertIsValidExpression = void 0;
7
7
  const trace_1 = require("@fibery/helpers/utils/trace");
8
8
  const lodash_1 = __importDefault(require("lodash"));
9
9
  const errors_1 = require("./errors");
@@ -59,6 +59,10 @@ const binaryOperations = new Set([
59
59
  exports.logicalOperators = new Set(["and", "or", "q/and", "q/or"]);
60
60
  exports.relationalOperators = new Set(["=", "!=", "<", ">", "<=", ">="]);
61
61
  exports.mathOperators = new Set(["+", "-", "*", "/", "q/+", "q/-", "q/concat"]);
62
+ const isDateType = (type) => type === "fibery/date" || type === "fibery/date-range";
63
+ exports.isDateType = isDateType;
64
+ const isDateTimeType = (type) => type === "fibery/date-time" || type === "fibery/date-time-range";
65
+ exports.isDateTimeType = isDateTimeType;
62
66
  const isFunctionCallExpression = (expression) => {
63
67
  if (!Array.isArray(expression)) {
64
68
  return false;
@@ -180,6 +184,35 @@ const getFieldObjectsByFieldExpression = ({ typeObject, expression, }) => {
180
184
  return fieldObjects;
181
185
  };
182
186
  exports.getFieldObjectsByFieldExpression = getFieldObjectsByFieldExpression;
187
+ const isFieldExpressionValid = ({ typeObject, expression }) => {
188
+ (0, exports.assertIsValidExpression)(expression);
189
+ return Boolean(expression.reduce((typeObject, fieldOrMultiFieldAccess) => {
190
+ if (!typeObject) {
191
+ return false;
192
+ }
193
+ if ((0, exports.isMultiFieldAccess)(fieldOrMultiFieldAccess)) {
194
+ const [multiField, type] = fieldOrMultiFieldAccess;
195
+ if (!Object.hasOwn(typeObject.fieldObjectsByName, multiField)) {
196
+ return false;
197
+ }
198
+ const fieldObject = typeObject.fieldObjectsByName[multiField];
199
+ const foundField = fieldObject.multiRelatedFieldObjects.find((f) => f.holderType === type);
200
+ if (!foundField) {
201
+ return false;
202
+ }
203
+ return foundField.holderTypeObject;
204
+ }
205
+ else {
206
+ if (Object.hasOwn(typeObject.fieldObjectsByName, fieldOrMultiFieldAccess)) {
207
+ return typeObject.fieldObjectsByName[fieldOrMultiFieldAccess].typeObject;
208
+ }
209
+ else {
210
+ return false;
211
+ }
212
+ }
213
+ }, typeObject));
214
+ };
215
+ exports.isFieldExpressionValid = isFieldExpressionValid;
183
216
  const getFieldObjectByFieldExpression = (x // TODO: review types. using type assertion now to avoid rewriting half of app
184
217
  ) => lodash_1.default.last((0, exports.getFieldObjectsByFieldExpression)(x));
185
218
  exports.getFieldObjectByFieldExpression = getFieldObjectByFieldExpression;
@@ -1,6 +1,6 @@
1
1
  import { fieldAccessVisitorTypeAware } from "./fieldExpressionVisitorTypeAware";
2
2
  import { TypeObject } from "@fibery/schema";
3
- import { Expression } from "./types";
3
+ import { Expression, SubQuery } from "./types";
4
4
  type OnFieldNotFoundInNamesTerms = (params: {
5
5
  fieldExpressionInNamesTerms: Expression;
6
6
  fieldId: string;
@@ -25,7 +25,7 @@ export declare const deleteExpressionsWithNotFoundFieldsVisitor: (typeObject: Ty
25
25
  export declare const expressionContainsAggregation: (expression: Expression) => boolean;
26
26
  export declare const UNKNOWN_EXPRESSION_TYPE = "unknown";
27
27
  export declare const getExpressionType: ({ expression, typeObject, functionsMeta, onFieldNotFound, returnRefTypeInsteadOfId, }: {
28
- expression: Expression;
28
+ expression: Expression | SubQuery;
29
29
  typeObject: TypeObject;
30
30
  functionsMeta: Record<string, {
31
31
  overloads: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fibery/expression-utils",
3
- "version": "9.4.1",
3
+ "version": "9.5.0",
4
4
  "description": "utils for working with fibery api expressions",
5
5
  "main": "./lib/index.js",
6
6
  "files": [
@@ -17,12 +17,18 @@
17
17
  "./src/utils": "./src/utils.ts",
18
18
  "./src/visitors": "./src/visitors.ts",
19
19
  "./src/params-placeholders": "./src/params-placeholders.ts",
20
- "./src/context-variables": "./src/context-variables.ts"
20
+ "./src/context-variables": "./src/context-variables.ts",
21
+ "./src/filter-expression": "./src/filter-expression/index.ts",
22
+ "./src/filter-expression/pattern-match": "./src/filter-expression/pattern-match.ts",
23
+ "./src/filter-expression/operators": "./src/filter-expression/operators.js",
24
+ "./src/filter-expression/patternMatchPlaceholders": "./src/filter-expression/patternMatchPlaceholders.js",
25
+ "./src/filter-expression/patternToExpression": "./src/filter-expression/patternToExpression.js"
21
26
  },
22
27
  "private": false,
23
28
  "dependencies": {
24
29
  "lodash": "4.17.21",
25
30
  "moment": "2.29.4",
31
+ "uuid": "11.1.0",
26
32
  "@fibery/helpers": "1.3.3"
27
33
  },
28
34
  "devDependencies": {