import.vue 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. <template>
  2. <div></div>
  3. </template>
  4. <script setup lang="ts">
  5. import axios from "axios"
  6. import * as TO from "fp-ts/TaskOption"
  7. import * as TE from "fp-ts/TaskEither"
  8. import * as RA from "fp-ts/ReadonlyArray"
  9. import { useRoute, useRouter, onMounted } from "@nuxtjs/composition-api"
  10. import * as E from "fp-ts/Either"
  11. import { pipe } from "fp-ts/function"
  12. import { HoppRESTRequest, HoppCollection } from "@hoppscotch/data"
  13. import { appendRESTCollections } from "~/newstore/collections"
  14. import { useToast, useI18n } from "~/helpers/utils/composables"
  15. import { URLImporters } from "~/helpers/import-export/import/importers"
  16. import { IMPORTER_INVALID_FILE_FORMAT } from "~/helpers/import-export/import"
  17. import { OPENAPI_DEREF_ERROR } from "~/helpers/import-export/import/openapi"
  18. import { isOfType } from "~/helpers/functional/primtive"
  19. import { TELeftType } from "~/helpers/functional/taskEither"
  20. const route = useRoute()
  21. const router = useRouter()
  22. const toast = useToast()
  23. const t = useI18n()
  24. const IMPORTER_INVALID_TYPE = "importer_invalid_type" as const
  25. const IMPORTER_INVALID_FETCH = "importer_invalid_fetch" as const
  26. const importCollections = (url: unknown, type: unknown) =>
  27. pipe(
  28. TE.Do,
  29. TE.bind("importer", () =>
  30. pipe(
  31. URLImporters,
  32. RA.findFirst(
  33. (importer) =>
  34. importer.applicableTo.includes("url-import") && importer.id === type
  35. ),
  36. TE.fromOption(() => IMPORTER_INVALID_TYPE)
  37. )
  38. ),
  39. TE.bindW("content", () =>
  40. pipe(
  41. url,
  42. TO.fromPredicate(isOfType("string")),
  43. TO.chain(fetchUrlData),
  44. TE.fromTaskOption(() => IMPORTER_INVALID_FETCH)
  45. )
  46. ),
  47. TE.chainW(({ importer, content }) =>
  48. pipe(
  49. content.data,
  50. TO.fromPredicate(isOfType("string")),
  51. TE.fromTaskOption(() => IMPORTER_INVALID_FILE_FORMAT),
  52. TE.chain((data) => importer.importer([data]))
  53. )
  54. )
  55. )
  56. type ImportCollectionsError = TELeftType<ReturnType<typeof importCollections>>
  57. onMounted(async () => {
  58. const { query } = route.value
  59. const url = query.url
  60. const type = query.type
  61. const result = await importCollections(url, type)()
  62. pipe(result, E.fold(handleImportFailure, handleImportSuccess))
  63. router.replace("/")
  64. })
  65. const IMPORT_ERROR_MAP: Record<ImportCollectionsError, string> = {
  66. [IMPORTER_INVALID_TYPE]: "import.import_from_url_invalid_type",
  67. [IMPORTER_INVALID_FETCH]: "import.import_from_url_invalid_fetch",
  68. [IMPORTER_INVALID_FILE_FORMAT]: "import.import_from_url_invalid_file_format",
  69. [OPENAPI_DEREF_ERROR]: "import.import_from_url_invalid_file_format",
  70. } as const
  71. const handleImportFailure = (error: ImportCollectionsError) => {
  72. toast.error(t(IMPORT_ERROR_MAP[error]).toString())
  73. }
  74. const handleImportSuccess = (
  75. collections: HoppCollection<HoppRESTRequest>[]
  76. ) => {
  77. appendRESTCollections(collections)
  78. toast.success(t("import.import_from_url_success").toString())
  79. }
  80. const fetchUrlData = (url: string) =>
  81. TO.tryCatch(() =>
  82. axios.get(url, {
  83. responseType: "text",
  84. transitional: { forcedJSONParsing: false },
  85. })
  86. )
  87. </script>