Compare commits
96 Commits
orphan-pr/
...
reference/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6086ebd824 | ||
|
|
dd83f8ef24 | ||
|
|
682200ce68 | ||
|
|
052595c076 | ||
|
|
18910e429c | ||
|
|
924d6a87d0 | ||
|
|
fc15a5a1e4 | ||
|
|
477811c414 | ||
|
|
6b8ae63747 | ||
|
|
c013aa52ac | ||
|
|
631a16feb0 | ||
|
|
d0f4080771 | ||
|
|
0da75cb23d | ||
|
|
017cbb5a71 | ||
|
|
2e1ca0cbb0 | ||
|
|
abba09ea80 | ||
|
|
a9e1a3002e | ||
|
|
fb5967294b | ||
|
|
73fdfbd2c8 | ||
|
|
0c31d9201f | ||
|
|
21d8b8fb2e | ||
|
|
7ce85fee81 | ||
|
|
10615ca1a1 | ||
|
|
dd5c876e32 | ||
|
|
c2002f0f27 | ||
|
|
9cfba797f6 | ||
|
|
d1e6ffda49 | ||
|
|
4f71b163ea | ||
|
|
775bf9a9c3 | ||
|
|
33ecea5d75 | ||
|
|
551dfd1e20 | ||
|
|
8663934075 | ||
|
|
a73d64ddc1 | ||
|
|
99f119d262 | ||
|
|
6a8a687616 | ||
|
|
6a33083790 | ||
|
|
5c7c355d95 | ||
|
|
328fb1176d | ||
|
|
fdf0c95f9a | ||
|
|
9e90e703f7 | ||
|
|
0a241663ac | ||
|
|
d58fc42190 | ||
|
|
7a9bcd0a5c | ||
|
|
e3482f66cc | ||
|
|
186803a465 | ||
|
|
bdfdb44743 | ||
|
|
4f8b346024 | ||
|
|
ec1104396e | ||
|
|
630ab1f4f4 | ||
|
|
cabc775f58 | ||
|
|
f515ac4f52 | ||
|
|
11b8bb4571 | ||
|
|
7bf66d8339 | ||
|
|
8d81ff3dc2 | ||
|
|
5538b9a5b9 | ||
|
|
7077fe4621 | ||
|
|
42144b724b | ||
|
|
14183d8b91 | ||
|
|
f8e1d78824 | ||
|
|
1e8805ab4f | ||
|
|
a294a2804b | ||
|
|
8507278c40 | ||
|
|
d22bae2c60 | ||
|
|
2fefa55dce | ||
|
|
e0787d7fca | ||
|
|
c9c5df36ab | ||
|
|
5768274ef1 | ||
|
|
493594b5d7 | ||
|
|
56c96f952d | ||
|
|
2c06a66c0a | ||
|
|
1a26a0e986 | ||
|
|
9f1ee724b4 | ||
|
|
d28679de15 | ||
|
|
fa0e7f4785 | ||
|
|
e9576dd339 | ||
|
|
c8f62c4f04 | ||
|
|
8aa066e2ab | ||
|
|
a38e6cd427 | ||
|
|
c3ba45f875 | ||
|
|
9061511609 | ||
|
|
443e095775 | ||
|
|
09e6fb246a | ||
|
|
d335ac1d80 | ||
|
|
c0e3a2be0b | ||
|
|
722864da62 | ||
|
|
5413bc584a | ||
|
|
7006fa57e2 | ||
|
|
1a629a1219 | ||
|
|
9b60dc5f2d | ||
|
|
21021a3cd9 | ||
|
|
fd5db6c8c9 | ||
|
|
54a12ef6fa | ||
|
|
d035262e1a | ||
|
|
1ab54b0ce7 | ||
|
|
cac3abd2ab | ||
|
|
c34185dc4b |
@@ -84,7 +84,7 @@
|
|||||||
|
|
||||||
_Customized themes are synced with cloud / local session_
|
_Customized themes are synced with cloud / local session_
|
||||||
|
|
||||||
🔥 **PWA:** Install as a [PWA](https://developers.google.com/web/progressive-web-apps) on your device.
|
🔥 **PWA:** Install as a [PWA](https://web.dev/what-are-pwas/) on your device.
|
||||||
|
|
||||||
- Instant loading with Service Workers
|
- Instant loading with Service Workers
|
||||||
- Offline support
|
- Offline support
|
||||||
|
|||||||
@@ -6,21 +6,26 @@
|
|||||||
'!flex-row-reverse': SIDEBAR_ON_LEFT && mdAndLarger,
|
'!flex-row-reverse': SIDEBAR_ON_LEFT && mdAndLarger,
|
||||||
}"
|
}"
|
||||||
:horizontal="!mdAndLarger"
|
:horizontal="!mdAndLarger"
|
||||||
|
@resize="setPaneEvent($event, 'vertical')"
|
||||||
>
|
>
|
||||||
<Pane
|
<Pane
|
||||||
size="75"
|
:size="PANE_MAIN_SIZE"
|
||||||
min-size="65"
|
min-size="65"
|
||||||
class="hide-scrollbar !overflow-auto flex flex-col"
|
class="hide-scrollbar !overflow-auto flex flex-col"
|
||||||
>
|
>
|
||||||
<Splitpanes class="smart-splitter" :horizontal="COLUMN_LAYOUT">
|
<Splitpanes
|
||||||
|
class="smart-splitter"
|
||||||
|
:horizontal="COLUMN_LAYOUT"
|
||||||
|
@resize="setPaneEvent($event, 'horizontal')"
|
||||||
|
>
|
||||||
<Pane
|
<Pane
|
||||||
:size="COLUMN_LAYOUT ? 45 : 50"
|
:size="PANE_MAIN_TOP_SIZE"
|
||||||
class="hide-scrollbar !overflow-auto flex flex-col"
|
class="hide-scrollbar !overflow-auto flex flex-col"
|
||||||
>
|
>
|
||||||
<slot name="primary" />
|
<slot name="primary" />
|
||||||
</Pane>
|
</Pane>
|
||||||
<Pane
|
<Pane
|
||||||
:size="COLUMN_LAYOUT ? 65 : 50"
|
:size="PANE_MAIN_BOTTOM_SIZE"
|
||||||
class="flex flex-col hide-scrollbar !overflow-auto"
|
class="flex flex-col hide-scrollbar !overflow-auto"
|
||||||
>
|
>
|
||||||
<slot name="secondary" />
|
<slot name="secondary" />
|
||||||
@@ -29,7 +34,7 @@
|
|||||||
</Pane>
|
</Pane>
|
||||||
<Pane
|
<Pane
|
||||||
v-if="SIDEBAR && hasSidebar"
|
v-if="SIDEBAR && hasSidebar"
|
||||||
size="25"
|
:size="PANE_SIDEBAR_SIZE"
|
||||||
min-size="20"
|
min-size="20"
|
||||||
class="hide-scrollbar !overflow-auto flex flex-col"
|
class="hide-scrollbar !overflow-auto flex flex-col"
|
||||||
>
|
>
|
||||||
@@ -42,8 +47,9 @@
|
|||||||
import { Splitpanes, Pane } from "splitpanes"
|
import { Splitpanes, Pane } from "splitpanes"
|
||||||
import "splitpanes/dist/splitpanes.css"
|
import "splitpanes/dist/splitpanes.css"
|
||||||
import { breakpointsTailwind, useBreakpoints } from "@vueuse/core"
|
import { breakpointsTailwind, useBreakpoints } from "@vueuse/core"
|
||||||
import { computed, useSlots } from "@nuxtjs/composition-api"
|
import { computed, useSlots, ref } from "@nuxtjs/composition-api"
|
||||||
import { useSetting } from "~/newstore/settings"
|
import { useSetting } from "~/newstore/settings"
|
||||||
|
import { setLocalConfig, getLocalConfig } from "~/newstore/localpersistence"
|
||||||
|
|
||||||
const SIDEBAR_ON_LEFT = useSetting("SIDEBAR_ON_LEFT")
|
const SIDEBAR_ON_LEFT = useSetting("SIDEBAR_ON_LEFT")
|
||||||
|
|
||||||
@@ -57,4 +63,60 @@ const SIDEBAR = useSetting("SIDEBAR")
|
|||||||
const slots = useSlots()
|
const slots = useSlots()
|
||||||
|
|
||||||
const hasSidebar = computed(() => !!slots.sidebar)
|
const hasSidebar = computed(() => !!slots.sidebar)
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
layoutId: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
type PaneEvent = {
|
||||||
|
max: number
|
||||||
|
min: number
|
||||||
|
size: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const PANE_SIDEBAR_SIZE = ref(25)
|
||||||
|
const PANE_MAIN_SIZE = ref(75)
|
||||||
|
const PANE_MAIN_TOP_SIZE = ref(45)
|
||||||
|
const PANE_MAIN_BOTTOM_SIZE = ref(65)
|
||||||
|
|
||||||
|
if (!COLUMN_LAYOUT.value) {
|
||||||
|
PANE_MAIN_TOP_SIZE.value = 50
|
||||||
|
PANE_MAIN_BOTTOM_SIZE.value = 50
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPaneEvent(event: PaneEvent[], type: "vertical" | "horizontal") {
|
||||||
|
if (!props.layoutId) return
|
||||||
|
const storageKey = `${props.layoutId}-pane-config-${type}`
|
||||||
|
setLocalConfig(storageKey, JSON.stringify(event))
|
||||||
|
}
|
||||||
|
|
||||||
|
function populatePaneEvent() {
|
||||||
|
if (!props.layoutId) return
|
||||||
|
|
||||||
|
const verticalPaneData = getPaneData("vertical")
|
||||||
|
if (verticalPaneData) {
|
||||||
|
const [mainPane, sidebarPane] = verticalPaneData
|
||||||
|
PANE_MAIN_SIZE.value = mainPane?.size
|
||||||
|
PANE_SIDEBAR_SIZE.value = sidebarPane?.size
|
||||||
|
}
|
||||||
|
|
||||||
|
const horizontalPaneData = getPaneData("horizontal")
|
||||||
|
if (horizontalPaneData) {
|
||||||
|
const [mainTopPane, mainBottomPane] = horizontalPaneData
|
||||||
|
PANE_MAIN_TOP_SIZE.value = mainTopPane?.size
|
||||||
|
PANE_MAIN_BOTTOM_SIZE.value = mainBottomPane?.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPaneData(type: "vertical" | "horizontal"): PaneEvent[] | null {
|
||||||
|
const storageKey = `${props.layoutId}-pane-config-${type}`
|
||||||
|
const paneEvent = getLocalConfig(storageKey)
|
||||||
|
if (!paneEvent) return null
|
||||||
|
return JSON.parse(paneEvent)
|
||||||
|
}
|
||||||
|
|
||||||
|
populatePaneEvent()
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="show">
|
<div v-show="show">
|
||||||
<SmartTabs
|
<SmartTabs
|
||||||
:id="'collections_tab'"
|
:id="'collections_tab'"
|
||||||
v-model="selectedCollectionTab"
|
v-model="selectedCollectionTab"
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t('action.search')"
|
:placeholder="$t('action.search')"
|
||||||
class="py-2 pl-4 pr-2 bg-transparent"
|
class="py-2 pl-4 pr-2 bg-transparent"
|
||||||
|
:disabled="collectionsType.type == 'team-collections'"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<CollectionsChooseType
|
<CollectionsChooseType
|
||||||
|
|||||||
@@ -339,7 +339,14 @@ const selectRequest = () => {
|
|||||||
confirmChange.value = false
|
confirmChange.value = false
|
||||||
setRestReq(props.request)
|
setRestReq(props.request)
|
||||||
} else if (!active.value) {
|
} else if (!active.value) {
|
||||||
confirmChange.value = true
|
// If the current request is the same as the request to be loaded in, there is no data loss
|
||||||
|
const currentReq = getRESTRequest()
|
||||||
|
|
||||||
|
if (isEqualHoppRESTRequest(currentReq, props.request)) {
|
||||||
|
setRestReq(props.request)
|
||||||
|
} else {
|
||||||
|
confirmChange.value = true
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const currentReqWithNoChange = active.value.req
|
const currentReqWithNoChange = active.value.req
|
||||||
const currentFullReq = getRESTRequest()
|
const currentFullReq = getRESTRequest()
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ const active = useReadonlyStream(restSaveContext$, null)
|
|||||||
const isSelected = computed(
|
const isSelected = computed(
|
||||||
() =>
|
() =>
|
||||||
props.picked &&
|
props.picked &&
|
||||||
props.picked.pickedType === "teams-collection" &&
|
props.picked.pickedType === "teams-request" &&
|
||||||
props.picked.requestID === props.requestIndex
|
props.picked.requestID === props.requestIndex
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -312,7 +312,7 @@ const selectRequest = () => {
|
|||||||
if (props.saveRequest) {
|
if (props.saveRequest) {
|
||||||
emit("select", {
|
emit("select", {
|
||||||
picked: {
|
picked: {
|
||||||
pickedType: "teams-collection",
|
pickedType: "teams-request",
|
||||||
requestID: props.requestIndex,
|
requestID: props.requestIndex,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -50,18 +50,18 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="border rounded divide-y divide-dividerLight border-divider">
|
<div class="border rounded divide-y divide-dividerLight border-divider">
|
||||||
<div
|
<div
|
||||||
v-for="(variable, index) in vars"
|
v-for="({ id, env }, index) in vars"
|
||||||
:key="`variable-${index}`"
|
:key="`variable-${id}-${index}`"
|
||||||
class="flex divide-x divide-dividerLight"
|
class="flex divide-x divide-dividerLight"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
v-model="variable.key"
|
v-model="env.key"
|
||||||
class="flex flex-1 px-4 py-2 bg-transparent"
|
class="flex flex-1 px-4 py-2 bg-transparent"
|
||||||
:placeholder="`${t('count.variable', { count: index + 1 })}`"
|
:placeholder="`${t('count.variable', { count: index + 1 })}`"
|
||||||
:name="'param' + index"
|
:name="'param' + index"
|
||||||
/>
|
/>
|
||||||
<SmartEnvInput
|
<SmartEnvInput
|
||||||
v-model="variable.value"
|
v-model="env.value"
|
||||||
:placeholder="`${t('count.value', { count: index + 1 })}`"
|
:placeholder="`${t('count.value', { count: index + 1 })}`"
|
||||||
:envs="liveEnvs"
|
:envs="liveEnvs"
|
||||||
:name="'value' + index"
|
:name="'value' + index"
|
||||||
@@ -119,6 +119,9 @@
|
|||||||
import clone from "lodash/clone"
|
import clone from "lodash/clone"
|
||||||
import { computed, ref, watch } from "@nuxtjs/composition-api"
|
import { computed, ref, watch } from "@nuxtjs/composition-api"
|
||||||
import * as E from "fp-ts/Either"
|
import * as E from "fp-ts/Either"
|
||||||
|
import * as A from "fp-ts/Array"
|
||||||
|
import * as O from "fp-ts/Option"
|
||||||
|
import { pipe, flow } from "fp-ts/function"
|
||||||
import { Environment, parseTemplateStringE } from "@hoppscotch/data"
|
import { Environment, parseTemplateStringE } from "@hoppscotch/data"
|
||||||
import { refAutoReset } from "@vueuse/core"
|
import { refAutoReset } from "@vueuse/core"
|
||||||
import {
|
import {
|
||||||
@@ -137,6 +140,14 @@ import {
|
|||||||
useToast,
|
useToast,
|
||||||
} from "~/helpers/utils/composables"
|
} from "~/helpers/utils/composables"
|
||||||
|
|
||||||
|
type EnvironmentVariable = {
|
||||||
|
id: number
|
||||||
|
env: {
|
||||||
|
key: string
|
||||||
|
value: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
|
|
||||||
@@ -159,8 +170,12 @@ const emit = defineEmits<{
|
|||||||
(e: "hide-modal"): void
|
(e: "hide-modal"): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
const idTicker = ref(0)
|
||||||
|
|
||||||
const name = ref<string | null>(null)
|
const name = ref<string | null>(null)
|
||||||
const vars = ref([{ key: "", value: "" }])
|
const vars = ref<EnvironmentVariable[]>([
|
||||||
|
{ id: idTicker.value++, env: { key: "", value: "" } },
|
||||||
|
])
|
||||||
|
|
||||||
const clearIcon = refAutoReset<"trash-2" | "check">("trash-2", 1000)
|
const clearIcon = refAutoReset<"trash-2" | "check">("trash-2", 1000)
|
||||||
|
|
||||||
@@ -187,15 +202,15 @@ const workingEnv = computed(() => {
|
|||||||
const envList = useReadonlyStream(environments$, []) || props.envVars()
|
const envList = useReadonlyStream(environments$, []) || props.envVars()
|
||||||
|
|
||||||
const evnExpandError = computed(() => {
|
const evnExpandError = computed(() => {
|
||||||
for (const variable of vars.value) {
|
const variables = pipe(
|
||||||
const result = parseTemplateStringE(variable.value.toString(), vars.value)
|
vars.value,
|
||||||
|
A.map((e) => e.env)
|
||||||
|
)
|
||||||
|
|
||||||
if (E.isLeft(result)) {
|
return pipe(
|
||||||
console.error("error", result.left)
|
variables,
|
||||||
return true
|
A.exists(({ value }) => E.isLeft(parseTemplateStringE(value, variables)))
|
||||||
}
|
)
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const liveEnvs = computed(() => {
|
const liveEnvs = computed(() => {
|
||||||
@@ -218,21 +233,38 @@ watch(
|
|||||||
(show) => {
|
(show) => {
|
||||||
if (show) {
|
if (show) {
|
||||||
name.value = workingEnv.value?.name ?? null
|
name.value = workingEnv.value?.name ?? null
|
||||||
vars.value = clone(workingEnv.value?.variables ?? [])
|
vars.value = pipe(
|
||||||
|
workingEnv.value?.variables ?? [],
|
||||||
|
A.map((e) => ({
|
||||||
|
id: idTicker.value++,
|
||||||
|
env: clone(e),
|
||||||
|
}))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const clearContent = () => {
|
const clearContent = () => {
|
||||||
vars.value = []
|
vars.value = [
|
||||||
|
{
|
||||||
|
id: idTicker.value++,
|
||||||
|
env: {
|
||||||
|
key: "",
|
||||||
|
value: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
clearIcon.value = "check"
|
clearIcon.value = "check"
|
||||||
toast.success(`${t("state.cleared")}`)
|
toast.success(`${t("state.cleared")}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const addEnvironmentVariable = () => {
|
const addEnvironmentVariable = () => {
|
||||||
vars.value.push({
|
vars.value.push({
|
||||||
key: "",
|
id: idTicker.value++,
|
||||||
value: "",
|
env: {
|
||||||
|
key: "",
|
||||||
|
value: "",
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,9 +278,19 @@ const saveEnvironment = () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const filterdVariables = pipe(
|
||||||
|
vars.value,
|
||||||
|
A.filterMap(
|
||||||
|
flow(
|
||||||
|
O.fromPredicate((e) => e.env.key !== ""),
|
||||||
|
O.map((e) => e.env)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
const environmentUpdated: Environment = {
|
const environmentUpdated: Environment = {
|
||||||
name: name.value,
|
name: name.value,
|
||||||
variables: vars.value,
|
variables: filterdVariables,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.action === "new") {
|
if (props.action === "new") {
|
||||||
|
|||||||
@@ -1,363 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col flex-1">
|
<div>
|
||||||
<div
|
<HttpQueryParams />
|
||||||
class="sticky z-10 flex items-center justify-between pl-4 border-b bg-primary border-dividerLight top-upperMobileSecondaryStickyFold sm:top-upperSecondaryStickyFold"
|
<br />
|
||||||
>
|
<HttpPathVariables />
|
||||||
<label class="font-semibold text-secondaryLight">
|
|
||||||
{{ t("request.parameter_list") }}
|
|
||||||
</label>
|
|
||||||
<div class="flex">
|
|
||||||
<ButtonSecondary
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
to="https://docs.hoppscotch.io/features/parameters"
|
|
||||||
blank
|
|
||||||
:title="t('app.wiki')"
|
|
||||||
svg="help-circle"
|
|
||||||
/>
|
|
||||||
<ButtonSecondary
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
:title="t('action.clear_all')"
|
|
||||||
svg="trash-2"
|
|
||||||
@click.native="clearContent()"
|
|
||||||
/>
|
|
||||||
<ButtonSecondary
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
:title="t('state.bulk_mode')"
|
|
||||||
svg="edit"
|
|
||||||
:class="{ '!text-accent': bulkMode }"
|
|
||||||
@click.native="bulkMode = !bulkMode"
|
|
||||||
/>
|
|
||||||
<ButtonSecondary
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
:title="t('add.new')"
|
|
||||||
svg="plus"
|
|
||||||
:disabled="bulkMode"
|
|
||||||
@click.native="addParam"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-if="bulkMode" ref="bulkEditor" class="flex flex-col flex-1"></div>
|
|
||||||
<div v-else>
|
|
||||||
<draggable
|
|
||||||
v-model="workingParams"
|
|
||||||
animation="250"
|
|
||||||
handle=".draggable-handle"
|
|
||||||
draggable=".draggable-content"
|
|
||||||
ghost-class="cursor-move"
|
|
||||||
chosen-class="bg-primaryLight"
|
|
||||||
drag-class="cursor-grabbing"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
v-for="(param, index) in workingParams"
|
|
||||||
:key="`param-${param.id}-${index}`"
|
|
||||||
class="flex border-b divide-x divide-dividerLight border-dividerLight draggable-content group"
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
<ButtonSecondary
|
|
||||||
svg="grip-vertical"
|
|
||||||
class="cursor-auto text-primary hover:text-primary"
|
|
||||||
:class="{
|
|
||||||
'draggable-handle group-hover:text-secondaryLight !cursor-grab':
|
|
||||||
index !== workingParams?.length - 1,
|
|
||||||
}"
|
|
||||||
tabindex="-1"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
<SmartEnvInput
|
|
||||||
v-model="param.key"
|
|
||||||
:placeholder="`${t('count.parameter', { count: index + 1 })}`"
|
|
||||||
@change="
|
|
||||||
updateParam(index, {
|
|
||||||
id: param.id,
|
|
||||||
key: $event,
|
|
||||||
value: param.value,
|
|
||||||
active: param.active,
|
|
||||||
})
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<SmartEnvInput
|
|
||||||
v-model="param.value"
|
|
||||||
:placeholder="`${t('count.value', { count: index + 1 })}`"
|
|
||||||
@change="
|
|
||||||
updateParam(index, {
|
|
||||||
id: param.id,
|
|
||||||
key: param.key,
|
|
||||||
value: $event,
|
|
||||||
active: param.active,
|
|
||||||
})
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<span>
|
|
||||||
<ButtonSecondary
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
:title="
|
|
||||||
param.hasOwnProperty('active')
|
|
||||||
? param.active
|
|
||||||
? t('action.turn_off')
|
|
||||||
: t('action.turn_on')
|
|
||||||
: t('action.turn_off')
|
|
||||||
"
|
|
||||||
:svg="
|
|
||||||
param.hasOwnProperty('active')
|
|
||||||
? param.active
|
|
||||||
? 'check-circle'
|
|
||||||
: 'circle'
|
|
||||||
: 'check-circle'
|
|
||||||
"
|
|
||||||
color="green"
|
|
||||||
@click.native="
|
|
||||||
updateParam(index, {
|
|
||||||
id: param.id,
|
|
||||||
key: param.key,
|
|
||||||
value: param.value,
|
|
||||||
active: param.hasOwnProperty('active')
|
|
||||||
? !param.active
|
|
||||||
: false,
|
|
||||||
})
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
<ButtonSecondary
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
:title="t('action.remove')"
|
|
||||||
svg="trash"
|
|
||||||
color="red"
|
|
||||||
@click.native="deleteParam(index)"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</draggable>
|
|
||||||
<div
|
|
||||||
v-if="workingParams.length === 0"
|
|
||||||
class="flex flex-col items-center justify-center p-4 text-secondaryLight"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
:src="`/images/states/${$colorMode.value}/add_files.svg`"
|
|
||||||
loading="lazy"
|
|
||||||
class="inline-flex flex-col object-contain object-center w-16 h-16 my-4"
|
|
||||||
:alt="`${t('empty.parameters')}`"
|
|
||||||
/>
|
|
||||||
<span class="pb-4 text-center">{{ t("empty.parameters") }}</span>
|
|
||||||
<ButtonSecondary
|
|
||||||
:label="`${t('add.new')}`"
|
|
||||||
svg="plus"
|
|
||||||
filled
|
|
||||||
class="mb-4"
|
|
||||||
@click.native="addParam"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Ref, ref, watch } from "@nuxtjs/composition-api"
|
/**
|
||||||
import { flow, pipe } from "fp-ts/function"
|
* TODO: Code duplication between QueryParams and Variables
|
||||||
import * as O from "fp-ts/Option"
|
*/
|
||||||
import * as A from "fp-ts/Array"
|
|
||||||
import * as RA from "fp-ts/ReadonlyArray"
|
|
||||||
import * as E from "fp-ts/Either"
|
|
||||||
import {
|
|
||||||
HoppRESTParam,
|
|
||||||
parseRawKeyValueEntriesE,
|
|
||||||
rawKeyValueEntriesToString,
|
|
||||||
RawKeyValueEntry,
|
|
||||||
} from "@hoppscotch/data"
|
|
||||||
import isEqual from "lodash/isEqual"
|
|
||||||
import cloneDeep from "lodash/cloneDeep"
|
|
||||||
import draggable from "vuedraggable"
|
|
||||||
import linter from "~/helpers/editor/linting/rawKeyValue"
|
|
||||||
import { useCodemirror } from "~/helpers/editor/codemirror"
|
|
||||||
import { useI18n, useToast, useStream } from "~/helpers/utils/composables"
|
|
||||||
import { restParams$, setRESTParams } from "~/newstore/RESTSession"
|
|
||||||
import { throwError } from "~/helpers/functional/error"
|
|
||||||
import { objRemoveKey } from "~/helpers/functional/object"
|
|
||||||
|
|
||||||
const t = useI18n()
|
|
||||||
const toast = useToast()
|
|
||||||
|
|
||||||
const idTicker = ref(0)
|
|
||||||
|
|
||||||
const bulkMode = ref(false)
|
|
||||||
const bulkParams = ref("")
|
|
||||||
const bulkEditor = ref<any | null>(null)
|
|
||||||
|
|
||||||
const deletionToast = ref<{ goAway: (delay: number) => void } | null>(null)
|
|
||||||
|
|
||||||
useCodemirror(bulkEditor, bulkParams, {
|
|
||||||
extendedEditorConfig: {
|
|
||||||
mode: "text/x-yaml",
|
|
||||||
placeholder: `${t("state.bulk_mode_placeholder")}`,
|
|
||||||
},
|
|
||||||
linter,
|
|
||||||
completer: null,
|
|
||||||
environmentHighlights: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
// The functional parameters list (the parameters actually applied to the session)
|
|
||||||
const params = useStream(restParams$, [], setRESTParams) as Ref<HoppRESTParam[]>
|
|
||||||
|
|
||||||
// The UI representation of the parameters list (has the empty end param)
|
|
||||||
const workingParams = ref<Array<HoppRESTParam & { id: number }>>([
|
|
||||||
{
|
|
||||||
id: idTicker.value++,
|
|
||||||
key: "",
|
|
||||||
value: "",
|
|
||||||
active: true,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
// Rule: Working Params always have last element is always an empty param
|
|
||||||
watch(workingParams, (paramsList) => {
|
|
||||||
if (paramsList.length > 0 && paramsList[paramsList.length - 1].key !== "") {
|
|
||||||
workingParams.value.push({
|
|
||||||
id: idTicker.value++,
|
|
||||||
key: "",
|
|
||||||
value: "",
|
|
||||||
active: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Sync logic between params and working/bulk params
|
|
||||||
watch(
|
|
||||||
params,
|
|
||||||
(newParamsList) => {
|
|
||||||
// Sync should overwrite working params
|
|
||||||
const filteredWorkingParams: HoppRESTParam[] = pipe(
|
|
||||||
workingParams.value,
|
|
||||||
A.filterMap(
|
|
||||||
flow(
|
|
||||||
O.fromPredicate((e) => e.key !== ""),
|
|
||||||
O.map(objRemoveKey("id"))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
const filteredBulkParams = pipe(
|
|
||||||
parseRawKeyValueEntriesE(bulkParams.value),
|
|
||||||
E.map(
|
|
||||||
flow(
|
|
||||||
RA.filter((e) => e.key !== ""),
|
|
||||||
RA.toArray
|
|
||||||
)
|
|
||||||
),
|
|
||||||
E.getOrElse(() => [] as RawKeyValueEntry[])
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!isEqual(newParamsList, filteredWorkingParams)) {
|
|
||||||
workingParams.value = pipe(
|
|
||||||
newParamsList,
|
|
||||||
A.map((x) => ({ id: idTicker.value++, ...x }))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isEqual(newParamsList, filteredBulkParams)) {
|
|
||||||
bulkParams.value = rawKeyValueEntriesToString(newParamsList)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ immediate: true }
|
|
||||||
)
|
|
||||||
|
|
||||||
watch(workingParams, (newWorkingParams) => {
|
|
||||||
const fixedParams = pipe(
|
|
||||||
newWorkingParams,
|
|
||||||
A.filterMap(
|
|
||||||
flow(
|
|
||||||
O.fromPredicate((e) => e.key !== ""),
|
|
||||||
O.map(objRemoveKey("id"))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!isEqual(params.value, fixedParams)) {
|
|
||||||
params.value = cloneDeep(fixedParams)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
watch(bulkParams, (newBulkParams) => {
|
|
||||||
const filteredBulkParams = pipe(
|
|
||||||
parseRawKeyValueEntriesE(newBulkParams),
|
|
||||||
E.map(
|
|
||||||
flow(
|
|
||||||
RA.filter((e) => e.key !== ""),
|
|
||||||
RA.toArray
|
|
||||||
)
|
|
||||||
),
|
|
||||||
E.getOrElse(() => [] as RawKeyValueEntry[])
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!isEqual(params.value, filteredBulkParams)) {
|
|
||||||
params.value = filteredBulkParams
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const addParam = () => {
|
|
||||||
workingParams.value.push({
|
|
||||||
id: idTicker.value++,
|
|
||||||
key: "",
|
|
||||||
value: "",
|
|
||||||
active: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const updateParam = (index: number, param: HoppRESTParam & { id: number }) => {
|
|
||||||
workingParams.value = workingParams.value.map((h, i) =>
|
|
||||||
i === index ? param : h
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const deleteParam = (index: number) => {
|
|
||||||
const paramsBeforeDeletion = cloneDeep(workingParams.value)
|
|
||||||
|
|
||||||
if (
|
|
||||||
!(
|
|
||||||
paramsBeforeDeletion.length > 0 &&
|
|
||||||
index === paramsBeforeDeletion.length - 1
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
if (deletionToast.value) {
|
|
||||||
deletionToast.value.goAway(0)
|
|
||||||
deletionToast.value = null
|
|
||||||
}
|
|
||||||
|
|
||||||
deletionToast.value = toast.success(`${t("state.deleted")}`, {
|
|
||||||
action: [
|
|
||||||
{
|
|
||||||
text: `${t("action.undo")}`,
|
|
||||||
onClick: (_, toastObject) => {
|
|
||||||
workingParams.value = paramsBeforeDeletion
|
|
||||||
toastObject.goAway(0)
|
|
||||||
deletionToast.value = null
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
onComplete: () => {
|
|
||||||
deletionToast.value = null
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
workingParams.value = pipe(
|
|
||||||
workingParams.value,
|
|
||||||
A.deleteAt(index),
|
|
||||||
O.getOrElseW(() => throwError("Working Params Deletion Out of Bounds"))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const clearContent = () => {
|
|
||||||
// set params list to the initial state
|
|
||||||
workingParams.value = [
|
|
||||||
{
|
|
||||||
id: idTicker.value++,
|
|
||||||
key: "",
|
|
||||||
value: "",
|
|
||||||
active: true,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
bulkParams.value = ""
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
271
packages/hoppscotch-app/components/http/PathVariables.vue
Normal file
271
packages/hoppscotch-app/components/http/PathVariables.vue
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
v-if="envExpandError"
|
||||||
|
class="w-full px-4 py-2 mb-2 overflow-auto font-mono text-red-400 whitespace-normal rounded bg-primaryLight"
|
||||||
|
>
|
||||||
|
{{ nestedVars }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="sticky z-10 flex items-center justify-between pl-4 border-b bg-primary border-dividerLight top-upperMobileSecondaryStickyFold sm:top-upperSecondaryStickyFold"
|
||||||
|
>
|
||||||
|
<label class="font-semibold text-secondaryLight"> My Variables </label>
|
||||||
|
<div class="flex">
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
to="https://docs.hoppscotch.io/features/#"
|
||||||
|
blank
|
||||||
|
:title="t('app.wiki')"
|
||||||
|
svg="help-circle"
|
||||||
|
/>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="t('action.clear_all')"
|
||||||
|
svg="trash-2"
|
||||||
|
@click.native="clearContent()"
|
||||||
|
/>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="t('add.new')"
|
||||||
|
svg="plus"
|
||||||
|
@click.native="addVar"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<draggable
|
||||||
|
v-model="workingVars"
|
||||||
|
animation="250"
|
||||||
|
handle=".draggable-handle"
|
||||||
|
draggable=".draggable-content"
|
||||||
|
ghost-class="cursor-move"
|
||||||
|
chosen-class="bg-primaryLight"
|
||||||
|
drag-class="cursor-grabbing"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="(variable, index) in workingVars"
|
||||||
|
:key="`vari-${variable.id}-${index}`"
|
||||||
|
class="flex border-b divide-x divide-dividerLight border-dividerLight draggable-content group"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
<ButtonSecondary
|
||||||
|
svg="grip-vertical"
|
||||||
|
class="cursor-auto text-primary hover:text-primary"
|
||||||
|
:class="{
|
||||||
|
'draggable-handle group-hover:text-secondaryLight !cursor-grab':
|
||||||
|
index !== workingVars?.length - 1,
|
||||||
|
}"
|
||||||
|
tabindex="-1"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<SmartEnvInput
|
||||||
|
v-model="variable.key"
|
||||||
|
:placeholder="`${t('count.variable', { count: index + 1 })}`"
|
||||||
|
@change="
|
||||||
|
updateVar(index, {
|
||||||
|
id: variable.id,
|
||||||
|
key: $event,
|
||||||
|
value: variable.value,
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<SmartEnvInput
|
||||||
|
v-model="variable.value"
|
||||||
|
:placeholder="`${t('count.value', { count: index + 1 })}`"
|
||||||
|
@change="
|
||||||
|
updateVar(index, {
|
||||||
|
id: variable.id,
|
||||||
|
key: variable.key,
|
||||||
|
value: $event,
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<span>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="t('action.remove')"
|
||||||
|
svg="trash"
|
||||||
|
color="red"
|
||||||
|
@click.native="deleteVar(index)"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</draggable>
|
||||||
|
<div
|
||||||
|
v-if="workingVars.length === 0"
|
||||||
|
class="flex flex-col items-center justify-center p-4 text-secondaryLight"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
:src="`/images/states/${$colorMode.value}/add_files.svg`"
|
||||||
|
loading="lazy"
|
||||||
|
class="inline-flex flex-col object-contain object-center w-16 h-16 my-4"
|
||||||
|
:alt="`${t('empty.parameters')}`"
|
||||||
|
/>
|
||||||
|
<span class="pb-4 text-center">{{ emptyVars }}</span>
|
||||||
|
<ButtonSecondary
|
||||||
|
:label="`${t('add.new')}`"
|
||||||
|
svg="plus"
|
||||||
|
filled
|
||||||
|
class="mb-4"
|
||||||
|
@click.native="addVar"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, Ref, ref, watch } from "@nuxtjs/composition-api"
|
||||||
|
import { flow, pipe } from "fp-ts/function"
|
||||||
|
import * as O from "fp-ts/Option"
|
||||||
|
import * as A from "fp-ts/Array"
|
||||||
|
import { HoppRESTVar, parseMyVariablesString } from "@hoppscotch/data"
|
||||||
|
import draggable from "vuedraggable"
|
||||||
|
import cloneDeep from "lodash/cloneDeep"
|
||||||
|
import isEqual from "lodash/isEqual"
|
||||||
|
import * as E from "fp-ts/Either"
|
||||||
|
import { useI18n, useStream, useToast } from "~/helpers/utils/composables"
|
||||||
|
import { throwError } from "~/helpers/functional/error"
|
||||||
|
import { restVars$, setRESTVars } from "~/newstore/RESTSession"
|
||||||
|
import { objRemoveKey } from "~/helpers/functional/object"
|
||||||
|
|
||||||
|
const t = useI18n()
|
||||||
|
const toast = useToast()
|
||||||
|
|
||||||
|
const emptyVars: string = "Add a new variable"
|
||||||
|
const nestedVars: string = "nested variables greater than 10 levels"
|
||||||
|
|
||||||
|
const idTicker = ref(0)
|
||||||
|
|
||||||
|
const deletionToast = ref<{ goAway: (delay: number) => void } | null>(null)
|
||||||
|
|
||||||
|
// The functional variables list (the variables actually applied to the session)
|
||||||
|
const vars = useStream(restVars$, [], setRESTVars) as Ref<HoppRESTVar[]>
|
||||||
|
|
||||||
|
// The UI representation of the variables list (has the empty end variable)
|
||||||
|
const workingVars = ref<Array<HoppRESTVar & { id: number }>>([
|
||||||
|
{
|
||||||
|
id: idTicker.value++,
|
||||||
|
key: "",
|
||||||
|
value: "",
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
// Rule: Working vars always have last element is always an empty var
|
||||||
|
watch(workingVars, (varsList) => {
|
||||||
|
if (varsList.length > 0 && varsList[varsList.length - 1].key !== "") {
|
||||||
|
workingVars.value.push({
|
||||||
|
id: idTicker.value++,
|
||||||
|
key: "",
|
||||||
|
value: "",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Sync logic between params and working/bulk params
|
||||||
|
watch(
|
||||||
|
vars,
|
||||||
|
(newVarsList) => {
|
||||||
|
// Sync should overwrite working params
|
||||||
|
const filteredWorkingVars: HoppRESTVar[] = pipe(
|
||||||
|
workingVars.value,
|
||||||
|
A.filterMap(
|
||||||
|
flow(
|
||||||
|
O.fromPredicate((e) => e.key !== ""),
|
||||||
|
O.map(objRemoveKey("id"))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!isEqual(newVarsList, filteredWorkingVars)) {
|
||||||
|
workingVars.value = pipe(
|
||||||
|
newVarsList,
|
||||||
|
A.map((x) => ({ id: idTicker.value++, ...x }))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(workingVars, (newWorkingVars) => {
|
||||||
|
const fixedVars = pipe(
|
||||||
|
newWorkingVars,
|
||||||
|
A.filterMap(
|
||||||
|
flow(
|
||||||
|
O.fromPredicate((e) => e.key !== ""),
|
||||||
|
O.map(objRemoveKey("id"))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if (!isEqual(vars.value, fixedVars)) {
|
||||||
|
vars.value = cloneDeep(fixedVars)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const addVar = () => {
|
||||||
|
workingVars.value.push({
|
||||||
|
id: idTicker.value++,
|
||||||
|
key: "",
|
||||||
|
value: "",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateVar = (index: number, vari: HoppRESTVar & { id: number }) => {
|
||||||
|
workingVars.value = workingVars.value.map((h, i) => (i === index ? vari : h))
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteVar = (index: number) => {
|
||||||
|
const varsBeforeDeletion = cloneDeep(workingVars.value)
|
||||||
|
if (
|
||||||
|
!(varsBeforeDeletion.length > 0 && index === varsBeforeDeletion.length - 1)
|
||||||
|
) {
|
||||||
|
if (deletionToast.value) {
|
||||||
|
deletionToast.value.goAway(0)
|
||||||
|
deletionToast.value = null
|
||||||
|
}
|
||||||
|
|
||||||
|
deletionToast.value = toast.success(`${t("state.deleted")}`, {
|
||||||
|
action: [
|
||||||
|
{
|
||||||
|
text: `${t("action.undo")}`,
|
||||||
|
onClick: (_, toastObject) => {
|
||||||
|
workingVars.value = varsBeforeDeletion
|
||||||
|
toastObject.goAway(0)
|
||||||
|
deletionToast.value = null
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
onComplete: () => {
|
||||||
|
deletionToast.value = null
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
workingVars.value = pipe(
|
||||||
|
workingVars.value,
|
||||||
|
A.deleteAt(index),
|
||||||
|
O.getOrElseW(() => throwError("Working Params Deletion Out of Bounds"))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const envExpandError = computed(() => {
|
||||||
|
const variables = pipe(vars.value)
|
||||||
|
|
||||||
|
return pipe(
|
||||||
|
variables,
|
||||||
|
A.exists(({ value }) => E.isLeft(parseMyVariablesString(value, variables)))
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const clearContent = () => {
|
||||||
|
// set params list to the initial state
|
||||||
|
workingVars.value = [
|
||||||
|
{
|
||||||
|
id: idTicker.value++,
|
||||||
|
key: "",
|
||||||
|
value: "",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
</script>
|
||||||
363
packages/hoppscotch-app/components/http/QueryParams.vue
Normal file
363
packages/hoppscotch-app/components/http/QueryParams.vue
Normal file
@@ -0,0 +1,363 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex flex-col flex-1">
|
||||||
|
<div
|
||||||
|
class="sticky z-10 flex items-center justify-between pl-4 border-b bg-primary border-dividerLight top-upperMobileSecondaryStickyFold sm:top-upperSecondaryStickyFold"
|
||||||
|
>
|
||||||
|
<label class="font-semibold text-secondaryLight">
|
||||||
|
{{ t("request.parameter_list") }}
|
||||||
|
</label>
|
||||||
|
<div class="flex">
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
to="https://docs.hoppscotch.io/features/parameters"
|
||||||
|
blank
|
||||||
|
:title="t('app.wiki')"
|
||||||
|
svg="help-circle"
|
||||||
|
/>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="t('action.clear_all')"
|
||||||
|
svg="trash-2"
|
||||||
|
@click.native="clearContent()"
|
||||||
|
/>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="t('state.bulk_mode')"
|
||||||
|
svg="edit"
|
||||||
|
:class="{ '!text-accent': bulkMode }"
|
||||||
|
@click.native="bulkMode = !bulkMode"
|
||||||
|
/>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="t('add.new')"
|
||||||
|
svg="plus"
|
||||||
|
:disabled="bulkMode"
|
||||||
|
@click.native="addParam"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="bulkMode" ref="bulkEditor" class="flex flex-col flex-1"></div>
|
||||||
|
<div v-else>
|
||||||
|
<draggable
|
||||||
|
v-model="workingParams"
|
||||||
|
animation="250"
|
||||||
|
handle=".draggable-handle"
|
||||||
|
draggable=".draggable-content"
|
||||||
|
ghost-class="cursor-move"
|
||||||
|
chosen-class="bg-primaryLight"
|
||||||
|
drag-class="cursor-grabbing"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="(param, index) in workingParams"
|
||||||
|
:key="`param-${param.id}-${index}`"
|
||||||
|
class="flex border-b divide-x divide-dividerLight border-dividerLight draggable-content group"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
<ButtonSecondary
|
||||||
|
svg="grip-vertical"
|
||||||
|
class="cursor-auto text-primary hover:text-primary"
|
||||||
|
:class="{
|
||||||
|
'draggable-handle group-hover:text-secondaryLight !cursor-grab':
|
||||||
|
index !== workingParams?.length - 1,
|
||||||
|
}"
|
||||||
|
tabindex="-1"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<SmartEnvInput
|
||||||
|
v-model="param.key"
|
||||||
|
:placeholder="`${t('count.parameter', { count: index + 1 })}`"
|
||||||
|
@change="
|
||||||
|
updateParam(index, {
|
||||||
|
id: param.id,
|
||||||
|
key: $event,
|
||||||
|
value: param.value,
|
||||||
|
active: param.active,
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<SmartEnvInput
|
||||||
|
v-model="param.value"
|
||||||
|
:placeholder="`${t('count.value', { count: index + 1 })}`"
|
||||||
|
@change="
|
||||||
|
updateParam(index, {
|
||||||
|
id: param.id,
|
||||||
|
key: param.key,
|
||||||
|
value: $event,
|
||||||
|
active: param.active,
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<span>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="
|
||||||
|
param.hasOwnProperty('active')
|
||||||
|
? param.active
|
||||||
|
? t('action.turn_off')
|
||||||
|
: t('action.turn_on')
|
||||||
|
: t('action.turn_off')
|
||||||
|
"
|
||||||
|
:svg="
|
||||||
|
param.hasOwnProperty('active')
|
||||||
|
? param.active
|
||||||
|
? 'check-circle'
|
||||||
|
: 'circle'
|
||||||
|
: 'check-circle'
|
||||||
|
"
|
||||||
|
color="green"
|
||||||
|
@click.native="
|
||||||
|
updateParam(index, {
|
||||||
|
id: param.id,
|
||||||
|
key: param.key,
|
||||||
|
value: param.value,
|
||||||
|
active: param.hasOwnProperty('active')
|
||||||
|
? !param.active
|
||||||
|
: false,
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="t('action.remove')"
|
||||||
|
svg="trash"
|
||||||
|
color="red"
|
||||||
|
@click.native="deleteParam(index)"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</draggable>
|
||||||
|
<div
|
||||||
|
v-if="workingParams.length === 0"
|
||||||
|
class="flex flex-col items-center justify-center p-4 text-secondaryLight"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
:src="`/images/states/${$colorMode.value}/add_files.svg`"
|
||||||
|
loading="lazy"
|
||||||
|
class="inline-flex flex-col object-contain object-center w-16 h-16 my-4"
|
||||||
|
:alt="`${t('empty.parameters')}`"
|
||||||
|
/>
|
||||||
|
<span class="pb-4 text-center">{{ t("empty.parameters") }}</span>
|
||||||
|
<ButtonSecondary
|
||||||
|
:label="`${t('add.new')}`"
|
||||||
|
svg="plus"
|
||||||
|
filled
|
||||||
|
class="mb-4"
|
||||||
|
@click.native="addParam"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Ref, ref, watch } from "@nuxtjs/composition-api"
|
||||||
|
import { flow, pipe } from "fp-ts/function"
|
||||||
|
import * as O from "fp-ts/Option"
|
||||||
|
import * as A from "fp-ts/Array"
|
||||||
|
import * as RA from "fp-ts/ReadonlyArray"
|
||||||
|
import * as E from "fp-ts/Either"
|
||||||
|
import {
|
||||||
|
HoppRESTParam,
|
||||||
|
parseRawKeyValueEntriesE,
|
||||||
|
rawKeyValueEntriesToString,
|
||||||
|
RawKeyValueEntry,
|
||||||
|
} from "@hoppscotch/data"
|
||||||
|
import isEqual from "lodash/isEqual"
|
||||||
|
import cloneDeep from "lodash/cloneDeep"
|
||||||
|
import draggable from "vuedraggable"
|
||||||
|
import linter from "~/helpers/editor/linting/rawKeyValue"
|
||||||
|
import { useCodemirror } from "~/helpers/editor/codemirror"
|
||||||
|
import { useI18n, useToast, useStream } from "~/helpers/utils/composables"
|
||||||
|
import { restParams$, setRESTParams } from "~/newstore/RESTSession"
|
||||||
|
import { throwError } from "~/helpers/functional/error"
|
||||||
|
import { objRemoveKey } from "~/helpers/functional/object"
|
||||||
|
|
||||||
|
const t = useI18n()
|
||||||
|
const toast = useToast()
|
||||||
|
|
||||||
|
const idTicker = ref(0)
|
||||||
|
|
||||||
|
const bulkMode = ref(false)
|
||||||
|
const bulkParams = ref("")
|
||||||
|
const bulkEditor = ref<any | null>(null)
|
||||||
|
|
||||||
|
const deletionToast = ref<{ goAway: (delay: number) => void } | null>(null)
|
||||||
|
|
||||||
|
useCodemirror(bulkEditor, bulkParams, {
|
||||||
|
extendedEditorConfig: {
|
||||||
|
mode: "text/x-yaml",
|
||||||
|
placeholder: `${t("state.bulk_mode_placeholder")}`,
|
||||||
|
},
|
||||||
|
linter,
|
||||||
|
completer: null,
|
||||||
|
environmentHighlights: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
// The functional parameters list (the parameters actually applied to the session)
|
||||||
|
const params = useStream(restParams$, [], setRESTParams) as Ref<HoppRESTParam[]>
|
||||||
|
|
||||||
|
// The UI representation of the parameters list (has the empty end param)
|
||||||
|
const workingParams = ref<Array<HoppRESTParam & { id: number }>>([
|
||||||
|
{
|
||||||
|
id: idTicker.value++,
|
||||||
|
key: "",
|
||||||
|
value: "",
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
// Rule: Working Params always have last element is always an empty param
|
||||||
|
watch(workingParams, (paramsList) => {
|
||||||
|
if (paramsList.length > 0 && paramsList[paramsList.length - 1].key !== "") {
|
||||||
|
workingParams.value.push({
|
||||||
|
id: idTicker.value++,
|
||||||
|
key: "",
|
||||||
|
value: "",
|
||||||
|
active: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Sync logic between params and working/bulk params
|
||||||
|
watch(
|
||||||
|
params,
|
||||||
|
(newParamsList) => {
|
||||||
|
// Sync should overwrite working params
|
||||||
|
const filteredWorkingParams: HoppRESTParam[] = pipe(
|
||||||
|
workingParams.value,
|
||||||
|
A.filterMap(
|
||||||
|
flow(
|
||||||
|
O.fromPredicate((e) => e.key !== ""),
|
||||||
|
O.map(objRemoveKey("id"))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
const filteredBulkParams = pipe(
|
||||||
|
parseRawKeyValueEntriesE(bulkParams.value),
|
||||||
|
E.map(
|
||||||
|
flow(
|
||||||
|
RA.filter((e) => e.key !== ""),
|
||||||
|
RA.toArray
|
||||||
|
)
|
||||||
|
),
|
||||||
|
E.getOrElse(() => [] as RawKeyValueEntry[])
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!isEqual(newParamsList, filteredWorkingParams)) {
|
||||||
|
workingParams.value = pipe(
|
||||||
|
newParamsList,
|
||||||
|
A.map((x) => ({ id: idTicker.value++, ...x }))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isEqual(newParamsList, filteredBulkParams)) {
|
||||||
|
bulkParams.value = rawKeyValueEntriesToString(newParamsList)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(workingParams, (newWorkingParams) => {
|
||||||
|
const fixedParams = pipe(
|
||||||
|
newWorkingParams,
|
||||||
|
A.filterMap(
|
||||||
|
flow(
|
||||||
|
O.fromPredicate((e) => e.key !== ""),
|
||||||
|
O.map(objRemoveKey("id"))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!isEqual(params.value, fixedParams)) {
|
||||||
|
params.value = cloneDeep(fixedParams)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(bulkParams, (newBulkParams) => {
|
||||||
|
const filteredBulkParams = pipe(
|
||||||
|
parseRawKeyValueEntriesE(newBulkParams),
|
||||||
|
E.map(
|
||||||
|
flow(
|
||||||
|
RA.filter((e) => e.key !== ""),
|
||||||
|
RA.toArray
|
||||||
|
)
|
||||||
|
),
|
||||||
|
E.getOrElse(() => [] as RawKeyValueEntry[])
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!isEqual(params.value, filteredBulkParams)) {
|
||||||
|
params.value = filteredBulkParams
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const addParam = () => {
|
||||||
|
workingParams.value.push({
|
||||||
|
id: idTicker.value++,
|
||||||
|
key: "",
|
||||||
|
value: "",
|
||||||
|
active: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateParam = (index: number, param: HoppRESTParam & { id: number }) => {
|
||||||
|
workingParams.value = workingParams.value.map((h, i) =>
|
||||||
|
i === index ? param : h
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteParam = (index: number) => {
|
||||||
|
const paramsBeforeDeletion = cloneDeep(workingParams.value)
|
||||||
|
|
||||||
|
if (
|
||||||
|
!(
|
||||||
|
paramsBeforeDeletion.length > 0 &&
|
||||||
|
index === paramsBeforeDeletion.length - 1
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (deletionToast.value) {
|
||||||
|
deletionToast.value.goAway(0)
|
||||||
|
deletionToast.value = null
|
||||||
|
}
|
||||||
|
|
||||||
|
deletionToast.value = toast.success(`${t("state.deleted")}`, {
|
||||||
|
action: [
|
||||||
|
{
|
||||||
|
text: `${t("action.undo")}`,
|
||||||
|
onClick: (_, toastObject) => {
|
||||||
|
workingParams.value = paramsBeforeDeletion
|
||||||
|
toastObject.goAway(0)
|
||||||
|
deletionToast.value = null
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
onComplete: () => {
|
||||||
|
deletionToast.value = null
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
workingParams.value = pipe(
|
||||||
|
workingParams.value,
|
||||||
|
A.deleteAt(index),
|
||||||
|
O.getOrElseW(() => throwError("Working Params Deletion Out of Bounds"))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearContent = () => {
|
||||||
|
// set params list to the initial state
|
||||||
|
workingParams.value = [
|
||||||
|
{
|
||||||
|
id: idTicker.value++,
|
||||||
|
key: "",
|
||||||
|
value: "",
|
||||||
|
active: true,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
bulkParams.value = ""
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -348,7 +348,8 @@ const newSendRequest = async () => {
|
|||||||
const ensureMethodInEndpoint = () => {
|
const ensureMethodInEndpoint = () => {
|
||||||
if (
|
if (
|
||||||
!/^http[s]?:\/\//.test(newEndpoint.value) &&
|
!/^http[s]?:\/\//.test(newEndpoint.value) &&
|
||||||
!newEndpoint.value.startsWith("<<")
|
!newEndpoint.value.startsWith("<<") &&
|
||||||
|
!newEndpoint.value.startsWith("{{")
|
||||||
) {
|
) {
|
||||||
const domain = newEndpoint.value.split(/[/:#?]+/)[0]
|
const domain = newEndpoint.value.split(/[/:#?]+/)[0]
|
||||||
if (domain === "localhost" || /([0-9]+\.)*[0-9]/.test(domain)) {
|
if (domain === "localhost" || /([0-9]+\.)*[0-9]/.test(domain)) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<SmartTab
|
<SmartTab
|
||||||
:id="'params'"
|
:id="'params'"
|
||||||
:label="`${$t('tab.parameters')}`"
|
:label="`${$t('tab.parameters')}`"
|
||||||
:info="`${newActiveParamsCount$}`"
|
:info="`${Number(newActiveParamsCount$) + Number(newActiveVarsCount$)}`"
|
||||||
>
|
>
|
||||||
<HttpParameters />
|
<HttpParameters />
|
||||||
</SmartTab>
|
</SmartTab>
|
||||||
@@ -50,6 +50,7 @@ import { useReadonlyStream } from "~/helpers/utils/composables"
|
|||||||
import {
|
import {
|
||||||
restActiveHeadersCount$,
|
restActiveHeadersCount$,
|
||||||
restActiveParamsCount$,
|
restActiveParamsCount$,
|
||||||
|
restActiveVarsCount$,
|
||||||
usePreRequestScript,
|
usePreRequestScript,
|
||||||
useTestScript,
|
useTestScript,
|
||||||
} from "~/newstore/RESTSession"
|
} from "~/newstore/RESTSession"
|
||||||
@@ -76,6 +77,16 @@ const newActiveParamsCount$ = useReadonlyStream(
|
|||||||
null
|
null
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const newActiveVarsCount$ = useReadonlyStream(
|
||||||
|
restActiveVarsCount$.pipe(
|
||||||
|
map((e) => {
|
||||||
|
if (e === 0) return null
|
||||||
|
return `${e}`
|
||||||
|
})
|
||||||
|
),
|
||||||
|
null
|
||||||
|
)
|
||||||
|
|
||||||
const newActiveHeadersCount$ = useReadonlyStream(
|
const newActiveHeadersCount$ = useReadonlyStream(
|
||||||
restActiveHeadersCount$.pipe(
|
restActiveHeadersCount$.pipe(
|
||||||
map((e) => {
|
map((e) => {
|
||||||
|
|||||||
@@ -35,10 +35,13 @@ import { EditorState, Extension } from "@codemirror/state"
|
|||||||
import clone from "lodash/clone"
|
import clone from "lodash/clone"
|
||||||
import { tooltips } from "@codemirror/tooltip"
|
import { tooltips } from "@codemirror/tooltip"
|
||||||
import { history, historyKeymap } from "@codemirror/history"
|
import { history, historyKeymap } from "@codemirror/history"
|
||||||
|
import { HoppRESTVar } from "@hoppscotch/data"
|
||||||
import { inputTheme } from "~/helpers/editor/themes/baseTheme"
|
import { inputTheme } from "~/helpers/editor/themes/baseTheme"
|
||||||
import { HoppReactiveEnvPlugin } from "~/helpers/editor/extensions/HoppEnvironment"
|
import { HoppReactiveEnvPlugin } from "~/helpers/editor/extensions/HoppEnvironment"
|
||||||
import { useReadonlyStream } from "~/helpers/utils/composables"
|
import { useReadonlyStream } from "~/helpers/utils/composables"
|
||||||
import { AggregateEnvironment, aggregateEnvs$ } from "~/newstore/environments"
|
import { AggregateEnvironment, aggregateEnvs$ } from "~/newstore/environments"
|
||||||
|
import { HoppReactiveVarPlugin } from "~/helpers/editor/extensions/HoppVariable"
|
||||||
|
import { restVars$ } from "~/newstore/RESTSession"
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
@@ -46,6 +49,7 @@ const props = withDefaults(
|
|||||||
placeholder: string
|
placeholder: string
|
||||||
styles: string
|
styles: string
|
||||||
envs: { key: string; value: string; source: string }[] | null
|
envs: { key: string; value: string; source: string }[] | null
|
||||||
|
vars: { key: string; value: string }[] | null
|
||||||
focus: boolean
|
focus: boolean
|
||||||
readonly: boolean
|
readonly: boolean
|
||||||
}>(),
|
}>(),
|
||||||
@@ -54,6 +58,7 @@ const props = withDefaults(
|
|||||||
placeholder: "",
|
placeholder: "",
|
||||||
styles: "",
|
styles: "",
|
||||||
envs: null,
|
envs: null,
|
||||||
|
vars: null,
|
||||||
focus: false,
|
focus: false,
|
||||||
readonly: false,
|
readonly: false,
|
||||||
}
|
}
|
||||||
@@ -109,6 +114,7 @@ let pastedValue: string | null = null
|
|||||||
const aggregateEnvs = useReadonlyStream(aggregateEnvs$, []) as Ref<
|
const aggregateEnvs = useReadonlyStream(aggregateEnvs$, []) as Ref<
|
||||||
AggregateEnvironment[]
|
AggregateEnvironment[]
|
||||||
>
|
>
|
||||||
|
const aggregateVars = useReadonlyStream(restVars$, []) as Ref<HoppRESTVar[]>
|
||||||
|
|
||||||
const envVars = computed(() =>
|
const envVars = computed(() =>
|
||||||
props.envs
|
props.envs
|
||||||
@@ -120,7 +126,17 @@ const envVars = computed(() =>
|
|||||||
: aggregateEnvs.value
|
: aggregateEnvs.value
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const varVars = computed(() =>
|
||||||
|
props.vars
|
||||||
|
? props.vars.map((x) => ({
|
||||||
|
key: x.key,
|
||||||
|
value: x.value,
|
||||||
|
}))
|
||||||
|
: aggregateVars.value
|
||||||
|
)
|
||||||
|
|
||||||
const envTooltipPlugin = new HoppReactiveEnvPlugin(envVars, view)
|
const envTooltipPlugin = new HoppReactiveEnvPlugin(envVars, view)
|
||||||
|
const varTooltipPlugin = new HoppReactiveVarPlugin(varVars, view)
|
||||||
|
|
||||||
const initView = (el: any) => {
|
const initView = (el: any) => {
|
||||||
const extensions: Extension = [
|
const extensions: Extension = [
|
||||||
@@ -146,6 +162,7 @@ const initView = (el: any) => {
|
|||||||
position: "absolute",
|
position: "absolute",
|
||||||
}),
|
}),
|
||||||
envTooltipPlugin,
|
envTooltipPlugin,
|
||||||
|
varTooltipPlugin,
|
||||||
placeholderExt(props.placeholder),
|
placeholderExt(props.placeholder),
|
||||||
EditorView.domEventHandlers({
|
EditorView.domEventHandlers({
|
||||||
paste(ev) {
|
paste(ev) {
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ export const runGQLSubscription = <
|
|||||||
createRequest(args.query, args.variables)
|
createRequest(args.query, args.variables)
|
||||||
)
|
)
|
||||||
|
|
||||||
wonkaPipe(
|
const sub = wonkaPipe(
|
||||||
source,
|
source,
|
||||||
subscribe((res) => {
|
subscribe((res) => {
|
||||||
result$.next(
|
result$.next(
|
||||||
@@ -256,7 +256,8 @@ export const runGQLSubscription = <
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
return result$
|
// Returns the stream and a subscription handle to unsub
|
||||||
|
return [result$, sub] as const
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useGQLQuery = <DocType, DocVarType, DocErrorType extends string>(
|
export const useGQLQuery = <DocType, DocVarType, DocErrorType extends string>(
|
||||||
|
|||||||
@@ -809,6 +809,37 @@ const samples = [
|
|||||||
testScript: "",
|
testScript: "",
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
command: `curl https://example.com -d "alpha=beta&request_id=4"`,
|
||||||
|
response: makeRESTRequest({
|
||||||
|
method: "POST",
|
||||||
|
name: "Untitled request",
|
||||||
|
endpoint: "https://example.com/",
|
||||||
|
auth: {
|
||||||
|
authType: "none",
|
||||||
|
authActive: true,
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
contentType: "application/x-www-form-urlencoded",
|
||||||
|
body: rawKeyValueEntriesToString([
|
||||||
|
{
|
||||||
|
active: true,
|
||||||
|
key: "alpha",
|
||||||
|
value: "beta",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
active: true,
|
||||||
|
key: "request_id",
|
||||||
|
value: "4",
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
params: [],
|
||||||
|
headers: [],
|
||||||
|
preRequestScript: "",
|
||||||
|
testScript: "",
|
||||||
|
}),
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
describe("Parse curl command to Hopp REST Request", () => {
|
describe("Parse curl command to Hopp REST Request", () => {
|
||||||
|
|||||||
@@ -93,7 +93,8 @@ export const parseCurlCommand = (curlCommand: string) => {
|
|||||||
hasBodyBeenParsed = true
|
hasBodyBeenParsed = true
|
||||||
} else if (
|
} else if (
|
||||||
rawContentType.includes("application/x-www-form-urlencoded") &&
|
rawContentType.includes("application/x-www-form-urlencoded") &&
|
||||||
!!pairs
|
!!pairs &&
|
||||||
|
Array.isArray(rawData)
|
||||||
) {
|
) {
|
||||||
body = pairs.map((p) => p.join(": ")).join("\n") || null
|
body = pairs.map((p) => p.join(": ")).join("\n") || null
|
||||||
contentType = "application/x-www-form-urlencoded"
|
contentType = "application/x-www-form-urlencoded"
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
getAggregateEnvs,
|
getAggregateEnvs,
|
||||||
} from "~/newstore/environments"
|
} from "~/newstore/environments"
|
||||||
|
|
||||||
const HOPP_ENVIRONMENT_REGEX = /(<<\w+>>)/g
|
const HOPP_ENVIRONMENT_REGEX = /(<<[a-zA-Z0-9-_]+>>)/g
|
||||||
|
|
||||||
const HOPP_ENV_HIGHLIGHT =
|
const HOPP_ENV_HIGHLIGHT =
|
||||||
"cursor-help transition rounded px-1 focus:outline-none mx-0.5 env-highlight"
|
"cursor-help transition rounded px-1 focus:outline-none mx-0.5 env-highlight"
|
||||||
@@ -44,8 +44,9 @@ const cursorTooltipField = (aggregateEnvs: AggregateEnvironment[]) =>
|
|||||||
let start = pos
|
let start = pos
|
||||||
let end = pos
|
let end = pos
|
||||||
|
|
||||||
while (start > from && /\w/.test(text[start - from - 1])) start--
|
while (start > from && /[a-zA-Z0-9-_]+/.test(text[start - from - 1]))
|
||||||
while (end < to && /\w/.test(text[end - from])) end++
|
start--
|
||||||
|
while (end < to && /[a-zA-Z0-9-_]+/.test(text[end - from])) end++
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(start === pos && side < 0) ||
|
(start === pos && side < 0) ||
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
import { watch, Ref } from "@nuxtjs/composition-api"
|
||||||
|
import { Compartment } from "@codemirror/state"
|
||||||
|
import { hoverTooltip } from "@codemirror/tooltip"
|
||||||
|
import {
|
||||||
|
Decoration,
|
||||||
|
EditorView,
|
||||||
|
MatchDecorator,
|
||||||
|
ViewPlugin,
|
||||||
|
} from "@codemirror/view"
|
||||||
|
import * as E from "fp-ts/Either"
|
||||||
|
import { HoppRESTVar, parseTemplateStringE } from "@hoppscotch/data"
|
||||||
|
|
||||||
|
const HOPP_ENVIRONMENT_REGEX = /({{\w+}})/g
|
||||||
|
|
||||||
|
const HOPP_ENV_HIGHLIGHT =
|
||||||
|
"cursor-help transition rounded px-1 focus:outline-none mx-0.5 env-highlight"
|
||||||
|
const HOPP_ENV_HIGHLIGHT_FOUND =
|
||||||
|
"bg-accentDark text-accentContrast hover:bg-accent"
|
||||||
|
const HOPP_ENV_HIGHLIGHT_NOT_FOUND =
|
||||||
|
"bg-red-500 text-accentContrast hover:bg-red-600"
|
||||||
|
|
||||||
|
const cursorTooltipField = (aggregateEnvs: HoppRESTVar[]) =>
|
||||||
|
hoverTooltip(
|
||||||
|
(view, pos, side) => {
|
||||||
|
const { from, to, text } = view.state.doc.lineAt(pos)
|
||||||
|
|
||||||
|
// TODO: When Codemirror 6 allows this to work (not make the
|
||||||
|
// popups appear half of the time) use this implementation
|
||||||
|
// const wordSelection = view.state.wordAt(pos)
|
||||||
|
// if (!wordSelection) return null
|
||||||
|
// const word = view.state.doc.sliceString(
|
||||||
|
// wordSelection.from - 2,
|
||||||
|
// wordSelection.to + 2
|
||||||
|
// )
|
||||||
|
// if (!HOPP_ENVIRONMENT_REGEX.test(word)) return null
|
||||||
|
|
||||||
|
// Tracking the start and the end of the words
|
||||||
|
let start = pos
|
||||||
|
let end = pos
|
||||||
|
|
||||||
|
while (start > from && /\w/.test(text[start - from - 1])) start--
|
||||||
|
while (end < to && /\w/.test(text[end - from])) end++
|
||||||
|
|
||||||
|
if (
|
||||||
|
(start === pos && side < 0) ||
|
||||||
|
(end === pos && side > 0) ||
|
||||||
|
!HOPP_ENVIRONMENT_REGEX.test(
|
||||||
|
text.slice(start - from - 2, end - from + 2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return null
|
||||||
|
|
||||||
|
const envValue =
|
||||||
|
aggregateEnvs.find(
|
||||||
|
(env) => env.key === text.slice(start - from, end - from)
|
||||||
|
// env.key === word.slice(wordSelection.from + 2, wordSelection.to - 2)
|
||||||
|
)?.value ?? "not found"
|
||||||
|
|
||||||
|
const result = parseTemplateStringE(envValue, aggregateEnvs)
|
||||||
|
|
||||||
|
const finalEnv = E.isLeft(result) ? "error" : result.right
|
||||||
|
|
||||||
|
return {
|
||||||
|
pos: start,
|
||||||
|
end: to,
|
||||||
|
above: true,
|
||||||
|
arrow: true,
|
||||||
|
create() {
|
||||||
|
const dom = document.createElement("span")
|
||||||
|
const xmp = document.createElement("xmp")
|
||||||
|
xmp.textContent = finalEnv
|
||||||
|
dom.appendChild(xmp)
|
||||||
|
dom.className = "tooltip-theme"
|
||||||
|
return { dom }
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// HACK: This is a hack to fix hover tooltip not coming half of the time
|
||||||
|
// https://github.com/codemirror/tooltip/blob/765c463fc1d5afcc3ec93cee47d72606bed27e1d/src/tooltip.ts#L622
|
||||||
|
// Still doesn't fix the not showing up some of the time issue, but this is atleast more consistent
|
||||||
|
{ hoverTime: 1 } as any
|
||||||
|
)
|
||||||
|
|
||||||
|
function checkEnv(env: string, aggregateEnvs: HoppRESTVar[]) {
|
||||||
|
const className = aggregateEnvs.find(
|
||||||
|
(k: { key: string }) => k.key === env.slice(2, -2)
|
||||||
|
)
|
||||||
|
? HOPP_ENV_HIGHLIGHT_FOUND
|
||||||
|
: HOPP_ENV_HIGHLIGHT_NOT_FOUND
|
||||||
|
|
||||||
|
return Decoration.mark({
|
||||||
|
class: `${HOPP_ENV_HIGHLIGHT} ${className}`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMatchDecorator = (aggregateEnvs: HoppRESTVar[]) =>
|
||||||
|
new MatchDecorator({
|
||||||
|
regexp: HOPP_ENVIRONMENT_REGEX,
|
||||||
|
decoration: (m) => checkEnv(m[0], aggregateEnvs),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const environmentHighlightStyle = (aggregateEnvs: HoppRESTVar[]) => {
|
||||||
|
const decorator = getMatchDecorator(aggregateEnvs)
|
||||||
|
|
||||||
|
return ViewPlugin.define(
|
||||||
|
(view) => ({
|
||||||
|
decorations: decorator.createDeco(view),
|
||||||
|
update(u) {
|
||||||
|
this.decorations = decorator.updateDeco(u, this.decorations)
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
decorations: (v) => v.decorations,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HoppReactiveVarPlugin {
|
||||||
|
private compartment = new Compartment()
|
||||||
|
|
||||||
|
private envs: HoppRESTVar[] = []
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
envsRef: Ref<HoppRESTVar[]>,
|
||||||
|
private editorView: Ref<EditorView | undefined>
|
||||||
|
) {
|
||||||
|
watch(
|
||||||
|
envsRef,
|
||||||
|
(envs) => {
|
||||||
|
this.envs = envs
|
||||||
|
|
||||||
|
this.editorView.value?.dispatch({
|
||||||
|
effects: this.compartment.reconfigure([
|
||||||
|
cursorTooltipField(this.envs),
|
||||||
|
environmentHighlightStyle(this.envs),
|
||||||
|
]),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get extension() {
|
||||||
|
return this.compartment.of([
|
||||||
|
cursorTooltipField(this.envs),
|
||||||
|
environmentHighlightStyle(this.envs),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -61,6 +61,8 @@ export const baseTheme = EditorView.theme({
|
|||||||
},
|
},
|
||||||
".cm-panels.cm-panels-top": {
|
".cm-panels.cm-panels-top": {
|
||||||
borderBottom: "1px solid var(--divider-light-color)",
|
borderBottom: "1px solid var(--divider-light-color)",
|
||||||
|
top: "var(--lower-tertiary-sticky-fold) !important",
|
||||||
|
"z-index": "10",
|
||||||
},
|
},
|
||||||
".cm-panels.cm-panels-bottom": {
|
".cm-panels.cm-panels-bottom": {
|
||||||
borderTop: "1px solid var(--divider-light-color)",
|
borderTop: "1px solid var(--divider-light-color)",
|
||||||
@@ -388,5 +390,7 @@ export const basicSetup: Extension = [
|
|||||||
...completionKeymap,
|
...completionKeymap,
|
||||||
...lintKeymap,
|
...lintKeymap,
|
||||||
]),
|
]),
|
||||||
search(),
|
search({
|
||||||
|
top: true,
|
||||||
|
}),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ export const bindings: {
|
|||||||
"alt-q": "navigation.jump.graphql",
|
"alt-q": "navigation.jump.graphql",
|
||||||
"alt-w": "navigation.jump.realtime",
|
"alt-w": "navigation.jump.realtime",
|
||||||
"alt-d": "navigation.jump.documentation",
|
"alt-d": "navigation.jump.documentation",
|
||||||
|
"alt-m": "navigation.jump.profile",
|
||||||
"alt-s": "navigation.jump.settings",
|
"alt-s": "navigation.jump.settings",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import * as E from "fp-ts/Either"
|
import * as E from "fp-ts/Either"
|
||||||
import { BehaviorSubject, Subscription } from "rxjs"
|
import { BehaviorSubject, Subscription } from "rxjs"
|
||||||
|
import { Subscription as WSubscription } from "wonka"
|
||||||
import { GQLError, runGQLQuery, runGQLSubscription } from "../backend/GQLClient"
|
import { GQLError, runGQLQuery, runGQLSubscription } from "../backend/GQLClient"
|
||||||
import {
|
import {
|
||||||
GetUserShortcodesQuery,
|
GetUserShortcodesQuery,
|
||||||
@@ -22,6 +23,9 @@ export default class ShortcodeListAdapter {
|
|||||||
private myShortcodesCreated: Subscription | null
|
private myShortcodesCreated: Subscription | null
|
||||||
private myShortcodesRevoked: Subscription | null
|
private myShortcodesRevoked: Subscription | null
|
||||||
|
|
||||||
|
private myShortcodesCreatedSub: WSubscription | null
|
||||||
|
private myShortcodesRevokedSub: WSubscription | null
|
||||||
|
|
||||||
constructor(deferInit: boolean = false) {
|
constructor(deferInit: boolean = false) {
|
||||||
this.error$ = new BehaviorSubject<GQLError<string> | null>(null)
|
this.error$ = new BehaviorSubject<GQLError<string> | null>(null)
|
||||||
this.loading$ = new BehaviorSubject<boolean>(false)
|
this.loading$ = new BehaviorSubject<boolean>(false)
|
||||||
@@ -33,6 +37,8 @@ export default class ShortcodeListAdapter {
|
|||||||
this.isDispose = false
|
this.isDispose = false
|
||||||
this.myShortcodesCreated = null
|
this.myShortcodesCreated = null
|
||||||
this.myShortcodesRevoked = null
|
this.myShortcodesRevoked = null
|
||||||
|
this.myShortcodesCreatedSub = null
|
||||||
|
this.myShortcodesRevokedSub = null
|
||||||
|
|
||||||
if (!deferInit) this.initialize()
|
if (!deferInit) this.initialize()
|
||||||
}
|
}
|
||||||
@@ -40,6 +46,8 @@ export default class ShortcodeListAdapter {
|
|||||||
unsubscribeSubscriptions() {
|
unsubscribeSubscriptions() {
|
||||||
this.myShortcodesCreated?.unsubscribe()
|
this.myShortcodesCreated?.unsubscribe()
|
||||||
this.myShortcodesRevoked?.unsubscribe()
|
this.myShortcodesRevoked?.unsubscribe()
|
||||||
|
this.myShortcodesCreatedSub?.unsubscribe()
|
||||||
|
this.myShortcodesRevokedSub?.unsubscribe()
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize() {
|
initialize() {
|
||||||
@@ -124,9 +132,12 @@ export default class ShortcodeListAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private registerSubscriptions() {
|
private registerSubscriptions() {
|
||||||
this.myShortcodesCreated = runGQLSubscription({
|
const [myShortcodeCreated$, myShortcodeCreatedSub] = runGQLSubscription({
|
||||||
query: ShortcodeCreatedDocument,
|
query: ShortcodeCreatedDocument,
|
||||||
}).subscribe((result) => {
|
})
|
||||||
|
|
||||||
|
this.myShortcodesCreatedSub = myShortcodeCreatedSub
|
||||||
|
this.myShortcodesCreated = myShortcodeCreated$.subscribe((result) => {
|
||||||
if (E.isLeft(result)) {
|
if (E.isLeft(result)) {
|
||||||
console.error(result.left)
|
console.error(result.left)
|
||||||
throw new Error(`Shortcode Create Error ${result.left}`)
|
throw new Error(`Shortcode Create Error ${result.left}`)
|
||||||
@@ -135,9 +146,12 @@ export default class ShortcodeListAdapter {
|
|||||||
this.createShortcode(result.right.myShortcodesCreated)
|
this.createShortcode(result.right.myShortcodesCreated)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.myShortcodesRevoked = runGQLSubscription({
|
const [myShortcodesRevoked$, myShortcodeRevokedSub] = runGQLSubscription({
|
||||||
query: ShortcodeDeletedDocument,
|
query: ShortcodeDeletedDocument,
|
||||||
}).subscribe((result) => {
|
})
|
||||||
|
|
||||||
|
this.myShortcodesRevokedSub = myShortcodeRevokedSub
|
||||||
|
this.myShortcodesRevoked = myShortcodesRevoked$.subscribe((result) => {
|
||||||
if (E.isLeft(result)) {
|
if (E.isLeft(result)) {
|
||||||
console.error(result.left)
|
console.error(result.left)
|
||||||
throw new Error(`Shortcode Delete Error ${result.left}`)
|
throw new Error(`Shortcode Delete Error ${result.left}`)
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ export default [
|
|||||||
label: "shortcut.navigation.settings",
|
label: "shortcut.navigation.settings",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
keys: [getPlatformAlternateKey(), "P"],
|
keys: [getPlatformAlternateKey(), "M"],
|
||||||
label: "shortcut.navigation.profile",
|
label: "shortcut.navigation.profile",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -171,7 +171,7 @@ export const spotlight = [
|
|||||||
icon: "arrow-right",
|
icon: "arrow-right",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
keys: [getPlatformAlternateKey(), "P"],
|
keys: [getPlatformAlternateKey(), "M"],
|
||||||
label: "shortcut.navigation.profile",
|
label: "shortcut.navigation.profile",
|
||||||
action: "navigation.jump.profile",
|
action: "navigation.jump.profile",
|
||||||
icon: "arrow-right",
|
icon: "arrow-right",
|
||||||
@@ -267,7 +267,7 @@ export const fuse = [
|
|||||||
tags: ["settings", "jump", "page", "navigation", "account", "theme", "go"],
|
tags: ["settings", "jump", "page", "navigation", "account", "theme", "go"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
keys: [getPlatformAlternateKey(), "P"],
|
keys: [getPlatformAlternateKey(), "M"],
|
||||||
label: "shortcut.navigation.profile",
|
label: "shortcut.navigation.profile",
|
||||||
action: "navigation.jump.profile",
|
action: "navigation.jump.profile",
|
||||||
icon: "arrow-right",
|
icon: "arrow-right",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { BehaviorSubject, Subscription } from "rxjs"
|
|||||||
import { translateToNewRequest } from "@hoppscotch/data"
|
import { translateToNewRequest } from "@hoppscotch/data"
|
||||||
import pull from "lodash/pull"
|
import pull from "lodash/pull"
|
||||||
import remove from "lodash/remove"
|
import remove from "lodash/remove"
|
||||||
|
import { Subscription as WSubscription } from "wonka"
|
||||||
import { runGQLQuery, runGQLSubscription } from "../backend/GQLClient"
|
import { runGQLQuery, runGQLSubscription } from "../backend/GQLClient"
|
||||||
import { TeamCollection } from "./TeamCollection"
|
import { TeamCollection } from "./TeamCollection"
|
||||||
import { TeamRequest } from "./TeamRequest"
|
import { TeamRequest } from "./TeamRequest"
|
||||||
@@ -193,6 +194,13 @@ export default class NewTeamCollectionAdapter {
|
|||||||
private teamRequestUpdated$: Subscription | null
|
private teamRequestUpdated$: Subscription | null
|
||||||
private teamRequestDeleted$: Subscription | null
|
private teamRequestDeleted$: Subscription | null
|
||||||
|
|
||||||
|
private teamCollectionAddedSub: WSubscription | null
|
||||||
|
private teamCollectionUpdatedSub: WSubscription | null
|
||||||
|
private teamCollectionRemovedSub: WSubscription | null
|
||||||
|
private teamRequestAddedSub: WSubscription | null
|
||||||
|
private teamRequestUpdatedSub: WSubscription | null
|
||||||
|
private teamRequestDeletedSub: WSubscription | null
|
||||||
|
|
||||||
constructor(private teamID: string | null) {
|
constructor(private teamID: string | null) {
|
||||||
this.collections$ = new BehaviorSubject<TeamCollection[]>([])
|
this.collections$ = new BehaviorSubject<TeamCollection[]>([])
|
||||||
this.loadingCollections$ = new BehaviorSubject<string[]>([])
|
this.loadingCollections$ = new BehaviorSubject<string[]>([])
|
||||||
@@ -204,6 +212,13 @@ export default class NewTeamCollectionAdapter {
|
|||||||
this.teamRequestDeleted$ = null
|
this.teamRequestDeleted$ = null
|
||||||
this.teamRequestUpdated$ = null
|
this.teamRequestUpdated$ = null
|
||||||
|
|
||||||
|
this.teamCollectionAddedSub = null
|
||||||
|
this.teamCollectionUpdatedSub = null
|
||||||
|
this.teamCollectionRemovedSub = null
|
||||||
|
this.teamRequestAddedSub = null
|
||||||
|
this.teamRequestDeletedSub = null
|
||||||
|
this.teamRequestUpdatedSub = null
|
||||||
|
|
||||||
if (this.teamID) this.initialize()
|
if (this.teamID) this.initialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,6 +243,13 @@ export default class NewTeamCollectionAdapter {
|
|||||||
this.teamRequestAdded$?.unsubscribe()
|
this.teamRequestAdded$?.unsubscribe()
|
||||||
this.teamRequestDeleted$?.unsubscribe()
|
this.teamRequestDeleted$?.unsubscribe()
|
||||||
this.teamRequestUpdated$?.unsubscribe()
|
this.teamRequestUpdated$?.unsubscribe()
|
||||||
|
|
||||||
|
this.teamCollectionAddedSub?.unsubscribe()
|
||||||
|
this.teamCollectionUpdatedSub?.unsubscribe()
|
||||||
|
this.teamCollectionRemovedSub?.unsubscribe()
|
||||||
|
this.teamRequestAddedSub?.unsubscribe()
|
||||||
|
this.teamRequestDeletedSub?.unsubscribe()
|
||||||
|
this.teamRequestUpdatedSub?.unsubscribe()
|
||||||
}
|
}
|
||||||
|
|
||||||
private async initialize() {
|
private async initialize() {
|
||||||
@@ -406,12 +428,16 @@ export default class NewTeamCollectionAdapter {
|
|||||||
private registerSubscriptions() {
|
private registerSubscriptions() {
|
||||||
if (!this.teamID) return
|
if (!this.teamID) return
|
||||||
|
|
||||||
this.teamCollectionAdded$ = runGQLSubscription({
|
const [teamCollAdded$, teamCollAddedSub] = runGQLSubscription({
|
||||||
query: TeamCollectionAddedDocument,
|
query: TeamCollectionAddedDocument,
|
||||||
variables: {
|
variables: {
|
||||||
teamID: this.teamID,
|
teamID: this.teamID,
|
||||||
},
|
},
|
||||||
}).subscribe((result) => {
|
})
|
||||||
|
|
||||||
|
this.teamCollectionAddedSub = teamCollAddedSub
|
||||||
|
|
||||||
|
this.teamCollectionAdded$ = teamCollAdded$.subscribe((result) => {
|
||||||
if (E.isLeft(result))
|
if (E.isLeft(result))
|
||||||
throw new Error(`Team Collection Added Error: ${result.left}`)
|
throw new Error(`Team Collection Added Error: ${result.left}`)
|
||||||
|
|
||||||
@@ -426,12 +452,15 @@ export default class NewTeamCollectionAdapter {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.teamCollectionUpdated$ = runGQLSubscription({
|
const [teamCollUpdated$, teamCollUpdatedSub] = runGQLSubscription({
|
||||||
query: TeamCollectionUpdatedDocument,
|
query: TeamCollectionUpdatedDocument,
|
||||||
variables: {
|
variables: {
|
||||||
teamID: this.teamID,
|
teamID: this.teamID,
|
||||||
},
|
},
|
||||||
}).subscribe((result) => {
|
})
|
||||||
|
|
||||||
|
this.teamCollectionUpdatedSub = teamCollUpdatedSub
|
||||||
|
this.teamCollectionUpdated$ = teamCollUpdated$.subscribe((result) => {
|
||||||
if (E.isLeft(result))
|
if (E.isLeft(result))
|
||||||
throw new Error(`Team Collection Updated Error: ${result.left}`)
|
throw new Error(`Team Collection Updated Error: ${result.left}`)
|
||||||
|
|
||||||
@@ -441,24 +470,30 @@ export default class NewTeamCollectionAdapter {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
this.teamCollectionRemoved$ = runGQLSubscription({
|
const [teamCollRemoved$, teamCollRemovedSub] = runGQLSubscription({
|
||||||
query: TeamCollectionRemovedDocument,
|
query: TeamCollectionRemovedDocument,
|
||||||
variables: {
|
variables: {
|
||||||
teamID: this.teamID,
|
teamID: this.teamID,
|
||||||
},
|
},
|
||||||
}).subscribe((result) => {
|
})
|
||||||
|
|
||||||
|
this.teamCollectionRemovedSub = teamCollRemovedSub
|
||||||
|
this.teamCollectionRemoved$ = teamCollRemoved$.subscribe((result) => {
|
||||||
if (E.isLeft(result))
|
if (E.isLeft(result))
|
||||||
throw new Error(`Team Collection Removed Error: ${result.left}`)
|
throw new Error(`Team Collection Removed Error: ${result.left}`)
|
||||||
|
|
||||||
this.removeCollection(result.right.teamCollectionRemoved)
|
this.removeCollection(result.right.teamCollectionRemoved)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.teamRequestAdded$ = runGQLSubscription({
|
const [teamReqAdded$, teamReqAddedSub] = runGQLSubscription({
|
||||||
query: TeamRequestAddedDocument,
|
query: TeamRequestAddedDocument,
|
||||||
variables: {
|
variables: {
|
||||||
teamID: this.teamID,
|
teamID: this.teamID,
|
||||||
},
|
},
|
||||||
}).subscribe((result) => {
|
})
|
||||||
|
|
||||||
|
this.teamRequestAddedSub = teamReqAddedSub
|
||||||
|
this.teamRequestAdded$ = teamReqAdded$.subscribe((result) => {
|
||||||
if (E.isLeft(result))
|
if (E.isLeft(result))
|
||||||
throw new Error(`Team Request Added Error: ${result.left}`)
|
throw new Error(`Team Request Added Error: ${result.left}`)
|
||||||
|
|
||||||
@@ -472,12 +507,15 @@ export default class NewTeamCollectionAdapter {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
this.teamRequestUpdated$ = runGQLSubscription({
|
const [teamReqUpdated$, teamReqUpdatedSub] = runGQLSubscription({
|
||||||
query: TeamRequestUpdatedDocument,
|
query: TeamRequestUpdatedDocument,
|
||||||
variables: {
|
variables: {
|
||||||
teamID: this.teamID,
|
teamID: this.teamID,
|
||||||
},
|
},
|
||||||
}).subscribe((result) => {
|
})
|
||||||
|
|
||||||
|
this.teamRequestUpdatedSub = teamReqUpdatedSub
|
||||||
|
this.teamRequestUpdated$ = teamReqUpdated$.subscribe((result) => {
|
||||||
if (E.isLeft(result))
|
if (E.isLeft(result))
|
||||||
throw new Error(`Team Request Updated Error: ${result.left}`)
|
throw new Error(`Team Request Updated Error: ${result.left}`)
|
||||||
|
|
||||||
@@ -489,12 +527,15 @@ export default class NewTeamCollectionAdapter {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
this.teamRequestDeleted$ = runGQLSubscription({
|
const [teamReqDeleted$, teamReqDeleted] = runGQLSubscription({
|
||||||
query: TeamRequestDeletedDocument,
|
query: TeamRequestDeletedDocument,
|
||||||
variables: {
|
variables: {
|
||||||
teamID: this.teamID,
|
teamID: this.teamID,
|
||||||
},
|
},
|
||||||
}).subscribe((result) => {
|
})
|
||||||
|
|
||||||
|
this.teamRequestUpdatedSub = teamReqDeleted
|
||||||
|
this.teamRequestDeleted$ = teamReqDeleted$.subscribe((result) => {
|
||||||
if (E.isLeft(result))
|
if (E.isLeft(result))
|
||||||
throw new Error(`Team Request Deleted Error ${result.left}`)
|
throw new Error(`Team Request Deleted Error ${result.left}`)
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
@@ -29,6 +34,7 @@ export interface EffectiveHoppRESTRequest extends HoppRESTRequest {
|
|||||||
effectiveFinalHeaders: { key: string; value: string }[]
|
effectiveFinalHeaders: { key: string; value: string }[]
|
||||||
effectiveFinalParams: { key: string; value: string }[]
|
effectiveFinalParams: { key: string; value: string }[]
|
||||||
effectiveFinalBody: FormData | string | null
|
effectiveFinalBody: FormData | string | null
|
||||||
|
effectiveFinalVars: { key: string; value: string }[]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -210,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]
|
|
||||||
),
|
/**
|
||||||
// Tuple to Record object
|
* Filtering and mapping only right-eithers for each key-value as [string, string].
|
||||||
tupleToRecord,
|
*/
|
||||||
// Stringify
|
A.filterMap(([key, value]) =>
|
||||||
qs.stringify
|
E.isRight(key) && E.isRight(value)
|
||||||
|
? O.some([key.right, value.right] as [string, string])
|
||||||
|
: O.none
|
||||||
|
),
|
||||||
|
tupleWithSameKeysToRecord,
|
||||||
|
(obj) => qs.stringify(obj, { indices: false })
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
return E.isRight(parsedBodyRecord) ? parsedBodyRecord.right : null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.body.contentType === "multipart/form-data") {
|
if (request.body.contentType === "multipart/form-data") {
|
||||||
@@ -298,15 +319,21 @@ export function getEffectiveRESTRequest(
|
|||||||
value: parseTemplateString(x.value, envVariables),
|
value: parseTemplateString(x.value, envVariables),
|
||||||
}))
|
}))
|
||||||
)
|
)
|
||||||
|
const effectiveFinalVars = request.vars
|
||||||
|
|
||||||
const effectiveFinalBody = getFinalBodyFromRequest(request, envVariables)
|
const effectiveFinalBody = getFinalBodyFromRequest(request, envVariables)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...request,
|
...request,
|
||||||
effectiveFinalURL: parseTemplateString(request.endpoint, envVariables),
|
effectiveFinalURL: parseTemplateString(
|
||||||
|
request.endpoint,
|
||||||
|
envVariables,
|
||||||
|
request.vars
|
||||||
|
),
|
||||||
effectiveFinalHeaders,
|
effectiveFinalHeaders,
|
||||||
effectiveFinalParams,
|
effectiveFinalParams,
|
||||||
effectiveFinalBody,
|
effectiveFinalBody,
|
||||||
|
effectiveFinalVars,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -143,6 +143,15 @@ export function useStreamSubscriber(): {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useI18nPathInfo() {
|
||||||
|
const { localePath, getRouteBaseName } = useContext() as any
|
||||||
|
|
||||||
|
return {
|
||||||
|
localePath: localePath as (x: string) => string,
|
||||||
|
getRouteBaseName: getRouteBaseName as (x?: any) => string, // Should be a route
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function useI18n() {
|
export function useI18n() {
|
||||||
const {
|
const {
|
||||||
app: { i18n },
|
app: { i18n },
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"action": {
|
"action": {
|
||||||
|
"autoscroll": "自動捲動",
|
||||||
"cancel": "取消",
|
"cancel": "取消",
|
||||||
"choose_file": "選擇一個檔案",
|
"choose_file": "選擇一個檔案",
|
||||||
"clear": "清除",
|
"clear": "清除",
|
||||||
@@ -9,10 +10,11 @@
|
|||||||
"delete": "刪除",
|
"delete": "刪除",
|
||||||
"disconnect": "斷開連線",
|
"disconnect": "斷開連線",
|
||||||
"dismiss": "忽略",
|
"dismiss": "忽略",
|
||||||
"download_file": "下載檔案",
|
|
||||||
"dont_save": "不要儲存",
|
"dont_save": "不要儲存",
|
||||||
|
"download_file": "下載檔案",
|
||||||
"duplicate": "複製",
|
"duplicate": "複製",
|
||||||
"edit": "編輯",
|
"edit": "編輯",
|
||||||
|
"filter_response": "篩選回應",
|
||||||
"go_back": "返回",
|
"go_back": "返回",
|
||||||
"label": "標籤",
|
"label": "標籤",
|
||||||
"learn_more": "瞭解更多",
|
"learn_more": "瞭解更多",
|
||||||
@@ -20,11 +22,14 @@
|
|||||||
"more": "更多",
|
"more": "更多",
|
||||||
"new": "新增",
|
"new": "新增",
|
||||||
"no": "否",
|
"no": "否",
|
||||||
|
"open_workspace": "開啟工作區",
|
||||||
"paste": "貼上",
|
"paste": "貼上",
|
||||||
"prettify": "美化",
|
"prettify": "美化",
|
||||||
"remove": "移除",
|
"remove": "移除",
|
||||||
"restore": "還原",
|
"restore": "還原",
|
||||||
"save": "儲存",
|
"save": "儲存",
|
||||||
|
"scroll_to_bottom": "捲動至底部",
|
||||||
|
"scroll_to_top": "捲動至頂部",
|
||||||
"search": "搜尋",
|
"search": "搜尋",
|
||||||
"send": "傳送",
|
"send": "傳送",
|
||||||
"start": "開始",
|
"start": "開始",
|
||||||
@@ -46,10 +51,10 @@
|
|||||||
"contact_us": "聯絡我們",
|
"contact_us": "聯絡我們",
|
||||||
"copy": "複製",
|
"copy": "複製",
|
||||||
"copy_user_id": "複製使用者驗證權杖",
|
"copy_user_id": "複製使用者驗證權杖",
|
||||||
"discord": "Discord",
|
|
||||||
"documentation": "幫助文件",
|
|
||||||
"developer_option": "開發者選項",
|
"developer_option": "開發者選項",
|
||||||
"developer_option_description": "協助開發和維護 Hoppscotch 的工具。",
|
"developer_option_description": "協助開發和維護 Hoppscotch 的工具。",
|
||||||
|
"discord": "Discord",
|
||||||
|
"documentation": "幫助文件",
|
||||||
"github": "GitHub",
|
"github": "GitHub",
|
||||||
"help": "幫助與回饋",
|
"help": "幫助與回饋",
|
||||||
"home": "主頁",
|
"home": "主頁",
|
||||||
@@ -164,6 +169,7 @@
|
|||||||
"profile": "登入以檢視您的設定檔",
|
"profile": "登入以檢視您的設定檔",
|
||||||
"protocols": "協議為空",
|
"protocols": "協議為空",
|
||||||
"schema": "連線至 GraphQL 端點",
|
"schema": "連線至 GraphQL 端點",
|
||||||
|
"shortcodes": "Shortcodes 為空",
|
||||||
"team_name": "團隊名稱為空",
|
"team_name": "團隊名稱為空",
|
||||||
"teams": "團隊為空",
|
"teams": "團隊為空",
|
||||||
"tests": "沒有針對該請求的測試"
|
"tests": "沒有針對該請求的測試"
|
||||||
@@ -197,9 +203,11 @@
|
|||||||
"invalid_link": "連結無效",
|
"invalid_link": "連結無效",
|
||||||
"invalid_link_description": "您點擊的連結無效或已過期。",
|
"invalid_link_description": "您點擊的連結無效或已過期。",
|
||||||
"json_prettify_invalid_body": "無法美化無效的請求主體,處理 JSON 語法錯誤並重試",
|
"json_prettify_invalid_body": "無法美化無效的請求主體,處理 JSON 語法錯誤並重試",
|
||||||
|
"json_parsing_failed": "JSON 無效",
|
||||||
"network_error": "似乎有網路錯誤。請再試一次。",
|
"network_error": "似乎有網路錯誤。請再試一次。",
|
||||||
"network_fail": "無法傳送請求",
|
"network_fail": "無法傳送請求",
|
||||||
"no_duration": "無持續時間",
|
"no_duration": "無持續時間",
|
||||||
|
"no_results_found": "找不到結果",
|
||||||
"script_fail": "無法執行預請求指令碼",
|
"script_fail": "無法執行預請求指令碼",
|
||||||
"something_went_wrong": "發生了一些錯誤",
|
"something_went_wrong": "發生了一些錯誤",
|
||||||
"test_script_fail": "無法執行測試指令碼"
|
"test_script_fail": "無法執行測試指令碼"
|
||||||
@@ -266,15 +274,19 @@
|
|||||||
"from_url": "從網址匯入",
|
"from_url": "從網址匯入",
|
||||||
"gist_url": "輸入 Gist 網址",
|
"gist_url": "輸入 Gist 網址",
|
||||||
"json_description": "從 Hoppscotch 組合 JSON 檔匯入組合",
|
"json_description": "從 Hoppscotch 組合 JSON 檔匯入組合",
|
||||||
"title": "匯入"
|
"title": "匯入",
|
||||||
|
"import_from_url_success": "已匯入組合",
|
||||||
|
"import_from_url_invalid_file_format": "匯入組合時發生錯誤",
|
||||||
|
"import_from_url_invalid_type": "不支援此類型。可接受的值為 'hoppscotch'、'openapi'、'postman'、'insomnia'",
|
||||||
|
"import_from_url_invalid_fetch": "無法從網址取得資料"
|
||||||
},
|
},
|
||||||
"layout": {
|
"layout": {
|
||||||
"column": "垂直布局",
|
|
||||||
"row": "水平布局",
|
|
||||||
"zen_mode": "專注模式",
|
|
||||||
"collapse_sidebar": "隱藏或顯示側邊欄",
|
|
||||||
"collapse_collection": "隱藏或顯示組合",
|
"collapse_collection": "隱藏或顯示組合",
|
||||||
"name": "配置"
|
"collapse_sidebar": "隱藏或顯示側邊欄",
|
||||||
|
"column": "垂直布局",
|
||||||
|
"name": "配置",
|
||||||
|
"row": "水平布局",
|
||||||
|
"zen_mode": "專注模式"
|
||||||
},
|
},
|
||||||
"modal": {
|
"modal": {
|
||||||
"collections": "組合",
|
"collections": "組合",
|
||||||
@@ -331,6 +343,11 @@
|
|||||||
"body": "請求本體",
|
"body": "請求本體",
|
||||||
"choose_language": "選擇語言",
|
"choose_language": "選擇語言",
|
||||||
"content_type": "內容類型",
|
"content_type": "內容類型",
|
||||||
|
"content_type_titles": {
|
||||||
|
"others": "其他",
|
||||||
|
"structured": "結構",
|
||||||
|
"text": "文字"
|
||||||
|
},
|
||||||
"copy_link": "複製連結",
|
"copy_link": "複製連結",
|
||||||
"duration": "持續時間",
|
"duration": "持續時間",
|
||||||
"enter_curl": "輸入 cURL",
|
"enter_curl": "輸入 cURL",
|
||||||
@@ -341,6 +358,9 @@
|
|||||||
"method": "方法",
|
"method": "方法",
|
||||||
"name": "請求名稱",
|
"name": "請求名稱",
|
||||||
"new": "新請求",
|
"new": "新請求",
|
||||||
|
"override": "覆寫",
|
||||||
|
"override_help": "在標頭設置 <xmp>Content-Type</xmp>",
|
||||||
|
"overriden": "已覆寫",
|
||||||
"parameter_list": "查詢參數",
|
"parameter_list": "查詢參數",
|
||||||
"parameters": "參數",
|
"parameters": "參數",
|
||||||
"path": "路徑",
|
"path": "路徑",
|
||||||
@@ -358,12 +378,11 @@
|
|||||||
"type": "請求類型",
|
"type": "請求類型",
|
||||||
"url": "網址",
|
"url": "網址",
|
||||||
"variables": "變數",
|
"variables": "變數",
|
||||||
"override": "覆寫",
|
"view_my_links": "檢視我的連結"
|
||||||
"override_help": "在標頭設置 <xmp>Content-Type</xmp>",
|
|
||||||
"overriden": "已覆寫"
|
|
||||||
},
|
},
|
||||||
"response": {
|
"response": {
|
||||||
"body": "回應本體",
|
"body": "回應本體",
|
||||||
|
"filter_response_body": "篩選 JSON 回應本體 (使用 JSONPath 語法)",
|
||||||
"headers": "回應標頭",
|
"headers": "回應標頭",
|
||||||
"html": "HTML",
|
"html": "HTML",
|
||||||
"image": "影像",
|
"image": "影像",
|
||||||
@@ -415,6 +434,8 @@
|
|||||||
"proxy_use_toggle": "使用 Proxy 中介軟體傳送請求",
|
"proxy_use_toggle": "使用 Proxy 中介軟體傳送請求",
|
||||||
"read_the": "閱讀",
|
"read_the": "閱讀",
|
||||||
"reset_default": "重置為預設",
|
"reset_default": "重置為預設",
|
||||||
|
"short_codes": "快捷碼",
|
||||||
|
"short_codes_description": "我們為您打造的快捷碼。",
|
||||||
"sidebar_on_left": "左側邊欄",
|
"sidebar_on_left": "左側邊欄",
|
||||||
"sync": "同步",
|
"sync": "同步",
|
||||||
"sync_collections": "組合",
|
"sync_collections": "組合",
|
||||||
@@ -447,7 +468,7 @@
|
|||||||
"documentation": "前往文件頁面",
|
"documentation": "前往文件頁面",
|
||||||
"forward": "前往下一頁面",
|
"forward": "前往下一頁面",
|
||||||
"graphql": "前往 GraphQL 頁面",
|
"graphql": "前往 GraphQL 頁面",
|
||||||
"profile": "Go to Profile page",
|
"profile": "前往個人檔案頁面",
|
||||||
"realtime": "前往實時頁面",
|
"realtime": "前往實時頁面",
|
||||||
"rest": "前往 REST 頁面",
|
"rest": "前往 REST 頁面",
|
||||||
"settings": "前往設定頁面",
|
"settings": "前往設定頁面",
|
||||||
@@ -476,6 +497,15 @@
|
|||||||
"title": "主題"
|
"title": "主題"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"shortcodes":{
|
||||||
|
"actions":"操作",
|
||||||
|
"created_on": "建立於",
|
||||||
|
"deleted" : "已刪除快捷碼",
|
||||||
|
"method": "方法",
|
||||||
|
"not_found":"找不到快捷碼",
|
||||||
|
"short_code":"快捷碼",
|
||||||
|
"url": "網址"
|
||||||
|
},
|
||||||
"show": {
|
"show": {
|
||||||
"code": "顯示程式碼",
|
"code": "顯示程式碼",
|
||||||
"more": "顯示更多",
|
"more": "顯示更多",
|
||||||
@@ -487,7 +517,8 @@
|
|||||||
"event_name": "事件名稱",
|
"event_name": "事件名稱",
|
||||||
"events": "事件",
|
"events": "事件",
|
||||||
"log": "日誌",
|
"log": "日誌",
|
||||||
"url": "網址"
|
"url": "網址",
|
||||||
|
"connection_not_authorized": "此 SocketIO 連線未使用任何驗證。"
|
||||||
},
|
},
|
||||||
"sse": {
|
"sse": {
|
||||||
"event_type": "事件類型",
|
"event_type": "事件類型",
|
||||||
@@ -517,7 +548,19 @@
|
|||||||
"loading": "正在載入……",
|
"loading": "正在載入……",
|
||||||
"none": "無",
|
"none": "無",
|
||||||
"nothing_found": "沒有找到",
|
"nothing_found": "沒有找到",
|
||||||
"waiting_send_request": "等待傳送請求"
|
"waiting_send_request": "等待傳送請求",
|
||||||
|
"subscribed_success": "成功訂閱此主題:{topic}",
|
||||||
|
"unsubscribed_success": "成功取消訂閱此主題:{topic}",
|
||||||
|
"subscribed_failed": "無法訂閱此主題:{topic}",
|
||||||
|
"unsubscribed_failed": "無法取消訂閱此主題:{topic}",
|
||||||
|
"published_message": "已將此訊息:{message} 發布至主題:{topic}",
|
||||||
|
"published_error": "將訊息:{topic} 發布至主題:{message} 時發生錯誤",
|
||||||
|
"message_received": "訊息:{message}已抵達主題:{topic}",
|
||||||
|
"mqtt_subscription_failed": "訂閱此主題時發生錯誤:{topic}",
|
||||||
|
"connection_lost": "失去連線",
|
||||||
|
"connection_failed": "連線失敗",
|
||||||
|
"connection_error": "連線失敗",
|
||||||
|
"reconnection_error": "重新連線失敗"
|
||||||
},
|
},
|
||||||
"support": {
|
"support": {
|
||||||
"changelog": "閱讀更多有關最新版本的內容",
|
"changelog": "閱讀更多有關最新版本的內容",
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
FormDataKeyValue,
|
FormDataKeyValue,
|
||||||
HoppRESTHeader,
|
HoppRESTHeader,
|
||||||
HoppRESTParam,
|
HoppRESTParam,
|
||||||
|
HoppRESTVar,
|
||||||
HoppRESTReqBody,
|
HoppRESTReqBody,
|
||||||
HoppRESTRequest,
|
HoppRESTRequest,
|
||||||
RESTReqSchemaVersion,
|
RESTReqSchemaVersion,
|
||||||
@@ -29,6 +30,7 @@ export const getDefaultRESTRequest = (): HoppRESTRequest => ({
|
|||||||
endpoint: "https://echo.hoppscotch.io",
|
endpoint: "https://echo.hoppscotch.io",
|
||||||
name: "Untitled request",
|
name: "Untitled request",
|
||||||
params: [],
|
params: [],
|
||||||
|
vars: [],
|
||||||
headers: [],
|
headers: [],
|
||||||
method: "GET",
|
method: "GET",
|
||||||
auth: {
|
auth: {
|
||||||
@@ -80,6 +82,14 @@ const dispatchers = defineDispatchers({
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setVars(curr: RESTSession, { entries }: { entries: HoppRESTVar[] }) {
|
||||||
|
return {
|
||||||
|
request: {
|
||||||
|
...curr.request,
|
||||||
|
vars: entries,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
addParam(curr: RESTSession, { newParam }: { newParam: HoppRESTParam }) {
|
addParam(curr: RESTSession, { newParam }: { newParam: HoppRESTParam }) {
|
||||||
return {
|
return {
|
||||||
request: {
|
request: {
|
||||||
@@ -88,6 +98,14 @@ const dispatchers = defineDispatchers({
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
addVar(curr: RESTSession, { newVar }: { newVar: HoppRESTVar }) {
|
||||||
|
return {
|
||||||
|
request: {
|
||||||
|
...curr.request,
|
||||||
|
vars: [...curr.request.vars, newVar],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
updateParam(
|
updateParam(
|
||||||
curr: RESTSession,
|
curr: RESTSession,
|
||||||
{ index, updatedParam }: { index: number; updatedParam: HoppRESTParam }
|
{ index, updatedParam }: { index: number; updatedParam: HoppRESTParam }
|
||||||
@@ -104,6 +122,22 @@ const dispatchers = defineDispatchers({
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
updateVar(
|
||||||
|
curr: RESTSession,
|
||||||
|
{ index, updatedVar }: { index: number; updatedVar: HoppRESTVar }
|
||||||
|
) {
|
||||||
|
const newVars = curr.request.vars.map((vari, i) => {
|
||||||
|
if (i === index) return updatedVar
|
||||||
|
else return vari
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
request: {
|
||||||
|
...curr.request,
|
||||||
|
vars: newVars,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
deleteParam(curr: RESTSession, { index }: { index: number }) {
|
deleteParam(curr: RESTSession, { index }: { index: number }) {
|
||||||
const newParams = curr.request.params.filter((_x, i) => i !== index)
|
const newParams = curr.request.params.filter((_x, i) => i !== index)
|
||||||
|
|
||||||
@@ -114,6 +148,16 @@ const dispatchers = defineDispatchers({
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
deleteVar(curr: RESTSession, { index }: { index: number }) {
|
||||||
|
const newVars = curr.request.vars.filter((_x, i) => i !== index)
|
||||||
|
|
||||||
|
return {
|
||||||
|
request: {
|
||||||
|
...curr.request,
|
||||||
|
vars: newVars,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
deleteAllParams(curr: RESTSession) {
|
deleteAllParams(curr: RESTSession) {
|
||||||
return {
|
return {
|
||||||
request: {
|
request: {
|
||||||
@@ -373,6 +417,14 @@ export function setRESTParams(entries: HoppRESTParam[]) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
export function setRESTVars(entries: HoppRESTVar[]) {
|
||||||
|
restSessionStore.dispatch({
|
||||||
|
dispatcher: "setVars",
|
||||||
|
payload: {
|
||||||
|
entries,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export function addRESTParam(newParam: HoppRESTParam) {
|
export function addRESTParam(newParam: HoppRESTParam) {
|
||||||
restSessionStore.dispatch({
|
restSessionStore.dispatch({
|
||||||
@@ -382,6 +434,14 @@ export function addRESTParam(newParam: HoppRESTParam) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
export function addRESTVar(newVar: HoppRESTVar) {
|
||||||
|
restSessionStore.dispatch({
|
||||||
|
dispatcher: "addVar",
|
||||||
|
payload: {
|
||||||
|
newVar,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export function updateRESTParam(index: number, updatedParam: HoppRESTParam) {
|
export function updateRESTParam(index: number, updatedParam: HoppRESTParam) {
|
||||||
restSessionStore.dispatch({
|
restSessionStore.dispatch({
|
||||||
@@ -392,6 +452,15 @@ export function updateRESTParam(index: number, updatedParam: HoppRESTParam) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
export function updateRESTVar(index: number, updatedVar: HoppRESTVar) {
|
||||||
|
restSessionStore.dispatch({
|
||||||
|
dispatcher: "updateVar",
|
||||||
|
payload: {
|
||||||
|
updatedVar,
|
||||||
|
index,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export function deleteRESTParam(index: number) {
|
export function deleteRESTParam(index: number) {
|
||||||
restSessionStore.dispatch({
|
restSessionStore.dispatch({
|
||||||
@@ -402,6 +471,15 @@ export function deleteRESTParam(index: number) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function deleteRESTVar(index: number) {
|
||||||
|
restSessionStore.dispatch({
|
||||||
|
dispatcher: "deleteVar",
|
||||||
|
payload: {
|
||||||
|
index,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export function deleteAllRESTParams() {
|
export function deleteAllRESTParams() {
|
||||||
restSessionStore.dispatch({
|
restSessionStore.dispatch({
|
||||||
dispatcher: "deleteAllParams",
|
dispatcher: "deleteAllParams",
|
||||||
@@ -592,12 +670,20 @@ export const restParams$ = restSessionStore.subject$.pipe(
|
|||||||
distinctUntilChanged()
|
distinctUntilChanged()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const restVars$ = restSessionStore.subject$.pipe(
|
||||||
|
pluck("request", "vars"),
|
||||||
|
distinctUntilChanged()
|
||||||
|
)
|
||||||
|
|
||||||
export const restActiveParamsCount$ = restParams$.pipe(
|
export const restActiveParamsCount$ = restParams$.pipe(
|
||||||
map(
|
map(
|
||||||
(params) =>
|
(params) =>
|
||||||
params.filter((x) => x.active && (x.key !== "" || x.value !== "")).length
|
params.filter((x) => x.active && (x.key !== "" || x.value !== "")).length
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
export const restActiveVarsCount$ = restVars$.pipe(
|
||||||
|
map((vars) => vars.filter((x) => x.key !== "" || x.value !== "").length)
|
||||||
|
)
|
||||||
|
|
||||||
export const restMethod$ = restSessionStore.subject$.pipe(
|
export const restMethod$ = restSessionStore.subject$.pipe(
|
||||||
pluck("request", "method"),
|
pluck("request", "method"),
|
||||||
|
|||||||
@@ -315,6 +315,7 @@ completedRESTResponse$.subscribe((res) => {
|
|||||||
method: res.req.method,
|
method: res.req.method,
|
||||||
name: res.req.name,
|
name: res.req.name,
|
||||||
params: res.req.params,
|
params: res.req.params,
|
||||||
|
vars: res.req.vars,
|
||||||
preRequestScript: res.req.preRequestScript,
|
preRequestScript: res.req.preRequestScript,
|
||||||
testScript: res.req.testScript,
|
testScript: res.req.testScript,
|
||||||
v: res.req.v,
|
v: res.req.v,
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
"@codemirror/tooltip": "^0.19.16",
|
"@codemirror/tooltip": "^0.19.16",
|
||||||
"@codemirror/view": "^0.19.48",
|
"@codemirror/view": "^0.19.48",
|
||||||
"@hoppscotch/codemirror-lang-graphql": "workspace:^0.2.0",
|
"@hoppscotch/codemirror-lang-graphql": "workspace:^0.2.0",
|
||||||
"@hoppscotch/data": "workspace:^0.4.2",
|
"@hoppscotch/data": "workspace:^0.4.3",
|
||||||
"@hoppscotch/js-sandbox": "workspace:^2.0.0",
|
"@hoppscotch/js-sandbox": "workspace:^2.0.0",
|
||||||
"@nuxtjs/axios": "^5.13.6",
|
"@nuxtjs/axios": "^5.13.6",
|
||||||
"@nuxtjs/composition-api": "^0.32.0",
|
"@nuxtjs/composition-api": "^0.32.0",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<AppPaneLayout>
|
<AppPaneLayout layout-id="docs">
|
||||||
<template #primary>
|
<template #primary>
|
||||||
<div class="flex items-start justify-between p-4">
|
<div class="flex items-start justify-between p-4">
|
||||||
<label>
|
<label>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<AppPaneLayout>
|
<AppPaneLayout layout-id="graphql">
|
||||||
<template #primary>
|
<template #primary>
|
||||||
<GraphqlRequest :conn="gqlConn" />
|
<GraphqlRequest :conn="gqlConn" />
|
||||||
<GraphqlRequestOptions :conn="gqlConn" />
|
<GraphqlRequestOptions :conn="gqlConn" />
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<AppPaneLayout>
|
<AppPaneLayout layout-id="http">
|
||||||
<template #primary>
|
<template #primary>
|
||||||
<HttpRequest />
|
<HttpRequest />
|
||||||
<HttpRequestOptions />
|
<HttpRequestOptions />
|
||||||
|
|||||||
@@ -13,9 +13,10 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { watch, ref, useRouter, useRoute } from "@nuxtjs/composition-api"
|
import { watch, ref, useRouter, useRoute } from "@nuxtjs/composition-api"
|
||||||
import { useI18n } from "~/helpers/utils/composables"
|
import { useI18n, useI18nPathInfo } from "~/helpers/utils/composables"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
|
const { localePath, getRouteBaseName } = useI18nPathInfo()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
@@ -44,17 +45,21 @@ const currentTab = ref<RealtimeNavTab>("websocket")
|
|||||||
|
|
||||||
// Update the router when the tab is updated
|
// Update the router when the tab is updated
|
||||||
watch(currentTab, (newTab) => {
|
watch(currentTab, (newTab) => {
|
||||||
router.push(`/realtime/${newTab}`)
|
router.push(localePath(`/realtime/${newTab}`))
|
||||||
})
|
})
|
||||||
|
|
||||||
// Update the tab when router is upgrad
|
// Update the tab when router is upgrad
|
||||||
watch(
|
watch(
|
||||||
route,
|
route,
|
||||||
(updateRoute) => {
|
(updateRoute) => {
|
||||||
if (updateRoute.path === "/realtime") router.replace("/realtime/websocket")
|
const path = getRouteBaseName(updateRoute)
|
||||||
|
|
||||||
const destination: string | undefined =
|
if (path.endsWith("realtime")) {
|
||||||
updateRoute.path.split("/realtime/")[1]
|
router.replace(localePath(`/realtime/websocket`))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const destination: string | undefined = path.split("realtime-")[1]
|
||||||
|
|
||||||
const target = REALTIME_NAVIGATION.find(
|
const target = REALTIME_NAVIGATION.find(
|
||||||
({ target }) => target === destination
|
({ target }) => target === destination
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<AppPaneLayout>
|
<AppPaneLayout layout-id="mqtt">
|
||||||
<template #primary>
|
<template #primary>
|
||||||
<div
|
<div
|
||||||
class="sticky top-0 z-10 flex flex-shrink-0 p-4 overflow-x-auto space-x-2 bg-primary hide-scrollbar"
|
class="sticky top-0 z-10 flex flex-shrink-0 p-4 overflow-x-auto space-x-2 bg-primary hide-scrollbar"
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<AppPaneLayout>
|
<AppPaneLayout layout-id="socketio">
|
||||||
<template #primary>
|
<template #primary>
|
||||||
<div
|
<div
|
||||||
class="sticky top-0 z-10 flex flex-shrink-0 p-4 overflow-x-auto space-x-2 bg-primary hide-scrollbar"
|
class="sticky top-0 z-10 flex flex-shrink-0 p-4 overflow-x-auto space-x-2 bg-primary hide-scrollbar"
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<AppPaneLayout>
|
<AppPaneLayout layout-id="sse">
|
||||||
<template #primary>
|
<template #primary>
|
||||||
<div
|
<div
|
||||||
class="sticky top-0 z-10 flex flex-shrink-0 p-4 overflow-x-auto space-x-2 bg-primary hide-scrollbar"
|
class="sticky top-0 z-10 flex flex-shrink-0 p-4 overflow-x-auto space-x-2 bg-primary hide-scrollbar"
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<AppPaneLayout>
|
<AppPaneLayout layout-id="websocket">
|
||||||
<template #primary>
|
<template #primary>
|
||||||
<div
|
<div
|
||||||
class="sticky top-0 z-10 flex flex-shrink-0 p-4 overflow-x-auto space-x-2 bg-primary hide-scrollbar"
|
class="sticky top-0 z-10 flex flex-shrink-0 p-4 overflow-x-auto space-x-2 bg-primary hide-scrollbar"
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@hoppscotch/cli",
|
"name": "@hoppscotch/cli",
|
||||||
"version": "0.2.1",
|
"version": "0.3.0",
|
||||||
"description": "A CLI to run Hoppscotch test scripts in CI environments.",
|
"description": "A CLI to run Hoppscotch test scripts in CI environments.",
|
||||||
"homepage": "https://hoppscotch.io",
|
"homepage": "https://hoppscotch.io",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"private": false,
|
"private": false,
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@hoppscotch/data": "workspace:^0.4.2",
|
"@hoppscotch/data": "workspace:^0.4.3",
|
||||||
"@hoppscotch/js-sandbox": "workspace:^2.0.0",
|
"@hoppscotch/js-sandbox": "workspace:^2.0.0",
|
||||||
"@relmify/jest-fp-ts": "^2.0.2",
|
"@relmify/jest-fp-ts": "^2.0.2",
|
||||||
"@swc/core": "^1.2.181",
|
"@swc/core": "^1.2.181",
|
||||||
|
|||||||
@@ -92,12 +92,41 @@ describe("Test 'hopp test <file> --env <file>' command:", () => {
|
|||||||
expect(out).toBe<HoppErrorCode>("FILE_NOT_FOUND");
|
expect(out).toBe<HoppErrorCode>("FILE_NOT_FOUND");
|
||||||
});
|
});
|
||||||
|
|
||||||
// test("No errors occured (exit code 0).", async () => {
|
test("No errors occured (exit code 0).", async () => {
|
||||||
// const TESTS_PATH = getTestJsonFilePath("env-flag-tests.json");
|
const TESTS_PATH = getTestJsonFilePath("env-flag-tests.json");
|
||||||
// const ENV_PATH = getTestJsonFilePath("env-flag-envs.json");
|
const ENV_PATH = getTestJsonFilePath("env-flag-envs.json");
|
||||||
// const cmd = `node ./bin/hopp test ${TESTS_PATH} --env ${ENV_PATH}`;
|
const cmd = `node ./bin/hopp test ${TESTS_PATH} --env ${ENV_PATH}`;
|
||||||
// const { error } = await execAsync(cmd);
|
const { error } = await execAsync(cmd);
|
||||||
|
|
||||||
// expect(error).toBeNull();
|
expect(error).toBeNull();
|
||||||
// });
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Test 'hopp test <file> --delay <delay_in_ms>' command:", () => {
|
||||||
|
const VALID_TEST_CMD = `node ./bin/hopp test ${getTestJsonFilePath(
|
||||||
|
"passes.json"
|
||||||
|
)}`;
|
||||||
|
|
||||||
|
test("No value passed to delay flag.", async () => {
|
||||||
|
const cmd = `${VALID_TEST_CMD} --delay`;
|
||||||
|
const { stdout } = await execAsync(cmd);
|
||||||
|
const out = getErrorCode(stdout);
|
||||||
|
|
||||||
|
expect(out).toBe<HoppErrorCode>("INVALID_ARGUMENT");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Invalid value passed to delay flag.", async () => {
|
||||||
|
const cmd = `${VALID_TEST_CMD} --delay 'NaN'`;
|
||||||
|
const { stdout } = await execAsync(cmd);
|
||||||
|
const out = getErrorCode(stdout);
|
||||||
|
|
||||||
|
expect(out).toBe<HoppErrorCode>("INVALID_ARGUMENT");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Valid value passed to delay flag.", async () => {
|
||||||
|
const cmd = `${VALID_TEST_CMD} --delay 1`;
|
||||||
|
const { error } = await execAsync(cmd);
|
||||||
|
|
||||||
|
expect(error).toBeNull();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import { hrtime } from "process";
|
||||||
|
import { getDurationInSeconds } from "../../../utils/getters";
|
||||||
|
import { delayPromiseFunction } from "../../../utils/request";
|
||||||
|
|
||||||
|
describe("describePromiseFunction", () => {
|
||||||
|
let promiseFunc = (): Promise<number> => new Promise((resolve) => resolve(2));
|
||||||
|
beforeEach(() => {
|
||||||
|
promiseFunc = (): Promise<number> => new Promise((resolve) => resolve(2));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should resolve the promise<number> after 2 seconds.", async () => {
|
||||||
|
const start = hrtime();
|
||||||
|
const res = await delayPromiseFunction(promiseFunc, 2000);
|
||||||
|
const end = hrtime(start);
|
||||||
|
const duration = getDurationInSeconds(end);
|
||||||
|
|
||||||
|
expect(Math.floor(duration)).toEqual(2);
|
||||||
|
expect(typeof res).toBe("number");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should resolve the promise<number> after 4 seconds.", async () => {
|
||||||
|
const start = hrtime();
|
||||||
|
const res = await delayPromiseFunction(promiseFunc, 4000);
|
||||||
|
const end = hrtime(start);
|
||||||
|
const duration = getDurationInSeconds(end);
|
||||||
|
|
||||||
|
expect(Math.floor(duration)).toEqual(4);
|
||||||
|
expect(typeof res).toBe("number");
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -58,7 +58,12 @@ describe("processRequest", () => {
|
|||||||
(axios as unknown as jest.Mock).mockResolvedValue(DEFAULT_RESPONSE);
|
(axios as unknown as jest.Mock).mockResolvedValue(DEFAULT_RESPONSE);
|
||||||
|
|
||||||
return expect(
|
return expect(
|
||||||
processRequest(SAMPLE_REQUEST, DEFAULT_ENVS, "fake/collection/path")()
|
processRequest({
|
||||||
|
request: SAMPLE_REQUEST,
|
||||||
|
envs: DEFAULT_ENVS,
|
||||||
|
path: "fake/collection/path",
|
||||||
|
delay: 0,
|
||||||
|
})()
|
||||||
).resolves.toMatchObject({
|
).resolves.toMatchObject({
|
||||||
report: {
|
report: {
|
||||||
result: true,
|
result: true,
|
||||||
@@ -79,7 +84,12 @@ describe("processRequest", () => {
|
|||||||
(axios as unknown as jest.Mock).mockResolvedValue(DEFAULT_RESPONSE);
|
(axios as unknown as jest.Mock).mockResolvedValue(DEFAULT_RESPONSE);
|
||||||
|
|
||||||
return expect(
|
return expect(
|
||||||
processRequest(SAMPLE_REQUEST, DEFAULT_ENVS, "fake/collection/path")()
|
processRequest({
|
||||||
|
request: SAMPLE_REQUEST,
|
||||||
|
envs: DEFAULT_ENVS,
|
||||||
|
path: "fake/collection/path",
|
||||||
|
delay: 0,
|
||||||
|
})()
|
||||||
).resolves.toMatchObject({
|
).resolves.toMatchObject({
|
||||||
envs: {
|
envs: {
|
||||||
selected: [{ key: "ENDPOINT", value: "https://example.com" }],
|
selected: [{ key: "ENDPOINT", value: "https://example.com" }],
|
||||||
@@ -96,7 +106,12 @@ describe("processRequest", () => {
|
|||||||
(axios as unknown as jest.Mock).mockResolvedValue(DEFAULT_RESPONSE);
|
(axios as unknown as jest.Mock).mockResolvedValue(DEFAULT_RESPONSE);
|
||||||
|
|
||||||
return expect(
|
return expect(
|
||||||
processRequest(SAMPLE_REQUEST, DEFAULT_ENVS, "fake/request/path")()
|
processRequest({
|
||||||
|
request: SAMPLE_REQUEST,
|
||||||
|
envs: DEFAULT_ENVS,
|
||||||
|
path: "fake/request/path",
|
||||||
|
delay: 0,
|
||||||
|
})()
|
||||||
).resolves.toMatchObject({
|
).resolves.toMatchObject({
|
||||||
report: { result: false },
|
report: { result: false },
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,12 +9,14 @@ import { handleError } from "../handlers/error";
|
|||||||
import { parseCollectionData } from "../utils/mutators";
|
import { parseCollectionData } from "../utils/mutators";
|
||||||
import { parseEnvsData } from "../options/test/env";
|
import { parseEnvsData } from "../options/test/env";
|
||||||
import { TestCmdOptions } from "../types/commands";
|
import { TestCmdOptions } from "../types/commands";
|
||||||
|
import { parseDelayOption } from "../options/test/delay";
|
||||||
|
|
||||||
export const test = (path: string, options: TestCmdOptions) => async () => {
|
export const test = (path: string, options: TestCmdOptions) => async () => {
|
||||||
await pipe(
|
await pipe(
|
||||||
TE.Do,
|
TE.Do,
|
||||||
TE.bind("envs", () => parseEnvsData(options.env)),
|
TE.bind("envs", () => parseEnvsData(options.env)),
|
||||||
TE.bind("collections", () => parseCollectionData(path)),
|
TE.bind("collections", () => parseCollectionData(path)),
|
||||||
|
TE.bind("delay", () => parseDelayOption(options.delay)),
|
||||||
TE.chainTaskK(collectionsRunner),
|
TE.chainTaskK(collectionsRunner),
|
||||||
TE.chainW(flow(collectionsRunnerResult, collectionsRunnerExit, TE.of)),
|
TE.chainW(flow(collectionsRunnerResult, collectionsRunnerExit, TE.of)),
|
||||||
TE.mapLeft((e) => {
|
TE.mapLeft((e) => {
|
||||||
|
|||||||
@@ -50,6 +50,10 @@ program
|
|||||||
"path to a hoppscotch collection.json file for CI testing"
|
"path to a hoppscotch collection.json file for CI testing"
|
||||||
)
|
)
|
||||||
.option("-e, --env <file_path>", "path to an environment variables json file")
|
.option("-e, --env <file_path>", "path to an environment variables json file")
|
||||||
|
.option(
|
||||||
|
"-d, --delay <delay_in_ms>",
|
||||||
|
"delay in milliseconds(ms) between consecutive requests within a collection"
|
||||||
|
)
|
||||||
.allowExcessArguments(false)
|
.allowExcessArguments(false)
|
||||||
.allowUnknownOption(false)
|
.allowUnknownOption(false)
|
||||||
.description("running hoppscotch collection.json file")
|
.description("running hoppscotch collection.json file")
|
||||||
|
|||||||
20
packages/hoppscotch-cli/src/options/test/delay.ts
Normal file
20
packages/hoppscotch-cli/src/options/test/delay.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import * as TE from "fp-ts/TaskEither";
|
||||||
|
import * as S from "fp-ts/string";
|
||||||
|
import { pipe } from "fp-ts/function";
|
||||||
|
import { error, HoppCLIError } from "../../types/errors";
|
||||||
|
|
||||||
|
export const parseDelayOption = (
|
||||||
|
delay: unknown
|
||||||
|
): TE.TaskEither<HoppCLIError, number> =>
|
||||||
|
!S.isString(delay)
|
||||||
|
? TE.right(0)
|
||||||
|
: pipe(
|
||||||
|
delay,
|
||||||
|
Number,
|
||||||
|
TE.fromPredicate(Number.isSafeInteger, () =>
|
||||||
|
error({
|
||||||
|
code: "INVALID_ARGUMENT",
|
||||||
|
data: "Expected '-d, --delay' value to be number",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
@@ -4,6 +4,7 @@ import { HoppEnvs } from "./request";
|
|||||||
export type CollectionRunnerParam = {
|
export type CollectionRunnerParam = {
|
||||||
collections: HoppCollection<HoppRESTRequest>[];
|
collections: HoppCollection<HoppRESTRequest>[];
|
||||||
envs: HoppEnvs;
|
envs: HoppEnvs;
|
||||||
|
delay?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type HoppCollectionFileExt = "json";
|
export type HoppCollectionFileExt = "json";
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
export type TestCmdOptions = {
|
export type TestCmdOptions = {
|
||||||
env: string;
|
env: string;
|
||||||
|
delay: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type HoppEnvFileExt = "json";
|
export type HoppEnvFileExt = "json";
|
||||||
|
|||||||
@@ -26,3 +26,10 @@ export type RequestReport = {
|
|||||||
result: boolean;
|
result: boolean;
|
||||||
duration: { test: number; request: number; preRequest: number };
|
duration: { test: number; request: number; preRequest: number };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ProcessRequestParams = {
|
||||||
|
request: HoppRESTRequest;
|
||||||
|
envs: HoppEnvs;
|
||||||
|
path: string;
|
||||||
|
delay: number;
|
||||||
|
};
|
||||||
|
|||||||
@@ -5,7 +5,12 @@ import { bold } from "chalk";
|
|||||||
import { log } from "console";
|
import { log } from "console";
|
||||||
import round from "lodash/round";
|
import round from "lodash/round";
|
||||||
import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data";
|
import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data";
|
||||||
import { HoppEnvs, CollectionStack, RequestReport } from "../types/request";
|
import {
|
||||||
|
HoppEnvs,
|
||||||
|
CollectionStack,
|
||||||
|
RequestReport,
|
||||||
|
ProcessRequestParams,
|
||||||
|
} from "../types/request";
|
||||||
import {
|
import {
|
||||||
getRequestMetrics,
|
getRequestMetrics,
|
||||||
preProcessRequest,
|
preProcessRequest,
|
||||||
@@ -41,6 +46,7 @@ export const collectionsRunner =
|
|||||||
(param: CollectionRunnerParam): T.Task<RequestReport[]> =>
|
(param: CollectionRunnerParam): T.Task<RequestReport[]> =>
|
||||||
async () => {
|
async () => {
|
||||||
const envs: HoppEnvs = param.envs;
|
const envs: HoppEnvs = param.envs;
|
||||||
|
const delay = param.delay ?? 0;
|
||||||
const requestsReport: RequestReport[] = [];
|
const requestsReport: RequestReport[] = [];
|
||||||
const collectionStack: CollectionStack[] = getCollectionStack(
|
const collectionStack: CollectionStack[] = getCollectionStack(
|
||||||
param.collections
|
param.collections
|
||||||
@@ -54,12 +60,18 @@ export const collectionsRunner =
|
|||||||
for (const request of collection.requests) {
|
for (const request of collection.requests) {
|
||||||
const _request = preProcessRequest(request);
|
const _request = preProcessRequest(request);
|
||||||
const requestPath = `${path}/${_request.name}`;
|
const requestPath = `${path}/${_request.name}`;
|
||||||
|
const processRequestParams: ProcessRequestParams = {
|
||||||
|
path: requestPath,
|
||||||
|
request: _request,
|
||||||
|
envs,
|
||||||
|
delay,
|
||||||
|
};
|
||||||
|
|
||||||
// Request processing initiated message.
|
// Request processing initiated message.
|
||||||
log(WARN(`\nRunning: ${bold(requestPath)}`));
|
log(WARN(`\nRunning: ${bold(requestPath)}`));
|
||||||
|
|
||||||
// Processing current request.
|
// Processing current request.
|
||||||
const result = await processRequest(_request, envs, requestPath)();
|
const result = await processRequest(processRequestParams)();
|
||||||
|
|
||||||
// Updating global & selected envs with new envs from processed-request output.
|
// Updating global & selected envs with new envs from processed-request output.
|
||||||
const { global, selected } = result.envs;
|
const { global, selected } = result.envs;
|
||||||
|
|||||||
@@ -129,3 +129,8 @@ export const getDurationInSeconds = (
|
|||||||
const durationInSeconds = (end[0] * 1e9 + end[1]) / 1e9;
|
const durationInSeconds = (end[0] * 1e9 + end[1]) / 1e9;
|
||||||
return round(durationInSeconds, precision);
|
return round(durationInSeconds, precision);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const roundDuration = (
|
||||||
|
duration: number,
|
||||||
|
precision: number = DEFAULT_DURATION_PRECISION
|
||||||
|
) => round(duration, precision);
|
||||||
|
|||||||
@@ -12,7 +12,11 @@ import { testRunner, getTestScriptParams, hasFailedTestCases } from "./test";
|
|||||||
import { RequestConfig, EffectiveHoppRESTRequest } from "../interfaces/request";
|
import { RequestConfig, EffectiveHoppRESTRequest } from "../interfaces/request";
|
||||||
import { RequestRunnerResponse } from "../interfaces/response";
|
import { RequestRunnerResponse } from "../interfaces/response";
|
||||||
import { preRequestScriptRunner } from "./pre-request";
|
import { preRequestScriptRunner } from "./pre-request";
|
||||||
import { HoppEnvs, RequestReport } from "../types/request";
|
import {
|
||||||
|
HoppEnvs,
|
||||||
|
ProcessRequestParams,
|
||||||
|
RequestReport,
|
||||||
|
} from "../types/request";
|
||||||
import {
|
import {
|
||||||
printPreRequestRunner,
|
printPreRequestRunner,
|
||||||
printRequestRunner,
|
printRequestRunner,
|
||||||
@@ -189,11 +193,11 @@ const getRequest = {
|
|||||||
*/
|
*/
|
||||||
export const processRequest =
|
export const processRequest =
|
||||||
(
|
(
|
||||||
request: HoppRESTRequest,
|
params: ProcessRequestParams
|
||||||
envs: HoppEnvs,
|
|
||||||
path: string
|
|
||||||
): T.Task<{ envs: HoppEnvs; report: RequestReport }> =>
|
): T.Task<{ envs: HoppEnvs; report: RequestReport }> =>
|
||||||
async () => {
|
async () => {
|
||||||
|
const { envs, path, request, delay } = params;
|
||||||
|
|
||||||
// Initialising updatedEnvs with given parameter envs, will eventually get updated.
|
// Initialising updatedEnvs with given parameter envs, will eventually get updated.
|
||||||
const result = {
|
const result = {
|
||||||
envs: <HoppEnvs>envs,
|
envs: <HoppEnvs>envs,
|
||||||
@@ -247,7 +251,9 @@ export const processRequest =
|
|||||||
duration: 0,
|
duration: 0,
|
||||||
};
|
};
|
||||||
// Executing request-runner.
|
// Executing request-runner.
|
||||||
const requestRunnerRes = await requestRunner(requestConfig)();
|
const requestRunnerRes = await delayPromiseFunction<
|
||||||
|
E.Either<HoppCLIError, RequestRunnerResponse>
|
||||||
|
>(requestRunner(requestConfig), delay);
|
||||||
if (E.isLeft(requestRunnerRes)) {
|
if (E.isLeft(requestRunnerRes)) {
|
||||||
// Updating report for errors & current result
|
// Updating report for errors & current result
|
||||||
report.errors.push(requestRunnerRes.left);
|
report.errors.push(requestRunnerRes.left);
|
||||||
@@ -358,3 +364,15 @@ export const getRequestMetrics = (
|
|||||||
hasReqErrors ? { failed: 1, passed: 0 } : { failed: 0, passed: 1 },
|
hasReqErrors ? { failed: 1, passed: 0 } : { failed: 0, passed: 1 },
|
||||||
(requests) => <RequestMetrics>{ requests, duration }
|
(requests) => <RequestMetrics>{ requests, duration }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function to execute promises with specific delay in milliseconds.
|
||||||
|
* @param func Function with promise with return type T.
|
||||||
|
* @param delay TIme in milliseconds to delay function.
|
||||||
|
* @returns Promise of type same as func.
|
||||||
|
*/
|
||||||
|
export const delayPromiseFunction = <T>(
|
||||||
|
func: () => Promise<T>,
|
||||||
|
delay: number
|
||||||
|
): Promise<T> =>
|
||||||
|
new Promise((resolve) => setTimeout(() => resolve(func()), delay));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@hoppscotch/data",
|
"name": "@hoppscotch/data",
|
||||||
"version": "0.4.2",
|
"version": "0.4.3",
|
||||||
"description": "Data Types, Validations and Migrations for Hoppscotch Public Data Structures",
|
"description": "Data Types, Validations and Migrations for Hoppscotch Public Data Structures",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"module": "true",
|
"module": "true",
|
||||||
|
|||||||
@@ -9,7 +9,13 @@ export type Environment = {
|
|||||||
}[]
|
}[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Variables = {
|
||||||
|
key: string
|
||||||
|
value: string
|
||||||
|
}[]
|
||||||
|
|
||||||
const REGEX_ENV_VAR = /<<([^>]*)>>/g // "<<myVariable>>"
|
const REGEX_ENV_VAR = /<<([^>]*)>>/g // "<<myVariable>>"
|
||||||
|
const REGEX_MY_VAR = /{{([^}]*)}}/g // "{{myVariable}}"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How much times can we expand environment variables
|
* How much times can we expand environment variables
|
||||||
@@ -59,26 +65,37 @@ export const parseBodyEnvVariables = (
|
|||||||
|
|
||||||
export function parseTemplateStringE(
|
export function parseTemplateStringE(
|
||||||
str: string,
|
str: string,
|
||||||
variables: Environment["variables"]
|
variables: Environment["variables"],
|
||||||
|
myVariables?: Variables | undefined
|
||||||
) {
|
) {
|
||||||
|
|
||||||
if (!variables || !str) {
|
if (!variables || !str) {
|
||||||
return E.right(str)
|
return E.right(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = str
|
let result = str
|
||||||
let depth = 0
|
let depthEnv = 0
|
||||||
|
let depthVar = 0
|
||||||
|
|
||||||
while (result.match(REGEX_ENV_VAR) != null && depth <= ENV_MAX_EXPAND_LIMIT) {
|
while (result.match(REGEX_ENV_VAR) != null && depthEnv <= ENV_MAX_EXPAND_LIMIT) {
|
||||||
result = decodeURI(encodeURI(result)).replace(
|
result = decodeURI(encodeURI(result)).replace(
|
||||||
REGEX_ENV_VAR,
|
REGEX_ENV_VAR,
|
||||||
(_, p1) => variables.find((x) => x.key === p1)?.value || ""
|
(_, p1) => variables.find((x) => x.key === p1)?.value || ""
|
||||||
)
|
)
|
||||||
depth++
|
depthEnv++
|
||||||
}
|
}
|
||||||
|
|
||||||
return depth > ENV_MAX_EXPAND_LIMIT
|
if (myVariables) {
|
||||||
? E.left(ENV_EXPAND_LOOP)
|
while (result.match(REGEX_MY_VAR) != null && depthVar <= ENV_MAX_EXPAND_LIMIT) {
|
||||||
: E.right(result)
|
result = decodeURI(encodeURI(result)).replace(
|
||||||
|
REGEX_MY_VAR,
|
||||||
|
(_, p1) => myVariables.find((x) => x.key === p1)?.value || ""
|
||||||
|
)
|
||||||
|
depthVar++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return depthEnv <= ENV_MAX_EXPAND_LIMIT && depthVar <= ENV_MAX_EXPAND_LIMIT ? E.right(result) : E.left(ENV_EXPAND_LOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -86,9 +103,33 @@ export function parseTemplateStringE(
|
|||||||
*/
|
*/
|
||||||
export const parseTemplateString = (
|
export const parseTemplateString = (
|
||||||
str: string,
|
str: string,
|
||||||
variables: Environment["variables"]
|
variables: Environment["variables"],
|
||||||
|
myVariables?: Variables
|
||||||
) =>
|
) =>
|
||||||
pipe(
|
pipe(
|
||||||
parseTemplateStringE(str, variables),
|
parseTemplateStringE(str, variables, myVariables),
|
||||||
E.getOrElse(() => str)
|
E.getOrElse(() => str)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export function parseMyVariablesString(
|
||||||
|
str: string,
|
||||||
|
variables: Variables,
|
||||||
|
) {
|
||||||
|
|
||||||
|
if (!variables || !str) {
|
||||||
|
return E.right(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = str
|
||||||
|
let depthVar = 0
|
||||||
|
|
||||||
|
while (result.match(REGEX_MY_VAR) != null && depthVar <= ENV_MAX_EXPAND_LIMIT) {
|
||||||
|
result = decodeURI(encodeURI(result)).replace(
|
||||||
|
REGEX_MY_VAR,
|
||||||
|
(_, p1) => variables.find((x) => x.key === p1)?.value || ""
|
||||||
|
)
|
||||||
|
depthVar++
|
||||||
|
}
|
||||||
|
|
||||||
|
return depthVar <= ENV_MAX_EXPAND_LIMIT ? E.right(result) : E.left(ENV_EXPAND_LOOP);
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,12 @@ import * as E from "fp-ts/Either"
|
|||||||
import * as P from "parser-ts/Parser"
|
import * as P from "parser-ts/Parser"
|
||||||
import * as S from "parser-ts/string"
|
import * as S from "parser-ts/string"
|
||||||
import * as C from "parser-ts/char"
|
import * as C from "parser-ts/char"
|
||||||
|
import { recordUpdate } from "./utils/record"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special characters in the Raw Key Value Grammar
|
||||||
|
*/
|
||||||
|
const SPECIAL_CHARS = ["#", ":"] as const
|
||||||
|
|
||||||
export type RawKeyValueEntry = {
|
export type RawKeyValueEntry = {
|
||||||
key: string
|
key: string
|
||||||
@@ -31,14 +37,31 @@ const stringTakeUntilCharsInclusive = flow(
|
|||||||
P.chainFirst(() => P.sat(() => true)),
|
P.chainFirst(() => P.sat(() => true)),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const quotedString = pipe(
|
||||||
|
S.doubleQuotedString,
|
||||||
|
P.map((x) => JSON.parse(`"${x}"`))
|
||||||
|
)
|
||||||
|
|
||||||
const key = pipe(
|
const key = pipe(
|
||||||
stringTakeUntilChars([":", "\n"]),
|
wsSurround(quotedString),
|
||||||
P.map(Str.trim)
|
|
||||||
|
P.alt(() =>
|
||||||
|
pipe(
|
||||||
|
stringTakeUntilChars([":", "\n"]),
|
||||||
|
P.map(Str.trim)
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
const value = pipe(
|
const value = pipe(
|
||||||
stringTakeUntilChars(["\n"]),
|
wsSurround(quotedString),
|
||||||
P.map(Str.trim)
|
|
||||||
|
P.alt(() =>
|
||||||
|
pipe(
|
||||||
|
stringTakeUntilChars(["\n"]),
|
||||||
|
P.map(Str.trim)
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
const commented = pipe(
|
const commented = pipe(
|
||||||
@@ -105,6 +128,37 @@ const tolerantFile = pipe(
|
|||||||
|
|
||||||
/* End of Parser Definitions */
|
/* End of Parser Definitions */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect whether the string needs to have escape characters in raw key value strings
|
||||||
|
* @param input The string to check against
|
||||||
|
*/
|
||||||
|
const stringNeedsEscapingForRawKVString = (input: string) => {
|
||||||
|
// If there are any of our special characters, it needs to be escaped definitely
|
||||||
|
if (SPECIAL_CHARS.some((x) => input.includes(x)))
|
||||||
|
return true
|
||||||
|
|
||||||
|
// The theory behind this impl is that if we apply JSON.stringify on a string
|
||||||
|
// it does escaping and then return a JSON string representation.
|
||||||
|
// We remove the quotes of the JSON and see if it can be matched against the input string
|
||||||
|
const stringified = JSON.stringify(input)
|
||||||
|
|
||||||
|
const y = stringified
|
||||||
|
.substring(1, stringified.length - 1)
|
||||||
|
.trim()
|
||||||
|
|
||||||
|
return y !== input
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies Raw Key Value escaping (via quotes + escape chars) if needed
|
||||||
|
* @param input The input to apply escape on
|
||||||
|
* @returns If needed, the escaped string, else the input string itself
|
||||||
|
*/
|
||||||
|
const applyEscapeIfNeeded = (input: string) =>
|
||||||
|
stringNeedsEscapingForRawKVString(input)
|
||||||
|
? JSON.stringify(input)
|
||||||
|
: input
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts Raw Key Value Entries to the file string format
|
* Converts Raw Key Value Entries to the file string format
|
||||||
* @param entries The entries array
|
* @param entries The entries array
|
||||||
@@ -113,8 +167,13 @@ const tolerantFile = pipe(
|
|||||||
export const rawKeyValueEntriesToString = (entries: RawKeyValueEntry[]) =>
|
export const rawKeyValueEntriesToString = (entries: RawKeyValueEntry[]) =>
|
||||||
pipe(
|
pipe(
|
||||||
entries,
|
entries,
|
||||||
A.map(({ key, value, active }) =>
|
A.map(
|
||||||
active ? `${key}: ${value}` : `# ${key}: ${value}`
|
flow(
|
||||||
|
recordUpdate("key", applyEscapeIfNeeded),
|
||||||
|
recordUpdate("value", applyEscapeIfNeeded),
|
||||||
|
({ key, value, active }) =>
|
||||||
|
active ? `${(key)}: ${value}` : `# ${key}: ${value}`
|
||||||
|
)
|
||||||
),
|
),
|
||||||
stringArrayJoin("\n")
|
stringArrayJoin("\n")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -16,6 +16,11 @@ export type HoppRESTParam = {
|
|||||||
active: boolean
|
active: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type HoppRESTVar = {
|
||||||
|
key: string
|
||||||
|
value: string
|
||||||
|
}
|
||||||
|
|
||||||
export type HoppRESTHeader = {
|
export type HoppRESTHeader = {
|
||||||
key: string
|
key: string
|
||||||
value: string
|
value: string
|
||||||
@@ -51,6 +56,7 @@ export interface HoppRESTRequest {
|
|||||||
method: string
|
method: string
|
||||||
endpoint: string
|
endpoint: string
|
||||||
params: HoppRESTParam[]
|
params: HoppRESTParam[]
|
||||||
|
vars: HoppRESTVar[]
|
||||||
headers: HoppRESTHeader[]
|
headers: HoppRESTHeader[]
|
||||||
preRequestScript: string
|
preRequestScript: string
|
||||||
testScript: string
|
testScript: string
|
||||||
@@ -74,6 +80,10 @@ export const HoppRESTRequestEq = Eq.struct<HoppRESTRequest>({
|
|||||||
(arr) => arr.filter((p) => p.key !== "" && p.value !== ""),
|
(arr) => arr.filter((p) => p.key !== "" && p.value !== ""),
|
||||||
lodashIsEqualEq
|
lodashIsEqualEq
|
||||||
),
|
),
|
||||||
|
vars: mapThenEq(
|
||||||
|
(arr) => arr.filter((v) => v.key !== "" && v.value !== ""),
|
||||||
|
lodashIsEqualEq
|
||||||
|
),
|
||||||
method: S.Eq,
|
method: S.Eq,
|
||||||
name: S.Eq,
|
name: S.Eq,
|
||||||
preRequestScript: S.Eq,
|
preRequestScript: S.Eq,
|
||||||
@@ -126,6 +136,9 @@ export function safelyExtractRESTRequest(
|
|||||||
if (x.hasOwnProperty("params") && Array.isArray(x.params))
|
if (x.hasOwnProperty("params") && Array.isArray(x.params))
|
||||||
req.params = x.params // TODO: Deep nested checks
|
req.params = x.params // TODO: Deep nested checks
|
||||||
|
|
||||||
|
if (x.hasOwnProperty("vars") && Array.isArray(x.vars))
|
||||||
|
req.vars = x.vars // TODO: Deep nested checks
|
||||||
|
|
||||||
if (x.hasOwnProperty("headers") && Array.isArray(x.headers))
|
if (x.hasOwnProperty("headers") && Array.isArray(x.headers))
|
||||||
req.headers = x.headers // TODO: Deep nested checks
|
req.headers = x.headers // TODO: Deep nested checks
|
||||||
}
|
}
|
||||||
@@ -186,6 +199,19 @@ export function translateToNewRequest(x: any): HoppRESTRequest {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const vars: HoppRESTVar[] = (x?.vars ?? []).map(
|
||||||
|
({
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
}: {
|
||||||
|
key: string
|
||||||
|
value: string
|
||||||
|
}) => ({
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
const name = x?.name ?? "Untitled request"
|
const name = x?.name ?? "Untitled request"
|
||||||
const method = x?.method ?? ""
|
const method = x?.method ?? ""
|
||||||
|
|
||||||
@@ -201,6 +227,7 @@ export function translateToNewRequest(x: any): HoppRESTRequest {
|
|||||||
endpoint,
|
endpoint,
|
||||||
headers,
|
headers,
|
||||||
params,
|
params,
|
||||||
|
vars,
|
||||||
method,
|
method,
|
||||||
preRequestScript,
|
preRequestScript,
|
||||||
testScript,
|
testScript,
|
||||||
|
|||||||
17
packages/hoppscotch-data/src/utils/record.ts
Normal file
17
packages/hoppscotch-data/src/utils/record.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* Modify a record value with a mapping function
|
||||||
|
* @param name The key to update
|
||||||
|
* @param func The value to update
|
||||||
|
* @returns The updated record
|
||||||
|
*/
|
||||||
|
export const recordUpdate =
|
||||||
|
<
|
||||||
|
X extends {},
|
||||||
|
K extends keyof X,
|
||||||
|
R
|
||||||
|
>(name: K, func: (input: X[K]) => R) =>
|
||||||
|
(x: X): Omit<X, K> & { [x in K]: R } => ({
|
||||||
|
...x,
|
||||||
|
[name]: func(x[name])
|
||||||
|
})
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
"author": "Hoppscotch (support@hoppscotch.io)",
|
"author": "Hoppscotch (support@hoppscotch.io)",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hoppscotch/data": "workspace:^0.4.2",
|
"@hoppscotch/data": "workspace:^0.4.3",
|
||||||
"fp-ts": "^2.11.10",
|
"fp-ts": "^2.11.10",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"quickjs-emscripten": "^0.15.0",
|
"quickjs-emscripten": "^0.15.0",
|
||||||
|
|||||||
376
pnpm-lock.yaml
generated
376
pnpm-lock.yaml
generated
@@ -76,7 +76,7 @@ importers:
|
|||||||
'@graphql-codegen/urql-introspection': ^2.1.1
|
'@graphql-codegen/urql-introspection': ^2.1.1
|
||||||
'@graphql-typed-document-node/core': ^3.1.1
|
'@graphql-typed-document-node/core': ^3.1.1
|
||||||
'@hoppscotch/codemirror-lang-graphql': workspace:^0.2.0
|
'@hoppscotch/codemirror-lang-graphql': workspace:^0.2.0
|
||||||
'@hoppscotch/data': workspace:^0.4.2
|
'@hoppscotch/data': workspace:^0.4.3
|
||||||
'@hoppscotch/js-sandbox': workspace:^2.0.0
|
'@hoppscotch/js-sandbox': workspace:^2.0.0
|
||||||
'@nuxt/types': ^2.15.8
|
'@nuxt/types': ^2.15.8
|
||||||
'@nuxt/typescript-build': ^2.1.0
|
'@nuxt/typescript-build': ^2.1.0
|
||||||
@@ -357,7 +357,7 @@ importers:
|
|||||||
|
|
||||||
packages/hoppscotch-cli:
|
packages/hoppscotch-cli:
|
||||||
specifiers:
|
specifiers:
|
||||||
'@hoppscotch/data': workspace:^0.4.2
|
'@hoppscotch/data': workspace:^0.4.3
|
||||||
'@hoppscotch/js-sandbox': workspace:^2.0.0
|
'@hoppscotch/js-sandbox': workspace:^2.0.0
|
||||||
'@relmify/jest-fp-ts': ^2.0.2
|
'@relmify/jest-fp-ts': ^2.0.2
|
||||||
'@swc/core': ^1.2.181
|
'@swc/core': ^1.2.181
|
||||||
@@ -427,7 +427,7 @@ importers:
|
|||||||
packages/hoppscotch-js-sandbox:
|
packages/hoppscotch-js-sandbox:
|
||||||
specifiers:
|
specifiers:
|
||||||
'@digitak/esrun': ^3.1.2
|
'@digitak/esrun': ^3.1.2
|
||||||
'@hoppscotch/data': workspace:^0.4.2
|
'@hoppscotch/data': workspace:^0.4.3
|
||||||
'@relmify/jest-fp-ts': ^2.0.1
|
'@relmify/jest-fp-ts': ^2.0.1
|
||||||
'@types/jest': ^27.4.1
|
'@types/jest': ^27.4.1
|
||||||
'@types/lodash': ^4.14.181
|
'@types/lodash': ^4.14.181
|
||||||
@@ -539,6 +539,13 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/highlight': 7.17.9
|
'@babel/highlight': 7.17.9
|
||||||
|
|
||||||
|
/@babel/code-frame/7.18.6:
|
||||||
|
resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
dependencies:
|
||||||
|
'@babel/highlight': 7.18.6
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/compat-data/7.16.0:
|
/@babel/compat-data/7.16.0:
|
||||||
resolution: {integrity: sha512-DGjt2QZse5SGd9nfOSqO4WLJ8NN/oHkijbXbPrxuoJO3oIPJL3TciZs9FX+cOHNiY9E9l0opL8g7BmLe3T+9ew==}
|
resolution: {integrity: sha512-DGjt2QZse5SGd9nfOSqO4WLJ8NN/oHkijbXbPrxuoJO3oIPJL3TciZs9FX+cOHNiY9E9l0opL8g7BmLe3T+9ew==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -556,6 +563,11 @@ packages:
|
|||||||
resolution: {integrity: sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==}
|
resolution: {integrity: sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
|
/@babel/compat-data/7.18.8:
|
||||||
|
resolution: {integrity: sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/core/7.17.9:
|
/@babel/core/7.17.9:
|
||||||
resolution: {integrity: sha512-5ug+SfZCpDAkVp9SFIZAzlW18rlzsOcJGaetCjkySnrXXDUw9AR8cDUm1iByTmdWM6yxX6/zycaV76w3YTF2gw==}
|
resolution: {integrity: sha512-5ug+SfZCpDAkVp9SFIZAzlW18rlzsOcJGaetCjkySnrXXDUw9AR8cDUm1iByTmdWM6yxX6/zycaV76w3YTF2gw==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -578,6 +590,29 @@ packages:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
/@babel/core/7.18.10:
|
||||||
|
resolution: {integrity: sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
dependencies:
|
||||||
|
'@ampproject/remapping': 2.1.2
|
||||||
|
'@babel/code-frame': 7.18.6
|
||||||
|
'@babel/generator': 7.18.12
|
||||||
|
'@babel/helper-compilation-targets': 7.18.9_@babel+core@7.18.10
|
||||||
|
'@babel/helper-module-transforms': 7.18.9
|
||||||
|
'@babel/helpers': 7.18.9
|
||||||
|
'@babel/parser': 7.18.11
|
||||||
|
'@babel/template': 7.18.10
|
||||||
|
'@babel/traverse': 7.18.11
|
||||||
|
'@babel/types': 7.18.10
|
||||||
|
convert-source-map: 1.8.0
|
||||||
|
debug: 4.3.4
|
||||||
|
gensync: 1.0.0-beta.2
|
||||||
|
json5: 2.2.1
|
||||||
|
semver: 6.3.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/generator/7.16.5:
|
/@babel/generator/7.16.5:
|
||||||
resolution: {integrity: sha512-kIvCdjZqcdKqoDbVVdt5R99icaRtrtYhYK/xux5qiWCBmfdvEYMFZ68QCrpE5cbFM1JsuArUNs1ZkuKtTtUcZA==}
|
resolution: {integrity: sha512-kIvCdjZqcdKqoDbVVdt5R99icaRtrtYhYK/xux5qiWCBmfdvEYMFZ68QCrpE5cbFM1JsuArUNs1ZkuKtTtUcZA==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -594,6 +629,15 @@ packages:
|
|||||||
jsesc: 2.5.2
|
jsesc: 2.5.2
|
||||||
source-map: 0.5.7
|
source-map: 0.5.7
|
||||||
|
|
||||||
|
/@babel/generator/7.18.12:
|
||||||
|
resolution: {integrity: sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
dependencies:
|
||||||
|
'@babel/types': 7.18.10
|
||||||
|
'@jridgewell/gen-mapping': 0.3.2
|
||||||
|
jsesc: 2.5.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/helper-annotate-as-pure/7.16.7:
|
/@babel/helper-annotate-as-pure/7.16.7:
|
||||||
resolution: {integrity: sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==}
|
resolution: {integrity: sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -631,6 +675,19 @@ packages:
|
|||||||
browserslist: 4.20.2
|
browserslist: 4.20.2
|
||||||
semver: 6.3.0
|
semver: 6.3.0
|
||||||
|
|
||||||
|
/@babel/helper-compilation-targets/7.18.9_@babel+core@7.18.10:
|
||||||
|
resolution: {integrity: sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/core': ^7.0.0
|
||||||
|
dependencies:
|
||||||
|
'@babel/compat-data': 7.18.8
|
||||||
|
'@babel/core': 7.18.10
|
||||||
|
'@babel/helper-validator-option': 7.18.6
|
||||||
|
browserslist: 4.20.2
|
||||||
|
semver: 6.3.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/helper-create-class-features-plugin/7.16.10_@babel+core@7.17.9:
|
/@babel/helper-create-class-features-plugin/7.16.10_@babel+core@7.17.9:
|
||||||
resolution: {integrity: sha512-wDeej0pu3WN/ffTxMNCPW5UCiOav8IcLRxSIyp/9+IF2xJUM9h/OYjg0IJLHaL6F8oU8kqMz9nc1vryXhMsgXg==}
|
resolution: {integrity: sha512-wDeej0pu3WN/ffTxMNCPW5UCiOav8IcLRxSIyp/9+IF2xJUM9h/OYjg0IJLHaL6F8oU8kqMz9nc1vryXhMsgXg==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -716,6 +773,11 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/types': 7.17.0
|
'@babel/types': 7.17.0
|
||||||
|
|
||||||
|
/@babel/helper-environment-visitor/7.18.9:
|
||||||
|
resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/helper-explode-assignable-expression/7.16.7:
|
/@babel/helper-explode-assignable-expression/7.16.7:
|
||||||
resolution: {integrity: sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==}
|
resolution: {integrity: sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -745,6 +807,14 @@ packages:
|
|||||||
'@babel/template': 7.16.7
|
'@babel/template': 7.16.7
|
||||||
'@babel/types': 7.17.0
|
'@babel/types': 7.17.0
|
||||||
|
|
||||||
|
/@babel/helper-function-name/7.18.9:
|
||||||
|
resolution: {integrity: sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
dependencies:
|
||||||
|
'@babel/template': 7.18.10
|
||||||
|
'@babel/types': 7.18.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/helper-get-function-arity/7.16.0:
|
/@babel/helper-get-function-arity/7.16.0:
|
||||||
resolution: {integrity: sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ==}
|
resolution: {integrity: sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -769,6 +839,13 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/types': 7.17.0
|
'@babel/types': 7.17.0
|
||||||
|
|
||||||
|
/@babel/helper-hoist-variables/7.18.6:
|
||||||
|
resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
dependencies:
|
||||||
|
'@babel/types': 7.18.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/helper-member-expression-to-functions/7.16.7:
|
/@babel/helper-member-expression-to-functions/7.16.7:
|
||||||
resolution: {integrity: sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==}
|
resolution: {integrity: sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -788,6 +865,13 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/types': 7.17.0
|
'@babel/types': 7.17.0
|
||||||
|
|
||||||
|
/@babel/helper-module-imports/7.18.6:
|
||||||
|
resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
dependencies:
|
||||||
|
'@babel/types': 7.18.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/helper-module-transforms/7.16.7:
|
/@babel/helper-module-transforms/7.16.7:
|
||||||
resolution: {integrity: sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==}
|
resolution: {integrity: sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -818,6 +902,22 @@ packages:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
/@babel/helper-module-transforms/7.18.9:
|
||||||
|
resolution: {integrity: sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
dependencies:
|
||||||
|
'@babel/helper-environment-visitor': 7.18.9
|
||||||
|
'@babel/helper-module-imports': 7.18.6
|
||||||
|
'@babel/helper-simple-access': 7.18.6
|
||||||
|
'@babel/helper-split-export-declaration': 7.18.6
|
||||||
|
'@babel/helper-validator-identifier': 7.18.6
|
||||||
|
'@babel/template': 7.18.10
|
||||||
|
'@babel/traverse': 7.18.11
|
||||||
|
'@babel/types': 7.18.10
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/helper-optimise-call-expression/7.16.7:
|
/@babel/helper-optimise-call-expression/7.16.7:
|
||||||
resolution: {integrity: sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==}
|
resolution: {integrity: sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -862,6 +962,13 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/types': 7.17.0
|
'@babel/types': 7.17.0
|
||||||
|
|
||||||
|
/@babel/helper-simple-access/7.18.6:
|
||||||
|
resolution: {integrity: sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
dependencies:
|
||||||
|
'@babel/types': 7.18.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/helper-skip-transparent-expression-wrappers/7.16.0:
|
/@babel/helper-skip-transparent-expression-wrappers/7.16.0:
|
||||||
resolution: {integrity: sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==}
|
resolution: {integrity: sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -880,14 +987,36 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/types': 7.17.0
|
'@babel/types': 7.17.0
|
||||||
|
|
||||||
|
/@babel/helper-split-export-declaration/7.18.6:
|
||||||
|
resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
dependencies:
|
||||||
|
'@babel/types': 7.18.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@babel/helper-string-parser/7.18.10:
|
||||||
|
resolution: {integrity: sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/helper-validator-identifier/7.16.7:
|
/@babel/helper-validator-identifier/7.16.7:
|
||||||
resolution: {integrity: sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==}
|
resolution: {integrity: sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
|
/@babel/helper-validator-identifier/7.18.6:
|
||||||
|
resolution: {integrity: sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/helper-validator-option/7.16.7:
|
/@babel/helper-validator-option/7.16.7:
|
||||||
resolution: {integrity: sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==}
|
resolution: {integrity: sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
|
/@babel/helper-validator-option/7.18.6:
|
||||||
|
resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/helper-wrap-function/7.16.8:
|
/@babel/helper-wrap-function/7.16.8:
|
||||||
resolution: {integrity: sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==}
|
resolution: {integrity: sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -909,6 +1038,17 @@ packages:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
/@babel/helpers/7.18.9:
|
||||||
|
resolution: {integrity: sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
dependencies:
|
||||||
|
'@babel/template': 7.18.10
|
||||||
|
'@babel/traverse': 7.18.11
|
||||||
|
'@babel/types': 7.18.10
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/highlight/7.17.9:
|
/@babel/highlight/7.17.9:
|
||||||
resolution: {integrity: sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==}
|
resolution: {integrity: sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -917,6 +1057,15 @@ packages:
|
|||||||
chalk: 2.4.2
|
chalk: 2.4.2
|
||||||
js-tokens: 4.0.0
|
js-tokens: 4.0.0
|
||||||
|
|
||||||
|
/@babel/highlight/7.18.6:
|
||||||
|
resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
dependencies:
|
||||||
|
'@babel/helper-validator-identifier': 7.18.6
|
||||||
|
chalk: 2.4.2
|
||||||
|
js-tokens: 4.0.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/parser/7.16.2:
|
/@babel/parser/7.16.2:
|
||||||
resolution: {integrity: sha512-RUVpT0G2h6rOZwqLDTrKk7ksNv7YpAilTnYe1/Q+eDjxEceRMKVWbCsX7t8h6C1qCFi/1Y8WZjcEPBAFG27GPw==}
|
resolution: {integrity: sha512-RUVpT0G2h6rOZwqLDTrKk7ksNv7YpAilTnYe1/Q+eDjxEceRMKVWbCsX7t8h6C1qCFi/1Y8WZjcEPBAFG27GPw==}
|
||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
@@ -940,6 +1089,14 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/types': 7.17.0
|
'@babel/types': 7.17.0
|
||||||
|
|
||||||
|
/@babel/parser/7.18.11:
|
||||||
|
resolution: {integrity: sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==}
|
||||||
|
engines: {node: '>=6.0.0'}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
'@babel/types': 7.18.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.16.7_@babel+core@7.17.9:
|
/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.16.7_@babel+core@7.17.9:
|
||||||
resolution: {integrity: sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==}
|
resolution: {integrity: sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -1844,8 +2001,8 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime: 0.13.9
|
regenerator-runtime: 0.13.9
|
||||||
|
|
||||||
/@babel/standalone/7.17.9:
|
/@babel/standalone/7.18.12:
|
||||||
resolution: {integrity: sha512-9wL9AtDlga8avxUrBvQJmhUtJWrelsUL0uV+TcP+49Sb6Pj8/bNIzQzU4dDp0NAPOvnZR/7msFIKsKoCl/W1/w==}
|
resolution: {integrity: sha512-wDh3K5IUJiSMAY0MLYBFoCaj2RCZwvDz5BHn2uHat9KOsGWEVDFgFQFIOO+81Js2phFKNppLC45iOCsZVfJniw==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
@@ -1863,6 +2020,15 @@ packages:
|
|||||||
debug: 4.3.3
|
debug: 4.3.3
|
||||||
globals: 11.12.0
|
globals: 11.12.0
|
||||||
|
|
||||||
|
/@babel/template/7.18.10:
|
||||||
|
resolution: {integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
dependencies:
|
||||||
|
'@babel/code-frame': 7.18.6
|
||||||
|
'@babel/parser': 7.18.11
|
||||||
|
'@babel/types': 7.18.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/traverse/7.17.3:
|
/@babel/traverse/7.17.3:
|
||||||
resolution: {integrity: sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==}
|
resolution: {integrity: sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -1898,6 +2064,24 @@ packages:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
/@babel/traverse/7.18.11:
|
||||||
|
resolution: {integrity: sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
dependencies:
|
||||||
|
'@babel/code-frame': 7.18.6
|
||||||
|
'@babel/generator': 7.18.12
|
||||||
|
'@babel/helper-environment-visitor': 7.18.9
|
||||||
|
'@babel/helper-function-name': 7.18.9
|
||||||
|
'@babel/helper-hoist-variables': 7.18.6
|
||||||
|
'@babel/helper-split-export-declaration': 7.18.6
|
||||||
|
'@babel/parser': 7.18.11
|
||||||
|
'@babel/types': 7.18.10
|
||||||
|
debug: 4.3.4
|
||||||
|
globals: 11.12.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@babel/types/7.16.0:
|
/@babel/types/7.16.0:
|
||||||
resolution: {integrity: sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==}
|
resolution: {integrity: sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -1920,6 +2104,15 @@ packages:
|
|||||||
'@babel/helper-validator-identifier': 7.16.7
|
'@babel/helper-validator-identifier': 7.16.7
|
||||||
to-fast-properties: 2.0.0
|
to-fast-properties: 2.0.0
|
||||||
|
|
||||||
|
/@babel/types/7.18.10:
|
||||||
|
resolution: {integrity: sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==}
|
||||||
|
engines: {node: '>=6.9.0'}
|
||||||
|
dependencies:
|
||||||
|
'@babel/helper-string-parser': 7.18.10
|
||||||
|
'@babel/helper-validator-identifier': 7.18.6
|
||||||
|
to-fast-properties: 2.0.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@bcoe/v8-coverage/0.2.3:
|
/@bcoe/v8-coverage/0.2.3:
|
||||||
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
|
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -3715,13 +3908,34 @@ packages:
|
|||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@jridgewell/gen-mapping/0.3.2:
|
||||||
|
resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==}
|
||||||
|
engines: {node: '>=6.0.0'}
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/set-array': 1.1.2
|
||||||
|
'@jridgewell/sourcemap-codec': 1.4.11
|
||||||
|
'@jridgewell/trace-mapping': 0.3.15
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@jridgewell/resolve-uri/3.0.5:
|
/@jridgewell/resolve-uri/3.0.5:
|
||||||
resolution: {integrity: sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==}
|
resolution: {integrity: sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==}
|
||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
|
|
||||||
|
/@jridgewell/set-array/1.1.2:
|
||||||
|
resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
|
||||||
|
engines: {node: '>=6.0.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@jridgewell/sourcemap-codec/1.4.11:
|
/@jridgewell/sourcemap-codec/1.4.11:
|
||||||
resolution: {integrity: sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==}
|
resolution: {integrity: sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==}
|
||||||
|
|
||||||
|
/@jridgewell/trace-mapping/0.3.15:
|
||||||
|
resolution: {integrity: sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==}
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/resolve-uri': 3.0.5
|
||||||
|
'@jridgewell/sourcemap-codec': 1.4.11
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@jridgewell/trace-mapping/0.3.4:
|
/@jridgewell/trace-mapping/0.3.4:
|
||||||
resolution: {integrity: sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==}
|
resolution: {integrity: sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -4028,12 +4242,12 @@ packages:
|
|||||||
ufo: 0.7.11
|
ufo: 0.7.11
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@nuxt/kit-edge/3.0.0-rc.4-27605536.8c2c80e:
|
/@nuxt/kit-edge/3.0.0-rc.7-27670958.b0bf25c:
|
||||||
resolution: {integrity: sha512-Fu9ygT3Gi5zbthzZC5PVzaDhVUxLunF1mgfF9b7RoHaO+UoQSWI7AptRwx2jxkUHpftLZjELtDV6MW96xZiWqg==}
|
resolution: {integrity: sha512-4sbICutKR7fOgnva7M6QBdwwDkMFULgaTafZ1oen+av+LTsOJVdNruPjlEKLhn/6gfLmxT3cLuY61jhTz4qP7A==}
|
||||||
engines: {node: ^14.16.0 || ^16.11.0 || ^17.0.0 || ^18.0.0}
|
engines: {node: ^14.16.0 || ^16.11.0 || ^17.0.0 || ^18.0.0}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nuxt/schema': /@nuxt/schema-edge/3.0.0-rc.4-27605536.8c2c80e
|
'@nuxt/schema': /@nuxt/schema-edge/3.0.0-rc.7-27670958.b0bf25c
|
||||||
c12: 0.2.7
|
c12: 0.2.9
|
||||||
consola: 2.15.3
|
consola: 2.15.3
|
||||||
defu: 6.0.0
|
defu: 6.0.0
|
||||||
globby: 13.1.2
|
globby: 13.1.2
|
||||||
@@ -4042,14 +4256,14 @@ packages:
|
|||||||
jiti: 1.14.0
|
jiti: 1.14.0
|
||||||
knitwork: 0.1.2
|
knitwork: 0.1.2
|
||||||
lodash.template: 4.5.0
|
lodash.template: 4.5.0
|
||||||
mlly: 0.5.3
|
mlly: 0.5.10
|
||||||
pathe: 0.3.0
|
pathe: 0.3.4
|
||||||
pkg-types: 0.3.3
|
pkg-types: 0.3.3
|
||||||
scule: 0.2.1
|
scule: 0.3.2
|
||||||
semver: 7.3.7
|
semver: 7.3.7
|
||||||
unctx: 1.1.4
|
unctx: 2.0.1
|
||||||
unimport: 0.3.0
|
unimport: 0.6.7
|
||||||
untyped: 0.4.4
|
untyped: 0.4.5
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- esbuild
|
- esbuild
|
||||||
- rollup
|
- rollup
|
||||||
@@ -4082,20 +4296,20 @@ packages:
|
|||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@nuxt/schema-edge/3.0.0-rc.4-27605536.8c2c80e:
|
/@nuxt/schema-edge/3.0.0-rc.7-27670958.b0bf25c:
|
||||||
resolution: {integrity: sha512-KOFpjN2efx9lXj84kSHhJV/XWJ8n0zztnJjjmEY3RhgBTd7mYtdI7BsYPtZ30Tz5vJGMlHrIGkLZW6c+IYAKzw==}
|
resolution: {integrity: sha512-GwZWyVPqpFWNDsPx1zwczv4DIv2ync/0xTTsec8Rnbg14W83apS9vw2GppHpcDAH7R3Hx8a8pHpeg7nPyD9uCg==}
|
||||||
engines: {node: ^14.16.0 || ^16.11.0 || ^17.0.0 || ^18.0.0}
|
engines: {node: ^14.16.0 || ^16.11.0 || ^17.0.0 || ^18.0.0}
|
||||||
dependencies:
|
dependencies:
|
||||||
c12: 0.2.7
|
c12: 0.2.9
|
||||||
create-require: 1.1.1
|
create-require: 1.1.1
|
||||||
defu: 6.0.0
|
defu: 6.0.0
|
||||||
jiti: 1.14.0
|
jiti: 1.14.0
|
||||||
pathe: 0.3.0
|
pathe: 0.3.4
|
||||||
postcss-import-resolver: 2.0.0
|
postcss-import-resolver: 2.0.0
|
||||||
scule: 0.2.1
|
scule: 0.3.2
|
||||||
std-env: 3.1.1
|
std-env: 3.1.1
|
||||||
ufo: 0.8.4
|
ufo: 0.8.5
|
||||||
unimport: 0.3.0
|
unimport: 0.6.7
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- esbuild
|
- esbuild
|
||||||
- rollup
|
- rollup
|
||||||
@@ -6515,6 +6729,12 @@ packages:
|
|||||||
engines: {node: '>=0.4.0'}
|
engines: {node: '>=0.4.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
/acorn/8.8.0:
|
||||||
|
resolution: {integrity: sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==}
|
||||||
|
engines: {node: '>=0.4.0'}
|
||||||
|
hasBin: true
|
||||||
|
dev: true
|
||||||
|
|
||||||
/after/0.8.2:
|
/after/0.8.2:
|
||||||
resolution: {integrity: sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=}
|
resolution: {integrity: sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=}
|
||||||
dev: false
|
dev: false
|
||||||
@@ -7496,15 +7716,15 @@ packages:
|
|||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/c12/0.2.7:
|
/c12/0.2.9:
|
||||||
resolution: {integrity: sha512-ih1nuHbZ6Ltf8Wss96JH6YvKIW5+9+uLAA08LUQAoDrFPGSyvPvQv/QBIRE+dCBWOK4PcwH0ylRkSa9huI1Acw==}
|
resolution: {integrity: sha512-6jYdexgAKr+3kYoTmvC5eDtDHUg7GmFQSdeQqZzAKiPlFAN1heGUoXDbAYYwUCfefZy+WgVJbmAej5TTQpp3jA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
defu: 6.0.0
|
defu: 6.0.0
|
||||||
dotenv: 16.0.0
|
dotenv: 16.0.1
|
||||||
gittar: 0.1.1
|
gittar: 0.1.1
|
||||||
jiti: 1.14.0
|
jiti: 1.14.0
|
||||||
mlly: 0.5.3
|
mlly: 0.5.10
|
||||||
pathe: 0.2.0
|
pathe: 0.3.4
|
||||||
rc9: 1.2.2
|
rc9: 1.2.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
@@ -8250,7 +8470,7 @@ packages:
|
|||||||
lodash: ^4.17.20
|
lodash: ^4.17.20
|
||||||
marko: ^3.14.4
|
marko: ^3.14.4
|
||||||
mote: ^0.2.0
|
mote: ^0.2.0
|
||||||
mustache: ^4.0.1
|
mustache: ^3.0.0
|
||||||
nunjucks: ^3.2.2
|
nunjucks: ^3.2.2
|
||||||
plates: ~0.4.11
|
plates: ~0.4.11
|
||||||
pug: ^3.0.0
|
pug: ^3.0.0
|
||||||
@@ -9376,8 +9596,8 @@ packages:
|
|||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/dotenv/16.0.0:
|
/dotenv/16.0.1:
|
||||||
resolution: {integrity: sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==}
|
resolution: {integrity: sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
@@ -10272,6 +10492,10 @@ packages:
|
|||||||
/estree-walker/2.0.2:
|
/estree-walker/2.0.2:
|
||||||
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
||||||
|
|
||||||
|
/estree-walker/3.0.1:
|
||||||
|
resolution: {integrity: sha512-woY0RUD87WzMBUiZLx8NsYr23N5BKsOMZHhu2hoNRVh6NXGfoiT1KOL8G3UHlJAnEDGmfa5ubNA/AacfG+Kb0g==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/esutils/2.0.3:
|
/esutils/2.0.3:
|
||||||
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
|
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -13632,8 +13856,8 @@ packages:
|
|||||||
emojis-list: 3.0.0
|
emojis-list: 3.0.0
|
||||||
json5: 2.2.1
|
json5: 2.2.1
|
||||||
|
|
||||||
/local-pkg/0.4.1:
|
/local-pkg/0.4.2:
|
||||||
resolution: {integrity: sha512-lL87ytIGP2FU5PWwNDo0w3WhIo2gopIAxPg9RxDYF7m4rr5ahuZxP22xnJHIvaLTe4Z9P6uKKY2UHiwyB4pcrw==}
|
resolution: {integrity: sha512-mlERgSPrbxU3BP4qBqAvvwlgW4MTg78iwJdGGnv7kibKjWcJksrG3t6LB5lXI93wXRDvG4NpUgJFmTG4T6rdrg==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
@@ -14329,11 +14553,13 @@ packages:
|
|||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
/mlly/0.5.3:
|
/mlly/0.5.10:
|
||||||
resolution: {integrity: sha512-im69tuLD9EJh9fc9TZRpJEFvsBcGMez7glUCWDcHWWCKzhvPmNvyaYjp/+h0qJJN/Xovrs//GzGjOOKmFw4Gog==}
|
resolution: {integrity: sha512-mY6i+bwcgn0XAdZTiiBt6kyoUjLsm3Cuv0T4CchQJcq/UCSUcGPapSxc4g7whtIsUfcsJ2kGqZAdmqCF/VNC/Q==}
|
||||||
dependencies:
|
dependencies:
|
||||||
pathe: 0.2.0
|
acorn: 8.8.0
|
||||||
|
pathe: 0.3.4
|
||||||
pkg-types: 0.3.3
|
pkg-types: 0.3.3
|
||||||
|
ufo: 0.8.5
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/mocha/9.2.2:
|
/mocha/9.2.2:
|
||||||
@@ -14707,7 +14933,7 @@ packages:
|
|||||||
/nuxt-windicss/2.2.11:
|
/nuxt-windicss/2.2.11:
|
||||||
resolution: {integrity: sha512-xobq725D6vqpIgYOrLJ6CVlR4xLlFGwuq//gZikXKOdoVRpoK8C+NpHazPd4+f17urGQ4H0LqGBCIujTvV1V0g==}
|
resolution: {integrity: sha512-xobq725D6vqpIgYOrLJ6CVlR4xLlFGwuq//gZikXKOdoVRpoK8C+NpHazPd4+f17urGQ4H0LqGBCIujTvV1V0g==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nuxt/kit': /@nuxt/kit-edge/3.0.0-rc.4-27605536.8c2c80e
|
'@nuxt/kit': /@nuxt/kit-edge/3.0.0-rc.7-27670958.b0bf25c
|
||||||
'@windicss/plugin-utils': 1.8.4
|
'@windicss/plugin-utils': 1.8.4
|
||||||
consola: 2.15.3
|
consola: 2.15.3
|
||||||
defu: 6.0.0
|
defu: 6.0.0
|
||||||
@@ -15285,8 +15511,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==}
|
resolution: {integrity: sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/pathe/0.3.0:
|
/pathe/0.3.4:
|
||||||
resolution: {integrity: sha512-3vUjp552BJzCw9vqKsO5sttHkbYqqsZtH0x1PNtItgqx8BXEXzoY1SYRKcL6BTyVh4lGJGLj0tM42elUDMvcYA==}
|
resolution: {integrity: sha512-YWgqEdxf36R6vcsyj0A+yT/rDRPe0wui4J9gRR7T4whjU5Lx/jZOr75ckEgTNaLVQABAwsrlzHRpIKcCdXAQ5A==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/pause-stream/0.0.11:
|
/pause-stream/0.0.11:
|
||||||
@@ -15383,8 +15609,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-6AJcCMnjUQPQv/Wk960w0TOmjhdjbeaQJoSKWRQv9N3rgkessCu6J0Ydsog/nw1MbpnxHuPzYbfOn2KmlZO1FA==}
|
resolution: {integrity: sha512-6AJcCMnjUQPQv/Wk960w0TOmjhdjbeaQJoSKWRQv9N3rgkessCu6J0Ydsog/nw1MbpnxHuPzYbfOn2KmlZO1FA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
jsonc-parser: 3.0.0
|
jsonc-parser: 3.0.0
|
||||||
mlly: 0.5.3
|
mlly: 0.5.10
|
||||||
pathe: 0.3.0
|
pathe: 0.3.4
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/pluralize/8.0.0:
|
/pluralize/8.0.0:
|
||||||
@@ -17120,6 +17346,11 @@ packages:
|
|||||||
|
|
||||||
/scule/0.2.1:
|
/scule/0.2.1:
|
||||||
resolution: {integrity: sha512-M9gnWtn3J0W+UhJOHmBxBTwv8mZCan5i1Himp60t6vvZcor0wr+IM0URKmIglsWJ7bRujNAVVN77fp+uZaWoKg==}
|
resolution: {integrity: sha512-M9gnWtn3J0W+UhJOHmBxBTwv8mZCan5i1Himp60t6vvZcor0wr+IM0URKmIglsWJ7bRujNAVVN77fp+uZaWoKg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/scule/0.3.2:
|
||||||
|
resolution: {integrity: sha512-zIvPdjOH8fv8CgrPT5eqtxHQXmPNnV/vHJYffZhE43KZkvULvpCTvOt1HPlFaCZx287INL9qaqrZg34e8NgI4g==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/selenium-webdriver/4.0.0-rc-1:
|
/selenium-webdriver/4.0.0-rc-1:
|
||||||
resolution: {integrity: sha512-bcrwFPRax8fifRP60p7xkWDGSJJoMkPAzufMlk5K2NyLPht/YZzR2WcIk1+3gR8VOCLlst1P2PI+MXACaFzpIw==}
|
resolution: {integrity: sha512-bcrwFPRax8fifRP60p7xkWDGSJJoMkPAzufMlk5K2NyLPht/YZzR2WcIk1+3gR8VOCLlst1P2PI+MXACaFzpIw==}
|
||||||
@@ -17934,7 +18165,7 @@ packages:
|
|||||||
/strip-literal/0.4.0:
|
/strip-literal/0.4.0:
|
||||||
resolution: {integrity: sha512-ql/sBDoJOybTKSIOWrrh8kgUEMjXMwRAkZTD0EwiwxQH/6tTPkZvMIEjp0CRlpi6V5FMiJyvxeRkEi1KrGISoA==}
|
resolution: {integrity: sha512-ql/sBDoJOybTKSIOWrrh8kgUEMjXMwRAkZTD0EwiwxQH/6tTPkZvMIEjp0CRlpi6V5FMiJyvxeRkEi1KrGISoA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: 8.7.1
|
acorn: 8.8.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/style-mod/4.0.0:
|
/style-mod/4.0.0:
|
||||||
@@ -19039,8 +19270,8 @@ packages:
|
|||||||
/ufo/0.8.3:
|
/ufo/0.8.3:
|
||||||
resolution: {integrity: sha512-AIkk06G21y/P+NCatfU+1qldCmI0XCszZLn8AkuKotffF3eqCvlce0KuwM7ZemLE/my0GSYADOAeM5zDYWMB+A==}
|
resolution: {integrity: sha512-AIkk06G21y/P+NCatfU+1qldCmI0XCszZLn8AkuKotffF3eqCvlce0KuwM7ZemLE/my0GSYADOAeM5zDYWMB+A==}
|
||||||
|
|
||||||
/ufo/0.8.4:
|
/ufo/0.8.5:
|
||||||
resolution: {integrity: sha512-/+BmBDe8GvlB2nIflWasLLAInjYG0bC9HRnfEpNi4sw77J2AJNnEVnTDReVrehoh825+Q/evF3THXTAweyam2g==}
|
resolution: {integrity: sha512-e4+UtA5IRO+ha6hYklwj6r7BjiGMxS0O+UaSg9HbaTefg4kMkzj4tXzEBajRR+wkxf+golgAWKzLbytCUDMJAA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/uglify-js/3.14.3:
|
/uglify-js/3.14.3:
|
||||||
@@ -19062,13 +19293,13 @@ packages:
|
|||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/unctx/1.1.4:
|
/unctx/2.0.1:
|
||||||
resolution: {integrity: sha512-fQMML+GjUpIjQa0HBrrJezo2dFpTAbQbU0/KFKw4T5wpc9deGjLHSYthdfNAo2xSWM34csI6arzedezQkqtfGw==}
|
resolution: {integrity: sha512-4VkJKSG+lh1yYkvdI0Xd3Gm7y7PU6F0mG5SoJqCI1j2jtIaHvTLAdBfbhDjbHxT93BsRkzcaxaeBtu8W/mX1Sg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: 8.7.1
|
acorn: 8.8.0
|
||||||
estree-walker: 2.0.2
|
estree-walker: 3.0.1
|
||||||
magic-string: 0.26.2
|
magic-string: 0.26.2
|
||||||
unplugin: 0.6.3
|
unplugin: 0.8.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- esbuild
|
- esbuild
|
||||||
- rollup
|
- rollup
|
||||||
@@ -19113,19 +19344,19 @@ packages:
|
|||||||
engines: {node: '>= 0.4.12'}
|
engines: {node: '>= 0.4.12'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/unimport/0.3.0:
|
/unimport/0.6.7:
|
||||||
resolution: {integrity: sha512-RxvfvKBY+CyBmIuYSuBeosSiudgcVakdhVofy5mO5sJ3purQRc5yjLw0Lir7MKHnqe6XT1++8flgAvpxu1UkqQ==}
|
resolution: {integrity: sha512-EMoVqDjswHkU+nD098QYHXH7Mkw7KwGDQAyeRF2lgairJnuO+wpkhIcmCqrD1OPJmsjkTbJ2tW6Ap8St0PuWZA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rollup/pluginutils': 4.2.1
|
'@rollup/pluginutils': 4.2.1
|
||||||
escape-string-regexp: 5.0.0
|
escape-string-regexp: 5.0.0
|
||||||
fast-glob: 3.2.11
|
fast-glob: 3.2.11
|
||||||
local-pkg: 0.4.1
|
local-pkg: 0.4.2
|
||||||
magic-string: 0.26.2
|
magic-string: 0.26.2
|
||||||
mlly: 0.5.3
|
mlly: 0.5.10
|
||||||
pathe: 0.3.0
|
pathe: 0.3.4
|
||||||
scule: 0.2.1
|
scule: 0.3.2
|
||||||
strip-literal: 0.4.0
|
strip-literal: 0.4.0
|
||||||
unplugin: 0.7.0
|
unplugin: 0.9.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- esbuild
|
- esbuild
|
||||||
- rollup
|
- rollup
|
||||||
@@ -19236,12 +19467,12 @@ packages:
|
|||||||
webpack-virtual-modules: 0.4.3
|
webpack-virtual-modules: 0.4.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/unplugin/0.6.3:
|
/unplugin/0.8.1:
|
||||||
resolution: {integrity: sha512-CoW88FQfCW/yabVc4bLrjikN9HC8dEvMU4O7B6K2jsYMPK0l6iAnd9dpJwqGcmXJKRCU9vwSsy653qg+RK0G6A==}
|
resolution: {integrity: sha512-o7rUZoPLG1fH4LKinWgb77gDtTE6mw/iry0Pq0Z5UPvZ9+HZ1/4+7fic7t58s8/CGkPrDpGq+RltO+DmswcR4g==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
esbuild: '>=0.13'
|
esbuild: '>=0.13'
|
||||||
rollup: ^2.50.0
|
rollup: ^2.50.0
|
||||||
vite: ^2.3.0
|
vite: ^2.3.0 || ^3.0.0-0
|
||||||
webpack: 4 || 5
|
webpack: 4 || 5
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
esbuild:
|
esbuild:
|
||||||
@@ -19253,17 +19484,18 @@ packages:
|
|||||||
webpack:
|
webpack:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
|
acorn: 8.8.0
|
||||||
chokidar: 3.5.3
|
chokidar: 3.5.3
|
||||||
webpack-sources: 3.2.3
|
webpack-sources: 3.2.3
|
||||||
webpack-virtual-modules: 0.4.3
|
webpack-virtual-modules: 0.4.4
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/unplugin/0.7.0:
|
/unplugin/0.9.0:
|
||||||
resolution: {integrity: sha512-OsiFrgybmqm5bGuaodvbLYhqUrvGuRHRMZDhddKEXTDbuQ1x+hR7M1WpQguXj03whVYjEYChhFo738cZH5RNig==}
|
resolution: {integrity: sha512-6o7q8Y9yxdPi5yCPmRuFfeNnVzGumRNZSK6hIkvZ6hd0cfigVdm0qBx/GgQ/NEjs54eUV1qTjvMYKRs9yh3rzw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
esbuild: '>=0.13'
|
esbuild: '>=0.13'
|
||||||
rollup: ^2.50.0
|
rollup: ^2.50.0
|
||||||
vite: ^2.3.0
|
vite: ^2.3.0 || ^3.0.0-0
|
||||||
webpack: 4 || 5
|
webpack: 4 || 5
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
esbuild:
|
esbuild:
|
||||||
@@ -19275,10 +19507,10 @@ packages:
|
|||||||
webpack:
|
webpack:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: 8.7.1
|
acorn: 8.8.0
|
||||||
chokidar: 3.5.3
|
chokidar: 3.5.3
|
||||||
webpack-sources: 3.2.3
|
webpack-sources: 3.2.3
|
||||||
webpack-virtual-modules: 0.4.3
|
webpack-virtual-modules: 0.4.4
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/unquote/1.1.1:
|
/unquote/1.1.1:
|
||||||
@@ -19291,13 +19523,13 @@ packages:
|
|||||||
has-value: 0.3.1
|
has-value: 0.3.1
|
||||||
isobject: 3.0.1
|
isobject: 3.0.1
|
||||||
|
|
||||||
/untyped/0.4.4:
|
/untyped/0.4.5:
|
||||||
resolution: {integrity: sha512-sY6u8RedwfLfBis0copfU/fzROieyAndqPs8Kn2PfyzTjtA88vCk81J1b5z+8/VJc+cwfGy23/AqOCpvAbkNVw==}
|
resolution: {integrity: sha512-buq9URfOj4xAnVfu6BYNKzHZLHAzsCbHsDc/kHy66ESMqRpj00oD9qWf2M2qm0pC0DigsVxRF3uhOa5HJtrwGA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.17.9
|
'@babel/core': 7.18.10
|
||||||
'@babel/standalone': 7.17.9
|
'@babel/standalone': 7.18.12
|
||||||
'@babel/types': 7.17.0
|
'@babel/types': 7.18.10
|
||||||
scule: 0.2.1
|
scule: 0.3.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
@@ -19924,6 +20156,10 @@ packages:
|
|||||||
/webpack-virtual-modules/0.4.3:
|
/webpack-virtual-modules/0.4.3:
|
||||||
resolution: {integrity: sha512-5NUqC2JquIL2pBAAo/VfBP6KuGkHIZQXW/lNKupLPfhViwh8wNsu0BObtl09yuKZszeEUfbXz8xhrHvSG16Nqw==}
|
resolution: {integrity: sha512-5NUqC2JquIL2pBAAo/VfBP6KuGkHIZQXW/lNKupLPfhViwh8wNsu0BObtl09yuKZszeEUfbXz8xhrHvSG16Nqw==}
|
||||||
|
|
||||||
|
/webpack-virtual-modules/0.4.4:
|
||||||
|
resolution: {integrity: sha512-h9atBP/bsZohWpHnr+2sic8Iecb60GxftXsWNLLLSqewgIsGzByd2gcIID4nXcG+3tNe4GQG3dLcff3kXupdRA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/webpack/4.46.0:
|
/webpack/4.46.0:
|
||||||
resolution: {integrity: sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==}
|
resolution: {integrity: sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==}
|
||||||
engines: {node: '>=6.11.5'}
|
engines: {node: '>=6.11.5'}
|
||||||
|
|||||||
Reference in New Issue
Block a user