diff --git a/packages/hoppscotch-common/src/helpers/import-export/import/openapi.ts b/packages/hoppscotch-common/src/helpers/import-export/import/openapi.ts index dddf4876..2678389d 100644 --- a/packages/hoppscotch-common/src/helpers/import-export/import/openapi.ts +++ b/packages/hoppscotch-common/src/helpers/import-export/import/openapi.ts @@ -27,13 +27,19 @@ import * as S from "fp-ts/string" import * as O from "fp-ts/Option" import * as TE from "fp-ts/TaskEither" import * as RA from "fp-ts/ReadonlyArray" +import * as E from "fp-ts/Either" import { IMPORTER_INVALID_FILE_FORMAT } from "." import { cloneDeep, isNumber } from "lodash-es" import { getStatusCodeReasonPhrase } from "~/helpers/utils/statusCodes" export const OPENAPI_DEREF_ERROR = "openapi/deref_error" as const -// TODO: URL Import Support +const worker = new Worker( + new URL("./workers/openapi-import-worker.ts", import.meta.url), + { + type: "module", + } +) const safeParseJSON = (str: string) => O.tryCatch(() => JSON.parse(str)) @@ -927,10 +933,7 @@ export const hoppOpenAPIImporter = (fileContents: string[]) => throw new Error("INVALID_OPENAPI_SPEC") } - const validatedDoc = await SwaggerParser.validate(docObj, { - // @ts-expect-error - this is a valid option, but seems like the types are not updated - continueOnError: true, - }) + const validatedDoc = await validateDocs(docObj) resultDoc.push(validatedDoc) } catch (err) { @@ -969,7 +972,8 @@ export const hoppOpenAPIImporter = (fileContents: string[]) => const resultDoc = [] for (const docObj of docArr) { - const validatedDoc = await SwaggerParser.dereference(docObj) + const validatedDoc = await dereferenceDocs(docObj) + resultDoc.push(validatedDoc) } @@ -981,3 +985,41 @@ export const hoppOpenAPIImporter = (fileContents: string[]) => ), TE.chainW(convertOpenApiDocsToHopp) ) + +const validateDocs = (docs: any): Promise => { + return new Promise((resolve, reject) => { + worker.postMessage({ + type: "validate", + docs, + }) + + worker.onmessage = (event) => { + if (event.data.type === "VALIDATION_RESULT") { + if (E.isLeft(event.data.data)) { + reject("COULD_NOT_VALIDATE") + } else { + resolve(event.data.data.right as OpenAPI.Document) + } + } + } + }) +} + +const dereferenceDocs = (docs: any): Promise => { + return new Promise((resolve, reject) => { + worker.postMessage({ + type: "dereference", + docs, + }) + + worker.onmessage = (event) => { + if (event.data.type === "DEREFERENCE_RESULT") { + if (E.isLeft(event.data.data)) { + reject("COULD_NOT_DEREFERENCE") + } else { + resolve(event.data.data.right as OpenAPI.Document) + } + } + } + }) +} diff --git a/packages/hoppscotch-common/src/helpers/import-export/import/workers/openapi-import-worker.ts b/packages/hoppscotch-common/src/helpers/import-export/import/workers/openapi-import-worker.ts new file mode 100644 index 00000000..43105fd1 --- /dev/null +++ b/packages/hoppscotch-common/src/helpers/import-export/import/workers/openapi-import-worker.ts @@ -0,0 +1,53 @@ +import { Buffer } from "buffer" +import process from "process" + +// Set up global shims for the swagger-parser library +self.Buffer = Buffer +self.global = self +self.process = process + +import SwaggerParser from "@apidevtools/swagger-parser" +import * as E from "fp-ts/Either" + +const validateDocs = async (docs: any) => { + try { + const res = await SwaggerParser.validate(docs, { + // @ts-expect-error - this is a valid option, but seems like the types are not updated + continueOnError: true, + }) + + return E.right(res) + } catch (error) { + return E.left("COULD_NOT_VALIDATE" as const) + } +} + +const dereferenceDocs = async (docs: any) => { + try { + const res = await SwaggerParser.dereference(docs) + + return E.right(res) + } catch (error) { + return E.left("COULD_NOT_DEREFERENCE" as const) + } +} + +self.addEventListener("message", async (event) => { + if (event.data.type === "validate") { + const res = await validateDocs(event.data.docs) + + self.postMessage({ + type: "VALIDATION_RESULT", + data: res, + }) + } + + if (event.data.type === "dereference") { + const res = await dereferenceDocs(event.data.docs) + + self.postMessage({ + type: "DEREFERENCE_RESULT", + data: res, + }) + } +}) diff --git a/packages/hoppscotch-selfhost-web/vite.config.ts b/packages/hoppscotch-selfhost-web/vite.config.ts index a505938e..a052edba 100644 --- a/packages/hoppscotch-selfhost-web/vite.config.ts +++ b/packages/hoppscotch-selfhost-web/vite.config.ts @@ -27,6 +27,7 @@ export default defineConfig({ define: { // For 'util' polyfill required by dep of '@apidevtools/swagger-parser' "process.env": {}, + "process.platform": '"browser"', }, server: { port: 3000,