feat: add platform-specific import support for personal collections (#5570)
Co-authored-by: mirarifhasan <arif.ishan05@gmail.com> Co-authored-by: James George <25279263+jamesgeorge007@users.noreply.github.com>
This commit is contained in:
parent
77af577778
commit
03212386fb
17 changed files with 214 additions and 419 deletions
|
|
@ -18,6 +18,7 @@ import {
|
||||||
UserCollection,
|
UserCollection,
|
||||||
UserCollectionDuplicatedData,
|
UserCollectionDuplicatedData,
|
||||||
UserCollectionExportJSONData,
|
UserCollectionExportJSONData,
|
||||||
|
UserCollectionImportResult,
|
||||||
UserCollectionRemovedData,
|
UserCollectionRemovedData,
|
||||||
UserCollectionReorderData,
|
UserCollectionReorderData,
|
||||||
} from './user-collections.model';
|
} from './user-collections.model';
|
||||||
|
|
@ -375,7 +376,7 @@ export class UserCollectionResolver {
|
||||||
return res.right;
|
return res.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Mutation(() => Boolean, {
|
@Mutation(() => UserCollectionExportJSONData, {
|
||||||
description: 'Import collections from JSON string to the specified Team',
|
description: 'Import collections from JSON string to the specified Team',
|
||||||
})
|
})
|
||||||
@UseGuards(GqlAuthGuard)
|
@UseGuards(GqlAuthGuard)
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import {
|
||||||
import { CollectionFolder } from 'src/types/CollectionFolder';
|
import { CollectionFolder } from 'src/types/CollectionFolder';
|
||||||
import { PrismaError } from 'src/prisma/prisma-error-codes';
|
import { PrismaError } from 'src/prisma/prisma-error-codes';
|
||||||
import { SortOptions } from 'src/types/SortOptions';
|
import { SortOptions } from 'src/types/SortOptions';
|
||||||
|
import { UserRequest } from 'src/user-request/user-request.model';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UserCollectionService {
|
export class UserCollectionService {
|
||||||
|
|
@ -970,7 +971,7 @@ export class UserCollectionService {
|
||||||
collectionListObjects.push(result.right);
|
collectionListObjects.push(result.right);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If collectionID is not null, return JSONified data for specific collection
|
// If collectionID is not null, return JSON stringified data for specific collection
|
||||||
if (collectionID) {
|
if (collectionID) {
|
||||||
// Get Details of collection
|
// Get Details of collection
|
||||||
const parentCollection = await this.getUserCollection(collectionID);
|
const parentCollection = await this.getUserCollection(collectionID);
|
||||||
|
|
@ -1033,7 +1034,10 @@ export class UserCollectionService {
|
||||||
let data = null;
|
let data = null;
|
||||||
if (folder.data) {
|
if (folder.data) {
|
||||||
try {
|
try {
|
||||||
data = JSON.parse(folder.data);
|
data =
|
||||||
|
typeof folder.data === 'string'
|
||||||
|
? JSON.parse(folder.data)
|
||||||
|
: folder.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// If data parsing fails, log error and continue without data
|
// If data parsing fails, log error and continue without data
|
||||||
console.error('Failed to parse collection data:', error);
|
console.error('Failed to parse collection data:', error);
|
||||||
|
|
@ -1149,14 +1153,24 @@ export class UserCollectionService {
|
||||||
return E.left(USER_COLLECTION_CREATION_FAILED);
|
return E.left(USER_COLLECTION_CREATION_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch nested collections after transaction is committed
|
||||||
|
const importedCollectionsWithChildren: CollectionFolder[] = [];
|
||||||
|
for (const userCollection of userCollections) {
|
||||||
|
const exportedCollectionJSON =
|
||||||
|
await this.exportUserCollectionToJSONObject(userID, userCollection.id);
|
||||||
|
if (E.isLeft(exportedCollectionJSON))
|
||||||
|
return E.left(exportedCollectionJSON.left);
|
||||||
|
importedCollectionsWithChildren.push(exportedCollectionJSON.right);
|
||||||
|
}
|
||||||
|
|
||||||
if (isCollectionDuplication) {
|
if (isCollectionDuplication) {
|
||||||
const collectionData = await this.fetchCollectionData(
|
const duplicatedCollectionData = await this.fetchCollectionData(
|
||||||
userCollections[0].id,
|
userCollections[0].id,
|
||||||
);
|
);
|
||||||
if (E.isRight(collectionData)) {
|
if (E.isRight(duplicatedCollectionData)) {
|
||||||
this.pubsub.publish(
|
this.pubsub.publish(
|
||||||
`user_coll/${userID}/duplicated`,
|
`user_coll/${userID}/duplicated`,
|
||||||
collectionData.right,
|
duplicatedCollectionData.right,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1168,7 +1182,10 @@ export class UserCollectionService {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return E.right(true);
|
return E.right({
|
||||||
|
exportedCollection: JSON.stringify(importedCollectionsWithChildren),
|
||||||
|
collectionType: reqType,
|
||||||
|
} as UserCollectionExportJSONData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -115,3 +115,16 @@ export class UserCollectionDuplicatedData {
|
||||||
})
|
})
|
||||||
requests: UserRequest[];
|
requests: UserRequest[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ObjectType()
|
||||||
|
export class UserCollectionImportResult {
|
||||||
|
@Field(() => [UserCollection], {
|
||||||
|
description: 'Flat array of all collections',
|
||||||
|
})
|
||||||
|
collections: UserCollection[];
|
||||||
|
|
||||||
|
@Field(() => [UserRequest], {
|
||||||
|
description: 'Flat array of all requests',
|
||||||
|
})
|
||||||
|
requests: UserRequest[];
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -298,6 +298,7 @@ declare module 'vue' {
|
||||||
MockServerMockServerDashboard: typeof import('./components/mockServer/MockServerDashboard.vue')['default']
|
MockServerMockServerDashboard: typeof import('./components/mockServer/MockServerDashboard.vue')['default']
|
||||||
MockServerMockServerLogs: typeof import('./components/mockServer/MockServerLogs.vue')['default']
|
MockServerMockServerLogs: typeof import('./components/mockServer/MockServerLogs.vue')['default']
|
||||||
MonacoScriptEditor: typeof import('./components/MonacoScriptEditor.vue')['default']
|
MonacoScriptEditor: typeof import('./components/MonacoScriptEditor.vue')['default']
|
||||||
|
Profile: typeof import('./components/profile/index.vue')['default']
|
||||||
ProfileUserDelete: typeof import('./components/profile/UserDelete.vue')['default']
|
ProfileUserDelete: typeof import('./components/profile/UserDelete.vue')['default']
|
||||||
RealtimeCommunication: typeof import('./components/realtime/Communication.vue')['default']
|
RealtimeCommunication: typeof import('./components/realtime/Communication.vue')['default']
|
||||||
RealtimeConnectionConfig: typeof import('./components/realtime/ConnectionConfig.vue')['default']
|
RealtimeConnectionConfig: typeof import('./components/realtime/ConnectionConfig.vue')['default']
|
||||||
|
|
@ -325,6 +326,7 @@ declare module 'vue' {
|
||||||
SmartEnvInput: typeof import('./components/smart/EnvInput.vue')['default']
|
SmartEnvInput: typeof import('./components/smart/EnvInput.vue')['default']
|
||||||
TabPrimary: typeof import('./components/tab/Primary.vue')['default']
|
TabPrimary: typeof import('./components/tab/Primary.vue')['default']
|
||||||
TabSecondary: typeof import('./components/tab/Secondary.vue')['default']
|
TabSecondary: typeof import('./components/tab/Secondary.vue')['default']
|
||||||
|
TabsNav: typeof import('./components/TabsNav.vue')['default']
|
||||||
Teams: typeof import('./components/teams/index.vue')['default']
|
Teams: typeof import('./components/teams/index.vue')['default']
|
||||||
TeamsAdd: typeof import('./components/teams/Add.vue')['default']
|
TeamsAdd: typeof import('./components/teams/Add.vue')['default']
|
||||||
TeamsEdit: typeof import('./components/teams/Edit.vue')['default']
|
TeamsEdit: typeof import('./components/teams/Edit.vue')['default']
|
||||||
|
|
@ -332,6 +334,7 @@ declare module 'vue' {
|
||||||
TeamsMemberStack: typeof import('./components/teams/MemberStack.vue')['default']
|
TeamsMemberStack: typeof import('./components/teams/MemberStack.vue')['default']
|
||||||
TeamsModal: typeof import('./components/teams/Modal.vue')['default']
|
TeamsModal: typeof import('./components/teams/Modal.vue')['default']
|
||||||
TeamsTeam: typeof import('./components/teams/Team.vue')['default']
|
TeamsTeam: typeof import('./components/teams/Team.vue')['default']
|
||||||
|
TeamsView: typeof import('./components/teams/View.vue')['default']
|
||||||
Tippy: typeof import('vue-tippy')['Tippy']
|
Tippy: typeof import('vue-tippy')['Tippy']
|
||||||
WorkspaceCurrent: typeof import('./components/workspace/Current.vue')['default']
|
WorkspaceCurrent: typeof import('./components/workspace/Current.vue')['default']
|
||||||
WorkspaceSelector: typeof import('./components/workspace/Selector.vue')['default']
|
WorkspaceSelector: typeof import('./components/workspace/Selector.vue')['default']
|
||||||
|
|
|
||||||
|
|
@ -34,11 +34,7 @@ import { defineStep } from "~/composables/step-components"
|
||||||
import AllCollectionImport from "~/components/importExport/ImportExportSteps/AllCollectionImport.vue"
|
import AllCollectionImport from "~/components/importExport/ImportExportSteps/AllCollectionImport.vue"
|
||||||
import { useI18n } from "~/composables/i18n"
|
import { useI18n } from "~/composables/i18n"
|
||||||
import { useToast } from "~/composables/toast"
|
import { useToast } from "~/composables/toast"
|
||||||
import {
|
import { appendRESTCollections, restCollections$ } from "~/newstore/collections"
|
||||||
appendRESTCollections,
|
|
||||||
restCollections$,
|
|
||||||
setRESTCollections,
|
|
||||||
} from "~/newstore/collections"
|
|
||||||
|
|
||||||
import IconInsomnia from "~icons/hopp/insomnia"
|
import IconInsomnia from "~icons/hopp/insomnia"
|
||||||
import IconPostman from "~icons/hopp/postman"
|
import IconPostman from "~icons/hopp/postman"
|
||||||
|
|
@ -51,11 +47,6 @@ import { useReadonlyStream } from "~/composables/stream"
|
||||||
import IconUser from "~icons/lucide/user"
|
import IconUser from "~icons/lucide/user"
|
||||||
|
|
||||||
import { getTeamCollectionJSON } from "~/helpers/backend/helpers"
|
import { getTeamCollectionJSON } from "~/helpers/backend/helpers"
|
||||||
import {
|
|
||||||
importUserCollectionsFromJSON,
|
|
||||||
fetchAndConvertUserCollections,
|
|
||||||
} from "~/helpers/backend/mutations/UserCollection"
|
|
||||||
import { ReqType } from "~/helpers/backend/graphql"
|
|
||||||
|
|
||||||
import { platform } from "~/platform"
|
import { platform } from "~/platform"
|
||||||
|
|
||||||
|
|
@ -68,6 +59,7 @@ import { ImporterOrExporter } from "~/components/importExport/types"
|
||||||
import { GistSource } from "~/helpers/import-export/import/import-sources/GistSource"
|
import { GistSource } from "~/helpers/import-export/import/import-sources/GistSource"
|
||||||
import { TeamWorkspace } from "~/services/workspace.service"
|
import { TeamWorkspace } from "~/services/workspace.service"
|
||||||
import { invokeAction } from "~/helpers/actions"
|
import { invokeAction } from "~/helpers/actions"
|
||||||
|
import { ReqType } from "~/helpers/backend/graphql"
|
||||||
|
|
||||||
const isInsomniaImporterInProgress = ref(false)
|
const isInsomniaImporterInProgress = ref(false)
|
||||||
const isOpenAPIImporterInProgress = ref(false)
|
const isOpenAPIImporterInProgress = ref(false)
|
||||||
|
|
@ -121,46 +113,19 @@ const handleImportToStore = async (collections: HoppCollection[]) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const importToPersonalWorkspace = async (collections: HoppCollection[]) => {
|
const importToPersonalWorkspace = (collections: HoppCollection[]) => {
|
||||||
// If user is logged in, try to import to backend first
|
if (
|
||||||
if (currentUser.value) {
|
platform.sync.collections.importToPersonalWorkspace &&
|
||||||
try {
|
currentUser.value
|
||||||
const transformedCollection = collections.map((collection) =>
|
) {
|
||||||
transformCollectionForImport(collection)
|
return platform.sync.collections.importToPersonalWorkspace(
|
||||||
)
|
collections,
|
||||||
|
ReqType.Rest
|
||||||
const res = await importUserCollectionsFromJSON(
|
)
|
||||||
JSON.stringify(transformedCollection),
|
|
||||||
ReqType.Rest
|
|
||||||
)()
|
|
||||||
|
|
||||||
if (E.isRight(res)) {
|
|
||||||
// Backend import succeeded, now fetch and persist collections in store
|
|
||||||
const fetchResult = await fetchAndConvertUserCollections(ReqType.Rest)
|
|
||||||
|
|
||||||
if (E.isRight(fetchResult)) {
|
|
||||||
// Replace local collections with backend collections
|
|
||||||
setRESTCollections(fetchResult.right)
|
|
||||||
} else {
|
|
||||||
// Failed to fetch, append to local store as fallback
|
|
||||||
appendRESTCollections(collections)
|
|
||||||
}
|
|
||||||
|
|
||||||
return E.right({ success: true })
|
|
||||||
}
|
|
||||||
// Backend import failed, fall back to local storage
|
|
||||||
appendRESTCollections(collections)
|
|
||||||
return E.right({ success: true })
|
|
||||||
} catch {
|
|
||||||
// Backend import failed, fall back to local storage
|
|
||||||
appendRESTCollections(collections)
|
|
||||||
return E.right({ success: true })
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// User not logged in, use local storage
|
|
||||||
appendRESTCollections(collections)
|
|
||||||
return E.right({ success: true })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
appendRESTCollections(collections)
|
||||||
|
return E.right({ success: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
const importToTeamsWorkspace = async (collections: HoppCollection[]) => {
|
const importToTeamsWorkspace = async (collections: HoppCollection[]) => {
|
||||||
|
|
|
||||||
|
|
@ -12,18 +12,12 @@
|
||||||
import { HoppCollection } from "@hoppscotch/data"
|
import { HoppCollection } from "@hoppscotch/data"
|
||||||
import * as E from "fp-ts/Either"
|
import * as E from "fp-ts/Either"
|
||||||
import { ref } from "vue"
|
import { ref } from "vue"
|
||||||
import { transformCollectionForImport } from "~/helpers/collection/collection"
|
|
||||||
|
|
||||||
import { useI18n } from "~/composables/i18n"
|
import { useI18n } from "~/composables/i18n"
|
||||||
import { useToast } from "~/composables/toast"
|
import { useToast } from "~/composables/toast"
|
||||||
import { ImporterOrExporter } from "~/components/importExport/types"
|
import { ImporterOrExporter } from "~/components/importExport/types"
|
||||||
import { FileSource } from "~/helpers/import-export/import/import-sources/FileSource"
|
import { FileSource } from "~/helpers/import-export/import/import-sources/FileSource"
|
||||||
import { GistSource } from "~/helpers/import-export/import/import-sources/GistSource"
|
import { GistSource } from "~/helpers/import-export/import/import-sources/GistSource"
|
||||||
import {
|
|
||||||
importUserCollectionsFromJSON,
|
|
||||||
fetchAndConvertUserCollections,
|
|
||||||
} from "~/helpers/backend/mutations/UserCollection"
|
|
||||||
import { ReqType } from "~/helpers/backend/graphql"
|
|
||||||
|
|
||||||
import IconFolderPlus from "~icons/lucide/folder-plus"
|
import IconFolderPlus from "~icons/lucide/folder-plus"
|
||||||
import IconUser from "~icons/lucide/user"
|
import IconUser from "~icons/lucide/user"
|
||||||
|
|
@ -34,13 +28,13 @@ import { platform } from "~/platform"
|
||||||
import {
|
import {
|
||||||
appendGraphqlCollections,
|
appendGraphqlCollections,
|
||||||
graphqlCollections$,
|
graphqlCollections$,
|
||||||
setGraphqlCollections,
|
|
||||||
} from "~/newstore/collections"
|
} from "~/newstore/collections"
|
||||||
import { hoppGqlCollectionsImporter } from "~/helpers/import-export/import/hoppGql"
|
import { hoppGqlCollectionsImporter } from "~/helpers/import-export/import/hoppGql"
|
||||||
import { gqlCollectionsExporter } from "~/helpers/import-export/export/gqlCollections"
|
import { gqlCollectionsExporter } from "~/helpers/import-export/export/gqlCollections"
|
||||||
import { gistExporter } from "~/helpers/import-export/export/gist"
|
import { gistExporter } from "~/helpers/import-export/export/gist"
|
||||||
import { computed } from "vue"
|
import { computed } from "vue"
|
||||||
import { hoppGQLImporter } from "~/helpers/import-export/import/hopp"
|
import { hoppGQLImporter } from "~/helpers/import-export/import/hopp"
|
||||||
|
import { ReqType } from "~/helpers/backend/graphql"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
|
|
@ -238,49 +232,19 @@ const showImportFailedError = () => {
|
||||||
toast.error(t("import.failed"))
|
toast.error(t("import.failed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleImportToStore = async (gqlCollections: HoppCollection[]) => {
|
const handleImportToStore = (gqlCollections: HoppCollection[]) => {
|
||||||
// If user is logged in, try to import to backend first
|
if (
|
||||||
if (currentUser.value) {
|
platform.sync.collections.importToPersonalWorkspace &&
|
||||||
try {
|
currentUser.value
|
||||||
const transformedCollection = gqlCollections.map((collection) =>
|
) {
|
||||||
transformCollectionForImport(collection)
|
return platform.sync.collections.importToPersonalWorkspace(
|
||||||
)
|
gqlCollections,
|
||||||
|
ReqType.Gql
|
||||||
const res = await importUserCollectionsFromJSON(
|
)
|
||||||
JSON.stringify(transformedCollection),
|
|
||||||
ReqType.Gql
|
|
||||||
)()
|
|
||||||
|
|
||||||
if (E.isRight(res)) {
|
|
||||||
// Backend import succeeded, now fetch and persist collections in store
|
|
||||||
const fetchResult = await fetchAndConvertUserCollections(ReqType.Gql)
|
|
||||||
|
|
||||||
if (E.isRight(fetchResult)) {
|
|
||||||
// Replace local collections with backend collections
|
|
||||||
setGraphqlCollections(fetchResult.right)
|
|
||||||
} else {
|
|
||||||
// Failed to fetch, append to local store as fallback
|
|
||||||
appendGraphqlCollections(gqlCollections)
|
|
||||||
}
|
|
||||||
|
|
||||||
toast.success(t("state.file_imported"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Backend import failed, fall back to local storage
|
|
||||||
appendGraphqlCollections(gqlCollections)
|
|
||||||
toast.success(t("state.file_imported"))
|
|
||||||
return
|
|
||||||
} catch {
|
|
||||||
// Backend import failed, fall back to local storage
|
|
||||||
appendGraphqlCollections(gqlCollections)
|
|
||||||
toast.success(t("state.file_imported"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// User not logged in, use local storage
|
|
||||||
appendGraphqlCollections(gqlCollections)
|
|
||||||
toast.success(t("state.file_imported"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
appendGraphqlCollections(gqlCollections)
|
||||||
|
toast.success(t("state.file_imported"))
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
mutation ImportUserCollectionsFromJSON(
|
|
||||||
$jsonString: String!
|
|
||||||
$reqType: ReqType!
|
|
||||||
$parentCollectionID: ID
|
|
||||||
) {
|
|
||||||
importUserCollectionsFromJSON(
|
|
||||||
jsonString: $jsonString
|
|
||||||
reqType: $reqType
|
|
||||||
parentCollectionID: $parentCollectionID
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
query GetUserRootCollections($cursor: ID, $take: Int) {
|
|
||||||
rootRESTUserCollections(cursor: $cursor, take: $take) {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
data
|
|
||||||
type
|
|
||||||
parent {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
requests {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
request
|
|
||||||
type
|
|
||||||
collectionID
|
|
||||||
}
|
|
||||||
childrenREST {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
data
|
|
||||||
type
|
|
||||||
parent {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
requests {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
request
|
|
||||||
type
|
|
||||||
collectionID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,200 +0,0 @@
|
||||||
import { runMutation } from "../GQLClient"
|
|
||||||
import { runGQLQuery } from "../GQLClient"
|
|
||||||
import {
|
|
||||||
GetGqlRootUserCollectionsDocument,
|
|
||||||
GetGqlRootUserCollectionsQuery,
|
|
||||||
GetGqlRootUserCollectionsQueryVariables,
|
|
||||||
GetUserRootCollectionsDocument,
|
|
||||||
GetUserRootCollectionsQuery,
|
|
||||||
GetUserRootCollectionsQueryVariables,
|
|
||||||
ImportUserCollectionsFromJsonDocument,
|
|
||||||
ImportUserCollectionsFromJsonMutation,
|
|
||||||
ImportUserCollectionsFromJsonMutationVariables,
|
|
||||||
ReqType,
|
|
||||||
UserCollection,
|
|
||||||
UserRequest,
|
|
||||||
} from "../graphql"
|
|
||||||
import {
|
|
||||||
HoppCollection,
|
|
||||||
makeCollection,
|
|
||||||
HoppRESTRequest,
|
|
||||||
HoppGQLRequest,
|
|
||||||
getDefaultRESTRequest,
|
|
||||||
getDefaultGQLRequest,
|
|
||||||
} from "@hoppscotch/data"
|
|
||||||
import * as E from "fp-ts/Either"
|
|
||||||
|
|
||||||
export const importUserCollectionsFromJSON = (
|
|
||||||
collectionJSON: string,
|
|
||||||
reqType: ReqType,
|
|
||||||
parentCollectionID?: string
|
|
||||||
) =>
|
|
||||||
runMutation<
|
|
||||||
ImportUserCollectionsFromJsonMutation,
|
|
||||||
ImportUserCollectionsFromJsonMutationVariables,
|
|
||||||
""
|
|
||||||
>(ImportUserCollectionsFromJsonDocument, {
|
|
||||||
jsonString: collectionJSON,
|
|
||||||
reqType,
|
|
||||||
parentCollectionID,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Use generated GraphQL documents instead of inline gql tags
|
|
||||||
export const getUserRootCollections = () =>
|
|
||||||
runGQLQuery<
|
|
||||||
GetUserRootCollectionsQuery,
|
|
||||||
GetUserRootCollectionsQueryVariables,
|
|
||||||
""
|
|
||||||
>({
|
|
||||||
query: GetUserRootCollectionsDocument,
|
|
||||||
variables: {},
|
|
||||||
})
|
|
||||||
|
|
||||||
export const getGQLRootUserCollections = () =>
|
|
||||||
runGQLQuery<
|
|
||||||
GetGqlRootUserCollectionsQuery,
|
|
||||||
GetGqlRootUserCollectionsQueryVariables,
|
|
||||||
""
|
|
||||||
>({
|
|
||||||
query: GetGqlRootUserCollectionsDocument,
|
|
||||||
variables: {},
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a UserRequest from backend format to HoppRequest format
|
|
||||||
*/
|
|
||||||
function convertUserRequestToHoppRequest(
|
|
||||||
userRequest: UserRequest
|
|
||||||
): HoppRESTRequest | HoppGQLRequest {
|
|
||||||
try {
|
|
||||||
const parsedRequest = JSON.parse(userRequest.request)
|
|
||||||
|
|
||||||
// Add the backend ID and title to the request
|
|
||||||
const request = {
|
|
||||||
...parsedRequest,
|
|
||||||
id: userRequest.id,
|
|
||||||
name: userRequest.title,
|
|
||||||
}
|
|
||||||
|
|
||||||
return request
|
|
||||||
} catch {
|
|
||||||
// Return a default request if parsing fails
|
|
||||||
if (userRequest.type === ReqType.Rest) {
|
|
||||||
const defaultRequest = getDefaultRESTRequest()
|
|
||||||
defaultRequest.id = userRequest.id
|
|
||||||
defaultRequest.name = userRequest.title
|
|
||||||
return defaultRequest
|
|
||||||
}
|
|
||||||
const defaultRequest = getDefaultGQLRequest()
|
|
||||||
defaultRequest.id = userRequest.id
|
|
||||||
defaultRequest.name = userRequest.title
|
|
||||||
return defaultRequest
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse collection data similar to the existing parseCollectionData function in helpers.ts
|
|
||||||
*/
|
|
||||||
function parseUserCollectionData(data: string | null | undefined) {
|
|
||||||
const defaultDataProps = {
|
|
||||||
auth: { authType: "inherit", authActive: true },
|
|
||||||
headers: [],
|
|
||||||
variables: [],
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
return defaultDataProps
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const parsedData = JSON.parse(data)
|
|
||||||
return {
|
|
||||||
auth: parsedData?.auth || defaultDataProps.auth,
|
|
||||||
headers: parsedData?.headers || defaultDataProps.headers,
|
|
||||||
variables: parsedData?.variables || defaultDataProps.variables,
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
return defaultDataProps
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a UserCollection from backend format to HoppCollection format
|
|
||||||
* Following the same pattern as teamCollectionJSONToHoppRESTColl in helpers.ts
|
|
||||||
*/
|
|
||||||
export function convertUserCollectionToHoppCollection(
|
|
||||||
userCollection: UserCollection,
|
|
||||||
reqType: ReqType
|
|
||||||
): HoppCollection {
|
|
||||||
const { auth, headers, variables } = parseUserCollectionData(
|
|
||||||
userCollection.data
|
|
||||||
)
|
|
||||||
|
|
||||||
// Get the appropriate children based on request type
|
|
||||||
const children =
|
|
||||||
reqType === ReqType.Rest
|
|
||||||
? userCollection.childrenREST
|
|
||||||
: userCollection.childrenGQL
|
|
||||||
|
|
||||||
// Convert requests - filter by type and convert
|
|
||||||
const requests = userCollection.requests
|
|
||||||
? userCollection.requests
|
|
||||||
.filter((req) => req.type === reqType)
|
|
||||||
.map(convertUserRequestToHoppRequest)
|
|
||||||
: []
|
|
||||||
|
|
||||||
const collection = makeCollection({
|
|
||||||
name: userCollection.title,
|
|
||||||
folders: children
|
|
||||||
? children.map((child) =>
|
|
||||||
convertUserCollectionToHoppCollection(child, reqType)
|
|
||||||
)
|
|
||||||
: [],
|
|
||||||
requests: requests,
|
|
||||||
auth,
|
|
||||||
headers,
|
|
||||||
variables,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Add the backend ID to the collection
|
|
||||||
collection.id = userCollection.id
|
|
||||||
|
|
||||||
return collection
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches user collections from backend and converts them to HoppCollection format
|
|
||||||
*/
|
|
||||||
export const fetchAndConvertUserCollections = async (reqType: ReqType) => {
|
|
||||||
const fetchFunction =
|
|
||||||
reqType === ReqType.Rest
|
|
||||||
? getUserRootCollections
|
|
||||||
: getGQLRootUserCollections
|
|
||||||
|
|
||||||
const result = await fetchFunction()
|
|
||||||
|
|
||||||
if (E.isLeft(result)) {
|
|
||||||
return E.left(result.left)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reqType === ReqType.Rest) {
|
|
||||||
const right = result.right as GetUserRootCollectionsQuery
|
|
||||||
const collections = right.rootRESTUserCollections
|
|
||||||
const convertedCollections = collections.map((collection) =>
|
|
||||||
convertUserCollectionToHoppCollection(
|
|
||||||
collection as unknown as UserCollection,
|
|
||||||
reqType
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return E.right(convertedCollections)
|
|
||||||
}
|
|
||||||
const right = result.right as GetGqlRootUserCollectionsQuery
|
|
||||||
const collections = right.rootGQLUserCollections
|
|
||||||
const convertedCollections = collections.map((collection) =>
|
|
||||||
convertUserCollectionToHoppCollection(
|
|
||||||
collection as unknown as UserCollection,
|
|
||||||
reqType
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return E.right(convertedCollections)
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +1,11 @@
|
||||||
|
import { HoppCollection } from "@hoppscotch/data"
|
||||||
|
import { ReqType } from "~/helpers/backend/graphql"
|
||||||
|
import * as E from "fp-ts/Either"
|
||||||
|
|
||||||
export type CollectionsPlatformDef = {
|
export type CollectionsPlatformDef = {
|
||||||
initCollectionsSync: () => void
|
initCollectionsSync: () => void
|
||||||
|
importToPersonalWorkspace?: (
|
||||||
|
collections: HoppCollection[],
|
||||||
|
reqType: ReqType
|
||||||
|
) => Promise<E.Either<string, { success: boolean }>>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,5 +7,8 @@ mutation ImportUserCollectionsFromJSON(
|
||||||
jsonString: $jsonString
|
jsonString: $jsonString
|
||||||
reqType: $reqType
|
reqType: $reqType
|
||||||
parentCollectionID: $parentCollectionID
|
parentCollectionID: $parentCollectionID
|
||||||
)
|
) {
|
||||||
|
exportedCollection
|
||||||
|
collectionType
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,3 @@
|
||||||
import {
|
|
||||||
runGQLQuery,
|
|
||||||
runGQLSubscription,
|
|
||||||
runMutation,
|
|
||||||
} from "@helpers/backend/GQLClient"
|
|
||||||
import {
|
import {
|
||||||
CreateGqlChildUserCollectionDocument,
|
CreateGqlChildUserCollectionDocument,
|
||||||
CreateGqlChildUserCollectionMutation,
|
CreateGqlChildUserCollectionMutation,
|
||||||
|
|
@ -34,12 +29,6 @@ import {
|
||||||
ExportUserCollectionsToJsonDocument,
|
ExportUserCollectionsToJsonDocument,
|
||||||
ExportUserCollectionsToJsonQuery,
|
ExportUserCollectionsToJsonQuery,
|
||||||
ExportUserCollectionsToJsonQueryVariables,
|
ExportUserCollectionsToJsonQueryVariables,
|
||||||
GetGqlRootUserCollectionsDocument,
|
|
||||||
GetGqlRootUserCollectionsQuery,
|
|
||||||
GetGqlRootUserCollectionsQueryVariables,
|
|
||||||
GetUserRootCollectionsDocument,
|
|
||||||
GetUserRootCollectionsQuery,
|
|
||||||
GetUserRootCollectionsQueryVariables,
|
|
||||||
ImportUserCollectionsFromJsonDocument,
|
ImportUserCollectionsFromJsonDocument,
|
||||||
ImportUserCollectionsFromJsonMutation,
|
ImportUserCollectionsFromJsonMutation,
|
||||||
ImportUserCollectionsFromJsonMutationVariables,
|
ImportUserCollectionsFromJsonMutationVariables,
|
||||||
|
|
@ -82,6 +71,11 @@ import {
|
||||||
UserRequestUpdatedDocument,
|
UserRequestUpdatedDocument,
|
||||||
UserRootCollectionsSortedDocument,
|
UserRootCollectionsSortedDocument,
|
||||||
} from "@app/api/generated/graphql"
|
} from "@app/api/generated/graphql"
|
||||||
|
import {
|
||||||
|
runGQLQuery,
|
||||||
|
runGQLSubscription,
|
||||||
|
runMutation,
|
||||||
|
} from "@hoppscotch/common/helpers/backend/GQLClient"
|
||||||
|
|
||||||
export const createRESTRootUserCollection = (title: string, data?: string) =>
|
export const createRESTRootUserCollection = (title: string, data?: string) =>
|
||||||
runMutation<
|
runMutation<
|
||||||
|
|
@ -300,26 +294,6 @@ export const updateUserCollectionOrder = (
|
||||||
nextCollectionID,
|
nextCollectionID,
|
||||||
})()
|
})()
|
||||||
|
|
||||||
export const getUserRootCollections = () =>
|
|
||||||
runGQLQuery<
|
|
||||||
GetUserRootCollectionsQuery,
|
|
||||||
GetUserRootCollectionsQueryVariables,
|
|
||||||
""
|
|
||||||
>({
|
|
||||||
query: GetUserRootCollectionsDocument,
|
|
||||||
variables: {},
|
|
||||||
})
|
|
||||||
|
|
||||||
export const getGQLRootUserCollections = () =>
|
|
||||||
runGQLQuery<
|
|
||||||
GetGqlRootUserCollectionsQuery,
|
|
||||||
GetGqlRootUserCollectionsQueryVariables,
|
|
||||||
""
|
|
||||||
>({
|
|
||||||
query: GetGqlRootUserCollectionsDocument,
|
|
||||||
variables: {},
|
|
||||||
})
|
|
||||||
|
|
||||||
export const exportUserCollectionsToJSON = (
|
export const exportUserCollectionsToJSON = (
|
||||||
collectionID?: string,
|
collectionID?: string,
|
||||||
collectionType: ReqType.Rest | ReqType.Gql = ReqType.Rest
|
collectionType: ReqType.Rest | ReqType.Gql = ReqType.Rest
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export { importToPersonalWorkspace } from "../web/import"
|
||||||
|
|
@ -98,7 +98,7 @@ function initCollectionsSync() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type ExportedUserCollectionREST = {
|
export type ExportedUserCollectionREST = {
|
||||||
id?: string
|
id?: string
|
||||||
_ref_id?: string
|
_ref_id?: string
|
||||||
folders: ExportedUserCollectionREST[]
|
folders: ExportedUserCollectionREST[]
|
||||||
|
|
@ -107,7 +107,7 @@ type ExportedUserCollectionREST = {
|
||||||
data: string
|
data: string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ExportedUserCollectionGQL = {
|
export type ExportedUserCollectionGQL = {
|
||||||
id?: string
|
id?: string
|
||||||
_ref_id?: string
|
_ref_id?: string
|
||||||
folders: ExportedUserCollectionGQL[]
|
folders: ExportedUserCollectionGQL[]
|
||||||
|
|
@ -125,7 +125,7 @@ function addDescriptionField(
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
function exportedCollectionToHoppCollection(
|
export function exportedCollectionToHoppCollection(
|
||||||
collection: ExportedUserCollectionREST | ExportedUserCollectionGQL,
|
collection: ExportedUserCollectionREST | ExportedUserCollectionGQL,
|
||||||
collectionType: "REST" | "GQL"
|
collectionType: "REST" | "GQL"
|
||||||
): HoppCollection {
|
): HoppCollection {
|
||||||
|
|
@ -1028,8 +1028,11 @@ function setupUserRequestDeletedSubscription() {
|
||||||
return userRequestDeletedSub
|
return userRequestDeletedSub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import { importToPersonalWorkspace } from "./import"
|
||||||
|
|
||||||
export const def: CollectionsPlatformDef = {
|
export const def: CollectionsPlatformDef = {
|
||||||
initCollectionsSync,
|
initCollectionsSync,
|
||||||
|
importToPersonalWorkspace,
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCollectionPathFromCollectionID(
|
function getCollectionPathFromCollectionID(
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,3 @@
|
||||||
import {
|
|
||||||
runGQLQuery,
|
|
||||||
runGQLSubscription,
|
|
||||||
runMutation,
|
|
||||||
} from "@helpers/backend/GQLClient"
|
|
||||||
import {
|
import {
|
||||||
CreateGqlChildUserCollectionDocument,
|
CreateGqlChildUserCollectionDocument,
|
||||||
CreateGqlChildUserCollectionMutation,
|
CreateGqlChildUserCollectionMutation,
|
||||||
|
|
@ -34,12 +29,6 @@ import {
|
||||||
ExportUserCollectionsToJsonDocument,
|
ExportUserCollectionsToJsonDocument,
|
||||||
ExportUserCollectionsToJsonQuery,
|
ExportUserCollectionsToJsonQuery,
|
||||||
ExportUserCollectionsToJsonQueryVariables,
|
ExportUserCollectionsToJsonQueryVariables,
|
||||||
GetGqlRootUserCollectionsDocument,
|
|
||||||
GetGqlRootUserCollectionsQuery,
|
|
||||||
GetGqlRootUserCollectionsQueryVariables,
|
|
||||||
GetUserRootCollectionsDocument,
|
|
||||||
GetUserRootCollectionsQuery,
|
|
||||||
GetUserRootCollectionsQueryVariables,
|
|
||||||
ImportUserCollectionsFromJsonDocument,
|
ImportUserCollectionsFromJsonDocument,
|
||||||
ImportUserCollectionsFromJsonMutation,
|
ImportUserCollectionsFromJsonMutation,
|
||||||
ImportUserCollectionsFromJsonMutationVariables,
|
ImportUserCollectionsFromJsonMutationVariables,
|
||||||
|
|
@ -82,6 +71,11 @@ import {
|
||||||
UserRequestUpdatedDocument,
|
UserRequestUpdatedDocument,
|
||||||
UserRootCollectionsSortedDocument,
|
UserRootCollectionsSortedDocument,
|
||||||
} from "@app/api/generated/graphql"
|
} from "@app/api/generated/graphql"
|
||||||
|
import {
|
||||||
|
runGQLQuery,
|
||||||
|
runGQLSubscription,
|
||||||
|
runMutation,
|
||||||
|
} from "@hoppscotch/common/helpers/backend/GQLClient"
|
||||||
|
|
||||||
export const createRESTRootUserCollection = (title: string, data?: string) =>
|
export const createRESTRootUserCollection = (title: string, data?: string) =>
|
||||||
runMutation<
|
runMutation<
|
||||||
|
|
@ -300,26 +294,6 @@ export const updateUserCollectionOrder = (
|
||||||
nextCollectionID,
|
nextCollectionID,
|
||||||
})()
|
})()
|
||||||
|
|
||||||
export const getUserRootCollections = () =>
|
|
||||||
runGQLQuery<
|
|
||||||
GetUserRootCollectionsQuery,
|
|
||||||
GetUserRootCollectionsQueryVariables,
|
|
||||||
""
|
|
||||||
>({
|
|
||||||
query: GetUserRootCollectionsDocument,
|
|
||||||
variables: {},
|
|
||||||
})
|
|
||||||
|
|
||||||
export const getGQLRootUserCollections = () =>
|
|
||||||
runGQLQuery<
|
|
||||||
GetGqlRootUserCollectionsQuery,
|
|
||||||
GetGqlRootUserCollectionsQueryVariables,
|
|
||||||
""
|
|
||||||
>({
|
|
||||||
query: GetGqlRootUserCollectionsDocument,
|
|
||||||
variables: {},
|
|
||||||
})
|
|
||||||
|
|
||||||
export const exportUserCollectionsToJSON = (
|
export const exportUserCollectionsToJSON = (
|
||||||
collectionID?: string,
|
collectionID?: string,
|
||||||
collectionType: ReqType.Rest | ReqType.Gql = ReqType.Rest
|
collectionType: ReqType.Rest | ReqType.Gql = ReqType.Rest
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
import { ReqType } from "@hoppscotch/common/helpers/backend/graphql"
|
||||||
|
import {
|
||||||
|
appendGraphqlCollections,
|
||||||
|
appendRESTCollections,
|
||||||
|
} from "@hoppscotch/common/newstore/collections"
|
||||||
|
import { HoppCollection } from "@hoppscotch/data"
|
||||||
|
import * as E from "fp-ts/Either"
|
||||||
|
import {
|
||||||
|
exportedCollectionToHoppCollection,
|
||||||
|
ExportedUserCollectionGQL,
|
||||||
|
ExportedUserCollectionREST,
|
||||||
|
} from "../web"
|
||||||
|
import { importUserCollectionsFromJSON } from "./api"
|
||||||
|
import { runDispatchWithOutSyncing } from "@app/lib/sync"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Platform-specific import function for selfhost-web that uses the correct nested collection queries
|
||||||
|
*/
|
||||||
|
export const importToPersonalWorkspace = async (
|
||||||
|
collections: HoppCollection[],
|
||||||
|
reqType: ReqType
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const transformedCollection = collections.map((collection) =>
|
||||||
|
translateToPersonalCollectionFormat(collection)
|
||||||
|
)
|
||||||
|
|
||||||
|
const res = await importUserCollectionsFromJSON(
|
||||||
|
JSON.stringify(transformedCollection),
|
||||||
|
reqType
|
||||||
|
)
|
||||||
|
|
||||||
|
if (E.isRight(res)) {
|
||||||
|
await loadImportedUserCollections(
|
||||||
|
res.right.importUserCollectionsFromJSON.exportedCollection,
|
||||||
|
res.right.importUserCollectionsFromJSON.collectionType === "REST"
|
||||||
|
? "REST"
|
||||||
|
: "GQL"
|
||||||
|
)
|
||||||
|
return E.right({ success: true })
|
||||||
|
}
|
||||||
|
// Backend import failed, fall back to local storage
|
||||||
|
return appendCollectionsToStore(collections, reqType)
|
||||||
|
} catch {
|
||||||
|
// On any error, fall back to local storage
|
||||||
|
return appendCollectionsToStore(collections, reqType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const appendCollectionsToStore = (
|
||||||
|
collections: HoppCollection[],
|
||||||
|
reqType: ReqType
|
||||||
|
) => {
|
||||||
|
if (reqType === ReqType.Rest) {
|
||||||
|
appendRESTCollections(collections)
|
||||||
|
} else {
|
||||||
|
appendGraphqlCollections(collections)
|
||||||
|
}
|
||||||
|
return E.right({ success: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function translateToPersonalCollectionFormat(x: HoppCollection) {
|
||||||
|
const folders: HoppCollection[] = (x.folders ?? []).map(
|
||||||
|
translateToPersonalCollectionFormat
|
||||||
|
)
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
auth: x.auth,
|
||||||
|
headers: x.headers,
|
||||||
|
variables: x.variables,
|
||||||
|
}
|
||||||
|
|
||||||
|
const obj = {
|
||||||
|
...x,
|
||||||
|
folders,
|
||||||
|
data,
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function loadImportedUserCollections(
|
||||||
|
collectionsJSONString: string,
|
||||||
|
collectionType: "REST" | "GQL"
|
||||||
|
) {
|
||||||
|
const importedCollections = (
|
||||||
|
JSON.parse(collectionsJSONString) as Array<
|
||||||
|
ExportedUserCollectionGQL | ExportedUserCollectionREST
|
||||||
|
>
|
||||||
|
).map((collection) => ({ v: 1, ...collection }))
|
||||||
|
runDispatchWithOutSyncing(() => {
|
||||||
|
collectionType === "REST"
|
||||||
|
? appendRESTCollections(
|
||||||
|
importedCollections.map(
|
||||||
|
(collection) =>
|
||||||
|
exportedCollectionToHoppCollection(
|
||||||
|
collection,
|
||||||
|
"REST"
|
||||||
|
) as HoppCollection
|
||||||
|
)
|
||||||
|
)
|
||||||
|
: appendGraphqlCollections(
|
||||||
|
importedCollections.map(
|
||||||
|
(collection) =>
|
||||||
|
exportedCollectionToHoppCollection(
|
||||||
|
collection,
|
||||||
|
"GQL"
|
||||||
|
) as HoppCollection
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -67,6 +67,7 @@ import {
|
||||||
} from "@hoppscotch/data"
|
} from "@hoppscotch/data"
|
||||||
import * as E from "fp-ts/Either"
|
import * as E from "fp-ts/Either"
|
||||||
import { gqlCollectionsSyncer } from "./gqlCollections.sync"
|
import { gqlCollectionsSyncer } from "./gqlCollections.sync"
|
||||||
|
import { importToPersonalWorkspace } from "./import"
|
||||||
|
|
||||||
function initCollectionsSync() {
|
function initCollectionsSync() {
|
||||||
const currentUser$ = platformAuth.getCurrentUserStream()
|
const currentUser$ = platformAuth.getCurrentUserStream()
|
||||||
|
|
@ -98,7 +99,7 @@ function initCollectionsSync() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type ExportedUserCollectionREST = {
|
export type ExportedUserCollectionREST = {
|
||||||
id?: string
|
id?: string
|
||||||
_ref_id?: string
|
_ref_id?: string
|
||||||
folders: ExportedUserCollectionREST[]
|
folders: ExportedUserCollectionREST[]
|
||||||
|
|
@ -107,7 +108,7 @@ type ExportedUserCollectionREST = {
|
||||||
data: string
|
data: string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ExportedUserCollectionGQL = {
|
export type ExportedUserCollectionGQL = {
|
||||||
id?: string
|
id?: string
|
||||||
_ref_id?: string
|
_ref_id?: string
|
||||||
folders: ExportedUserCollectionGQL[]
|
folders: ExportedUserCollectionGQL[]
|
||||||
|
|
@ -125,7 +126,7 @@ function addDescriptionField(
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
function exportedCollectionToHoppCollection(
|
export function exportedCollectionToHoppCollection(
|
||||||
collection: ExportedUserCollectionREST | ExportedUserCollectionGQL,
|
collection: ExportedUserCollectionREST | ExportedUserCollectionGQL,
|
||||||
collectionType: "REST" | "GQL"
|
collectionType: "REST" | "GQL"
|
||||||
): HoppCollection {
|
): HoppCollection {
|
||||||
|
|
@ -1031,6 +1032,7 @@ function setupUserRequestDeletedSubscription() {
|
||||||
|
|
||||||
export const def: CollectionsPlatformDef = {
|
export const def: CollectionsPlatformDef = {
|
||||||
initCollectionsSync,
|
initCollectionsSync,
|
||||||
|
importToPersonalWorkspace,
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCollectionPathFromCollectionID(
|
function getCollectionPathFromCollectionID(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue