Firebase REST Firestore
日本語版はこちら(Japanese Version)
Firebase Firestore REST API client for Edge runtime environments like Cloudflare Workers and Vercel Edge Functions.
Features
- Works in Edge runtime environments where Firebase Admin SDK is not available
- Full CRUD operations support
- TypeScript support
- Token caching for better performance
- Simple and intuitive API
- Explicit configuration without hidden environment variable dependencies
Installation
npm install firebase-rest-firestore
Quick Start
import { createFirestoreClient } from "firebase-rest-firestore";
const firestore = createFirestoreClient({
projectId: "your-project-id",
privateKey: "your-private-key",
clientEmail: "your-client-email",
});
const newDoc = await firestore.add("collection", {
name: "Test Document",
value: 100,
});
const doc = await firestore.get("collection", newDoc.id);
await firestore.update("collection", newDoc.id, { value: 200 });
const querySnapshot = await firestore
.collection("games")
.where("score", ">", 50)
.where("active", "==", true)
.orderBy("score", "desc")
.limit(10)
.get();
const games = [];
querySnapshot.forEach(doc => {
games.push({
id: doc.id,
...doc.data(),
});
});
console.log("Games with score > 50:", games);
await firestore.delete("collection", newDoc.id);
Configuration
The FirestoreConfig
object requires the following properties:
projectId | Firebase project ID |
privateKey | Service account private key |
clientEmail | Service account client email |
API Reference
FirestoreClient
The main class for interacting with Firestore.
collection(collectionPath).add(data)
Creates a new document with an auto-generated ID in the specified collection.
Parameters:
data
: Document data to be added
Returns: A reference to the created document.
collection(collectionPath).doc(id?).set(data)
Creates or overwrites a document with the specified ID. If no ID is provided, one will be auto-generated.
Parameters:
id
(optional): Document ID
data
: Document data
Returns: A promise that resolves when the set operation is complete.
get(collectionName, documentId)
Retrieves a document by ID.
update(collectionName, documentId, data)
Updates an existing document.
delete(collectionName, documentId)
Deletes a document.
query(collectionName, options)
Queries documents in a collection with filtering, ordering, and pagination.
createFirestoreClient(config)
Creates a new FirestoreClient instance with the provided configuration.
add(collectionName, data)
Adds a new document to the specified collection.
Parameters:
collectionName
: Name of the collection
data
: Document data to be added
Returns: The added document with auto-generated ID.
Error Handling
Firebase REST Firestore throws exceptions with appropriate error messages when API requests fail. Here's an example of error handling:
try {
const game = await firestore.get("games", "non-existent-id");
if (game === null) {
console.log("Document not found");
return;
}
console.log("Fetched game:", game);
} catch (error) {
console.error("Firestore error:", error.message);
}
Common error cases:
- Authentication errors (invalid credentials)
- Network errors
- Invalid query parameters
- Firestore rate limits
Query Options Details
The query
method supports the following options for filtering, sorting, and paginating Firestore documents:
where
Specify multiple filter conditions. Each condition is an object with the following properties:
field
: The field name to filter on
op
: The comparison operator. Available values:
EQUAL
: Equal to
NOT_EQUAL
: Not equal to
LESS_THAN
: Less than
LESS_THAN_OR_EQUAL
: Less than or equal to
GREATER_THAN
: Greater than
GREATER_THAN_OR_EQUAL
: Greater than or equal to
ARRAY_CONTAINS
: Array contains
IN
: Equal to any of the specified values
ARRAY_CONTAINS_ANY
: Array contains any of the specified values
NOT_IN
: Not equal to any of the specified values
value
: The value to compare against
const games = await firestore.query("games", {
where: [
{ field: "score", op: "GREATER_THAN", value: 50 },
{ field: "active", op: "EQUAL", value: true },
],
});
orderBy
Specifies the field name to sort results by. Results are sorted in ascending order by default.
const games = await firestore.query("games", {
orderBy: "createdAt",
});
limit
Limits the maximum number of results returned.
const games = await firestore.query("games", {
limit: 10,
});
offset
Specifies the number of results to skip. Useful for pagination.
const games = await firestore.query("games", {
offset: 20,
limit: 10,
});
Example of a compound query:
const topGames = await firestore.query("games", {
where: [{ field: "active", op: "EQUAL", value: true }],
orderBy: "score",
limit: 10,
});
Edge Runtime Examples
Cloudflare Workers
import { createFirestoreClient } from "firebase-rest-firestore";
export default {
async fetch(request, env, ctx) {
const firestore = createFirestoreClient({
projectId: env.FIREBASE_PROJECT_ID,
privateKey: env.FIREBASE_PRIVATE_KEY.replace(/\\n/g, "\n"),
clientEmail: env.FIREBASE_CLIENT_EMAIL,
});
const url = new URL(request.url);
const path = url.pathname;
if (path === "/api/games" && request.method === "GET") {
try {
const games = await firestore.query("games", {
where: [{ field: "active", op: "EQUAL", value: true }],
limit: 10,
});
return new Response(JSON.stringify(games), {
headers: { "Content-Type": "application/json" },
});
} catch (error) {
return new Response(JSON.stringify({ error: error.message }), {
status: 500,
headers: { "Content-Type": "application/json" },
});
}
}
return new Response("Not found", { status: 404 });
},
};
Vercel Edge Functions
import { createFirestoreClient } from "firebase-rest-firestore";
export const config = {
runtime: "edge",
};
export default async function handler(request) {
const firestore = createFirestoreClient({
projectId: process.env.FIREBASE_PROJECT_ID,
privateKey: process.env.FIREBASE_PRIVATE_KEY.replace(/\\n/g, "\n"),
clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
});
try {
const documents = await firestore.query("posts", {
orderBy: "createdAt",
limit: 10,
});
return new Response(JSON.stringify(documents), {
headers: { "Content-Type": "application/json" },
});
} catch (error) {
return new Response(JSON.stringify({ error: error.message }), {
status: 500,
headers: { "Content-Type": "application/json" },
});
}
}
Performance Considerations
Token Caching
Firebase REST Firestore caches JWT tokens to improve performance. By default, tokens are cached for 50 minutes (actual token expiry is 1 hour). This eliminates the need to generate a new token for each request, improving API request speed.
const doc1 = await firestore.get("collection", "doc1");
const doc2 = await firestore.get("collection", "doc2");
const doc3 = await firestore.get("collection", "doc3");
Query Optimization
When dealing with large amounts of data, consider the following:
-
Set appropriate limits: Always use the limit
parameter to restrict the number of documents returned.
-
Query only needed fields: Future versions will add support for retrieving only specific fields.
-
Create indexes: For complex queries, create appropriate indexes in the Firebase console.
-
Use pagination: When retrieving large datasets, implement pagination using offset
and limit
.
Edge Environment Considerations
In edge environments, be aware of:
-
Cold starts: Initial execution has token generation overhead.
-
Memory usage: Be mindful of memory limits when processing large amounts of data.
-
Timeouts: Long-running queries may hit edge environment timeout limits.
Limitations and Roadmap
Current Limitations
- Batch operations: The current version does not support batch processing for operating on multiple documents at once.
- Transactions: Atomic transaction operations are not supported.
- Real-time listeners: Due to the nature of REST APIs, real-time data synchronization is not supported.
- Subcollections: The current version has limited direct support for nested subcollections.
Future Roadmap
The following features are planned for future versions:
- Batch operations support
- Basic transaction support
- Improved subcollection support
- More detailed query options (compound indexes, etc.)
- Performance optimizations
Please report feature requests and bugs via GitHub Issues.
License
MIT