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
9 changes: 8 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,9 @@ jobs:
run: npm run build

- name: Run tests with coverage
run: npm run test:cov
# Full-suite coverage runs native TS compilers alongside real fork/HTTP
# fixtures; bound parallelism to keep their existing 30s deadlines useful.
run: npm run test:cov -- --maxWorkers=2
env:
VEXT_TEST_MONGODB_URI: mongodb://127.0.0.1:27017/vextjs_ci_cov
VEXT_TEST_REDIS_URL: redis://127.0.0.1:6379
Expand Down Expand Up @@ -473,6 +475,11 @@ jobs:
test/unit/frontend-deploy-validation.test.ts
test/unit/frontend-runtime.test.ts
test/unit/frontend-repairs.test.ts
test/unit/cluster/affinity-router.test.ts
test/unit/cluster/socket-receiver.test.ts
test/unit/cluster/socket-dispatcher.test.ts
test/unit/cluster/socket-http-server.test.ts
test/integration/cluster/ip-affinity.test.ts
--reporter=verbose

- name: Verify Windows package exports
Expand Down
12 changes: 10 additions & 2 deletions src/adapters/express/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import type {
Response as ExpressResponse,
} from "express";
import crypto from "node:crypto";
import { createServer } from "node:http";
import {
createAdapterHTTPServer,
socketHandoffControls,
} from "../../lib/socket-http-server.js";
import type { VextAdapterRuntimeContext } from "../../types/adapter.js";
import type { IncomingMessage, ServerResponse } from "node:http";
import { createVextRequest } from "./request.js";
import { createVextResponse } from "./response.js";
Expand Down Expand Up @@ -217,6 +221,7 @@ function collectRawBody(
export function createExpressAdapter(
options: ExpressAdapterOptions,
app: VextApp,
context?: VextAdapterRuntimeContext,
): VextAdapter {
// ── 创建 Express 实例 ────────────────────────────────────
//
Expand Down Expand Up @@ -423,6 +428,7 @@ export function createExpressAdapter(

return {
name: "express",
supportsSocketHandoff: Boolean(context?.socketHandoff),

// ── registerMiddleware ───────────────────────────────────
//
Expand Down Expand Up @@ -642,7 +648,8 @@ export function createExpressAdapter(
// 注册兜底中间件(确保在所有路由之后)
registerFallbacks();

const server = createServer(
const server = createAdapterHTTPServer(
context,
createNodeServerOptions(options?.server),
expressApp,
);
Expand All @@ -663,6 +670,7 @@ export function createExpressAdapter(
: host;

resolve({
...socketHandoffControls(server),
port: actualPort,
host: actualHost,

Expand Down
12 changes: 8 additions & 4 deletions src/adapters/express/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { createExpressAdapter } from "./adapter.js";
import type { ExpressAdapterOptions } from "./adapter.js";
import type { VextAdapter } from "../../types/adapter.js";
import type {
VextAdapter,
VextAdapterFactory,
VextAdapterRuntimeContext,
} from "../../types/adapter.js";
import type { VextApp } from "../../types/app.js";

/**
Expand Down Expand Up @@ -65,11 +69,11 @@ export type { ExpressAdapterOptions } from "./adapter.js";
*/
export function expressAdapter(
options?: ExpressAdapterOptions,
): (app: VextApp) => VextAdapter {
): VextAdapterFactory {
const opts = options ?? {};

return (app: VextApp): VextAdapter => {
return createExpressAdapter(opts, app);
return (app: VextApp, context?: VextAdapterRuntimeContext): VextAdapter => {
return createExpressAdapter(opts, app, context);
};
}

Expand Down
31 changes: 20 additions & 11 deletions src/adapters/fastify/adapter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import Fastify from "fastify";
import type { FastifyInstance, FastifyRequest, FastifyReply } from "fastify";
import { createServer } from "node:http";
import {
createAdapterHTTPServer,
socketHandoffControls,
} from "../../lib/socket-http-server.js";
import type { VextAdapterRuntimeContext } from "../../types/adapter.js";
import type { IncomingMessage, ServerResponse, Server } from "node:http";
import crypto from "node:crypto";
import { createVextRequest } from "./request.js";
Expand Down Expand Up @@ -181,6 +185,7 @@ const _noop = async (): Promise<void> => {};
export function createFastifyAdapter(
options: FastifyAdapterOptions,
app: VextApp,
context?: VextAdapterRuntimeContext,
): VextAdapter {
// ── 创建 Fastify 实例 ────────────────────────────────────
//
Expand All @@ -197,16 +202,18 @@ export function createFastifyAdapter(
adapterBodyLimit: options.bodyLimit,
});
const serverConfig = app.config.server;
const serverFactory = hasServerConfig(serverConfig)
? (handler: NodeRequestHandler): Server => {
const server = createServer(
createNodeServerOptions(serverConfig),
handler,
);
applyServerConfig(server, serverConfig);
return server;
}
: undefined;
const serverFactory =
context?.socketHandoff || hasServerConfig(serverConfig)
? (handler: NodeRequestHandler): Server => {
const server = createAdapterHTTPServer(
context,
createNodeServerOptions(serverConfig),
handler,
);
applyServerConfig(server, serverConfig);
return server;
}
: undefined;

const fastify: FastifyInstance = Fastify({
logger: options.logger ?? false,
Expand Down Expand Up @@ -263,6 +270,7 @@ export function createFastifyAdapter(

return {
name: "fastify",
supportsSocketHandoff: Boolean(context?.socketHandoff),

// ── registerMiddleware ───────────────────────────────────
//
Expand Down Expand Up @@ -574,6 +582,7 @@ export function createFastifyAdapter(
: host;

return {
...socketHandoffControls(fastify.server),
port: actualPort,
host: actualHost,

Expand Down
12 changes: 8 additions & 4 deletions src/adapters/fastify/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { createFastifyAdapter } from "./adapter.js";
import type { FastifyAdapterOptions } from "./adapter.js";
import type { VextAdapter } from "../../types/adapter.js";
import type {
VextAdapter,
VextAdapterFactory,
VextAdapterRuntimeContext,
} from "../../types/adapter.js";
import type { VextApp } from "../../types/app.js";

/**
Expand Down Expand Up @@ -91,11 +95,11 @@ export type { FastifyAdapterOptions } from "./adapter.js";
*/
export function fastifyAdapter(
options?: FastifyAdapterOptions,
): (app: VextApp) => VextAdapter {
): VextAdapterFactory {
const opts = options ?? {};

return (app: VextApp): VextAdapter => {
return createFastifyAdapter(opts, app);
return (app: VextApp, context?: VextAdapterRuntimeContext): VextAdapter => {
return createFastifyAdapter(opts, app, context);
};
}

Expand Down
16 changes: 13 additions & 3 deletions src/adapters/hono/adapter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { Hono, type Context } from "hono";
import { Buffer } from "node:buffer";
import { createServer } from "node:http";
import {
createAdapterHTTPServer,
socketHandoffControls,
} from "../../lib/socket-http-server.js";
import type { VextAdapterRuntimeContext } from "../../types/adapter.js";
import type { IncomingMessage, ServerResponse } from "node:http";
import crypto from "node:crypto";
import { createRouter } from "route-core";
Expand Down Expand Up @@ -292,7 +296,10 @@ async function writeWebResponse(
* @param app VextApp 实例(用于传递给 createVextRequest 的 app 引用)
* @returns VextAdapter 实例
*/
export function createHonoAdapter(app: VextApp): VextAdapter {
export function createHonoAdapter(
app: VextApp,
context?: VextAdapterRuntimeContext,
): VextAdapter {
const hono = new Hono();
const explicitHeadRouter = createRouter({
ignoreTrailingSlash: true,
Expand All @@ -310,6 +317,7 @@ export function createHonoAdapter(app: VextApp): VextAdapter {

return {
name: "hono",
supportsSocketHandoff: Boolean(context?.socketHandoff),

registerMiddleware(middleware: VextMiddleware): void {
globalMiddlewares.push(middleware);
Expand Down Expand Up @@ -505,7 +513,8 @@ export function createHonoAdapter(app: VextApp): VextAdapter {
const requestHandler = this.buildHandler();

return new Promise<VextServerHandle>((resolve, reject) => {
const server = createServer(
const server = createAdapterHTTPServer(
context,
createNodeServerOptions(options?.server),
requestHandler,
);
Expand All @@ -525,6 +534,7 @@ export function createHonoAdapter(app: VextApp): VextAdapter {
: host;

resolve({
...socketHandoffControls(server),
port: actualPort,
host: actualHost,

Expand Down
11 changes: 8 additions & 3 deletions src/adapters/hono/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { createHonoAdapter } from "./adapter.js";
import type { VextAdapter } from "../../types/adapter.js";
import type {
VextAdapter,
VextAdapterFactory,
VextAdapterRuntimeContext,
} from "../../types/adapter.js";
import type { VextApp } from "../../types/app.js";

/**
Expand All @@ -17,8 +21,9 @@ import type { VextApp } from "../../types/app.js";
*
* 内置字符串方式仍然可用:`adapter: "hono"`。
*/
export function honoAdapter(): (app: VextApp) => VextAdapter {
return (app: VextApp): VextAdapter => createHonoAdapter(app);
export function honoAdapter(): VextAdapterFactory {
return (app: VextApp, context?: VextAdapterRuntimeContext): VextAdapter =>
createHonoAdapter(app, context);
}

export { createHonoAdapter } from "./adapter.js";
12 changes: 10 additions & 2 deletions src/adapters/koa/adapter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import Koa from "koa";
import Router from "@koa/router";
import type { Context as KoaContext } from "koa";
import { createServer } from "node:http";
import {
createAdapterHTTPServer,
socketHandoffControls,
} from "../../lib/socket-http-server.js";
import type { VextAdapterRuntimeContext } from "../../types/adapter.js";
import type { IncomingMessage, ServerResponse } from "node:http";
import crypto from "node:crypto";
import { createVextRequest } from "./request.js";
Expand Down Expand Up @@ -242,6 +246,7 @@ function getKoaParams(ctx: KoaContext): Record<string, string> {
export function createKoaAdapter(
options: KoaAdapterOptions,
vextApp: VextApp,
context?: VextAdapterRuntimeContext,
): VextAdapter {
// ── 创建 Koa 实例 ─────────────────────────────────────────
//
Expand Down Expand Up @@ -497,6 +502,7 @@ export function createKoaAdapter(

return {
name: "koa",
supportsSocketHandoff: Boolean(context?.socketHandoff),

// ── registerMiddleware ───────────────────────────────────
//
Expand Down Expand Up @@ -591,7 +597,8 @@ export function createKoaAdapter(
registerKoaMiddleware();

const handler = koaApp.callback();
const server = createServer(
const server = createAdapterHTTPServer(
context,
createNodeServerOptions(options?.server),
handler,
);
Expand All @@ -612,6 +619,7 @@ export function createKoaAdapter(
: host;

resolve({
...socketHandoffControls(server),
port: actualPort,
host: actualHost,

Expand Down
14 changes: 8 additions & 6 deletions src/adapters/koa/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { createKoaAdapter } from "./adapter.js";
import type { KoaAdapterOptions } from "./adapter.js";
import type { VextAdapter } from "../../types/adapter.js";
import type {
VextAdapter,
VextAdapterFactory,
VextAdapterRuntimeContext,
} from "../../types/adapter.js";
import type { VextApp } from "../../types/app.js";

/**
Expand Down Expand Up @@ -64,13 +68,11 @@ export type { KoaAdapterOptions } from "./adapter.js";
* import { koaAdapter } from 'vextjs/adapters/koa'
* export default { adapter: koaAdapter({ bodyLimit: '5mb' }) }
*/
export function koaAdapter(
options?: KoaAdapterOptions,
): (app: VextApp) => VextAdapter {
export function koaAdapter(options?: KoaAdapterOptions): VextAdapterFactory {
const opts = options ?? {};

return (app: VextApp): VextAdapter => {
return createKoaAdapter(opts, app);
return (app: VextApp, context?: VextAdapterRuntimeContext): VextAdapter => {
return createKoaAdapter(opts, app, context);
};
}

Expand Down
12 changes: 10 additions & 2 deletions src/adapters/native/adapter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { createServer } from "node:http";
import {
createAdapterHTTPServer,
socketHandoffControls,
} from "../../lib/socket-http-server.js";
import type { VextAdapterRuntimeContext } from "../../types/adapter.js";
import type { IncomingMessage, ServerResponse, Server } from "node:http";
import crypto from "node:crypto";
import { createRouter } from "route-core";
Expand Down Expand Up @@ -218,6 +222,7 @@ const _noop = async (): Promise<void> => {};
export function createNativeAdapter(
options: NativeAdapterOptions,
app: VextApp,
context?: VextAdapterRuntimeContext,
): VextAdapter {
// ── 创建 route-core 路由器 ────────────────────────────────
//
Expand Down Expand Up @@ -611,6 +616,7 @@ export function createNativeAdapter(

return {
name: "native",
supportsSocketHandoff: Boolean(context?.socketHandoff),

// ── registerMiddleware ───────────────────────────────────
//
Expand Down Expand Up @@ -716,7 +722,8 @@ export function createNativeAdapter(
host: string = "0.0.0.0",
options?: VextAdapterListenOptions,
): Promise<VextServerHandle> {
const server: Server = createServer(
const server: Server = createAdapterHTTPServer(
context,
createNodeServerOptions(options?.server),
handleRequest,
);
Expand All @@ -737,6 +744,7 @@ export function createNativeAdapter(
: host;

resolve({
...socketHandoffControls(server),
port: actualPort,
host: actualHost,

Expand Down
Loading
Loading