1use pyo3::prelude::*;
2use pyo3::types::PyDict;
3use std::path::PathBuf;
4
5use crate::config::ProjectConfig;
6
7mod config;
8mod engine;
9
10macro_rules! extract_config {
12 ($dict:expr, $key:literal, required) => {{
14 if let Some(value) = $dict.get_item($key)? {
15 value.extract()?
16 } else {
17 return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>(concat!(
18 $key,
19 " is required"
20 )));
21 }
22 }};
23
24 ($dict:expr, $key:literal, $default:expr) => {{
26 if let Some(value) = $dict.get_item($key)? {
27 value.extract()?
28 } else {
29 $default
30 }
31 }};
32}
33
34#[pyfunction]
35fn get_crate_version() -> String {
36 env!("CARGO_PKG_VERSION").to_string()
37}
38
39#[pyfunction]
41fn run_engine(config_dict: &Bound<'_, PyDict>) -> PyResult<bool> {
42 let project_name: String = extract_config!(config_dict, "project_name", required);
44 let destination: String = extract_config!(config_dict, "destination", ".".to_string());
45 let destination_path = PathBuf::from(destination);
46
47 let author_name: String = extract_config!(config_dict, "author_name", "Test User".to_string());
49 let author_email: String =
50 extract_config!(config_dict, "author_email", "test@example.com".to_string());
51
52 let db_name: Option<String> = extract_config!(
53 config_dict,
54 "db_name",
55 Some(project_name.to_lowercase().replace('-', "_"))
56 );
57
58 let db_owner_admin: Option<String> = extract_config!(
59 config_dict,
60 "db_owner_admin",
61 Some(format!(
62 "{}_owner",
63 project_name.to_lowercase().replace('-', "_")
64 ))
65 );
66
67 let db_owner_pword: Option<String> =
68 extract_config!(config_dict, "db_owner_pword", Some("password".to_string()));
69
70 let include_server: bool = extract_config!(config_dict, "include_server", true);
71 let include_frontend: bool = extract_config!(config_dict, "include_frontend", true);
72 let include_tauri_desktop: bool = extract_config!(config_dict, "include_tauri_desktop", true);
73
74 let app_identifier: String = extract_config!(
75 config_dict,
76 "app_identifier",
77 format!(
78 "com.example.{}",
79 project_name.to_lowercase().replace('-', "")
80 )
81 );
82
83 let deno_package_name: String = extract_config!(
84 config_dict,
85 "deno_package_name",
86 "@test/gwa-project".to_string()
87 );
88
89 let project_config = ProjectConfig {
91 project_name: project_name.clone(),
92 author_name,
93 author_email,
94 app_identifier,
95 db_name,
96 db_owner_admin,
97 db_owner_pword,
98 include_server,
99 include_frontend,
100 include_tauri_desktop,
101 deno_package_name,
102 };
103
104 match engine::run(&project_config, &destination_path) {
106 Ok(_) => Ok(true),
107 Err(e) => Err(PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(format!(
108 "Failed to generate project with engine: {}",
109 e
110 ))),
111 }
112}
113
114#[pymodule]
118fn _core(m: &Bound<PyModule>) -> PyResult<()> {
119 m.add_function(wrap_pyfunction!(get_crate_version, m)?)?;
122 m.add_function(wrap_pyfunction!(run_engine, m)?)?;
123 Ok(())
124}