Skip to content
Projects

willsoto/nestjs-objection

View on GitHub

willsoto/nestjs-objection has 143 GitHub stars and 8 forks. GitHot measured 0 stars in 24 hours. Last checked 2026-11-09 06:47 UTC. Last push 2026-11-02.

How these counts are measured

NestJS module for Objection

Measured star growth

in 24h
0
in 7 days
Update delayed
in 15 days
Update delayed
in 1 month
Update delayed

Net star changes over overlapping periods, not daily totals. Missing measurements are left blank. Stars measure attention, not software quality.

README.md

Original

NestJS Objection

npm version NPM downloads

Description

Integrates Objection.js and Knex with Nest

Installation

pnpm add @willsoto/nestjs-objection

Note that Knex and Objection are peerDependencies to make version management easier, so those must be installed separately

pnpm add knex objection

API

ObjectionModule.register

import { Module } from "@nestjs/common";
import { ObjectionModule } from "@willsoto/nestjs-objection";

import { BaseModel } from "./base";
import { User } from "./user";

@Module({
  imports: [
    ObjectionModule.register({
      // You can specify a custom BaseModel
      // If none is provided, the default Model will be used
      // https://vincit.github.io/objection.js/#models
      Model: BaseModel,
      config: {
        client: "sqlite3",
        useNullAsDefault: true,
        connection: {
          filename: "./example.sqlite",
        },
      },
    }),

    //Register your objection models so it can be provided when needed.
    ObjectionModule.forFeature([User]),
  ],
  exports: [ObjectionModule],
})
export class DatabaseModule {}

ObjectionModule.registerAsync

import { Module } from "@nestjs/common";
import { ObjectionModule } from "@willsoto/nestjs-objection";
import knex from "knex";
import { knexSnakeCaseMappers } from "objection";

import { ConfigModule, ConfigService } from "../config";
import { BaseModel } from "./base";
import { User } from "./user";

@Module({
  imports: [
    ObjectionModule.registerAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory(config: ConfigService) {
        return {
          // You can specify a custom BaseModel
          // If none is provided, the default Model will be used
          // https://vincit.github.io/objection.js/#models
          Model: BaseModel,
          config: {
            ...config.get<knex.Config>("database"),
            ...knexSnakeCaseMappers(),
          },
        };
      },
    }),
    //Register your objection models so it can be provided when needed.
    ObjectionModule.forFeature([User]),
  ],
  exports: [ObjectionModule],
})
export class DatabaseModule {}

Configuration

Name Type Required Default Notes
name string false KNEX_CONNECTION token This is required only if you are using multiple connections
Model Object false objection.Model
config Object true

Examples

Injecting the connection

import { Inject, Injectable } from "@nestjs/common";
import { HealthCheckError, HealthIndicator, HealthIndicatorResult } from "@nestjs/terminus";
import { Connection, KNEX_CONNECTION } from "@willsoto/nestjs-objection";

@Injectable()
export class PrimaryDatabaseHealthIndicator extends HealthIndicator {
  constructor(@Inject(KNEX_CONNECTION) public connection: Connection) {}

  async ping(key: string = "db-primary"): Promise<HealthIndicatorResult> {
    try {
      await this.connection.raw("SELECT 1");
      return super.getStatus(key, true);
    } catch (error) {
      const status = super.getStatus(key, false, { message: error.message });
      throw new HealthCheckError("Unable to connect to database", status);
    }
  }
}

Injecting an objection model

import { Inject, Injectable } from "@nestjs/common";

import { User } from "./user";

@Injectable()
export class UserService {
  constructor(@Inject(User) private readonly userModel: typeof User) {}

  async getUsers(): Promise<User[]> {
    return await this.userModel.query();
  }
}

Multiple connections

When using multiple connections, you must name each connection when registering it. Otherwise subsequent connections will override the previous ones. With registerAsync, set name on the registerAsync options themselves; any name returned from the factory is ignored.

@Module({
  imports: [
    ObjectionModule.registerAsync({
      // You must provide a name for the connection
      name: "connection1",
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory(config: ConfigService) {
        return {
          Model: BaseModel1,
          config: {
            client: "sqlite3",
            useNullAsDefault: true,
            connection: {
              filename: "./testing1.sqlite",
            },
          },
        };
      },
    }),
    ObjectionModule.register({
      // You must provide a name for the connection
      name: "connection2",
      Model: BaseModel2,
      config: {
        client: "sqlite3",
        useNullAsDefault: true,
        connection: {
          filename: "./testing2.sqlite",
        },
      },
    }),
  ],
})
export class DatabaseModule {}

Explore related projects