fix: schema error and test updation flow (#5124)
Co-authored-by: jamesgeorge007 <25279263+jamesgeorge007@users.noreply.github.com>
This commit is contained in:
parent
2a633720a5
commit
2bd3f36bfa
55 changed files with 1013 additions and 918 deletions
|
|
@ -24,9 +24,9 @@ import { HoppRequestDocument } from "~/helpers/rest/document"
|
||||||
import { useResponseBody } from "@composables/lens-actions"
|
import { useResponseBody } from "@composables/lens-actions"
|
||||||
import { getStatusCodeReasonPhrase } from "~/helpers/utils/statusCodes"
|
import { getStatusCodeReasonPhrase } from "~/helpers/utils/statusCodes"
|
||||||
import {
|
import {
|
||||||
HoppRESTResponseOriginalRequest,
|
|
||||||
HoppRESTRequestResponse,
|
HoppRESTRequestResponse,
|
||||||
RESTResOriginalReqSchemaVersion,
|
HoppRESTResponseOriginalRequest,
|
||||||
|
makeHoppRESTResponseOriginalRequest,
|
||||||
} from "@hoppscotch/data"
|
} from "@hoppscotch/data"
|
||||||
import { editRESTRequest } from "~/newstore/collections"
|
import { editRESTRequest } from "~/newstore/collections"
|
||||||
import { useToast } from "@composables/toast"
|
import { useToast } from "@composables/toast"
|
||||||
|
|
@ -94,17 +94,17 @@ const onSaveAsExample = () => {
|
||||||
requestVariables,
|
requestVariables,
|
||||||
} = response.req
|
} = response.req
|
||||||
|
|
||||||
const originalRequest: HoppRESTResponseOriginalRequest = {
|
const originalRequest: HoppRESTResponseOriginalRequest =
|
||||||
v: RESTResOriginalReqSchemaVersion,
|
makeHoppRESTResponseOriginalRequest({
|
||||||
method,
|
method,
|
||||||
endpoint,
|
endpoint,
|
||||||
headers,
|
headers,
|
||||||
body,
|
body,
|
||||||
auth,
|
auth,
|
||||||
params,
|
params,
|
||||||
name,
|
name,
|
||||||
requestVariables,
|
requestVariables,
|
||||||
}
|
})
|
||||||
|
|
||||||
const resName = responseName.value.trim()
|
const resName = responseName.value.trim()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
</span>
|
</span>
|
||||||
<span class="inline-flex text-secondaryDark">
|
<span class="inline-flex text-secondaryDark">
|
||||||
<icon-lucide-minus class="svg-icons mr-2" />
|
<icon-lucide-minus class="svg-icons mr-2" />
|
||||||
{{ env.value }}
|
{{ env.currentValue }}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
v-if="status === 'updations'"
|
v-if="status === 'updations'"
|
||||||
|
|
@ -45,7 +45,7 @@ type Status = "updations" | "additions" | "deletions"
|
||||||
type Props = {
|
type Props = {
|
||||||
env: {
|
env: {
|
||||||
key: string
|
key: string
|
||||||
value: string
|
currentValue: string
|
||||||
previousValue?: string
|
previousValue?: string
|
||||||
}
|
}
|
||||||
status: Status
|
status: Status
|
||||||
|
|
|
||||||
|
|
@ -455,10 +455,10 @@ export function runRESTRequest$(
|
||||||
}))
|
}))
|
||||||
) as E.Right<SandboxTestResult>
|
) as E.Right<SandboxTestResult>
|
||||||
|
|
||||||
const updatedRunResult = updateEnvsAfterTestScript(combinedResult)
|
tab.value.document.testResults = translateToSandboxTestResults(
|
||||||
|
combinedResult.right
|
||||||
tab.value.document.testResults =
|
)
|
||||||
translateToSandboxTestResults(updatedRunResult)
|
updateEnvsAfterTestScript(combinedResult)
|
||||||
} else {
|
} else {
|
||||||
tab.value.document.testResults = {
|
tab.value.document.testResults = {
|
||||||
description: "",
|
description: "",
|
||||||
|
|
@ -492,26 +492,6 @@ export function runRESTRequest$(
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateEnvsAfterTestScript(runResult: E.Right<SandboxTestResult>) {
|
function updateEnvsAfterTestScript(runResult: E.Right<SandboxTestResult>) {
|
||||||
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(
|
const globalEnvVariables = updateEnvironments(
|
||||||
// @ts-expect-error Typescript can't figure out this inference for some reason
|
// @ts-expect-error Typescript can't figure out this inference for some reason
|
||||||
runResult.right.envs.global,
|
runResult.right.envs.global,
|
||||||
|
|
@ -522,6 +502,11 @@ function updateEnvsAfterTestScript(runResult: E.Right<SandboxTestResult>) {
|
||||||
v: 2,
|
v: 2,
|
||||||
variables: globalEnvVariables,
|
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") {
|
if (environmentsStore.value.selectedEnvironmentIndex.type === "MY_ENV") {
|
||||||
const env = getEnvironment({
|
const env = getEnvironment({
|
||||||
type: "MY_ENV",
|
type: "MY_ENV",
|
||||||
|
|
@ -531,7 +516,7 @@ function updateEnvsAfterTestScript(runResult: E.Right<SandboxTestResult>) {
|
||||||
name: env.name,
|
name: env.name,
|
||||||
v: 2,
|
v: 2,
|
||||||
id: "id" in env ? env.id : "",
|
id: "id" in env ? env.id : "",
|
||||||
variables: updatedRunResult.envs.selected,
|
variables: runResult.right.envs.selected,
|
||||||
})
|
})
|
||||||
} else if (
|
} else if (
|
||||||
environmentsStore.value.selectedEnvironmentIndex.type === "TEAM_ENV"
|
environmentsStore.value.selectedEnvironmentIndex.type === "TEAM_ENV"
|
||||||
|
|
@ -541,14 +526,12 @@ function updateEnvsAfterTestScript(runResult: E.Right<SandboxTestResult>) {
|
||||||
})
|
})
|
||||||
pipe(
|
pipe(
|
||||||
updateTeamEnvironment(
|
updateTeamEnvironment(
|
||||||
JSON.stringify(updatedRunResult.envs.selected),
|
JSON.stringify(runResult.right.envs.selected),
|
||||||
environmentsStore.value.selectedEnvironmentIndex.teamEnvID,
|
environmentsStore.value.selectedEnvironmentIndex.teamEnvID,
|
||||||
env.name
|
env.name
|
||||||
)
|
)
|
||||||
)()
|
)()
|
||||||
}
|
}
|
||||||
|
|
||||||
return updatedRunResult
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
@ -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<typeof REST_TAB_STATE_SCHEMA>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -20,7 +20,7 @@ import {
|
||||||
HoppRESTRequest,
|
HoppRESTRequest,
|
||||||
HoppRESTRequestResponses,
|
HoppRESTRequestResponses,
|
||||||
HoppRESTResponseOriginalRequest,
|
HoppRESTResponseOriginalRequest,
|
||||||
RESTResOriginalReqSchemaVersion,
|
makeHoppRESTResponseOriginalRequest,
|
||||||
} from "@hoppscotch/data"
|
} from "@hoppscotch/data"
|
||||||
import { pipe, flow } from "fp-ts/function"
|
import { pipe, flow } from "fp-ts/function"
|
||||||
import * as A from "fp-ts/Array"
|
import * as A from "fp-ts/Array"
|
||||||
|
|
@ -828,24 +828,27 @@ const convertPathToHoppReqs = (
|
||||||
(info.parameters as OpenAPIParamsType[] | undefined) ?? []
|
(info.parameters as OpenAPIParamsType[] | undefined) ?? []
|
||||||
),
|
),
|
||||||
|
|
||||||
responses: parseOpenAPIResponses(doc, info, {
|
responses: parseOpenAPIResponses(
|
||||||
name: info.operationId ?? info.summary ?? "Untitled Request",
|
doc,
|
||||||
auth: parseOpenAPIAuth(doc, info),
|
info,
|
||||||
body: parseOpenAPIBody(doc, info),
|
makeHoppRESTResponseOriginalRequest({
|
||||||
endpoint,
|
name: info.operationId ?? info.summary ?? "Untitled Request",
|
||||||
// We don't need to worry about reference types as the Dereferencing pass should remove them
|
auth: parseOpenAPIAuth(doc, info),
|
||||||
params: parseOpenAPIParams(
|
body: parseOpenAPIBody(doc, info),
|
||||||
(info.parameters as OpenAPIParamsType[] | undefined) ?? []
|
endpoint,
|
||||||
),
|
// We don't need to worry about reference types as the Dereferencing pass should remove them
|
||||||
headers: parseOpenAPIHeaders(
|
params: parseOpenAPIParams(
|
||||||
(info.parameters as OpenAPIParamsType[] | undefined) ?? []
|
(info.parameters as OpenAPIParamsType[] | undefined) ?? []
|
||||||
),
|
),
|
||||||
method: method.toUpperCase(),
|
headers: parseOpenAPIHeaders(
|
||||||
requestVariables: parseOpenAPIVariables(
|
(info.parameters as OpenAPIParamsType[] | undefined) ?? []
|
||||||
(info.parameters as OpenAPIParamsType[] | undefined) ?? []
|
),
|
||||||
),
|
method: method.toUpperCase(),
|
||||||
v: RESTResOriginalReqSchemaVersion,
|
requestVariables: parseOpenAPIVariables(
|
||||||
}),
|
(info.parameters as OpenAPIParamsType[] | undefined) ?? []
|
||||||
|
),
|
||||||
|
})
|
||||||
|
),
|
||||||
}),
|
}),
|
||||||
metadata: {
|
metadata: {
|
||||||
tags: info.tags ?? [],
|
tags: info.tags ?? [],
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,9 @@ import {
|
||||||
knownContentTypes,
|
knownContentTypes,
|
||||||
makeCollection,
|
makeCollection,
|
||||||
makeRESTRequest,
|
makeRESTRequest,
|
||||||
RESTResOriginalReqSchemaVersion,
|
|
||||||
ValidContentTypes,
|
ValidContentTypes,
|
||||||
|
HoppRESTRequestResponses,
|
||||||
|
makeHoppRESTResponseOriginalRequest,
|
||||||
} from "@hoppscotch/data"
|
} from "@hoppscotch/data"
|
||||||
import * as A from "fp-ts/Array"
|
import * as A from "fp-ts/Array"
|
||||||
import { flow, pipe } from "fp-ts/function"
|
import { flow, pipe } from "fp-ts/function"
|
||||||
|
|
@ -31,7 +32,6 @@ import {
|
||||||
import { stringArrayJoin } from "~/helpers/functional/array"
|
import { stringArrayJoin } from "~/helpers/functional/array"
|
||||||
import { PMRawLanguage } from "~/types/pm-coll-exts"
|
import { PMRawLanguage } from "~/types/pm-coll-exts"
|
||||||
import { IMPORTER_INVALID_FILE_FORMAT } from "."
|
import { IMPORTER_INVALID_FILE_FORMAT } from "."
|
||||||
import { HoppRESTRequestResponses } from "@hoppscotch/data"
|
|
||||||
|
|
||||||
const safeParseJSON = (jsonStr: string) => O.tryCatch(() => JSON.parse(jsonStr))
|
const safeParseJSON = (jsonStr: string) => O.tryCatch(() => JSON.parse(jsonStr))
|
||||||
|
|
||||||
|
|
@ -160,7 +160,7 @@ const getHoppResponses = (
|
||||||
body: response.body ?? "",
|
body: response.body ?? "",
|
||||||
headers: getHoppReqHeaders(response.headers),
|
headers: getHoppReqHeaders(response.headers),
|
||||||
code: response.code,
|
code: response.code,
|
||||||
originalRequest: {
|
originalRequest: makeHoppRESTResponseOriginalRequest({
|
||||||
auth: getHoppReqAuth(response.originalRequest?.auth),
|
auth: getHoppReqAuth(response.originalRequest?.auth),
|
||||||
body: getHoppReqBody({
|
body: getHoppReqBody({
|
||||||
body: response.originalRequest?.body,
|
body: response.originalRequest?.body,
|
||||||
|
|
@ -178,8 +178,7 @@ const getHoppResponses = (
|
||||||
requestVariables: getHoppReqVariables(
|
requestVariables: getHoppReqVariables(
|
||||||
response.originalRequest?.url.variables ?? null
|
response.originalRequest?.url.variables ?? null
|
||||||
),
|
),
|
||||||
v: RESTResOriginalReqSchemaVersion,
|
}),
|
||||||
},
|
|
||||||
}
|
}
|
||||||
return [response.name, res]
|
return [response.name, res]
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ import {
|
||||||
} from "../backend/graphql"
|
} from "../backend/graphql"
|
||||||
import { TeamEnvironment } from "./TeamEnvironment"
|
import { TeamEnvironment } from "./TeamEnvironment"
|
||||||
import { Environment, EnvironmentSchemaVersion } from "@hoppscotch/data"
|
import { Environment, EnvironmentSchemaVersion } from "@hoppscotch/data"
|
||||||
import { entityReference } from "verzod"
|
|
||||||
|
|
||||||
type EntityType = "environment"
|
type EntityType = "environment"
|
||||||
type EntityID = `${EntityType}-${string}`
|
type EntityID = `${EntityType}-${string}`
|
||||||
|
|
@ -121,18 +120,18 @@ export default class TeamEnvironmentAdapter {
|
||||||
variables: JSON.parse(x.variables),
|
variables: JSON.parse(x.variables),
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsedEnvironment =
|
const parsedEnvironment = Environment.safeParse(environment)
|
||||||
entityReference(Environment).safeParse(environment)
|
|
||||||
|
|
||||||
return <TeamEnvironment>{
|
return <TeamEnvironment>{
|
||||||
id: x.id,
|
id: x.id,
|
||||||
teamID: x.teamID,
|
teamID: x.teamID,
|
||||||
environment: parsedEnvironment.success
|
environment:
|
||||||
? parsedEnvironment.data
|
parsedEnvironment.type === "ok"
|
||||||
: {
|
? parsedEnvironment.value
|
||||||
...environment,
|
: {
|
||||||
v: EnvironmentSchemaVersion,
|
...environment,
|
||||||
},
|
v: EnvironmentSchemaVersion,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ export const getFullStatusCodePhrase = () => {
|
||||||
// return all status codes and their phrases
|
// return all status codes and their phrases
|
||||||
// like code • phrase
|
// like code • phrase
|
||||||
export const getStatusCodePhrase = (
|
export const getStatusCodePhrase = (
|
||||||
code: number | undefined,
|
code: number | undefined | null,
|
||||||
statusText: string
|
statusText: string
|
||||||
) => {
|
) => {
|
||||||
if (!code) return statusText
|
if (!code) return statusText
|
||||||
|
|
|
||||||
|
|
@ -57,11 +57,16 @@ export const Store = (() => {
|
||||||
return module().listNamespaces(STORE_PATH)
|
return module().listNamespaces(STORE_PATH)
|
||||||
},
|
},
|
||||||
|
|
||||||
listKeys: async (namespace: string): Promise<E.Either<StoreError, string[]>> => {
|
listKeys: async (
|
||||||
|
namespace: string
|
||||||
|
): Promise<E.Either<StoreError, string[]>> => {
|
||||||
return module().listKeys(STORE_PATH, namespace)
|
return module().listKeys(STORE_PATH, namespace)
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: async (namespace: string, key: string): Promise<StoreEventEmitter<StoreEvents>> => {
|
watch: async (
|
||||||
|
namespace: string,
|
||||||
|
key: string
|
||||||
|
): Promise<StoreEventEmitter<StoreEvents>> => {
|
||||||
return module().watch(STORE_PATH, namespace, key)
|
return module().watch(STORE_PATH, namespace, key)
|
||||||
},
|
},
|
||||||
} as const
|
} as const
|
||||||
|
|
|
||||||
|
|
@ -92,17 +92,14 @@ export class KernelInterceptorAgentStore extends Service {
|
||||||
|
|
||||||
private async setupWatchers() {
|
private async setupWatchers() {
|
||||||
const watcher = await Store.watch(STORE_NAMESPACE, STORE_KEYS.SETTINGS)
|
const watcher = await Store.watch(STORE_NAMESPACE, STORE_KEYS.SETTINGS)
|
||||||
watcher.on(
|
watcher.on("change", async ({ value }) => {
|
||||||
"change",
|
if (value) {
|
||||||
async ({ value }) => {
|
const store = value as StoredData
|
||||||
if (value) {
|
this.domainSettings = new Map(Object.entries(store.domains))
|
||||||
const store = value as StoredData
|
this.authKey.value = store.auth.key
|
||||||
this.domainSettings = new Map(Object.entries(store.domains))
|
this.sharedSecretB16.value = store.auth.sharedSecret
|
||||||
this.authKey.value = store.auth.key
|
|
||||||
this.sharedSecretB16.value = store.auth.sharedSecret
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private async persistStore(): Promise<void> {
|
private async persistStore(): Promise<void> {
|
||||||
|
|
|
||||||
|
|
@ -89,15 +89,12 @@ export class KernelInterceptorExtensionStore extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
const watcher = await Store.watch(STORE_NAMESPACE, SETTINGS_KEY)
|
const watcher = await Store.watch(STORE_NAMESPACE, SETTINGS_KEY)
|
||||||
watcher.on(
|
watcher.on("change", async ({ value }) => {
|
||||||
"change",
|
if (value) {
|
||||||
async ({ value }) => {
|
const storedData = value as StoredData
|
||||||
if (value) {
|
this.settings = storedData.settings
|
||||||
const storedData = value as StoredData
|
|
||||||
this.settings = storedData.settings
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public getExtensionVersion(): O.Option<ExtensionVersion> {
|
public getExtensionVersion(): O.Option<ExtensionVersion> {
|
||||||
|
|
|
||||||
|
|
@ -74,15 +74,12 @@ export class KernelInterceptorNativeStore extends Service {
|
||||||
|
|
||||||
private async setupWatchers() {
|
private async setupWatchers() {
|
||||||
const watcher = await Store.watch(STORE_NAMESPACE, STORE_KEYS.SETTINGS)
|
const watcher = await Store.watch(STORE_NAMESPACE, STORE_KEYS.SETTINGS)
|
||||||
watcher.on(
|
watcher.on("change", async ({ value }) => {
|
||||||
"change",
|
if (value) {
|
||||||
async ({ value }) => {
|
const store = value as StoredData
|
||||||
if (value) {
|
this.domainSettings = new Map(Object.entries(store.domains))
|
||||||
const store = value as StoredData
|
|
||||||
this.domainSettings = new Map(Object.entries(store.domains))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private async persistStore(): Promise<void> {
|
private async persistStore(): Promise<void> {
|
||||||
|
|
|
||||||
|
|
@ -39,15 +39,12 @@ export class KernelInterceptorProxyStore extends Service {
|
||||||
await this.loadSettings()
|
await this.loadSettings()
|
||||||
|
|
||||||
const watcher = await Store.watch(STORE_NAMESPACE, SETTINGS_KEY)
|
const watcher = await Store.watch(STORE_NAMESPACE, SETTINGS_KEY)
|
||||||
watcher.on(
|
watcher.on("change", async ({ value }) => {
|
||||||
"change",
|
if (value) {
|
||||||
async ({ value }) => {
|
const storedData = value as StoredData
|
||||||
if (value) {
|
this.settings = storedData.settings
|
||||||
const storedData = value as StoredData
|
|
||||||
this.settings = storedData.settings
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private async loadSettings(): Promise<void> {
|
private async loadSettings(): Promise<void> {
|
||||||
|
|
|
||||||
|
|
@ -954,10 +954,10 @@ describe("PersistenceService", () => {
|
||||||
// Invalid shape for `environments`
|
// Invalid shape for `environments`
|
||||||
const environments = [
|
const environments = [
|
||||||
// `entries` -> `variables`
|
// `entries` -> `variables`
|
||||||
|
// no name for the environment
|
||||||
{
|
{
|
||||||
v: 1,
|
v: 1,
|
||||||
id: "ENV_1",
|
id: "ENV_1",
|
||||||
name: "Test",
|
|
||||||
entries: [{ key: "test-key", value: "test-value", secret: false }],
|
entries: [{ key: "test-key", value: "test-value", secret: false }],
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,9 @@ import {
|
||||||
CurrentValueService,
|
CurrentValueService,
|
||||||
Variable,
|
Variable,
|
||||||
} from "../current-environment-value.service"
|
} 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"
|
export const STORE_NAMESPACE = "persistence.v1"
|
||||||
|
|
||||||
|
|
@ -528,7 +531,9 @@ export class PersistenceService extends Service {
|
||||||
try {
|
try {
|
||||||
if (E.isRight(loadResult)) {
|
if (E.isRight(loadResult)) {
|
||||||
const data = loadResult.right ?? []
|
const data = loadResult.right ?? []
|
||||||
const result = ENVIRONMENTS_SCHEMA.safeParse(data)
|
const environments = fixBrokenEnvironmentVersion(data)
|
||||||
|
|
||||||
|
const result = ENVIRONMENTS_SCHEMA.safeParse(environments)
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
// Check for and handle globals
|
// Check for and handle globals
|
||||||
|
|
@ -866,8 +871,16 @@ export class PersistenceService extends Service {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (E.isRight(loadResult) && loadResult.right) {
|
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) {
|
if (result.success) {
|
||||||
// SAFETY: We know the schema matches
|
// SAFETY: We know the schema matches
|
||||||
this.restTabService.loadTabsFromPersistedState(
|
this.restTabService.loadTabsFromPersistedState(
|
||||||
|
|
|
||||||
|
|
@ -405,12 +405,9 @@ const HoppTestResultSchema = z
|
||||||
.object({
|
.object({
|
||||||
additions: z.array(EnvironmentVariablesSchema),
|
additions: z.array(EnvironmentVariablesSchema),
|
||||||
updations: z.array(
|
updations: z.array(
|
||||||
EnvironmentVariablesSchema.refine(
|
z.intersection(
|
||||||
(x) => "secret" in x && !x.secret
|
EnvironmentVariablesSchema,
|
||||||
).and(
|
z.object({ previousValue: z.optional(z.string()) })
|
||||||
z.object({
|
|
||||||
previousValue: z.optional(z.string()),
|
|
||||||
})
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
deletions: z.array(EnvironmentVariablesSchema),
|
deletions: z.array(EnvironmentVariablesSchema),
|
||||||
|
|
@ -420,12 +417,9 @@ const HoppTestResultSchema = z
|
||||||
.object({
|
.object({
|
||||||
additions: z.array(EnvironmentVariablesSchema),
|
additions: z.array(EnvironmentVariablesSchema),
|
||||||
updations: z.array(
|
updations: z.array(
|
||||||
EnvironmentVariablesSchema.refine(
|
z.intersection(
|
||||||
(x) => "secret" in x && !x.secret
|
EnvironmentVariablesSchema,
|
||||||
).and(
|
z.object({ previousValue: z.optional(z.string()) })
|
||||||
z.object({
|
|
||||||
previousValue: z.optional(z.string()),
|
|
||||||
})
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
deletions: z.array(EnvironmentVariablesSchema),
|
deletions: z.array(EnvironmentVariablesSchema),
|
||||||
|
|
@ -582,7 +576,7 @@ export const REST_TAB_STATE_SCHEMA = z
|
||||||
}),
|
}),
|
||||||
z.object({
|
z.object({
|
||||||
type: z.literal("example-response").catch("example-response"),
|
type: z.literal("example-response").catch("example-response"),
|
||||||
response: HoppRESTRequestResponse,
|
response: entityReference(HoppRESTRequestResponse),
|
||||||
saveContext: z.optional(HoppRESTSaveContextSchema),
|
saveContext: z.optional(HoppRESTSaveContextSchema),
|
||||||
isDirty: z.boolean(),
|
isDirty: z.boolean(),
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { defineVersion, entityRefUptoVersion } from "verzod"
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
import { HoppGQLAuth } from "../../graphql/v/7"
|
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 { V3_SCHEMA, v3_baseCollectionSchema } from "./3"
|
||||||
import { HoppCollection } from ".."
|
import { HoppCollection } from ".."
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { defineVersion, entityRefUptoVersion } from "verzod"
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
import { HoppGQLAuth } from "../../graphql/v/8"
|
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 { V5_SCHEMA, v5_baseCollectionSchema } from "./5"
|
||||||
import { HoppCollection } from ".."
|
import { HoppCollection } from ".."
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { defineVersion, entityRefUptoVersion } from "verzod"
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
import { HoppGQLAuth } from "../../graphql/v/8"
|
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 { V6_SCHEMA, v6_baseCollectionSchema } from "./6"
|
||||||
import { HoppCollection } from ".."
|
import { HoppCollection } from ".."
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { defineVersion, entityRefUptoVersion } from "verzod"
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
import { HoppGQLAuth } from "../../graphql/v/8"
|
import { HoppGQLAuth } from "../../graphql/v/8"
|
||||||
import { HoppRESTAuth } from "../../rest/v/13"
|
import { HoppRESTAuth } from "../../rest/v/13/auth"
|
||||||
|
|
||||||
import { HoppCollection } from ".."
|
import { HoppCollection } from ".."
|
||||||
import { v7_baseCollectionSchema, V7_SCHEMA } from "./7"
|
import { v7_baseCollectionSchema, V7_SCHEMA } from "./7"
|
||||||
|
|
|
||||||
|
|
@ -205,7 +205,7 @@ export const translateToNewEnvironmentVariables = (
|
||||||
key: x.key,
|
key: x.key,
|
||||||
initialValue: x.initialValue ?? x.value ?? "",
|
initialValue: x.initialValue ?? x.value ?? "",
|
||||||
currentValue: x.currentValue ?? x.value ?? "",
|
currentValue: x.currentValue ?? x.value ?? "",
|
||||||
secret: false,
|
secret: x.secret ?? false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,15 @@ export default defineVersion({
|
||||||
...old,
|
...old,
|
||||||
v: 2,
|
v: 2,
|
||||||
variables: old.variables.map((variable) => {
|
variables: old.variables.map((variable) => {
|
||||||
|
const { key, secret } = variable
|
||||||
// if the variable is secret, set initialValue and currentValue to empty string
|
// if the variable is secret, set initialValue and currentValue to empty string
|
||||||
// else set initialValue and currentValue to value
|
// else set initialValue and currentValue to value
|
||||||
// and delete value
|
// and delete value
|
||||||
return {
|
return {
|
||||||
...variable,
|
key,
|
||||||
|
secret: secret ?? false,
|
||||||
initialValue: variable.secret ? "" : variable.value,
|
initialValue: variable.secret ? "" : variable.value,
|
||||||
currentValue: variable.secret ? "" : variable.value,
|
currentValue: variable.secret ? "" : variable.value,
|
||||||
value: undefined,
|
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,10 @@ import {
|
||||||
} from "./2"
|
} from "./2"
|
||||||
import { HoppGQLAuthAPIKey } from "./4"
|
import { HoppGQLAuthAPIKey } from "./4"
|
||||||
import { HoppGQLAuthAWSSignature } from "./6"
|
import { HoppGQLAuthAWSSignature } from "./6"
|
||||||
import { HoppRESTAuthOAuth2 } from "./../../rest/v/11"
|
import { HoppRESTAuthOAuth2 } from "../../rest/v/11/auth"
|
||||||
import { V7_SCHEMA } from "./7"
|
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
|
export const HoppGQLAuth = z
|
||||||
.discriminatedUnion("authType", [
|
.discriminatedUnion("authType", [
|
||||||
|
|
|
||||||
|
|
@ -9,3 +9,4 @@ export * from "./utils/collection"
|
||||||
export * from "./utils/hawk"
|
export * from "./utils/hawk"
|
||||||
export * from "./utils/akamai-eg"
|
export * from "./utils/akamai-eg"
|
||||||
export * from "./utils/jwt"
|
export * from "./utils/jwt"
|
||||||
|
export * from "./rest-request-response"
|
||||||
|
|
|
||||||
50
packages/hoppscotch-data/src/rest-request-response/index.ts
Normal file
50
packages/hoppscotch-data/src/rest-request-response/index.ts
Normal file
|
|
@ -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<typeof HoppRESTRequestResponses>
|
||||||
|
|
||||||
|
export function makeHoppRESTResponseOriginalRequest(
|
||||||
|
x: Omit<HoppRESTResponseOriginalRequest, "v">
|
||||||
|
): HoppRESTResponseOriginalRequest {
|
||||||
|
return {
|
||||||
|
v: HoppRESTResOriginalReqSchemaVersion,
|
||||||
|
...x,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
>
|
||||||
|
|
@ -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,
|
||||||
|
})
|
||||||
|
|
@ -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<typeof V1_SCHEMA>) {
|
||||||
|
return {
|
||||||
|
...old,
|
||||||
|
v: "2" as const,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
@ -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<typeof V2_SCHEMA>) {
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
@ -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<typeof V3_SCHEMA>) {
|
||||||
|
return {
|
||||||
|
...old,
|
||||||
|
v: "4" as const,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
@ -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<typeof V4_SCHEMA>) {
|
||||||
|
return {
|
||||||
|
...old,
|
||||||
|
v: "5" as const,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
35
packages/hoppscotch-data/src/rest-request-response/v/0.ts
Normal file
35
packages/hoppscotch-data/src/rest-request-response/v/0.ts
Normal file
|
|
@ -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<number>,
|
||||||
|
z.ZodLiteral<number>,
|
||||||
|
...z.ZodLiteral<number>[]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
export const HoppRESTResponseHeaders = z.array(
|
||||||
|
z.object({
|
||||||
|
key: z.string(),
|
||||||
|
value: z.string(),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
export type HoppRESTResponseHeader = z.infer<typeof HoppRESTResponseHeaders>
|
||||||
|
|
||||||
|
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,
|
||||||
|
})
|
||||||
|
|
@ -16,10 +16,14 @@ import V6_VERSION from "./v/6"
|
||||||
import V7_VERSION, { HoppRESTHeaders, HoppRESTParams } from "./v/7"
|
import V7_VERSION, { HoppRESTHeaders, HoppRESTParams } from "./v/7"
|
||||||
import V8_VERSION from "./v/8"
|
import V8_VERSION from "./v/8"
|
||||||
import V9_VERSION from "./v/9"
|
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 V11_VERSION from "./v/11"
|
||||||
import V12_VERSION from "./v/12"
|
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"
|
export * from "./content-types"
|
||||||
|
|
||||||
|
|
@ -44,23 +48,25 @@ export {
|
||||||
HoppRESTParams,
|
HoppRESTParams,
|
||||||
} from "./v/7"
|
} from "./v/7"
|
||||||
|
|
||||||
export { HoppRESTAuthDigest, PasswordGrantTypeParams } from "./v/8"
|
export { HoppRESTAuthDigest, PasswordGrantTypeParams } from "./v/8/auth"
|
||||||
|
|
||||||
export { FormDataKeyValue } from "./v/9"
|
export { FormDataKeyValue } from "./v/9/body"
|
||||||
|
|
||||||
export { HoppRESTAuthOAuth2, ClientCredentialsGrantTypeParams } from "./v/11"
|
export {
|
||||||
|
HoppRESTAuthOAuth2,
|
||||||
export { HoppRESTReqBody } from "./v/10"
|
ClientCredentialsGrantTypeParams,
|
||||||
|
} from "./v/11/auth"
|
||||||
export { HoppRESTAuthHAWK, HoppRESTAuthAkamaiEdgeGrid } from "./v/12"
|
|
||||||
|
export { HoppRESTReqBody } from "./v/10/body"
|
||||||
|
|
||||||
|
export { HoppRESTAuthHAWK, HoppRESTAuthAkamaiEdgeGrid } from "./v/12/auth"
|
||||||
|
|
||||||
|
export { HoppRESTAuth, HoppRESTAuthJWT } from "./v/13/auth"
|
||||||
|
|
||||||
export {
|
export {
|
||||||
HoppRESTAuth,
|
|
||||||
HoppRESTAuthJWT,
|
|
||||||
HoppRESTRequestResponses,
|
|
||||||
HoppRESTResponseOriginalRequest,
|
|
||||||
HoppRESTRequestResponse,
|
HoppRESTRequestResponse,
|
||||||
} from "./v/13"
|
HoppRESTRequestResponses,
|
||||||
|
} from "../rest-request-response"
|
||||||
|
|
||||||
const versionedObject = z.object({
|
const versionedObject = z.object({
|
||||||
// v is a stringified number
|
// v is a stringified number
|
||||||
|
|
@ -68,7 +74,7 @@ const versionedObject = z.object({
|
||||||
})
|
})
|
||||||
|
|
||||||
export const HoppRESTRequest = createVersionedEntity({
|
export const HoppRESTRequest = createVersionedEntity({
|
||||||
latestVersion: 13,
|
latestVersion: 14,
|
||||||
versionMap: {
|
versionMap: {
|
||||||
0: V0_VERSION,
|
0: V0_VERSION,
|
||||||
1: V1_VERSION,
|
1: V1_VERSION,
|
||||||
|
|
@ -84,6 +90,7 @@ export const HoppRESTRequest = createVersionedEntity({
|
||||||
11: V11_VERSION,
|
11: V11_VERSION,
|
||||||
12: V12_VERSION,
|
12: V12_VERSION,
|
||||||
13: V13_VERSION,
|
13: V13_VERSION,
|
||||||
|
14: V14_VERSION,
|
||||||
},
|
},
|
||||||
getVersion(data) {
|
getVersion(data) {
|
||||||
// For V1 onwards we have the v string storing the number
|
// For V1 onwards we have the v string storing the number
|
||||||
|
|
@ -126,8 +133,7 @@ const HoppRESTRequestEq = Eq.struct<HoppRESTRequest>({
|
||||||
responses: lodashIsEqualEq,
|
responses: lodashIsEqualEq,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const RESTReqSchemaVersion = "13"
|
export const RESTReqSchemaVersion = "14"
|
||||||
export const RESTResOriginalReqSchemaVersion = "5" as const
|
|
||||||
|
|
||||||
export type HoppRESTParam = HoppRESTRequest["params"][number]
|
export type HoppRESTParam = HoppRESTRequest["params"][number]
|
||||||
export type HoppRESTHeader = HoppRESTRequest["headers"][number]
|
export type HoppRESTHeader = HoppRESTRequest["headers"][number]
|
||||||
|
|
@ -210,7 +216,6 @@ export function safelyExtractRESTRequest(
|
||||||
|
|
||||||
if ("responses" in x) {
|
if ("responses" in x) {
|
||||||
const result = HoppRESTRequestResponses.safeParse(x.responses)
|
const result = HoppRESTRequestResponses.safeParse(x.responses)
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
req.responses = result.data
|
req.responses = result.data
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
import { FormDataKeyValue, V9_SCHEMA } from "./9"
|
import { FormDataKeyValue } from "../9/body"
|
||||||
import { defineVersion } from "verzod"
|
|
||||||
|
|
||||||
export const HoppRESTReqBody = z.union([
|
export const HoppRESTReqBody = z.union([
|
||||||
z.object({
|
z.object({
|
||||||
|
|
@ -39,19 +38,3 @@ export const HoppRESTReqBody = z.union([
|
||||||
])
|
])
|
||||||
|
|
||||||
export type HoppRESTReqBody = z.infer<typeof HoppRESTReqBody>
|
export type HoppRESTReqBody = z.infer<typeof HoppRESTReqBody>
|
||||||
|
|
||||||
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<typeof V9_SCHEMA>) {
|
|
||||||
return {
|
|
||||||
...old,
|
|
||||||
v: "10" as const,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
20
packages/hoppscotch-data/src/rest/v/10/index.ts
Normal file
20
packages/hoppscotch-data/src/rest/v/10/index.ts
Normal file
|
|
@ -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<typeof V9_SCHEMA>) {
|
||||||
|
return {
|
||||||
|
...old,
|
||||||
|
v: "10" as const,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
@ -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<typeof HoppRESTAuthOAuth2>
|
|
||||||
|
|
||||||
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<typeof HoppRESTAuth>
|
|
||||||
|
|
||||||
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<typeof HoppRESTRequestResponse>
|
|
||||||
|
|
||||||
export const HoppRESTRequestResponses = z.record(
|
|
||||||
z.string(),
|
|
||||||
HoppRESTRequestResponse
|
|
||||||
)
|
|
||||||
|
|
||||||
export type HoppRESTRequestResponses = z.infer<typeof HoppRESTRequestResponses>
|
|
||||||
|
|
||||||
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<typeof V10_SCHEMA>) {
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
52
packages/hoppscotch-data/src/rest/v/11/auth.ts
Normal file
52
packages/hoppscotch-data/src/rest/v/11/auth.ts
Normal file
|
|
@ -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<typeof HoppRESTAuthOAuth2>
|
||||||
|
|
||||||
|
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<typeof HoppRESTAuth>
|
||||||
37
packages/hoppscotch-data/src/rest/v/11/index.ts
Normal file
37
packages/hoppscotch-data/src/rest/v/11/index.ts
Normal file
|
|
@ -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<typeof V10_SCHEMA>) {
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
@ -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<typeof HoppRESTAuthHAWK>
|
|
||||||
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<typeof HoppRESTAuth>
|
|
||||||
|
|
||||||
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<typeof HoppRESTRequestResponse>
|
|
||||||
|
|
||||||
export const HoppRESTRequestResponses = z.record(
|
|
||||||
z.string(),
|
|
||||||
HoppRESTRequestResponse
|
|
||||||
)
|
|
||||||
|
|
||||||
export type HoppRESTRequestResponses = z.infer<typeof HoppRESTRequestResponses>
|
|
||||||
|
|
||||||
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<typeof V11_SCHEMA>) {
|
|
||||||
// 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,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
67
packages/hoppscotch-data/src/rest/v/12/auth.ts
Normal file
67
packages/hoppscotch-data/src/rest/v/12/auth.ts
Normal file
|
|
@ -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<typeof HoppRESTAuthHAWK>
|
||||||
|
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<typeof HoppRESTAuth>
|
||||||
21
packages/hoppscotch-data/src/rest/v/12/index.ts
Normal file
21
packages/hoppscotch-data/src/rest/v/12/index.ts
Normal file
|
|
@ -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<typeof V11_SCHEMA>) {
|
||||||
|
return {
|
||||||
|
...old,
|
||||||
|
v: "12" as const,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
@ -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<typeof HoppRESTAuthJWT>
|
|
||||||
|
|
||||||
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<typeof HoppRESTAuth>
|
|
||||||
|
|
||||||
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<typeof HoppRESTRequestResponse>
|
|
||||||
|
|
||||||
export const HoppRESTRequestResponses = z.record(
|
|
||||||
z.string(),
|
|
||||||
HoppRESTRequestResponse
|
|
||||||
)
|
|
||||||
|
|
||||||
export type HoppRESTRequestResponses = z.infer<typeof HoppRESTRequestResponses>
|
|
||||||
|
|
||||||
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<typeof V12_SCHEMA>) {
|
|
||||||
// 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,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
64
packages/hoppscotch-data/src/rest/v/13/auth.ts
Normal file
64
packages/hoppscotch-data/src/rest/v/13/auth.ts
Normal file
|
|
@ -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<typeof HoppRESTAuthJWT>
|
||||||
|
|
||||||
|
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<typeof HoppRESTAuth>
|
||||||
22
packages/hoppscotch-data/src/rest/v/13/index.ts
Normal file
22
packages/hoppscotch-data/src/rest/v/13/index.ts
Normal file
|
|
@ -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<typeof V12_SCHEMA>) {
|
||||||
|
return {
|
||||||
|
...old,
|
||||||
|
v: "13" as const,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
19
packages/hoppscotch-data/src/rest/v/14.ts
Normal file
19
packages/hoppscotch-data/src/rest/v/14.ts
Normal file
|
|
@ -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<typeof V13_SCHEMA>) {
|
||||||
|
return {
|
||||||
|
...old,
|
||||||
|
v: "14" as const,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
@ -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<typeof HoppRESTAuthOAuth2>
|
|
||||||
|
|
||||||
// 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<typeof HoppRESTAuthDigest>
|
|
||||||
|
|
||||||
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<typeof HoppRESTAuth>
|
|
||||||
|
|
||||||
export const ValidCodes = z.union(
|
|
||||||
Object.keys(StatusCodes).map((code) => z.literal(parseInt(code))) as [
|
|
||||||
z.ZodLiteral<number>,
|
|
||||||
z.ZodLiteral<number>,
|
|
||||||
...z.ZodLiteral<number>[]
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
export const HoppRESTResponseHeaders = z.array(
|
|
||||||
z.object({
|
|
||||||
key: z.string(),
|
|
||||||
value: z.string(),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
export type HoppRESTResponseHeader = z.infer<typeof HoppRESTResponseHeaders>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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<typeof HoppRESTRequestResponse>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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<typeof HoppRESTRequestResponses>
|
|
||||||
|
|
||||||
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<typeof V7_SCHEMA>) {
|
|
||||||
return {
|
|
||||||
...old,
|
|
||||||
v: "8" as const,
|
|
||||||
// no need to update anything for HoppRESTAuth, because we loosened the previous schema by making `clientSecret` optional
|
|
||||||
responses: {},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
75
packages/hoppscotch-data/src/rest/v/8/auth.ts
Normal file
75
packages/hoppscotch-data/src/rest/v/8/auth.ts
Normal file
|
|
@ -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<typeof HoppRESTAuthOAuth2>
|
||||||
|
|
||||||
|
// 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<typeof HoppRESTAuthDigest>
|
||||||
|
|
||||||
|
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<typeof HoppRESTAuth>
|
||||||
27
packages/hoppscotch-data/src/rest/v/8/index.ts
Normal file
27
packages/hoppscotch-data/src/rest/v/8/index.ts
Normal file
|
|
@ -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<typeof V7_SCHEMA>) {
|
||||||
|
return {
|
||||||
|
...old,
|
||||||
|
v: "8" as const,
|
||||||
|
// no need to update anything for HoppRESTAuth, because we loosened the previous schema by making `clientSecret` optional
|
||||||
|
responses: {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
@ -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<typeof FormDataKeyValue>
|
|
||||||
|
|
||||||
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<typeof HoppRESTReqBody>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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<typeof HoppRESTRequestResponse>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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<typeof HoppRESTRequestResponses>
|
|
||||||
|
|
||||||
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<typeof V8_SCHEMA>) {
|
|
||||||
// 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,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
68
packages/hoppscotch-data/src/rest/v/9/body.ts
Normal file
68
packages/hoppscotch-data/src/rest/v/9/body.ts
Normal file
|
|
@ -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<typeof FormDataKeyValue>
|
||||||
|
|
||||||
|
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<typeof HoppRESTReqBody>
|
||||||
22
packages/hoppscotch-data/src/rest/v/9/index.ts
Normal file
22
packages/hoppscotch-data/src/rest/v/9/index.ts
Normal file
|
|
@ -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<typeof V8_SCHEMA>) {
|
||||||
|
// No migration for body, the new contentType added to each formdata field is optional
|
||||||
|
return {
|
||||||
|
...old,
|
||||||
|
v: "9" as const,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
@ -96,11 +96,10 @@ async function loadUserEnvironments() {
|
||||||
|
|
||||||
replaceEnvironments(
|
replaceEnvironments(
|
||||||
formatedEnvironments.map((environment) => {
|
formatedEnvironments.map((environment) => {
|
||||||
const parsedEnv =
|
const parsedEnv = Environment.safeParse(environment)
|
||||||
entityReference(Environment).safeParse(environment)
|
|
||||||
|
|
||||||
return parsedEnv.success
|
return parsedEnv.type === "ok"
|
||||||
? parsedEnv.data
|
? parsedEnv.value
|
||||||
: {
|
: {
|
||||||
...environment,
|
...environment,
|
||||||
v: EnvironmentSchemaVersion,
|
v: EnvironmentSchemaVersion,
|
||||||
|
|
@ -191,12 +190,24 @@ function setupUserEnvironmentUpdatedSubscription() {
|
||||||
)
|
)
|
||||||
|
|
||||||
if ((localIndex || localIndex == 0) && name) {
|
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(() => {
|
runDispatchWithOutSyncing(() => {
|
||||||
updateEnvironment(localIndex, {
|
updateEnvironment(localIndex, parsedEnv)
|
||||||
id,
|
|
||||||
name,
|
|
||||||
variables: JSON.parse(variables),
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,11 +97,10 @@ async function loadUserEnvironments() {
|
||||||
|
|
||||||
replaceEnvironments(
|
replaceEnvironments(
|
||||||
formatedEnvironments.map((environment) => {
|
formatedEnvironments.map((environment) => {
|
||||||
const parsedEnv =
|
const parsedEnv = Environment.safeParse(environment)
|
||||||
entityReference(Environment).safeParse(environment)
|
|
||||||
|
|
||||||
return parsedEnv.success
|
return parsedEnv.type === "ok"
|
||||||
? parsedEnv.data
|
? parsedEnv.value
|
||||||
: {
|
: {
|
||||||
...environment,
|
...environment,
|
||||||
v: EnvironmentSchemaVersion,
|
v: EnvironmentSchemaVersion,
|
||||||
|
|
|
||||||
|
|
@ -97,11 +97,10 @@ async function loadUserEnvironments() {
|
||||||
|
|
||||||
replaceEnvironments(
|
replaceEnvironments(
|
||||||
formatedEnvironments.map((environment) => {
|
formatedEnvironments.map((environment) => {
|
||||||
const parsedEnv =
|
const parsedEnv = Environment.safeParse(environment)
|
||||||
entityReference(Environment).safeParse(environment)
|
|
||||||
|
|
||||||
return parsedEnv.success
|
return parsedEnv.type === "ok"
|
||||||
? parsedEnv.data
|
? parsedEnv.value
|
||||||
: {
|
: {
|
||||||
...environment,
|
...environment,
|
||||||
v: EnvironmentSchemaVersion,
|
v: EnvironmentSchemaVersion,
|
||||||
|
|
@ -192,13 +191,24 @@ function setupUserEnvironmentUpdatedSubscription() {
|
||||||
)
|
)
|
||||||
|
|
||||||
if ((localIndex || localIndex == 0) && name) {
|
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(() => {
|
runDispatchWithOutSyncing(() => {
|
||||||
updateEnvironment(localIndex, {
|
updateEnvironment(localIndex, parsedEnv)
|
||||||
v: 2,
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
variables: JSON.parse(variables),
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue