mod composite;
mod data;
mod fs;
pub mod known;
mod logic;
mod messaging;
mod trigger;
mod web;
use serde_json::{Map, Value};
use super::RewriteContext;
use super::graph::OldOutput;
use super::node::NodeRewrite;
pub use trigger::function_result;
pub type Config = Map<String, Value>;
#[derive(Clone, Copy)]
pub enum NewKind {
Fixed(&'static str),
By(fn(&Config) -> String),
Unprefixed,
}
#[derive(Clone, Copy)]
pub struct Rule {
pub new_kind: NewKind,
pub output: fn(&Config, &RewriteContext) -> OldOutput,
pub error_output: fn(&Config) -> OldOutput,
pub self_routed: bool,
pub code_keys: &'static [(&'static str, Code)],
pub rewrite: fn(&mut NodeRewrite<'_>),
}
impl Rule {
pub fn new(
new_kind: &'static str,
output: fn(&Config, &RewriteContext) -> OldOutput,
rewrite: fn(&mut NodeRewrite<'_>),
) -> Self {
Rule { new_kind: NewKind::Fixed(new_kind), output, error_output: engine_error, self_routed: false, code_keys: &[], rewrite }
}
pub fn by(
new_kind: fn(&Config) -> String,
output: fn(&Config, &RewriteContext) -> OldOutput,
rewrite: fn(&mut NodeRewrite<'_>),
) -> Self {
Rule { new_kind: NewKind::By(new_kind), output, error_output: engine_error, self_routed: false, code_keys: &[], rewrite }
}
pub fn code(mut self, keys: &'static [(&'static str, Code)]) -> Self {
self.code_keys = keys;
self
}
pub fn errors(mut self, error_output: fn(&Config) -> OldOutput) -> Self {
self.error_output = error_output;
self.self_routed = true;
self
}
pub fn kind_for(&self, old_kind: &str, config: &Config) -> String {
match self.new_kind {
NewKind::Fixed(kind) => kind.to_string(),
NewKind::By(f) => f(config),
NewKind::Unprefixed => old_kind.trim_start_matches("n.").to_string(),
}
}
pub fn unprefixed(mut self) -> Self {
self.new_kind = NewKind::Unprefixed;
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Code {
Expression,
ExpressionMap,
ChangedScope,
Body,
Foreign,
}
pub fn rule(kind: &str) -> Option<Rule> {
data::rule(kind)
.or_else(|| fs::rule(kind))
.or_else(|| trigger::rule(kind))
.or_else(|| logic::rule(kind))
.or_else(|| web::rule(kind))
.or_else(|| messaging::rule(kind))
.or_else(|| composite::rule(kind))
}
pub fn engine_error(_: &Config) -> OldOutput {
OldOutput::ErrorEnvelope
}
pub fn pass(_: &Config, _: &RewriteContext) -> OldOutput {
OldOutput::Pass
}
pub fn is_old_kind(kind: &str) -> bool {
kind.starts_with("n.")
}
pub fn engine_keys(n: &mut NodeRewrite<'_>) {
n.keep("title");
n.keep("preview");
n.keep("ui");
n.duration("timeout_secs", "timeout", "s");
}
pub fn words(value: &Value) -> Option<Vec<String>> {
super::node::word_list(value)
}
pub fn sql_keyword(sql: &str) -> String {
let mut rest = sql.trim_start();
loop {
if let Some(after) = rest.strip_prefix("--") {
rest = after.split_once('\n').map(|(_, r)| r).unwrap_or("").trim_start();
} else if let Some(after) = rest.strip_prefix("/*") {
rest = after.split_once("*/").map(|(_, r)| r).unwrap_or("").trim_start();
} else if let Some(after) = rest.strip_prefix('(') {
rest = after.trim_start();
} else {
break;
}
}
rest.split(|c: char| !c.is_ascii_alphabetic()).next().unwrap_or("").to_ascii_lowercase()
}