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
8 changes: 1 addition & 7 deletions packages/cloud/src/WebAuthService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ export class WebAuthService extends EventEmitter<AuthServiceEvents> implements A
private changeState(newState: AuthState): void {
const previousState = this.state
this.state = newState
this.log(`[auth] changeState: ${previousState} -> ${newState}`)
this.emit("auth-state-changed", { state: newState, previousState })
}

Expand Down Expand Up @@ -162,8 +163,6 @@ export class WebAuthService extends EventEmitter<AuthServiceEvents> implements A
this.userInfo = null

this.changeState("logged-out")

this.log("[auth] Transitioned to logged-out state")
}

private transitionToAttemptingSession(credentials: AuthCredentials): void {
Expand All @@ -176,17 +175,13 @@ export class WebAuthService extends EventEmitter<AuthServiceEvents> implements A
this.changeState("attempting-session")

this.timer.start()

this.log("[auth] Transitioned to attempting-session state")
}

private transitionToInactiveSession(): void {
this.sessionToken = null
this.userInfo = null

this.changeState("inactive-session")

this.log("[auth] Transitioned to inactive-session state")
}

/**
Expand Down Expand Up @@ -422,7 +417,6 @@ export class WebAuthService extends EventEmitter<AuthServiceEvents> implements A

if (previousState !== "active-session") {
this.changeState("active-session")
this.log("[auth] Transitioned to active-session state")
this.fetchUserInfo()
} else {
this.state = "active-session"
Expand Down
109 changes: 109 additions & 0 deletions packages/cloud/src/bridge/BaseChannel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import type { Socket } from "socket.io-client"

/**
* Abstract base class for communication channels in the bridge system.
* Provides common functionality for bidirectional communication between
* the VSCode extension and web application.
*
* @template TCommand - Type of commands this channel can receive.
* @template TEvent - Type of events this channel can publish.
*/
export abstract class BaseChannel<TCommand = unknown, TEventName extends string = string, TEventData = unknown> {
protected socket: Socket | null = null
protected readonly instanceId: string

constructor(instanceId: string) {
this.instanceId = instanceId
}

/**
* Called when socket connects.
*/
public async onConnect(socket: Socket): Promise<void> {
this.socket = socket
await this.handleConnect(socket)
}

/**
* Called when socket disconnects.
*/
public onDisconnect(): void {
this.socket = null
this.handleDisconnect()
}

/**
* Called when socket reconnects.
*/
public async onReconnect(socket: Socket): Promise<void> {
this.socket = socket
await this.handleReconnect(socket)
}

/**
* Cleanup resources.
*/
public async cleanup(socket: Socket | null): Promise<void> {
if (socket) {
await this.handleCleanup(socket)
}

this.socket = null
}

/**
* Emit a socket event with error handling.
*/
protected publish<Params extends object>(
eventName: TEventName,
data: TEventData,
callback?: (params: Params) => void,
): boolean {
if (!this.socket) {
console.error(`[${this.constructor.name}#emit] socket not available for ${eventName}`)
return false
}

try {
// console.log(`[${this.constructor.name}#emit] emit() -> ${eventName}`, data)
this.socket.emit(eventName, data, callback)

return true
} catch (error) {
console.error(
`[${this.constructor.name}#emit] emit() failed -> ${eventName}: ${
error instanceof Error ? error.message : String(error)
}`,
)

return false
}
}

/**
* Handle incoming commands - must be implemented by subclasses.
*/
public abstract handleCommand(command: TCommand): void

/**
* Handle connection-specific logic.
*/
protected abstract handleConnect(socket: Socket): Promise<void>

/**
* Handle disconnection-specific logic.
*/
protected handleDisconnect(): void {
// Default implementation - can be overridden.
}

/**
* Handle reconnection-specific logic.
*/
protected abstract handleReconnect(socket: Socket): Promise<void>

/**
* Handle cleanup-specific logic.
*/
protected abstract handleCleanup(socket: Socket): Promise<void>
}
Loading
Loading