Type-safe MongoDB for Fastify. A first-class Papr integration that turns your schemas into fully typed collections, decorated right onto your Fastify instance — no boilerplate, no any, no runtime surprises.
const user = await fastify.papr.user.insertOne(req.body) // fully typed, validated, ready- End-to-end type safety — Papr schemas become TypeScript types automatically. Your routes, queries, and inserts are checked at compile time.
- MongoDB-native validation — Schemas compile to native MongoDB
$jsonSchemavalidators, so invalid data is rejected at the database layer, not just in application code. - First-class error handling —
MongoValidationErrorparses MongoDB's cryptic validation errors into structured, field-level details you can return to clients. - Zero-ceremony DI — Register models once with
asCollection(...), access them anywhere viafastify.papr.<model>. - Modern by default — ESM-only, Node.js
>=22.12.0, built on top of@fastify/mongodb.
pnpm add @inaiat/fastify-papr @fastify/mongodbDefine a schema, register the plugin, and you're done:
import fastifyMongodb from '@fastify/mongodb'
import fastifyPaprPlugin, { asCollection, type FastifyPaprOptions, type PaprModel } from '@inaiat/fastify-papr'
import fp from 'fastify-plugin'
import { schema, types } from 'papr'
const userSchema = schema({
name: types.string({ required: true, minLength: 10, maxLength: 100 }),
phone: types.string({ required: true, minLength: 8, maxLength: 20 }),
})
const userIndexes = [{ key: { name: 1 } }]
type UserModel = PaprModel<typeof userSchema>
declare module '@inaiat/fastify-papr' {
interface FastifyPapr {
user: UserModel
}
}
export default fp<FastifyPaprOptions>(
async (fastify) => {
await fastify.register(fastifyMongodb, {
url: 'mongodb://localhost:27017',
})
await fastify.register(fastifyPaprPlugin, {
db: fastify.mongo.client.db('test'),
models: {
user: asCollection('user', userSchema, userIndexes),
},
})
},
{ name: 'papr' },
)Access fully typed collections anywhere through fastify.papr:
import { FastifyPluginAsync } from 'fastify'
import { Static, Type } from '@sinclair/typebox'
import { extractValidationErrors, isMongoServerError } from '@inaiat/fastify-papr'
const userDto = Type.Object({
name: Type.String({ maxLength: 100, minLength: 10 }),
phone: Type.String({ maxLength: 20, minLength: 8 }),
})
const userRoute: FastifyPluginAsync = async (fastify) => {
fastify.post<{ readonly Body: Static<typeof userDto> }>(
'/user',
{ schema: { body: userDto } },
async (req, reply) => {
try {
return await fastify.papr.user.insertOne(req.body)
} catch (error) {
if (isMongoServerError(error) && error.code === 121) {
const details = extractValidationErrors(error)
if (details) {
fastify.log.error({ details }, 'validation failed')
return reply.status(400).send({ message: 'Validation failed', errors: details })
}
}
fastify.log.error(error)
return reply.status(500).send({ message: 'Internal Server Error' })
}
},
)
}
export default userRouteIf you need field-level inspection after the MongoDB validation guard, wrap the error in MongoValidationError and use helpers like getFieldErrors('name').
- Papr documentation — schema options, operators, and advanced queries
- Explore the
tests/folder in this repo for runnable examples
- Node.js
>=22.12.0 - MongoDB server (any version supported by the official driver)
- ESM — this package is published as ESM-only
- The package is now distributed as ESM-only.
- The CommonJS bundle (
dist/index.cjs) is no longer published. - The minimum supported Node.js version is now
22.12.0.
Prefer ESM imports:
import fastifyPaprPlugin, { asCollection } from '@inaiat/fastify-papr'If you still consume it from CommonJS on modern Node.js, load the ESM default export explicitly:
const { default: fastifyPaprPlugin, asCollection } = require('@inaiat/fastify-papr')SimpleDocFailedValidationError was replaced with a consolidated MongoValidationError class with better type safety and new helper methods.
Replace imports:
- import { SimpleDocFailedValidationError, tryExtractSimpleDocFailedValidation } from '@inaiat/fastify-papr'
+ import { MongoValidationError, extractValidationErrors } from '@inaiat/fastify-papr'Use the new class and methods:
- const simpleError = new SimpleDocFailedValidationError(error)
- const hasErrors = simpleError.documentFailedValidation
- const errorDetails = simpleError.schemaRulesNotSatisfied
- const errorJson = simpleError.schemaRulesNotSatisfiedAsString()
+ const validationError = new MongoValidationError(error)
+ const hasErrors = validationError.hasValidationFailures
+ const errorDetails = validationError.validationErrors
+ const errorJson = validationError.getValidationErrorsAsString()New: get validation errors for a specific field:
const nameErrors = validationError.getFieldErrors('name')Type renames:
- DocumentFailedValidation → DocumentValidationError
- PropertiesNotSatisfied → ValidationProperty
- PropertyDetail → ValidationDetail
- SimpleDocFailedValidation → ValidationErrorsThis package uses Vite+ for packaging, testing, formatting, and static checks. pnpm scripts are the main interface:
pnpm build
pnpm test
pnpm lint
pnpm coverageThe published package ships a single ESM build plus declarations in dist/.