cratestack/lib.rs
1//! CrateStack server facade for procedures-only, no-database services.
2//!
3//! This crate is the `db = None` slice of the framework (epic #326). It
4//! re-exports the shared schema / parser / policy / SQL surface plus the
5//! Axum HTTP bindings and the generated Rust client runtime — everything a
6//! `datasource { provider = "none" }` server needs for routing, procedure
7//! dispatch, and REST/RPC transport, minus a database backend.
8//!
9//! It deliberately does **not** depend on `cratestack-sqlx` — not behind a
10//! feature flag, genuinely absent from `Cargo.toml`. `datasource { provider
11//! = "none" }` schemas can never declare a `model` (enforced at parse time,
12//! cratestack#327), and `db = Postgres` codegen is the only path that ever
13//! references sqlx-backed symbols (`::cratestack::sqlx::PgPool`, the
14//! `Json<T>` sqlx variant, `SqlxRuntime`, …) — so a facade that structurally
15//! never has those symbols to offer can only ever support `db = None`. A
16//! schema compiled with `include_server_schema!(schema, db = Postgres)`
17//! under this crate fails to compile with a single, clear `compile_error!`
18//! (cratestack#347's `guard_server_postgres_backend`, in
19//! `cratestack-macros/src/include/datasource_guard.rs`) rather than a wall
20//! of unrelated "cannot find `sqlx`/`SqlxRuntime` in `cratestack`" errors —
21//! see this crate's `README.md` for the exact reproduction and transcript.
22//!
23//! For the same reason, this crate also does not depend on `cratestack-grpc`
24//! or `prost`. `transport grpc` codegen is entirely model-driven — CRUD
25//! routes generated per `model` block — and procedures are not (yet) wired
26//! into the generated gRPC service at all (see
27//! `crates/cratestack-macros/src/include/server/grpc/mod.rs`). Since
28//! `db = None` schemas can never declare a model, a `transport grpc` schema
29//! paired with `db = None` could only ever produce a gRPC service with zero
30//! methods — there is nothing useful gRPC adds here, so the dependency
31//! (`tonic`/`prost` and everything they pull in) is left out entirely
32//! rather than kept around unused. `transport rpc` and REST (the default)
33//! both work fully under `db = None` — see `docs/design/rpc-transport.md`
34//! and `docs/design/no-database-mode.md`.
35//!
36//! `cratestack-pg` (with `default-features = false` to drop its `postgres`
37//! feature) also supports `db = None` and continues to work — this crate
38//! doesn't replace that path, it just names the "I never touch Postgres"
39//! case directly instead of asking a consumer to depend on a crate named
40//! for the database backend they're explicitly opting out of.
41//!
42//! Schema macros emit `::cratestack::*` paths, so consumers rename this
43//! crate via Cargo's `package =` field:
44//!
45//! ```toml
46//! [dependencies]
47//! cratestack = { package = "cratestack-api", version = "0.6" }
48//! ```
49//!
50//! ```ignore
51//! cratestack::include_server_schema!("schema/foo.cstack", db = None);
52//! ```
53//!
54//! See `docs/design/no-database-mode.md` for the full `db = None` design
55//! and this crate's `README.md` for a quick-start.
56
57// Both `cratestack_core` and `cratestack_axum` expose `codec` and
58// `transport` modules, and this facade re-exports both crates with a glob.
59// The overlap is intentional — consumers reach those via the originating
60// crate's path, not the facade root — so silence the ambiguity warning
61// rather than dropping either glob. Mirrors `cratestack-pg`.
62#![allow(ambiguous_glob_reexports)]
63
64// Re-exported so the axum dispatch tokens `cratestack-macros` generates for
65// `@stream` procedures (`crate::axum::procedure::invoke_call`) can reference
66// `::cratestack::async_stream::stream!` without every consumer adding
67// `async-stream` to their own `Cargo.toml`. See `cratestack-pg`'s doc
68// comment for the full lifetime-capture rationale — identical here, since
69// `@stream` procedures are shared codegen, not `db`-conditional.
70pub use async_stream;
71pub use chrono;
72pub use cratestack_client_rust as client_rust;
73pub use cratestack_core::*;
74// Re-exported (renamed from the `futures-util` crate, which is what
75// actually implements it) so `@stream` procedures' generated
76// `ProcedureRegistry` trait method has somewhere to point without every
77// consumer adding its own `futures`/`futures-core`/`futures-util`
78// dependency. Mirrors `cratestack-pg`.
79pub use cratestack_macros::{
80 include_client_schema, include_embedded_schema, include_server_schema,
81};
82pub use cratestack_parser::{SchemaError, parse_schema, parse_schema_file, parse_schema_named};
83pub use cratestack_policy::{
84 PolicyExpr, PolicyLiteral, ProcedureArgs, ProcedurePolicy, ProcedurePolicyExpr,
85 ProcedurePolicyLiteral, ProcedurePredicate, ReadPolicy, ReadPredicate, RelationQuantifier,
86 authorize_procedure,
87};
88pub use futures_util as futures;
89
90// SQL primitives shared by every backend — re-exported directly from
91// `cratestack-sql` so consumers don't transit through a runtime crate.
92// `db = None` schemas never construct these (no models), but procedure
93// codegen references some of the same shared descriptor types, so this
94// mirrors `cratestack-pg`'s re-export list rather than trimming it.
95pub use cratestack_sql::{
96 CoalesceExpr, CoalesceFilter, ConflictTarget, CreateDefault, CreateDefaultType,
97 CreateModelInput, FieldRef, Filter, FilterExpr, FilterOp, IntoColumnName, IntoSqlValue,
98 JsonFilter, JsonTextPath, ModelColumn, ModelDescriptor, ModelPrimaryKey, NullOrder,
99 OrderCatalog, OrderClause, OrderRelationEdge, Orderable, Projection, ReadSource,
100 RelationFilter, RelationHop, RelationInclude, ResolvedOrderTarget, SortDirection,
101 SpatialFilter, SpatialPoint, SqlColumnValue, SqlValue, Unorderable, UpdateModelInput,
102 UpsertModelInput, VectorDistanceExpr, VectorDistanceFilter, VectorMetric, ViewDescriptor,
103 WriteSource, coalesce, is_orderable, order_value_sql, point, resolve_order_target, wrap_filter,
104};
105
106pub use regex;
107pub use serde;
108pub use serde_json;
109pub use tracing;
110pub use uuid;
111
112// `Json<T>` is a serde-only newtype here — there is no `postgres` feature
113// to switch on, and there never will be: `cratestack-sqlx` is not a
114// dependency of this crate under any feature. `db = None` schemas only ever
115// need a codec-friendly `Json<T>` for procedure args/returns (never
116// `sqlx::FromRow` row decoding, since models can't exist), so this is the
117// only `Json` this crate ever needs to offer. Compare `cratestack-pg`,
118// which switches between this same type and `cratestack_sqlx::sqlx::types::
119// Json` behind its `postgres` feature.
120pub use cratestack_core::json::Json;
121
122// -----------------------------------------------------------------------------
123// Server surface — axum, audit/idempotency/isolation. No migrations module:
124// that's sqlx (Postgres schema migrations)-only and has no `db = None`
125// equivalent (there is no schema to migrate without a database).
126// -----------------------------------------------------------------------------
127
128pub use cratestack_axum::axum;
129pub use cratestack_axum::*;
130
131// Disambiguate the `rpc` module path. Both `cratestack_core` (wire shapes)
132// and `cratestack_axum` (binding helpers) expose an `rpc` module, so the two
133// `pub use ..::*` globs collide on the name and `::cratestack::rpc::*`
134// resolves non-deterministically. Macro-emitted code in `transport rpc`
135// schemas references symbols like `encode_rpc_error`,
136// `convert_handler_error_response`, `response_to_frame`, and
137// `RPC_BINDING_CAPABILITIES` — all of which live in `cratestack-axum::rpc`.
138// An explicit `pub use` re-export takes precedence over the globs, pinning
139// `::cratestack::rpc` to the axum module. Mirrors `cratestack-pg`.
140pub use cratestack_axum::rpc;
141
142#[doc(hidden)]
143pub mod __private {
144 /// Re-exports for the macro-emitted RPC batch dispatcher
145 /// (`crates/cratestack-macros/src/include/server/rpc_module/batch.rs`).
146 /// Not part of the public API surface — schema authors should never
147 /// reference these directly. Public helpers live at
148 /// `cratestack::rpc::*`.
149 ///
150 /// `bridge_grpc_response` is deliberately **not** re-exported here —
151 /// it's `transport grpc`-only, and this crate doesn't support gRPC (see
152 /// this module's parent doc comment). `SqlxRuntime` is likewise absent
153 /// — it's the `db = Postgres` runtime handle, which this crate cannot
154 /// offer without `cratestack-sqlx`.
155 pub use cratestack_axum::rpc::{decode_rpc_body, encode_rpc_value, response_to_frame};
156}