Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Codefied-CodePix/Karokar-backend/llms.txt

Use this file to discover all available pages before exploring further.

KaroKar Backend persists all data in a PostgreSQL database accessed through TypeORM 0.3.x. The ORM is wired into NestJS via TypeOrmModule.forRootAsync, which defers connection setup until the dependency-injection container has resolved ConfigService — ensuring the DATABASE_URL environment variable is present before the first connection attempt. Schema changes are managed exclusively through TypeORM migrations; the synchronize flag is permanently disabled to prevent accidental schema drift in shared and production databases.

Runtime Connection (AppModule)

The TypeORM integration is configured asynchronously inside src/app.module.ts:
TypeOrmModule.forRootAsync({
  inject: [ConfigService],
  useFactory: (configService: ConfigService) => ({
    type: 'postgres' as const,
    url: configService.getOrThrow<string>('DATABASE_URL'),
    autoLoadEntities: true,
    synchronize: false,
  }),
}),
OptionValueNotes
type'postgres'Selects the pg driver (declared as a dependency in package.json).
urlDATABASE_URL env varUses getOrThrow — the process exits immediately at startup if the variable is missing.
autoLoadEntitiestrueAny entity registered with TypeOrmModule.forFeature(...) in a feature module is automatically included in the connection without manually listing it here.
synchronizefalseTypeORM will not alter the database schema automatically. All schema changes must go through migrations.
Never set synchronize: true in a production or shared environment. When enabled, TypeORM compares the live schema to your entity definitions at every startup and applies destructive changes — including dropping columns — without any review step. Always use migrations instead.

CLI DataSource (src/database/data-source.ts)

The TypeORM CLI commands need a standalone DataSource that can be loaded outside the NestJS application context. This file is the entry point for all migration tooling:
import { config } from 'dotenv';
import { DataSource } from 'typeorm';

config();

export default new DataSource({
  type: 'postgres',
  url: process.env.DATABASE_URL,
  entities: [__dirname + '/../**/*.entity{.ts,.js}'],
  migrations: [__dirname + '/migrations/*{.ts,.js}'],
  synchronize: false,
});
config() from the dotenv package is called at the top of the file so that process.env.DATABASE_URL is populated from .env when the CLI is invoked directly with ts-node — no NestJS bootstrap is involved.
  • entities — glob that discovers every *.entity.ts / *.entity.js file anywhere under src/, matching the module-per-domain folder structure.
  • migrations — points to src/database/migrations/, the canonical location for all generated and hand-authored migration files.
The typeorm npm script in package.json runs TypeORM through typeorm-ts-node-commonjs, which lets the CLI consume TypeScript source directly without a prior compilation step:
"typeorm": "typeorm-ts-node-commonjs -d src/database/data-source.ts"

Migration Commands

All migration operations are available as npm scripts. The underlying command always uses the DataSource defined in src/database/data-source.ts.
# Generate a new migration by diffing entities against the live schema
npm run migration:generate -- src/database/migrations/MigrationName

# Apply all pending migrations in chronological order
npm run migration:run

# Roll back the most recently applied migration
npm run migration:revert
1

Make your entity changes

Add, modify, or remove columns and relations in the relevant *.entity.ts file inside the appropriate domain module.
2

Generate the migration

Run npm run migration:generate -- src/database/migrations/DescriptiveName. TypeORM connects to the database defined by DATABASE_URL, compares the current schema to your updated entities, and writes a timestamped migration file containing the forward (up) and rollback (down) SQL.
3

Review the generated file

Open the new file in src/database/migrations/ and verify that the generated SQL matches your intent. Pay particular attention to any DROP statements.
4

Run the migration

Execute npm run migration:run to apply all pending migrations. TypeORM tracks applied migrations in the migrations table it manages in your database.

Entity Conventions

All domain entities in the codebase extend the shared BaseEntity class defined in src/shared/domain/base.entity.ts:
import {
  CreateDateColumn,
  PrimaryGeneratedColumn,
  UpdateDateColumn,
} from 'typeorm';

export abstract class BaseEntity {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @CreateDateColumn({ name: 'created_at' })
  createdAt!: Date;

  @UpdateDateColumn({ name: 'updated_at' })
  updatedAt!: Date;
}
Every entity therefore inherits:
ColumnTypeORM decoratorTypeNotes
id@PrimaryGeneratedColumn('uuid')string (UUID)Primary key. TypeORM generates the value using the database’s uuid_generate_v4() function.
created_at@CreateDateColumnDateSet automatically by TypeORM on INSERT; never updated.
updated_at@UpdateDateColumnDateUpdated automatically by TypeORM on every UPDATE.
The uuid package (v11, listed in package.json) is available for application-layer UUID generation when you need to assign an ID before persisting — for example when publishing a domain event that must carry the future entity’s ID. Use import { v4 as uuidv4 } from 'uuid' in those cases.
Additional conventions observed across domain entity files:
  • Column names use snake_case via the name option on @Column:
    @Column({ name: 'vehicle_id', type: 'uuid' })
    vehicleId!: string;
    
  • TypeScript property names use camelCase — TypeORM maps between the two automatically at query time.
  • Repositories are injected with @InjectRepository() inside service constructors. Direct use of EntityManager is avoided to keep data-access logic scoped to the owning module.
  • Entities are registered per feature module using TypeOrmModule.forFeature([EntityClass]), which works in combination with autoLoadEntities: true on the root connection.

Concrete Example

src/booking/domain/entities/booking.entity.ts illustrates the full pattern:
import { Column, Entity, Index } from 'typeorm';
import { BaseEntity } from '../../../shared/domain/base.entity';
import { BookingStatus } from '../enums/booking-status.enum';

@Entity('bookings')
@Index(['corporateOrganizationId', 'status'])
@Index(['vendorOrganizationId', 'status'])
export class Booking extends BaseEntity {
  @Column({ name: 'vehicle_id', type: 'uuid' })
  vehicleId!: string;

  @Column({ name: 'vendor_organization_id', type: 'uuid' })
  vendorOrganizationId!: string;

  @Column({ name: 'corporate_organization_id', type: 'uuid' })
  corporateOrganizationId!: string;

  @Column({ name: 'requested_by', type: 'uuid' })
  requestedBy!: string;

  @Column({ name: 'start_date', type: 'timestamptz' })
  startDate!: Date;

  @Column({ name: 'end_date', type: 'timestamptz' })
  endDate!: Date;

  @Column({ type: 'enum', enum: BookingStatus })
  status!: BookingStatus;
}

Connection String Reference

The DATABASE_URL follows the standard PostgreSQL URI format. Common patterns:
# Local development (default from .env.example)
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/karokar

# Docker Compose service name as host
DATABASE_URL=postgresql://postgres:postgres@db:5432/karokar

# Cloud provider with SSL required (e.g. Supabase, Neon, RDS)
DATABASE_URL=postgresql://user:password@host.provider.com:5432/karokar?sslmode=require
When connecting to a cloud-hosted PostgreSQL instance that enforces SSL, append ?sslmode=require (or ?sslmode=verify-full with a CA certificate) to the connection string. The pg driver respects these query parameters without any additional TypeORM configuration.

Build docs developers (and LLMs) love