Seeding Firestore Data in Emulator

Fresh start, every time

Tomas Radvansky
4 min readOct 6, 2023

--

In many development scenarios, it becomes essential to prepopulate Firestore collections with data for testing and development purposes. Whether you need specific collections pre-created or users with different roles and authentication claims, having a reliable method for seeding Firestore data can greatly streamline the development process. In this article, we'll explore how to accomplish this using an npm run script.

Why Seeding Firestore Data?

Firestore is a popular NoSQL database provided by Firebase, and it's commonly used for building web and mobile applications. During development, you may encounter situations where it's necessary to initialize your Firestore database with predefined data. Here are a few scenarios where seeding Firestore data becomes invaluable:

  1. Testing Environments: In a testing environment, you may want to ensure that certain collections exist with specific documents to test different aspects of your application.
  2. Simulating Production Data: To accurately mimic the production environment, you might need to create sample data that resembles what your users will encounter in the real world.
  3. Role-Based Testing: If your application has role-based access control, you may want to create users with different roles or authentication claims for testing various scenarios.
  4. Database Schema Changes: When you update your Firestore database schema, you may need to modify existing data to conform to the new structure.

To efficiently handle these scenarios, creating an npm run script for Firestore data seeding can be a game-changer. Let's walk through how to set up such a script.

Setting Up the Seeding Script

To begin, we'll create a TypeScript file called seed.ts inside the Scripts folder within your Functions directory. This file will contain the actual Firestore seeding script. Here's an outline of the file:

import * as dotenv from 'dotenv';
dotenv.config({ path: '.secret.local' });

import { getFirestore, Firestore } from 'firebase-admin/firestore';
import { getAuth, Auth } from 'firebase-admin/auth';
import { initializeApp } from 'firebase-admin/app';
import { withFunctionTriggersDisabled } from '@firebase/rules-unit-testing';

initializeApp();

// Function to seed Firestore
const seedFirestore = async (): Promise<void> => {
const auth = getAuth();
const db = getFirestore();

// Wrap your seeding logic with withFunctionTriggersDisabled
await withFunctionTriggersDisabled(async () => {
// Your seeding logic goes here
// This code block will prevent function triggers and database updates
});
};

// Invoke the seeding function
seedFirestore();

In this script, we first load environment variables using dotenv. Next, we initialize Firebase Admin SDK with initializeApp() and get references to the Firestore and Auth instances.

Inside the seedFirestore function, you should include your custom logic to seed the Firestore database with the desired data.

Preventing Trigger Execution with withFunctionTriggersDisabled

In some cases, you may want to prevent the execution of database or authentication triggers while running your Firestore seeding script. This is particularly useful when you want to ensure that your seeding process does not inadvertently trigger any functions or database updates that you’d like to exclude during seeding. To achieve this, you can utilize the withFunctionTriggersDisabled method from the @firebase/rules-unit-testing package.

By wrapping your seeding logic with withFunctionTriggersDisabled, you can ensure that any Firebase Cloud Functions triggered by Firestore or authentication events will be temporarily disabled during the execution of your seeding script. This is advantageous because it prevents any unintentional side effects or trigger executions that could occur as a result of your seeding process.

Using withFunctionTriggersDisabled helps maintain a controlled environment for seeding data, making it easier to manage and test your Firestore seeding script without interference from Firebase Cloud Functions or other triggers. This ensures that your seeding process remains predictable and focused on its intended purpose: populating Firestore with the desired data for testing and development.

Running the Seeding Script with npm

To execute this seeding script using npm, we'll define two npm run scripts in your package.json file:

{
"scripts": {
"seed": "ts-node ./scripts/seed.ts && tsc --watch",
"serve:seeded": "npm run build && firebase emulators:exec --inspect-functions --ui --only functions,firestore,auth,pubsub,storage \"npm run seed\""
}
}
  • The seed script uses ts-node to run the seed.ts file and then watches for TypeScript changes with tsc --watch. This allows you to iterate quickly during development.
  • The serve:seeded script builds your project (npm run build) and starts Firebase emulators, including Firestore and Auth. It then runs the seed script using the firebase emulators:exec command.

Now, you can execute the seeding process by running the following command:

npm run serve:seeded

This command will start the desired emulators, seed the data into Firestore, and monitor for TypeScript changes, ensuring that your development environment is ready for testing and debugging.

By following this approach, you can efficiently seed Firestore data and accelerate the development and testing of your Firebase-powered applications. This process is particularly beneficial when working on complex applications with specific data requirements or role-based access control.

References

Firebase Firestore Documentation:

  • Firestore is Firebase’s NoSQL cloud database, and it’s essential for understanding how to interact with Firestore collections and documents.
  • Firebase Firestore Documentation

Firebase Admin SDK Documentation:

dotenv Package Documentation:

@firebase/rules-unit-testing Package Documentation:

Firebase Cloud Functions Documentation:

npm (Node Package Manager) Documentation:

  • Learn more about npm and how to manage packages for your Node.js projects.
  • npm Documentation

--

--