From 2bd3f36bfaf15f6833ca62962804a9cd828efc2b Mon Sep 17 00:00:00 2001
From: Nivedin <53208152+nivedin@users.noreply.github.com>
Date: Fri, 13 Jun 2025 09:55:05 +0530
Subject: [PATCH] fix: schema error and test updation flow (#5124)
Co-authored-by: jamesgeorge007 <25279263+jamesgeorge007@users.noreply.github.com>
---
.../src/components/http/Response.vue | 26 +--
.../src/components/http/TestResultEnv.vue | 4 +-
.../src/helpers/RequestRunner.ts | 39 ++--
.../helpers/fixBrokenEnvironmentVersion.ts | 27 +++
.../src/helpers/fixBrokenRequestVersion.ts | 54 ++++++
.../helpers/import-export/import/openapi.ts | 41 +++--
.../helpers/import-export/import/postman.ts | 9 +-
.../helpers/teams/TeamEnvironmentAdapter.ts | 17 +-
.../src/helpers/utils/statusCodes.ts | 2 +-
.../hoppscotch-common/src/kernel/store.ts | 9 +-
.../std/kernel-interceptors/agent/store.ts | 17 +-
.../kernel-interceptors/extension/store.ts | 13 +-
.../std/kernel-interceptors/native/store.ts | 13 +-
.../std/kernel-interceptors/proxy/store.ts | 13 +-
.../persistence/__tests__/index.spec.ts | 2 +-
.../src/services/persistence/index.ts | 17 +-
.../persistence/validation-schemas/index.ts | 20 +--
.../hoppscotch-data/src/collection/v/4.ts | 2 +-
.../hoppscotch-data/src/collection/v/6.ts | 2 +-
.../hoppscotch-data/src/collection/v/7.ts | 2 +-
.../hoppscotch-data/src/collection/v/8.ts | 2 +-
.../hoppscotch-data/src/environment/index.ts | 2 +-
.../src/global-environment/v/2.ts | 5 +-
packages/hoppscotch-data/src/graphql/v/8.ts | 4 +-
packages/hoppscotch-data/src/index.ts | 1 +
.../src/rest-request-response/index.ts | 50 ++++++
.../original-request/index.ts | 39 ++++
.../original-request/v/1.ts | 24 +++
.../original-request/v/2.ts | 20 +++
.../original-request/v/3.ts | 38 ++++
.../original-request/v/4.ts | 20 +++
.../original-request/v/5.ts | 20 +++
.../src/rest-request-response/v/0.ts | 35 ++++
packages/hoppscotch-data/src/rest/index.ts | 43 +++--
.../src/rest/v/{10.ts => 10/body.ts} | 19 +-
.../hoppscotch-data/src/rest/v/10/index.ts | 20 +++
packages/hoppscotch-data/src/rest/v/11.ts | 146 ---------------
.../hoppscotch-data/src/rest/v/11/auth.ts | 52 ++++++
.../hoppscotch-data/src/rest/v/11/index.ts | 37 ++++
packages/hoppscotch-data/src/rest/v/12.ts | 128 --------------
.../hoppscotch-data/src/rest/v/12/auth.ts | 67 +++++++
.../hoppscotch-data/src/rest/v/12/index.ts | 21 +++
packages/hoppscotch-data/src/rest/v/13.ts | 126 -------------
.../hoppscotch-data/src/rest/v/13/auth.ts | 64 +++++++
.../hoppscotch-data/src/rest/v/13/index.ts | 22 +++
packages/hoppscotch-data/src/rest/v/14.ts | 19 ++
packages/hoppscotch-data/src/rest/v/8.ts | 166 ------------------
packages/hoppscotch-data/src/rest/v/8/auth.ts | 75 ++++++++
.../hoppscotch-data/src/rest/v/8/index.ts | 27 +++
packages/hoppscotch-data/src/rest/v/9.ts | 154 ----------------
packages/hoppscotch-data/src/rest/v/9/body.ts | 68 +++++++
.../hoppscotch-data/src/rest/v/9/index.ts | 22 +++
.../environments/environments.platform.ts | 29 ++-
.../platform/environments/desktop/index.ts | 7 +-
.../src/platform/environments/web/index.ts | 30 ++--
55 files changed, 1013 insertions(+), 918 deletions(-)
create mode 100644 packages/hoppscotch-common/src/helpers/fixBrokenEnvironmentVersion.ts
create mode 100644 packages/hoppscotch-common/src/helpers/fixBrokenRequestVersion.ts
create mode 100644 packages/hoppscotch-data/src/rest-request-response/index.ts
create mode 100644 packages/hoppscotch-data/src/rest-request-response/original-request/index.ts
create mode 100644 packages/hoppscotch-data/src/rest-request-response/original-request/v/1.ts
create mode 100644 packages/hoppscotch-data/src/rest-request-response/original-request/v/2.ts
create mode 100644 packages/hoppscotch-data/src/rest-request-response/original-request/v/3.ts
create mode 100644 packages/hoppscotch-data/src/rest-request-response/original-request/v/4.ts
create mode 100644 packages/hoppscotch-data/src/rest-request-response/original-request/v/5.ts
create mode 100644 packages/hoppscotch-data/src/rest-request-response/v/0.ts
rename packages/hoppscotch-data/src/rest/v/{10.ts => 10/body.ts} (76%)
create mode 100644 packages/hoppscotch-data/src/rest/v/10/index.ts
delete mode 100644 packages/hoppscotch-data/src/rest/v/11.ts
create mode 100644 packages/hoppscotch-data/src/rest/v/11/auth.ts
create mode 100644 packages/hoppscotch-data/src/rest/v/11/index.ts
delete mode 100644 packages/hoppscotch-data/src/rest/v/12.ts
create mode 100644 packages/hoppscotch-data/src/rest/v/12/auth.ts
create mode 100644 packages/hoppscotch-data/src/rest/v/12/index.ts
delete mode 100644 packages/hoppscotch-data/src/rest/v/13.ts
create mode 100644 packages/hoppscotch-data/src/rest/v/13/auth.ts
create mode 100644 packages/hoppscotch-data/src/rest/v/13/index.ts
create mode 100644 packages/hoppscotch-data/src/rest/v/14.ts
delete mode 100644 packages/hoppscotch-data/src/rest/v/8.ts
create mode 100644 packages/hoppscotch-data/src/rest/v/8/auth.ts
create mode 100644 packages/hoppscotch-data/src/rest/v/8/index.ts
delete mode 100644 packages/hoppscotch-data/src/rest/v/9.ts
create mode 100644 packages/hoppscotch-data/src/rest/v/9/body.ts
create mode 100644 packages/hoppscotch-data/src/rest/v/9/index.ts
diff --git a/packages/hoppscotch-common/src/components/http/Response.vue b/packages/hoppscotch-common/src/components/http/Response.vue
index c3218c2f..95289a1b 100644
--- a/packages/hoppscotch-common/src/components/http/Response.vue
+++ b/packages/hoppscotch-common/src/components/http/Response.vue
@@ -24,9 +24,9 @@ import { HoppRequestDocument } from "~/helpers/rest/document"
import { useResponseBody } from "@composables/lens-actions"
import { getStatusCodeReasonPhrase } from "~/helpers/utils/statusCodes"
import {
- HoppRESTResponseOriginalRequest,
HoppRESTRequestResponse,
- RESTResOriginalReqSchemaVersion,
+ HoppRESTResponseOriginalRequest,
+ makeHoppRESTResponseOriginalRequest,
} from "@hoppscotch/data"
import { editRESTRequest } from "~/newstore/collections"
import { useToast } from "@composables/toast"
@@ -94,17 +94,17 @@ const onSaveAsExample = () => {
requestVariables,
} = response.req
- const originalRequest: HoppRESTResponseOriginalRequest = {
- v: RESTResOriginalReqSchemaVersion,
- method,
- endpoint,
- headers,
- body,
- auth,
- params,
- name,
- requestVariables,
- }
+ const originalRequest: HoppRESTResponseOriginalRequest =
+ makeHoppRESTResponseOriginalRequest({
+ method,
+ endpoint,
+ headers,
+ body,
+ auth,
+ params,
+ name,
+ requestVariables,
+ })
const resName = responseName.value.trim()
diff --git a/packages/hoppscotch-common/src/components/http/TestResultEnv.vue b/packages/hoppscotch-common/src/components/http/TestResultEnv.vue
index e34de824..84d529e7 100644
--- a/packages/hoppscotch-common/src/components/http/TestResultEnv.vue
+++ b/packages/hoppscotch-common/src/components/http/TestResultEnv.vue
@@ -14,7 +14,7 @@
- {{ env.value }}
+ {{ env.currentValue }}
- const updatedRunResult = updateEnvsAfterTestScript(combinedResult)
-
- tab.value.document.testResults =
- translateToSandboxTestResults(updatedRunResult)
+ tab.value.document.testResults = translateToSandboxTestResults(
+ combinedResult.right
+ )
+ updateEnvsAfterTestScript(combinedResult)
} else {
tab.value.document.testResults = {
description: "",
@@ -492,26 +492,6 @@ export function runRESTRequest$(
}
function updateEnvsAfterTestScript(runResult: E.Right) {
- const updatedGlobalEnvVariables = updateEnvironments(
- // @ts-expect-error Typescript can't figure out this inference for some reason
- cloneDeep(runResult.right.envs.global),
- "global"
- )
-
- const updatedSelectedEnvVariables = updateEnvironments(
- // @ts-expect-error Typescript can't figure out this inference for some reason
- cloneDeep(runResult.right.envs.selected),
- "selected"
- )
-
- const updatedRunResult = {
- ...runResult.right,
- envs: {
- global: updatedGlobalEnvVariables,
- selected: updatedSelectedEnvVariables,
- },
- }
-
const globalEnvVariables = updateEnvironments(
// @ts-expect-error Typescript can't figure out this inference for some reason
runResult.right.envs.global,
@@ -522,6 +502,11 @@ function updateEnvsAfterTestScript(runResult: E.Right) {
v: 2,
variables: globalEnvVariables,
})
+ updateEnvironments(
+ // @ts-expect-error Typescript can't figure out this inference for some reason
+ cloneDeep(runResult.right.envs.selected),
+ "selected"
+ )
if (environmentsStore.value.selectedEnvironmentIndex.type === "MY_ENV") {
const env = getEnvironment({
type: "MY_ENV",
@@ -531,7 +516,7 @@ function updateEnvsAfterTestScript(runResult: E.Right) {
name: env.name,
v: 2,
id: "id" in env ? env.id : "",
- variables: updatedRunResult.envs.selected,
+ variables: runResult.right.envs.selected,
})
} else if (
environmentsStore.value.selectedEnvironmentIndex.type === "TEAM_ENV"
@@ -541,14 +526,12 @@ function updateEnvsAfterTestScript(runResult: E.Right) {
})
pipe(
updateTeamEnvironment(
- JSON.stringify(updatedRunResult.envs.selected),
+ JSON.stringify(runResult.right.envs.selected),
environmentsStore.value.selectedEnvironmentIndex.teamEnvID,
env.name
)
)()
}
-
- return updatedRunResult
}
/**
diff --git a/packages/hoppscotch-common/src/helpers/fixBrokenEnvironmentVersion.ts b/packages/hoppscotch-common/src/helpers/fixBrokenEnvironmentVersion.ts
new file mode 100644
index 00000000..76090d92
--- /dev/null
+++ b/packages/hoppscotch-common/src/helpers/fixBrokenEnvironmentVersion.ts
@@ -0,0 +1,27 @@
+import {
+ Environment,
+ translateToNewEnvironmentVariables,
+} from "@hoppscotch/data"
+
+/**
+ * Fixes broken environment versions in the given environments.
+ * This function ensures that all environment variables are translated
+ * to the new format, which is necessary for compatibility with the latest
+ * version of the application.
+ *
+ * Some environments may have been created with an unsupported
+ * variable format, which can lead to issues when trying to access or manipulate those environments.
+ *
+ *
+ * @param envs - The array of environments to fix.
+ * @returns The fixed array of environments with updated variable formats.
+ */
+export const fixBrokenEnvironmentVersion = (envs: Environment[]) => {
+ if (!Array.isArray(envs)) {
+ return envs
+ }
+ return envs.map((env) => ({
+ ...env,
+ variables: (env.variables ?? []).map(translateToNewEnvironmentVariables),
+ }))
+}
diff --git a/packages/hoppscotch-common/src/helpers/fixBrokenRequestVersion.ts b/packages/hoppscotch-common/src/helpers/fixBrokenRequestVersion.ts
new file mode 100644
index 00000000..c9dee8f2
--- /dev/null
+++ b/packages/hoppscotch-common/src/helpers/fixBrokenRequestVersion.ts
@@ -0,0 +1,54 @@
+import {
+ getDefaultRESTRequest,
+ safelyExtractRESTRequest,
+} from "@hoppscotch/data"
+import { z } from "zod"
+import { REST_TAB_STATE_SCHEMA } from "~/services/persistence/validation-schemas"
+
+type HoppRESTab = z.infer
+
+/**
+ * Fixes broken request versions in the given REST tab documents.
+ * This function ensures that all requests and test runners have valid
+ * request data, defaulting to the default REST request structure if necessary.
+ *
+ * There were requests in the REST tab that had an invalid version
+ * structure, with response and parent request which could lead to issues when trying to access or
+ * manipulate those requests. This function iterates through the
+ * ordered documents of the REST tab and checks each request.
+ *
+ * @param docs - The ordered documents of the REST tab to fix.
+ * @returns The fixed ordered documents with valid request structures.
+ */
+export const fixBrokenRequestVersion = (
+ docs: HoppRESTab["orderedDocs"]
+): HoppRESTab["orderedDocs"] => {
+ return docs.map((x: HoppRESTab["orderedDocs"][number]) => {
+ if (x.doc.type === "request") {
+ const req = safelyExtractRESTRequest(
+ x.doc.request,
+ getDefaultRESTRequest()
+ )
+ if (req) {
+ x.doc.request = req
+ }
+ }
+
+ if (x.doc.type === "test-runner") {
+ x.doc.request = safelyExtractRESTRequest(
+ x.doc.request,
+ getDefaultRESTRequest()
+ )
+
+ if (x.doc.resultCollection) {
+ x.doc.resultCollection.requests = x.doc.resultCollection?.requests.map(
+ (req) => {
+ return safelyExtractRESTRequest(req, getDefaultRESTRequest())
+ }
+ )
+ }
+ }
+
+ return x
+ })
+}
diff --git a/packages/hoppscotch-common/src/helpers/import-export/import/openapi.ts b/packages/hoppscotch-common/src/helpers/import-export/import/openapi.ts
index 6fead267..9d2a4576 100644
--- a/packages/hoppscotch-common/src/helpers/import-export/import/openapi.ts
+++ b/packages/hoppscotch-common/src/helpers/import-export/import/openapi.ts
@@ -20,7 +20,7 @@ import {
HoppRESTRequest,
HoppRESTRequestResponses,
HoppRESTResponseOriginalRequest,
- RESTResOriginalReqSchemaVersion,
+ makeHoppRESTResponseOriginalRequest,
} from "@hoppscotch/data"
import { pipe, flow } from "fp-ts/function"
import * as A from "fp-ts/Array"
@@ -828,24 +828,27 @@ const convertPathToHoppReqs = (
(info.parameters as OpenAPIParamsType[] | undefined) ?? []
),
- responses: parseOpenAPIResponses(doc, info, {
- name: info.operationId ?? info.summary ?? "Untitled Request",
- auth: parseOpenAPIAuth(doc, info),
- body: parseOpenAPIBody(doc, info),
- endpoint,
- // We don't need to worry about reference types as the Dereferencing pass should remove them
- params: parseOpenAPIParams(
- (info.parameters as OpenAPIParamsType[] | undefined) ?? []
- ),
- headers: parseOpenAPIHeaders(
- (info.parameters as OpenAPIParamsType[] | undefined) ?? []
- ),
- method: method.toUpperCase(),
- requestVariables: parseOpenAPIVariables(
- (info.parameters as OpenAPIParamsType[] | undefined) ?? []
- ),
- v: RESTResOriginalReqSchemaVersion,
- }),
+ responses: parseOpenAPIResponses(
+ doc,
+ info,
+ makeHoppRESTResponseOriginalRequest({
+ name: info.operationId ?? info.summary ?? "Untitled Request",
+ auth: parseOpenAPIAuth(doc, info),
+ body: parseOpenAPIBody(doc, info),
+ endpoint,
+ // We don't need to worry about reference types as the Dereferencing pass should remove them
+ params: parseOpenAPIParams(
+ (info.parameters as OpenAPIParamsType[] | undefined) ?? []
+ ),
+ headers: parseOpenAPIHeaders(
+ (info.parameters as OpenAPIParamsType[] | undefined) ?? []
+ ),
+ method: method.toUpperCase(),
+ requestVariables: parseOpenAPIVariables(
+ (info.parameters as OpenAPIParamsType[] | undefined) ?? []
+ ),
+ })
+ ),
}),
metadata: {
tags: info.tags ?? [],
diff --git a/packages/hoppscotch-common/src/helpers/import-export/import/postman.ts b/packages/hoppscotch-common/src/helpers/import-export/import/postman.ts
index a41df9af..f396c4b6 100644
--- a/packages/hoppscotch-common/src/helpers/import-export/import/postman.ts
+++ b/packages/hoppscotch-common/src/helpers/import-export/import/postman.ts
@@ -10,8 +10,9 @@ import {
knownContentTypes,
makeCollection,
makeRESTRequest,
- RESTResOriginalReqSchemaVersion,
ValidContentTypes,
+ HoppRESTRequestResponses,
+ makeHoppRESTResponseOriginalRequest,
} from "@hoppscotch/data"
import * as A from "fp-ts/Array"
import { flow, pipe } from "fp-ts/function"
@@ -31,7 +32,6 @@ import {
import { stringArrayJoin } from "~/helpers/functional/array"
import { PMRawLanguage } from "~/types/pm-coll-exts"
import { IMPORTER_INVALID_FILE_FORMAT } from "."
-import { HoppRESTRequestResponses } from "@hoppscotch/data"
const safeParseJSON = (jsonStr: string) => O.tryCatch(() => JSON.parse(jsonStr))
@@ -160,7 +160,7 @@ const getHoppResponses = (
body: response.body ?? "",
headers: getHoppReqHeaders(response.headers),
code: response.code,
- originalRequest: {
+ originalRequest: makeHoppRESTResponseOriginalRequest({
auth: getHoppReqAuth(response.originalRequest?.auth),
body: getHoppReqBody({
body: response.originalRequest?.body,
@@ -178,8 +178,7 @@ const getHoppResponses = (
requestVariables: getHoppReqVariables(
response.originalRequest?.url.variables ?? null
),
- v: RESTResOriginalReqSchemaVersion,
- },
+ }),
}
return [response.name, res]
})
diff --git a/packages/hoppscotch-common/src/helpers/teams/TeamEnvironmentAdapter.ts b/packages/hoppscotch-common/src/helpers/teams/TeamEnvironmentAdapter.ts
index c43d521b..6f1143c7 100644
--- a/packages/hoppscotch-common/src/helpers/teams/TeamEnvironmentAdapter.ts
+++ b/packages/hoppscotch-common/src/helpers/teams/TeamEnvironmentAdapter.ts
@@ -11,7 +11,6 @@ import {
} from "../backend/graphql"
import { TeamEnvironment } from "./TeamEnvironment"
import { Environment, EnvironmentSchemaVersion } from "@hoppscotch/data"
-import { entityReference } from "verzod"
type EntityType = "environment"
type EntityID = `${EntityType}-${string}`
@@ -121,18 +120,18 @@ export default class TeamEnvironmentAdapter {
variables: JSON.parse(x.variables),
}
- const parsedEnvironment =
- entityReference(Environment).safeParse(environment)
+ const parsedEnvironment = Environment.safeParse(environment)
return {
id: x.id,
teamID: x.teamID,
- environment: parsedEnvironment.success
- ? parsedEnvironment.data
- : {
- ...environment,
- v: EnvironmentSchemaVersion,
- },
+ environment:
+ parsedEnvironment.type === "ok"
+ ? parsedEnvironment.value
+ : {
+ ...environment,
+ v: EnvironmentSchemaVersion,
+ },
}
})
)
diff --git a/packages/hoppscotch-common/src/helpers/utils/statusCodes.ts b/packages/hoppscotch-common/src/helpers/utils/statusCodes.ts
index 44d7f8a8..6f2cf56d 100644
--- a/packages/hoppscotch-common/src/helpers/utils/statusCodes.ts
+++ b/packages/hoppscotch-common/src/helpers/utils/statusCodes.ts
@@ -111,7 +111,7 @@ export const getFullStatusCodePhrase = () => {
// return all status codes and their phrases
// like code • phrase
export const getStatusCodePhrase = (
- code: number | undefined,
+ code: number | undefined | null,
statusText: string
) => {
if (!code) return statusText
diff --git a/packages/hoppscotch-common/src/kernel/store.ts b/packages/hoppscotch-common/src/kernel/store.ts
index 0cdbdbe8..25971db2 100644
--- a/packages/hoppscotch-common/src/kernel/store.ts
+++ b/packages/hoppscotch-common/src/kernel/store.ts
@@ -57,11 +57,16 @@ export const Store = (() => {
return module().listNamespaces(STORE_PATH)
},
- listKeys: async (namespace: string): Promise> => {
+ listKeys: async (
+ namespace: string
+ ): Promise> => {
return module().listKeys(STORE_PATH, namespace)
},
- watch: async (namespace: string, key: string): Promise> => {
+ watch: async (
+ namespace: string,
+ key: string
+ ): Promise> => {
return module().watch(STORE_PATH, namespace, key)
},
} as const
diff --git a/packages/hoppscotch-common/src/platform/std/kernel-interceptors/agent/store.ts b/packages/hoppscotch-common/src/platform/std/kernel-interceptors/agent/store.ts
index 416e7481..48e4024e 100644
--- a/packages/hoppscotch-common/src/platform/std/kernel-interceptors/agent/store.ts
+++ b/packages/hoppscotch-common/src/platform/std/kernel-interceptors/agent/store.ts
@@ -92,17 +92,14 @@ export class KernelInterceptorAgentStore extends Service {
private async setupWatchers() {
const watcher = await Store.watch(STORE_NAMESPACE, STORE_KEYS.SETTINGS)
- watcher.on(
- "change",
- async ({ value }) => {
- if (value) {
- const store = value as StoredData
- this.domainSettings = new Map(Object.entries(store.domains))
- this.authKey.value = store.auth.key
- this.sharedSecretB16.value = store.auth.sharedSecret
- }
+ watcher.on("change", async ({ value }) => {
+ if (value) {
+ const store = value as StoredData
+ this.domainSettings = new Map(Object.entries(store.domains))
+ this.authKey.value = store.auth.key
+ this.sharedSecretB16.value = store.auth.sharedSecret
}
- )
+ })
}
private async persistStore(): Promise {
diff --git a/packages/hoppscotch-common/src/platform/std/kernel-interceptors/extension/store.ts b/packages/hoppscotch-common/src/platform/std/kernel-interceptors/extension/store.ts
index ad386d73..4adc757e 100644
--- a/packages/hoppscotch-common/src/platform/std/kernel-interceptors/extension/store.ts
+++ b/packages/hoppscotch-common/src/platform/std/kernel-interceptors/extension/store.ts
@@ -89,15 +89,12 @@ export class KernelInterceptorExtensionStore extends Service {
}
const watcher = await Store.watch(STORE_NAMESPACE, SETTINGS_KEY)
- watcher.on(
- "change",
- async ({ value }) => {
- if (value) {
- const storedData = value as StoredData
- this.settings = storedData.settings
- }
+ watcher.on("change", async ({ value }) => {
+ if (value) {
+ const storedData = value as StoredData
+ this.settings = storedData.settings
}
- )
+ })
}
public getExtensionVersion(): O.Option {
diff --git a/packages/hoppscotch-common/src/platform/std/kernel-interceptors/native/store.ts b/packages/hoppscotch-common/src/platform/std/kernel-interceptors/native/store.ts
index 64995890..c8294386 100644
--- a/packages/hoppscotch-common/src/platform/std/kernel-interceptors/native/store.ts
+++ b/packages/hoppscotch-common/src/platform/std/kernel-interceptors/native/store.ts
@@ -74,15 +74,12 @@ export class KernelInterceptorNativeStore extends Service {
private async setupWatchers() {
const watcher = await Store.watch(STORE_NAMESPACE, STORE_KEYS.SETTINGS)
- watcher.on(
- "change",
- async ({ value }) => {
- if (value) {
- const store = value as StoredData
- this.domainSettings = new Map(Object.entries(store.domains))
- }
+ watcher.on("change", async ({ value }) => {
+ if (value) {
+ const store = value as StoredData
+ this.domainSettings = new Map(Object.entries(store.domains))
}
- )
+ })
}
private async persistStore(): Promise {
diff --git a/packages/hoppscotch-common/src/platform/std/kernel-interceptors/proxy/store.ts b/packages/hoppscotch-common/src/platform/std/kernel-interceptors/proxy/store.ts
index 271d448b..f70308a2 100644
--- a/packages/hoppscotch-common/src/platform/std/kernel-interceptors/proxy/store.ts
+++ b/packages/hoppscotch-common/src/platform/std/kernel-interceptors/proxy/store.ts
@@ -39,15 +39,12 @@ export class KernelInterceptorProxyStore extends Service {
await this.loadSettings()
const watcher = await Store.watch(STORE_NAMESPACE, SETTINGS_KEY)
- watcher.on(
- "change",
- async ({ value }) => {
- if (value) {
- const storedData = value as StoredData
- this.settings = storedData.settings
- }
+ watcher.on("change", async ({ value }) => {
+ if (value) {
+ const storedData = value as StoredData
+ this.settings = storedData.settings
}
- )
+ })
}
private async loadSettings(): Promise {
diff --git a/packages/hoppscotch-common/src/services/persistence/__tests__/index.spec.ts b/packages/hoppscotch-common/src/services/persistence/__tests__/index.spec.ts
index fb3d2d31..c338266e 100644
--- a/packages/hoppscotch-common/src/services/persistence/__tests__/index.spec.ts
+++ b/packages/hoppscotch-common/src/services/persistence/__tests__/index.spec.ts
@@ -954,10 +954,10 @@ describe("PersistenceService", () => {
// Invalid shape for `environments`
const environments = [
// `entries` -> `variables`
+ // no name for the environment
{
v: 1,
id: "ENV_1",
- name: "Test",
entries: [{ key: "test-key", value: "test-value", secret: false }],
},
]
diff --git a/packages/hoppscotch-common/src/services/persistence/index.ts b/packages/hoppscotch-common/src/services/persistence/index.ts
index 986dd82b..a68ad0c0 100644
--- a/packages/hoppscotch-common/src/services/persistence/index.ts
+++ b/packages/hoppscotch-common/src/services/persistence/index.ts
@@ -97,6 +97,9 @@ import {
CurrentValueService,
Variable,
} from "../current-environment-value.service"
+import { cloneDeep } from "lodash-es"
+import { fixBrokenRequestVersion } from "~/helpers/fixBrokenRequestVersion"
+import { fixBrokenEnvironmentVersion } from "~/helpers/fixBrokenEnvironmentVersion"
export const STORE_NAMESPACE = "persistence.v1"
@@ -528,7 +531,9 @@ export class PersistenceService extends Service {
try {
if (E.isRight(loadResult)) {
const data = loadResult.right ?? []
- const result = ENVIRONMENTS_SCHEMA.safeParse(data)
+ const environments = fixBrokenEnvironmentVersion(data)
+
+ const result = ENVIRONMENTS_SCHEMA.safeParse(environments)
if (result.success) {
// Check for and handle globals
@@ -866,8 +871,16 @@ export class PersistenceService extends Service {
try {
if (E.isRight(loadResult) && loadResult.right) {
- const result = REST_TAB_STATE_SCHEMA.safeParse(loadResult.right)
+ // Correcting the request schema for broken data
+ const orderedDocs = fixBrokenRequestVersion(
+ cloneDeep(loadResult.right.orderedDocs) ?? []
+ )
+ const transformedTabs = {
+ ...loadResult.right,
+ orderedDocs,
+ }
+ const result = REST_TAB_STATE_SCHEMA.safeParse(transformedTabs)
if (result.success) {
// SAFETY: We know the schema matches
this.restTabService.loadTabsFromPersistedState(
diff --git a/packages/hoppscotch-common/src/services/persistence/validation-schemas/index.ts b/packages/hoppscotch-common/src/services/persistence/validation-schemas/index.ts
index 4e9d8460..65ad931c 100644
--- a/packages/hoppscotch-common/src/services/persistence/validation-schemas/index.ts
+++ b/packages/hoppscotch-common/src/services/persistence/validation-schemas/index.ts
@@ -405,12 +405,9 @@ const HoppTestResultSchema = z
.object({
additions: z.array(EnvironmentVariablesSchema),
updations: z.array(
- EnvironmentVariablesSchema.refine(
- (x) => "secret" in x && !x.secret
- ).and(
- z.object({
- previousValue: z.optional(z.string()),
- })
+ z.intersection(
+ EnvironmentVariablesSchema,
+ z.object({ previousValue: z.optional(z.string()) })
)
),
deletions: z.array(EnvironmentVariablesSchema),
@@ -420,12 +417,9 @@ const HoppTestResultSchema = z
.object({
additions: z.array(EnvironmentVariablesSchema),
updations: z.array(
- EnvironmentVariablesSchema.refine(
- (x) => "secret" in x && !x.secret
- ).and(
- z.object({
- previousValue: z.optional(z.string()),
- })
+ z.intersection(
+ EnvironmentVariablesSchema,
+ z.object({ previousValue: z.optional(z.string()) })
)
),
deletions: z.array(EnvironmentVariablesSchema),
@@ -582,7 +576,7 @@ export const REST_TAB_STATE_SCHEMA = z
}),
z.object({
type: z.literal("example-response").catch("example-response"),
- response: HoppRESTRequestResponse,
+ response: entityReference(HoppRESTRequestResponse),
saveContext: z.optional(HoppRESTSaveContextSchema),
isDirty: z.boolean(),
}),
diff --git a/packages/hoppscotch-data/src/collection/v/4.ts b/packages/hoppscotch-data/src/collection/v/4.ts
index 7af4ab38..7fa2bb09 100644
--- a/packages/hoppscotch-data/src/collection/v/4.ts
+++ b/packages/hoppscotch-data/src/collection/v/4.ts
@@ -2,7 +2,7 @@ import { defineVersion, entityRefUptoVersion } from "verzod"
import { z } from "zod"
import { HoppGQLAuth } from "../../graphql/v/7"
-import { HoppRESTAuth } from "../../rest/v/8"
+import { HoppRESTAuth } from "../../rest/v/8/auth"
import { V3_SCHEMA, v3_baseCollectionSchema } from "./3"
import { HoppCollection } from ".."
diff --git a/packages/hoppscotch-data/src/collection/v/6.ts b/packages/hoppscotch-data/src/collection/v/6.ts
index ca65d7a5..437091d5 100644
--- a/packages/hoppscotch-data/src/collection/v/6.ts
+++ b/packages/hoppscotch-data/src/collection/v/6.ts
@@ -2,7 +2,7 @@ import { defineVersion, entityRefUptoVersion } from "verzod"
import { z } from "zod"
import { HoppGQLAuth } from "../../graphql/v/8"
-import { HoppRESTAuth } from "../../rest/v/11"
+import { HoppRESTAuth } from "../../rest/v/11/auth"
import { V5_SCHEMA, v5_baseCollectionSchema } from "./5"
import { HoppCollection } from ".."
diff --git a/packages/hoppscotch-data/src/collection/v/7.ts b/packages/hoppscotch-data/src/collection/v/7.ts
index ce6fb29f..8b069824 100644
--- a/packages/hoppscotch-data/src/collection/v/7.ts
+++ b/packages/hoppscotch-data/src/collection/v/7.ts
@@ -2,7 +2,7 @@ import { defineVersion, entityRefUptoVersion } from "verzod"
import { z } from "zod"
import { HoppGQLAuth } from "../../graphql/v/8"
-import { HoppRESTAuth } from "../../rest/v/12"
+import { HoppRESTAuth } from "../../rest/v/12/auth"
import { V6_SCHEMA, v6_baseCollectionSchema } from "./6"
import { HoppCollection } from ".."
diff --git a/packages/hoppscotch-data/src/collection/v/8.ts b/packages/hoppscotch-data/src/collection/v/8.ts
index d11ed776..1426a625 100644
--- a/packages/hoppscotch-data/src/collection/v/8.ts
+++ b/packages/hoppscotch-data/src/collection/v/8.ts
@@ -2,7 +2,7 @@ import { defineVersion, entityRefUptoVersion } from "verzod"
import { z } from "zod"
import { HoppGQLAuth } from "../../graphql/v/8"
-import { HoppRESTAuth } from "../../rest/v/13"
+import { HoppRESTAuth } from "../../rest/v/13/auth"
import { HoppCollection } from ".."
import { v7_baseCollectionSchema, V7_SCHEMA } from "./7"
diff --git a/packages/hoppscotch-data/src/environment/index.ts b/packages/hoppscotch-data/src/environment/index.ts
index e2438a29..66118a41 100644
--- a/packages/hoppscotch-data/src/environment/index.ts
+++ b/packages/hoppscotch-data/src/environment/index.ts
@@ -205,7 +205,7 @@ export const translateToNewEnvironmentVariables = (
key: x.key,
initialValue: x.initialValue ?? x.value ?? "",
currentValue: x.currentValue ?? x.value ?? "",
- secret: false,
+ secret: x.secret ?? false,
}
}
diff --git a/packages/hoppscotch-data/src/global-environment/v/2.ts b/packages/hoppscotch-data/src/global-environment/v/2.ts
index 6058ad58..e205d510 100644
--- a/packages/hoppscotch-data/src/global-environment/v/2.ts
+++ b/packages/hoppscotch-data/src/global-environment/v/2.ts
@@ -22,14 +22,15 @@ export default defineVersion({
...old,
v: 2,
variables: old.variables.map((variable) => {
+ const { key, secret } = variable
// if the variable is secret, set initialValue and currentValue to empty string
// else set initialValue and currentValue to value
// and delete value
return {
- ...variable,
+ key,
+ secret: secret ?? false,
initialValue: variable.secret ? "" : variable.value,
currentValue: variable.secret ? "" : variable.value,
- value: undefined,
}
}),
}
diff --git a/packages/hoppscotch-data/src/graphql/v/8.ts b/packages/hoppscotch-data/src/graphql/v/8.ts
index b34e5bfa..d7e8f8e3 100644
--- a/packages/hoppscotch-data/src/graphql/v/8.ts
+++ b/packages/hoppscotch-data/src/graphql/v/8.ts
@@ -9,10 +9,10 @@ import {
} from "./2"
import { HoppGQLAuthAPIKey } from "./4"
import { HoppGQLAuthAWSSignature } from "./6"
-import { HoppRESTAuthOAuth2 } from "./../../rest/v/11"
+import { HoppRESTAuthOAuth2 } from "../../rest/v/11/auth"
import { V7_SCHEMA } from "./7"
-export { HoppRESTAuthOAuth2 as HoppGQLAuthOAuth2 } from "../../rest/v/11"
+export { HoppRESTAuthOAuth2 as HoppGQLAuthOAuth2 } from "../../rest/v/11/auth"
export const HoppGQLAuth = z
.discriminatedUnion("authType", [
diff --git a/packages/hoppscotch-data/src/index.ts b/packages/hoppscotch-data/src/index.ts
index b3bb743a..37e6ae94 100644
--- a/packages/hoppscotch-data/src/index.ts
+++ b/packages/hoppscotch-data/src/index.ts
@@ -9,3 +9,4 @@ export * from "./utils/collection"
export * from "./utils/hawk"
export * from "./utils/akamai-eg"
export * from "./utils/jwt"
+export * from "./rest-request-response"
diff --git a/packages/hoppscotch-data/src/rest-request-response/index.ts b/packages/hoppscotch-data/src/rest-request-response/index.ts
new file mode 100644
index 00000000..5eb26564
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest-request-response/index.ts
@@ -0,0 +1,50 @@
+import { InferredEntity, createVersionedEntity, entityReference } from "verzod"
+import { z } from "zod"
+import V0_VERSION from "./v/0"
+import {
+ HoppRESTResOriginalReqSchemaVersion,
+ HoppRESTResponseOriginalRequest,
+} from "./original-request"
+
+export { HoppRESTResponseOriginalRequest } from "./original-request"
+
+const versionedObject = z.object({
+ v: z.number(),
+})
+
+export const HoppRESTRequestResponse = createVersionedEntity({
+ latestVersion: 0,
+ versionMap: {
+ 0: V0_VERSION,
+ },
+ getVersion(data) {
+ const versionCheck = versionedObject.safeParse(data)
+
+ if (versionCheck.success) return versionCheck.data.v
+
+ // Schema starts from version 0, so if the version is not present,
+ // we assume it's version 0
+ const result = V0_VERSION.schema.safeParse(data)
+ return result.success ? 0 : null
+ },
+})
+
+export type HoppRESTRequestResponse = InferredEntity<
+ typeof HoppRESTRequestResponse
+>
+
+export const HoppRESTRequestResponses = z.record(
+ z.string(),
+ entityReference(HoppRESTRequestResponse)
+)
+
+export type HoppRESTRequestResponses = z.infer
+
+export function makeHoppRESTResponseOriginalRequest(
+ x: Omit
+): HoppRESTResponseOriginalRequest {
+ return {
+ v: HoppRESTResOriginalReqSchemaVersion,
+ ...x,
+ }
+}
diff --git a/packages/hoppscotch-data/src/rest-request-response/original-request/index.ts b/packages/hoppscotch-data/src/rest-request-response/original-request/index.ts
new file mode 100644
index 00000000..53f4ef09
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest-request-response/original-request/index.ts
@@ -0,0 +1,39 @@
+import { InferredEntity, createVersionedEntity } from "verzod"
+import { z } from "zod"
+import V1_VERSION from "./v/1"
+import V2_VERSION from "./v/2"
+import V3_VERSION from "./v/3"
+import V4_VERSION from "./v/4"
+import V5_VERSION from "./v/5"
+
+const versionedObject = z.object({
+ // v is a stringified number
+ v: z.string().regex(/^\d+$/).transform(Number),
+})
+
+export const HoppRESTResponseOriginalRequest = createVersionedEntity({
+ latestVersion: 5,
+ versionMap: {
+ 1: V1_VERSION,
+ 2: V2_VERSION,
+ 3: V3_VERSION,
+ 4: V4_VERSION,
+ 5: V5_VERSION,
+ },
+ getVersion(data) {
+ const versionCheck = versionedObject.safeParse(data)
+
+ if (versionCheck.success) return versionCheck.data.v
+
+ // For V1 we have to check the schema
+ const result = V1_VERSION.schema.safeParse(data)
+
+ return result.success ? 1 : null
+ },
+})
+
+export const HoppRESTResOriginalReqSchemaVersion = "5"
+
+export type HoppRESTResponseOriginalRequest = InferredEntity<
+ typeof HoppRESTResponseOriginalRequest
+>
diff --git a/packages/hoppscotch-data/src/rest-request-response/original-request/v/1.ts b/packages/hoppscotch-data/src/rest-request-response/original-request/v/1.ts
new file mode 100644
index 00000000..a4307bd7
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest-request-response/original-request/v/1.ts
@@ -0,0 +1,24 @@
+import { defineVersion } from "verzod"
+import { z } from "zod"
+import { HoppRESTHeaders, HoppRESTParams } from "../../../rest/v/7"
+import { HoppRESTReqBody } from "../../../rest/v/6"
+import { HoppRESTRequestVariables } from "../../../rest/v/2"
+
+import { HoppRESTAuth } from "../../../rest/v/8/auth"
+
+export const V1_SCHEMA = z.object({
+ v: z.literal("1"),
+ name: z.string(),
+ method: z.string(),
+ endpoint: z.string(),
+ headers: HoppRESTHeaders,
+ params: HoppRESTParams,
+ body: HoppRESTReqBody,
+ auth: HoppRESTAuth,
+ requestVariables: HoppRESTRequestVariables,
+})
+
+export default defineVersion({
+ initial: true,
+ schema: V1_SCHEMA,
+})
diff --git a/packages/hoppscotch-data/src/rest-request-response/original-request/v/2.ts b/packages/hoppscotch-data/src/rest-request-response/original-request/v/2.ts
new file mode 100644
index 00000000..cf6231a5
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest-request-response/original-request/v/2.ts
@@ -0,0 +1,20 @@
+import { defineVersion } from "verzod"
+import { z } from "zod"
+import { V1_SCHEMA } from "./1"
+import { HoppRESTReqBody } from "../../../rest/v/9/body"
+
+export const V2_SCHEMA = V1_SCHEMA.extend({
+ v: z.literal("2"),
+ body: HoppRESTReqBody,
+})
+
+export default defineVersion({
+ initial: false,
+ schema: V2_SCHEMA,
+ up(old: z.infer) {
+ return {
+ ...old,
+ v: "2" as const,
+ }
+ },
+})
diff --git a/packages/hoppscotch-data/src/rest-request-response/original-request/v/3.ts b/packages/hoppscotch-data/src/rest-request-response/original-request/v/3.ts
new file mode 100644
index 00000000..57a03f2d
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest-request-response/original-request/v/3.ts
@@ -0,0 +1,38 @@
+import { defineVersion } from "verzod"
+import { z } from "zod"
+
+import { V2_SCHEMA } from "./2"
+import { HoppRESTAuth } from "../../../rest/v/11/auth"
+import { HoppRESTReqBody } from "../../../rest/v/10/body"
+
+export const V3_SCHEMA = V2_SCHEMA.extend({
+ v: z.literal("3"),
+ auth: HoppRESTAuth,
+ body: HoppRESTReqBody,
+})
+
+export default defineVersion({
+ initial: false,
+ schema: V3_SCHEMA,
+ up(old: z.infer) {
+ const auth = old.auth
+
+ return {
+ ...old,
+ v: "3" as const,
+ auth:
+ auth.authType === "oauth-2"
+ ? {
+ ...auth,
+ grantTypeInfo:
+ auth.grantTypeInfo.grantType === "CLIENT_CREDENTIALS"
+ ? {
+ ...auth.grantTypeInfo,
+ clientAuthentication: "IN_BODY" as const,
+ }
+ : auth.grantTypeInfo,
+ }
+ : auth,
+ }
+ },
+})
diff --git a/packages/hoppscotch-data/src/rest-request-response/original-request/v/4.ts b/packages/hoppscotch-data/src/rest-request-response/original-request/v/4.ts
new file mode 100644
index 00000000..a97b954f
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest-request-response/original-request/v/4.ts
@@ -0,0 +1,20 @@
+import { defineVersion } from "verzod"
+import { z } from "zod"
+import { V3_SCHEMA } from "./3"
+import { HoppRESTAuth } from "../../../rest/v/12/auth"
+
+export const V4_SCHEMA = V3_SCHEMA.extend({
+ v: z.literal("4"),
+ auth: HoppRESTAuth,
+})
+
+export default defineVersion({
+ initial: false,
+ schema: V4_SCHEMA,
+ up(old: z.infer) {
+ return {
+ ...old,
+ v: "4" as const,
+ }
+ },
+})
diff --git a/packages/hoppscotch-data/src/rest-request-response/original-request/v/5.ts b/packages/hoppscotch-data/src/rest-request-response/original-request/v/5.ts
new file mode 100644
index 00000000..2fa26a76
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest-request-response/original-request/v/5.ts
@@ -0,0 +1,20 @@
+import { defineVersion } from "verzod"
+import { z } from "zod"
+import { V4_SCHEMA } from "./4"
+import { HoppRESTAuth } from "../../../rest/v/13/auth"
+
+export const V5_SCHEMA = V4_SCHEMA.extend({
+ v: z.literal("5"),
+ auth: HoppRESTAuth,
+})
+
+export default defineVersion({
+ initial: false,
+ schema: V5_SCHEMA,
+ up(old: z.infer) {
+ return {
+ ...old,
+ v: "5" as const,
+ }
+ },
+})
diff --git a/packages/hoppscotch-data/src/rest-request-response/v/0.ts b/packages/hoppscotch-data/src/rest-request-response/v/0.ts
new file mode 100644
index 00000000..9e4bb9e5
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest-request-response/v/0.ts
@@ -0,0 +1,35 @@
+import { defineVersion, entityReference } from "verzod"
+import { z } from "zod"
+import { HoppRESTResponseOriginalRequest } from "../original-request"
+import { StatusCodes } from "../../utils/statusCodes"
+
+export const ValidCodes = z.union(
+ Object.keys(StatusCodes).map((code) => z.literal(parseInt(code))) as [
+ z.ZodLiteral,
+ z.ZodLiteral,
+ ...z.ZodLiteral[]
+ ]
+)
+
+export const HoppRESTResponseHeaders = z.array(
+ z.object({
+ key: z.string(),
+ value: z.string(),
+ })
+)
+
+export type HoppRESTResponseHeader = z.infer
+
+export const V0_SCHEMA = z.object({
+ name: z.string(),
+ originalRequest: entityReference(HoppRESTResponseOriginalRequest),
+ status: z.string(),
+ code: z.optional(ValidCodes).nullable().catch(null),
+ headers: HoppRESTResponseHeaders,
+ body: z.string(),
+})
+
+export default defineVersion({
+ initial: true,
+ schema: V0_SCHEMA,
+})
diff --git a/packages/hoppscotch-data/src/rest/index.ts b/packages/hoppscotch-data/src/rest/index.ts
index d3f1ca14..e03967c2 100644
--- a/packages/hoppscotch-data/src/rest/index.ts
+++ b/packages/hoppscotch-data/src/rest/index.ts
@@ -16,10 +16,14 @@ import V6_VERSION from "./v/6"
import V7_VERSION, { HoppRESTHeaders, HoppRESTParams } from "./v/7"
import V8_VERSION from "./v/8"
import V9_VERSION from "./v/9"
-import V10_VERSION, { HoppRESTReqBody } from "./v/10"
+import V10_VERSION from "./v/10"
+import { HoppRESTReqBody } from "./v/10/body"
import V11_VERSION from "./v/11"
import V12_VERSION from "./v/12"
-import V13_VERSION, { HoppRESTAuth, HoppRESTRequestResponses } from "./v/13"
+import V13_VERSION from "./v/13"
+import { HoppRESTAuth } from "./v/13/auth"
+import V14_VERSION from "./v/14"
+import { HoppRESTRequestResponses } from "../rest-request-response"
export * from "./content-types"
@@ -44,23 +48,25 @@ export {
HoppRESTParams,
} from "./v/7"
-export { HoppRESTAuthDigest, PasswordGrantTypeParams } from "./v/8"
+export { HoppRESTAuthDigest, PasswordGrantTypeParams } from "./v/8/auth"
-export { FormDataKeyValue } from "./v/9"
-
-export { HoppRESTAuthOAuth2, ClientCredentialsGrantTypeParams } from "./v/11"
-
-export { HoppRESTReqBody } from "./v/10"
-
-export { HoppRESTAuthHAWK, HoppRESTAuthAkamaiEdgeGrid } from "./v/12"
+export { FormDataKeyValue } from "./v/9/body"
+
+export {
+ HoppRESTAuthOAuth2,
+ ClientCredentialsGrantTypeParams,
+} from "./v/11/auth"
+
+export { HoppRESTReqBody } from "./v/10/body"
+
+export { HoppRESTAuthHAWK, HoppRESTAuthAkamaiEdgeGrid } from "./v/12/auth"
+
+export { HoppRESTAuth, HoppRESTAuthJWT } from "./v/13/auth"
export {
- HoppRESTAuth,
- HoppRESTAuthJWT,
- HoppRESTRequestResponses,
- HoppRESTResponseOriginalRequest,
HoppRESTRequestResponse,
-} from "./v/13"
+ HoppRESTRequestResponses,
+} from "../rest-request-response"
const versionedObject = z.object({
// v is a stringified number
@@ -68,7 +74,7 @@ const versionedObject = z.object({
})
export const HoppRESTRequest = createVersionedEntity({
- latestVersion: 13,
+ latestVersion: 14,
versionMap: {
0: V0_VERSION,
1: V1_VERSION,
@@ -84,6 +90,7 @@ export const HoppRESTRequest = createVersionedEntity({
11: V11_VERSION,
12: V12_VERSION,
13: V13_VERSION,
+ 14: V14_VERSION,
},
getVersion(data) {
// For V1 onwards we have the v string storing the number
@@ -126,8 +133,7 @@ const HoppRESTRequestEq = Eq.struct({
responses: lodashIsEqualEq,
})
-export const RESTReqSchemaVersion = "13"
-export const RESTResOriginalReqSchemaVersion = "5" as const
+export const RESTReqSchemaVersion = "14"
export type HoppRESTParam = HoppRESTRequest["params"][number]
export type HoppRESTHeader = HoppRESTRequest["headers"][number]
@@ -210,7 +216,6 @@ export function safelyExtractRESTRequest(
if ("responses" in x) {
const result = HoppRESTRequestResponses.safeParse(x.responses)
-
if (result.success) {
req.responses = result.data
}
diff --git a/packages/hoppscotch-data/src/rest/v/10.ts b/packages/hoppscotch-data/src/rest/v/10/body.ts
similarity index 76%
rename from packages/hoppscotch-data/src/rest/v/10.ts
rename to packages/hoppscotch-data/src/rest/v/10/body.ts
index 9dc77e23..af22ca93 100644
--- a/packages/hoppscotch-data/src/rest/v/10.ts
+++ b/packages/hoppscotch-data/src/rest/v/10/body.ts
@@ -1,6 +1,5 @@
import { z } from "zod"
-import { FormDataKeyValue, V9_SCHEMA } from "./9"
-import { defineVersion } from "verzod"
+import { FormDataKeyValue } from "../9/body"
export const HoppRESTReqBody = z.union([
z.object({
@@ -39,19 +38,3 @@ export const HoppRESTReqBody = z.union([
])
export type HoppRESTReqBody = z.infer
-
-export const V10_SCHEMA = V9_SCHEMA.extend({
- v: z.literal("10"),
- body: HoppRESTReqBody,
-})
-
-export default defineVersion({
- schema: V10_SCHEMA,
- initial: false,
- up(old: z.infer) {
- return {
- ...old,
- v: "10" as const,
- }
- },
-})
diff --git a/packages/hoppscotch-data/src/rest/v/10/index.ts b/packages/hoppscotch-data/src/rest/v/10/index.ts
new file mode 100644
index 00000000..95367fb3
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest/v/10/index.ts
@@ -0,0 +1,20 @@
+import { z } from "zod"
+import { V9_SCHEMA } from "../9"
+import { HoppRESTReqBody } from "./body"
+import { defineVersion } from "verzod"
+
+export const V10_SCHEMA = V9_SCHEMA.extend({
+ v: z.literal("10"),
+ body: HoppRESTReqBody,
+})
+
+export default defineVersion({
+ schema: V10_SCHEMA,
+ initial: false,
+ up(old: z.infer) {
+ return {
+ ...old,
+ v: "10" as const,
+ }
+ },
+})
diff --git a/packages/hoppscotch-data/src/rest/v/11.ts b/packages/hoppscotch-data/src/rest/v/11.ts
deleted file mode 100644
index 2db50114..00000000
--- a/packages/hoppscotch-data/src/rest/v/11.ts
+++ /dev/null
@@ -1,146 +0,0 @@
-import {
- HoppRESTAuthBasic,
- HoppRESTAuthBearer,
- HoppRESTAuthInherit,
- HoppRESTAuthNone,
-} from "./1"
-import { HoppRESTAuthAPIKey } from "./4"
-import { AuthCodeGrantTypeParams, HoppRESTAuthAWSSignature } from "./7"
-import {
- ClientCredentialsGrantTypeParams as ClientCredentialsGrantTypeParamsOld,
- HoppRESTAuthDigest,
- PasswordGrantTypeParams,
-} from "./8"
-import { ImplicitOauthFlowParams } from "./3"
-import { z } from "zod"
-
-import { HoppRESTReqBody, V10_SCHEMA } from "./10"
-import { defineVersion } from "verzod"
-import {
- HoppRESTResponseOriginalRequest as HoppRESTResponseOriginalRequestOld,
- HoppRESTRequestResponse as HoppRESTRequestResponseOld,
-} from "./9"
-
-export const ClientCredentialsGrantTypeParams =
- ClientCredentialsGrantTypeParamsOld.extend({
- clientAuthentication: z.enum(["AS_BASIC_AUTH_HEADERS", "IN_BODY"]),
- })
-
-export const HoppRESTAuthOAuth2 = z.object({
- authType: z.literal("oauth-2"),
- grantTypeInfo: z.discriminatedUnion("grantType", [
- AuthCodeGrantTypeParams,
- ClientCredentialsGrantTypeParams,
- PasswordGrantTypeParams,
- ImplicitOauthFlowParams,
- ]),
- addTo: z.enum(["HEADERS", "QUERY_PARAMS"]).catch("HEADERS"),
-})
-
-export type HoppRESTAuthOAuth2 = z.infer
-
-export const HoppRESTAuth = z
- .discriminatedUnion("authType", [
- HoppRESTAuthNone,
- HoppRESTAuthInherit,
- HoppRESTAuthBasic,
- HoppRESTAuthBearer,
- HoppRESTAuthOAuth2,
- HoppRESTAuthAPIKey,
- HoppRESTAuthAWSSignature,
- HoppRESTAuthDigest,
- ])
- .and(
- z.object({
- authActive: z.boolean(),
- })
- )
-
-export type HoppRESTAuth = z.infer
-
-export const HoppRESTResponseOriginalRequest =
- HoppRESTResponseOriginalRequestOld.extend({
- v: z.literal("3"),
- auth: HoppRESTAuth,
- body: HoppRESTReqBody,
- })
-
-export type HoppRESTResponseOriginalRequest = z.infer<
- typeof HoppRESTResponseOriginalRequest
->
-
-export const HoppRESTRequestResponse = HoppRESTRequestResponseOld.extend({
- originalRequest: HoppRESTResponseOriginalRequest,
-})
-
-export type HoppRESTRequestResponse = z.infer
-
-export const HoppRESTRequestResponses = z.record(
- z.string(),
- HoppRESTRequestResponse
-)
-
-export type HoppRESTRequestResponses = z.infer
-
-export const V11_SCHEMA = V10_SCHEMA.extend({
- v: z.literal("11"),
- auth: HoppRESTAuth,
- responses: HoppRESTRequestResponses,
-})
-
-export default defineVersion({
- schema: V11_SCHEMA,
- initial: false,
- up(old: z.infer) {
- const auth = old.auth
-
- // update auth for responses
- const responses = Object.fromEntries(
- Object.entries(old.responses).map(([key, response]) => [
- key,
- {
- ...response,
- originalRequest: {
- ...response.originalRequest,
-
- auth:
- auth.authType === "oauth-2"
- ? {
- ...auth,
- grantTypeInfo:
- auth.grantTypeInfo.grantType === "CLIENT_CREDENTIALS"
- ? {
- ...auth.grantTypeInfo,
- clientAuthentication: "IN_BODY" as const,
- }
- : auth.grantTypeInfo,
- }
- : auth,
-
- // just following the previous pattern here, but is this a good idea to overwrite the request version ?
- v: "3" as const,
- },
- },
- ])
- )
-
- return {
- ...old,
- v: "11" as const,
- auth:
- auth.authType === "oauth-2"
- ? {
- ...auth,
- grantTypeInfo:
- auth.grantTypeInfo.grantType === "CLIENT_CREDENTIALS"
- ? {
- ...auth.grantTypeInfo,
- clientAuthentication: "IN_BODY" as const,
- }
- : auth.grantTypeInfo,
- }
- : auth,
- responses,
- }
- },
-})
diff --git a/packages/hoppscotch-data/src/rest/v/11/auth.ts b/packages/hoppscotch-data/src/rest/v/11/auth.ts
new file mode 100644
index 00000000..81be6cc8
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest/v/11/auth.ts
@@ -0,0 +1,52 @@
+import {
+ HoppRESTAuthBasic,
+ HoppRESTAuthBearer,
+ HoppRESTAuthInherit,
+ HoppRESTAuthNone,
+} from "../1"
+import { HoppRESTAuthAPIKey } from "../4"
+import { AuthCodeGrantTypeParams, HoppRESTAuthAWSSignature } from "../7"
+import {
+ ClientCredentialsGrantTypeParams as ClientCredentialsGrantTypeParamsOld,
+ HoppRESTAuthDigest,
+ PasswordGrantTypeParams,
+} from "../8/auth"
+import { ImplicitOauthFlowParams } from "../3"
+import { z } from "zod"
+
+export const ClientCredentialsGrantTypeParams =
+ ClientCredentialsGrantTypeParamsOld.extend({
+ clientAuthentication: z.enum(["AS_BASIC_AUTH_HEADERS", "IN_BODY"]),
+ })
+
+export const HoppRESTAuthOAuth2 = z.object({
+ authType: z.literal("oauth-2"),
+ grantTypeInfo: z.discriminatedUnion("grantType", [
+ AuthCodeGrantTypeParams,
+ ClientCredentialsGrantTypeParams,
+ PasswordGrantTypeParams,
+ ImplicitOauthFlowParams,
+ ]),
+ addTo: z.enum(["HEADERS", "QUERY_PARAMS"]).catch("HEADERS"),
+})
+
+export type HoppRESTAuthOAuth2 = z.infer
+
+export const HoppRESTAuth = z
+ .discriminatedUnion("authType", [
+ HoppRESTAuthNone,
+ HoppRESTAuthInherit,
+ HoppRESTAuthBasic,
+ HoppRESTAuthBearer,
+ HoppRESTAuthOAuth2,
+ HoppRESTAuthAPIKey,
+ HoppRESTAuthAWSSignature,
+ HoppRESTAuthDigest,
+ ])
+ .and(
+ z.object({
+ authActive: z.boolean(),
+ })
+ )
+
+export type HoppRESTAuth = z.infer
diff --git a/packages/hoppscotch-data/src/rest/v/11/index.ts b/packages/hoppscotch-data/src/rest/v/11/index.ts
new file mode 100644
index 00000000..4fb0d977
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest/v/11/index.ts
@@ -0,0 +1,37 @@
+import { z } from "zod"
+
+import { V10_SCHEMA } from "../10"
+import { defineVersion } from "verzod"
+
+import { HoppRESTAuth } from "./auth"
+
+export const V11_SCHEMA = V10_SCHEMA.extend({
+ v: z.literal("11"),
+ auth: HoppRESTAuth,
+})
+
+export default defineVersion({
+ schema: V11_SCHEMA,
+ initial: false,
+ up(old: z.infer) {
+ const auth = old.auth
+
+ return {
+ ...old,
+ v: "11" as const,
+ auth:
+ auth.authType === "oauth-2"
+ ? {
+ ...auth,
+ grantTypeInfo:
+ auth.grantTypeInfo.grantType === "CLIENT_CREDENTIALS"
+ ? {
+ ...auth.grantTypeInfo,
+ clientAuthentication: "IN_BODY" as const,
+ }
+ : auth.grantTypeInfo,
+ }
+ : auth,
+ }
+ },
+})
diff --git a/packages/hoppscotch-data/src/rest/v/12.ts b/packages/hoppscotch-data/src/rest/v/12.ts
deleted file mode 100644
index 9f42b8b3..00000000
--- a/packages/hoppscotch-data/src/rest/v/12.ts
+++ /dev/null
@@ -1,128 +0,0 @@
-import {
- HoppRESTAuthBasic,
- HoppRESTAuthBearer,
- HoppRESTAuthInherit,
- HoppRESTAuthNone,
-} from "./1"
-import { HoppRESTAuthAPIKey } from "./4"
-import { HoppRESTAuthAWSSignature } from "./7"
-import { HoppRESTAuthDigest } from "./8"
-
-import { z } from "zod"
-import { defineVersion } from "verzod"
-import { HoppRESTAuthOAuth2, V11_SCHEMA } from "./11"
-
-import {
- HoppRESTResponseOriginalRequest as HoppRESTResponseOriginalRequestOld,
- HoppRESTRequestResponse as HoppRESTRequestResponseOld,
-} from "./9"
-
-export const HoppRESTAuthHAWK = z.object({
- authType: z.literal("hawk"),
- authId: z.string().catch(""),
- authKey: z.string().catch(""),
- algorithm: z.enum(["sha256", "sha1"]).catch("sha256"),
- includePayloadHash: z.boolean().catch(false),
-
- // Optional fields
- user: z.string().optional(),
- nonce: z.string().optional(),
- ext: z.string().optional(),
- app: z.string().optional(),
- dlg: z.string().optional(),
- timestamp: z.string().optional(),
-})
-
-export const HoppRESTAuthAkamaiEdgeGrid = z.object({
- authType: z.literal("akamai-eg"),
- accessToken: z.string().catch(""),
- clientToken: z.string().catch(""),
- clientSecret: z.string().catch(""),
-
- // Optional fields
- nonce: z.string().optional(),
- timestamp: z.string().optional(),
- host: z.string().optional(),
- headersToSign: z.string().optional(),
- maxBodySize: z.string().optional(),
-})
-
-export type HoppRESTAuthHAWK = z.infer
-export type HoppRESTAuthAkamaiEdgeGrid = z.infer<
- typeof HoppRESTAuthAkamaiEdgeGrid
->
-
-export const HoppRESTAuth = z
- .discriminatedUnion("authType", [
- HoppRESTAuthNone,
- HoppRESTAuthInherit,
- HoppRESTAuthBasic,
- HoppRESTAuthBearer,
- HoppRESTAuthOAuth2,
- HoppRESTAuthAPIKey,
- HoppRESTAuthAWSSignature,
- HoppRESTAuthDigest,
- HoppRESTAuthHAWK,
- HoppRESTAuthAkamaiEdgeGrid,
- ])
- .and(
- z.object({
- authActive: z.boolean(),
- })
- )
-
-export type HoppRESTAuth = z.infer
-
-export const HoppRESTResponseOriginalRequest =
- HoppRESTResponseOriginalRequestOld.extend({
- v: z.literal("4"),
- auth: HoppRESTAuth,
- })
-
-export type HoppRESTResponseOriginalRequest = z.infer<
- typeof HoppRESTResponseOriginalRequest
->
-
-export const HoppRESTRequestResponse = HoppRESTRequestResponseOld.extend({
- originalRequest: HoppRESTResponseOriginalRequest,
-})
-
-export type HoppRESTRequestResponse = z.infer
-
-export const HoppRESTRequestResponses = z.record(
- z.string(),
- HoppRESTRequestResponse
-)
-
-export type HoppRESTRequestResponses = z.infer
-
-export const V12_SCHEMA = V11_SCHEMA.extend({
- v: z.literal("12"),
- auth: HoppRESTAuth,
- responses: HoppRESTRequestResponses,
-})
-
-export default defineVersion({
- schema: V12_SCHEMA,
- initial: false,
- up(old: z.infer) {
- // update the version number of response original request
- const responses = Object.fromEntries(
- Object.entries(old.responses).map(([key, response]) => [
- key,
- {
- ...response,
- originalRequest: {
- ...response.originalRequest,
- v: "4" as const,
- },
- },
- ])
- )
- return {
- ...old,
- v: "12" as const,
- responses,
- }
- },
-})
diff --git a/packages/hoppscotch-data/src/rest/v/12/auth.ts b/packages/hoppscotch-data/src/rest/v/12/auth.ts
new file mode 100644
index 00000000..4eb3af75
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest/v/12/auth.ts
@@ -0,0 +1,67 @@
+import { z } from "zod"
+import {
+ HoppRESTAuthBasic,
+ HoppRESTAuthBearer,
+ HoppRESTAuthInherit,
+ HoppRESTAuthNone,
+} from "../1"
+import { HoppRESTAuthAPIKey } from "../4"
+import { HoppRESTAuthAWSSignature } from "../7"
+import { HoppRESTAuthDigest } from "../8/auth"
+import { HoppRESTAuthOAuth2 } from "../11/auth"
+
+export const HoppRESTAuthHAWK = z.object({
+ authType: z.literal("hawk"),
+ authId: z.string().catch(""),
+ authKey: z.string().catch(""),
+ algorithm: z.enum(["sha256", "sha1"]).catch("sha256"),
+ includePayloadHash: z.boolean().catch(false),
+
+ // Optional fields
+ user: z.string().optional(),
+ nonce: z.string().optional(),
+ ext: z.string().optional(),
+ app: z.string().optional(),
+ dlg: z.string().optional(),
+ timestamp: z.string().optional(),
+})
+
+export const HoppRESTAuthAkamaiEdgeGrid = z.object({
+ authType: z.literal("akamai-eg"),
+ accessToken: z.string().catch(""),
+ clientToken: z.string().catch(""),
+ clientSecret: z.string().catch(""),
+
+ // Optional fields
+ nonce: z.string().optional(),
+ timestamp: z.string().optional(),
+ host: z.string().optional(),
+ headersToSign: z.string().optional(),
+ maxBodySize: z.string().optional(),
+})
+
+export type HoppRESTAuthHAWK = z.infer
+export type HoppRESTAuthAkamaiEdgeGrid = z.infer<
+ typeof HoppRESTAuthAkamaiEdgeGrid
+>
+
+export const HoppRESTAuth = z
+ .discriminatedUnion("authType", [
+ HoppRESTAuthNone,
+ HoppRESTAuthInherit,
+ HoppRESTAuthBasic,
+ HoppRESTAuthBearer,
+ HoppRESTAuthOAuth2,
+ HoppRESTAuthAPIKey,
+ HoppRESTAuthAWSSignature,
+ HoppRESTAuthDigest,
+ HoppRESTAuthHAWK,
+ HoppRESTAuthAkamaiEdgeGrid,
+ ])
+ .and(
+ z.object({
+ authActive: z.boolean(),
+ })
+ )
+
+export type HoppRESTAuth = z.infer
diff --git a/packages/hoppscotch-data/src/rest/v/12/index.ts b/packages/hoppscotch-data/src/rest/v/12/index.ts
new file mode 100644
index 00000000..49460101
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest/v/12/index.ts
@@ -0,0 +1,21 @@
+import { z } from "zod"
+import { defineVersion } from "verzod"
+import { V11_SCHEMA } from "../11"
+
+import { HoppRESTAuth } from "./auth"
+
+export const V12_SCHEMA = V11_SCHEMA.extend({
+ v: z.literal("12"),
+ auth: HoppRESTAuth,
+})
+
+export default defineVersion({
+ schema: V12_SCHEMA,
+ initial: false,
+ up(old: z.infer) {
+ return {
+ ...old,
+ v: "12" as const,
+ }
+ },
+})
diff --git a/packages/hoppscotch-data/src/rest/v/13.ts b/packages/hoppscotch-data/src/rest/v/13.ts
deleted file mode 100644
index 994df695..00000000
--- a/packages/hoppscotch-data/src/rest/v/13.ts
+++ /dev/null
@@ -1,126 +0,0 @@
-import {
- HoppRESTAuthBasic,
- HoppRESTAuthBearer,
- HoppRESTAuthInherit,
- HoppRESTAuthNone,
-} from "./1"
-import { HoppRESTAuthAPIKey } from "./4"
-import { HoppRESTAuthAWSSignature } from "./7"
-import { HoppRESTAuthDigest } from "./8"
-
-import { HoppRESTAuthHAWK, HoppRESTAuthAkamaiEdgeGrid, V12_SCHEMA } from "./12"
-
-import { z } from "zod"
-import { defineVersion } from "verzod"
-import { HoppRESTAuthOAuth2 } from "./11"
-
-import {
- HoppRESTResponseOriginalRequest as HoppRESTResponseOriginalRequestOld,
- HoppRESTRequestResponse as HoppRESTRequestResponseOld,
-} from "./9"
-
-export const HoppRESTAuthJWT = z.object({
- authType: z.literal("jwt"),
- secret: z.string().catch(""),
- privateKey: z.string().catch(""), // For RSA/ECDSA algorithms
- algorithm: z
- .enum([
- "HS256",
- "HS384",
- "HS512",
- "RS256",
- "RS384",
- "RS512",
- "PS256",
- "PS384",
- "PS512",
- "ES256",
- "ES384",
- "ES512",
- ])
- .catch("HS256"),
- payload: z.string().catch("{}"),
- addTo: z.enum(["HEADERS", "QUERY_PARAMS"]).catch("HEADERS"),
- isSecretBase64Encoded: z.boolean().catch(false),
- headerPrefix: z.string().catch("Bearer "),
- paramName: z.string().catch("token"),
- jwtHeaders: z.string().catch("{}"),
-})
-
-export type HoppRESTAuthJWT = z.infer
-
-export const HoppRESTAuth = z
- .discriminatedUnion("authType", [
- HoppRESTAuthNone,
- HoppRESTAuthInherit,
- HoppRESTAuthBasic,
- HoppRESTAuthBearer,
- HoppRESTAuthOAuth2,
- HoppRESTAuthAPIKey,
- HoppRESTAuthAWSSignature,
- HoppRESTAuthDigest,
- HoppRESTAuthHAWK,
- HoppRESTAuthAkamaiEdgeGrid,
- HoppRESTAuthJWT,
- ])
- .and(
- z.object({
- authActive: z.boolean(),
- })
- )
-
-export type HoppRESTAuth = z.infer
-
-export const HoppRESTResponseOriginalRequest =
- HoppRESTResponseOriginalRequestOld.extend({
- v: z.literal("5"),
- auth: HoppRESTAuth,
- })
-
-export type HoppRESTResponseOriginalRequest = z.infer<
- typeof HoppRESTResponseOriginalRequest
->
-
-export const HoppRESTRequestResponse = HoppRESTRequestResponseOld.extend({
- originalRequest: HoppRESTResponseOriginalRequest,
-})
-
-export type HoppRESTRequestResponse = z.infer
-
-export const HoppRESTRequestResponses = z.record(
- z.string(),
- HoppRESTRequestResponse
-)
-
-export type HoppRESTRequestResponses = z.infer
-
-export const V13_SCHEMA = V12_SCHEMA.extend({
- v: z.literal("13"),
- auth: HoppRESTAuth,
- responses: HoppRESTRequestResponses,
-})
-
-export default defineVersion({
- schema: V13_SCHEMA,
- initial: false,
- up(old: z.infer) {
- // update the version number of response original request
- const responses = Object.fromEntries(
- Object.entries(old.responses).map(([key, response]) => [
- key,
- {
- ...response,
- originalRequest: {
- ...response.originalRequest,
- v: "5" as const,
- },
- },
- ])
- )
- return {
- ...old,
- v: "13" as const,
- responses,
- }
- },
-})
diff --git a/packages/hoppscotch-data/src/rest/v/13/auth.ts b/packages/hoppscotch-data/src/rest/v/13/auth.ts
new file mode 100644
index 00000000..01d20317
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest/v/13/auth.ts
@@ -0,0 +1,64 @@
+import { z } from "zod"
+import {
+ HoppRESTAuthBasic,
+ HoppRESTAuthBearer,
+ HoppRESTAuthInherit,
+ HoppRESTAuthNone,
+} from "../1"
+import { HoppRESTAuthAPIKey } from "../4"
+import { HoppRESTAuthAWSSignature } from "../7"
+import { HoppRESTAuthDigest } from "../8/auth"
+import { HoppRESTAuthOAuth2 } from "../11/auth"
+import { HoppRESTAuthAkamaiEdgeGrid, HoppRESTAuthHAWK } from "../12/auth"
+
+export const HoppRESTAuthJWT = z.object({
+ authType: z.literal("jwt"),
+ secret: z.string().catch(""),
+ privateKey: z.string().catch(""), // For RSA/ECDSA algorithms
+ algorithm: z
+ .enum([
+ "HS256",
+ "HS384",
+ "HS512",
+ "RS256",
+ "RS384",
+ "RS512",
+ "PS256",
+ "PS384",
+ "PS512",
+ "ES256",
+ "ES384",
+ "ES512",
+ ])
+ .catch("HS256"),
+ payload: z.string().catch("{}"),
+ addTo: z.enum(["HEADERS", "QUERY_PARAMS"]).catch("HEADERS"),
+ isSecretBase64Encoded: z.boolean().catch(false),
+ headerPrefix: z.string().catch("Bearer "),
+ paramName: z.string().catch("token"),
+ jwtHeaders: z.string().catch("{}"),
+})
+
+export type HoppRESTAuthJWT = z.infer
+
+export const HoppRESTAuth = z
+ .discriminatedUnion("authType", [
+ HoppRESTAuthNone,
+ HoppRESTAuthInherit,
+ HoppRESTAuthBasic,
+ HoppRESTAuthBearer,
+ HoppRESTAuthOAuth2,
+ HoppRESTAuthAPIKey,
+ HoppRESTAuthAWSSignature,
+ HoppRESTAuthDigest,
+ HoppRESTAuthHAWK,
+ HoppRESTAuthAkamaiEdgeGrid,
+ HoppRESTAuthJWT,
+ ])
+ .and(
+ z.object({
+ authActive: z.boolean(),
+ })
+ )
+
+export type HoppRESTAuth = z.infer
diff --git a/packages/hoppscotch-data/src/rest/v/13/index.ts b/packages/hoppscotch-data/src/rest/v/13/index.ts
new file mode 100644
index 00000000..ff4ca826
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest/v/13/index.ts
@@ -0,0 +1,22 @@
+import { V12_SCHEMA } from "../12"
+
+import { z } from "zod"
+import { defineVersion } from "verzod"
+
+import { HoppRESTAuth } from "./auth"
+
+export const V13_SCHEMA = V12_SCHEMA.extend({
+ v: z.literal("13"),
+ auth: HoppRESTAuth,
+})
+
+export default defineVersion({
+ schema: V13_SCHEMA,
+ initial: false,
+ up(old: z.infer) {
+ return {
+ ...old,
+ v: "13" as const,
+ }
+ },
+})
diff --git a/packages/hoppscotch-data/src/rest/v/14.ts b/packages/hoppscotch-data/src/rest/v/14.ts
new file mode 100644
index 00000000..f49167ba
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest/v/14.ts
@@ -0,0 +1,19 @@
+import { z } from "zod"
+import { defineVersion } from "verzod"
+import { V13_SCHEMA } from "./13"
+
+// Update the HoppRESTRequestResponses while migrating HoppRESTRequest
+export const V14_SCHEMA = V13_SCHEMA.extend({
+ v: z.literal("14"),
+})
+
+export default defineVersion({
+ schema: V14_SCHEMA,
+ initial: false,
+ up(old: z.infer) {
+ return {
+ ...old,
+ v: "14" as const,
+ }
+ },
+})
diff --git a/packages/hoppscotch-data/src/rest/v/8.ts b/packages/hoppscotch-data/src/rest/v/8.ts
deleted file mode 100644
index 868fa3a4..00000000
--- a/packages/hoppscotch-data/src/rest/v/8.ts
+++ /dev/null
@@ -1,166 +0,0 @@
-import { defineVersion } from "verzod"
-import { z } from "zod"
-
-import {
- HoppRESTAuthBasic,
- HoppRESTAuthBearer,
- HoppRESTAuthInherit,
- HoppRESTAuthNone,
-} from "./1"
-
-import { HoppRESTAuthAPIKey } from "./4"
-
-import {
- ClientCredentialsGrantTypeParams as ClientCredentialsGrantTypeParamsOld,
- ImplicitOauthFlowParams,
- PasswordGrantTypeParams as PasswordGrantTypeParamsOld,
-} from "./3"
-
-import {
- AuthCodeGrantTypeParams,
- HoppRESTAuthAWSSignature,
- HoppRESTHeaders,
- HoppRESTParams,
- V7_SCHEMA,
-} from "./7"
-
-import { StatusCodes } from "../../utils/statusCodes"
-import { HoppRESTReqBody } from "./6"
-import { HoppRESTRequestVariables } from "./2"
-
-export const ClientCredentialsGrantTypeParams =
- ClientCredentialsGrantTypeParamsOld.extend({
- clientSecret: z.string().optional(),
- })
-
-export const PasswordGrantTypeParams = PasswordGrantTypeParamsOld.extend({
- clientSecret: z.string().optional(),
-})
-
-export const HoppRESTAuthOAuth2 = z.object({
- authType: z.literal("oauth-2"),
- grantTypeInfo: z.discriminatedUnion("grantType", [
- AuthCodeGrantTypeParams,
- ClientCredentialsGrantTypeParams,
- PasswordGrantTypeParams,
- ImplicitOauthFlowParams,
- ]),
- addTo: z.enum(["HEADERS", "QUERY_PARAMS"]).catch("HEADERS"),
-})
-
-export type HoppRESTAuthOAuth2 = z.infer
-
-// in this new version, we add a new auth type for Digest authentication
-export const HoppRESTAuthDigest = z.object({
- authType: z.literal("digest"),
- username: z.string().catch(""),
- password: z.string().catch(""),
- realm: z.string().catch(""),
- nonce: z.string().catch(""),
- algorithm: z.enum(["MD5", "MD5-sess"]).catch("MD5"),
- qop: z.enum(["auth", "auth-int"]).catch("auth"),
- nc: z.string().catch(""),
- cnonce: z.string().catch(""),
- opaque: z.string().catch(""),
- disableRetry: z.boolean().catch(false),
-})
-
-export type HoppRESTAuthDigest = z.infer
-
-export const HoppRESTAuth = z
- .discriminatedUnion("authType", [
- HoppRESTAuthNone,
- HoppRESTAuthInherit,
- HoppRESTAuthBasic,
- HoppRESTAuthBearer,
- HoppRESTAuthOAuth2,
- HoppRESTAuthAPIKey,
- HoppRESTAuthAWSSignature,
- HoppRESTAuthDigest,
- ])
- .and(
- z.object({
- authActive: z.boolean(),
- })
- )
-
-export type HoppRESTAuth = z.infer
-
-export const ValidCodes = z.union(
- Object.keys(StatusCodes).map((code) => z.literal(parseInt(code))) as [
- z.ZodLiteral,
- z.ZodLiteral,
- ...z.ZodLiteral[]
- ]
-)
-
-export const HoppRESTResponseHeaders = z.array(
- z.object({
- key: z.string(),
- value: z.string(),
- })
-)
-
-export type HoppRESTResponseHeader = z.infer
-
-/**
- * The original request that was made to get this response
- * Only the necessary fields are saved
- */
-export const HoppRESTResponseOriginalRequest = z.object({
- v: z.literal("1"),
- name: z.string(),
- method: z.string(),
- endpoint: z.string(),
- headers: HoppRESTHeaders,
- params: HoppRESTParams,
- body: HoppRESTReqBody,
- auth: HoppRESTAuth,
- requestVariables: HoppRESTRequestVariables,
-})
-
-export type HoppRESTResponseOriginalRequest = z.infer<
- typeof HoppRESTResponseOriginalRequest
->
-
-export const HoppRESTRequestResponse = z.object({
- name: z.string(),
- originalRequest: HoppRESTResponseOriginalRequest,
- status: z.string(),
- code: z.optional(ValidCodes),
- headers: HoppRESTResponseHeaders,
- body: z.string(),
-})
-
-export type HoppRESTRequestResponse = z.infer
-
-/**
- * The responses saved for a request
- * The key is the name of the response saved by the user
- * The value is the response
- */
-export const HoppRESTRequestResponses = z.record(
- z.string(),
- HoppRESTRequestResponse
-)
-
-export type HoppRESTRequestResponses = z.infer
-
-export const V8_SCHEMA = V7_SCHEMA.extend({
- v: z.literal("8"),
- auth: HoppRESTAuth,
- responses: HoppRESTRequestResponses,
-})
-
-export default defineVersion({
- schema: V8_SCHEMA,
- initial: false,
- up(old: z.infer) {
- return {
- ...old,
- v: "8" as const,
- // no need to update anything for HoppRESTAuth, because we loosened the previous schema by making `clientSecret` optional
- responses: {},
- }
- },
-})
diff --git a/packages/hoppscotch-data/src/rest/v/8/auth.ts b/packages/hoppscotch-data/src/rest/v/8/auth.ts
new file mode 100644
index 00000000..1ff66e10
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest/v/8/auth.ts
@@ -0,0 +1,75 @@
+import {
+ HoppRESTAuthBasic,
+ HoppRESTAuthBearer,
+ HoppRESTAuthInherit,
+ HoppRESTAuthNone,
+} from "../1"
+
+import { HoppRESTAuthAPIKey } from "../4"
+
+import {
+ ClientCredentialsGrantTypeParams as ClientCredentialsGrantTypeParamsOld,
+ ImplicitOauthFlowParams,
+ PasswordGrantTypeParams as PasswordGrantTypeParamsOld,
+} from "../3"
+
+import { AuthCodeGrantTypeParams, HoppRESTAuthAWSSignature } from "../7"
+import { z } from "zod"
+
+export const ClientCredentialsGrantTypeParams =
+ ClientCredentialsGrantTypeParamsOld.extend({
+ clientSecret: z.string().optional(),
+ })
+
+export const PasswordGrantTypeParams = PasswordGrantTypeParamsOld.extend({
+ clientSecret: z.string().optional(),
+})
+
+export const HoppRESTAuthOAuth2 = z.object({
+ authType: z.literal("oauth-2"),
+ grantTypeInfo: z.discriminatedUnion("grantType", [
+ AuthCodeGrantTypeParams,
+ ClientCredentialsGrantTypeParams,
+ PasswordGrantTypeParams,
+ ImplicitOauthFlowParams,
+ ]),
+ addTo: z.enum(["HEADERS", "QUERY_PARAMS"]).catch("HEADERS"),
+})
+
+export type HoppRESTAuthOAuth2 = z.infer
+
+// in this new version, we add a new auth type for Digest authentication
+export const HoppRESTAuthDigest = z.object({
+ authType: z.literal("digest"),
+ username: z.string().catch(""),
+ password: z.string().catch(""),
+ realm: z.string().catch(""),
+ nonce: z.string().catch(""),
+ algorithm: z.enum(["MD5", "MD5-sess"]).catch("MD5"),
+ qop: z.enum(["auth", "auth-int"]).catch("auth"),
+ nc: z.string().catch(""),
+ cnonce: z.string().catch(""),
+ opaque: z.string().catch(""),
+ disableRetry: z.boolean().catch(false),
+})
+
+export type HoppRESTAuthDigest = z.infer
+
+export const HoppRESTAuth = z
+ .discriminatedUnion("authType", [
+ HoppRESTAuthNone,
+ HoppRESTAuthInherit,
+ HoppRESTAuthBasic,
+ HoppRESTAuthBearer,
+ HoppRESTAuthOAuth2,
+ HoppRESTAuthAPIKey,
+ HoppRESTAuthAWSSignature,
+ HoppRESTAuthDigest,
+ ])
+ .and(
+ z.object({
+ authActive: z.boolean(),
+ })
+ )
+
+export type HoppRESTAuth = z.infer
diff --git a/packages/hoppscotch-data/src/rest/v/8/index.ts b/packages/hoppscotch-data/src/rest/v/8/index.ts
new file mode 100644
index 00000000..c1b818f5
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest/v/8/index.ts
@@ -0,0 +1,27 @@
+import { defineVersion } from "verzod"
+import { z } from "zod"
+
+import { V7_SCHEMA } from "../7"
+
+import { HoppRESTRequestResponses } from "../../../rest-request-response"
+
+import { HoppRESTAuth } from "./auth"
+
+export const V8_SCHEMA = V7_SCHEMA.extend({
+ v: z.literal("8"),
+ auth: HoppRESTAuth,
+ responses: HoppRESTRequestResponses,
+})
+
+export default defineVersion({
+ schema: V8_SCHEMA,
+ initial: false,
+ up(old: z.infer) {
+ return {
+ ...old,
+ v: "8" as const,
+ // no need to update anything for HoppRESTAuth, because we loosened the previous schema by making `clientSecret` optional
+ responses: {},
+ }
+ },
+})
diff --git a/packages/hoppscotch-data/src/rest/v/9.ts b/packages/hoppscotch-data/src/rest/v/9.ts
deleted file mode 100644
index ffacb537..00000000
--- a/packages/hoppscotch-data/src/rest/v/9.ts
+++ /dev/null
@@ -1,154 +0,0 @@
-import { defineVersion } from "verzod"
-import { z } from "zod"
-
-import { HoppRESTRequestVariables } from "./2"
-import { HoppRESTHeaders, HoppRESTParams } from "./7"
-import {
- HoppRESTAuth,
- HoppRESTResponseHeaders,
- V8_SCHEMA,
- ValidCodes,
-} from "./8"
-
-export const FormDataKeyValue = z
- .object({
- key: z.string(),
- active: z.boolean(),
- contentType: z.string().optional().catch(undefined),
- })
- .and(
- z.union([
- z.object({
- isFile: z.literal(true),
- value: z.array(z.instanceof(Blob).nullable()).catch([]),
- }),
- z.object({
- isFile: z.literal(false),
- value: z.string(),
- }),
- ])
- )
- .transform((data) => {
- // Sample use case about restoring the `value` field in an empty state during page reload
- // for files chosen in the previous attempt
- if (data.isFile && Array.isArray(data.value) && data.value.length === 0) {
- return {
- ...data,
- isFile: false,
- value: "",
- }
- }
-
- return data
- })
-
-export type FormDataKeyValue = z.infer
-
-export const HoppRESTReqBody = z.union([
- z.object({
- contentType: z.literal(null),
- body: z.literal(null).catch(null),
- }),
- z.object({
- contentType: z.literal("multipart/form-data"),
- body: z.array(FormDataKeyValue).catch([]),
- showIndividualContentType: z.boolean().optional().catch(false),
- }),
- z.object({
- contentType: z.literal("application/octet-stream"),
- body: z.instanceof(File).nullable().catch(null),
- }),
- z.object({
- contentType: z.union([
- z.literal("application/json"),
- z.literal("application/ld+json"),
- z.literal("application/hal+json"),
- z.literal("application/vnd.api+json"),
- z.literal("application/xml"),
- z.literal("text/xml"),
- z.literal("application/x-www-form-urlencoded"),
- z.literal("binary"),
- z.literal("text/html"),
- z.literal("text/plain"),
- ]),
- body: z.string().catch(""),
- }),
-])
-
-export type HoppRESTReqBody = z.infer
-
-/**
- * The original request that was made to get this response
- * Only the necessary fields are saved
- */
-export const HoppRESTResponseOriginalRequest = z.object({
- v: z.literal("2"),
- name: z.string(),
- method: z.string(),
- endpoint: z.string(),
- headers: HoppRESTHeaders,
- params: HoppRESTParams,
- body: HoppRESTReqBody,
- auth: HoppRESTAuth,
- requestVariables: HoppRESTRequestVariables,
-})
-
-export type HoppRESTResponseOriginalRequest = z.infer<
- typeof HoppRESTResponseOriginalRequest
->
-
-export const HoppRESTRequestResponse = z.object({
- name: z.string(),
- originalRequest: HoppRESTResponseOriginalRequest,
- status: z.string(),
- code: z.optional(ValidCodes).nullable().catch(null),
- headers: HoppRESTResponseHeaders,
- body: z.string(),
-})
-
-export type HoppRESTRequestResponse = z.infer
-
-/**
- * The responses saved for a request
- * The key is the name of the response saved by the user
- * The value is the response
- */
-export const HoppRESTRequestResponses = z.record(
- z.string(),
- HoppRESTRequestResponse
-)
-
-export type HoppRESTRequestResponses = z.infer
-
-export const V9_SCHEMA = V8_SCHEMA.extend({
- v: z.literal("9"),
- body: HoppRESTReqBody,
- responses: HoppRESTRequestResponses,
-})
-
-export default defineVersion({
- schema: V9_SCHEMA,
- initial: false,
- up(old: z.infer) {
- // update the version number of response original request
- const responses = Object.fromEntries(
- Object.entries(old.responses).map(([key, response]) => [
- key,
- {
- ...response,
- originalRequest: {
- ...response.originalRequest,
- v: "2" as const,
- },
- },
- ])
- )
-
- // No migration for body, the new contentType added to each formdata field is optional
- return {
- ...old,
- v: "9" as const,
- responses,
- }
- },
-})
diff --git a/packages/hoppscotch-data/src/rest/v/9/body.ts b/packages/hoppscotch-data/src/rest/v/9/body.ts
new file mode 100644
index 00000000..1ad19ae3
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest/v/9/body.ts
@@ -0,0 +1,68 @@
+import { z } from "zod"
+
+export const FormDataKeyValue = z
+ .object({
+ key: z.string(),
+ active: z.boolean(),
+ contentType: z.string().optional().catch(undefined),
+ })
+ .and(
+ z.union([
+ z.object({
+ isFile: z.literal(true),
+ value: z.array(z.instanceof(Blob).nullable()).catch([]),
+ }),
+ z.object({
+ isFile: z.literal(false),
+ value: z.string(),
+ }),
+ ])
+ )
+ .transform((data) => {
+ // Sample use case about restoring the `value` field in an empty state during page reload
+ // for files chosen in the previous attempt
+ if (data.isFile && Array.isArray(data.value) && data.value.length === 0) {
+ return {
+ ...data,
+ isFile: false,
+ value: "",
+ }
+ }
+
+ return data
+ })
+
+export type FormDataKeyValue = z.infer
+
+export const HoppRESTReqBody = z.union([
+ z.object({
+ contentType: z.literal(null),
+ body: z.literal(null).catch(null),
+ }),
+ z.object({
+ contentType: z.literal("multipart/form-data"),
+ body: z.array(FormDataKeyValue).catch([]),
+ showIndividualContentType: z.boolean().optional().catch(false),
+ }),
+ z.object({
+ contentType: z.literal("application/octet-stream"),
+ body: z.instanceof(File).nullable().catch(null),
+ }),
+ z.object({
+ contentType: z.union([
+ z.literal("application/json"),
+ z.literal("application/ld+json"),
+ z.literal("application/hal+json"),
+ z.literal("application/vnd.api+json"),
+ z.literal("application/xml"),
+ z.literal("text/xml"),
+ z.literal("application/x-www-form-urlencoded"),
+ z.literal("binary"),
+ z.literal("text/html"),
+ z.literal("text/plain"),
+ ]),
+ body: z.string().catch(""),
+ }),
+])
+
+export type HoppRESTReqBody = z.infer
diff --git a/packages/hoppscotch-data/src/rest/v/9/index.ts b/packages/hoppscotch-data/src/rest/v/9/index.ts
new file mode 100644
index 00000000..e38a64d1
--- /dev/null
+++ b/packages/hoppscotch-data/src/rest/v/9/index.ts
@@ -0,0 +1,22 @@
+import { defineVersion } from "verzod"
+import { z } from "zod"
+
+import { V8_SCHEMA } from "../8"
+import { HoppRESTReqBody } from "./body"
+
+export const V9_SCHEMA = V8_SCHEMA.extend({
+ v: z.literal("9"),
+ body: HoppRESTReqBody,
+})
+
+export default defineVersion({
+ schema: V9_SCHEMA,
+ initial: false,
+ up(old: z.infer) {
+ // No migration for body, the new contentType added to each formdata field is optional
+ return {
+ ...old,
+ v: "9" as const,
+ }
+ },
+})
diff --git a/packages/hoppscotch-selfhost-desktop/src/platform/environments/environments.platform.ts b/packages/hoppscotch-selfhost-desktop/src/platform/environments/environments.platform.ts
index 95a741b3..e0a55a61 100644
--- a/packages/hoppscotch-selfhost-desktop/src/platform/environments/environments.platform.ts
+++ b/packages/hoppscotch-selfhost-desktop/src/platform/environments/environments.platform.ts
@@ -96,11 +96,10 @@ async function loadUserEnvironments() {
replaceEnvironments(
formatedEnvironments.map((environment) => {
- const parsedEnv =
- entityReference(Environment).safeParse(environment)
+ const parsedEnv = Environment.safeParse(environment)
- return parsedEnv.success
- ? parsedEnv.data
+ return parsedEnv.type === "ok"
+ ? parsedEnv.value
: {
...environment,
v: EnvironmentSchemaVersion,
@@ -191,12 +190,24 @@ function setupUserEnvironmentUpdatedSubscription() {
)
if ((localIndex || localIndex == 0) && name) {
+ const environment = {
+ id,
+ name,
+ variables: JSON.parse(variables),
+ }
+
+ const parsedEnvResult = Environment.safeParse(environment)
+
+ const parsedEnv: Environment =
+ parsedEnvResult.type === "ok"
+ ? parsedEnvResult.value
+ : {
+ ...environment,
+ v: EnvironmentSchemaVersion,
+ }
+
runDispatchWithOutSyncing(() => {
- updateEnvironment(localIndex, {
- id,
- name,
- variables: JSON.parse(variables),
- })
+ updateEnvironment(localIndex, parsedEnv)
})
}
}
diff --git a/packages/hoppscotch-selfhost-web/src/platform/environments/desktop/index.ts b/packages/hoppscotch-selfhost-web/src/platform/environments/desktop/index.ts
index 02749f79..fd65e24d 100644
--- a/packages/hoppscotch-selfhost-web/src/platform/environments/desktop/index.ts
+++ b/packages/hoppscotch-selfhost-web/src/platform/environments/desktop/index.ts
@@ -97,11 +97,10 @@ async function loadUserEnvironments() {
replaceEnvironments(
formatedEnvironments.map((environment) => {
- const parsedEnv =
- entityReference(Environment).safeParse(environment)
+ const parsedEnv = Environment.safeParse(environment)
- return parsedEnv.success
- ? parsedEnv.data
+ return parsedEnv.type === "ok"
+ ? parsedEnv.value
: {
...environment,
v: EnvironmentSchemaVersion,
diff --git a/packages/hoppscotch-selfhost-web/src/platform/environments/web/index.ts b/packages/hoppscotch-selfhost-web/src/platform/environments/web/index.ts
index 03b0292a..f80136e8 100644
--- a/packages/hoppscotch-selfhost-web/src/platform/environments/web/index.ts
+++ b/packages/hoppscotch-selfhost-web/src/platform/environments/web/index.ts
@@ -97,11 +97,10 @@ async function loadUserEnvironments() {
replaceEnvironments(
formatedEnvironments.map((environment) => {
- const parsedEnv =
- entityReference(Environment).safeParse(environment)
+ const parsedEnv = Environment.safeParse(environment)
- return parsedEnv.success
- ? parsedEnv.data
+ return parsedEnv.type === "ok"
+ ? parsedEnv.value
: {
...environment,
v: EnvironmentSchemaVersion,
@@ -192,13 +191,24 @@ function setupUserEnvironmentUpdatedSubscription() {
)
if ((localIndex || localIndex == 0) && name) {
+ const environment = {
+ id,
+ name,
+ variables: JSON.parse(variables),
+ }
+
+ const parsedEnvResult = Environment.safeParse(environment)
+
+ const parsedEnv: Environment =
+ parsedEnvResult.type === "ok"
+ ? parsedEnvResult.value
+ : {
+ ...environment,
+ v: EnvironmentSchemaVersion,
+ }
+
runDispatchWithOutSyncing(() => {
- updateEnvironment(localIndex, {
- v: 2,
- id,
- name,
- variables: JSON.parse(variables),
- })
+ updateEnvironment(localIndex, parsedEnv)
})
}
}