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` / `metrics` *(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
61use icydb_core::{
62    error::{ErrorClass, ErrorOrigin, InternalError},
63    traits::Visitable,
64};
65use serde::{Serialize, de::DeserializeOwned};
66
67// crates
68pub use icydb_build as build;
69pub use icydb_build::build;
70pub use icydb_schema as schema;
71pub use icydb_schema_derive as macros;
72
73// core modules
74#[doc(hidden)]
75pub use icydb_core::{types, value};
76
77#[doc(hidden)]
78pub mod model {
79    pub mod entity {
80        pub use icydb_core::model::EntityModel;
81    }
82
83    pub mod field {
84        pub use icydb_core::model::{FieldKind, FieldModel, RelationStrength};
85    }
86
87    pub mod index {
88        pub use icydb_core::model::IndexModel;
89    }
90
91    pub use entity::EntityModel;
92    pub use field::FieldModel;
93    pub use index::IndexModel;
94}
95
96#[doc(hidden)]
97pub mod metrics {
98    pub use icydb_core::metrics::{EventReport, MetricsSink, metrics_report, metrics_reset_all};
99}
100
101pub mod patch {
102    pub use icydb_core::patch::{ListPatch, MapPatch, MergePatchError, SetPatch};
103}
104
105pub mod visitor {
106    pub use icydb_core::visitor::{
107        Issue, PathSegment, ScopedContext, VisitorContext, VisitorCore, VisitorError,
108        VisitorIssues, VisitorMutCore, perform_visit, perform_visit_mut,
109    };
110    pub use icydb_core::{sanitize::sanitize, validate::validate};
111}
112
113// facade modules
114pub mod base;
115pub mod db;
116pub mod error;
117pub mod traits;
118pub use error::Error;
119
120/// Macro/runtime wiring surface used by generated code.
121/// This is intentionally narrow and not semver-stable.
122#[doc(hidden)]
123pub mod __macro {
124    pub use icydb_core::db::{
125        DataStore, DbSession as CoreDbSession, EntityRuntimeHooks, IndexStore, StoreRegistry,
126    };
127    pub use icydb_core::traits::{
128        AsView as CoreAsView, CreateView as CoreCreateView, UpdateView as CoreUpdateView,
129    };
130}
131
132/// re-exports
133///
134/// macros can use these, stops the user having to specify all the dependencies
135/// in the Cargo.toml file manually
136///
137/// these have to be in icydb_core because of the base library not being able to import icydb
138#[doc(hidden)]
139pub mod __reexports {
140    pub use candid;
141    pub use canic_cdk;
142    pub use canic_memory;
143    pub use ctor;
144    pub use derive_more;
145    pub use icydb_derive;
146    pub use num_traits;
147    pub use remain;
148    pub use serde;
149}
150
151///
152/// Actor Prelude
153/// using _ brings traits into scope and avoids name conflicts
154///
155
156pub mod prelude {
157    pub use crate::{
158        db,
159        db::{
160            query,
161            query::{
162                FilterExpr, SortExpr,
163                builder::{
164                    FieldRef, count, count_by, exists, first, last, max, max_by, min, min_by, sum,
165                },
166                predicate::Predicate,
167            },
168        },
169        traits::{
170            AsView, Collection as _, Create, CreateView as _, EntityKind as _, EntityValue,
171            Inner as _, MapCollection as _, Path as _, Update, UpdateView as _, View,
172        },
173        types::*,
174        value::Value,
175    };
176    pub use candid::CandidType;
177    pub use serde::{Deserialize, Serialize};
178}
179
180///
181/// Design Prelude
182/// For schema/design code (macros, traits, base helpers).
183///
184
185pub mod design {
186    pub mod prelude {
187        pub use ::candid::CandidType;
188        pub use ::derive_more;
189
190        pub use crate::{
191            base, db,
192            db::query::builder::{
193                FieldRef, count, count_by, exists, first, last, max, max_by, min, min_by, sum,
194            },
195            macros::*,
196            traits::{
197                AsView, Collection as _, Create, CreateView, EntityKind, EntityValue as _,
198                FieldValue as _, Inner as _, MapCollection as _, Path as _, Sanitize as _,
199                Sanitizer, Serialize as _, Update, UpdateView, Validate as _, ValidateCustom,
200                Validator, View, Visitable as _,
201            },
202            types::*,
203            value::Value,
204            visitor::VisitorContext,
205        };
206    }
207}
208
209///
210/// -------------------------- CODE -----------------------------------
211///
212///
213/// Consts
214///
215
216/// Workspace version re-export for downstream tooling/tests.
217pub const VERSION: &str = env!("CARGO_PKG_VERSION");
218
219///
220/// Macros
221///
222
223/// Include the generated actor module emitted by `build!` (placed in `OUT_DIR/actor.rs`).
224#[macro_export]
225macro_rules! start {
226    () => {
227        // actor.rs
228        include!(concat!(env!("OUT_DIR"), "/actor.rs"));
229    };
230}
231
232/// Access the current canister's database session; use `db!().debug()` for verbose tracing.
233#[macro_export]
234#[expect(clippy::crate_in_macro_def)]
235macro_rules! db {
236    () => {
237        crate::db()
238    };
239}
240
241///
242/// Helpers
243///
244
245/// Run sanitization over a mutable visitable tree.
246pub fn sanitize(node: &mut dyn Visitable) -> Result<(), Error> {
247    icydb_core::sanitize::sanitize(node)
248        .map_err(InternalError::from)
249        .map_err(Error::from)
250}
251
252/// Validate a visitable tree, collecting issues by path.
253pub fn validate(node: &dyn Visitable) -> Result<(), Error> {
254    icydb_core::validate::validate(node)
255        .map_err(InternalError::from)
256        .map_err(Error::from)
257}
258
259/// Serialize a visitable value into bytes.
260///
261/// The encoding format is an internal detail of icydb and is only
262/// guaranteed to round-trip via `deserialize`.
263pub fn serialize<T>(ty: &T) -> Result<Vec<u8>, Error>
264where
265    T: Serialize,
266{
267    icydb_core::serialize::serialize(ty)
268        .map_err(|err| {
269            InternalError::new(
270                ErrorClass::Internal,
271                ErrorOrigin::Serialize,
272                err.to_string(),
273            )
274        })
275        .map_err(Error::from)
276}
277
278/// Deserialize bytes into a concrete visitable value.
279///
280/// This is intended for testing, tooling, and round-trip verification.
281/// It should not be used in hot runtime paths.
282pub fn deserialize<T>(bytes: &[u8]) -> Result<T, Error>
283where
284    T: DeserializeOwned,
285{
286    icydb_core::serialize::deserialize(bytes)
287        .map_err(|err| {
288            InternalError::new(
289                ErrorClass::Internal,
290                ErrorOrigin::Serialize,
291                err.to_string(),
292            )
293        })
294        .map_err(Error::from)
295}