How to Seed Your Database using TypeORM Seeding
Seeding your database is an essential step in the application development process. It not only facilitates prototyping but also streamlines the transition to a production environment. Whether you're in the early stages of ideation or have a fully-fledged application, database seeding can be a game-changer. In this tutorial, we'll walk you through how to seed your database using TypeORM and TypeORM Seeding, focusing on creating random data and establishing relationships.
Setting Up the Project
Setting up your project is a crucial initial step when you embark on a journey to seed your database using TypeORM Seeding. Properly configuring your project environment ensures a smooth and efficient database seeding process. In this section, we will delve deeper into setting up your project, covering essential aspects like project structure, dependencies, and configurations.
Project Structure
A well-organized project structure is essential for efficient development and maintenance. To set up your project for TypeORM Seeding, consider a structure like this:
my-project/
|-- src/
| |-- db/
| | |-- entities/
| | | |-- user.ts
| | | |-- post.ts
| | |-- seeding/
| | | |-- factories/
| | | | |-- user.factory.ts
| | | | |-- post.factory.ts
| | | |-- seeds/
| | | | |-- initialSeed.ts
| | |-- dev.db
| |-- seed.ts
|-- tsconfig.json
|-- package.json
my-project/
|-- src/
| |-- db/
| | |-- entities/
| | | |-- user.ts
| | | |-- post.ts
| | |-- seeding/
| | | |-- factories/
| | | | |-- user.factory.ts
| | | | |-- post.factory.ts
| | | |-- seeds/
| | | | |-- initialSeed.ts
| | |-- dev.db
| |-- seed.ts
|-- tsconfig.json
|-- package.json
-
src: This directory contains your application's source code. The
db
folder insidesrc
is where you define your database entities and the database seeding-related code. -
db/entities: Here, you define your TypeORM entities like
User
andPost
. These entities represent your database tables and define their properties and relationships. -
db/seeding: This is where you organize your database seeding code.
-
factories: In the
factories
directory, you define factories for generating random data for your entities. For each entity, create a corresponding factory file. -
seeds: The
seeds
directory is where you define the seeders responsible for populating your database with data.
-
-
package.json: The package.json file is where you manage your project's dependencies and scripts.
Installing Dependencies
To start setting up your project, you need to install the necessary dependencies. As mentioned earlier, you will require two crucial packages: typeorm-seeding
and faker
. Here's how to install them:
npm i typeorm-extension @faker-js/faker typeorm reflect-metadata sqlite
npm i typeorm-extension @faker-js/faker typeorm reflect-metadata sqlite
Configuring Your Project
After setting up the directory structure and installing the required dependencies, it's crucial to configure your project properly. Key configuration steps include:
-
Defining your entities in the
db/entities
directory. -
Creating factories for your entities in the
db/seeding/factories
directory. -
Defining seeders in the
db/seeding/seeds
directory. -
Creating a script in your
package.json
to execute the database seeding process.
With these project setup steps, you're well on your way to efficiently seeding your database using TypeORM Seeding. A well-structured project and the right dependencies are the foundation for creating a robust and testable database seeding process, ultimately leading to a more robust and production-ready application.
Understanding Factories
Before we dive into seeding, let's understand the concept of factories. Factories are essential for generating data to populate your application. For each entity in your application, you define a factory. Each factory is responsible for generating data corresponding to the properties of the entity.
For instance, if you have the following entities:
// @/src/db/entities/user.ts
import {
Entity,
Column,
PrimaryGeneratedColumn,
OneToMany,
} from "typeorm";
import { Post } from "./post";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id?: string;
@Column()
userName?: string;
@OneToMany(() => Post, (post) => post.author)
posts?: Post[];
}
// @/src/db/entities/post.ts
import typeorm, {
Entity,
Column,
PrimaryGeneratedColumn,
ManyToOne,
} from "typeorm";
import { User } from "./user";
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id?: string;
@Column()
title!: string;
@Column()
content!: string;
@ManyToOne(() => User, (user) => user.posts)
author!: typeorm.Relation<User>;
}
// @/src/db/entities/user.ts
import {
Entity,
Column,
PrimaryGeneratedColumn,
OneToMany,
} from "typeorm";
import { Post } from "./post";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id?: string;
@Column()
userName?: string;
@OneToMany(() => Post, (post) => post.author)
posts?: Post[];
}
// @/src/db/entities/post.ts
import typeorm, {
Entity,
Column,
PrimaryGeneratedColumn,
ManyToOne,
} from "typeorm";
import { User } from "./user";
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id?: string;
@Column()
title!: string;
@Column()
content!: string;
@ManyToOne(() => User, (user) => user.posts)
author!: typeorm.Relation<User>;
}
For the User
entity, you might define a factory like this:
// @/src/db/seeding/factories/user.factory.ts
import { Faker } from "@faker-js/faker";
import { setSeederFactory } from "typeorm-extension";
import { User } from "../../entities/user";
export const UsersFactory = setSeederFactory(User, (faker: Faker) => {
const user = new User();
user.userName = faker.internet.userName();
return user;
});
// @/src/db/seeding/factories/user.factory.ts
import { Faker } from "@faker-js/faker";
import { setSeederFactory } from "typeorm-extension";
import { User } from "../../entities/user";
export const UsersFactory = setSeederFactory(User, (faker: Faker) => {
const user = new User();
user.userName = faker.internet.userName();
return user;
});
And for the Post
entity:
// @/src/db/seeding/factories/post.factory.ts
import { Faker } from "@faker-js/faker";
import { setSeederFactory } from "typeorm-extension";
import { Post } from "../../entities/post";
export const PostsFactory = setSeederFactory(Post, (faker: Faker) => {
const post = new Post();
post.title = faker.lorem.sentence();
post.content = faker.lorem.sentence();
return post;
});
// @/src/db/seeding/factories/post.factory.ts
import { Faker } from "@faker-js/faker";
import { setSeederFactory } from "typeorm-extension";
import { Post } from "../../entities/post";
export const PostsFactory = setSeederFactory(Post, (faker: Faker) => {
const post = new Post();
post.title = faker.lorem.sentence();
post.content = faker.lorem.sentence();
return post;
});
With these factories defined, you can generate random data for your entities.
Creating a Seeder
Now, let's create a seeder, which is responsible for executing the database seeding. The seeder class name should match the name of the seed class (not the filename). Here's a basic structure for a seeder:
// @/src/db/seeding/seeds/initialSeed.ts
import { DataSource } from "typeorm";
import { Seeder, SeederFactoryManager } from "typeorm-extension";
import { User } from "../../entities/user";
import { Post } from "../../entities/post";
import { faker } from '@faker-js/faker';
export class MainSeeder implements Seeder {
public async run(
dataSource: DataSource,
factoryManager: SeederFactoryManager,
): Promise<any> {
const postsRepository = dataSource.getRepository(Post);
const userFactory = factoryManager.get(User);
const postsFactory = factoryManager.get(Post);
const users = await userFactory.saveMany(10);
const posts = await Promise.all(
Array(17)
.fill("")
.map(async () => {
const made = await postsFactory.make({
author: faker.helpers.arrayElement(users),
});
return made;
}),
);
await postsRepository.save(posts);
}
}
// @/src/db/seeding/seeds/initialSeed.ts
import { DataSource } from "typeorm";
import { Seeder, SeederFactoryManager } from "typeorm-extension";
import { User } from "../../entities/user";
import { Post } from "../../entities/post";
import { faker } from '@faker-js/faker';
export class MainSeeder implements Seeder {
public async run(
dataSource: DataSource,
factoryManager: SeederFactoryManager,
): Promise<any> {
const postsRepository = dataSource.getRepository(Post);
const userFactory = factoryManager.get(User);
const postsFactory = factoryManager.get(Post);
const users = await userFactory.saveMany(10);
const posts = await Promise.all(
Array(17)
.fill("")
.map(async () => {
const made = await postsFactory.make({
author: faker.helpers.arrayElement(users),
});
return made;
}),
);
await postsRepository.save(posts);
}
}
Seeding the Database
Now, let's seed the database. First, create users and specify how many you want to insert:
// @/src/seed.ts
import "reflect-metadata";
import { DataSource, DataSourceOptions } from "typeorm";
import { runSeeders, SeederOptions } from "typeorm-extension";
import { User } from "./db/entities/user";
import { Post } from "./db/entities/post";
import { UsersFactory } from "./db/seeding/factories/user.factory";
import { PostsFactory } from "./db/seeding/factories/post.factory";
import { MainSeeder } from "./db/seeding/seeds/initialSeed";
const options: DataSourceOptions & SeederOptions = {
type: "sqlite", // Use SQLite instead of MySQL
database: "src/db/dev.db", // SQLite database file path
entities: [User, Post],
// Additional config options brought by typeorm-extension
factories: [UsersFactory, PostsFactory],
seeds: [MainSeeder],
};
const dataSource = new DataSource(options);
dataSource.initialize().then(async () => {
await dataSource.synchronize(true);
await runSeeders(dataSource);
process.exit();
});
// @/src/seed.ts
import "reflect-metadata";
import { DataSource, DataSourceOptions } from "typeorm";
import { runSeeders, SeederOptions } from "typeorm-extension";
import { User } from "./db/entities/user";
import { Post } from "./db/entities/post";
import { UsersFactory } from "./db/seeding/factories/user.factory";
import { PostsFactory } from "./db/seeding/factories/post.factory";
import { MainSeeder } from "./db/seeding/seeds/initialSeed";
const options: DataSourceOptions & SeederOptions = {
type: "sqlite", // Use SQLite instead of MySQL
database: "src/db/dev.db", // SQLite database file path
entities: [User, Post],
// Additional config options brought by typeorm-extension
factories: [UsersFactory, PostsFactory],
seeds: [MainSeeder],
};
const dataSource = new DataSource(options);
dataSource.initialize().then(async () => {
await dataSource.synchronize(true);
await runSeeders(dataSource);
process.exit();
});
Seeding Your Database
Finally, add a script to your package.json
to run the seeding process:
{
"scripts": {
"seed": "ts-node src/seeds.ts"
}
}
{
"scripts": {
"seed": "ts-node src/seeds.ts"
}
}
Make sure your API is running, and execute the following command to seed your database:
npm run seed
npm run seed
For a working example of how to seed your database using TypeORM Seeding, you can refer to this GitHub repository. The repository provides a practical implementation of the concepts discussed in this article.
And that's it! Your database is now populated with random data. This is a powerful way to test your application and ensure it's ready for production. Happy coding!
About Testingfly
Testingfly is my spot for sharing insights and experiences, with a primary focus on tools and technologies related to test automation and governance.
Comments
Want to give your thoughts or chat about more ideas? Feel free to leave a comment here.
Instead of authenticating the giscus application, you can also comment directly on GitHub.
Related Articles
Testing iFrames using Playwright
Automated testing has become an integral part of web application development. However, testing in Safari, Apple's web browser, presents unique challenges due to the browser's strict Same-Origin Policy (SOP), especially when dealing with iframes. In this article, we'll explore known issues related to Safari's SOP, discuss workarounds, and demonstrate how Playwright, a popular automation testing framework, supports automated testing in this context.
Overview of SiteCore for Beginners
Sitecore is a digital experience platform that combines content management, marketing automation, and eCommerce. It's an enterprise-level content management system (CMS) built on ASP.NET. Sitecore allows businesses to create, manage, and publish content across all channels using simple tools.