Merge branch 'hoppscotch:main' into codeday/main
This commit is contained in:
@@ -1,3 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Converts an array of key-value tuples (for e.g ["key", "value"]), into a record.
|
||||||
|
* (for eg. output -> { "key": "value" })
|
||||||
|
* NOTE: This function will discard duplicate key occurances and only keep the last occurance. If you do not want that behaviour,
|
||||||
|
* use `tupleWithSamesKeysToRecord`.
|
||||||
|
* @param tuples Array of tuples ([key, value])
|
||||||
|
* @returns A record with value corresponding to the last occurance of that key
|
||||||
|
*/
|
||||||
export const tupleToRecord = <
|
export const tupleToRecord = <
|
||||||
KeyType extends string | number | symbol,
|
KeyType extends string | number | symbol,
|
||||||
ValueType
|
ValueType
|
||||||
@@ -5,5 +13,32 @@ export const tupleToRecord = <
|
|||||||
tuples: [KeyType, ValueType][]
|
tuples: [KeyType, ValueType][]
|
||||||
): Record<KeyType, ValueType> =>
|
): Record<KeyType, ValueType> =>
|
||||||
tuples.length > 0
|
tuples.length > 0
|
||||||
? (Object.assign as any)(...tuples.map(([key, val]) => ({ [key]: val })))
|
? (Object.assign as any)(...tuples.map(([key, val]) => ({ [key]: val }))) // This is technically valid, but we have no way of telling TypeScript it is valid. Hence the assertion
|
||||||
: {}
|
: {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an array of key-value tuples (for e.g ["key", "value"]), into a record.
|
||||||
|
* (for eg. output -> { "key": ["value"] })
|
||||||
|
* NOTE: If you do not want the array as values (because of duplicate keys) and want to instead get the last occurance, use `tupleToRecord`
|
||||||
|
* @param tuples Array of tuples ([key, value])
|
||||||
|
* @returns A Record with values being arrays corresponding to each key occurance
|
||||||
|
*/
|
||||||
|
export const tupleWithSameKeysToRecord = <
|
||||||
|
KeyType extends string | number | symbol,
|
||||||
|
ValueType
|
||||||
|
>(
|
||||||
|
tuples: [KeyType, ValueType][]
|
||||||
|
): Record<KeyType, ValueType[]> => {
|
||||||
|
// By the end of the function we do ensure this typing, this can't be infered now though, hence the assertion
|
||||||
|
const out = {} as Record<KeyType, ValueType[]>
|
||||||
|
|
||||||
|
for (const [key, value] of tuples) {
|
||||||
|
if (!out[key]) {
|
||||||
|
out[key] = [value]
|
||||||
|
} else {
|
||||||
|
out[key].push(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
import * as A from "fp-ts/Array"
|
import * as A from "fp-ts/Array"
|
||||||
|
import * as E from "fp-ts/Either"
|
||||||
|
import * as O from "fp-ts/Option"
|
||||||
|
import * as RA from "fp-ts/ReadonlyArray"
|
||||||
|
import * as S from "fp-ts/string"
|
||||||
import qs from "qs"
|
import qs from "qs"
|
||||||
import { pipe } from "fp-ts/function"
|
import { flow, pipe } from "fp-ts/function"
|
||||||
import { combineLatest, Observable } from "rxjs"
|
import { combineLatest, Observable } from "rxjs"
|
||||||
import { map } from "rxjs/operators"
|
import { map } from "rxjs/operators"
|
||||||
import {
|
import {
|
||||||
@@ -9,14 +13,15 @@ import {
|
|||||||
HoppRESTRequest,
|
HoppRESTRequest,
|
||||||
parseTemplateString,
|
parseTemplateString,
|
||||||
parseBodyEnvVariables,
|
parseBodyEnvVariables,
|
||||||
parseRawKeyValueEntries,
|
|
||||||
Environment,
|
Environment,
|
||||||
HoppRESTHeader,
|
HoppRESTHeader,
|
||||||
HoppRESTParam,
|
HoppRESTParam,
|
||||||
|
parseRawKeyValueEntriesE,
|
||||||
|
parseTemplateStringE,
|
||||||
} from "@hoppscotch/data"
|
} from "@hoppscotch/data"
|
||||||
import { arrayFlatMap, arraySort } from "../functional/array"
|
import { arrayFlatMap, arraySort } from "../functional/array"
|
||||||
import { toFormData } from "../functional/formData"
|
import { toFormData } from "../functional/formData"
|
||||||
import { tupleToRecord } from "../functional/record"
|
import { tupleWithSameKeysToRecord } from "../functional/record"
|
||||||
import { getGlobalVariables } from "~/newstore/environments"
|
import { getGlobalVariables } from "~/newstore/environments"
|
||||||
|
|
||||||
export interface EffectiveHoppRESTRequest extends HoppRESTRequest {
|
export interface EffectiveHoppRESTRequest extends HoppRESTRequest {
|
||||||
@@ -211,25 +216,40 @@ function getFinalBodyFromRequest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (request.body.contentType === "application/x-www-form-urlencoded") {
|
if (request.body.contentType === "application/x-www-form-urlencoded") {
|
||||||
return pipe(
|
const parsedBodyRecord = pipe(
|
||||||
request.body.body,
|
request.body.body,
|
||||||
parseRawKeyValueEntries,
|
parseRawKeyValueEntriesE,
|
||||||
|
E.map(
|
||||||
|
flow(
|
||||||
|
RA.toArray,
|
||||||
|
/**
|
||||||
|
* Filtering out empty keys and non-active pairs.
|
||||||
|
*/
|
||||||
|
A.filter(({ active, key }) => active && !S.isEmpty(key)),
|
||||||
|
|
||||||
// Filter out active
|
/**
|
||||||
A.filter((x) => x.active),
|
* Mapping each key-value to template-string-parser with either on array,
|
||||||
// Convert to tuple
|
* which will be resolved in further steps.
|
||||||
A.map(
|
*/
|
||||||
({ key, value }) =>
|
A.map(({ key, value }) => [
|
||||||
[
|
parseTemplateStringE(key, envVariables),
|
||||||
parseTemplateString(key, envVariables),
|
parseTemplateStringE(value, envVariables),
|
||||||
parseTemplateString(value, envVariables),
|
]),
|
||||||
] as [string, string]
|
|
||||||
|
/**
|
||||||
|
* Filtering and mapping only right-eithers for each key-value as [string, string].
|
||||||
|
*/
|
||||||
|
A.filterMap(([key, value]) =>
|
||||||
|
E.isRight(key) && E.isRight(value)
|
||||||
|
? O.some([key.right, value.right] as [string, string])
|
||||||
|
: O.none
|
||||||
),
|
),
|
||||||
// Tuple to Record object
|
tupleWithSameKeysToRecord,
|
||||||
tupleToRecord,
|
(obj) => qs.stringify(obj, { indices: false })
|
||||||
// Stringify
|
|
||||||
qs.stringify
|
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return E.isRight(parsedBodyRecord) ? parsedBodyRecord.right : null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.body.contentType === "multipart/form-data") {
|
if (request.body.contentType === "multipart/form-data") {
|
||||||
|
|||||||
Reference in New Issue
Block a user