Skip to main content

Nestjs Firestore Basic Crud

· 5 min read
Sivabharathy

Learn how to integrate Firestore with NestJS in this step-by-step guide. This example demonstrates setting up Firebase Admin SDK, creating services for CRUD operations, and exposing RESTful APIs to interact with Firestore in your NestJS application.

To integrate NestJS with Google Firestore, you will need to follow a few steps to set up and interact with Firestore within a NestJS application.

Here’s a simple example that demonstrates how to set up Firestore with NestJS, including the installation and usage of required dependencies, as well as an example service and controller to interact with Firestore.

1. Install Required Dependencies

First, you'll need to install the Firebase SDK and @nestjs/common for NestJS functionality.

npm install firebase-admin @nestjs/common @nestjs/core

Then, install the @nestjs/firebase module for easier integration with Firestore.

npm install @nestjs/firebase

If you're not using @nestjs/firebase, you can directly use firebase-admin as shown below.

2. Initialize Firebase Admin SDK

You will need to set up the Firebase Admin SDK, which requires a service account key from Firebase.

  • Go to Firebase Console, select your project.
  • Go to Project Settings > Service Accounts > Generate New Private Key.
  • This will download a .json file. You will use this file to authenticate your app.

3. Create Firebase Module

Now, let’s create a Firebase module to initialize Firestore.

firebase.module.ts

import { Module } from "@nestjs/common";
import * as admin from "firebase-admin";

@Module({
providers: [
{
provide: "FIREBASE_ADMIN",
useFactory: async () => {
const serviceAccount = require("./path-to-your-firebase-service-account-file.json");
if (!admin.apps.length) {
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
}
return admin.firestore();
},
},
],
exports: ["FIREBASE_ADMIN"],
})
export class FirebaseModule {}

In the above code, we initialize Firebase Admin SDK and export the Firestore instance (admin.firestore()) for use in other parts of the application.

4. Create Firestore Service

Now, let’s create a service that will interact with Firestore.

firestore.service.ts

import { Injectable, Inject } from "@nestjs/common";
import { Firestore } from "firebase-admin/firestore";

@Injectable()
export class FirestoreService {
constructor(@Inject("FIREBASE_ADMIN") private firestore: Firestore) {}

async addDocument(collection: string, data: any): Promise<any> {
const docRef = this.firestore.collection(collection).doc();
const doc = await docRef.set(data);
return docRef.id;
}

async getDocument(collection: string, id: string): Promise<any> {
const doc = await this.firestore.collection(collection).doc(id).get();
if (!doc.exists) {
throw new Error("Document not found");
}
return doc.data();
}

async updateDocument(
collection: string,
id: string,
data: any
): Promise<void> {
await this.firestore.collection(collection).doc(id).update(data);
}

async deleteDocument(collection: string, id: string): Promise<void> {
await this.firestore.collection(collection).doc(id).delete();
}

async getAllDocuments(collection: string): Promise<any[]> {
const snapshot = await this.firestore.collection(collection).get();
return snapshot.docs.map((doc) => doc.data());
}
}

In this service, we’re creating basic Firestore CRUD methods:

  • addDocument: Adds a document to a collection.
  • getDocument: Retrieves a document by ID.
  • updateDocument: Updates an existing document.
  • deleteDocument: Deletes a document.
  • getAllDocuments: Retrieves all documents in a collection.

5. Create Firestore Controller

We will create a controller to interact with the Firestore service and expose endpoints for performing CRUD operations.

firestore.controller.ts

import {
Controller,
Get,
Param,
Post,
Body,
Put,
Delete,
} from "@nestjs/common";
import { FirestoreService } from "./firestore.service";

@Controller("firestore")
export class FirestoreController {
constructor(private readonly firestoreService: FirestoreService) {}

@Post("add/:collection")
async addDocument(
@Param("collection") collection: string,
@Body() data: any
): Promise<any> {
return this.firestoreService.addDocument(collection, data);
}

@Get("get/:collection/:id")
async getDocument(
@Param("collection") collection: string,
@Param("id") id: string
): Promise<any> {
return this.firestoreService.getDocument(collection, id);
}

@Put("update/:collection/:id")
async updateDocument(
@Param("collection") collection: string,
@Param("id") id: string,
@Body() data: any
): Promise<void> {
return this.firestoreService.updateDocument(collection, id, data);
}

@Delete("delete/:collection/:id")
async deleteDocument(
@Param("collection") collection: string,
@Param("id") id: string
): Promise<void> {
return this.firestoreService.deleteDocument(collection, id);
}

@Get("all/:collection")
async getAllDocuments(
@Param("collection") collection: string
): Promise<any[]> {
return this.firestoreService.getAllDocuments(collection);
}
}

6. Firebase Module Registration

Make sure that the FirebaseModule is imported into your main application module and the Firestore service is provided.

app.module.ts

import { Module } from "@nestjs/common";
import { FirestoreModule } from "./firestore/firestore.module"; // Import your Firestore module
import { FirebaseModule } from "./firebase.module"; // Import Firebase module
import { FirestoreService } from "./firestore/firestore.service";
import { FirestoreController } from "./firestore/firestore.controller";

@Module({
imports: [FirebaseModule], // Register Firebase module here
controllers: [FirestoreController],
providers: [FirestoreService],
})
export class AppModule {}

7. Running the Application

Make sure you have a valid Firebase Service Account Key, and place it in the correct path as specified in the firebase.module.ts.

Run the application:

npm run start

8. Testing the Endpoints

  • POST /firestore/add/your-collection: Add a document to a Firestore collection.
  • GET /firestore/get/your-collection/your-doc-id: Get a document by its ID.
  • PUT /firestore/update/your-collection/your-doc-id: Update a document by its ID.
  • DELETE /firestore/delete/your-collection/your-doc-id: Delete a document by its ID.
  • GET /firestore/all/your-collection: Get all documents from a Firestore collection.

9. Firestore Data Example

For example, if you're adding a user document:

POST to /firestore/add/users with body:

{
"name": "John Doe",
"email": "john@example.com",
"age": 30
}

Conclusion

This is a basic example to integrate Firestore with NestJS using the Firebase Admin SDK. You can extend this by adding validation, error handling, pagination, and more as needed for your application. Firestore provides powerful real-time data handling, which can be further leveraged based on your application's needs.