Seeding

Database seeding is the process of populating your database with initial, foundational data. This is particularly useful for establishing default roles, a master administrator account, or any other reference data your application requires to function out of the box.

Harpia comes with a robust, custom-built seeding engine that automatically discovers and executes your seed files. This approach makes it easy to maintain modular, organised seed data without having to maintain a single massive file.

Generating a Seeder

To create a new seed file, use the Harpia CLI generator command:

bun harpia generate seed admin

Alternatively, you can use the shorthand:

bun g seed admin

This will generate a new file at app/database/seeds/admin.seed.ts with the required run() function.

The Seeder Architecture

Unlike traditional setups that rely on a single seed.ts file, Harpia’s database layer contains a central runner (app/database/seeds/index.ts) that searches for any file ending with .seed.ts within the seeds directory.

Each generated seed file looks like this:

// app/database/seeds/admin.seed.ts
import { User } from "app/database";

export async function run() {
  /**
   * This is a template function used by the generator.
   * Replace the content below with your own seed logic.
   *
   * Example:
   * await User.createMany({
   *   data: [
   *     { name: "Admin", email: "admin@example.com" },
   *     { name: "User", email: "user@example.com" },
   *   ],
   * });
   *
   * Or using factories (recommended)
   * await UserFactory.createMany(5);
   *
   */
}

The runner automatically invokes the run() function of each discovered module.

Running Seeders

Harpia provides two ways to execute your seed scripts, depending on whether you are doing a full database reset or just targeting a specific seed.

Running All Seeds

To discover and execute all .seed.ts files sequentially, run:

bun harpia seed

The CLI will log the execution status of each file.

Running a Specific Seed

If you only want to execute one specific script (for instance, to seed some test products without resetting your user data), you can pass the seed name as an argument. You do not need to include the .seed.ts extension.

bun harpia seed admin

Best Practices

  • Use Upserts: When writing seeders using the raw Prisma Client, prefer upsert over create. This makes your seeding script idempotent, meaning you can safely run it multiple times without causing duplicate key errors.
  • Leverage Factories: For generating large amounts of fake data (like users, posts, or products), avoid hardcoding arrays of objects. Instead, use Harpia’s Factories to generate realistic mock data elegantly.
  • Environment Isolation: Be cautious about running seed scripts in a production environment. Ensure that destructive or test-data seeds are restricted to development or staging environments using standard process.env.MODE or process.env.NODE_ENV checks.