pub const SPEC_VERSION: &str = "1.0.0-draft";
pub mod analysis;
pub mod capability;
pub mod compatibility;
pub mod compile;
pub mod diagnostics;
pub mod lineage;
pub mod metadata;
pub mod model;
pub mod parser;
pub mod plan;
pub mod registry;
pub mod runtime;
pub mod validation;
pub mod versioning;
#[cfg(feature = "cli")]
pub mod cli;
#[cfg(feature = "python")]
mod python;
pub use analysis::{check_contract, check_expression, AnalysisFinding, AnalysisReport};
pub use capability::{
discover as discover_capabilities, match_plan, match_plan_with_registry, reference_profile,
CapabilityMatchReport, EngineCapabilityDeclaration,
};
pub use compatibility::{
analyze as analyze_compatibility, analyze_evolution, ChangeCategory, ComparisonScope,
CompatibilityLevel, CompatibilityReport, EvolutionReport,
};
pub use compile::{
compile, compile_after_match, compile_with_capability, validate as validate_execution_plan,
CompileResult, ExecutionPlan,
};
pub use diagnostics::{
codes, inspect_contract, Diagnostic, DiagnosticCategory, DiagnosticReport, DiagnosticStage,
Severity, ValidationReport,
};
pub use lineage::{analyze as analyze_lineage, LineageAnalysisReport, LineageGovernance};
pub use model::{
parse_logical_type, type_compatible, types_assignable, ExtensionCompatibility, LogicalType,
RegistryCategory, RegistryDocument, RegistryEntry, RegistryEntryStatus,
RegistryPublicationStatus, RegistryRef, Rule, RulePhase, TransformationContract,
TypeCompatibility, TypeParseError,
};
pub use parser::{parse, parse_file, parse_json, parse_yaml, DocumentFormat, ParseResult};
pub use plan::{
equivalent, equivalent as plan_equivalent, lower as lower_plan, optimize,
optimize as optimize_plan, validate as validate_plan, OptimizeOptions, OptimizeResult,
PlanResult, TransformationPlan,
};
pub use registry::{
default_registry, is_known_action, is_known_function, is_known_rule, load as load_registry,
load_merged, resolve as resolve_registry, resolve_default,
};
pub use runtime::{execute, ExecuteResult, RuntimeInputs, RuntimeOutputs, RuntimeValue};
pub use validation::{validate, validate_with_registry, ValidationPhase};
#[must_use]
pub fn parse_and_validate(content: &[u8], format: DocumentFormat) -> ValidationReport {
parse(content, format).validate()
}
#[must_use]
pub fn parse_validate_and_plan(content: &[u8], format: DocumentFormat) -> plan::PlanResult {
parse_validate_and_plan_with_registry(content, format, None)
}
#[must_use]
pub fn parse_validate_and_plan_with_registry(
content: &[u8],
format: DocumentFormat,
registry_path: Option<&std::path::Path>,
) -> plan::PlanResult {
let parse_result = parse(content, format);
let Some(contract) = parse_result.contract else {
return plan::PlanResult {
diagnostics: parse_result.report.diagnostics,
..plan::PlanResult::default()
};
};
let registry_doc = match registry_path {
Some(path) => match load_merged(path) {
Ok(merged) => merged,
Err(report) => {
return plan::PlanResult {
diagnostics: report.diagnostics,
..plan::PlanResult::default()
};
}
},
None => default_registry().clone(),
};
let validation = validate_with_registry(&contract, ®istry_doc);
if !validation.is_valid() {
return plan::PlanResult {
diagnostics: validation.diagnostics,
..plan::PlanResult::default()
};
}
let analysis = analysis::check_contract(&contract, Some(®istry_doc));
plan::lower(&contract, Some(®istry_doc), Some(&analysis))
}
#[must_use]
pub fn parse_validate_and_optimize(content: &[u8], format: DocumentFormat) -> plan::OptimizeResult {
parse_validate_and_optimize_with_registry(content, format, None)
}
#[must_use]
pub fn parse_validate_and_optimize_with_registry(
content: &[u8],
format: DocumentFormat,
registry_path: Option<&std::path::Path>,
) -> plan::OptimizeResult {
let plan_result = parse_validate_and_plan_with_registry(content, format, registry_path);
let Some(plan) = plan_result.plan else {
return plan::OptimizeResult {
diagnostics: plan_result.diagnostics,
..plan::OptimizeResult::default()
};
};
let registry_doc = match registry_path {
Some(path) => match load_merged(path) {
Ok(merged) => merged,
Err(report) => {
return plan::OptimizeResult {
diagnostics: report.diagnostics,
..plan::OptimizeResult::default()
};
}
},
None => default_registry().clone(),
};
let mut result =
plan::optimize_with_registry(&plan, ®istry_doc, &plan::OptimizeOptions::default());
result.diagnostics = plan_result
.diagnostics
.into_iter()
.chain(result.diagnostics)
.collect();
result
}
#[must_use]
pub fn parse_validate_and_compile(
content: &[u8],
format: DocumentFormat,
) -> compile::CompileResult {
parse_validate_and_compile_with_registry(content, format, None)
}
#[must_use]
pub fn parse_validate_and_compile_with_registry(
content: &[u8],
format: DocumentFormat,
registry_path: Option<&std::path::Path>,
) -> compile::CompileResult {
let plan_result = parse_validate_and_plan_with_registry(content, format, registry_path);
let Some(plan) = plan_result.plan else {
return compile::CompileResult {
diagnostics: plan_result.diagnostics,
..compile::CompileResult::default()
};
};
let mut result = compile::compile(&plan);
result.diagnostics = plan_result
.diagnostics
.into_iter()
.chain(result.diagnostics)
.collect();
result
}
#[must_use]
pub fn parse_validate_and_run(
content: &[u8],
format: DocumentFormat,
inputs: &runtime::RuntimeInputs,
) -> runtime::ExecuteResult {
parse_validate_and_run_with_registry(content, format, None, inputs)
}
#[must_use]
pub fn parse_validate_and_run_with_registry(
content: &[u8],
format: DocumentFormat,
registry_path: Option<&std::path::Path>,
inputs: &runtime::RuntimeInputs,
) -> runtime::ExecuteResult {
let compile_result = parse_validate_and_compile_with_registry(content, format, registry_path);
let Some(execution_plan) = compile_result.plan else {
return runtime::ExecuteResult {
diagnostics: compile_result.diagnostics,
..runtime::ExecuteResult::default()
};
};
let mut result = runtime::execute(&execution_plan, inputs);
result.diagnostics = compile_result
.diagnostics
.into_iter()
.chain(result.diagnostics)
.collect();
result
}
impl TransformationContract {
pub fn from_yaml(content: &str) -> ParseResult {
parse(content.as_bytes(), DocumentFormat::Yaml)
}
pub fn from_json(content: &str) -> ParseResult {
parse(content.as_bytes(), DocumentFormat::Json)
}
pub fn from_file(path: impl AsRef<std::path::Path>) -> miette::Result<ParseResult> {
parse_file(path)
}
}