How to Seed Database using TypeORM Seeding

Francisco Mendes - Jan 16 '22 - - Dev Community

Overview

One of the things that, in addition to being immensely convenient during the prototyping of an application, can also be favorable to us during the production environment. That is, it helps us from the ideation process and application creation to the production environment.

As you may have noticed by the title of the article, or I decided to create a simple article in which we use one of the most popular ORM's and we are going to seed our database.

Database seeding can be done in different contexts, from inserting random batches so that we can test our application faster (which helps in our development experience), but we can also define an array of objects that can be data. admin accounts or simply data that needs to be used in the production environment.

In today's example I will explain how we can insert random data into our database, as well as how we will establish a relationship between them. In the end we will have an API that will have only two endpoints, one to fetch all users and their articles, the other to fetch all articles and their authors.

I also add that in this article I will not explain how to create an API using Express, TypeORM and TypeScript. I will just explain how to implement the seeding of our database in an existing API. If you want access to the github repository with the final result of this article, you can click here.

Let's code

In the root of our project (where the package.json is located) we will install the following dependencies:

npm install typeorm-seeding faker --save
npm install @types/faker --save-dev
Enter fullscreen mode Exit fullscreen mode

Now I will explain two things that I think are fundamental about the library we are going to use (typeorm-seeding).

The first thing I will talk about is Factories, basically for each entity we have in our application we will define a factory and this will be responsible for generating the data that will populate our application. Each of these data corresponds to the properties that we have defined in our entity.

So let's assume that these are your entities:

// @/src/db/entities/user.ts
import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  OneToMany,
  BaseEntity,
} from "typeorm";
import { Post } from "./post";

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

  @Column()
  name!: string;

  @OneToMany(() => Post, (post) => post.user)
  posts?: Post[];
}
Enter fullscreen mode Exit fullscreen mode
// @/src/db/entities/post.ts
import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  ManyToOne,
  BaseEntity,
} from "typeorm";
import { User } from "./user";

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

  @Column()
  title!: string;

  @Column()
  description!: string;

  @Column({ type: "boolean", default: false })
  isPublished!: boolean;

  @ManyToOne(() => User, (user) => user.posts)
  user!: User;
}
Enter fullscreen mode Exit fullscreen mode

In the case of the user entity, we will need to generate only the username, which would correspond to this factory:

// @/src/db/seeding/factories/user.factory.ts
import * as Faker from "faker";
import { define } from "typeorm-seeding";

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

define(User, (faker: typeof Faker) => {
  const user = new User();
  const firstName = faker.name.firstName();
  const lastName = faker.name.lastName();
  user.name = `${firstName} ${lastName}`;
  return user;
});
Enter fullscreen mode Exit fullscreen mode

And in the case of the post, it would be like this:

// @/src/db/seeding/factories/post.factory.ts
import * as Faker from "faker";
import { define } from "typeorm-seeding";

import { Post } from "../../entities";

define(Post, (faker: typeof Faker) => {
  const post = new Post();
  post.title = faker.lorem.words(8);
  post.description = faker.lorem.paragraph(6);
  post.isPublished = faker.random.boolean();
  return post;
});
Enter fullscreen mode Exit fullscreen mode

Now with our factories defined, as soon as we define how many users or articles we want to create, the factory will always generate random values in each of the properties.

Now we can move to the Seeder, the seeder is a class that is used to execute the seeding of our database and here I want you to be careful with the name, because the name of the seed corresponds to the name of the class (and not of the file ).

The boilerplate of a Seeder is as follows:

// @/src/db/seeding/seeds/initialSeed.ts
import { Factory, Seeder } from "typeorm-seeding";
import { Connection } from "typeorm";

// ...

export default class InitialDatabaseSeed implements Seeder {
  public async run(factory: Factory, connection: Connection): Promise<void> {
    // ...
  }
}
Enter fullscreen mode Exit fullscreen mode

What we need to do first is import our entities, which we are going to seed.

// @/src/db/seeding/seeds/initialSeed.ts
import { Factory, Seeder } from "typeorm-seeding";
import { Connection } from "typeorm";

import { User, Post } from "../../entities";

export default class InitialDatabaseSeed implements Seeder {
  public async run(factory: Factory, connection: Connection): Promise<void> {
    // ...
  }
}
Enter fullscreen mode Exit fullscreen mode

Now let's seed the users table first and define that we want to insert 15 users in the table in total.

// @/src/db/seeding/seeds/initialSeed.ts
import { Factory, Seeder } from "typeorm-seeding";
import { Connection } from "typeorm";

import { User, Post } from "../../entities";

export default class InitialDatabaseSeed implements Seeder {
  public async run(factory: Factory, connection: Connection): Promise<void> {
    const users = await factory(User)().createMany(15);

    // ...
  }
}
Enter fullscreen mode Exit fullscreen mode

With the users created, we are now going to generate the articles, but this time, in addition to defining the number of articles we want to generate, we will also pass the user who must be the author of the article. In this case we have to assign it in a random way. Like this:

// @/src/db/seeding/seeds/initialSeed.ts
import { Factory, Seeder } from "typeorm-seeding";
import { Connection } from "typeorm";

import { User, Post } from "../../entities";

export default class InitialDatabaseSeed implements Seeder {
  public async run(factory: Factory, connection: Connection): Promise<void> {
    const users = await factory(User)().createMany(15);

    await factory(Post)()
      .map(async (post) => {
        post.user = users[Math.floor(Math.random() * users.length)];
        return post;
      })
      .createMany(100);
  }
}
Enter fullscreen mode Exit fullscreen mode

With our factories defined and our seeder created, the next step is to define the directories where our factories and our seeders are in our TypeORM configuration.

// @/ormconfig.ts
import { User, Post } from "./src/db/entities";

export default {
  name: "default",
  type: "sqlite",
  database: "src/db/dev.db",
  entities: [User, Post],
  synchronize: true,
  logging: false,
  // These two lines have been added:
  seeds: ["src/db/seeding/seeds/**/*{.ts,.js}"],
  factories: ["src/db/seeding/factories/**/*{.ts,.js}"],
};
Enter fullscreen mode Exit fullscreen mode

Finally, just go to our package.json and create the script that will be responsible for seeding our database.

// @/package.json
{
  // ...
  "scripts": {
    // ...
    "db:seed": "ts-node ./node_modules/typeorm-seeding/dist/cli.js seed"
  },
  // ...
}
Enter fullscreen mode Exit fullscreen mode

Don't forget to have your API process running and run the command npm run db:seed to seed your database.

Conclusion

As always, I hope you found it interesting. If you noticed any errors in this article, please mention them in the comments. 🧑🏻‍💻

Hope you have a great day! 👋 🌱

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player