From 167373c0770180680c497f8dbba175b0e4b1563e Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Wed, 21 Aug 2024 15:25:09 +0200 Subject: [PATCH] feat(kit): introduce `host-client` utility --- docs/content/2.module/0.guide.md | 2 +- docs/content/2.module/1.utils-kit.md | 35 ++++++++++++- packages/devtools-kit/host-client.d.ts | 1 + packages/devtools-kit/host-client.mjs | 1 + packages/devtools-kit/package.json | 4 ++ .../devtools-kit/src/runtime/host-client.ts | 50 +++++++++++++++++++ 6 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 packages/devtools-kit/host-client.d.ts create mode 100644 packages/devtools-kit/host-client.mjs create mode 100644 packages/devtools-kit/src/runtime/host-client.ts diff --git a/docs/content/2.module/0.guide.md b/docs/content/2.module/0.guide.md index 8c3b646ad..917351728 100644 --- a/docs/content/2.module/0.guide.md +++ b/docs/content/2.module/0.guide.md @@ -153,7 +153,7 @@ export default defineNuxtModule({ }) ``` -And on the client side, you can do: +And on the embedded iframe client side, you can do: ```ts import { onDevtoolsClientConnected } from '@nuxt/devtools-kit/iframe-client' diff --git a/docs/content/2.module/1.utils-kit.md b/docs/content/2.module/1.utils-kit.md index 2d2f1f7d8..d5b626b7b 100644 --- a/docs/content/2.module/1.utils-kit.md +++ b/docs/content/2.module/1.utils-kit.md @@ -109,7 +109,7 @@ It will return a ref of `NuxtDevtoolsIframeClient` object that are intially `nul `NuxtDevtoolsIframeClient` contains two properties: -- `host`: APIs to communicate with the client app +- `host`: APIs to communicate with the main app in browser - `devtools`: APIs to communicate with the devtools `host` can be undefined when devtools are accessed standalone or from a different origin. @@ -134,3 +134,36 @@ onDevtoolsClientConnected(async (client) => { // ... }) ``` + +## `@nuxt/devtools-kit/host-client` + +When you have iframe for your devtools view, sometimes you need to communicate with the devtools host (the main app in browser) with a runtime plugin. You can use `@nuxt/devtools-kit/host-client` to do that. + +### `useDevtoolsHostClient()` + +It will return a ref of `NuxtDevtoolsHostClient` object that are intially `null` and will be updated when the host is initialized by NuxtDevtools. + +```ts +import { useDevtoolsHostClient } from '@nuxt/devtools-kit/host-client' + +export default defineNuxtPlugin({ + name: 'my-module:devtools', + setup(nuxtApp) { + const devtoolsHost = useDevtoolsHostClient() + + // ... + } +}) +``` + +### `onDevtoolsHostClientConnected()` + +Similiar to `useDevtoolsHostClient()` but as a callback style: + +```ts +import { onDevtoolsHostClientConnected } from '@nuxt/devtools-kit/host-client' + +onDevtoolsHostClientConnected(async (host) => { + +}) +``` diff --git a/packages/devtools-kit/host-client.d.ts b/packages/devtools-kit/host-client.d.ts new file mode 100644 index 000000000..269d571bb --- /dev/null +++ b/packages/devtools-kit/host-client.d.ts @@ -0,0 +1 @@ +export * from './dist/runtime/host-client' diff --git a/packages/devtools-kit/host-client.mjs b/packages/devtools-kit/host-client.mjs new file mode 100644 index 000000000..32b20aede --- /dev/null +++ b/packages/devtools-kit/host-client.mjs @@ -0,0 +1 @@ +export * from './dist/runtime/host-client.mjs' diff --git a/packages/devtools-kit/package.json b/packages/devtools-kit/package.json index 7a1dffcc5..fa9988eeb 100644 --- a/packages/devtools-kit/package.json +++ b/packages/devtools-kit/package.json @@ -23,6 +23,10 @@ "./iframe-client": { "types": "./iframe-client.d.ts", "import": "./iframe-client.mjs" + }, + "./host-client": { + "types": "./host-client.d.ts", + "import": "./host-client.mjs" } }, "main": "./dist/index.cjs", diff --git a/packages/devtools-kit/src/runtime/host-client.ts b/packages/devtools-kit/src/runtime/host-client.ts new file mode 100644 index 000000000..a4ab8c85f --- /dev/null +++ b/packages/devtools-kit/src/runtime/host-client.ts @@ -0,0 +1,50 @@ +import type { Ref } from 'vue' +import { shallowRef } from 'vue' +import type { NuxtDevtoolsHostClient } from '../types' + +let clientRef: Ref | undefined +const fns = [] as ((client: NuxtDevtoolsHostClient) => void)[] + +export function onDevtoolsHostClientConnected(fn: (client: NuxtDevtoolsHostClient) => void) { + fns.push(fn) + + if (typeof window === 'undefined') + return + + // eslint-disable-next-line ts/ban-ts-comment + // @ts-ignore injection + if (window.__NUXT_DEVTOOLS_HOST__) { + // eslint-disable-next-line ts/ban-ts-comment + // @ts-ignore injection + fns.forEach(fn => fn(window.__NUXT_DEVTOOLS_HOST__)) + } + + Object.defineProperty(window, '__NUXT_DEVTOOLS_HOST__', { + set(value) { + if (value) + fns.forEach(fn => fn(value)) + }, + get() { + return clientRef!.value + }, + configurable: true, + }) + + return () => { + fns.splice(fns.indexOf(fn), 1) + } +} + +export function useDevtoolsHostClient() { + if (!clientRef) { + clientRef = shallowRef() + + onDevtoolsHostClientConnected(setup) + } + + function setup(client: NuxtDevtoolsHostClient) { + clientRef!.value = client + } + + return clientRef +}