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