A lightweight, TypeScript-first JPA-style ORM for PostgreSQL, utilizing decorators for elegant data mapping and generic repositories for robust CRUD operations.
npm install pg-jpa-lite@Entity and @Column.
BaseRepository that understands your entity's primary keys, unique constraints, and relationships.
findById, update, and delete operations.
@Column({ unique: true }) fields.
@Column({ notNull: true }) constraints before the query reaches the database.
@Column({ references: { ... } }).
bash
npm install pg-jpa-lite reflect-metadata
`
⚙️ TypeScript Configuration
This library requires experimental decorators and metadata reflection to be enabled in your tsconfig.json. Use the following configuration for optimal performance:
`json
{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"lib": ["ES2020", "ESNext.AsyncIterable"],
"rootDir": "src",
"outDir": "dist",
/ JPA Magic (Required) /
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
/ Strictness & NPM Readiness /
"strict": true,
"strictPropertyInitialization": false,
"esModuleInterop": true,
"declaration": true,
"sourceMap": true,
"moduleResolution": "node",
"skipLibCheck": true
},
"include": ["src/*/"],
"exclude": ["node_modules", "dist"]
}
`
🏗 Architecture Overview
The library operates on a Metadata Store pattern. When your application starts, the decorators register the structure of your classes. The BaseRepository then uses this store to build dynamic SQL queries at runtime.
🚀 Quick Start
$3
First, establish a connection to your PostgreSQL database.
`typescript
import { Connection } from 'pg-jpa-lite';
Connection.connect({
host: 'localhost',
user: 'shubham',
password: 'shubham123',
database: 'pgrm',
port: 5432
});
`
$3
Create a class and decorate it with entity and column metadata.
`typescript
import { Entity, Column } from 'pg-jpa-lite';
@Entity("students")
export class Student {
@Column({ primary: true })
id: number;
@Column({ notNull: true })
name: string;
@Column({ unique: true, notNull: true })
email: string;
// Relational Link: courseId must exist in the 'courses' table 'id' column
@Column({
references: { table: 'courses', column: 'id' }
})
courseId: number;
}
`
$3
Initialize the repository with your entity class to perform CRUD operations.
`typescript
import { BaseRepository } from 'pg-jpa-lite';
import { Student } from './entities/Student';
const studentRepo = new BaseRepository(Student);
async function manageStudents() {
try {
// SAVE: Runs all unique and foreign key checks before inserting
const newStudent = await studentRepo.save({
name: "Rahul Kumar",
email: "rahul@example.com",
courseId: 5
});
// FIND: Fetch by ID (detects 'id' as primary key from metadata)
const student = await studentRepo.findByID(1);
// UPDATE: Automatically excludes the primary key from the SET clause
await studentRepo.updateById(1, { name: "Rahul K. Sharma" });
// DELETE: Removes the record
await studentRepo.deleteById(1);
} catch (error) {
console.error("ORM Error:", error.message);
}
}
`
🛡 Advanced Validations
The library provides robust error handling to ensure data integrity:
- Duplicate Detection: If you attempt to save an email that already exists, the library throws a detailed [PGORM] Duplicate Error.
- Foreign Key Safety: If a courseId is provided that doesn't exist in the courses table, it throws a [PGORM] Foreign Key Error before the SQL execution fails.
🛠 API Reference
$3
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| primary | boolean | false | Marks the column as the primary identifier. |
| unique | boolean | false | Enforces uniqueness validation before saving. |
| notNull | boolean | false | Enforces mandatory field check. |
| name | string | snake_case | Custom database column name override. |
| references | object | undefined | Defines FK relations: { table: string, column: string }`. |