Azura Logo
GitHub

Core Concepts

Understand the key concepts and architecture of Azura.JS Framework.

Server Architecture

Azura is built around a modular architecture that separates concerns and makes your code more maintainable:

  • AzuraServer - The core HTTP server that handles requests and responses
  • Router - Responsible for matching URLs to route handlers
  • Controllers - Class-based handlers for organizing your API endpoints
  • Plugins - Modular extensions that add functionality to the server
  • Lifecycle Hooks - Allow you to execute logic at various stages of the request/response cycle

Request Flow

1. Client sends HTTP request
2. AzuraServer receives the request
3. Middleware and global plugins process the request
4. Router matches the URL to a handler
5. Controller method executes
6. Response is sent back to the client

Decorators

Azura makes extensive use of TypeScript decorators to provide a clean and intuitive API:

Controller Decorators

typescript
@Controller('/users')
class UserController {
  // Controller methods
}

Route Decorators

typescript
@Controller('/users')
class UserController {
  @Get('/')
  getAllUsers() {
    // Handle GET /users
  }

  @Post('/')
  createUser() {
    // Handle POST /users
  }

  @Get('/:id')
  getUserById(@Param('id') id: string) {
    // Handle GET /users/:id
  }
}

Parameter Decorators

typescript
@Controller('/users')
class UserController {
  @Post('/')
  createUser(
    @Body() userData: any,
    @Headers('user-agent') userAgent: string,
    @Query('role') role?: string
  ) {
    // Access to parsed body, headers, and query parameters
  }
}

Plugin System

Azura's plugin system allows you to extend the framework's functionality in a modular way:

typescript
import { AzuraServer, cors, rateLimit } from '@azura/framework';

const app = new AzuraServer();

// Register built-in plugins
app.registerPlugin(cors, {
  origin: '*',
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
});

app.registerPlugin(rateLimit, {
  limit: 100,
  timeframe: 60000, // 1 minute
});

// Create and register a custom plugin
const myPlugin = {
  name: 'my-plugin',
  register: (app, options) => {
    app.use((req, res, next) => {
      console.log('Request to', req.url);
      next();
    });
    
    return {
      // Plugin API that other plugins can use
      logMessage: (msg: string) => console.log('[MyPlugin]', msg)
    };
  }
};

app.registerPlugin(myPlugin);

Configuration

Azura uses a configuration system that supports multiple formats:

  • azura.config.ts - TypeScript configuration
  • azura.config.js - JavaScript configuration
  • azura.config.json - JSON configuration
  • azura.config.yaml - YAML configuration
typescript
// azura.config.ts
import { AzuraConfig } from '@azura/framework';

const config: AzuraConfig = {
  server: {
    port: 8080,
    cluster: true, // Enable cluster mode
    ipHost: true,  // Show IP addresses on startup
  },
  plugins: {
    cors: {
      enabled: true,
      origin: '*',
    },
    compression: {
      enabled: true,
      level: 6,
    },
    rateLimit: {
      enabled: true,
      limit: 100,
      timeframe: 60000, // 1 minute
    },
  },
};

export default config;

Azura automatically loads this configuration when you create a new server instance.

Database Adapters

Azura provides a unified interface for working with different databases through adapters:

typescript
import { JSONAdapter, MongoAdapter, PostgresAdapter } from '@azura/framework';

// Simple JSON file database
const jsonDB = new JSONAdapter('database.json');
await jsonDB.connect();

// MongoDB adapter
const mongoDB = new MongoAdapter('mongodb://localhost:27017', 'my-app');
await mongoDB.connect();

// PostgreSQL adapter
const pgDB = new PostgresAdapter({
  host: 'localhost',
  port: 5432,
  user: 'postgres',
  password: 'secret',
  database: 'my-app'
});
await pgDB.connect();

// All adapters share the same API
const users = await mongoDB.find('users', { active: true });
await pgDB.insert('users', { name: 'John', email: 'john@example.com' });
await jsonDB.update('users', { id: '123' }, { lastLogin: new Date() });

Authentication

Azura provides built-in support for JWT-based authentication and API keys:

typescript
import { JwtManager, KeyManager, Auth, Public, Roles } from '@azura/framework';

// JWT authentication
const jwt = new JwtManager();
const token = jwt.sign({ userId: '123', role: 'admin' });
const payload = jwt.verify(token);

// API key management
const keyManager = new KeyManager(['key1', 'key2', 'key3']);
keyManager.check('key1'); // Passes
keyManager.check('invalid'); // Throws HttpError

// Using auth decorators
@Controller('/admin')
class AdminController {
  @Get('/')
  @Auth('admin') // Requires authentication with 'admin' role
  getDashboard() {
    return { /* dashboard data */ };
  }

  @Get('/public-stats')
  @Public() // No authentication required
  getPublicStats() {
    return { /* public stats */ };
  }
}

Middleware

Middleware functions can be used to process requests before they reach your route handlers:

typescript
import { AzuraServer } from '@azura/framework';

const app = new AzuraServer();

// Global middleware
app.use((req, res, next) => {
  console.log(`${req.method} ${req.path}`);
  next();
});

// Error handling middleware
app.use((req, res, next) => {
  try {
    next();
  } catch (error) {
    console.error('Error:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

// Route-specific middleware
const authMiddleware = (req, res, next) => {
  const token = req.headers.authorization;
  if (!token) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  next();
};

app.get('/protected', authMiddleware, (req, res) => {
  res.json({ message: 'This is protected' });
});