Allow expressions in provision arguments

This commit is contained in:
Zaid Abdulla committed 2020-08-17 16:51:10 -07:00
1 parent fef4ddfbba
commit 6385f54888
6 files changed
+54 -22

No files matched your search

+11 -3
View File
@@ -215,9 +215,7 @@ const lang = parsimmon.createLanguage({
.regexp(/([a-zA-Z0-9_]+)/, 1)
.skip(parsimmon.optWhitespace)
.desc("function"),
r.Expression.sepBy(
parsimmon.string(",").skip(parsimmon.optWhitespace)
).wrap(
r.ExpressionList.wrap(
parsimmon.string("(").skip(parsimmon.optWhitespace),
parsimmon.string(")").skip(parsimmon.optWhitespace)
),
@@ -330,6 +328,11 @@ const lang = parsimmon.createLanguage({
)
);
},
ExpressionList: function (r) {
return r.Expression.sepBy(
parsimmon.string(",").skip(parsimmon.optWhitespace)
);
},
Expression: function (r) {
function unary(operatorsParser, nextParser): parsimmon.Parser<unknown> {
return parsimmon.seq(operatorsParser, nextParser).or(nextParser);
@@ -350,6 +353,11 @@ export function parse(str: string): Expression {
return lang.Expression.tryParse(str);
}
export function parseList(str: string): Expression[] {
if (!str) return [];
return lang.ExpressionList.tryParse(str);
}
export function stringify(exp: Expression, level = 0): string {
if (!Array.isArray(exp)) return JSON.stringify(exp);
+10 -10
View File
@@ -112,7 +112,8 @@ export function evaluateCallback(exp: Expression): Expression {
if (exp[i]) return exp[i + 1];
}
return null;
} else if (exp[0] === "FUNC" && exp[1] === "COALESCE") {
} else if (exp[0] === "FUNC") {
if (exp[1] === "COALESCE") {
const args: Expression[] = [];
for (let i = 2; i < exp.length; ++i) {
const e = exp[i];
@@ -123,6 +124,13 @@ export function evaluateCallback(exp: Expression): Expression {
if (!args.length) return null;
if (args.length === 1) return args[0];
return ["FUNC", "COALESCE", ...args];
} else if (exp[1] === "UPPER") {
if (exp[2] == null) return null;
if (!isArray(exp[2])) return toString(exp[2]).toUpperCase();
} else if (exp[1] === "LOWER") {
if (exp[2] == null) return null;
if (!isArray(exp[2])) return toString(exp[2]).toLowerCase();
}
} else if (exp[0] === "AND") {
for (let i = 1; i < exp.length; ++i)
if (!Array.isArray(exp[i]) && exp[i] != null && !exp[i]) return false;
@@ -274,16 +282,8 @@ export function evaluate(
if (cb) e = cb(e);
if (!isArray(e)) return e;
if (e[0] === "FUNC") {
if (e[1] === "NOW") {
if (e[0] === "FUNC" && e[1] === "NOW") {
if (now) return now;
} else if (e[1] === "UPPER") {
if (e[2] == null) return null;
if (!isArray(e[2])) return `${e[2]}`.toUpperCase();
} else if (e[1] === "LOWER") {
if (e[2] == null) return null;
if (!isArray(e[2])) return `${e[2]}`.toLowerCase();
}
} else if (e[0] === "PARAM") {
if (e[1] == null) return null;
if (obj && !isArray(e[1])) {
+28 -4
View File
@@ -45,6 +45,7 @@ import {
SoapMessage,
InformRequest,
AcsResponse,
Preset,
} from "./types";
import { IncomingMessage, ServerResponse } from "http";
import { Readable } from "stream";
@@ -431,7 +432,7 @@ async function applyPresets(sessionContext: SessionContext): Promise<void> {
}
const parameters: { [name: string]: Path } = {};
const filteredPresets = [];
const filteredPresets: Preset[] = [];
for (const preset of presets) {
if (whiteList != null) {
@@ -460,11 +461,24 @@ async function applyPresets(sessionContext: SessionContext): Promise<void> {
}
filteredPresets.push(preset);
for (const k of extractParams(preset.precondition)) {
for (const k of extractParams(
evaluate(preset.precondition, null, sessionContext.timestamp)
)) {
// Mark channel in case of fault during fetching precondition
sessionContext.channels[preset.channel] = 0;
if (typeof k === "string") parameters[k] = Path.parse(k);
}
for (const prov of preset.provisions) {
for (const arg of prov.slice(1)) {
for (const k of extractParams(
evaluate(arg, null, sessionContext.timestamp)
)) {
// Mark channel in case of fault during fetching precondition
sessionContext.channels[preset.channel] = 0;
if (typeof k === "string") parameters[k] = Path.parse(k);
}
}
}
}
const declarations = Object.values(parameters).map((v) => ({
@@ -501,12 +515,22 @@ async function applyPresets(sessionContext: SessionContext): Promise<void> {
session.configContextCallback(sessionContext, e)
)
) {
const provs = p.provisions.map((pp) => [
pp[0],
...pp
.slice(1)
.map((arg) =>
evaluate(arg, {}, sessionContext.timestamp, (e) =>
session.configContextCallback(sessionContext, e)
)
),
]);
if (blackList[p.channel] === 2) {
appendProvisionsToFaults[p.channel] = (
appendProvisionsToFaults[p.channel] || []
).concat(p.provisions);
).concat(provs);
} else {
session.addProvisions(sessionContext, p.channel, p.provisions);
session.addProvisions(sessionContext, p.channel, provs);
}
}
}
+3 -3
View File
@@ -18,7 +18,7 @@
*/
import { ObjectID } from "mongodb";
import { map, parse, stringify } from "./common/expression-parser";
import { map, parse, stringify, parseList } from "./common/expression-parser";
import { likePatternToRegExp, evaluate } from "./common/expression";
import { Expression, Fault, Task } from "./types";
@@ -593,7 +593,7 @@ export function flattenPreset(
) {
p.provision = provision.name;
p.provisionArgs = provision.args
? JSON.stringify(provision.args).slice(1, -1)
? provision.args.map((a) => stringify(a)).join(", ")
: "";
}
@@ -650,7 +650,7 @@ export function preProcessPreset(
};
if (preset.provisionArgs)
configuration.args = JSON.parse(`[${preset.provisionArgs}]`);
configuration.args = parseList(preset.provisionArgs as string);
delete preset.provision;
delete preset.provisionArgs;
+1 -1
View File
@@ -323,7 +323,7 @@ export interface Preset {
schedule?: { md5: string; duration: number; schedule: any };
events?: { [event: string]: boolean };
precondition?: Expression;
provisions: string[][];
provisions: [string, ...Expression[]][];
}
export interface Provisions {
+1 -1
View File
@@ -43,7 +43,7 @@ const attributes = [
{ id: "events", label: "Events" },
{ id: "precondition", label: "Precondition", type: "textarea" },
{ id: "provision", label: "Provision", type: "combo" },
{ id: "provisionArgs", label: "Arguments" },
{ id: "provisionArgs", label: "Arguments", type: "textarea" },
];
const unpackSmartQuery = memoize((query) => {