From: Eduardo San Martin Morote Date: Wed, 12 May 2021 22:43:39 +0000 (+0200) Subject: feat(devtools): display only relevant stores X-Git-Tag: v2.0.0-alpha.17~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=58f0af617b6516f69024cecb95ef8e0dd665104f;p=thirdparty%2Fvuejs%2Fpinia.git feat(devtools): display only relevant stores --- diff --git a/src/devtools/plugin.ts b/src/devtools/plugin.ts index 5e14011c..2716dc89 100644 --- a/src/devtools/plugin.ts +++ b/src/devtools/plugin.ts @@ -1,5 +1,5 @@ import { setupDevtoolsPlugin, TimelineEvent } from '@vue/devtools-api' -import { App } from 'vue' +import { App, ComponentPublicInstance } from 'vue' import { PiniaPluginContext, setActivePinia } from '../rootStore' import { Store, @@ -19,7 +19,7 @@ import { /** * Registered stores used for devtools. */ -const registeredStores = /*#__PURE__*/ new Set() +const registeredStores = /*#__PURE__*/ new Map() let isAlreadyInstalled: boolean | undefined // timeline can be paused when directly changing the state @@ -30,8 +30,11 @@ const MUTATIONS_LAYER_ID = 'pinia:mutations' const INSPECTOR_ID = 'pinia' export function addDevtools(app: App, store: Store) { - registeredStores.add(store) - componentStateTypes.push('🍍 ' + store.$id) + if (!registeredStores.has(store.$id)) { + registeredStores.set(store.$id, store) + componentStateTypes.push('🍍 ' + store.$id) + } + setupDevtoolsPlugin( { id: 'dev.esm.pinia', @@ -43,35 +46,6 @@ export function addDevtools(app: App, store: Store) { app, }, (api) => { - // watch(router.currentRoute, () => { - // // @ts-ignore - // api.notifyComponentUpdate() - // }) - - // TODO: only load stores used by the component? - api.on.inspectComponent((payload, ctx) => { - if (payload.instanceData) { - payload.instanceData.state.push({ - type: '🍍 ' + store.$id, - key: 'state', - editable: false, - value: store.$state, - }) - - if (store._getters?.length) { - payload.instanceData.state.push({ - type: '🍍 ' + store.$id, - key: 'getters', - editable: false, - value: store._getters.reduce((getters, key) => { - getters[key] = store[key] - return getters - }, {} as GettersTree), - }) - } - } - }) - if (!isAlreadyInstalled) { api.addTimelineLayer({ id: MUTATIONS_LAYER_ID, @@ -86,9 +60,44 @@ export function addDevtools(app: App, store: Store) { treeFilterPlaceholder: 'Search stores', }) + api.on.inspectComponent((payload, ctx) => { + if ( + ( + payload.componentInstance?.proxy as + | ComponentPublicInstance + | undefined + )?._pStores + ) { + const piniaStores = ( + payload.componentInstance.proxy as ComponentPublicInstance + )._pStores! + + Object.values(piniaStores).forEach((store) => { + payload.instanceData.state.push({ + type: '🍍 ' + store.$id, + key: 'state', + editable: false, + value: store.$state, + }) + + if (store._getters?.length) { + payload.instanceData.state.push({ + type: '🍍 ' + store.$id, + key: 'getters', + editable: false, + value: store._getters.reduce((getters, key) => { + getters[key] = store[key] + return getters + }, {} as GettersTree), + }) + } + }) + } + }) + api.on.getInspectorTree((payload) => { if (payload.app === app && payload.inspectorId === INSPECTOR_ID) { - const stores = Array.from(registeredStores) + const stores = Array.from(registeredStores.values()) payload.rootNodes = ( payload.filter @@ -104,7 +113,7 @@ export function addDevtools(app: App, store: Store) { api.on.getInspectorState((payload) => { if (payload.app === app && payload.inspectorId === INSPECTOR_ID) { - const store = Array.from(registeredStores).find( + const store = Array.from(registeredStores.values()).find( (store) => store.$id === payload.nodeId ) @@ -125,7 +134,7 @@ export function addDevtools(app: App, store: Store) { api.on.editInspectorState((payload) => { if (payload.app === app && payload.inspectorId === INSPECTOR_ID) { - const store = Array.from(registeredStores).find( + const store = Array.from(registeredStores.values()).find( (store) => store.$id === payload.nodeId ) diff --git a/src/store.ts b/src/store.ts index f927028f..87eae11f 100644 --- a/src/store.ts +++ b/src/store.ts @@ -380,11 +380,11 @@ export function defineStore< const { id, state, getters, actions } = options function useStore(pinia?: Pinia | null): Store { - const hasInstance = getCurrentInstance() + const currentInstance = getCurrentInstance() // only run provide when pinia hasn't been manually passed - const shouldProvide = hasInstance && !pinia + const shouldProvide = currentInstance && !pinia // avoid injecting if `useStore` when not possible - pinia = pinia || (hasInstance && inject(piniaSymbol)) + pinia = pinia || (currentInstance && inject(piniaSymbol)) if (pinia) setActivePinia(pinia) // TODO: worth warning on server if no piniaKey as it can leak data pinia = getActivePinia() @@ -398,13 +398,16 @@ export function defineStore< InjectionKey> ] | undefined + + let store: Store + if (!storeAndDescriptor) { storeAndDescriptor = initStore(id, state, pinia.state.value[id]) // annoying to type stores.set(id, storeAndDescriptor as any) - const store = buildStoreToUse< + store = buildStoreToUse< Id, S, G, @@ -424,28 +427,41 @@ export function defineStore< if (shouldProvide) { provide(storeAndDescriptor[2], store) } + } else { + store = + // null avoids the warning for not found injection key + (currentInstance && inject(storeAndDescriptor[2], null)) || + buildStoreToUse< + Id, + S, + G, + // @ts-expect-error: A without extends + A + >( + storeAndDescriptor[0], + storeAndDescriptor[1], + id, + getters as GettersTree | undefined, + actions as A | undefined, + options + ) + } - return store + // save stores in instances to access them devtools + if ( + __DEV__ && + __BROWSER__ && + IS_CLIENT && + currentInstance && + currentInstance.proxy + ) { + const vm = currentInstance.proxy + const cache = '_pStores' in vm ? vm._pStores! : (vm._pStores = {}) + // @ts-expect-error: still can't cast Store with generics to Store + cache[store.$id] = store } - return ( - // null avoids the warning for not found injection key - (hasInstance && inject(storeAndDescriptor[2], null)) || - buildStoreToUse< - Id, - S, - G, - // @ts-expect-error: A without extends - A - >( - storeAndDescriptor[0], - storeAndDescriptor[1], - id, - getters as GettersTree | undefined, - actions as A | undefined, - options - ) - ) + return store } // needed by map helpers