Skip to content
v1.0.0-beta.8

Commands and Scaffold

The Harpia Framework provides a set of commands to streamline development. These commands are defined in the package.json file:

CommandDescription
startStarts the application.
devStarts the application in development mode with hot-reloading.
testsRuns tests for a specific module or directory (e.g., user/store).
gGenerates modules, files, and other scaffolding components.
studioStarts Prisma Studio for database management.
seedRuns database seed scripts.
migrateGenerates prisma client types and applies all pending database migrations.

Scaffold

The Harpia Framework includes a powerful scaffolding system to help you generate commonly used application components with ease. This tool accelerates development and enforces a consistent structure across your codebase.

You can invoke the scaffolding tool using the following command:

Terminal window
bun g

Or if you prefer, you can use the shorthand:

Terminal window
bun g <type>

Where <type> can be one of the following:

  • module
  • controller
  • test
  • factory
  • seed
  • task
  • validation
  • observer

Examples

Upon execution, you’ll be prompted to select what you want to generate:

Terminal window
? What do you want to forge? (Use arrow keys)
❯ Module
Controller
Test
Factory
Seed
Task
Validation
Observer

Or you can specify the type directly:

Terminal window
bun g module

Module

The Module option scaffolds a complete directory structure for a new feature or resource in your application. A typical module includes controllers, views, services, tests, and more, organized as follows:

  • Directoryyour-module-name
    • Directorycontrollers
      • index.ts
      • Create.ts
      • Delete.ts
      • Edit.ts
      • List.ts
      • Show.ts
      • Store.ts
      • Update.ts
    • Directorypages
      • Directorycreate
        • page.html
      • Directoryedit
        • page.html
      • Directorylist
        • page.html
      • Directoryshow
        • page.html
    • Directoryrepositories
      • index.ts
      • Create.ts
      • Delete.ts
      • List.ts
      • Show.ts
      • Update.ts
    • Directoryservices
      • index.ts
      • Create.ts
      • Delete.ts
      • List.ts
      • Show.ts
      • Update.ts
    • Directorytests
      • .gitignore
    • Directoryvalidations
      • index.ts
      • Create.ts
      • Update.ts
    • your-module-name.routes.ts

πŸ› οΈ Note: The pages/ directory is only generated if the application is running in MODE=fullstack. If the mode is set to MODE=api, the pages/ directory will not be included.

This layout promotes modular development, making your application easier to scale and maintain by clearly separating responsibilities.

Controller

Harpia lets you scaffold generic controller files with just one command:

Terminal window
bun g controller

Choose the Test option, then specify the module and test name.
Example:

Terminal window
βœ” Module name: user
βœ” Controller name: generic

This creates a new file at:
modules/user/controllers/Generic.ts

Test

Harpia lets you scaffold ready-to-use test files with just one command:

Terminal window
bun g

Choose the Test option, then specify the module and test name.
Example:

Terminal window
βœ” What do you want to forge? Test
βœ” Module name: user
βœ” Test name: store

This creates a new file at:
modules/user/tests/store.spec.ts

Each test file comes pre-configured with bun:test and the TestClient utility to help you get started quickly.

πŸ”— Learn more: Test Documentation

Factory

The Factory option scaffolds a factory class used to generate seed data for your models.
To create a new factory, run the command:

Terminal window
bun g

Then choose the Factory option:

Terminal window
? What do you want to forge? (Use arrow keys)
Module
Controller
Test
❯ Factory
Seed
Task
Validation
Observer

You’ll be prompted to enter a factory name, typically matching the model it’s for:

Terminal window
βœ” What do you want to forge? Factory
βœ” Factory name (use a model name): user

This will generate a new file at:
app/database/factories/User.ts

The generated file comes with a base structure like this:

import { Factory } from "app/helpers/Factory";
import { User } from "..";
export default new Factory().define(User, (faker) => {
return {
/**
* Define your model fields here using faker.js.
*
* Example:
* name: faker.person.fullName(),
*/
};
});

Factories include five core methods:

  • .create() – Creates and persists one record to the database.
  • .createMany(count) – Creates and persists multiple records.
  • .makeStubbed() – Generates one record’s data without saving it.
  • .makeStubbedMany(count) – Generates multiple records’ data without saving.
  • .merge(data) – Merges custom fields with generated data (works with all other methods).

Here’s an example of how to use a factory:

import UserFactory from "app/database/factories/User";
await UserFactory.create();
await UserFactory.createMany(2);
const user = await UserFactory.makeStubbed();
const users = await UserFactory.makeStubbedMany(5);
await UserFactory.merge({ name: "John Doe" }).create();
const customUser = await UserFactory.merge({ name: "John Doe" }).makeStubbed();

πŸ’‘ You can use factories in your tests and seeders to generate reliable and consistent mock data during development.

Seed

Seeding is the process of populating your database with initial data β€” useful for development, testing, or simply bootstrapping your application with some default content.
Harpia provides a powerful and flexible seeding system that integrates seamlessly with factories, allowing you to generate realistic data with ease.

You can generate seed files using the bun g command, or create them manually for full control over the data flow.

πŸ“– Check out the full seeding guide to learn how to create, run, and structure your seed files effectively.

Tasks and Jobs

Harpia supports background processing and scheduled tasks using the powerful cron library. Tasks are placed in the app/tasks directory and can be easily scaffolded using the bun g command.

Each task is a CronJob instance and runs on a schedule you define β€” perfect for background processing, database cleanup, notifications, and more.

πŸ“– For a complete walkthrough, check the full guide on Tasks and Jobs.

Validation

Harpia uses the Zod library for schema-based validation, providing a powerful and type-safe way to ensure that data conforms to expected formats before processing.

Scaffolding a Validation

You can generate a custom validation file using the bun g command:

Terminal window
bun g

Then select the Validation option:

Terminal window
? What do you want to forge? (Use arrow keys)
Module
Controller
Test
Factory
Seed
Task
❯ Validation
Observer
βœ” Module name: user
βœ” Validation name: create

This will generate a new file at:

modules/user/validations/Create.ts

With the following structure:

import AppError from "app/helpers/AppError";
import * as z from "zod";
export const Schema = z.object({
// name: z.string().min(1).max(255),
});
export type SchemaType = z.infer<typeof Schema>;
export async function CreateValidation(data: SchemaType) {
try {
Schema.parse(data);
} catch (error) {
if (error instanceof z.ZodError || error instanceof AppError) {
throw error;
}
}
}

Default Validators on Module Creation

When generating a new Module using bun g, Harpia automatically creates two default validation files:

  • Create.ts
  • Update.ts

These files are located in:

modules/[module]/validations/

They are also automatically exported through the module’s index.ts file:

import { CreateValidation } from "./Create";
import { UpdateValidation } from "./Update";
const UserValidator = {
Create: CreateValidation,
Update: UpdateValidation,
};
export default UserValidator;

This structure makes it easy to reuse validation logic consistently across your controllers or services.


πŸ’‘ Tip: You can enhance your validations using Zod features like .refine(), .superRefine(), .transform(), or schema composition for advanced use cases.

Observers

Harpia provides a simple and powerful way to hook into Prisma lifecycle events using Observers. These let you react to model-level database operations such as create, update, delete, and more.

Observers live in the app/observers directory and are automatically registered when the application boots.

You can scaffold a new observer with:

Terminal window
bun g

Use observers to:

  • Log database activity
  • Send notifications or emails
  • Sync data with external APIs or services

Each observer is defined by attaching a callback to a Prisma operation on a specific model:

app/observers/UserCreate.observer.ts
import { Observer } from ".";
Observer.model("User", "create", ({ data }) => {
console.log("New user created:", data);
});

πŸ”— Learn more: Observer Documentation