Package Exports
- nox-mongo-driver
- nox-mongo-driver/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (nox-mongo-driver) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
nox-mongo-driver
A fast, async-first, schema-driven payload sanitizer and validator for Node.js and MongoDB applications. Built as a lightweight alternative to Mongoose validation — ideal for multi-tenant systems where schemas are defined dynamically at runtime.
Installation
npm install nox-mongo-driverQuick Start
import { sanitize } from "nox-mongo-driver";
const schema = {
name: { type: "String", required: true, trim: true },
age: { type: "Number", min: 18 },
};
const { value, errors } = await sanitize(
{ name: " Sahil ", age: "25" },
schema,
{ mode: "strict" }
);
// value → { name: "Sahil", age: 25 }
// errors → []Features
- Three processing modes — strict, transform, validate
- Type coercion — strings to numbers, booleans, dates, ObjectIds
- Rule validation — required, min/max, enum, regex, minLength/maxLength
- Nested objects & arrays — inline and explicit styles
- Bare Object / Array types — type-only validation without nested schema
- Recursive schemas — self-referencing via lazy functions
- Custom validators — sync and async with context injection
- Setter functions — transform values before coercion
- Immutable fields — prevent updates on specific fields
- Auto timestamps — createdAt / updatedAt with customizable field names
- Partial mode — skip required checks for PATCH / update operations
- Bulk sanitization — process arrays of payloads with concurrency control
- Cleanup options — strip nulls, empty objects, empty arrays, undefined
- Unknown field handling — strip, keep, or error
- Prototype pollution protection — blocks
__proto__,constructor,prototype - i18n support — custom error messages per language
- Stop on first error — bail early for performance
Modes
| Mode | Type Validation | Rule Validation | Transformation |
|---|---|---|---|
strict |
Yes | Yes | Yes |
transform |
Yes | No | Yes |
validate |
Yes | Yes | No |
await sanitize(payload, schema, { mode: "transform" });Schema Field Options
{
type: "String" | "Number" | "Boolean" | "Date" | "ObjectId" | "Object" | "Array" | "Mixed",
required: boolean,
default: any | (() => any),
enum: any[],
match: RegExp,
min: number,
max: number,
minLength: number,
maxLength: number,
trim: boolean,
lowercase: boolean,
uppercase: boolean,
immutable: boolean,
set: (value, context) => any,
validate: (value, context) => boolean | string,
asyncValidate: async (value, context) => boolean | string,
}Type Coercion
In strict or transform mode, values are automatically coerced to the declared type:
const schema = {
age: { type: "Number" },
isActive: { type: "Boolean" },
createdAt: { type: "Date" },
};
// Input: { age: "25", isActive: "true", createdAt: "2024-01-01" }
// Output: { age: 25, isActive: true, createdAt: Date("2024-01-01") }Nested Objects
Inline Style
const schema = {
profile: {
age: { type: "Number", required: true },
email: { type: "String", match: /^[^@]+@[^@]+$/ },
},
};Explicit Object Schema
const schema = {
profile: {
type: "Object",
required: true,
schema: {
age: { type: "Number", required: true },
},
},
};Bare Object (type-only validation)
When you only need to check that a value is an object without validating its internal structure, use type: "Object" without a schema property. The value passes through as-is:
const schema = {
metadata: { type: "Object" },
};
// Input: { metadata: { anything: "goes", nested: { deep: true } } }
// Output: { metadata: { anything: "goes", nested: { deep: true } } }Arrays
Array of Primitives
tags: [{ type: "String" }]Inline Array of Objects
items: [
{
name: { type: "String", required: true },
},
];Explicit Array Schema
items: {
type: "Array",
required: true,
minItems: 1,
maxItems: 50,
schema: {
name: { type: "String", required: true },
value: { type: "Number", min: 0 }
}
}Bare Array (type-only validation)
When you only need to check that a value is an array without validating its items, use type: "Array" without a schema property:
const schema = {
tags: { type: "Array" },
};
// Input: { tags: ["anything", 42, { mixed: true }] }
// Output: { tags: ["anything", 42, { mixed: true }] }minItems / maxItems
Available on explicit Array schemas:
items: {
type: "Array",
minItems: 1,
maxItems: 10,
schema: { name: { type: "String" } }
}Recursive Schemas (Lazy)
Self-referencing schemas using functions:
const MenuItemSchema = () => ({
id: { type: "String", required: true },
children: [MenuItemSchema],
});
const schema = { modules: [MenuItemSchema] };Also works with explicit style:
children: {
type: "Array",
schema: MenuItemSchema
}Setter (set)
Transform a value before type coercion and validation. Runs in strict and transform modes, skipped in validate mode:
const schema = {
slug: {
type: "String",
set: (value) => value.toLowerCase().replace(/\s+/g, "-"),
},
};
// Input: { slug: "My Blog Post" }
// Output: { slug: "my-blog-post" }The setter receives context as the second argument:
set: (value, context) => {
return context.tenant === "admin" ? value : value.trim();
};Custom Validation
Sync
username: {
type: "String",
validate: (value) => value.length >= 3 || "Too short"
}Async
email: {
type: "String",
asyncValidate: async (value, context) => {
const exists = await context.db.findUser(value);
return !exists || "Email already exists";
}
}Pass context via options:
await sanitize(payload, schema, { context: { db } });Immutable Fields
Prevent specific fields from being modified during updates (partial mode):
const schema = {
email: { type: "String", immutable: true },
name: { type: "String" },
};
// On create (partial: false) — both fields are accepted
// On update (partial: true) — email is rejected with IMMUTABLE_FIELD errorAuto Timestamps
Automatically add createdAt and updatedAt fields:
await sanitize(payload, schema, {
timestamps: true,
});
// Create → adds createdAt + updatedAt
// Update (partial: true) → adds updatedAt onlyCustom field names:
await sanitize(payload, schema, {
timestamps: true,
timestampFields: {
createdAt: "created_at",
updatedAt: "updated_at",
},
});Unknown Field Handling
unknownFields: "strip" // default — removes unknown fields
unknownFields: "keep" // preserves unknown fields in output
unknownFields: "error" // adds an error for each unknown fieldCleanup Options
await sanitize(payload, schema, {
removeNull: true,
removeUndefined: true,
removeEmptyObjects: true,
removeEmptyArrays: true,
});Partial Mode (For Updates)
await sanitize(updatePayload, schema, { partial: true });Skips required validation and default assignment for missing fields. Ideal for PATCH / update APIs.
Stop On First Error
await sanitize(payload, schema, { stopOnFirstError: true });Returns immediately on the first validation failure for better performance on large payloads.
Bulk Sanitization
import { sanitizeBulk } from "nox-mongo-driver";
const result = await sanitizeBulk(payloads, schema, {
concurrency: 5,
});
console.log(result.valid); // successfully sanitized items
console.log(result.invalid); // items with errors + index + partial valuesi18n / Custom Messages
await sanitize(payload, schema, {
language: "nl",
messages: {
nl: {
FIELD_REQUIRED: "Veld is verplicht",
EXPECTED_OBJECT: "Object verwacht",
},
},
});Error Format
{
path: "profile.age",
code: "MIN_VIOLATION",
message: "Minimum allowed is 18",
meta: { min: 18, received: 15 }
}Error Codes
FIELD_REQUIRED · INVALID_TYPE · INVALID_NUMBER · INVALID_BOOLEAN · INVALID_DATE · INVALID_OBJECT_ID · ENUM_MISMATCH · REGEX_MISMATCH · MIN_VIOLATION · MAX_VIOLATION · MIN_LENGTH_VIOLATION · MAX_LENGTH_VIOLATION · MIN_ITEMS_VIOLATION · MAX_ITEMS_VIOLATION · EXPECTED_ARRAY · EXPECTED_OBJECT · UNKNOWN_FIELD · IMMUTABLE_FIELD · CUSTOM_VALIDATION · CUSTOM_ASYNC_VALIDATION
Recommended Usage Patterns
Create — full validation + coercion:
await sanitize(payload, schema, { mode: "strict" });Update — skip required, reject immutable:
await sanitize(payload, schema, { mode: "strict", partial: true });Data transformation layer — coerce types only:
await sanitize(payload, schema, { mode: "transform" });Validation gate — check without mutating:
await sanitize(payload, schema, { mode: "validate" });Security
Automatically strips prototype pollution vectors (__proto__, constructor, prototype) from both schema keys and input data when unknownFields is set to keep.
License
MIT — NOX Team