From: Eduardo San Martin Morote Date: Mon, 10 May 2021 20:42:18 +0000 (+0200) Subject: feat: wip devtools action X-Git-Tag: v2.0.0-alpha.17~39 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=af9cd5c2b86e1edfc62dcdcc75f1a6646ac06a26;p=thirdparty%2Fvuejs%2Fpinia.git feat: wip devtools action --- diff --git a/src/devtools.ts b/src/devtools.ts index 9886a8fe..f97f6810 100644 --- a/src/devtools.ts +++ b/src/devtools.ts @@ -4,13 +4,14 @@ import { setupDevtoolsPlugin, TimelineEvent, } from '@vue/devtools-api' -import { App, DebuggerEvent } from 'vue' -import { PiniaPluginContext } from './rootStore' +import { App, computed, DebuggerEvent, reactive, toRefs } from 'vue' +import { PiniaPluginContext, setActivePinia } from './rootStore' import { GenericStore, GettersTree, MutationType, StateTree, + StoreWithActions, _Method, } from './types' @@ -174,9 +175,24 @@ export function addDevtools(app: App, store: GenericStore) { api.sendInspectorState(INSPECTOR_ID) } + // TODO: implement + store.$before?.('action', ({ name, handler, args, context }) => { + context._actionId = actionId++ + }) + + store.$after?.('patch', ({ context }) => { + // TODO: use context._actionId as the group + }) + + store.$after?.('action', ({ context, result }) => { + // TODO: use context._actionId as the group + // result.then.catch + }) + store.$subscribe(({ events, type }, state) => { // rootStore.state[store.id] = state console.log('subscribe devtools', events) + console.log('subscribe with active', activeAction) api.notifyComponentUpdate() api.sendInspectorState(INSPECTOR_ID) @@ -293,6 +309,11 @@ function formatMutationType(type: MutationType): string { } } +let actionId = 0 +let activeAction = -1 + +const actionMap = new WeakMap, number>() + /** * pinia.use(devtoolsPlugin) */ @@ -302,28 +323,63 @@ export function devtoolsPlugin< G extends GettersTree = GettersTree, A = Record >({ app, store, options, pinia }: PiniaPluginContext) { - // const wrappedActions: StoreWithActions = {} as StoreWithActions - // const actions: A = options.actions || ({} as any) + const wrappedActions: StoreWithActions = {} as StoreWithActions + const actions: A = options.actions || ({} as any) // custom patch method - // for (const actionName in actions) { - // wrappedActions[actionName] = function () { - // setActivePinia(pinia) - // const patchedStore = reactive({ - // ...toRefs(store), - // $patch() { - // // TODO: should call subscribe listeners with a group ID - // store.$patch.apply(null, arguments as any) - // }, - // }) - // // @ts-expect-error: not recognizing it's a _Method for some reason - // return actions[actionName].apply( - // patchedStore, - // (arguments as unknown) as any[] - // ) - // } as StoreWithActions[typeof actionName] - // } + for (const actionName in actions) { + wrappedActions[actionName] = function () { + setActivePinia(pinia) + const keys = Object.keys(options.state?.() || {}) + const _actionId = actionId++ + const patchedStore = reactive({ + ...toRefs(store), + // $patch() { + // // TODO: should call subscribe listeners with a group ID + // store.$patch.apply(null, arguments as any) + // }, + ...keys.reduce((stateProperties, stateName) => { + // @ts-expect-error + stateProperties[stateName] = computed({ + get() { + activeAction = _actionId + return store[stateName] + }, + set(value) { + activeAction = _actionId + // @ts-expect-error + return (store[stateName] = value) + }, + }) + return stateProperties + }, {}), + _actionId, + }) + console.log('beforeAction', _actionId) + const promise = Promise.resolve( + // @ts-expect-error: not recognizing it's a _Method for some reason + actions[actionName].apply(patchedStore, (arguments as unknown) as any[]) + ) + .then(() => { + // TODO: finish and mark as completed + }) + .catch((err) => { + // TODO: finish and mark as failed + }) + .finally(() => { + activeAction = -1 + }) + + return promise + } as StoreWithActions[typeof actionName] + } addDevtools(app, store) + + return { ...wrappedActions } } + +/** + * Another idea: wrap the getter/setter of all state properties to call setActiveAction. This way, we can directly use it in $subscribe to attach it to its action + */ diff --git a/src/store.ts b/src/store.ts index ecb4fd96..6e6b9db2 100644 --- a/src/store.ts +++ b/src/store.ts @@ -74,7 +74,7 @@ function computedFromState( } const state = rootStateRef.value[id] for (const key in state) { - // @ts-ignore: the key matches + // @ts-expect-error: the key matches reactiveObject[key] = computed({ get: () => rootStateRef.value[id][key as keyof T], set: (value) => (rootStateRef.value[id][key as keyof T] = value),