Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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