feat: import environments from insomnia (#3625)
Co-authored-by: jamesgeorge007 <jamesgeorge998001@gmail.com>
This commit is contained in:
16
packages/hoppscotch-common/src/helpers/functional/yaml.ts
Normal file
16
packages/hoppscotch-common/src/helpers/functional/yaml.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import yaml from "js-yaml"
|
||||
import * as O from "fp-ts/Option"
|
||||
import { safeParseJSON } from "./json"
|
||||
import { pipe } from "fp-ts/function"
|
||||
|
||||
export const safeParseYAML = (str: string) => O.tryCatch(() => yaml.load(str))
|
||||
|
||||
export const safeParseJSONOrYAML = (str: string) =>
|
||||
pipe(
|
||||
str,
|
||||
safeParseJSON,
|
||||
O.match(
|
||||
() => safeParseYAML(str),
|
||||
(data) => O.of(data)
|
||||
)
|
||||
)
|
||||
@@ -1,5 +1,5 @@
|
||||
import { convert, ImportRequest } from "insomnia-importers"
|
||||
import { pipe, flow } from "fp-ts/function"
|
||||
import { pipe } from "fp-ts/function"
|
||||
import {
|
||||
HoppRESTAuth,
|
||||
HoppRESTHeader,
|
||||
@@ -12,10 +12,10 @@ import {
|
||||
makeCollection,
|
||||
} from "@hoppscotch/data"
|
||||
import * as A from "fp-ts/Array"
|
||||
import * as S from "fp-ts/string"
|
||||
import * as TO from "fp-ts/TaskOption"
|
||||
import * as TE from "fp-ts/TaskEither"
|
||||
import { IMPORTER_INVALID_FILE_FORMAT } from "."
|
||||
import { replaceInsomniaTemplating } from "./insomniaEnv"
|
||||
|
||||
// TODO: Insomnia allows custom prefixes for Bearer token auth, Hoppscotch doesn't. We just ignore the prefix for now
|
||||
|
||||
@@ -32,10 +32,8 @@ type InsomniaRequestResource = ImportRequest & { _type: "request" }
|
||||
const parseInsomniaDoc = (content: string) =>
|
||||
TO.tryCatch(() => convert(content))
|
||||
|
||||
const replaceVarTemplating = flow(
|
||||
S.replace(/{{\s*/g, "<<"),
|
||||
S.replace(/\s*}}/g, ">>")
|
||||
)
|
||||
const replaceVarTemplating = (expression: string) =>
|
||||
replaceInsomniaTemplating(expression)
|
||||
|
||||
const getFoldersIn = (
|
||||
folder: InsomniaFolderResource | null,
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
import * as TE from "fp-ts/TaskEither"
|
||||
import * as O from "fp-ts/Option"
|
||||
|
||||
import { IMPORTER_INVALID_FILE_FORMAT } from "."
|
||||
|
||||
import { z } from "zod"
|
||||
import { Environment } from "@hoppscotch/data"
|
||||
import { safeParseJSONOrYAML } from "~/helpers/functional/yaml"
|
||||
|
||||
const insomniaResourcesSchema = z.object({
|
||||
resources: z.array(
|
||||
z
|
||||
.object({
|
||||
_type: z.string(),
|
||||
})
|
||||
.passthrough()
|
||||
),
|
||||
})
|
||||
|
||||
const insomniaEnvSchema = z.object({
|
||||
_type: z.literal("environment"),
|
||||
name: z.string(),
|
||||
data: z.record(z.string()),
|
||||
})
|
||||
|
||||
export const replaceInsomniaTemplating = (expression: string) => {
|
||||
const regex = /\{\{ _\.([^}]+) \}\}/g
|
||||
return expression.replaceAll(regex, "<<$1>>")
|
||||
}
|
||||
|
||||
export const insomniaEnvImporter = (content: string) => {
|
||||
const parsedContent = safeParseJSONOrYAML(content)
|
||||
|
||||
if (O.isNone(parsedContent)) {
|
||||
return TE.left(IMPORTER_INVALID_FILE_FORMAT)
|
||||
}
|
||||
|
||||
const validationResult = insomniaResourcesSchema.safeParse(
|
||||
parsedContent.value
|
||||
)
|
||||
|
||||
if (!validationResult.success) {
|
||||
return TE.left(IMPORTER_INVALID_FILE_FORMAT)
|
||||
}
|
||||
|
||||
const insomniaEnvs = validationResult.data.resources
|
||||
.filter((resource) => resource._type === "environment")
|
||||
.map((envResource) => {
|
||||
const envResourceData = envResource.data as Record<string, unknown>
|
||||
const stringifiedData: Record<string, string> = {}
|
||||
|
||||
Object.keys(envResourceData).forEach((key) => {
|
||||
stringifiedData[key] = String(envResourceData[key])
|
||||
})
|
||||
|
||||
return { ...envResource, data: stringifiedData }
|
||||
})
|
||||
|
||||
const environments: Environment[] = []
|
||||
|
||||
insomniaEnvs.forEach((insomniaEnv) => {
|
||||
const parsedInsomniaEnv = insomniaEnvSchema.safeParse(insomniaEnv)
|
||||
|
||||
if (parsedInsomniaEnv.success) {
|
||||
const environment: Environment = {
|
||||
name: parsedInsomniaEnv.data.name,
|
||||
variables: Object.entries(parsedInsomniaEnv.data.data).map(
|
||||
([key, value]) => ({ key, value })
|
||||
),
|
||||
}
|
||||
|
||||
environments.push(environment)
|
||||
}
|
||||
})
|
||||
|
||||
const processedEnvironments = environments.map((env) => ({
|
||||
...env,
|
||||
variables: env.variables.map((variable) => ({
|
||||
...variable,
|
||||
value: replaceInsomniaTemplating(variable.value),
|
||||
})),
|
||||
}))
|
||||
|
||||
return TE.right(processedEnvironments)
|
||||
}
|
||||
Reference in New Issue
Block a user