diff --git a/components/realtime/Log.vue b/components/realtime/Log.vue index a09fdf7ca..ef1bf74d0 100644 --- a/components/realtime/Log.vue +++ b/components/realtime/Log.vue @@ -17,14 +17,13 @@ {{ title }} -
+
{{ entry.ts }}{{ getSourcePrefix(entry.source) - }}{{ entry.payload }}{{ entry.ts }}{{ source(entry.source) }}{{ entry.payload }} {{ $t("response.waiting_for_connection") }} @@ -32,27 +31,14 @@
- diff --git a/components/realtime/Mqtt.vue b/components/realtime/Mqtt.vue index 9f1bb3b7b..5cc5f0b7f 100644 --- a/components/realtime/Mqtt.vue +++ b/components/realtime/Mqtt.vue @@ -145,7 +145,7 @@ import { defineComponent } from "@nuxtjs/composition-api" import { Splitpanes, Pane } from "splitpanes" import "splitpanes/dist/splitpanes.css" import Paho from "paho-mqtt" -import debounce from "~/helpers/utils/debounce" +import debounce from "lodash/debounce" import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics" import { useSetting } from "~/newstore/settings" import useWindowSize from "~/helpers/utils/useWindowSize" diff --git a/components/realtime/Socketio.vue b/components/realtime/Socketio.vue index e9e461aee..7d933e3bf 100644 --- a/components/realtime/Socketio.vue +++ b/components/realtime/Socketio.vue @@ -165,7 +165,7 @@ import { Splitpanes, Pane } from "splitpanes" import "splitpanes/dist/splitpanes.css" import { io as Client } from "socket.io-client" import wildcard from "socketio-wildcard" -import debounce from "~/helpers/utils/debounce" +import debounce from "lodash/debounce" import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics" import { useSetting } from "~/newstore/settings" import useWindowSize from "~/helpers/utils/useWindowSize" diff --git a/components/realtime/Sse.vue b/components/realtime/Sse.vue index 3d230dc38..ca78d4b1a 100644 --- a/components/realtime/Sse.vue +++ b/components/realtime/Sse.vue @@ -89,8 +89,8 @@ import { defineComponent } from "@nuxtjs/composition-api" import { Splitpanes, Pane } from "splitpanes" import "splitpanes/dist/splitpanes.css" +import debounce from "lodash/debounce" import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics" -import debounce from "~/helpers/utils/debounce" export default defineComponent({ components: { Splitpanes, Pane }, diff --git a/components/realtime/Websocket.vue b/components/realtime/Websocket.vue index 75220c973..2bacf97e5 100644 --- a/components/realtime/Websocket.vue +++ b/components/realtime/Websocket.vue @@ -205,8 +205,8 @@ import { defineComponent } from "@nuxtjs/composition-api" import { Splitpanes, Pane } from "splitpanes" import "splitpanes/dist/splitpanes.css" +import debounce from "lodash/debounce" import { logHoppRequestRunToAnalytics } from "~/helpers/fb/analytics" -import debounce from "~/helpers/utils/debounce" import useWindowSize from "~/helpers/utils/useWindowSize" import { useSetting } from "~/newstore/settings" diff --git a/helpers/lenses/htmlLens.js b/helpers/lenses/htmlLens.ts similarity index 62% rename from helpers/lenses/htmlLens.js rename to helpers/lenses/htmlLens.ts index 7a18570eb..8c4f9da65 100644 --- a/helpers/lenses/htmlLens.js +++ b/helpers/lenses/htmlLens.ts @@ -1,10 +1,12 @@ -const htmlLens = { +import { Lens } from "./lenses" + +const htmlLens: Lens = { lensName: "response.html", isSupportedContentType: (contentType) => /\btext\/html|application\/xhtml\+xml\b/i.test(contentType), renderer: "htmlres", rendererImport: () => - import("~/components/lenses/renderers/HTMLLensRenderer"), + import("~/components/lenses/renderers/HTMLLensRenderer.vue"), } export default htmlLens diff --git a/helpers/lenses/imageLens.js b/helpers/lenses/imageLens.ts similarity index 67% rename from helpers/lenses/imageLens.js rename to helpers/lenses/imageLens.ts index 2c49b38df..d08d204ad 100644 --- a/helpers/lenses/imageLens.js +++ b/helpers/lenses/imageLens.ts @@ -1,4 +1,6 @@ -const imageLens = { +import { Lens } from "./lenses" + +const imageLens: Lens = { lensName: "response.image", isSupportedContentType: (contentType) => /\bimage\/(?:gif|jpeg|png|bmp|svg\+xml|x-icon|vnd\.microsoft\.icon)\b/i.test( @@ -6,7 +8,7 @@ const imageLens = { ), renderer: "imageres", rendererImport: () => - import("~/components/lenses/renderers/ImageLensRenderer"), + import("~/components/lenses/renderers/ImageLensRenderer.vue"), } export default imageLens diff --git a/helpers/lenses/jsonLens.js b/helpers/lenses/jsonLens.ts similarity index 62% rename from helpers/lenses/jsonLens.js rename to helpers/lenses/jsonLens.ts index 1d9135a24..28ad97348 100644 --- a/helpers/lenses/jsonLens.js +++ b/helpers/lenses/jsonLens.ts @@ -1,11 +1,12 @@ import { isJSONContentType } from "../utils/contenttypes" +import { Lens } from "./lenses" -const jsonLens = { +const jsonLens: Lens = { lensName: "response.json", isSupportedContentType: isJSONContentType, renderer: "json", rendererImport: () => - import("~/components/lenses/renderers/JSONLensRenderer"), + import("~/components/lenses/renderers/JSONLensRenderer.vue"), } export default jsonLens diff --git a/helpers/lenses/lenses.js b/helpers/lenses/lenses.js deleted file mode 100644 index 674797fce..000000000 --- a/helpers/lenses/lenses.js +++ /dev/null @@ -1,28 +0,0 @@ -import jsonLens from "./jsonLens" -import rawLens from "./rawLens" -import imageLens from "./imageLens" -import htmlLens from "./htmlLens" -import xmlLens from "./xmlLens" - -export const lenses = [jsonLens, imageLens, htmlLens, xmlLens, rawLens] - -export function getSuitableLenses(response) { - const contentType = response.headers.find((h) => h.key === "content-type") - - if (!contentType) return [rawLens] - - const result = [] - for (const lens of lenses) { - if (lens.isSupportedContentType(contentType.value)) result.push(lens) - } - - return result -} - -export function getLensRenderers() { - const response = {} - for (const lens of lenses) { - response[lens.renderer] = lens.rendererImport - } - return response -} diff --git a/helpers/lenses/lenses.ts b/helpers/lenses/lenses.ts new file mode 100644 index 000000000..a6fe10728 --- /dev/null +++ b/helpers/lenses/lenses.ts @@ -0,0 +1,42 @@ +import { HoppRESTResponse } from "../types/HoppRESTResponse" +import jsonLens from "./jsonLens" +import rawLens from "./rawLens" +import imageLens from "./imageLens" +import htmlLens from "./htmlLens" +import xmlLens from "./xmlLens" + +export type Lens = { + lensName: string + isSupportedContentType: (contentType: string) => boolean + renderer: string + rendererImport: () => Promise +} + +export const lenses: Lens[] = [jsonLens, imageLens, htmlLens, xmlLens, rawLens] + +export function getSuitableLenses(response: HoppRESTResponse): Lens[] { + // return empty array if response is loading or error + if (response.type === "loading" || response.type === "network_fail") return [] + + const contentType = response.headers.find((h) => h.key === "content-type") + + if (!contentType) return [rawLens] + + const result = [] + for (const lens of lenses) { + if (lens.isSupportedContentType(contentType.value)) result.push(lens) + } + return result +} + +type LensRenderers = { + [key: string]: Lens["rendererImport"] +} + +export function getLensRenderers(): LensRenderers { + const response: LensRenderers = {} + for (const lens of lenses) { + response[lens.renderer] = lens.rendererImport + } + return response +} diff --git a/helpers/lenses/rawLens.js b/helpers/lenses/rawLens.js deleted file mode 100644 index f8a18e193..000000000 --- a/helpers/lenses/rawLens.js +++ /dev/null @@ -1,8 +0,0 @@ -const rawLens = { - lensName: "response.raw", - isSupportedContentType: () => true, - renderer: "raw", - rendererImport: () => import("~/components/lenses/renderers/RawLensRenderer"), -} - -export default rawLens diff --git a/helpers/lenses/rawLens.ts b/helpers/lenses/rawLens.ts new file mode 100644 index 000000000..ec3a7c64f --- /dev/null +++ b/helpers/lenses/rawLens.ts @@ -0,0 +1,11 @@ +import { Lens } from "./lenses" + +const rawLens: Lens = { + lensName: "response.raw", + isSupportedContentType: () => true, + renderer: "raw", + rendererImport: () => + import("~/components/lenses/renderers/RawLensRenderer.vue"), +} + +export default rawLens diff --git a/helpers/lenses/xmlLens.js b/helpers/lenses/xmlLens.ts similarity index 50% rename from helpers/lenses/xmlLens.js rename to helpers/lenses/xmlLens.ts index d393be5f2..2f126bbb7 100644 --- a/helpers/lenses/xmlLens.js +++ b/helpers/lenses/xmlLens.ts @@ -1,8 +1,11 @@ -const xmlLens = { +import { Lens } from "./lenses" + +const xmlLens: Lens = { lensName: "response.xml", isSupportedContentType: (contentType) => /\bxml\b/i.test(contentType), renderer: "xmlres", - rendererImport: () => import("~/components/lenses/renderers/XMLLensRenderer"), + rendererImport: () => + import("~/components/lenses/renderers/XMLLensRenderer.vue"), } export default xmlLens diff --git a/helpers/utils/StreamUtils.ts b/helpers/utils/StreamUtils.ts index fad17f58e..342e9b4b3 100644 --- a/helpers/utils/StreamUtils.ts +++ b/helpers/utils/StreamUtils.ts @@ -8,9 +8,9 @@ import { map } from "rxjs/operators" * * @returns The constructed object observable */ -export function constructFromStreams( - streamObj: { [key in keyof T]: Observable } -): Observable { +export function constructFromStreams(streamObj: { + [key in keyof T]: Observable +}): Observable { return combineLatest(Object.values>(streamObj)).pipe( map((streams) => { const keys = Object.keys(streamObj) as (keyof T)[] diff --git a/helpers/utils/__tests__/debounce.spec.js b/helpers/utils/__tests__/debounce.spec.js deleted file mode 100644 index 198c103d9..000000000 --- a/helpers/utils/__tests__/debounce.spec.js +++ /dev/null @@ -1,38 +0,0 @@ -import debounce from "../debounce" - -describe("debounce", () => { - test("doesn't call function right after calling", () => { - const fn = jest.fn() - - const debFunc = debounce(fn, 100) - debFunc() - - expect(fn).not.toHaveBeenCalled() - }) - - test("calls the function after the given timeout", () => { - const fn = jest.fn() - - jest.useFakeTimers() - - const debFunc = debounce(fn, 100) - debFunc() - - jest.runAllTimers() - - expect(fn).toHaveBeenCalled() - // expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 100) - }) - - test("calls the function only one time within the timeframe", () => { - const fn = jest.fn() - - const debFunc = debounce(fn, 1000) - - for (let i = 0; i < 100; i++) debFunc() - - jest.runAllTimers() - - expect(fn).toHaveBeenCalledTimes(1) - }) -}) diff --git a/helpers/utils/__tests__/uri.spec.js b/helpers/utils/__tests__/uri.spec.js deleted file mode 100644 index 1b1dcf5a0..000000000 --- a/helpers/utils/__tests__/uri.spec.js +++ /dev/null @@ -1,21 +0,0 @@ -import { parseUrlAndPath } from "../uri" - -describe("parseUrlAndPath", () => { - test("has url and path fields", () => { - const result = parseUrlAndPath("https://hoppscotch.io/") - - expect(result).toHaveProperty("url") - expect(result).toHaveProperty("path") - }) - - test("parses out URL correctly", () => { - const result = parseUrlAndPath("https://hoppscotch.io/test/page") - - expect(result.url).toBe("https://hoppscotch.io") - }) - test("parses out Path correctly", () => { - const result = parseUrlAndPath("https://hoppscotch.io/test/page") - - expect(result.path).toBe("/test/page") - }) -}) diff --git a/helpers/utils/b64.js b/helpers/utils/b64.ts similarity index 91% rename from helpers/utils/b64.js rename to helpers/utils/b64.ts index 942b003c4..3b364c0e9 100644 --- a/helpers/utils/b64.js +++ b/helpers/utils/b64.ts @@ -1,4 +1,4 @@ -export const decodeB64StringToArrayBuffer = (input) => { +export function decodeB64StringToArrayBuffer(input: string): ArrayBuffer { const bytes = Math.floor((input.length / 4) * 3) const ab = new ArrayBuffer(bytes) const uarray = new Uint8Array(ab) diff --git a/helpers/utils/debounce.js b/helpers/utils/debounce.js deleted file mode 100644 index 0db17993b..000000000 --- a/helpers/utils/debounce.js +++ /dev/null @@ -1,15 +0,0 @@ -// Debounce is a higher order function which makes its enclosed function be executed -// only if the function wasn't called again till 'delay' time has passed, this helps reduce impact of heavy working -// functions which might be called frequently -// NOTE : Don't use lambda functions as this doesn't get bound properly in them, use the 'function (args) {}' format -const debounce = (func, delay) => { - let inDebounce - return function () { - const context = this - const args = arguments - clearTimeout(inDebounce) - inDebounce = setTimeout(() => func.apply(context, args), delay) - } -} - -export default debounce diff --git a/helpers/utils/string.js b/helpers/utils/string.js deleted file mode 100644 index 6967e1c35..000000000 --- a/helpers/utils/string.js +++ /dev/null @@ -1,12 +0,0 @@ -export function getSourcePrefix(source) { - const sourceEmojis = { - // Source used for info messages. - info: "\tℹ️ [INFO]:\t", - // Source used for client to server messages. - client: "\t⬅️ [SENT]:\t", - // Source used for server to client messages. - server: "\t➡️ [RECEIVED]:\t", - } - if (Object.keys(sourceEmojis).includes(source)) return sourceEmojis[source] - return "" -} diff --git a/helpers/utils/string.ts b/helpers/utils/string.ts new file mode 100644 index 000000000..f23107591 --- /dev/null +++ b/helpers/utils/string.ts @@ -0,0 +1,12 @@ +const sourceEmojis = { + // Source used for info messages. + info: "\tℹ️ [INFO]:\t", + // Source used for client to server messages. + client: "\t⬅️ [SENT]:\t", + // Source used for server to client messages. + server: "\t➡️ [RECEIVED]:\t", +} + +export function getSourcePrefix(source: keyof typeof sourceEmojis) { + return sourceEmojis[source] +} diff --git a/helpers/utils/uri.js b/helpers/utils/uri.js deleted file mode 100644 index 69b57ee04..000000000 --- a/helpers/utils/uri.js +++ /dev/null @@ -1,15 +0,0 @@ -export function parseUrlAndPath(value) { - const result = {} - try { - const url = new URL(value) - result.url = url.origin - result.path = url.pathname - } catch (e) { - const uriRegex = value.match( - /^((http[s]?:\/\/)?(<<[^/]+>>)?[^/]*|)(\/?.*)$/ - ) - result.url = uriRegex[1] - result.path = uriRegex[4] - } - return result -}