cornucopia/
lib.rs

1mod cli;
2mod codegen;
3mod error;
4mod load_schema;
5mod parser;
6mod prepare_queries;
7mod read_queries;
8mod type_registrar;
9mod utils;
10mod validation;
11
12/// Helpers to establish connections to database instances.
13pub mod conn;
14/// High-level interfaces to work with Cornucopia's container manager.
15pub mod container;
16
17use postgres::Client;
18
19use codegen::generate as generate_internal;
20use error::WriteOutputError;
21use parser::parse_query_module;
22use prepare_queries::prepare;
23use read_queries::read_query_modules;
24
25#[doc(hidden)]
26pub use cli::run;
27
28pub use error::Error;
29pub use load_schema::load_schema;
30
31/// Struct containing the settings for code generation.
32#[derive(Clone, Copy)]
33pub struct CodegenSettings {
34    pub is_async: bool,
35    pub derive_ser: bool,
36}
37
38/// Generates Rust queries from PostgreSQL queries located at `queries_path`,
39/// using a live database managed by you. If some `destination` is given,
40/// the generated code will be written at that path. Code generation settings are
41/// set using the `settings` parameter.
42pub fn generate_live(
43    client: &mut Client,
44    queries_path: &str,
45    destination: Option<&str>,
46    settings: CodegenSettings,
47) -> Result<String, Error> {
48    // Read
49    let modules = read_query_modules(queries_path)?
50        .into_iter()
51        .map(parse_query_module)
52        .collect::<Result<_, parser::error::Error>>()?;
53    // Generate
54    let prepared_modules = prepare(client, modules)?;
55    let generated_code = generate_internal(prepared_modules, settings);
56    // Write
57    if let Some(d) = destination {
58        write_generated_code(d, &generated_code)?;
59    };
60
61    Ok(generated_code)
62}
63
64/// Generates Rust queries from PostgreSQL queries located at `queries_path`, using
65/// a container managed by cornucopia. The database schema is created using `schema_files`.
66/// If some `destination` is given, the generated code will be written at that path.
67/// Code generation settings are set using the `settings` parameter.
68///
69/// By default, the container manager is Docker, but Podman can be used by setting the
70/// `podman` parameter to `true`.
71pub fn generate_managed(
72    queries_path: &str,
73    schema_files: Vec<String>,
74    destination: Option<&str>,
75    podman: bool,
76    settings: CodegenSettings,
77) -> Result<String, Error> {
78    // Read
79    let modules = read_query_modules(queries_path)?
80        .into_iter()
81        .map(parse_query_module)
82        .collect::<Result<_, parser::error::Error>>()?;
83    container::setup(podman)?;
84    let mut client = conn::cornucopia_conn()?;
85    load_schema(&mut client, schema_files)?;
86    let prepared_modules = prepare(&mut client, modules)?;
87    let generated_code = generate_internal(prepared_modules, settings);
88    container::cleanup(podman)?;
89
90    if let Some(destination) = destination {
91        write_generated_code(destination, &generated_code)?;
92    };
93
94    Ok(generated_code)
95}
96
97fn write_generated_code(destination: &str, generated_code: &str) -> Result<(), Error> {
98    Ok(
99        std::fs::write(destination, generated_code).map_err(|err| WriteOutputError {
100            err,
101            file_path: String::from(destination),
102        })?,
103    )
104}