1extern crate self as icydb_model;
8
9pub mod application;
10pub mod base;
11pub mod build;
12pub mod error;
13pub mod fragment;
14#[cfg_attr(
18 target_arch = "wasm32",
19 allow(
20 dead_code,
21 reason = "Wasm retains declaration nodes while host code owns whole-graph traversal"
22 )
23)]
24pub mod node;
25pub mod normalize;
26#[cfg_attr(
27 target_arch = "wasm32",
28 expect(dead_code, reason = "whole-graph schema validation is host-owned")
29)]
30mod schema_validate;
31mod typed_adapter;
32pub mod types;
33pub mod validate;
34#[cfg_attr(
35 target_arch = "wasm32",
36 allow(
37 dead_code,
38 reason = "Wasm retains declarations while host code owns graph visitation"
39 )
40)]
41mod visit;
42pub mod visitor;
43
44pub const MAX_ENTITY_NAME_LEN: usize = 64;
46
47pub const MAX_FIELD_NAME_LEN: usize = 64;
49
50pub const MAX_INDEX_FIELDS: usize = 4;
52
53pub const MAX_INDEX_NAME_LEN: usize =
55 MAX_ENTITY_NAME_LEN + (MAX_INDEX_FIELDS * (1 + MAX_FIELD_NAME_LEN));
56
57use crate::{build::BuildError, node::NodeError};
58use thiserror::Error as ThisError;
59
60pub mod prelude {
62 pub(crate) use crate::build::schema_read;
63 pub use crate::{
64 EntitySource as _, Inner as _, NormalizeAndValidate as _, Path as _, base, canister,
65 entity, enum_, err,
66 error::ErrorTree,
67 list, map, newtype,
68 node::*,
69 normalizer, record,
70 schema::*,
71 set, store, tuple,
72 types::{Cardinality, Primitive},
73 validator,
74 visitor::{
75 Issue, Normalize as _, NormalizeAuto, NormalizeCustom, Normalizer as _, Validate as _,
76 ValidateAuto, ValidateCustom, Validator as _, Visitable as _, VisitorContext,
77 },
78 };
79 pub(crate) use crate::{
80 node::{MacroNode, ValidateNode, VisitableNode},
81 visit::Visitor,
82 };
83
84 pub use serde::{Deserialize, Serialize};
85}
86
87pub use application::NormalizeAndValidate;
88pub use icydb_model_macros::{
89 Add, AddAssign, Deref, DerefMut, Display, Div, DivAssign, Inner, Mul, MulAssign, Neg, Product,
90 Rem, RemAssign, Sub, SubAssign, Sum, canister, entity, enum_, list, map, newtype, normalizer,
91 record, set, store, tuple, validator,
92};
93pub use normalize::normalize;
94#[doc(hidden)]
95pub use typed_adapter::{
96 TypedAdapterContext, TypedEnumDescriptor, TypedEnumSelection, TypedInputValue, TypedNamedType,
97 TypedOutputValue, TypedScalarValue, TypedValueError,
98};
99pub use validate::validate;
100
101pub trait Path {
103 const PATH: &'static str;
105}
106
107pub trait EntitySource {
113 const ENTITY: &'static str;
115}
116
117pub trait Inner<T> {
119 fn inner(&self) -> &T;
121
122 fn into_inner(self) -> T;
124}
125
126pub mod schema {
128 pub use icydb_schema::*;
129}
130
131#[doc(hidden)]
133pub mod __reexports {
134
135 #[cfg(not(target_arch = "wasm32"))]
136 pub use ctor;
137 pub use icydb_model_macros;
138 pub use remain;
139 pub use serde;
140}
141
142#[derive(Debug, ThisError)]
149pub enum Error {
150 #[error(transparent)]
151 BuildError(#[from] BuildError),
152
153 #[error(transparent)]
154 NodeError(#[from] NodeError),
155}
156
157#[cfg(test)]
162mod tests {
163 use super::{Error, build::BuildError, error::ErrorTree, node::NodeError};
164
165 #[test]
166 fn build_errors_remain_in_build_boundary() {
167 let schema_error = Error::from(BuildError::Validation(ErrorTree::from(
168 "missing schema relation target",
169 )));
170
171 match schema_error {
172 Error::BuildError(BuildError::Validation(tree)) => {
173 assert!(
174 tree.messages()
175 .iter()
176 .any(|message| message == "missing schema relation target"),
177 "build validation errors must remain wrapped as build-boundary failures",
178 );
179 }
180 Error::BuildError(BuildError::Graph(error)) => {
181 panic!("unexpected graph error: {error}");
182 }
183 Error::NodeError(_) => {
184 panic!("build validation failures must not be remapped into node-boundary errors");
185 }
186 }
187 }
188
189 #[test]
190 fn node_errors_remain_in_node_boundary() {
191 let schema_error = Error::from(NodeError::PathNotFound("entity.user_id".to_string()));
192
193 match schema_error {
194 Error::NodeError(NodeError::PathNotFound(path)) => {
195 assert_eq!(path, "entity.user_id");
196 }
197 Error::NodeError(NodeError::IncorrectNodeType(path)) => {
198 panic!("unexpected node error kind after conversion for path {path}");
199 }
200 Error::BuildError(_) => {
201 panic!("node errors must not be remapped into build-boundary failures");
202 }
203 }
204 }
205}