Skip to main content

architect_sdk/config/
resolved.rs

1//! Resolved entity model: config validated and flattened for runtime use.
2
3use crate::config::types::{AssetColumnConfig, EntityEventTrigger};
4use crate::config::ValidationRule;
5use std::collections::{HashMap, HashSet};
6
7/// Direction of a related-include: to_one (we have FK to them) or to_many (they have FK to us).
8#[derive(Clone, Debug)]
9pub enum IncludeDirection {
10    ToOne,
11    ToMany,
12}
13
14/// Spec for including a related entity in list/read responses. Name is the related entity's path_segment (e.g. "orders", "users").
15#[derive(Clone, Debug)]
16pub struct IncludeSpec {
17    /// API name for the include (path_segment of the related entity).
18    pub name: String,
19    pub direction: IncludeDirection,
20    /// Path segment of the related entity (for lookup in model).
21    pub related_path_segment: String,
22    /// Our column used in the join (our FK for to_one; our PK for to_many).
23    pub our_key_column: String,
24    /// Their column used in the join (their PK for to_one; their FK for to_many).
25    pub their_key_column: String,
26}
27
28/// Primary key type for parsing path/body ids.
29#[derive(Clone, Debug)]
30pub enum PkType {
31    Uuid,
32    BigInt,
33    Int,
34    Text,
35}
36
37#[derive(Clone, Debug)]
38pub struct ColumnInfo {
39    pub name: String,
40    pub pk_type: Option<PkType>,
41    pub nullable: bool,
42    /// Whether the column has a DB default (e.g. gen_random_uuid(), NOW()).
43    pub has_default: bool,
44    /// PostgreSQL type name for SQL casts (e.g. "timestamptz") when binding string values.
45    pub pg_type: Option<String>,
46    /// True when the column was declared with type "asset" or "asset[]".
47    pub is_asset: bool,
48    /// True when the column was declared with type "asset[]" (stores a JSONB array of paths).
49    pub asset_is_array: bool,
50    /// Storage config for asset columns (prefix template, compression).
51    pub asset_config: Option<AssetColumnConfig>,
52}
53
54#[derive(Clone, Debug)]
55pub struct ResolvedEntity {
56    pub table_id: String,
57    pub schema_name: String,
58    pub table_name: String,
59    pub path_segment: String,
60    pub pk_columns: Vec<String>,
61    pub pk_type: PkType,
62    pub columns: Vec<ColumnInfo>,
63    pub operations: Vec<String>,
64    /// Column names to strip from all API responses (sensitive data).
65    pub sensitive_columns: HashSet<String>,
66    /// Available includes (related entities) for ?include= name1,name2. Built from relationships.
67    pub includes: Vec<IncludeSpec>,
68    pub validation: HashMap<String, ValidationRule>,
69    /// Decision-hub event triggers. Empty when no events are configured.
70    pub events: Vec<EntityEventTrigger>,
71    /// Column whose null→non-null transition signals an archive (for on:"archive" triggers).
72    pub archive_field: Option<String>,
73    /// Package id this entity belongs to. Set via ResolvedModel::with_package_id().
74    pub package_id: String,
75    /// When true, a companion `{table}_audit` table exists and every write is journaled there.
76    pub audit_log: bool,
77    /// Natural-key column used to resolve `parentRef` in bulk create (e.g. `"location_id"`).
78    pub parent_ref_column: Option<String>,
79}
80
81#[derive(Clone, Debug)]
82pub struct ResolvedModel {
83    pub entities: Vec<ResolvedEntity>,
84    pub entity_by_path: HashMap<String, ResolvedEntity>,
85}
86
87impl ResolvedModel {
88    pub fn entity_by_path(&self, path: &str) -> Option<&ResolvedEntity> {
89        self.entity_by_path.get(path)
90    }
91
92    /// Backfill `package_id` on all contained entities. Call this after `resolve()` when the
93    /// package id is known (e.g. from manifest.id or the route parameter).
94    pub fn with_package_id(mut self, package_id: &str) -> Self {
95        for e in &mut self.entities {
96            e.package_id = package_id.to_string();
97        }
98        for e in self.entity_by_path.values_mut() {
99            e.package_id = package_id.to_string();
100        }
101        self
102    }
103}