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` / `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` / `ErrorKind` / `ErrorOrigin`
31//!   Shared error types for generated code and runtime boundaries.
32//!
33//! - `macros`
34//!   Derive macros for entities, canisters, and schema helpers.
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::{error::InternalError, traits::Visitable};
62// crates
63pub use icydb_build as build;
64pub use icydb_build::build;
65pub use icydb_schema as schema;
66pub use icydb_schema_derive as macros;
67
68// core modules
69#[doc(hidden)]
70pub use icydb_core::types;
71
72pub mod value {
73    pub use icydb_core::value::{
74        InputValue, InputValueEnum, OutputValue, OutputValueEnum, StorageKey,
75        StorageKeyDecodeError, StorageKeyEncodeError, ValueTag,
76    };
77}
78
79#[doc(hidden)]
80pub mod model {
81    pub mod entity {
82        pub use icydb_core::model::EntityModel;
83    }
84
85    pub mod field {
86        pub use icydb_core::model::{
87            EnumVariantModel, FieldDatabaseDefault, FieldInsertGeneration, FieldKind, FieldModel,
88            FieldStorageDecode, FieldWriteManagement, RelationStrength,
89        };
90    }
91
92    pub mod index {
93        pub use icydb_core::model::{
94            IndexExpression, IndexKeyItem, IndexKeyItemsRef, IndexModel, IndexPredicateMetadata,
95        };
96    }
97
98    pub use entity::EntityModel;
99    pub use field::{FieldDatabaseDefault, FieldModel};
100    pub use index::{IndexExpression, IndexModel};
101}
102
103#[doc(hidden)]
104pub mod metrics {
105    pub use icydb_core::metrics::{
106        EventCounters, EventReport, MetricsSink, metrics_report, metrics_reset_all,
107    };
108}
109
110pub mod visitor {
111    pub use icydb_core::visitor::{
112        Issue, PathSegment, SanitizeFieldDescriptor, ScopedContext, ValidateFieldDescriptor,
113        VisitableFieldDescriptor, VisitorContext, VisitorCore, VisitorError, VisitorIssues,
114        VisitorMutCore, drive_sanitize_fields, drive_validate_fields, drive_visitable_fields,
115        drive_visitable_fields_mut, perform_visit, perform_visit_mut,
116    };
117    pub use icydb_core::{
118        sanitize::{SanitizeWriteContext, SanitizeWriteMode, sanitize, sanitize_with_context},
119        validate::validate,
120    };
121}
122
123// facade modules
124pub mod base;
125pub mod db;
126mod error;
127pub mod traits;
128pub use error::{Error, ErrorKind, ErrorOrigin, QueryErrorKind, RuntimeErrorKind};
129
130/// Generic create-input alias for one entity type.
131pub type Create<E> = <E as icydb_core::traits::EntityCreateType>::Create;
132
133// Macro/runtime wiring surface used by generated code.
134// This is intentionally narrow and not semver-stable.
135#[doc(hidden)]
136pub mod __macro {
137    pub use crate::db::execute_generated_storage_report;
138    pub use icydb_core::__macro::{
139        GeneratedStructuralEnumPayload, GeneratedStructuralMapPayloadSlices,
140        decode_generated_structural_enum_payload_bytes,
141        decode_generated_structural_list_payload_bytes,
142        decode_generated_structural_map_payload_bytes,
143        decode_generated_structural_text_payload_bytes, decode_persisted_many_slot_payload_by_meta,
144        decode_persisted_option_scalar_slot_payload, decode_persisted_option_slot_payload_by_kind,
145        decode_persisted_option_slot_payload_by_meta, decode_persisted_scalar_slot_payload,
146        decode_persisted_slot_payload_by_kind, decode_persisted_slot_payload_by_meta,
147        decode_persisted_structured_many_slot_payload, decode_persisted_structured_slot_payload,
148        decode_schema_runtime_field_slot, encode_generated_structural_enum_payload_bytes,
149        encode_generated_structural_list_payload_bytes,
150        encode_generated_structural_map_payload_bytes,
151        encode_generated_structural_text_payload_bytes, encode_persisted_many_slot_payload_by_meta,
152        encode_persisted_option_scalar_slot_payload, encode_persisted_option_slot_payload_by_meta,
153        encode_persisted_scalar_slot_payload, encode_persisted_slot_payload_by_kind,
154        encode_persisted_slot_payload_by_meta, encode_persisted_structured_many_slot_payload,
155        encode_persisted_structured_slot_payload, encode_schema_runtime_field_slot,
156        generated_persisted_structured_payload_decode_failed,
157    };
158    pub use icydb_core::__macro::{PersistedScalar, ScalarSlotValueRef, ScalarValueRef};
159    #[cfg(feature = "sql")]
160    pub use icydb_core::db::LoweredSqlCommand;
161    pub use icydb_core::db::{
162        DataStore, DbSession as CoreDbSession, EntityRuntimeHooks, IndexStore, SchemaStore,
163        StoreRegistry,
164    };
165    pub use icydb_core::error::InternalError;
166    pub use icydb_core::traits::{
167        EnumValue, FieldProjection, PersistedByKindCodec, PersistedFieldMetaCodec,
168        PersistedFieldSlotCodec, PersistedStructuredFieldCodec, RuntimeValueDecode,
169        RuntimeValueEncode, RuntimeValueKind, RuntimeValueMeta, runtime_value_btree_map_from_value,
170        runtime_value_btree_set_from_value, runtime_value_collection_to_value,
171        runtime_value_from_value, runtime_value_from_vec_into,
172        runtime_value_from_vec_into_btree_map, runtime_value_from_vec_into_btree_set,
173        runtime_value_into, runtime_value_map_collection_to_value, runtime_value_to_value,
174        runtime_value_vec_from_value,
175    };
176    pub use icydb_core::value::{InputValue, Value, ValueEnum};
177}
178
179// re-exports
180//
181// macros can use these, stops the user having to specify all the dependencies
182// in the Cargo.toml file manually
183//
184// these have to be in icydb_core because of the base library not being able to import icydb
185#[doc(hidden)]
186pub mod __reexports {
187    pub use candid;
188    pub use canic_cdk;
189    pub use canic_memory;
190    pub use ctor;
191    pub use derive_more;
192    pub use icydb_derive;
193    pub use remain;
194    pub use serde;
195}
196
197//
198// Actor Prelude
199// using _ brings traits into scope and avoids name conflicts
200//
201
202pub mod prelude {
203    pub use crate::{
204        db,
205        db::{
206            query,
207            query::{
208                FieldRef, FilterExpr, FilterValue, OrderExpr, OrderTerm, asc, count, count_by,
209                desc, exists, field, first, last, max, max_by, min, min_by, sum,
210            },
211        },
212        traits::{
213            Collection as _, EntityKind as _, EntityValue, Inner as _, MapCollection as _,
214            Path as _,
215        },
216        types::*,
217        value::{InputValue, OutputValue},
218    };
219    pub use candid::CandidType;
220    pub use serde::{Deserialize, Serialize};
221}
222
223//
224// Design Prelude
225// For schema/design code (macros, traits, base helpers).
226//
227
228pub mod design {
229    pub mod prelude {
230        pub use ::candid::CandidType;
231        pub use ::derive_more;
232
233        pub use crate::{
234            base, db,
235            db::query::{
236                FieldRef, count, count_by, exists, first, last, max, max_by, min, min_by, sum,
237            },
238            macros::*,
239            traits::{
240                Collection as _, EntityKind, EntityValue as _, Inner as _, MapCollection as _,
241                Path as _, Sanitize as _, Sanitizer, Serialize as _, Validate as _, ValidateCustom,
242                Validator, Visitable as _,
243            },
244            types::*,
245            value::{InputValue, OutputValue},
246            visitor::VisitorContext,
247            visitor::{SanitizeWriteContext, SanitizeWriteMode},
248        };
249    }
250}
251
252//
253// -------------------------- CODE -----------------------------------
254//
255
256//
257// Consts
258//
259
260// Workspace version re-export for downstream tooling/tests.
261pub const VERSION: &str = env!("CARGO_PKG_VERSION");
262
263//
264// Macros
265//
266
267// Include the generated actor module emitted by `build!` (placed in `OUT_DIR/actor.rs`).
268#[macro_export]
269macro_rules! start {
270    () => {
271        // actor.rs
272        include!(concat!(env!("OUT_DIR"), "/actor.rs"));
273    };
274}
275
276// Access the current canister's database session; use `db!().debug()` for verbose tracing.
277#[macro_export]
278#[expect(clippy::crate_in_macro_def)]
279macro_rules! db {
280    () => {
281        crate::db()
282    };
283}
284
285//
286// Helpers
287//
288
289// Run sanitization over a mutable visitable tree.
290pub fn sanitize(node: &mut dyn Visitable) -> Result<(), Error> {
291    icydb_core::sanitize::sanitize(node)
292        .map_err(InternalError::from)
293        .map_err(Error::from)
294}
295
296// Validate a visitable tree, collecting issues by path.
297pub fn validate(node: &dyn Visitable) -> Result<(), Error> {
298    icydb_core::validate::validate(node)
299        .map_err(InternalError::from)
300        .map_err(Error::from)
301}