refactor: nested $json/$select syntax, migrate stored queries

This commit is contained in:
M1
2026-03-16 13:14:22 +04:00
parent ab2cbaa5cc
commit fe7a0bf19b
3 changed files with 46 additions and 55 deletions
+11 -11
View File
@@ -117,22 +117,22 @@ export function evaluate(query: unknown, ctx: EvalContext): boolean {
return evalCondition(q.$certExpiry, val);
}
// $select — CSS selector shorthand
// $select — { "$select": { "css.selector": { "$op": val } } }
if ("$select" in q) {
// Server-side: we don't have a DOM parser here, so we just validate structure.
// Actual evaluation happens in Rust runner. This returns true for validation purposes.
// Server-side: no DOM parser available, pass through (Rust runner evaluates)
// Validate structure only
const selMap = q.$select as Record<string, unknown>;
if (typeof selMap !== "object" || Array.isArray(selMap)) throw new Error("$select expects { selector: condition }");
return true;
}
// $json — JSONPath shorthand
// $json — { "$json": { "$.path": { "$op": val } } }
if ("$json" in q) {
const expr = q.$json as string;
const cond = q as Record<string, unknown>;
const resolved = resolveJsonPath(ctx.body, expr);
// Apply operators from remaining keys
for (const [op, opVal] of Object.entries(cond)) {
if (op === "$json") continue;
if (!evalOp(op, resolved, opVal)) return false;
const pathMap = q.$json as Record<string, unknown>;
if (typeof pathMap !== "object" || Array.isArray(pathMap)) throw new Error("$json expects { path: condition }");
for (const [path, condition] of Object.entries(pathMap)) {
const resolved = resolveJsonPath(ctx.body, path);
if (!evalCondition(condition, resolved)) return false;
}
return true;
}