Files
smartserve/ts/adapters/adapter.base.ts

133 lines
2.9 KiB
TypeScript
Raw Normal View History

2025-11-29 15:24:00 +00:00
import * as plugins from '../plugins.js';
import type {
ISmartServeOptions,
ISmartServeInstance,
IRequestContext,
IConnectionInfo,
IServerStats,
TRuntime,
THttpMethod,
} from '../core/smartserve.interfaces.js';
/**
* Adapter characteristics - what each runtime supports
*/
export interface IAdapterCharacteristics {
/** Zero-copy streaming support */
zeroCopyStreaming: boolean;
/** HTTP/2 support */
http2Support: boolean;
/** Maximum concurrent connections */
maxConnections: number | 'unlimited';
/** Native WebSocket upgrade support */
nativeWebSocket: boolean;
}
/**
* Handler function that receives web standard Request and returns Response
*/
export type TRequestHandler = (
request: Request,
info: IConnectionInfo
) => Response | Promise<Response>;
/**
* Abstract base adapter for all runtime implementations
*/
export abstract class BaseAdapter {
protected options: ISmartServeOptions;
protected handler: TRequestHandler | null = null;
protected stats: IServerStats = {
uptime: 0,
requestsTotal: 0,
requestsActive: 0,
connectionsTotal: 0,
connectionsActive: 0,
bytesReceived: 0,
bytesSent: 0,
};
protected startTime: number = 0;
constructor(options: ISmartServeOptions) {
this.options = options;
}
/**
* Runtime name
*/
abstract get name(): TRuntime;
/**
* Adapter characteristics
*/
abstract get characteristics(): IAdapterCharacteristics;
/**
* Check if this adapter is supported in current runtime
*/
abstract isSupported(): boolean;
/**
* Start the server
*/
abstract start(handler: TRequestHandler): Promise<ISmartServeInstance>;
/**
* Stop the server
*/
abstract stop(): Promise<void>;
/**
* Get current server statistics
*/
getStats(): IServerStats {
return {
...this.stats,
uptime: this.startTime > 0 ? Date.now() - this.startTime : 0,
};
}
/**
* Create ISmartServeInstance from adapter
*/
protected createInstance(): ISmartServeInstance {
return {
port: this.options.port,
hostname: this.options.hostname ?? '0.0.0.0',
secure: !!this.options.tls,
runtime: this.name,
stop: () => this.stop(),
stats: () => this.getStats(),
};
}
/**
* Parse URL from request for cross-platform compatibility
*/
protected parseUrl(request: Request): URL {
return new URL(request.url);
}
/**
* Parse query parameters from URL
*/
protected parseQuery(url: URL): Record<string, string> {
const query: Record<string, string> = {};
url.searchParams.forEach((value, key) => {
query[key] = value;
});
return query;
}
/**
* Get HTTP method from request
*/
protected parseMethod(request: Request): THttpMethod {
const method = request.method.toUpperCase();
if (['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'].includes(method)) {
return method as THttpMethod;
}
return 'GET';
}
}