use serde_json::json;
pub(crate) fn rust_template_cargo_toml(name: &str) -> String {
format!(
"[package]\nname = \"{name}\"\nversion = \"0.1.0\"\nedition = \"2024\"\npublish = false\n\n[lints.rust]\nunsafe_code = \"forbid\"\nwarnings = \"deny\"\n\n[lints.clippy]\nall = {{ level = \"deny\", priority = -1 }}\npedantic = {{ level = \"deny\", priority = -1 }}\ndbg_macro = \"deny\"\ntodo = \"deny\"\nunimplemented = \"deny\"\npanic = \"deny\"\nunwrap_used = \"deny\"\nexpect_used = \"deny\"\nlarge_futures = \"deny\"\nlarge_include_file = \"deny\"\nlarge_stack_frames = \"deny\"\nmem_forget = \"deny\"\nrc_buffer = \"deny\"\nrc_mutex = \"deny\"\nredundant_clone = \"deny\"\nclone_on_ref_ptr = \"deny\"\n"
)
}
pub(crate) fn rust_template_cargo_lock(name: &str) -> String {
format!(
"# This file is automatically @generated by Cargo.\nversion = 4\n\n[[package]]\nname = \"{name}\"\nversion = \"0.1.0\"\n"
)
}
pub(crate) fn frontend_package_json(name: &str) -> String {
serde_json::to_string_pretty(&json!({
"name": name,
"private": true,
"type": "module",
"scripts": {
"typecheck": "oxlint src vite.config.ts --deny-warnings --type-aware --type-check --tsconfig tsconfig.json",
"lint": "oxlint src vite.config.ts --deny-warnings && fallow dead-code --production --include-dupes --include-entry-exports --fail-on-issues && fallow dupes --production --mode semantic --threshold 1 --ignore-imports --fail-on-issues && fallow health --production --max-cyclomatic 10 --max-cognitive 15 --max-crap 20 --complexity",
"build": "vite build",
"preview": "vite preview --host 0.0.0.0"
},
"dependencies": {
"@tanstack/react-router": "^1.170.8",
"react": "^19.2.6",
"react-dom": "^19.2.6"
},
"devDependencies": {
"@types/node": "^25.9.1",
"@types/react": "^19.2.15",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^6.0.2",
"fallow": "^2.84.0",
"oxlint": "^1.67.0",
"oxlint-tsgolint": "^0.23.0",
"vite": "^8.0.14"
}
}))
.map_or_else(|_error| "{}\n".to_owned(), |source| format!("{source}\n"))
}
pub(crate) fn frontend_ts_config() -> String {
serde_json::to_string_pretty(&json!({
"compilerOptions": {
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"alwaysStrict": true,
"erasableSyntaxOnly": true,
"exactOptionalPropertyTypes": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"jsx": "react-jsx",
"lib": ["ESNext", "DOM"],
"module": "ESNext",
"moduleDetection": "force",
"moduleResolution": "Bundler",
"noEmit": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noPropertyAccessFromIndexSignature": true,
"noUncheckedIndexedAccess": true,
"noUncheckedSideEffectImports": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"skipLibCheck": false,
"strict": true,
"strictBindCallApply": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"strictPropertyInitialization": true,
"target": "ES2022",
"types": ["vite/client", "node"],
"useUnknownInCatchVariables": true,
"verbatimModuleSyntax": true
},
"include": ["src", "vite.config.ts"]
}))
.map_or_else(|_error| "{}\n".to_owned(), |source| format!("{source}\n"))
}
pub(crate) fn rust_api_source() -> &'static str {
r##"use std::{
io::{Read, Write},
net::{TcpListener, TcpStream},
};
fn main() -> std::io::Result<()> {
let port = std::env::var("PORT").unwrap_or_else(|_error| "3000".to_owned());
let listener = TcpListener::bind(format!("0.0.0.0:{port}"))?;
for stream in listener.incoming() {
handle(stream?)?;
}
Ok(())
}
fn handle(mut stream: TcpStream) -> std::io::Result<()> {
let mut buffer = [0_u8; 2048];
let size = stream.read(&mut buffer)?;
let request = String::from_utf8_lossy(&buffer[..size]);
let mut parts = request
.lines()
.next()
.unwrap_or_default()
.split_whitespace();
let method = parts.next().unwrap_or_default();
let path = parts.next().unwrap_or("/");
let origin = request
.lines()
.find_map(|line| line.strip_prefix("Origin: "))
.unwrap_or("*");
let cors_origin = allowed_origin(origin);
if method == "OPTIONS" {
return write_response(&mut stream, "204 No Content", "", &cors_origin);
}
let body = if path == "/healthz" || path == "/api/healthz" {
r#"{"ok":true}"#
} else {
r#"{"message":"hello from tovuk","backend":"rust"}"#
};
write_response(&mut stream, "200 OK", body, &cors_origin)
}
fn allowed_origin(request_origin: &str) -> String {
let configured = std::env::var("FRONTEND_ORIGIN").unwrap_or_else(|_error| request_origin.to_owned());
if configured == "*" || configured == request_origin {
configured
} else {
"null".to_owned()
}
}
fn write_response(
stream: &mut TcpStream,
status: &str,
body: &str,
origin: &str,
) -> std::io::Result<()> {
write!(
stream,
"HTTP/1.1 {status}\r\ncontent-type: application/json\r\ncontent-length: {}\r\naccess-control-allow-origin: {origin}\r\naccess-control-allow-methods: GET, OPTIONS\r\naccess-control-allow-headers: content-type, authorization\r\nconnection: close\r\n\r\n{body}",
body.len()
)
}
"##
}
pub(crate) fn frontend_source(api_base_url: &str) -> String {
format!(
"import {{ createRootRoute, createRouter, RouterProvider }} from '@tanstack/react-router'\nimport {{ createRoot }} from 'react-dom/client'\nimport './styles.css'\n\nconst apiBaseUrl = import.meta.env.VITE_API_URL ?? '{api_base_url}'\n\nfunction App() {{\n return (\n <main>\n <section>\n <h1>Tovuk TanStack Frontend</h1>\n <p>Static runtime, dynamic Rust backend calls.</p>\n <code>{{apiBaseUrl}}</code>\n </section>\n </main>\n )\n}}\n\nconst rootRoute = createRootRoute({{ component: App }})\nconst router = createRouter({{ routeTree: rootRoute }})\n\ndeclare module '@tanstack/react-router' {{\n interface Register {{\n router: typeof router\n }}\n}}\n\nconst rootElement = document.getElementById('root')\nif (rootElement === null) {{\n throw new Error('missing root element')\n}}\n\ncreateRoot(rootElement).render(<RouterProvider router={{router}} />)\n"
)
}
pub(crate) fn frontend_vite_env_source() -> &'static str {
"/// <reference types=\"vite/client\" />\n\ninterface ViteTypeOptions {\n strictImportMetaEnv: unknown\n}\n\ninterface ImportMetaEnv {\n readonly VITE_API_URL?: string\n}\n"
}