npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lintangoao/soulcode-http

v1.0.0

Published

Reusable HTTP server wrapper for Soulcode API

Readme

@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 @soulcode-api/http

Usage

Basic Server

import { HttpServer } from "@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 "@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 "@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 "@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 "@soulcode-api/http";
import { log } from "@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 "@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 "@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 @soulcode-api/core

API Reference

HttpServer

Constructor

new HttpServer(config?: HttpServerConfig)

Properties

  • app: Application - Express application instance

Methods

  • start(): Promise<void> - Start the HTTP server
  • stop(): Promise<void> - Stop the HTTP server gracefully
  • getPort(): 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
): TRequestHandler

Wrap 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 Express Request
  • TResponse - Alias untuk Express Response
  • TNextFunction - Alias untuk Express NextFunction
  • TRequestFunction<T> - Main type untuk controller methods
    type TRequestFunction<T = any> = (req: TRequest) => Promise<ApiResponse<T>>
      
    // Usage:
    myMethod: TRequestFunction = async (req) => { return {...} }
  • TRequestHandler<T> - Alias untuk TRequestFunction
  • TAsyncRequestHandler<T> - Alias untuk TRequestFunction
  • ApiResponse<T> - Standard response format
    interface ApiResponse<T = any> {
      statusCode?: number;  // default: 200
      message?: string;     // default: "Success"
      result?: T;          // data payload
    }

License

MIT