feat: duplicate REST/GraphQL collections (#4211)

Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
Co-authored-by: nivedin <nivedinp@gmail.com>
This commit is contained in:
James George
2024-07-29 06:07:34 -07:00
committed by GitHub
parent c24d5c5302
commit c9f92282bf
26 changed files with 734 additions and 105 deletions

View File

@@ -0,0 +1,3 @@
mutation DuplicateTeamCollection($collectionID: String!) {
duplicateTeamCollection(collectionID: $collectionID)
}

View File

@@ -1,12 +1,18 @@
import * as A from "fp-ts/Array"
import * as E from "fp-ts/Either"
import * as TE from "fp-ts/TaskEither"
import { pipe, flow } from "fp-ts/function"
import {
HoppCollection,
HoppRESTAuth,
HoppRESTHeaders,
HoppRESTRequest,
makeCollection,
translateToNewRequest,
} from "@hoppscotch/data"
import * as A from "fp-ts/Array"
import * as E from "fp-ts/Either"
import * as TE from "fp-ts/TaskEither"
import { flow, pipe } from "fp-ts/function"
import { z } from "zod"
import { getI18n } from "~/modules/i18n"
import { TeamCollection } from "../teams/TeamCollection"
import { TeamRequest } from "../teams/TeamRequest"
import { GQLError, runGQLQuery } from "./GQLClient"
@@ -17,6 +23,15 @@ import {
GetCollectionTitleAndDataDocument,
} from "./graphql"
type TeamCollectionJSON = {
name: string
folders: TeamCollectionJSON[]
requests: HoppRESTRequest[]
data: string
}
type CollectionDataProps = { auth: HoppRESTAuth; headers: HoppRESTHeaders }
export const BACKEND_PAGE_SIZE = 10
const getCollectionChildrenIDs = async (collID: string) => {
@@ -78,6 +93,68 @@ const getCollectionRequests = async (collID: string) => {
return E.right(reqList)
}
// Pick the value from the parsed result if it is successful, otherwise, return the default value
const parseWithDefaultValue = <T>(
parseResult: z.SafeParseReturnType<T, T>,
defaultValue: T
): T => (parseResult.success ? parseResult.data : defaultValue)
// Parse the incoming value for the `data` (authorization/headers) field and obtain the value in the expected format
const parseCollectionData = (
data: string | Record<string, unknown> | null
): CollectionDataProps => {
const defaultDataProps: CollectionDataProps = {
auth: { authType: "inherit", authActive: true },
headers: [],
}
if (!data) {
return defaultDataProps
}
let parsedData: CollectionDataProps | Record<string, unknown> | null
if (typeof data === "string") {
try {
parsedData = JSON.parse(data)
} catch {
return defaultDataProps
}
} else {
parsedData = data
}
const auth = parseWithDefaultValue<CollectionDataProps["auth"]>(
HoppRESTAuth.safeParse(parsedData?.auth),
defaultDataProps.auth
)
const headers = parseWithDefaultValue<CollectionDataProps["headers"]>(
HoppRESTHeaders.safeParse(parsedData?.headers),
defaultDataProps.headers
)
return {
auth,
headers,
}
}
// Transforms the collection JSON string obtained with workspace level export to `HoppRESTCollection`
const teamCollectionJSONToHoppRESTColl = (
coll: TeamCollectionJSON
): HoppCollection => {
const { auth, headers } = parseCollectionData(coll.data)
return makeCollection({
name: coll.name,
folders: coll.folders.map(teamCollectionJSONToHoppRESTColl),
requests: coll.requests,
auth,
headers,
})
}
export const getCompleteCollectionTree = (
collID: string
): TE.TaskEither<GQLError<string>, TeamCollection> =>
@@ -146,10 +223,26 @@ export const teamCollToHoppRESTColl = (
* @param teamID - ID of the team
* @returns Either of the JSON string of the collection or the error
*/
export const getTeamCollectionJSON = async (teamID: string) =>
await runGQLQuery({
export const getTeamCollectionJSON = async (teamID: string) => {
const data = await runGQLQuery({
query: ExportAsJsonDocument,
variables: {
teamID,
},
})
if (E.isLeft(data)) {
return E.left(data.left.error.toString())
}
const collections = JSON.parse(data.right.exportCollectionsToJSON)
if (!collections.length) {
const t = getI18n()
return E.left(t("error.no_collections_to_export"))
}
const hoppCollections = collections.map(teamCollectionJSONToHoppRESTColl)
return E.right(JSON.stringify(hoppCollections))
}

View File

@@ -9,6 +9,9 @@ import {
DeleteCollectionDocument,
DeleteCollectionMutation,
DeleteCollectionMutationVariables,
DuplicateTeamCollectionDocument,
DuplicateTeamCollectionMutation,
DuplicateTeamCollectionMutationVariables,
ImportFromJsonDocument,
ImportFromJsonMutation,
ImportFromJsonMutationVariables,
@@ -140,3 +143,12 @@ export const updateTeamCollection = (
data,
newTitle,
})
export const duplicateTeamCollection = (collectionID: string) =>
runMutation<
DuplicateTeamCollectionMutation,
DuplicateTeamCollectionMutationVariables,
""
>(DuplicateTeamCollectionDocument, {
collectionID,
})