@witchcraft/expressit 0.3.0 → 0.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/dist/Lexer.js +14 -19
- package/dist/Parser.js +104 -115
- package/dist/ast/builders/array.js +7 -8
- package/dist/ast/builders/condition.js +1 -1
- package/dist/ast/builders/expression.js +4 -4
- package/dist/ast/builders/group.js +8 -9
- package/dist/ast/builders/token.js +1 -1
- package/dist/ast/builders/variable.js +5 -6
- package/dist/ast/createConditionNode.js +1 -2
- package/dist/ast/handlers.js +22 -25
- package/dist/examples/ParserWithSqlSupport.js +22 -30
- package/dist/examples/ShortcutContextParser.js +2 -5
- package/dist/internal/ExpressitError.js +7 -10
- package/dist/internal/checkParserOpts.js +10 -11
- package/dist/internal/escapeVariableOrPrefix.js +1 -1
- package/dist/internal/parseParserOptions.js +3 -4
- package/dist/package.json.js +1 -1
- package/dist/types/ast.js +1 -1
- package/dist/types/autocomplete.js +1 -1
- package/dist/types/errors.js +1 -1
- package/dist/utils/extractTokens.js +4 -5
- package/dist/utils/generateParentsMap.js +7 -8
- package/dist/utils/getCursorInfo.js +3 -3
- package/dist/utils/getOppositeDelimiter.js +1 -1
- package/dist/utils/getSurroundingErrors.js +2 -3
- package/dist/utils/isBracket.js +1 -1
- package/dist/utils/isDelimiter.js +1 -1
- package/dist/utils/isNode.js +1 -1
- package/dist/utils/isParen.js +1 -1
- package/dist/utils/isQuote.js +1 -1
- package/dist/utils/isToken.js +1 -1
- package/dist/utils/prettyAst.js +10 -11
- package/package.json +20 -33
- package/src/Lexer.ts +3 -3
- package/src/Parser.ts +7 -7
- package/src/ast/builders/token.ts +1 -1
- package/src/examples/ParserWithSqlSupport.ts +1 -1
- package/src/internal/ExpressitError.ts +3 -3
- package/src/internal/checkParserOpts.ts +2 -2
- package/src/internal/escapeVariableOrPrefix.ts +1 -1
- package/src/types/ast.ts +1 -1
- package/src/types/autocomplete.ts +1 -1
- package/src/types/errors.ts +1 -1
- package/src/utils/extractTokens.ts +1 -1
- package/src/utils/getCursorInfo.ts +2 -2
- package/src/utils/getOppositeDelimiter.ts +1 -1
- package/src/utils/prettyAst.ts +3 -3
|
@@ -2,17 +2,16 @@ import { token } from "./token.js";
|
|
|
2
2
|
import { TOKEN_TYPE } from "../../types/ast.js";
|
|
3
3
|
import { createArrayNode } from "../createArrayNode.js";
|
|
4
4
|
function array(values, bracket = { right: true, left: true }, parenLeftPos, parenRightPos) {
|
|
5
|
-
var _a, _b, _c, _d, _e, _f;
|
|
6
5
|
const node = {
|
|
7
6
|
values
|
|
8
7
|
};
|
|
9
8
|
node.bracket = {};
|
|
10
|
-
const start =
|
|
11
|
-
const end =
|
|
12
|
-
parenLeftPos
|
|
13
|
-
parenRightPos
|
|
9
|
+
const start = values[0]?.start ?? parenLeftPos?.end;
|
|
10
|
+
const end = values[values.length - 1]?.end ?? parenRightPos?.start ?? parenLeftPos?.end;
|
|
11
|
+
parenLeftPos ??= start !== void 0 ? { start: start - 1, end: start } : void 0;
|
|
12
|
+
parenRightPos ??= end !== void 0 ? { start: end, end: end + 1 } : void 0;
|
|
14
13
|
node.bracket.left = token(TOKEN_TYPE.BRACKETL, "[", parenLeftPos);
|
|
15
|
-
if (bracket
|
|
14
|
+
if (bracket?.right) {
|
|
16
15
|
node.bracket.right = token(TOKEN_TYPE.BRACKETR, "]", parenRightPos);
|
|
17
16
|
} else {
|
|
18
17
|
if (parenRightPos) {
|
|
@@ -20,8 +19,8 @@ function array(values, bracket = { right: true, left: true }, parenLeftPos, pare
|
|
|
20
19
|
}
|
|
21
20
|
node.bracket.right = token(TOKEN_TYPE.BRACKETR, void 0, parenRightPos);
|
|
22
21
|
}
|
|
23
|
-
node.start =
|
|
24
|
-
node.end =
|
|
22
|
+
node.start = node.bracket.left?.start ?? start ?? node.bracket?.right.start;
|
|
23
|
+
node.end = node.bracket?.right?.end ?? end ?? node.bracket.left.end;
|
|
25
24
|
return createArrayNode(node);
|
|
26
25
|
}
|
|
27
26
|
export {
|
|
@@ -4,7 +4,7 @@ import { createConditionNode } from "../createConditionNode.js";
|
|
|
4
4
|
function condition(value, not = true, property, propertyOperator, { right, left } = {}) {
|
|
5
5
|
const position = pos(value);
|
|
6
6
|
const notStart = not === true ? void 0 : not.start;
|
|
7
|
-
position.start = notStart ??
|
|
7
|
+
position.start = notStart ?? property?.start ?? propertyOperator?.start ?? position.start;
|
|
8
8
|
const node = {
|
|
9
9
|
property,
|
|
10
10
|
value,
|
|
@@ -3,15 +3,15 @@ import { token } from "./token.js";
|
|
|
3
3
|
import { TOKEN_TYPE } from "../../types/ast.js";
|
|
4
4
|
import { createExpressionNode } from "../createExpressionNode.js";
|
|
5
5
|
function expression(left, operator, right) {
|
|
6
|
-
const start =
|
|
7
|
-
const end =
|
|
6
|
+
const start = left?.start ?? operator?.start ?? right?.start;
|
|
7
|
+
const end = right?.end ?? operator?.end ?? left?.end;
|
|
8
8
|
const position = pos({ start, end });
|
|
9
|
-
left
|
|
9
|
+
left ??= token(TOKEN_TYPE.VALUE, void 0, { start: position.start });
|
|
10
10
|
let op;
|
|
11
11
|
if (operator === void 0) {
|
|
12
12
|
operator = token([TOKEN_TYPE.AND, TOKEN_TYPE.OR], void 0, { start: left.end });
|
|
13
13
|
} else op = operator;
|
|
14
|
-
right
|
|
14
|
+
right ??= token(TOKEN_TYPE.VALUE, void 0, { start: op.end });
|
|
15
15
|
return createExpressionNode({
|
|
16
16
|
left,
|
|
17
17
|
operator: op,
|
|
@@ -2,15 +2,14 @@ import { token } from "./token.js";
|
|
|
2
2
|
import { TOKEN_TYPE } from "../../types/ast.js";
|
|
3
3
|
import { createGroupNode } from "../createGroupNode.js";
|
|
4
4
|
function group(prefix, expression, paren = { right: true, left: true }, parenLeftPos, parenRightPos) {
|
|
5
|
-
|
|
6
|
-
expression ?? (expression = token(TOKEN_TYPE.VALUE, void 0, (prefix == null ? void 0 : prefix.end) !== void 0 ? { start: prefix.end } : void 0));
|
|
5
|
+
expression ??= token(TOKEN_TYPE.VALUE, void 0, prefix?.end !== void 0 ? { start: prefix.end } : void 0);
|
|
7
6
|
const node = {
|
|
8
7
|
prefix: void 0,
|
|
9
8
|
expression
|
|
10
9
|
};
|
|
11
10
|
if (prefix) {
|
|
12
11
|
node.prefix = prefix;
|
|
13
|
-
const locToRight =
|
|
12
|
+
const locToRight = node.paren?.left?.start ?? node.expression?.start ?? node.paren?.right.start;
|
|
14
13
|
if (prefix.start === void 0 && locToRight !== void 0) {
|
|
15
14
|
throw new Error("group builder: missing prefix location when passed expression with location");
|
|
16
15
|
}
|
|
@@ -18,9 +17,9 @@ function group(prefix, expression, paren = { right: true, left: true }, parenLef
|
|
|
18
17
|
node.paren = {};
|
|
19
18
|
const start = expression.start;
|
|
20
19
|
const end = expression.end;
|
|
21
|
-
parenLeftPos
|
|
22
|
-
parenRightPos
|
|
23
|
-
if (paren
|
|
20
|
+
parenLeftPos ??= start !== void 0 ? { start: start - 1, end: start } : void 0;
|
|
21
|
+
parenRightPos ??= end !== void 0 ? { start: end, end: end + 1 } : void 0;
|
|
22
|
+
if (paren?.left) {
|
|
24
23
|
node.paren.left = token(TOKEN_TYPE.PARENL, "(", parenLeftPos);
|
|
25
24
|
} else {
|
|
26
25
|
if (parenLeftPos) {
|
|
@@ -28,7 +27,7 @@ function group(prefix, expression, paren = { right: true, left: true }, parenLef
|
|
|
28
27
|
}
|
|
29
28
|
node.paren.left = token(TOKEN_TYPE.PARENL, void 0, parenLeftPos);
|
|
30
29
|
}
|
|
31
|
-
if (paren
|
|
30
|
+
if (paren?.right) {
|
|
32
31
|
node.paren.right = token(TOKEN_TYPE.PARENR, ")", parenRightPos);
|
|
33
32
|
} else {
|
|
34
33
|
if (parenRightPos) {
|
|
@@ -36,8 +35,8 @@ function group(prefix, expression, paren = { right: true, left: true }, parenLef
|
|
|
36
35
|
}
|
|
37
36
|
node.paren.right = token(TOKEN_TYPE.PARENR, void 0, parenRightPos);
|
|
38
37
|
}
|
|
39
|
-
node.start =
|
|
40
|
-
node.end =
|
|
38
|
+
node.start = node.prefix?.start ?? node.paren?.left?.start ?? node.expression?.start ?? node.paren?.right.start;
|
|
39
|
+
node.end = node.paren?.right?.end ?? node.expression?.end ?? node.paren?.left.end ?? node.prefix?.end;
|
|
41
40
|
return createGroupNode(node);
|
|
42
41
|
}
|
|
43
42
|
export {
|
|
@@ -3,7 +3,6 @@ import { token } from "./token.js";
|
|
|
3
3
|
import { TOKEN_TYPE } from "../../types/ast.js";
|
|
4
4
|
import { createVariableNode } from "../createVariableNode.js";
|
|
5
5
|
function variable(prefix, value, quote, position) {
|
|
6
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
7
6
|
if (typeof value === "string") {
|
|
8
7
|
value = token(TOKEN_TYPE.VALUE, value, position);
|
|
9
8
|
}
|
|
@@ -14,14 +13,14 @@ function variable(prefix, value, quote, position) {
|
|
|
14
13
|
};
|
|
15
14
|
if (quote) {
|
|
16
15
|
node.quote = {};
|
|
17
|
-
const quoteLeftPos =
|
|
16
|
+
const quoteLeftPos = position?.start !== void 0 ? pos({ start: position.start }, { fill: true }) : void 0;
|
|
18
17
|
if (quote.left) {
|
|
19
18
|
if (quoteLeftPos) quoteLeftPos.start -= 1;
|
|
20
19
|
node.quote.left = token(quote.type, quoteFromType(quote.type), quoteLeftPos);
|
|
21
20
|
} else {
|
|
22
21
|
node.quote.left = token(quote.type, void 0, quoteLeftPos);
|
|
23
22
|
}
|
|
24
|
-
const quoteRightPos =
|
|
23
|
+
const quoteRightPos = position?.end !== void 0 ? pos({ end: position.end }, { fill: true }) : void 0;
|
|
25
24
|
if (quote.right) {
|
|
26
25
|
if (quoteRightPos) quoteRightPos.end += 1;
|
|
27
26
|
node.quote.right = token(quote.type, quoteFromType(quote.type), quoteRightPos);
|
|
@@ -32,12 +31,12 @@ function variable(prefix, value, quote, position) {
|
|
|
32
31
|
const start = node.quote.right.end;
|
|
33
32
|
node.quote.flags = token(TOKEN_TYPE.VALUE, quote.flags, {
|
|
34
33
|
start,
|
|
35
|
-
end: start +
|
|
34
|
+
end: start + quote.flags?.length
|
|
36
35
|
});
|
|
37
36
|
}
|
|
38
37
|
}
|
|
39
|
-
node.start =
|
|
40
|
-
node.end =
|
|
38
|
+
node.start = node.prefix?.start ?? node.quote?.left.start ?? node.value?.start ?? node.quote?.right.start;
|
|
39
|
+
node.end = node.quote?.flags?.end ?? node.quote?.right.end ?? node.value?.end ?? node.quote?.left.end;
|
|
41
40
|
return createVariableNode(node);
|
|
42
41
|
}
|
|
43
42
|
function quoteFromType(type) {
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { AST_TYPE } from "../types/ast.js";
|
|
2
2
|
import { isNode } from "../utils/isNode.js";
|
|
3
3
|
function createConditionNode(raw) {
|
|
4
|
-
|
|
5
|
-
const valid = (raw.operator === void 0 || ((_a = raw.operator) == null ? void 0 : _a.valid)) && isNode(raw.value) && raw.value.valid && (raw.property === void 0 && raw.propertyOperator === void 0 && raw.sep === void 0 || raw.property !== void 0 && "type" in raw.property && raw.property.type === AST_TYPE.VARIABLE && (((_b = raw.propertyOperator) == null ? void 0 : _b.valid) === true || ((_d = (_c = raw.sep) == null ? void 0 : _c.left) == null ? void 0 : _d.valid) === true && (raw.sep.right === void 0 || ((_e = raw.sep) == null ? void 0 : _e.right.valid))));
|
|
4
|
+
const valid = (raw.operator === void 0 || raw.operator?.valid) && isNode(raw.value) && raw.value.valid && (raw.property === void 0 && raw.propertyOperator === void 0 && raw.sep === void 0 || raw.property !== void 0 && "type" in raw.property && raw.property.type === AST_TYPE.VARIABLE && (raw.propertyOperator?.valid === true || raw.sep?.left?.valid === true && (raw.sep.right === void 0 || raw.sep?.right.valid)));
|
|
6
5
|
return {
|
|
7
6
|
property: void 0,
|
|
8
7
|
propertyOperator: void 0,
|
package/dist/ast/handlers.js
CHANGED
|
@@ -43,12 +43,11 @@ const operator = {
|
|
|
43
43
|
not: operators(TOKEN_TYPE.NOT)
|
|
44
44
|
};
|
|
45
45
|
function variable(prefix, quoteL, value, quoteR, flags) {
|
|
46
|
-
var _a, _b;
|
|
47
46
|
const node = {
|
|
48
47
|
prefix: prefix ?? void 0,
|
|
49
|
-
value: value ?? error(
|
|
50
|
-
start:
|
|
51
|
-
end:
|
|
48
|
+
value: value ?? error(prefix?.end ?? quoteL?.end ?? quoteR?.start, [TOKEN_TYPE.VALUE]),
|
|
49
|
+
start: prefix?.start ?? quoteL?.start ?? value?.start ?? quoteR?.start,
|
|
50
|
+
end: quoteR?.end ?? value?.end ?? quoteL?.end ?? prefix?.end
|
|
52
51
|
};
|
|
53
52
|
if (quoteL || quoteR) {
|
|
54
53
|
node.quote = {
|
|
@@ -57,15 +56,14 @@ function variable(prefix, quoteL, value, quoteR, flags) {
|
|
|
57
56
|
};
|
|
58
57
|
if (flags) {
|
|
59
58
|
node.quote.flags = flags;
|
|
60
|
-
node.end =
|
|
59
|
+
node.end = node.quote?.flags?.end ?? node.end;
|
|
61
60
|
}
|
|
62
61
|
}
|
|
63
62
|
return createVariableNode(node);
|
|
64
63
|
}
|
|
65
64
|
function condition(not, property, { propertyOperator, sepL, sepR } = {}, value) {
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
const end = (value == null ? void 0 : value.end) ?? (sepR == null ? void 0 : sepR.end) ?? (propertyOperator == null ? void 0 : propertyOperator.end) ?? (sepL == null ? void 0 : sepL.end) ?? (property == null ? void 0 : property.end) ?? (not == null ? void 0 : not.end);
|
|
65
|
+
const start = not?.start ?? property?.start ?? sepL?.start ?? propertyOperator?.start ?? sepR?.start ?? value?.start;
|
|
66
|
+
const end = value?.end ?? sepR?.end ?? propertyOperator?.end ?? sepL?.end ?? property?.end ?? not?.end;
|
|
69
67
|
const node = {
|
|
70
68
|
value: value ?? error(end, [TOKEN_TYPE.VALUE]),
|
|
71
69
|
start,
|
|
@@ -80,50 +78,49 @@ function condition(not, property, { propertyOperator, sepL, sepR } = {}, value)
|
|
|
80
78
|
node.sep = {};
|
|
81
79
|
if (sepL) {
|
|
82
80
|
node.sep.left = sepL;
|
|
83
|
-
node.property
|
|
84
|
-
node.propertyOperator
|
|
81
|
+
node.property ??= error(sepL.start, [TOKEN_TYPE.VALUE]);
|
|
82
|
+
node.propertyOperator ??= error(sepL?.end ?? sepR?.start, [TOKEN_TYPE.VALUE]);
|
|
85
83
|
}
|
|
86
84
|
if (sepR) node.sep.right = sepR;
|
|
87
85
|
else if (!node.value || node.value.type === AST_TYPE.VARIABLE) {
|
|
88
|
-
node.sep.right = error(
|
|
86
|
+
node.sep.right = error(node.value?.start ?? end, [TOKEN_TYPE.OP_EXPANDED_SEP]);
|
|
89
87
|
}
|
|
90
88
|
} else if (propertyOperator) {
|
|
91
|
-
node.property
|
|
89
|
+
node.property ??= error(propertyOperator.start, [TOKEN_TYPE.VALUE]);
|
|
92
90
|
}
|
|
93
91
|
return createConditionNode(node);
|
|
94
92
|
}
|
|
95
93
|
function expression(left, operator2, right) {
|
|
96
94
|
return createExpressionNode({
|
|
97
|
-
left: left ?? error(
|
|
98
|
-
operator: operator2 ?? error(
|
|
99
|
-
right: right ?? error(
|
|
100
|
-
start:
|
|
101
|
-
end:
|
|
95
|
+
left: left ?? error(operator2?.start ?? right?.start, [TOKEN_TYPE.VALUE]),
|
|
96
|
+
operator: operator2 ?? error(left?.end ?? right?.start, [TOKEN_TYPE.AND, TOKEN_TYPE.OR]),
|
|
97
|
+
right: right ?? error(operator2?.end ?? left?.end, [TOKEN_TYPE.VALUE]),
|
|
98
|
+
start: left?.start ?? operator2?.start ?? right?.start,
|
|
99
|
+
end: right?.end ?? operator2?.end ?? left?.end
|
|
102
100
|
});
|
|
103
101
|
}
|
|
104
102
|
function group(operator2, prefix, parenL, condition2, parenR) {
|
|
105
103
|
return createGroupNode({
|
|
106
104
|
prefix: prefix ?? operator2 ?? void 0,
|
|
107
|
-
expression: condition2 ?? error(
|
|
105
|
+
expression: condition2 ?? error(parenL?.end ?? parenR?.start, [TOKEN_TYPE.VALUE]),
|
|
108
106
|
paren: {
|
|
109
|
-
left: parenL ?? error(
|
|
110
|
-
right: parenR ?? error(
|
|
107
|
+
left: parenL ?? error(prefix?.end ?? operator2?.end ?? condition2?.start ?? parenR?.start, [TOKEN_TYPE.PARENL]),
|
|
108
|
+
right: parenR ?? error(condition2?.end ?? parenL?.end, [TOKEN_TYPE.PARENR])
|
|
111
109
|
},
|
|
112
|
-
start:
|
|
113
|
-
end:
|
|
110
|
+
start: prefix?.start ?? operator2?.start ?? parenL?.start ?? condition2?.start ?? parenR?.start,
|
|
111
|
+
end: parenR?.end ?? condition2?.end ?? parenL?.end ?? operator2?.end ?? prefix?.end
|
|
114
112
|
});
|
|
115
113
|
}
|
|
116
114
|
function array(bracketL, values, bracketR) {
|
|
117
|
-
var _a, _b;
|
|
118
115
|
return createArrayNode({
|
|
119
116
|
values,
|
|
120
117
|
bracket: {
|
|
121
118
|
left: bracketL,
|
|
122
119
|
// always valid for now
|
|
123
|
-
right: bracketR ?? error(
|
|
120
|
+
right: bracketR ?? error(values[values.length - 1]?.end ?? bracketL?.end, [TOKEN_TYPE.BRACKETR])
|
|
124
121
|
},
|
|
125
122
|
start: bracketL.start,
|
|
126
|
-
end:
|
|
123
|
+
end: bracketR?.end ?? values[values.length - 1]?.end ?? bracketL.end
|
|
127
124
|
});
|
|
128
125
|
}
|
|
129
126
|
export {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
-
import { unreachable } from "@alanscodelog/utils/unreachable.js";
|
|
1
|
+
import { unreachable } from "@alanscodelog/utils/unreachable";
|
|
5
2
|
import { Parser } from "../Parser.js";
|
|
6
3
|
import { AST_TYPE, TOKEN_TYPE } from "../types/ast.js";
|
|
7
4
|
class ParserWithSqlSupport extends Parser {
|
|
5
|
+
sqlEscapeValue;
|
|
6
|
+
operatorMap;
|
|
7
|
+
propertyDefinitions;
|
|
8
|
+
operatorDefinitions;
|
|
8
9
|
constructor(propertyDefinitions, operatorDefinitions, { sqlEscapeValue }) {
|
|
9
10
|
const operators = [];
|
|
10
11
|
const operatorMap = {};
|
|
@@ -31,7 +32,6 @@ class ParserWithSqlSupport extends Parser {
|
|
|
31
32
|
customPropertyOperators: operators,
|
|
32
33
|
prefixableGroups: false,
|
|
33
34
|
valueComparer: (condition, contextValue, _context) => {
|
|
34
|
-
var _a;
|
|
35
35
|
if (typeof condition.value !== typeof contextValue) {
|
|
36
36
|
throw new Error(`Expected type of property ${condition.property[0]} to be the same type as the context value ${contextValue} (${typeof contextValue}). If the ast has been validated this is likely because the type of the context value is incorrect.`);
|
|
37
37
|
}
|
|
@@ -40,13 +40,12 @@ class ParserWithSqlSupport extends Parser {
|
|
|
40
40
|
const propDefinition = propertyDefinitions[prop];
|
|
41
41
|
const operatorDefinition = condition.operator && operatorDefinitions[condition.operator];
|
|
42
42
|
if (!operatorDefinition) unreachable("Did you validate the ast before evaluating it?");
|
|
43
|
-
const isSupported = !
|
|
43
|
+
const isSupported = !propDefinition.supportedOperators?.includes(condition.operator);
|
|
44
44
|
if (!isSupported) unreachable("Did you validate the ast before evaluating it?");
|
|
45
45
|
const res = operatorDefinition.valueComparer(condition, contextValue);
|
|
46
46
|
return res;
|
|
47
47
|
},
|
|
48
48
|
valueValidator: (_contextValue, query) => {
|
|
49
|
-
var _a, _b, _c;
|
|
50
49
|
const prop = query.propertyKeys[0];
|
|
51
50
|
let tokens = [];
|
|
52
51
|
const propDefinition = propertyDefinitions[prop];
|
|
@@ -62,12 +61,12 @@ class ParserWithSqlSupport extends Parser {
|
|
|
62
61
|
const opKey = op && operatorMap[op.value];
|
|
63
62
|
if (!op || !opKey) {
|
|
64
63
|
tokens.push({
|
|
65
|
-
start: (
|
|
66
|
-
end: (
|
|
64
|
+
start: (op ?? query.condition)?.start,
|
|
65
|
+
end: (op ?? query.condition)?.end,
|
|
67
66
|
type: "unknownOperator"
|
|
68
67
|
});
|
|
69
68
|
} else {
|
|
70
|
-
if (propDefinition.supportedOperators && !
|
|
69
|
+
if (propDefinition.supportedOperators && !propDefinition.supportedOperators?.includes(opKey)) {
|
|
71
70
|
tokens.push({
|
|
72
71
|
start: query.condition.start,
|
|
73
72
|
end: query.condition.end,
|
|
@@ -94,7 +93,7 @@ class ParserWithSqlSupport extends Parser {
|
|
|
94
93
|
if (tokens.length > 0) return tokens;
|
|
95
94
|
return;
|
|
96
95
|
}
|
|
97
|
-
if (
|
|
96
|
+
if (val?.type !== "VARIABLE") unreachable();
|
|
98
97
|
const value = val.value.value;
|
|
99
98
|
const res = convertAndValidateValue(query.isQuoted, value, prop, propertyDefinitions);
|
|
100
99
|
if (res instanceof Error) {
|
|
@@ -110,8 +109,7 @@ class ParserWithSqlSupport extends Parser {
|
|
|
110
109
|
if (tokens.length > 0) return tokens;
|
|
111
110
|
},
|
|
112
111
|
conditionNormalizer(query) {
|
|
113
|
-
|
|
114
|
-
const prop = (_a = query.property) == null ? void 0 : _a[0];
|
|
112
|
+
const prop = query.property?.[0];
|
|
115
113
|
if (!prop) unreachable("Did you validate the ast before normalizing it?");
|
|
116
114
|
const propDefinition = propertyDefinitions[prop];
|
|
117
115
|
let finalValue;
|
|
@@ -140,7 +138,7 @@ class ParserWithSqlSupport extends Parser {
|
|
|
140
138
|
if (!opKey) unreachable("Did you validate the ast before normalizing it?");
|
|
141
139
|
const operatorDefinition = opKey && operatorDefinitions[opKey];
|
|
142
140
|
if (!operatorDefinition) unreachable("Did you validate the ast before normalizing it?");
|
|
143
|
-
const isNegatableOperator =
|
|
141
|
+
const isNegatableOperator = operatorDefinition.negatedOperators?.includes(query.operator);
|
|
144
142
|
finalOperator = operatorDefinition.operator;
|
|
145
143
|
let isNegated = query.isNegated;
|
|
146
144
|
if (isNegatableOperator) {
|
|
@@ -149,30 +147,25 @@ class ParserWithSqlSupport extends Parser {
|
|
|
149
147
|
return { value: finalValue, operator: finalOperator, negate: isNegated };
|
|
150
148
|
}
|
|
151
149
|
});
|
|
152
|
-
__publicField(this, "sqlEscapeValue");
|
|
153
|
-
__publicField(this, "operatorMap");
|
|
154
|
-
__publicField(this, "propertyDefinitions");
|
|
155
|
-
__publicField(this, "operatorDefinitions");
|
|
156
150
|
this.propertyDefinitions = propertyDefinitions;
|
|
157
151
|
this.operatorDefinitions = operatorDefinitions;
|
|
158
152
|
this.operatorMap = operatorMap;
|
|
159
153
|
this.sqlEscapeValue = sqlEscapeValue;
|
|
160
154
|
}
|
|
161
155
|
toSql(ast, wrapStrings) {
|
|
162
|
-
var _a, _b;
|
|
163
156
|
this._checkEvaluationOptions();
|
|
164
157
|
const chunks = [];
|
|
165
158
|
if (ast.type === AST_TYPE.NORMALIZED_CONDITION) {
|
|
166
|
-
const prop =
|
|
159
|
+
const prop = ast.property?.[0];
|
|
167
160
|
const definition = this.propertyDefinitions[prop];
|
|
168
161
|
const value = ast.value;
|
|
169
|
-
const col =
|
|
162
|
+
const col = definition.transformToColumn?.(prop, definition.name) ?? `"${prop}"`;
|
|
170
163
|
const op = ast.operator;
|
|
171
164
|
if (ast.negate) {
|
|
172
|
-
chunks.push(
|
|
165
|
+
chunks.push(wrapStrings?.(`NOT(`) ?? `NOT(`);
|
|
173
166
|
}
|
|
174
|
-
chunks.push(
|
|
175
|
-
chunks.push(
|
|
167
|
+
chunks.push(wrapStrings?.(`${col} `) ?? `${col} `);
|
|
168
|
+
chunks.push(wrapStrings?.(`${op} `) ?? `${op} `);
|
|
176
169
|
const val = this.sqlEscapeValue(value);
|
|
177
170
|
if (definition.transformValue) {
|
|
178
171
|
const transformed = definition.transformValue(val, value);
|
|
@@ -185,7 +178,7 @@ class ParserWithSqlSupport extends Parser {
|
|
|
185
178
|
chunks.push(val);
|
|
186
179
|
}
|
|
187
180
|
if (ast.negate) {
|
|
188
|
-
chunks.push(
|
|
181
|
+
chunks.push(wrapStrings?.(`)`) ?? `)`);
|
|
189
182
|
}
|
|
190
183
|
return chunks;
|
|
191
184
|
}
|
|
@@ -193,11 +186,11 @@ class ParserWithSqlSupport extends Parser {
|
|
|
193
186
|
const left = this.toSql(ast.left, wrapStrings);
|
|
194
187
|
const right = this.toSql(ast.right, wrapStrings);
|
|
195
188
|
const op = ast.operator === TOKEN_TYPE.AND ? "AND" : "OR";
|
|
196
|
-
chunks.push(
|
|
189
|
+
chunks.push(wrapStrings?.(`(`) ?? `(`);
|
|
197
190
|
chunks.push(...left);
|
|
198
|
-
chunks.push(
|
|
191
|
+
chunks.push(wrapStrings?.(` ${op} `) ?? ` ${op} `);
|
|
199
192
|
chunks.push(...right);
|
|
200
|
-
chunks.push(
|
|
193
|
+
chunks.push(wrapStrings?.(`)`) ?? `)`);
|
|
201
194
|
return chunks;
|
|
202
195
|
}
|
|
203
196
|
return unreachable();
|
|
@@ -210,7 +203,6 @@ function createTypeError(prop, type, isArray) {
|
|
|
210
203
|
return new Error(`Property ${prop} must be of type ${type}.`);
|
|
211
204
|
}
|
|
212
205
|
function convertAndValidateValue(isQuoted, value, prop, propertyDefinitions, { isArray = false } = {}) {
|
|
213
|
-
var _a;
|
|
214
206
|
let finalValue = value;
|
|
215
207
|
let isFloat = false;
|
|
216
208
|
const propDefinition = propertyDefinitions[prop];
|
|
@@ -233,7 +225,7 @@ function convertAndValidateValue(isQuoted, value, prop, propertyDefinitions, { i
|
|
|
233
225
|
}
|
|
234
226
|
}
|
|
235
227
|
const type = propDefinition.type;
|
|
236
|
-
finalValue =
|
|
228
|
+
finalValue = propDefinition.postParse?.(finalValue) ?? finalValue;
|
|
237
229
|
switch (type) {
|
|
238
230
|
case "integer":
|
|
239
231
|
case "float": {
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
1
|
import { Parser } from "../Parser.js";
|
|
5
2
|
class ShortcutContextParser extends Parser {
|
|
3
|
+
validKeys = [];
|
|
4
|
+
regexablekeys = [];
|
|
6
5
|
constructor(dummyContext, validRegexFlags = ["i", "u", "m"]) {
|
|
7
6
|
super({
|
|
8
7
|
arrayValues: false,
|
|
@@ -97,8 +96,6 @@ class ShortcutContextParser extends Parser {
|
|
|
97
96
|
return { value: finalValue, operator: finalOperator, negate: isNegated };
|
|
98
97
|
}
|
|
99
98
|
});
|
|
100
|
-
__publicField(this, "validKeys", []);
|
|
101
|
-
__publicField(this, "regexablekeys", []);
|
|
102
99
|
this._extractKeysFromContext(dummyContext);
|
|
103
100
|
}
|
|
104
101
|
setContext(context) {
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { crop } from "@alanscodelog/utils/crop.js";
|
|
5
|
-
import { indent } from "@alanscodelog/utils/indent.js";
|
|
6
|
-
import { pretty } from "@alanscodelog/utils/pretty.js";
|
|
1
|
+
import { crop } from "@alanscodelog/utils/crop";
|
|
2
|
+
import { indent } from "@alanscodelog/utils/indent";
|
|
3
|
+
import { pretty } from "@alanscodelog/utils/pretty";
|
|
7
4
|
import packageJson from "../package.json.js";
|
|
8
5
|
const { version, repository } = packageJson;
|
|
9
6
|
class ExpressitError extends Error {
|
|
7
|
+
version = version;
|
|
8
|
+
repo = repository;
|
|
9
|
+
type;
|
|
10
|
+
info;
|
|
10
11
|
constructor(type, info, message) {
|
|
11
12
|
super(
|
|
12
13
|
message ? `${message}
|
|
@@ -17,10 +18,6 @@ ${crop`
|
|
|
17
18
|
info: ${indent(JSON.stringify(info, forceStringifyErrors, " "), 5)}
|
|
18
19
|
`}`
|
|
19
20
|
);
|
|
20
|
-
__publicField(this, "version", version);
|
|
21
|
-
__publicField(this, "repo", repository);
|
|
22
|
-
__publicField(this, "type");
|
|
23
|
-
__publicField(this, "info");
|
|
24
21
|
this.type = type;
|
|
25
22
|
this.info = info;
|
|
26
23
|
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { isBlank } from "@alanscodelog/utils/isBlank
|
|
2
|
-
import { pushIfNotIn } from "@alanscodelog/utils/pushIfNotIn
|
|
1
|
+
import { isBlank } from "@alanscodelog/utils/isBlank";
|
|
2
|
+
import { pushIfNotIn } from "@alanscodelog/utils/pushIfNotIn";
|
|
3
3
|
import { ExpressitError } from "./ExpressitError.js";
|
|
4
4
|
import { defaultConditionNormalizer } from "../defaults/defaultConditionNormalizer.js";
|
|
5
5
|
import { defaultValueComparer } from "../defaults/defaultValueComparer.js";
|
|
6
6
|
import { PARSER_ERROR } from "../types/errors.js";
|
|
7
7
|
function checkParserOpts(opts, evaluatorChecks = false, validatorChecks = false) {
|
|
8
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
9
8
|
if (!evaluatorChecks) {
|
|
10
9
|
const keywordsList = [...opts.keywords.and, ...opts.keywords.or, ...opts.keywords.not].map((keyword) => keyword.value);
|
|
11
10
|
const symNots = opts.keywords.not.filter((op) => op.isSymbol).map((op) => op.value);
|
|
@@ -25,7 +24,7 @@ function checkParserOpts(opts, evaluatorChecks = false, validatorChecks = false)
|
|
|
25
24
|
`expandedPropertySeparator cannot be blank`
|
|
26
25
|
);
|
|
27
26
|
}
|
|
28
|
-
const customInvalid =
|
|
27
|
+
const customInvalid = opts.customPropertyOperators?.find((_) => isBlank(_));
|
|
29
28
|
if (customInvalid !== void 0) {
|
|
30
29
|
throw new ExpressitError(
|
|
31
30
|
PARSER_ERROR.CONFLICTING_OPTIONS_ERROR,
|
|
@@ -33,7 +32,7 @@ function checkParserOpts(opts, evaluatorChecks = false, validatorChecks = false)
|
|
|
33
32
|
`customPropertyOperators cannot contain blank entries`
|
|
34
33
|
);
|
|
35
34
|
}
|
|
36
|
-
const prefixInvalid =
|
|
35
|
+
const prefixInvalid = opts.prefixableStrings?.find((_) => isBlank(_));
|
|
37
36
|
if (prefixInvalid !== void 0) {
|
|
38
37
|
throw new ExpressitError(
|
|
39
38
|
PARSER_ERROR.CONFLICTING_OPTIONS_ERROR,
|
|
@@ -42,7 +41,7 @@ function checkParserOpts(opts, evaluatorChecks = false, validatorChecks = false)
|
|
|
42
41
|
);
|
|
43
42
|
}
|
|
44
43
|
for (const key of ["and", "or", "not"]) {
|
|
45
|
-
const invalid =
|
|
44
|
+
const invalid = opts.keywords[key]?.find((_) => isBlank(_.value))?.value;
|
|
46
45
|
if (invalid !== void 0) {
|
|
47
46
|
throw new ExpressitError(
|
|
48
47
|
PARSER_ERROR.CONFLICTING_OPTIONS_ERROR,
|
|
@@ -55,7 +54,7 @@ function checkParserOpts(opts, evaluatorChecks = false, validatorChecks = false)
|
|
|
55
54
|
const allKeywords = [...keywords, ...symNots];
|
|
56
55
|
const messageInvalidAny = "cannot contain operators or special symbols, but found";
|
|
57
56
|
const messageInvalidBool = "cannot contain boolean operators or special symbols, but found";
|
|
58
|
-
const invalidPrefixableString =
|
|
57
|
+
const invalidPrefixableString = opts.prefixableStrings?.find((val) => all.includes(val));
|
|
59
58
|
if (invalidPrefixableString) {
|
|
60
59
|
throw new ExpressitError(
|
|
61
60
|
PARSER_ERROR.CONFLICTING_OPTIONS_ERROR,
|
|
@@ -71,7 +70,7 @@ function checkParserOpts(opts, evaluatorChecks = false, validatorChecks = false)
|
|
|
71
70
|
`expandedPropertySeparator ${messageInvalidBool} "${invalidExpandedPropertySeparator}"`
|
|
72
71
|
);
|
|
73
72
|
}
|
|
74
|
-
const invalidCustomPropertyOperator =
|
|
73
|
+
const invalidCustomPropertyOperator = opts.customPropertyOperators?.find((val) => keywords.includes(val)) ? opts.expandedPropertySeparator : void 0;
|
|
75
74
|
if (invalidCustomPropertyOperator) {
|
|
76
75
|
throw new ExpressitError(
|
|
77
76
|
PARSER_ERROR.CONFLICTING_OPTIONS_ERROR,
|
|
@@ -82,9 +81,9 @@ function checkParserOpts(opts, evaluatorChecks = false, validatorChecks = false)
|
|
|
82
81
|
}
|
|
83
82
|
if (evaluatorChecks) {
|
|
84
83
|
const requireCustomNormalizer = [];
|
|
85
|
-
if ((
|
|
86
|
-
if ((
|
|
87
|
-
if ((
|
|
84
|
+
if ((opts.prefixableStrings?.length ?? 0) > 0) requireCustomNormalizer.push("prefixableStrings");
|
|
85
|
+
if ((opts.customPropertyOperators?.length ?? 0) > 0) requireCustomNormalizer.push("customPropertyOperators");
|
|
86
|
+
if ((opts.expandedPropertySeparator?.length ?? 0) > 0) requireCustomNormalizer.push("expandedPropertySeparator");
|
|
88
87
|
if (opts.regexValues) requireCustomNormalizer.push("regexValues");
|
|
89
88
|
if (requireCustomNormalizer.length > 0 && opts.conditionNormalizer === defaultConditionNormalizer) {
|
|
90
89
|
throw new ExpressitError(
|
|
@@ -3,7 +3,6 @@ import { defaultKeyParser } from "../defaults/defaultKeyParser.js";
|
|
|
3
3
|
import { defaultPrefixApplier } from "../defaults/defaultPrefixApplier.js";
|
|
4
4
|
import { defaultValueComparer } from "../defaults/defaultValueComparer.js";
|
|
5
5
|
function parseParserOptions(options) {
|
|
6
|
-
var _a, _b, _c;
|
|
7
6
|
const opts = {
|
|
8
7
|
prefixApplier: defaultPrefixApplier,
|
|
9
8
|
keyParser: defaultKeyParser,
|
|
@@ -19,19 +18,19 @@ function parseParserOptions(options) {
|
|
|
19
18
|
...options,
|
|
20
19
|
// todo fix
|
|
21
20
|
keywords: {
|
|
22
|
-
or:
|
|
21
|
+
or: options.keywords?.or ? options.keywords.or : [
|
|
23
22
|
{ value: "||", isSymbol: true },
|
|
24
23
|
{ value: "|", isSymbol: true },
|
|
25
24
|
{ value: "or", isSymbol: false },
|
|
26
25
|
{ value: "OR", isSymbol: false }
|
|
27
26
|
],
|
|
28
|
-
and:
|
|
27
|
+
and: options.keywords?.and ? options.keywords.and : [
|
|
29
28
|
{ value: "&&", isSymbol: true },
|
|
30
29
|
{ value: "&", isSymbol: true },
|
|
31
30
|
{ value: "and", isSymbol: false },
|
|
32
31
|
{ value: "AND", isSymbol: false }
|
|
33
32
|
],
|
|
34
|
-
not:
|
|
33
|
+
not: options.keywords?.not ? options.keywords.not : [
|
|
35
34
|
{ value: "!", isSymbol: true },
|
|
36
35
|
{ value: "not", isSymbol: false },
|
|
37
36
|
{ value: "NOT", isSymbol: false }
|
package/dist/package.json.js
CHANGED
package/dist/types/ast.js
CHANGED