tatara_render/backend.rs
1//! `Backend` trait — the morphism interface.
2//!
3//! Pleme-io's `arch-synthesizer/Backend` (the IaC-forge family)
4//! takes typed-IR resources and produces target-language source.
5//! This crate's `Backend` is the env-shaped variant: takes a
6//! `tatara_env::Env`, produces a list of typed `Manifest`s.
7
8use serde::{Deserialize, Serialize};
9use tatara_env::compile::Env;
10use thiserror::Error;
11
12#[derive(Debug, Error)]
13pub enum RenderError {
14 #[error("unsupported keyword `{0}` — backend has no renderer for this domain")]
15 Unsupported(String),
16 #[error("resource `{keyword}/{name}`: {message}")]
17 Resource {
18 keyword: String,
19 name: String,
20 message: String,
21 },
22 #[error("yaml emit: {0}")]
23 Yaml(String),
24}
25
26/// One rendered manifest. The `kind` is the target's idea of a
27/// document type (`yaml`, `helm-template`, `pangea-rb`,
28/// `terraform-json`); the `path` is where the manifest expects
29/// to land in a Kustomization-style tree; the `content` is the
30/// rendered bytes.
31#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
32pub struct Manifest {
33 /// Target document kind. Backends pick stable strings here
34 /// so downstream consumers can fan out per-kind.
35 pub kind: String,
36 /// Suggested filesystem path inside the output tree, e.g.
37 /// `gateways/production-gateway.yaml`. Backends produce paths
38 /// the typical FluxCD / Kustomize layout prefers.
39 pub path: String,
40 /// Rendered bytes. UTF-8 by convention for text targets.
41 pub content: String,
42}
43
44/// The morphism. Stateless by convention — backend impls hold
45/// only their config (e.g. namespace defaults, label conventions),
46/// not state derived from the env.
47pub trait Backend {
48 /// Render the env. Each domain handled by this backend
49 /// produces zero-or-more manifests; unhandled domains return
50 /// `RenderError::Unsupported` so the caller can decide
51 /// whether to fail-soft or fail-hard.
52 fn render(&self, env: &Env) -> Result<Vec<Manifest>, RenderError>;
53}