Core Concepts

Detailed explanation of the fundamental concepts and architecture of the C15T Backend package, including instance management, context system, and request handling.

This document covers the fundamental concepts and architecture of the C15T Backend package.

Instance Management

Creating an Instance

The C15T instance is the core of the system, managing all components and their interactions:

import { c15tInstance } from '@c15t/backend';
import { memoryAdapter } from '@c15t/backend/db/adapters/memory';
 
const instance = c15tInstance({
  baseURL: 'http://localhost:3000',
  database: memoryAdapter({}),
  plugins: [],
  context: {},
});

For a quick start guide, see Getting Started.

Instance Configuration

The instance configuration includes:

interface C15TOptions {
  // Base URL for the API
  baseURL: string;
  
  // Database adapter
  database: DatabaseAdapter;
  
  // Optional base path for API routes
  basePath?: string;
  
  // Trusted origins for CORS
  trustedOrigins?: string[] | ((request: Request) => string[]);
  
  // Plugin configurations
  plugins?: C15TPlugin[];
  
  // Additional context data
  context?: Record<string, unknown>;
  
  // Authentication configuration
  auth?: AuthConfig;
  
  // Rate limiting configuration
  rateLimit?: RateLimitConfig;
}

Learn more about database adapters in Database Adapters.

Context System

Context Structure

The context is a shared state that persists throughout the request lifecycle:

interface C15TContext {
  // Request-specific data
  request: Request;
  response?: Response;
  
  // Database access
  database: DatabaseAdapter;
  
  // Authentication data
  auth?: {
    userId: string;
    roles: string[];
    metadata?: Record<string, unknown>;
  };
  
  // Plugin data
  plugins: Record<string, PluginData>;
  
  // Custom context data
  [key: string]: unknown;
}

Context Extensions

Plugins can extend the context with additional data:

const contextPlugin: C15TPlugin = {
  id: 'context-plugin',
  name: 'Context Plugin',
  type: 'core',
  init: () => ({
    context: {
      customData: {
        timestamp: Date.now(),
        requestId: generateId(),
      },
    },
  }),
};

Learn more about plugins in Plugin System.

Request Handling

Request Flow

  1. Request Reception

    const request = new Request('http://localhost:3000/api/c15t/status', {
      method: 'GET',
      headers: {
        'Accept': 'application/json',
        'Origin': 'http://localhost:3000',
      },
    });
  2. Request Processing

    const response = await instance.handler(request);
  3. Response Generation

    if (response.isOk()) {
      const data = await response.value.json();
      console.log(data);
    } else {
      console.error(response.error);
    }

For API endpoint details, see API Endpoints.

Request Lifecycle

  1. Pre-processing

    const preProcessed = await instance.preProcess(request);
  2. Authentication

    const authenticated = await instance.authenticate(preProcessed);
  3. Authorization

    const authorized = await instance.authorize(authenticated);
  4. Handler Execution

    const result = await instance.executeHandler(authorized);
  5. Post-processing

    const response = await instance.postProcess(result);

Response Processing

Response Types

interface C15TResponse<T = unknown> {
  // Response data
  data?: T;
  
  // Response metadata
  metadata?: {
    timestamp: string;
    requestId: string;
    processingTime: number;
  };
  
  // Response status
  status: number;
  
  // Response headers
  headers: Headers;
}

For API response formats, see API Endpoints.

Response Formatting

const formatResponse = (data: unknown): C15TResponse => ({
  data,
  metadata: {
    timestamp: new Date().toISOString(),
    requestId: generateId(),
    processingTime: Date.now() - startTime,
  },
  status: 200,
  headers: new Headers({
    'Content-Type': 'application/json',
  }),
});

Error Handling

Error Types

// Authentication errors
class AuthenticationError extends C15TError {
  constructor(message: string) {
    super(message, 401);
  }
}
 
// Authorization errors
class AuthorizationError extends C15TError {
  constructor(message: string) {
    super(message, 403);
  }
}
 
// Validation errors
class ValidationError extends C15TError {
  constructor(message: string, details?: Record<string, unknown>) {
    super(message, 400, details);
  }
}
 
// Database errors
class DatabaseError extends C15TError {
  constructor(message: string) {
    super(message, 500);
  }
}

For error handling in plugins, see Plugin System.

Error Handling

try {
  const response = await instance.handler(request);
} catch (error) {
  if (error instanceof AuthenticationError) {
    // Handle authentication errors
  } else if (error instanceof AuthorizationError) {
    // Handle authorization errors
  } else if (error instanceof ValidationError) {
    // Handle validation errors
  } else if (error instanceof DatabaseError) {
    // Handle database errors
  } else {
    // Handle unexpected errors
  }
}

Middleware System

Middleware Types

  1. Request Middleware

    const requestMiddleware = async (request: Request, ctx: C15TContext) => {
      // Modify request
      return { request };
    };
  2. Response Middleware

    const responseMiddleware = async (response: Response, ctx: C15TContext) => {
      // Modify response
      return { response };
    };
  3. Error Middleware

    const errorMiddleware = async (error: Error, ctx: C15TContext) => {
      // Handle error
      return { error };
    };

Learn more about middleware in Plugin System.

Middleware Chain

const middlewareChain = [
  requestMiddleware,
  authMiddleware,
  validationMiddleware,
  responseMiddleware,
];
 
const result = await middlewareChain.reduce(
  async (acc, middleware) => middleware(acc, ctx),
  request
);

Event System

Event Types

interface C15TEvent {
  type: string;
  data: unknown;
  timestamp: string;
  metadata?: Record<string, unknown>;
}

Event Handling

const eventHandler = async (event: C15TEvent) => {
  switch (event.type) {
    case 'request.received':
      // Handle request received
      break;
    case 'response.sent':
      // Handle response sent
      break;
    case 'error.occurred':
      // Handle error occurred
      break;
  }
};

Event Emission

const emitEvent = async (type: string, data: unknown) => {
  const event: C15TEvent = {
    type,
    data,
    timestamp: new Date().toISOString(),
  };
  await eventHandler(event);
};

Testing

Test Utilities

import { createTestInstance, createTestRequest } from '@c15t/backend/testing';
 
describe('Core Functionality', () => {
  it('should handle requests', async () => {
    const instance = createTestInstance();
    const request = createTestRequest({
      url: 'http://localhost:3000/api/c15t/status',
      method: 'GET',
    });
    
    const response = await instance.handler(request);
    expect(response.status).toBe(200);
  });
});

Mock Context

import { createMockContext } from '@c15t/backend/testing';
 
const ctx = createMockContext({
  database: mockDatabase,
  auth: {
    userId: 'test-user',
    roles: ['admin'],
  },
});

Performance Optimization

Caching

const cache = new Map<string, unknown>();
 
const getCachedData = async (key: string) => {
  if (cache.has(key)) {
    return cache.get(key);
  }
  
  const data = await fetchData();
  cache.set(key, data);
  return data;
};

For database performance, see Database Adapters.

Connection Pooling

const pool = new Pool({
  max: 20,
  idleTimeoutMillis: 30000,
});
 
const getConnection = async () => {
  return await pool.connect();
};

Request Batching

const batchRequests = async (requests: Request[]) => {
  return await Promise.all(
    requests.map(request => instance.handler(request))
  );
};
c15t.com