Take your database seeding to the next level with Faker.js

Database seeding is term used to describe the initial data population of database. the data is either a dummy data for testing or some initial necessary data.

We will use knex.js for our migrations and seeding. you can use any other library or method you want.

First let's instantiate Knex config file via Knex cli:
npx knex init

and then setup your Knex configuration in knexfile.js/ts

Now We will create user and post migrations via:
npx knex migrate:make users
npx knex migrate:make posts

A migrations files will be created in migrations folder(or your configured migrations folder).

Then set up your tables in the migration files. the final result will be something like:

//xxxxxxxxxxxx_users.js

/** @param {import("knex").Knex} knex */
exports.up = function(knex) {
    return knex.schema.createTable("user", (table) => {
        table.uuid("id").primary().defaultTo(knex.raw("gen_random_uuid()")); // gen_random_uuid is postgres only
        table.string("username").unique().notNullable();
        table.string("email").notNullable();
        table.string("password").notNullable();
        table.string("full_name").notNullable();
        table.string("avatar");
        table.timestamps(true, true); // created_at, updated_at
    });
};

/** @param {import("knex").Knex} knex */
exports.down = function(knex) {
    return knex.schema.dropTable("users");
};
//xxxxxxxxxxxx_posts.js

/** @param {import("knex").Knex} knex */
exports.up = function(knex) {
    return knex.schema.createTable("posts", (table) => {
        table.uuid("id").primary().defaultTo(knex.raw("gen_random_uuid()"));
        table.uuid("author").notNullable().references("users.id");
        table.text("title").notNullable();
        table.text("content").notNullable();
        table.integer("likes").notNullable().defaultTo(0);
        table.timestamps(true, true); // created_at, updated_at
    });
};

/** @param {import("knex").Knex} knex */
exports.down = function(knex) {
    return knex.schema.dropTable("posts");
};

Then run npx knex migrate:latest to run your migrations

After we setup the tables. We're ready for seeding. to create seeding file, run:
knex seed:make users
knex seed:make posts

This will create seeding files in seeding folder. each file has exported seed function. we will use that function generate the seeding data

Let's first create a function to generate our user object. so we can get an idea of user entry before inserting them to the databse:

we will use faker.helpers.contextualCard. this function will generate some random user related info like username, full name, email, or even avatars!. the output of the function looks like:

{
  "name": "Samanta",
  "username": "Samanta22",
  "avatar": "https://cdn.fakercloud.com/avatars/solid_color_128.jpg",
  "email": "[email protected]",
  "dob": "1970-04-17T02:17:28.907Z",
  "phone": "350-910-3872 x539",
  "address": {
    "street": "Hudson Loaf",
    "suite": "Suite 371",
    "city": "Elodyborough",
    "zipcode": "12496-9242",
    "geo": {
      "lat": "74.0449",
      "lng": "-53.5555"
    }
  },
  "website": "chance.org",
  "company": {
    "name": "West - Gislason",
    "catchPhrase": "Managed tertiary utilisation",
    "bs": "exploit dynamic blockchains"
  }
}

we don't need all of that. so we will take in what we defined in the users table:

function generateRandomUser() {
    const user = faker.helpers.contextualCard();
    return {
        username: user.username,
        // password is required. so we need to throw any value to avoid errors.
        // in real world scenario we will hash the password 
        password: "1234",
        email: user.email,
        full_name: user.name,
        avatar: user.avatar,
    };
}

Now we will use this function to generate multiples fake users:

const USER_COUNT = 10;
const TABLE_NAME = "users"

/** @param {import("knex").Knex} knex */
exports.seed = async function (knex) {
    // Deletes ALL existing entries
    await knex(TABLE_NAME).del();

    // Inserts seed entries
    return knex(TABLE_NAME).insert(
        Array.from({ length: USER_COUNT }, () => {
            return generateUser();
        })
    );
};

Now our users seeding is ready. but before run the seeding. we need to define some random user posts. so we will use the same approach:

const faker = require("faker");

const TABLE_NAME = "posts";


function randomArray(arr) {
    return arr[
        // We could use Math.random. but this function give us more less predicted numbers
        faker.datatype.number({
            max: Math.max(0, arr.length - 1)
        })
    ];
}

function generateRandomPosts(author) {
    return {
        author, // author id
        title: faker.lorem.sentence(), // random sentence.
        content: faker.lorem.paragraph(), // random paragraph
        likes: faker.datatype.number(1e6) // random likes count between 0 to 1m
    };
}

const POST_COUNT = 1000; // specify your generated posts count

/** @param {import("knex").Knex} knex */
exports.seed = async function(knex) {

    // delete all previous rows
    await knex(TABLE_NAME).del();

    // select some users from database. so we can create random posts from random users
    const users = await knex.table("users").select().limit(50);
    if (!users || !users.length) throw Error("Cannot find users");

    const posts = Array.from({length: POST_COUNT}, async () => {
        const user = randomArray(users); // to link the post to a random user
        return generateRandomPosts(user.id);
    });

    return knex(TABLE_NAME).insert(posts); // now insert the generated data 🎉🥳
};

Finally. after you finish setting up your seeding data you can run all seeding via one command:
npx knex seed:run

Now your database test data is ready. your front-end dev will be happy😁

21