chore: remove hoppscotch-web from self-hosted
This commit is contained in:
@@ -1,64 +0,0 @@
|
||||
/* eslint-env node */
|
||||
require("@rushstack/eslint-patch/modern-module-resolution")
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
jest: true,
|
||||
},
|
||||
parserOptions: {
|
||||
sourceType: "module",
|
||||
requireConfigFile: false,
|
||||
},
|
||||
extends: [
|
||||
"@vue/typescript/recommended",
|
||||
"plugin:vue/vue3-recommended",
|
||||
"plugin:prettier/recommended",
|
||||
],
|
||||
ignorePatterns: [
|
||||
"static/**/*",
|
||||
"./helpers/backend/graphql.ts",
|
||||
"**/*.d.ts",
|
||||
"types/**/*",
|
||||
],
|
||||
plugins: ["vue", "prettier"],
|
||||
// add your custom rules here
|
||||
rules: {
|
||||
semi: [2, "never"],
|
||||
"import/named": "off", // because, named import issue with typescript see: https://github.com/typescript-eslint/typescript-eslint/issues/154
|
||||
"no-console": "off",
|
||||
"no-debugger": process.env.HOPP_LINT_FOR_PROD === "true" ? "error" : "warn",
|
||||
"prettier/prettier":
|
||||
process.env.HOPP_LINT_FOR_PROD === "true" ? "error" : "warn",
|
||||
"vue/multi-word-component-names": "off",
|
||||
"vue/no-side-effects-in-computed-properties": "off",
|
||||
"import/no-named-as-default": "off",
|
||||
"import/no-named-as-default-member": "off",
|
||||
"@typescript-eslint/no-unused-vars":
|
||||
process.env.HOPP_LINT_FOR_PROD === "true" ? "error" : "warn",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"import/default": "off",
|
||||
"no-undef": "off",
|
||||
// localStorage block
|
||||
"no-restricted-globals": [
|
||||
"error",
|
||||
{
|
||||
name: "localStorage",
|
||||
message:
|
||||
"Do not use 'localStorage' directly. Please use localpersistence.ts functions or stores",
|
||||
},
|
||||
],
|
||||
// window.localStorage block
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
selector: "CallExpression[callee.object.property.name='localStorage']",
|
||||
message:
|
||||
"Do not use 'localStorage' directly. Please use localpersistence.ts functions or stores",
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
27
packages/hoppscotch-web/.gitignore
vendored
27
packages/hoppscotch-web/.gitignore
vendored
@@ -1,27 +0,0 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
# Sitemap Generation Artifacts (see vite.config.ts)
|
||||
.sitemap-gen
|
||||
@@ -1,26 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Hoppscotch • Open source API development ecosystem</title>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="apple-touch-icon" href="/icon.png" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script>
|
||||
// Shims to make swagger-parser package work
|
||||
window.global = window
|
||||
</script>
|
||||
<script type="module">
|
||||
import { Buffer } from "buffer"
|
||||
import process from "process"
|
||||
|
||||
// // Shims to make postman-collection work
|
||||
window.Buffer = Buffer
|
||||
window.process = process
|
||||
</script>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,118 +0,0 @@
|
||||
import { IHTMLTag } from "vite-plugin-html-config"
|
||||
|
||||
export const APP_INFO = {
|
||||
name: "Hoppscotch",
|
||||
shortDescription: "Open source API development ecosystem",
|
||||
description:
|
||||
"Helps you create requests faster, saving precious time on development.",
|
||||
keywords:
|
||||
"hoppscotch, hopp scotch, hoppscotch online, hoppscotch app, postwoman, postwoman chrome, postwoman online, postwoman for mac, postwoman app, postwoman for windows, postwoman google chrome, postwoman chrome app, get postwoman, postwoman web, postwoman android, postwoman app for chrome, postwoman mobile app, postwoman web app, api, request, testing, tool, rest, websocket, sse, graphql, socketio",
|
||||
app: {
|
||||
background: "#202124",
|
||||
},
|
||||
social: {
|
||||
twitter: "@hoppscotch_io",
|
||||
},
|
||||
} as const
|
||||
|
||||
export const META_TAGS = (env: Record<string, string>): IHTMLTag[] => [
|
||||
{
|
||||
name: "keywords",
|
||||
content: APP_INFO.keywords,
|
||||
},
|
||||
{
|
||||
name: "X-UA-Compatible",
|
||||
content: "IE=edge, chrome=1",
|
||||
},
|
||||
{
|
||||
name: "name",
|
||||
content: `${APP_INFO.name} • ${APP_INFO.shortDescription}`,
|
||||
},
|
||||
{
|
||||
name: "description",
|
||||
content: APP_INFO.description,
|
||||
},
|
||||
{
|
||||
name: "image",
|
||||
content: `${env.VITE_BASE_URL}/banner.png`,
|
||||
},
|
||||
// Open Graph tags
|
||||
{
|
||||
name: "og:title",
|
||||
content: `${APP_INFO.name} • ${APP_INFO.shortDescription}`,
|
||||
},
|
||||
{
|
||||
name: "og:description",
|
||||
content: APP_INFO.description,
|
||||
},
|
||||
{
|
||||
name: "og:image",
|
||||
content: `${env.VITE_BASE_URL}/banner.png`,
|
||||
},
|
||||
// Twitter tags
|
||||
{
|
||||
name: "twitter:card",
|
||||
content: "summary_large_image",
|
||||
},
|
||||
{
|
||||
name: "twitter:site",
|
||||
content: APP_INFO.social.twitter,
|
||||
},
|
||||
{
|
||||
name: "twitter:creator",
|
||||
content: APP_INFO.social.twitter,
|
||||
},
|
||||
{
|
||||
name: "twitter:title",
|
||||
content: `${APP_INFO.name} • ${APP_INFO.shortDescription}`,
|
||||
},
|
||||
{
|
||||
name: "twitter:description",
|
||||
content: APP_INFO.description,
|
||||
},
|
||||
{
|
||||
name: "twitter:image",
|
||||
content: `${env.VITE_BASE_URL}/banner.png`,
|
||||
},
|
||||
// Add to homescreen for Chrome on Android. Fallback for PWA (handled by nuxt)
|
||||
{
|
||||
name: "application-name",
|
||||
content: APP_INFO.name,
|
||||
},
|
||||
// Windows phone tile icon
|
||||
{
|
||||
name: "msapplication-TileImage",
|
||||
content: `${env.VITE_BASE_URL}/icon.png`,
|
||||
},
|
||||
{
|
||||
name: "msapplication-TileColor",
|
||||
content: APP_INFO.app.background,
|
||||
},
|
||||
{
|
||||
name: "msapplication-tap-highlight",
|
||||
content: "no",
|
||||
},
|
||||
// iOS Safari
|
||||
{
|
||||
name: "apple-mobile-web-app-title",
|
||||
content: APP_INFO.name,
|
||||
},
|
||||
{
|
||||
name: "apple-mobile-web-app-capable",
|
||||
content: "yes",
|
||||
},
|
||||
{
|
||||
name: "apple-mobile-web-app-status-bar-style",
|
||||
content: "black-translucent",
|
||||
},
|
||||
// PWA
|
||||
{
|
||||
name: "theme-color",
|
||||
content: APP_INFO.app.background,
|
||||
},
|
||||
{
|
||||
name: "mask-icon",
|
||||
content: "/icon.png",
|
||||
color: APP_INFO.app.background,
|
||||
},
|
||||
]
|
||||
@@ -1,62 +0,0 @@
|
||||
{
|
||||
"name": "@hoppscotch/web",
|
||||
"private": true,
|
||||
"version": "2023.4.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "node --max_old_space_size=16384 ./node_modules/vite/bin/vite.js build",
|
||||
"preview": "vite preview",
|
||||
"lint": "eslint src --ext .ts,.js,.vue --ignore-path .gitignore .",
|
||||
"lint:ts": "vue-tsc --noEmit",
|
||||
"lintfix": "eslint --fix src --ext .ts,.js,.vue --ignore-path .gitignore .",
|
||||
"prod-lint": "cross-env HOPP_LINT_FOR_PROD=true pnpm run lint",
|
||||
"generate": "pnpm run build",
|
||||
"do-dev": "pnpm run dev",
|
||||
"do-build-prod": "pnpm run build",
|
||||
"do-lint": "pnpm run prod-lint",
|
||||
"do-typecheck": "pnpm run lint",
|
||||
"do-lintfix": "pnpm run lintfix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hoppscotch/common": "workspace:^",
|
||||
"@hoppscotch/ui": "workspace:^",
|
||||
"buffer": "^6.0.3",
|
||||
"firebase": "^9.8.4",
|
||||
"process": "^0.11.10",
|
||||
"rxjs": "^7.5.5",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"util": "^0.12.4",
|
||||
"vue": "^3.2.41",
|
||||
"workbox-window": "^6.5.4",
|
||||
"@hoppscotch/data": "workspace:^"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@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",
|
||||
"@vitejs/plugin-legacy": "^2.3.0",
|
||||
"@vitejs/plugin-vue": "^3.2.0",
|
||||
"@vue/eslint-config-typescript": "^11.0.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^8.28.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-vue": "^9.5.1",
|
||||
"typescript": "^4.6.4",
|
||||
"unplugin-icons": "^0.14.9",
|
||||
"unplugin-vue-components": "^0.21.0",
|
||||
"vite": "^3.2.3",
|
||||
"vite-plugin-fonts": "^0.6.0",
|
||||
"vite-plugin-html-config": "^1.0.10",
|
||||
"vite-plugin-inspect": "^0.7.4",
|
||||
"vite-plugin-pages": "^0.26.0",
|
||||
"vite-plugin-pages-sitemap": "^1.4.0",
|
||||
"vite-plugin-pwa": "^0.13.1",
|
||||
"vite-plugin-static-copy": "^0.12.0",
|
||||
"vite-plugin-vue-layouts": "^0.7.0",
|
||||
"vite-plugin-windicss": "^1.8.8",
|
||||
"vue-tsc": "^1.0.9",
|
||||
"windicss": "^3.5.6"
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
import {
|
||||
AnalyticsPlatformDef,
|
||||
HoppRequestEvent,
|
||||
} from "@hoppscotch/common/platform/analytics"
|
||||
|
||||
import {
|
||||
Analytics,
|
||||
getAnalytics,
|
||||
logEvent,
|
||||
setAnalyticsCollectionEnabled,
|
||||
setUserId,
|
||||
setUserProperties,
|
||||
} from "firebase/analytics"
|
||||
import { def as platformAuth } from "./firebase/auth"
|
||||
import {
|
||||
HoppAccentColor,
|
||||
HoppBgColor,
|
||||
settings$,
|
||||
settingsStore,
|
||||
} from "@hoppscotch/common/newstore/settings"
|
||||
|
||||
let analytics: Analytics | null = null
|
||||
|
||||
type SettingsCustomDimensions = {
|
||||
usesProxy: boolean
|
||||
usesExtension: boolean
|
||||
syncCollections: boolean
|
||||
syncEnvironments: boolean
|
||||
syncHistory: boolean
|
||||
usesBg: HoppBgColor
|
||||
usesAccent: HoppAccentColor
|
||||
usesTelemetry: boolean
|
||||
}
|
||||
|
||||
export function initAnalytics() {
|
||||
analytics = getAnalytics()
|
||||
|
||||
initLoginListeners()
|
||||
initSettingsListeners()
|
||||
}
|
||||
|
||||
function initLoginListeners() {
|
||||
const authEvents$ = platformAuth.getAuthEventsStream()
|
||||
|
||||
authEvents$.subscribe((ev) => {
|
||||
if (ev.event === "login") {
|
||||
if (settingsStore.value.TELEMETRY_ENABLED && analytics) {
|
||||
setUserId(analytics, ev.user.uid)
|
||||
|
||||
logEvent(analytics, "login", {
|
||||
method: ev.user.provider, // Assume the first provider is the login provider
|
||||
})
|
||||
}
|
||||
} else if (ev.event === "logout") {
|
||||
if (settingsStore.value.TELEMETRY_ENABLED && analytics) {
|
||||
logEvent(analytics, "logout")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function initSettingsListeners() {
|
||||
// Keep track of the telemetry status
|
||||
let telemetryStatus = settingsStore.value.TELEMETRY_ENABLED
|
||||
|
||||
settings$.subscribe((settings) => {
|
||||
const conf: SettingsCustomDimensions = {
|
||||
usesProxy: settings.PROXY_ENABLED,
|
||||
usesExtension: settings.EXTENSIONS_ENABLED,
|
||||
syncCollections: settings.syncCollections,
|
||||
syncEnvironments: settings.syncEnvironments,
|
||||
syncHistory: settings.syncHistory,
|
||||
usesAccent: settings.THEME_COLOR,
|
||||
usesBg: settings.BG_COLOR,
|
||||
usesTelemetry: settings.TELEMETRY_ENABLED,
|
||||
}
|
||||
|
||||
// User toggled telemetry mode to off or to on
|
||||
if (
|
||||
((telemetryStatus && !settings.TELEMETRY_ENABLED) ||
|
||||
settings.TELEMETRY_ENABLED) &&
|
||||
analytics
|
||||
) {
|
||||
setUserProperties(analytics, conf)
|
||||
}
|
||||
|
||||
telemetryStatus = settings.TELEMETRY_ENABLED
|
||||
|
||||
if (analytics) setAnalyticsCollectionEnabled(analytics, telemetryStatus)
|
||||
})
|
||||
|
||||
if (analytics) setAnalyticsCollectionEnabled(analytics, telemetryStatus)
|
||||
}
|
||||
|
||||
export function logHoppRequestRunToAnalytics(ev: HoppRequestEvent) {
|
||||
if (settingsStore.value.TELEMETRY_ENABLED && analytics) {
|
||||
logEvent(analytics, "hopp-request", ev)
|
||||
}
|
||||
}
|
||||
|
||||
export function logPageView(pagePath: string) {
|
||||
if (settingsStore.value.TELEMETRY_ENABLED && analytics) {
|
||||
logEvent(analytics, "page_view", {
|
||||
page_path: pagePath,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const def: AnalyticsPlatformDef = {
|
||||
initAnalytics,
|
||||
logHoppRequestRunToAnalytics,
|
||||
logPageView,
|
||||
}
|
||||
@@ -1,193 +0,0 @@
|
||||
import {
|
||||
collection,
|
||||
doc,
|
||||
getFirestore,
|
||||
onSnapshot,
|
||||
setDoc,
|
||||
} from "firebase/firestore"
|
||||
import {
|
||||
translateToNewRESTCollection,
|
||||
translateToNewGQLCollection,
|
||||
} from "@hoppscotch/data"
|
||||
|
||||
import { def as platformAuth } from "./firebase/auth"
|
||||
|
||||
import {
|
||||
restCollections$,
|
||||
graphqlCollections$,
|
||||
setRESTCollections,
|
||||
setGraphqlCollections,
|
||||
} from "@hoppscotch/common/newstore/collections"
|
||||
|
||||
import {
|
||||
getSettingSubject,
|
||||
settingsStore,
|
||||
} from "@hoppscotch/common/newstore/settings"
|
||||
|
||||
import { CollectionsPlatformDef } from "@hoppscotch/common/platform/collections"
|
||||
|
||||
type CollectionFlags = "collectionsGraphql" | "collections"
|
||||
|
||||
/**
|
||||
* Whether the collections are loaded. If this is set to true
|
||||
* Updates to the collections store are written into firebase.
|
||||
*
|
||||
* If you have want to update the store and not fire the store update
|
||||
* subscription, set this variable to false, do the update and then
|
||||
* set it to true
|
||||
*/
|
||||
let loadedRESTCollections = false
|
||||
|
||||
/**
|
||||
* Whether the collections are loaded. If this is set to true
|
||||
* Updates to the collections store are written into firebase.
|
||||
*
|
||||
* If you have want to update the store and not fire the store update
|
||||
* subscription, set this variable to false, do the update and then
|
||||
* set it to true
|
||||
*/
|
||||
let loadedGraphqlCollections = false
|
||||
|
||||
async function writeCollections(collection: any[], flag: CollectionFlags) {
|
||||
const currentUser = platformAuth.getCurrentUser()
|
||||
|
||||
if (currentUser === null)
|
||||
throw new Error("User not logged in to write collections")
|
||||
|
||||
const cl = {
|
||||
updatedOn: new Date(),
|
||||
author: currentUser.uid,
|
||||
author_name: currentUser.displayName,
|
||||
author_image: currentUser.photoURL,
|
||||
collection,
|
||||
}
|
||||
|
||||
try {
|
||||
await setDoc(
|
||||
doc(getFirestore(), "users", currentUser.uid, flag, "sync"),
|
||||
cl
|
||||
)
|
||||
} catch (e) {
|
||||
console.error("error updating", cl, e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
function initCollectionsSync() {
|
||||
const currentUser$ = platformAuth.getCurrentUserStream()
|
||||
|
||||
const restCollSub = restCollections$.subscribe((collections) => {
|
||||
const currentUser = platformAuth.getCurrentUser()
|
||||
|
||||
if (
|
||||
loadedRESTCollections &&
|
||||
currentUser &&
|
||||
settingsStore.value.syncCollections
|
||||
) {
|
||||
writeCollections(collections, "collections")
|
||||
}
|
||||
})
|
||||
|
||||
const gqlCollSub = graphqlCollections$.subscribe((collections) => {
|
||||
const currentUser = platformAuth.getCurrentUser()
|
||||
|
||||
if (
|
||||
loadedGraphqlCollections &&
|
||||
currentUser &&
|
||||
settingsStore.value.syncCollections
|
||||
) {
|
||||
writeCollections(collections, "collectionsGraphql")
|
||||
}
|
||||
})
|
||||
|
||||
let restSnapshotStop: (() => void) | null = null
|
||||
let graphqlSnapshotStop: (() => void) | null = null
|
||||
|
||||
const currentUserSub = currentUser$.subscribe((user) => {
|
||||
if (!user) {
|
||||
if (restSnapshotStop) {
|
||||
restSnapshotStop()
|
||||
restSnapshotStop = null
|
||||
}
|
||||
|
||||
if (graphqlSnapshotStop) {
|
||||
graphqlSnapshotStop()
|
||||
graphqlSnapshotStop = null
|
||||
}
|
||||
} else {
|
||||
restSnapshotStop = onSnapshot(
|
||||
collection(getFirestore(), "users", user.uid, "collections"),
|
||||
(collectionsRef) => {
|
||||
const collections: any[] = []
|
||||
collectionsRef.forEach((doc) => {
|
||||
const collection = doc.data()
|
||||
collection.id = doc.id
|
||||
collections.push(collection)
|
||||
})
|
||||
|
||||
// Prevent infinite ping-pong of updates
|
||||
loadedRESTCollections = false
|
||||
|
||||
// TODO: Wth is with collections[0]
|
||||
if (collections.length > 0 && settingsStore.value.syncCollections) {
|
||||
setRESTCollections(
|
||||
(collections[0].collection ?? []).map(
|
||||
translateToNewRESTCollection
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
loadedRESTCollections = true
|
||||
}
|
||||
)
|
||||
|
||||
graphqlSnapshotStop = onSnapshot(
|
||||
collection(getFirestore(), "users", user.uid, "collectionsGraphql"),
|
||||
(collectionsRef) => {
|
||||
const collections: any[] = []
|
||||
collectionsRef.forEach((doc) => {
|
||||
const collection = doc.data()
|
||||
collection.id = doc.id
|
||||
collections.push(collection)
|
||||
})
|
||||
|
||||
// Prevent infinite ping-pong of updates
|
||||
loadedGraphqlCollections = false
|
||||
|
||||
// TODO: Wth is with collections[0]
|
||||
if (collections.length > 0 && settingsStore.value.syncCollections) {
|
||||
setGraphqlCollections(
|
||||
(collections[0].collection ?? []).map(translateToNewGQLCollection)
|
||||
)
|
||||
}
|
||||
|
||||
loadedGraphqlCollections = true
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
let oldSyncStatus = settingsStore.value.syncCollections
|
||||
|
||||
const syncStop = getSettingSubject("syncCollections").subscribe(
|
||||
(newStatus) => {
|
||||
if (oldSyncStatus === true && newStatus === false) {
|
||||
restSnapshotStop?.()
|
||||
graphqlSnapshotStop?.()
|
||||
|
||||
oldSyncStatus = newStatus
|
||||
} else if (oldSyncStatus === false && newStatus === true) {
|
||||
syncStop.unsubscribe()
|
||||
restCollSub.unsubscribe()
|
||||
gqlCollSub.unsubscribe()
|
||||
currentUserSub.unsubscribe()
|
||||
|
||||
initCollectionsSync()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
export const def: CollectionsPlatformDef = {
|
||||
initCollectionsSync,
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
import { Environment } from "@hoppscotch/data"
|
||||
import {
|
||||
collection,
|
||||
doc,
|
||||
getFirestore,
|
||||
onSnapshot,
|
||||
setDoc,
|
||||
} from "firebase/firestore"
|
||||
import { def as platformAuth } from "./firebase/auth"
|
||||
import {
|
||||
environments$,
|
||||
globalEnv$,
|
||||
replaceEnvironments,
|
||||
setGlobalEnvVariables,
|
||||
} from "@hoppscotch/common/newstore/environments"
|
||||
import {
|
||||
getSettingSubject,
|
||||
settingsStore,
|
||||
} from "@hoppscotch/common/newstore/settings"
|
||||
import { EnvironmentsPlatformDef } from "@hoppscotch/common/platform/environments"
|
||||
|
||||
/**
|
||||
* Used locally to prevent infinite loop when environment sync update
|
||||
* is applied to the store which then fires the store sync listener.
|
||||
* When you want to update environments and not want to fire the update listener,
|
||||
* set this to true and then set it back to false once it is done
|
||||
*/
|
||||
let loadedEnvironments = false
|
||||
|
||||
/**
|
||||
* Used locally to prevent infinite loop when global env sync update
|
||||
* is applied to the store which then fires the store sync listener.
|
||||
* When you want to update global env and not want to fire the update listener,
|
||||
* set this to true and then set it back to false once it is done
|
||||
*/
|
||||
let loadedGlobals = true
|
||||
|
||||
async function writeEnvironments(environment: Environment[]) {
|
||||
const currentUser = platformAuth.getCurrentUser()
|
||||
|
||||
if (currentUser === null)
|
||||
throw new Error("Cannot write environments when signed out")
|
||||
|
||||
const ev = {
|
||||
updatedOn: new Date(),
|
||||
author: currentUser.uid,
|
||||
author_name: currentUser.displayName,
|
||||
author_image: currentUser.photoURL,
|
||||
environment,
|
||||
}
|
||||
|
||||
try {
|
||||
await setDoc(
|
||||
doc(getFirestore(), "users", currentUser.uid, "environments", "sync"),
|
||||
ev
|
||||
)
|
||||
} catch (e) {
|
||||
console.error("error updating", ev, e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
async function writeGlobalEnvironment(variables: Environment["variables"]) {
|
||||
const currentUser = platformAuth.getCurrentUser()
|
||||
|
||||
if (currentUser === null)
|
||||
throw new Error("Cannot write global environment when signed out")
|
||||
|
||||
const ev = {
|
||||
updatedOn: new Date(),
|
||||
author: currentUser.uid,
|
||||
author_name: currentUser.displayName,
|
||||
author_image: currentUser.photoURL,
|
||||
variables,
|
||||
}
|
||||
|
||||
try {
|
||||
await setDoc(
|
||||
doc(getFirestore(), "users", currentUser.uid, "globalEnv", "sync"),
|
||||
ev
|
||||
)
|
||||
} catch (e) {
|
||||
console.error("error updating", ev, e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
export function initEnvironmentsSync() {
|
||||
const currentUser$ = platformAuth.getCurrentUserStream()
|
||||
|
||||
const envListenSub = environments$.subscribe((envs) => {
|
||||
const currentUser = platformAuth.getCurrentUser()
|
||||
|
||||
if (
|
||||
currentUser &&
|
||||
settingsStore.value.syncEnvironments &&
|
||||
loadedEnvironments
|
||||
) {
|
||||
writeEnvironments(envs)
|
||||
}
|
||||
})
|
||||
|
||||
const globalListenSub = globalEnv$.subscribe((vars) => {
|
||||
const currentUser = platformAuth.getCurrentUser()
|
||||
|
||||
if (currentUser && settingsStore.value.syncEnvironments && loadedGlobals) {
|
||||
writeGlobalEnvironment(vars)
|
||||
}
|
||||
})
|
||||
|
||||
let envSnapshotStop: (() => void) | null = null
|
||||
let globalsSnapshotStop: (() => void) | null = null
|
||||
|
||||
const currentUserSub = currentUser$.subscribe((user) => {
|
||||
if (!user) {
|
||||
// User logged out, clean up snapshot listener
|
||||
if (envSnapshotStop) {
|
||||
envSnapshotStop()
|
||||
envSnapshotStop = null
|
||||
}
|
||||
|
||||
if (globalsSnapshotStop) {
|
||||
globalsSnapshotStop()
|
||||
globalsSnapshotStop = null
|
||||
}
|
||||
} else if (user) {
|
||||
envSnapshotStop = onSnapshot(
|
||||
collection(getFirestore(), "users", user.uid, "environments"),
|
||||
(environmentsRef) => {
|
||||
const environments: any[] = []
|
||||
|
||||
environmentsRef.forEach((doc) => {
|
||||
const environment = doc.data()
|
||||
environment.id = doc.id
|
||||
environments.push(environment)
|
||||
})
|
||||
|
||||
loadedEnvironments = false
|
||||
if (environments.length > 0 && settingsStore.value.syncEnvironments) {
|
||||
replaceEnvironments(environments[0].environment)
|
||||
}
|
||||
loadedEnvironments = true
|
||||
}
|
||||
)
|
||||
globalsSnapshotStop = onSnapshot(
|
||||
collection(getFirestore(), "users", user.uid, "globalEnv"),
|
||||
(globalsRef) => {
|
||||
if (globalsRef.docs.length === 0) {
|
||||
loadedGlobals = true
|
||||
return
|
||||
}
|
||||
|
||||
const doc = globalsRef.docs[0].data()
|
||||
loadedGlobals = false
|
||||
if (settingsStore.value.syncEnvironments)
|
||||
setGlobalEnvVariables(doc.variables)
|
||||
loadedGlobals = true
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
let oldSyncStatus = settingsStore.value.syncEnvironments
|
||||
|
||||
const syncStop = getSettingSubject("syncEnvironments").subscribe(
|
||||
(newStatus) => {
|
||||
if (oldSyncStatus === true && newStatus === false) {
|
||||
envSnapshotStop?.()
|
||||
globalsSnapshotStop?.()
|
||||
|
||||
oldSyncStatus = newStatus
|
||||
} else if (oldSyncStatus === false && newStatus === true) {
|
||||
syncStop.unsubscribe()
|
||||
envListenSub.unsubscribe()
|
||||
globalListenSub.unsubscribe()
|
||||
currentUserSub.unsubscribe()
|
||||
|
||||
initEnvironmentsSync()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
export const def: EnvironmentsPlatformDef = {
|
||||
initEnvironmentsSync,
|
||||
}
|
||||
@@ -1,436 +0,0 @@
|
||||
import {
|
||||
AuthEvent,
|
||||
AuthPlatformDef,
|
||||
HoppUser,
|
||||
} from "@hoppscotch/common/platform/auth"
|
||||
import {
|
||||
Subscription,
|
||||
BehaviorSubject,
|
||||
Subject,
|
||||
filter,
|
||||
map,
|
||||
combineLatest,
|
||||
} from "rxjs"
|
||||
import {
|
||||
setDoc,
|
||||
onSnapshot,
|
||||
updateDoc,
|
||||
doc,
|
||||
getFirestore,
|
||||
} from "firebase/firestore"
|
||||
import {
|
||||
AuthError,
|
||||
AuthCredential,
|
||||
User as FBUser,
|
||||
sendSignInLinkToEmail,
|
||||
linkWithCredential,
|
||||
getAuth,
|
||||
ActionCodeSettings,
|
||||
isSignInWithEmailLink as isSignInWithEmailLinkFB,
|
||||
signInWithEmailLink as signInWithEmailLinkFB,
|
||||
sendEmailVerification,
|
||||
signInWithPopup,
|
||||
GoogleAuthProvider,
|
||||
GithubAuthProvider,
|
||||
OAuthProvider,
|
||||
fetchSignInMethodsForEmail,
|
||||
updateEmail,
|
||||
updateProfile,
|
||||
reauthenticateWithCredential,
|
||||
onAuthStateChanged,
|
||||
onIdTokenChanged,
|
||||
signOut,
|
||||
} from "firebase/auth"
|
||||
import {
|
||||
getLocalConfig,
|
||||
removeLocalConfig,
|
||||
setLocalConfig,
|
||||
} from "@hoppscotch/common/newstore/localpersistence"
|
||||
|
||||
export const currentUserFB$ = new BehaviorSubject<FBUser | null>(null)
|
||||
export const authEvents$ = new Subject<AuthEvent>()
|
||||
export const probableUser$ = new BehaviorSubject<HoppUser | null>(null)
|
||||
|
||||
const authIdToken$ = new BehaviorSubject<string | null>(null)
|
||||
|
||||
async function signInWithEmailLink(email: string, url: string) {
|
||||
return await signInWithEmailLinkFB(getAuth(), email, url)
|
||||
}
|
||||
|
||||
function fbUserToHoppUser(user: FBUser): HoppUser {
|
||||
return {
|
||||
uid: user.uid,
|
||||
displayName: user.displayName,
|
||||
email: user.email,
|
||||
photoURL: user.photoURL,
|
||||
emailVerified: user.emailVerified,
|
||||
}
|
||||
}
|
||||
|
||||
const currentUser$ = new BehaviorSubject<HoppUser | null>(null)
|
||||
|
||||
const EMAIL_ACTION_CODE_SETTINGS: ActionCodeSettings = {
|
||||
url: `${import.meta.env.VITE_BASE_URL}/enter`,
|
||||
handleCodeInApp: true,
|
||||
}
|
||||
|
||||
async function signInUserWithGithubFB() {
|
||||
return await signInWithPopup(
|
||||
getAuth(),
|
||||
new GithubAuthProvider().addScope("gist")
|
||||
)
|
||||
}
|
||||
|
||||
async function signInUserWithGoogleFB() {
|
||||
return await signInWithPopup(getAuth(), new GoogleAuthProvider())
|
||||
}
|
||||
|
||||
async function signInUserWithMicrosoftFB() {
|
||||
return await signInWithPopup(getAuth(), new OAuthProvider("microsoft.com"))
|
||||
}
|
||||
|
||||
/**
|
||||
* Reauthenticate the user with the given credential
|
||||
*/
|
||||
async function reauthenticateUser() {
|
||||
if (!currentUserFB$.value || !currentUser$.value)
|
||||
throw new Error("No user has logged in")
|
||||
|
||||
const currentAuthMethod = currentUser$.value.provider
|
||||
|
||||
let credential
|
||||
if (currentAuthMethod === "google.com") {
|
||||
// const result = await signInUserWithGithubFB()
|
||||
const result = await signInUserWithGoogleFB()
|
||||
credential = GithubAuthProvider.credentialFromResult(result)
|
||||
} else if (currentAuthMethod === "github.com") {
|
||||
// const result = await signInUserWithGoogleFB()
|
||||
const result = await signInUserWithGithubFB()
|
||||
credential = GoogleAuthProvider.credentialFromResult(result)
|
||||
} else if (currentAuthMethod === "microsoft.com") {
|
||||
const result = await signInUserWithMicrosoftFB()
|
||||
credential = OAuthProvider.credentialFromResult(result)
|
||||
} else if (currentAuthMethod === "password") {
|
||||
const email = prompt(
|
||||
"Reauthenticate your account using your current email:"
|
||||
)
|
||||
|
||||
await def
|
||||
.signInWithEmail(email as string)
|
||||
.then(() =>
|
||||
alert(
|
||||
`Check your inbox - we sent an email to ${email}. It contains a magic link that will reauthenticate your account.`
|
||||
)
|
||||
)
|
||||
.catch((e) => {
|
||||
alert(`Error: ${e.message}`)
|
||||
console.error(e)
|
||||
})
|
||||
return
|
||||
}
|
||||
try {
|
||||
await reauthenticateWithCredential(
|
||||
currentUserFB$.value,
|
||||
credential as AuthCredential
|
||||
)
|
||||
} catch (e) {
|
||||
console.error("error updating", e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Links account with another account given in a auth/account-exists-with-different-credential error
|
||||
*
|
||||
* @param error - Error caught after trying to login
|
||||
*
|
||||
* @returns Promise of UserCredential
|
||||
*/
|
||||
async function linkWithFBCredentialFromAuthError(error: unknown) {
|
||||
// credential is not null since this function is called after an auth/account-exists-with-different-credential error, ie credentials actually exist
|
||||
const credentials = OAuthProvider.credentialFromError(error as AuthError)!
|
||||
|
||||
const otherLinkedProviders = (
|
||||
await getSignInMethodsForEmail((error as AuthError).customData.email!)
|
||||
).filter((providerId) => credentials.providerId !== providerId)
|
||||
|
||||
let user: FBUser | null = null
|
||||
|
||||
if (otherLinkedProviders.indexOf("google.com") >= -1) {
|
||||
user = (await signInUserWithGoogleFB()).user
|
||||
} else if (otherLinkedProviders.indexOf("github.com") >= -1) {
|
||||
user = (await signInUserWithGithubFB()).user
|
||||
} else if (otherLinkedProviders.indexOf("microsoft.com") >= -1) {
|
||||
user = (await signInUserWithMicrosoftFB()).user
|
||||
}
|
||||
|
||||
// user is not null since going through each provider will return a user
|
||||
return await linkWithCredential(user!, credentials)
|
||||
}
|
||||
|
||||
async function setProviderInfo(id: string, token: string) {
|
||||
if (!currentUser$.value) throw new Error("No user has logged in")
|
||||
|
||||
const us = {
|
||||
updatedOn: new Date(),
|
||||
provider: id,
|
||||
accessToken: token,
|
||||
}
|
||||
|
||||
try {
|
||||
await updateDoc(doc(getFirestore(), "users", currentUser$.value.uid), us)
|
||||
} catch (e) {
|
||||
console.error("error updating provider info", e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
async function getSignInMethodsForEmail(email: string) {
|
||||
return await fetchSignInMethodsForEmail(getAuth(), email)
|
||||
}
|
||||
|
||||
export const def: AuthPlatformDef = {
|
||||
getCurrentUserStream: () => currentUser$,
|
||||
getAuthEventsStream: () => authEvents$,
|
||||
getProbableUserStream: () => probableUser$,
|
||||
|
||||
getCurrentUser: () => currentUser$.value,
|
||||
getProbableUser: () => probableUser$.value,
|
||||
|
||||
getBackendHeaders() {
|
||||
return {
|
||||
authorization: `Bearer ${authIdToken$.value}`,
|
||||
}
|
||||
},
|
||||
willBackendHaveAuthError() {
|
||||
return !authIdToken$.value
|
||||
},
|
||||
onBackendGQLClientShouldReconnect(func) {
|
||||
authIdToken$.subscribe(() => {
|
||||
func()
|
||||
})
|
||||
},
|
||||
getDevOptsBackendIDToken() {
|
||||
return authIdToken$.value
|
||||
},
|
||||
performAuthInit() {
|
||||
// todo: implement
|
||||
const auth = getAuth()
|
||||
const firestore = getFirestore()
|
||||
|
||||
combineLatest([currentUserFB$, authIdToken$])
|
||||
.pipe(
|
||||
map(([user, token]) => {
|
||||
// If there is no auth token, we will just consider as the auth as not complete
|
||||
if (token === null) return null
|
||||
if (user !== null) return fbUserToHoppUser(user)
|
||||
return null
|
||||
})
|
||||
)
|
||||
.subscribe((x) => {
|
||||
currentUser$.next(x)
|
||||
})
|
||||
|
||||
let extraSnapshotStop: (() => void) | null = null
|
||||
|
||||
probableUser$.next(JSON.parse(getLocalConfig("login_state") ?? "null"))
|
||||
|
||||
onAuthStateChanged(auth, (user) => {
|
||||
const wasLoggedIn = currentUser$.value !== null
|
||||
|
||||
if (user) {
|
||||
probableUser$.next(user)
|
||||
} else {
|
||||
probableUser$.next(null)
|
||||
removeLocalConfig("login_state")
|
||||
}
|
||||
|
||||
if (!user && extraSnapshotStop) {
|
||||
extraSnapshotStop()
|
||||
extraSnapshotStop = null
|
||||
} else if (user) {
|
||||
// Merge all the user info from all the authenticated providers
|
||||
user.providerData.forEach((profile) => {
|
||||
if (!profile) return
|
||||
|
||||
const us = {
|
||||
updatedOn: new Date(),
|
||||
provider: profile.providerId,
|
||||
name: profile.displayName,
|
||||
email: profile.email,
|
||||
photoUrl: profile.photoURL,
|
||||
uid: profile.uid,
|
||||
}
|
||||
|
||||
setDoc(doc(firestore, "users", user.uid), us, { merge: true }).catch(
|
||||
(e) => console.error("error updating", us, e)
|
||||
)
|
||||
})
|
||||
|
||||
extraSnapshotStop = onSnapshot(
|
||||
doc(firestore, "users", user.uid),
|
||||
(doc) => {
|
||||
const data = doc.data()
|
||||
|
||||
const userUpdate: HoppUser = fbUserToHoppUser(user)
|
||||
|
||||
if (data) {
|
||||
// Write extra provider data
|
||||
userUpdate.provider = data.provider
|
||||
userUpdate.accessToken = data.accessToken
|
||||
}
|
||||
|
||||
currentUser$.next(userUpdate)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
currentUserFB$.next(user)
|
||||
currentUser$.next(user === null ? null : fbUserToHoppUser(user))
|
||||
|
||||
// User wasn't found before, but now is there (login happened)
|
||||
if (!wasLoggedIn && user) {
|
||||
authEvents$.next({
|
||||
event: "login",
|
||||
user: currentUser$.value!,
|
||||
})
|
||||
} else if (wasLoggedIn && !user) {
|
||||
// User was found before, but now is not there (logout happened)
|
||||
authEvents$.next({
|
||||
event: "logout",
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
onIdTokenChanged(auth, async (user) => {
|
||||
if (user) {
|
||||
authIdToken$.next(await user.getIdToken())
|
||||
|
||||
setLocalConfig("login_state", JSON.stringify(user))
|
||||
} else {
|
||||
authIdToken$.next(null)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
waitProbableLoginToConfirm() {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
if (authIdToken$.value) resolve()
|
||||
|
||||
if (!probableUser$.value) reject(new Error("no_probable_user"))
|
||||
|
||||
let sub: Subscription | null = null
|
||||
sub = authIdToken$.pipe(filter((token) => !!token)).subscribe(() => {
|
||||
sub?.unsubscribe()
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
async signInWithEmail(email: string) {
|
||||
return await sendSignInLinkToEmail(
|
||||
getAuth(),
|
||||
email,
|
||||
EMAIL_ACTION_CODE_SETTINGS
|
||||
)
|
||||
},
|
||||
|
||||
isSignInWithEmailLink(url: string) {
|
||||
return isSignInWithEmailLinkFB(getAuth(), url)
|
||||
},
|
||||
|
||||
async verifyEmailAddress() {
|
||||
if (!currentUserFB$.value) throw new Error("No user has logged in")
|
||||
|
||||
try {
|
||||
await sendEmailVerification(currentUserFB$.value)
|
||||
} catch (e) {
|
||||
console.error("error verifying email address", e)
|
||||
throw e
|
||||
}
|
||||
},
|
||||
async signInUserWithGoogle() {
|
||||
await signInUserWithGoogleFB()
|
||||
},
|
||||
async signInUserWithGithub() {
|
||||
try {
|
||||
const cred = await signInUserWithGithubFB()
|
||||
const oAuthCred = GithubAuthProvider.credentialFromResult(cred)!
|
||||
const token = oAuthCred.accessToken
|
||||
await setProviderInfo(cred.providerId!, token!)
|
||||
|
||||
return {
|
||||
type: "success",
|
||||
user: fbUserToHoppUser(cred.user),
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("error while logging in with github", e)
|
||||
|
||||
if ((e as any).code === "auth/account-exists-with-different-credential") {
|
||||
return {
|
||||
type: "account-exists-with-different-cred",
|
||||
link: async () => {
|
||||
await linkWithFBCredentialFromAuthError(e)
|
||||
},
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
type: "error",
|
||||
err: e,
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
async signInUserWithMicrosoft() {
|
||||
await signInUserWithMicrosoftFB()
|
||||
},
|
||||
async signInWithEmailLink(email: string, url: string) {
|
||||
await signInWithEmailLinkFB(getAuth(), email, url)
|
||||
},
|
||||
async setEmailAddress(email: string) {
|
||||
if (!currentUserFB$.value) throw new Error("No user has logged in")
|
||||
|
||||
try {
|
||||
await updateEmail(currentUserFB$.value, email)
|
||||
} catch (e) {
|
||||
await reauthenticateUser()
|
||||
console.log("error setting email address", e)
|
||||
throw e
|
||||
}
|
||||
},
|
||||
async setDisplayName(name: string) {
|
||||
if (!currentUserFB$.value) throw new Error("No user has logged in")
|
||||
|
||||
const us = {
|
||||
displayName: name,
|
||||
}
|
||||
|
||||
try {
|
||||
await updateProfile(currentUserFB$.value, us)
|
||||
} catch (e) {
|
||||
console.error("error updating display name", e)
|
||||
throw e
|
||||
}
|
||||
},
|
||||
async signOutUser() {
|
||||
if (!currentUser$.value) throw new Error("No user has logged in")
|
||||
|
||||
await signOut(getAuth())
|
||||
},
|
||||
async processMagicLink() {
|
||||
if (this.isSignInWithEmailLink(window.location.href)) {
|
||||
let email = getLocalConfig("emailForSignIn")
|
||||
|
||||
if (!email) {
|
||||
email = window.prompt(
|
||||
"Please provide your email for confirmation"
|
||||
) as string
|
||||
}
|
||||
|
||||
await signInWithEmailLink(email, window.location.href)
|
||||
|
||||
removeLocalConfig("emailForSignIn")
|
||||
window.location.href = "/"
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import { initializeApp } from "firebase/app"
|
||||
|
||||
const firebaseConfig = {
|
||||
apiKey: import.meta.env.VITE_API_KEY,
|
||||
authDomain: import.meta.env.VITE_AUTH_DOMAIN,
|
||||
databaseURL: import.meta.env.VITE_DATABASE_URL,
|
||||
projectId: import.meta.env.VITE_PROJECT_ID,
|
||||
storageBucket: import.meta.env.VITE_STORAGE_BUCKET,
|
||||
messagingSenderId: import.meta.env.VITE_MESSAGING_SENDER_ID,
|
||||
appId: import.meta.env.VITE_APP_ID,
|
||||
measurementId: import.meta.env.VITE_MEASUREMENT_ID,
|
||||
}
|
||||
|
||||
let initialized = false
|
||||
|
||||
export function initializeFirebase() {
|
||||
if (!initialized) {
|
||||
try {
|
||||
initializeApp(firebaseConfig)
|
||||
initialized = true
|
||||
} catch (e) {
|
||||
// initializeApp throws exception if we reinitialize
|
||||
initialized = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,276 +0,0 @@
|
||||
import {
|
||||
addDoc,
|
||||
collection,
|
||||
deleteDoc,
|
||||
doc,
|
||||
getDocs,
|
||||
getFirestore,
|
||||
limit,
|
||||
onSnapshot,
|
||||
orderBy,
|
||||
query,
|
||||
updateDoc,
|
||||
} from "firebase/firestore"
|
||||
import { FormDataKeyValue } from "@hoppscotch/data"
|
||||
import { def as platformAuth } from "./firebase/auth"
|
||||
import {
|
||||
getSettingSubject,
|
||||
settingsStore,
|
||||
} from "@hoppscotch/common/newstore/settings"
|
||||
import {
|
||||
GQLHistoryEntry,
|
||||
graphqlHistoryStore,
|
||||
HISTORY_LIMIT,
|
||||
RESTHistoryEntry,
|
||||
restHistoryStore,
|
||||
setGraphqlHistoryEntries,
|
||||
setRESTHistoryEntries,
|
||||
translateToNewGQLHistory,
|
||||
translateToNewRESTHistory,
|
||||
} from "@hoppscotch/common/newstore/history"
|
||||
import { HistoryPlatformDef } from "@hoppscotch/common/platform/history"
|
||||
|
||||
type HistoryFBCollections = "history" | "graphqlHistory"
|
||||
|
||||
/**
|
||||
* Whether the history are loaded. If this is set to true
|
||||
* Updates to the history store are written into firebase.
|
||||
*
|
||||
* If you have want to update the store and not fire the store update
|
||||
* subscription, set this variable to false, do the update and then
|
||||
* set it to true
|
||||
*/
|
||||
let loadedRESTHistory = false
|
||||
|
||||
/**
|
||||
* Whether the history are loaded. If this is set to true
|
||||
* Updates to the history store are written into firebase.
|
||||
*
|
||||
* If you have want to update the store and not fire the store update
|
||||
* subscription, set this variable to false, do the update and then
|
||||
* set it to true
|
||||
*/
|
||||
let loadedGraphqlHistory = false
|
||||
|
||||
const purgeFormDataFromRequest = (req: RESTHistoryEntry): RESTHistoryEntry => {
|
||||
if (req.request.body.contentType !== "multipart/form-data") return req
|
||||
|
||||
req.request.body.body = req.request.body.body.map<FormDataKeyValue>(
|
||||
(formData) => {
|
||||
if (!formData.isFile) return formData
|
||||
|
||||
return {
|
||||
active: formData.active,
|
||||
isFile: false, // Something we can do to keep the status ?
|
||||
key: formData.key,
|
||||
value: "",
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return req
|
||||
}
|
||||
|
||||
async function writeHistory(
|
||||
entry: RESTHistoryEntry | GQLHistoryEntry,
|
||||
col: HistoryFBCollections
|
||||
) {
|
||||
const processedEntry =
|
||||
col === "history"
|
||||
? purgeFormDataFromRequest(entry as RESTHistoryEntry)
|
||||
: entry
|
||||
|
||||
const currentUser = platformAuth.getCurrentUser()
|
||||
|
||||
if (currentUser === null)
|
||||
throw new Error("User not logged in to sync history")
|
||||
|
||||
const hs = {
|
||||
...processedEntry,
|
||||
updatedOn: new Date(),
|
||||
}
|
||||
|
||||
try {
|
||||
await addDoc(collection(getFirestore(), "users", currentUser.uid, col), hs)
|
||||
} catch (e) {
|
||||
console.error("error writing to history", hs, e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteHistory(
|
||||
entry: (RESTHistoryEntry | GQLHistoryEntry) & { id: string },
|
||||
col: HistoryFBCollections
|
||||
) {
|
||||
const currentUser = platformAuth.getCurrentUser()
|
||||
|
||||
if (currentUser === null)
|
||||
throw new Error("User not logged in to delete history")
|
||||
|
||||
try {
|
||||
await deleteDoc(
|
||||
doc(getFirestore(), "users", currentUser.uid, col, entry.id)
|
||||
)
|
||||
} catch (e) {
|
||||
console.error("error deleting history", entry, e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
async function clearHistory(col: HistoryFBCollections) {
|
||||
const currentUser = platformAuth.getCurrentUser()
|
||||
|
||||
if (currentUser === null)
|
||||
throw new Error("User not logged in to clear history")
|
||||
|
||||
const { docs } = await getDocs(
|
||||
collection(getFirestore(), "users", currentUser.uid, col)
|
||||
)
|
||||
|
||||
await Promise.all(docs.map((e) => deleteHistory(e as any, col)))
|
||||
}
|
||||
|
||||
async function toggleStar(
|
||||
entry: (RESTHistoryEntry | GQLHistoryEntry) & { id: string },
|
||||
col: HistoryFBCollections
|
||||
) {
|
||||
const currentUser = platformAuth.getCurrentUser()
|
||||
|
||||
if (currentUser === null) throw new Error("User not logged in to toggle star")
|
||||
|
||||
try {
|
||||
await updateDoc(
|
||||
doc(getFirestore(), "users", currentUser.uid, col, entry.id),
|
||||
{ star: !entry.star }
|
||||
)
|
||||
} catch (e) {
|
||||
console.error("error toggling star", entry, e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
export function initHistorySync() {
|
||||
const currentUser$ = platformAuth.getCurrentUserStream()
|
||||
|
||||
const restHistorySub = restHistoryStore.dispatches$.subscribe((dispatch) => {
|
||||
const currentUser = platformAuth.getCurrentUser()
|
||||
|
||||
if (loadedRESTHistory && currentUser && settingsStore.value.syncHistory) {
|
||||
if (dispatch.dispatcher === "addEntry") {
|
||||
writeHistory(dispatch.payload.entry, "history")
|
||||
} else if (dispatch.dispatcher === "deleteEntry") {
|
||||
deleteHistory(dispatch.payload.entry, "history")
|
||||
} else if (dispatch.dispatcher === "clearHistory") {
|
||||
clearHistory("history")
|
||||
} else if (dispatch.dispatcher === "toggleStar") {
|
||||
toggleStar(dispatch.payload.entry, "history")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const gqlHistorySub = graphqlHistoryStore.dispatches$.subscribe(
|
||||
(dispatch) => {
|
||||
const currentUser = platformAuth.getCurrentUser()
|
||||
|
||||
if (
|
||||
loadedGraphqlHistory &&
|
||||
currentUser &&
|
||||
settingsStore.value.syncHistory
|
||||
) {
|
||||
if (dispatch.dispatcher === "addEntry") {
|
||||
writeHistory(dispatch.payload.entry, "graphqlHistory")
|
||||
} else if (dispatch.dispatcher === "deleteEntry") {
|
||||
deleteHistory(dispatch.payload.entry, "graphqlHistory")
|
||||
} else if (dispatch.dispatcher === "clearHistory") {
|
||||
clearHistory("graphqlHistory")
|
||||
} else if (dispatch.dispatcher === "toggleStar") {
|
||||
toggleStar(dispatch.payload.entry, "graphqlHistory")
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
let restSnapshotStop: (() => void) | null = null
|
||||
let graphqlSnapshotStop: (() => void) | null = null
|
||||
|
||||
const currentUserSub = currentUser$.subscribe((user) => {
|
||||
if (!user) {
|
||||
// Clear the snapshot listeners when the user logs out
|
||||
if (restSnapshotStop) {
|
||||
restSnapshotStop()
|
||||
restSnapshotStop = null
|
||||
}
|
||||
|
||||
if (graphqlSnapshotStop) {
|
||||
graphqlSnapshotStop()
|
||||
graphqlSnapshotStop = null
|
||||
}
|
||||
} else {
|
||||
restSnapshotStop = onSnapshot(
|
||||
query(
|
||||
collection(getFirestore(), "users", user.uid, "history"),
|
||||
orderBy("updatedOn", "desc"),
|
||||
limit(HISTORY_LIMIT)
|
||||
),
|
||||
(historyRef) => {
|
||||
const history: RESTHistoryEntry[] = []
|
||||
|
||||
historyRef.forEach((doc) => {
|
||||
const entry = doc.data()
|
||||
entry.id = doc.id
|
||||
entry.updatedOn = doc.data().updatedOn.toDate()
|
||||
history.push(translateToNewRESTHistory(entry))
|
||||
})
|
||||
|
||||
loadedRESTHistory = false
|
||||
setRESTHistoryEntries(history)
|
||||
loadedRESTHistory = true
|
||||
}
|
||||
)
|
||||
|
||||
graphqlSnapshotStop = onSnapshot(
|
||||
query(
|
||||
collection(getFirestore(), "users", user.uid, "graphqlHistory"),
|
||||
orderBy("updatedOn", "desc"),
|
||||
limit(HISTORY_LIMIT)
|
||||
),
|
||||
(historyRef) => {
|
||||
const history: GQLHistoryEntry[] = []
|
||||
|
||||
historyRef.forEach((doc) => {
|
||||
const entry = doc.data()
|
||||
entry.id = doc.id
|
||||
entry.updatedOn = doc.data().updatedOn.toDate()
|
||||
history.push(translateToNewGQLHistory(entry))
|
||||
})
|
||||
|
||||
loadedGraphqlHistory = false
|
||||
setGraphqlHistoryEntries(history)
|
||||
loadedGraphqlHistory = true
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
let oldSyncStatus = settingsStore.value.syncHistory
|
||||
|
||||
const syncStop = getSettingSubject("syncHistory").subscribe((newStatus) => {
|
||||
if (oldSyncStatus === true && newStatus === false) {
|
||||
restSnapshotStop?.()
|
||||
graphqlSnapshotStop?.()
|
||||
|
||||
oldSyncStatus = newStatus
|
||||
} else if (oldSyncStatus === false && newStatus === true) {
|
||||
syncStop.unsubscribe()
|
||||
restHistorySub.unsubscribe()
|
||||
gqlHistorySub.unsubscribe()
|
||||
currentUserSub.unsubscribe()
|
||||
|
||||
initHistorySync()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const def: HistoryPlatformDef = {
|
||||
initHistorySync,
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import { createHoppApp } from "@hoppscotch/common"
|
||||
import { initializeFirebase } from "./firebase/init"
|
||||
import { def as authDef } from "./firebase/auth"
|
||||
import { def as envDef } from "./environments"
|
||||
import { def as collectionsDef } from "./collections"
|
||||
import { def as settingsDef } from "./settings"
|
||||
import { def as historyDef } from "./history"
|
||||
import { def as tabStateDef } from "./tab"
|
||||
import { def as analyticsDef } from "./analytics"
|
||||
|
||||
initializeFirebase()
|
||||
|
||||
createHoppApp("#app", {
|
||||
auth: authDef,
|
||||
analytics: analyticsDef,
|
||||
sync: {
|
||||
environments: envDef,
|
||||
collections: collectionsDef,
|
||||
settings: settingsDef,
|
||||
history: historyDef,
|
||||
tabState: tabStateDef,
|
||||
},
|
||||
platformFeatureFlags: {
|
||||
exportAsGIST: true,
|
||||
},
|
||||
})
|
||||
@@ -1,108 +0,0 @@
|
||||
import {
|
||||
collection,
|
||||
doc,
|
||||
getFirestore,
|
||||
onSnapshot,
|
||||
setDoc,
|
||||
} from "firebase/firestore"
|
||||
import { def as platformAuth } from "./firebase/auth"
|
||||
import {
|
||||
applySetting,
|
||||
settingsStore,
|
||||
SettingsDef,
|
||||
} from "@hoppscotch/common/newstore/settings"
|
||||
import { SettingsPlatformDef } from "@hoppscotch/common/platform/settings"
|
||||
|
||||
/**
|
||||
* Used locally to prevent infinite loop when settings sync update
|
||||
* is applied to the store which then fires the store sync listener.
|
||||
* When you want to update settings and not want to fire the update listener,
|
||||
* set this to true and then set it back to false once it is done
|
||||
*/
|
||||
let loadedSettings = false
|
||||
|
||||
/**
|
||||
* Write Transform
|
||||
*/
|
||||
async function writeSettings(setting: string, value: any) {
|
||||
const currentUser = platformAuth.getCurrentUser()
|
||||
|
||||
if (currentUser === null)
|
||||
throw new Error("Cannot write setting, user not signed in")
|
||||
|
||||
const st = {
|
||||
updatedOn: new Date(),
|
||||
author: currentUser.uid,
|
||||
author_name: currentUser.displayName,
|
||||
author_image: currentUser.photoURL,
|
||||
name: setting,
|
||||
value,
|
||||
}
|
||||
|
||||
try {
|
||||
await setDoc(
|
||||
doc(getFirestore(), "users", currentUser.uid, "settings", setting),
|
||||
st
|
||||
)
|
||||
} catch (e) {
|
||||
console.error("error updating", st, e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
export function initSettingsSync() {
|
||||
const currentUser$ = platformAuth.getCurrentUserStream()
|
||||
|
||||
settingsStore.dispatches$.subscribe((dispatch) => {
|
||||
const currentUser = platformAuth.getCurrentUser()
|
||||
|
||||
if (currentUser && loadedSettings) {
|
||||
if (dispatch.dispatcher === "bulkApplySettings") {
|
||||
Object.keys(dispatch.payload).forEach((key) => {
|
||||
writeSettings(key, dispatch.payload[key])
|
||||
})
|
||||
} else {
|
||||
writeSettings(
|
||||
dispatch.payload.settingKey,
|
||||
settingsStore.value[dispatch.payload.settingKey as keyof SettingsDef]
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let snapshotStop: (() => void) | null = null
|
||||
|
||||
// Subscribe and unsubscribe event listeners
|
||||
currentUser$.subscribe((user) => {
|
||||
if (!user && snapshotStop) {
|
||||
// User logged out
|
||||
snapshotStop()
|
||||
snapshotStop = null
|
||||
} else if (user) {
|
||||
snapshotStop = onSnapshot(
|
||||
collection(getFirestore(), "users", user.uid, "settings"),
|
||||
(settingsRef) => {
|
||||
const settings: any[] = []
|
||||
|
||||
settingsRef.forEach((doc) => {
|
||||
const setting = doc.data()
|
||||
setting.id = doc.id
|
||||
settings.push(setting)
|
||||
})
|
||||
|
||||
loadedSettings = false
|
||||
settings.forEach((e) => {
|
||||
if (e && e.name && e.value != null) {
|
||||
applySetting(e.name, e.value)
|
||||
}
|
||||
})
|
||||
loadedSettings = true
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const def: SettingsPlatformDef = {
|
||||
initSettingsSync,
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
import { PersistableRESTTabState } from "@hoppscotch/common/helpers/rest/tab"
|
||||
import { HoppUser } from "@hoppscotch/common/platform/auth"
|
||||
import { TabStatePlatformDef } from "@hoppscotch/common/platform/tab"
|
||||
import { doc, getDoc, getFirestore, setDoc } from "firebase/firestore"
|
||||
import { def as platformAuth } from "./firebase/auth"
|
||||
|
||||
/**
|
||||
* Writes tab state to a user's firestore sync
|
||||
*
|
||||
* @param persistableTabState The tab state to write to the request sync
|
||||
*/
|
||||
function writeCurrentTabState(
|
||||
user: HoppUser,
|
||||
persistableTabState: PersistableRESTTabState
|
||||
) {
|
||||
// Remove FormData entries because those can't be stored on Firestore ?
|
||||
|
||||
return setDoc(
|
||||
doc(getFirestore(), "users", user.uid, "requests", "tab-state"),
|
||||
persistableTabState
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the synced tab state from the firestore sync
|
||||
*
|
||||
* @returns Fetched tab state object if exists else null
|
||||
*/
|
||||
async function loadTabStateFromSync(): Promise<PersistableRESTTabState | null> {
|
||||
const currentUser = platformAuth.getCurrentUser()
|
||||
|
||||
if (!currentUser)
|
||||
throw new Error("Cannot load request from sync without login")
|
||||
|
||||
const fbDoc = await getDoc(
|
||||
doc(getFirestore(), "users", currentUser.uid, "requests", "tab-state")
|
||||
)
|
||||
|
||||
const data = fbDoc.data()
|
||||
|
||||
if (!data) return null
|
||||
else return data as PersistableRESTTabState
|
||||
}
|
||||
|
||||
export const def: TabStatePlatformDef = {
|
||||
loadTabStateFromSync,
|
||||
writeCurrentTabState,
|
||||
}
|
||||
7
packages/hoppscotch-web/src/vite-env.d.ts
vendored
7
packages/hoppscotch-web/src/vite-env.d.ts
vendored
@@ -1,7 +0,0 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
declare module '*.vue' {
|
||||
import type { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"skipLibCheck": true,
|
||||
"noEmit": true,
|
||||
"paths": {
|
||||
"@hoppscotch/common": [ "../hoppscotch-common/src/index.ts" ],
|
||||
"@hoppscotch/common/*": [ "../hoppscotch-common/src/*" ]
|
||||
}
|
||||
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts", "meta.ts"]
|
||||
}
|
||||
@@ -1,195 +0,0 @@
|
||||
import { defineConfig, loadEnv, normalizePath } from "vite"
|
||||
import { APP_INFO, META_TAGS } from "./meta"
|
||||
import { viteStaticCopy as StaticCopy } from "vite-plugin-static-copy"
|
||||
import generateSitemap from "vite-plugin-pages-sitemap"
|
||||
import HtmlConfig from "vite-plugin-html-config"
|
||||
import Vue from "@vitejs/plugin-vue"
|
||||
import VueI18n from "@intlify/vite-plugin-vue-i18n"
|
||||
import Components from "unplugin-vue-components/vite"
|
||||
import Icons from "unplugin-icons/vite"
|
||||
import Inspect from "vite-plugin-inspect"
|
||||
import WindiCSS from "vite-plugin-windicss"
|
||||
import { VitePWA } from "vite-plugin-pwa"
|
||||
import Pages from "vite-plugin-pages"
|
||||
import Layouts from "vite-plugin-vue-layouts"
|
||||
import IconResolver from "unplugin-icons/resolver"
|
||||
import { FileSystemIconLoader } from "unplugin-icons/loaders"
|
||||
import * as path from "path"
|
||||
import { VitePluginFonts } from "vite-plugin-fonts"
|
||||
import legacy from "@vitejs/plugin-legacy"
|
||||
|
||||
const ENV = loadEnv("development", path.resolve(__dirname, "../../"))
|
||||
|
||||
export default defineConfig({
|
||||
envDir: path.resolve(__dirname, "../../"),
|
||||
// TODO: Migrate @hoppscotch/data to full ESM
|
||||
define: {
|
||||
// For 'util' polyfill required by dep of '@apidevtools/swagger-parser'
|
||||
"process.env": {},
|
||||
},
|
||||
server: {
|
||||
port: 3000,
|
||||
},
|
||||
preview: {
|
||||
port: 3000,
|
||||
},
|
||||
publicDir: path.resolve(__dirname, "../hoppscotch-common/public"),
|
||||
build: {
|
||||
sourcemap: true,
|
||||
emptyOutDir: true,
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
// TODO: Maybe leave ~ only for individual apps and not use on common
|
||||
"~": path.resolve(__dirname, "../hoppscotch-common/src"),
|
||||
"@hoppscotch/common": "@hoppscotch/common/src",
|
||||
"@composables": path.resolve(
|
||||
__dirname,
|
||||
"../hoppscotch-common/src/composables"
|
||||
),
|
||||
"@modules": path.resolve(__dirname, "../hoppscotch-common/src/modules"),
|
||||
"@components": path.resolve(
|
||||
__dirname,
|
||||
"../hoppscotch-common/src/components"
|
||||
),
|
||||
"@helpers": path.resolve(__dirname, "../hoppscotch-common/src/helpers"),
|
||||
"@functional": path.resolve(
|
||||
__dirname,
|
||||
"../hoppscotch-common/src/helpers/functional"
|
||||
),
|
||||
"@workers": path.resolve(__dirname, "../hoppscotch-common/src/workers"),
|
||||
|
||||
stream: "stream-browserify",
|
||||
util: "util",
|
||||
},
|
||||
dedupe: ["vue"],
|
||||
},
|
||||
plugins: [
|
||||
Inspect(), // go to url -> /__inspect
|
||||
HtmlConfig({
|
||||
metas: META_TAGS(ENV),
|
||||
}),
|
||||
Vue(),
|
||||
Pages({
|
||||
routeStyle: "nuxt",
|
||||
dirs: "../hoppscotch-common/src/pages",
|
||||
importMode: "async",
|
||||
onRoutesGenerated(routes) {
|
||||
// HACK: See: https://github.com/jbaubree/vite-plugin-pages-sitemap/issues/173
|
||||
return ((generateSitemap as any).default as typeof generateSitemap)({
|
||||
routes,
|
||||
nuxtStyle: true,
|
||||
allowRobots: true,
|
||||
dest: ".sitemap-gen",
|
||||
hostname: ENV.VITE_BASE_URL,
|
||||
})
|
||||
},
|
||||
}),
|
||||
StaticCopy({
|
||||
targets: [
|
||||
{
|
||||
src: normalizePath(path.resolve(__dirname, "./.sitemap-gen/*")),
|
||||
dest: normalizePath(path.resolve(__dirname, "./dist")),
|
||||
},
|
||||
],
|
||||
}),
|
||||
Layouts({
|
||||
layoutsDirs: "../hoppscotch-common/src/layouts",
|
||||
defaultLayout: "default",
|
||||
}),
|
||||
VueI18n({
|
||||
runtimeOnly: false,
|
||||
compositionOnly: true,
|
||||
include: [path.resolve(__dirname, "locales")],
|
||||
}),
|
||||
WindiCSS({
|
||||
root: path.resolve(__dirname, "../hoppscotch-common"),
|
||||
}),
|
||||
Components({
|
||||
dts: "../hoppscotch-common/src/components.d.ts",
|
||||
dirs: ["../hoppscotch-common/src/components"],
|
||||
directoryAsNamespace: true,
|
||||
resolvers: [
|
||||
IconResolver({
|
||||
prefix: "icon",
|
||||
customCollections: ["hopp", "auth", "brands"],
|
||||
}),
|
||||
(compName: string) => {
|
||||
if (compName.startsWith("Hopp"))
|
||||
return { name: compName, from: "@hoppscotch/ui" }
|
||||
else return undefined
|
||||
},
|
||||
],
|
||||
types: [
|
||||
{
|
||||
from: "vue-tippy",
|
||||
names: ["Tippy"],
|
||||
},
|
||||
],
|
||||
}),
|
||||
Icons({
|
||||
compiler: "vue3",
|
||||
customCollections: {
|
||||
hopp: FileSystemIconLoader("../hoppscotch-common/assets/icons"),
|
||||
auth: FileSystemIconLoader("../hoppscotch-common/assets/icons/auth"),
|
||||
brands: FileSystemIconLoader(
|
||||
"../hoppscotch-common/assets/icons/brands"
|
||||
),
|
||||
},
|
||||
}),
|
||||
VitePWA({
|
||||
manifest: {
|
||||
name: APP_INFO.name,
|
||||
short_name: APP_INFO.name,
|
||||
description: APP_INFO.shortDescription,
|
||||
start_url: "/?source=pwa",
|
||||
background_color: APP_INFO.app.background,
|
||||
theme_color: APP_INFO.app.background,
|
||||
icons: [
|
||||
{
|
||||
src: "/icon.png",
|
||||
sizes: "512x512",
|
||||
type: "image/png",
|
||||
purpose: "any maskable",
|
||||
},
|
||||
{
|
||||
src: "/logo.svg",
|
||||
sizes: "48x48 72x72 96x96 128x128 256x256 512x512",
|
||||
type: "image/svg+xml",
|
||||
purpose: "any maskable",
|
||||
},
|
||||
],
|
||||
},
|
||||
registerType: "prompt",
|
||||
workbox: {
|
||||
cleanupOutdatedCaches: true,
|
||||
maximumFileSizeToCacheInBytes: 4194304,
|
||||
navigateFallbackDenylist: [
|
||||
/robots.txt/,
|
||||
/sitemap.xml/,
|
||||
/discord/,
|
||||
/telegram/,
|
||||
/beta/,
|
||||
/careers/,
|
||||
/newsletter/,
|
||||
/twitter/,
|
||||
/github/,
|
||||
/announcements/,
|
||||
],
|
||||
},
|
||||
}),
|
||||
VitePluginFonts({
|
||||
google: {
|
||||
families: [
|
||||
"Inter:wght@400;500;600;700;800",
|
||||
"Roboto+Mono:wght@400;500",
|
||||
"Material+Icons",
|
||||
],
|
||||
},
|
||||
}),
|
||||
legacy({
|
||||
modernPolyfills: ["es.string.replace-all"],
|
||||
renderLegacyChunks: false,
|
||||
}),
|
||||
],
|
||||
})
|
||||
412
pnpm-lock.yaml
generated
412
pnpm-lock.yaml
generated
@@ -1310,121 +1310,6 @@ importers:
|
||||
specifier: ^3.5.6
|
||||
version: 3.5.6
|
||||
|
||||
packages/hoppscotch-web:
|
||||
dependencies:
|
||||
'@hoppscotch/common':
|
||||
specifier: workspace:^
|
||||
version: link:../hoppscotch-common
|
||||
'@hoppscotch/data':
|
||||
specifier: workspace:^
|
||||
version: link:../hoppscotch-data
|
||||
'@hoppscotch/ui':
|
||||
specifier: workspace:^
|
||||
version: link:../hoppscotch-ui
|
||||
buffer:
|
||||
specifier: ^6.0.3
|
||||
version: 6.0.3
|
||||
firebase:
|
||||
specifier: ^9.8.4
|
||||
version: 9.8.4
|
||||
process:
|
||||
specifier: ^0.11.10
|
||||
version: 0.11.10
|
||||
rxjs:
|
||||
specifier: ^7.5.5
|
||||
version: 7.5.5
|
||||
stream-browserify:
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0
|
||||
util:
|
||||
specifier: ^0.12.4
|
||||
version: 0.12.4
|
||||
vue:
|
||||
specifier: ^3.2.41
|
||||
version: 3.2.45
|
||||
workbox-window:
|
||||
specifier: ^6.5.4
|
||||
version: 6.5.4
|
||||
devDependencies:
|
||||
'@intlify/vite-plugin-vue-i18n':
|
||||
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
|
||||
'@typescript-eslint/eslint-plugin':
|
||||
specifier: ^5.19.0
|
||||
version: 5.30.6(@typescript-eslint/parser@5.30.6)(eslint@8.28.0)(typescript@4.7.4)
|
||||
'@typescript-eslint/parser':
|
||||
specifier: ^5.19.0
|
||||
version: 5.30.6(eslint@8.28.0)(typescript@4.7.4)
|
||||
'@vitejs/plugin-legacy':
|
||||
specifier: ^2.3.0
|
||||
version: 2.3.0(terser@5.14.1)(vite@3.2.4)
|
||||
'@vitejs/plugin-vue':
|
||||
specifier: ^3.2.0
|
||||
version: 3.2.0(vite@3.2.4)(vue@3.2.45)
|
||||
'@vue/eslint-config-typescript':
|
||||
specifier: ^11.0.1
|
||||
version: 11.0.1(eslint-plugin-vue@9.5.1)(eslint@8.28.0)(typescript@4.7.4)
|
||||
cross-env:
|
||||
specifier: ^7.0.3
|
||||
version: 7.0.3
|
||||
eslint:
|
||||
specifier: ^8.28.0
|
||||
version: 8.28.0
|
||||
eslint-plugin-prettier:
|
||||
specifier: ^4.2.1
|
||||
version: 4.2.1(eslint-config-prettier@8.6.0)(eslint@8.19.0)(prettier@2.8.4)
|
||||
eslint-plugin-vue:
|
||||
specifier: ^9.5.1
|
||||
version: 9.5.1(eslint@8.28.0)
|
||||
typescript:
|
||||
specifier: ^4.6.4
|
||||
version: 4.7.4
|
||||
unplugin-icons:
|
||||
specifier: ^0.14.9
|
||||
version: 0.14.9(@vue/compiler-sfc@3.2.39)(esbuild@0.15.15)(rollup@2.79.1)(vite@3.1.4)
|
||||
unplugin-vue-components:
|
||||
specifier: ^0.21.0
|
||||
version: 0.21.0(esbuild@0.15.15)(rollup@2.79.1)(vite@3.2.4)(vue@3.2.45)(webpack@5.74.0)
|
||||
vite:
|
||||
specifier: ^3.2.3
|
||||
version: 3.2.4(@types/node@17.0.45)(sass@1.53.0)(terser@5.14.1)
|
||||
vite-plugin-fonts:
|
||||
specifier: ^0.6.0
|
||||
version: 0.6.0(vite@3.2.4)
|
||||
vite-plugin-html-config:
|
||||
specifier: ^1.0.10
|
||||
version: 1.0.10(vite@3.2.4)
|
||||
vite-plugin-inspect:
|
||||
specifier: ^0.7.4
|
||||
version: 0.7.4(vite@3.2.4)
|
||||
vite-plugin-pages:
|
||||
specifier: ^0.26.0
|
||||
version: 0.26.0(@vue/compiler-sfc@3.2.45)(vite@3.2.4)
|
||||
vite-plugin-pages-sitemap:
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0
|
||||
vite-plugin-pwa:
|
||||
specifier: ^0.13.1
|
||||
version: 0.13.1(vite@3.2.4)(workbox-build@6.5.4)(workbox-window@6.5.4)
|
||||
vite-plugin-static-copy:
|
||||
specifier: ^0.12.0
|
||||
version: 0.12.0(vite@3.2.4)
|
||||
vite-plugin-vue-layouts:
|
||||
specifier: ^0.7.0
|
||||
version: 0.7.0(vite@3.2.4)(vue-router@4.1.0)(vue@3.2.45)
|
||||
vite-plugin-windicss:
|
||||
specifier: ^1.8.8
|
||||
version: 1.8.8(vite@3.2.4)
|
||||
vue-tsc:
|
||||
specifier: ^1.0.9
|
||||
version: 1.0.9(typescript@4.7.4)
|
||||
windicss:
|
||||
specifier: ^3.5.6
|
||||
version: 3.5.6
|
||||
|
||||
packages:
|
||||
|
||||
/@ampproject/remapping@2.2.0:
|
||||
@@ -7687,33 +7572,6 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/eslint-plugin@5.30.6(@typescript-eslint/parser@5.30.6)(eslint@8.28.0)(typescript@4.7.4):
|
||||
resolution: {integrity: sha512-J4zYMIhgrx4MgnZrSDD7sEnQp7FmhKNOaqaOpaoQ/SfdMfRB/0yvK74hTnvH+VQxndZynqs5/Hn4t+2/j9bADg==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': ^5.0.0
|
||||
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 5.30.6(eslint@8.28.0)(typescript@4.7.4)
|
||||
'@typescript-eslint/scope-manager': 5.30.6
|
||||
'@typescript-eslint/type-utils': 5.30.6(eslint@8.28.0)(typescript@4.7.4)
|
||||
'@typescript-eslint/utils': 5.30.6(eslint@8.28.0)(typescript@4.7.4)
|
||||
debug: 4.3.4(supports-color@9.2.2)
|
||||
eslint: 8.28.0
|
||||
functional-red-black-tree: 1.0.1
|
||||
ignore: 5.2.0
|
||||
regexpp: 3.2.0
|
||||
semver: 7.3.7
|
||||
tsutils: 3.21.0(typescript@4.7.4)
|
||||
typescript: 4.7.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/eslint-plugin@5.45.0(@typescript-eslint/parser@5.45.0)(eslint@8.24.0)(typescript@4.7.4):
|
||||
resolution: {integrity: sha512-CXXHNlf0oL+Yg021cxgOdMHNTXD17rHkq7iW6RFHoybdFgQBjU3yIXhhcPpGwr1CjZlo6ET8C6tzX5juQoXeGA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
@@ -7741,33 +7599,6 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/eslint-plugin@5.45.0(@typescript-eslint/parser@5.45.0)(eslint@8.28.0)(typescript@4.7.4):
|
||||
resolution: {integrity: sha512-CXXHNlf0oL+Yg021cxgOdMHNTXD17rHkq7iW6RFHoybdFgQBjU3yIXhhcPpGwr1CjZlo6ET8C6tzX5juQoXeGA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': ^5.0.0
|
||||
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 5.45.0(eslint@8.28.0)(typescript@4.7.4)
|
||||
'@typescript-eslint/scope-manager': 5.45.0
|
||||
'@typescript-eslint/type-utils': 5.45.0(eslint@8.28.0)(typescript@4.7.4)
|
||||
'@typescript-eslint/utils': 5.45.0(eslint@8.28.0)(typescript@4.7.4)
|
||||
debug: 4.3.4(supports-color@9.2.2)
|
||||
eslint: 8.28.0
|
||||
ignore: 5.2.0
|
||||
natural-compare-lite: 1.4.0
|
||||
regexpp: 3.2.0
|
||||
semver: 7.3.8
|
||||
tsutils: 3.21.0(typescript@4.7.4)
|
||||
typescript: 4.7.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/eslint-plugin@5.45.0(@typescript-eslint/parser@5.45.0)(eslint@8.29.0)(typescript@4.9.3):
|
||||
resolution: {integrity: sha512-CXXHNlf0oL+Yg021cxgOdMHNTXD17rHkq7iW6RFHoybdFgQBjU3yIXhhcPpGwr1CjZlo6ET8C6tzX5juQoXeGA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
@@ -7835,26 +7666,6 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/parser@5.30.6(eslint@8.28.0)(typescript@4.7.4):
|
||||
resolution: {integrity: sha512-gfF9lZjT0p2ZSdxO70Xbw8w9sPPJGfAdjK7WikEjB3fcUI/yr9maUVEdqigBjKincUYNKOmf7QBMiTf719kbrA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': 5.30.6
|
||||
'@typescript-eslint/types': 5.30.6
|
||||
'@typescript-eslint/typescript-estree': 5.30.6(typescript@4.7.4)
|
||||
debug: 4.3.4(supports-color@9.2.2)
|
||||
eslint: 8.28.0
|
||||
typescript: 4.7.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/parser@5.45.0(eslint@8.24.0)(typescript@4.7.4):
|
||||
resolution: {integrity: sha512-brvs/WSM4fKUmF5Ot/gEve6qYiCMjm6w4HkHPfS6ZNmxTS0m0iNN4yOChImaCkqc1hRwFGqUyanMXuGal6oyyQ==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
@@ -7875,26 +7686,6 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/parser@5.45.0(eslint@8.28.0)(typescript@4.7.4):
|
||||
resolution: {integrity: sha512-brvs/WSM4fKUmF5Ot/gEve6qYiCMjm6w4HkHPfS6ZNmxTS0m0iNN4yOChImaCkqc1hRwFGqUyanMXuGal6oyyQ==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': 5.45.0
|
||||
'@typescript-eslint/types': 5.45.0
|
||||
'@typescript-eslint/typescript-estree': 5.45.0(typescript@4.7.4)
|
||||
debug: 4.3.4(supports-color@9.2.2)
|
||||
eslint: 8.28.0
|
||||
typescript: 4.7.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/parser@5.45.0(eslint@8.29.0)(typescript@4.9.3):
|
||||
resolution: {integrity: sha512-brvs/WSM4fKUmF5Ot/gEve6qYiCMjm6w4HkHPfS6ZNmxTS0m0iNN4yOChImaCkqc1hRwFGqUyanMXuGal6oyyQ==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
@@ -7969,25 +7760,6 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/type-utils@5.30.6(eslint@8.28.0)(typescript@4.7.4):
|
||||
resolution: {integrity: sha512-GFVVzs2j0QPpM+NTDMXtNmJKlF842lkZKDSanIxf+ArJsGeZUIaeT4jGg+gAgHt7AcQSFwW7htzF/rbAh2jaVA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: '*'
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/utils': 5.30.6(eslint@8.28.0)(typescript@4.7.4)
|
||||
debug: 4.3.4(supports-color@9.2.2)
|
||||
eslint: 8.28.0
|
||||
tsutils: 3.21.0(typescript@4.7.4)
|
||||
typescript: 4.7.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/type-utils@5.45.0(eslint@8.24.0)(typescript@4.7.4):
|
||||
resolution: {integrity: sha512-DY7BXVFSIGRGFZ574hTEyLPRiQIvI/9oGcN8t1A7f6zIs6ftbrU0nhyV26ZW//6f85avkwrLag424n+fkuoJ1Q==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
@@ -8008,26 +7780,6 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/type-utils@5.45.0(eslint@8.28.0)(typescript@4.7.4):
|
||||
resolution: {integrity: sha512-DY7BXVFSIGRGFZ574hTEyLPRiQIvI/9oGcN8t1A7f6zIs6ftbrU0nhyV26ZW//6f85avkwrLag424n+fkuoJ1Q==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: '*'
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/typescript-estree': 5.45.0(typescript@4.7.4)
|
||||
'@typescript-eslint/utils': 5.45.0(eslint@8.28.0)(typescript@4.7.4)
|
||||
debug: 4.3.4(supports-color@9.2.2)
|
||||
eslint: 8.28.0
|
||||
tsutils: 3.21.0(typescript@4.7.4)
|
||||
typescript: 4.7.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/type-utils@5.45.0(eslint@8.29.0)(typescript@4.9.3):
|
||||
resolution: {integrity: sha512-DY7BXVFSIGRGFZ574hTEyLPRiQIvI/9oGcN8t1A7f6zIs6ftbrU0nhyV26ZW//6f85avkwrLag424n+fkuoJ1Q==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
@@ -8157,24 +7909,6 @@ packages:
|
||||
- typescript
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/utils@5.30.6(eslint@8.28.0)(typescript@4.7.4):
|
||||
resolution: {integrity: sha512-xFBLc/esUbLOJLk9jKv0E9gD/OH966M40aY9jJ8GiqpSkP2xOV908cokJqqhVd85WoIvHVHYXxSFE4cCSDzVvA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
dependencies:
|
||||
'@types/json-schema': 7.0.9
|
||||
'@typescript-eslint/scope-manager': 5.30.6
|
||||
'@typescript-eslint/types': 5.30.6
|
||||
'@typescript-eslint/typescript-estree': 5.30.6(typescript@4.7.4)
|
||||
eslint: 8.28.0
|
||||
eslint-scope: 5.1.1
|
||||
eslint-utils: 3.0.0(eslint@8.28.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/utils@5.45.0(eslint@8.24.0)(typescript@4.7.4):
|
||||
resolution: {integrity: sha512-OUg2JvsVI1oIee/SwiejTot2OxwU8a7UfTFMOdlhD2y+Hl6memUSL4s98bpUTo8EpVEr0lmwlU7JSu/p2QpSvA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
@@ -8195,26 +7929,6 @@ packages:
|
||||
- typescript
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/utils@5.45.0(eslint@8.28.0)(typescript@4.7.4):
|
||||
resolution: {integrity: sha512-OUg2JvsVI1oIee/SwiejTot2OxwU8a7UfTFMOdlhD2y+Hl6memUSL4s98bpUTo8EpVEr0lmwlU7JSu/p2QpSvA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
dependencies:
|
||||
'@types/json-schema': 7.0.9
|
||||
'@types/semver': 7.3.13
|
||||
'@typescript-eslint/scope-manager': 5.45.0
|
||||
'@typescript-eslint/types': 5.45.0
|
||||
'@typescript-eslint/typescript-estree': 5.45.0(typescript@4.7.4)
|
||||
eslint: 8.28.0
|
||||
eslint-scope: 5.1.1
|
||||
eslint-utils: 3.0.0(eslint@8.28.0)
|
||||
semver: 7.3.8
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/utils@5.45.0(eslint@8.29.0)(typescript@4.9.3):
|
||||
resolution: {integrity: sha512-OUg2JvsVI1oIee/SwiejTot2OxwU8a7UfTFMOdlhD2y+Hl6memUSL4s98bpUTo8EpVEr0lmwlU7JSu/p2QpSvA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
@@ -8667,27 +8381,6 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@vue/eslint-config-typescript@11.0.1(eslint-plugin-vue@9.5.1)(eslint@8.28.0)(typescript@4.7.4):
|
||||
resolution: {integrity: sha512-0U+nL0nA7ahnGPk3rTN49x76miUwuQtQPQNWOFvAcjg6nFJkIkA8qbGNtXwsuHtwBwRtWpHhShL3zK07v+632w==}
|
||||
engines: {node: ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: ^6.2.0 || ^7.0.0 || ^8.0.0
|
||||
eslint-plugin-vue: ^9.0.0
|
||||
typescript: '*'
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': 5.45.0(@typescript-eslint/parser@5.45.0)(eslint@8.28.0)(typescript@4.7.4)
|
||||
'@typescript-eslint/parser': 5.45.0(eslint@8.28.0)(typescript@4.7.4)
|
||||
eslint: 8.28.0
|
||||
eslint-plugin-vue: 9.5.1(eslint@8.28.0)
|
||||
typescript: 4.7.4
|
||||
vue-eslint-parser: 9.1.0(eslint@8.28.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@vue/eslint-config-typescript@11.0.1(eslint-plugin-vue@9.5.1)(eslint@8.29.0)(typescript@4.9.3):
|
||||
resolution: {integrity: sha512-0U+nL0nA7ahnGPk3rTN49x76miUwuQtQPQNWOFvAcjg6nFJkIkA8qbGNtXwsuHtwBwRtWpHhShL3zK07v+632w==}
|
||||
engines: {node: ^14.17.0 || >=16.0.0}
|
||||
@@ -12172,24 +11865,6 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-vue@9.5.1(eslint@8.28.0):
|
||||
resolution: {integrity: sha512-Y0sL2RY7Xc9S8kNih9lbwHIDmewUg9bfas6WSzsOWRgDXhIHKxRBZYNAnVcXBFfE+bMWHUA5GLChl7TcTYUI8w==}
|
||||
engines: {node: ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: ^6.2.0 || ^7.0.0 || ^8.0.0
|
||||
dependencies:
|
||||
eslint: 8.28.0
|
||||
eslint-utils: 3.0.0(eslint@8.28.0)
|
||||
natural-compare: 1.4.0
|
||||
nth-check: 2.1.1
|
||||
postcss-selector-parser: 6.0.10
|
||||
semver: 7.3.7
|
||||
vue-eslint-parser: 9.1.0(eslint@8.28.0)
|
||||
xml-name-validator: 4.0.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-vue@9.5.1(eslint@8.29.0):
|
||||
resolution: {integrity: sha512-Y0sL2RY7Xc9S8kNih9lbwHIDmewUg9bfas6WSzsOWRgDXhIHKxRBZYNAnVcXBFfE+bMWHUA5GLChl7TcTYUI8w==}
|
||||
engines: {node: ^14.17.0 || >=16.0.0}
|
||||
@@ -12249,16 +11924,6 @@ packages:
|
||||
eslint-visitor-keys: 2.1.0
|
||||
dev: true
|
||||
|
||||
/eslint-utils@3.0.0(eslint@8.28.0):
|
||||
resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==}
|
||||
engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0}
|
||||
peerDependencies:
|
||||
eslint: '>=5'
|
||||
dependencies:
|
||||
eslint: 8.28.0
|
||||
eslint-visitor-keys: 2.1.0
|
||||
dev: true
|
||||
|
||||
/eslint-utils@3.0.0(eslint@8.29.0):
|
||||
resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==}
|
||||
engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0}
|
||||
@@ -12373,54 +12038,6 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint@8.28.0:
|
||||
resolution: {integrity: sha512-S27Di+EVyMxcHiwDrFzk8dJYAaD+/5SoWKxL1ri/71CRHsnJnRDPNt2Kzj24+MT9FDupf4aqqyqPrvI8MvQ4VQ==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@eslint/eslintrc': 1.3.3
|
||||
'@humanwhocodes/config-array': 0.11.7
|
||||
'@humanwhocodes/module-importer': 1.0.1
|
||||
'@nodelib/fs.walk': 1.2.8
|
||||
ajv: 6.12.6
|
||||
chalk: 4.1.2
|
||||
cross-spawn: 7.0.3
|
||||
debug: 4.3.4(supports-color@9.2.2)
|
||||
doctrine: 3.0.0
|
||||
escape-string-regexp: 4.0.0
|
||||
eslint-scope: 7.1.1
|
||||
eslint-utils: 3.0.0(eslint@8.28.0)
|
||||
eslint-visitor-keys: 3.3.0
|
||||
espree: 9.4.0
|
||||
esquery: 1.4.0
|
||||
esutils: 2.0.3
|
||||
fast-deep-equal: 3.1.3
|
||||
file-entry-cache: 6.0.1
|
||||
find-up: 5.0.0
|
||||
glob-parent: 6.0.2
|
||||
globals: 13.16.0
|
||||
grapheme-splitter: 1.0.4
|
||||
ignore: 5.2.0
|
||||
import-fresh: 3.3.0
|
||||
imurmurhash: 0.1.4
|
||||
is-glob: 4.0.3
|
||||
is-path-inside: 3.0.3
|
||||
js-sdsl: 4.1.4
|
||||
js-yaml: 4.1.0
|
||||
json-stable-stringify-without-jsonify: 1.0.1
|
||||
levn: 0.4.1
|
||||
lodash.merge: 4.6.2
|
||||
minimatch: 3.1.2
|
||||
natural-compare: 1.4.0
|
||||
optionator: 0.9.1
|
||||
regexpp: 3.2.0
|
||||
strip-ansi: 6.0.1
|
||||
strip-json-comments: 3.1.1
|
||||
text-table: 0.2.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint@8.29.0:
|
||||
resolution: {integrity: sha512-isQ4EEiyUjZFbEKvEGJKKGBwXtvXX+zJbkVKCgTuB9t/+jUBcy8avhkEwWJecI15BkRkOYmvIM5ynbhRjEkoeg==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
@@ -21461,24 +21078,6 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/vue-eslint-parser@9.1.0(eslint@8.28.0):
|
||||
resolution: {integrity: sha512-NGn/iQy8/Wb7RrRa4aRkokyCZfOUWk19OP5HP6JEozQFX5AoS/t+Z0ZN7FY4LlmWc4FNI922V7cvX28zctN8dQ==}
|
||||
engines: {node: ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
eslint: '>=6.0.0'
|
||||
dependencies:
|
||||
debug: 4.3.4(supports-color@9.2.2)
|
||||
eslint: 8.28.0
|
||||
eslint-scope: 7.1.1
|
||||
eslint-visitor-keys: 3.3.0
|
||||
espree: 9.4.0
|
||||
esquery: 1.4.0
|
||||
lodash: 4.17.21
|
||||
semver: 7.3.8
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/vue-eslint-parser@9.1.0(eslint@8.29.0):
|
||||
resolution: {integrity: sha512-NGn/iQy8/Wb7RrRa4aRkokyCZfOUWk19OP5HP6JEozQFX5AoS/t+Z0ZN7FY4LlmWc4FNI922V7cvX28zctN8dQ==}
|
||||
engines: {node: ^14.17.0 || >=16.0.0}
|
||||
@@ -21614,17 +21213,6 @@ packages:
|
||||
typescript: 4.9.3
|
||||
dev: true
|
||||
|
||||
/vue-tsc@1.0.9(typescript@4.7.4):
|
||||
resolution: {integrity: sha512-vRmHD1K6DmBymNhoHjQy/aYKTRQNLGOu2/ESasChG9Vy113K6CdP0NlhR0bzgFJfv2eFB9Ez/9L5kIciUajBxQ==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
typescript: '*'
|
||||
dependencies:
|
||||
'@volar/vue-language-core': 1.0.9
|
||||
'@volar/vue-typescript': 1.0.9
|
||||
typescript: 4.7.4
|
||||
dev: true
|
||||
|
||||
/vue-tsc@1.0.9(typescript@4.9.3):
|
||||
resolution: {integrity: sha512-vRmHD1K6DmBymNhoHjQy/aYKTRQNLGOu2/ESasChG9Vy113K6CdP0NlhR0bzgFJfv2eFB9Ez/9L5kIciUajBxQ==}
|
||||
hasBin: true
|
||||
|
||||
Reference in New Issue
Block a user