dataflow-rs 4.0.1

A lightweight rules engine for building IFTTT-style automation and data processing pipelines in Rust. Define rules with JSONLogic conditions, execute actions, and chain workflows.
Documentation
//! Definitions: the authored form of workflows and tasks.
//!
//! A definition is plain data with raw expressions. It enters only through
//! [`parse`] or [`parse_owned`], which also lint: one walk over the authored JSON builds
//! a [`WorkflowDef`] and reports every issue at the path the author typed, at
//! v3's codes for v3's rules. With [`ParseOptions::compat`] on, the compat
//! reader rewrites v3's spellings first (see [`compat`](crate::compat)). A
//! definition serializes in the v4 spelling, which `parse` reads back with the
//! reader off.
//!
//! ```
//! use dataflow_rs::def::{ParseOptions, parse};
//! use dataflow_rs::program::IssueCode;
//! use serde_json::json;
//!
//! let parsed = parse(
//!     &json!({"id": "w", "tasks": [
//!         {"id": "t", "conditon": true, "function": {"name": "f"}}
//!     ]}),
//!     ParseOptions::default(),
//! );
//! // A near miss of a known key loads, kept in the task's `ext`, and is reported.
//! assert_eq!(parsed.issues[0].code, IssueCode::LikelyTypo);
//! assert_eq!(parsed.issues[0].path.to_string(), "tasks[0].conditon");
//! assert!(parsed.def.is_some());
//! ```

mod for_each;
pub(crate) mod keys;
mod loops;
mod parse;
pub(crate) mod reader;
mod rollout;
mod ser;
#[cfg(test)]
mod tests;
mod types;

pub use keys::{DefinitionKeys, definition_keys};
pub use parse::{ParseOptions, Parsed, parse, parse_owned};
pub(crate) use parse::{fragment_place, parse_steps, parse_with_rewrites};
pub use rollout::{Rollout, RolloutError};
pub use types::defaults;
pub use types::{
    FailurePolicy, ForEachDef, FunctionRef, GroupDef, Logic, LoopDef, NodeHeader, RejectionPolicy,
    Status, StepDef, TaskDef, WorkflowDef, WorkflowFailurePolicy,
};

/// The deepest group nesting a definition may use.
///
/// Depth counts enclosing groups: a top-level group is at depth 0, so groups
/// are accepted at depths `0..MAX_GROUP_DEPTH`, and a group at
/// `MAX_GROUP_DEPTH` is `GROUP_TOO_DEEP`.
pub const MAX_GROUP_DEPTH: usize = 8;

/// v3's alias for `validation`, which the compat reader rewrites and no
/// host function may take.
const V3_VALIDATE: &str = "validate";

/// The `validation` built-in's name, which the compat reader writes for
/// [`V3_VALIDATE`].
const VALIDATION: &str = "validation";

/// Whether no host function may be registered as `name`: a name in
/// [`BUILTIN_FUNCTIONS`], since a built-in cannot be shadowed, or `validate`,
/// 3.x's alias for `validation`, which the compat reader rewrites before any
/// name is looked up. [`Registry::register`](crate::Registry::register)
/// panics on one; a host that registers names from data checks them here
/// first.
///
/// ```
/// use dataflow_rs::def::is_reserved_function;
///
/// assert!(is_reserved_function("map") && is_reserved_function("validate"));
/// assert!(!is_reserved_function("http_call"));
/// ```
#[must_use]
pub fn is_reserved_function(name: &str) -> bool {
    BUILTIN_FUNCTIONS.contains(&name) || name == V3_VALIDATE
}

/// The built-in function names. They are reserved: no registration shadows
/// one, and a task running one cannot carry `for_each`, since a built-in runs
/// inline.
pub const BUILTIN_FUNCTIONS: [&str; 8] = [
    "map",
    "validation",
    "filter",
    "log",
    "parse_json",
    "parse_xml",
    "publish_json",
    "publish_xml",
];