@lintangoao/soulcode-api-http
v1.0.3
Published
Reusable HTTP server wrapper for Soulcode API
Readme
@lintangoao/soulcode-api-http
Reusable HTTP server wrapper untuk Soulcode API. Package ini menyediakan abstraksi yang mudah untuk membuat HTTP server dengan Express.
Installation
pnpm add @lintangoao/soulcode-api-httpUsage
Basic Server
import { HttpServer } from "@lintangoao/soulcode-api-http";
const server = new HttpServer({
port: 3000,
onReady: (port) => {
console.log(`Server ready on port ${port}`);
},
});
// Setup routes
server.app.get("/", (req, res) => {
res.json({ message: "Hello World" });
});
// Start server
await server.start();Auto-Load Routes
Package ini menyediakan fitur auto-loading untuk routes. Semua file dengan pattern *.routes.ts akan otomatis di-load.
import { HttpServer, autoLoadRoutes } from "@lintangoao/soulcode-api-http";
import { fileURLToPath } from "url";
import { dirname } from "path";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const server = new HttpServer({ port: 3000 });
// Auto-load semua routes dari directory
await autoLoadRoutes(server.app, {
baseDir: __dirname,
pattern: "**/*.routes.{ts,js}", // optional, default value
});
await server.start();File structure example:
src/app/http/
├── index.ts
├── home/
│ └── home.routes.ts -> akan di-load ke "/"
└── users/
└── users.routes.ts -> akan di-load ke "/users"Example route file (home.routes.ts):
import { Router, requestHandler } from "@lintangoao/soulcode-api-http";
import { HomeController } from "@src/app/http/home/home.controller";
const router = Router();
const homeController = new HomeController();
// Gunakan requestHandler untuk auto error handling
router.get("/", requestHandler(homeController.index));
// IMPORTANT: harus export default
export default router;Example controller (home.controller.ts):
import { TRequest, TRequestFunction } from "@lintangoao/soulcode-api-http";
export class HomeController {
// Gunakan arrow function untuk auto-bind
index: TRequestFunction = async (req) => {
// Tidak perlu try-catch, requestHandler akan handle errors
const data = await someAsyncOperation();
// Return standard response format
return {
// statusCode: 200, // optional, default 200
// message: "Success", // optional, default "Success"
result: data,
};
};
}Configuration Options
interface HttpServerConfig {
port?: number; // Default: 3000
host?: string; // Default: "0.0.0.0"
cors?: boolean; // Default: true
helmet?: boolean; // Default: true
onReady?: (port: number) => void;
onError?: (error: Error) => void;
}
interface AutoLoadOptions {
baseDir: string; // Directory untuk search routes
pattern?: string; // Glob pattern (default: **/*.routes.{ts,js})
}Advanced Example
import { HttpServer } from "@lintangoao/soulcode-api-http";
import { log } from "@lintangoao/soulcode-api-core";
const server = new HttpServer({
port: 8080,
host: "localhost",
cors: true,
helmet: true,
onReady: (port) => log.info(`Server running on port ${port}`),
onError: (error) => log.error("Server error:", error),
});
// Access Express app directly
server.app.use((req, res, next) => {
log.info(`${req.method} ${req.path}`);
next();
});
// Define routes
server.app.get("/api/users", (req, res) => {
res.json({ users: [] });
});
server.app.post("/api/users", (req, res) => {
const user = req.body;
res.status(201).json({ user });
});
// Start server
await server.start();
// Later, stop the server
await server.stop();Request Handler
Package ini menyediakan requestHandler (alias: catchAsync) untuk wrap async controller methods dengan automatic error handling.
import { Router, requestHandler, TRequestFunction } from "@lintangoao/soulcode-api-http";
class UserController {
// Gunakan arrow function untuk auto-bind
getUsers: TRequestFunction = async (req) => {
// Jika error, otomatis di-catch dan di-pass ke error middleware
const users = await db.users.findMany();
return {
message: "Users retrieved successfully",
result: users,
};
};
}
const controller = new UserController();
const router = Router();
// Wrap dengan requestHandler (tidak perlu .bind lagi)
router.get("/users", requestHandler(controller.getUsers));Standard Response Format:
{
"statusCode": 200,
"message": "Success",
"result": { ... }
}Custom Types
Tidak perlu import dari express lagi:
import type { TRequest, TResponse, TNextFunction } from "@lintangoao/soulcode-api-http";
// Bukan: import { Request, Response } from "express";Features
- ✅ Express.js wrapper dengan konfigurasi yang clean
- ✅ Built-in CORS support
- ✅ Built-in Helmet security headers
- ✅ JSON body parsing
- ✅ URL-encoded body parsing
- ✅ Auto-loading routes dengan glob pattern
- ✅ Request handler wrapper dengan auto error handling
- ✅ Custom types untuk menghindari import express di setiap file
- ✅ Graceful shutdown
- ✅ TypeScript support
- ✅ Logger integration dengan @lintangoao/soulcode-api-core
API Reference
HttpServer
Constructor
new HttpServer(config?: HttpServerConfig)Properties
app: Application- Express application instance
Methods
start(): Promise<void>- Start the HTTP serverstop(): Promise<void>- Stop the HTTP server gracefullygetPort(): number- Get the current port number
autoLoadRoutes
async function autoLoadRoutes(
app: Application,
options: AutoLoadOptions
): Promise<void>Auto-load semua file routes berdasarkan pattern. File harus export default router.
requestHandler / catchAsync
function requestHandler(
handler: TAsyncRequestHandler
): TRequestHandlerWrap async controller methods untuk automatic error handling. Errors akan otomatis di-catch dan di-pass ke error middleware.
Parameters:
handler: (req: TRequest, res: TResponse) => Promise<void>- Async controller method
Returns:
- Express-compatible request handler dengan error handling
Example:
router.get("/users", requestHandler(controller.getUsers));Response Examples:
// Default (statusCode: 200, message: "Success")
return { result: data };
// Custom message
return {
message: "User created successfully",
result: newUser
};
// Custom status code
return {
statusCode: 201,
message: "Resource created",
result: newResource
};
// No data
return {
message: "Operation completed"
};Tips: Gunakan arrow functions di controller untuk auto-binding:
class MyController {
// ✅ Arrow function dengan type annotation - auto-bind, clean syntax
myMethod: TRequestFunction = async (req) => {
// this.service works!
return { result: data };
};
// ❌ Regular method - perlu .bind(this)
async myMethod2(req: TRequest): Promise<ApiResponse> {
// this.service might be undefined
}
}Types
TRequest- Alias untuk ExpressRequestTResponse- Alias untuk ExpressResponseTNextFunction- Alias untuk ExpressNextFunctionTRequestFunction<T>- Main type untuk controller methodstype TRequestFunction<T = any> = (req: TRequest) => Promise<ApiResponse<T>> // Usage: myMethod: TRequestFunction = async (req) => { return {...} }TRequestHandler<T>- Alias untukTRequestFunctionTAsyncRequestHandler<T>- Alias untukTRequestFunctionApiResponse<T>- Standard response formatinterface ApiResponse<T = any> { statusCode?: number; // default: 200 message?: string; // default: "Success" result?: T; // data payload }
License
MIT
