ferriorm-codegen 0.1.5

Code generator for ferriorm ORM - generates type-safe Rust client code
Documentation
//! Generates the `client.rs` module containing the `FerriormClient` struct.
//!
//! `FerriormClient` is the user-facing entry point. It wraps a
//! `ferriorm_runtime::client::DatabaseClient` and exposes a method per model
//! (e.g., `.user()`, `.post()`) that returns the model's `Actions` struct
//! for performing CRUD operations.

use ferriorm_core::schema::Schema;
use ferriorm_core::utils::to_snake_case;
use proc_macro2::TokenStream;
use quote::{format_ident, quote};

/// Generate the `client.rs` module with the `FerriormClient` struct.
#[must_use]
pub fn generate_client_module(schema: &Schema) -> TokenStream {
    let model_accessors: Vec<TokenStream> = schema
        .models
        .iter()
        .map(|m| {
            let method_name = format_ident!("{}", to_snake_case(&m.name));
            let actions_type = format_ident!("{}Actions", m.name);
            let module_name = format_ident!("{}", to_snake_case(&m.name));

            quote! {
                pub fn #method_name(&self) -> super::#module_name::#actions_type<'_> {
                    super::#module_name::#actions_type::new(&self.inner)
                }
            }
        })
        .collect();

    quote! {
        #![allow(unused_imports, dead_code, unused_variables, clippy::all, clippy::pedantic, clippy::nursery)]

        use ferriorm_runtime::prelude::*;

        pub struct FerriormClient {
            inner: DatabaseClient,
        }

        impl FerriormClient {
            /// Connect to the database using the provided URL.
            pub async fn connect(url: &str) -> Result<Self, FerriormError> {
                let inner = DatabaseClient::connect(url).await?;
                Ok(Self { inner })
            }

            /// Connect to the database using the provided URL and pool configuration.
            pub async fn connect_with_config(url: &str, config: &PoolConfig) -> Result<Self, FerriormError> {
                let inner = DatabaseClient::connect_with_config(url, config).await?;
                Ok(Self { inner })
            }

            /// Get a reference to the underlying [`DatabaseClient`].
            ///
            /// Use this for raw SQL queries via `client().pg_pool()` or
            /// `client().sqlite_pool()`.
            pub fn client(&self) -> &DatabaseClient {
                &self.inner
            }

            #(#model_accessors)*

            /// Close the database connection.
            pub async fn disconnect(self) {
                self.inner.disconnect().await;
            }
        }
    }
}