@dataql/firebase-adapter
Version:
Firebase adapter for DataQL with zero API changes
354 lines (293 loc) โข 9.76 kB
text/typescript
import { initializeApp, getFirestore } from "@dataql/firebase-adapter";
// Firebase configuration
const firebaseConfig = {
apiKey: "your-api-key",
authDomain: "your-project.firebaseapp.com",
projectId: "your-project",
storageBucket: "your-project.appspot.com",
messagingSenderId: "123456789",
appId: "1:123456789:web:abcdef123456",
};
// Initialize Firebase app with DataQL backend
const app = initializeApp(firebaseConfig, {
// DataQL automatically handles routing
appToken: "your-app-token",
env: "dev",
});
// Get Firestore instance
const db = getFirestore(app);
async function basicOperations() {
console.log("๐ Starting Firebase adapter example...");
try {
// Add a document to a collection
console.log("\n๐ Creating a new user...");
const usersRef = db.collection("users");
const newUserRef = await usersRef.add({
name: "John Doe",
email: "john@example.com",
age: 30,
active: true,
tags: ["developer", "javascript"],
profile: {
bio: "Software developer",
avatar: "https://example.com/avatar.jpg",
},
});
console.log("โ
User created with ID:", newUserRef.id);
// Get a document by ID
console.log("\n๐ Getting user by ID...");
const userDoc = await newUserRef.get();
if (userDoc.exists) {
console.log("โ
User found:", userDoc.data());
} else {
console.log("โ User not found");
}
// Query documents with filters
console.log("\n๐ Querying active users...");
const activeUsersSnapshot = await usersRef
.where("active", "==", true)
.where("age", ">=", 18)
.orderBy("name")
.limit(10)
.get();
console.log(`โ
Found ${activeUsersSnapshot.size} active users:`);
activeUsersSnapshot.forEach((doc) => {
console.log(` - ${doc.id}: ${doc.get("name")} (${doc.get("email")})`);
});
// Update a document
console.log("\nโ๏ธ Updating user...");
await newUserRef.update({
name: "John Smith",
age: 31,
lastUpdated: new Date(),
});
console.log("โ
User updated successfully");
// Set document with merge
console.log("\n๐ Merging user data...");
await newUserRef.set(
{
preferences: {
theme: "dark",
notifications: true,
},
lastLogin: new Date(),
},
{ merge: true }
);
console.log("โ
User data merged successfully");
// Query with array operations
console.log("\n๐ Querying users by tags...");
const developersSnapshot = await usersRef
.where("tags", "array-contains", "developer")
.get();
console.log(`โ
Found ${developersSnapshot.size} developers:`);
developersSnapshot.forEach((doc) => {
const userData = doc.data();
console.log(
` - ${doc.id}: ${userData.name} (tags: ${userData.tags?.join(", ")})`
);
});
// Query with multiple array values
console.log("\n๐ Querying users by multiple tags...");
const techUsersSnapshot = await usersRef
.where("tags", "array-contains-any", ["developer", "designer", "manager"])
.get();
console.log(`โ
Found ${techUsersSnapshot.size} tech users`);
// Range queries
console.log("\n๐ Range query on age...");
const youngUsersSnapshot = await usersRef
.where("age", ">=", 20)
.where("age", "<=", 40)
.orderBy("age", "asc")
.get();
console.log(`โ
Found ${youngUsersSnapshot.size} users aged 20-40`);
console.log("\n๐ All operations completed successfully!");
} catch (error) {
console.error("โ Error:", error);
}
}
async function realtimeExample() {
console.log("\n๐ก Setting up real-time subscriptions...");
const usersRef = db.collection("users");
const messagesRef = db.collection("messages");
// Listen to users collection
const unsubscribeUsers = usersRef.onSnapshot((snapshot) => {
console.log("๐ฑ Users collection updated:");
snapshot.forEach((doc) => {
const userData = doc.data();
console.log(` - User ${doc.id}: ${userData.name}`);
});
});
// Listen to a specific document
const specificUserRef = usersRef.doc("user123");
const unsubscribeUser = specificUserRef.onSnapshot((doc) => {
if (doc.exists) {
console.log("๐ค Specific user updated:", doc.data());
} else {
console.log("๐ค Specific user does not exist");
}
});
console.log("โ
Real-time listeners active");
// Simulate some changes
setTimeout(async () => {
console.log("\n๐ฌ Simulating real-time events...");
// Add a new user
await usersRef.add({
name: "Jane Doe",
email: "jane@example.com",
active: true,
});
// Add a message
await messagesRef.add({
text: "Hello from Firebase adapter!",
userId: "user123",
timestamp: new Date(),
});
// Update specific user
await specificUserRef.set({
name: "Updated User",
email: "updated@example.com",
lastUpdated: new Date(),
});
}, 2000);
// Cleanup after 10 seconds
setTimeout(() => {
console.log("\n๐งน Cleaning up subscriptions...");
unsubscribeUsers();
unsubscribeUser();
console.log("โ
Subscriptions cleaned up");
}, 10000);
}
async function advancedQueriesExample() {
console.log("\n๐ Advanced queries example...");
try {
const postsRef = db.collection("posts");
const productsRef = db.collection("products");
// Complex compound query
console.log("\n๐ฏ Complex compound query...");
const complexSnapshot = await postsRef
.where("published", "==", true)
.where("category", "in", ["tech", "science", "programming"])
.where("likes", ">=", 10)
.orderBy("publishedAt", "desc")
.limit(5)
.get();
console.log(`โ
Found ${complexSnapshot.size} popular published posts`);
// Inequality queries
console.log("\n๐ Inequality queries...");
const recentPostsSnapshot = await postsRef
.where("publishedAt", ">=", "2024-01-01")
.where("views", "!=", 0)
.orderBy("views", "desc")
.get();
console.log(`โ
Found ${recentPostsSnapshot.size} recent posts with views`);
// Array queries
console.log("\n๐ Array queries...");
const taggedProductsSnapshot = await productsRef
.where("tags", "array-contains", "featured")
.where("inStock", "==", true)
.get();
console.log(
`โ
Found ${taggedProductsSnapshot.size} featured products in stock`
);
// Multiple array queries
console.log("\n๐ท๏ธ Multiple array queries...");
const categoryProductsSnapshot = await productsRef
.where("categories", "array-contains-any", [
"electronics",
"computers",
"phones",
])
.where("price", "<=", 1000)
.get();
console.log(
`โ
Found ${categoryProductsSnapshot.size} affordable tech products`
);
} catch (error) {
console.error("โ Advanced queries error:", error);
}
}
async function documentOperationsExample() {
console.log("\n๐ Document operations example...");
try {
const userRef = db.collection("users").doc("detailed-user-example");
// Create document with set
console.log("\n๐ Creating document with set...");
await userRef.set({
name: "Alice Johnson",
email: "alice@example.com",
role: "admin",
profile: {
bio: "System administrator",
avatar: "https://example.com/alice.jpg",
social: {
twitter: "@alice",
github: "alice-dev",
},
},
permissions: ["read", "write", "admin"],
preferences: {
theme: "light",
language: "en",
notifications: true,
},
createdAt: new Date(),
});
console.log("โ
Document created");
// Update specific fields
console.log("\nโ๏ธ Updating specific fields...");
await userRef.update({
"profile.bio": "Senior system administrator",
"preferences.theme": "dark",
lastUpdated: new Date(),
});
console.log("โ
Document updated");
// Merge new data
console.log("\n๐ Merging new data...");
await userRef.set(
{
settings: {
twoFactorAuth: true,
sessionTimeout: 3600,
},
lastLogin: new Date(),
},
{ merge: true }
);
console.log("โ
Data merged");
// Get and display document
console.log("\n๐ Getting complete document...");
const doc = await userRef.get();
if (doc.exists) {
const userData = doc.data();
console.log("โ
Complete user data:", JSON.stringify(userData, null, 2));
// Access nested fields
console.log("๐ง Email:", doc.get("email"));
console.log("๐จ Theme:", doc.get("preferences.theme"));
console.log("๐ GitHub:", doc.get("profile.social.github"));
}
// Delete document
console.log("\n๐๏ธ Deleting document...");
await userRef.delete();
console.log("โ
Document deleted");
// Verify deletion
const deletedDoc = await userRef.get();
console.log("๐ Document exists after deletion:", deletedDoc.exists);
} catch (error) {
console.error("โ Document operations error:", error);
}
}
async function runExample() {
console.log("๐ฏ DataQL Firebase Adapter Example");
console.log("===================================");
await basicOperations();
await realtimeExample();
await advancedQueriesExample();
await documentOperationsExample();
console.log("\nโ
Example completed!");
}
// Run the example
if (require.main === module) {
runExample().catch(console.error);
}
export { runExample };