noether-core 0.7.1

Noether core: type system, effects, content-addressed stage schema, Ed25519 signing, stdlib
Documentation
use crate::effects::{Effect, EffectSet};
use crate::stage::{Stage, StageBuilder};
use crate::types::NType;
use ed25519_dalek::SigningKey;
use serde_json::json;

pub fn stages(key: &SigningKey) -> Vec<Stage> {
    vec![
        StageBuilder::new("csv_parse")
            .input(NType::record([
                ("text", NType::Text),
                ("has_header", NType::optional(NType::Bool)),
                ("delimiter", NType::optional(NType::Text)),
            ]))
            .output(NType::List(Box::new(NType::Map {
                key: Box::new(NType::Text),
                value: Box::new(NType::Text),
            })))
            .effects(EffectSet::new([Effect::Pure, Effect::Fallible]))
            .description("Parse CSV text into a list of row maps")
            .example(json!({"text": "name,age\nAlice,30\nBob,25", "has_header": true, "delimiter": null}), json!([{"name": "Alice", "age": "30"}, {"name": "Bob", "age": "25"}]))
            .example(json!({"text": "a;b\n1;2", "has_header": true, "delimiter": ";"}), json!([{"a": "1", "b": "2"}]))
            .example(json!({"text": "x,y\n1,2\n3,4", "has_header": true, "delimiter": null}), json!([{"x": "1", "y": "2"}, {"x": "3", "y": "4"}]))
            .example(json!({"text": "a,b", "has_header": true, "delimiter": null}), json!([]))
            .example(json!({"text": "h1,h2\nv1,v2", "has_header": true, "delimiter": ","}), json!([{"h1": "v1", "h2": "v2"}]))
            .tag("data").tag("csv").tag("parsing").tag("pure")
            .alias("parse_csv").alias("read_csv").alias("csv_decode")
            .build_stdlib(key)
            .unwrap(),
        StageBuilder::new("csv_write")
            .input(NType::record([
                (
                    "records",
                    NType::List(Box::new(NType::Map {
                        key: Box::new(NType::Text),
                        value: Box::new(NType::Text),
                    })),
                ),
                ("delimiter", NType::optional(NType::Text)),
            ]))
            .output(NType::Text)
            .pure()
            .description("Serialize a list of row maps to CSV text")
            .example(json!({"records": [{"name": "Alice", "age": "30"}], "delimiter": null}), json!("age,name\n30,Alice"))
            .example(json!({"records": [{"a": "1", "b": "2"}], "delimiter": ";"}), json!("a;b\n1;2"))
            .example(json!({"records": [], "delimiter": null}), json!(""))
            .example(json!({"records": [{"x": "1"}, {"x": "2"}], "delimiter": null}), json!("x\n1\n2"))
            .example(json!({"records": [{"k": "v"}], "delimiter": ","}), json!("k\nv"))
            .tag("data").tag("csv").tag("pure")
            .alias("write_csv").alias("serialize_csv").alias("csv_encode")
            .build_stdlib(key)
            .unwrap(),
        StageBuilder::new("json_schema_validate")
            .input(NType::record([
                ("data", NType::Any),
                ("schema", NType::Any),
            ]))
            .output(NType::record([
                ("valid", NType::Bool),
                ("errors", NType::List(Box::new(NType::Text))),
            ]))
            .pure()
            .description("Validate data against a JSON schema; returns validation results")
            .example(json!({"data": {"name": "Alice"}, "schema": {"type": "object"}}), json!({"valid": true, "errors": []}))
            .example(json!({"data": 42, "schema": {"type": "string"}}), json!({"valid": false, "errors": ["expected string, got number"]}))
            .example(json!({"data": "hello", "schema": {"type": "string"}}), json!({"valid": true, "errors": []}))
            .example(json!({"data": [1, 2], "schema": {"type": "array"}}), json!({"valid": true, "errors": []}))
            .example(json!({"data": null, "schema": {"type": "null"}}), json!({"valid": true, "errors": []}))
            .tag("data").tag("validation").tag("json").tag("pure")
            .alias("jsonschema").alias("schema_check").alias("validate_json")
            .build_stdlib(key)
            .unwrap(),
        StageBuilder::new("arrow_from_records")
            .input(NType::List(Box::new(NType::Any)))
            .output(NType::Bytes)
            .effects(EffectSet::new([Effect::Fallible, Effect::NonDeterministic]))
            .description("Convert a list of records to Apache Arrow IPC bytes")
            .example(json!([{"a": 1}, {"a": 2}]), json!("QVJST1dfSVBD"))
            .example(json!([{"x": "hello"}]), json!("QVJST1dfSVBD"))
            .example(json!([]), json!("QVJST1dfRU1QVFk="))
            .example(json!([{"k": true}]), json!("QVJST1dfSVBD"))
            .example(json!([{"n": 9.81}]), json!("QVJST1dfSVBD"))
            .tag("data").tag("arrow").tag("analytics").tag("serialization")
            .alias("to_arrow").alias("records_to_ipc").alias("dataframe")
            .build_stdlib(key)
            .unwrap(),
        StageBuilder::new("records_to_arrow")
            .input(NType::Bytes)
            .output(NType::List(Box::new(NType::Map {
                key: Box::new(NType::Text),
                value: Box::new(NType::Any),
            })))
            .effects(EffectSet::new([Effect::Fallible, Effect::NonDeterministic]))
            .description("Decode Apache Arrow IPC bytes to a list of record maps")
            .example(json!("QVJST1dfSVBD"), json!([{"a": 1}, {"a": 2}]))
            .example(json!("QVJST1dfSVBD"), json!([{"x": "hello"}]))
            .example(json!("QVJST1dfRU1QVFk="), json!([]))
            .example(json!("QVJST1dfSVBD"), json!([{"k": true}]))
            .example(json!("QVJST1dfSVBD"), json!([{"n": 9.81}]))
            .tag("data").tag("arrow").tag("analytics").tag("serialization")
            .alias("from_arrow").alias("ipc_to_records").alias("decode_arrow")
            .build_stdlib(key)
            .unwrap(),
        StageBuilder::new("json_merge")
            .input(NType::record([
                ("base", NType::Any),
                ("patch", NType::Any),
            ]))
            .output(NType::Any)
            .pure()
            .description("Deep merge two JSON values; patch values override base")
            .example(json!({"base": {"a": 1}, "patch": {"b": 2}}), json!({"a": 1, "b": 2}))
            .example(json!({"base": {"a": 1}, "patch": {"a": 2}}), json!({"a": 2}))
            .example(json!({"base": {}, "patch": {"x": "y"}}), json!({"x": "y"}))
            .example(json!({"base": {"a": {"b": 1}}, "patch": {"a": {"c": 2}}}), json!({"a": {"b": 1, "c": 2}}))
            .example(json!({"base": [1, 2], "patch": [3]}), json!([3]))
            .tag("data").tag("json").tag("pure")
            .alias("merge_json").alias("deep_merge").alias("patch_json")
            .build_stdlib(key)
            .unwrap(),
        StageBuilder::new("json_path")
            .input(NType::record([
                ("data", NType::Any),
                ("path", NType::Text),
            ]))
            .output(NType::Any)
            .effects(EffectSet::new([Effect::Pure, Effect::Fallible]))
            .description("Extract a value from JSON data using a JSONPath expression")
            .example(json!({"data": {"a": {"b": 42}}, "path": "$.a.b"}), json!(42))
            .example(json!({"data": {"items": [1, 2, 3]}, "path": "$.items[0]"}), json!(1))
            .example(json!({"data": {"x": "hello"}, "path": "$.x"}), json!("hello"))
            .example(json!({"data": [10, 20, 30], "path": "$[1]"}), json!(20))
            .example(json!({"data": {"a": {"b": {"c": true}}}, "path": "$.a.b.c"}), json!(true))
            .tag("data").tag("json").tag("query").tag("pure")
            .alias("jsonpath").alias("jq").alias("json_query").alias("extract_field")
            .build_stdlib(key)
            .unwrap(),
    ]
}