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 🙏

© 2024 – Pkg Stats / Ryan Hefner

ex-lite

v1.0.2

Published

`ex-lite` is a lightweight utility library for Express.js, designed to simplify common patterns and improve error handling in your Express applications. It includes helper functions, HTTP error handling, status code management, response formatting, input

Downloads

30

Readme

ex-lite

ex-lite is a lightweight utility library for Express.js, designed to simplify common patterns and improve error handling in your Express applications. It includes helper functions, HTTP error handling, status code management, response formatting, input validation with Zod, and dependency injection with tsyringe.

Installation

Install ex-lite and its peer dependencies via npm, yarn and pnpm:

npm install ex-lite zod tsyringe
yarn add ex-lite zod tsyringe
pnpm add ex-lite zod tsyringe

Features

  • HttpError: A class for handling and customizing HTTP errors. and includes some prebuilt error classes BadRequestError, ConflictError, ForbiddenError, InternalServerError, NotFoundError, and UnauthorizedError.
  • wrapper: A function to simplify async controller functions.
  • HttpStatus: An enumeration of HTTP status codes.
  • HttpRes: A class for creating standardized JSON responses.
  • ApiRes: An extension of HttpRes with static methods for common API responses(Ok, Create).
  • validate: Middleware for validating request body, query, and params using Zod.
  • controllerFactory: A factory function for creating controller handlers with dependency injection using tsyringe.

Project Configuration

To use ex-lite in your Express.js project, follow these steps to set up your project structure and configure the library.

1. Project Structure

Here’s a basic example of how to structure your Express.js project using ex-lite:

my-express-app/
│
├── src/
│   ├── controllers/
│   │   └── AuthController.ts
│   ├── services/
│   │   └── AuthService.ts
│   ├── middlewares/
│   │   └── error.middleware.ts
│   ├── routes/
│   │   └── auth.routes.ts
│   ├── app.ts
│   └── server.ts
│
├── package.json
└── tsconfig.json

2. Global Error Handler

Use the following global error handler to handle exceptions across your application:

// src/middlewares/error.middleware.ts
import { ErrorRequestHandler } from "express";
import { HttpError, InternalServerError, HttpStatus } from "ex-lite";

export const globalError: ErrorRequestHandler = (err, req, res, next) => {
  // Handle known HTTP errors
  if (HttpError.isHttpError(err)) {
    return res.status(err.status).json(err.getBody());
  }

  // Log unknown errors to the console
  console.error(err);

  // Handle unknown errors with a generic Internal Server Error response
  return res
    .status(HttpStatus.INTERNAL_SERVER_ERROR)
    .send(new InternalServerError(err.message).getBody());
};

3. Setting Up ex-lite in Express

Integrate ex-lite into your Express application as follows:

// src/app.ts
import express from "express";
import { globalError } from "./middlewares/error.middleware";
import authRoutes from "./routes/auth.routes";

const app = express();

// Middleware for parsing JSON bodies
app.use(express.json());

// Register your routes
app.use("/auth", authRoutes);

// Global error handler
app.use(globalError);

export default app;

4. Setting Up Your Server

Create an entry point to start your Express application:

// src/server.ts
import app from "./app";

const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

Usage

1. Handling Async Controllers with wrapper

The wrapper function helps you manage async controller functions, automatically handling promise resolution and errors.

import { wrapper } from "ex-lite";

const getUser = wrapper(async (req, res) => {
  const user = await getUserById(req.params.id);
  return ApiRes.ok(user);
});

app.get("/user/:id", getUser);

2. With Prebuilt HTTP Errors

ex-lite provides a set of prebuilt HTTP errors to make error handling easier.

import { BadRequestError, NotFoundError } from "ex-lite";

app.post(
  "/example",
  wrapper((req, res, next) => {
    if (!req.body.name) throw new BadRequestError("Name is required");
  })
);

app.get(
  "/example/:id",
  wrapper((req, res, next) => {
    const item = findItemById(req.params.id);
    if (!item) throw new NotFoundError("Item not found");

    return new HttpRes(item);
  })
);

// example with unknown error
app.get(
  "/unknown-error",
  wrapper((req, res, next) => {
    throw new Error("Hello World");
  })
);

3. Using HttpStatus for Consistent Status Codes

The HttpStatus enumeration provides a consistent way to manage HTTP status codes.

import { HttpStatus } from "ex-lite";

app.get("/status-example", (req, res) => {
  res.status(HttpStatus.OK).json({ message: "All good!" });
});

4. Standardized JSON Responses with HttpRes and ApiRes

HttpRes provides a consistent structure for JSON responses. ApiRes extends HttpRes and includes static methods like ok and created for common API response patterns.

import { ApiRes } from "ex-lite";

app.post(
  "/create-user",
  wrapper((req) => {
    const user = createUser(req.body);
    return ApiRes.created(user, "User created successfully");
  })
);

app.get(
  "/get-user",
  wrapper((req) => {
    const user = getUserById(req.query.id);
    return ApiRes.ok(user);
  })
);

5. Request Validation with validate

Use the validate middleware to enforce schema-based validation using Zod.

import { validate } from "ex-lite";
import { z } from "zod";

const userSchema = z.object({
  name: z.string().min(1),
  age: z.number().min(0),
});

app.post("/user", validate.body(userSchema), (req, res) => {
  res.json(ApiRes.ok(req.body));
});

6. Dependency Injection with controllerFactory

ex-lite supports dependency injection for controllers using tsyringe. Use the controllerFactory function to create controller handlers.

import { singleton } from "tsyringe";
import { controllerFactory } from "ex-lite";
import { AuthService } from "./services";

@singleton()
export class AuthController {
  constructor(private authService: AuthService) {}

  async signin(req, res) {
    const { access, refresh, user } = await this.authService.signin(req.body);
    res.cookie("access-token", access.token, {
      httpOnly: true,
      maxAge: access.maxAge,
    });
    res.cookie("refresh-token", refresh.token, {
      httpOnly: true,
      maxAge: refresh.maxAge,
    });
    return ApiRes.ok(user.id, "User login successfully");
  }

  async signup(req) {
    const user = await this.authService.signup(req.body);
    return ApiRes.created(user.id, "User created successfully");
  }
}

// Create controller handlers with dependency injection
const authController = controllerFactory(AuthController);

app.post("/signin", authController.getMethod("signin"));
app.post("/signup", authController.getMethod("signup"));

Contributing

Contributions are welcome! Please fork the repository and submit a pull request with your improvements.

License

ex-lite is licensed under the MIT License. See the LICENSE file for more information.


Disclaimer: This library is currently under development. While contributions are appreciated, there is no need to start begging for features or fixes.