@aigne/afs-session 1.11.0-beta.10

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 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/protocol/types.ts","../src/protocol/frame.ts","../src/protocol/frame-decoder.ts","../src/protocol/message.ts","../src/session/types.ts","../src/session/host.ts","../src/transport/types.ts","../src/transport/unix-socket.ts","../src/transport/websocket.ts"],"sourcesContent":["/**\n * Protocol constants\n */\nexport const HEADER_SIZE = 9; // Length(4) + Type(1) + ReqId(4)\nexport const MAX_PAYLOAD_SIZE = 16 * 1024 * 1024; // 16MB\nexport const MAX_JSON_DEPTH = 100;\nexport const MAX_JSON_SIZE = 1 * 1024 * 1024; // 1MB\nexport const MAX_UINT32 = 0xffffffff;\n\n/**\n * Frame types\n */\nexport enum FrameType {\n JSON = 0x01,\n Binary = 0x02,\n}\n\n/**\n * Frame structure after decoding\n */\nexport interface Frame {\n type: FrameType;\n reqId: number;\n payload: Uint8Array;\n}\n\n/**\n * Protocol errors\n */\nexport class ProtocolError extends Error {\n constructor(\n public readonly code: string,\n message: string,\n ) {\n super(message);\n this.name = \"ProtocolError\";\n }\n}\n\nexport class PayloadTooLargeError extends ProtocolError {\n constructor(size: number) {\n super(\"payload_too_large\", `Payload size ${size} exceeds maximum ${MAX_PAYLOAD_SIZE}`);\n this.name = \"PayloadTooLargeError\";\n }\n}\n\nexport class InvalidPayloadError extends ProtocolError {\n constructor(message: string) {\n super(\"invalid_payload\", message);\n this.name = \"InvalidPayloadError\";\n }\n}\n\nexport class InvalidFrameTypeError extends ProtocolError {\n constructor(type: number) {\n super(\"invalid_frame_type\", `Invalid frame type: 0x${type.toString(16).padStart(2, \"0\")}`);\n this.name = \"InvalidFrameTypeError\";\n }\n}\n\nexport class InvalidReqIdError extends ProtocolError {\n constructor(reqId: number) {\n super(\"invalid_req_id\", `Invalid request ID: ${reqId} (must be 0-${MAX_UINT32})`);\n this.name = \"InvalidReqIdError\";\n }\n}\n\nexport class IncompleteFrameError extends ProtocolError {\n constructor(message: string) {\n super(\"incomplete_frame\", message);\n this.name = \"IncompleteFrameError\";\n }\n}\n","import {\n type Frame,\n FrameType,\n HEADER_SIZE,\n IncompleteFrameError,\n InvalidFrameTypeError,\n InvalidPayloadError,\n InvalidReqIdError,\n MAX_PAYLOAD_SIZE,\n MAX_UINT32,\n PayloadTooLargeError,\n} from \"./types.js\";\n\n/**\n * Validates frame type.\n */\nfunction isValidFrameType(type: number): type is FrameType {\n return type === FrameType.JSON || type === FrameType.Binary;\n}\n\n/**\n * Encodes a frame with the given type, request ID, and payload.\n *\n * Frame structure (big-endian):\n * - Length (4 bytes): payload length\n * - Type (1 byte): frame type\n * - ReqId (4 bytes): request ID\n * - Payload (variable): actual data\n *\n * @param type Frame type (JSON or Binary)\n * @param reqId Request ID (0 for events, >0 for request/response)\n * @param payload The payload data\n * @returns Encoded frame as Uint8Array\n */\nexport function encodeFrame(type: FrameType, reqId: number, payload: Uint8Array): Uint8Array {\n // Validate payload\n if (payload == null) {\n throw new InvalidPayloadError(\"Payload cannot be null or undefined\");\n }\n\n // Validate payload size\n if (payload.length > MAX_PAYLOAD_SIZE) {\n throw new PayloadTooLargeError(payload.length);\n }\n\n // Validate frame type\n if (!isValidFrameType(type)) {\n throw new InvalidFrameTypeError(type);\n }\n\n // Validate reqId\n if (reqId < 0 || reqId > MAX_UINT32 || !Number.isInteger(reqId)) {\n throw new InvalidReqIdError(reqId);\n }\n\n // Allocate buffer\n const frame = new Uint8Array(HEADER_SIZE + payload.length);\n const view = new DataView(frame.buffer, frame.byteOffset);\n\n // Write header (big-endian)\n view.setUint32(0, payload.length); // Length\n view.setUint8(4, type); // Type\n view.setUint32(5, reqId); // ReqId\n\n // Copy payload\n frame.set(payload, HEADER_SIZE);\n\n return frame;\n}\n\n/**\n * Decodes a frame from a buffer.\n *\n * @param buffer The buffer containing the frame data\n * @returns Object containing the decoded frame and any remaining bytes\n * @throws IncompleteFrameError if buffer doesn't contain a complete frame\n * @throws InvalidFrameTypeError if frame type is invalid\n * @throws PayloadTooLargeError if payload length exceeds maximum\n */\nexport function decodeFrame(buffer: Uint8Array): { frame: Frame; remaining: Uint8Array } {\n // Check if we have enough bytes for header\n if (buffer.length < HEADER_SIZE) {\n throw new IncompleteFrameError(\n `Buffer too small: ${buffer.length} bytes, need at least ${HEADER_SIZE}`,\n );\n }\n\n const view = new DataView(buffer.buffer, buffer.byteOffset);\n\n // Read header\n const length = view.getUint32(0);\n const type = view.getUint8(4);\n const reqId = view.getUint32(5);\n\n // Security: Check payload size before allocating\n if (length > MAX_PAYLOAD_SIZE) {\n throw new PayloadTooLargeError(length);\n }\n\n // Validate frame type\n if (!isValidFrameType(type)) {\n throw new InvalidFrameTypeError(type);\n }\n\n // Check if we have the complete payload\n const totalSize = HEADER_SIZE + length;\n if (buffer.length < totalSize) {\n throw new IncompleteFrameError(\n `Incomplete frame: have ${buffer.length} bytes, need ${totalSize}`,\n );\n }\n\n // Extract payload\n const payload = buffer.slice(HEADER_SIZE, totalSize);\n\n // Extract remaining bytes\n const remaining = buffer.slice(totalSize);\n\n return {\n frame: { type, reqId, payload },\n remaining,\n };\n}\n","import { decodeFrame } from \"./frame.js\";\nimport {\n type Frame,\n HEADER_SIZE,\n MAX_PAYLOAD_SIZE,\n PayloadTooLargeError,\n ProtocolError,\n} from \"./types.js\";\n\n/**\n * Configuration options for FrameDecoder\n */\nexport interface FrameDecoderOptions {\n /**\n * Maximum size of pending buffer to prevent memory attacks.\n * Default: MAX_PAYLOAD_SIZE + HEADER_SIZE\n */\n maxPendingSize?: number;\n}\n\n/**\n * Error thrown when pending buffer exceeds maximum size\n */\nexport class BufferOverflowError extends ProtocolError {\n constructor(size: number, maxSize: number) {\n super(\"buffer_overflow\", `Pending buffer size ${size} exceeds maximum ${maxSize}`);\n this.name = \"BufferOverflowError\";\n }\n}\n\n/**\n * Streaming frame decoder that handles:\n * - Partial frames across multiple pushes (拆包)\n * - Multiple frames in single push (粘包)\n * - Buffer overflow protection (security)\n */\nexport class FrameDecoder {\n private buffer: Uint8Array = new Uint8Array(0);\n private readonly maxPendingSize: number;\n\n constructor(options?: FrameDecoderOptions) {\n this.maxPendingSize = options?.maxPendingSize ?? MAX_PAYLOAD_SIZE + HEADER_SIZE;\n }\n\n /**\n * Push data into the decoder and return any complete frames.\n *\n * @param data New data to append to buffer\n * @returns Array of complete frames (may be empty)\n * @throws InvalidFrameTypeError if frame type is invalid\n * @throws PayloadTooLargeError if payload exceeds maximum\n * @throws BufferOverflowError if pending buffer exceeds maximum\n */\n push(data: Uint8Array): Frame[] {\n // Empty data - nothing to do\n if (data.length === 0) {\n return [];\n }\n\n // Append to buffer\n const newBuffer = new Uint8Array(this.buffer.length + data.length);\n newBuffer.set(this.buffer, 0);\n newBuffer.set(data, this.buffer.length);\n this.buffer = newBuffer;\n\n // Security: Check buffer size\n if (this.buffer.length > this.maxPendingSize) {\n throw new BufferOverflowError(this.buffer.length, this.maxPendingSize);\n }\n\n // Try to decode frames\n const frames: Frame[] = [];\n\n while (this.buffer.length >= HEADER_SIZE) {\n // Peek at length to see if we have enough data\n const view = new DataView(this.buffer.buffer, this.buffer.byteOffset);\n const payloadLength = view.getUint32(0);\n\n // Security: Check payload size before proceeding\n if (payloadLength > MAX_PAYLOAD_SIZE) {\n throw new PayloadTooLargeError(payloadLength);\n }\n\n const totalFrameSize = HEADER_SIZE + payloadLength;\n\n // Not enough data for complete frame\n if (this.buffer.length < totalFrameSize) {\n break;\n }\n\n // Decode frame (will validate type)\n const { frame, remaining } = decodeFrame(this.buffer);\n frames.push(frame);\n this.buffer = remaining;\n }\n\n return frames;\n }\n\n /**\n * Reset the decoder state, discarding any buffered data.\n */\n reset(): void {\n this.buffer = new Uint8Array(0);\n }\n\n /**\n * Get the current pending buffer size.\n */\n get pendingSize(): number {\n return this.buffer.length;\n }\n}\n","import { MAX_JSON_DEPTH, MAX_JSON_SIZE, ProtocolError } from \"./types.js\";\n\n/**\n * Request message - needs a response\n */\nexport interface Request {\n type: \"request\";\n id: string;\n method: string;\n params?: unknown;\n}\n\n/**\n * Response message - response to a request\n */\nexport interface Response {\n type: \"response\";\n id: string;\n result?: unknown;\n error?: unknown;\n hasBinary?: boolean;\n}\n\n/**\n * Event message - one-way notification\n */\nexport interface Event {\n type: \"event\";\n event: string;\n data?: unknown;\n}\n\n/**\n * Union of all message types\n */\nexport type Message = Request | Response | Event;\n\n/**\n * Error for invalid message structure\n */\nexport class InvalidMessageError extends ProtocolError {\n constructor(message: string) {\n super(\"invalid_message\", message);\n this.name = \"InvalidMessageError\";\n }\n}\n\n/**\n * Error for JSON parsing failures\n */\nexport class ParseError extends ProtocolError {\n constructor(message: string) {\n super(\"parse_error\", `Parse error: ${message}`);\n this.name = \"ParseError\";\n }\n}\n\n/**\n * Error for depth limit exceeded\n */\nexport class DepthLimitExceededError extends ProtocolError {\n constructor() {\n super(\"depth_limit_exceeded\", `JSON depth limit exceeded (max ${MAX_JSON_DEPTH})`);\n this.name = \"DepthLimitExceededError\";\n }\n}\n\n/**\n * Error for message too large\n */\nexport class MessageTooLargeError extends ProtocolError {\n constructor(size: number) {\n super(\"message_too_large\", `Message too large: ${size} bytes (max ${MAX_JSON_SIZE})`);\n this.name = \"MessageTooLargeError\";\n }\n}\n\n/**\n * Dangerous keys that should be filtered for security\n */\nconst DANGEROUS_KEYS = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n\n/**\n * Recursively filter dangerous keys from an object\n */\nfunction filterDangerousKeys(obj: unknown, depth = 0): unknown {\n if (depth > MAX_JSON_DEPTH) {\n throw new DepthLimitExceededError();\n }\n\n if (obj === null || typeof obj !== \"object\") {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => filterDangerousKeys(item, depth + 1));\n }\n\n const filtered: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (!DANGEROUS_KEYS.has(key)) {\n filtered[key] = filterDangerousKeys(value, depth + 1);\n }\n }\n return filtered;\n}\n\n/**\n * Calculate depth of a JSON object\n */\nfunction calculateDepth(obj: unknown, depth = 0): number {\n if (depth > MAX_JSON_DEPTH) {\n return depth;\n }\n\n if (obj === null || typeof obj !== \"object\") {\n return depth;\n }\n\n let maxDepth = depth;\n\n if (Array.isArray(obj)) {\n for (const item of obj) {\n maxDepth = Math.max(maxDepth, calculateDepth(item, depth + 1));\n if (maxDepth > MAX_JSON_DEPTH) {\n return maxDepth;\n }\n }\n } else {\n for (const value of Object.values(obj)) {\n maxDepth = Math.max(maxDepth, calculateDepth(value, depth + 1));\n if (maxDepth > MAX_JSON_DEPTH) {\n return maxDepth;\n }\n }\n }\n\n return maxDepth;\n}\n\n/**\n * Serialize a message to JSON bytes.\n *\n * @param message The message to serialize\n * @returns UTF-8 encoded JSON bytes\n * @throws InvalidMessageError if message is invalid\n */\nexport function serializeMessage(message: Message): Uint8Array {\n // Validate message type\n if (!message || typeof message !== \"object\" || !(\"type\" in message)) {\n throw new InvalidMessageError(\"Invalid message: missing type\");\n }\n\n const { type } = message;\n\n if (type === \"request\") {\n const req = message as Request;\n if (!req.id) {\n throw new InvalidMessageError(\"Invalid request: missing id\");\n }\n if (!req.method) {\n throw new InvalidMessageError(\"Invalid request: missing method\");\n }\n }\n\n // Create clean object without undefined values\n const clean: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(message)) {\n if (value !== undefined) {\n clean[key] = value;\n }\n }\n\n const json = JSON.stringify(clean);\n return new TextEncoder().encode(json);\n}\n\n/**\n * Deserialize JSON bytes to a message.\n *\n * @param data UTF-8 encoded JSON bytes\n * @returns Parsed message\n * @throws ParseError if JSON is invalid\n * @throws InvalidMessageError if message structure is invalid\n * @throws DepthLimitExceededError if JSON is too deeply nested\n * @throws MessageTooLargeError if message exceeds size limit\n */\nexport function deserializeMessage(data: Uint8Array): Message {\n // Check size\n if (data.length > MAX_JSON_SIZE) {\n throw new MessageTooLargeError(data.length);\n }\n\n // Parse JSON\n let parsed: unknown;\n try {\n const json = new TextDecoder().decode(data);\n parsed = JSON.parse(json);\n } catch (e) {\n throw new ParseError(e instanceof Error ? e.message : \"Invalid JSON\");\n }\n\n // Validate structure\n if (!parsed || typeof parsed !== \"object\") {\n throw new InvalidMessageError(\"Invalid message: not an object\");\n }\n\n // Check depth\n const depth = calculateDepth(parsed);\n if (depth > MAX_JSON_DEPTH) {\n throw new DepthLimitExceededError();\n }\n\n // Filter dangerous keys\n const filtered = filterDangerousKeys(parsed) as Record<string, unknown>;\n\n // Validate type\n if (!(\"type\" in filtered) || typeof filtered.type !== \"string\") {\n throw new InvalidMessageError(\"Invalid message: missing type\");\n }\n\n const { type } = filtered;\n\n if (type !== \"request\" && type !== \"response\" && type !== \"event\") {\n throw new InvalidMessageError(`Invalid message type: ${type}`);\n }\n\n return filtered as unknown as Message;\n}\n","import type { AFSModule } from \"@aigne/afs\";\n\n/**\n * Protocol version\n */\nexport const PROTOCOL_VERSION = \"1.0\";\n\n/**\n * Session state\n */\nexport type SessionState = \"pending\" | \"attached\" | \"disconnected\";\n\n/**\n * Session error codes (defined by protocol)\n */\nexport type SessionErrorCode =\n | \"namespace_conflict\"\n | \"invalid_session\"\n | \"unavailable\"\n | \"protocol_error\"\n | \"version_mismatch\"\n | \"auth_required\"\n | \"auth_failed\"\n | \"invalid_request\";\n\n/**\n * Session error\n */\nexport class SessionError extends Error {\n constructor(\n public readonly code: SessionErrorCode,\n message: string,\n ) {\n super(message);\n this.name = \"SessionError\";\n }\n}\n\n/**\n * Parameters for session.attach request\n */\nexport interface AttachParams {\n version: string;\n namespace: string;\n name?: string;\n path?: string;\n sessionId?: string;\n replace?: boolean;\n auth?: {\n type: \"token\";\n credential: string;\n };\n}\n\n/**\n * Result of session.attach request\n */\nexport interface AttachResult {\n sessionId: string;\n namespace: string;\n}\n\n/**\n * Session represents a connected AFS namespace\n */\nexport interface Session {\n /**\n * Unique session ID\n */\n readonly id: string;\n\n /**\n * Namespace this session is attached to\n */\n readonly namespace: string;\n\n /**\n * Optional friendly name\n */\n readonly name?: string;\n\n /**\n * Session state\n */\n readonly state: SessionState;\n\n /**\n * When the session was created\n */\n readonly createdAt: Date;\n\n /**\n * The AFS module this session provides access to\n */\n readonly afs: AFSModule;\n}\n\n/**\n * Session host manages multiple sessions (Observer side)\n */\nexport interface SessionHostEvents {\n sessionCreated: (session: Session) => void;\n sessionClosed: (session: Session) => void;\n}\n\n/**\n * Options for SessionHost\n */\nexport interface SessionHostOptions {\n /**\n * Maximum number of concurrent sessions\n */\n maxSessions?: number;\n\n /**\n * Request timeout in milliseconds\n */\n requestTimeout?: number;\n\n /**\n * Grace period for disconnected sessions (milliseconds).\n * Sessions can be reconnected within this period.\n */\n sessionTimeout?: number;\n\n /**\n * Idle timeout (milliseconds)\n */\n idleTimeout?: number;\n\n /**\n * Heartbeat interval in milliseconds.\n * Set to 0 to disable heartbeat.\n */\n heartbeatInterval?: number;\n\n /**\n * Heartbeat timeout in milliseconds.\n * If no pong received within this time, session is disconnected.\n */\n heartbeatTimeout?: number;\n}\n\n/**\n * Default options\n */\nexport const DEFAULT_SESSION_OPTIONS: Required<SessionHostOptions> = {\n maxSessions: 100,\n requestTimeout: 30000,\n sessionTimeout: 30000,\n idleTimeout: 300000,\n heartbeatInterval: 30000,\n heartbeatTimeout: 90000,\n};\n","import type { AFSModule } from \"@aigne/afs\";\nimport {\n deserializeMessage,\n type Event,\n type Request,\n type Response,\n serializeMessage,\n} from \"../protocol/message.js\";\nimport { type Frame, FrameType } from \"../protocol/types.js\";\nimport type { Transport } from \"../transport/types.js\";\nimport {\n type AttachParams,\n type AttachResult,\n DEFAULT_SESSION_OPTIONS,\n PROTOCOL_VERSION,\n type Session,\n type SessionHostOptions,\n type SessionState,\n} from \"./types.js\";\n\n/**\n * Counter for generating unique session IDs\n */\nlet sessionCounter = 0;\n\n/**\n * Validates namespace string\n */\nfunction isValidNamespace(namespace: string): boolean {\n // Check length\n if (namespace.length === 0 || namespace.length > 255) {\n return false;\n }\n\n // Check for path traversal\n if (namespace.includes(\"..\") || namespace.includes(\"/\") || namespace.includes(\":\")) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Generate session ID with uniqueness guarantee\n */\nfunction generateSessionId(namespace: string): string {\n sessionCounter++;\n const random = Math.random().toString(36).substring(2, 8);\n return `sess_${namespace}_${Date.now()}_${sessionCounter}_${random}`;\n}\n\n/**\n * Connection state for each transport\n */\ninterface ConnectionState {\n transport: Transport;\n session?: SessionImpl;\n attached: boolean;\n lastPong: number;\n heartbeatTimer?: ReturnType<typeof setInterval>;\n}\n\n/**\n * Disconnected session waiting for reconnect\n */\ninterface DisconnectedSession {\n session: SessionImpl;\n disconnectedAt: number;\n timeoutId: ReturnType<typeof setTimeout>;\n}\n\n/**\n * Session implementation\n */\nclass SessionImpl implements Session {\n readonly id: string;\n readonly namespace: string;\n readonly name?: string;\n readonly createdAt: Date;\n readonly afs: AFSModule;\n private _state: SessionState = \"pending\";\n\n constructor(params: { id?: string; namespace: string; name?: string; afs: AFSModule }) {\n this.id = params.id || generateSessionId(params.namespace);\n this.namespace = params.namespace;\n this.name = params.name;\n this.createdAt = new Date();\n this.afs = params.afs;\n this._state = \"attached\";\n }\n\n get state(): SessionState {\n return this._state;\n }\n\n setState(state: SessionState): void {\n this._state = state;\n }\n}\n\n/**\n * Stub AFS module for injected sessions.\n * The real AFS operations are proxied back to the client.\n */\nclass InjectedAFSModule implements AFSModule {\n readonly name: string;\n readonly description?: string;\n\n constructor(name: string, description?: string) {\n this.name = name;\n this.description = description;\n }\n\n // AFS methods will be implemented when we add passthrough\n // For now, they're stubs\n}\n\n/**\n * Session host manages multiple client sessions (Observer side).\n */\nexport class SessionHost {\n private options: Required<SessionHostOptions>;\n private connections: Map<Transport, ConnectionState> = new Map();\n private sessions: Map<string, SessionImpl> = new Map();\n private namespaces: Map<string, SessionImpl> = new Map();\n private sessionToConnection: Map<string, ConnectionState> = new Map();\n private disconnectedSessions: Map<string, DisconnectedSession> = new Map();\n\n constructor(options: SessionHostOptions = {}) {\n this.options = { ...DEFAULT_SESSION_OPTIONS, ...options };\n }\n\n /**\n * Handle a new transport connection.\n */\n handleConnection(transport: Transport): void {\n const state: ConnectionState = {\n transport,\n attached: false,\n lastPong: Date.now(),\n };\n\n this.connections.set(transport, state);\n\n transport.on(\"frame\", (frame) => {\n this.handleFrame(state, frame).catch((err) => {\n console.error(\"Error handling frame:\", err);\n });\n });\n\n transport.on(\"close\", () => {\n this.handleDisconnect(state);\n });\n\n transport.on(\"error\", (err) => {\n console.error(\"Transport error:\", err);\n });\n }\n\n /**\n * Handle incoming frame from a connection.\n */\n private async handleFrame(state: ConnectionState, frame: Frame): Promise<void> {\n if (frame.type !== FrameType.JSON) {\n // Binary frames handled separately\n return;\n }\n\n try {\n const message = deserializeMessage(frame.payload);\n\n if (message.type === \"event\") {\n // Handle pong events\n const event = message as Event;\n if (event.event === \"session.pong\") {\n state.lastPong = Date.now();\n }\n return;\n }\n\n if (message.type !== \"request\") {\n // Only handle requests and events\n return;\n }\n\n const request = message as Request;\n let response: Response;\n\n if (request.method === \"session.attach\") {\n response = await this.handleAttach(state, request);\n } else if (request.method === \"session.detach\") {\n response = await this.handleDetach(state, request);\n } else if (request.method.startsWith(\"afs.\")) {\n response = await this.handleAfsRequest(state, request);\n } else {\n response = {\n type: \"response\",\n id: request.id,\n error: { code: \"invalid_request\", message: `Unknown method: ${request.method}` },\n };\n }\n\n await this.sendResponse(state.transport, response);\n } catch (err) {\n console.error(\"Error processing frame:\", err);\n }\n }\n\n /**\n * Handle session.attach request.\n */\n private async handleAttach(state: ConnectionState, request: Request): Promise<Response> {\n // Check if already attached\n if (state.attached) {\n return {\n type: \"response\",\n id: request.id,\n error: { code: \"invalid_request\", message: \"Already attached to a session\" },\n };\n }\n\n const params = request.params as AttachParams | undefined;\n\n // Validate params\n if (!params || !params.version) {\n return {\n type: \"response\",\n id: request.id,\n error: { code: \"invalid_request\", message: \"Missing required parameter: version\" },\n };\n }\n\n if (!params.namespace) {\n return {\n type: \"response\",\n id: request.id,\n error: { code: \"invalid_request\", message: \"Missing required parameter: namespace\" },\n };\n }\n\n // Check version\n if (params.version !== PROTOCOL_VERSION) {\n return {\n type: \"response\",\n id: request.id,\n error: {\n code: \"version_mismatch\",\n message: `Version mismatch: expected ${PROTOCOL_VERSION}, got ${params.version}`,\n },\n };\n }\n\n // Validate namespace\n if (!isValidNamespace(params.namespace)) {\n return {\n type: \"response\",\n id: request.id,\n error: { code: \"invalid_request\", message: \"Invalid namespace\" },\n };\n }\n\n // Handle reconnect with session ID\n if (params.sessionId) {\n return this.handleReconnect(state, request, params);\n }\n\n // Check max sessions\n if (this.sessions.size >= this.options.maxSessions) {\n return {\n type: \"response\",\n id: request.id,\n error: { code: \"invalid_request\", message: \"Maximum sessions reached\" },\n };\n }\n\n // Check namespace conflict\n const existingSession = this.namespaces.get(params.namespace);\n if (existingSession) {\n if (params.replace) {\n // Send replaced event to old session before replacing\n const oldConnectionState = this.sessionToConnection.get(existingSession.id);\n if (oldConnectionState) {\n await this.sendEvent(oldConnectionState.transport, {\n type: \"event\",\n event: \"session.replaced\",\n data: {\n sessionId: existingSession.id,\n namespace: existingSession.namespace,\n reason: \"replaced by new connection\",\n },\n });\n // Stop heartbeat for old connection\n if (oldConnectionState.heartbeatTimer) {\n clearInterval(oldConnectionState.heartbeatTimer);\n }\n // Clear the old connection's session reference\n oldConnectionState.session = undefined;\n oldConnectionState.attached = false;\n this.sessionToConnection.delete(existingSession.id);\n }\n // Replace existing session\n existingSession.setState(\"disconnected\");\n this.sessions.delete(existingSession.id);\n this.namespaces.delete(params.namespace);\n } else {\n return {\n type: \"response\",\n id: request.id,\n error: {\n code: \"namespace_conflict\",\n message: `Namespace '${params.namespace}' already exists`,\n },\n };\n }\n }\n\n // Create session\n const afs = new InjectedAFSModule(params.namespace, params.name);\n const session = new SessionImpl({\n namespace: params.namespace,\n name: params.name,\n afs,\n });\n\n this.sessions.set(session.id, session);\n this.namespaces.set(session.namespace, session);\n this.sessionToConnection.set(session.id, state);\n state.session = session;\n state.attached = true;\n\n // Start heartbeat if enabled\n this.startHeartbeat(state);\n\n const result: AttachResult = {\n sessionId: session.id,\n namespace: session.namespace,\n };\n\n return {\n type: \"response\",\n id: request.id,\n result,\n };\n }\n\n /**\n * Handle reconnect with existing session ID.\n */\n private async handleReconnect(\n state: ConnectionState,\n request: Request,\n params: AttachParams,\n ): Promise<Response> {\n const sessionId = params.sessionId!;\n const namespace = params.namespace;\n\n // Check if session exists in disconnected sessions\n const disconnected = this.disconnectedSessions.get(sessionId);\n if (disconnected) {\n const session = disconnected.session;\n\n // Verify namespace matches\n if (session.namespace !== namespace) {\n return {\n type: \"response\",\n id: request.id,\n error: {\n code: \"invalid_session\",\n message: \"Session ID does not match namespace\",\n },\n };\n }\n\n // Cancel timeout\n clearTimeout(disconnected.timeoutId);\n this.disconnectedSessions.delete(sessionId);\n\n // Reattach session\n session.setState(\"attached\");\n this.sessions.set(session.id, session);\n this.namespaces.set(session.namespace, session);\n this.sessionToConnection.set(session.id, state);\n state.session = session;\n state.attached = true;\n\n // Start heartbeat\n this.startHeartbeat(state);\n\n return {\n type: \"response\",\n id: request.id,\n result: {\n sessionId: session.id,\n namespace: session.namespace,\n },\n };\n }\n\n // Check if session is currently active (invalid - can't reconnect to active session)\n const activeSession = this.sessions.get(sessionId);\n if (activeSession) {\n // Verify namespace matches\n if (activeSession.namespace !== namespace) {\n return {\n type: \"response\",\n id: request.id,\n error: {\n code: \"invalid_session\",\n message: \"Session ID does not match namespace\",\n },\n };\n }\n\n // Session is active, can't reconnect\n return {\n type: \"response\",\n id: request.id,\n error: {\n code: \"invalid_session\",\n message: \"Session is already active\",\n },\n };\n }\n\n // Session not found\n return {\n type: \"response\",\n id: request.id,\n error: {\n code: \"invalid_session\",\n message: \"Session not found or expired\",\n },\n };\n }\n\n /**\n * Start heartbeat for a connection.\n */\n private startHeartbeat(state: ConnectionState): void {\n if (this.options.heartbeatInterval <= 0) {\n return;\n }\n\n state.lastPong = Date.now();\n\n state.heartbeatTimer = setInterval(() => {\n // Check timeout\n const elapsed = Date.now() - state.lastPong;\n if (elapsed > this.options.heartbeatTimeout) {\n // Heartbeat timeout - disconnect\n this.handleHeartbeatTimeout(state);\n return;\n }\n\n // Send ping\n this.sendEvent(state.transport, {\n type: \"event\",\n event: \"session.ping\",\n data: { timestamp: Date.now() },\n }).catch((err) => {\n console.error(\"Error sending ping:\", err);\n });\n }, this.options.heartbeatInterval);\n }\n\n /**\n * Handle heartbeat timeout.\n */\n private handleHeartbeatTimeout(state: ConnectionState): void {\n if (state.heartbeatTimer) {\n clearInterval(state.heartbeatTimer);\n state.heartbeatTimer = undefined;\n }\n\n // Force disconnect\n this.handleDisconnect(state);\n state.transport.close().catch(() => {\n // Ignore close errors\n });\n }\n\n /**\n * Handle session.detach request.\n */\n private async handleDetach(state: ConnectionState, request: Request): Promise<Response> {\n if (!state.attached || !state.session) {\n return {\n type: \"response\",\n id: request.id,\n error: { code: \"invalid_session\", message: \"Not attached to a session\" },\n };\n }\n\n const session = state.session;\n\n // Stop heartbeat\n if (state.heartbeatTimer) {\n clearInterval(state.heartbeatTimer);\n state.heartbeatTimer = undefined;\n }\n\n session.setState(\"disconnected\");\n this.sessions.delete(session.id);\n this.namespaces.delete(session.namespace);\n this.sessionToConnection.delete(session.id);\n state.session = undefined;\n state.attached = false;\n\n return {\n type: \"response\",\n id: request.id,\n result: {},\n };\n }\n\n /**\n * Handle AFS request (passthrough to client).\n */\n private async handleAfsRequest(state: ConnectionState, request: Request): Promise<Response> {\n if (!state.attached) {\n return {\n type: \"response\",\n id: request.id,\n error: { code: \"invalid_session\", message: \"Must attach before sending AFS requests\" },\n };\n }\n\n // TODO: Implement passthrough to the client's AFS\n // For now, return not implemented\n return {\n type: \"response\",\n id: request.id,\n error: { code: \"not_implemented\", message: \"AFS passthrough not yet implemented\" },\n };\n }\n\n /**\n * Handle transport disconnect.\n */\n private handleDisconnect(state: ConnectionState): void {\n // Stop heartbeat\n if (state.heartbeatTimer) {\n clearInterval(state.heartbeatTimer);\n state.heartbeatTimer = undefined;\n }\n\n if (state.session) {\n const session = state.session;\n session.setState(\"disconnected\");\n\n // Remove from active\n this.sessions.delete(session.id);\n this.namespaces.delete(session.namespace);\n this.sessionToConnection.delete(session.id);\n\n // Start grace period for reconnection\n if (this.options.sessionTimeout > 0) {\n const timeoutId = setTimeout(() => {\n // Session expired\n this.disconnectedSessions.delete(session.id);\n }, this.options.sessionTimeout);\n\n this.disconnectedSessions.set(session.id, {\n session,\n disconnectedAt: Date.now(),\n timeoutId,\n });\n }\n }\n this.connections.delete(state.transport);\n }\n\n /**\n * Send response back to client.\n */\n private async sendResponse(transport: Transport, response: Response): Promise<void> {\n const payload = serializeMessage(response);\n await transport.send({\n type: FrameType.JSON,\n reqId: Number.parseInt(response.id, 10),\n payload,\n });\n }\n\n /**\n * Send event to client.\n */\n private async sendEvent(transport: Transport, event: Event): Promise<void> {\n const payload = serializeMessage(event);\n await transport.send({\n type: FrameType.JSON,\n reqId: 0, // Events use reqId=0\n payload,\n });\n }\n\n /**\n * Get all active sessions.\n */\n getSessions(): Session[] {\n return Array.from(this.sessions.values());\n }\n\n /**\n * Close the session host and all sessions.\n */\n async close(): Promise<void> {\n // Clear all heartbeat timers\n for (const state of this.connections.values()) {\n if (state.heartbeatTimer) {\n clearInterval(state.heartbeatTimer);\n }\n }\n\n // Clear all reconnect timeouts\n for (const disconnected of this.disconnectedSessions.values()) {\n clearTimeout(disconnected.timeoutId);\n }\n\n for (const state of this.connections.values()) {\n await state.transport.close();\n }\n this.connections.clear();\n this.sessions.clear();\n this.namespaces.clear();\n this.sessionToConnection.clear();\n this.disconnectedSessions.clear();\n }\n}\n","import type { Frame } from \"../protocol/types.js\";\n\n/**\n * Transport layer events\n */\nexport interface TransportEvents {\n frame: (frame: Frame) => void;\n error: (error: Error) => void;\n close: () => void;\n}\n\n/**\n * Abstract transport interface for sending/receiving frames.\n * Transport is responsible only for:\n * - Establishing connections\n * - Transmitting frames\n * - Handling binary data\n *\n * Transport does NOT:\n * - Know about AFS operations\n * - Validate request content\n * - Handle business logic\n */\nexport interface Transport {\n /**\n * Send a frame over the transport.\n */\n send(frame: Frame): Promise<void>;\n\n /**\n * Close the transport connection.\n */\n close(): Promise<void>;\n\n /**\n * Register event handler.\n */\n on<E extends keyof TransportEvents>(event: E, handler: TransportEvents[E]): void;\n\n /**\n * Unregister event handler.\n */\n off<E extends keyof TransportEvents>(event: E, handler: TransportEvents[E]): void;\n\n /**\n * Whether the transport is connected.\n */\n readonly connected: boolean;\n}\n\n/**\n * Server-side transport that can accept multiple connections.\n */\nexport interface TransportServer {\n /**\n * Start listening for connections.\n */\n listen(): Promise<void>;\n\n /**\n * Stop listening and close all connections.\n */\n close(): Promise<void>;\n\n /**\n * Event when a new connection is established.\n */\n onConnection(handler: (transport: Transport) => void): void;\n\n /**\n * Whether the server is listening.\n */\n readonly listening: boolean;\n}\n\n/**\n * Options for Unix Socket transport.\n */\nexport interface UnixSocketOptions {\n /**\n * Path to the Unix socket file.\n * Default: ~/.afs/observer.sock\n */\n socketPath?: string;\n\n /**\n * Maximum number of pending connections.\n * Default: 100\n */\n backlog?: number;\n}\n\n/**\n * Default socket path\n */\nexport const DEFAULT_SOCKET_PATH = \"~/.afs/observer.sock\";\n\n/**\n * Options for WebSocket transport.\n */\nexport interface WebSocketOptions {\n /**\n * Host to bind/connect to.\n * Default: \"localhost\"\n */\n host?: string;\n\n /**\n * Port to bind/connect to.\n * Default: 9999\n */\n port?: number;\n\n /**\n * Authentication token.\n * Required for secure connections.\n */\n authToken?: string;\n\n /**\n * Maximum number of connections (server only).\n * Default: 100\n */\n maxConnections?: number;\n}\n\n/**\n * Default WebSocket port\n */\nexport const DEFAULT_WS_PORT = 9999;\n","import * as fs from \"node:fs\";\nimport type * as net from \"node:net\";\nimport * as path from \"node:path\";\nimport { encodeFrame } from \"../protocol/frame.js\";\nimport { FrameDecoder } from \"../protocol/frame-decoder.js\";\nimport type { Frame } from \"../protocol/types.js\";\nimport type { Transport, TransportEvents, TransportServer, UnixSocketOptions } from \"./types.js\";\n\n/**\n * Expand ~ to home directory\n */\nfunction expandPath(p: string): string {\n if (p.startsWith(\"~/\")) {\n const home = process.env.HOME || process.env.USERPROFILE || \"/\";\n return path.join(home, p.slice(2));\n }\n return p;\n}\n\n/**\n * Error for Unix socket operations\n */\nexport class UnixSocketError extends Error {\n constructor(\n public readonly code: string,\n message: string,\n ) {\n super(message);\n this.name = \"UnixSocketError\";\n }\n}\n\ntype EventCallback = (...args: any[]) => void;\n\n/**\n * Unix socket transport implementation.\n */\nexport class UnixSocketTransport implements Transport {\n private socket: net.Socket;\n private decoder = new FrameDecoder();\n private handlers: Map<keyof TransportEvents, Set<EventCallback>> = new Map();\n private _connected = false;\n\n constructor(socket: net.Socket) {\n this.socket = socket;\n this._connected = true;\n this.setupHandlers();\n }\n\n private setupHandlers(): void {\n this.socket.on(\"data\", (data: Buffer) => {\n try {\n const frames = this.decoder.push(new Uint8Array(data));\n for (const frame of frames) {\n this.emit(\"frame\", frame);\n }\n } catch (error) {\n this.emit(\"error\", error as Error);\n }\n });\n\n this.socket.on(\"close\", () => {\n this._connected = false;\n this.emit(\"close\");\n });\n\n this.socket.on(\"error\", (error: Error) => {\n this.emit(\"error\", error);\n });\n }\n\n async send(frame: Frame): Promise<void> {\n if (!this._connected) {\n throw new UnixSocketError(\"not_connected\", \"Transport is not connected\");\n }\n\n const encoded = encodeFrame(frame.type, frame.reqId, frame.payload);\n return new Promise((resolve, reject) => {\n this.socket.write(Buffer.from(encoded), (err) => {\n if (err) reject(err);\n else resolve();\n });\n });\n }\n\n async close(): Promise<void> {\n return new Promise((resolve) => {\n if (!this._connected) {\n resolve();\n return;\n }\n\n this.socket.end(() => {\n this._connected = false;\n resolve();\n });\n });\n }\n\n on<E extends keyof TransportEvents>(event: E, handler: TransportEvents[E]): void {\n if (!this.handlers.has(event)) {\n this.handlers.set(event, new Set());\n }\n this.handlers.get(event)!.add(handler);\n }\n\n off<E extends keyof TransportEvents>(event: E, handler: TransportEvents[E]): void {\n this.handlers.get(event)?.delete(handler);\n }\n\n private emit<E extends keyof TransportEvents>(\n event: E,\n ...args: Parameters<TransportEvents[E]>\n ): void {\n const handlers = this.handlers.get(event);\n if (handlers) {\n for (const handler of handlers) {\n handler(...args);\n }\n }\n }\n\n get connected(): boolean {\n return this._connected;\n }\n}\n\n/**\n * Options for Unix socket server\n */\nexport interface UnixSocketServerOptions extends UnixSocketOptions {\n maxConnections?: number;\n}\n\n/**\n * Unix socket server implementation.\n */\nexport class UnixSocketServer implements TransportServer {\n private server: net.Server | null = null;\n private socketPath: string;\n private maxConnections: number;\n private connections: Set<UnixSocketTransport> = new Set();\n private connectionHandler?: (transport: Transport) => void;\n private _listening = false;\n\n constructor(options: UnixSocketServerOptions = {}) {\n this.socketPath = expandPath(options.socketPath || \"~/.afs/observer.sock\");\n this.maxConnections = options.maxConnections ?? 100;\n }\n\n async listen(): Promise<void> {\n // Check for symlink (security)\n try {\n const stat = fs.lstatSync(this.socketPath);\n if (stat.isSymbolicLink()) {\n throw new UnixSocketError(\n \"symlink_not_allowed\",\n `Socket path is a symlink: ${this.socketPath}`,\n );\n }\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code !== \"ENOENT\") {\n if (e instanceof UnixSocketError) throw e;\n // Other stat errors are ok\n }\n }\n\n // Create directory if needed\n const dir = path.dirname(this.socketPath);\n fs.mkdirSync(dir, { recursive: true });\n\n // Remove existing socket file\n try {\n fs.unlinkSync(this.socketPath);\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code !== \"ENOENT\") {\n // Permission or other error\n throw new UnixSocketError(\n \"remove_failed\",\n `Failed to remove existing socket: ${(e as Error).message}`,\n );\n }\n }\n\n // Import net module dynamically to avoid bundling issues\n const net = await import(\"node:net\");\n\n return new Promise((resolve, reject) => {\n this.server = net.createServer((socket) => {\n // Check max connections\n if (this.connections.size >= this.maxConnections) {\n socket.end();\n socket.destroy();\n return;\n }\n\n const transport = new UnixSocketTransport(socket);\n this.connections.add(transport);\n\n transport.on(\"close\", () => {\n this.connections.delete(transport);\n });\n\n this.connectionHandler?.(transport);\n });\n\n this.server.on(\"error\", (err) => {\n reject(err);\n });\n\n this.server.listen(this.socketPath, () => {\n this._listening = true;\n resolve();\n });\n });\n }\n\n async close(): Promise<void> {\n if (!this.server) return;\n\n // Close all connections\n for (const conn of this.connections) {\n await conn.close();\n }\n this.connections.clear();\n\n return new Promise((resolve) => {\n this.server!.close(() => {\n this._listening = false;\n\n // Remove socket file\n try {\n fs.unlinkSync(this.socketPath);\n } catch {\n // Ignore\n }\n\n resolve();\n });\n });\n }\n\n onConnection(handler: (transport: Transport) => void): void {\n this.connectionHandler = handler;\n }\n\n get listening(): boolean {\n return this._listening;\n }\n}\n\n/**\n * Unix socket client implementation.\n */\nexport class UnixSocketClient implements Transport {\n private socket: net.Socket | null = null;\n private transport: UnixSocketTransport | null = null;\n private socketPath: string;\n private handlers: Map<keyof TransportEvents, Set<EventCallback>> = new Map();\n\n constructor(options: UnixSocketOptions = {}) {\n this.socketPath = expandPath(options.socketPath || \"~/.afs/observer.sock\");\n }\n\n async connect(): Promise<void> {\n const net = await import(\"node:net\");\n\n return new Promise((resolve, reject) => {\n this.socket = net.connect(this.socketPath, () => {\n this.transport = new UnixSocketTransport(this.socket!);\n\n // Forward events\n this.transport.on(\"frame\", (frame) => this.emit(\"frame\", frame));\n this.transport.on(\"error\", (error) => this.emit(\"error\", error));\n this.transport.on(\"close\", () => this.emit(\"close\"));\n\n resolve();\n });\n\n this.socket.on(\"error\", (err) => {\n reject(err);\n });\n });\n }\n\n async send(frame: Frame): Promise<void> {\n if (!this.transport) {\n throw new UnixSocketError(\"not_connected\", \"Client is not connected\");\n }\n return this.transport.send(frame);\n }\n\n async close(): Promise<void> {\n if (this.transport) {\n await this.transport.close();\n }\n this.socket = null;\n this.transport = null;\n }\n\n on<E extends keyof TransportEvents>(event: E, handler: TransportEvents[E]): void {\n if (!this.handlers.has(event)) {\n this.handlers.set(event, new Set());\n }\n this.handlers.get(event)!.add(handler);\n }\n\n off<E extends keyof TransportEvents>(event: E, handler: TransportEvents[E]): void {\n this.handlers.get(event)?.delete(handler);\n }\n\n private emit<E extends keyof TransportEvents>(\n event: E,\n ...args: Parameters<TransportEvents[E]>\n ): void {\n const handlers = this.handlers.get(event);\n if (handlers) {\n for (const handler of handlers) {\n handler(...args);\n }\n }\n }\n\n get connected(): boolean {\n return this.transport?.connected ?? false;\n }\n}\n","import * as crypto from \"node:crypto\";\nimport { encodeFrame } from \"../protocol/frame.js\";\nimport { FrameDecoder } from \"../protocol/frame-decoder.js\";\nimport type { Frame } from \"../protocol/types.js\";\nimport type { Transport, TransportEvents, TransportServer, WebSocketOptions } from \"./types.js\";\n\ntype EventCallback = (...args: any[]) => void;\n\n/**\n * Error for WebSocket operations\n */\nexport class WebSocketError extends Error {\n constructor(\n public readonly code: string,\n message: string,\n ) {\n super(message);\n this.name = \"WebSocketError\";\n }\n}\n\n/**\n * Constant-time string comparison to prevent timing attacks\n */\nfunction secureCompare(a: string, b: string): boolean {\n if (a.length !== b.length) {\n // Still do comparison to maintain constant time\n crypto.timingSafeEqual(Buffer.from(a), Buffer.from(a));\n return false;\n }\n return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));\n}\n\n/**\n * Rate limiter for auth attempts\n */\nclass AuthRateLimiter {\n private attempts: Map<string, { count: number; resetAt: number }> = new Map();\n private maxAttempts = 5;\n private windowMs = 60000; // 1 minute\n\n isRateLimited(ip: string): boolean {\n const now = Date.now();\n const record = this.attempts.get(ip);\n\n if (!record || record.resetAt < now) {\n return false;\n }\n\n return record.count >= this.maxAttempts;\n }\n\n recordAttempt(ip: string): void {\n const now = Date.now();\n const record = this.attempts.get(ip);\n\n if (!record || record.resetAt < now) {\n this.attempts.set(ip, { count: 1, resetAt: now + this.windowMs });\n } else {\n record.count++;\n }\n }\n\n recordSuccess(ip: string): void {\n this.attempts.delete(ip);\n }\n}\n\n/**\n * WebSocket transport for server-side (Bun WebSocket).\n * Wraps Bun's ServerWebSocket to provide Transport interface.\n */\nexport class WebSocketTransport implements Transport {\n private ws: any; // Bun.ServerWebSocket\n private decoder = new FrameDecoder();\n private handlers: Map<keyof TransportEvents, Set<EventCallback>> = new Map();\n private _connected = true;\n\n constructor(ws: any) {\n this.ws = ws;\n }\n\n /**\n * Called by server when message is received.\n */\n handleMessage(data: ArrayBuffer | Uint8Array): void {\n try {\n const bytes = data instanceof ArrayBuffer ? new Uint8Array(data) : data;\n const frames = this.decoder.push(bytes);\n for (const frame of frames) {\n this.emit(\"frame\", frame);\n }\n } catch (error) {\n this.emit(\"error\", error as Error);\n }\n }\n\n /**\n * Called by server when connection closes.\n */\n handleClose(): void {\n this._connected = false;\n this.emit(\"close\");\n }\n\n /**\n * Called by server when error occurs.\n */\n handleError(error: Error): void {\n this.emit(\"error\", error);\n }\n\n async send(frame: Frame): Promise<void> {\n if (!this._connected) {\n throw new WebSocketError(\"not_connected\", \"Transport is not connected\");\n }\n\n const encoded = encodeFrame(frame.type, frame.reqId, frame.payload);\n this.ws.sendBinary(encoded);\n }\n\n async close(): Promise<void> {\n if (this._connected) {\n this.ws.close();\n this._connected = false;\n }\n }\n\n on<E extends keyof TransportEvents>(event: E, handler: TransportEvents[E]): void {\n if (!this.handlers.has(event)) {\n this.handlers.set(event, new Set());\n }\n this.handlers.get(event)!.add(handler);\n }\n\n off<E extends keyof TransportEvents>(event: E, handler: TransportEvents[E]): void {\n this.handlers.get(event)?.delete(handler);\n }\n\n private emit<E extends keyof TransportEvents>(\n event: E,\n ...args: Parameters<TransportEvents[E]>\n ): void {\n const handlers = this.handlers.get(event);\n if (handlers) {\n for (const handler of handlers) {\n handler(...args);\n }\n }\n }\n\n get connected(): boolean {\n return this._connected;\n }\n}\n\n/**\n * WebSocket server implementation using Bun.serve.\n */\nexport class WebSocketServer implements TransportServer {\n private server: any = null; // Bun.Server\n private host: string;\n private port: number;\n private authToken?: string;\n private maxConnections: number;\n private connections: Set<WebSocketTransport> = new Set();\n private wsToTransport: Map<any, WebSocketTransport> = new Map();\n private connectionHandler?: (transport: Transport) => void;\n private _listening = false;\n private rateLimiter = new AuthRateLimiter();\n\n constructor(options: WebSocketOptions = {}) {\n this.host = options.host || \"localhost\";\n this.port = options.port || 9999;\n this.authToken = options.authToken;\n this.maxConnections = options.maxConnections ?? 100;\n }\n\n async listen(): Promise<void> {\n const self = this;\n\n this.server = Bun.serve<{ ip: string }>({\n hostname: this.host,\n port: this.port,\n fetch(req, server) {\n // Extract client IP for rate limiting\n const ip = server.requestIP(req)?.address || \"unknown\";\n\n // Check rate limiting\n if (self.authToken && self.rateLimiter.isRateLimited(ip)) {\n return new Response(\"Too many auth attempts\", { status: 429 });\n }\n\n // Check authentication if required\n if (self.authToken) {\n // Token can be in Authorization header or query string\n const url = new URL(req.url);\n const queryToken = url.searchParams.get(\"token\");\n const authHeader = req.headers.get(\"Authorization\");\n const headerToken = authHeader?.startsWith(\"Bearer \") ? authHeader.slice(7) : null;\n\n const providedToken = headerToken || queryToken;\n\n if (!providedToken) {\n self.rateLimiter.recordAttempt(ip);\n return new Response(\"Authentication required\", { status: 401 });\n }\n\n if (!secureCompare(providedToken, self.authToken)) {\n self.rateLimiter.recordAttempt(ip);\n return new Response(\"Authentication failed\", { status: 403 });\n }\n\n // Successful auth\n self.rateLimiter.recordSuccess(ip);\n }\n\n // Check max connections\n if (self.connections.size >= self.maxConnections) {\n return new Response(\"Too many connections\", { status: 503 });\n }\n\n // Upgrade to WebSocket\n const success = server.upgrade(req, {\n data: { ip },\n });\n\n if (!success) {\n return new Response(\"WebSocket upgrade failed\", { status: 400 });\n }\n\n return undefined;\n },\n websocket: {\n open(ws: any) {\n const transport = new WebSocketTransport(ws);\n self.connections.add(transport);\n self.wsToTransport.set(ws, transport);\n\n transport.on(\"close\", () => {\n self.connections.delete(transport);\n self.wsToTransport.delete(ws);\n });\n\n self.connectionHandler?.(transport);\n },\n message(ws: any, message: string | ArrayBuffer | Buffer) {\n const transport = self.wsToTransport.get(ws);\n if (transport) {\n // Convert message to Uint8Array\n const data =\n typeof message === \"string\"\n ? new TextEncoder().encode(message)\n : message instanceof ArrayBuffer\n ? new Uint8Array(message)\n : new Uint8Array((message as Buffer).buffer);\n transport.handleMessage(data);\n }\n },\n close(ws: any) {\n const transport = self.wsToTransport.get(ws);\n if (transport) {\n transport.handleClose();\n self.connections.delete(transport);\n self.wsToTransport.delete(ws);\n }\n },\n // Note: Bun WebSocket doesn't have error handler, errors are logged by Bun\n perMessageDeflate: false,\n },\n });\n\n this._listening = true;\n }\n\n async close(): Promise<void> {\n // Close all connections\n for (const conn of this.connections) {\n await conn.close();\n }\n this.connections.clear();\n this.wsToTransport.clear();\n\n if (this.server) {\n this.server.stop();\n this._listening = false;\n }\n }\n\n onConnection(handler: (transport: Transport) => void): void {\n this.connectionHandler = handler;\n }\n\n get listening(): boolean {\n return this._listening;\n }\n\n get address(): string {\n return `ws://${this.host}:${this.port}`;\n }\n}\n\n/**\n * WebSocket client transport (uses browser WebSocket API).\n */\nclass ClientWebSocketTransport implements Transport {\n private ws: WebSocket;\n private decoder = new FrameDecoder();\n private handlers: Map<keyof TransportEvents, Set<EventCallback>> = new Map();\n private _connected = false;\n\n constructor(ws: WebSocket) {\n this.ws = ws;\n this._connected = ws.readyState === WebSocket.OPEN;\n this.setupHandlers();\n }\n\n private setupHandlers(): void {\n this.ws.onmessage = (event) => {\n try {\n // Handle binary data\n const data =\n event.data instanceof ArrayBuffer\n ? new Uint8Array(event.data)\n : typeof event.data === \"string\"\n ? new TextEncoder().encode(event.data)\n : new Uint8Array(event.data);\n\n const frames = this.decoder.push(data);\n for (const frame of frames) {\n this.emit(\"frame\", frame);\n }\n } catch (error) {\n this.emit(\"error\", error as Error);\n }\n };\n\n this.ws.onclose = () => {\n this._connected = false;\n this.emit(\"close\");\n };\n\n this.ws.onerror = () => {\n this.emit(\"error\", new Error(\"WebSocket error\"));\n };\n\n this.ws.onopen = () => {\n this._connected = true;\n };\n }\n\n async send(frame: Frame): Promise<void> {\n if (!this._connected) {\n throw new WebSocketError(\"not_connected\", \"Transport is not connected\");\n }\n\n const encoded = encodeFrame(frame.type, frame.reqId, frame.payload);\n this.ws.send(encoded);\n }\n\n async close(): Promise<void> {\n if (this._connected) {\n this.ws.close();\n this._connected = false;\n }\n }\n\n on<E extends keyof TransportEvents>(event: E, handler: TransportEvents[E]): void {\n if (!this.handlers.has(event)) {\n this.handlers.set(event, new Set());\n }\n this.handlers.get(event)!.add(handler);\n }\n\n off<E extends keyof TransportEvents>(event: E, handler: TransportEvents[E]): void {\n this.handlers.get(event)?.delete(handler);\n }\n\n private emit<E extends keyof TransportEvents>(\n event: E,\n ...args: Parameters<TransportEvents[E]>\n ): void {\n const handlers = this.handlers.get(event);\n if (handlers) {\n for (const handler of handlers) {\n handler(...args);\n }\n }\n }\n\n get connected(): boolean {\n return this._connected;\n }\n}\n\n/**\n * WebSocket client implementation.\n */\nexport class WebSocketClient implements Transport {\n private ws: WebSocket | null = null;\n private transport: ClientWebSocketTransport | null = null;\n private host: string;\n private port: number;\n private authToken?: string;\n private handlers: Map<keyof TransportEvents, Set<EventCallback>> = new Map();\n\n constructor(options: WebSocketOptions = {}) {\n this.host = options.host || \"localhost\";\n this.port = options.port || 9999;\n this.authToken = options.authToken;\n }\n\n async connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n // Build URL with optional token\n let url = `ws://${this.host}:${this.port}`;\n if (this.authToken) {\n url += `?token=${encodeURIComponent(this.authToken)}`;\n }\n\n this.ws = new WebSocket(url);\n this.ws.binaryType = \"arraybuffer\";\n\n this.ws.onopen = () => {\n this.transport = new ClientWebSocketTransport(this.ws!);\n\n // Forward events\n this.transport.on(\"frame\", (frame) => this.emit(\"frame\", frame));\n this.transport.on(\"error\", (error) => this.emit(\"error\", error));\n this.transport.on(\"close\", () => this.emit(\"close\"));\n\n resolve();\n };\n\n this.ws.onerror = () => {\n reject(new WebSocketError(\"connection_failed\", \"Failed to connect\"));\n };\n\n this.ws.onclose = (event) => {\n if (!this.transport) {\n // Connection failed before open\n if (event.code === 1002 || event.code === 1008) {\n reject(new WebSocketError(\"auth_failed\", \"Authentication failed\"));\n } else {\n reject(new WebSocketError(\"connection_failed\", \"Connection closed\"));\n }\n }\n };\n });\n }\n\n async send(frame: Frame): Promise<void> {\n if (!this.transport) {\n throw new WebSocketError(\"not_connected\", \"Client is not connected\");\n }\n return this.transport.send(frame);\n }\n\n async close(): Promise<void> {\n if (this.transport) {\n await this.transport.close();\n }\n this.ws = null;\n this.transport = null;\n }\n\n on<E extends keyof TransportEvents>(event: E, handler: TransportEvents[E]): void {\n if (!this.handlers.has(event)) {\n this.handlers.set(event, new Set());\n }\n this.handlers.get(event)!.add(handler);\n }\n\n off<E extends keyof TransportEvents>(event: E, handler: TransportEvents[E]): void {\n this.handlers.get(event)?.delete(handler);\n }\n\n private emit<E extends keyof TransportEvents>(\n event: E,\n ...args: Parameters<TransportEvents[E]>\n ): void {\n const handlers = this.handlers.get(event);\n if (handlers) {\n for (const handler of handlers) {\n handler(...args);\n }\n }\n }\n\n get connected(): boolean {\n return this.transport?.connected ?? false;\n }\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@aigne/afs-session",
3
+ "version": "1.11.0-beta.10",
4
+ "description": "AFS Session Protocol - Transport layer for AFS Explorer Observer architecture",
5
+ "license": "UNLICENSED",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "author": "Arcblock <blocklet@arcblock.io> https://github.com/arcblock",
10
+ "homepage": "https://github.com/arcblock/afs",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/arcblock/afs"
14
+ },
15
+ "bugs": {
16
+ "url": "https://github.com/arcblock/afs/issues"
17
+ },
18
+ "type": "module",
19
+ "main": "./dist/index.cjs",
20
+ "module": "./dist/index.mjs",
21
+ "types": "./dist/index.d.cts",
22
+ "exports": {
23
+ ".": {
24
+ "require": "./dist/index.cjs",
25
+ "import": "./dist/index.mjs"
26
+ },
27
+ "./protocol": {
28
+ "require": "./dist/protocol/index.cjs",
29
+ "import": "./dist/protocol/index.mjs"
30
+ },
31
+ "./*": "./*"
32
+ },
33
+ "files": [
34
+ "dist",
35
+ "LICENSE",
36
+ "README.md",
37
+ "CHANGELOG.md"
38
+ ],
39
+ "dependencies": {
40
+ "zod": "^4.0.0",
41
+ "@aigne/afs": "1.11.0-beta.10"
42
+ },
43
+ "devDependencies": {
44
+ "@types/bun": "^1.3.6",
45
+ "npm-run-all": "^4.1.5",
46
+ "rimraf": "^6.1.2",
47
+ "tsdown": "0.20.0-beta.3",
48
+ "typescript": "5.9.2",
49
+ "@aigne/scripts": "0.0.0",
50
+ "@aigne/typescript-config": "0.0.0"
51
+ },
52
+ "scripts": {
53
+ "build": "tsdown",
54
+ "check-types": "tsc --noEmit",
55
+ "clean": "rimraf dist coverage",
56
+ "test": "bun test",
57
+ "test:coverage": "bun test --coverage --coverage-reporter=lcov --coverage-reporter=text"
58
+ }
59
+ }