feat: Add Rust API Server with REST and GraphQL support

- Implement JWT authentication layer
- Add Engine Registry with 20+ conversion engines
- Implement Conversion Service with background job processing
- REST API endpoints for file conversion operations
- GraphQL API with queries and mutations
- Comprehensive error handling with conversion suggestions
- Integration tests for both REST and GraphQL APIs
- Complete API documentation

Features:
- REST API: /api/v1/* endpoints
- GraphQL API: /graphql endpoint with playground
- JWT Bearer token authentication
- Engine validation with alternative suggestions
- File download via API (not exposing file paths)
- Support for FFmpeg, ImageMagick, LibreOffice, Pandoc, and more
This commit is contained in:
Your Name 2026-01-21 11:40:03 +08:00
parent d0388066a5
commit e083e5d11d
18 changed files with 5235 additions and 0 deletions

44
api-server/src/main.rs Normal file
View file

@ -0,0 +1,44 @@
//! ConvertX API Server - Main entry point
//!
//! A REST and GraphQL API server for file conversion operations.
use std::net::SocketAddr;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
use convertx_api::{build_router, config::Config, AppState};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Initialize logging
tracing_subscriber::registry()
.with(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| "convertx_api=debug,tower_http=debug".into()),
)
.with(tracing_subscriber::fmt::layer())
.init();
// Load configuration
dotenvy::dotenv().ok();
let config = Config::from_env()?;
tracing::info!("Starting ConvertX API Server");
tracing::info!("REST API: http://{}:{}/api/v1", config.host, config.port);
tracing::info!("GraphQL Playground: http://{}:{}/graphql", config.host, config.port);
// Build application state
let state = AppState::new(config.clone());
// Build router
let app = build_router(state);
// Start server
let addr = SocketAddr::new(config.host.parse()?, config.port);
let listener = tokio::net::TcpListener::bind(addr).await?;
tracing::info!("Server listening on {}", addr);
axum::serve(listener, app).await?;
Ok(())
}