CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-typeorm

Data-Mapper ORM for TypeScript and ES2021+ supporting MySQL/MariaDB, PostgreSQL, MS SQL Server, Oracle, SAP HANA, SQLite, MongoDB databases.

Overview
Eval results
Files

repository.mddocs/

Repository Pattern

Type-safe repository pattern implementation providing CRUD operations, custom queries, and specialized repositories for different data access patterns. TypeORM repositories abstract database operations with a clean, consistent API across all supported databases.

Capabilities

Base Repository

The primary repository class providing standard CRUD operations with full type safety and relation loading capabilities.

/**
 * Repository for entity operations and queries
 * @template Entity - The entity type this repository manages
 */
class Repository<Entity> {
  /** The target entity class or schema */
  readonly target: EntityTarget<Entity>;

  /** The underlying entity manager */
  readonly manager: EntityManager;

  /** Create a new query builder for this entity */
  createQueryBuilder(alias?: string): SelectQueryBuilder<Entity>;

  /**
   * Saves a given entity or array of entities
   * @param entity - Entity or entities to save
   * @param options - Save operation options
   * @returns Promise resolving to saved entities
   */
  save<T extends DeepPartial<Entity>>(
    entity: T,
    options?: SaveOptions
  ): Promise<T & Entity>;
  save<T extends DeepPartial<Entity>>(
    entities: T[],
    options?: SaveOptions
  ): Promise<(T & Entity)[]>;

  /**
   * Removes a given entity or array of entities
   * @param entity - Entity or entities to remove
   * @param options - Remove operation options
   * @returns Promise resolving to removed entities
   */
  remove(entity: Entity, options?: RemoveOptions): Promise<Entity>;
  remove(entities: Entity[], options?: RemoveOptions): Promise<Entity[]>;

  /**
   * Soft removes entities by setting their @DeleteDateColumn
   * @param entity - Entity or entities to soft remove
   * @returns Promise resolving to soft removed entities
   */
  softRemove(entity: Entity, options?: SaveOptions): Promise<Entity>;
  softRemove(entities: Entity[], options?: SaveOptions): Promise<Entity[]>;

  /**
   * Recovers soft-deleted entities by clearing @DeleteDateColumn
   * @param entity - Entity or entities to recover
   * @returns Promise resolving to recovered entities
   */
  recover(entity: Entity, options?: SaveOptions): Promise<Entity>;
  recover(entities: Entity[], options?: SaveOptions): Promise<Entity[]>;

  /**
   * Inserts new entities into database
   * @param entity - Entity or entities to insert
   * @returns Promise resolving to insert result
   */
  insert(entity: QueryDeepPartialEntity<Entity> | QueryDeepPartialEntity<Entity>[]): Promise<InsertResult>;

  /**
   * Updates entities that match given conditions
   * @param criteria - Update conditions
   * @param partialEntity - Values to update
   * @returns Promise resolving to update result
   */
  update(
    criteria: string | string[] | number | number[] | Date | Date[] | ObjectID | ObjectID[] | FindOptionsWhere<Entity>,
    partialEntity: QueryDeepPartialEntity<Entity>
  ): Promise<UpdateResult>;

  /**
   * Upsert operation (insert or update if exists)
   * @param entityOrEntities - Entity or entities to upsert
   * @param conflictPathsOrOptions - Conflict resolution paths or options
   * @returns Promise resolving to upsert result
   */
  upsert(
    entityOrEntities: QueryDeepPartialEntity<Entity> | QueryDeepPartialEntity<Entity>[],
    conflictPathsOrOptions: string[] | UpsertOptions<Entity>
  ): Promise<InsertResult>;

  /**
   * Deletes entities that match given conditions
   * @param criteria - Delete conditions
   * @returns Promise resolving to delete result
   */
  delete(
    criteria: string | string[] | number | number[] | Date | Date[] | ObjectID | ObjectID[] | FindOptionsWhere<Entity>
  ): Promise<DeleteResult>;

  /**
   * Soft deletes entities that match given conditions
   * @param criteria - Soft delete conditions
   * @returns Promise resolving to update result (sets delete date)
   */
  softDelete(
    criteria: string | string[] | number | number[] | Date | Date[] | ObjectID | ObjectID[] | FindOptionsWhere<Entity>
  ): Promise<UpdateResult>;

  /**
   * Restores soft-deleted entities that match given conditions
   * @param criteria - Restore conditions
   * @returns Promise resolving to update result (clears delete date)
   */
  restore(
    criteria: string | string[] | number | number[] | Date | Date[] | ObjectID | ObjectID[] | FindOptionsWhere<Entity>
  ): Promise<UpdateResult>;

  /**
   * Finds entities that match given find options
   * @param options - Find options
   * @returns Promise resolving to entities array
   */
  find(options?: FindManyOptions<Entity>): Promise<Entity[]>;

  /**
   * Finds entities that match given conditions
   * @param where - Where conditions
   * @returns Promise resolving to entities array
   */
  findBy(where: FindOptionsWhere<Entity> | FindOptionsWhere<Entity>[]): Promise<Entity[]>;

  /**
   * Finds first entity that matches given find options
   * @param options - Find options
   * @returns Promise resolving to entity or null
   */
  findOne(options: FindOneOptions<Entity>): Promise<Entity | null>;

  /**
   * Finds first entity that matches given conditions
   * @param where - Where conditions
   * @returns Promise resolving to entity or null
   */
  findOneBy(where: FindOptionsWhere<Entity> | FindOptionsWhere<Entity>[]): Promise<Entity | null>;

  /**
   * Finds entity by ID, throws error if not found
   * @param options - Find options
   * @returns Promise resolving to entity
   * @throws EntityNotFoundError if entity not found
   */
  findOneOrFail(options: FindOneOptions<Entity>): Promise<Entity>;

  /**
   * Finds entity by conditions, throws error if not found
   * @param where - Where conditions
   * @returns Promise resolving to entity
   * @throws EntityNotFoundError if entity not found
   */
  findOneByOrFail(where: FindOptionsWhere<Entity> | FindOptionsWhere<Entity>[]): Promise<Entity>;

  /**
   * Counts entities that match given find options
   * @param options - Count options
   * @returns Promise resolving to count number
   */
  count(options?: FindManyOptions<Entity>): Promise<number>;

  /**
   * Counts entities that match given conditions
   * @param where - Where conditions
   * @returns Promise resolving to count number
   */
  countBy(where: FindOptionsWhere<Entity> | FindOptionsWhere<Entity>[]): Promise<number>;

  /**
   * Checks if entity exists that matches given conditions
   * @param options - Existence check options
   * @returns Promise resolving to boolean
   */
  exist(options?: FindManyOptions<Entity>): Promise<boolean>;

  /**
   * Checks if entity exists that matches given conditions
   * @param where - Where conditions
   * @returns Promise resolving to boolean
   */
  existsBy(where: FindOptionsWhere<Entity> | FindOptionsWhere<Entity>[]): Promise<boolean>;

  /**
   * Increments some column by provided value
   * @param conditions - Update conditions
   * @param propertyPath - Property path to increment
   * @param value - Value to increment by
   * @returns Promise resolving to update result
   */
  increment(
    conditions: FindOptionsWhere<Entity>,
    propertyPath: string,
    value: number | string
  ): Promise<UpdateResult>;

  /**
   * Decrements some column by provided value
   * @param conditions - Update conditions
   * @param propertyPath - Property path to decrement
   * @param value - Value to decrement by
   * @returns Promise resolving to update result
   */
  decrement(
    conditions: FindOptionsWhere<Entity>,
    propertyPath: string,
    value: number | string
  ): Promise<UpdateResult>;

  /**
   * Gets sum of values in numeric column
   * @param columnName - Column name to sum
   * @param where - Where conditions
   * @returns Promise resolving to sum or null
   */
  sum(
    columnName: string,
    where?: FindOptionsWhere<Entity>
  ): Promise<number | null>;

  /**
   * Gets average of values in numeric column
   * @param columnName - Column name to average
   * @param where - Where conditions
   * @returns Promise resolving to average or null
   */
  average(
    columnName: string,
    where?: FindOptionsWhere<Entity>
  ): Promise<number | null>;

  /**
   * Gets minimum value in column
   * @param columnName - Column name
   * @param where - Where conditions
   * @returns Promise resolving to minimum value or null
   */
  minimum(
    columnName: string,
    where?: FindOptionsWhere<Entity>
  ): Promise<any>;

  /**
   * Gets maximum value in column
   * @param columnName - Column name
   * @param where - Where conditions
   * @returns Promise resolving to maximum value or null
   */
  maximum(
    columnName: string,
    where?: FindOptionsWhere<Entity>
  ): Promise<any>;

  /**
   * Checks if entity has an ID value
   * @param entity - Entity to check
   * @returns True if entity has ID
   */
  hasId(entity: Entity): boolean;

  /**
   * Gets entity ID value
   * @param entity - Entity to get ID from
   * @returns Entity ID value
   */
  getId(entity: Entity): any;

  /**
   * Creates a new empty entity instance
   * @returns New empty entity
   */
  create(): Entity;

  /**
   * Creates entity from partial data
   * @param entityLike - Partial entity data
   * @returns New entity with provided data
   */
  create(entityLike: DeepPartial<Entity>): Entity;

  /**
   * Creates multiple entities from array of partial data
   * @param entityLikeArray - Array of partial entity data
   * @returns Array of new entities
   */
  create(entityLikeArray: DeepPartial<Entity>[]): Entity[];

  /**
   * Merges multiple entity data into a single entity
   * @param mergeIntoEntity - Base entity to merge into
   * @param entityLikes - Additional entity data to merge
   * @returns Merged entity
   */
  merge(mergeIntoEntity: Entity, ...entityLikes: DeepPartial<Entity>[]): Entity;

  /**
   * Preloads entity by finding it and loading all defined relations
   * @param entityLike - Entity-like object to preload
   * @returns Promise resolving to preloaded entity or undefined
   */
  preload(entityLike: DeepPartial<Entity>): Promise<Entity | undefined>;

  /**
   * Clears all entities from the table (truncate)
   * @returns Promise resolving when clear is complete
   */
  clear(): Promise<void>;

  /**
   * Checks if any entity exists matching given options
   * @param options - Find options to check existence
   * @returns Promise resolving to true if any entity exists
   */
  exist(options?: FindManyOptions<Entity>): Promise<boolean>;

  /**
   * Checks if any entity exists matching given where conditions
   * @param where - Where conditions to check
   * @returns Promise resolving to true if any entity exists
   */
  existBy(where: FindOptionsWhere<Entity> | FindOptionsWhere<Entity>[]): Promise<boolean>;
}

interface SaveOptions {
  /** Array of listeners to skip */
  listeners?: boolean;
  /** Whether to skip transaction for this operation */
  transaction?: boolean;
  /** Chunk size for bulk operations */
  chunk?: number;
  /** Whether to reload entity after save */
  reload?: boolean;
}

interface RemoveOptions {
  /** Array of listeners to skip */
  listeners?: boolean;
  /** Whether to skip transaction for this operation */
  transaction?: boolean;
  /** Chunk size for bulk operations */
  chunk?: number;
}

interface UpsertOptions<Entity> {
  /** Columns that define uniqueness constraint */
  conflictPaths: string[];
  /** Whether to skip update on conflict */
  skipUpdateIfNoValuesChanged?: boolean;
  /** Index predicate for partial unique indexes */
  indexPredicate?: string;
}

Usage Examples:

import { Repository } from "typeorm";
import { User } from "./entities/User";

// Get repository from data source
const userRepository = dataSource.getRepository(User);

// Basic CRUD operations
const user = await userRepository.save({
  name: "John Doe",
  email: "john@example.com"
});

const users = await userRepository.find();
const userById = await userRepository.findOneBy({ id: 1 });

await userRepository.update({ id: 1 }, { name: "Jane Doe" });
await userRepository.delete({ id: 1 });

// Soft delete operations
await userRepository.softDelete({ id: 1 });
await userRepository.restore({ id: 1 });

// Aggregation operations
const userCount = await userRepository.count();
const totalAge = await userRepository.sum("age");
const averageAge = await userRepository.average("age");

// Bulk operations
await userRepository.insert([
  { name: "User 1", email: "user1@example.com" },
  { name: "User 2", email: "user2@example.com" }
]);

// Upsert operation
await userRepository.upsert(
  { email: "john@example.com", name: "John Smith" },
  { conflictPaths: ["email"] }
);

Tree Repository

Specialized repository for hierarchical data structures with tree-specific operations.

/**
 * Repository for tree entities with hierarchical operations
 * @template Entity - Tree entity type
 */
class TreeRepository<Entity> extends Repository<Entity> {
  /**
   * Finds all root nodes (nodes without parents)
   * @param options - Find options
   * @returns Promise resolving to root nodes
   */
  findRoots(options?: FindTreeOptions): Promise<Entity[]>;

  /**
   * Finds all descendants of a given node
   * @param entity - Parent entity
   * @param options - Find options
   * @returns Promise resolving to descendant nodes
   */
  findDescendants(entity: Entity, options?: FindTreeOptions): Promise<Entity[]>;

  /**
   * Finds all ancestors of a given node
   * @param entity - Child entity
   * @param options - Find options
   * @returns Promise resolving to ancestor nodes
   */
  findAncestors(entity: Entity, options?: FindTreeOptions): Promise<Entity[]>;

  /**
   * Finds complete trees with all nodes
   * @param options - Find options
   * @returns Promise resolving to complete tree structures
   */
  findTrees(options?: FindTreeOptions): Promise<Entity[]>;

  /**
   * Counts descendants of a given node
   * @param entity - Parent entity
   * @param options - Count options
   * @returns Promise resolving to descendant count
   */
  countDescendants(entity: Entity, options?: FindTreeOptions): Promise<number>;

  /**
   * Counts ancestors of a given node
   * @param entity - Child entity
   * @param options - Count options
   * @returns Promise resolving to ancestor count
   */
  countAncestors(entity: Entity, options?: FindTreeOptions): Promise<number>;

  /**
   * Creates query builder to find descendants
   * @param alias - Alias for the entity
   * @param entity - Parent entity
   * @returns SelectQueryBuilder for descendants
   */
  createDescendantsQueryBuilder(
    alias: string,
    entity: Entity
  ): SelectQueryBuilder<Entity>;

  /**
   * Creates query builder to find ancestors
   * @param alias - Alias for the entity
   * @param entity - Child entity
   * @returns SelectQueryBuilder for ancestors
   */
  createAncestorsQueryBuilder(
    alias: string,
    entity: Entity
  ): SelectQueryBuilder<Entity>;
}

interface FindTreeOptions {
  /** Relations to load */
  relations?: string[];
  /** Tree depth limit */
  depth?: number;
}

Tree Repository Examples:

import { TreeRepository } from "typeorm";
import { Category } from "./entities/Category";

const categoryRepository = dataSource.getTreeRepository(Category);

// Find all root categories
const roots = await categoryRepository.findRoots();

// Find all subcategories under a category
const subcategories = await categoryRepository.findDescendants(parentCategory);

// Find category path (all ancestors)
const path = await categoryRepository.findAncestors(childCategory);

// Load complete category tree
const tree = await categoryRepository.findTrees();

// Count subcategories
const subcategoryCount = await categoryRepository.countDescendants(parentCategory);

MongoDB Repository

Specialized repository for MongoDB with document-specific operations and MongoDB query syntax.

/**
 * Repository for MongoDB entities with document operations
 * @template Entity - MongoDB entity type
 */
class MongoRepository<Entity> extends Repository<Entity> {
  /**
   * Creates a cursor for the entities
   * @param query - MongoDB query
   * @returns Cursor for iteration
   */
  createCursor<T = any>(query?: ObjectLiteral): Cursor<T>;

  /**
   * Creates an aggregation cursor
   * @param pipeline - Aggregation pipeline
   * @returns Aggregation cursor
   */
  aggregate<R = any>(pipeline: ObjectLiteral[]): AggregationCursor<R>;

  /**
   * Finds entities using MongoDB query syntax
   * @param query - MongoDB query
   * @param options - Find options
   * @returns Promise resolving to entities
   */
  findByIds(ids: any[], options?: FindManyOptions<Entity>): Promise<Entity[]>;

  /**
   * Finds one entity by MongoDB ObjectId
   * @param id - MongoDB ObjectId
   * @param options - Find options
   * @returns Promise resolving to entity or null
   */
  findOneById(id: string | ObjectID, options?: FindOneOptions<Entity>): Promise<Entity | null>;

  /**
   * Creates distinct query
   * @param key - Field to get distinct values for
   * @param query - MongoDB query
   * @returns Promise resolving to distinct values
   */
  distinct(key: string, query?: ObjectLiteral): Promise<any>;

  /**
   * Updates many documents
   * @param query - MongoDB query
   * @param update - Update operations
   * @returns Promise resolving to update result
   */
  updateMany(
    query: ObjectLiteral,
    update: ObjectLiteral
  ): Promise<UpdateResult>;

  /**
   * Deletes many documents
   * @param query - MongoDB query
   * @returns Promise resolving to delete result
   */
  deleteMany(query: ObjectLiteral): Promise<DeleteResult>;

  /**
   * Finds and modifies a document atomically
   * @param query - MongoDB query
   * @param update - Update operations
   * @param options - Find and modify options
   * @returns Promise resolving to modified document
   */
  findOneAndUpdate(
    query: ObjectLiteral,
    update: ObjectLiteral,
    options?: { returnOriginal?: boolean; upsert?: boolean }
  ): Promise<Entity | null>;

  /**
   * Finds and deletes a document atomically
   * @param query - MongoDB query
   * @returns Promise resolving to deleted document
   */
  findOneAndDelete(query: ObjectLiteral): Promise<Entity | null>;
}

Entity Manager

Direct database operations interface with transaction support, providing lower-level access to database operations.

/**
 * Entity manager for direct database operations
 */
class EntityManager {
  /** DataSource connection */
  readonly connection: DataSource;

  /** Query runner for this manager */
  readonly queryRunner?: QueryRunner;

  /**
   * Gets repository for entity
   * @param target - Entity target
   * @returns Repository instance
   */
  getRepository<Entity>(target: EntityTarget<Entity>): Repository<Entity>;

  /**
   * Gets tree repository for entity
   * @param target - Entity target
   * @returns TreeRepository instance
   */
  getTreeRepository<Entity>(target: EntityTarget<Entity>): TreeRepository<Entity>;

  /**
   * Gets MongoDB repository for entity
   * @param target - Entity target
   * @returns MongoRepository instance
   */
  getMongoRepository<Entity>(target: EntityTarget<Entity>): MongoRepository<Entity>;

  /**
   * Creates a new query builder
   * @param entityClass - Entity class
   * @param alias - Table alias
   * @returns SelectQueryBuilder instance
   */
  createQueryBuilder<Entity>(
    entityClass?: ObjectType<Entity> | EntitySchema<Entity>,
    alias?: string
  ): SelectQueryBuilder<Entity>;

  /** All repository methods available on EntityManager */
  save<T>(entity: T, options?: SaveOptions): Promise<T>;
  remove<T>(entity: T, options?: RemoveOptions): Promise<T>;
  insert<Entity>(target: EntityTarget<Entity>, entity: QueryDeepPartialEntity<Entity>): Promise<InsertResult>;
  update<Entity>(target: EntityTarget<Entity>, criteria: any, partialEntity: QueryDeepPartialEntity<Entity>): Promise<UpdateResult>;
  delete<Entity>(target: EntityTarget<Entity>, criteria: any): Promise<DeleteResult>;
  find<Entity>(entityClass: EntityTarget<Entity>, options?: FindManyOptions<Entity>): Promise<Entity[]>;
  findOne<Entity>(entityClass: EntityTarget<Entity>, options: FindOneOptions<Entity>): Promise<Entity | null>;
  // ... all other repository methods
}

Abstract Repository & Base Entity

Base classes for implementing custom repositories and Active Record pattern.

/**
 * Abstract base class for custom repositories
 * @template Entity - Entity type
 */
abstract class AbstractRepository<Entity> {
  /** Repository for the entity */
  readonly repository: Repository<Entity>;

  /** Entity manager */
  readonly manager: EntityManager;

  /**
   * Creates query builder for the entity
   * @param alias - Table alias
   * @returns SelectQueryBuilder instance
   */
  createQueryBuilder(alias?: string): SelectQueryBuilder<Entity>;
}

/**
 * Base entity class providing Active Record pattern methods
 */
abstract class BaseEntity {
  /** Whether this entity has an ID assigned */
  hasId(): boolean;

  /** Saves this entity */
  save(options?: SaveOptions): Promise<this>;

  /** Removes this entity */
  remove(options?: RemoveOptions): Promise<this>;

  /** Soft removes this entity */
  softRemove(options?: SaveOptions): Promise<this>;

  /** Recovers this soft-removed entity */
  recover(options?: SaveOptions): Promise<this>;

  /** Reloads this entity from database */
  reload(): Promise<void>;

  /** Static methods for entity operations */
  static save<T extends BaseEntity>(this: ObjectType<T>, entity: T, options?: SaveOptions): Promise<T>;
  static save<T extends BaseEntity>(this: ObjectType<T>, entities: T[], options?: SaveOptions): Promise<T[]>;
  static remove<T extends BaseEntity>(this: ObjectType<T>, entity: T, options?: RemoveOptions): Promise<T>;
  static remove<T extends BaseEntity>(this: ObjectType<T>, entities: T[], options?: RemoveOptions): Promise<T[]>;
  static insert<T extends BaseEntity>(this: ObjectType<T>, entity: QueryDeepPartialEntity<T>): Promise<InsertResult>;
  static update<T extends BaseEntity>(this: ObjectType<T>, criteria: any, partialEntity: QueryDeepPartialEntity<T>): Promise<UpdateResult>;
  static delete<T extends BaseEntity>(this: ObjectType<T>, criteria: any): Promise<DeleteResult>;
  static find<T extends BaseEntity>(this: ObjectType<T>, options?: FindManyOptions<T>): Promise<T[]>;
  static findOne<T extends BaseEntity>(this: ObjectType<T>, options: FindOneOptions<T>): Promise<T | null>;
  static findOneBy<T extends BaseEntity>(this: ObjectType<T>, where: FindOptionsWhere<T>): Promise<T | null>;
  // ... other static repository methods
}

Active Record Pattern Example:

import { Entity, BaseEntity, PrimaryGeneratedColumn, Column } from "typeorm";

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

  @Column()
  name: string;

  @Column()
  email: string;

  // Custom instance methods
  async updateLastLogin(): Promise<void> {
    this.lastLoginAt = new Date();
    await this.save();
  }
}

// Active Record usage
const user = new User();
user.name = "John";
user.email = "john@example.com";
await user.save(); // Saves the user

// Static methods
const users = await User.find();
const userById = await User.findOneBy({ id: 1 });
await User.delete({ id: 1 });

Repository Usage Patterns

Custom Repositories

Create custom repositories by extending Repository or using AbstractRepository:

@CustomRepository(User)
export class UserRepository extends Repository<User> {
  findActiveUsers(): Promise<User[]> {
    return this.findBy({ active: true });
  }

  findByEmail(email: string): Promise<User | null> {
    return this.findOneBy({ email });
  }
}

// Register custom repository
const userRepository = dataSource.getCustomRepository(UserRepository);

Repository Patterns

TypeORM supports multiple repository patterns:

  • Data Mapper Pattern: Use Repository classes (recommended)
  • Active Record Pattern: Extend BaseEntity class
  • Custom Repository Pattern: Create custom repository classes

Install with Tessl CLI

npx tessl i tessl/npm-typeorm

docs

data-source.md

entity-definition.md

entity-schema.md

events.md

find-options.md

index.md

migrations.md

query-builder.md

relationships.md

repository.md

tile.json