Skip to content

mqnoy/http-keong

Repository files navigation

http-ke@ng

http-ke@ng: Express.js Wrapper with SwaggerUI

Light. Steady. Protected.


http-keong is a developer-friendly, decorator-powered wrapper for Express.js. It brings the architectural elegance of frameworks like NestJS to the lightweight Express ecosystem, featuring automatic Swagger UI generation, Standardized JSON Responses, and Context-Aware Request Augmentation.


🐚 Why "Keong"?

In Indonesian, Keong means snail. This library isn't about being slow; it's about carrying your "shell" (your protection and logic) with you everywhere.

  • Steady: High-quality code structure using TypeScript decorators.
  • Lightweight: Zero fluff, just a thin, powerful layer over Express.
  • Protected: Encapsulation of routes, middlewares, and documentation.
  • Progressive: Built for engineers who want clean code without complex boilerplate.

πŸš€ Quick Start

1. Installation

pnpm install @mqnoy/http-keong reflect-metadata express

2. Configure TypeScript

Enable decorators in your tsconfig.json:

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

3. Build your first Controller

import 'reflect-metadata';
import { KeongFactory, Controller, Get, ApiResponse } from '@mqnoy/http-keong';

@Controller('/hello')
class HelloController {
  @Get('/')
  index() {
    // Standardized response with data and metadata
    return ApiResponse.success({ message: 'Hello World!' });
  }
}

const app = KeongFactory.create([HelloController], {
  swagger: { title: 'My Awesome API' }
});

app.listen(3000, () => console.log('🐌 Keong is crawling at http://localhost:3000'));

✨ Core Features

πŸ›€ Decorator-Based Routing

Clean and intuitive routing using class and method decorators.

  • @Controller(prefix): Define base paths.
  • @Get(path), @Post(path), @Put(path), @Delete(path), @Patch(path): Standard HTTP verbs.

πŸ›‘ Middleware Integration

Apply cross-cutting concerns at the class level or individual route level.

@Middleware(loggerMiddleware)
@Controller('/users')
class UserController {
  @Post('/')
  @Middleware(authGuard)
  create() { ... }
}

πŸ“– Automated Swagger Documentation

Stop writing documentation manually. http-keong generates a full OpenAPI spec from your code.

  • @ApiTags(): Group your routes.
  • @ApiOperation(): Add summaries and descriptions.
  • @ApiBody({ type: MyDto }): Document request payloads.
  • @ApiDocResponse(status, options): Document expected responses.
  • @ApiBearerAuth(): Flag secure routes in Swagger UI.

πŸ“¦ Type-Safe DTOs

Use @ApiProperty to define your data structures. These are automatically converted into Swagger schemas.

class UserDto {
  @ApiProperty({ example: 'John Doe', required: true })
  name!: string;

  @ApiProperty({ example: 25, description: 'Age in years' })
  age!: number;
}

πŸ’Ž Standardized JSON Responses & Errors

The specialized ApiResponse class ensures your API always speaks the same language. All response and error helpers follow a "Message First" convention for better readability.

1. Success Responses

Use static helpers for consistent data delivery.

// Simple success (Defaults: message="Success", code="SUCCESS")
return ApiResponse.success({ id: 1 }); 

// Custom message and business code
return ApiResponse.success(data, 'User updated successfully', 'UPDATE_OK');

2. Error Handling

You can throw built-in error classes or return an error response manually.

// Standard Errors (message first)
throw new NotFoundError('User profile not found');
throw new ValidationHttpError('Invalid payload', { email: 'is required' });

// Generic Error Helper
return ApiResponse.error('Connection timed out', 'GATEWAY_ERROR', 504);

Production Format (Default):

{
  "data": { "id": 1, "name": "John Doe" }
}

Debug Format (HTTP_KEONG_DEBUG=true):

{
  "data": { "id": 1, "name": "John Doe" },
  "meta": {
    "code": "SUCCESS",
    "message": "Operation successful",
    "checksum": "a1b2c3d4e5",
    "timestamp": "2024-02-22T20:00:00.000Z",
    "requestId": "uuid-v4-abc"
  }
}

πŸ›  Configuration & Debug Mode

You can enable debug mode to see detailed metadata in your responses.

# Enable debug mode via environment variable
HTTP_KEONG_DEBUG=true pnpm run dev

When HTTP_KEONG_DEBUG is true, http-keong will:

  1. Include the meta object in all JSON responses.
  2. Generate a base64 checksum for the data payload.
  3. Include an ISO timestamp in the response.
  4. Print the route table to the console on startup.

🧩 Context-Aware Requests

http-keong automatically augments the Express Request object with a ctx property, which includes a requestId by default. You can extend this context for your own needs.

@Get('/me')
getMe(req: Request) {
  const requestId = req.ctx.requestId;
  return ApiResponse.success({ id: 1, reqId: requestId });
}

πŸ₯ Built-in Health Check

A dedicated health check endpoint is available by default at /health. You can customize the path and handler if needed.

KeongFactory.create(controllers, {
  healthCheckHandler: {
    path: '/ping',
    handler: (req, res) => res.send('pong')
  }
});

πŸͺ΅ Custom Logger Injection

Integrates seamlessly with @mqnoy/lolog or any logger implementing the ILogger interface.

KeongFactory.create(controllers, { logger: myLogger });

πŸ”‘ Configurable Business Codes

Decouple HTTP status codes from your internal logic codes.

KeongFactory.create(controllers, {
  responseCodes: {
    success: 'PROCESS_OK',
    error: 'API_FAILURE'
  }
});

πŸ“‚ Deep Dive & Examples

Explore our examples directory for practical implementations:


🀝 Honesty Section (Trade-offs)

  • Express Dependent: It's a wrapper, so you're still within the Express ecosystem.
  • Experimental Decorators: Relies on experimentalDecorators: true in TypeScript.
  • Reflect Metadata: Requires the reflect-metadata polyfill.

πŸ›  Development & Testing

pnpm run build  # Build the project
pnpm test       # Run the test suite (Jest + SWC)

Built with care for the production Node.js ecosystem. Issues and contributions are welcome on GitHub.

About

In Indonesian, Keong means snail. This library isn't about being slow; it's about carrying your "shell" (your protection and logic) with you everywhere.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors