feat: description field for request parameters and headers (#4187)
* feat: key-value component added for reuse * chore: inspection result added * chore: add `HoppRESTRequest` schema `v7` * feat: add `description` for field for REST request headers * feat: add `description` for field for GraphQL request headers * fix: synchronization logic b/w bulk edit context and the default view - Add `HoppGQLRequest` schema `v6`. - Fix pre-existing issue with changes in bulk edit context not immediately reflecting in the default GQL request headers view. * feat: support importing `description` fields from external sources * test: fix failing tests * chore: include description field for computed headers Headers computed based on authorization info & inherited entries. * feat: add `description` field for headers at the collection level Add `HoppCollection` schema `v3`. * test: fix failing tests * ci: update tests workflow target branch trigger * chore: cleanup * chore: cleanup * chore: rely on type inference --------- Co-authored-by: jamesgeorge007 <25279263+jamesgeorge007@users.noreply.github.com> Co-authored-by: nivedin <nivedinp@gmail.com>
This commit is contained in:
@@ -112,31 +112,37 @@ const samples = [
|
||||
key: "User-Agent",
|
||||
value:
|
||||
"Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0",
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
key: "Accept",
|
||||
value: "application/json, text/plain, */*",
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
key: "Accept-Language",
|
||||
value: "en",
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
key: "Origin",
|
||||
value: "http://localhost:3012",
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
key: "Connection",
|
||||
value: "keep-alive",
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
key: "Referer",
|
||||
value: "http://localhost:3012/crm/company/4",
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
params: [],
|
||||
@@ -180,6 +186,7 @@ const samples = [
|
||||
active: true,
|
||||
key: "bar",
|
||||
value: "baz",
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
preRequestScript: "",
|
||||
@@ -204,11 +211,13 @@ const samples = [
|
||||
active: true,
|
||||
key: "tool",
|
||||
value: "curl",
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
key: "age",
|
||||
value: "old",
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
preRequestScript: "",
|
||||
@@ -270,6 +279,7 @@ const samples = [
|
||||
active: true,
|
||||
key: "Accept",
|
||||
value: "application/json",
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
preRequestScript: "",
|
||||
@@ -366,11 +376,13 @@ const samples = [
|
||||
active: true,
|
||||
key: "tool",
|
||||
value: "curl",
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
key: "platform",
|
||||
value: "hoppscotch",
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
headers: [],
|
||||
@@ -415,11 +427,13 @@ const samples = [
|
||||
active: true,
|
||||
key: "and",
|
||||
value: "params",
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
key: "stay",
|
||||
value: "tuned",
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
headers: [
|
||||
@@ -427,16 +441,19 @@ const samples = [
|
||||
active: true,
|
||||
key: "user-agent",
|
||||
value: "Mozilla/5.0",
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
key: "accept",
|
||||
value: "text/html",
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
key: "cookie",
|
||||
value: "cookie-cookie",
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
preRequestScript: "",
|
||||
@@ -497,33 +514,39 @@ const samples = [
|
||||
active: true,
|
||||
key: "authority",
|
||||
value: "hoppscotch.io",
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
key: "sec-ch-ua",
|
||||
value:
|
||||
'" Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"',
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
key: "accept",
|
||||
value: "*/*",
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
key: "user-agent",
|
||||
value:
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36",
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
key: "sec-ch-ua-platform",
|
||||
value: '"Windows"',
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
key: "accept-language",
|
||||
value: "en-US,en;q=0.9,ml;q=0.8",
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
preRequestScript: "",
|
||||
@@ -563,6 +586,7 @@ const samples = [
|
||||
active: true,
|
||||
key: "hello",
|
||||
value: "there",
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
headers: [
|
||||
@@ -570,6 +594,7 @@ const samples = [
|
||||
active: true,
|
||||
key: "something",
|
||||
value: "other-thing",
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
preRequestScript: "",
|
||||
@@ -594,6 +619,7 @@ const samples = [
|
||||
active: true,
|
||||
key: "something",
|
||||
value: "other-thing",
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
body: {
|
||||
@@ -618,6 +644,7 @@ const samples = [
|
||||
active: true,
|
||||
key: "hello",
|
||||
value: "there",
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
preRequestScript: "",
|
||||
@@ -695,6 +722,7 @@ const samples = [
|
||||
active: true,
|
||||
key: "User-Agent",
|
||||
value: "pinephone",
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
body: {
|
||||
@@ -742,6 +770,7 @@ const samples = [
|
||||
active: true,
|
||||
key: "tool",
|
||||
value: "hopp",
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
preRequestScript: "",
|
||||
@@ -893,6 +922,7 @@ data2: {"type":"test2","typeId":"123"}`,
|
||||
active: true,
|
||||
key: "Accept",
|
||||
value: "application/vnd.test-data.v2.1+json",
|
||||
description: "",
|
||||
},
|
||||
],
|
||||
preRequestScript: "",
|
||||
|
||||
@@ -3,28 +3,28 @@
|
||||
* just adding the /browser import as a fix for now, which does not have type info on DefinitelyTyped.
|
||||
* remove/update this comment before merging the vue3 port.
|
||||
*/
|
||||
import parser from "yargs-parser/browser"
|
||||
import * as O from "fp-ts/Option"
|
||||
import * as A from "fp-ts/Array"
|
||||
import { pipe, flow } from "fp-ts/function"
|
||||
import {
|
||||
FormDataKeyValue,
|
||||
HoppRESTReqBody,
|
||||
makeRESTRequest,
|
||||
} from "@hoppscotch/data"
|
||||
import * as A from "fp-ts/Array"
|
||||
import { flow, pipe } from "fp-ts/function"
|
||||
import * as O from "fp-ts/Option"
|
||||
import parser from "yargs-parser/browser"
|
||||
import { getAuthObject } from "./sub_helpers/auth"
|
||||
import { getHeaders, recordToHoppHeaders } from "./sub_helpers/headers"
|
||||
// import { getCookies } from "./sub_helpers/cookies"
|
||||
import { getQueries } from "./sub_helpers/queries"
|
||||
import { getMethod } from "./sub_helpers/method"
|
||||
import { concatParams, getURLObject } from "./sub_helpers/url"
|
||||
import { preProcessCurlCommand } from "./sub_helpers/preproc"
|
||||
import { getBody, getFArgumentMultipartData } from "./sub_helpers/body"
|
||||
import { getDefaultRESTRequest } from "../rest/default"
|
||||
import {
|
||||
objHasProperty,
|
||||
objHasArrayProperty,
|
||||
objHasProperty,
|
||||
} from "~/helpers/functional/object"
|
||||
import { getDefaultRESTRequest } from "../rest/default"
|
||||
import { getBody, getFArgumentMultipartData } from "./sub_helpers/body"
|
||||
import { getMethod } from "./sub_helpers/method"
|
||||
import { preProcessCurlCommand } from "./sub_helpers/preproc"
|
||||
import { getQueries } from "./sub_helpers/queries"
|
||||
import { concatParams, getURLObject } from "./sub_helpers/url"
|
||||
|
||||
const defaultRESTReq = getDefaultRESTRequest()
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import parser from "yargs-parser"
|
||||
import { pipe, flow } from "fp-ts/function"
|
||||
import { HoppRESTHeader } from "@hoppscotch/data"
|
||||
import * as A from "fp-ts/Array"
|
||||
import * as S from "fp-ts/string"
|
||||
import { flow, pipe } from "fp-ts/function"
|
||||
import * as O from "fp-ts/Option"
|
||||
import { tupleToRecord } from "~/helpers/functional/record"
|
||||
import * as S from "fp-ts/string"
|
||||
import parser from "yargs-parser"
|
||||
import {
|
||||
objHasProperty,
|
||||
objHasArrayProperty,
|
||||
objHasProperty,
|
||||
} from "~/helpers/functional/object"
|
||||
import { tupleToRecord } from "~/helpers/functional/record"
|
||||
|
||||
const getHeaderPair = flow(
|
||||
S.split(": "),
|
||||
@@ -66,6 +66,7 @@ export const recordToHoppHeaders = (
|
||||
key,
|
||||
value: headers[key],
|
||||
active: true,
|
||||
description: "",
|
||||
})),
|
||||
A.filter(
|
||||
(header) =>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { pipe, flow } from "fp-ts/function"
|
||||
import * as O from "fp-ts/Option"
|
||||
import * as A from "fp-ts/Array"
|
||||
import * as Sep from "fp-ts/Separated"
|
||||
import { HoppRESTParam } from "@hoppscotch/data"
|
||||
import * as A from "fp-ts/Array"
|
||||
import { flow, pipe } from "fp-ts/function"
|
||||
import * as O from "fp-ts/Option"
|
||||
import * as Sep from "fp-ts/Separated"
|
||||
|
||||
const isDangling = ([, value]: [string, string]) => !value
|
||||
|
||||
@@ -26,6 +26,7 @@ export function getQueries(params: Array<[string, string]>): {
|
||||
key,
|
||||
value,
|
||||
active: true,
|
||||
description: "",
|
||||
})),
|
||||
A.map(([key]) => key)
|
||||
),
|
||||
|
||||
@@ -5,10 +5,10 @@ import {
|
||||
HoppRESTParam,
|
||||
HoppRESTReqBody,
|
||||
HoppRESTRequest,
|
||||
HoppRESTRequestVariable,
|
||||
knownContentTypes,
|
||||
makeCollection,
|
||||
makeRESTRequest,
|
||||
HoppRESTRequestVariable,
|
||||
} from "@hoppscotch/data"
|
||||
|
||||
import * as A from "fp-ts/Array"
|
||||
@@ -16,6 +16,7 @@ import * as TE from "fp-ts/TaskEither"
|
||||
import * as TO from "fp-ts/TaskOption"
|
||||
import { pipe } from "fp-ts/function"
|
||||
import { ImportRequest, convert } from "insomnia-importers"
|
||||
import { Header, Parameter } from "insomnia-importers/dist/src/entities"
|
||||
|
||||
import { IMPORTER_INVALID_FILE_FORMAT } from "."
|
||||
import { replaceInsomniaTemplating } from "./insomniaEnv"
|
||||
@@ -36,10 +37,13 @@ type InsomniaPathParameter = {
|
||||
}
|
||||
|
||||
type InsomniaFolderResource = ImportRequest & { _type: "request_group" }
|
||||
type InsomniaRequestResource = ImportRequest & {
|
||||
type InsomniaRequestResource = Omit<ImportRequest, "headers" | "parameters"> & {
|
||||
_type: "request"
|
||||
} & {
|
||||
pathParameters?: InsomniaPathParameter[]
|
||||
} & {
|
||||
headers: (Header & { description: string })[]
|
||||
parameters: (Parameter & { description: string })[]
|
||||
}
|
||||
|
||||
const parseInsomniaDoc = (content: string) =>
|
||||
@@ -192,6 +196,7 @@ const getHoppReqHeaders = (req: InsomniaRequestResource): HoppRESTHeader[] =>
|
||||
key: replaceVarTemplating(header.name),
|
||||
value: replaceVarTemplating(header.value),
|
||||
active: !header.disabled,
|
||||
description: header.description ?? "",
|
||||
})) ?? []
|
||||
|
||||
const getHoppReqParams = (req: InsomniaRequestResource): HoppRESTParam[] =>
|
||||
@@ -199,6 +204,7 @@ const getHoppReqParams = (req: InsomniaRequestResource): HoppRESTParam[] =>
|
||||
key: replaceVarTemplating(param.name),
|
||||
value: replaceVarTemplating(param.value ?? ""),
|
||||
active: !(param.disabled ?? false),
|
||||
description: param.description ?? "",
|
||||
})) ?? []
|
||||
|
||||
const getHoppReqVariables = (
|
||||
|
||||
@@ -79,6 +79,7 @@ const parseOpenAPIParams = (params: OpenAPIParamsType[]): HoppRESTParam[] =>
|
||||
key: param.name,
|
||||
value: "", // TODO: Can we do anything more ? (parse default values maybe)
|
||||
active: true,
|
||||
description: param.description ?? "",
|
||||
}
|
||||
)
|
||||
)
|
||||
@@ -113,14 +114,14 @@ const parseOpenAPIHeaders = (params: OpenAPIParamsType[]): HoppRESTHeader[] =>
|
||||
A.filterMap(
|
||||
flow(
|
||||
O.fromPredicate((param) => param.in === "header"),
|
||||
O.map(
|
||||
(header) =>
|
||||
<HoppRESTParam>{
|
||||
key: header.name,
|
||||
value: "", // TODO: Can we do anything more ? (parse default values maybe)
|
||||
active: true,
|
||||
}
|
||||
)
|
||||
O.map((header) => {
|
||||
return <HoppRESTParam>{
|
||||
key: header.name,
|
||||
value: "", // TODO: Can we do anything more ? (parse default values maybe)
|
||||
active: true,
|
||||
description: header.description ?? "",
|
||||
}
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1,34 +1,35 @@
|
||||
import {
|
||||
Collection as PMCollection,
|
||||
Item,
|
||||
ItemGroup,
|
||||
QueryParam,
|
||||
RequestAuthDefinition,
|
||||
VariableDefinition,
|
||||
Variable,
|
||||
} from "postman-collection"
|
||||
import {
|
||||
FormDataKeyValue,
|
||||
HoppCollection,
|
||||
HoppRESTAuth,
|
||||
HoppRESTHeader,
|
||||
HoppRESTParam,
|
||||
HoppRESTReqBody,
|
||||
HoppRESTRequest,
|
||||
makeRESTRequest,
|
||||
HoppCollection,
|
||||
makeCollection,
|
||||
ValidContentTypes,
|
||||
knownContentTypes,
|
||||
FormDataKeyValue,
|
||||
HoppRESTRequestVariable,
|
||||
knownContentTypes,
|
||||
makeCollection,
|
||||
makeRESTRequest,
|
||||
ValidContentTypes,
|
||||
} from "@hoppscotch/data"
|
||||
import { pipe, flow } from "fp-ts/function"
|
||||
import * as S from "fp-ts/string"
|
||||
import * as A from "fp-ts/Array"
|
||||
import { flow, pipe } from "fp-ts/function"
|
||||
import * as O from "fp-ts/Option"
|
||||
import * as S from "fp-ts/string"
|
||||
import * as TE from "fp-ts/TaskEither"
|
||||
import { IMPORTER_INVALID_FILE_FORMAT } from "."
|
||||
import { PMRawLanguage } from "~/types/pm-coll-exts"
|
||||
import {
|
||||
DescriptionDefinition,
|
||||
Item,
|
||||
ItemGroup,
|
||||
Collection as PMCollection,
|
||||
QueryParam,
|
||||
RequestAuthDefinition,
|
||||
Variable,
|
||||
VariableDefinition,
|
||||
} from "postman-collection"
|
||||
import { stringArrayJoin } from "~/helpers/functional/array"
|
||||
import { PMRawLanguage } from "~/types/pm-coll-exts"
|
||||
import { IMPORTER_INVALID_FILE_FORMAT } from "."
|
||||
|
||||
const safeParseJSON = (jsonStr: string) => O.tryCatch(() => JSON.parse(jsonStr))
|
||||
|
||||
@@ -64,14 +65,29 @@ const readPMCollection = (def: string) =>
|
||||
)
|
||||
)
|
||||
|
||||
const parseDescription = (descField?: string | DescriptionDefinition) => {
|
||||
if (!descField) {
|
||||
return ""
|
||||
}
|
||||
|
||||
if (typeof descField === "string") {
|
||||
return descField
|
||||
}
|
||||
|
||||
return descField.content
|
||||
}
|
||||
|
||||
const getHoppReqHeaders = (item: Item): HoppRESTHeader[] =>
|
||||
pipe(
|
||||
item.request.headers.all(),
|
||||
A.map((header) => {
|
||||
const description = parseDescription(header.description)
|
||||
|
||||
return <HoppRESTHeader>{
|
||||
key: replacePMVarTemplating(header.key),
|
||||
value: replacePMVarTemplating(header.value),
|
||||
active: !header.disabled,
|
||||
description,
|
||||
}
|
||||
})
|
||||
)
|
||||
@@ -84,10 +100,13 @@ const getHoppReqParams = (item: Item): HoppRESTParam[] => {
|
||||
param.key !== undefined && param.key !== null && param.key.length > 0
|
||||
),
|
||||
A.map((param) => {
|
||||
const description = parseDescription(param.description)
|
||||
|
||||
return <HoppRESTHeader>{
|
||||
key: replacePMVarTemplating(param.key),
|
||||
value: replacePMVarTemplating(param.value ?? ""),
|
||||
active: !param.disabled,
|
||||
description,
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
@@ -93,6 +93,7 @@ export const getComputedAuthHeaders = (
|
||||
active: true,
|
||||
key: "Authorization",
|
||||
value: `Basic ${btoa(`${username}:${password}`)}`,
|
||||
description: "",
|
||||
})
|
||||
} else if (
|
||||
request.auth.authType === "bearer" ||
|
||||
@@ -111,6 +112,7 @@ export const getComputedAuthHeaders = (
|
||||
? parseTemplateString(token, envVars, false, showKeyIfSecret)
|
||||
: token
|
||||
}`,
|
||||
description: "",
|
||||
})
|
||||
} else if (request.auth.authType === "api-key") {
|
||||
const { key, addTo } = request.auth
|
||||
@@ -126,6 +128,7 @@ export const getComputedAuthHeaders = (
|
||||
showKeyIfSecret
|
||||
)
|
||||
: request.auth.value ?? "",
|
||||
description: "",
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -164,6 +167,7 @@ export const getComputedBodyHeaders = (
|
||||
active: true,
|
||||
key: "content-type",
|
||||
value: req.body.contentType,
|
||||
description: "",
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -249,6 +253,7 @@ export const getComputedParams = (
|
||||
active: true,
|
||||
key: parseTemplateString(req.auth.key, envVars, false, true),
|
||||
value: parseTemplateString(req.auth.value, envVars, false, true),
|
||||
description: "",
|
||||
},
|
||||
},
|
||||
]
|
||||
@@ -263,6 +268,7 @@ export const getComputedParams = (
|
||||
active: true,
|
||||
key: "access_token",
|
||||
value: parseTemplateString(grantTypeInfo.token, envVars, false, true),
|
||||
description: "",
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user