refactor: updates based on the provider methods signature changes

This commit is contained in:
jamesgeorge007
2024-02-09 22:49:38 +05:30
parent c1a8a871d2
commit 392b2fc48d
8 changed files with 476 additions and 432 deletions

View File

@@ -292,20 +292,19 @@ const saveRequestAs = async () => {
return
}
const resultHandle = await workspaceService.updateRESTRequest(
const updateRequestResult = await workspaceService.updateRESTRequest(
requestHandle,
updatedRequest
)
if (E.isLeft(resultHandle)) {
if (E.isLeft(updateRequestResult)) {
// WORKSPACE_INVALIDATED | INVALID_REQUEST_HANDLE
return
}
const result = resultHandle.right
if (updateRequestResult.right.type === "invalid") {
// REQUEST_INVALIDATED | REQUEST_PATH_NOT_FOUND
if (result.value.type === "invalid") {
// WORKSPACE_INVALIDATED | INVALID_REQUEST_HANDLE
return
}

View File

@@ -544,9 +544,18 @@ const saveRequest = async () => {
if (E.isLeft(updateRequestResult)) {
// INVALID_REQUEST_HANDLE
showSaveRequestModal.value = true
return
}
if (!tab.value.document.isDirty) {
tab.value.document.isDirty = true
const resultHandle = updateRequestResult.right
if (resultHandle.type === "invalid") {
// REQUEST_INVALIDATED | REQUEST_PATH_NOT_FOUND
if (resultHandle.reason === "REQUEST_PATH_NOT_FOUND") {
// REQUEST_PATH_NOT_FOUND
tab.value.document.saveContext = undefined
await saveRequest()
}
return
}

View File

@@ -139,9 +139,7 @@ import IconImport from "~icons/lucide/folder-down"
import IconHelpCircle from "~icons/lucide/help-circle"
import IconPlus from "~icons/lucide/plus"
import {
cascadeParentCollectionForHeaderAuth,
navigateToFolderWithIndexPath,
restCollectionStore,
restCollections$,
saveRESTRequestAs,
} from "~/newstore/collections"
@@ -256,12 +254,9 @@ const displayConfirmModal = (show: boolean) => {
const addNewRootCollection = async (name: string) => {
modalLoadingState.value = true
const newCollectionID = restCollectionState.value.length.toString()
const result = await workspaceService.createRESTRootCollection(
props.workspaceHandle,
name,
newCollectionID
{ name }
)
if (E.isLeft(result)) {
@@ -306,19 +301,13 @@ const onRemoveRootCollection = async () => {
return
}
const result =
await workspaceService.removeRESTRootCollection(collectionHandle)
const result = await workspaceService.removeRESTCollection(collectionHandle)
if (E.isLeft(result)) {
// INVALID_COLLECTION_HANDLE
return
}
if (result.right.value.type === "invalid") {
// COLLECTION_INVALIDATED
return
}
toast.success(t("state.deleted"))
displayConfirmModal(false)
}
@@ -370,10 +359,24 @@ const onAddRequest = async (requestName: string) => {
return
}
const { auth, headers } = cascadeParentCollectionForHeaderAuth(
requestHandle.value.data.collectionID,
"rest"
)
const cascadingAuthHeadersHandleResult =
await workspaceService.getRESTCollectionLevelAuthHeadersView(
collectionHandle
)
if (E.isLeft(cascadingAuthHeadersHandleResult)) {
// INVALID_COLLECTION_HANDLE
return
}
const cascadingAuthHeadersHandle = cascadingAuthHeadersHandleResult.right
if (cascadingAuthHeadersHandle.value.type === "invalid") {
// COLLECTION_INVALIDATED
return
}
const { auth, headers } = cascadingAuthHeadersHandle.value.data
tabs.createNewTab({
request: newRequest,
@@ -396,7 +399,7 @@ const addChildCollection = (parentCollectionIndexPath: string) => {
displayModalAddChildColl(true)
}
const onAddChildCollection = async (childCollectionName: string) => {
const onAddChildCollection = async (newChildCollectionName: string) => {
const parentCollectionIndexPath = editingCollectionIndexPath.value
const collectionHandleResult = await workspaceService.getCollectionHandle(
@@ -418,7 +421,7 @@ const onAddChildCollection = async (childCollectionName: string) => {
const result = await workspaceService.createRESTChildCollection(
collectionHandle,
childCollectionName
{ name: newChildCollectionName }
)
if (E.isLeft(result)) {
@@ -466,29 +469,15 @@ const onEditRootCollection = async (newCollectionName: string) => {
return
}
// We're sure that the collection exists in the given `collectionIndexPath` as there's a validation happening in `getCollectionHandle` above
const updatedCollection = navigateToFolderWithIndexPath(
restCollectionStore.value.state,
collectionIndexPath.split("/").map((id) => parseInt(id))
) as HoppCollection
updatedCollection.name = newCollectionName
const result = await workspaceService.editRESTCollection(
collectionHandle,
updatedCollection
)
const result = await workspaceService.updateRESTCollection(collectionHandle, {
name: newCollectionName,
})
if (E.isLeft(result)) {
// INVALID_COLLECTION_HANDLE
return
}
if (result.right.value.type === "invalid") {
// COLLECTION_INVALIDATED
return
}
displayModalEditCollection(false)
toast.success(t("collection.renamed"))
}
@@ -505,7 +494,7 @@ const editChildCollection = (payload: {
displayModalEditChildCollection(true)
}
const onEditChildCollection = async (newCollectionName: string) => {
const onEditChildCollection = async (newChildCollectionName: string) => {
const collectionIndexPath = editingChildCollectionIndexPath.value
const collectionHandleResult = await workspaceService.getCollectionHandle(
@@ -525,29 +514,15 @@ const onEditChildCollection = async (newCollectionName: string) => {
return
}
// We're sure that the collection exists in the given `collectionIndexPath` as there's a validation happening in `getCollectionHandle` above
const updatedCollection = navigateToFolderWithIndexPath(
restCollectionStore.value.state,
collectionIndexPath.split("/").map((id) => parseInt(id))
) as HoppCollection
updatedCollection.name = newCollectionName
const result = await workspaceService.editRESTCollection(
collectionHandle,
updatedCollection
)
const result = await workspaceService.updateRESTCollection(collectionHandle, {
name: newChildCollectionName,
})
if (E.isLeft(result)) {
// INVALID_COLLECTION_HANDLE
return
}
if (result.right.value.type === "invalid") {
// COLLECTION_INVALIDATED
return
}
displayModalEditChildCollection(false)
toast.success(t("collection.renamed"))
}
@@ -580,7 +555,7 @@ const onRemoveChildCollection = async () => {
return
}
const result = await workspaceService.removeRESTChildCollection(
const result = await workspaceService.removeRESTCollection(
parentCollectionHandle
)
@@ -589,11 +564,6 @@ const onRemoveChildCollection = async () => {
return
}
if (result.right.value.type === "invalid") {
// COLLECTION_INVALIDATED
return
}
toast.success(t("state.deleted"))
displayConfirmModal(false)
}
@@ -635,11 +605,6 @@ const onRemoveRequest = async () => {
return
}
if (result.right.value.type === "invalid") {
// WORKSPACE_INVALIDATED
return
}
const possibleTab = tabs.getTabRefWithSaveContext({
originLocation: "workspace-user-collection",
requestHandle,
@@ -669,6 +634,23 @@ const onRemoveRequest = async () => {
const selectRequest = async (requestIndexPath: string) => {
const collectionIndexPath = requestIndexPath.split("/").slice(0, -1).join("/")
const collectionHandleResult = await workspaceService.getCollectionHandle(
props.workspaceHandle,
collectionIndexPath
)
if (E.isLeft(collectionHandleResult)) {
// INVALID_WORKSPACE_HANDLE
return
}
const collectionHandle = collectionHandleResult.right
if (collectionHandle.value.type === "invalid") {
// WORKSPACE_INVALIDATED | INVALID_COLLECTION_HANDLE
return
}
const requestHandleResult = await workspaceService.getRequestHandle(
props.workspaceHandle,
requestIndexPath
@@ -686,15 +668,30 @@ const selectRequest = async (requestIndexPath: string) => {
return
}
const request = requestHandle.value.data.request as HoppRESTRequest
const request = requestHandle.value.data.request
// If there is a request with this save context, switch into it
let possibleTab = null
const { auth, headers } = cascadeParentCollectionForHeaderAuth(
collectionIndexPath,
"rest"
)
const cascadingAuthHeadersHandleResult =
await workspaceService.getRESTCollectionLevelAuthHeadersView(
collectionHandle
)
if (E.isLeft(cascadingAuthHeadersHandleResult)) {
// INVALID_COLLECTION_HANDLE
return
}
const cascadingAuthHeadersHandle = cascadingAuthHeadersHandleResult.right
if (cascadingAuthHeadersHandle.value.type === "invalid") {
// COLLECTION_INVALIDATED
return
}
const { auth, headers } = cascadingAuthHeadersHandle.value.data
possibleTab = tabs.getTabRefWithSaveContext({
originLocation: "workspace-user-collection",
requestHandle,
@@ -766,7 +763,7 @@ const editRequest = (payload: {
displayModalEditRequest(true)
}
const onEditRequest = async (newReqName: string) => {
const onEditRequest = async (newRequestName: string) => {
const requestID = editingRequestIndexPath.value
const requestHandleResult = await workspaceService.getRequestHandle(
@@ -786,22 +783,16 @@ const onEditRequest = async (newReqName: string) => {
return
}
const updatedRequest = {
...requestHandle.value.data.request,
name: newReqName,
} as HoppRESTRequest
const result = await workspaceService.updateRESTRequest(
requestHandle,
updatedRequest
)
const result = await workspaceService.updateRESTRequest(requestHandle, {
name: newRequestName,
})
if (E.isLeft(result)) {
// INVALID_REQUEST_HANDLE
return
}
if (result.right.value.type === "invalid") {
if (result.right.type === "invalid") {
// REQUEST_INVALIDATED
return
}
@@ -830,18 +821,6 @@ const editCollectionProperties = async (collectionIndexPath: string) => {
},
],
} as HoppInheritedProperty
// Have a provider level implementation that returns a view that says what the headesd and auth are
if (parentIndex) {
const { auth, headers } = cascadeParentCollectionForHeaderAuth(
parentIndex,
"rest"
)
inheritedProperties = {
auth,
headers,
}
}
const collectionHandleResult = await workspaceService.getCollectionHandle(
props.workspaceHandle,
@@ -860,6 +839,32 @@ const editCollectionProperties = async (collectionIndexPath: string) => {
return
}
if (parentIndex) {
const cascadingAuthHeadersHandleResult =
await workspaceService.getRESTCollectionLevelAuthHeadersView(
collectionHandle
)
if (E.isLeft(cascadingAuthHeadersHandleResult)) {
// INVALID_COLLECTION_HANDLE
return
}
const cascadingAuthHeadersHandle = cascadingAuthHeadersHandleResult.right
if (cascadingAuthHeadersHandle.value.type === "invalid") {
// COLLECTION_INVALIDATED
return
}
const { auth, headers } = cascadingAuthHeadersHandle.value.data
inheritedProperties = {
auth,
headers,
}
}
const collection = navigateToFolderWithIndexPath(
restCollectionState.value,
collectionIndexPath.split("/").map((id) => parseInt(id))
@@ -899,35 +904,35 @@ const setCollectionProperties = async (updatedCollectionProps: {
return
}
// We're sure that the collection exists in the given `collectionIndexPath` as there's a validation happening in `getCollectionHandle` above
const collection = navigateToFolderWithIndexPath(
restCollectionStore.value.state,
collectionIndexPath.split("/").map((id) => parseInt(id))
) as HoppCollection
const updatedCollection = {
...collection,
const result = await workspaceService.updateRESTCollection(collectionHandle, {
auth,
headers,
}
const result = await workspaceService.editRESTCollection(
collectionHandle,
updatedCollection
)
})
if (E.isLeft(result)) {
// INVALID_COLLECTION_HANDLE
return
}
if (result.right.value.type === "invalid") {
const cascadingAuthHeadersHandleResult =
await workspaceService.getRESTCollectionLevelAuthHeadersView(
collectionHandle
)
if (E.isLeft(cascadingAuthHeadersHandleResult)) {
// INVALID_COLLECTION_HANDLE
return
}
const cascadingAuthHeadersHandle = cascadingAuthHeadersHandleResult.right
if (cascadingAuthHeadersHandle.value.type === "invalid") {
// COLLECTION_INVALIDATED
return
}
const { auth: cascadedAuth, headers: cascadedHeaders } =
cascadeParentCollectionForHeaderAuth(collectionIndexPath, "rest")
cascadingAuthHeadersHandle.value.data
nextTick(() => {
updateInheritedPropertiesForAffectedRequests(

View File

@@ -17,3 +17,19 @@ export type HoppInheritedProperty = {
inheritedHeader: HoppRESTHeader | GQLHeader
}[]
}
type ModifiedAuth<T, AuthType> = {
[K in keyof T]: K extends 'inheritedAuth' ? Extract<T[K], AuthType> : T[K]
}
type ModifiedHeaders<T, HeaderType> = {
[K in keyof T]: K extends 'inheritedHeader' ? Extract<T[K], HeaderType> : T[K]
}
type ModifiedHoppInheritedProperty<AuthType, HeaderType> = {
auth: ModifiedAuth<HoppInheritedProperty['auth'], AuthType>
headers: ModifiedHeaders<HoppInheritedProperty['headers'][number], HeaderType>[]
}
export type HoppInheritedRESTProperty = ModifiedHoppInheritedProperty<HoppRESTAuth, HoppRESTHeader>

View File

@@ -12,7 +12,7 @@ import { WorkspaceProvider } from "./provider"
import { HandleRef } from "./handle"
import * as E from "fp-ts/Either"
import { Workspace, WorkspaceCollection, WorkspaceRequest } from "./workspace"
import { RESTCollectionChildrenView, RootRESTCollectionView } from "./view"
import { RESTCollectionChildrenView, RESTCollectionLevelAuthHeadersView, RootRESTCollectionView } from "./view"
import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data"
export type WorkspaceError<ServiceErr> =
@@ -170,8 +170,7 @@ export class NewWorkspaceService extends Service {
public async createRESTRootCollection(
workspaceHandle: HandleRef<Workspace>,
collectionName: string,
newCollectionID: string
newCollection: Partial<HoppCollection>
): Promise<
E.Either<
WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
@@ -192,8 +191,7 @@ export class NewWorkspaceService extends Service {
const result = await provider.createRESTRootCollection(
workspaceHandle,
collectionName,
newCollectionID
newCollection
)
if (E.isLeft(result)) {
@@ -205,7 +203,7 @@ export class NewWorkspaceService extends Service {
public async createRESTChildCollection(
parentCollectionHandle: HandleRef<WorkspaceCollection>,
collectionName: string
newChildCollection: Partial<HoppCollection>
): Promise<
E.Either<
WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
@@ -226,7 +224,7 @@ export class NewWorkspaceService extends Service {
const result = await provider.createRESTChildCollection(
parentCollectionHandle,
collectionName
newChildCollection
)
if (E.isLeft(result)) {
@@ -236,14 +234,11 @@ export class NewWorkspaceService extends Service {
return E.right(result.right)
}
public async editRESTCollection(
public async updateRESTCollection(
collectionHandle: HandleRef<WorkspaceCollection>,
updatedCollection: HoppCollection
updatedCollection: Partial<HoppCollection>
): Promise<
E.Either<
WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
HandleRef<boolean>
>
E.Either<WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">, void>
> {
if (collectionHandle.value.type === "invalid") {
return E.left({ type: "SERVICE_ERROR", error: "INVALID_HANDLE" })
@@ -257,7 +252,7 @@ export class NewWorkspaceService extends Service {
return E.left({ type: "SERVICE_ERROR", error: "INVALID_PROVIDER" })
}
const result = await provider.editRESTCollection(
const result = await provider.updateRESTCollection(
collectionHandle,
updatedCollection
)
@@ -266,16 +261,13 @@ export class NewWorkspaceService extends Service {
return E.left({ type: "PROVIDER_ERROR", error: result.left })
}
return E.right(result.right)
return E.right(undefined)
}
public async removeRESTRootCollection(
public async removeRESTCollection(
collectionHandle: HandleRef<WorkspaceCollection>
): Promise<
E.Either<
WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
HandleRef<boolean>
>
E.Either<WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">, void>
> {
if (collectionHandle.value.type === "invalid") {
return E.left({ type: "SERVICE_ERROR", error: "INVALID_HANDLE" })
@@ -289,44 +281,13 @@ export class NewWorkspaceService extends Service {
return E.left({ type: "SERVICE_ERROR", error: "INVALID_PROVIDER" })
}
const result = await provider.removeRESTRootCollection(collectionHandle)
const result = await provider.removeRESTCollection(collectionHandle)
if (E.isLeft(result)) {
return E.left({ type: "PROVIDER_ERROR", error: result.left })
}
return E.right(result.right)
}
public async removeRESTChildCollection(
parentCollectionHandle: HandleRef<WorkspaceCollection>
): Promise<
E.Either<
WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
HandleRef<boolean>
>
> {
if (parentCollectionHandle.value.type === "invalid") {
return E.left({ type: "SERVICE_ERROR", error: "INVALID_HANDLE" })
}
const provider = this.registeredProviders.get(
parentCollectionHandle.value.data.providerID
)
if (!provider) {
return E.left({ type: "SERVICE_ERROR", error: "INVALID_PROVIDER" })
}
const result = await provider.removeRESTChildCollection(
parentCollectionHandle
)
if (E.isLeft(result)) {
return E.left({ type: "PROVIDER_ERROR", error: result.left })
}
return E.right(result.right)
return E.right(undefined)
}
public async createRESTRequest(
@@ -365,10 +326,7 @@ export class NewWorkspaceService extends Service {
public async removeRESTRequest(
requestHandle: HandleRef<WorkspaceRequest>
): Promise<
E.Either<
WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
HandleRef<boolean>
>
E.Either<WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">, void>
> {
if (requestHandle.value.type === "invalid") {
return E.left({ type: "SERVICE_ERROR", error: "INVALID_HANDLE" })
@@ -388,16 +346,16 @@ export class NewWorkspaceService extends Service {
return E.left({ type: "PROVIDER_ERROR", error: result.left })
}
return E.right(result.right)
return E.right(undefined)
}
public async updateRESTRequest(
requestHandle: HandleRef<WorkspaceRequest>,
updatedRequest: HoppRESTRequest
updatedRequest: Partial<HoppRESTRequest>
): Promise<
E.Either<
WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
HandleRef<boolean>
HandleRef<boolean>["value"]
>
> {
if (requestHandle.value.type === "invalid") {
@@ -483,6 +441,36 @@ export class NewWorkspaceService extends Service {
return E.right(result.right)
}
public async getRESTCollectionLevelAuthHeadersView(
collectionHandle: HandleRef<WorkspaceCollection>
): Promise<
E.Either<
WorkspaceError<"INVALID_HANDLE" | "INVALID_PROVIDER">,
HandleRef<RESTCollectionLevelAuthHeadersView>
>
> {
if (collectionHandle.value.type === "invalid") {
return E.left({ type: "SERVICE_ERROR", error: "INVALID_HANDLE" })
}
const provider = this.registeredProviders.get(
collectionHandle.value.data.providerID
)
if (!provider) {
return E.left({ type: "SERVICE_ERROR", error: "INVALID_PROVIDER" })
}
const result =
await provider.getRESTCollectionLevelAuthHeadersView(collectionHandle)
if (E.isLeft(result)) {
return E.left({ type: "PROVIDER_ERROR", error: result.left })
}
return E.right(result.right)
}
public registerWorkspaceProvider(provider: WorkspaceProvider) {
if (this.registeredProviders.has(provider.providerID)) {
console.warn(

View File

@@ -7,7 +7,11 @@ import {
WorkspaceDecor,
WorkspaceRequest,
} from "./workspace"
import { RESTCollectionChildrenView, RootRESTCollectionView } from "./view"
import {
RESTCollectionLevelAuthHeadersView,
RESTCollectionChildrenView,
RootRESTCollectionView,
} from "./view"
import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data"
export interface WorkspaceProvider {
@@ -33,38 +37,34 @@ export interface WorkspaceProvider {
getRESTCollectionChildrenView(
collectionHandle: HandleRef<WorkspaceCollection>
): Promise<E.Either<unknown, HandleRef<RESTCollectionChildrenView>>>
// getRESTCollectionAuthHeaders(
// collectionHandle: HandleRef<WorkspaceCollection>
// ): Promise<E.Either<unknown, HandleRef<RESTCollectionAuthHeadersView>>>
getRESTCollectionLevelAuthHeadersView(
collectionHandle: HandleRef<WorkspaceCollection>
): Promise<E.Either<unknown, HandleRef<RESTCollectionLevelAuthHeadersView>>>
createRESTRootCollection(
workspaceHandle: HandleRef<Workspace>,
collectionName: string,
newCollectionID: string
newCollection: Partial<HoppCollection>
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>>
createRESTChildCollection(
parentCollectionHandle: HandleRef<WorkspaceCollection>,
collectionName: string
newChildCollection: Partial<HoppCollection>
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>>
editRESTCollection(
updateRESTCollection(
collectionHandle: HandleRef<WorkspaceCollection>,
updatedCollection: HoppCollection
): Promise<E.Either<unknown, HandleRef<boolean>>>
removeRESTRootCollection(
updatedCollection: Partial<HoppCollection>
): Promise<E.Either<unknown, void>>
removeRESTCollection(
collectionHandle: HandleRef<WorkspaceCollection>
): Promise<E.Either<unknown, HandleRef<boolean>>>
removeRESTChildCollection(
parentCollectionHandle: HandleRef<WorkspaceCollection>
): Promise<E.Either<unknown, HandleRef<boolean>>>
): Promise<E.Either<unknown, void>>
createRESTRequest(
parentCollectionHandle: HandleRef<WorkspaceCollection>,
request: HoppRESTRequest
newRequest: HoppRESTRequest
): Promise<E.Either<unknown, HandleRef<WorkspaceRequest>>>
updateRESTRequest(
requestHandle: HandleRef<WorkspaceRequest>,
updatedRequest: HoppRESTRequest
): Promise<E.Either<unknown, HandleRef<boolean>>>
updatedRequest: Partial<HoppRESTRequest>
): Promise<E.Either<unknown, HandleRef<boolean>["value"]>>
removeRESTRequest(
requestHandle: HandleRef<WorkspaceRequest>
): Promise<E.Either<unknown, HandleRef<boolean>>>
): Promise<E.Either<unknown, void>>
}

View File

@@ -1,4 +1,10 @@
import { HoppCollection, makeCollection } from "@hoppscotch/data"
import {
HoppCollection,
HoppGQLAuth,
HoppRESTAuth,
HoppRESTHeaders,
makeCollection,
} from "@hoppscotch/data"
import { Service } from "dioc"
import * as E from "fp-ts/Either"
import { Ref, computed, markRaw, ref, shallowRef } from "vue"
@@ -24,6 +30,7 @@ import { platform } from "~/platform"
import { HandleRef } from "~/services/new-workspace/handle"
import { WorkspaceProvider } from "~/services/new-workspace/provider"
import {
RESTCollectionLevelAuthHeadersView,
RESTCollectionChildrenView,
RESTCollectionViewItem,
RootRESTCollectionView,
@@ -43,6 +50,9 @@ import {
resolveSaveContextOnCollectionReorder,
getFoldersByPath,
} from "~/helpers/collection/collection"
import { HoppGQLHeader } from "~/helpers/graphql"
import { HoppInheritedProperty } from "~/helpers/types/HoppInheritedProperties"
import { computedAsync } from "@vueuse/core"
export class PersonalWorkspaceProviderService
extends Service
@@ -88,8 +98,7 @@ export class PersonalWorkspaceProviderService
public createRESTRootCollection(
workspaceHandle: HandleRef<Workspace>,
collectionName: string,
newCollectionID: string
newCollection: Partial<HoppCollection>
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>> {
if (
workspaceHandle.value.type !== "ok" ||
@@ -113,8 +122,12 @@ export class PersonalWorkspaceProviderService
}
}
const newCollectionName = newCollection.name as string
const newCollectionID =
this.restCollectionState.value.state.length.toString()
const newRootCollection = makeCollection({
name: collectionName,
name: newCollectionName,
folders: [],
requests: [],
headers: [],
@@ -138,7 +151,7 @@ export class PersonalWorkspaceProviderService
providerID: this.providerID,
workspaceID: workspaceHandle.value.data.workspaceID,
collectionID: newCollectionID,
name: collectionName,
name: newCollectionName,
},
}
})
@@ -147,13 +160,13 @@ export class PersonalWorkspaceProviderService
}
public createRESTChildCollection(
parentCollHandle: HandleRef<WorkspaceCollection>,
collectionName: string
parentCollectionHandle: HandleRef<WorkspaceCollection>,
newChildCollection: Partial<HoppCollection>
): Promise<E.Either<unknown, HandleRef<WorkspaceCollection>>> {
if (
parentCollHandle.value.type !== "ok" ||
parentCollHandle.value.data.providerID !== this.providerID ||
parentCollHandle.value.data.workspaceID !== "personal"
parentCollectionHandle.value.type !== "ok" ||
parentCollectionHandle.value.data.providerID !== this.providerID ||
parentCollectionHandle.value.data.workspaceID !== "personal"
) {
return Promise.resolve(E.left("INVALID_COLLECTION_HANDLE" as const))
}
@@ -162,9 +175,9 @@ export class PersonalWorkspaceProviderService
E.right(
computed(() => {
if (
parentCollHandle.value.type !== "ok" ||
parentCollHandle.value.data.providerID !== this.providerID ||
parentCollHandle.value.data.workspaceID !== "personal"
parentCollectionHandle.value.type !== "ok" ||
parentCollectionHandle.value.data.providerID !== this.providerID ||
parentCollectionHandle.value.data.workspaceID !== "personal"
) {
return {
type: "invalid" as const,
@@ -173,9 +186,10 @@ export class PersonalWorkspaceProviderService
}
const { collectionID, providerID, workspaceID } =
parentCollHandle.value.data
parentCollectionHandle.value.data
addRESTFolder(collectionName, collectionID)
const newCollectionName = newChildCollection.name as string
addRESTFolder(newCollectionName, collectionID)
platform.analytics?.logEvent({
type: "HOPP_CREATE_COLLECTION",
@@ -190,7 +204,7 @@ export class PersonalWorkspaceProviderService
providerID,
workspaceID,
collectionID,
name: collectionName,
name: newCollectionName,
},
}
})
@@ -198,186 +212,111 @@ export class PersonalWorkspaceProviderService
)
}
public editRESTCollection(
collHandle: HandleRef<WorkspaceCollection>,
updatedCollection: HoppCollection
): Promise<E.Either<unknown, HandleRef<boolean>>> {
public updateRESTCollection(
collectionHandle: HandleRef<WorkspaceCollection>,
updatedCollection: Partial<HoppCollection>
): Promise<E.Either<unknown, void>> {
if (
collHandle.value.type !== "ok" ||
collHandle.value.data.providerID !== this.providerID ||
collHandle.value.data.workspaceID !== "personal"
collectionHandle.value.type !== "ok" ||
collectionHandle.value.data.providerID !== this.providerID ||
collectionHandle.value.data.workspaceID !== "personal"
) {
return Promise.resolve(E.left("INVALID_WORKSPACE_HANDLE" as const))
}
return Promise.resolve(
E.right(
computed(() => {
if (
collHandle.value.type !== "ok" ||
collHandle.value.data.providerID !== this.providerID ||
collHandle.value.data.workspaceID !== "personal"
) {
return {
type: "invalid" as const,
reason: "WORKSPACE_INVALIDATED" as const,
}
}
const { collectionID } = collectionHandle.value.data
const { collectionID } = collHandle.value.data
const collection: HoppCollection | null =
navigateToFolderWithIndexPath(
this.restCollectionState.value.state,
collectionID.split("/").map((id) => parseInt(id))
)
if (!collection) {
return {
type: "invalid" as const,
reason: "COLLECTION_NOT_FOUND" as const,
}
}
const isRootCollection = collectionID.split("/").length === 1
if (isRootCollection) {
editRESTCollection(parseInt(collectionID), updatedCollection)
} else {
editRESTFolder(collectionID, updatedCollection)
}
return {
type: "ok",
data: true,
}
})
)
const collection = navigateToFolderWithIndexPath(
this.restCollectionState.value.state,
collectionID.split("/").map((id) => parseInt(id))
)
}
public removeRESTRootCollection(
collHandle: HandleRef<WorkspaceCollection>
): Promise<E.Either<unknown, HandleRef<boolean>>> {
if (
collHandle.value.type !== "ok" ||
collHandle.value.data.providerID !== this.providerID ||
collHandle.value.data.workspaceID !== "personal"
) {
return Promise.resolve(E.left("INVALID_WORKSPACE_HANDLE" as const))
const newCollection = {
...collection,
...updatedCollection,
}
return Promise.resolve(
E.right(
computed(() => {
if (
collHandle.value.type !== "ok" ||
collHandle.value.data.providerID !== this.providerID ||
collHandle.value.data.workspaceID !== "personal"
) {
return {
type: "invalid" as const,
reason: "WORKSPACE_INVALIDATED" as const,
}
}
const isRootCollection = collectionID.split("/").length === 1
const { collectionID } = collHandle.value.data
if (isRootCollection) {
editRESTCollection(parseInt(collectionID), newCollection)
} else {
editRESTFolder(collectionID, newCollection)
}
const collectionIndex = parseInt(collectionID)
const collectionToRemove = navigateToFolderWithIndexPath(
restCollectionStore.value.state,
[collectionIndex]
)
removeRESTCollection(
collectionIndex,
collectionToRemove ? collectionToRemove.id : undefined
)
resolveSaveContextOnCollectionReorder({
lastIndex: collectionIndex,
newIndex: -1,
folderPath: "", // root collection
length: this.restCollectionState.value.state.length,
})
return {
type: "ok",
data: true,
}
})
)
)
return Promise.resolve(E.right(undefined))
}
public removeRESTChildCollection(
parentCollHandle: HandleRef<WorkspaceCollection>
): Promise<E.Either<unknown, HandleRef<boolean>>> {
public removeRESTCollection(
collectionHandle: HandleRef<WorkspaceCollection>
): Promise<E.Either<unknown, void>> {
if (
parentCollHandle.value.type !== "ok" ||
parentCollHandle.value.data.providerID !== this.providerID ||
parentCollHandle.value.data.workspaceID !== "personal"
collectionHandle.value.type !== "ok" ||
collectionHandle.value.data.providerID !== this.providerID ||
collectionHandle.value.data.workspaceID !== "personal"
) {
return Promise.resolve(E.left("INVALID_COLLECTION_HANDLE" as const))
}
return Promise.resolve(
E.right(
computed(() => {
if (
parentCollHandle.value.type !== "ok" ||
parentCollHandle.value.data.providerID !== this.providerID ||
parentCollHandle.value.data.workspaceID !== "personal"
) {
return {
type: "invalid" as const,
reason: "COLLECTION_INVALIDATED" as const,
}
}
const { collectionID } = collectionHandle.value.data
const { collectionID } = parentCollHandle.value.data
const isRootCollection = collectionID.split("/").length === 1
const folderToRemove = path
? navigateToFolderWithIndexPath(
restCollectionStore.value.state,
collectionID.split("/").map((id) => parseInt(id))
)
: undefined
if (isRootCollection) {
const collectionIndex = parseInt(collectionID)
removeRESTFolder(
collectionID,
folderToRemove ? folderToRemove.id : undefined
)
const parentFolder = collectionID.split("/").slice(0, -1).join("/") // remove last folder to get parent folder
resolveSaveContextOnCollectionReorder({
lastIndex: this.pathToLastIndex(collectionID),
newIndex: -1,
folderPath: parentFolder,
length: getFoldersByPath(
this.restCollectionState.value.state,
parentFolder
).length,
})
return {
type: "ok",
data: true,
}
})
const collectionToRemove = navigateToFolderWithIndexPath(
restCollectionStore.value.state,
[collectionIndex]
)
)
removeRESTCollection(
collectionIndex,
collectionToRemove ? collectionToRemove.id : undefined
)
resolveSaveContextOnCollectionReorder({
lastIndex: collectionIndex,
newIndex: -1,
folderPath: "", // root collection
length: this.restCollectionState.value.state.length,
})
} else {
const folderToRemove = path
? navigateToFolderWithIndexPath(
restCollectionStore.value.state,
collectionID.split("/").map((id) => parseInt(id))
)
: undefined
removeRESTFolder(
collectionID,
folderToRemove ? folderToRemove.id : undefined
)
const parentFolder = collectionID.split("/").slice(0, -1).join("/") // Remove last folder to get parent folder
resolveSaveContextOnCollectionReorder({
lastIndex: this.pathToLastIndex(collectionID),
newIndex: -1,
folderPath: parentFolder,
length: getFoldersByPath(
this.restCollectionState.value.state,
parentFolder
).length,
})
}
return Promise.resolve(E.right(undefined))
}
public createRESTRequest(
parentCollHandle: HandleRef<WorkspaceCollection>,
parentCollectionHandle: HandleRef<WorkspaceCollection>,
newRequest: HoppRESTRequest
): Promise<E.Either<unknown, HandleRef<WorkspaceRequest>>> {
if (
parentCollHandle.value.type !== "ok" ||
parentCollHandle.value.data.providerID !== this.providerID ||
parentCollHandle.value.data.workspaceID !== "personal"
parentCollectionHandle.value.type !== "ok" ||
parentCollectionHandle.value.data.providerID !== this.providerID ||
parentCollectionHandle.value.data.workspaceID !== "personal"
) {
return Promise.resolve(E.left("INVALID_COLLECTION_HANDLE" as const))
}
@@ -386,9 +325,9 @@ export class PersonalWorkspaceProviderService
E.right(
computed(() => {
if (
parentCollHandle.value.type !== "ok" ||
parentCollHandle.value.data.providerID !== this.providerID ||
parentCollHandle.value.data.workspaceID !== "personal"
parentCollectionHandle.value.type !== "ok" ||
parentCollectionHandle.value.data.providerID !== this.providerID ||
parentCollectionHandle.value.data.workspaceID !== "personal"
) {
return {
type: "invalid" as const,
@@ -397,7 +336,7 @@ export class PersonalWorkspaceProviderService
}
const { collectionID, providerID, workspaceID } =
parentCollHandle.value.data
parentCollectionHandle.value.data
const insertionIndex = saveRESTRequestAs(collectionID, newRequest)
@@ -427,7 +366,7 @@ export class PersonalWorkspaceProviderService
public removeRESTRequest(
requestHandle: HandleRef<WorkspaceRequest>
): Promise<E.Either<unknown, HandleRef<boolean>>> {
): Promise<E.Either<unknown, void>> {
if (
requestHandle.value.type !== "ok" ||
requestHandle.value.data.providerID !== this.providerID ||
@@ -436,43 +375,23 @@ export class PersonalWorkspaceProviderService
return Promise.resolve(E.left("INVALID_REQUEST_HANDLE" as const))
}
return Promise.resolve(
E.right(
computed(() => {
if (
requestHandle.value.type !== "ok" ||
requestHandle.value.data.providerID !== this.providerID ||
requestHandle.value.data.workspaceID !== "personal"
) {
return {
type: "invalid" as const,
reason: "REQUEST_INVALIDATED" as const,
}
}
const { collectionID, requestID } = requestHandle.value.data
const requestIndex = parseInt(requestID.split("/").slice(-1)[0])
const { collectionID, requestID } = requestHandle.value.data
const requestIndex = parseInt(requestID.split("/").slice(-1)[0])
const requestToRemove = navigateToFolderWithIndexPath(
restCollectionStore.value.state,
collectionID.split("/").map((id) => parseInt(id))
)?.requests[requestIndex]
const requestToRemove = navigateToFolderWithIndexPath(
restCollectionStore.value.state,
collectionID.split("/").map((id) => parseInt(id))
)?.requests[requestIndex]
removeRESTRequest(collectionID, requestIndex, requestToRemove?.id)
removeRESTRequest(collectionID, requestIndex, requestToRemove?.id)
return {
type: "ok",
data: true,
}
})
)
)
return Promise.resolve(E.right(undefined))
}
public updateRESTRequest(
requestHandle: HandleRef<WorkspaceRequest>,
updatedRequest: HoppRESTRequest
): Promise<E.Either<unknown, HandleRef<boolean>>> {
updatedRequest: Partial<HoppRESTRequest>
): Promise<E.Either<unknown, HandleRef<boolean>["value"]>> {
if (
requestHandle.value.type !== "ok" ||
requestHandle.value.data.providerID !== this.providerID ||
@@ -481,45 +400,36 @@ export class PersonalWorkspaceProviderService
return Promise.resolve(E.left("INVALID_REQUEST_HANDLE" as const))
}
return Promise.resolve(
E.right(
computed(() => {
if (
requestHandle.value.type !== "ok" ||
requestHandle.value.data.providerID !== this.providerID ||
requestHandle.value.data.workspaceID !== "personal"
) {
return {
type: "invalid" as const,
reason: "REQUEST_INVALIDATED" as const,
}
}
const { collectionID, requestID, request } = requestHandle.value.data
const { collectionID, requestID } = requestHandle.value.data
try {
const newRequest: HoppRESTRequest = {
...request,
...updatedRequest,
}
const requestIndex = parseInt(requestID)
editRESTRequest(collectionID, requestIndex, newRequest)
try {
const requestIndex = parseInt(requestID)
editRESTRequest(collectionID, requestIndex, updatedRequest)
platform.analytics?.logEvent({
type: "HOPP_SAVE_REQUEST",
platform: "rest",
createdNow: false,
workspaceType: "personal",
})
} catch (err) {
return {
type: "invalid" as const,
reason: "REQUEST_PATH_NOT_FOUND" as const,
}
}
return {
type: "ok",
data: true,
}
platform.analytics?.logEvent({
type: "HOPP_SAVE_REQUEST",
platform: "rest",
createdNow: false,
workspaceType: "personal",
})
} catch (err) {
return Promise.resolve(
E.right({
type: "invalid" as const,
reason: "REQUEST_PATH_NOT_FOUND" as const,
})
)
}
return Promise.resolve(
E.right({
type: "ok",
data: true,
})
)
}
@@ -766,6 +676,117 @@ export class PersonalWorkspaceProviderService
)
}
public getRESTCollectionLevelAuthHeadersView(
collectionHandle: HandleRef<WorkspaceCollection>
): Promise<E.Either<never, HandleRef<RESTCollectionLevelAuthHeadersView>>> {
return Promise.resolve(
E.right(
computed(() => {
if (
collectionHandle.value.type === "invalid" ||
collectionHandle.value.data.providerID !== this.providerID ||
collectionHandle.value.data.workspaceID !== "personal"
) {
return {
type: "invalid" as const,
reason: "INVALID_COLLECTION_HANDLE" as const,
}
}
const { collectionID } = collectionHandle.value.data
let auth: HoppInheritedProperty["auth"] = {
parentID: collectionID ?? "",
parentName: "",
inheritedAuth: {
authType: "none",
authActive: true,
},
}
const headers: HoppInheritedProperty["headers"] = []
if (!collectionID) return { type: "ok", data: { auth, headers } }
const path = collectionID.split("/").map((i) => parseInt(i))
// Check if the path is empty or invalid
if (!path || path.length === 0) {
console.error("Invalid path:", collectionID)
return { type: "ok", data: { auth, headers } }
}
// Loop through the path and get the last parent folder with authType other than 'inherit'
for (let i = 0; i < path.length; i++) {
const parentFolder = navigateToFolderWithIndexPath(
this.restCollectionState.value.state,
[...path.slice(0, i + 1)] // Create a copy of the path array
)
// Check if parentFolder is undefined or null
if (!parentFolder) {
console.error("Parent folder not found for path:", path)
return { type: "ok", data: { auth, headers } }
}
const parentFolderAuth = parentFolder.auth as
| HoppRESTAuth
| HoppGQLAuth
const parentFolderHeaders = parentFolder.headers as
| HoppRESTHeaders
| HoppGQLHeader[]
// check if the parent folder has authType 'inherit' and if it is the root folder
if (
parentFolderAuth?.authType === "inherit" &&
[...path.slice(0, i + 1)].length === 1
) {
auth = {
parentID: [...path.slice(0, i + 1)].join("/"),
parentName: parentFolder.name,
inheritedAuth: auth.inheritedAuth,
}
}
if (parentFolderAuth?.authType !== "inherit") {
auth = {
parentID: [...path.slice(0, i + 1)].join("/"),
parentName: parentFolder.name,
inheritedAuth: parentFolderAuth,
}
}
// Update headers, overwriting duplicates by key
if (parentFolderHeaders) {
const activeHeaders = parentFolderHeaders.filter((h) => h.active)
activeHeaders.forEach((header) => {
const index = headers.findIndex(
(h) => h.inheritedHeader?.key === header.key
)
const currentPath = [...path.slice(0, i + 1)].join("/")
if (index !== -1) {
// Replace the existing header with the same key
headers[index] = {
parentID: currentPath,
parentName: parentFolder.name,
inheritedHeader: header,
}
} else {
headers.push({
parentID: currentPath,
parentName: parentFolder.name,
inheritedHeader: header,
})
}
})
}
}
return { type: "ok", data: { auth, headers } }
})
)
)
}
public getWorkspaceHandle(
workspaceID: string
): Promise<E.Either<unknown, HandleRef<Workspace>>> {

View File

@@ -1,5 +1,11 @@
import { HoppRESTRequest } from "@hoppscotch/data"
import { Ref } from "vue"
import { HoppInheritedRESTProperty } from "~/helpers/types/HoppInheritedProperties"
export type RESTCollectionLevelAuthHeadersView = {
auth: HoppInheritedRESTProperty["auth"]
headers: HoppInheritedRESTProperty["headers"]
}
export type RESTCollectionViewCollection = {
collectionID: string