Skip to content

Commit 1e4c46f

Browse files
authored
Refactor the extension bridge (#7515)
1 parent cd9e92f commit 1e4c46f

24 files changed

+1647
-1061
lines changed

packages/cloud/src/WebAuthService.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ export class WebAuthService extends EventEmitter<AuthServiceEvents> implements A
129129
private changeState(newState: AuthState): void {
130130
const previousState = this.state
131131
this.state = newState
132+
this.log(`[auth] changeState: ${previousState} -> ${newState}`)
132133
this.emit("auth-state-changed", { state: newState, previousState })
133134
}
134135

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

164165
this.changeState("logged-out")
165-
166-
this.log("[auth] Transitioned to logged-out state")
167166
}
168167

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

178177
this.timer.start()
179-
180-
this.log("[auth] Transitioned to attempting-session state")
181178
}
182179

183180
private transitionToInactiveSession(): void {
184181
this.sessionToken = null
185182
this.userInfo = null
186183

187184
this.changeState("inactive-session")
188-
189-
this.log("[auth] Transitioned to inactive-session state")
190185
}
191186

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

423418
if (previousState !== "active-session") {
424419
this.changeState("active-session")
425-
this.log("[auth] Transitioned to active-session state")
426420
this.fetchUserInfo()
427421
} else {
428422
this.state = "active-session"
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import type { Socket } from "socket.io-client"
2+
3+
/**
4+
* Abstract base class for communication channels in the bridge system.
5+
* Provides common functionality for bidirectional communication between
6+
* the VSCode extension and web application.
7+
*
8+
* @template TCommand - Type of commands this channel can receive.
9+
* @template TEvent - Type of events this channel can publish.
10+
*/
11+
export abstract class BaseChannel<TCommand = unknown, TEventName extends string = string, TEventData = unknown> {
12+
protected socket: Socket | null = null
13+
protected readonly instanceId: string
14+
15+
constructor(instanceId: string) {
16+
this.instanceId = instanceId
17+
}
18+
19+
/**
20+
* Called when socket connects.
21+
*/
22+
public async onConnect(socket: Socket): Promise<void> {
23+
this.socket = socket
24+
await this.handleConnect(socket)
25+
}
26+
27+
/**
28+
* Called when socket disconnects.
29+
*/
30+
public onDisconnect(): void {
31+
this.socket = null
32+
this.handleDisconnect()
33+
}
34+
35+
/**
36+
* Called when socket reconnects.
37+
*/
38+
public async onReconnect(socket: Socket): Promise<void> {
39+
this.socket = socket
40+
await this.handleReconnect(socket)
41+
}
42+
43+
/**
44+
* Cleanup resources.
45+
*/
46+
public async cleanup(socket: Socket | null): Promise<void> {
47+
if (socket) {
48+
await this.handleCleanup(socket)
49+
}
50+
51+
this.socket = null
52+
}
53+
54+
/**
55+
* Emit a socket event with error handling.
56+
*/
57+
protected publish<Params extends object>(
58+
eventName: TEventName,
59+
data: TEventData,
60+
callback?: (params: Params) => void,
61+
): boolean {
62+
if (!this.socket) {
63+
console.error(`[${this.constructor.name}#emit] socket not available for ${eventName}`)
64+
return false
65+
}
66+
67+
try {
68+
// console.log(`[${this.constructor.name}#emit] emit() -> ${eventName}`, data)
69+
this.socket.emit(eventName, data, callback)
70+
71+
return true
72+
} catch (error) {
73+
console.error(
74+
`[${this.constructor.name}#emit] emit() failed -> ${eventName}: ${
75+
error instanceof Error ? error.message : String(error)
76+
}`,
77+
)
78+
79+
return false
80+
}
81+
}
82+
83+
/**
84+
* Handle incoming commands - must be implemented by subclasses.
85+
*/
86+
public abstract handleCommand(command: TCommand): void
87+
88+
/**
89+
* Handle connection-specific logic.
90+
*/
91+
protected abstract handleConnect(socket: Socket): Promise<void>
92+
93+
/**
94+
* Handle disconnection-specific logic.
95+
*/
96+
protected handleDisconnect(): void {
97+
// Default implementation - can be overridden.
98+
}
99+
100+
/**
101+
* Handle reconnection-specific logic.
102+
*/
103+
protected abstract handleReconnect(socket: Socket): Promise<void>
104+
105+
/**
106+
* Handle cleanup-specific logic.
107+
*/
108+
protected abstract handleCleanup(socket: Socket): Promise<void>
109+
}

0 commit comments

Comments
 (0)