Papr

MongoDB integration via Papr with schema validation and model registration.

@miiajs/papr integrates Papr with MiiaJS, providing MongoDB connection management, model registration, and direct model injection via DI.

Installation

npm install @miiajs/papr mongodb papr

Setup

Configure the module

import { Module } from '@miiajs/core'
import { PaprModule } from '@miiajs/papr'

@Module({
  imports: [
    PaprModule.configure({
      connection: {
        url: 'mongodb://localhost:27017',
        dbName: 'myapp',
      },
    }),
  ],
})
class AppModule {}

With ConfigService (from @miiajs/config):

import { ConfigService } from '@miiajs/config'

PaprModule.configure((resolve) => {
  const config = resolve(ConfigService)
  return {
    connection: {
      url: config.getOrThrow('MONGODB_URL'),
      dbName: config.get('MONGODB_DB'),
      retry: { attempts: 10, delay: 10_000 },
    },
  }
})

Configuration options

interface PaprModuleOptions {
  connection: {
    url: string             // MongoDB connection URL
    dbName?: string         // Database name
    retry?: {
      attempts?: number     // Default: 10
      delay?: number        // Default: 10_000 ms
    }
  }
}

Define models

Use Papr's schema definition with defineModel to create a ModelRef for registration and injection:

import { schema, types } from 'papr'
import { defineModel } from '@miiajs/papr'

const userSchema = schema({
  name: types.string({ required: true }),
  email: types.string({ required: true }),
  role: types.string({ required: true }),
  password: types.string({ required: true }),
}, {
  defaults: { role: 'user' },
  timestamps: true,
})

export const User = defineModel('users', userSchema)

export type UserDocument = (typeof userSchema)[0]

Register models

Register models per feature module:

import { Module } from '@miiajs/core'
import { PaprModule } from '@miiajs/papr'
import { User } from './user.schema.js'

@Module({
  imports: [PaprModule.register([User])],
  controllers: [UserController],
  providers: [UserService],
})
class UserModule {}

Models from multiple register() calls accumulate and are available when the app starts.

Use in services

Inject models directly using injectModel or @InjectModel:

import { Injectable } from '@miiajs/core'
import { injectModel } from '@miiajs/papr'
import { User } from './user.schema.js'

@Injectable()
class UserService {
  private users = injectModel(User)

  async findAll() {
    return this.users.find({})
  }

  async findById(id: string) {
    const { ObjectId } = await import('mongodb')
    return this.users.findOne({ _id: new ObjectId(id) })
  }

  async findByEmail(email: string) {
    return this.users.findOne({ email })
  }

  async create(data: { name: string; email: string; password: string }) {
    return this.users.insertOne({
      ...data,
      role: 'user',
      createdAt: new Date(),
    })
  }

  async update(id: string, data: Record<string, any>) {
    const { ObjectId } = await import('mongodb')
    return this.users.findOneAndUpdate(
      { _id: new ObjectId(id) },
      { $set: data },
      { returnDocument: 'after' },
    )
  }

  async delete(id: string) {
    const { ObjectId } = await import('mongodb')
    const result = await this.users.deleteOne({ _id: new ObjectId(id) })
    return result.deletedCount > 0
  }
}

Decorator style:

import { Injectable } from '@miiajs/core'
import { InjectModel } from '@miiajs/papr'
import { User } from './user.schema.js'

@Injectable()
class UserService {
  @InjectModel(User) private users!: any
}

Raw service access

For advanced operations, inject PaprService directly:

import { inject, Injectable } from '@miiajs/core'
import { PaprService } from '@miiajs/papr'

@Injectable()
class AdminService {
  private papr = inject(PaprService)

  async stats() {
    return this.papr.db.stats()
  }
}

PaprService API

Property/MethodReturnsDescription
.model(name)Papr modelGet a registered model by collection name
.paprPapr instanceAccess the Papr instance directly
.dbMongoDB DbAccess the MongoDB database directly

All getters throw if called before app.init().

Connection lifecycle

  • onInit — connects to MongoDB with automatic retry on transient errors, registers all models with Papr, updates schemas
  • onDestroy — closes the MongoDB client and clears all references

Peer dependencies

PackageVersion
mongodb>= 6.0.0
papr>= 15.0.0

Exports

import { PaprModule, PaprService, defineModel, InjectModel, injectModel } from '@miiajs/papr'
import type { PaprModuleOptions, ModelRef } from '@miiajs/papr'