UNPKG

@dataql/firebase-adapter

Version:

Firebase adapter for DataQL with zero API changes

293 lines 9.77 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.initializeApp = initializeApp; exports.getFirestore = getFirestore; const core_1 = require("@dataql/core"); // Implementation classes class DataQLDocumentSnapshot { constructor(id, _data, exists) { this.id = id; this._data = _data; this.exists = exists; } data() { return this._data || undefined; } get(field) { return this._data && typeof this._data === "object" ? this._data[field] : undefined; } } class DataQLQueryDocumentSnapshot { constructor(id, _data) { this.id = id; this._data = _data; } data() { return this._data; } get(field) { return typeof this._data === "object" ? this._data[field] : undefined; } } class DataQLQuerySnapshot { constructor(documents) { this.docs = documents.map((doc) => new DataQLQueryDocumentSnapshot(doc.id, doc.data)); this.empty = documents.length === 0; this.size = documents.length; } forEach(callback) { this.docs.forEach(callback); } } class DataQLDocumentReference { constructor(id, path, _data, _collectionName) { this.id = id; this.path = path; this._data = _data; this._collectionName = _collectionName; } get _collection() { return this._data.collection(this._collectionName, this._getDefaultSchema()); } _getDefaultSchema() { return { id: { type: "ID", required: true }, createdAt: { type: "Date", default: "now" }, updatedAt: { type: "Date", default: "now" }, }; } async get() { try { const results = await this._collection.find({ id: this.id }); const result = results[0] || null; return new DataQLDocumentSnapshot(this.id, result, !!result); } catch (error) { return new DataQLDocumentSnapshot(this.id, null, false); } } async set(data, options) { try { if (options?.merge) { await this._collection.upsert({ id: this.id, ...data }); } else { await this._collection.create({ id: this.id, ...data }); } return { writeTime: new Date().toISOString() }; } catch (error) { throw new Error(`Failed to set document: ${error instanceof Error ? error.message : "Unknown error"}`); } } async update(data) { try { await this._collection.update({ id: this.id }, data); return { writeTime: new Date().toISOString() }; } catch (error) { throw new Error(`Failed to update document: ${error instanceof Error ? error.message : "Unknown error"}`); } } async delete() { try { await this._collection.delete({ id: this.id }); return { writeTime: new Date().toISOString() }; } catch (error) { throw new Error(`Failed to delete document: ${error instanceof Error ? error.message : "Unknown error"}`); } } onSnapshot(onNext, onError) { console.log(`Subscribed to document ${this.path}`); return () => { console.log(`Unsubscribed from document ${this.path}`); }; } } class DataQLQuery { constructor(_data, _collectionName) { this._data = _data; this._collectionName = _collectionName; this._filters = []; } get _collection() { return this._data.collection(this._collectionName, this._getDefaultSchema()); } _getDefaultSchema() { return { id: { type: "ID", required: true }, createdAt: { type: "Date", default: "now" }, updatedAt: { type: "Date", default: "now" }, }; } where(fieldPath, opStr, value) { const newQuery = new DataQLQuery(this._data, this._collectionName); newQuery._filters = [ ...this._filters, { field: fieldPath, operator: opStr, value }, ]; newQuery._orderBy = this._orderBy; newQuery._limit = this._limit; return newQuery; } orderBy(fieldPath, directionStr) { const newQuery = new DataQLQuery(this._data, this._collectionName); newQuery._filters = [...this._filters]; newQuery._orderBy = { field: fieldPath, direction: directionStr || "asc" }; newQuery._limit = this._limit; return newQuery; } limit(limit) { const newQuery = new DataQLQuery(this._data, this._collectionName); newQuery._filters = [...this._filters]; newQuery._orderBy = this._orderBy; newQuery._limit = limit; return newQuery; } _buildDataQLFilter() { const filter = {}; for (const filterItem of this._filters) { const { field, operator, value } = filterItem; switch (operator) { case "==": filter[field] = value; break; case "!=": filter[field] = { $ne: value }; break; case "<": filter[field] = { $lt: value }; break; case "<=": filter[field] = { $lte: value }; break; case ">": filter[field] = { $gt: value }; break; case ">=": filter[field] = { $gte: value }; break; case "array-contains": filter[field] = { $in: [value] }; break; case "in": filter[field] = { $in: value }; break; case "array-contains-any": filter[field] = { $in: value }; break; default: filter[field] = value; } } return filter; } _applySort(results) { if (!this._orderBy) return results; const { field, direction } = this._orderBy; return results.sort((a, b) => { const aVal = a[field]; const bVal = b[field]; let comparison = 0; if (aVal < bVal) comparison = -1; else if (aVal > bVal) comparison = 1; return direction === "desc" ? -comparison : comparison; }); } async get() { try { const filter = this._buildDataQLFilter(); let results = await this._collection.find(filter); results = this._applySort(results); if (this._limit) { results = results.slice(0, this._limit); } const documents = results.map((item) => ({ id: item.id || Math.random().toString(36).substr(2, 9), data: item, })); return new DataQLQuerySnapshot(documents); } catch (error) { throw new Error(`Query failed: ${error instanceof Error ? error.message : "Unknown error"}`); } } onSnapshot(onNext, onError) { console.log(`Subscribed to collection ${this._collectionName} query`); return () => { console.log(`Unsubscribed from collection ${this._collectionName} query`); }; } } class DataQLCollectionReference extends DataQLQuery { constructor(id, path, data) { super(data, id); this.id = id; this.path = path; } doc(documentPath) { const docId = documentPath || Math.random().toString(36).substr(2, 9); return new DataQLDocumentReference(docId, `${this.path}/${docId}`, this._data, this.id); } async add(data) { const docId = Math.random().toString(36).substr(2, 9); const docRef = this.doc(docId); await docRef.set(data); return docRef; } } class DataQLFirestore { constructor(_data) { this._data = _data; } collection(collectionPath) { return new DataQLCollectionReference(collectionPath, collectionPath, this._data); } doc(documentPath) { const pathParts = documentPath.split("/"); const collectionName = pathParts[0]; const docId = pathParts[1]; return new DataQLDocumentReference(docId, documentPath, this._data, collectionName); } } class DataQLFirebaseApp { constructor(name, options, _data) { this.name = name; this.options = options; this._data = _data; this.firestore = new DataQLFirestore(_data); } } // Main Firebase functions function initializeApp(config, options) { // Ensure proper DataQL infrastructure routing (Client → Worker → Lambda → Database) const dataqlOptions = { appToken: options?.appToken || "default", // Required for DataQL routing env: options?.env || "prod", // Routes to production infrastructure devPrefix: options?.devPrefix || "dev_", // Optional prefix for dev environments dbName: options?.dbName, // Database isolation per client customConnection: options?.customConnection, // Optional custom connection }; const data = new core_1.Data(dataqlOptions); return new DataQLFirebaseApp("default", config, data); } function getFirestore(app) { if (!app) { throw new Error("Firebase app not initialized"); } return app.firestore; } // Default export exports.default = { initializeApp, getFirestore, }; //# sourceMappingURL=index.js.map