Files
hoppscotch/packages/hoppscotch-app/newstore/localpersistence.ts
2022-07-21 20:58:53 -07:00

370 lines
9.7 KiB
TypeScript

/* eslint-disable no-restricted-globals, no-restricted-syntax */
import clone from "lodash/clone"
import assign from "lodash/assign"
import isEmpty from "lodash/isEmpty"
import * as O from "fp-ts/Option"
import { pipe } from "fp-ts/function"
import {
safelyExtractRESTRequest,
translateToNewRequest,
translateToNewRESTCollection,
translateToNewGQLCollection,
Environment,
} from "@hoppscotch/data"
import { cloneDeep } from "lodash"
import {
settingsStore,
bulkApplySettings,
defaultSettings,
applySetting,
HoppAccentColor,
HoppBgColor,
} from "./settings"
import {
restHistoryStore,
graphqlHistoryStore,
setRESTHistoryEntries,
setGraphqlHistoryEntries,
translateToNewRESTHistory,
translateToNewGQLHistory,
} from "./history"
import {
restCollectionStore,
graphqlCollectionStore,
setGraphqlCollections,
setRESTCollections,
} from "./collections"
import {
replaceEnvironments,
environments$,
addGlobalEnvVariable,
setGlobalEnvVariables,
globalEnv$,
selectedEnvIndex$,
setCurrentEnvironment,
} from "./environments"
import {
getDefaultRESTRequest,
restRequest$,
setRESTRequest,
} from "./RESTSession"
import { WSRequest$, setWSRequest } from "./WebSocketSession"
import { SIORequest$, setSIORequest } from "./SocketIOSession"
import { SSERequest$, setSSERequest } from "./SSESession"
import { MQTTRequest$, setMQTTRequest } from "./MQTTSession"
import { bulkApplyLocalState, localStateStore } from "./localstate"
function checkAndMigrateOldSettings() {
const vuexData = JSON.parse(window.localStorage.getItem("vuex") || "{}")
if (isEmpty(vuexData)) return
const { postwoman } = vuexData
if (!isEmpty(postwoman?.settings)) {
const settingsData = assign(clone(defaultSettings), postwoman.settings)
window.localStorage.setItem("settings", JSON.stringify(settingsData))
delete postwoman.settings
window.localStorage.setItem("vuex", JSON.stringify(vuexData))
}
if (postwoman?.collections) {
window.localStorage.setItem(
"collections",
JSON.stringify(postwoman.collections)
)
delete postwoman.collections
window.localStorage.setItem("vuex", JSON.stringify(vuexData))
}
if (postwoman?.collectionsGraphql) {
window.localStorage.setItem(
"collectionsGraphql",
JSON.stringify(postwoman.collectionsGraphql)
)
delete postwoman.collectionsGraphql
window.localStorage.setItem("vuex", JSON.stringify(vuexData))
}
if (postwoman?.environments) {
window.localStorage.setItem(
"environments",
JSON.stringify(postwoman.environments)
)
delete postwoman.environments
window.localStorage.setItem("vuex", JSON.stringify(vuexData))
}
if (window.localStorage.getItem("THEME_COLOR")) {
const themeColor = window.localStorage.getItem("THEME_COLOR")
applySetting("THEME_COLOR", themeColor as HoppAccentColor)
window.localStorage.removeItem("THEME_COLOR")
}
if (window.localStorage.getItem("nuxt-color-mode")) {
const color = window.localStorage.getItem("nuxt-color-mode") as HoppBgColor
applySetting("BG_COLOR", color)
window.localStorage.removeItem("nuxt-color-mode")
}
}
function setupLocalStatePersistence() {
const localStateData = JSON.parse(
window.localStorage.getItem("localState") ?? "{}"
)
if (localStateData) bulkApplyLocalState(localStateData)
localStateStore.subject$.subscribe((state) => {
window.localStorage.setItem("localState", JSON.stringify(state))
})
}
function setupSettingsPersistence() {
const settingsData = JSON.parse(
window.localStorage.getItem("settings") || "{}"
)
if (settingsData) {
bulkApplySettings(settingsData)
}
settingsStore.subject$.subscribe((settings) => {
window.localStorage.setItem("settings", JSON.stringify(settings))
})
}
function setupHistoryPersistence() {
const restHistoryData = JSON.parse(
window.localStorage.getItem("history") || "[]"
).map(translateToNewRESTHistory)
const graphqlHistoryData = JSON.parse(
window.localStorage.getItem("graphqlHistory") || "[]"
).map(translateToNewGQLHistory)
setRESTHistoryEntries(restHistoryData)
setGraphqlHistoryEntries(graphqlHistoryData)
restHistoryStore.subject$.subscribe(({ state }) => {
window.localStorage.setItem("history", JSON.stringify(state))
})
graphqlHistoryStore.subject$.subscribe(({ state }) => {
window.localStorage.setItem("graphqlHistory", JSON.stringify(state))
})
}
function setupCollectionsPersistence() {
const restCollectionData = JSON.parse(
window.localStorage.getItem("collections") || "[]"
).map(translateToNewRESTCollection)
const graphqlCollectionData = JSON.parse(
window.localStorage.getItem("collectionsGraphql") || "[]"
).map(translateToNewGQLCollection)
setRESTCollections(restCollectionData)
setGraphqlCollections(graphqlCollectionData)
restCollectionStore.subject$.subscribe(({ state }) => {
window.localStorage.setItem("collections", JSON.stringify(state))
})
graphqlCollectionStore.subject$.subscribe(({ state }) => {
window.localStorage.setItem("collectionsGraphql", JSON.stringify(state))
})
}
function setupEnvironmentsPersistence() {
const environmentsData: Environment[] = JSON.parse(
window.localStorage.getItem("environments") || "[]"
)
// 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(
"environments",
JSON.stringify(environmentsData)
)
}
replaceEnvironments(environmentsData)
environments$.subscribe((envs) => {
window.localStorage.setItem("environments", JSON.stringify(envs))
})
}
function setupSelectedEnvPersistence() {
const selectedEnvIndex = pipe(
// Value from local storage can be nullable
O.fromNullable(window.localStorage.getItem("selectedEnvIndex")),
O.map(parseInt), // If not null, parse to integer
O.chain(
O.fromPredicate(
Number.isInteger // Check if the number is proper int (not NaN)
)
),
O.getOrElse(() => -1) // If all the above conditions pass, we are good, else set default value (-1)
)
setCurrentEnvironment(selectedEnvIndex)
selectedEnvIndex$.subscribe((index) => {
window.localStorage.setItem("selectedEnvIndex", index.toString())
})
}
function setupWebsocketPersistence() {
const request = JSON.parse(
window.localStorage.getItem("WebsocketRequest") || "null"
)
setWSRequest(request)
WSRequest$.subscribe((req) => {
window.localStorage.setItem("WebsocketRequest", JSON.stringify(req))
})
}
function setupSocketIOPersistence() {
const request = JSON.parse(
window.localStorage.getItem("SocketIORequest") || "null"
)
setSIORequest(request)
SIORequest$.subscribe((req) => {
window.localStorage.setItem("SocketIORequest", JSON.stringify(req))
})
}
function setupSSEPersistence() {
const request = JSON.parse(
window.localStorage.getItem("SSERequest") || "null"
)
setSSERequest(request)
SSERequest$.subscribe((req) => {
window.localStorage.setItem("SSERequest", JSON.stringify(req))
})
}
function setupMQTTPersistence() {
const request = JSON.parse(
window.localStorage.getItem("MQTTRequest") || "null"
)
setMQTTRequest(request)
MQTTRequest$.subscribe((req) => {
window.localStorage.setItem("MQTTRequest", JSON.stringify(req))
})
}
function setupGlobalEnvsPersistence() {
const globals: Environment["variables"] = JSON.parse(
window.localStorage.getItem("globalEnv") || "[]"
)
setGlobalEnvVariables(globals)
globalEnv$.subscribe((vars) => {
window.localStorage.setItem("globalEnv", JSON.stringify(vars))
})
}
function setupRequestPersistence() {
const localRequest = JSON.parse(
window.localStorage.getItem("restRequest") || "null"
)
if (localRequest) {
const parsedLocal = translateToNewRequest(localRequest)
setRESTRequest(
safelyExtractRESTRequest(parsedLocal, getDefaultRESTRequest())
)
}
restRequest$.subscribe((req) => {
const reqClone = cloneDeep(req)
if (reqClone.body.contentType === "multipart/form-data") {
reqClone.body.body = reqClone.body.body.map((x) => {
if (x.isFile)
return {
...x,
isFile: false,
value: "",
}
else return x
})
}
window.localStorage.setItem("restRequest", JSON.stringify(reqClone))
})
}
export function setupLocalPersistence() {
checkAndMigrateOldSettings()
setupLocalStatePersistence()
setupSettingsPersistence()
setupRequestPersistence()
setupHistoryPersistence()
setupCollectionsPersistence()
setupGlobalEnvsPersistence()
setupEnvironmentsPersistence()
setupSelectedEnvPersistence()
setupWebsocketPersistence()
setupSocketIOPersistence()
setupSSEPersistence()
setupMQTTPersistence()
}
/**
* Gets a value in LocalStorage.
*
* NOTE: Use LocalStorage to only store non-reactive simple data
* For more complex data, use stores and connect it to localpersistence
*/
export function 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 localpersistence
*/
export function setLocalConfig(key: string, value: string) {
window.localStorage.setItem(key, value)
}
/**
* Clear config value in LocalStorage.
* @param key Key to be cleared
*/
export function removeLocalConfig(key: string) {
window.localStorage.removeItem(key)
}