amk-dev 9 months ago
parent
commit
4a5042898d

+ 283 - 17
packages/hoppscotch-common/src/services/new-workspace/providers/teams.workspace.ts

@@ -8,7 +8,12 @@ import {
   WorkspaceDecor,
   WorkspaceRequest,
 } from "../workspace"
-import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data"
+import {
+  HoppCollection,
+  HoppRESTAuth,
+  HoppRESTHeader,
+  HoppRESTRequest,
+} from "@hoppscotch/data"
 
 import * as E from "fp-ts/Either"
 import { platform } from "~/platform"
@@ -27,8 +32,8 @@ import { createTeam } from "~/helpers/backend/mutations/Team"
 import { Ref, computed, ref } from "vue"
 import {
   RESTCollectionChildrenView,
+  RESTCollectionJSONView,
   RESTCollectionLevelAuthHeadersView,
-  RESTCollectionViewItem,
   RootRESTCollectionView,
 } from "../view"
 import { runGQLQuery, runGQLSubscription } from "~/helpers/backend/GQLClient"
@@ -53,6 +58,19 @@ import { generateKeyBetween } from "fractional-indexing"
 import IconUser from "~icons/lucide/user"
 import TeamsWorkspaceSelector from "~/components/workspace/TeamsWorkspaceSelector.vue"
 import { lazy } from "~/helpers/utils/lazy"
+import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
+import { initializeDownloadFile } from "~/helpers/import-export/export"
+
+type TeamsWorkspaceCollection = WorkspaceCollection & {
+  parentCollectionID?: string
+  order: string
+  auth: HoppRESTAuth
+  headers: HoppRESTHeader[]
+}
+
+type TeamsWorkspaceRequest = WorkspaceRequest & {
+  order: string
+}
 
 export class TeamsWorkspaceProviderService
   extends Service
@@ -66,18 +84,9 @@ export class TeamsWorkspaceProviderService
 
   private workspaces: Ref<Workspace[]> = ref([])
 
-  private collections: Ref<
-    (WorkspaceCollection & {
-      parentCollectionID?: string
-      order: string
-    })[]
-  > = ref([])
+  private collections: Ref<TeamsWorkspaceCollection[]> = ref([])
 
-  private requests: Ref<
-    (WorkspaceRequest & {
-      order: string
-    })[]
-  > = ref([])
+  private requests: Ref<TeamsWorkspaceRequest[]> = ref([])
 
   private orderedRequests = computed(() => {
     return sortByOrder(this.requests.value)
@@ -716,6 +725,196 @@ export class TeamsWorkspaceProviderService
     })
   }
 
+  async getRESTCollectionLevelAuthHeadersView(
+    collectionHandle: Handle<WorkspaceCollection>
+  ): Promise<E.Either<never, Handle<RESTCollectionLevelAuthHeadersView>>> {
+    return E.right({
+      get: () =>
+        computed(() => {
+          const collectionHandleRef = collectionHandle.get()
+
+          if (!isValidCollectionHandle(collectionHandleRef, this.providerID)) {
+            return {
+              type: "invalid" as const,
+              reason: "INVALID_COLLECTION_HANDLE",
+            }
+          }
+
+          const { collectionID } = collectionHandleRef.value.data
+
+          const collection = this.collections.value.find(
+            (collection) => collection.collectionID === collectionID
+          )
+
+          if (!collection) {
+            return {
+              type: "invalid" as const,
+              reason: "COLLECTION_DOES_NOT_EXIST",
+            }
+          }
+
+          let inheritedAuth: HoppInheritedProperty["auth"] = {
+            parentID: "",
+            parentName: "",
+            inheritedAuth: {
+              authType: "none",
+              authActive: true,
+            },
+          }
+
+          let collectionToProcess: typeof collection | undefined = collection
+
+          // TODO: move this into a function
+          while (collectionToProcess) {
+            if (collectionToProcess.auth.authType !== "inherit") {
+              inheritedAuth = {
+                parentID: collectionToProcess.collectionID,
+                parentName: collectionToProcess.name,
+                inheritedAuth: collectionToProcess.auth,
+              }
+
+              break
+            }
+
+            const parentCollectionID: string | undefined =
+              collectionToProcess.parentCollectionID
+
+            if (!parentCollectionID) {
+              break
+            }
+
+            collectionToProcess = this.collections.value.find(
+              (collection) => collection.collectionID === parentCollectionID
+            )
+          }
+
+          let collectionToProcessHeaders: typeof collection | undefined =
+            collection
+
+          const inheritedHeaders: HoppInheritedProperty["headers"] = []
+
+          const headerKeys = new Set<string>()
+
+          // TODO: move this into a function
+          while (collectionToProcessHeaders) {
+            collectionToProcessHeaders.headers
+              .filter((header) => header.active)
+              .forEach((header) => {
+                if (!headerKeys.has(header.key) && collectionToProcessHeaders) {
+                  inheritedHeaders.push({
+                    parentID: collectionToProcessHeaders.collectionID,
+                    parentName: collectionToProcessHeaders.name,
+                    inheritedHeader: header,
+                  })
+
+                  headerKeys.add(header.key)
+                }
+              })
+
+            const parentCollectionID: string | undefined =
+              collectionToProcessHeaders.parentCollectionID
+
+            if (!parentCollectionID) {
+              break
+            }
+
+            collectionToProcessHeaders = this.collections.value.find(
+              (collection) => collection.collectionID === parentCollectionID
+            )
+          }
+
+          return {
+            data: {
+              auth: inheritedAuth,
+              headers: inheritedHeaders,
+            },
+            type: "ok" as const,
+          }
+        }),
+    })
+  }
+
+  public async exportRESTCollections(
+    workspaceHandle: Handle<WorkspaceCollection>
+  ): Promise<E.Either<unknown, void>> {
+    const workspaceHandleRef = workspaceHandle.get()
+
+    if (!isValidWorkspaceHandle(workspaceHandleRef, this.providerID)) {
+      return E.left("INVALID_WORKSPACE_HANDLE" as const)
+    }
+
+    const workspaceID = workspaceHandleRef.value.data.workspaceID
+
+    const collectionsInWorkspace = this.collections.value.filter(
+      (collection) => {
+        return collection.workspaceID === workspaceID
+      }
+    )
+
+    const requestsInWorkspace = this.requests.value.filter((request) => {
+      return request.workspaceID === workspaceID
+    })
+
+    const tree = makeCollectionTree(collectionsInWorkspace, requestsInWorkspace)
+
+    const downloadRes = await initializeDownloadFile(
+      JSON.stringify(tree, null, 2),
+      "Collections"
+    )
+
+    if (E.isLeft(downloadRes)) {
+      return downloadRes
+    }
+
+    return E.right(undefined)
+  }
+
+  public async getRESTCollectionJSONView(
+    workspaceHandle: Handle<Workspace>
+  ): Promise<E.Either<never, Handle<RESTCollectionJSONView>>> {
+    const workspaceHandleRef = workspaceHandle.get()
+
+    return E.right({
+      get: () =>
+        computed(() => {
+          if (!isValidWorkspaceHandle(workspaceHandleRef, this.providerID)) {
+            return {
+              type: "invalid" as const,
+              reason: "INVALID_WORKSPACE_HANDLE",
+            }
+          }
+
+          const workspaceID = workspaceHandleRef.value.data.workspaceID
+
+          const collectionsInWorkspace = this.collections.value.filter(
+            (collection) => {
+              return collection.workspaceID === workspaceID
+            }
+          )
+
+          const requestsInWorkspace = this.requests.value.filter((request) => {
+            return request.workspaceID === workspaceID
+          })
+
+          const tree = makeCollectionTree(
+            collectionsInWorkspace,
+            requestsInWorkspace
+          )
+
+          const view: RESTCollectionJSONView = {
+            providerID: this.providerID,
+            workspaceID,
+            content: JSON.stringify(tree, null, 2),
+          }
+
+          return {
+            type: "ok" as const,
+            data: view,
+          }
+        }),
+    })
+  }
+
   // this might be temporary, might move this to decor
   async getWorkspaceHandle(
     workspaceID: string
@@ -758,10 +957,6 @@ export class TeamsWorkspaceProviderService
         return
       }
 
-      console.group("Team Collection Added")
-      console.log(result)
-      console.groupEnd()
-
       const parentCollectionID = result.right.teamCollectionAdded.parent?.id
 
       const siblingCollections = this.collections.value.filter(
@@ -1346,6 +1541,77 @@ const sortByOrder = <OrderedItem extends { order: string }>(
   })
 }
 
+// converts the flat collections structure to the HoppCollection tree format
+function makeCollectionTree(
+  collections: TeamsWorkspaceCollection[],
+  requests: TeamsWorkspaceRequest[]
+) {
+  const collectionsTree: HoppCollection[] = []
+  const collectionsMap = new Map<
+    string,
+    HoppCollection & { parentCollectionID?: string; id: string; order: string }
+  >()
+
+  // build a copy of the collections array with empty folders & requests
+  // so we don't mutate the original argument array
+  const hoppCollections = collections.map(
+    (
+      collection
+    ): HoppCollection & {
+      parentCollectionID?: string
+      id: string
+      order: string
+    } => ({
+      parentCollectionID: collection.parentCollectionID,
+      order: collection.order,
+      id: collection.collectionID,
+      name: collection.name,
+      auth: collection.auth,
+      headers: collection.headers,
+      // we'll populate the child collections and child requests in the next steps
+      folders: [],
+      requests: [],
+      v: 2,
+    })
+  )
+
+  const uniqueParentCollectionIDs = new Set<string>()
+
+  hoppCollections.forEach((collection) => {
+    if (collection.parentCollectionID) {
+      uniqueParentCollectionIDs.add(collection.parentCollectionID)
+    } else {
+      collectionsTree.push(collection)
+      uniqueParentCollectionIDs.add(collection.id)
+    }
+
+    collectionsMap.set(collection.id, collection)
+  })
+
+  const collectionsMapArray = Array.from(collectionsMap)
+
+  uniqueParentCollectionIDs.forEach((parentCollectionID) => {
+    const childCollections = collectionsMapArray
+      .filter(([, collection]) => {
+        return collection.parentCollectionID === parentCollectionID
+      })
+      .map(([, collection]) => collection)
+      .sort((a, b) => a.order.localeCompare(b.order))
+
+    const childRequests = requests
+      .filter((request) => request.collectionID === parentCollectionID)
+      .sort((a, b) => a.order.localeCompare(b.order))
+
+    const parentCollection = collectionsMap.get(parentCollectionID)
+    parentCollection?.folders.push(...childCollections)
+    parentCollection?.requests.push(
+      ...childRequests.map((request): HoppRESTRequest => request.request)
+    )
+  })
+
+  return collectionsTree
+}
+
 // TODO
 // where to put the getChildren api call
 // cursor + pagination stuff