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

seven365-http-foundation

v0.0.7

Published

Clean Architecture utilities for Express: Type-safe DTOs, standardized service returns, and MongoDB-friendly request helpers.

Readme

seven365-http-foundation

Clean Architecture utilities for Express: Type-safe DTOs, standardized service returns, and MongoDB-friendly request helpers.

Installation

npm install seven365-http-foundation

Ideal Folder Structure

To maintain a clean Service-Repository pattern in your Node.js backend, we recommend the following structure:

src/
├── controllers/    # Express Controllers: Handle HTTP logic & use ResponseHelper
├── services/       # Business Logic: Use Repositories & return ServiceResponse
├── repositories/   # Data Access: Interaction with MongoDB/Mongoose
├── models/         # Database Schemas: Mongoose Models/Entities
├── requests/       # Request Validation: Extends BaseRequest with Joi Schemas
├── dtos/           # Data Transfer: Extends BaseDto for structured data
├── middleware/     # Custom Middleware: Validation, Auth, etc.
└── index.ts        # Entry point

Complete Usage Flow

1. The Model (Entity)

import { Schema, model } from 'mongoose';

const UserSchema = new Schema({
  email: { type: String, required: true, unique: true },
  username: { type: String, required: true },
  isActive: { type: Boolean, default: true }
}, { timestamps: true });

export const UserModel = model('User', UserSchema);

2. The Request & DTO

import { BaseRequest } from 'seven365-http-foundation';
import Joi from 'joi';

// Joi Schema for Middleware validation
export const CreateUserSchema = Joi.object({
  email: Joi.string().email().required(),
  username: Joi.string().min(3).required(),
});

// Request Class
export class CreateUserRequest extends BaseRequest {
  public toDto() {
    return {
      email: this.getString('email'),
      username: this.getString('username')
    };
  }
}

3. The Repository

import { UserModel } from '../models/UserModel';

export class UserRepository {
  async findByEmail(email: string) {
    return await UserModel.findOne({ email });
  }

  async create(data: any) {
    return await UserModel.create(data);
  }
}

4. The Service

import { ServiceResponse } from 'seven365-http-foundation';
import { UserRepository } from '../repositories/UserRepository';

export class UserService {
  private userRepository = new UserRepository();

  async registerUser(dto: any): Promise<ServiceResponse> {
    const existingUser = await this.userRepository.findByEmail(dto.email);
    
    if (existingUser) {
      return ServiceResponse.error('User already exists');
    }

    const newUser = await this.userRepository.create(dto);
    return ServiceResponse.success('Registration successful', newUser);
  }
}

5. The Controller

import { Request, Response } from 'express';
import { CreateUserRequest } from '../requests/CreateUserRequest';
import { UserService } from '../services/UserService';
import { ResponseHelper, HttpResponse } from 'seven365-http-foundation';

export class UserController {
  private service = new UserService();

  public store = async (req: Request, res: Response) => {
    const userRequest = new CreateUserRequest(req);
    
    const result = await this.service.registerUser(userRequest.toDto());

    if (result.isError()) {
      return ResponseHelper.error(res, result.getMessage()!, HttpResponse.HTTP_BAD_REQUEST);
    }

    return ResponseHelper.json(res, result.getData(), HttpResponse.HTTP_CREATED);
  }
}

6. The Routes (with Validation Middleware)

import { Router } from 'express';
import { UserController } from '../controllers/UserController';
import { CreateUserSchema } from '../requests/CreateUserRequest';
import { validateDto } from 'seven365-http-foundation';

const router = Router();
const userController = new UserController();

/**
 * POST /api/users
 * Validates request body against CreateUserSchema before passing to controller.
 * 
 * Example request:
 * {
 *   "email": "[email protected]",
 *   "username": "john_doe"
 * }
 * 
 * On validation error (HTTP 422):
 * {
 *   "success": false,
 *   "message": "Validation Error: email must be a valid email, username must be at least 3 characters"
 * }
 */
router.post('/users', validateDto(CreateUserSchema), userController.store);

export default router;

How ValidateDto Middleware Works

The validateDto middleware:

  1. Validates incoming request body against a Joi schema
  2. Strips unknown fields for security (removes unexpected properties)
  3. Rejects invalid fields with detailed error messages
  4. Replaces req.body with sanitized data before passing to controller
  5. Returns standardized errors using ResponseHelper on validation failure

Features:

  • ✅ Security: Prevents injection of unknown fields
  • ✅ Sanitization: Automatically cleans request data
  • ✅ Detailed errors: Maps all Joi validation errors
  • ✅ Type-safe: Works seamlessly with TypeScript

Key Features

  • BaseRequest: Type-safe casting (getString, getInt, getBoolean) and MongoDB-specific helpers like getMongoId.
  • ServiceResponse: Standardized return type for services to prevent leaky abstractions.
  • HttpResponse: Full list of Symfony-style HTTP status constants.
  • ResponseHelper: Concise methods for consistent JSON API responses.

Requirements

  • Node.js >= 14
  • Express >= 4.17
  • Joi >= 17.0.0

License

MIT

Author

Billy Joel Ranario