New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@feedloop/expression-parser

Package Overview
Dependencies
Maintainers
1
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@feedloop/expression-parser - npm Package Compare versions

Comparing version 0.1.5 to 0.1.7

17

lib/evaluator.js

@@ -87,8 +87,15 @@ "use strict";

return expression.value;
case "string":
return expression.parts
.slice(1)
.reduce(function (string, part, i) {
return string.concat((0, exports.evaluate)(expression.expressions[i], configs, true), part.value);
case "string": {
var concatFn_1 = configs.functions.find(function (fn) {
return fn.name === "Concatenate" &&
fn.parameters.every(function (param) { return param.type === "string"; }) &&
fn.return.type === "string";
});
return expression.parts.slice(1).reduce(function (string, part, i) {
var concat = concatFn_1
? concatFn_1.evaluate.bind(null, string)
: string.concat.bind(string);
return concat((0, exports.evaluate)(expression.expressions[i], configs, true), part.value);
}, expression.parts[0].value);
}
}

@@ -95,0 +102,0 @@ };

@@ -61,8 +61,25 @@ "use strict";

return "".concat(expression.value);
case "string":
return JSON.stringify(expression.parts
.slice(1)
.reduce(function (string, part, i) {
return string.concat((0, exports.generate)(expression.expressions[i], configs), part.value);
}, expression.parts[0].value));
case "string": {
var concatFn = configs.functions.find(function (fn) {
return fn.name === "Concatenate" &&
fn.parameters.every(function (param) { return param.type === "string"; }) &&
fn.return.type === "string";
});
return concatFn
? expression.parts
.slice(0, -1)
.map(function (part, i) { return [
part.value,
(0, exports.generate)(expression.expressions[i], configs),
]; })
.reduce(function (prevPart, _a) {
var _b = __read(_a, 2), part = _b[0], expr = _b[1];
return "Concatenate('".concat(part, "', Concatenate(").concat(expr, ", ").concat(prevPart, "))");
}, "'".concat(expression.parts[expression.parts.length - 1].value, "'"))
: "\"".concat(expression.parts
.slice(1)
.reduce(function (string, part, i) {
return string.concat("{{".concat((0, exports.generate)(expression.expressions[i], configs), "}}"), "".concat(part.value));
}, "".concat(expression.parts[0].value)), "\"");
}
case "expression":

@@ -69,0 +86,0 @@ return "(".concat((0, exports.generate)(expression.expression, configs), ")");

@@ -94,9 +94,17 @@ "use strict";

var buildExpressionSyntaxParser = function (operatorConfigs) {
var operator = (0, parser_utils_1.oneOf)(operatorConfigs.map(function (config) {
return (0, parser_utils_1.map)((0, exports.text)(config.name), function (name) { return ({
kind: "operator",
name: name,
unary: !config.left,
}); });
}));
var binaryOperator = (0, parser_utils_1.map)((0, parser_utils_1.oneOf)(operatorConfigs
.filter(function (config) { return !!config.left; })
.map(function (config) { return (0, exports.text)(config.name); })
.concat(exports.nonspaces)), function (name) { return ({
kind: "operator",
name: name,
unary: false,
}); });
var unaryOperator = (0, parser_utils_1.map)((0, parser_utils_1.oneOf)(operatorConfigs
.filter(function (config) { return !config.left; })
.map(function (config) { return (0, exports.text)(config.name); })), function (name) { return ({
kind: "operator",
name: name,
unary: true,
}); });
var functionParser = (0, parser_utils_1.chain)(exports.nonspaces, function (name) {

@@ -132,3 +140,3 @@ return (0, parser_utils_1.map)((0, parser_utils_1.between)((0, exports.text)("("), (0, parser_utils_1.sepBy)((0, exports.lexeme)(expression), (0, exports.text)(",")), (0, exports.text)(")")), function (args) { return ({

subExpression,
operator,
unaryOperator,
string,

@@ -148,4 +156,4 @@ (0, parser_utils_1.map)(exports.number, function (value) { return ({ kind: "number", value: value }); }),

.entries()), false).sort(function (a, b) { return a[0] - b[0]; });
var reoderTerms = function (termsAndOperators) {
var firstOpIndex = operatorPrecedenceGroup.reduce(function (operator, _a) {
var reorderTerms = function (termsAndOperators) {
var firstValidOperatorIndex = operatorPrecedenceGroup.reduce(function (operator, _a) {
var _b = __read(_a, 2), group = _b[1];

@@ -158,3 +166,6 @@ return operator === -1

: operator;
}, -1) || termsAndOperators.findIndex(function (to) { return to.kind === "operator"; });
}, -1);
var firstOpIndex = firstValidOperatorIndex !== -1
? firstValidOperatorIndex
: termsAndOperators.findIndex(function (to) { return to.kind === "operator"; });
if (firstOpIndex === -1) {

@@ -169,10 +180,15 @@ return termsAndOperators[0];

return firstOpIndex !== 0 && !op.unary
? __assign(__assign({}, op), { left: reoderTerms(leftTermsAndOperators), right: reoderTerms(rightTermsAndOperators) }) : __assign(__assign({}, op), { right: reoderTerms(rightTermsAndOperators) });
? __assign(__assign({}, op), { left: reorderTerms(leftTermsAndOperators), right: reorderTerms(rightTermsAndOperators) }) : __assign(__assign({}, op), { right: reorderTerms(rightTermsAndOperators) });
};
function expression() {
return (0, parser_utils_1.map)((0, parser_utils_1.chain)((0, parser_utils_1.sepBy)(termParser, exports.spaces), function (terms) {
return (0, parser_utils_1.chain)((0, parser_utils_1.chainRec)(termParser, function (expression, expressions) { return [
(0, exports.lexeme)(expression.kind !== "operator"
? (0, parser_utils_1.spanned)(binaryOperator)
: termParser),
expressions.concat(expression),
]; }, []), function (terms) {
return terms.length
? (0, parser_utils_1.pure)(terms)
: (0, parser_utils_1.map)((0, parser_utils_1.spanned)((0, parser_utils_1.pure)({ kind: "placeholder" })), function (exp) { return [exp]; });
}), reoderTerms);
? (0, parser_utils_1.pure)(reorderTerms(terms))
: (0, parser_utils_1.spanned)((0, parser_utils_1.pure)({ kind: "placeholder" }));
});
}

@@ -179,0 +195,0 @@ return function (input) { return (0, parser_utils_1.parse)((0, parser_utils_1.applyFirst)(expression, exports.eof), input, 0); };

{
"name": "@feedloop/expression-parser",
"version": "0.1.5",
"version": "0.1.7",
"main": "lib/index.js",

@@ -16,3 +16,3 @@ "types": "lib/index.d.ts",

},
"gitHead": "fcfa6dc6a723b4e64b2fb328f23b1e72dea7e6c4"
"gitHead": "ae0ab03c577bcb92e961fc3656fb81621cdb106a"
}

@@ -99,13 +99,19 @@ import { VariableConfig } from ".";

case "string":
return expression.parts
.slice(1)
.reduce(
(string, part, i) =>
string.concat(
evaluate(expression.expressions[i], configs, true),
part.value
),
expression.parts[0].value
case "string": {
const concatFn = configs.functions.find(
(fn) =>
fn.name === "Concatenate" &&
fn.parameters.every((param) => param.type === "string") &&
fn.return.type === "string"
);
return expression.parts.slice(1).reduce((string, part, i) => {
const concat = concatFn
? concatFn.evaluate.bind(null, string)
: string.concat.bind(string);
return concat(
evaluate(expression.expressions[i], configs, true),
part.value
);
}, expression.parts[0].value);
}
}

@@ -112,0 +118,0 @@ };

@@ -66,15 +66,34 @@ import { VariableConfig } from ".";

case "string":
return JSON.stringify(
expression.parts
.slice(1)
.reduce(
(string, part, i) =>
string.concat(
generate(expression.expressions[i], configs),
part.value
),
expression.parts[0].value
)
case "string": {
const concatFn = configs.functions.find(
(fn) =>
fn.name === "Concatenate" &&
fn.parameters.every((param) => param.type === "string") &&
fn.return.type === "string"
);
return concatFn
? expression.parts
.slice(0, -1)
.map((part, i) => [
part.value,
generate(expression.expressions[i], configs),
])
.reduce(
(prevPart, [part, expr]): string =>
`Concatenate('${part}', Concatenate(${expr}, ${prevPart}))`,
`'${
expression.parts[expression.parts.length - 1].value
}'` as string
)
: `"${expression.parts
.slice(1)
.reduce(
(string, part, i) =>
string.concat(
`{{${generate(expression.expressions[i], configs)}}}`,
`${part.value}`
),
`${expression.parts[0].value}`
)}"`;
}

@@ -81,0 +100,0 @@ case "expression":

@@ -158,14 +158,27 @@ import {

) => {
const operator = oneOf(
operatorConfigs.map((config) =>
map(
text(config.name),
(name): OperatorSyntax => ({
kind: "operator",
name,
unary: !config.left,
})
)
)
const binaryOperator = map(
oneOf(
operatorConfigs
.filter((config) => !!config.left)
.map((config) => text(config.name))
.concat(nonspaces)
),
(name): OperatorSyntax => ({
kind: "operator",
name,
unary: false,
})
);
const unaryOperator = map(
oneOf(
operatorConfigs
.filter((config) => !config.left)
.map((config) => text(config.name))
),
(name): OperatorSyntax => ({
kind: "operator",
name,
unary: true,
})
);
const functionParser: Parser<FunctionSyntax> = chain(nonspaces, (name) =>

@@ -224,3 +237,3 @@ map(

subExpression,
operator,
unaryOperator,
string,

@@ -248,17 +261,20 @@ map(number, (value) => ({ kind: "number", value })),

].sort((a, b) => a[0] - b[0]);
const reoderTerms = (
const reorderTerms = (
termsAndOperators: ExpressionSyntax[]
): ExpressionSyntax => {
const firstValidOperatorIndex = operatorPrecedenceGroup.reduce(
(operator, [, group]) =>
operator === -1
? termsAndOperators.findIndex(
(to) =>
to.kind === "operator" &&
group.map((op) => op.name).includes(to.name)
)
: operator,
-1
);
const firstOpIndex =
operatorPrecedenceGroup.reduce(
(operator, [, group]) =>
operator === -1
? termsAndOperators.findIndex(
(to) =>
to.kind === "operator" &&
group.map((op) => op.name).includes(to.name)
)
: operator,
-1
) || termsAndOperators.findIndex((to) => to.kind === "operator");
firstValidOperatorIndex !== -1
? firstValidOperatorIndex
: termsAndOperators.findIndex((to) => to.kind === "operator");
if (firstOpIndex === -1) {

@@ -276,8 +292,8 @@ return termsAndOperators[0];

...op,
left: reoderTerms(leftTermsAndOperators),
right: reoderTerms(rightTermsAndOperators),
left: reorderTerms(leftTermsAndOperators),
right: reorderTerms(rightTermsAndOperators),
}
: {
...op,
right: reoderTerms(rightTermsAndOperators),
right: reorderTerms(rightTermsAndOperators),
};

@@ -287,14 +303,19 @@ };

function expression() {
return map(
chain(
sepBy(termParser, spaces),
(terms): Parser<ExpressionSyntax[]> =>
terms.length
? pure(terms)
: map(
spanned(pure({ kind: "placeholder" } as PlaceholderSyntax)),
(exp) => [exp]
)
return chain(
chainRec(
termParser,
(expression, expressions) => [
lexeme(
expression.kind !== "operator"
? spanned(binaryOperator as Parser<ExpressionSyntax>)
: termParser
),
expressions.concat(expression),
],
[] as ExpressionSyntax[]
),
reoderTerms
(terms): Parser<ExpressionSyntax> =>
terms.length
? pure(reorderTerms(terms))
: spanned(pure({ kind: "placeholder" } as PlaceholderSyntax))
) as EagerParser<ExpressionSyntax>;

@@ -301,0 +322,0 @@ }

@@ -10,3 +10,3 @@ import { generateFromExpression } from "./parseHelpers";

expect(generateFromExpression('upper("hello world")')).toEqual(
'UPPER("hello world")'
"UPPER('hello world')"
);

@@ -34,2 +34,8 @@ });

});
it("should convert string interpolation with concat function", () => {
expect(generateFromExpression('"Hello {{"World"}}"')).toEqual(
"Concatenate('Hello ', Concatenate('World', ''))"
);
});
});

@@ -7,58 +7,53 @@ import { parseExpressionWithoutSuggestions } from "./parseHelpers";

.toMatchInlineSnapshot(`
Object {
"ast": Object {
"end": 6,
"kind": "operator",
"left": Object {
"end": 4,
"kind": "boolean",
"start": 0,
"type": "boolean",
"value": true,
},
"name": "&",
"right": Object {
"end": 8,
Object {
"ast": Object {
"end": 6,
"kind": "operator",
"left": undefined,
"name": "!",
"right": Object {
"end": 13,
"left": Object {
"end": 4,
"kind": "boolean",
"start": 8,
"start": 0,
"type": "boolean",
"value": false,
"value": true,
},
"start": 7,
"name": "&",
"right": Object {
"end": 8,
"kind": "operator",
"left": undefined,
"name": "!",
"right": Object {
"end": 13,
"kind": "boolean",
"start": 8,
"type": "boolean",
"value": false,
},
"start": 7,
"type": "boolean",
"unary": true,
},
"start": 5,
"type": "boolean",
"unary": true,
"unary": false,
},
"start": 5,
"type": "boolean",
"unary": false,
},
"errors": Array [],
}
`);
"errors": Array [],
}
`);
expect(parseExpressionWithoutSuggestions("true & !!false"))
.toMatchInlineSnapshot(`
Object {
"ast": Object {
"end": 6,
"kind": "operator",
"left": Object {
"end": 4,
"kind": "boolean",
"start": 0,
"type": "boolean",
"value": true,
},
"name": "&",
"right": Object {
"end": 8,
Object {
"ast": Object {
"end": 6,
"kind": "operator",
"left": undefined,
"name": "!",
"left": Object {
"end": 4,
"kind": "boolean",
"start": 0,
"type": "boolean",
"value": true,
},
"name": "&",
"right": Object {
"end": 9,
"end": 8,
"kind": "operator",

@@ -68,23 +63,28 @@ "left": undefined,

"right": Object {
"end": 14,
"kind": "boolean",
"start": 9,
"end": 9,
"kind": "operator",
"left": undefined,
"name": "!",
"right": Object {
"end": 14,
"kind": "boolean",
"start": 9,
"type": "boolean",
"value": false,
},
"start": 8,
"type": "boolean",
"value": false,
"unary": true,
},
"start": 8,
"start": 7,
"type": "boolean",
"unary": true,
},
"start": 7,
"start": 5,
"type": "boolean",
"unary": true,
"unary": false,
},
"start": 5,
"type": "boolean",
"unary": false,
},
"errors": Array [],
}
`);
"errors": Array [],
}
`);
});

@@ -94,133 +94,158 @@

expect(parseExpressionWithoutSuggestions('1 + "2"')).toMatchInlineSnapshot(`
Object {
"ast": Object {
"end": 3,
"kind": "operator",
"left": Object {
"end": 1,
"kind": "number",
"start": 0,
Object {
"ast": Object {
"end": 3,
"kind": "operator",
"left": Object {
"end": 1,
"kind": "number",
"start": 0,
"type": "number",
"value": 1,
},
"name": "+",
"right": Object {
"end": 7,
"expressions": Array [],
"kind": "string",
"parts": Array [
Object {
"end": 6,
"start": 5,
"value": "2",
},
],
"start": 4,
"type": "string",
},
"start": 2,
"type": "number",
"value": 1,
"unary": false,
},
"name": "+",
"right": Object {
"end": 7,
"expressions": Array [],
"kind": "string",
"parts": Array [
Object {
"end": 6,
"start": 5,
"value": "2",
},
],
"start": 4,
"type": "string",
},
"start": 2,
"type": "number",
"unary": false,
},
"errors": Array [
Object {
"end": 7,
"id": 0,
"message": "expected type of number",
"start": 4,
},
],
}
`);
"errors": Array [
Object {
"end": 7,
"id": 0,
"message": "expected type of number",
"start": 4,
},
],
}
`);
expect(parseExpressionWithoutSuggestions('1 + lower("UPPER")'))
.toMatchInlineSnapshot(`
Object {
"ast": Object {
"end": 3,
"kind": "operator",
"left": Object {
"end": 1,
"kind": "number",
"start": 0,
Object {
"ast": Object {
"end": 3,
"kind": "operator",
"left": Object {
"end": 1,
"kind": "number",
"start": 0,
"type": "number",
"value": 1,
},
"name": "+",
"right": Object {
"arguments": Array [
Object {
"end": 17,
"expressions": Array [],
"kind": "string",
"parts": Array [
Object {
"end": 16,
"start": 11,
"value": "UPPER",
},
],
"start": 10,
"type": "string",
},
],
"end": 18,
"kind": "function",
"name": "lower",
"start": 4,
"type": "string",
},
"start": 2,
"type": "number",
"value": 1,
"unary": false,
},
"name": "+",
"right": Object {
"arguments": Array [
Object {
"end": 17,
"expressions": Array [],
"kind": "string",
"parts": Array [
Object {
"end": 16,
"start": 11,
"value": "UPPER",
},
],
"start": 10,
"type": "string",
},
],
"end": 18,
"kind": "function",
"name": "lower",
"start": 4,
"type": "string",
},
"start": 2,
"type": "number",
"unary": false,
},
"errors": Array [
Object {
"end": 18,
"id": 1,
"message": "expected return type of number but got string",
"start": 4,
},
],
}
`);
"errors": Array [
Object {
"end": 18,
"id": 1,
"message": "expected return type of number but got string",
"start": 4,
},
],
}
`);
expect(parseExpressionWithoutSuggestions('lower("UPPER") + 2'))
.toMatchInlineSnapshot(`
Object {
"ast": Object {
"end": 16,
"kind": "operator",
"left": Object {
"arguments": Array [
Object {
"end": 13,
"expressions": Array [],
"kind": "string",
"parts": Array [
Object {
"end": 12,
"start": 7,
"value": "UPPER",
},
],
"start": 6,
"type": "string",
},
],
"end": 14,
"kind": "function",
"name": "lower",
"start": 0,
"type": "string",
},
"name": "+",
"right": Object {
"end": 18,
"kind": "number",
"start": 17,
"type": "number",
"value": 2,
},
"start": 15,
"type": "number",
"unary": false,
},
"errors": Array [
Object {
"end": 14,
"id": 2,
"message": "expected return type of number but got string",
"start": 0,
},
],
}
`);
});
it("should parse undefined binary operator", () => {
expect(parseExpressionWithoutSuggestions("1 ^ 2")).toMatchInlineSnapshot(`
Object {
"ast": Object {
"end": 16,
"end": 3,
"kind": "operator",
"left": Object {
"arguments": Array [
Object {
"end": 13,
"expressions": Array [],
"kind": "string",
"parts": Array [
Object {
"end": 12,
"start": 7,
"value": "UPPER",
},
],
"start": 6,
"type": "string",
},
],
"end": 14,
"kind": "function",
"name": "lower",
"start": 0,
"type": "string",
},
"name": "+",
"right": Object {
"end": 18,
"kind": "number",
"start": 17,
"type": "number",
"value": 2,
},
"start": 15,
"type": "number",
"left": undefined,
"name": "^",
"right": undefined,
"start": 2,
"type": "any",
"unary": false,

@@ -230,6 +255,6 @@ },

Object {
"end": 14,
"id": 2,
"message": "expected return type of number but got string",
"start": 0,
"end": 3,
"id": 3,
"message": "operator ^ is not defined",
"start": 2,
},

@@ -236,0 +261,0 @@ ],

@@ -111,2 +111,24 @@ import {

},
{
name: "Concatenate",
description: "concatenate 2 strings together",
parameters: [
{
name: "part",
description: "part of string",
type: "string",
},
{
name: "part",
description: "part of string",
type: "string",
},
],
return: {
type: "string",
},
examples: [],
evaluate: (str1: string, str2: string) => str1.concat(str2),
generate: (str1: string, str2: string) => `CONCATENATE(${str1}, ${str2})`,
},
];

@@ -113,0 +135,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc