Skip to main content

neutrino_schema/
lib.rs

1//! Multi-database schema-to-Rust compiler pipeline.
2//!
3//! Introspects a live PostgreSQL, MySQL/MariaDB, or SQLite database, normalises
4//! column types into a database-agnostic Intermediate Representation
5//! ([`SchemaIR`]), and generates strongly typed Rust model structs.
6//!
7//! # Pipeline
8//!
9//! 1. **Introspect** — reads schema metadata via [`DatabaseIntrospector`]
10//! 2. **Normalise** — raw column types map to [`DbType`]; fields, tables,
11//!    constraints, enums, and indexes collect into [`SchemaIR`]
12//! 3. **Generate** — [`SchemaIR`] is consumed by [`generate()`] which returns
13//!    a [`GeneratedOutput`] containing file contents; the CLI writes them via
14//!    [`OutputWriter`]
15//!
16//! # Quick start (programmatic)
17//!
18//! ```rust,no_run
19//! use neutrino_schema::*;
20//!
21//! let tables = vec![
22//!     TableIR {
23//!         name: "users".into(),
24//!         fields: vec![FieldIR {
25//!             name: "email".into(),
26//!             ty: DbType::String,
27//!             nullable: false,
28//!             raw_type: "Varchar".into(),
29//!             default_value: None,
30//!             generated: false,
31//!             comment: None,
32//!         }],
33//!         constraints: vec![],
34//!         comment: None,
35//!         indexes: vec![],
36//!     },
37//! ];
38//!
39//! let schema = SchemaIR::from_tables(tables, RelationStrategy::NamingHeuristic);
40//!
41//! let output = generate(&schema, &GenerateOptions::default());
42//! let generated = output.file("users.rs").map(|f| &f.content[..]).unwrap_or("");
43//! assert!(generated.contains("pub struct Users"));
44//! ```
45//!
46//! # Quick start (CLI)
47//!
48//! ```bash
49//! # First run — creates neutrino-schema.toml
50//! neutrino-schema generate
51//! # → prompts for database URL, saves it, generates types
52//!
53//! # Subsequent runs — just works from config
54//! neutrino-schema generate
55//!
56//! # Explicit setup (CI / scripting)
57//! neutrino-schema init --database-url "postgres://localhost/mydb"
58//! neutrino-schema generate
59//!
60//! # All flags still work
61//! neutrino-schema generate --database-url "mysql://user:pass@localhost/mydb" --output src/entities
62//! ```
63
64pub mod codegen;
65pub mod config;
66pub mod inference;
67pub mod ir;
68pub mod types;
69pub mod util;
70pub mod validation;
71
72#[cfg(any(feature = "postgres", feature = "sqlite", feature = "mysql"))]
73pub mod introspect;
74
75#[cfg(feature = "cli")]
76pub mod cli;
77
78pub use codegen::{
79    generate, generate_enum_defs, generate_files, generate_files_with_registry, generate_imports,
80    generate_struct, GenerateOptions, GeneratedFile, GeneratedOutput, OutputWriter, RenderMode,
81    RustGeneratorConfig,
82};
83pub use ir::{
84    ConstraintIR, ConstraintKind, EnumIR, EnumVariantIR, FieldIR, IndexEntryIR, IndexIR, IndexKind,
85    MatchType, ReferentialAction, RelationCardinality, RelationIR, RelationInferenceStrategy,
86    RelationOrigin, RelationStrategy, SchemaIR, SemanticRelationIR, TableIR,
87};
88pub use validation::{validate, ValidationEntry, ValidationLevel, ValidationReport};
89pub use types::{
90    dbtype_to_rust, mysql_to_db_type, sqlite_declared_to_db_type, sqlite_to_db_type, to_db_type,
91    DbType, EnumRef, MysqlType, PgType, RustType, SqliteType, TypeRegistry,
92};
93pub use util::naming::{
94    deduplicate_identifier, enum_variant_name, sanitize_identifier, to_struct_name,
95};
96
97#[cfg(any(feature = "postgres", feature = "sqlite", feature = "mysql"))]
98pub use introspect::{Column, DatabaseIntrospector};
99
100#[cfg(feature = "postgres")]
101pub use introspect::PostgresIntrospector;
102
103#[cfg(feature = "sqlite")]
104pub use introspect::SqliteIntrospector;
105
106#[cfg(feature = "mysql")]
107pub use introspect::MysqlIntrospector;