Node.js - TypeORM support

Introduction

TypeORM is an ORM that can run in NodeJS, Browser, Cordova, PhoneGap, Ionic, React Native, NativeScript, Expo, and Electron platforms and can be used with TypeScript - see https://typeorm.io/external link for more information.

Objects

TypeORM can be used both with SQL and NoSQL databases.

  • For the SQL:

    • a NodeJS Entity object when the decorator Entity attached to a class declaration or an EntitySchema instance is found;
    • a NodeJS Entity Operation object when one of the supported TypeORM APIs is used and linked to one of the entities;
    • a TypeScript SQL Query object when the APIs query or createQueryBuilder is found.
  • For the NoSQL, the only NoSQL database supported is MongoDB.

    • a NodeJS MongoDB connection object when the APIs createConnection, createConnections, or a DataSource instance is found. The name of connection is constructed from the host and database values;
    • a NodeJS MongoDB collection object when the decorator Entity attached to a class declaration or an EntitySchema instance is found, and linked to one of the connections.
Icon Description
NodeJS Entity
NodeJS Entity Operation
TypeScript SQL Query
NodeJS MongoDB connection
NodeJS MongoDB collection

Supported persistence SQL databases

Supported operations

Entity Operation Supported APIs
Add
  • insert
Update
  • preload
  • increment
  • decrement
  • update
  • save
  • merge
  • upsert
Remove
  • remove
  • delete
  • clear
  • softDelete
  • softRemove
Select
  • find
  • findAndCount
  • findByIds
  • findOne
  • findOneOrFail
  • count
  • hasId
  • getId
  • findBy
  • findAndCountBy
  • findOneBy
  • findOneByOrFail
  • findTrees
  • findRoots
  • findDescendants
  • findDescendantsTree
  • countDescendants
  • findAncestors
  • findAncestorsTree
  • countAncestors

TypeORM provide several ways to access and/or update a table. One can use:

  • an entity manager: getManager, getConnection().manager, DataSource().manager;
  • a repository: getRepository, getManager().getRepository, DataSource().getRepository;
  • a query builder: getConnection().createQueryBuilder, getManager().createQueryBuilder, getRepository().createQueryBuilder, DataSource().createQueryBuilder, DataSource().manager.createQueryBuilder, DataSource().getRepository().createQueryBuilder.

The use of InjectRepository from @nestjs/typeorm is also supported.

Link Type Caller type Callee type Comment
callLink
  • TypeScript Function
  • TypeScript Method
  • TypeScript Module
  • NodeJS Entity Operation
  • TypeScript SQL Query
relyonLink
  • NodeJS Entity
  • TypeScript Class
When the entity is defined using the decorator ‘Entity’ attached to a class declaration.
useInsertLink
  • NodeJS Entity Operation: Add
  • TypeScript SQL Query
  • Table
  • Missing Table
Created by SQL Analyzer when DDL source files are analyzed or by Missing tables and procedures for Node.js when the object is not analyzed.
useUpdateLink
  • NodeJS Entity Operation: Update
  • TypeScript SQL Query
  • Table
  • Missing Table
Created by SQL Analyzer when DDL source files are analyzed or by Missing tables and procedures for Node.js when the object is not analyzed.
useDeleteLink
  • NodeJS Entity Operation: Remove
  • TypeScript SQL Query
  • Table
  • Missing Table
Created by SQL Analyzer when DDL source files are analyzed or by Missing tables and procedures for Node.js when the object is not analyzed.
useSelectLink
  • NodeJS Entity Operation: Select
  • TypeScript SQL Query
  • Table
  • Missing Table
Created by SQL Analyzer when DDL source files are analyzed or by Missing tables and procedures for Node.js when the object is not analyzed.

Cascades

In the following example, the ‘User’ entity has its column profile with a one-to-one relation with the ‘Profile’ entity and cascade set to true:

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

@Entity()
export class Profile {
    @PrimaryGeneratedColumn()
    id: number;
    
    @Column()
    gender: string;
    
    @Column()
    photo: string;
}
import { Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from "typeorm";
import { Profile } from "./profile";

@Entity()
export class User {
    @PrimaryGeneratedColumn()
    id: number;
    
    @Column()
    name: string;
    
    @OneToOne(type => Profile, {
        cascade: true
    })
    
    @JoinColumn()
    profile: Profile;
}

When the profile column of a user instance is saved, if the profile column of that instance was updated with a profile instance, that profile instance is also saved.

import { getRepository } from "typeorm";
import { User } from "../entity_dir/user";
import { Profile } from "../entity_dir/profile";

function update_user(){
    const userRepository = getRepository(User); 
    const user = await userRepository.findOne(1);
    const profile = new Profile()
    user.name = "fooname";
    user.profile = profile
    await userRepository.save(user);
}

In this example, two ‘NodeJS Entity’ and three ‘NodeJS Entity Operation’ objects are created. Two ‘relyOn’ links are added when ‘User’ and ‘Profile’ entities are created from their classes. Three ‘call’ links are added from ‘update_user’ function to three ‘NodeJS Entity Operation’ objects. Two ‘useUpdate’ and one ‘useSelect’ links are added between the ‘NodeJS Entity Operation’ objects and both the ‘user’ and ‘profile’ tables:

SQL Queries

SQL queries can also be carried out using TypeORM such as with the following code:

import { getManager } from "typeorm";
import { User } from "../entity_dir/user";
import { getConnection } from "typeorm";

export class AuthService {
  private userRepository = getRepository(User);

  signUp = async (userData: CreateUserDTO) => {
    const { username, email, password } = userData;
    const existingUser = await this.userRepository
      .createQueryBuilder()
      .where('username = :username OR email = :email', { username, email })
      .getMany();
  };

  public foo() {
    const manager = getConnection().manager;
    const rawData = await manager.query(`SELECT * FROM USER`);
  }
}

In this example, two ‘TypeScript SQL Query’ objects are created, and two callLink between the two methods and these queries are added. The SQL Analyzer or by Missing tables and procedures for Node.js can then link these queries to the corresponding table:

Supported persistence MongoDB database

Link Type Caller type Callee type Supported APIs
useInsertLink
  • TypeScript Function
  • TypeScript Method
  • TypeScript Module
  • NodeJS MongoDB collection
  • insertMany
  • insertOne
useUpdateLink
  • TypeScript Function
  • TypeScript Method
  • TypeScript Module
  • NodeJS MongoDB collection
  • findOneAndUpdate
  • replaceOne
  • updateMany
  • updateOne
  • rename
useDeleteLink
  • TypeScript Function
  • TypeScript Method
  • TypeScript Module
  • NodeJS MongoDB collection
  • deleteMany
  • deleteOne
  • findOneAndDelete
useSelectLink
  • TypeScript Function
  • TypeScript Method
  • TypeScript Module
  • NodeJS MongoDB collection
  • aggregate
  • count
  • group
  • collectionIndexInformation
  • initializeOrderedBulkOp
  • initializeUnorderedBulkOp
  • isCapped
  • listCollectionIndexes
  • mapReduce
  • parallelCollectionScan
  • stats
  • createCollectionIndex
  • createCollectionIndexes
  • dropCollectionIndex
  • dropCollectionIndexes
  • collectionIndexes
  • collectionIndexExists
  • reIndex
  • exists
  • existsBy

TypeORM provide several ways to access and/or update a collection. One can use:

  • an entity manager: getMongoManager, getConnection().mongoManager, DataSource().manager;
  • a repository: getMongoRepository, getConnection().getMongoRepository, DataSource().getRepository.

The use of InjectRepository from @nestjs/typeorm is also supported.

In the following example, a ‘NodeJS MongoDB connection’ object is created.

import { DataSource } from "typeorm";

export const myDataSource = new DataSource({
    type: "mongodb",
    host: "localhost",
    port: 3306,
    username: "root",
    password: "admin",
    database: "test",
    entities: [
        "../entity_dir/*.ts"
    ],
    synchronize: true,
    logging: false
})

When a MongoDB database is used, for each entity, the extension creates a ‘NodeJS MongoDB collection’ object. A parentLink between that collection and the corresponding connection is added.

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

@Entity()
export class User {
    @PrimaryGeneratedColumn()
    id: number;
    
    @Column()
    firstName: string;
    
    @Column()
    lastName: string;
    
    @Column()
    isActive: boolean;
}

TypeORM provides several ways to access and/or update a collection. Here is an example with a repository:

import { myDataSource } from "./create_connection_datasource";
import { User } from "../entity_dir/user";

function update_user(){
    const userRepository = myDataSource.getRepository(User);
    const user = await userRepository.findOne({
      id: 1,
    })
    user.name = "fooname";
    await userRepository.save(user);
}

Both ‘useSelect’ and ‘useUpdate’ links are created between the ‘update_user’ function and the ‘User’ collection which belongs to the ‘mongodb://localhost/test’ connection:

Known limitations

The following features are not supported

  • use of ormconfigs.yml, ormconfigs.env and ormconfigs.xm ORM configuration files
  • custom repositories
  • view entities
  • entity listeners and subscribers
  • connectionManager