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