
Research
/Security News
Critical Vulnerability in NestJS Devtools: Localhost RCE via Sandbox Escape
A flawed sandbox in @nestjs/devtools-integration lets attackers run code on your machine via CSRF, leading to full Remote Code Execution (RCE).
mongodb-api-router
Advanced tools
mongodb-api-router
DocumentationWelcome to the comprehensive documentation for mongodb-api-router
, a powerful factory for creating multilingual, filterable, paginated CRUD API routes in an Express.js + Mongoose application.
apiRoute()
Factory
mongodb-api-router
exports:
messages
, defineMessage
, message
).BrowserLanguage
Symbol for locale control.apiRoute(model, options)
— a factory that generates Express middleware for RESTful endpoints on a given Mongoose model.Features:
Export | Type | Description |
---|---|---|
BrowserLanguage | Symbol | Force-use a specific language instead of the browser’s. |
defineMessage | Function | Add or override localized messages by code number. |
message | Function | Retrieve a translated message (with placeholders). |
apiRoute (default) | Function | Factory to create an Express.js route handler for a Mongoose model. |
A set of default messages keyed by numeric codes (1–11), each with translations:
Code | English Default |
---|---|
1 | The request is invalid. |
2 | You cannot filter results by the “{key}” parameter. |
3 | The field “{target}” is required. |
4 | The field “{target}” is too short. |
5 | The field “{target}” is too long. |
6 | The value of “{target}” is too low. |
7 | The value of “{target}” is too high. |
8 | The value of “{target}” is not valid. |
9 | The format of “{target}” is incorrect. |
10 | The value of “{target}” is not of the expected type. |
11 | You cannot make this request. |
// messages structure (excerpt)
const messages = {
__userMessages: {},
1: { en: 'The request is invalid.', it: 'La richiesta non è valida.', /*...*/ },
2: { en: 'You cannot filter results by the “{key}” parameter.', /*...*/ },
// ...
11: { en: 'You cannot make this request.', /*...*/ }
}
const BrowserLanguage = Symbol('BrowserLanguage');
Use this symbol in the options.language
field of apiRoute()
to force all responses to a given locale, ignoring the client’s Accept-Language
header.
defineMessage(number, value)
Register or override a set of translations for message code number
.
Parameters
• number
(Number): The message code to define.
• value
(Object): { [langCode]: 'Translated text', ... }
.
Returns
• undefined
(modifies internal messages.__userMessages
).
defineMessage(12, {
en: 'Custom error occurred.',
es: 'Ocurrió un error personalizado.'
});
message(number, lang, replace)
Retrieve a translated message by code, with optional placeholder replacement.
Parameters
• number
(Number): Message code.
• lang
(String): Language code ('en'
, 'it'
, etc.).
• replace
(Object): { key: 'value', target: 'fieldName' }
.
Returns
• String
: The localized, interpolated message.
message(3, 'fr', { target: 'nom' });
// → 'Le champ « nom » est requis.'
Generate an Express middleware that provides CRUD endpoints on a Mongoose model with:
import express from 'express';
import mongoose from 'mongoose';
import apiRoute from './index.js';
const User = mongoose.model('User', new mongoose.Schema({
name: String,
age: Number
}));
const app = express();
app.use(express.json());
// Mount /api/users
app.use(
apiRoute(User, {
methods: ['GET','POST','PUT','DELETE'],
pagesManager: { maxResults: 100 },
acceptedQueryFields: ['name','age'],
fields: { name: { en: 'name', it: 'nome' } },
options: {
POST: {
middleware: async ({ document }) => {
document.createdAt = Date.now();
}
}
}
})
);
app.listen(3000);
Option | Type | Default | Description |
---|---|---|---|
model (first arg) | Mongoose Model | — | The target model for CRUD. |
filter | Function | Function[] | [] | Pre-handler checks. Return true to continue; false or object for error. |
methods | String[] | ['GET','POST','PUT','DELETE'] | Allowed HTTP methods. |
route | String | '/api/{collectionName}' | Base path ({modelName} , {collectionName} placeholders supported). |
fields | Object | null | Map model fields to custom names per locale. |
pagesManager | Object | undefined | { limit: '?limit', page: '?page', maxResults } for pagination. |
acceptedQueryFields | String[] | Object | model.schema.paths | Fields allowed in req.query / req.body . |
throwRefusedQueryFields | Boolean | true | 400 on unallowed query fields. |
language | String | Symbol | req.acceptsLanguages()[0] | Force locale if not BrowserLanguage . |
options | Object | {} | Method-specific: |
• options.GET , options.POST , etc. |
options[method]
sub‐optionsSub‐Option | Type | Description |
---|---|---|
middleware | Function | Function[] | Runs before saving/updating. Receives { document, req, res, next, query } . |
skimming | Function | Function[] | Post‐query filter: return true to keep each document. |
filter
, methods
, route
.options.language !== BrowserLanguage
).options[method]
.parseFilter()
:
acceptedQueryFields
filter
function → may short‐circuit with 403/custom error.Model.find()
, optional skimming, field translation, JSON result + paging.middleware
, .save()
, skimming, field translation..findOneAndUpdate()
, middleware({ query, set })
, re‐fetch, skimming, translation..deleteOne()
/.deleteMany()
.Method | Action | Response Body |
---|---|---|
GET | .find(query).sort().skip().limit().lean() → skimming() → translate → { ok: true, [collection]: [...] } | Results array + optional pagesManager info |
POST | new model(query).save() → skimming() → translate → { ok: true, document } | Newly created document |
PUT | findOneAndUpdate(query, set) → re‐fetch → skimming() → translate → { ok: true, modelName: document } | Updated document |
DELETE | .find(query).lean() → skimming() → deletion → { ok: true } | Confirmation |
methods
, invalid route
type).403
or custom payload.400
with per‐field errors using localized messages (codes 3–10).400
with error code 2.sequenceDiagram
participant Client
participant ExpressJS
participant Handler as "apiRoute Handler"
participant Model as "Mongoose Model"
participant DB
Client->>ExpressJS: |"GET /api/items?name=John&limit=10&page=2"|
ExpressJS->>Handler: |"invoke apiRoute(model, options)"|
Handler->>Handler: Determine language (Accept-Language or forced)
Handler->>Handler: parseFilter(req.query)
Handler->>Handler: Validate acceptedQueryFields
Handler->>Handler: Apply pagination → limit, page
Handler->>Handler: Execute filter functions
Handler->>Model: find(query).sort().skip().limit()
Model->>DB: Execute MongoDB query
DB-->>Model: Return documents
Model-->>Handler: Lean results
Handler->>Handler: skimming(results)
Handler->>Handler: Translate field names
Handler->>Client: Return JSON `{ ok:true, items: [...], pagesManager }`
import express from 'express';
import mongoose from 'mongoose';
import apiRoute, { defineMessage, BrowserLanguage } from './index.js';
// 1. Define schema & model
const productSchema = new mongoose.Schema({
title: String,
price: Number,
category: String
});
const Product = mongoose.model('Product', productSchema);
// 2. Override a default message
defineMessage(2, { en: 'Filtering by “{key}” is not permitted.' });
// 3. Create Express app
const app = express();
app.use(express.json());
// 4. Mount API route
app.use(
apiRoute(Product, {
methods: ['GET','POST','DELETE'],
fields: {
title: { en: 'title', es: 'titulo' },
price: { en: 'price', es: 'precio' }
},
acceptedQueryFields: ['title','price'],
pagesManager: { limit: '?limit', page: '?page', maxResults: 50 },
options: {
POST: {
middleware: async ({ document }) => {
// Auto‐stamp creation date
document.createdAt = new Date();
}
}
},
language: BrowserLanguage // always use Accept-Language
})
);
// 5. Start server
app.listen(3000, () => console.log('API listening on 3000'));
Condition | Exception Message |
---|---|
filter not function or array of functions | apiRoute(model, { filter }) -> filter must be a function, or an array of functions |
methods not an array | apiRoute(model, { methods }) -> methods must be an array of methods |
Invalid HTTP method in methods | apiRoute(model, { methods }) -> invalid method "<METHOD>" |
route not a string | apiRoute(model, { route }) -> invalid route, it must be a string |
Unallowed query field (by default) | 400 JSON { ok:false, status:400, error: message(2) } |
MongoDB ValidationError | 400 JSON with errors: [ { target, error } ] using codes 3–10 |
Enjoy building multilingual, flexible REST APIs with zero boilerplate! 🚀
FAQs
MongoDB API Router
The npm package mongodb-api-router receives a total of 7 weekly downloads. As such, mongodb-api-router popularity was classified as not popular.
We found that mongodb-api-router demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
/Security News
A flawed sandbox in @nestjs/devtools-integration lets attackers run code on your machine via CSRF, leading to full Remote Code Execution (RCE).
Product
Customize license detection with Socket’s new license overlays: gain control, reduce noise, and handle edge cases with precision.
Product
Socket now supports Rust and Cargo, offering package search for all users and experimental SBOM generation for enterprise projects.