localpersistence.ts 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /* eslint-disable no-restricted-globals, no-restricted-syntax */
  2. import clone from "lodash/clone"
  3. import assign from "lodash/assign"
  4. import isEmpty from "lodash/isEmpty"
  5. import * as O from "fp-ts/Option"
  6. import { pipe } from "fp-ts/function"
  7. import { translateToNewRequest } from "@hoppscotch/data"
  8. import {
  9. settingsStore,
  10. bulkApplySettings,
  11. defaultSettings,
  12. applySetting,
  13. HoppAccentColor,
  14. HoppBgColor,
  15. } from "./settings"
  16. import {
  17. restHistoryStore,
  18. graphqlHistoryStore,
  19. setRESTHistoryEntries,
  20. setGraphqlHistoryEntries,
  21. translateToNewRESTHistory,
  22. translateToNewGQLHistory,
  23. } from "./history"
  24. import {
  25. restCollectionStore,
  26. graphqlCollectionStore,
  27. setGraphqlCollections,
  28. setRESTCollections,
  29. translateToNewRESTCollection,
  30. translateToNewGQLCollection,
  31. } from "./collections"
  32. import {
  33. replaceEnvironments,
  34. environments$,
  35. Environment,
  36. addGlobalEnvVariable,
  37. setGlobalEnvVariables,
  38. globalEnv$,
  39. selectedEnvIndex$,
  40. setCurrentEnvironment,
  41. } from "./environments"
  42. import { restRequest$, setRESTRequest } from "./RESTSession"
  43. import { WSRequest$, setWSRequest } from "./WebSocketSession"
  44. import { SIORequest$, setSIORequest } from "./SocketIOSession"
  45. import { SSERequest$, setSSERequest } from "./SSESession"
  46. import { MQTTRequest$, setMQTTRequest } from "./MQTTSession"
  47. function checkAndMigrateOldSettings() {
  48. const vuexData = JSON.parse(window.localStorage.getItem("vuex") || "{}")
  49. if (isEmpty(vuexData)) return
  50. const { postwoman } = vuexData
  51. if (!isEmpty(postwoman?.settings)) {
  52. const settingsData = assign(clone(defaultSettings), postwoman.settings)
  53. window.localStorage.setItem("settings", JSON.stringify(settingsData))
  54. delete postwoman.settings
  55. window.localStorage.setItem("vuex", JSON.stringify(vuexData))
  56. }
  57. if (postwoman?.collections) {
  58. window.localStorage.setItem(
  59. "collections",
  60. JSON.stringify(postwoman.collections)
  61. )
  62. delete postwoman.collections
  63. window.localStorage.setItem("vuex", JSON.stringify(vuexData))
  64. }
  65. if (postwoman?.collectionsGraphql) {
  66. window.localStorage.setItem(
  67. "collectionsGraphql",
  68. JSON.stringify(postwoman.collectionsGraphql)
  69. )
  70. delete postwoman.collectionsGraphql
  71. window.localStorage.setItem("vuex", JSON.stringify(vuexData))
  72. }
  73. if (postwoman?.environments) {
  74. window.localStorage.setItem(
  75. "environments",
  76. JSON.stringify(postwoman.environments)
  77. )
  78. delete postwoman.environments
  79. window.localStorage.setItem("vuex", JSON.stringify(vuexData))
  80. }
  81. if (window.localStorage.getItem("THEME_COLOR")) {
  82. const themeColor = window.localStorage.getItem("THEME_COLOR")
  83. applySetting("THEME_COLOR", themeColor as HoppAccentColor)
  84. window.localStorage.removeItem("THEME_COLOR")
  85. }
  86. if (window.localStorage.getItem("nuxt-color-mode")) {
  87. const color = window.localStorage.getItem("nuxt-color-mode") as HoppBgColor
  88. applySetting("BG_COLOR", color)
  89. window.localStorage.removeItem("nuxt-color-mode")
  90. }
  91. }
  92. function setupSettingsPersistence() {
  93. const settingsData = JSON.parse(
  94. window.localStorage.getItem("settings") || "{}"
  95. )
  96. if (settingsData) {
  97. bulkApplySettings(settingsData)
  98. }
  99. settingsStore.subject$.subscribe((settings) => {
  100. window.localStorage.setItem("settings", JSON.stringify(settings))
  101. })
  102. }
  103. function setupHistoryPersistence() {
  104. const restHistoryData = JSON.parse(
  105. window.localStorage.getItem("history") || "[]"
  106. ).map(translateToNewRESTHistory)
  107. const graphqlHistoryData = JSON.parse(
  108. window.localStorage.getItem("graphqlHistory") || "[]"
  109. ).map(translateToNewGQLHistory)
  110. setRESTHistoryEntries(restHistoryData)
  111. setGraphqlHistoryEntries(graphqlHistoryData)
  112. restHistoryStore.subject$.subscribe(({ state }) => {
  113. window.localStorage.setItem("history", JSON.stringify(state))
  114. })
  115. graphqlHistoryStore.subject$.subscribe(({ state }) => {
  116. window.localStorage.setItem("graphqlHistory", JSON.stringify(state))
  117. })
  118. }
  119. function setupCollectionsPersistence() {
  120. const restCollectionData = JSON.parse(
  121. window.localStorage.getItem("collections") || "[]"
  122. ).map(translateToNewRESTCollection)
  123. const graphqlCollectionData = JSON.parse(
  124. window.localStorage.getItem("collectionsGraphql") || "[]"
  125. ).map(translateToNewGQLCollection)
  126. setRESTCollections(restCollectionData)
  127. setGraphqlCollections(graphqlCollectionData)
  128. restCollectionStore.subject$.subscribe(({ state }) => {
  129. window.localStorage.setItem("collections", JSON.stringify(state))
  130. })
  131. graphqlCollectionStore.subject$.subscribe(({ state }) => {
  132. window.localStorage.setItem("collectionsGraphql", JSON.stringify(state))
  133. })
  134. }
  135. function setupEnvironmentsPersistence() {
  136. const environmentsData: Environment[] = JSON.parse(
  137. window.localStorage.getItem("environments") || "[]"
  138. )
  139. // Check if a global env is defined and if so move that to globals
  140. const globalIndex = environmentsData.findIndex(
  141. (x) => x.name.toLowerCase() === "globals"
  142. )
  143. if (globalIndex !== -1) {
  144. const globalEnv = environmentsData[globalIndex]
  145. globalEnv.variables.forEach((variable) => addGlobalEnvVariable(variable))
  146. // Remove global from environments
  147. environmentsData.splice(globalIndex, 1)
  148. // Just sync the changes manually
  149. window.localStorage.setItem(
  150. "environments",
  151. JSON.stringify(environmentsData)
  152. )
  153. }
  154. replaceEnvironments(environmentsData)
  155. environments$.subscribe((envs) => {
  156. window.localStorage.setItem("environments", JSON.stringify(envs))
  157. })
  158. }
  159. function setupSelectedEnvPersistence() {
  160. const selectedEnvIndex = pipe(
  161. // Value from local storage can be nullable
  162. O.fromNullable(window.localStorage.getItem("selectedEnvIndex")),
  163. O.map(parseInt), // If not null, parse to integer
  164. O.chain(
  165. O.fromPredicate(
  166. Number.isInteger // Check if the number is proper int (not NaN)
  167. )
  168. ),
  169. O.getOrElse(() => -1) // If all the above conditions pass, we are good, else set default value (-1)
  170. )
  171. setCurrentEnvironment(selectedEnvIndex)
  172. selectedEnvIndex$.subscribe((index) => {
  173. window.localStorage.setItem("selectedEnvIndex", index.toString())
  174. })
  175. }
  176. function setupWebsocketPersistence() {
  177. const request = JSON.parse(
  178. window.localStorage.getItem("WebsocketRequest") || "null"
  179. )
  180. setWSRequest(request)
  181. WSRequest$.subscribe((req) => {
  182. window.localStorage.setItem("WebsocketRequest", JSON.stringify(req))
  183. })
  184. }
  185. function setupSocketIOPersistence() {
  186. const request = JSON.parse(
  187. window.localStorage.getItem("SocketIORequest") || "null"
  188. )
  189. setSIORequest(request)
  190. SIORequest$.subscribe((req) => {
  191. window.localStorage.setItem("SocketIORequest", JSON.stringify(req))
  192. })
  193. }
  194. function setupSSEPersistence() {
  195. const request = JSON.parse(
  196. window.localStorage.getItem("SSERequest") || "null"
  197. )
  198. setSSERequest(request)
  199. SSERequest$.subscribe((req) => {
  200. window.localStorage.setItem("SSERequest", JSON.stringify(req))
  201. })
  202. }
  203. function setupMQTTPersistence() {
  204. const request = JSON.parse(
  205. window.localStorage.getItem("MQTTRequest") || "null"
  206. )
  207. setMQTTRequest(request)
  208. MQTTRequest$.subscribe((req) => {
  209. window.localStorage.setItem("MQTTRequest", JSON.stringify(req))
  210. })
  211. }
  212. function setupGlobalEnvsPersistence() {
  213. const globals: Environment["variables"] = JSON.parse(
  214. window.localStorage.getItem("globalEnv") || "[]"
  215. )
  216. setGlobalEnvVariables(globals)
  217. globalEnv$.subscribe((vars) => {
  218. window.localStorage.setItem("globalEnv", JSON.stringify(vars))
  219. })
  220. }
  221. function setupRequestPersistence() {
  222. const localRequest = JSON.parse(
  223. window.localStorage.getItem("restRequest") || "null"
  224. )
  225. if (localRequest) {
  226. const parsedLocal = translateToNewRequest(localRequest)
  227. setRESTRequest(parsedLocal)
  228. }
  229. restRequest$.subscribe((req) => {
  230. window.localStorage.setItem("restRequest", JSON.stringify(req))
  231. })
  232. }
  233. export function setupLocalPersistence() {
  234. checkAndMigrateOldSettings()
  235. setupSettingsPersistence()
  236. setupRequestPersistence()
  237. setupHistoryPersistence()
  238. setupCollectionsPersistence()
  239. setupGlobalEnvsPersistence()
  240. setupEnvironmentsPersistence()
  241. setupSelectedEnvPersistence()
  242. setupWebsocketPersistence()
  243. setupSocketIOPersistence()
  244. setupSSEPersistence()
  245. setupMQTTPersistence()
  246. }
  247. /**
  248. * Gets a value in LocalStorage.
  249. *
  250. * NOTE: Use LocalStorage to only store non-reactive simple data
  251. * For more complex data, use stores and connect it to localpersistence
  252. */
  253. export function getLocalConfig(name: string) {
  254. return window.localStorage.getItem(name)
  255. }
  256. /**
  257. * Sets a value in LocalStorage.
  258. *
  259. * NOTE: Use LocalStorage to only store non-reactive simple data
  260. * For more complex data, use stores and connect it to localpersistence
  261. */
  262. export function setLocalConfig(key: string, value: string) {
  263. window.localStorage.setItem(key, value)
  264. }
  265. /**
  266. * Clear config value in LocalStorage.
  267. * @param key Key to be cleared
  268. */
  269. export function removeLocalConfig(key: string) {
  270. window.localStorage.removeItem(key)
  271. }