Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions knip.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,24 @@
"src/{client,node,rpc,inject,engine,registry}/index.ts"
]
},
"plugins/inspect": {
// The lockstep assets package is referenced only as a runtime string
// (`${pkg.name}--assets` in `cli.distDir`), never imported, so knip
// can't see the dev-only workspace link that makes it resolvable in
// the monorepo. Repeat the `plugins/*` entry glob (a workspace config
// replaces, not merges, it).
"entry": [
"src/{index,cli,vite,constants,types}.ts",
"src/{client,node,rpc,inject,engine,registry}/index.ts"
],
"ignoreDependencies": ["@devframes/plugin-inspect--assets"]
},
"plugins/inspect/assets-pkg": {
// Assets-only package: no source, just a prebuilt `dist` produced by
// the sibling plugin's Vite build.
"entry": [],
"project": []
},
"plugins/a11y": {
// `storybook-solidjs-vite` (not an official `@storybook/*` framework
// package) doesn't match knip's Storybook plugin trigger, so it never
Expand Down
30 changes: 30 additions & 0 deletions plugins/inspect/assets-pkg/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "@devframes/plugin-inspect--assets",
"type": "module",
"version": "0.9.0-beta.4",
"description": "Prebuilt browser assets (SPA) for @devframes/plugin-inspect, served on demand through devframe's remote-assets back-proxy.",
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
"license": "MIT",
"homepage": "https://github.com/devframes/devframe#readme",
"repository": {
"directory": "plugins/inspect/assets-pkg",
"type": "git",
"url": "git+https://github.com/devframes/devframe.git"
},
"bugs": "https://github.com/devframes/devframe/issues",
"keywords": [
"devframe",
"devframe-plugin",
"devtools",
"client-assets"
],
"exports": {
"./package.json": "./package.json"
},
"files": [
"dist"
],
"scripts": {
"prepack": "pnpm --filter @devframes/plugin-inspect run build"
}
}
1 change: 1 addition & 0 deletions plugins/inspect/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
"devDependencies": {
"@antfu/design": "catalog:frontend",
"@devframes/hub": "workspace:*",
"@devframes/plugin-inspect--assets": "workspace:*",
"@iconify-json/ph": "catalog:frontend",
"@standard-schema/spec": "catalog:deps",
"@storybook/addon-docs": "catalog:storybook",
Expand Down
20 changes: 12 additions & 8 deletions plugins/inspect/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import type { DevframeDefinition } from 'devframe'
import { existsSync } from 'node:fs'
import { fileURLToPath } from 'node:url'
import type { DevframeDefinition, RemoteAssets } from 'devframe'
import { defineDevframe } from 'devframe'
import pkg from '../package.json' with { type: 'json' }
import { setupInspect } from './node/index'

/** Default devframe id — drives the hosted mount path `/__<id>/`. */
const DEFAULT_ID = 'devframes_plugin_inspect'

// The Vue SPA is built (by Vite) into `dist/spa`. From both the source
// entry (`src/index.ts`, via the workspace alias) and the published
// entry (`dist/index.mjs`), `../dist/spa` resolves to `<pkg>/dist/spa`.
const distDir = fileURLToPath(new URL('../dist/spa', import.meta.url))
// The Vue SPA ships in the lockstep-versioned `@devframes/plugin-inspect--assets`
// package rather than inside this (slim) node package. `resolveFrom` lets a
// locally installed copy (a workspace link in this monorepo, or an explicit
// `npm install` for air-gapped setups) be served with zero network; otherwise
// the assets stream on demand through devframe's caching CDN back-proxy.
const distDir: RemoteAssets = {
package: `${pkg.name}--assets`,
version: pkg.version,
resolveFrom: import.meta.url,
}

export interface InspectDevframeOptions {
/** Override the devframe id (and default CLI command / mount path). */
Expand Down Expand Up @@ -58,7 +62,7 @@ export function createInspectDevframe(options: InspectDevframeOptions = {}): Dev
cli: {
command: id,
port: options.port ?? 9012,
distDir: existsSync(distDir) ? distDir : undefined,
distDir,
// Gate the standalone server by default; `maybeOpenBrowser` folds the
// current OTP into the `--open` URL so the tab lands already trusted.
// Hosted adapters (Vite/hub) supply their own auth layer and ignore this.
Expand Down
5 changes: 4 additions & 1 deletion plugins/inspect/src/spa/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ export default defineConfig({
// SFCs instead of esbuild pre-bundling them.
optimizeDeps: { exclude: ['@antfu/design'] },
build: {
outDir: fileURLToPath(new URL('../../dist/spa', import.meta.url)),
// Emit into the sibling `@devframes/plugin-inspect--assets` package, which
// ships these assets to npm; the node package stays slim and serves them
// on demand through devframe's remote-assets back-proxy.
outDir: fileURLToPath(new URL('../../assets-pkg/dist', import.meta.url)),
emptyOutDir: true,
},
})
29 changes: 23 additions & 6 deletions plugins/inspect/test/_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { DevframeHubContext } from '@devframes/hub/node'
import type { DevframeNodeContext } from 'devframe'
import type { StartedServer } from 'devframe/internal'
import { existsSync } from 'node:fs'
import os from 'node:os'
import path from 'node:path'
import process from 'node:process'
import { createHubContext } from '@devframes/hub/node'
Expand All @@ -10,22 +11,38 @@ import { DEVFRAME_CONNECTION_META_FILENAME } from 'devframe/constants'
import { createH3DevframeHost } from 'devframe/internal'
import { createHostContext } from 'devframe/node'
import { resolveBasePath } from 'devframe/node/hub-internals'
import { resolveStaticAssetsSource } from 'devframe/utils/remote-assets'
import { mountStaticHandler } from 'devframe/utils/serve-static'
import { getPort } from 'get-port-please'
import { H3 } from 'h3'
import { serveTestContext } from '../../../tests/helpers/serve-test-context'

const SPA_DIST = inspectDevframe.cli!.distDir!
/**
* Resolve the inspector's SPA to a local directory. Its `distDir` is a
* remote-assets declaration; in this monorepo the lockstep
* `@devframes/plugin-inspect--assets` package is workspace-linked, so
* resolution short-circuits to its built `dist`. A store (rather than a
* string) means that build hasn't run.
*/
function localSpaDir(): string {
const resolved = resolveStaticAssetsSource(inspectDevframe.cli!.distDir!, path.join(os.tmpdir(), 'devframes_plugin_inspect-test'))
if (typeof resolved !== 'string') {
throw new TypeError(
'[devframes_plugin_inspect] client SPA missing — run `pnpm -C plugins/inspect run build` first.',
)
}
return resolved
}

/**
* Assert the Vue SPA has been built. The dev-server and static-build
* tests mount / copy `dist/spa`; a missing build produces a loud, fixable
* failure rather than an opaque 404.
* tests mount / copy the client SPA; a missing build produces a loud,
* fixable failure rather than an opaque 404.
*/
export function assertSpaBuilt(): void {
if (!existsSync(path.join(SPA_DIST, 'index.html'))) {
if (!existsSync(path.join(localSpaDir(), 'index.html'))) {
throw new Error(
'[devframes_plugin_inspect] dist/spa missing — run `pnpm -C plugins/inspect run build` first.',
'[devframes_plugin_inspect] client SPA missing — run `pnpm -C plugins/inspect run build` first.',
)
}
}
Expand All @@ -51,7 +68,7 @@ interface BootOptions {
* context exercises the no-hub path (empty list, thrown diagnostic).
*/
async function boot(options: BootOptions): Promise<InspectorServer> {
const distDir = inspectDevframe.cli!.distDir!
const distDir = localSpaDir()
const basePath = resolveBasePath(inspectDevframe, 'standalone')
const host = '127.0.0.1'
const port = await getPort({ host, random: true })
Expand Down
5 changes: 5 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ trustPolicyExclude:
packages:
- packages/*
- plugins/*
- plugins/*/assets-pkg
- examples/*
- storybook
- docs
Expand Down
2 changes: 1 addition & 1 deletion turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
"@devframes/plugin-inspect#build": {
"outputLogs": "new-only",
"dependsOn": ["devframe#build", "@devframes/vite#build"],
"outputs": ["dist/**"]
"outputs": ["dist/**", "assets-pkg/dist/**"]
},
"@devframes/plugin-og#build": {
"outputLogs": "new-only",
Expand Down
Loading