npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@takepack/db-ext

v2.0.0

Published

A NestJS library providing dynamic database configuration with TypeORM, migration management, and seeding capabilities

Readme

@takepack/db-ext

A comprehensive NestJS library providing dynamic database configuration with TypeORM, migration management, seeding capabilities, and CLI commands.

Features

  • 🚀 Dynamic Database Configuration - Easy setup with static or async configuration
  • 🔄 Migration Management - Run, revert, and generate migrations with auto-run support
  • 🌱 Database Seeding - Flexible seeding system with transaction support
  • 🛠️ CLI Commands - Built-in commands for migrations and seeders
  • 📦 Factory Pattern - Base factory class for generating test data
  • 🎯 TypeORM Integration - Seamless integration with TypeORM
  • 🔌 Modular Design - Export command runners for use in other CLI modules

Installation

npm install @takepack/db-ext

Peer Dependencies

npm install @nestjs/common @nestjs/core @nestjs/typeorm typeorm reflect-metadata rxjs nest-commander

Database Drivers

Install the appropriate database driver:

# PostgreSQL
npm install pg

# MySQL/MariaDB
npm install mysql2

# SQLite
npm install sqlite3

# MSSQL
npm install mssql

Optional Dependencies

# For factories and seeders
npm install @faker-js/faker

# For TypeScript migrations
npm install ts-node

Quick Start

1. Basic Configuration

// app.module.ts
import { Module } from '@nestjs/common';
import { DatabaseExtensionModule } from '@takepack/db-ext';
import { User } from './entities/user.entity';

@Module({
  imports: [
    DatabaseExtensionModule.register({
      connection: {
        type: 'postgres',
        host: 'localhost',
        port: 5432,
        username: 'user',
        password: 'password',
        database: 'mydb',
        synchronize: false,
        logging: true,
      },
      entities: [User],
      migration: {
        enabled: true,
        migrationsPath: 'src/database/migrations',
        tableName: 'migrations',
        autoRun: false,
      },
      seeder: {
        enabled: true,
        seeders: [],
        autoRun: false,
      },
    }),
  ],
})
export class AppModule {}

2. Async Configuration

// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { DatabaseExtensionModule } from '@takepack/db-ext';

@Module({
  imports: [
    ConfigModule.forRoot(),
    DatabaseExtensionModule.registerAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => ({
        connection: {
          type: 'postgres',
          host: configService.get('DB_HOST'),
          port: configService.get('DB_PORT'),
          username: configService.get('DB_USERNAME'),
          password: configService.get('DB_PASSWORD'),
          database: configService.get('DB_DATABASE'),
          synchronize: false,
          logging: configService.get('NODE_ENV') !== 'production',
        },
        entities: [__dirname + '/**/*.entity{.ts,.js}'],
        migration: {
          enabled: true,
          migrationsPath: 'src/database/migrations',
          autoRun: configService.get('NODE_ENV') === 'production',
        },
        seeder: {
          enabled: true,
          seeders: [],
          autoRun: configService.get('NODE_ENV') === 'development',
        },
      }),
    }),
  ],
})
export class AppModule {}

Migrations

Creating a Migration

Create a migration file manually:

// src/database/migrations/1234567890-CreateUsersTable.ts
import { MigrationInterface, QueryRunner, Table } from 'typeorm';

export class CreateUsersTable1234567890 implements MigrationInterface {
  name = 'CreateUsersTable1234567890';

  public async up(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.createTable(
      new Table({
        name: 'users',
        columns: [
          {
            name: 'id',
            type: 'uuid',
            isPrimary: true,
            generationStrategy: 'uuid',
            default: 'uuid_generate_v4()',
          },
          {
            name: 'email',
            type: 'varchar',
            isUnique: true,
          },
          {
            name: 'name',
            type: 'varchar',
          },
          {
            name: 'created_at',
            type: 'timestamp',
            default: 'now()',
          },
        ],
      }),
    );
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.dropTable('users');
  }
}

Using Migration Service

import { Injectable } from '@nestjs/common';
import { MigrationService } from '@takepack/db-ext';

@Injectable()
export class MyService {
  constructor(private readonly migrationService: MigrationService) {}

  async runMigrations() {
    await this.migrationService.runMigrations();
  }

  async revertMigration() {
    await this.migrationService.revertMigration();
  }

  async checkStatus() {
    const hasPending = await this.migrationService.hasPendingMigrations();
    console.log('Has pending migrations:', hasPending);
  }
}

Seeders

Creating a Seeder

// src/database/seeders/user.seeder.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { BaseSeeder } from '@takepack/db-ext';
import { User } from '../entities/user.entity';

@Injectable()
export class UserSeeder extends BaseSeeder {
  constructor(
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
  ) {
    super();
  }

  async seed(): Promise<void> {
    const users = [
      { email: '[email protected]', name: 'Admin User' },
      { email: '[email protected]', name: 'Regular User' },
    ];

    for (const userData of users) {
      const exists = await this.userRepository.findOne({
        where: { email: userData.email },
      });

      if (!exists) {
        await this.userRepository.save(userData);
        console.log(`✓ Created user: ${userData.email}`);
      }
    }
  }
}

Using Factory Pattern

// src/database/factories/user.factory.ts
import { Injectable } from '@nestjs/common';
import { BaseFactory } from '@takepack/db-ext';
import { User } from '../entities/user.entity';
import { faker } from '@faker-js/faker';

@Injectable()
export class UserFactory extends BaseFactory<User> {
  protected definition(): Partial<User> {
    return {
      email: faker.internet.email(),
      name: faker.person.fullName(),
      createdAt: faker.date.past(),
    };
  }
}
// src/database/seeders/user.seeder.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { BaseSeeder } from '@takepack/db-ext';
import { User } from '../entities/user.entity';
import { UserFactory } from '../factories/user.factory';

@Injectable()
export class UserSeeder extends BaseSeeder {
  constructor(
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
    private readonly userFactory: UserFactory,
  ) {
    super();
  }

  async seed(): Promise<void> {
    // Create 50 random users using factory
    const users = await this.userFactory.createMany(50);
    await this.userRepository.save(users);
    console.log('✓ Created 50 users');
  }
}

Register Seeders

// app.module.ts
DatabaseExtensionModule.register({
  // ... other config
  seeder: {
    enabled: true,
    seeders: [UserSeeder, ProductSeeder, CategorySeeder],
    autoRun: false,
  },
}),

Using Seeder Service

import { Injectable } from '@nestjs/common';
import { SeederService } from '@takepack/db-ext';

@Injectable()
export class MyService {
  constructor(private readonly seederService: SeederService) {}

  async seedDatabase() {
    // Run all seeders
    await this.seederService.runSeeders();

    // Run specific seeders
    await this.seederService.runSeeders({
      only: ['UserSeeder', 'ProductSeeder'],
    });

    // Run with custom transaction mode
    await this.seederService.runSeeders({
      transaction: 'each', // 'all' | 'each' | 'none'
    });
  }
}

CLI Commands

Setting Up CLI

Create a CLI module to use the exported command runners:

// cli.module.ts
import { Module } from '@nestjs/common';
import { MigrationCommandRunner, SeederCommandRunner } from '@takepack/db-ext';
import { AppModule } from './app.module';

@Module({
  imports: [AppModule],
  providers: [MigrationCommandRunner, SeederCommandRunner],
})
export class CliModule {}
// cli.ts
import { CommandFactory } from 'nest-commander';
import { CliModule } from './cli.module';

async function bootstrap() {
  await CommandFactory.run(CliModule);
}

bootstrap();

Update package.json:

{
  "scripts": {
    "cli": "ts-node src/cli.ts"
  }
}

Migration Commands

# Run all pending migrations
npm run cli migration run

# Revert last migration
npm run cli migration revert

# Generate new migration
npm run cli migration generate CreateUsersTable

# Show migration status
npm run cli migration status

# Show pending migrations
npm run cli migration pending

# Show executed migrations
npm run cli migration executed

Seeder Commands

# Run all seeders
npm run cli seed

# Run specific seeders
npm run cli seed UserSeeder ProductSeeder

# Run with options
npm run cli seed --only UserSeeder,ProductSeeder
npm run cli seed --transaction each

# List available seeders
npm run cli seed --list

Configuration Options

DatabaseModuleConfig

interface DatabaseModuleConfig {
  connection: DatabaseConnectionConfig;
  entities: any[];
  migration?: MigrationConfig;
  seeder?: SeederConfig;
}

DatabaseConnectionConfig

interface DatabaseConnectionConfig {
  type: 'postgres' | 'mysql' | 'mariadb' | 'sqlite' | 'mssql';
  host: string;
  port: number;
  username: string;
  password: string;
  database: string;
  synchronize?: boolean; // Default: false
  logging?: boolean; // Default: false
}

MigrationConfig

interface MigrationConfig {
  enabled: boolean;
  migrationsPath: string;
  tableName?: string; // Default: 'migrations'
  autoRun?: boolean; // Default: false
}

SeederConfig

interface SeederConfig {
  enabled: boolean;
  seeders: any[];
  autoRun?: boolean; // Default: false
}

Exported Components

The library exports the following components for use in your application:

Modules

  • DatabaseExtensionModule - Main module

Services

  • MigrationService - Migration management service
  • SeederService - Seeder management service

Commands (for CLI integration)

  • MigrationCommandRunner - Migration CLI commands
  • SeederCommandRunner - Seeder CLI commands

Helpers

  • BaseSeeder - Base class for seeders
  • BaseFactory - Base class for factories
  • ConfigBuilder - Helper for building configurations

Types

  • DatabaseModuleConfig
  • DatabaseConnectionConfig
  • MigrationConfig
  • SeederConfig
  • SeederInterface

Best Practices

1. Use Async Configuration for Production

Always use environment variables and async configuration in production:

DatabaseExtensionModule.registerAsync({
  imports: [ConfigModule],
  inject: [ConfigService],
  useFactory: (config: ConfigService) => ({
    connection: {
      type: config.get('DB_TYPE'),
      host: config.get('DB_HOST'),
      // ...
    },
  }),
});

2. Disable Auto-Run in Production

migration: {
  enabled: true,
  autoRun: process.env.NODE_ENV !== 'production',
}

3. Use Transactions for Seeders

await seederService.runSeeders({
  transaction: 'all', // Run all seeders in one transaction
});

4. Order Your Seeders

seeder: {
  enabled: true,
  seeders: [
    CategorySeeder,  // Run first (no dependencies)
    ProductSeeder,   // Run second (depends on categories)
    UserSeeder,      // Run third
  ],
}

5. Use Factories for Test Data

// In tests
const users = await userFactory.createMany(100);
await userRepository.save(users);

Examples

Complete Application Setup

// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { DatabaseExtensionModule } from '@takepack/db-ext';
import { User } from './entities/user.entity';
import { Product } from './entities/product.entity';
import { UserSeeder } from './database/seeders/user.seeder';
import { ProductSeeder } from './database/seeders/product.seeder';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
    }),
    DatabaseExtensionModule.registerAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        connection: {
          type: 'postgres',
          host: config.get('DB_HOST', 'localhost'),
          port: config.get('DB_PORT', 5432),
          username: config.get('DB_USERNAME', 'postgres'),
          password: config.get('DB_PASSWORD', 'password'),
          database: config.get('DB_DATABASE', 'mydb'),
          synchronize: false,
          logging: config.get('NODE_ENV') !== 'production',
        },
        entities: [User, Product],
        migration: {
          enabled: true,
          migrationsPath: 'src/database/migrations',
          tableName: 'migrations',
          autoRun: config.get('AUTO_RUN_MIGRATIONS') === 'true',
        },
        seeder: {
          enabled: true,
          seeders: [UserSeeder, ProductSeeder],
          autoRun: config.get('AUTO_RUN_SEEDERS') === 'true',
        },
      }),
    }),
  ],
})
export class AppModule {}

CLI Setup with Commands

// cli.module.ts
import { Module } from '@nestjs/common';
import { MigrationCommandRunner, SeederCommandRunner } from '@takepack/db-ext';
import { AppModule } from './app.module';

@Module({
  imports: [AppModule],
  providers: [MigrationCommandRunner, SeederCommandRunner],
})
export class CliModule {}

// cli.ts
import { CommandFactory } from 'nest-commander';
import { CliModule } from './cli.module';

async function bootstrap() {
  await CommandFactory.run(CliModule, {
    errorHandler: (err) => {
      console.error('CLI Error:', err);
      process.exit(1);
    },
  });
}

bootstrap();

Troubleshooting

Migrations Not Running

  1. Check that migrations are enabled:

    migration: { enabled: true }
  2. Verify migrations path exists and contains migration files

  3. Ensure migration files follow naming convention: timestamp-Name.ts

Seeders Not Found

  1. Verify seeders are registered in the module:

    seeder: { seeders: [UserSeeder] }
  2. Check that seeder classes extend BaseSeeder and have @Injectable() decorator

  3. Make sure seeder dependencies are properly injected

Command Not Found

  1. Install nest-commander:

    npm install nest-commander
  2. Verify CLI module imports the main application module

  3. Check that command runners are provided in the CLI module

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Support

For issues and questions, please open an issue on the GitHub repository.