import { hasPluginPermission , PluginPermission } from '@vue-devtools/shared-utils' ; import { Hooks , HookPayloads , Hookable , HookHandler } from '@vue/devtools-api' ; import { BackendContext } from './backend-context' ; import { Plugin } from './plugin' ; type Handler < TPayload > = HookHandler < TPayload , BackendContext > ; export interface HookHandlerData < THandlerPayload > { handler : Handler < THandlerPayload > ; plugin : Plugin ; } export class DevtoolsHookable implements Hookable < BackendContext > { private handlers : Partial < { [ eventType in Hooks ] : HookHandlerData < HookPayloads [ eventType ] > [ ] ; } > = { } ; private ctx : BackendContext ; private plugin : Plugin ; constructor ( ctx , plugin = null ) { this . ctx = ctx ; this . plugin = plugin ; } private hook < T extends Hooks > ( eventType , handler , pluginPermision = null ) { const handlers = ( this . handlers [ eventType ] = this . handlers [ eventType ] || [ ] ) as HookHandlerData < HookPayloads [ T ] > [ ] ; if ( this . plugin ) { const originalHandler = handler ; handler = ( ... args ) => { if ( ! hasPluginPermission ( this . plugin . descriptor . id , PluginPermission . ENABLED ) || ( pluginPermision && ! hasPluginPermission ( this . plugin . descriptor . id , pluginPermision ) ) ) return ; if ( ! this . plugin . descriptor . disableAppScope && this . ctx . currentAppRecord . options . app !== this . plugin . descriptor . app ) return ; if ( ! this . plugin . descriptor . disablePluginScope && ( args [ 0 ] as any ) . pluginId != null && ( args [ 0 ] as any ) . pluginId !== this . plugin . descriptor . id ) return ; return originalHandler ( ... args ) ; } ; } handlers . push ( { handler , plugin : this . ctx . currentPlugin , } ) ; } async callHandlers < T extends Hooks > ( eventType , payload , ctx ) { if ( this . handlers [ eventType ] ) { const handlers = this . handlers [ eventType ] as HookHandlerData < HookPayloads [ T ] > [ ] ; for ( let i = 0 ; i < handlers . length ; i ++ ) { const { handler , plugin } = handlers [ i ] ; try { await handler ( payload , ctx ) ; } catch ( e ) { console . error ( `An error occurred in hook ${ eventType }${ plugin ? ` registered by plugin ${ plugin . descriptor . id }` : '' }` ) ; console . error ( e ) ; } } } return payload ; } transformCall ( handler ) { this . hook ( Hooks . TRANSFORM_CALL , handler ) ; } getAppRecordName ( handler ) { this . hook ( Hooks . GET_APP_RECORD_NAME , handler ) ; } getAppRootInstance ( handler ) { this . hook ( Hooks . GET_APP_ROOT_INSTANCE , handler ) ; } registerApplication ( handler ) { this . hook ( Hooks . REGISTER_APPLICATION , handler ) ; } walkComponentTree ( handler ) { this . hook ( Hooks . WALK_COMPONENT_TREE , handler , PluginPermission . COMPONENTS ) ; } visitComponentTree ( handler ) { this . hook ( Hooks . VISIT_COMPONENT_TREE , handler , PluginPermission . COMPONENTS ) ; } walkComponentParents ( handler ) { this . hook ( Hooks . WALK_COMPONENT_PARENTS , handler , PluginPermission . COMPONENTS ) ; } inspectComponent ( handler ) { this . hook ( Hooks . INSPECT_COMPONENT , handler , PluginPermission . COMPONENTS ) ; } getComponentBounds ( handler ) { this . hook ( Hooks . GET_COMPONENT_BOUNDS , handler , PluginPermission . COMPONENTS ) ; } getComponentName ( handler ) { this . hook ( Hooks . GET_COMPONENT_NAME , handler , PluginPermission . COMPONENTS ) ; } getComponentInstances ( handler ) { this . hook ( Hooks . GET_COMPONENT_INSTANCES , handler , PluginPermission . COMPONENTS ) ; } getElementComponent ( handler ) { this . hook ( Hooks . GET_ELEMENT_COMPONENT , handler , PluginPermission . COMPONENTS ) ; } getComponentRootElements ( handler ) { this . hook ( Hooks . GET_COMPONENT_ROOT_ELEMENTS , handler , PluginPermission . COMPONENTS ) ; } editComponentState ( handler ) { this . hook ( Hooks . EDIT_COMPONENT_STATE , handler , PluginPermission . COMPONENTS ) ; } getComponentDevtoolsOptions ( handler ) { this . hook ( Hooks . GET_COMPONENT_DEVTOOLS_OPTIONS , handler , PluginPermission . COMPONENTS ) ; } getComponentRenderCode ( handler ) { this . hook ( Hooks . GET_COMPONENT_RENDER_CODE , handler , PluginPermission . COMPONENTS ) ; } inspectTimelineEvent ( handler ) { this . hook ( Hooks . INSPECT_TIMELINE_EVENT , handler , PluginPermission . TIMELINE ) ; } timelineCleared ( handler ) { this . hook ( Hooks . TIMELINE_CLEARED , handler , PluginPermission . TIMELINE ) ; } getInspectorTree ( handler ) { this . hook ( Hooks . GET_INSPECTOR_TREE , handler , PluginPermission . CUSTOM_INSPECTOR ) ; } getInspectorState ( handler ) { this . hook ( Hooks . GET_INSPECTOR_STATE , handler , PluginPermission . CUSTOM_INSPECTOR ) ; } editInspectorState ( handler ) { this . hook ( Hooks . EDIT_INSPECTOR_STATE , handler , PluginPermission . CUSTOM_INSPECTOR ) ; } setPluginSettings ( handler ) { this . hook ( Hooks . SET_PLUGIN_SETTINGS , handler ) ; } }