controller-sets v3.3.0

Which section applies to you#

You're onReadEffort
3.0 – 3.2, using createRouterS3uploadUploads move into createRouterMinutes. Not urgent until 4.0.
3.x, using legacyMode or other deprecated APIsBefore 4.0Depends on how much you rely on it.
2.xFrom 2.x to 3.xAn afternoon. Security release — urgent.

The complete guide, with every change explained, is MIGRATION.md; release notes are in CHANGELOG.md.

Uploads move into createRouter (3.3)#

createRouterS3upload is deprecated in 3.3 and removed in 4.0. It still works, and emits a DeprecationWarning (code ECS_DEP001) once per process. Move path, fields and imgOptimizations into upload, next to the settings already there:

createRouterS3upload({
  model: Product,
  path: 'products/',
  fields: [{ name: 'cover', maxCount: 1 }],
  imgOptimizations: 'medium',
  upload: { acl: 'public-read' },
});
createRouter({
  model: Product,
  upload: {
    path: 'products/',
    fields: [{ name: 'cover', maxCount: 1 }],
    imgOptimizations: 'medium',
    acl: 'public-read',
  },
});

createRouter ignores path, fields and imgOptimizations at the top level and logs a warning if it sees them. In TypeScript, replace RouterS3Options with RouterOptions.

Before 4.0#

Everything here still works in 3.x. The first two are removed in 4.0; the rest are deprecated, so move off them when you touch the code.

DeprecatedReplace with
createRouterS3upload(opts)createRouter({ upload }) — above
legacyMode: trueThe 3.x options it bypasses: allowedFields, filterableFields, sortableFields, maxLimit.
new ControllerSets(Model, '-createdAt', ['category'], ['name'])new ControllerSets({ model: Model, orderBy: '-createdAt', query: ['category'], search: ['name'] })
controller.getById · controller.queryAllcontroller.get · controller.query
fileUploadMiddleware(req, res, next, path, fields, level)fileUploadMiddleware(req, res, next, { uploadPath, fields, imgOptimizations })
otp.delivermail.sender / sms.sender — Email & SMS

From 2.x to 3.x#

If you run 2.x on a public endpoint, treat this as urgent. In 2.x a client could write any schema field, filter and sort on fields your API never returned, hang the database with a crafted search term, read entire collections in one request, and upload world-readable HTML to your bucket. Every breaking change in 3.0 is a default that used to be unsafe.

Deploy today, tighten after#

createRouter({ model: Product, legacyMode: true });

legacyMode restores 2.x behaviour so you can upgrade immediately, then remove it router by router as you add the options below. It re-enables every vulnerability listed, so don't leave it on.

What changed, and what to do#

What changedWhat to do
Request bodies are filteredAdd allowedFields or blockedFields to every router.
?compareField=, ?rangeField=, ?sort= are allowlistedList fields in filterableFields / sortableFields, or rely on the query default.
Search terms are escaped and length-cappedNothing — unless clients sent real patterns; then allowRawRegex: true, behind auth.
Unpaginated reads capped at 100Paginate, or raise maxLimit deliberately.
Relational search resolves the full nested pathRe-check depth-2 paths — they queried the wrong field before.
String-form search reads ?s=Update clients that searched with ?title=.
Uploads default to private, type sniffed from bytesSet upload.acl and upload.allowedMimeTypes if needed. Existing objects keep their old ACL — audit them.
Clients no longer choose compression levelupload.allowClientImageOptions: true to opt back in.
GIF and SVG no longer transcodedNothing — they were being corrupted.
5xx responses no longer echo internals; duplicates are 409Update clients that parsed 500 message text.
Reads are no longer .lean()Your toJSON transforms now apply. lean: true restores speed — check what those transforms hide first.
No dotenv.config() at import; multer-s3 removedLoad your environment yourself; uninstall multer-s3.

The lean change is the one most likely to alter responses. 2.x list endpoints bypassed toJSON transforms. If you strip sensitive fields there, 2.x was leaking them on every list request, and 3.x stops. Compare a list response before and after upgrading.

Esc
↑ ↓ to move↵ to open