Skip to main content

icydb/
lib.rs

1//! # icydb
2//!
3//! `icydb` is the **public facade crate** for the IcyDB runtime.
4//! It is the recommended dependency for downstream canister projects.
5//!
6//! This crate exposes:
7//! - the stable runtime surface used inside canister actor code,
8//! - schema and design-time helpers for macros and validation,
9//! - and a small set of macros and entry points that wire generated code.
10//!
11//! Low-level execution, storage, and engine internals live in
12//! `icydb-core` and are re-exposed selectively through stable facade modules.
13//!
14//! ## Crate layout
15//!
16//! - `base`
17//!   Design-time helpers, sanitizers, and validators used by schemas and macros.
18//!
19//! - `build`
20//!   Internal code generation helpers used by macros and tests
21//!   (not intended for direct use).
22//!
23//! - `traits` / `types` / `value` / `view` / `visitor`
24//!   Stable runtime and schema-facing building blocks used by generated code.
25//!
26//! - `model` / `obs` *(internal)*
27//!   Runtime model and metrics internals. Exposed for advanced tooling only;
28//!   not part of the supported semver surface.
29//!
30//! - `error`
31//!   Shared error types for generated code and runtime boundaries.
32//!
33//! - `macros`
34//!   Derive macros for entities, schemas, and views.
35//!
36//! - `schema`
37//!   Schema AST, builders, and validation utilities.
38//!
39//! - `db`
40//!   The public database façade: session handles, query builders,
41//!   and typed responses.
42//!
43//! ## Preludes
44//!
45//! - `prelude`
46//!   Opinionated runtime prelude for canister actor code.
47//!   Intended to be glob-imported in `lib.rs` to keep endpoints concise.
48//!
49//! - `design::prelude`
50//!   Prelude for schema and design-time code (macros, validators,
51//!   and base helpers).
52//!
53//! ## Internal boundaries
54//!
55//! Generated code targets explicit facade surfaces (`traits`, `patch`,
56//! and `__macro`) instead of a broad internal-export module.
57
58// export so things just work in base/
59extern crate self as icydb;
60
61// crates
62pub use icydb_build as build;
63pub use icydb_build::build;
64pub use icydb_schema as schema;
65pub use icydb_schema_derive as macros;
66
67// core modules
68#[doc(hidden)]
69pub use icydb_core::{types, value};
70
71#[doc(hidden)]
72pub mod model {
73    pub mod entity {
74        pub use icydb_core::model::EntityModel;
75    }
76
77    pub mod field {
78        pub use icydb_core::model::{FieldKind, FieldModel, RelationStrength};
79    }
80
81    pub mod index {
82        pub use icydb_core::model::IndexModel;
83    }
84
85    pub use entity::EntityModel;
86    pub use field::FieldModel;
87    pub use index::IndexModel;
88}
89
90#[doc(hidden)]
91pub mod obs {
92    pub use icydb_core::obs::{
93        EventReport, MetricsSink, StorageReport, metrics_report, metrics_reset_all, storage_report,
94    };
95}
96
97pub mod patch {
98    pub use icydb_core::patch::{ListPatch, MapPatch, MergePatchError, SetPatch};
99}
100
101pub mod visitor {
102    pub use icydb_core::visitor::{
103        Issue, PathSegment, ScopedContext, VisitorContext, VisitorCore, VisitorError,
104        VisitorIssues, VisitorMutCore, perform_visit, perform_visit_mut,
105    };
106    pub use icydb_core::{sanitize::sanitize, validate::validate};
107}
108
109// facade modules
110pub mod base;
111pub mod db;
112pub mod error;
113pub mod traits;
114pub use error::Error;
115
116/// Macro/runtime wiring surface used by generated code.
117/// This is intentionally narrow and not semver-stable.
118#[doc(hidden)]
119pub mod __macro {
120    pub use icydb_core::db::{
121        DataStore, Db, EntityRuntimeHooks, IndexStore, StoreRegistry,
122        validate_delete_strong_relations_for_source,
123    };
124    pub use icydb_core::traits::{
125        AsView as CoreAsView, CreateView as CoreCreateView, UpdateView as CoreUpdateView,
126    };
127}
128
129/// re-exports
130///
131/// macros can use these, stops the user having to specify all the dependencies
132/// in the Cargo.toml file manually
133///
134/// these have to be in icydb_core because of the base library not being able to import icydb
135#[doc(hidden)]
136pub mod __reexports {
137    pub use candid;
138    pub use canic_cdk;
139    pub use canic_memory;
140    pub use ctor;
141    pub use derive_more;
142    pub use icydb_derive;
143    pub use num_traits;
144    pub use remain;
145    pub use serde;
146}
147
148///
149/// Actor Prelude
150/// using _ brings traits into scope and avoids name conflicts
151///
152
153pub mod prelude {
154    pub use crate::{
155        db,
156        db::{
157            query,
158            query::{
159                FilterExpr, SortExpr,
160                builder::{
161                    FieldRef, count, count_by, exists, first, last, max, max_by, min, min_by, sum,
162                },
163                predicate::Predicate,
164            },
165        },
166        traits::{
167            AsView, Collection as _, Create, CreateView as _, EntityKind as _, EntityValue,
168            Inner as _, MapCollection as _, Path as _, Update, UpdateView as _, View,
169        },
170        types::*,
171        value::Value,
172    };
173    pub use candid::CandidType;
174    pub use serde::{Deserialize, Serialize};
175}
176
177///
178/// Design Prelude
179/// For schema/design code (macros, traits, base helpers).
180///
181
182pub mod design {
183    pub mod prelude {
184        pub use ::candid::CandidType;
185        pub use ::derive_more;
186
187        pub use crate::{
188            base, db,
189            db::query::builder::{
190                FieldRef, count, count_by, exists, first, last, max, max_by, min, min_by, sum,
191            },
192            macros::*,
193            traits::{
194                AsView, Collection as _, Create, CreateView, EntityKind, EntityValue as _,
195                FieldValue as _, Inner as _, MapCollection as _, Path as _, Sanitize as _,
196                Sanitizer, Serialize as _, Update, UpdateView, Validate as _, ValidateCustom,
197                Validator, View, Visitable as _,
198            },
199            types::*,
200            value::Value,
201            visitor::VisitorContext,
202        };
203    }
204}
205
206///
207/// -------------------------- CODE -----------------------------------
208///
209use icydb_core::{
210    error::{ErrorClass, ErrorOrigin, InternalError},
211    traits::Visitable,
212};
213use serde::{Serialize, de::DeserializeOwned};
214
215///
216/// Consts
217///
218
219/// Workspace version re-export for downstream tooling/tests.
220pub const VERSION: &str = env!("CARGO_PKG_VERSION");
221
222///
223/// Macros
224///
225
226/// Include the generated actor module emitted by `build!` (placed in `OUT_DIR/actor.rs`).
227#[macro_export]
228macro_rules! start {
229    () => {
230        // actor.rs
231        include!(concat!(env!("OUT_DIR"), "/actor.rs"));
232    };
233}
234
235/// Access the current canister's database session; use `db!().debug()` for verbose tracing.
236#[macro_export]
237#[expect(clippy::crate_in_macro_def)]
238macro_rules! db {
239    () => {
240        crate::db()
241    };
242}
243
244///
245/// Helpers
246///
247
248/// Run sanitization over a mutable visitable tree.
249pub fn sanitize(node: &mut dyn Visitable) -> Result<(), Error> {
250    icydb_core::sanitize::sanitize(node)
251        .map_err(InternalError::from)
252        .map_err(Error::from)
253}
254
255/// Validate a visitable tree, collecting issues by path.
256pub fn validate(node: &dyn Visitable) -> Result<(), Error> {
257    icydb_core::validate::validate(node)
258        .map_err(InternalError::from)
259        .map_err(Error::from)
260}
261
262/// Serialize a visitable value into bytes.
263///
264/// The encoding format is an internal detail of icydb and is only
265/// guaranteed to round-trip via `deserialize`.
266pub fn serialize<T>(ty: &T) -> Result<Vec<u8>, Error>
267where
268    T: Serialize,
269{
270    icydb_core::serialize::serialize(ty)
271        .map_err(|err| {
272            InternalError::new(
273                ErrorClass::Internal,
274                ErrorOrigin::Serialize,
275                err.to_string(),
276            )
277        })
278        .map_err(Error::from)
279}
280
281/// Deserialize bytes into a concrete visitable value.
282///
283/// This is intended for testing, tooling, and round-trip verification.
284/// It should not be used in hot runtime paths.
285pub fn deserialize<T>(bytes: &[u8]) -> Result<T, Error>
286where
287    T: DeserializeOwned,
288{
289    icydb_core::serialize::deserialize(bytes)
290        .map_err(|err| {
291            InternalError::new(
292                ErrorClass::Internal,
293                ErrorOrigin::Serialize,
294                err.to_string(),
295            )
296        })
297        .map_err(Error::from)
298}