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
2 changes: 1 addition & 1 deletion alias.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const alias = {
'@devframes/json-render-ui/hub': r('json-render-ui/src/hub.ts'),
'@devframes/json-render-ui/spa': r('json-render-ui/src/spa.ts'),
'@devframes/json-render-ui': r('json-render-ui/src/index.ts'),
'json-render/dashboard': fileURLToPath(new URL('./examples/json-render/src/dashboard.ts', import.meta.url)),
'json-render/dashboard': fileURLToPath(new URL('./examples/json-render/src/node/dashboard.ts', import.meta.url)),
'@devframes/plugin-code-server/node': p('code-server/src/node/setup.ts'),
'@devframes/plugin-code-server/constants': p('code-server/src/node/constants.ts'),
'@devframes/plugin-code-server/types': p('code-server/src/node/types.ts'),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// Re-exports the shared devframe class-helper builders (see
// `design/design.ts`) so this surface stays in lockstep with every other.
export * from '../../../../design/design'
export * from '../../../design/design'
50 changes: 50 additions & 0 deletions examples/files-inspector/app/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import type { Server } from 'node:http'
import type { Plugin } from 'vite'
import { fileURLToPath } from 'node:url'
import preact from '@preact/preset-vite'
import { initDevframe } from 'devframe/initiate'
import { resolveBasePath } from 'devframe/internal'
import UnoCSS from 'unocss/vite'
import { defineConfig } from 'vite'
import { alias } from '../../../alias'
import devframe from '../src/node/index.ts'

/**
* Serve-only plugin that bridges the node side (RPC + WebSocket +
* `__connection.json`) onto Vite's dev server under the devframe base path,
* mounted as a post middleware so Vite serves the HMR SPA first and the
* devframe host only answers the routes it owns. Inert during `vite build`.
*/
function filesInspectorDevBridge(): Plugin {
return {
name: 'files-inspector-dev-bridge',
apply: 'serve',
configureServer(server) {
const instance = initDevframe(devframe, {
base: resolveBasePath(devframe, 'hosted'),
distDir: false,
server: server.httpServer as Server,
auth: false,
})
return () => server.middlewares.use(instance.nodeMiddleware)
},
}
}

/**
* `base: './'` for the build keeps the mount path portable: the same output
* works whether devframe serves it at `/` (standalone) or under a base path
* (mounted in a hub). In `vite dev` the panel is served under the devframe
* base path so its `document.baseURI` matches production, and the dev bridge
* bridges the node side there with HMR.
*/
export default defineConfig(({ command }) => ({
base: command === 'serve' ? resolveBasePath(devframe, 'hosted') : './',
root: fileURLToPath(new URL('.', import.meta.url)),
resolve: { alias },
plugins: [UnoCSS(), preact(), filesInspectorDevBridge()],
build: {
outDir: fileURLToPath(new URL('../dist/client', import.meta.url)),
emptyOutDir: true,
},
}))
2 changes: 1 addition & 1 deletion examples/files-inspector/bin.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env node
import process from 'node:process'
import { createCac } from 'devframe/adapters/cac'
import devframe from './src/devframe.ts'
import devframe from './src/node/index.ts'

async function main() {
// Serve the agent surface at `/__mcp` and register for `devframe connect`
Expand Down
8 changes: 5 additions & 3 deletions examples/files-inspector/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
"private": true,
"description": "Devframe demo that lists files in the working directory over RPC across the dev and build surfaces.",
"homepage": "https://github.com/devframes/devframe/tree/main/examples/files-inspector",
"main": "src/devframe.ts",
"main": "src/node/index.ts",
"bin": {
"files-inspector": "./bin.mjs"
},
"scripts": {
"build": "vite build --config src/client/vite.config.ts",
"dev": "node bin.mjs",
"build": "vite build --config app/vite.config.ts",
"build:app": "vite build --config app/vite.config.ts",
"dev": "vite --config app/vite.config.ts --host",
"play": "pnpm run build && node playgrounds/server.mjs",
"cli:build": "node bin.mjs build --out-dir dist/static",
"test": "vitest run",
"typecheck": "tsc --noEmit"
Expand Down
65 changes: 65 additions & 0 deletions examples/files-inspector/playgrounds/server.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env node
/**
* Playground host for the Files Inspector: boots the built tool and serves its
* SPA panel + live WebSocket RPC off one origin, mirroring how a hub would
* mount it under the devframe base path.
*
* node playgrounds/server.mjs → serves `dist/client` with live RPC
*/
import { existsSync } from 'node:fs'
import { createServer } from 'node:http'
import process from 'node:process'
import { fileURLToPath } from 'node:url'
import { initDevframe } from 'devframe/initiate'
import { getPort } from 'devframe/utils/get-port'
import { H3, toNodeHandler } from 'h3'
import { resolve } from 'pathe'
import devframe from '../src/node/index.ts'

const HERE = fileURLToPath(new URL('.', import.meta.url))
const ROOT = resolve(HERE, '..')

const basePath = devframe.basePath
const panelDir = resolve(ROOT, 'dist/client')

function requireBuilt(file, hint) {
if (!existsSync(file)) {
console.error(`\n[files-inspector playground] missing ${file}\n → run \`${hint}\` first.\n`)
process.exit(1)
}
}

function banner(origin) {
process.stdout.write(
`\n Files Inspector demo: dev (live WebSocket RPC)\n`
+ ` ▸ panel: ${origin}${basePath}\n\n`,
)
}

async function main() {
requireBuilt(resolve(panelDir, 'index.html'), 'pnpm -C examples/files-inspector build')

const bindHost = '0.0.0.0'
const port = await getPort({ host: bindHost, port: 9876 })
const origin = `http://localhost:${port}`

const app = new H3()
const server = createServer(toNodeHandler(app))
const instance = initDevframe(devframe, {
base: basePath,
distDir: panelDir,
app,
server,
host: bindHost,
origin,
auth: false,
})
await new Promise(r => server.listen(port, bindHost, r))
await instance.ready
banner(origin)
}

main().catch((error) => {
console.error(error)
process.exit(1)
})
16 changes: 0 additions & 16 deletions examples/files-inspector/src/client/vite.config.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { fileURLToPath } from 'node:url'
import { defineDevframe } from 'devframe'
import pkg from '../package.json' with { type: 'json' }
import pkg from '../../package.json' with { type: 'json' }
import { NAMESPACE, serverFunctions } from './rpc/index.ts'

const BASE_PATH = '/__devframe-files-inspector/'
const distDir = fileURLToPath(new URL('../dist/client', import.meta.url))
const distDir = fileURLToPath(new URL('../../dist/client', import.meta.url))

export default defineDevframe({
id: 'example:files-inspector',
Expand Down Expand Up @@ -39,7 +39,7 @@ export default defineDevframe({
description: 'Locate the Files Inspector\'s documentation on disk. Call before answering questions about how this tool works, then read the returned files directly.',
safety: 'read',
handler: () => ({
readmePath: fileURLToPath(new URL('../README.md', import.meta.url)),
readmePath: fileURLToPath(new URL('../../README.md', import.meta.url)),
hint: 'Read the file at readmePath with your own file tools; do not rely on training-data knowledge of this example.',
}),
})
Expand Down
2 changes: 1 addition & 1 deletion examples/files-inspector/tests/_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { getPort } from 'get-port-please'
import { H3 } from 'h3'
import { resolve } from 'pathe'
import { serveTestContext } from '../../../tests/helpers/serve-test-context'
import devframe from '../src/devframe'
import devframe from '../src/node/index'

const HERE = fileURLToPath(new URL('.', import.meta.url))
const CLIENT_DIST = resolve(HERE, '../dist/client')
Expand Down
2 changes: 1 addition & 1 deletion examples/files-inspector/tests/static-build.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
DEVFRAME_RPC_DUMP_MANIFEST_FILENAME,
} from 'devframe/constants'
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
import devframe from '../src/devframe'
import devframe from '../src/node/index'
import { assertClientBuilt, makeFixtureCwd } from './_utils'

interface DumpManifest {
Expand Down
2 changes: 1 addition & 1 deletion examples/files-inspector/tests/static-serve.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { mountStaticHandler } from 'devframe/utils/serve-static'
import { getPort } from 'get-port-please'
import { H3, toNodeHandler } from 'h3'
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
import devframe from '../src/devframe'
import devframe from '../src/node/index'
import { assertClientBuilt, makeFixtureCwd } from './_utils'

interface StaticServer {
Expand Down
2 changes: 1 addition & 1 deletion examples/files-inspector/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@
"esModuleInterop": true,
"isolatedDeclarations": false
},
"include": ["src", "tests", "bin.mjs"]
"include": ["src", "app", "tests", "playgrounds", "bin.mjs"]
}
2 changes: 1 addition & 1 deletion examples/json-render/bin.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env node
import process from 'node:process'
import { createCac } from 'devframe/adapters/cac'
import devframe from './src/devframe.ts'
import devframe from './src/node/index.ts'

async function main() {
const cli = createCac(devframe)
Expand Down
6 changes: 3 additions & 3 deletions examples/json-render/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
"description": "Standalone devframe that serves a JSON view spec with live state and an action bridge.",
"homepage": "https://github.com/devframes/devframe/tree/main/examples/json-render",
"exports": {
".": "./src/devframe.ts",
"./dashboard": "./src/dashboard.ts"
".": "./src/node/index.ts",
"./dashboard": "./src/node/dashboard.ts"
},
"main": "src/devframe.ts",
"main": "src/node/index.ts",
"bin": {
"json-render": "./bin.mjs"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createJsonRenderDevframe } from '@devframes/json-render-ui/spa'
import pkg from '../package.json' with { type: 'json' }
import pkg from '../../package.json' with { type: 'json' }
import { createDashboardView } from './dashboard.ts'

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'

import type { EnvSnapshot } from '../../../devframe'
import type { EnvSnapshot } from '../../../src/node/index'
import { useCallback, useEffect, useState } from 'react'
import { card, input as inputClass } from '../design'
import { useRpc } from './connect'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'

import type { MemorySnapshot } from '../../../devframe'
import type { MemorySnapshot } from '../../../src/node/index'
import { useCallback, useEffect, useState } from 'react'
import { button, card } from '../design'
import { useRpc } from './connect'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'

import type { SystemInfo } from '../../../devframe'
import type { SystemInfo } from '../../../src/node/index'
import { useEffect, useState } from 'react'
import { card } from '../design'
import { useRpc } from './connect'
Expand Down
27 changes: 27 additions & 0 deletions examples/next-runtime-snapshot/app/next.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { PHASE_DEVELOPMENT_SERVER } from 'next/constants.js'

/**
* The static-export options (`output: 'export'`, a relative `assetPrefix`, and
* `trailingSlash`) exist so `next build` emits a self-contained SPA that mounts
* at any base. They are wrong for `next dev`: a relative `assetPrefix` breaks
* the dev client runtime's chunk base, so the page never hydrates (no
* interactivity, and the RPC client never connects). Apply them only for the
* production build so `pnpm dev:client` hydrates normally.
*
* @type {(phase: string) => import('next').NextConfig}
*/
export default (phase) => {
const isDev = phase === PHASE_DEVELOPMENT_SERVER
return {
...(isDev ? {} : { output: 'export', assetPrefix: '.', trailingSlash: true }),
images: { unoptimized: true },
/**
* The workspace tsconfig uses path aliases that point at devframe's
* source so source-level edits HMR cleanly. Next.js's incremental TS
* check can't follow workspace project references through those aliases
* and ends up type-checking unrelated source. Defer typechecking to the
* workspace's own `tsc -b` (`pnpm typecheck`), which honors references.
*/
typescript: { ignoreBuildErrors: true },
}
}
25 changes: 25 additions & 0 deletions examples/next-runtime-snapshot/app/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"incremental": true,
"jsx": "preserve",
"lib": ["ESNext", "DOM"],
"module": "ESNext",
"moduleResolution": "Bundler",
"allowJs": true,
"noEmit": true,
"esModuleInterop": true,
"isolatedDeclarations": false,
"plugins": [{ "name": "next" }]
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
],
"exclude": [
"node_modules",
".next",
"out"
]
}
2 changes: 1 addition & 1 deletion examples/next-runtime-snapshot/bin.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env node
import process from 'node:process'
import { createCac } from 'devframe/adapters/cac'
import devframe from './src/devframe.ts'
import devframe from './src/node/index.ts'

async function main() {
const cli = createCac(devframe)
Expand Down
7 changes: 4 additions & 3 deletions examples/next-runtime-snapshot/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
"private": true,
"description": "Devframe demo exposing the host Node runtime snapshot through a Next.js App Router SPA.",
"homepage": "https://github.com/devframes/devframe/tree/main/examples/next-runtime-snapshot",
"main": "src/devframe.ts",
"main": "src/node/index.ts",
"bin": {
"next-runtime-snapshot": "./bin.mjs"
},
"scripts": {
"build": "next build src/client && node scripts/build-spa.mjs",
"build": "next build app && node scripts/build-spa.mjs",
"cli:build": "node bin.mjs build --out-dir dist/static",
"dev": "node bin.mjs",
"next:dev": "next dev src/client",
"dev:client": "next dev app",
"play": "pnpm run build && node playgrounds/server.mjs",
"test": "vitest run",
"typecheck": "tsc --noEmit"
},
Expand Down
Loading
Loading