SkillAgentSearch skills...

Armature

A modern, type-safe HTTP framework for Rust heavily inspired by **Angular** and **NestJS**.

Install / Use

/learn @pegasusheavy/Armature
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Armature 🦾

A modern, type-safe HTTP framework for Rust heavily inspired by Angular and NestJS.

Armature brings the elegant decorator syntax and powerful dependency injection from the TypeScript/JavaScript ecosystem to Rust, combining the developer experience of NestJS with Rust's performance and safety guarantees.

Features

  • Completely Stateless: No server-side sessions, fully stateless JWT-based authentication
  • Decorator Syntax: Use Angular-style decorators via procedural macros
  • Full Dependency Injection: Automatic service injection into controllers based on field types
  • Type-Safe DI Container: Compile-time verified dependency resolution
  • Modular Architecture: Organize your application into modules with providers and controllers
  • Service Dependencies: Services can depend on other services with automatic resolution
  • Singleton Pattern: Services are created once and shared across the application
  • Lifecycle Hooks: NestJS-style hooks (OnModuleInit, OnModuleDestroy, OnApplicationBootstrap, OnApplicationShutdown) for resource management
  • Authentication & Authorization: Optional comprehensive auth system with guards, RBAC, and strategies
  • OAuth2/OIDC Providers: Built-in support for Google, Microsoft, AWS Cognito, Okta, and Auth0
  • SAML 2.0 Support: Enterprise SSO with Service Provider implementation
  • Password Hashing: Bcrypt and Argon2 support with auto-detection
  • JWT Authentication: Optional JWT token management with HS256/RS256/ES256 support
  • Configuration Management: Optional NestJS-style config system with env, .env, JSON, and TOML support
  • GraphQL Support: Optional type-safe GraphQL API with queries, mutations, and subscriptions
  • Rate Limiting: Token bucket, sliding window, and fixed window algorithms with Redis support
  • Response Compression: Automatic gzip, brotli, and zstd compression with content-type awareness
  • Comprehensive Logging: Highly configurable structured logging with JSON/Pretty/Plain formats, multiple outputs, and HTTP middleware
  • Testing Utilities: Comprehensive testing framework with mocks, spies, and assertions
  • Validation Framework: Powerful validation with built-in validators and custom rules
  • WebSocket Support: Full-duplex real-time communication with rooms and broadcasting
  • Server-Sent Events (SSE): Efficient server-to-client streaming for live updates
  • HTTPS/TLS Support: Built-in TLS support with certificate management and automatic HTTP to HTTPS redirect
  • OpenTelemetry Integration: Distributed tracing, metrics, and observability with OTLP, Jaeger, Zipkin, and Prometheus support
  • Async-First: Built on Tokio and Hyper for high-performance async I/O
  • Type-Safe Routing: Path parameters and query string parsing with compile-time validation
  • JSON Serialization: Built-in support for JSON request/response handling

Quick Start

Using the CLI (Recommended)

Install the Armature CLI for the best development experience:

# Install the CLI
cargo install armature-cli

# Create a new project
armature new my-api

# Navigate to your project
cd my-api

# Start the development server with hot reloading
armature dev

Generate Code

# Generate a controller
armature generate controller users

# Generate a service
armature generate service users

# Generate a complete resource (controller + service + module)
armature generate resource products --crud

# Generate middleware, guards, and more
armature generate middleware auth
armature generate guard admin

Manual Setup

use armature_framework::prelude::*;
use serde::{Deserialize, Serialize};

// Define your domain model
#[derive(Serialize, Deserialize)]
struct User {
    id: u32,
    name: String,
}

// Create an injectable service
#[injectable]
#[derive(Default, Clone)]
struct DatabaseService;

#[injectable]
#[derive(Default, Clone)]
struct UserService {
    database: DatabaseService,  // Automatically injected!
}

impl UserService {
    fn get_users(&self) -> Vec<User> {
        vec![User { id: 1, name: "Alice".to_string() }]
    }
}

// Create a controller with automatic DI
#[controller("/users")]
#[derive(Default, Clone)]
struct UserController {
    user_service: UserService,  // Automatically injected!
}

impl UserController {
    // Use injected service in methods
    fn get_all(&self) -> Result<Json<Vec<User>>, Error> {
        Ok(Json(self.user_service.get_users()))
    }

    fn get_one(&self, id: u32) -> Result<Json<User>, Error> {
        // Use self.user_service throughout the controller
        Ok(Json(User { id, name: "Alice".to_string() }))
    }
}

// Define your application module
#[module(
    providers: [DatabaseService, UserService],
    controllers: [UserController]
)]
#[derive(Default)]
struct AppModule;

// Bootstrap your application - DI happens automatically!
#[tokio::main]
async fn main() {
    let app = Application::create::<AppModule>();
    app.listen(3000).await.unwrap();
}

Architecture

The framework is organized into three main crates:

armature-core

Core runtime functionality including:

  • Traits (Provider, Controller, Module, RequestHandler)
  • DI Container with type-based resolution
  • Router with path parameter extraction
  • HTTP request/response types
  • Error handling

armature-macro

Procedural macros for decorator syntax:

  • #[injectable] - Mark structs as injectable services
  • #[controller("/path")] - Define controllers with base paths
  • #[get], #[post], #[put], #[delete], #[patch] - HTTP route decorators
  • #[module(...)] - Organize components into modules
  • #[derive(Body)], #[derive(Param)], #[derive(Query)] - Request parameter extraction

armature-framework

Main library that re-exports everything from core and macros. Add to your Cargo.toml:

[dependencies]
armature-framework = "0.1"

Or with specific features:

[dependencies]
armature-framework = { version = "0.1", features = ["auth", "cache", "validation"] }

Decorators

Service Decorators

#[injectable]

Marks a struct as injectable, allowing it to be registered in the DI container:

#[injectable]
struct DatabaseService {
    connection: DbConnection,
}

Controller Decorators

#[controller("/path")]

Marks a struct as a controller with a base path:

#[controller("/api/users")]
struct UserController {
    user_service: UserService,
}

Route Decorators

HTTP method decorators for defining routes:

#[get("/")]           // GET /api/users/
#[get("/:id")]        // GET /api/users/:id
#[post("/")]          // POST /api/users/
#[put("/:id")]        // PUT /api/users/:id
#[delete("/:id")]     // DELETE /api/users/:id
#[patch("/:id")]      // PATCH /api/users/:id

Module Decorator

#[module(...)]

Defines a module with providers, controllers, and imports:

#[module(
    providers: [UserService, DatabaseService],
    controllers: [UserController],
    imports: [CommonModule],
    exports: [UserService]
)]
struct UserModule;

Dependency Injection

The DI container uses Rust's type system for service resolution:

// Register a service
container.register(MyService::default());

// Resolve a service
let service = container.resolve::<MyService>()?;

Services are singletons by default and shared across the application.

Lifecycle Hooks

Armature provides NestJS-inspired lifecycle hooks for managing service initialization and cleanup:

use armature_framework::prelude::*;
use armature_framework::lifecycle::{OnModuleInit, OnModuleDestroy, LifecycleResult};
use async_trait::async_trait;

#[injectable]
struct DatabaseService {
    connected: Arc<RwLock<bool>>,
}

#[async_trait]
impl OnModuleInit for DatabaseService {
    async fn on_module_init(&self) -> LifecycleResult {
        println!("Connecting to database...");
        *self.connected.write().await = true;
        Ok(())
    }
}

#[async_trait]
impl OnModuleDestroy for DatabaseService {
    async fn on_module_destroy(&self) -> LifecycleResult {
        println!("Closing database connection...");
        *self.connected.write().await = false;
        Ok(())
    }
}

Available hooks:

  • OnModuleInit - Called after module initialization
  • OnModuleDestroy - Called before module destruction
  • OnApplicationBootstrap - Called after full application bootstrap
  • OnApplicationShutdown - Called during graceful shutdown
  • BeforeApplicationShutdown - Called before shutdown hooks

See the Lifecycle Hooks Guide for complete documentation.

Routing

The router supports:

  • Static paths: /users
  • Path parameters: /users/:id
  • Query parameters: /users?page=1&limit=10
  • Multiple HTTP methods per route

Path parameters are extracted automatically:

#[get("/:id")]
async fn get_user(req: HttpRequest) -> Result<Json<User>, Error> {
    let id = req.param("id").unwrap();
    // ...
}

HTTP Status Codes and Error Handling

Comprehensive HTTP status code support with type-safe error handling:

use armature_framework::{Error, HttpStatus};

// Type-safe status codes
let status = HttpStatus::NotFound;
assert_eq!(status.code(), 404);
assert_eq!(status.reason(), "Not Found");

// Structured errors for all 4xx/5xx codes
return Err(Error::NotFound("User not found".to_string()));
return Err(Error::TooManyRequests("Rate limit exceeded".to_string()));
return Err(Error::ServiceUnavailable("Database down".to_string()));

// Error helpers
let error = Error::Unauthorized("Invalid token".to_string());
assert_eq!(error.status_code(), 401);
assert!(error.is_client_error());

See the HTTP Status & Errors Guide for complete documentation.

Guards and Interceptors

Protect and transform your routes with Guards and Interceptors:

use armature_framework::{Guard, AuthenticationGuard, Gu

Related Skills

View on GitHub
GitHub Stars8
CategoryDevelopment
Updated12d ago
Forks3

Languages

Rust

Security Score

85/100

Audited on Mar 28, 2026

No findings