The Code-First, Type-Safe ORM for Postgres. Stop writing migrations. Start writing Classes.
GirdORM is a modern Object-Relational Mapper built for developers who want speed without the bloat. It was designed to rival tools like TypeORM and Prisma by offering Class-Based Models, Auto-Sync Migrations, and Zero-Config Setup.
- ⚡ Zero-Config Migrations: No
.sqlfiles to manage. GirdORM inspects your classes and syncs the database automatically at startup. - 🏗️ Class-Based Schemas: Define your database tables using standard TypeScript classes and decorators.
- 🔗 Auto-Relations: Use
@HasManyand@BelongsToto link tables instantly. - 🐘 Postgres Native: Built specifically for the power and reliability of PostgreSQL.
- 🛡️ Type-Safety: Full TypeScript support for queries and returns.
npm install girdorm pg reflect-metadata dotenv
(Note: You also need tsx or ts-node to run your TypeScript files)
Run the magic command to set up your folder structure and configuration:
npx gird init
This creates src/schema/, gird.json, and generates a .env file.
Create a new database table definition in seconds:
npx gird make:model User
This automatically creates src/schema/User.ts:
import { Model, Column } from 'girdorm';
export class User extends Model {
// 1. Define Table Name
static tableName = "users";
// 2. Define Columns
@Column({ type: 'int', primary: true, generated: true })
id!: number;
@Column({ type: 'text' })
name!: string;
@Column({ type: 'text' })
email!: string;
}Connect your models in your main entry file (e.g., src/main.ts):
import "reflect-metadata"; // Required at top
import "dotenv/config";
import { GirdDB, PostgresAdapter } from "girdorm";
import { User } from "./schema/User";
async function main() {
// 1. Connect
const db = new GirdDB(new PostgresAdapter(process.env.DATABASE_URL));
// 2. Register Models (Crucial Step!)
db.register([ User ]);
// 3. Sync Database (Auto-creates tables)
await db.init();
// 4. Use It!
const user = await User.create({
name: "Adesope",
email: "dev@gird.com"
});
console.log(`Created User: ${user.name} with ID: ${user.id}`);
}
main();GirdORM handles complex joins with simple decorators.
The User (Parent):
import { HasMany } from 'girdorm';
import { Post } from './Post';
export class User extends Model {
// ... columns ...
@HasMany(() => Post, "authorid")
posts?: Post[];
}The Post (Child):
import { BelongsTo } from 'girdorm';
import { User } from './User';
export class Post extends Model {
@Column({ type: 'int' })
authorid!: number;
@BelongsTo(() => User, "authorid")
author?: User;
}Fetch a User and all their Posts in a single, efficient query.
const user = await User.get(1, { with: "posts" });
console.log(user.posts);
// Output: [{ id: 1, title: "GirdORM is Live", authorid: 1 }]Perform atomic operations safely.
await db.transaction(async (tx) => {
await User.create({ name: "Alice" });
await User.create({ name: "Bob" });
// If anything fails here, BOTH creates are rolled back.
});How does the Magic work?
GirdORM uses TypeScript Decorators and Reflect Metadata.
- When you add
@Column(), we store metadata about that property on the class prototype. - When you call
db.register([User]), we read that metadata. - The Migrator compares your Class Metadata against the actual Postgres
information_schema. - If a table or column is missing, GirdORM generates the raw SQL (
CREATE TABLE...orALTER TABLE...) to fix it instantly.
Adesope Building tools for cracked developers.