725 lines
20 KiB
TypeScript
725 lines
20 KiB
TypeScript
/* eslint-disable no-restricted-globals, no-restricted-syntax */
|
|
|
|
import {
|
|
Environment,
|
|
translateToNewGQLCollection,
|
|
translateToNewRESTCollection,
|
|
} from "@hoppscotch/data"
|
|
import { StorageLike, watchDebounced } from "@vueuse/core"
|
|
import { Service } from "dioc"
|
|
import { assign, clone, isEmpty } from "lodash-es"
|
|
import { z } from "zod"
|
|
|
|
import { GQLTabService } from "~/services/tab/graphql"
|
|
import { RESTTabService } from "~/services/tab/rest"
|
|
|
|
import { useToast } from "~/composables/toast"
|
|
import { MQTTRequest$, setMQTTRequest } from "../../newstore/MQTTSession"
|
|
import { SSERequest$, setSSERequest } from "../../newstore/SSESession"
|
|
import { SIORequest$, setSIORequest } from "../../newstore/SocketIOSession"
|
|
import { WSRequest$, setWSRequest } from "../../newstore/WebSocketSession"
|
|
import {
|
|
graphqlCollectionStore,
|
|
restCollectionStore,
|
|
setGraphqlCollections,
|
|
setRESTCollections,
|
|
} from "../../newstore/collections"
|
|
import {
|
|
addGlobalEnvVariable,
|
|
environments$,
|
|
globalEnv$,
|
|
replaceEnvironments,
|
|
selectedEnvironmentIndex$,
|
|
setGlobalEnvVariables,
|
|
setSelectedEnvironmentIndex,
|
|
} from "../../newstore/environments"
|
|
import {
|
|
graphqlHistoryStore,
|
|
restHistoryStore,
|
|
setGraphqlHistoryEntries,
|
|
setRESTHistoryEntries,
|
|
translateToNewGQLHistory,
|
|
translateToNewRESTHistory,
|
|
} from "../../newstore/history"
|
|
import { bulkApplyLocalState, localStateStore } from "../../newstore/localstate"
|
|
import {
|
|
HoppAccentColor,
|
|
HoppBgColor,
|
|
applySetting,
|
|
bulkApplySettings,
|
|
getDefaultSettings,
|
|
performSettingsDataMigrations,
|
|
settingsStore,
|
|
} from "../../newstore/settings"
|
|
import {
|
|
ENVIRONMENTS_SCHEMA,
|
|
GLOBAL_ENV_SCHEMA,
|
|
GQL_COLLECTION_SCHEMA,
|
|
GQL_HISTORY_ENTRY_SCHEMA,
|
|
GQL_TAB_STATE_SCHEMA,
|
|
LOCAL_STATE_SCHEMA,
|
|
MQTT_REQUEST_SCHEMA,
|
|
NUXT_COLOR_MODE_SCHEMA,
|
|
REST_COLLECTION_SCHEMA,
|
|
REST_HISTORY_ENTRY_SCHEMA,
|
|
REST_TAB_STATE_SCHEMA,
|
|
SELECTED_ENV_INDEX_SCHEMA,
|
|
SETTINGS_SCHEMA,
|
|
SOCKET_IO_REQUEST_SCHEMA,
|
|
SSE_REQUEST_SCHEMA,
|
|
THEME_COLOR_SCHEMA,
|
|
VUEX_SCHEMA,
|
|
WEBSOCKET_REQUEST_SCHEMA,
|
|
} from "./validation-schemas"
|
|
|
|
/**
|
|
* This service compiles persistence logic across the codebase
|
|
*/
|
|
export class PersistenceService extends Service {
|
|
public static readonly ID = "PERSISTENCE_SERVICE"
|
|
|
|
private readonly restTabService = this.bind(RESTTabService)
|
|
private readonly gqlTabService = this.bind(GQLTabService)
|
|
|
|
public hoppLocalConfigStorage: StorageLike = localStorage
|
|
|
|
constructor() {
|
|
super()
|
|
}
|
|
|
|
private showErrorToast(localStorageKey: string) {
|
|
const toast = useToast()
|
|
toast.error(
|
|
`There's a mismatch with the expected schema for the value corresponding to ${localStorageKey} read from localStorage, keeping a backup in ${localStorageKey}-backup`
|
|
)
|
|
}
|
|
|
|
private 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 vuexKey = "vuex"
|
|
let vuexData = JSON.parse(window.localStorage.getItem(vuexKey) || "{}")
|
|
|
|
if (isEmpty(vuexData)) return
|
|
|
|
// Validate data read from localStorage
|
|
const result = VUEX_SCHEMA.safeParse(vuexData)
|
|
if (result.success) {
|
|
vuexData = result.data
|
|
} else {
|
|
this.showErrorToast(vuexKey)
|
|
window.localStorage.setItem(`${vuexKey}-backup`, JSON.stringify(vuexData))
|
|
}
|
|
|
|
const { postwoman } = vuexData
|
|
|
|
if (!isEmpty(postwoman?.settings)) {
|
|
const settingsData = assign(
|
|
clone(getDefaultSettings()),
|
|
postwoman.settings
|
|
)
|
|
|
|
window.localStorage.setItem("settings", JSON.stringify(settingsData))
|
|
|
|
delete postwoman.settings
|
|
window.localStorage.setItem(vuexKey, JSON.stringify(vuexData))
|
|
}
|
|
|
|
if (postwoman?.collections) {
|
|
window.localStorage.setItem(
|
|
"collections",
|
|
JSON.stringify(postwoman.collections)
|
|
)
|
|
|
|
delete postwoman.collections
|
|
window.localStorage.setItem(vuexKey, JSON.stringify(vuexData))
|
|
}
|
|
|
|
if (postwoman?.collectionsGraphql) {
|
|
window.localStorage.setItem(
|
|
"collectionsGraphql",
|
|
JSON.stringify(postwoman.collectionsGraphql)
|
|
)
|
|
|
|
delete postwoman.collectionsGraphql
|
|
window.localStorage.setItem(vuexKey, JSON.stringify(vuexData))
|
|
}
|
|
|
|
if (postwoman?.environments) {
|
|
window.localStorage.setItem(
|
|
"environments",
|
|
JSON.stringify(postwoman.environments)
|
|
)
|
|
|
|
delete postwoman.environments
|
|
window.localStorage.setItem(vuexKey, JSON.stringify(vuexData))
|
|
}
|
|
|
|
const themeColorKey = "THEME_COLOR"
|
|
let themeColorValue = window.localStorage.getItem(themeColorKey)
|
|
|
|
if (themeColorValue) {
|
|
// Validate data read from localStorage
|
|
const result = THEME_COLOR_SCHEMA.safeParse(themeColorValue)
|
|
|
|
if (result.success) {
|
|
themeColorValue = result.data
|
|
} else {
|
|
this.showErrorToast(themeColorKey)
|
|
window.localStorage.setItem(`${themeColorKey}-backup`, themeColorValue)
|
|
}
|
|
|
|
applySetting(themeColorKey, themeColorValue as HoppAccentColor)
|
|
window.localStorage.removeItem(themeColorKey)
|
|
}
|
|
|
|
const nuxtColorModeKey = "nuxt-color-mode"
|
|
let nuxtColorModeValue = window.localStorage.getItem(nuxtColorModeKey)
|
|
|
|
if (nuxtColorModeValue) {
|
|
// Validate data read from localStorage
|
|
const result = NUXT_COLOR_MODE_SCHEMA.safeParse(nuxtColorModeValue)
|
|
|
|
if (result.success) {
|
|
nuxtColorModeValue = result.data
|
|
} else {
|
|
this.showErrorToast(nuxtColorModeKey)
|
|
window.localStorage.setItem(
|
|
`${nuxtColorModeKey}-backup`,
|
|
nuxtColorModeValue
|
|
)
|
|
}
|
|
|
|
applySetting("BG_COLOR", nuxtColorModeValue as HoppBgColor)
|
|
window.localStorage.removeItem(nuxtColorModeKey)
|
|
}
|
|
}
|
|
|
|
public setupLocalStatePersistence() {
|
|
const localStateKey = "localState"
|
|
let localStateData = JSON.parse(
|
|
window.localStorage.getItem(localStateKey) ?? "{}"
|
|
)
|
|
|
|
// Validate data read from localStorage
|
|
const result = LOCAL_STATE_SCHEMA.safeParse(localStateData)
|
|
|
|
if (result.success) {
|
|
localStateData = result.data
|
|
} else {
|
|
this.showErrorToast(localStateKey)
|
|
window.localStorage.setItem(
|
|
`${localStateKey}-backup`,
|
|
JSON.stringify(localStateData)
|
|
)
|
|
}
|
|
|
|
if (localStateData) bulkApplyLocalState(localStateData)
|
|
|
|
localStateStore.subject$.subscribe((state) => {
|
|
window.localStorage.setItem(localStateKey, JSON.stringify(state))
|
|
})
|
|
}
|
|
|
|
private setupSettingsPersistence() {
|
|
const settingsKey = "settings"
|
|
let settingsData = JSON.parse(
|
|
window.localStorage.getItem(settingsKey) || "{}"
|
|
)
|
|
|
|
// Validate data read from localStorage
|
|
const result = SETTINGS_SCHEMA.safeParse(settingsData)
|
|
if (result.success) {
|
|
settingsData = result.data
|
|
} else {
|
|
this.showErrorToast(settingsKey)
|
|
window.localStorage.setItem(
|
|
`${settingsKey}-backup`,
|
|
JSON.stringify(settingsData)
|
|
)
|
|
}
|
|
|
|
const updatedSettings = settingsData
|
|
? performSettingsDataMigrations(settingsData)
|
|
: settingsData
|
|
|
|
if (updatedSettings) {
|
|
bulkApplySettings(updatedSettings)
|
|
}
|
|
|
|
settingsStore.subject$.subscribe((settings) => {
|
|
window.localStorage.setItem(settingsKey, JSON.stringify(settings))
|
|
})
|
|
}
|
|
|
|
private setupHistoryPersistence() {
|
|
const restHistoryKey = "history"
|
|
let restHistoryData = JSON.parse(
|
|
window.localStorage.getItem(restHistoryKey) || "[]"
|
|
)
|
|
|
|
const graphqlHistoryKey = "graphqlHistory"
|
|
let graphqlHistoryData = JSON.parse(
|
|
window.localStorage.getItem(graphqlHistoryKey) || "[]"
|
|
)
|
|
|
|
// Validate data read from localStorage
|
|
const restHistorySchemaParsedresult = z
|
|
.array(REST_HISTORY_ENTRY_SCHEMA)
|
|
.safeParse(restHistoryData)
|
|
|
|
if (restHistorySchemaParsedresult.success) {
|
|
restHistoryData = restHistorySchemaParsedresult.data
|
|
} else {
|
|
this.showErrorToast(restHistoryKey)
|
|
window.localStorage.setItem(
|
|
`${restHistoryKey}-backup`,
|
|
JSON.stringify(restHistoryData)
|
|
)
|
|
}
|
|
|
|
const gqlHistorySchemaParsedresult = z
|
|
.array(GQL_HISTORY_ENTRY_SCHEMA)
|
|
.safeParse(graphqlHistoryData)
|
|
|
|
if (gqlHistorySchemaParsedresult.success) {
|
|
graphqlHistoryData = gqlHistorySchemaParsedresult.data
|
|
} else {
|
|
this.showErrorToast(graphqlHistoryKey)
|
|
window.localStorage.setItem(
|
|
`${graphqlHistoryKey}-backup`,
|
|
JSON.stringify(graphqlHistoryData)
|
|
)
|
|
}
|
|
|
|
const translatedRestHistoryData = restHistoryData.map(
|
|
translateToNewRESTHistory
|
|
)
|
|
const translatedGraphqlHistoryData = graphqlHistoryData.map(
|
|
translateToNewGQLHistory
|
|
)
|
|
|
|
setRESTHistoryEntries(translatedRestHistoryData)
|
|
setGraphqlHistoryEntries(translatedGraphqlHistoryData)
|
|
|
|
restHistoryStore.subject$.subscribe(({ state }) => {
|
|
window.localStorage.setItem(restHistoryKey, JSON.stringify(state))
|
|
})
|
|
|
|
graphqlHistoryStore.subject$.subscribe(({ state }) => {
|
|
window.localStorage.setItem(graphqlHistoryKey, JSON.stringify(state))
|
|
})
|
|
}
|
|
|
|
private setupCollectionsPersistence() {
|
|
const restCollectionsKey = "collections"
|
|
let restCollectionsData = JSON.parse(
|
|
window.localStorage.getItem(restCollectionsKey) || "[]"
|
|
)
|
|
|
|
const graphqlCollectionsKey = "collectionsGraphql"
|
|
let graphqlCollectionsData = JSON.parse(
|
|
window.localStorage.getItem(graphqlCollectionsKey) || "[]"
|
|
)
|
|
|
|
// Validate data read from localStorage
|
|
const restCollectionsSchemaParsedresult = z
|
|
.array(REST_COLLECTION_SCHEMA)
|
|
.safeParse(restCollectionsData)
|
|
|
|
if (restCollectionsSchemaParsedresult.success) {
|
|
restCollectionsData = restCollectionsSchemaParsedresult.data
|
|
} else {
|
|
this.showErrorToast(restCollectionsKey)
|
|
window.localStorage.setItem(
|
|
`${restCollectionsKey}-backup`,
|
|
JSON.stringify(restCollectionsData)
|
|
)
|
|
}
|
|
|
|
const gqlCollectionsSchemaParsedresult = z
|
|
.array(GQL_COLLECTION_SCHEMA)
|
|
.safeParse(graphqlCollectionsData)
|
|
|
|
if (gqlCollectionsSchemaParsedresult.success) {
|
|
graphqlCollectionsData = gqlCollectionsSchemaParsedresult.data
|
|
} else {
|
|
this.showErrorToast(graphqlCollectionsKey)
|
|
window.localStorage.setItem(
|
|
`${graphqlCollectionsKey}-backup`,
|
|
JSON.stringify(graphqlCollectionsData)
|
|
)
|
|
}
|
|
|
|
const translatedRestCollectionsData = restCollectionsData.map(
|
|
translateToNewRESTCollection
|
|
)
|
|
const translatedGraphqlCollectionsData = graphqlCollectionsData.map(
|
|
translateToNewGQLCollection
|
|
)
|
|
|
|
setRESTCollections(translatedRestCollectionsData)
|
|
setGraphqlCollections(translatedGraphqlCollectionsData)
|
|
|
|
restCollectionStore.subject$.subscribe(({ state }) => {
|
|
window.localStorage.setItem(restCollectionsKey, JSON.stringify(state))
|
|
})
|
|
|
|
graphqlCollectionStore.subject$.subscribe(({ state }) => {
|
|
window.localStorage.setItem(graphqlCollectionsKey, JSON.stringify(state))
|
|
})
|
|
}
|
|
|
|
private setupEnvironmentsPersistence() {
|
|
const environmentsKey = "environments"
|
|
let environmentsData: Environment[] = JSON.parse(
|
|
window.localStorage.getItem(environmentsKey) || "[]"
|
|
)
|
|
|
|
// Validate data read from localStorage
|
|
const result = ENVIRONMENTS_SCHEMA.safeParse(environmentsData)
|
|
if (result.success) {
|
|
environmentsData = result.data
|
|
} else {
|
|
this.showErrorToast(environmentsKey)
|
|
window.localStorage.setItem(
|
|
`${environmentsKey}-backup`,
|
|
JSON.stringify(environmentsData)
|
|
)
|
|
}
|
|
|
|
// Check if a global env is defined and if so move that to globals
|
|
const globalIndex = environmentsData.findIndex(
|
|
(x) => x.name.toLowerCase() === "globals"
|
|
)
|
|
|
|
if (globalIndex !== -1) {
|
|
const globalEnv = environmentsData[globalIndex]
|
|
globalEnv.variables.forEach((variable) => addGlobalEnvVariable(variable))
|
|
|
|
// Remove global from environments
|
|
environmentsData.splice(globalIndex, 1)
|
|
|
|
// Just sync the changes manually
|
|
window.localStorage.setItem(
|
|
environmentsKey,
|
|
JSON.stringify(environmentsData)
|
|
)
|
|
}
|
|
|
|
replaceEnvironments(environmentsData)
|
|
|
|
environments$.subscribe((envs) => {
|
|
window.localStorage.setItem(environmentsKey, JSON.stringify(envs))
|
|
})
|
|
}
|
|
|
|
private setupSelectedEnvPersistence() {
|
|
const selectedEnvIndexKey = "selectedEnvIndex"
|
|
let selectedEnvIndexValue = JSON.parse(
|
|
window.localStorage.getItem(selectedEnvIndexKey) ?? "null"
|
|
)
|
|
|
|
// Validate data read from localStorage
|
|
const result = SELECTED_ENV_INDEX_SCHEMA.safeParse(selectedEnvIndexValue)
|
|
if (result.success) {
|
|
selectedEnvIndexValue = result.data
|
|
} else {
|
|
this.showErrorToast(selectedEnvIndexKey)
|
|
window.localStorage.setItem(
|
|
`${selectedEnvIndexKey}-backup`,
|
|
JSON.stringify(selectedEnvIndexValue)
|
|
)
|
|
}
|
|
|
|
// If there is a selected env index, set it to the store else set it to null
|
|
if (selectedEnvIndexValue) {
|
|
setSelectedEnvironmentIndex(selectedEnvIndexValue)
|
|
} else {
|
|
setSelectedEnvironmentIndex({
|
|
type: "NO_ENV_SELECTED",
|
|
})
|
|
}
|
|
|
|
selectedEnvironmentIndex$.subscribe((envIndex) => {
|
|
window.localStorage.setItem(selectedEnvIndexKey, JSON.stringify(envIndex))
|
|
})
|
|
}
|
|
|
|
private setupWebsocketPersistence() {
|
|
const wsRequestKey = "WebsocketRequest"
|
|
let wsRequestData = JSON.parse(
|
|
window.localStorage.getItem(wsRequestKey) || "null"
|
|
)
|
|
|
|
// Validate data read from localStorage
|
|
const result = WEBSOCKET_REQUEST_SCHEMA.safeParse(wsRequestData)
|
|
if (result.success) {
|
|
wsRequestData = result.data
|
|
} else {
|
|
this.showErrorToast(wsRequestKey)
|
|
window.localStorage.setItem(
|
|
`${wsRequestKey}-backup`,
|
|
JSON.stringify(wsRequestData)
|
|
)
|
|
}
|
|
|
|
setWSRequest(wsRequestData)
|
|
|
|
WSRequest$.subscribe((req) => {
|
|
window.localStorage.setItem(wsRequestKey, JSON.stringify(req))
|
|
})
|
|
}
|
|
|
|
private setupSocketIOPersistence() {
|
|
const sioRequestKey = "SocketIORequest"
|
|
let sioRequestData = JSON.parse(
|
|
window.localStorage.getItem(sioRequestKey) || "null"
|
|
)
|
|
|
|
// Validate data read from localStorage
|
|
const result = SOCKET_IO_REQUEST_SCHEMA.safeParse(sioRequestData)
|
|
if (result.success) {
|
|
sioRequestData = result.data
|
|
} else {
|
|
this.showErrorToast(sioRequestKey)
|
|
window.localStorage.setItem(
|
|
`${sioRequestKey}-backup`,
|
|
JSON.stringify(sioRequestData)
|
|
)
|
|
}
|
|
|
|
setSIORequest(sioRequestData)
|
|
|
|
SIORequest$.subscribe((req) => {
|
|
window.localStorage.setItem(sioRequestKey, JSON.stringify(req))
|
|
})
|
|
}
|
|
|
|
private setupSSEPersistence() {
|
|
const sseRequestKey = "SSERequest"
|
|
let sseRequestData = JSON.parse(
|
|
window.localStorage.getItem(sseRequestKey) || "null"
|
|
)
|
|
|
|
// Validate data read from localStorage
|
|
const result = SSE_REQUEST_SCHEMA.safeParse(sseRequestData)
|
|
if (result.success) {
|
|
sseRequestData = result.data
|
|
} else {
|
|
this.showErrorToast(sseRequestKey)
|
|
window.localStorage.setItem(
|
|
`${sseRequestKey}-backup`,
|
|
JSON.stringify(sseRequestData)
|
|
)
|
|
}
|
|
|
|
setSSERequest(sseRequestData)
|
|
|
|
SSERequest$.subscribe((req) => {
|
|
window.localStorage.setItem(sseRequestKey, JSON.stringify(req))
|
|
})
|
|
}
|
|
|
|
private setupMQTTPersistence() {
|
|
const mqttRequestKey = "MQTTRequest"
|
|
let mqttRequestData = JSON.parse(
|
|
window.localStorage.getItem(mqttRequestKey) || "null"
|
|
)
|
|
|
|
// Validate data read from localStorage
|
|
const result = MQTT_REQUEST_SCHEMA.safeParse(mqttRequestData)
|
|
if (result.success) {
|
|
mqttRequestData = result.data
|
|
} else {
|
|
this.showErrorToast(mqttRequestKey)
|
|
window.localStorage.setItem(
|
|
`${mqttRequestKey}-backup`,
|
|
JSON.stringify(mqttRequestData)
|
|
)
|
|
}
|
|
|
|
setMQTTRequest(mqttRequestData)
|
|
|
|
MQTTRequest$.subscribe((req) => {
|
|
window.localStorage.setItem(mqttRequestKey, JSON.stringify(req))
|
|
})
|
|
}
|
|
|
|
private setupGlobalEnvsPersistence() {
|
|
const globalEnvKey = "globalEnv"
|
|
let globalEnvData: Environment["variables"] = JSON.parse(
|
|
window.localStorage.getItem(globalEnvKey) || "[]"
|
|
)
|
|
|
|
// Validate data read from localStorage
|
|
const result = GLOBAL_ENV_SCHEMA.safeParse(globalEnvData)
|
|
if (result.success) {
|
|
globalEnvData = result.data
|
|
} else {
|
|
this.showErrorToast(globalEnvKey)
|
|
window.localStorage.setItem(
|
|
`${globalEnvKey}-backup`,
|
|
JSON.stringify(globalEnvData)
|
|
)
|
|
}
|
|
|
|
setGlobalEnvVariables(globalEnvData)
|
|
|
|
globalEnv$.subscribe((vars) => {
|
|
window.localStorage.setItem(globalEnvKey, JSON.stringify(vars))
|
|
})
|
|
}
|
|
|
|
private setupGQLTabsPersistence() {
|
|
const gqlTabStateKey = "gqlTabState"
|
|
const gqlTabStateData = window.localStorage.getItem(gqlTabStateKey)
|
|
|
|
try {
|
|
if (gqlTabStateData) {
|
|
let parsedGqlTabStateData = JSON.parse(gqlTabStateData)
|
|
|
|
// Validate data read from localStorage
|
|
const result = GQL_TAB_STATE_SCHEMA.safeParse(parsedGqlTabStateData)
|
|
|
|
if (result.success) {
|
|
parsedGqlTabStateData = result.data
|
|
} else {
|
|
this.showErrorToast(gqlTabStateKey)
|
|
window.localStorage.setItem(
|
|
`${gqlTabStateKey}-backup`,
|
|
JSON.stringify(parsedGqlTabStateData)
|
|
)
|
|
}
|
|
|
|
this.gqlTabService.loadTabsFromPersistedState(parsedGqlTabStateData)
|
|
}
|
|
} catch (e) {
|
|
console.error(
|
|
`Failed parsing persisted tab state, state:`,
|
|
gqlTabStateData
|
|
)
|
|
}
|
|
|
|
watchDebounced(
|
|
this.gqlTabService.persistableTabState,
|
|
(newGqlTabStateData) => {
|
|
window.localStorage.setItem(
|
|
gqlTabStateKey,
|
|
JSON.stringify(newGqlTabStateData)
|
|
)
|
|
},
|
|
{ debounce: 500, deep: true }
|
|
)
|
|
}
|
|
|
|
private setupRESTTabsPersistence() {
|
|
const restTabStateKey = "restTabState"
|
|
const restTabStateData = window.localStorage.getItem(restTabStateKey)
|
|
|
|
try {
|
|
if (restTabStateData) {
|
|
let parsedGqlTabStateData = JSON.parse(restTabStateData)
|
|
|
|
// Validate data read from localStorage
|
|
const result = REST_TAB_STATE_SCHEMA.safeParse(parsedGqlTabStateData)
|
|
|
|
if (result.success) {
|
|
parsedGqlTabStateData = result.data
|
|
} else {
|
|
this.showErrorToast(restTabStateKey)
|
|
window.localStorage.setItem(
|
|
`${restTabStateKey}-backup`,
|
|
JSON.stringify(parsedGqlTabStateData)
|
|
)
|
|
}
|
|
|
|
this.restTabService.loadTabsFromPersistedState(parsedGqlTabStateData)
|
|
}
|
|
} catch (e) {
|
|
console.error(
|
|
`Failed parsing persisted tab state, state:`,
|
|
restTabStateData
|
|
)
|
|
}
|
|
|
|
watchDebounced(
|
|
this.restTabService.persistableTabState,
|
|
(newRestTabStateData) => {
|
|
window.localStorage.setItem(
|
|
restTabStateKey,
|
|
JSON.stringify(newRestTabStateData)
|
|
)
|
|
},
|
|
{ debounce: 500, deep: true }
|
|
)
|
|
}
|
|
|
|
public setupLocalPersistence() {
|
|
this.checkAndMigrateOldSettings()
|
|
|
|
this.setupLocalStatePersistence()
|
|
this.setupSettingsPersistence()
|
|
this.setupRESTTabsPersistence()
|
|
|
|
this.setupGQLTabsPersistence()
|
|
|
|
this.setupHistoryPersistence()
|
|
this.setupCollectionsPersistence()
|
|
this.setupGlobalEnvsPersistence()
|
|
this.setupEnvironmentsPersistence()
|
|
this.setupSelectedEnvPersistence()
|
|
this.setupWebsocketPersistence()
|
|
this.setupSocketIOPersistence()
|
|
this.setupSSEPersistence()
|
|
this.setupMQTTPersistence()
|
|
}
|
|
|
|
/**
|
|
* Gets a value from localStorage
|
|
*
|
|
* NOTE: Use localStorage to only store non-reactive simple data
|
|
* For more complex data, use stores and connect it to `PersistenceService`
|
|
*/
|
|
public getLocalConfig(name: string) {
|
|
return window.localStorage.getItem(name)
|
|
}
|
|
|
|
/**
|
|
* Sets a value in localStorage
|
|
*
|
|
* NOTE: Use localStorage to only store non-reactive simple data
|
|
* For more complex data, use stores and connect it to `PersistenceService`
|
|
*/
|
|
public setLocalConfig(key: string, value: string) {
|
|
window.localStorage.setItem(key, value)
|
|
}
|
|
|
|
/**
|
|
* Clear config value in localStorage
|
|
*/
|
|
public removeLocalConfig(key: string) {
|
|
window.localStorage.removeItem(key)
|
|
}
|
|
}
|