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

hivest-js

v0.8.0

Published

A simple, fast and minimalist framework for Node.js that allows you to create modular applications with dependency injection using decorators

Readme

Hivest

A simple, fast and minimalist framework for Node.js that allows you to create modular applications with dependency injection using decorators.

🎯 What is Hivest?

Hivest is a framework that simplifies the creation of modular Node.js applications, offering:

  • Hierarchical modules with provider inheritance
  • Decorators for controllers, routes, and middlewares
  • Automatic dependency injection
  • Organized path structure
  • Zero complex configuration
  • Clean architecture patterns

🚀 Key Features

Simplicity

  • Minimal setup, no complex configurations
  • Intuitive and familiar API
  • Simple and direct decorators

Performance

  • Fast initialization
  • Efficient dependency resolution
  • No unnecessary overhead

🧩 Modularity

  • Independent and reusable modules
  • Automatic provider inheritance
  • Clear hierarchical structure

🎨 Flexibility

  • Customizable decorators
  • Hierarchically organized paths
  • Easy to extend
  • Middleware support
  • Automatic middleware classes
  • Error handler middleware system

🏗️ Architecture

  • Clean design patterns (Strategy, Composite, Template Method)
  • Separation of concerns
  • Well-documented codebase
  • Type-safe development
  • Automatic middleware detection
  • Centralized error handling

🎯 Installation

npm install hivest
# or
yarn add hivest

🏗️ Core Concepts

AppModule

The basic building block. Each module can have:

  • Providers: Services, repositories, configurations
  • Controllers: API endpoints and middlewares
  • Imports: Other imported modules

Decorators

  • @Controller(): Defines base path for a controller
  • @HttpPost(), @HttpGet(), etc.: Defines HTTP routes
  • @HttpMiddleware(): Defines middleware methods
  • @Middleware(): Defines middleware classes (all methods become middleware)
  • @ErrorHandlerMiddleware(): Defines error handler classes
  • @Injectable(): Marks class for dependency injection
  • @Inject(): Inject specific dependencies

Providers

  • Class Providers: Classes that will be instantiated
  • Value Providers: Simple values
  • Smart Providers: Automatic type detection

📚 Usage Examples

1. Creating a Simple Module

import { AppModule, Controller, HttpGet } from 'hivest';

@Controller({ path: '/users' })
class UserController {
  @HttpGet('/')
  async getUsers({ req, res }) {
    return res.json({ users: [] });
  }
}

const userModule = new AppModule({
  path: '/api',
  controllers: [UserController],
  providers: [UserService],
});

2. Controllers with Middleware

@Controller({ path: '/auth' })
class AuthController {
  @HttpMiddleware()
  async validateToken({ req, res, next }) {
    const token = req.headers.authorization;
    if (!token) {
      return res.status(401).json({ error: 'No token provided' });
    }
    next();
  }

  @HttpPost('/login')
  async login({ req, res }) {
    return res.json({ message: 'Login successful' });
  }

  @HttpGet('/profile')
  async getProfile({ req, res }) {
    return res.json({ user: req.user });
  }
}

3. Automatic Middleware Classes

// Global logging middleware
@Middleware()
export class LogMiddleware {
  async log({ req, next }) {
    console.log(`[LOG] ${req.method} ${req.path}`);
    next();
  }

  // This method has a decorator, so it becomes a route
  @HttpGet('/test')
  async test({ req, res }) {
    console.log(`[TEST] ${req.method} ${req.path}`);
    res.json({ message: 'test' });
  }
}

// Authentication middleware with routes
@Middleware({ path: '/auth' })
export class AuthMiddleware {
  async validateToken({ req, res, next }) {
    const token = req.headers.authorization;
    if (!token) {
      return res.status(401).json({ error: 'No token provided' });
    }
    next();
  }

  @HttpPost('/login')
  async login({ req, res }) {
    return res.json({ message: 'Login successful' });
  }
}

// Register in module
const app = new AppModule({
  path: '/api',
  controllers: [LogMiddleware, AuthMiddleware], // All methods become middleware automatically
});

4. Error Handler Middleware

// Global error handler middleware
@ErrorHandlerMiddleware()
export class ErrorMiddleware {
  async handleError({ req, res, err }: HttpContext) {
    if (!err) return;

    console.error(`[ERROR] ${req.method} ${req.path}:`, err);

    const status = err.status || err.statusCode || 500;
    const message = err.message || 'Internal Server Error';

    return res.status(status).json({
      error: {
        message,
        status,
        timestamp: new Date().toISOString(),
        path: req.path,
        method: req.method,
      },
    });
  }
}

// Controller with error throwing
@Controller({ path: '/users' })
class UserController {
  @HttpGet('/:id')
  async getUser({ req, res }) {
    const user = await this.userService.getUser(req.params.id);

    if (!user) {
      const error: any = new Error('User not found');
      error.status = 404;
      throw error; // Capturado automaticamente pelo ErrorMiddleware
    }

    return res.status(200).json(user);
  }
}

// Register in module
const app = new AppModule({
  path: '/api',
  controllers: [ErrorMiddleware, UserController], // Error handler é detectado automaticamente
});

5. Modules with Inheritance

// Parent module with providers
const mainModule = new AppModule({
  path: '/api',
  providers: [
    { key: 'UserService', provide: UserService },
    { key: 'Database', provide: Database },
  ],
  imports: [UserModule], // Child module inherits providers
});

// Child module
class UserModule extends AppModule {
  constructor() {
    super({
      path: '/users',
      controllers: [UserController, AuthController],
    });
  }
}

5. Path Hierarchy

@Controller({ path: '/auth' })
class AuthController {
  @HttpPost('/login')     // → /api/users/auth/login
  @HttpPost('/register')  // → /api/users/auth/register
  @HttpGet('/profile')    // → /api/users/auth/profile
}

6. Dependency Injection

@Injectable()
class UserController {
  constructor(
    @Inject('UserService')
    readonly userService: UserService,

    @Inject('Database')
    readonly database: Database,
  ) {}
}

🏃‍♂️ Quick Start

1. Install dependencies

yarn add hivest express reflect-metadata tsyringe

2. Create main module

import { AppModule } from 'hivest';

const app = new AppModule({
  path: '/api',
  providers: [UserService],
  controllers: [UserController],
});

app.listen(3000);

3. Create controller

import { Controller, HttpGet } from 'hivest';

@Controller({ path: '/users' })
class UserController {
  @HttpGet('/')
  async getUsers({ req, res }) {
    return res.json({ message: 'Hello Hivest!' });
  }
}

📁 Recommended Project Structure

src/
├── modules/
│   ├── user/
│   │   ├── user.controller.ts
│   │   ├── user.service.ts
│   │   └── user.module.ts
│   └── auth/
│       ├── auth.controller.ts
│       ├── auth.service.ts
│       └── auth.module.ts
├── shared/
│   ├── database.ts
│   └── config.ts
└── main.module.ts

🔧 Available Scripts

Development

yarn dev          # Runs server with examples and tests
yarn build        # Compiles TypeScript project
yarn start        # Runs compiled server

Examples

The project includes complete examples in src/exemple/ that demonstrate:

  • Hierarchical modules
  • Controllers with custom paths
  • Provider inheritance
  • Authentication and settings endpoints
  • Middleware implementation

🌟 Example Endpoints

  • POST /api/companies - Create company
  • GET /api/companies/:id - Get company
  • POST /api/users - Create user
  • GET /api/users/:id - Get user
  • POST /api/users/auth/login - Login
  • POST /api/users/auth/register - Register
  • GET /api/users/auth/profile - Profile
  • POST /api/users/auth/logout - Logout
  • GET /api/users/settings/ - Settings
  • PUT /api/users/settings/theme - Update theme

🎨 Available Decorators

@Controller(options)

Defines base path for a controller and automatically makes it injectable:

@Controller({ path: '/auth' })
class AuthController {
  // Routes will be prefixed with /auth
  // Class is automatically injectable (no need for @Injectable())
}

@HttpPost(path), @HttpGet(path), etc.

Defines HTTP routes:

@HttpPost('/login')
@HttpGet('/profile')
@HttpPut('/update')
@HttpDelete('/remove')

@HttpMiddleware()

Defines middleware methods within a controller:

@HttpMiddleware()
async validateToken({ req, res, next }) {
  // Middleware logic here
  next();
}

@Middleware(options?)

Defines a middleware class where all methods without HTTP decorators are automatically treated as middleware:

// Global middleware (executes on all routes)
@Middleware()
export class LogMiddleware {
  async log({ req, next }) {
    console.log(`[LOG] ${req.method} ${req.path}`);
    next();
  }
}

// Specific path middleware (executes only on matching routes)
@Middleware({ path: '/auth' })
export class AuthMiddleware {
  async validateToken({ req, res, next }) {
    const token = req.headers.authorization;
    if (!token) {
      return res.status(401).json({ error: 'No token provided' });
    }
    next();
  }

  // This method has a decorator, so it becomes a route
  @HttpPost('/login')
  async login({ req, res }) {
    return res.json({ message: 'Login successful' });
  }
}

Nota: Em classes com @Middleware, métodos com decorators HTTP (como @HttpGet, @HttpPost, etc.) se tornam rotas, enquanto métodos sem decorators se tornam middleware automaticamente.

@ErrorHandlerMiddleware()

Defines an error handler class where all methods are automatically registered as Express error middleware:

@ErrorHandlerMiddleware()
export class ErrorMiddleware {
  async handleError({ req, res, err }: HttpContext) {
    if (!err) return;

    console.error(`[ERROR] ${req.method} ${req.path}:`, err);

    const status = err.status || err.statusCode || 500;
    const message = err.message || 'Internal Server Error';

    return res.status(status).json({
      error: {
        message,
        status,
        timestamp: new Date().toISOString(),
        path: req.path,
        method: req.method,
      },
    });
  }
}

Nota: Classes com @ErrorHandlerMiddleware() são automaticamente detectadas pelo AppModule e registradas como middleware de erro no Express. Todos os métodos da classe se tornam error handlers.

@Injectable()

Marks class for dependency injection:

@Injectable()
class UserService {
  // Will be injectable in other services
}

@Inject(token)

Injects specific dependency:

constructor(
  @Inject('UserService')
  readonly userService: UserService
) {}

🔄 Provider Inheritance

Child modules automatically inherit all providers from parent modules:

// Parent module
const mainModule = new AppModule({
  providers: [UserService, Database],
});

// Child module has access to UserService and Database
class UserModule extends AppModule {
  constructor() {
    super({
      controllers: [UserController], // Can use UserService and Database
    });
  }
}

🏗️ Architecture Patterns

Hivest implements several design patterns for clean and maintainable code:

Strategy Pattern

  • Handles different provider types (class, value, smart)
  • Processes different controller item types (route, middleware)

Composite Pattern

  • Manages module hierarchy and provider inheritance
  • Allows modules to be composed of other modules

Template Method Pattern

  • Consistent processing of controllers across modules
  • Standardized route and middleware registration

Visitor Pattern

  • Processes controllers from imported modules
  • Maintains separation between local and external module logic

🚀 Why Hivest?

vs NestJS

  • ✅ Simpler and more direct
  • ✅ Less configuration
  • ✅ Smaller learning curve
  • ✅ Focus on simplicity
  • ✅ Cleaner architecture

vs Pure Express

  • ✅ Organized structure
  • ✅ Dependency injection
  • ✅ Intuitive decorators
  • ✅ Native modularity
  • ✅ Middleware support

vs Other frameworks

  • ✅ Zero unnecessary overhead
  • ✅ Familiar API
  • ✅ Easy migration
  • ✅ Optimized performance
  • ✅ Design patterns implementation

🤝 Contributing

  1. Fork the project
  2. Create a branch for your feature
  3. Commit your changes
  4. Push to the branch
  5. Open a Pull Request

📄 License

This project is licensed under the MIT License. See the LICENSE file for details.

🆘 Support


Hivest - Transforming code into modules in a simple and efficient way! 🚀

🆕 What's New in v0.7.1

  • Provider Inheritance Fix: Providers (services, repositories, etc.) registered in parent modules are now correctly available to all imported child modules and their controllers. This makes dependency injection work reliably across complex module hierarchies.
  • No breaking changes. If you had issues with DI in nested modules, just update to v0.7.1!