Files
hoppscotch/packages/hoppscotch-web/src/collections.ts

194 lines
5.1 KiB
TypeScript

import {
collection,
doc,
getFirestore,
onSnapshot,
setDoc,
} from "firebase/firestore"
import {
translateToNewRESTCollection,
translateToNewGQLCollection,
} from "@hoppscotch/data"
import { def as platformAuth } from "./firebase/auth"
import {
restCollections$,
graphqlCollections$,
setRESTCollections,
setGraphqlCollections,
} from "@hoppscotch/common/newstore/collections"
import {
getSettingSubject,
settingsStore,
} from "@hoppscotch/common/newstore/settings"
import { CollectionsPlatformDef } from "@hoppscotch/common/platform/collections"
type CollectionFlags = "collectionsGraphql" | "collections"
/**
* Whether the collections are loaded. If this is set to true
* Updates to the collections store are written into firebase.
*
* If you have want to update the store and not fire the store update
* subscription, set this variable to false, do the update and then
* set it to true
*/
let loadedRESTCollections = false
/**
* Whether the collections are loaded. If this is set to true
* Updates to the collections store are written into firebase.
*
* If you have want to update the store and not fire the store update
* subscription, set this variable to false, do the update and then
* set it to true
*/
let loadedGraphqlCollections = false
async function writeCollections(collection: any[], flag: CollectionFlags) {
const currentUser = platformAuth.getCurrentUser()
if (currentUser === null)
throw new Error("User not logged in to write collections")
const cl = {
updatedOn: new Date(),
author: currentUser.uid,
author_name: currentUser.displayName,
author_image: currentUser.photoURL,
collection,
}
try {
await setDoc(
doc(getFirestore(), "users", currentUser.uid, flag, "sync"),
cl
)
} catch (e) {
console.error("error updating", cl, e)
throw e
}
}
function initCollectionsSync() {
const currentUser$ = platformAuth.getCurrentUserStream()
const restCollSub = restCollections$.subscribe((collections) => {
const currentUser = platformAuth.getCurrentUser()
if (
loadedRESTCollections &&
currentUser &&
settingsStore.value.syncCollections
) {
writeCollections(collections, "collections")
}
})
const gqlCollSub = graphqlCollections$.subscribe((collections) => {
const currentUser = platformAuth.getCurrentUser()
if (
loadedGraphqlCollections &&
currentUser &&
settingsStore.value.syncCollections
) {
writeCollections(collections, "collectionsGraphql")
}
})
let restSnapshotStop: (() => void) | null = null
let graphqlSnapshotStop: (() => void) | null = null
const currentUserSub = currentUser$.subscribe((user) => {
if (!user) {
if (restSnapshotStop) {
restSnapshotStop()
restSnapshotStop = null
}
if (graphqlSnapshotStop) {
graphqlSnapshotStop()
graphqlSnapshotStop = null
}
} else {
restSnapshotStop = onSnapshot(
collection(getFirestore(), "users", user.uid, "collections"),
(collectionsRef) => {
const collections: any[] = []
collectionsRef.forEach((doc) => {
const collection = doc.data()
collection.id = doc.id
collections.push(collection)
})
// Prevent infinite ping-pong of updates
loadedRESTCollections = false
// TODO: Wth is with collections[0]
if (collections.length > 0 && settingsStore.value.syncCollections) {
setRESTCollections(
(collections[0].collection ?? []).map(
translateToNewRESTCollection
)
)
}
loadedRESTCollections = true
}
)
graphqlSnapshotStop = onSnapshot(
collection(getFirestore(), "users", user.uid, "collectionsGraphql"),
(collectionsRef) => {
const collections: any[] = []
collectionsRef.forEach((doc) => {
const collection = doc.data()
collection.id = doc.id
collections.push(collection)
})
// Prevent infinite ping-pong of updates
loadedGraphqlCollections = false
// TODO: Wth is with collections[0]
if (collections.length > 0 && settingsStore.value.syncCollections) {
setGraphqlCollections(
(collections[0].collection ?? []).map(translateToNewGQLCollection)
)
}
loadedGraphqlCollections = true
}
)
}
})
let oldSyncStatus = settingsStore.value.syncCollections
const syncStop = getSettingSubject("syncCollections").subscribe(
(newStatus) => {
if (oldSyncStatus === true && newStatus === false) {
restSnapshotStop?.()
graphqlSnapshotStop?.()
oldSyncStatus = newStatus
} else if (oldSyncStatus === false && newStatus === true) {
syncStop.unsubscribe()
restCollSub.unsubscribe()
gqlCollSub.unsubscribe()
currentUserSub.unsubscribe()
initCollectionsSync()
}
}
)
}
export const def: CollectionsPlatformDef = {
initCollectionsSync,
}