diff --git a/examples/devframe-files-inspector/tests/_utils.ts b/examples/devframe-files-inspector/tests/_utils.ts index 5336435..816c8c5 100644 --- a/examples/devframe-files-inspector/tests/_utils.ts +++ b/examples/devframe-files-inspector/tests/_utils.ts @@ -12,9 +12,9 @@ import { createHostContext, startHttpAndWs, } from 'devframe/node' -import { serveStaticHandler } from 'devframe/utils/serve-static' +import { mountStaticHandler } from 'devframe/utils/serve-static' import { getPort } from 'get-port-please' -import { createApp, eventHandler } from 'h3' +import { H3 } from 'h3' import { resolve } from 'pathe' import devframe from '../src/devframe' @@ -66,13 +66,13 @@ export async function startInspectorServer( const host = '127.0.0.1' const port = await getPort({ host, random: true }) - const app = createApp() + const app = new H3() const origin = `http://${host}:${port}` const h3Host = createH3DevToolsHost({ origin, appName: devframe.id, mount: (base, dir) => { - app.use(base, serveStaticHandler(dir)) + mountStaticHandler(app, base, dir) }, }) @@ -80,16 +80,8 @@ export async function startInspectorServer( await devframe.setup(ctx) const metaPath = `${basePath}${DEVTOOLS_CONNECTION_META_FILENAME}` - app.use( - metaPath, - eventHandler((event) => { - event.node.res.setHeader('Content-Type', 'application/json') - return event.node.res.end( - JSON.stringify({ backend: 'websocket', websocket: port }), - ) - }), - ) - app.use(basePath, serveStaticHandler(resolve(distDir))) + app.use(metaPath, () => ({ backend: 'websocket', websocket: port })) + mountStaticHandler(app, basePath, resolve(distDir)) const server = await startHttpAndWs({ context: ctx, diff --git a/examples/devframe-files-inspector/tests/static-serve.test.ts b/examples/devframe-files-inspector/tests/static-serve.test.ts index 8b6e5af..143fb83 100644 --- a/examples/devframe-files-inspector/tests/static-serve.test.ts +++ b/examples/devframe-files-inspector/tests/static-serve.test.ts @@ -3,9 +3,9 @@ import { createServer } from 'node:http' import os from 'node:os' import path from 'node:path' import { createBuild } from 'devframe/adapters/build' -import { serveStaticHandler } from 'devframe/utils/serve-static' +import { mountStaticHandler } from 'devframe/utils/serve-static' import { getPort } from 'get-port-please' -import { createApp, toNodeListener } from 'h3' +import { H3, toNodeHandler } from 'h3' import { afterAll, beforeAll, describe, expect, it } from 'vitest' import devframe from '../src/devframe' import { assertClientBuilt, makeFixtureCwd } from './_utils' @@ -20,9 +20,9 @@ interface StaticServer { async function startStaticServer(outDir: string, mountBase: string): Promise { const host = '127.0.0.1' const port = await getPort({ host, random: true }) - const app = createApp() - app.use(mountBase, serveStaticHandler(outDir)) - const httpServer = createServer(toNodeListener(app)) + const app = new H3() + mountStaticHandler(app, mountBase, outDir) + const httpServer = createServer(toNodeHandler(app)) await new Promise(r => httpServer.listen(port, host, () => r())) return { origin: `http://${host}:${port}`, diff --git a/examples/devframe-streaming-chat/tests/_utils.ts b/examples/devframe-streaming-chat/tests/_utils.ts index 6dbffad..54d48d9 100644 --- a/examples/devframe-streaming-chat/tests/_utils.ts +++ b/examples/devframe-streaming-chat/tests/_utils.ts @@ -11,9 +11,9 @@ import { createHostContext, startHttpAndWs, } from 'devframe/node' -import { serveStaticHandler } from 'devframe/utils/serve-static' +import { mountStaticHandler } from 'devframe/utils/serve-static' import { getPort } from 'get-port-please' -import { createApp, eventHandler } from 'h3' +import { H3 } from 'h3' import { resolve } from 'pathe' import devframe from '../src/devframe' @@ -39,30 +39,21 @@ export async function startStreamingChatServer(): Promise - app.use(base, serveStaticHandler(dir)), + mount: (base, dir) => mountStaticHandler(app, base, dir), }) const ctx = await createHostContext({ cwd: process.cwd(), mode: 'dev', host: h3Host }) await devframe.setup(ctx) const metaPath = `${basePath}${DEVTOOLS_CONNECTION_META_FILENAME}` - app.use( - metaPath, - eventHandler((event) => { - event.node.res.setHeader('Content-Type', 'application/json') - return event.node.res.end( - JSON.stringify({ backend: 'websocket', websocket: port }), - ) - }), - ) + app.use(metaPath, () => ({ backend: 'websocket', websocket: port })) if (existsSync(path.join(resolve(distDir), 'index.html'))) { - app.use(basePath, serveStaticHandler(resolve(distDir))) + mountStaticHandler(app, basePath, resolve(distDir)) } const server = await startHttpAndWs({ diff --git a/packages/devframe/package.json b/packages/devframe/package.json index 40e1210..4bc5770 100644 --- a/packages/devframe/package.json +++ b/packages/devframe/package.json @@ -1,7 +1,7 @@ { "name": "devframe", "type": "module", - "version": "0.1.22", + "version": "0.2.0", "description": "Framework for building generic DevTools", "author": "Anthony Fu ", "license": "MIT", diff --git a/packages/devframe/src/adapters/cli.ts b/packages/devframe/src/adapters/cli.ts index c3a0bab..7daba59 100644 --- a/packages/devframe/src/adapters/cli.ts +++ b/packages/devframe/src/adapters/cli.ts @@ -1,5 +1,5 @@ import type { CAC } from 'cac' -import type { App } from 'h3' +import type { H3 } from 'h3' import type { DevframeDefinition } from '../types/devframe' import process from 'node:process' import cac from 'cac' @@ -24,7 +24,7 @@ export interface CreateCliOptions { * Called once the dev server is listening. Use this to print a * startup banner or trigger side-effects that depend on the live URL. */ - onReady?: (info: { origin: string, port: number, app: App }) => void | Promise + onReady?: (info: { origin: string, port: number, app: H3 }) => void | Promise } export interface CliHandle { diff --git a/packages/devframe/src/adapters/dev.ts b/packages/devframe/src/adapters/dev.ts index 63c2702..90d4337 100644 --- a/packages/devframe/src/adapters/dev.ts +++ b/packages/devframe/src/adapters/dev.ts @@ -1,16 +1,15 @@ -import type { App } from 'h3' import type { StartedServer } from '../node/server' import type { DevframeDefinition, DevframeSetupInfo } from '../types/devframe' import process from 'node:process' import { getPort } from 'get-port-please' -import { createApp, eventHandler } from 'h3' +import { H3 } from 'h3' import { resolve } from 'pathe' import { DEVTOOLS_CONNECTION_META_FILENAME } from '../constants' import { createHostContext } from '../node/context' import { createH3DevToolsHost } from '../node/host-h3' import { startHttpAndWs } from '../node/server' import { open } from '../utils/open' -import { serveStaticHandler } from '../utils/serve-static' +import { mountStaticHandler } from '../utils/serve-static' import { normalizeBasePath, resolveBasePath } from './_shared' const DEFAULT_PORT = 9999 @@ -49,7 +48,7 @@ export interface CreateDevServerOptions { * middleware (auth, logging, extra static assets) before devframe's * own handlers. */ - app?: App + app?: H3 /** * Auto-open the browser. When `undefined` the resolution falls * through to `flags.open` (incl. string path) and finally @@ -61,7 +60,7 @@ export interface CreateDevServerOptions { * Called once the WS server is bound. Devframe stays headless * otherwise — wire this if you want a startup banner. */ - onReady?: (info: { origin: string, port: number, app: App }) => void | Promise + onReady?: (info: { origin: string, port: number, app: H3 }) => void | Promise } export interface ResolveDevServerPortOptions { @@ -123,14 +122,14 @@ export async function createDevServer( const port = options.port ?? await resolveDevServerPort(def, { host }) const flags = options.flags ?? {} const basePath = options.basePath ? normalizeBasePath(options.basePath) : resolveBasePath(def, 'standalone') - const app = options.app ?? createApp() + const app = options.app ?? new H3() const origin = `http://${host}:${port}` const h3Host = createH3DevToolsHost({ origin, appName: def.id, mount: (base, dir) => { - app.use(base, serveStaticHandler(dir)) + mountStaticHandler(app, base, dir) }, }) @@ -148,13 +147,10 @@ export async function createDevServer( // sits at the SPA root (next to index.html) so the deployed SPA can // discover it via a relative `./__connection.json` fetch. const connectionMetaPath = `${basePath}${DEVTOOLS_CONNECTION_META_FILENAME}` - app.use(connectionMetaPath, eventHandler((event) => { - event.node.res.setHeader('Content-Type', 'application/json') - return event.node.res.end(JSON.stringify({ backend: 'websocket', websocket: port })) - })) + app.use(connectionMetaPath, () => ({ backend: 'websocket', websocket: port })) if (distDir) - app.use(basePath, serveStaticHandler(resolve(distDir))) + mountStaticHandler(app, basePath, resolve(distDir)) return startHttpAndWs({ context: ctx, diff --git a/packages/devframe/src/node/server.ts b/packages/devframe/src/node/server.ts index 3f40c11..b32dfa8 100644 --- a/packages/devframe/src/node/server.ts +++ b/packages/devframe/src/node/server.ts @@ -1,13 +1,12 @@ import type { BirpcGroup } from 'birpc' import type { DevToolsNodeContext, DevToolsNodeRpcSession, DevToolsRpcClientFunctions, DevToolsRpcServerFunctions } from 'devframe/types' -import type { App } from 'h3' import type { WebSocketServer } from 'ws' import type { RpcFunctionsHost } from './host-functions' import { AsyncLocalStorage } from 'node:async_hooks' import { createServer } from 'node:http' import { createRpcServer } from 'devframe/rpc/server' import { attachWsRpcTransport } from 'devframe/rpc/transports/ws-server' -import { createApp, toNodeListener } from 'h3' +import { H3, toNodeHandler } from 'h3' import { WebSocketServer as WSServer } from 'ws' export interface StartHttpAndWsOptions { @@ -19,7 +18,7 @@ export interface StartHttpAndWsOptions { * when provided, callers can add their own routes (static handlers, * auth middleware, etc.) first. */ - app?: App + app?: H3 /** * When `false`, the RPC server is started without a trust handshake. * Intended for single-user localhost tools where an auth round-trip @@ -36,14 +35,14 @@ export interface StartHttpAndWsOptions { * handlers whose origin depends on the resolved port, or print their * own startup banner. Devframe does not print one itself. */ - onReady?: (info: { origin: string, port: number, app: App }) => void | Promise + onReady?: (info: { origin: string, port: number, app: H3 }) => void | Promise } export interface StartedServer { /** Listening origin, e.g. `http://localhost:9999`. */ origin: string port: number - app: App + app: H3 wss: WebSocketServer rpcGroup: BirpcGroup close: () => Promise @@ -57,8 +56,8 @@ export interface StartedServer { export async function startHttpAndWs(options: StartHttpAndWsOptions): Promise { const { context, port } = options const bindHost = options.host ?? 'localhost' - const app = options.app ?? createApp() - const httpServer = createServer(toNodeListener(app)) + const app = options.app ?? new H3() + const httpServer = createServer(toNodeHandler(app)) const wss = new WSServer({ server: httpServer }) const rpcHost = context.rpc as unknown as RpcFunctionsHost diff --git a/packages/devframe/src/utils/serve-static.test.ts b/packages/devframe/src/utils/serve-static.test.ts index 82b01a3..f2797be 100644 --- a/packages/devframe/src/utils/serve-static.test.ts +++ b/packages/devframe/src/utils/serve-static.test.ts @@ -4,7 +4,7 @@ import { mkdirSync, mkdtempSync, writeFileSync } from 'node:fs' import { createServer } from 'node:http' import { tmpdir } from 'node:os' import { join } from 'node:path' -import { createApp, toNodeListener } from 'h3' +import { H3, toNodeHandler } from 'h3' import { afterEach, describe, expect, it } from 'vitest' import { serveStaticHandler, serveStaticNodeMiddleware } from './serve-static' @@ -19,9 +19,9 @@ function makeTmp(prefix = 'devframe-serve-'): string { } async function startH3(dir: string, options?: ServeStaticOptions): Promise { - const app = createApp() + const app = new H3() app.use(serveStaticHandler(dir, options)) - const server = createServer(toNodeListener(app)) + const server = createServer(toNodeHandler(app)) await new Promise(r => server.listen(0, '127.0.0.1', r)) const port = (server.address() as AddressInfo).port return { diff --git a/packages/devframe/src/utils/serve-static.ts b/packages/devframe/src/utils/serve-static.ts index 7c49e2a..a555e90 100644 --- a/packages/devframe/src/utils/serve-static.ts +++ b/packages/devframe/src/utils/serve-static.ts @@ -1,8 +1,9 @@ -import type { EventHandler, EventHandlerRequest } from 'h3' +import type { EventHandler, H3 } from 'h3' import type { IncomingMessage, ServerResponse } from 'node:http' import { createReadStream } from 'node:fs' import { stat } from 'node:fs/promises' -import { defineEventHandler, sendStream, setResponseHeader, setResponseStatus } from 'h3' +import { Readable } from 'node:stream' +import { defineHandler, withBase } from 'h3' import { lookup } from 'mrmime' import { extname, join, normalize, resolve, sep } from 'pathe' @@ -105,11 +106,18 @@ function contentTypeFor(abs: string): string { return type } -function setStaticHeaders(res: ServerResponse, file: ResolvedFile): void { - res.setHeader('Content-Type', contentTypeFor(file.abs)) - res.setHeader('Content-Length', file.size) - res.setHeader('Last-Modified', file.mtime.toUTCString()) - res.setHeader('Cache-Control', 'no-store') +function staticHeadersFor(file: ResolvedFile): Record { + return { + 'Content-Type': contentTypeFor(file.abs), + 'Content-Length': String(file.size), + 'Last-Modified': file.mtime.toUTCString(), + 'Cache-Control': 'no-store', + } +} + +function applyStaticHeadersToNode(res: ServerResponse, file: ResolvedFile): void { + for (const [k, v] of Object.entries(staticHeadersFor(file))) + res.setHeader(k, v) } interface NormalizedOptions { @@ -136,31 +144,53 @@ function normalizeOptions(options: ServeStaticOptions | undefined): NormalizedOp export function serveStaticHandler( dir: string, options?: ServeStaticOptions, -): EventHandler { +): EventHandler { const absDir = resolve(dir) const opts = normalizeOptions(options) - return defineEventHandler(async (event) => { - const method = event.node.req.method + return defineHandler(async (event) => { + const method = event.req.method if (method !== 'GET' && method !== 'HEAD') { - setResponseStatus(event, 405) - setResponseHeader(event, 'Allow', 'GET, HEAD') + event.res.status = 405 + event.res.headers.set('Allow', 'GET, HEAD') return '' } - const url = event.node.req.url ?? '/' - const file = await resolveTarget(absDir, url, opts.indexNames, opts.single) + const file = await resolveTarget(absDir, event.url.pathname, opts.indexNames, opts.single) if (!file) { - setResponseStatus(event, 404) + event.res.status = 404 return '' } - setStaticHeaders(event.node.res, file) - if (method === 'HEAD') { - event.node.res.end() + for (const [k, v] of Object.entries(staticHeadersFor(file))) + event.res.headers.set(k, v) + if (method === 'HEAD') return '' - } - return sendStream(event, createReadStream(file.abs)) + return Readable.toWeb(createReadStream(file.abs)) as ReadableStream }) } +/** + * Mount {@link serveStaticHandler} on an h3 app at `base`, handling the + * route pattern and prefix-stripping required by h3 v2. + * + * h3 v2's `app.use(base, handler)` only matches the exact `base` path and + * does not strip the prefix from `event.url.pathname`. Static serving + * needs both subpath matching (`/base/**`) and the URL stripped so the + * file resolver sees paths relative to `dir` — this helper bundles both. + */ +export function mountStaticHandler( + app: H3, + base: string, + dir: string, + options?: ServeStaticOptions, +): void { + const trimmed = base.replace(/\/$/, '') + const handler = serveStaticHandler(dir, options) + if (trimmed === '') { + app.use('/**', handler) + return + } + app.use(`${trimmed}/**`, withBase(trimmed, handler)) +} + /** * Connect/Express-style Node middleware variant of {@link serveStaticHandler}. * @@ -198,7 +228,7 @@ export function serveStaticNodeMiddleware( res.end() return } - setStaticHeaders(res, file) + applyStaticHeadersToNode(res, file) if (method === 'HEAD') { res.end() return diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 53dcaad..df10a72 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -47,8 +47,8 @@ catalogs: specifier: ^3.2.0 version: 3.2.0 h3: - specifier: ^1.15.11 - version: 1.15.11 + specifier: 2.0.1-rc.22 + version: 2.0.1-rc.22 immer: specifier: ^11.1.8 version: 11.1.8 @@ -258,7 +258,7 @@ importers: version: 3.2.0 h3: specifier: catalog:deps - version: 1.15.11 + version: 2.0.1-rc.22 vite: specifier: catalog:build version: 8.0.11(@types/node@25.6.2)(esbuild@0.27.7)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.4) @@ -286,7 +286,7 @@ importers: version: 3.2.0 h3: specifier: catalog:deps - version: 1.15.11 + version: 2.0.1-rc.22 vite: specifier: catalog:build version: 8.0.11(@types/node@25.6.2)(esbuild@0.27.7)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.8.4) @@ -310,7 +310,7 @@ importers: version: 7.0.0 h3: specifier: catalog:deps - version: 1.15.11 + version: 2.0.1-rc.22 logs-sdk: specifier: catalog:deps version: 0.0.6 @@ -2113,9 +2113,6 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - cookie-es@1.2.3: - resolution: {integrity: sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==} - cookie-signature@1.2.2: resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} engines: {node: '>=6.6.0'} @@ -2141,9 +2138,6 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} - crossws@0.3.5: - resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==} - css-select@5.2.2: resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} @@ -2851,8 +2845,15 @@ packages: resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} engines: {node: '>=6.0'} - h3@1.15.11: - resolution: {integrity: sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==} + h3@2.0.1-rc.22: + resolution: {integrity: sha512-Esv0DMIuPkCTSWCA0vO73vcTqwzH1wjSrAO1TXNu/K3up1sZHa9EKMapbmxCDYBeymC3fVTk4qxp7ogQWQ+KgA==} + engines: {node: '>=20.11.1'} + hasBin: true + peerDependencies: + crossws: ^0.4.1 + peerDependenciesMeta: + crossws: + optional: true hachure-fill@0.5.2: resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==} @@ -2951,9 +2952,6 @@ packages: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} - iron-webcrypto@1.2.1: - resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} - is-builtin-module@5.0.0: resolution: {integrity: sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA==} engines: {node: '>=18.20'} @@ -3399,9 +3397,6 @@ packages: node-html-parser@6.1.13: resolution: {integrity: sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==} - node-mock-http@1.0.4: - resolution: {integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==} - node-releases@2.0.38: resolution: {integrity: sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==} @@ -3576,9 +3571,6 @@ packages: quansync@1.0.0: resolution: {integrity: sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==} - radix3@1.1.2: - resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} - range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} @@ -3667,6 +3659,9 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + rou3@0.8.1: + resolution: {integrity: sha512-ePa+XGk00/3HuCqrEnK3LxJW7I0SdNg6EFzKUJG73hMAdDcOUC/i/aSz7LSDwLrGr33kal/rqOGydzwl6U7zBA==} + roughjs@4.6.6: resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==} @@ -3782,6 +3777,11 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + srvx@0.11.15: + resolution: {integrity: sha512-iXsux0UcOjdvs0LCMa2Ws3WwcDUozA3JN3BquNXkaFPP7TpRqgunKdEgoZ/uwb1J6xaYHfxtz9Twlh6yzwM6Tg==} + engines: {node: '>=20.16.0'} + hasBin: true + stack-trace@1.0.0: resolution: {integrity: sha512-H6D7134xi6qONvh7ZHKgviXf+rd3vhGBSvebPZCaUkd8zvQ+7PtDw6CljPTe4cXWNf2IKZGNqw6VJXSb9IgBpA==} engines: {node: '>=20.0.0'} @@ -3954,9 +3954,6 @@ packages: unconfig@7.5.0: resolution: {integrity: sha512-oi8Qy2JV4D3UQ0PsopR28CzdQ3S/5A1zwsUwp/rosSbfhJ5z7b90bIyTwi/F7hCLD4SGcZVjDzd4XoUQcEanvA==} - uncrypto@0.1.3: - resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} - unctx@2.5.0: resolution: {integrity: sha512-p+Rz9x0R7X+CYDkT+Xg8/GhpcShTlU8n+cf9OtOEf7zEQsNcCZO1dPKNRDqvUTaq+P32PMMkxWHwfrxkqfqAYg==} @@ -5891,8 +5888,6 @@ snapshots: convert-source-map@2.0.0: {} - cookie-es@1.2.3: {} - cookie-signature@1.2.2: {} cookie@0.7.2: {} @@ -5920,10 +5915,6 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - crossws@0.3.5: - dependencies: - uncrypto: 0.1.3 - css-select@5.2.2: dependencies: boolbase: 1.0.0 @@ -6731,17 +6722,10 @@ snapshots: section-matter: 1.0.0 strip-bom-string: 1.0.0 - h3@1.15.11: + h3@2.0.1-rc.22: dependencies: - cookie-es: 1.2.3 - crossws: 0.3.5 - defu: 6.1.7 - destr: 2.0.5 - iron-webcrypto: 1.2.1 - node-mock-http: 1.0.4 - radix3: 1.1.2 - ufo: 1.6.4 - uncrypto: 0.1.3 + rou3: 0.8.1 + srvx: 0.11.15 hachure-fill@0.5.2: {} @@ -6823,8 +6807,6 @@ snapshots: ipaddr.js@1.9.1: {} - iron-webcrypto@1.2.1: {} - is-builtin-module@5.0.0: dependencies: builtin-modules: 5.2.0 @@ -7431,8 +7413,6 @@ snapshots: css-select: 5.2.2 he: 1.2.0 - node-mock-http@1.0.4: {} - node-releases@2.0.38: {} non-layered-tidy-tree-layout@2.0.2: @@ -7614,8 +7594,6 @@ snapshots: quansync@1.0.0: {} - radix3@1.1.2: {} - range-parser@1.2.1: {} raw-body@3.0.2: @@ -7754,6 +7732,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.60.3 fsevents: 2.3.3 + rou3@0.8.1: {} + roughjs@4.6.6: dependencies: hachure-fill: 0.5.2 @@ -7904,6 +7884,8 @@ snapshots: sprintf-js@1.0.3: {} + srvx@0.11.15: {} + stack-trace@1.0.0: {} stackback@0.0.2: {} @@ -8054,8 +8036,6 @@ snapshots: quansync: 1.0.0 unconfig-core: 7.5.0 - uncrypto@0.1.3: {} - unctx@2.5.0: dependencies: acorn: 8.16.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 9551b19..7659554 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -34,7 +34,7 @@ catalogs: birpc: ^4.0.0 cac: ^7.0.0 get-port-please: ^3.2.0 - h3: ^1.15.11 + h3: 2.0.1-rc.22 immer: ^11.1.8 launch-editor: ^2.13.2 logs-sdk: ^0.0.6 diff --git a/tests/__snapshots__/tsnapi/devframe/adapters/cli.snapshot.d.ts b/tests/__snapshots__/tsnapi/devframe/adapters/cli.snapshot.d.ts index e7329cf..e941e7a 100644 --- a/tests/__snapshots__/tsnapi/devframe/adapters/cli.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/devframe/adapters/cli.snapshot.d.ts @@ -12,7 +12,7 @@ export interface CreateCliOptions { onReady?: (_: { origin: string; port: number; - app: App; + app: H3; }) => void | Promise; } // #endregion diff --git a/tests/__snapshots__/tsnapi/devframe/adapters/dev.snapshot.d.ts b/tests/__snapshots__/tsnapi/devframe/adapters/dev.snapshot.d.ts index 1678628..623185f 100644 --- a/tests/__snapshots__/tsnapi/devframe/adapters/dev.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/devframe/adapters/dev.snapshot.d.ts @@ -8,12 +8,12 @@ export interface CreateDevServerOptions { flags?: Record; distDir?: string; basePath?: string; - app?: App; + app?: H3; openBrowser?: boolean | string; onReady?: (_: { origin: string; port: number; - app: App; + app: H3; }) => void | Promise; } export interface ResolveDevServerPortOptions { diff --git a/tests/__snapshots__/tsnapi/devframe/utils/serve-static.snapshot.d.ts b/tests/__snapshots__/tsnapi/devframe/utils/serve-static.snapshot.d.ts index f7dc079..8924025 100644 --- a/tests/__snapshots__/tsnapi/devframe/utils/serve-static.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/devframe/utils/serve-static.snapshot.d.ts @@ -9,6 +9,7 @@ export interface ServeStaticOptions { // #endregion // #region Functions -export declare function serveStaticHandler(_: string, _?: ServeStaticOptions): EventHandler; +export declare function mountStaticHandler(_: H3, _: string, _: string, _?: ServeStaticOptions): void; +export declare function serveStaticHandler(_: string, _?: ServeStaticOptions): EventHandler; export declare function serveStaticNodeMiddleware(_: string, _?: ServeStaticOptions): (_: IncomingMessage, _: ServerResponse, _?: (_?: Error) => void) => void; // #endregion \ No newline at end of file diff --git a/tests/__snapshots__/tsnapi/devframe/utils/serve-static.snapshot.js b/tests/__snapshots__/tsnapi/devframe/utils/serve-static.snapshot.js index 6d015db..f55fc86 100644 --- a/tests/__snapshots__/tsnapi/devframe/utils/serve-static.snapshot.js +++ b/tests/__snapshots__/tsnapi/devframe/utils/serve-static.snapshot.js @@ -2,6 +2,7 @@ * Generated by tsnapi — public API snapshot of `devframe/utils/serve-static` */ // #region Functions +export function mountStaticHandler(_, _, _, _) {} export function serveStaticHandler(_, _) {} export function serveStaticNodeMiddleware(_, _) {} // #endregion \ No newline at end of file