1
0
Fork 0
mirror of synced 2024-06-02 10:34:40 +12:00
budibase/packages/server/src/integrations/firebase.ts

188 lines
4.2 KiB
TypeScript

import {
DatasourceFieldType,
Integration,
QueryType,
IntegrationBase,
} from "@budibase/types"
import { Firestore, WhereFilterOp } from "@google-cloud/firestore"
interface FirebaseConfig {
email: string
privateKey: string
projectId: string
}
const SCHEMA: Integration = {
docs: "https://firebase.google.com/docs/firestore/quickstart",
friendlyName: "Firestore",
type: "Non-relational",
description:
"Cloud Firestore is a flexible, scalable database for mobile, web, and server development from Firebase and Google Cloud.",
datasource: {
email: {
type: DatasourceFieldType.STRING,
required: true,
},
privateKey: {
type: DatasourceFieldType.STRING,
required: true,
},
projectId: {
type: DatasourceFieldType.STRING,
required: true,
},
},
query: {
create: {
type: QueryType.JSON,
},
read: {
type: QueryType.JSON,
},
update: {
type: QueryType.JSON,
},
delete: {
type: QueryType.JSON,
},
},
extra: {
collection: {
displayName: "Collection",
type: DatasourceFieldType.STRING,
required: true,
},
filterField: {
displayName: "Filter field",
type: DatasourceFieldType.STRING,
required: false,
},
filter: {
displayName: "Filter comparison",
type: DatasourceFieldType.LIST,
required: false,
data: {
read: [
"==",
"<",
"<=",
"!=",
">=",
">",
"array-contains",
"in",
"not-in",
"array-contains-any",
],
},
},
filterValue: {
displayName: "Filter value",
type: DatasourceFieldType.STRING,
required: false,
},
},
}
class FirebaseIntegration implements IntegrationBase {
private config: FirebaseConfig
private client: Firestore
constructor(config: FirebaseConfig) {
this.config = config
this.client = new Firestore({
projectId: config.projectId,
credentials: {
client_email: config.email,
private_key: config.privateKey?.replace(/\\n/g, "\n"),
},
})
}
async create(query: { json: object; extra: { [key: string]: string } }) {
try {
const documentReference = this.client
.collection(query.extra.collection)
.doc()
await documentReference.set({ ...query.json, id: documentReference.id })
const snapshot = await documentReference.get()
return snapshot.data()
} catch (err) {
console.error("Error writing to Firestore", err)
throw err
}
}
async read(query: { json: object; extra: { [key: string]: string } }) {
try {
let snapshot
const collectionRef = this.client.collection(query.extra.collection)
if (
query.extra.filterField &&
query.extra.filter &&
query.extra.filterValue
) {
snapshot = await collectionRef
.where(
query.extra.filterField,
query.extra.filter as WhereFilterOp,
query.extra.filterValue
)
.get()
} else {
snapshot = await collectionRef.get()
}
const result: any[] = []
snapshot.forEach(doc => result.push(doc.data()))
return result
} catch (err) {
console.error("Error querying Firestore", err)
throw err
}
}
async update(query: {
json: Record<string, any>
extra: { [key: string]: string }
}) {
try {
await this.client
.collection(query.extra.collection)
.doc(query.json.id)
.update(query.json)
return (
await this.client
.collection(query.extra.collection)
.doc(query.json.id)
.get()
).data()
} catch (err) {
console.error("Error writing to Firestore", err)
throw err
}
}
async delete(query: {
json: { id: string }
extra: { [key: string]: string }
}) {
try {
await this.client
.collection(query.extra.collection)
.doc(query.json.id)
.delete()
return true
} catch (err) {
console.error("Error deleting from Firestore", err)
throw err
}
}
}
export default {
schema: SCHEMA,
integration: FirebaseIntegration,
}