Commands and Scaffold
The Harpia Framework provides a set of commands to streamline development. These commands are defined in the package.json
file:
Command | Description |
---|---|
start | Starts the application. |
dev | Starts the application in development mode with hot-reloading. |
tests | Runs tests for a specific module or directory (e.g., user/store ). |
g | Generates modules, files, and other scaffolding components. |
studio | Starts Prisma Studio for database management. |
seed | Runs database seed scripts. |
migrate | Generates 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:
bun g
Or if you prefer, you can use the shorthand:
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:
? What do you want to forge? (Use arrow keys)β― Module Controller Test Factory Seed Task Validation Observer
Or you can specify the type directly:
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:
bun g controller
Choose the Test
option, then specify the module and test name.
Example:
β 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:
bun g
Choose the Test
option, then specify the module and test name.
Example:
β 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:
bun g
Then choose the Factory
option:
? 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:
β 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:
bun g
Then select the Validation
option:
? 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:
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:
import { Observer } from ".";
Observer.model("User", "create", ({ data }) => { console.log("New user created:", data);});
π Learn more: Observer Documentation