Compare commits

..

7 Commits

Author SHA1 Message Date
Liyas Thomas
3d69b808b9 chore: updated remaining codemirror instances 2023-04-23 11:37:51 +05:30
gitstart
9cbb75ba78 chore: use :deep()
Co-authored-by: collinewait <21334508+collinewait@users.noreply.github.com>
2023-04-20 05:00:19 +00:00
gitstart
380f232c04 chore: make search panel visible on codemirror instances
Co-authored-by: collinewait <21334508+collinewait@users.noreply.github.com>
2023-04-19 16:01:58 +00:00
gitstart
506331c8cf Merge commit 'bd09a6ac452940cfd178c7f3146d6ce82fb41014' of https://github.com/GitStartHQ/hoppscotch into HPS-OSS-1 2023-04-19 16:01:57 +00:00
gitstart
abf953f780 chore: restrict offset changes to the json response
Co-authored-by: collinewait <21334508+collinewait@users.noreply.github.com>
2023-04-18 09:53:49 +00:00
Liyas Thomas
8dd09ca9dd chore: use css variable instead of hard-code value 2023-04-18 10:48:56 +05:30
gitstart
66f15c15d5 fix: make finder in response body visible when scrolling
Co-authored-by: collinewait <21334508+collinewait@users.noreply.github.com>
2023-04-17 12:29:17 +00:00
49 changed files with 384 additions and 282 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "hoppscotch-backend",
"version": "2023.4.1",
"version": "2023.4.0",
"description": "",
"author": "",
"private": true,

View File

@@ -63,7 +63,7 @@ export const authCookieHandler = (
});
if (!redirect) {
return res.status(HttpStatus.OK).send();
res.status(HttpStatus.OK).send();
}
// check to see if redirectUrl is a whitelisted url
@@ -72,7 +72,7 @@ export const authCookieHandler = (
// if it is not redirect by default to REDIRECT_URL
redirectUrl = process.env.REDIRECT_URL;
return res.status(HttpStatus.OK).redirect(redirectUrl);
res.status(HttpStatus.OK).redirect(redirectUrl);
};
/**

View File

@@ -459,14 +459,6 @@ pre.ace_editor {
@apply bg-dividerLight;
}
.splitpanes--horizontal .splitpanes__pane {
@apply transition-none;
}
.splitpanes--vertical .splitpanes__pane {
@apply transition-none;
}
.cm-focused {
@apply select-auto;
@apply outline-none #{!important};

View File

@@ -269,6 +269,7 @@
--lower-secondary-sticky-fold: 5.063rem;
--lower-tertiary-sticky-fold: 7.125rem;
--sidebar-primary-sticky-fold: 2rem;
--request-body-sticky-fold: 10rem;
}
@mixin font-medium {
@@ -285,6 +286,7 @@
--lower-secondary-sticky-fold: 5.563rem;
--lower-tertiary-sticky-fold: 7.875rem;
--sidebar-primary-sticky-fold: 2.25rem;
--request-body-sticky-fold: 11rem;
}
@mixin font-large {
@@ -301,6 +303,7 @@
--lower-secondary-sticky-fold: 6.063rem;
--lower-tertiary-sticky-fold: 8.625rem;
--sidebar-primary-sticky-fold: 2.5rem;
--request-body-sticky-fold: 12rem;
}
:root[data-font-size="small"] {

View File

@@ -1,7 +1,7 @@
{
"name": "@hoppscotch/common",
"private": true,
"version": "2023.4.1",
"version": "2023.4.0",
"scripts": {
"dev": "pnpm exec npm-run-all -p -l dev:*",
"dev:vite": "vite",
@@ -62,7 +62,7 @@
"js-yaml": "^4.1.0",
"jsonpath-plus": "^7.0.0",
"lodash-es": "^4.17.21",
"lossless-json": "^2.0.8",
"lossless-json": "^1.0.5",
"nprogress": "^0.2.0",
"paho-mqtt": "^1.1.0",
"path": "^0.12.7",
@@ -106,7 +106,7 @@
"@graphql-codegen/urql-introspection": "^2.2.0",
"@graphql-typed-document-node/core": "^3.1.1",
"@iconify-json/lucide": "^1.1.40",
"@intlify/vite-plugin-vue-i18n": "^7.0.0",
"@intlify/vite-plugin-vue-i18n": "^6.0.1",
"@rushstack/eslint-patch": "^1.1.4",
"@types/js-yaml": "^4.0.5",
"@types/lodash-es": "^4.17.6",

View File

@@ -73,26 +73,6 @@ declare module '@vue/runtime-core' {
History: typeof import('./components/history/index.vue')['default']
HistoryGraphqlCard: typeof import('./components/history/graphql/Card.vue')['default']
HistoryRestCard: typeof import('./components/history/rest/Card.vue')['default']
HoppButtonPrimary: typeof import('@hoppscotch/ui')['HoppButtonPrimary']
HoppButtonSecondary: typeof import('@hoppscotch/ui')['HoppButtonSecondary']
HoppSmartAnchor: typeof import('@hoppscotch/ui')['HoppSmartAnchor']
HoppSmartAutoComplete: typeof import('@hoppscotch/ui')['HoppSmartAutoComplete']
HoppSmartCheckbox: typeof import('@hoppscotch/ui')['HoppSmartCheckbox']
HoppSmartConfirmModal: typeof import('@hoppscotch/ui')['HoppSmartConfirmModal']
HoppSmartExpand: typeof import('@hoppscotch/ui')['HoppSmartExpand']
HoppSmartFileChip: typeof import('@hoppscotch/ui')['HoppSmartFileChip']
HoppSmartItem: typeof import('@hoppscotch/ui')['HoppSmartItem']
HoppSmartLink: typeof import('@hoppscotch/ui')['HoppSmartLink']
HoppSmartModal: typeof import('@hoppscotch/ui')['HoppSmartModal']
HoppSmartPicture: typeof import('@hoppscotch/ui')['HoppSmartPicture']
HoppSmartProgressRing: typeof import('@hoppscotch/ui')['HoppSmartProgressRing']
HoppSmartRadioGroup: typeof import('@hoppscotch/ui')['HoppSmartRadioGroup']
HoppSmartSlideOver: typeof import('@hoppscotch/ui')['HoppSmartSlideOver']
HoppSmartSpinner: typeof import('@hoppscotch/ui')['HoppSmartSpinner']
HoppSmartTab: typeof import('@hoppscotch/ui')['HoppSmartTab']
HoppSmartTabs: typeof import('@hoppscotch/ui')['HoppSmartTabs']
HoppSmartWindow: typeof import('@hoppscotch/ui')['HoppSmartWindow']
HoppSmartWindows: typeof import('@hoppscotch/ui')['HoppSmartWindows']
HttpAuthorization: typeof import('./components/http/Authorization.vue')['default']
HttpAuthorizationApiKey: typeof import('./components/http/authorization/ApiKey.vue')['default']
HttpAuthorizationBasic: typeof import('./components/http/authorization/Basic.vue')['default']
@@ -118,20 +98,6 @@ declare module '@vue/runtime-core' {
HttpTestResultReport: typeof import('./components/http/TestResultReport.vue')['default']
HttpTests: typeof import('./components/http/Tests.vue')['default']
HttpURLEncodedParams: typeof import('./components/http/URLEncodedParams.vue')['default']
IconLucideAlertTriangle: typeof import('~icons/lucide/alert-triangle')['default']
IconLucideArrowLeft: typeof import('~icons/lucide/arrow-left')['default']
IconLucideCheckCircle: typeof import('~icons/lucide/check-circle')['default']
IconLucideChevronRight: typeof import('~icons/lucide/chevron-right')['default']
IconLucideGlobe: typeof import('~icons/lucide/globe')['default']
IconLucideHelpCircle: typeof import('~icons/lucide/help-circle')['default']
IconLucideInbox: typeof import('~icons/lucide/inbox')['default']
IconLucideInfo: typeof import('~icons/lucide/info')['default']
IconLucideLayers: typeof import('~icons/lucide/layers')['default']
IconLucideListEnd: typeof import('~icons/lucide/list-end')['default']
IconLucideMinus: typeof import('~icons/lucide/minus')['default']
IconLucideSearch: typeof import('~icons/lucide/search')['default']
IconLucideUser: typeof import('~icons/lucide/user')['default']
IconLucideUsers: typeof import('~icons/lucide/users')['default']
LensesHeadersRenderer: typeof import('./components/lenses/HeadersRenderer.vue')['default']
LensesHeadersRendererEntry: typeof import('./components/lenses/HeadersRendererEntry.vue')['default']
LensesRenderersHTMLLensRenderer: typeof import('./components/lenses/renderers/HTMLLensRenderer.vue')['default']
@@ -165,7 +131,6 @@ declare module '@vue/runtime-core' {
SmartItem: typeof import('./../../hoppscotch-ui/src/components/smart/Item.vue')['default']
SmartLink: typeof import('./../../hoppscotch-ui/src/components/smart/Link.vue')['default']
SmartModal: typeof import('./../../hoppscotch-ui/src/components/smart/Modal.vue')['default']
SmartPicture: typeof import('./../../hoppscotch-ui/src/components/smart/Picture.vue')['default']
SmartProgressRing: typeof import('./../../hoppscotch-ui/src/components/smart/ProgressRing.vue')['default']
SmartRadio: typeof import('./../../hoppscotch-ui/src/components/smart/Radio.vue')['default']
SmartRadioGroup: typeof import('./../../hoppscotch-ui/src/components/smart/RadioGroup.vue')['default']

View File

@@ -124,7 +124,7 @@
theme="popover"
:on-shown="() => tippyActions.focus()"
>
<HoppSmartPicture
<ProfilePicture
v-if="currentUser.photoURL"
v-tippy="{
theme: 'tooltip',
@@ -144,7 +144,7 @@
network.isOnline ? 'bg-green-500' : 'bg-red-500'
"
/>
<HoppSmartPicture
<ProfilePicture
v-else
v-tippy="{ theme: 'tooltip' }"
:title="

View File

@@ -62,7 +62,7 @@
</template>
<script setup lang="ts">
import { nextTick, reactive, ref, watch } from "vue"
import { reactive, ref, watch } from "vue"
import { cloneDeep } from "lodash-es"
import {
HoppGQLRequest,
@@ -126,22 +126,12 @@ const emit = defineEmits<{
}>()
const gqlRequestName = useGQLRequestName()
const restRequestName = computedWithControl(
() => currentActiveTab.value,
() => currentActiveTab.value.document.request.name
)
const requestName = ref(
props.mode === "rest" ? restRequestName.value : gqlRequestName.value
)
watch(
() => [currentActiveTab.value.document.request.name, gqlRequestName.value],
() => {
if (props.mode === "rest")
requestName.value = currentActiveTab.value.document.request.name
else requestName.value = gqlRequestName.value
}
const requestName = computedWithControl(
() => [currentActiveTab.value, gqlRequestName.value],
() =>
props.mode === "rest"
? currentActiveTab.value.document.request.name
: gqlRequestName.value
)
const requestData = reactive({
@@ -202,8 +192,6 @@ const saveRequestAs = async () => {
? cloneDeep(currentActiveTab.value.document.request)
: cloneDeep(getGQLSession().request)
requestUpdated.name = requestName.value
if (picked.value.pickedType === "my-collection") {
if (!isHoppRESTRequest(requestUpdated))
throw new Error("requestUpdated is not a REST Request")
@@ -385,9 +373,6 @@ const updateTeamCollectionOrFolder = (
const requestSaved = () => {
toast.success(`${t("request.added")}`)
nextTick(() => {
currentActiveTab.value.document.isDirty = false
})
hideModal()
}

View File

@@ -90,7 +90,7 @@
'!flex': draggingToRoot && currentReorderingStatus.type !== 'request',
}"
>
<icon-lucide-list-end class="svg-icons !w-8 !h-8" />
<component :is="IconListEnd" class="svg-icons !w-8 !h-8" />
</div>
<CollectionsAdd
:show="showModalAdd"
@@ -221,6 +221,7 @@ import * as E from "fp-ts/Either"
import { platform } from "~/platform"
import { createCollectionGists } from "~/helpers/gist"
import { workspaceStatus$ } from "~/newstore/workspace"
import IconListEnd from "~icons/lucide/list-end"
import {
createNewTab,
currentActiveTab,

View File

@@ -408,9 +408,11 @@ const selectedEnv = computed(() => {
teamEnvID: selectedEnvironmentIndex.value.teamEnvID,
}
} else {
selectedEnvironmentIndex.value = { type: "NO_ENV_SELECTED" }
return { type: "NO_ENV_SELECTED" }
}
} else {
selectedEnvironmentIndex.value = { type: "NO_ENV_SELECTED" }
return { type: "NO_ENV_SELECTED" }
}
})

View File

@@ -802,3 +802,9 @@ defineActionHandler("request.send-cancel", runQuery)
defineActionHandler("request.save", saveRequest)
defineActionHandler("request.reset", clearGQLQuery)
</script>
<style lang="scss" scoped>
:deep(.cm-panels) {
top: var(--upper-tertiary-sticky-fold) !important;
}
</style>

View File

@@ -120,3 +120,9 @@ const downloadResponse = () => {
defineActionHandler("response.file.download", () => downloadResponse())
defineActionHandler("response.copy", () => copyResponse())
</script>
<style lang="scss" scoped>
:deep(.cm-panels) {
top: var(--sidebar-primary-sticky-fold) !important;
}
</style>

View File

@@ -470,3 +470,9 @@ const handleUseHistory = (entry: GQLHistoryEntry) => {
props.conn.reset()
}
</script>
<style lang="scss" scoped>
:deep(.cm-panels) {
top: var(--lower-primary-sticky-fold) !important;
}
</style>

View File

@@ -191,3 +191,9 @@ const isContentTypeAlreadyExist = () => {
// Template refs
const tippyActions = ref<any | null>(null)
</script>
<style lang="scss" scoped>
:deep(.cm-panels) {
top: var(--request-body-sticky-fold) !important;
}
</style>

View File

@@ -273,3 +273,9 @@ const filteredCodegenDefinitions = computed(() => {
const { copyIcon, copyResponse } = useCopyResponse(requestCode)
const { downloadIcon, downloadResponse } = useDownloadResponse("", requestCode)
</script>
<style lang="scss" scoped>
:deep(.cm-panels) {
top: -1rem !important;
}
</style>

View File

@@ -508,3 +508,9 @@ const changeTab = (tab: ComputedHeader["source"]) => {
else emit("change-tab", "bodyParams")
}
</script>
<style lang="scss" scoped>
:deep(.cm-panels) {
top: var(--upper-tertiary-sticky-fold) !important;
}
</style>

View File

@@ -405,3 +405,9 @@ const clearContent = () => {
bulkParams.value = ""
}
</script>
<style lang="scss" scoped>
:deep(.cm-panels) {
top: var(--upper-tertiary-sticky-fold) !important;
}
</style>

View File

@@ -110,3 +110,9 @@ const clearContent = () => {
preRequestScript.value = ""
}
</script>
<style lang="scss" scoped>
:deep(.cm-panels) {
top: var(--upper-tertiary-sticky-fold) !important;
}
</style>

View File

@@ -220,3 +220,9 @@ const prettifyXML = (xml: string) => {
.join("\r\n")
}
</script>
<style lang="scss" scoped>
:deep(.cm-panels) {
top: var(--request-body-sticky-fold) !important;
}
</style>

View File

@@ -42,7 +42,7 @@
class="flex p-4 bg-error text-secondaryDark"
role="alert"
>
<icon-lucide-alert-triangle class="mr-4 svg-icons" />
<component :is="IconAlertTriangle" class="mr-4 svg-icons" />
<div class="flex flex-col">
<p>
{{ t("environment.no_environment_description") }}
@@ -220,6 +220,7 @@ import { HoppTestResult } from "~/helpers/types/HoppTestResult"
import IconTrash2 from "~icons/lucide/trash-2"
import IconExternalLink from "~icons/lucide/external-link"
import IconAlertTriangle from "~icons/lucide/alert-triangle"
import IconCheck from "~icons/lucide/check"
import IconClose from "~icons/lucide/x"

View File

@@ -106,3 +106,9 @@ const clearContent = () => {
testScript.value = ""
}
</script>
<style lang="scss" scoped>
:deep(.cm-panels) {
top: var(--upper-tertiary-sticky-fold) !important;
}
</style>

View File

@@ -432,3 +432,9 @@ const clearContent = () => {
bulkUrlEncodedParams.value = ""
}
</script>
<style lang="scss" scoped>
:deep(.cm-panels) {
top: var(--request-body-sticky-fold) !important;
}
</style>

View File

@@ -123,3 +123,9 @@ watch(selectedLensTab, (newLensID) => {
selectedTabPreference.value = newLensID
})
</script>
<style lang="scss" scoped>
:deep(.cm-panels) {
top: var(--lower-tertiary-sticky-fold) !important;
}
</style>

View File

@@ -0,0 +1,87 @@
<template>
<button
tabindex="0"
class="relative flex items-center justify-center overflow-visible cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-primaryDark"
:class="[`rounded-${rounded}`, `w-${size} h-${size}`]"
>
<img
v-if="url"
class="absolute object-cover object-center transition bg-primaryDark"
:class="[`rounded-${rounded}`, `w-${size} h-${size}`]"
:src="url"
:alt="alt"
loading="lazy"
/>
<div
v-else
class="absolute flex items-center justify-center object-cover object-center transition bg-primaryDark text-accentContrast"
:class="[`rounded-${rounded}`, `w-${size} h-${size}`]"
:style="`background-color: ${initial ? toHex(initial) : '#480000'}`"
>
<template v-if="initial && initial.charAt(0).toUpperCase()">
{{ initial.charAt(0).toUpperCase() }}
</template>
<icon-lucide-user v-else></icon-lucide-user>
</div>
<span
v-if="indicator"
class="border-primary border-2 h-2.5 -top-0.5 -right-0.5 w-2.5 absolute"
:class="[`rounded-${rounded}`, indicatorStyles]"
></span>
<!-- w-5 h-5 rounded-lg -->
</button>
</template>
<script lang="ts">
import { defineComponent, PropType } from "vue"
export default defineComponent({
props: {
url: {
type: String,
default: "",
},
alt: {
type: String,
default: "Profile picture",
},
indicator: {
type: Boolean,
default: false,
},
indicatorStyles: {
type: String,
default: "bg-green-500",
},
rounded: {
type: String,
default: "full",
},
size: {
type: String,
default: "5",
},
initial: {
type: String as PropType<string | undefined | null>,
default: "",
},
},
methods: {
toHex(initial: string) {
let hash = 0
if (initial.length === 0) return hash
for (let i = 0; i < initial.length; i++) {
hash = initial.charCodeAt(i) + ((hash << 5) - hash)
hash = hash & hash
}
let color = "#"
for (let i = 0; i < 3; i++) {
const value = (hash >> (i * 8)) & 255
color += `00${value.toString(16)}`.slice(-2)
}
return color
},
},
})
</script>

View File

@@ -1,5 +1,8 @@
<template>
<div class="flex flex-col flex-1">
<div
class="flex flex-col flex-1"
:class="{ 'showing-event-field': showEventField }"
>
<div
v-if="showEventField"
class="sticky z-10 flex items-center justify-center flex-shrink-0 overflow-x-auto border-b bg-primary border-dividerLight"
@@ -271,3 +274,13 @@ const prettifyRequestBody = () => {
defineActionHandler("request.send-cancel", sendMessage)
</script>
<style lang="scss" scoped>
:deep(.cm-panels) {
top: var(--upper-tertiary-sticky-fold) !important;
}
.showing-event-field :deep(.cm-panels) {
top: var(--request-body-sticky-fold) !important;
}
</style>

View File

@@ -167,7 +167,7 @@
v-if="!teamDetails.loading && E.isLeft(teamDetails.data)"
class="flex flex-col items-center"
>
<icon-lucide-help-circle class="mb-4 svg-icons" />
<component :is="IconHelpCircle" class="mb-4 svg-icons" />
{{ t("error.something_went_wrong") }}
</div>
</div>
@@ -220,6 +220,7 @@ import IconCircleDot from "~icons/lucide/circle-dot"
import IconCircle from "~icons/lucide/circle"
import IconUserPlus from "~icons/lucide/user-plus"
import IconUserMinus from "~icons/lucide/user-minus"
import IconHelpCircle from "~icons/lucide/help-circle"
const t = useI18n()
const colorMode = useColorMode()

View File

@@ -113,7 +113,7 @@
v-if="!pendingInvites.loading && E.isLeft(pendingInvites.data)"
class="flex flex-col items-center p-4"
>
<icon-lucide-help-circle class="mb-4 svg-icons" />
<component :is="IconHelpCircle" class="mb-4 svg-icons" />
{{ t("error.something_went_wrong") }}
</div>
</div>
@@ -248,7 +248,8 @@
<span
class="flex items-center justify-center px-2 py-1 mb-4 font-semibold border rounded-full bg-primaryDark border-divider"
>
<icon-lucide-help-circle
<component
:is="IconHelpCircle"
class="mr-2 text-secondaryLight svg-icons"
/>
{{ t("profile.roles") }}
@@ -367,6 +368,7 @@ import { useColorMode } from "~/composables/theming"
import IconTrash from "~icons/lucide/trash"
import IconPlus from "~icons/lucide/plus"
import IconHelpCircle from "~icons/lucide/help-circle"
import IconAlertTriangle from "~icons/lucide/alert-triangle"
import IconMailCheck from "~icons/lucide/mail-check"
import IconCircleDot from "~icons/lucide/circle-dot"

View File

@@ -5,7 +5,7 @@
:key="`member-${index}`"
class="inline-flex"
>
<HoppSmartPicture
<ProfilePicture
v-if="member.user.photoURL"
v-tippy="{ theme: 'tooltip' }"
:url="member.user.photoURL"
@@ -14,7 +14,7 @@
class="ring-primary ring-2"
@click="handleClick()"
/>
<HoppSmartPicture
<ProfilePicture
v-else
v-tippy="{ theme: 'tooltip' }"
:title="getUserName(member)"

View File

@@ -47,7 +47,7 @@
/>
</div>
<div v-if="!loading && adapterError" class="flex flex-col items-center">
<icon-lucide-help-circle class="mb-4 svg-icons" />
<component :is="IconHelpCircle" class="mb-4 svg-icons" />
{{ t("error.something_went_wrong") }}
</div>
</div>
@@ -82,6 +82,8 @@ import { useI18n } from "@composables/i18n"
import { useReadonlyStream } from "@composables/stream"
import { useColorMode } from "@composables/theming"
import IconHelpCircle from "~icons/lucide/help-circle"
const t = useI18n()
const colorMode = useColorMode()

View File

@@ -67,7 +67,7 @@
v-if="!loading && teamListAdapterError"
class="flex flex-col items-center py-4"
>
<icon-lucide-help-circle class="mb-4 svg-icons" />
<i class="mb-4 material-icons">help_outline</i>
{{ t("error.something_went_wrong") }}
</div>
</div>

View File

@@ -63,6 +63,7 @@ export const baseTheme = EditorView.theme({
".cm-panels": {
backgroundColor: "var(--primary-light-color)",
color: "var(--secondary-light-color)",
zIndex: "1",
},
".cm-panels.cm-panels-top": {
borderBottom: "1px solid var(--divider-light-color)",
@@ -198,6 +199,7 @@ export const inputTheme = EditorView.theme({
".cm-panels": {
backgroundColor: "var(--primary-light-color)",
color: "var(--secondary-light-color)",
zIndex: "1",
},
".cm-panels.cm-panels-top": {
borderBottom: "1px solid var(--divider-light-color)",

View File

@@ -24,10 +24,7 @@
>
<Pane class="flex flex-1 !overflow-auto">
<main class="flex flex-1 w-full" role="main">
<RouterView
v-slot="{ Component }"
class="flex flex-1 min-w-0"
>
<RouterView v-slot="{ Component }" class="flex flex-1">
<Transition name="fade" mode="out-in" appear>
<component :is="Component" />
</Transition>

View File

@@ -7,6 +7,7 @@ import { HoppModule } from "."
import languages from "../../languages.json"
import en from "../../locales/en.json"
import { throwError } from "~/helpers/functional/error"
import { getLocalConfig, setLocalConfig } from "~/newstore/localpersistence"
@@ -122,6 +123,11 @@ export default <HoppModule>{
fallbackLocale: "en",
legacy: false,
allowComposition: true,
// TODO: Fix this to allow for dynamic imports
messages: {
en,
},
})
app.use(i18n)

View File

@@ -1,6 +1,8 @@
/* eslint-disable no-restricted-globals, no-restricted-syntax */
import { clone, assign, isEmpty } from "lodash-es"
import * as O from "fp-ts/Option"
import { pipe } from "fp-ts/function"
import {
translateToNewRESTCollection,
translateToNewGQLCollection,
@@ -49,30 +51,7 @@ import {
} from "~/helpers/rest/tab"
function checkAndMigrateOldSettings() {
if (window.localStorage.getItem("selectedEnvIndex")) {
const index = window.localStorage.getItem("selectedEnvIndex")
if (index) {
if (index === "-1") {
window.localStorage.setItem(
"selectedEnvIndex",
JSON.stringify({
type: "NO_ENV_SELECTED",
})
)
} else if (Number(index) >= 0) {
window.localStorage.setItem(
"selectedEnvIndex",
JSON.stringify({
type: "MY_ENV",
index: parseInt(index),
})
)
}
}
}
const vuexData = JSON.parse(window.localStorage.getItem("vuex") || "{}")
if (isEmpty(vuexData)) return
const { postwoman } = vuexData
@@ -231,21 +210,35 @@ function setupEnvironmentsPersistence() {
}
function setupSelectedEnvPersistence() {
const selectedEnvIndex = JSON.parse(
window.localStorage.getItem("selectedEnvIndex") ?? "null"
const selectedEnvIndex = pipe(
// Value from local storage can be nullable
O.fromNullable(window.localStorage.getItem("selectedEnvIndex")),
O.map(parseInt), // If not null, parse to integer
O.chain(
O.fromPredicate(
Number.isInteger // Check if the number is proper int (not NaN)
)
),
O.getOrElse(() => -1) // If all the above conditions pass, we are good, else set default value (-1)
)
// If there is a selected env index, set it to the store else set it to null
if (selectedEnvIndex) {
setSelectedEnvironmentIndex(selectedEnvIndex)
} else {
// Check if current environment index is -1 ie. no environment is selected
if (selectedEnvIndex === -1) {
setSelectedEnvironmentIndex({
type: "NO_ENV_SELECTED",
})
} else {
setSelectedEnvironmentIndex({
type: "MY_ENV",
index: selectedEnvIndex,
})
}
selectedEnvironmentIndex$.subscribe((envIndex) => {
window.localStorage.setItem("selectedEnvIndex", JSON.stringify(envIndex))
if (envIndex.type === "MY_ENV") {
window.localStorage.setItem("selectedEnvIndex", envIndex.index.toString())
} else {
window.localStorage.setItem("selectedEnvIndex", "-1")
}
})
}

View File

@@ -38,15 +38,10 @@
<template #suffix>
<span
v-if="tab.document.isDirty"
class="flex items-center justify-center text-secondary group-hover:hidden w-4"
class="text-green-600 text-[8px] group-hover:hidden w-4"
>
<svg
viewBox="0 0 24 24"
width="1.2em"
height="1.2em"
class="h-1.5 w-1.5"
>
<circle cx="12" cy="12" r="12" fill="currentColor"></circle>
<svg viewBox="0 0 24 24" width="1.2em" height="1.2em">
<circle cx="12" cy="12" r="10" fill="currentColor"></circle>
</svg>
</span>
</template>

View File

@@ -34,7 +34,7 @@
></div>
<div class="flex flex-col justify-between px-4 space-y-8 md:flex-row">
<div class="flex items-end">
<HoppSmartPicture
<ProfilePicture
v-if="currentUser.photoURL"
:url="currentUser.photoURL"
:alt="
@@ -44,7 +44,7 @@
size="16"
rounded="lg"
/>
<HoppSmartPicture
<ProfilePicture
v-else
:initial="currentUser.displayName || currentUser.email"
rounded="lg"

View File

@@ -1,7 +1,7 @@
{
"name": "@hoppscotch/selfhost-web",
"private": true,
"version": "2023.4.1",
"version": "2023.4.0",
"type": "module",
"scripts": {
"dev:vite": "vite",
@@ -46,7 +46,7 @@
"@graphql-codegen/typescript-urql-graphcache": "^2.3.1",
"@graphql-codegen/urql-introspection": "^2.2.0",
"@graphql-typed-document-node/core": "^3.1.1",
"@intlify/vite-plugin-vue-i18n": "^7.0.0",
"@intlify/vite-plugin-vue-i18n": "^6.0.1",
"@rushstack/eslint-patch": "^1.1.4",
"@typescript-eslint/eslint-plugin": "^5.19.0",
"@typescript-eslint/parser": "^5.19.0",

View File

@@ -1,7 +1,7 @@
{
"name": "hoppscotch-sh-admin",
"private": true,
"version": "2023.4.1",
"version": "2023.4.0",
"type": "module",
"scripts": {
"dev": "pnpm exec npm-run-all -p -l dev:*",

View File

@@ -28,7 +28,7 @@
arrow
:on-shown="() => tippyActions!.focus()"
>
<HoppSmartPicture
<ProfilePicture
v-if="currentUser.photoURL"
v-tippy="{
theme: 'tooltip',
@@ -37,7 +37,7 @@
:alt="currentUser.displayName ?? 'No Name'"
:title="currentUser.displayName ?? currentUser.email ?? 'No Name'"
/>
<HoppSmartPicture
<ProfilePicture
v-else
v-tippy="{ theme: 'tooltip' }"
:title="currentUser.displayName ?? currentUser.email ?? 'No Name'"

View File

@@ -33,40 +33,55 @@
</div>
</template>
<script setup lang="ts">
withDefaults(
defineProps<{
url: string
alt: string
indicator: boolean
indicatorStyles: string
rounded: string
size: string
initial: string | undefined | null
}>(),
{
url: "",
alt: "Profile picture",
indicator: false,
indicatorStyles: "bg-green-500",
rounded: "full",
size: "5",
initial: "",
}
)
<script lang="ts">
import { defineComponent, PropType } from 'vue';
const toHex = (initial: string) => {
let hash = 0
if (initial.length === 0) return hash
for (let i = 0; i < initial.length; i++) {
hash = initial.charCodeAt(i) + ((hash << 5) - hash)
hash = hash & hash
}
let color = "#"
for (let i = 0; i < 3; i++) {
const value = (hash >> (i * 8)) & 255
color += `00${value.toString(16)}`.slice(-2)
}
return color
}
export default defineComponent({
props: {
url: {
type: String,
default: '',
},
alt: {
type: String,
default: 'Profile picture',
},
indicator: {
type: Boolean,
default: false,
},
indicatorStyles: {
type: String,
default: 'bg-green-500',
},
rounded: {
type: String,
default: 'full',
},
size: {
type: String,
default: '5',
},
initial: {
type: String as PropType<string | undefined | null>,
default: '',
},
},
methods: {
toHex(initial: string) {
let hash = 0;
if (initial.length === 0) return hash;
for (let i = 0; i < initial.length; i++) {
hash = initial.charCodeAt(i) + ((hash << 5) - hash);
hash = hash & hash;
}
let color = '#';
for (let i = 0; i < 3; i++) {
const value = (hash >> (i * 8)) & 255;
color += `00${value.toString(16)}`.slice(-2);
}
return color;
},
},
});
</script>

View File

@@ -131,7 +131,10 @@
<span
class="flex items-center justify-center px-2 py-1 mb-4 font-semibold border rounded-full bg-primaryDark border-divider"
>
<icon-lucide-help-circle class="mr-2 text-secondaryLight svg-icons" />
<component
:is="IconHelpCircle"
class="mr-2 text-secondaryLight svg-icons"
/>
Roles
</span>
<p>
@@ -205,6 +208,7 @@ import { useMutation, useQuery } from '@urql/vue';
import { Email, EmailCodec } from '~/helpers/backend/Email';
import IconTrash from '~icons/lucide/trash';
import IconPlus from '~icons/lucide/plus';
import IconHelpCircle from '~icons/lucide/help-circle';
import IconCircleDot from '~icons/lucide/circle-dot';
import IconCircle from '~icons/lucide/circle';
import { computed } from 'vue';

View File

@@ -133,7 +133,7 @@
</div>
</div>
<div v-if="!fetching && !team" class="flex flex-col items-center">
<icon-lucide-help-circle class="mb-4 svg-icons" />
<component :is="IconHelpCircle" class="mb-4 svg-icons" />
Something went wrong. Please try again later.
</div>
</div>
@@ -159,6 +159,7 @@ import IconCircleDot from '~icons/lucide/circle-dot';
import IconCircle from '~icons/lucide/circle';
import IconUserPlus from '~icons/lucide/user-plus';
import IconUserMinus from '~icons/lucide/user-minus';
import IconHelpCircle from '~icons/lucide/help-circle';
import IconChevronDown from '~icons/lucide/chevron-down';
import { useClientHandle, useMutation } from '@urql/vue';
import { computed, onMounted, onUnmounted, ref, watch } from 'vue';

View File

@@ -44,7 +44,7 @@
<span class="text-center"> No pending invites </span>
</div>
<div v-if="!fetching && error" class="flex flex-col items-center p-4">
<icon-lucide-help-circle class="mb-4 svg-icons" />
<component :is="IconHelpCircle" class="mb-4 svg-icons" />
Something went wrong. Please try again later.
</div>
</div>
@@ -53,6 +53,7 @@
<script setup lang="ts">
import IconTrash from '~icons/lucide/trash';
import IconHelpCircle from '~icons/lucide/help-circle';
import { useMutation, useClientHandle } from '@urql/vue';
import { ref, onMounted } from 'vue';
import {

View File

@@ -6,7 +6,7 @@ const isAdmin = () => {
return user ? user.isAdmin : false;
};
const GUEST_ROUTES = ['index', 'enter'];
const GUEST_ROUTES = ['index', 'magic-link'];
const isGuestRoute = (to: unknown) => GUEST_ROUTES.includes(to as string);

View File

@@ -1,6 +1,22 @@
<template>
<span class="inline-flex items-center justify-center rounded pl-2 pr-0.5 bg-primaryDark">
<icon-lucide-file class="opacity-75 svg-icons" />
<span class="chip">
<component :is="IconFile" class="opacity-75 svg-icons" />
<span class="px-2 truncate max-w-54"><slot></slot></span>
</span>
</template>
<script setup lang="ts">
import IconFile from "~icons/lucide/file"
</script>
<style lang="scss" scoped>
.chip {
@apply inline-flex;
@apply items-center;
@apply justify-center;
@apply rounded;
@apply pl-2;
@apply pr-0.5;
@apply bg-primaryDark;
}
</style>

View File

@@ -8,7 +8,7 @@
ref="scrollContainer"
>
<div
class="flex justify-between divide-x divide-divider"
class="flex justify-between divide-x divide-dividerLight"
@wheel.prevent="scroll"
>
<div class="flex">
@@ -50,12 +50,7 @@
<component :is="tabMeta.tabhead" />
</div>
<div
v-if="tabMeta.suffix"
class="flex items-center justify-center"
>
<component :is="tabMeta.suffix" />
</div>
<component v-if="tabMeta.suffix" :is="tabMeta.suffix" />
<HoppButtonSecondary
v-if="tabMeta.isRemovable"
@@ -72,7 +67,7 @@
},
'close',
]"
class="!p-0.25 rounded"
class="!p-0.5"
@click.stop="emit('removeTab', tabID)"
/>
</button>
@@ -85,13 +80,13 @@
<slot name="actions">
<span
v-if="canAddNewTab"
class="flex items-center justify-center px-3 bg-primaryLight z-8 h-full"
class="flex items-center justify-center px-2 py-1.5 bg-primaryLight z-8 h-full"
>
<HoppButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="newText ?? t?.('action.new') ?? 'New'"
:icon="IconPlus"
class="rounded !text-secondaryDark !p-1"
class="rounded !p-1"
filled
@click="addTab"
/>
@@ -228,6 +223,9 @@ const removeTabEntry = (tabID: string) => {
O.chain((index) => pipe(tabEntries.value, A.deleteAt(index))),
O.getOrElseW(() => throwError(`Failed to remove tab entry: ${tabID}`))
)
// If we tried to remove the active tabEntries, switch to first tab entry
if (props.modelValue === tabID)
if (tabEntries.value.length > 0) selectTab(tabEntries.value[0][0])
}
const sortTabs = (e: {
oldDraggableIndex: number
@@ -342,48 +340,43 @@ watch(thumbPosition, (newVal) => {
@apply opacity-50;
&.active {
@apply opacity-100;
@apply opacity-80;
}
}
}
}
$slider-height: 4px;
.slider {
--thumb-width: 0;
--thumb-width: 300px;
-webkit-appearance: none;
width: 100%;
height: $slider-height;
@apply appearance-none;
@apply w-full;
@apply bg-transparent;
@apply outline-none;
@apply opacity-0;
@apply transition;
background: transparent;
outline: none;
opacity: 0;
-webkit-transition: 0.2s;
transition: opacity 0.2s;
&::-webkit-slider-thumb {
@apply appearance-none;
@apply min-w-0;
@apply bg-dividerDark;
@apply hover:bg-secondaryLight;
-webkit-appearance: none;
appearance: none;
min-width: 300px;
width: var(--thumb-width);
height: $slider-height;
background: gray;
cursor: pointer;
}
&::-moz-range-thumb {
@apply appearance-none;
@apply min-w-0;
@apply bg-dividerDark;
@apply hover:bg-secondaryLight;
min-width: 300px;
width: var(--thumb-width);
height: $slider-height;
background: gray;
cursor: pointer;
}
}
.group-tabs:hover .slider {
@apply opacity-100;
opacity: 0.8;
}
</style>

View File

@@ -18,4 +18,3 @@ export { default as HoppSmartTabs } from "./Tabs.vue"
export { default as HoppSmartToggle } from "./Toggle.vue"
export { default as HoppSmartWindow } from "./Window.vue"
export { default as HoppSmartWindows } from "./Windows.vue"
export { default as HoppSmartPicture } from "./Picture.vue"

102
pnpm-lock.yaml generated
View File

@@ -485,8 +485,8 @@ importers:
specifier: ^4.17.21
version: 4.17.21
lossless-json:
specifier: ^2.0.8
version: 2.0.8
specifier: ^1.0.5
version: 1.0.5
nprogress:
specifier: ^0.2.0
version: 0.2.0
@@ -612,8 +612,8 @@ importers:
specifier: ^1.1.40
version: 1.1.40
'@intlify/vite-plugin-vue-i18n':
specifier: ^7.0.0
version: 7.0.0(vite@3.1.4)(vue-i18n@9.2.2)
specifier: ^6.0.1
version: 6.0.1(vite@3.1.4)(vue-i18n@9.2.2)
'@rushstack/eslint-patch':
specifier: ^1.1.4
version: 1.1.4
@@ -891,8 +891,8 @@ importers:
specifier: ^3.1.1
version: 3.1.1(graphql@15.8.0)
'@intlify/vite-plugin-vue-i18n':
specifier: ^7.0.0
version: 7.0.0(vite@3.1.4)(vue-i18n@9.2.2)
specifier: ^6.0.1
version: 6.0.1(vite@3.1.4)(vue-i18n@9.2.2)
'@rushstack/eslint-patch':
specifier: ^1.1.4
version: 1.1.4
@@ -1203,7 +1203,7 @@ importers:
version: 1.1.40
'@intlify/vite-plugin-vue-i18n':
specifier: ^6.0.1
version: 6.0.1(vite@3.2.4)
version: 6.0.1(vite@3.1.4)(vue-i18n@9.2.2)
'@rushstack/eslint-patch':
specifier: ^1.1.4
version: 1.1.4
@@ -1700,7 +1700,7 @@ packages:
convert-source-map: 1.8.0
debug: 4.3.4(supports-color@9.2.2)
gensync: 1.0.0-beta.2
json5: 2.2.3
json5: 2.2.1
semver: 6.3.0
transitivePeerDependencies:
- supports-color
@@ -1729,7 +1729,7 @@ packages:
resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.21.2
'@babel/types': 7.18.7
dev: true
/@babel/helper-builder-binary-assignment-operator-visitor@7.18.6:
@@ -1831,14 +1831,14 @@ packages:
resolution: {integrity: sha512-CeHxqwwipekotzPDUuJOfIMtcIHBuc7WAzLmTYWctVigqS5RktNMQ5bEwQSuGewzYnCtTWa3BARXeiLxDTv+Ng==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.21.2
'@babel/types': 7.18.7
dev: true
/@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.21.2
'@babel/types': 7.18.7
dev: true
/@babel/helper-module-transforms@7.18.6:
@@ -1861,7 +1861,7 @@ packages:
resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.21.2
'@babel/types': 7.18.7
dev: true
/@babel/helper-plugin-utils@7.18.6:
@@ -1897,7 +1897,7 @@ packages:
'@babel/helper-member-expression-to-functions': 7.18.6
'@babel/helper-optimise-call-expression': 7.18.6
'@babel/traverse': 7.18.6
'@babel/types': 7.21.2
'@babel/types': 7.18.7
transitivePeerDependencies:
- supports-color
dev: true
@@ -1906,14 +1906,14 @@ packages:
resolution: {integrity: sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.21.2
'@babel/types': 7.18.7
dev: true
/@babel/helper-skip-transparent-expression-wrappers@7.18.6:
resolution: {integrity: sha512-4KoLhwGS9vGethZpAhYnMejWkX64wsnHPDwvOsKWU6Fg4+AlK2Jz3TyjQLMEPvz+1zemi/WBdkYxCD0bAfIkiw==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.21.2
'@babel/types': 7.18.7
dev: true
/@babel/helper-split-export-declaration@7.18.6:
@@ -2897,7 +2897,7 @@ packages:
engines: {node: '>=6.9.0'}
dependencies:
'@babel/code-frame': 7.18.6
'@babel/parser': 7.21.2
'@babel/parser': 7.18.6
'@babel/types': 7.18.7
dev: true
@@ -5414,27 +5414,7 @@ packages:
- supports-color
dev: true
/@intlify/bundle-utils@3.4.0(vue-i18n@9.2.2):
resolution: {integrity: sha512-2UQkqiSAOSPEHMGWlybqWm4G2K0X+FyYho5AwXz6QklSX1EY5EDmOSxZmwscn2qmKBnp6OYsme5kUrnN9xrWzQ==}
engines: {node: '>= 12'}
peerDependencies:
petite-vue-i18n: '*'
vue-i18n: '*'
peerDependenciesMeta:
petite-vue-i18n:
optional: true
vue-i18n:
optional: true
dependencies:
'@intlify/message-compiler': 9.3.0-beta.17
'@intlify/shared': 9.3.0-beta.17
jsonc-eslint-parser: 1.4.1
source-map: 0.6.1
vue-i18n: 9.2.2(vue@3.2.37)
yaml-eslint-parser: 0.3.2
dev: true
/@intlify/bundle-utils@6.0.0:
/@intlify/bundle-utils@6.0.0(vue-i18n@9.2.2):
resolution: {integrity: sha512-c8nTDgsTrBqVk3LPoF/YEarqeqcW0XAY5Y0UmFl5VKWKRNQh47jzvHRDmeRWhos5bUw1zIdiTixrs99FMJ9j5g==}
engines: {node: '>= 14.16'}
peerDependencies:
@@ -5455,6 +5435,7 @@ packages:
magic-string: 0.30.0
mlly: 1.2.0
source-map: 0.6.1
vue-i18n: 9.2.2(vue@3.2.37)
yaml-eslint-parser: 0.3.2
dev: true
@@ -5497,7 +5478,7 @@ packages:
engines: {node: '>= 14'}
dev: true
/@intlify/vite-plugin-vue-i18n@6.0.1(vite@3.2.4):
/@intlify/vite-plugin-vue-i18n@6.0.1(vite@3.1.4)(vue-i18n@9.2.2):
resolution: {integrity: sha512-FFVcxVU4bR9vdDLNbltM5mrhndnXMErO01i0RrpdyMegEt3Nu/YLoH0sFdjRun7/RY4vaEnhTnFvVf9uO0dQvg==}
engines: {node: '>= 14.6'}
peerDependencies:
@@ -5512,39 +5493,12 @@ packages:
vue-i18n:
optional: true
dependencies:
'@intlify/bundle-utils': 6.0.0
'@intlify/bundle-utils': 6.0.0(vue-i18n@9.2.2)
'@intlify/shared': 9.3.0-beta.17
'@rollup/pluginutils': 4.2.1
debug: 4.3.4(supports-color@9.2.2)
fast-glob: 3.2.11
source-map: 0.6.1
vite: 3.2.4(@types/node@17.0.45)(sass@1.53.0)(terser@5.14.1)
transitivePeerDependencies:
- supports-color
dev: true
/@intlify/vite-plugin-vue-i18n@7.0.0(vite@3.1.4)(vue-i18n@9.2.2):
resolution: {integrity: sha512-2TbDOQ8XD+vkc0s5OFmr+IY/k4mYMC7pzvx0xGQn+cU/ev314+yi7Z7N7rWcBgiYk1WOUalbGSo3d4nJDxOOyw==}
engines: {node: '>= 14.6'}
deprecated: This plugin support until Vite 3. If you would like to use on Vite 4, please use @intlify/unplugin-vue-i18n
peerDependencies:
petite-vue-i18n: '*'
vite: ^2.9.0 || ^3.0.0
vue-i18n: '*'
peerDependenciesMeta:
petite-vue-i18n:
optional: true
vite:
optional: true
vue-i18n:
optional: true
dependencies:
'@intlify/bundle-utils': 3.4.0(vue-i18n@9.2.2)
'@intlify/shared': 9.3.0-beta.17
'@rollup/pluginutils': 4.2.1
debug: 4.3.4(supports-color@9.2.2)
fast-glob: 3.2.12
source-map: 0.6.1
vite: 3.1.4(sass@1.53.0)(terser@5.14.1)
vue-i18n: 9.2.2(vue@3.2.37)
transitivePeerDependencies:
@@ -7085,7 +7039,7 @@ packages:
/@types/babel__core@7.1.19:
resolution: {integrity: sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==}
dependencies:
'@babel/parser': 7.21.2
'@babel/parser': 7.18.6
'@babel/types': 7.18.7
'@types/babel__generator': 7.6.4
'@types/babel__template': 7.4.1
@@ -7095,14 +7049,14 @@ packages:
/@types/babel__generator@7.6.4:
resolution: {integrity: sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==}
dependencies:
'@babel/types': 7.21.2
'@babel/types': 7.18.7
dev: true
/@types/babel__template@7.4.1:
resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==}
dependencies:
'@babel/parser': 7.21.2
'@babel/types': 7.21.2
'@babel/parser': 7.18.6
'@babel/types': 7.18.7
dev: true
/@types/babel__traverse@7.17.1:
@@ -9419,7 +9373,7 @@ packages:
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
dependencies:
'@babel/template': 7.18.6
'@babel/types': 7.21.2
'@babel/types': 7.18.7
'@types/babel__core': 7.1.19
'@types/babel__traverse': 7.17.1
dev: true
@@ -9429,7 +9383,7 @@ packages:
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
'@babel/template': 7.18.6
'@babel/types': 7.21.2
'@babel/types': 7.18.7
'@types/babel__core': 7.1.19
'@types/babel__traverse': 7.17.1
dev: true
@@ -15937,8 +15891,8 @@ packages:
js-tokens: 4.0.0
dev: true
/lossless-json@2.0.8:
resolution: {integrity: sha512-7/GaZldUc7H5oNZlSk6bF06cRbtA7oF8zWXwbfMZm8yrYC2debx0KvWTBbQIbj6fh08LsXTWg+YtHJshXgYKow==}
/lossless-json@1.0.5:
resolution: {integrity: sha512-RicKUuLwZVNZ6ZdJHgIZnSeA05p8qWc5NW0uR96mpPIjN9WDLUg9+kj1esQU1GkPn9iLZVKatSQK5gyiaFHgJA==}
dev: false
/loupe@2.3.6: