mirror of
https://github.com/graphql-hive/console
synced 2026-04-21 14:37:17 +00:00
Console 1994 migrate laboratory from localstorage to indexeddb (#7904)
This commit is contained in:
parent
70b3e19fe2
commit
4acd1c0446
4 changed files with 82 additions and 4 deletions
|
|
@ -106,6 +106,7 @@
|
|||
"graphql": "16.9.0",
|
||||
"graphql-sse": "2.5.3",
|
||||
"graphql-ws": "5.16.1",
|
||||
"idb-keyval": "6.2.1",
|
||||
"immer": "10.1.3",
|
||||
"js-cookie": "3.0.5",
|
||||
"json-schema-typed": "8.0.1",
|
||||
|
|
|
|||
53
packages/web/app/src/lib/laboratory-history-storage.ts
Normal file
53
packages/web/app/src/lib/laboratory-history-storage.ts
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
import { createStore, del, get, set } from 'idb-keyval';
|
||||
import type { LaboratoryHistory } from '@graphql-hive/laboratory';
|
||||
|
||||
const STORE = createStore('hive-laboratory-db', 'history-store');
|
||||
const HISTORY_KEY = 'history';
|
||||
const LS_KEY = 'hive:laboratory:history';
|
||||
|
||||
export async function loadHistory(): Promise<LaboratoryHistory[]> {
|
||||
try {
|
||||
const fromIdb = await get<LaboratoryHistory[]>(HISTORY_KEY, STORE);
|
||||
if (fromIdb !== undefined) {
|
||||
return fromIdb;
|
||||
}
|
||||
|
||||
// Migrate from localStorage on first load
|
||||
const raw = localStorage.getItem(LS_KEY);
|
||||
if (raw) {
|
||||
const parsed = JSON.parse(raw) as LaboratoryHistory[];
|
||||
await set(HISTORY_KEY, parsed, STORE);
|
||||
localStorage.removeItem(LS_KEY);
|
||||
return parsed;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[Laboratory] Failed to load history from IndexedDB:', err);
|
||||
// Fall back to localStorage
|
||||
try {
|
||||
const raw = localStorage.getItem(LS_KEY);
|
||||
if (raw) {
|
||||
return JSON.parse(raw) as LaboratoryHistory[];
|
||||
}
|
||||
} catch {
|
||||
// Corrupt data — start fresh
|
||||
localStorage.removeItem(LS_KEY);
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
export async function saveHistory(history: LaboratoryHistory[]): Promise<void> {
|
||||
try {
|
||||
await set(HISTORY_KEY, history, STORE);
|
||||
} catch (err) {
|
||||
console.error('[Laboratory] Failed to save history to IndexedDB:', err);
|
||||
}
|
||||
}
|
||||
|
||||
export async function clearHistory(): Promise<void> {
|
||||
try {
|
||||
await del(HISTORY_KEY, STORE);
|
||||
} catch (err) {
|
||||
console.error('[Laboratory] Failed to clear history from IndexedDB:', err);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { useCallback, useEffect, useMemo } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import { buildSchema, introspectionFromSchema, Kind, parse, print } from 'graphql';
|
||||
import { throttle } from 'lodash';
|
||||
|
|
@ -30,6 +30,7 @@ import { useCurrentOperationWithFetchingState } from '@/lib/hooks/laboratory/use
|
|||
import { TargetLaboratoryPageQuery } from '@/lib/hooks/laboratory/use-operation-collections-plugin';
|
||||
import { useOperationFromQueryString } from '@/lib/hooks/laboratory/useOperationFromQueryString';
|
||||
import { useResetState } from '@/lib/hooks/use-reset-state';
|
||||
import { loadHistory, saveHistory } from '@/lib/laboratory-history-storage';
|
||||
import { cn } from '@/lib/utils';
|
||||
import {
|
||||
Laboratory,
|
||||
|
|
@ -319,6 +320,18 @@ function useLaboratoryState(props: {
|
|||
},
|
||||
});
|
||||
|
||||
const [historyData, setHistoryData] = useState<LaboratoryHistory[] | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
void loadHistory().then(history => {
|
||||
if (!cancelled) setHistoryData(history);
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, []);
|
||||
|
||||
const preflight = useFragment(LaboratoryPreflightScriptTargetFragment, data?.target ?? null);
|
||||
|
||||
const collections = useMemo(
|
||||
|
|
@ -566,18 +579,21 @@ function useLaboratoryState(props: {
|
|||
const operationIdFromSearch = useOperationFromQueryString();
|
||||
|
||||
const fetching = useMemo(() => {
|
||||
if (historyData === null) {
|
||||
return true;
|
||||
}
|
||||
if (operationIdFromSearch) {
|
||||
return dataFetching || currentOperationFetching;
|
||||
}
|
||||
|
||||
return dataFetching;
|
||||
}, [dataFetching, currentOperationFetching, operationIdFromSearch]);
|
||||
}, [dataFetching, currentOperationFetching, operationIdFromSearch, historyData]);
|
||||
|
||||
return {
|
||||
fetching,
|
||||
defaultCollections: collections,
|
||||
defaultOperations,
|
||||
defaultHistory: getLocalStorageState('history', []),
|
||||
defaultHistory: historyData ?? [],
|
||||
defaultTabs,
|
||||
defaultActiveTabId: getLocalStorageState('activeTabId', null),
|
||||
defaultSettings: getLocalStorageState('settings', {
|
||||
|
|
@ -603,7 +619,7 @@ function useLaboratoryState(props: {
|
|||
setLocalStorageState('operations', operations);
|
||||
},
|
||||
onHistoryChange: (history: LaboratoryHistory[]) => {
|
||||
setLocalStorageState('history', history);
|
||||
void saveHistory(history);
|
||||
},
|
||||
onTabsChange: (tabs: LaboratoryTab[]) => {
|
||||
setLocalStorageState('tabs', tabs);
|
||||
|
|
|
|||
|
|
@ -2319,6 +2319,9 @@ importers:
|
|||
graphql-ws:
|
||||
specifier: 5.16.1
|
||||
version: 5.16.1(graphql@16.9.0)
|
||||
idb-keyval:
|
||||
specifier: 6.2.1
|
||||
version: 6.2.1
|
||||
immer:
|
||||
specifier: 10.1.3
|
||||
version: 10.1.3
|
||||
|
|
@ -13569,6 +13572,9 @@ packages:
|
|||
resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
idb-keyval@6.2.1:
|
||||
resolution: {integrity: sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==}
|
||||
|
||||
ieee754@1.2.1:
|
||||
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
|
||||
|
||||
|
|
@ -35186,6 +35192,8 @@ snapshots:
|
|||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
|
||||
idb-keyval@6.2.1: {}
|
||||
|
||||
ieee754@1.2.1: {}
|
||||
|
||||
ignore-walk@6.0.4:
|
||||
|
|
|
|||
Loading…
Reference in a new issue