Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions packages/devtools/src/context/devtools-context.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { beforeEach, describe, expect, it } from 'vitest'
import { TANSTACK_DEVTOOLS_STATE } from '../utils/storage'
import { getStateFromLocalStorage } from './devtools-context'

describe('getStateFromLocalStorage', () => {
beforeEach(() => {
localStorage.clear()
})
it('should return undefined when no data in localStorage', () => {
const state = getStateFromLocalStorage()
expect(state).toEqual(undefined)
})
it('should return parsed state from localStorage and not remove valid plugins', () => {
const mockState = {
activePlugins: ['plugin1'],
settings: {
theme: 'dark',
},
}
localStorage.setItem(TANSTACK_DEVTOOLS_STATE, JSON.stringify(mockState))
const state = getStateFromLocalStorage([
{
id: 'plugin1',
render: () => {},
name: 'Plugin 1',
},
])
expect(state).toEqual(mockState)
})
it('should filter out inactive plugins', () => {
const mockState = {
activePlugins: ['plugin1', 'plugin2'],
settings: {
theme: 'dark',
},
}
localStorage.setItem(TANSTACK_DEVTOOLS_STATE, JSON.stringify(mockState))
const plugins = [{ id: 'plugin1', render: () => {}, name: 'Plugin 1' }]
const state = getStateFromLocalStorage(plugins)
expect(state?.activePlugins).toEqual(['plugin1'])
})
it('should return empty plugin state if all active plugins are invalid', () => {
const mockState = {
activePlugins: ['plugin1', 'plugin2'],
settings: {
theme: 'dark',
},
}
localStorage.setItem(TANSTACK_DEVTOOLS_STATE, JSON.stringify(mockState))
const plugins = [{ id: 'plugin3', render: () => {}, name: 'Plugin 3' }]
const state = getStateFromLocalStorage(plugins)
expect(state?.activePlugins).toEqual([])
})
it('should handle invalid JSON in localStorage gracefully', () => {
localStorage.setItem(TANSTACK_DEVTOOLS_STATE, 'invalid json')
const state = getStateFromLocalStorage()
expect(state).toEqual(undefined)
})
})
28 changes: 26 additions & 2 deletions packages/devtools/src/context/devtools-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,35 @@ const generatePluginId = (plugin: TanStackDevtoolsPlugin, index: number) => {
return index.toString()
}

export function getStateFromLocalStorage(
plugins?: Array<TanStackDevtoolsPlugin>,
) {
const existingStateString = getStorageItem(TANSTACK_DEVTOOLS_STATE)
const existingState =
tryParseJson<DevtoolsStore['state']>(existingStateString)
const pluginIds =
plugins?.map((plugin, i) => generatePluginId(plugin, i)) || []
if (existingState?.activePlugins) {
const originalLength = existingState.activePlugins.length
// Filter out any active plugins that are no longer available
existingState.activePlugins = existingState.activePlugins.filter((id) =>
pluginIds.includes(id),
)

if (existingState.activePlugins.length !== originalLength) {
// If any active plugins were removed, update local storage
setStorageItem(TANSTACK_DEVTOOLS_STATE, JSON.stringify(existingState))
}
}

return existingState
}

const getExistingStateFromStorage = (
config?: TanStackDevtoolsConfig,
plugins?: Array<TanStackDevtoolsPlugin>,
) => {
const existingState = getStorageItem(TANSTACK_DEVTOOLS_STATE)
const existingState = getStateFromLocalStorage()
const settings = getSettings()

const state: DevtoolsStore = {
Expand All @@ -118,7 +142,7 @@ const getExistingStateFromStorage = (
}) || [],
state: {
...initialState.state,
...(existingState ? JSON.parse(existingState) : {}),
...existingState,
},
settings: {
...initialState.settings,
Expand Down
1 change: 1 addition & 0 deletions packages/devtools/src/context/devtools-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export const initialState: DevtoolsStore = {
urlFlag: 'tanstack-devtools',
theme:
typeof window !== 'undefined' &&
typeof window.matchMedia !== 'undefined' &&
window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light',
Expand Down
2 changes: 2 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading