Guide to Seeding Mock Data for PostgreSQL Using Prisma and Snaplet Seed
Introduction
@snaplet/seed is a highly powerful library that supports automatic mock data generation for databases based on the Prisma schema. Instead of manually writing hundreds of lines of complex insert code, @snaplet/seed automatically analyzes relations in the database to generate logical, consistent and data-integrity-assured data. Standout advantages include the ability to automatically reset the database, inherently understand foreign key constraints and support concise syntax for easily creating nested data structures.
Prerequisites
This article is used alongside Prisma in a NestJS project, I will not specifically mention how to set up Prisma anymore, you can review the previous article to have the necessary preparation before proceeding
Detail
First, install the package
yarn add -D @snaplet/seed
Then, add the following scripts to package.json
{
"scripts": {
"seed:init": "npx @snaplet/seed init prisma/seed",
"seed:sync": "npx @snaplet/seed sync",
"prisma:seed": "prisma db seed"
}
}
Below is the content of the prisma/schema.prisma file, which establishes the relationship between the Product and Category tables
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
generator nestgraphql {
provider = "prisma-nestjs-graphql"
output = "../gen/graphql"
}
model Category {
id Int @id @default(autoincrement())
name String
products Product[]
}
model Product {
id Int @id @default(autoincrement())
name String
price Float
categoryId Int
category Category @relation(fields: [categoryId], references: [id])
}
Please execute the following command to create the prisma/seed folder
yarn seed:initCreate the prisma/seed/seed.config.ts file with the !*_prisma_migrations configuration to skip Prisma system tables (which are tables generated automatically by Prisma, not our data tables)
import {SeedPrisma} from '@snaplet/seed/adapter-prisma'
import {defineConfig} from '@snaplet/seed/config'
import * as dotenv from 'dotenv'
import {PrismaService} from '../../src/service/prisma.service'
dotenv.config()
export default defineConfig({
adapter: () => {
const client = new PrismaService()
return new SeedPrisma(client)
},
select: [
'!*_prisma_migrations',
],
})
Create the prisma/seed/seed.ts file
import {createSeedClient} from '@snaplet/seed'
async function main() {
const seed = await createSeedClient()
await seed.$resetDatabase()
await seed.category(x =>
x(10, {
products: x => x({min: 2, max: 5}),
})
)
console.log('🚀 Seeding Category and Product have completed!')
process.exit(0)
}
main().catch(e => {
console.error('❌ Seeding Error:', e)
process.exit(1)
})
seed.$resetDatabase(): Cleanly reset the database before pouring new data- Mock data generation: Create 10 Category rows, each row accompanied by random Products
- Snaplet will automatically mock realistic Category names (name) and Product details (name, price).
- Each category randomly generates from 2 to 5 products belonging to that category
Because by default @snaplet/seed only supports random data in a technical format, which will not resemble real-world data, I will give you another version of the prisma/seed/seed.ts file using @faker-js/faker with support for more diverse data types
import {faker} from '@faker-js/faker'
import {createSeedClient} from '@snaplet/seed'
async function main() {
const seed = await createSeedClient()
await seed.$resetDatabase()
await seed.category(x =>
x(10, () => ({
name: faker.commerce.department(),
products: x =>
x({min: 2, max: 5}, () => ({
name: faker.commerce.productName(),
price: faker.number.int({min: 10, max: 1000}),
})),
}))
)
console.log('🚀 Seeding Category and Product have completed!')
process.exit(0)
}
main().catch(e => {
console.error('❌ Seeding Error:', e)
process.exit(1)
})
faker.commerce.department(): Use pure faker, generate a realistic department namefaker.commerce.productName(): Define the products belonging to this categoryfaker.number.int({min: 10, max: 1000}): Create an Integer from 10 to 1000
Update the prisma.config.ts file, you only need to add the migrations field and point to the seed.ts file created above
import {defineConfig, env} from '@prisma/config'
import * as dotenv from 'dotenv'
dotenv.config()
export default defineConfig({
migrations: {
seed: 'ts-node ./prisma/seed/seed.ts',
},
datasource: {
url: env('DATABASE_URL'),
},
})
After that, just execute the following 2 commands to sync between prisma and seed then create the seed data
$ yarn seed:sync
$ yarn prisma:seed
yarn run v1.22.22
$ prisma db seed
Loaded Prisma config from prisma.config.ts.
Running seed command `ts-node ./prisma/seed/seed.ts` ...
🚀 Seeding Category and Product completed!
🌱 The seed command has been executed.
✨ Done in 2.25s.
Check the results in PostgreSQL as follows
Happy coding!
Comments
Post a Comment