Working with Firestore
This guide will walk you through performing CRUD (Create, Read, Update, Delete) operations in Firestore using the
@hyper-fetch/firebase-admin adapter. We'll cover the available methods and demonstrate how to use them with practical
examples.
- How to set up the Hyper-fetch client for Firestore
- How to use
getDocsto retrieve a collection - How to use
getDocto fetch a single document - How to add a new document with
addDoc - How to modify a document with
setDocandupdateDoc - How to remove a document with
deleteDoc
Setup
First, let's set up our Hyper-fetch client to work with Firestore. We'll need to initialize the Firebase Admin SDK and pass the Firestore instance to our adapter.
import { createClient } from "@hyper-fetch/core";
import { firebaseAdminAdapter } from "@hyper-fetch/firebase-admin";
import * as admin from "firebase-admin";
// 1. Initialize Firebase Admin
// Make sure to replace with your actual service account key and database URL
const serviceAccount = require("./path/to/your/serviceAccountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://your-project-id.firebaseio.com",
});
const db = admin.firestore();
// 2. Define the data structure for our examples
interface Tea {
name: string;
origin: string;
type: "Green" | "Black" | "Oolong" | "Herbal";
year: number;
amount: number;
__key?: string; // This will be automatically added by Hyper-fetch
}
// 3. Create a Hyper-fetch client
// We set a base endpoint of 'teas' which corresponds to a Firestore collection
const client = createClient({
url: "teas/",
}).setAdapter(() => firebaseAdminAdapter(db));
Available Methods
The Firestore adapter maps familiar Firestore SDK methods to Hyper-fetch requests. This allows you to interact with your database using a consistent, declarative syntax.
The available methods are:
getDocsgetDocsetDocupdateDocaddDocdeleteDoc
const request = client.createRequest<{ response Tea[] }>()({
endpoint: "",
method: "getDocs", // "addDoc" | "getDoc" | "getDocs" | "setDoc" | "updateDoc" | "deleteDoc"
});
Due to its nature, we've solved the realtime listening a bit differently, and thus - this method is not allowed in a
standard adapter. For the onSnapshot-like usage, please check how to
listen to queries.
Usage Examples
Let's walk through a complete CRUD cycle to see how these methods work together.
1. addDoc
To start, we'll add a new tea to our teas collection. The addDoc method creates a new document with an
auto-generated ID.
const newData: Omit<Tea, "__key"> = {
name: "Pai Mu Tan",
origin: "China",
type: "Green",
year: 2023,
amount: 50,
};
const addDocReq = client.createRequest<{ response: Tea; payload: typeof newData }>()({
endpoint: "",
method: "addDoc",
});
const { data: addedTea, error: addError } = await addDocReq.setData(newData).send();
if (addedTea) {
console.log("Added tea:", addedTea);
// The response data includes the original data plus the new document ID in the `__key` field.
// { name: 'Pai Mu Tan', ..., __key: 'Abc123xyz' }
}
When using addDoc, the response data is the same as the data you sent, but with the addition of a __key field
containing the newly created document's ID.
2. getDoc
Now, let's fetch the tea we just created using its ID. The :teaId in the endpoint is a dynamic parameter that we'll
fill in using setParams.
const getDocReq = client.createRequest<{ response Tea }>()({
endpoint: ":teaId",
method: "getDoc",
});
// We use the `__key` from the previous step to fetch the document
const { data, extra } = await getDocReq.setParams({ teaId: addedTea.__key }).send();
console.log("Fetched tea:", data);
extra response
ref: The FirestoreDocumentReference.snapshot: The raw FirestoreDocumentSnapshot.
3. getDocs
To fetch all the teas in our collection, we use getDocs. This method returns an array of documents.
const getDocsReq = client.createRequest<{ response Tea[] }>()({
endpoint: "",
method: "getDocs",
});
const { data: allTeas, extra: getDocsExtra } = await getDocsReq.send();
// data is an array of objects, where each object also contains the `__key` property.
console.log("All teas:", allTeas);
extra response
ref: The FirestoreCollectionReference.snapshot: The raw FirestoreQuerySnapshot.
4. setDoc
The setDoc method allows you to overwrite a document. If the document doesn't exist, it will be created.
const updatedData = {
name: "Pai Mu Tan (Organic)",
origin: "China",
type: "Green",
year: 2024,
amount: 100,
};
const setDocReq = client.createRequest<Tea, typeof updatedData>()({
endpoint: ":teaId",
method: "setDoc",
// You can also pass { merge: true } to merge fields instead of overwriting
});
const { data: setResponse } = await setDocReq.setParams({ teaId: addedTea.__key }).setData(updatedData).send();
// The response from setDoc is the same data that was sent.
console.log("Set response:", setResponse);
5. updateDoc
If you only want to update specific fields in a document without overwriting the entire document, use updateDoc.
const partialUpdate = {
amount: 95,
year: 2025,
};
const updateDocReq = client.createRequest<Tea, typeof partialUpdate>()({
endpoint: ":teaId",
method: "updateDoc",
});
const { data: updateResponse } = await updateDocReq.setParams({ teaId: addedTea.__key }).setData(partialUpdate).send();
// The response from updateDoc is the same data that was sent for the update.
console.log("Update response:", updateResponse);
6. deleteDoc
Finally, let's remove the tea from our collection using deleteDoc.
const deleteDocReq = client.createRequest()({
endpoint: ":teaId",
method: "deleteDoc",
});
const { data: deleteResponse } = await deleteDocReq.setParams({ teaId: addedTea.__key }).send();
// The response from deleteDoc is always `null`.
console.log("Delete response:", deleteResponse);
