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

@vulkano/core

v1.20.0

Published

A MVC framework using Express 4

Readme


What is Vulkano?

Vulkano is a lightweight MVC framework for building web applications and APIs with Node.js. It wires together Express, MongoDB (Mongoose), Socket.io, i18n, JWT, file uploads, cron jobs, and more — so you spend time writing features, not boilerplate.

Inspired by KumbiaPHP.


Requirements

  • Node.js ^22
  • MongoDB (optional — only needed if you use models)
  • Redis (optional — only needed for Socket.io Redis adapter or sessions)

Installation

npm install @vulkano/core

Quick Start

1. Entry point — app.js

const vulkano = require('@vulkano/core');
vulkano();

2. Project structure

your-app/
├── app.js                  # Entry point
├── public/                 # Static files served over HTTP
│   ├── css/
│   ├── js/
│   ├── img/
│   └── files/              # Uploaded files
└── vulkano/                # Your application
    ├── config/
    │   ├── settings.js     # App-wide settings (port, database, JWT…)
    │   ├── routes.js       # Explicit route overrides (optional)
    │   ├── env/            # Per-environment config overrides
    │   ├── express/        # Express middleware customization
    │   ├── settings.js     # App-wide settings (port, database, JWT…)
    │   ├── routes.js       # Explicit route overrides (optional)
    │   └── locales/        # i18n translation files (en.js, es.js, etc.)
    ├── controllers/        # Request handlers
    ├── models/             # Mongoose model definitions
    └── services/           # Shared services & libs (auto-loaded as globals)

Routing

Vulkano resolves routes by convention — no route file required for standard CRUD.

Convention-based (automatic)

| HTTP method | URL | Resolves to | |-------------|------------------|-------------------------------------| | GET | /user | UserController.get | | POST | /user | UserController.post | | PUT | /user/42 | UserController['put :id'] | | PATCH | /user/42 | UserController['patch :id'] | | DELETE | /user/42 | UserController['delete :id'] | | POST | /user/save | UserController['post save'] | | GET | /user/42/info | UserController['get :id/info'] |

Controller example

// vulkano/controllers/UserController.js
module.exports = {

  get(req, res) {
    res.vsr(Promise.resolve({ users: [] }));
  },

  'get :id': function (req, res) {
    res.vsr(Promise.resolve({ id: req.params.id }));
  },

  'post save': function (req, res) {
    res.vsr(Promise.resolve({ saved: true }));
  }

};

Explicit routes — config/routes.js

module.exports = [
  { method: 'GET',  path: '/health', controller: 'StatusController', action: 'ping' },
  { method: 'POST', path: '/auth/login', controller: 'AuthController', action: 'login' },
];

You can also register routes with inline handlers or using app.vulkano.get/post/….


Responses — res.vsr()

Every controller action uses res.vsr(promise). It wraps the resolved value in a standard envelope:

{ "success": true, "statusCode": 200, "data": { … } }

Errors are handled automatically:

// Custom error with status code
res.vsr(VSError.reject('Not allowed', 403));

// 404
res.vsr(VSError.notFound('User'));

// Plain rejection → 500
res.vsr(Promise.reject(new Error('Something went wrong')));

Scaffold — zero-code REST API

Point a controller at a model and get a full REST API for free:

// vulkano/controllers/api/ProductController.js
module.exports = {
  scaffold: 'Product',           // Mongoose model name
  allowedMethods: ['get', 'post', 'put', 'patch', 'delete']
};

This automatically exposes:

| Method | Path | Action | |----------|--------------------|------------------| | GET | /api/product | List (paginated) | | GET | /api/product/:id | Get by ID | | POST | /api/product | Create | | PUT | /api/product/:id | Replace | | PATCH | /api/product/:id | Partial update | | DELETE | /api/product/:id | Soft-delete |

Query string params supported on list: page, per_page, sort, search, fields.


Models

Models live in vulkano/models/ and are auto-loaded as globals (e.g., Product).

// vulkano/models/Product.js
module.exports = {
  attributes: {
    name:  { type: String, required: true },
    price: { type: Number, default: 0 },
    tags:  { type: [String] }
  },

  // Lifecycle hooks
  beforeSave(next) {
    this.updatedAt = new Date();
    next();
  }
};

Every model automatically gets active, createdAt, and updatedAt fields. Models use mongoose-paginate-v2 for pagination.


Built-in Global Libs

All files in vulkano/services/ are auto-loaded as globals. The framework also exposes:

| Global | Description | |-------------|-----------------------------------------------------------------| | VSError | Structured error factory (reject, notFound, badRequest) | | Jwt | Sign / verify JWT tokens | | Paginate | Query serialization and pagination helpers | | Merge | Deep-merge utility (deepmerge-compatible, full option support) | | Encrypter | Hash and compare passwords (bcrypt-based) | | Filter | Input sanitization helpers | | Crontab | Schedule recurring jobs with cron expressions | | ApiClient | HTTP client for calling external APIs (native fetch + undici) | | Download | File download helper | | i18n | Internationalization via i18next | | mongoose | Mongoose instance |


File Uploads

Vulkano uses Multer v2. Files are available on req.files after a multipart/form-data POST:

'post upload': function (req, res) {
  const files = (req.files || []).map((f) => ({
    fieldname:    f.fieldname,
    originalname: f.originalname,
    mimetype:     f.mimetype,
    size:         f.size
  }));
  res.vsr(Promise.resolve({ uploaded: files.length, files }));
}

JWT Authentication

Configure in vulkano/config/express/jwt.js:

module.exports = {
  secret: process.env.JWT_SECRET,
  unless: ['/auth/login', '/health']   // Public paths (no token required)
};

Sign a token anywhere in your app:

const token = Jwt.encode({ userId: user._id });

Cron Jobs

// vulkano/services/Jobs.js
module.exports = {
  init() {
    Crontab.add('cleanup', '0 3 * * *', async () => {
      await Report.deleteMany({ active: false });
    });
  }
};

i18n

Translation files go in vulkano/config/locales/. Use i18n.t('key') anywhere in your app.


Socket.io

Enabled via vulkano/config/settings.js. Adapters for MongoDB and Redis are included out of the box.


Configuration — vulkano/config/settings.js

module.exports = {

  // PORT to listen on
  port: process.env.PORT || 3000,

  // Salt for password
  salt: process.env.SALT_KEY || '',

  // Database configuration
  database: {

    // MONGO_URI connection
    connection: process.env.MONGO_URI,

    // Settings before to connect
    settings: {
      strictQuery: false,
      debug: false
    },

    // Additional config to mongoose
    config: {
      useNewUrlParser: true,
      useUnifiedTopology: true,
      // family: 4 // 4 (IPv4), 6 (IPv6), or null (default: OS family)
      // useFindAndModify: false,
      // useCreateIndex: true
    }

  }
};

Running Tests

npm test              # all suites
npm run test:watch    # watch mode
npm run test:coverage # with coverage report

Tests require Node.js 22. Use nvm use 22 if needed.


Support


License

MIT © Vulkano Team