Skip to content

Latest commit

 

History

History
893 lines (694 loc) · 19.3 KB

File metadata and controls

893 lines (694 loc) · 19.3 KB

API Reference

Complete API documentation for the Qwe Framework.

Table of Contents

Core Classes

QweApp

Main application class for creating and configuring Qwe applications.

Constructor

createApp(options?: QweAppOptions): QweApp

Parameters:

  • options (optional): Application configuration options

Returns: QweApp instance

Methods

use(middleware: QweMiddleware | string, handler?: QweHandler): QweApp

Register middleware or mount paths.

app.use(jwtMiddleware({ secret: 'key' }));
app.use('/api', apiRouter);
get|post|put|delete|patch(path: string, ...handlers: QweHandler[]): QweApp

Register route handlers for HTTP methods.

app.get('/users', (qwe) => qwe.success('Users', users));
app.post('/users', validateUser, (qwe) => qwe.created('User created', user));
ws(path: string, options: WSOptions, handler: WSHandler): QweApp

Register WebSocket handlers.

app.ws('/chat', {}, (ws) => {
  ws.on('message', (data) => ws.broadcast(data));
});
plugin(plugin: QwePlugin): QweApp

Register framework plugins.

app.plugin(cors({ origin: 'https://example.com' }));
listen(port: number, callback?: () => void): QweServer

Start the HTTP server.

const server = app.listen(3000, () => {
  console.log('Server running on port 3000');
});

QweContext

Request/response context object available in all route handlers.

Properties

Request Properties
interface QweContext {
  // HTTP method
  method: string;
  
  // Request URL
  url: string;
  
  // URL pathname
  path: string;
  
  // Query parameters
  query: Record<string, string>;
  
  // Route parameters
  params: Record<string, string>;
  
  // Request headers
  headers: Record<string, string>;
  
  // Request body (parsed)
  body: any;
  
  // Raw request body
  rawBody: Buffer;
  
  // Client IP address
  ip: string;
  
  // Cookies
  cookies: Record<string, string>;
  
  // User agent
  userAgent: string;
}

Response Methods

json(data: any, statusCode?: number): QweResponse

Send JSON response.

qwe.json({ message: 'Hello' }); // 200
qwe.json({ error: 'Not found' }, 404); // 404
send(data: string | Buffer, statusCode?: number): QweResponse

Send raw response.

qwe.send('Hello World');
qwe.send(buffer, 200);
html(content: string, statusCode?: number): QweResponse

Send HTML response.

qwe.html('<h1>Hello World</h1>');
redirect(url: string, statusCode?: number): QweResponse

Redirect response.

qwe.redirect('/login'); // 302
qwe.redirect('/home', 301); // 301
Status-specific Methods
// 2xx Success
qwe.success(message: string, data?: any): QweResponse;
qwe.created(message: string, data?: any): QweResponse;
qwe.accepted(message: string, data?: any): QweResponse;
qwe.noContent(): QweResponse;

// 4xx Client Errors
qwe.badRequest(message: string, errors?: any): QweResponse;
qwe.unauthorized(message: string): QweResponse;
qwe.forbidden(message: string): QweResponse;
qwe.notFound(message: string): QweResponse;
qwe.conflict(message: string): QweResponse;
qwe.unprocessableEntity(message: string, errors?: any): QweResponse;
qwe.tooManyRequests(message: string): QweResponse;

// 5xx Server Errors
qwe.internalServerError(message: string, error?: any): QweResponse;
qwe.notImplemented(message: string): QweResponse;
qwe.badGateway(message: string): QweResponse;
qwe.serviceUnavailable(message: string): QweResponse;
Header Methods
// Set response header
qwe.header(name: string, value: string): QweContext;

// Set multiple headers
qwe.headers(headers: Record<string, string>): QweContext;

// Set cookie
qwe.cookie(name: string, value: string, options?: CookieOptions): QweContext;

Context API

Built-in Utilities

All utilities are accessible through the context object:

Validation

interface ValidationAPI {
  validate(schema: ValidationSchema, data: any): Promise<ValidationResult>;
  
  // Schema builders
  string(): StringSchema;
  number(): NumberSchema;
  boolean(): BooleanSchema;
  array(): ArraySchema;
  object(properties: Record<string, Schema>): ObjectSchema;
  date(): DateSchema;
  custom(validator: (value: any) => boolean | Promise<boolean>): CustomSchema;
}

// Usage
const result = await qwe.validate(userSchema, qwe.body);
if (!result.success) {
  return qwe.badRequest('Validation failed', result.errors);
}

JWT

interface JwtAPI {
  sign(payload: any, secret: string, options?: JwtSignOptions): string;
  verify(token: string, secret: string, options?: JwtVerifyOptions): any;
  decode(token: string): any;
  
  createTokenPair(
    payload: any, 
    secret: string, 
    options?: TokenPairOptions
  ): { accessToken: string; refreshToken: string };
  
  refreshAccessToken(
    refreshToken: string,
    secret: string,
    newPayload: any,
    expiresIn: string
  ): string;
}

// Usage
const token = qwe.jwt.sign({ userId: 123 }, 'secret', { expiresIn: '1h' });
const payload = qwe.jwt.verify(token, 'secret');

Hashing

interface HashAPI {
  hash(password: string, rounds?: number): Promise<string>;
  verify(password: string, hash: string): Promise<boolean>;
  scrypt(password: string, salt: string): string;
  generateSalt(length?: number): string;
}

// Usage
const hashed = await qwe.hash.hash('password123');
const isValid = await qwe.hash.verify('password123', hashed);

File Upload

interface UploadAPI {
  handle(options?: UploadOptions): Promise<UploadedFile[]>;
  single(fieldName: string, options?: UploadOptions): Promise<UploadedFile>;
  array(fieldName: string, maxCount?: number, options?: UploadOptions): Promise<UploadedFile[]>;
}

interface UploadedFile {
  fieldname: string;
  originalname: string;
  encoding: string;
  mimetype: string;
  size: number;
  destination: string;
  filename: string;
  path: string;
  buffer: Buffer;
}

// Usage
const files = await qwe.upload.handle({
  maxFileSize: 5 * 1024 * 1024,
  allowedTypes: ['image/jpeg', 'image/png']
});

ID Generation

interface IdAPI {
  generateId(): string;
  generateShortId(length?: number): string;
  generateUUID(): string;
  generateNanoId(size?: number): string;
  generateSecureToken(bytes?: number): string;
  generateAlphanumeric(length?: number): string;
}

// Usage
const id = qwe.generateId(); // timestamp-based
const uuid = qwe.generateUUID(); // UUID v4
const shortId = qwe.generateShortId(8); // 8-character short ID

Utilities API

Standalone Utilities

Validator

import { createValidator } from 'qwe-framework';

const validator = createValidator();

// String validation
const stringSchema = validator.string()
  .min(3)
  .max(50)
  .email()
  .required();

// Number validation  
const numberSchema = validator.number()
  .min(0)
  .max(100)
  .integer()
  .positive();

// Object validation
const userSchema = validator.object({
  name: validator.string().min(2).max(50),
  email: validator.string().email(),
  age: validator.number().min(18).max(100)
});

// Array validation
const arraySchema = validator.array()
  .items(validator.string())
  .min(1)
  .max(10)
  .unique();

JWT Utilities

import { createJWT } from 'qwe-framework';

const jwt = createJWT();

// Basic operations
const token = jwt.sign(payload, secret, options);
const decoded = jwt.verify(token, secret);
const payload = jwt.decode(token);

// Token pairs
const { accessToken, refreshToken } = jwt.createTokenPair(
  payload, 
  secret, 
  { accessTokenExpiry: '15m', refreshTokenExpiry: '7d' }
);

Hasher

import { createHasher } from 'qwe-framework';

const hasher = createHasher();

// Password hashing
const hash = await hasher.hash('password', 12);
const isValid = await hasher.verify('password', hash);

// Scrypt hashing
const salt = hasher.generateSalt();
const scryptHash = hasher.scrypt('password', salt);

Cache

import { createCache } from 'qwe-framework';

// Memory cache
const memoryCache = createCache('memory', {
  maxSize: 1000,
  ttl: 300
});

// Redis cache
const redisCache = createCache('redis', {
  host: 'localhost',
  port: 6379,
  password: 'password'
});

// Cache operations
await cache.set('key', 'value', 300); // TTL in seconds
const value = await cache.get('key');
await cache.delete('key');
await cache.clear();

Plugin API

Built-in Plugins

CORS

import { cors } from 'qwe-framework';

app.plugin(cors({
  origin: string | string[] | boolean | function;
  methods?: string[];
  allowedHeaders?: string[];
  exposedHeaders?: string[];
  credentials?: boolean;
  maxAge?: number;
  preflightContinue?: boolean;
  optionsSuccessStatus?: number;
}));

Logger

import { logger } from 'qwe-framework';

app.plugin(logger({
  format?: 'combined' | 'common' | 'dev' | 'short' | 'tiny';
  skip?: (qwe: QweContext) => boolean;
  stream?: WritableStream;
}));

Rate Limiter

import { rateLimiter } from 'qwe-framework';

app.plugin(rateLimiter({
  windowMs: number;
  max: number;
  message?: string;
  standardHeaders?: boolean;
  legacyHeaders?: boolean;
  keyGenerator?: (qwe: QweContext) => string;
  skip?: (qwe: QweContext) => boolean;
  handler?: (qwe: QweContext) => QweResponse;
}));

Security Headers

import { security } from 'qwe-framework';

app.plugin(security({
  contentSecurityPolicy?: CSPOptions;
  crossOriginEmbedderPolicy?: boolean;
  crossOriginOpenerPolicy?: boolean;
  crossOriginResourcePolicy?: boolean;
  dnsPrefetchControl?: boolean;
  frameguard?: FrameguardOptions;
  hidePoweredBy?: boolean;
  hsts?: HSTSOptions;
  ieNoOpen?: boolean;
  noSniff?: boolean;
  originAgentCluster?: boolean;
  permittedCrossDomainPolicies?: boolean;
  referrerPolicy?: ReferrerPolicyOptions;
  xssFilter?: boolean;
}));

Compression

import { compression } from 'qwe-framework';

app.plugin(compression({
  level?: number; // 1-9
  chunkSize?: number;
  windowBits?: number;
  memLevel?: number;
  threshold?: number;
  filter?: (qwe: QweContext) => boolean;
}));

Middleware Functions

JWT Middleware

import { jwtMiddleware, requireRoles, requirePermissions } from 'qwe-framework';

// Basic JWT authentication
app.use(jwtMiddleware({
  secret: string;
  algorithms?: string[];
  audience?: string | string[];
  issuer?: string | string[];
  ignoreExpiration?: boolean;
  clockTolerance?: number;
  maxAge?: string | number;
  getToken?: (qwe: QweContext) => string;
  isRevoked?: (qwe: QweContext, payload: any) => boolean;
  onError?: (qwe: QweContext, error: Error) => void;
}));

// Role-based access
app.use(requireRoles('admin', 'moderator'));

// Permission-based access
app.use(requirePermissions('users:read', 'users:write'));

Custom Plugin Development

interface QwePlugin {
  name: string;
  version?: string;
  dependencies?: string[];
  install: (app: QweApp, options?: any) => void;
}

// Example custom plugin
const customPlugin = (options: any): QwePlugin => ({
  name: 'custom-plugin',
  version: '1.0.0',
  install: (app: QweApp) => {
    app.use(async (qwe, next) => {
      // Plugin logic here
      await next();
    });
  }
});

app.plugin(customPlugin({ option: 'value' }));

Real-time API

WebSocket API

interface WSConnection {
  id: string;
  ip: string;
  params: Record<string, string>;
  query: Record<string, string>;
  headers: Record<string, string>;
  user?: any;
  
  // Send message to this connection
  send(data: any): void;
  
  // Broadcast to all connections in room
  broadcast(data: any, room?: string): void;
  
  // Broadcast to all connections
  broadcastToAll(data: any, excludeSelf?: boolean): void;
  
  // Room management
  join(room: string): void;
  leave(room: string): void;
  rooms(): string[];
  
  // Event handlers
  onMessage(handler: (data: any) => void): void;
  onClose(handler: (code: number, message: string) => void): void;
  onError(handler: (error: Error) => void): void;
  
  // Connection state
  readyState: number;
  close(code?: number, message?: string): void;
}

interface WSOptions {
  compression?: number;
  maxCompressedSize?: number;
  maxBackpressure?: number;
  closeOnBackpressureLimit?: boolean;
  idleTimeout?: number;
  maxPayloadLength?: number;
  authenticate?: (req: any) => Promise<any>;
  message?: (data: any, ws: WSConnection) => Promise<void>;
  close?: (code: number, message: string, ws: WSConnection) => Promise<void>;
  error?: (error: Error, ws: WSConnection) => Promise<void>;
}

// WebSocket route registration
app.ws('/path/:param', options, (ws: WSConnection) => {
  // Handle connection
});

Server-Sent Events API

interface SSEConnection {
  id: string;
  context: QweContext;
  
  // Send events
  send(data: string): void;
  sendJSON(data: any): void;
  sendEvent(event: SSEEvent): void;
  
  // Connection management
  close(): void;
  ping(): void;
}

interface SSEEvent {
  id?: string;
  event?: string;
  data: any;
  retry?: number;
}

interface SSEOptions {
  heartbeatInterval?: number;
  maxConnections?: number;
  authenticate?: (qwe: QweContext) => Promise<any>;
  onConnect?: (connection: SSEConnection) => void;
  onDisconnect?: (connection: SSEConnection) => void;
}

// SSE endpoint creation
import { createSSEEndpoint } from 'qwe-framework';

app.get('/events', createSSEEndpoint(options));

// SSE utilities
import { SSEUtils } from 'qwe-framework';

SSEUtils.broadcast(channel: string, event: SSEEvent): void;
SSEUtils.broadcastToAll(event: SSEEvent): void;
SSEUtils.subscribe(connectionId: string, channel: string): void;
SSEUtils.unsubscribe(connectionId: string, channel: string): void;

Testing API

Test Framework

import { 
  createTestFramework, 
  createTestClient,
  describe, 
  it, 
  beforeEach, 
  afterEach,
  assert 
} from 'qwe-framework';

const testFramework = createTestFramework();
const client = createTestClient(app);

describe('API Tests', () => {
  beforeEach(async () => {
    await setupTestData();
  });

  afterEach(async () => {
    await cleanupTestData();
  });

  it('should create user', async () => {
    const response = await client
      .post('/users')
      .send({ name: 'John', email: 'john@test.com' })
      .expect(201);

    assert.equal(response.body.success, true);
    assert.equal(response.body.data.name, 'John');
  });
});

HTTP Client

interface TestClient {
  get(path: string): TestRequest;
  post(path: string): TestRequest;
  put(path: string): TestRequest;
  delete(path: string): TestRequest;
  patch(path: string): TestRequest;
}

interface TestRequest {
  set(header: string, value: string): TestRequest;
  send(data: any): TestRequest;
  query(params: Record<string, any>): TestRequest;
  expect(status: number): Promise<TestResponse>;
  expect(field: string, value: any): Promise<TestResponse>;
  expect(callback: (res: TestResponse) => void): Promise<TestResponse>;
}

interface TestResponse {
  status: number;
  headers: Record<string, string>;
  body: any;
  text: string;
}

Assertions

interface AssertAPI {
  equal(actual: any, expected: any, message?: string): void;
  notEqual(actual: any, expected: any, message?: string): void;
  strictEqual(actual: any, expected: any, message?: string): void;
  deepEqual(actual: any, expected: any, message?: string): void;
  ok(value: any, message?: string): void;
  notOk(value: any, message?: string): void;
  throws(fn: () => void, expected?: Error | RegExp, message?: string): void;
  doesNotThrow(fn: () => void, message?: string): void;
  rejects(promise: Promise<any>, expected?: Error | RegExp, message?: string): Promise<void>;
  doesNotReject(promise: Promise<any>, message?: string): Promise<void>;
}

Configuration API

Environment Configuration

import { createConfig } from 'qwe-framework';

interface ConfigOptions {
  sources?: ('env' | 'file' | 'args')[];
  schema?: ConfigSchema;
  defaults?: Record<string, any>;
  validation?: boolean;
}

interface ConfigSchema {
  [key: string]: {
    type: 'string' | 'number' | 'boolean' | 'object' | 'array';
    required?: boolean;
    default?: any;
    properties?: ConfigSchema; // for object type
    items?: ConfigSchema; // for array type
  };
}

const config = createConfig({
  sources: ['env', 'file'],
  schema: {
    port: { type: 'number', default: 3000 },
    database: {
      type: 'object',
      properties: {
        host: { type: 'string', required: true },
        port: { type: 'number', default: 5432 }
      }
    }
  }
});

// Get configuration values
const port = config.get('port');
const dbHost = config.get('database.host');

// Watch for changes
config.watch('database.port', (newValue, oldValue) => {
  console.log(`Database port changed: ${oldValue}${newValue}`);
});

Type Definitions

// Core types
export interface QweAppOptions {
  trustProxy?: boolean;
  jsonLimit?: string;
  urlEncoded?: boolean;
  multipart?: boolean;
  static?: StaticOptions;
}

export interface QweHandler {
  (qwe: QweContext, next?: () => Promise<void>): Promise<QweResponse> | QweResponse;
}

export interface QweMiddleware {
  (qwe: QweContext, next: () => Promise<void>): Promise<void>;
}

export interface QweResponse {
  statusCode: number;
  headers: Record<string, string>;
  body: any;
}

export interface CookieOptions {
  maxAge?: number;
  expires?: Date;
  path?: string;
  domain?: string;
  secure?: boolean;
  httpOnly?: boolean;
  sameSite?: 'strict' | 'lax' | 'none';
  signed?: boolean;
}

// Error types
export class QweError extends Error {
  statusCode: number;
  details?: any;
  
  constructor(message: string, statusCode: number, details?: any);
}

export class ValidationError extends QweError {
  errors: ValidationErrorDetail[];
  
  constructor(message: string, errors: ValidationErrorDetail[]);
}

export interface ValidationErrorDetail {
  field: string;
  message: string;
  value?: any;
}

Error Handling

Built-in Error Types

// Framework errors
class QweError extends Error {
  statusCode: number;
  details?: any;
}

class ValidationError extends QweError {
  errors: ValidationErrorDetail[];
}

class AuthenticationError extends QweError {}
class AuthorizationError extends QweError {}
class RateLimitError extends QweError {}

// Error handler
app.use(async (qwe, next) => {
  try {
    await next();
  } catch (error) {
    if (error instanceof ValidationError) {
      return qwe.badRequest('Validation failed', error.errors);
    }
    
    if (error instanceof AuthenticationError) {
      return qwe.unauthorized(error.message);
    }
    
    if (error instanceof AuthorizationError) {
      return qwe.forbidden(error.message);
    }
    
    console.error('Unhandled error:', error);
    return qwe.internalServerError('Internal server error');
  }
});

This completes the comprehensive API reference for the Qwe Framework. The documentation covers all major APIs, utilities, plugins, and features with detailed examples and type definitions.