typeorm

TypeORM Core Knowledge

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "typeorm" with this command: npx skills add claude-dev-suite/claude-dev-suite/claude-dev-suite-claude-dev-suite-typeorm

TypeORM Core Knowledge

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: typeorm for comprehensive documentation.

When NOT to Use This Skill

  • Prisma Projects: Use prisma skill for Prisma-based applications

  • Drizzle Projects: Use drizzle skill for Drizzle ORM

  • Python Applications: Use sqlalchemy skill for Python ORMs

  • Raw SQL Operations: Use database-query MCP server for direct SQL

  • NoSQL Databases: Use mongodb skill for MongoDB (TypeORM MongoDB support is limited)

  • Database Design: Consult sql-expert or architect-expert for schema architecture

  • Migration Strategy: Engage devops-expert for production deployment planning

Entity Definition

import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, ManyToOne, OneToMany } from 'typeorm';

@Entity() export class User { @PrimaryGeneratedColumn() id: number;

@Column({ length: 100 }) name: string;

@Column({ unique: true }) email: string;

@Column({ default: true }) isActive: boolean;

@CreateDateColumn() createdAt: Date;

@OneToMany(() => Post, post => post.author) posts: Post[]; }

@Entity() export class Post { @PrimaryGeneratedColumn() id: number;

@Column() title: string;

@Column({ type: 'text', nullable: true }) content: string;

@ManyToOne(() => User, user => user.posts) author: User; }

Repository Operations

import { AppDataSource } from './data-source';

const userRepository = AppDataSource.getRepository(User);

// Create const user = userRepository.create({ name: 'John', email: 'john@example.com' }); await userRepository.save(user);

// Read const users = await userRepository.find(); const user = await userRepository.findOneBy({ id: 1 }); const userWithPosts = await userRepository.findOne({ where: { id: 1 }, relations: { posts: true }, });

// Update await userRepository.update(1, { name: 'Jane' });

// Delete await userRepository.delete(1);

Query Builder

const users = await userRepository .createQueryBuilder('user') .leftJoinAndSelect('user.posts', 'post') .where('user.isActive = :active', { active: true }) .andWhere('post.published = :published', { published: true }) .orderBy('user.createdAt', 'DESC') .take(10) .getMany();

Data Source Config

import { DataSource } from 'typeorm';

export const AppDataSource = new DataSource({ type: 'postgres', host: 'localhost', port: 5432, username: 'user', password: 'password', database: 'mydb', entities: [User, Post], synchronize: false, migrations: ['src/migrations/*.ts'], });

Anti-Patterns

Anti-Pattern Why It's Bad Better Approach

synchronize: true in production Can drop tables, loses data Always use migrations in production

Using find() without relations N+1 query problem Use relations option or QueryBuilder with joins

Not using transactions for multi-step ops Data inconsistency risk Wrap related operations in transaction()

Hardcoded credentials in DataSource Security vulnerability Use environment variables

No connection pool configuration Connection exhaustion Set extra.max and pool timeouts

Using @Column() without type for large text May truncate data Specify type: 'text' for long content

Lazy loading relations everywhere Performance issues, N+1 queries Use eager loading strategically

Not handling unique constraint errors Poor error messages to users Catch and handle constraint violations

Manual SQL without parameters SQL injection risk Use QueryBuilder with parameters

No indexes on frequently queried columns Slow queries Add @Index() decorators

Quick Troubleshooting

Issue Likely Cause Solution

"Cannot find name 'AppDataSource'" DataSource not initialized Call AppDataSource.initialize() at startup

"relation does not exist" Migration not run Execute pending migrations

"column does not exist" Entity/DB out of sync Generate and run new migration

Type errors on entities Decorator metadata issue Enable emitDecoratorMetadata and experimentalDecorators in tsconfig

"Repository not found" Entity not registered Add entity to DataSource entities array

Slow queries Missing indexes, no joins Add indexes, use leftJoinAndSelect

Connection pool exhausted Too many concurrent queries Increase extra.max pool size

"Cannot query across many-to-many" Missing join table Add explicit join table or use QueryBuilder

Migration generation creates no file No entity changes detected Manually create migration if needed

"ECONNREFUSED" Database not running Start database, verify connection details

Production Readiness

Data Source Configuration

// data-source.ts import { DataSource } from 'typeorm';

export const AppDataSource = new DataSource({ type: 'postgres', url: process.env.DATABASE_URL, // SECURITY: Use proper CA certificate in production instead of disabling verification // ssl: { rejectUnauthorized: false } is INSECURE - vulnerable to MITM attacks ssl: process.env.NODE_ENV === 'production' ? { ca: process.env.DB_CA_CERT } : false,

// Connection pool extra: { max: 20, idleTimeoutMillis: 30000, connectionTimeoutMillis: 10000, },

entities: ['dist/entities//*.js'], migrations: ['dist/migrations//.js'], subscribers: ['dist/subscribers/**/.js'],

// Never use in production synchronize: false,

// Logging logging: process.env.NODE_ENV === 'development' ? ['query', 'error'] : ['error'], logger: 'advanced-console',

// Cache cache: { type: 'ioredis', options: { host: process.env.REDIS_HOST, port: parseInt(process.env.REDIS_PORT || '6379'), }, duration: 30000, // 30 seconds }, });

// Initialize AppDataSource.initialize() .then(() => console.log('Database connected')) .catch((err) => console.error('Database connection error:', err));

Transaction Management

import { EntityManager } from 'typeorm';

async function transferFunds( manager: EntityManager, fromId: number, toId: number, amount: number ) { return await manager.transaction(async (transactionalManager) => { const from = await transactionalManager .createQueryBuilder(Account, 'account') .setLock('pessimistic_write') .where('account.id = :id', { id: fromId }) .getOne();

if (!from || from.balance < amount) {
  throw new Error('Insufficient funds');
}

await transactionalManager
  .createQueryBuilder()
  .update(Account)
  .set({ balance: () => `balance - ${amount}` })
  .where('id = :id', { id: fromId })
  .execute();

await transactionalManager
  .createQueryBuilder()
  .update(Account)
  .set({ balance: () => `balance + ${amount}` })
  .where('id = :id', { id: toId })
  .execute();

}); }

Query Optimization

// Pagination async function getUsers(page: number, limit: number) { const [users, total] = await userRepository.findAndCount({ skip: (page - 1) * limit, take: limit, order: { createdAt: 'DESC' }, });

return { data: users, meta: { total, page, lastPage: Math.ceil(total / limit), }, }; }

// Select specific columns const users = await userRepository .createQueryBuilder('user') .select(['user.id', 'user.name', 'user.email']) .where('user.isActive = :active', { active: true }) .getMany();

// Batch operations await userRepository .createQueryBuilder() .insert() .into(User) .values(usersToCreate) .orIgnore() // Skip duplicates .execute();

Soft Deletes

@Entity() @DeleteDateColumn() export class User { @PrimaryGeneratedColumn() id: number;

@Column() name: string;

@DeleteDateColumn() deletedAt?: Date; }

// Soft delete await userRepository.softDelete(1);

// Include soft deleted const allUsers = await userRepository .createQueryBuilder('user') .withDeleted() .getMany();

// Restore await userRepository.restore(1);

Migration Best Practices

// migrations/1234567890-CreateUsersTable.ts import { MigrationInterface, QueryRunner } from 'typeorm';

export class CreateUsersTable1234567890 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise<void> { await queryRunner.query( CREATE TABLE "users" ( "id" SERIAL PRIMARY KEY, "email" VARCHAR(255) UNIQUE NOT NULL, "name" VARCHAR(100) NOT NULL, "created_at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ); await queryRunner.query( CREATE INDEX "idx_users_email" ON "users" ("email") ); }

public async down(queryRunner: QueryRunner): Promise<void> { await queryRunner.query(DROP TABLE "users"); } }

// CLI commands // npm run typeorm migration:generate -- -n CreateUsersTable // npm run typeorm migration:run // npm run typeorm migration:revert

Testing

// test-utils.ts import { DataSource } from 'typeorm';

export const TestDataSource = new DataSource({ type: 'postgres', url: process.env.TEST_DATABASE_URL, entities: ['src/entities/**/*.ts'], synchronize: true, dropSchema: true, });

// tests/user.test.ts describe('UserRepository', () => { beforeAll(async () => { await TestDataSource.initialize(); });

afterAll(async () => { await TestDataSource.destroy(); });

beforeEach(async () => { await TestDataSource.synchronize(true); });

it('should create user', async () => { const repo = TestDataSource.getRepository(User); const user = await repo.save({ name: 'Test', email: 'test@example.com' }); expect(user.id).toBeDefined(); }); });

Monitoring Metrics

Metric Target

Query time (p99) < 100ms

Connection pool usage < 80%

Slow query count 0

Migration success 100%

Checklist

  • Connection pooling configured

  • SSL in production

  • synchronize: false in production

  • Query caching with Redis

  • Transaction management

  • Soft deletes where appropriate

  • Pagination for list queries

  • Migration versioning

  • Logging only errors in production

  • Test database isolation

Reference Documentation

  • Relations

  • Migrations

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

cron-scheduling

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

token-optimization

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

webrtc

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

react-19

No summary provided by upstream source.

Repository SourceNeeds Review