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