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:
@@ -0,0 +1,3 @@
|
||||
mutation DuplicateTeamCollection($collectionID: String!) {
|
||||
duplicateTeamCollection(collectionID: $collectionID)
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user