controller-sets v3.3.0
v3.3 — uploads and Redis caching built into createRouter

One model in,a whole REST API out.

controller-sets turns a Mongoose model into six working Express endpoints — list, query, read, create, update, delete — with filtering, search, pagination, caching and file uploads already wired up. You write the model and say what clients are allowed to do; it writes the controller.

What you write

createRouter({
  model: Product,
  query: ['category'],
  search: ['name'],
  allowedFields: ['name', 'price'],
});

What you get

  • GET/productsfilter · search · page
  • QUERY/productsthe same read, from a JSON body
  • POST/productscreate
  • GET/products/:idread one
  • PATCH/products/:idupdate
  • DELETE/products/:iddelete
6 endpoints per call Node 20.19+ Express 5 · Mongoose 9 TypeScript included MIT licensed

What it does for you#

Every Express + Mongoose API writes the same controllers: list with filters, read one, create, update, delete — and each hand-written copy has its own bugs. controller-sets writes them once and lets you configure the rest.

Less code

One call gives a model six endpoints with filtering, search, sorting and pagination. No controller code to write or test.

Secure by default

Nothing is filterable or sortable until you allow it. Mass assignment, NoSQL injection and regex attacks are closed off.

Fast at any size

Cursor pagination serves page 1,000 of 200,000 records in under a millisecond; opt-in Redis caching skips the database entirely.

Batteries included

S3 uploads with image compression, JWT auth with refresh tokens and social sign-in, email and SMS codes — each optional.

Your models

No schema of its own. Point it at the Mongoose models you already have.

Typed

Full TypeScript declarations ship with the package — autocomplete for every option.

Which page do I need?#

The docs are split by what you are trying to do. Guides explain how and why; Reference pages are look-up tables.

I want to…Go to
Get something running for the first timeQuickstart
Understand the mental model before configuring anythingCore concepts
Decide what clients can filter, search, sort and writecreateRouter
Require login, split public and admin access, or show users only their own dataProtecting routes
Accept images or filesFile uploads
Make reads faster with RedisCaching
Add sign-up, login, roles and password resetAuthentication and Email & SMS
Mix generated handlers with my own routesCustom routes
Look up any option, its default and why to use itcreateRouter
Call the API from a web or mobile clientHTTP API
Fix an error or unexpected responseTroubleshooting

Less code, same result#

app.use('/api/products', createRouter({
  model: Product,
  query: ['category'],
  search: ['name'],
  sortableFields: ['price', 'createdAt'],
  allowedFields: ['name', 'price', 'category'],
}));

Six endpoints, filtered input, pagination, consistent errors.

router.get('/', async (req, res, next) => {
  try {
    const filter = {};
    if (req.query.category) filter.category = req.query.category;
    if (req.query.s) filter.name = { $regex: escape(req.query.s), $options: 'i' };
    const sort = ['price', 'createdAt'].includes(req.query.sort?.replace('-', ''))
      ? req.query.sort : '-createdAt';
    const page = Math.max(1, parseInt(req.query.page) || 1);
    const limit = Math.min(100, parseInt(req.query.pageSize) || 50);
    const [data, total] = await Promise.all([
      Product.find(filter).sort(sort).skip((page - 1) * limit).limit(limit),
      Product.countDocuments(filter),
    ]);
    res.json({ success: true, data, pagination: { page, total } });
  } catch (err) { next(err); }
});
// …and POST, GET /:id, PATCH /:id, DELETE /:id, input filtering, id validation…

Installation#

npm install express-controller-sets express mongoose
RequirementVersion
Node.js20.19+ — 22.2+ for the QUERY route (skipped with one warning on older Node)
Express5
Mongoose9
Module systemES modules — "type": "module" in package.json. From CommonJS, use await import().

Everything else is optional. Install a package only when you use the feature — they load lazily, so an app that never uploads never loads the AWS SDK.

FeatureExtra install
CRUD routes, authenticationnothing
File uploadsnpm install multer @aws-sdk/client-s3
Image compressionnpm install sharp
Redis cachenpm install ioredis (or redis)
Email via SMTPnpm install nodemailer

Next: the Quickstart builds a working API step by step.

Esc
↑ ↓ to move↵ to open