From 09867f3543ba057536909af4cd686398a6ccca8f Mon Sep 17 00:00:00 2001 From: neverland Date: Thu, 12 Mar 2026 12:59:01 +0800 Subject: [PATCH 1/2] refactor: migrate types to use rspack/core definitions --- package.json | 2 +- pnpm-lock.yaml | 6 +-- src/config.ts | 5 +-- src/server.ts | 97 ++++++++++++++++++++++------------------- src/types.ts | 114 ++++++++----------------------------------------- 5 files changed, 75 insertions(+), 149 deletions(-) diff --git a/package.json b/package.json index dfdb059..619064a 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,6 @@ }, "dependencies": { "@types/connect-history-api-fallback": "^1.5.4", - "@types/serve-static": "^2.2.0", "@types/ws": "^8.18.1", "chokidar": "^5.0.0", "connect-history-api-fallback": "^2.0.0", @@ -67,6 +66,7 @@ "@types/mime-types": "3.0.1", "@types/node": "^24.12.0", "@types/node-forge": "^1.3.14", + "@types/serve-static": "^2.2.0", "@types/trusted-types": "^2.0.7", "@types/ws": "8.18.1", "cross-env": "^10.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index afa832a..99056ed 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,9 +11,6 @@ importers: '@types/connect-history-api-fallback': specifier: ^1.5.4 version: 1.5.4 - '@types/serve-static': - specifier: ^2.2.0 - version: 2.2.0 '@types/ws': specifier: ^8.18.1 version: 8.18.1 @@ -69,6 +66,9 @@ importers: '@types/node-forge': specifier: ^1.3.14 version: 1.3.14 + '@types/serve-static': + specifier: ^2.2.0 + version: 2.2.0 '@types/trusted-types': specifier: ^2.0.7 version: 2.0.7 diff --git a/src/config.ts b/src/config.ts index 51837fb..25310d3 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,6 +1,5 @@ -import type { DevServerOpenOptions } from '@rspack/core'; +import type { DevServerOpenOptions, DevServerClient } from '@rspack/core'; import type { - ClientConfiguration, ConnectHistoryApiFallbackOptions, DevServer, NormalizedStatic, @@ -20,7 +19,7 @@ export interface ResolvedDevServer extends DevServer { liveReload: boolean; webSocketServer: false | WebSocketServerConfiguration; proxy: Required; - client: ClientConfiguration; + client: DevServerClient; allowedHosts: 'auto' | string[] | 'all'; compress: boolean; historyApiFallback: false | ConnectHistoryApiFallbackOptions; diff --git a/src/server.ts b/src/server.ts index a0c543c..7e54feb 100644 --- a/src/server.ts +++ b/src/server.ts @@ -14,7 +14,25 @@ import * as os from 'node:os'; import * as path from 'node:path'; import * as url from 'node:url'; import * as util from 'node:util'; +import type { App } from 'open'; import compression from 'http-compression'; +import type { + HandleFunction, + NextFunction, + NextHandleFunction, + SimpleHandleFunction, +} from 'connect-next'; +import type { + DevServerHost, + DevServerHeaders, + DevServerClient, + DevServerStaticItem, + DevServerMiddlewareHandler, + DevServerWebSocketURL, + DevServerProxyConfigArray, + DevServerProxyConfigArrayItem, + DevServerStatic, +} from '@rspack/core'; import ipaddr from 'ipaddr.js'; import { getPort } from './getPort'; import { WebsocketServer } from './servers/WebsocketServer'; @@ -22,7 +40,6 @@ import type { AddressInfo, BasicApplication, BasicServer, - ClientConfiguration, ClientConnection, Compiler, ConnectHistoryApiFallbackOptions, @@ -32,37 +49,26 @@ import type { EXPECTED_ANY, FSWatcher, HTTPServer, - HandleFunction, - Headers, - Host, IPv6, IncomingMessage, LiteralUnion, Middleware, - MiddlewareHandler, MiddlewareObject, MultiCompiler, MultiStats, NetworkInterfaceInfo, - NextFunction, - NextHandleFunction, NormalizedOpen, NormalizedStatic, Open, - OpenApp, OverlayMessageOptions, Port, - ProxyConfigArray, - ProxyConfigArrayItem, Request, RequestHandler, Response, ServerConfiguration, ServerOptions, ServerType, - SimpleHandleFunction, Socket, - Static, Stats, StatsCompilation, StatsOptions, @@ -71,7 +77,6 @@ import type { WebSocketServer, WebSocketServerConfiguration, WebSocketServerImplementation, - WebSocketURL, } from './types'; import type { ConnectApplication } from './types'; @@ -83,7 +88,7 @@ export interface Configuration< S extends BasicServer = HTTPServer, > { ipc?: boolean | string; - host?: Host; + host?: DevServerHost; port?: Port; hot?: boolean | 'only'; liveReload?: boolean; @@ -92,24 +97,24 @@ export interface Configuration< allowedHosts?: LiteralUnion<'auto' | 'all', string> | string[]; historyApiFallback?: boolean | ConnectHistoryApiFallbackOptions; watchFiles?: string | string[] | WatchFiles | Array; - static?: boolean | string | Static | Array; + static?: DevServerStatic; server?: ServerType | ServerConfiguration; app?: () => Promise; webSocketServer?: | boolean | LiteralUnion<'ws', string> | WebSocketServerConfiguration; - proxy?: ProxyConfigArray; + proxy?: DevServerProxyConfigArray; open?: boolean | string | Open | Array; setupExitSignals?: boolean; - client?: boolean | ClientConfiguration; + client?: boolean | DevServerClient; headers?: - | Headers + | DevServerHeaders | (( req: Request, res: Response, context: DevMiddlewareContext | undefined, - ) => Headers); + ) => DevServerHeaders); onListening?: (devServer: Server) => void; setupMiddlewares?: ( middlewares: Middleware[], @@ -315,7 +320,7 @@ class Server< } } - static async getHostname(hostname: Host) { + static async getHostname(hostname: DevServerHost) { if (hostname === 'local-ip') { return ( Server.findIp('v4', false) || Server.findIp('v6', false) || '0.0.0.0' @@ -399,8 +404,8 @@ class Server< let webSocketURLStr = ''; if (this.options.webSocketServer) { - const webSocketURL = (this.options.client as ClientConfiguration) - .webSocketURL as WebSocketURL; + const webSocketURL = (this.options.client as DevServerClient) + .webSocketURL as DevServerWebSocketURL; const webSocketServer = this.options.webSocketServer as { type: WebSocketServerConfiguration['type']; options: NonNullable; @@ -493,7 +498,7 @@ class Server< searchParams.set('pathname', pathname); - const client = this.options.client as ClientConfiguration; + const client = this.options.client as DevServerClient; if (typeof client.logging !== 'undefined') { searchParams.set('logging', client.logging); @@ -650,7 +655,7 @@ class Server< }; }; const getStaticItem = ( - optionsForStatic?: string | Static, + optionsForStatic?: string | DevServerStaticItem, ): NormalizedStatic => { const getDefaultStaticOptions = () => { return { @@ -1209,10 +1214,10 @@ class Server< if (this.options.client) { if ( - typeof (this.options.client as ClientConfiguration) - .webSocketTransport !== 'undefined' + typeof (this.options.client as DevServerClient).webSocketTransport !== + 'undefined' ) { - clientTransport = (this.options.client as ClientConfiguration) + clientTransport = (this.options.client as DevServerClient) .webSocketTransport; } else if (isKnownWebSocketServerImplementation) { clientTransport = ( @@ -1434,7 +1439,7 @@ class Server< if ( this.options.client && - (this.options.client as ClientConfiguration).progress + (this.options.client as DevServerClient).progress ) { this.#setupProgressPlugin(); } @@ -1644,7 +1649,7 @@ class Server< middlewares.push({ name: 'webpack-dev-middleware', - middleware: this.middleware as MiddlewareHandler, + middleware: this.middleware as DevServerMiddlewareHandler, }); middlewares.push({ @@ -1771,7 +1776,7 @@ class Server< const { createProxyMiddleware } = require('http-proxy-middleware'); const getProxyMiddleware = ( - proxyConfig: ProxyConfigArrayItem, + proxyConfig: DevServerProxyConfigArrayItem, ): RequestHandler | undefined => { const { context, ...proxyOptions } = proxyConfig; const pathFilter = proxyOptions.pathFilter ?? context; @@ -1874,7 +1879,7 @@ class Server< middlewares.push({ name: 'webpack-dev-middleware', - middleware: this.middleware as MiddlewareHandler, + middleware: this.middleware as DevServerMiddlewareHandler, }); } @@ -1923,7 +1928,7 @@ class Server< // it is able to handle '/index.html' request after redirect middlewares.push({ name: 'webpack-dev-middleware', - middleware: this.middleware as MiddlewareHandler, + middleware: this.middleware as DevServerMiddlewareHandler, }); if (staticOptions.length > 0) { @@ -1982,7 +1987,7 @@ class Server< if (typeof (item as MiddlewareObject).middleware === 'undefined') { (item as MiddlewareObject).middleware = - lazyInitDevMiddleware() as unknown as MiddlewareHandler; + lazyInitDevMiddleware() as unknown as DevServerMiddlewareHandler; } } } @@ -2087,31 +2092,31 @@ class Server< if ( this.options.client && - (this.options.client as ClientConfiguration).progress + (this.options.client as DevServerClient).progress ) { this.sendMessage( [client], 'progress', - (this.options.client as ClientConfiguration).progress, + (this.options.client as DevServerClient).progress, ); } if ( this.options.client && - (this.options.client as ClientConfiguration).reconnect + (this.options.client as DevServerClient).reconnect ) { this.sendMessage( [client], 'reconnect', - (this.options.client as ClientConfiguration).reconnect, + (this.options.client as DevServerClient).reconnect, ); } if ( this.options.client && - (this.options.client as ClientConfiguration).overlay + (this.options.client as DevServerClient).overlay ) { - const overlayConfig = (this.options.client as ClientConfiguration) + const overlayConfig = (this.options.client as DevServerClient) .overlay; this.sendMessage( @@ -2163,7 +2168,7 @@ class Server< // Type assertion needed: OpenOptions is compatible at runtime but TypeScript can't verify // the type match between our type definition and the ES module's type in CommonJS context return open(openTarget, item.options as EXPECTED_ANY).catch(() => { - const app = item.options.app as OpenApp | undefined; + const app = item.options.app as App; this.logger.warn( `Unable to open "${openTarget}" page${ app @@ -2342,12 +2347,12 @@ class Server< // Also allow if `client.webSocketURL.hostname` provided if ( this.options.client && - typeof (this.options.client as ClientConfiguration).webSocketURL !== + typeof (this.options.client as DevServerClient).webSocketURL !== 'undefined' ) { return ( - ((this.options.client as ClientConfiguration).webSocketURL as - | WebSocketURL['hostname'] + ((this.options.client as DevServerClient).webSocketURL as + | DevServerWebSocketURL['hostname'] | undefined) === value ); } @@ -2589,10 +2594,12 @@ class Server< }); }); } else { - this.options.host = await Server.getHostname(this.options.host as Host); + this.options.host = await Server.getHostname( + this.options.host as DevServerHost, + ); this.options.port = await Server.getFreePort( this.options.port as string, - this.options.host as Host, + this.options.host as DevServerHost, ); } diff --git a/src/types.ts b/src/types.ts index ed2e95d..4aa826e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -4,19 +4,21 @@ import type { ServerResponse, } from 'node:http'; import type { ServerOptions } from 'node:https'; -import type { DevServerOpenOptions } from '@rspack/core'; +import type { + DevServerMiddlewareHandler, + DevServerOpenOptions, + DevServerStaticItem, +} from '@rspack/core'; import type { FSWatcher, ChokidarOptions as WatchOptions } from 'chokidar'; import type { Options as ConnectHistoryApiFallbackOptions } from 'connect-history-api-fallback'; import type { Server as ConnectApplication, IncomingMessage as ConnectIncomingMessage, + ErrorHandleFunction, + HandleFunction, + NextHandleFunction, } from 'connect-next'; -import type { - Options as HttpProxyMiddlewareOptions, - Filter as HttpProxyMiddlewareOptionsFilter, - RequestHandler, -} from 'http-proxy-middleware'; -import type { ServeStaticOptions } from 'serve-static'; +import type { RequestHandler } from 'http-proxy-middleware'; export type { FSWatcher, @@ -51,27 +53,6 @@ type BasicServer = import('node:net').Server | import('node:tls').Server; /** https://github.com/microsoft/TypeScript/issues/29729 */ export type LiteralUnion = T | (U & Record); -export type NextFunction = (err?: EXPECTED_ANY) => void; -export type SimpleHandleFunction = ( - req: IncomingMessage, - res: ServerResponse, -) => void; -export type NextHandleFunction = ( - req: IncomingMessage, - res: ServerResponse, - next: NextFunction, -) => void; -export type ErrorHandleFunction = ( - err: EXPECTED_ANY, - req: IncomingMessage, - res: ServerResponse, - next: NextFunction, -) => void; -export type HandleFunction = - | SimpleHandleFunction - | NextHandleFunction - | ErrorHandleFunction; - // type-level helpers, inferred as util types export type Request = T extends ConnectApplication ? ConnectIncomingMessage : IncomingMessage; @@ -86,10 +67,6 @@ export type DevMiddlewareContext< U extends Response, > = import('webpack-dev-middleware').Context; -export type Host = LiteralUnion< - 'local-ip' | 'local-ipv4' | 'local-ipv6', - string ->; export type Port = number | LiteralUnion<'auto', string>; export interface WatchFiles { @@ -100,17 +77,10 @@ export interface WatchFiles { }; } -export interface Static { - directory?: string; - publicPath?: string | string[]; - staticOptions?: ServeStaticOptions; - watch?: boolean | NonNullable; -} - export interface NormalizedStatic { directory: string; publicPath: string[]; - staticOptions: ServeStaticOptions; + staticOptions: DevServerStaticItem['staticOptions']; watch: false | WatchOptions; } @@ -140,75 +110,25 @@ export interface WebSocketServerImplementation { clients: ClientConnection[]; } -export type ProxyConfigArrayItem = { - /** - * Alias for `pathFilter` in `http-proxy-middleware` options. - * When both `context` and `pathFilter` are provided, `pathFilter` takes precedence. - */ - context?: HttpProxyMiddlewareOptionsFilter; -} & HttpProxyMiddlewareOptions; - -export type ProxyConfigArray = Array< - | ProxyConfigArrayItem - | (( - req?: Request | undefined, - res?: Response | undefined, - next?: NextFunction | undefined, - ) => ProxyConfigArrayItem) ->; - -export interface OpenApp { - name?: string; - arguments?: string[]; -} - -export interface Open { - app?: string | string[] | OpenApp; +export type Open = DevServerOpenOptions & { target?: string | string[]; -} +}; export interface NormalizedOpen { target: string; options: DevServerOpenOptions; } -export interface WebSocketURL { - hostname?: string; - password?: string; - pathname?: string; - port?: number | string; - protocol?: string; - username?: string; -} - -export interface ClientConfiguration { - logging?: 'log' | 'info' | 'warn' | 'error' | 'none' | 'verbose'; - overlay?: - | boolean - | { - warnings?: OverlayMessageOptions; - errors?: OverlayMessageOptions; - runtimeErrors?: OverlayMessageOptions; - }; - progress?: boolean; - reconnect?: boolean | number; - webSocketTransport?: LiteralUnion<'ws', string>; - webSocketURL?: string | WebSocketURL; -} - -export type Headers = - | Array<{ key: string; value: string }> - | Record; - -export type MiddlewareHandler = (...args: EXPECTED_ANY[]) => EXPECTED_ANY; - export interface MiddlewareObject { name?: string; path?: string; - middleware: MiddlewareHandler; + middleware: DevServerMiddlewareHandler | ErrorHandleFunction; } -export type Middleware = MiddlewareObject | MiddlewareHandler; +export type Middleware = + | MiddlewareObject + | DevServerMiddlewareHandler + | ErrorHandleFunction; export type OverlayMessageOptions = boolean | ((error: Error) => void); From fb91ce51c7b68ad74e4e6403dc9d4a006f80553f Mon Sep 17 00:00:00 2001 From: neverland Date: Thu, 12 Mar 2026 13:01:11 +0800 Subject: [PATCH 2/2] fix --- src/config.ts | 2 +- src/server.ts | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/config.ts b/src/config.ts index 25310d3..fa9a619 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,4 +1,4 @@ -import type { DevServerOpenOptions, DevServerClient } from '@rspack/core'; +import type { DevServerClient, DevServerOpenOptions } from '@rspack/core'; import type { ConnectHistoryApiFallbackOptions, DevServer, diff --git a/src/server.ts b/src/server.ts index 7e54feb..0122262 100644 --- a/src/server.ts +++ b/src/server.ts @@ -14,26 +14,26 @@ import * as os from 'node:os'; import * as path from 'node:path'; import * as url from 'node:url'; import * as util from 'node:util'; -import type { App } from 'open'; -import compression from 'http-compression'; -import type { - HandleFunction, - NextFunction, - NextHandleFunction, - SimpleHandleFunction, -} from 'connect-next'; import type { - DevServerHost, - DevServerHeaders, DevServerClient, - DevServerStaticItem, + DevServerHeaders, + DevServerHost, DevServerMiddlewareHandler, - DevServerWebSocketURL, DevServerProxyConfigArray, DevServerProxyConfigArrayItem, DevServerStatic, + DevServerStaticItem, + DevServerWebSocketURL, } from '@rspack/core'; +import type { + HandleFunction, + NextFunction, + NextHandleFunction, + SimpleHandleFunction, +} from 'connect-next'; +import compression from 'http-compression'; import ipaddr from 'ipaddr.js'; +import type { App } from 'open'; import { getPort } from './getPort'; import { WebsocketServer } from './servers/WebsocketServer'; import type {