Files
hoppscotch/packages/hoppscotch-selfhost-web/src/platform/collections/gqlCollections.sync.ts
2023-12-13 22:35:44 +05:30

280 lines
7.6 KiB
TypeScript

import {
graphqlCollectionStore,
navigateToFolderWithIndexPath,
removeDuplicateGraphqlCollectionOrFolder,
} from "@hoppscotch/common/newstore/collections"
import {
getSettingSubject,
settingsStore,
} from "@hoppscotch/common/newstore/settings"
import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data"
import { getSyncInitFunction } from "../../lib/sync"
import { StoreSyncDefinitionOf } from "../../lib/sync"
import { createMapper } from "../../lib/sync/mapper"
import {
createGQLChildUserCollection,
createGQLRootUserCollection,
createGQLUserRequest,
deleteUserCollection,
deleteUserRequest,
editGQLUserRequest,
updateUserCollection,
} from "./collections.api"
import * as E from "fp-ts/Either"
import { moveOrReorderRequests } from "./collections.sync"
// gqlCollectionsMapper uses the collectionPath as the local identifier
export const gqlCollectionsMapper = createMapper<string, string>()
// gqlRequestsMapper uses the collectionPath/requestIndex as the local identifier
export const gqlRequestsMapper = createMapper<string, string>()
// temp implementation untill the backend implements an endpoint that accepts an entire collection
// TODO: use importCollectionsJSON to do this
const recursivelySyncCollections = async (
collection: HoppCollection<HoppRESTRequest>,
collectionPath: string,
parentUserCollectionID?: string
) => {
let parentCollectionID = parentUserCollectionID
// if parentUserCollectionID does not exist, create the collection as a root collection
if (!parentUserCollectionID) {
const res = await createGQLRootUserCollection(collection.name)
if (E.isRight(res)) {
parentCollectionID = res.right.createGQLRootUserCollection.id
collection.id = parentCollectionID
removeDuplicateGraphqlCollectionOrFolder(
parentCollectionID,
collectionPath
)
} else {
parentCollectionID = undefined
}
} else {
// if parentUserCollectionID exists, create the collection as a child collection
const res = await createGQLChildUserCollection(
collection.name,
parentUserCollectionID
)
if (E.isRight(res)) {
const childCollectionId = res.right.createGQLChildUserCollection.id
collection.id = childCollectionId
removeDuplicateGraphqlCollectionOrFolder(
childCollectionId,
`${collectionPath}`
)
}
}
// create the requests
if (parentCollectionID) {
collection.requests.forEach(async (request) => {
const res =
parentCollectionID &&
(await createGQLUserRequest(
request.name,
JSON.stringify(request),
parentCollectionID
))
if (res && E.isRight(res)) {
const requestId = res.right.createGQLUserRequest.id
request.id = requestId
}
})
}
// create the folders aka child collections
if (parentCollectionID)
collection.folders.forEach(async (folder, index) => {
recursivelySyncCollections(
folder,
`${collectionPath}/${index}`,
parentCollectionID
)
})
}
// TODO: generalize this
// TODO: ask backend to send enough info on the subscription to not need this
export const collectionReorderOrMovingOperations: {
sourceCollectionID: string
destinationCollectionID?: string
reorderOperation: {
fromPath: string
toPath?: string
}
}[] = []
type OperationStatus = "pending" | "completed"
type OperationCollectionRemoved = {
type: "COLLECTION_REMOVED"
collectionBackendID: string
status: OperationStatus
}
export const gqlCollectionsOperations: Array<OperationCollectionRemoved> = []
export const storeSyncDefinition: StoreSyncDefinitionOf<
typeof graphqlCollectionStore
> = {
appendCollections({ entries }) {
let indexStart = graphqlCollectionStore.value.state.length - entries.length
entries.forEach((collection) => {
recursivelySyncCollections(collection, `${indexStart}`)
indexStart++
})
},
async addCollection({ collection }) {
const lastCreatedCollectionIndex =
graphqlCollectionStore.value.state.length - 1
await recursivelySyncCollections(
collection,
`${lastCreatedCollectionIndex}`
)
},
async removeCollection({ collectionID }) {
if (collectionID) {
await deleteUserCollection(collectionID)
}
},
editCollection({ collection, collectionIndex }) {
const collectionID = navigateToFolderWithIndexPath(
graphqlCollectionStore.value.state,
[collectionIndex]
)?.id
const data = {
auth: collection.auth,
headers: collection.headers,
}
if (collectionID) {
updateUserCollection(collectionID, collection.name, JSON.stringify(data))
}
},
async addFolder({ name, path }) {
const parentCollection = navigateToFolderWithIndexPath(
graphqlCollectionStore.value.state,
path.split("/").map((index) => parseInt(index))
)
const parentCollectionBackendID = parentCollection?.id
if (parentCollectionBackendID) {
const foldersLength = parentCollection.folders.length
const res = await createGQLChildUserCollection(
name,
parentCollectionBackendID
)
if (E.isRight(res)) {
const { id } = res.right.createGQLChildUserCollection
if (foldersLength) {
parentCollection.folders[foldersLength - 1].id = id
removeDuplicateGraphqlCollectionOrFolder(
id,
`${path}/${foldersLength - 1}`
)
}
}
}
},
editFolder({ folder, path }) {
const folderBackendId = navigateToFolderWithIndexPath(
graphqlCollectionStore.value.state,
path.split("/").map((index) => parseInt(index))
)?.id
const data = {
auth: folder.auth,
headers: folder.headers,
}
if (folderBackendId) {
updateUserCollection(folderBackendId, folder.name, JSON.stringify(data))
}
},
async removeFolder({ folderID }) {
if (folderID) {
await deleteUserCollection(folderID)
}
},
editRequest({ path, requestIndex, requestNew }) {
const request = navigateToFolderWithIndexPath(
graphqlCollectionStore.value.state,
path.split("/").map((index) => parseInt(index))
)?.requests[requestIndex]
const requestBackendID = request?.id
if (requestBackendID) {
editGQLUserRequest(
requestBackendID,
(requestNew as HoppRESTRequest).name,
JSON.stringify(requestNew)
)
}
},
async saveRequestAs({ path, request }) {
const folder = navigateToFolderWithIndexPath(
graphqlCollectionStore.value.state,
path.split("/").map((index) => parseInt(index))
)
const parentCollectionBackendID = folder?.id
if (parentCollectionBackendID) {
const newRequest = folder.requests[folder.requests.length - 1]
const res = await createGQLUserRequest(
(request as HoppRESTRequest).name,
JSON.stringify(request),
parentCollectionBackendID
)
if (E.isRight(res)) {
const { id } = res.right.createGQLUserRequest
newRequest.id = id
removeDuplicateGraphqlCollectionOrFolder(
id,
`${path}/${folder.requests.length - 1}`,
"request"
)
}
}
},
async removeRequest({ requestID }) {
if (requestID) {
await deleteUserRequest(requestID)
}
},
moveRequest({ destinationPath, path, requestIndex }) {
moveOrReorderRequests(requestIndex, path, destinationPath, undefined, "GQL")
},
}
export const gqlCollectionsSyncer = getSyncInitFunction(
graphqlCollectionStore,
storeSyncDefinition,
() => settingsStore.value.syncCollections,
getSettingSubject("syncCollections")
)