@jeffusion/bungee-core 5.16.0 → 5.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ import type { ForwardPublicRequestOptions } from './forwarding';
2
+ import { type WebSocketBridge } from '../websocket';
3
+ /** Pin the admitted worker for this connection; publication never migrates an open socket. */
4
+ export declare function forwardPublicWebSocket(request: Request, server: Bun.Server<any>, bridge: WebSocketBridge, options: ForwardPublicRequestOptions, peer?: string): Promise<Response | undefined>;
@@ -231,6 +231,8 @@ export declare class ScopedPluginRegistry {
231
231
  private combinedHooksCache;
232
232
  /** Phase-aware Hooks 缓存:`phase-aware:${routeId}#${upstreamId}#${serviceName}` → PhaseAwareHooks */
233
233
  private phaseAwareCache;
234
+ private websocketHandshakeHooks;
235
+ private websocketObservationHooks;
234
236
  private attemptObservationHooks;
235
237
  /** 已加载的插件类:pluginName → PluginClass */
236
238
  private pluginClasses;
@@ -390,6 +392,16 @@ export declare class ScopedPluginRegistry {
390
392
  * ```
391
393
  */
392
394
  getPrecompiledHooks(routeId: string, upstreamId?: string, serviceName?: string): PhaseAwareHooks;
395
+ /** Retain every instance actually executed by handshake phases; observer precedence is different. */
396
+ getWebSocketHandshakeOwners(routeId: string, upstreamId: string, serviceName?: string): Array<{
397
+ pluginName: string;
398
+ scopeKey: string;
399
+ }>;
400
+ getWebSocketOwners(routeId: string, upstreamId?: string, serviceName?: string): Array<{
401
+ pluginName: string;
402
+ scopeKey: string;
403
+ hooks: PluginHooks['onWebSocketObservation'];
404
+ }>;
393
405
  getAttemptObservationOwners(routeId: string, upstreamId?: string, serviceName?: string, context?: PluginBodyRequirementContext): AttemptObservationOwner[];
394
406
  /**
395
407
  * 获取路由级预编译 Hooks(不含上游插件)
@@ -0,0 +1,9 @@
1
+ import type { IncomingMessage, OutgoingHttpHeaders } from 'node:http';
2
+ /** Ordinary HTTP and other upgrade protocols remain owned by the HTTP router. */
3
+ export declare function isWebSocketUpgradeRequest(request: Request): boolean;
4
+ export declare function validateWebSocketRequest(request: Request): Response | undefined;
5
+ export declare function offeredProtocols(request: Request): string[];
6
+ /** ws generates a fresh key, Host, Connection, Upgrade and version for this hop. */
7
+ export declare function upstreamHeaders(headers: Headers, protocols: readonly string[]): OutgoingHttpHeaders;
8
+ /** rawHeaders retains repeated Set-Cookie; framing and internal headers do not cross hops. */
9
+ export declare function downstreamHeaders(response: IncomingMessage, rejection?: boolean): Headers;
@@ -0,0 +1,3 @@
1
+ export { createWebSocketMessageView } from './message';
2
+ export { isWebSocketUpgradeRequest, validateWebSocketRequest } from './headers';
3
+ export { createWebSocketBridge, WebSocketBridge, WEBSOCKET_BRIDGE_DEFAULTS, type WebSocketBridgeOptions, type WebSocketBridgeData, type WebSocketUpgradeOptions, type WebSocketBridgeStats, } from './transport';
@@ -0,0 +1,3 @@
1
+ import type { WebSocketMessageView } from '../gateway/websocket-contracts';
2
+ /** One immutable view per complete message; parsing is shared and demand driven. */
3
+ export declare function createWebSocketMessageView(message: string | Uint8Array): WebSocketMessageView;
@@ -0,0 +1,17 @@
1
+ import type { PluginHooks } from '../hooks';
2
+ import type { WebSocketObservationEvent, WebSocketSessionContext } from '../gateway/websocket-contracts';
3
+ type Detail = WebSocketObservationEvent extends infer E ? E extends WebSocketObservationEvent ? Omit<E, keyof WebSocketSessionContext | 'isActive'> : never : never;
4
+ type Owner = {
5
+ pluginName: string;
6
+ hooks: PluginHooks['onWebSocketObservation'];
7
+ };
8
+ /** Independent, ordered queues: an optional observer cannot block forwarding or another owner. */
9
+ export declare class WebSocketObservers {
10
+ private branches;
11
+ constructor(context: WebSocketSessionContext, owners: readonly Owner[]);
12
+ emit(detail: Detail): void;
13
+ close(detail: Extract<Detail, {
14
+ phase: 'close';
15
+ }>): Promise<void>;
16
+ }
17
+ export {};
@@ -0,0 +1,77 @@
1
+ import type { WebSocketMessageView, WebSocketSessionMetrics } from '../gateway/websocket-contracts';
2
+ export declare const WEBSOCKET_BRIDGE_DEFAULTS: Readonly<{
3
+ maxMessageBytes: number;
4
+ maxConnections: 64;
5
+ maxHandshakes: 16;
6
+ handshakeTimeoutMs: 10000;
7
+ maxBufferedBytes: number;
8
+ maxTotalBufferedBytes: number;
9
+ maxEarlyMessages: 16;
10
+ maxFragments: 1024;
11
+ maxRejectedBodyBytes: number;
12
+ closeTimeoutMs: 1000;
13
+ }>;
14
+ type Limits = {
15
+ [K in keyof typeof WEBSOCKET_BRIDGE_DEFAULTS]: number;
16
+ };
17
+ export type WebSocketBridgeOptions = Partial<Limits>;
18
+ /** Opaque token prevents callbacks from taking ownership of another bridge's session. */
19
+ export interface WebSocketBridgeData {
20
+ readonly connection: object;
21
+ }
22
+ export interface WebSocketUpgradeOptions {
23
+ readonly url: URL | string;
24
+ readonly headers: Headers;
25
+ /** Handshake cancellation only. Removed before committing the downstream upgrade. */
26
+ readonly signal?: AbortSignal;
27
+ readonly onOpen?: () => unknown;
28
+ readonly onMessage?: (direction: 'client' | 'upstream', message: WebSocketMessageView) => unknown;
29
+ /** Runs once after both native close callbacks, for committed sessions only. */
30
+ readonly onClose?: (code: number, reason: string, metrics: WebSocketSessionMetrics) => unknown;
31
+ }
32
+ export interface WebSocketBridgeStats {
33
+ readonly accepting: boolean;
34
+ readonly connections: number;
35
+ readonly handshakes: number;
36
+ readonly bufferedBytes: number;
37
+ readonly processBufferedBytes: number;
38
+ readonly downstreamBackpressureEvents: number;
39
+ readonly downstreamDrainEvents: number;
40
+ }
41
+ export declare class WebSocketBridge {
42
+ #private;
43
+ readonly limits: Readonly<Limits>;
44
+ readonly websocket: Bun.WebSocketHandler<WebSocketBridgeData>;
45
+ constructor(options?: WebSocketBridgeOptions);
46
+ get stats(): WebSocketBridgeStats;
47
+ /** Call only for upgrade candidates; ordinary HTTP returns undefined without taking ownership. */
48
+ upgrade(request: Request, server: Bun.Server<any>, options: WebSocketUpgradeOptions): Promise<Response | undefined>;
49
+ stopAccepting(): void;
50
+ /** 1012 close, bounded grace, then terminate, and require actual native close confirmation. */
51
+ stop(): Promise<void>;
52
+ forceStop(): Promise<void>;
53
+ get accepting(): boolean;
54
+ /** @internal */ endHandshake(): void;
55
+ /** @internal */ backpressure(): void;
56
+ /** @internal */ confirmGone(session: BridgeSession): void;
57
+ }
58
+ type Message = string | Buffer;
59
+ declare class BridgeSession {
60
+ #private;
61
+ readonly token: Readonly<{}>;
62
+ readonly response: Promise<Response | undefined>;
63
+ constructor(bridge: WebSocketBridge, request: Request, server: Bun.Server<any>, options: WebSocketUpgradeOptions, url: URL);
64
+ get bufferedBytes(): number;
65
+ get processLimit(): number;
66
+ start(): void;
67
+ cancelHandshake(status: number, reason: string): void;
68
+ downstreamOpen(socket: Bun.ServerWebSocket<WebSocketBridgeData>): void;
69
+ fromClient(message: Message): void;
70
+ downstreamDrain(): void;
71
+ refreshBuffered(): void;
72
+ close(code: number, reason: string): void;
73
+ terminate(): void;
74
+ downstreamClose(code: number, reason: string): void;
75
+ }
76
+ export declare function createWebSocketBridge(options?: WebSocketBridgeOptions): WebSocketBridge;
77
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jeffusion/bungee-core",
3
- "version": "5.16.0",
3
+ "version": "5.17.0",
4
4
  "description": "Bungee reverse proxy core engine",
5
5
  "main": "./dist/main.js",
6
6
  "types": "./dist/main.d.ts",
@@ -12,7 +12,9 @@
12
12
  "test": "bun test"
13
13
  },
14
14
  "dependencies": {
15
- "@jeffusion/bungee-types": "^5.16.0",
15
+ "@bungee/ws-client": "npm:ws@8.22.0",
16
+ "@types/ws": "^8.18.1",
17
+ "@jeffusion/bungee-types": "^5.17.0",
16
18
  "@types/lodash-es": "^4.17.12",
17
19
  "acorn": "^8.15.0",
18
20
  "canonicalize": "3.0.0",