From a53a894223ec6658a879af596296b9db410b867b Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 16 Jun 2024 22:25:03 +0800 Subject: [PATCH 1/3] feat(api): introduce inspectSetupState --- packages/devtools-api/package.json | 6 ++- packages/devtools-api/src/constants.ts | 8 ++++ packages/devtools-api/src/index.ts | 2 + packages/devtools-api/src/state/index.ts | 39 +++++++++++++++++++ .../src/core/component/state/process.ts | 17 ++++++-- packages/playground/basic/src/main.ts | 5 +++ .../basic/src/pages/InspectCustomState.ts | 28 +++++++++++++ packages/shared/src/constants.ts | 3 ++ pnpm-lock.yaml | 6 +++ 9 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 packages/devtools-api/src/constants.ts create mode 100644 packages/devtools-api/src/state/index.ts create mode 100644 packages/playground/basic/src/pages/InspectCustomState.ts diff --git a/packages/devtools-api/package.json b/packages/devtools-api/package.json index 5366dfa03..d490b0580 100644 --- a/packages/devtools-api/package.json +++ b/packages/devtools-api/package.json @@ -25,8 +25,12 @@ "prepare:type": "tsup --dts-only", "stub": "tsup --watch --onSuccess 'tsup --dts-only'" }, + "peerDependencies": { + "vue": ">=3.0.0" + }, "dependencies": { - "@vue/devtools-kit": "workspace:^" + "@vue/devtools-kit": "workspace:^", + "@vue/devtools-shared": "workspace:*" }, "publishConfig": { "tag": "next" diff --git a/packages/devtools-api/src/constants.ts b/packages/devtools-api/src/constants.ts new file mode 100644 index 000000000..41f6614fa --- /dev/null +++ b/packages/devtools-api/src/constants.ts @@ -0,0 +1,8 @@ +/** + * - https://vitejs.dev/guide/env-and-mode.html#node-env-and-modes + * - https://webpack.js.org/guides/production/#specify-the-mode + * - https://www.rspack.dev/config/mode + * + * Modern bundlers are support NODE_ENV environment variable out-of the box, so we can use it to determine the environment. + */ +export const __DEV__ = typeof process !== 'undefined' && process.env.NODE_ENV !== 'production' diff --git a/packages/devtools-api/src/index.ts b/packages/devtools-api/src/index.ts index f20639d3b..4d5c98deb 100644 --- a/packages/devtools-api/src/index.ts +++ b/packages/devtools-api/src/index.ts @@ -13,3 +13,5 @@ export type { CustomCommand, CustomTab, } from '@vue/devtools-kit' + +export * from './state' diff --git a/packages/devtools-api/src/state/index.ts b/packages/devtools-api/src/state/index.ts new file mode 100644 index 000000000..def32f788 --- /dev/null +++ b/packages/devtools-api/src/state/index.ts @@ -0,0 +1,39 @@ +import { getCurrentInstance } from 'vue' +import { DEVTOOLS_API_INSPECT_STATE_KEY } from '@vue/devtools-shared' +import { __DEV__ } from '../constants' + +/** + * Register a setup state on an instance, which will be displayed in the "Component" tab. + * This is very useful when using `defineComponent` with setup returning the render function. + * + * @param state any states you want to see in the vue devtool + * + * @example + * const Component = defineComponent({ + * setup() { + * const name = ref('foo') + * inspectSetupState({ + * name, + * }) + * return h('div', name.value) + * }, + * }) + * + */ +export const inspectSetupState = __DEV__ + ? function inspectSetupState(state: Record) { + const currentInstance = getCurrentInstance() + if (!currentInstance) { + throw new Error('[Vue Devtools API]: Please using `inspectSetupState()` inside `setup()`.') + } + // @ts-expect-error internal api + currentInstance.devtoolsRawSetupState ??= {} + // @ts-expect-error internal api + const devtoolsRawSetupState = currentInstance.devtoolsRawSetupState + Object.assign(devtoolsRawSetupState, state) + devtoolsRawSetupState[DEVTOOLS_API_INSPECT_STATE_KEY] ??= [] + devtoolsRawSetupState[DEVTOOLS_API_INSPECT_STATE_KEY].push(...Object.keys(state)) + } + : (state: Record) => { + // do nothing + } diff --git a/packages/devtools-kit/src/core/component/state/process.ts b/packages/devtools-kit/src/core/component/state/process.ts index 4e4804ea1..10a11f523 100644 --- a/packages/devtools-kit/src/core/component/state/process.ts +++ b/packages/devtools-kit/src/core/component/state/process.ts @@ -1,4 +1,4 @@ -import { camelize } from '@vue/devtools-shared' +import { DEVTOOLS_API_INSPECT_STATE_KEY, camelize } from '@vue/devtools-shared' import type { VueAppInstance } from '../../../types' import type { InspectorState } from '../types' import { returnError } from '../utils' @@ -132,10 +132,21 @@ function getStateTypeAndName(info: ReturnType) { function processSetupState(instance: VueAppInstance) { const raw = instance.devtoolsRawSetupState || {} - return Object.keys(instance.setupState) + const customInspectStateKeys = raw[DEVTOOLS_API_INSPECT_STATE_KEY] || [] + + // Shallow clone to prevent mutating the original + const setupState = { + ...instance.setupState, + ...customInspectStateKeys.reduce((map, key) => { + map[key] = raw[key] + return map + }, {}), + } + + return Object.keys(setupState) .filter(key => !vueBuiltins.has(key) && key.split(/(?=[A-Z])/)[0] !== 'use') .map((key) => { - const value = returnError(() => toRaw(instance.setupState[key])) as unknown as { + const value = returnError(() => toRaw(setupState[key])) as unknown as { render: Function __asyncLoader: Function diff --git a/packages/playground/basic/src/main.ts b/packages/playground/basic/src/main.ts index 85983036f..4852e254e 100644 --- a/packages/playground/basic/src/main.ts +++ b/packages/playground/basic/src/main.ts @@ -54,6 +54,11 @@ const routes: RouteRecordRaw[] = [ component: () => import('./pages/CircularState.vue'), name: 'circular-state', }, + { + path: '/inspect-custom-state', + component: () => import('./pages/InspectCustomState'), + name: 'inspect-custom-state', + }, ] const router = createRouter({ diff --git a/packages/playground/basic/src/pages/InspectCustomState.ts b/packages/playground/basic/src/pages/InspectCustomState.ts new file mode 100644 index 000000000..690d995fd --- /dev/null +++ b/packages/playground/basic/src/pages/InspectCustomState.ts @@ -0,0 +1,28 @@ +import { defineComponent, h, reactive, ref } from 'vue' +import { inspectSetupState } from '@vue/devtools-api' + +export default defineComponent({ + name: 'InspectCustomState', + setup() { + const count = ref(1) + const state = reactive({ + name: 'foo', + age: 10, + }) + + inspectSetupState({ + count, + state, + }) + + return () => h('div', [ + h('button', { + onClick() { + count.value++ + }, + }, `count: ${count.value}`), + h('div', `name: ${state.name}`), + h('div', `age: ${state.age}`), + ]) + }, +}) diff --git a/packages/shared/src/constants.ts b/packages/shared/src/constants.ts index 2a62c99c8..9d38bf6ad 100644 --- a/packages/shared/src/constants.ts +++ b/packages/shared/src/constants.ts @@ -2,3 +2,6 @@ export const VIEW_MODE_STORAGE_KEY = '__vue-devtools-view-mode__' export const VITE_PLUGIN_DETECTED_STORAGE_KEY = '__vue-devtools-vite-plugin-detected__' export const VITE_PLUGIN_CLIENT_URL_STORAGE_KEY = '__vue-devtools-vite-plugin-client-url__' export const BROADCAST_CHANNEL_NAME = '__vue-devtools-broadcast-channel__' + +// [Devtools API] +export const DEVTOOLS_API_INSPECT_STATE_KEY = '__vue-devtools-inspect-custom-setup-state' diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index df7e4cbbb..c4ef3f875 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -375,6 +375,12 @@ importers: '@vue/devtools-kit': specifier: workspace:^ version: link:../devtools-kit + '@vue/devtools-shared': + specifier: workspace:* + version: link:../shared + vue: + specifier: '>=3.0.0' + version: 3.4.27(typescript@5.4.5) packages/devtools-kit: dependencies: From e4bae1e43a35bea29149a67b1d0682e28071c8cf Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 4 Sep 2024 09:50:52 +0800 Subject: [PATCH 2/3] fix: lockfile --- pnpm-lock.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4c5cd5fca..f07e56e27 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -386,7 +386,7 @@ importers: version: link:../shared vue: specifier: '>=3.0.0' - version: 3.4.27(typescript@5.4.5) + version: 3.4.38(typescript@5.5.4) packages/devtools-kit: dependencies: From 0b6464b3262b58f41dced597a38e65e196ed7b14 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Wed, 4 Sep 2024 01:53:22 +0000 Subject: [PATCH 3/3] [autofix.ci] apply automated fixes --- packages/playground/basic/src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/playground/basic/src/main.ts b/packages/playground/basic/src/main.ts index 86ad3382d..9ecdbcd6f 100644 --- a/packages/playground/basic/src/main.ts +++ b/packages/playground/basic/src/main.ts @@ -70,7 +70,7 @@ const routes: RouteRecordRaw[] = [ path: '/inspect-custom-state', component: () => import('./pages/InspectCustomState'), name: 'inspect-custom-state', - } + }, ] const router = createRouter({