GitHub Copilot Instructions for TypeORM
This document provides guidance for GitHub Copilot when working with the TypeORM codebase.
Project Overview
TypeORM is a TypeScript-based Object-Relational Mapping (ORM) library that supports multiple databases including MySQL/MariaDB, PostgreSQL, MS SQL Server, Oracle, SAP HANA, SQLite, MongoDB, and Google Spanner. It implements both Active Record and Data Mapper patterns and runs on Node.js, Browser, React Native, and Electron platforms.
Architecture & Structure
Core Components
src/data-source/- DataSource (formerly Connection) managementsrc/entity-manager/- Entity management and operationssrc/repository/- Repository pattern implementationsrc/query-builder/- SQL query buildingsrc/decorator/- TypeScript decorators for entities, columns, relationssrc/driver/- Database-specific driverssrc/metadata/- Entity metadata managementsrc/schema-builder/- Schema creation and migrationsrc/migration/- Database migration systemsrc/subscriber/- Event subscriber systemsrc/persistence/- Entity persistence logic
Design Patterns
Active Record Pattern: Entities have methods to save, remove, and query themselves
Data Mapper Pattern: Repositories handle entity persistence separately from business logic
Decorator Pattern: Extensive use of TypeScript decorators for metadata definition
Builder Pattern: QueryBuilder for constructing complex queries
Coding Standards
TypeScript Configuration
Target: ES2021+ with CommonJS modules
Decorators:
experimentalDecoratorsandemitDecoratorMetadataenabled
Code Style
Formatting: Use Prettier with these settings:
No semicolons (
"semi": false)Arrow function parentheses always (
"arrowParens": "always")Trailing commas everywhere (
"trailingComma": "all")
Linting: ESLint with TypeScript support
Use
@typescript-eslintrulesWarnings allowed for some
@typescript-eslint/no-*rulesUnused variables starting with
_are ignored
Naming Conventions:
Classes: PascalCase (e.g.,
DataSource,EntityManager)Interfaces: PascalCase (e.g.,
ColumnOptions,RelationOptions)Variables/functions: camelCase
Constants: UPPER_SNAKE_CASE for true constants
Private members: Use standard camelCase (no underscore prefix)
TypeScript Patterns
Use explicit types for public APIs
Prefer interfaces over type aliases for object shapes
Use generics for reusable components
Avoid
anywhere possible; useunknownor proper typesUse optional chaining (
?.) and nullish coalescing (??) operatorsLeverage TypeScript utility types (
Partial<T>,Required<T>,Pick<T>, etc.)
Testing
Test Structure
Tests are organized in test/ directory:
test/functional/- Feature and integration tests organized by functionality (preferred)test/github-issues/- Tests for specific GitHub issuestest/unit/- Unit tests for individual componentstest/utils/- Test utilities and helpers
Note: Prefer writing functional tests over per-issue tests.
Test Writing Guidelines
Use the standard test template:
import "reflect-metadata"
import { createTestingConnections, closeTestingConnections, reloadTestingDatabases } from "../../utils/test-utils"
import { DataSource } from "../../../src/data-source/DataSource"
import { expect } from "chai"
describe("description of functionality", () => {
let dataSources: DataSource[]
before(async () => dataSources = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
schemaCreate: true,
dropSchema: true,
}))
beforeEach(() => reloadTestingDatabases(dataSources))
after(() => closeTestingConnections(dataSources))
it("should do something specific", () => Promise.all(dataSources.map(async dataSource => {
// Test implementation
})))
})Test Configuration:
Tests run against multiple databases (as configured in
ormconfig.json)Each test should work across all supported databases unless database-specific
Place entity files in
./entity/relative to test file for automatic loadingUse
Promise.all(dataSources.map(...))pattern to test against all databases
Test Naming:
Use descriptive
describe()blocks for featuresUse "should..." format for
it()descriptionsReference GitHub issue numbers when fixing specific issues
Running Tests:
Full test suite:
npm test(compiles then runs tests)Fast iteration:
npm run test:fast(runs without recompiling)Specific tests:
npm run test:fast -- --grep "pattern"Watch mode:
npm run compile -- --watch+npm run test:fast
Database-Specific Considerations
Multi-Database Support
When writing code or tests:
Ensure compatibility across all supported databases
Use driver-specific code only in
src/driver/directoryTest database-agnostic code against multiple databases
Use
DataSource.options.typeto check database type when neededBe aware of SQL dialect differences (LIMIT vs TOP, etc.)
Driver Implementation
Each driver in src/driver/ implements common interfaces:
Connection management
Query execution
Schema synchronization
Type mapping
Transaction handling
Common Development Tasks
Adding a New Feature
Create entities in appropriate test directory
Write tests first (TDD approach encouraged)
Implement feature in
src/Ensure tests pass across all databases
Update documentation if public API changes
Follow commit message conventions
Adding a New Decorator
Create decorator file in
src/decorator/Create metadata args in
src/metadata-args/Update metadata builder in
src/metadata-builder/Export from
src/index.tsAdd comprehensive tests
Update TypeScript type definitions if needed
Working with Migrations
Migrations are in
src/migration/Migration files should be timestamped
Support both up and down migrations
Test migrations against all supported databases
Ensure schema changes are reversible
Build & Development Workflow
Commands
Build:
npm run compile- Compiles TypeScript tobuild/compiled/Package:
npm run package- Creates distribution inbuild/package/Pack:
npm run pack- Creates.tgzfile inbuild/Test:
npm test- Compile and run all testsLint:
npm run lint- Run ESLintFormat:
npm run format- Run PrettierWatch:
npm run watch- Watch mode for TypeScript compilation
Development Setup
Install dependencies:
npm installCopy config:
cp ormconfig.sample.json ormconfig.jsonConfigure database connections in
ormconfig.jsonOptionally use Docker:
docker-compose upfor database services
Pre-commit Hooks
Husky runs pre-commit hooks
Lint-staged runs on staged files
Format and lint checks must pass
Contribution Guidelines
Commit Message Format
Follow conventional commits:
<type>: <subject>
<body>
<footer>Types: feat, fix, docs, style, refactor, perf, test, build, chore, revert
Subject:
Use imperative, present tense
Don't capitalize first letter
No period at the end
Max 100 characters per line
Pull Request Requirements
All tests must pass
Include appropriate tests for changes
Follow existing code style
Update documentation for API changes
Reference related GitHub issues
Get approval before merging
Common Patterns & Idioms
Entity Definition
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column()
name: string
@OneToMany(() => Photo, photo => photo.user)
photos: Photo[]
}Repository Usage
const userRepository = dataSource.getRepository(User)
const user = await userRepository.findOne({ where: { id: 1 } })QueryBuilder
const users = await dataSource
.getRepository(User)
.createQueryBuilder("user")
.leftJoinAndSelect("user.photos", "photo")
.where("user.name = :name", { name: "John" })
.getMany()Transactions
await dataSource.transaction(async (manager) => {
await manager.save(user)
await manager.save(photo)
})Important Notes
Always import
reflect-metadatabefore TypeORMBe careful with circular dependencies between entities
Use lazy relations or forward references for circular entity references
Connection pooling is handled automatically by drivers
Be mindful of N+1 query problems; use joins or eager loading
Repository methods are async; always use
awaitEntity instances should be plain objects, not class instances with methods (Data Mapper pattern)
Resources
Last updated
Was this helpful?